@bnbagent/studio-cli 0.0.7 → 0.0.8
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/dist/bag.js +96 -14
- package/package.json +2 -2
package/dist/bag.js
CHANGED
|
@@ -6439,7 +6439,11 @@ import {
|
|
|
6439
6439
|
} from "@bnbagent/sdk/wallets";
|
|
6440
6440
|
import { auditedOp as auditedOp2 } from "@bnbagent/studio-runtime/audit";
|
|
6441
6441
|
import { loadStudioToml as loadStudioToml9 } from "@bnbagent/studio-runtime/config";
|
|
6442
|
-
import {
|
|
6442
|
+
import {
|
|
6443
|
+
BSC_TESTNET_FAUCET_URLS,
|
|
6444
|
+
getNetwork as getNetwork5,
|
|
6445
|
+
toRaw as toRaw2
|
|
6446
|
+
} from "@bnbagent/studio-runtime/networks";
|
|
6443
6447
|
import { writePrivate } from "@bnbagent/studio-runtime/secretWrite";
|
|
6444
6448
|
import {
|
|
6445
6449
|
ALTANA_NETWORK_BY_STUDIO,
|
|
@@ -6495,6 +6499,23 @@ function loadContext(projectRoot) {
|
|
|
6495
6499
|
address
|
|
6496
6500
|
};
|
|
6497
6501
|
}
|
|
6502
|
+
async function requireAltanaAdminGas(ctx) {
|
|
6503
|
+
let balance;
|
|
6504
|
+
try {
|
|
6505
|
+
balance = await readNativeBalanceRaw(ctx.address, ctx.networkName);
|
|
6506
|
+
} catch (error) {
|
|
6507
|
+
printErr(
|
|
6508
|
+
`warning: could not check Altana admin gas balance on ${ctx.networkName} (${error instanceof Error ? error.message : String(error)}); continuing and letting Altana return the authoritative result.`
|
|
6509
|
+
);
|
|
6510
|
+
return;
|
|
6511
|
+
}
|
|
6512
|
+
if (balance !== 0n) return;
|
|
6513
|
+
const symbol = ctx.networkName === "bsc-testnet" ? "tBNB" : "BNB";
|
|
6514
|
+
const funding = ctx.networkName === "bsc-testnet" ? ` Fund it and retry. Testnet faucets: ${BSC_TESTNET_FAUCET_URLS.join(", ")}` : " Fund it with BNB and retry.";
|
|
6515
|
+
throw new Error(
|
|
6516
|
+
`Altana admin wallet ${ctx.address} has 0 ${symbol} on ${ctx.networkName} and cannot pay gas for session administration.${funding}`
|
|
6517
|
+
);
|
|
6518
|
+
}
|
|
6498
6519
|
function requirePassword() {
|
|
6499
6520
|
const password = process.env[PASSWORD_ENV];
|
|
6500
6521
|
if (!password) {
|
|
@@ -6646,6 +6667,7 @@ async function cmdSessionGrant(opts) {
|
|
|
6646
6667
|
projectRoot
|
|
6647
6668
|
},
|
|
6648
6669
|
async () => {
|
|
6670
|
+
await requireAltanaAdminGas(ctx);
|
|
6649
6671
|
await admin2.approveQuoteSignatureChecker(
|
|
6650
6672
|
restored,
|
|
6651
6673
|
deployedAddresses(ctx.network.chainId).commerceProxy
|
|
@@ -6690,6 +6712,7 @@ async function cmdSessionGrant(opts) {
|
|
|
6690
6712
|
projectRoot
|
|
6691
6713
|
},
|
|
6692
6714
|
async (h) => {
|
|
6715
|
+
await requireAltanaAdminGas(ctx);
|
|
6693
6716
|
if (existing !== null) {
|
|
6694
6717
|
printErr(`Revoking existing Altana session ${existing.publicKey}\u2026`);
|
|
6695
6718
|
await admin.revokeSession(existing.publicKey);
|
|
@@ -6779,6 +6802,7 @@ async function cmdSessionRevoke(opts) {
|
|
|
6779
6802
|
projectRoot
|
|
6780
6803
|
},
|
|
6781
6804
|
async () => {
|
|
6805
|
+
await requireAltanaAdminGas(ctx);
|
|
6782
6806
|
await admin.revokeSession(envelope.publicKey);
|
|
6783
6807
|
}
|
|
6784
6808
|
);
|
|
@@ -6818,6 +6842,7 @@ async function cmdSessionX402Setup(opts) {
|
|
|
6818
6842
|
projectRoot
|
|
6819
6843
|
},
|
|
6820
6844
|
async () => {
|
|
6845
|
+
await requireAltanaAdminGas(ctx);
|
|
6821
6846
|
await admin.approveX402SignatureChecker(restored);
|
|
6822
6847
|
try {
|
|
6823
6848
|
await admin.setPermit2Allowance(
|
|
@@ -8013,6 +8038,12 @@ async function cmdInit(nameArg, opts) {
|
|
|
8013
8038
|
printErr(`error: ${target} already exists. Use --force to overwrite.`);
|
|
8014
8039
|
return 2;
|
|
8015
8040
|
}
|
|
8041
|
+
if (opts.destination === "platform" && opts.network === "bsc-mainnet") {
|
|
8042
|
+
printErr(
|
|
8043
|
+
"error: --destination platform cannot be combined with --network bsc-mainnet. The managed platform trial is testnet-only; use --destination self for mainnet, or select bsc-testnet."
|
|
8044
|
+
);
|
|
8045
|
+
return 2;
|
|
8046
|
+
}
|
|
8016
8047
|
let runtime = opts.runtime;
|
|
8017
8048
|
let network = opts.network;
|
|
8018
8049
|
let destination = opts.destination;
|
|
@@ -9205,10 +9236,10 @@ function readWalletAddress(studioToml) {
|
|
|
9205
9236
|
async function printFaucetHint(network, address) {
|
|
9206
9237
|
printOut("");
|
|
9207
9238
|
if (network === "bsc-testnet") {
|
|
9208
|
-
const { BSC_TESTNET_FAUCET_URLS:
|
|
9239
|
+
const { BSC_TESTNET_FAUCET_URLS: BSC_TESTNET_FAUCET_URLS5 } = await import("@bnbagent/studio-runtime/networks");
|
|
9209
9240
|
printOut(`Your testnet wallet address: ${address}`);
|
|
9210
9241
|
printOut("Fund it (free) from these faucets \u2014 paste the address above:");
|
|
9211
|
-
for (const url of
|
|
9242
|
+
for (const url of BSC_TESTNET_FAUCET_URLS5) {
|
|
9212
9243
|
printOut(` \xB7 ${url}`);
|
|
9213
9244
|
}
|
|
9214
9245
|
printOut("(Faucets are needed only for paid models / on-chain settle.");
|
|
@@ -10200,6 +10231,10 @@ function isDir4(p) {
|
|
|
10200
10231
|
}
|
|
10201
10232
|
|
|
10202
10233
|
// src/cli/_runtimeEnvKeys.ts
|
|
10234
|
+
var PAYMASTER_URL_ENV_KEYS = [
|
|
10235
|
+
"BNBAGENT_PAYMASTER_URL_BSC_MAINNET",
|
|
10236
|
+
"BNBAGENT_PAYMASTER_URL_BSC_TESTNET"
|
|
10237
|
+
];
|
|
10203
10238
|
function tableOf8(cfg, key) {
|
|
10204
10239
|
const v = cfg[key];
|
|
10205
10240
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
@@ -10236,6 +10271,9 @@ function runtimeEnvKeysCore(cfg, resolvable) {
|
|
|
10236
10271
|
if (resolvable("RPC_URL")) {
|
|
10237
10272
|
keys.push("RPC_URL");
|
|
10238
10273
|
}
|
|
10274
|
+
for (const key of PAYMASTER_URL_ENV_KEYS) {
|
|
10275
|
+
if (resolvable(key)) keys.push(key);
|
|
10276
|
+
}
|
|
10239
10277
|
if (commerceRails(cfg).erc8183) {
|
|
10240
10278
|
for (const key of ERC8183_ADDRESS_OVERRIDE_KEYS) {
|
|
10241
10279
|
if (resolvable(key)) keys.push(key);
|
|
@@ -11408,6 +11446,29 @@ function erc8183RailChecks(cfg, env = process.env) {
|
|
|
11408
11446
|
}
|
|
11409
11447
|
return out;
|
|
11410
11448
|
}
|
|
11449
|
+
function dockerUsesNode22OrNewer(source) {
|
|
11450
|
+
for (const line of source.split(/\r?\n/)) {
|
|
11451
|
+
const from = /^\s*FROM\s+(.+)$/i.exec(line);
|
|
11452
|
+
if (from === null) continue;
|
|
11453
|
+
const tokens = from[1].trim().split(/\s+/);
|
|
11454
|
+
if (tokens[0]?.startsWith("--platform=")) {
|
|
11455
|
+
tokens.shift();
|
|
11456
|
+
} else if (tokens[0] === "--platform") {
|
|
11457
|
+
tokens.splice(0, 2);
|
|
11458
|
+
}
|
|
11459
|
+
const image = tokens[0];
|
|
11460
|
+
if (!image || image.includes("${")) continue;
|
|
11461
|
+
const withoutDigest = image.split("@", 1)[0];
|
|
11462
|
+
const lastSegment = withoutDigest.slice(withoutDigest.lastIndexOf("/") + 1);
|
|
11463
|
+
const colon = lastSegment.lastIndexOf(":");
|
|
11464
|
+
if (colon <= 0 || lastSegment.slice(0, colon) !== "node") continue;
|
|
11465
|
+
const major = /^(\d+)(?:[.-]|$)/.exec(lastSegment.slice(colon + 1));
|
|
11466
|
+
if (major !== null && Number.parseInt(major[1], 10) >= 22) {
|
|
11467
|
+
return true;
|
|
11468
|
+
}
|
|
11469
|
+
}
|
|
11470
|
+
return false;
|
|
11471
|
+
}
|
|
11411
11472
|
function x402SellerRailChecks(agentRoot2, cfg, target) {
|
|
11412
11473
|
const payments = tableOf2(cfg, "payments");
|
|
11413
11474
|
const rawSeller = payments.x402_seller;
|
|
@@ -11524,11 +11585,11 @@ function x402SellerRailChecks(agentRoot2, cfg, target) {
|
|
|
11524
11585
|
const dockerfile = path25.join(agentRoot2, "Dockerfile");
|
|
11525
11586
|
if (rails.x402 && isFile11(dockerfile)) {
|
|
11526
11587
|
const source = fs26.readFileSync(dockerfile, "utf8");
|
|
11527
|
-
if (
|
|
11588
|
+
if (!dockerUsesNode22OrNewer(source)) {
|
|
11528
11589
|
out.push({
|
|
11529
11590
|
level: Level.WARNING,
|
|
11530
11591
|
name: "x402_node_version",
|
|
11531
|
-
message: "The x402/B402 seller requires Node 22, but this container Dockerfile
|
|
11592
|
+
message: "The x402/B402 seller requires Node >=22, but this container Dockerfile has no exact node image with a numeric major >=22.",
|
|
11532
11593
|
details: { dockerfile }
|
|
11533
11594
|
});
|
|
11534
11595
|
}
|
|
@@ -12974,7 +13035,7 @@ import {
|
|
|
12974
13035
|
findSubProjectRoot as findSubProjectRoot13,
|
|
12975
13036
|
loadStudioToml as loadStudioToml17
|
|
12976
13037
|
} from "@bnbagent/studio-runtime/config";
|
|
12977
|
-
import { BSC_TESTNET_FAUCET_URLS } from "@bnbagent/studio-runtime/networks";
|
|
13038
|
+
import { BSC_TESTNET_FAUCET_URLS as BSC_TESTNET_FAUCET_URLS2 } from "@bnbagent/studio-runtime/networks";
|
|
12978
13039
|
|
|
12979
13040
|
// src/cli/_deploy/checks/warning.ts
|
|
12980
13041
|
import * as crypto4 from "crypto";
|
|
@@ -13447,8 +13508,8 @@ var checkPlatformFundingHint = async (_root, _target) => [
|
|
|
13447
13508
|
{
|
|
13448
13509
|
level: Level.INFO,
|
|
13449
13510
|
name: "platform_funding_hint",
|
|
13450
|
-
message: `testnet trial \u2014 keep a little tBNB for gas and testnet $U for commerce. Faucets: ${
|
|
13451
|
-
details: { faucets: [...
|
|
13511
|
+
message: `testnet trial \u2014 keep a little tBNB for gas and testnet $U for commerce. Faucets: ${BSC_TESTNET_FAUCET_URLS2.join(" \xB7 ")}`,
|
|
13512
|
+
details: { faucets: [...BSC_TESTNET_FAUCET_URLS2] }
|
|
13452
13513
|
}
|
|
13453
13514
|
];
|
|
13454
13515
|
var criticalChecks = [
|
|
@@ -14428,7 +14489,7 @@ function walletWarning(root, secrets) {
|
|
|
14428
14489
|
const who2 = typeof address === "string" && address ? ` (wallet ${address})` : "";
|
|
14429
14490
|
warn(
|
|
14430
14491
|
`
|
|
14431
|
-
|
|
14492
|
+
[expected \xB7 bounded Altana session]
|
|
14432
14493
|
This project's bounded Altana session${who2} will be transmitted to the BNB Chain operator's Secrets Manager so the trial runtime can sign on testnet. The session is budget-limited, expiring, and revocable \u2014 the admin keystore and WALLET_PASSWORD never ship.
|
|
14433
14494
|
If the current budget or expiry is wider than you want an operator-held key to carry, stop and grant a tighter one first:
|
|
14434
14495
|
bag wallet session grant --force --budget-u <small> --expiry-days <short>
|
|
@@ -15070,6 +15131,15 @@ function agentNetworkDefault(root) {
|
|
|
15070
15131
|
}
|
|
15071
15132
|
return String(tableOf13(cfg, "network").default ?? "").toLowerCase();
|
|
15072
15133
|
}
|
|
15134
|
+
function rejectPlatformMainnet(root) {
|
|
15135
|
+
if (agentNetworkDefault(root) !== "bsc-mainnet") {
|
|
15136
|
+
return null;
|
|
15137
|
+
}
|
|
15138
|
+
printErr(
|
|
15139
|
+
"error: the BNB Chain managed platform is testnet-only, but [network].default is bsc-mainnet. Deploy to your own provider or change the project to bsc-testnet. --skip-prepare, --force, and --yes cannot bypass this boundary."
|
|
15140
|
+
);
|
|
15141
|
+
return 1;
|
|
15142
|
+
}
|
|
15073
15143
|
function agentDeployDestination(root) {
|
|
15074
15144
|
const cfg = loadAgentCfg2(root);
|
|
15075
15145
|
if (cfg === null) {
|
|
@@ -15483,6 +15553,10 @@ async function cmdDeploy(opts, deployArgs) {
|
|
|
15483
15553
|
const rc = applyProjectRoot(opts.projectRoot);
|
|
15484
15554
|
if (rc !== null) return rc;
|
|
15485
15555
|
const root = resolveProjectRoot2(opts.projectRoot);
|
|
15556
|
+
if (opts.provider === "bnb") {
|
|
15557
|
+
const networkGate = rejectPlatformMainnet(root);
|
|
15558
|
+
if (networkGate !== null) return networkGate;
|
|
15559
|
+
}
|
|
15486
15560
|
const deployments = discoverRecordedDeployments(root);
|
|
15487
15561
|
const unavailable = unavailableProvidersForProject(root);
|
|
15488
15562
|
const interactive = stdinIsTty();
|
|
@@ -15516,6 +15590,10 @@ async function cmdDeploy(opts, deployArgs) {
|
|
|
15516
15590
|
printErr("cancelled: no deployment was started.");
|
|
15517
15591
|
return selection.exitCode;
|
|
15518
15592
|
}
|
|
15593
|
+
if (selection.provider === "bnb") {
|
|
15594
|
+
const networkGate = rejectPlatformMainnet(root);
|
|
15595
|
+
if (networkGate !== null) return networkGate;
|
|
15596
|
+
}
|
|
15519
15597
|
if (!interactive && !opts.yes) {
|
|
15520
15598
|
printErr(
|
|
15521
15599
|
`error: non-interactive ${selection.operation} on ${selection.provider} requires --yes`
|
|
@@ -15587,6 +15665,10 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15587
15665
|
const root = resolveProjectRoot2(opts.projectRoot);
|
|
15588
15666
|
const destination = opts.provider ? opts.provider === "bnb" ? "platform" : "self" : opts.to ?? opts.destination ?? agentDeployDestination(root);
|
|
15589
15667
|
const packagingDestination = opts.to ?? opts.destination ?? agentDeployDestination(root);
|
|
15668
|
+
if (destination === "platform") {
|
|
15669
|
+
const networkGate = rejectPlatformMainnet(root);
|
|
15670
|
+
if (networkGate !== null) return networkGate;
|
|
15671
|
+
}
|
|
15590
15672
|
const driftAgentRoot = findSubProjectRoot16("agent", root) ?? root;
|
|
15591
15673
|
const driftKind = deployWalletKind(driftAgentRoot);
|
|
15592
15674
|
rc = checkPackagingDrift(
|
|
@@ -16565,7 +16647,7 @@ import { pieverseKeyHash as pieverseKeyHash4 } from "@bnbagent/studio-runtime/ll
|
|
|
16565
16647
|
import {
|
|
16566
16648
|
BSC_MAINNET_MIN_BNB,
|
|
16567
16649
|
BSC_MAINNET_MIN_U,
|
|
16568
|
-
BSC_TESTNET_FAUCET_URLS as
|
|
16650
|
+
BSC_TESTNET_FAUCET_URLS as BSC_TESTNET_FAUCET_URLS3,
|
|
16569
16651
|
BSC_TESTNET_MIN_BNB,
|
|
16570
16652
|
BSC_TESTNET_MIN_U,
|
|
16571
16653
|
ERC8183_SUBMIT_GAS_RESERVE_BNB,
|
|
@@ -17555,7 +17637,7 @@ async function checkBalances(projectRoot, data, networkOverride) {
|
|
|
17555
17637
|
const isMainnet = name === "bsc-mainnet";
|
|
17556
17638
|
const minBnb = isTestnet ? BSC_TESTNET_MIN_BNB : isMainnet ? BSC_MAINNET_MIN_BNB : 0;
|
|
17557
17639
|
const minBnbWei = BigInt(Math.round(minBnb * 1e6)) * 10n ** 12n;
|
|
17558
|
-
const faucetHint = isTestnet ? ` \u2014 faucets: ${
|
|
17640
|
+
const faucetHint = isTestnet ? ` \u2014 faucets: ${BSC_TESTNET_FAUCET_URLS3.join(", ")}` : "";
|
|
17559
17641
|
const bnbRaw = await readNativeBalanceRaw(address, name);
|
|
17560
17642
|
const reserve = ERC8183_SUBMIT_GAS_RESERVE_BNB;
|
|
17561
17643
|
const reserveHint = ` (each on-chain action reserves \u2248 ${reserve} BNB worst-case)`;
|
|
@@ -17963,7 +18045,7 @@ import {
|
|
|
17963
18045
|
updateServiceEndpoint as updateServiceEndpoint2
|
|
17964
18046
|
} from "@bnbagent/studio-runtime/erc8004";
|
|
17965
18047
|
import {
|
|
17966
|
-
BSC_TESTNET_FAUCET_URLS as
|
|
18048
|
+
BSC_TESTNET_FAUCET_URLS as BSC_TESTNET_FAUCET_URLS4,
|
|
17967
18049
|
fromRaw as fromRaw4,
|
|
17968
18050
|
getNetwork as getNetwork10
|
|
17969
18051
|
} from "@bnbagent/studio-runtime/networks";
|
|
@@ -18127,7 +18209,7 @@ async function precheckRegisterGas(wallet, network) {
|
|
|
18127
18209
|
if (balance >= REGISTER_MIN_BNB) {
|
|
18128
18210
|
return null;
|
|
18129
18211
|
}
|
|
18130
|
-
const faucet =
|
|
18212
|
+
const faucet = BSC_TESTNET_FAUCET_URLS4[0];
|
|
18131
18213
|
return `ERC-8004 register needs gas to broadcast, but ${wallet.address} holds only ${balance} BNB on ${network} (need ~${REGISTER_MIN_BNB}). Fund a little tBNB and retry. Faucet: ${faucet}`;
|
|
18132
18214
|
}
|
|
18133
18215
|
function syncAgentRegistry(agentId, op) {
|
|
@@ -20760,7 +20842,7 @@ function buildProgram() {
|
|
|
20760
20842
|
return program;
|
|
20761
20843
|
}
|
|
20762
20844
|
function cliVersion() {
|
|
20763
|
-
return "0.0.
|
|
20845
|
+
return "0.0.8";
|
|
20764
20846
|
}
|
|
20765
20847
|
|
|
20766
20848
|
// src/cli/updateCheck.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bnbagent/studio-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Skills-first toolkit and bag CLI for BNB Chain seller agents: ERC-8004 identity, ERC-8183 escrowed commerce, and x402 payments.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bnb-chain",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@bnbagent/sdk": "0.5.0",
|
|
54
|
-
"@bnbagent/studio-runtime": "0.0.
|
|
54
|
+
"@bnbagent/studio-runtime": "0.0.8",
|
|
55
55
|
"ai": "^7.0.29",
|
|
56
56
|
"archiver": "^8.0.0",
|
|
57
57
|
"commander": "^15.0.0",
|