@bnbagent/studio-cli 0.0.10 → 0.0.11-alpha.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/LICENSE +201 -0
- package/README.md +2 -2
- package/dist/_agentcoreName-DZDWEYD3.js +0 -0
- package/dist/_twak-4XF4H5PL.js +0 -0
- package/dist/bag.js +322 -125
- package/dist/chunk-RO726HJG.js +0 -0
- package/dist/{chunk-YFEM4564.js → chunk-TTPOH453.js} +79 -37
- package/dist/chunk-U7IDQ3K5.js +0 -0
- package/dist/{deployCli-NJFCWBSF.js → deployCli-K55GXDVO.js} +1 -1
- package/package.json +11 -12
- package/recipes/runtimes/agentcore/code/{{PKG}}/Dockerfile.tmpl +20 -21
- package/recipes/runtimes/agentcore/code/{{PKG}}/executor.ts.tmpl +36 -0
- package/recipes/runtimes/agentcore/code/{{PKG}}/unifiedMain.ts.tmpl +620 -0
- package/recipes/runtimes/agentcore/recipe.toml +3 -3
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/Dockerfile.tmpl +25 -23
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/agentCard.ts.tmpl +16 -12
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/executor.ts.tmpl +72 -393
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/mcpMain.ts.tmpl +160 -43
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/sellerCore.ts.tmpl +504 -0
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/unifiedMain.ts.tmpl +620 -0
- package/recipes/runtimes/azure-foundry/recipe.toml +19 -11
- package/recipes/x402-buyer/code/{{PKG}}/x402Buyer.ts.tmpl +6 -4
- package/skills/bnbagent-studio.md +2 -2
- package/skills/references/bnbagent-studio-adding-to-project.md +1 -1
- package/skills/references/bnbagent-studio-buying-from-bazaar.md +1 -1
- package/skills/references/bnbagent-studio-operating.md +4 -4
- package/skills/references/bnbagent-studio-scaffolding-agent.md +4 -4
- package/skills/references/bnbagent-studio-selling-via-8183.md +3 -3
- package/skills/references/bnbagent-studio-selling-via-b402.md +2 -2
- package/skills/references/bnbagent-studio-use-aws-agentcore.md +1 -1
- package/skills/references/bnbagent-studio-use-azure-foundry.md +3 -3
- package/skills/references/bnbagent-studio-use-bnb-trial.md +1 -1
- package/skills/references/bnbagent-studio-wiring-llm-tools.md +3 -3
- package/recipes/runtimes/agentcore/code/{{PKG}}/main.ts.tmpl +0 -347
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/foundryMain.ts.tmpl +0 -422
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/main.ts.tmpl +0 -196
package/dist/bag.js
CHANGED
|
@@ -6,17 +6,21 @@ import {
|
|
|
6
6
|
CliExit,
|
|
7
7
|
DEFAULT_B402_PRICE_USD,
|
|
8
8
|
DEFAULT_B402_TESTNET_BASE_URL,
|
|
9
|
+
LEGACY_ENTRY_STEMS,
|
|
10
|
+
X402_CAPABLE_RUNTIMES,
|
|
9
11
|
act,
|
|
10
12
|
agentcoreFlavor,
|
|
11
13
|
b402Credentials,
|
|
12
14
|
bnbEnv,
|
|
13
15
|
bnbPlatformApiUrl,
|
|
16
|
+
checkBunx,
|
|
14
17
|
checkDocker,
|
|
15
18
|
checkTwak,
|
|
16
19
|
commerceRails,
|
|
17
20
|
deployChecks,
|
|
18
21
|
deployEndpointValue,
|
|
19
22
|
devPortOf,
|
|
23
|
+
dryRunBundle,
|
|
20
24
|
entryStemOf,
|
|
21
25
|
getEnvVar,
|
|
22
26
|
hasA2aFace,
|
|
@@ -44,7 +48,7 @@ import {
|
|
|
44
48
|
x402SellerIsFree,
|
|
45
49
|
x402SellerPricingState,
|
|
46
50
|
x402SellerUsesB402
|
|
47
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-TTPOH453.js";
|
|
48
52
|
import {
|
|
49
53
|
TWAK_CLI_MIN_VERSION,
|
|
50
54
|
TWAK_CLI_VERSION,
|
|
@@ -222,7 +226,7 @@ import {
|
|
|
222
226
|
var CAMPAIGN_DOC_URL = "https://www.bnbchain.org/en/blog/bnb-agent-studio-is-live-on-bnb-chain-ai-agents-from-one-prompt";
|
|
223
227
|
var CAMPAIGN_CHECK_TIMEOUT_MS = 6e3;
|
|
224
228
|
async function fetchCampaignActive() {
|
|
225
|
-
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-
|
|
229
|
+
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-K55GXDVO.js");
|
|
226
230
|
const controller = new AbortController();
|
|
227
231
|
const timer = setTimeout(() => controller.abort(), CAMPAIGN_CHECK_TIMEOUT_MS);
|
|
228
232
|
try {
|
|
@@ -454,8 +458,8 @@ function packageRoot() {
|
|
|
454
458
|
}
|
|
455
459
|
}
|
|
456
460
|
function studioCliVersion() {
|
|
457
|
-
if ("0.0.
|
|
458
|
-
return "0.0.
|
|
461
|
+
if ("0.0.11-alpha.2") {
|
|
462
|
+
return "0.0.11-alpha.2";
|
|
459
463
|
}
|
|
460
464
|
const file = path2.join(packageRoot(), "package.json");
|
|
461
465
|
const pkg = JSON.parse(fs3.readFileSync(file, "utf-8"));
|
|
@@ -491,15 +495,34 @@ import { parse, stringify } from "smol-toml";
|
|
|
491
495
|
|
|
492
496
|
// src/cli/utils/prompt.ts
|
|
493
497
|
import * as readline from "readline/promises";
|
|
498
|
+
var PromptCancelled = class extends Error {
|
|
499
|
+
constructor() {
|
|
500
|
+
super("prompt cancelled");
|
|
501
|
+
this.name = "PromptCancelled";
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
async function ask(rl, question) {
|
|
505
|
+
try {
|
|
506
|
+
return await Promise.race([
|
|
507
|
+
rl.question(question),
|
|
508
|
+
new Promise((_, reject) => {
|
|
509
|
+
rl.once("SIGINT", () => reject(new PromptCancelled()));
|
|
510
|
+
})
|
|
511
|
+
]);
|
|
512
|
+
} catch (exc) {
|
|
513
|
+
if (exc instanceof PromptCancelled) {
|
|
514
|
+
throw exc;
|
|
515
|
+
}
|
|
516
|
+
return "";
|
|
517
|
+
}
|
|
518
|
+
}
|
|
494
519
|
async function promptUser(question) {
|
|
495
520
|
const rl = readline.createInterface({
|
|
496
521
|
input: process.stdin,
|
|
497
522
|
output: process.stdout
|
|
498
523
|
});
|
|
499
524
|
try {
|
|
500
|
-
return await rl
|
|
501
|
-
} catch {
|
|
502
|
-
return "";
|
|
525
|
+
return await ask(rl, question);
|
|
503
526
|
} finally {
|
|
504
527
|
rl.close();
|
|
505
528
|
}
|
|
@@ -510,9 +533,7 @@ async function promptUserStderr(question) {
|
|
|
510
533
|
output: process.stderr
|
|
511
534
|
});
|
|
512
535
|
try {
|
|
513
|
-
return await rl
|
|
514
|
-
} catch {
|
|
515
|
-
return "";
|
|
536
|
+
return await ask(rl, question);
|
|
516
537
|
} finally {
|
|
517
538
|
rl.close();
|
|
518
539
|
}
|
|
@@ -526,9 +547,7 @@ async function promptHidden(question) {
|
|
|
526
547
|
terminal: false
|
|
527
548
|
});
|
|
528
549
|
try {
|
|
529
|
-
return await rl
|
|
530
|
-
} catch {
|
|
531
|
-
return "";
|
|
550
|
+
return await ask(rl, "");
|
|
532
551
|
} finally {
|
|
533
552
|
rl.close();
|
|
534
553
|
process.stderr.write("\n");
|
|
@@ -3366,7 +3385,11 @@ var PROVIDER_SHORT_LABELS = {
|
|
|
3366
3385
|
function providerDigit(provider) {
|
|
3367
3386
|
return PROVIDER_MENU_ORDER.indexOf(provider) + 1;
|
|
3368
3387
|
}
|
|
3369
|
-
var ADVERTISED_PROVIDERS = [
|
|
3388
|
+
var ADVERTISED_PROVIDERS = [
|
|
3389
|
+
"bnb",
|
|
3390
|
+
"aws",
|
|
3391
|
+
"azure"
|
|
3392
|
+
];
|
|
3370
3393
|
var ADVERTISED_PROVIDERS_HELP = ADVERTISED_PROVIDERS.join("|");
|
|
3371
3394
|
function tableOf3(data, key) {
|
|
3372
3395
|
const value = data[key];
|
|
@@ -3455,13 +3478,13 @@ function unavailableProvidersForProject(root) {
|
|
|
3455
3478
|
const cfg = loadStudioToml6(path13.join(agentRoot2, "studio.toml"));
|
|
3456
3479
|
runtime = text(tableOf3(cfg, "stack").runtime) ?? "agentcore";
|
|
3457
3480
|
const faces = stackFaces(tableOf3(cfg, "stack"), tableOf3(cfg, "payments"));
|
|
3458
|
-
azureProtocolUnsupported = !hasA2aFace(faces)
|
|
3481
|
+
azureProtocolUnsupported = hasMcpFace(faces) || !hasA2aFace(faces) && !hasX402Face(faces);
|
|
3459
3482
|
} catch {
|
|
3460
3483
|
return {};
|
|
3461
3484
|
}
|
|
3462
3485
|
if (runtime === "azure-foundry") {
|
|
3463
3486
|
const reason = "this project uses a different container adapter; scaffold an agentcore project before selecting this provider";
|
|
3464
|
-
const azureProtocolReason = "Azure Foundry deploy
|
|
3487
|
+
const azureProtocolReason = "Azure Foundry deploy supports A2A and X402 seller projects; use AgentCore for MCP";
|
|
3465
3488
|
return {
|
|
3466
3489
|
aws: reason,
|
|
3467
3490
|
...azureProtocolUnsupported ? {
|
|
@@ -4488,22 +4511,23 @@ var checkEntrypointAndDockerfile = async (root, _target) => {
|
|
|
4488
4511
|
const findings = [];
|
|
4489
4512
|
const cfg = loadStudioCfg(deployWorkspaceRoot(root));
|
|
4490
4513
|
const faces = stackFaces(tableOf4(cfg, "stack"), tableOf4(cfg, "payments"));
|
|
4491
|
-
if (!hasA2aFace(faces)
|
|
4514
|
+
if (hasMcpFace(faces) || !hasA2aFace(faces) && !hasX402Face(faces)) {
|
|
4492
4515
|
return [
|
|
4493
4516
|
{
|
|
4494
4517
|
level: "CRITICAL",
|
|
4495
4518
|
name: "azure_protocol_supported",
|
|
4496
|
-
message: "azure-foundry deploy
|
|
4519
|
+
message: "azure-foundry deploy supports the A2A carrier, including X402-only seller configs. The delegated Foundry version declares the invocations contract (:8088, /readiness, /invocations), not native MCP /mcp. Re-scaffold with --protocols A2A, X402, or A2A,X402; or use AgentCore for MCP.",
|
|
4497
4520
|
details: { faces }
|
|
4498
4521
|
}
|
|
4499
4522
|
];
|
|
4500
4523
|
}
|
|
4501
|
-
const
|
|
4524
|
+
const entryCandidates = ["src/unifiedMain.ts", "src/foundryMain.ts"];
|
|
4525
|
+
const entry = entryCandidates.find((c2) => isFile6(path17.join(agentRoot2, c2))) ?? entryCandidates[0];
|
|
4502
4526
|
if (!isFile6(path17.join(agentRoot2, entry))) {
|
|
4503
4527
|
findings.push({
|
|
4504
4528
|
level: "CRITICAL",
|
|
4505
4529
|
name: "azure_agent_entrypoint",
|
|
4506
|
-
message: `app/agent/${entry} is missing \u2014 the A2A
|
|
4530
|
+
message: `app/agent/${entry} is missing \u2014 the A2A entrypoint the container image runs. Re-scaffold with \`bag init \u2026 --runtime azure-foundry\`.`,
|
|
4507
4531
|
details: { entrypoint: entry }
|
|
4508
4532
|
});
|
|
4509
4533
|
}
|
|
@@ -4606,7 +4630,11 @@ import * as walletRt2 from "@bnbagent/studio-runtime/wallet";
|
|
|
4606
4630
|
import { generateText } from "ai";
|
|
4607
4631
|
|
|
4608
4632
|
// src/cli/_pieverseHelpers.ts
|
|
4609
|
-
import {
|
|
4633
|
+
import {
|
|
4634
|
+
BSC_TESTNET_U_FAUCET_URL,
|
|
4635
|
+
fromRaw as fromRaw2,
|
|
4636
|
+
getNetwork as getNetwork3
|
|
4637
|
+
} from "@bnbagent/studio-runtime/networks";
|
|
4610
4638
|
import {
|
|
4611
4639
|
siweLogin
|
|
4612
4640
|
} from "@bnbagent/studio-runtime/pieverse";
|
|
@@ -4659,9 +4687,7 @@ function printUBalanceShortfall(walletAddress, currentRaw, neededRaw, neededUsd,
|
|
|
4659
4687
|
` swap on PancakeSwap: https://pancakeswap.finance/swap?outputCurrency=${u.address}`
|
|
4660
4688
|
);
|
|
4661
4689
|
} else {
|
|
4662
|
-
printErr(
|
|
4663
|
-
" testnet U faucet URL is TBD \u2014 see docs/guides/pieverse-integration.md \xA76"
|
|
4664
|
-
);
|
|
4690
|
+
printErr(` testnet U faucet: ${BSC_TESTNET_U_FAUCET_URL}`);
|
|
4665
4691
|
}
|
|
4666
4692
|
}
|
|
4667
4693
|
function writeEnvLocal(key, value, envPath = ".env.local") {
|
|
@@ -6450,6 +6476,7 @@ import {
|
|
|
6450
6476
|
findProjectRoot as findProjectRoot3,
|
|
6451
6477
|
loadStudioToml as loadStudioToml10
|
|
6452
6478
|
} from "@bnbagent/studio-runtime/config";
|
|
6479
|
+
import { tbnbFaucetHint as tbnbFaucetHint2 } from "@bnbagent/studio-runtime/networks";
|
|
6453
6480
|
import { buildPolicy, buildWallet } from "@bnbagent/studio-runtime/wallet";
|
|
6454
6481
|
|
|
6455
6482
|
// src/cli/walletSession.ts
|
|
@@ -6467,8 +6494,8 @@ import {
|
|
|
6467
6494
|
import { auditedOp as auditedOp2 } from "@bnbagent/studio-runtime/audit";
|
|
6468
6495
|
import { loadStudioToml as loadStudioToml9 } from "@bnbagent/studio-runtime/config";
|
|
6469
6496
|
import {
|
|
6470
|
-
BSC_TESTNET_FAUCET_URLS,
|
|
6471
6497
|
getNetwork as getNetwork5,
|
|
6498
|
+
tbnbFaucetHint,
|
|
6472
6499
|
toRaw as toRaw2
|
|
6473
6500
|
} from "@bnbagent/studio-runtime/networks";
|
|
6474
6501
|
import { writePrivate } from "@bnbagent/studio-runtime/secretWrite";
|
|
@@ -6538,7 +6565,7 @@ async function requireAltanaAdminGas(ctx) {
|
|
|
6538
6565
|
}
|
|
6539
6566
|
if (balance !== 0n) return;
|
|
6540
6567
|
const symbol = ctx.networkName === "bsc-testnet" ? "tBNB" : "BNB";
|
|
6541
|
-
const funding = ctx.networkName === "bsc-testnet" ? ` Fund it and retry
|
|
6568
|
+
const funding = ctx.networkName === "bsc-testnet" ? ` Fund it and retry \u2014 ${tbnbFaucetHint(ctx.address)}` : " Fund it with BNB and retry.";
|
|
6542
6569
|
throw new Error(
|
|
6543
6570
|
`Altana admin wallet ${ctx.address} has 0 ${symbol} on ${ctx.networkName} and cannot pay gas for session administration.${funding}`
|
|
6544
6571
|
);
|
|
@@ -7000,6 +7027,14 @@ function projectNetwork(projectRoot) {
|
|
|
7000
7027
|
const dflt = net2 !== null && typeof net2 === "object" ? net2.default : void 0;
|
|
7001
7028
|
return dflt ? String(dflt) : "bsc-testnet";
|
|
7002
7029
|
}
|
|
7030
|
+
function printNextAfterNew(projectRoot, address) {
|
|
7031
|
+
const network = projectNetwork(projectRoot);
|
|
7032
|
+
const fund = network === "bsc-testnet" ? `fund it (free, only needed for paid models / on-chain settle): ${tbnbFaucetHint2(address)}` : "fund it with BNB (gas) + U before selling paid work";
|
|
7033
|
+
printErr(
|
|
7034
|
+
`Next: ${fund}
|
|
7035
|
+
then \`bag doctor\` to verify the project, \`bag dev\` to run it locally.`
|
|
7036
|
+
);
|
|
7037
|
+
}
|
|
7003
7038
|
function twakProvider(projectRoot, walletCfg) {
|
|
7004
7039
|
return buildWallet(walletCfg, projectRoot, {
|
|
7005
7040
|
network: projectNetwork(projectRoot)
|
|
@@ -7193,6 +7228,8 @@ async function cmdNew(opts) {
|
|
|
7193
7228
|
printErr(
|
|
7194
7229
|
"Altana admin keystore created. Fund this address with about 0.05 tBNB for testnet bootstrap/registration, then run `bag wallet session grant` to create the bounded runtime session."
|
|
7195
7230
|
);
|
|
7231
|
+
} else {
|
|
7232
|
+
printNextAfterNew(projectRoot, provider.address);
|
|
7196
7233
|
}
|
|
7197
7234
|
return 0;
|
|
7198
7235
|
}
|
|
@@ -7232,6 +7269,7 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
7232
7269
|
const address = provider.address;
|
|
7233
7270
|
printOut(address);
|
|
7234
7271
|
persistAddress(projectRoot, address);
|
|
7272
|
+
printNextAfterNew(projectRoot, address);
|
|
7235
7273
|
return 0;
|
|
7236
7274
|
}
|
|
7237
7275
|
function ensureTwakCredentials(walletFile, homeDir) {
|
|
@@ -7964,6 +8002,44 @@ function enclosingProjectRoot(start) {
|
|
|
7964
8002
|
}
|
|
7965
8003
|
}
|
|
7966
8004
|
async function cmdInit(nameArg, opts) {
|
|
8005
|
+
const target = path23.resolve(process.cwd(), nameArg);
|
|
8006
|
+
const targetPreexisted = fs24.existsSync(target);
|
|
8007
|
+
const cleanupOnCancel = () => {
|
|
8008
|
+
if (targetPreexisted || !fs24.existsSync(target)) {
|
|
8009
|
+
printErr("cancelled: no project was created.");
|
|
8010
|
+
return;
|
|
8011
|
+
}
|
|
8012
|
+
const walletsDir = path23.join(target, ".studio", "wallets");
|
|
8013
|
+
const hasWallet = fs24.existsSync(walletsDir) && fs24.readdirSync(walletsDir).length > 0;
|
|
8014
|
+
if (hasWallet) {
|
|
8015
|
+
printErr(
|
|
8016
|
+
`cancelled: ${target} is KEPT \u2014 it already contains a wallet keystore (.studio/wallets/). Finish setup there, or back the keystore up before removing the directory.`
|
|
8017
|
+
);
|
|
8018
|
+
} else {
|
|
8019
|
+
fs24.rmSync(target, { recursive: true, force: true });
|
|
8020
|
+
printErr(
|
|
8021
|
+
`cancelled: removed the partially created ${target}; re-run \`bag init\` to start over.`
|
|
8022
|
+
);
|
|
8023
|
+
}
|
|
8024
|
+
};
|
|
8025
|
+
const onSigint = () => {
|
|
8026
|
+
cleanupOnCancel();
|
|
8027
|
+
process.exit(130);
|
|
8028
|
+
};
|
|
8029
|
+
process.once("SIGINT", onSigint);
|
|
8030
|
+
try {
|
|
8031
|
+
return await cmdInitFlow(nameArg, opts);
|
|
8032
|
+
} catch (exc) {
|
|
8033
|
+
if (exc instanceof Error && exc.name === "PromptCancelled") {
|
|
8034
|
+
cleanupOnCancel();
|
|
8035
|
+
return 130;
|
|
8036
|
+
}
|
|
8037
|
+
throw exc;
|
|
8038
|
+
} finally {
|
|
8039
|
+
process.removeListener("SIGINT", onSigint);
|
|
8040
|
+
}
|
|
8041
|
+
}
|
|
8042
|
+
async function cmdInitFlow(nameArg, opts) {
|
|
7967
8043
|
const target = path23.resolve(process.cwd(), nameArg);
|
|
7968
8044
|
let projectName2 = path23.basename(target);
|
|
7969
8045
|
if (!projectName2) {
|
|
@@ -7972,6 +8048,14 @@ async function cmdInit(nameArg, opts) {
|
|
|
7972
8048
|
);
|
|
7973
8049
|
return 2;
|
|
7974
8050
|
}
|
|
8051
|
+
if (opts.runtime === "agentcore" || opts.destination === "platform") {
|
|
8052
|
+
try {
|
|
8053
|
+
projectName2 = validateProjectName(projectName2);
|
|
8054
|
+
} catch (exc) {
|
|
8055
|
+
printErr(`error: ${exc instanceof Error ? exc.message : exc}`);
|
|
8056
|
+
return 2;
|
|
8057
|
+
}
|
|
8058
|
+
}
|
|
7975
8059
|
if (opts.protocols !== void 0 && opts.protocol !== void 0) {
|
|
7976
8060
|
printErr("error: pass either --protocols or --protocol, not both.");
|
|
7977
8061
|
return 2;
|
|
@@ -8062,7 +8146,9 @@ async function cmdInit(nameArg, opts) {
|
|
|
8062
8146
|
return 2;
|
|
8063
8147
|
}
|
|
8064
8148
|
if (fs24.existsSync(target) && !opts.force) {
|
|
8065
|
-
printErr(
|
|
8149
|
+
printErr(
|
|
8150
|
+
`error: ${target} already exists (perhaps from an interrupted \`bag init\`). Re-run with --force to overwrite \u2014 this DELETES the whole directory, including any wallet keystore under its .studio/ \u2014 or pick another name.`
|
|
8151
|
+
);
|
|
8066
8152
|
return 2;
|
|
8067
8153
|
}
|
|
8068
8154
|
if (opts.destination === "platform" && opts.network === "bsc-mainnet") {
|
|
@@ -8086,13 +8172,20 @@ async function cmdInit(nameArg, opts) {
|
|
|
8086
8172
|
destination = "self";
|
|
8087
8173
|
runtime = "agentcore";
|
|
8088
8174
|
}
|
|
8089
|
-
if (destination === "self" && runtime === "azure-foundry" && (!hasA2aFace(faces)
|
|
8175
|
+
if (destination === "self" && runtime === "azure-foundry" && (hasMcpFace(faces) || !hasA2aFace(faces) && !hasX402Face(faces))) {
|
|
8090
8176
|
printErr(
|
|
8091
|
-
"error: azure-foundry supports
|
|
8177
|
+
"error: azure-foundry supports the A2A carrier (including X402-only seller configs) and does not support an MCP face. Foundry is delegated through its invocations container contract (:8088, /readiness, /invocations), not the native MCP /mcp transport. Use --protocols A2A, X402, or A2A,X402; or use --runtime agentcore for MCP."
|
|
8092
8178
|
);
|
|
8093
8179
|
return 2;
|
|
8094
8180
|
}
|
|
8095
8181
|
if (fs24.existsSync(target)) {
|
|
8182
|
+
const walletsDir = path23.join(target, ".studio", "wallets");
|
|
8183
|
+
if (fs24.existsSync(walletsDir) && fs24.readdirSync(walletsDir).length > 0) {
|
|
8184
|
+
printErr(
|
|
8185
|
+
`error: refusing --force: ${walletsDir} contains a wallet keystore and overwriting would DELETE the key. Back the keystore up and remove the directory yourself, or init under a different name.`
|
|
8186
|
+
);
|
|
8187
|
+
return 2;
|
|
8188
|
+
}
|
|
8096
8189
|
fs24.rmSync(target, { recursive: true, force: true });
|
|
8097
8190
|
}
|
|
8098
8191
|
if (destination === "platform") {
|
|
@@ -8410,17 +8503,18 @@ function scaffold(target, name, o) {
|
|
|
8410
8503
|
const isContainer = packaging === "container";
|
|
8411
8504
|
const mode = recipeModeOf(o.faces);
|
|
8412
8505
|
const stem2 = entryStemOf(o.faces);
|
|
8413
|
-
const a2aEntry = o.runtime === "azure-foundry" ? "dist/foundryMain.js" : "dist/main.js";
|
|
8414
8506
|
const runtimeCtx = {
|
|
8415
8507
|
PKG: AGENT_SRC,
|
|
8416
8508
|
TWAK_CLI_VERSION,
|
|
8417
8509
|
PNPM_VERSION: packageManagerVersion,
|
|
8418
8510
|
DEPLOYMENT_TYPE: isContainer ? "container" : "direct_code_deploy",
|
|
8419
|
-
|
|
8420
|
-
//
|
|
8421
|
-
//
|
|
8422
|
-
|
|
8423
|
-
//
|
|
8511
|
+
// The A2A entrypoint (unifiedMain) is cloud-portable: it binds BOTH the
|
|
8512
|
+
// AgentCore (9000) and Foundry (8088) contract ports itself, so the same
|
|
8513
|
+
// rendered image deploys to either cloud — no runtime-specific entry.
|
|
8514
|
+
ENTRYPOINT: `dist/${stem2}.js`,
|
|
8515
|
+
// AGENT_PORT only prepends a primary override; the Foundry contract port
|
|
8516
|
+
// stays reachable regardless. MCP keeps its 8000 contract; Foundry
|
|
8517
|
+
// renders 8088 for continuity with the provider's documented default.
|
|
8424
8518
|
CONTAINER_PORT: o.runtime === "azure-foundry" ? "8088" : String(devPortOf(o.faces))
|
|
8425
8519
|
};
|
|
8426
8520
|
emitRecipe(agentRoot2, "agent", { context: runtimeCtx });
|
|
@@ -8786,10 +8880,11 @@ function renderAgentStudioToml(name, o) {
|
|
|
8786
8880
|
# Read by the Agent: it quotes the FIXED \`price\`, CLAMPS it to [min,max],
|
|
8787
8881
|
# freezes a short-TTL offer, and EIP-191 signs it \u2014 pricing is rule-based, the
|
|
8788
8882
|
# LLM never prices. price=0 is FREE and is supported by the canonical stack.
|
|
8789
|
-
currency = "${currencyAddr}" # $U token address \u2014 prefilled from [network].default
|
|
8790
|
-
|
|
8883
|
+
currency = "${currencyAddr}" # $U token address \u2014 prefilled from [network].default; rarely changed
|
|
8884
|
+
# All prices are in wei of the currency token. U has 18 decimals (not 6 like USDC).
|
|
8885
|
+
price = "${o.erc8183Price}" # wei; 0 = FREE (zero token escrow)
|
|
8791
8886
|
min_price = "0" # wei \u2014 clamp floor
|
|
8792
|
-
max_price = "" # wei \u2014 clamp ceiling; SET before going live
|
|
8887
|
+
max_price = "" # wei \u2014 clamp ceiling; empty = unbounded; SET before going live
|
|
8793
8888
|
quote_ttl_seconds = 900 # seconds a signed quote stays valid; SDK caps at 900 (~15min work window)
|
|
8794
8889
|
default_estimated_completion_seconds = 600
|
|
8795
8890
|
poll_interval_seconds = 30
|
|
@@ -8927,7 +9022,7 @@ function renderAgentReadme(name, faces, destination, walletKind2) {
|
|
|
8927
9022
|
const port = String(devPortOf(faces));
|
|
8928
9023
|
const x402Only = faces.length === 1 && hasX402Face(faces);
|
|
8929
9024
|
const surface = mode === "both" ? "A2A natively on `0.0.0.0:9000` (agent card + JSON-RPC `message/send`) and buffered streamable-HTTP MCP on `/mcp` through the platform envelope tunnel" : mode === "mcp" ? "streamable-HTTP MCP on `0.0.0.0:8000/mcp` (negotiate + notify_funded sync-delivery + read-only chain tools)" : x402Only ? "only the public `/x402` seller face; AgentCore uses an internal A2A-native process on port 9000 but the gateway suppresses A2A discovery" : "`serveA2a`: the agent card at `/.well-known/agent-card.json` + JSON-RPC `message/send` on `0.0.0.0:9000`";
|
|
8930
|
-
const filesA2a = `- \`src/
|
|
9025
|
+
const filesA2a = `- \`src/unifiedMain.ts\` \u2014 unified serving entrypoint (A2A on port 9000 + Foundry invocations on 8088).
|
|
8931
9026
|
- \`src/executor.ts\` \u2014 the SellerAgentExecutor: the negotiate + notify_funded A2A skills.
|
|
8932
9027
|
- \`src/agentCard.ts\` \u2014 the discoverable AgentCard (+ OAuth2/Cognito scheme).`;
|
|
8933
9028
|
const filesMcp = `- \`src/mcpMain.ts\` \u2014 MCP serving entrypoint (streamable HTTP on \`/mcp\`; deploy
|
|
@@ -9077,10 +9172,23 @@ async function resolveWalletKind(flagValue, isTty) {
|
|
|
9077
9172
|
);
|
|
9078
9173
|
return "evm-local";
|
|
9079
9174
|
}
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9175
|
+
printOut("Wallet backend (who holds the Agent's signer key):");
|
|
9176
|
+
printOut(
|
|
9177
|
+
" 1. evm-local [default] \u2014 encrypted local keystore under .studio/; simplest, works everywhere"
|
|
9178
|
+
);
|
|
9179
|
+
printOut(
|
|
9180
|
+
" 2. twak \u2014 Trust Wallet CLI wallet; forces container packaging for deploys"
|
|
9181
|
+
);
|
|
9182
|
+
printOut(
|
|
9183
|
+
" 3. altana \u2014 bounded session signer; incompatible with pieverse-llm and paid b402 selling"
|
|
9184
|
+
);
|
|
9185
|
+
const answer = (await promptUser("Wallet backend [1-3, Enter = evm-local]: ")).trim().toLowerCase();
|
|
9186
|
+
if (answer === "2" || answer === "twak") return "twak";
|
|
9187
|
+
if (answer === "3" || answer === "altana") return "altana";
|
|
9188
|
+
if (answer !== "" && answer !== "1" && answer !== "evm-local") {
|
|
9189
|
+
printErr(`hint: unknown wallet backend '${answer}' \u2014 using evm-local.`);
|
|
9190
|
+
}
|
|
9191
|
+
return "evm-local";
|
|
9084
9192
|
}
|
|
9085
9193
|
async function resolveLlmProviderForWallet(walletKind2, configuredProvider, valueSource, isTty) {
|
|
9086
9194
|
if (walletKind2 !== "altana") {
|
|
@@ -9263,12 +9371,22 @@ function readWalletAddress(studioToml) {
|
|
|
9263
9371
|
async function printFaucetHint(network, address) {
|
|
9264
9372
|
printOut("");
|
|
9265
9373
|
if (network === "bsc-testnet") {
|
|
9266
|
-
const {
|
|
9374
|
+
const {
|
|
9375
|
+
BSC_TESTNET_TBNB_TELEGRAM_FAUCET: BSC_TESTNET_TBNB_TELEGRAM_FAUCET2,
|
|
9376
|
+
BSC_TESTNET_FAUCET_DOCS_URL: BSC_TESTNET_FAUCET_DOCS_URL2,
|
|
9377
|
+
BSC_TESTNET_U_FAUCET_URL: BSC_TESTNET_U_FAUCET_URL4
|
|
9378
|
+
} = await import("@bnbagent/studio-runtime/networks");
|
|
9267
9379
|
printOut(`Your testnet wallet address: ${address}`);
|
|
9268
|
-
printOut("Fund it (free)
|
|
9269
|
-
|
|
9270
|
-
|
|
9271
|
-
|
|
9380
|
+
printOut("Fund it (free):");
|
|
9381
|
+
printOut(
|
|
9382
|
+
` tBNB \u2014 message the official Telegram bot ${BSC_TESTNET_TBNB_TELEGRAM_FAUCET2}`
|
|
9383
|
+
);
|
|
9384
|
+
printOut(
|
|
9385
|
+
` send: "I would like to get tBNB to my wallet ${address}"`
|
|
9386
|
+
);
|
|
9387
|
+
printOut(" (up to 0.3 tBNB per day; it replies with the tx hash)");
|
|
9388
|
+
printOut(` more ways to get tBNB: ${BSC_TESTNET_FAUCET_DOCS_URL2}`);
|
|
9389
|
+
printOut(` $U \u2014 ${BSC_TESTNET_U_FAUCET_URL4}`);
|
|
9272
9390
|
printOut("(Faucets are needed only for paid models / on-chain settle.");
|
|
9273
9391
|
printOut(" The default `auto/free` LLM model and AgentCore deploy");
|
|
9274
9392
|
printOut(" do NOT require any funds.)");
|
|
@@ -9632,18 +9750,26 @@ function printMainTwakWalletWarning() {
|
|
|
9632
9750
|
);
|
|
9633
9751
|
}
|
|
9634
9752
|
async function onboardIpfsKey(envPath, ipfsKey) {
|
|
9753
|
+
const url = (await promptUser(
|
|
9754
|
+
"\nIPFS pinning-service UPLOAD ENDPOINT for deliverable storage \u2014 REQUIRED before `bag deploy` (e.g. your provider's pin/upload URL or a self-hosted node's /api/v0/add; blank to fill STORAGE_API_URL later): "
|
|
9755
|
+
)).trim();
|
|
9756
|
+
if (url) {
|
|
9757
|
+
setEnvVar(envPath, "STORAGE_API_URL", url);
|
|
9758
|
+
printOut("\u2713 STORAGE_API_URL written to .studio/.env.local");
|
|
9759
|
+
}
|
|
9635
9760
|
let key = ipfsKey;
|
|
9636
9761
|
if (key === void 0) {
|
|
9637
9762
|
key = (await promptUser(
|
|
9638
|
-
"
|
|
9763
|
+
"IPFS pinning-service write key/JWT (blank to skip, fill STORAGE_API_KEY later): "
|
|
9639
9764
|
)).trim();
|
|
9640
9765
|
}
|
|
9641
9766
|
if (key) {
|
|
9642
9767
|
setEnvVar(envPath, "STORAGE_API_KEY", key);
|
|
9643
9768
|
printOut("\u2713 STORAGE_API_KEY written to .studio/.env.local");
|
|
9644
|
-
}
|
|
9769
|
+
}
|
|
9770
|
+
if (!url || !key) {
|
|
9645
9771
|
printErr(
|
|
9646
|
-
"hint: set STORAGE_API_URL (your pinning service's upload endpoint) and STORAGE_API_KEY (its write key/JWT)\n in .studio/.env.local before `bag dev`, or re-scaffold with --storage-provider local for offline dev."
|
|
9772
|
+
"hint: set STORAGE_API_URL (your pinning service's upload endpoint) and STORAGE_API_KEY (its write key/JWT)\n in .studio/.env.local before `bag dev`, or re-scaffold with --storage-provider local for offline dev.\n `bag deploy prepare` blocks (CRITICAL) until STORAGE_API_URL is set."
|
|
9647
9773
|
);
|
|
9648
9774
|
}
|
|
9649
9775
|
}
|
|
@@ -9665,7 +9791,7 @@ function printCampaignIntro() {
|
|
|
9665
9791
|
);
|
|
9666
9792
|
}
|
|
9667
9793
|
function printTwakNotice(destination = "self") {
|
|
9668
|
-
const deployLine = destination === "platform" ? " \xB7 DEPLOY (managed platform): builds + pushes the arm64 twak image\n (Node + the twak CLI) FROM YOUR MACHINE \u2014 local Docker is\n REQUIRED (no CodeBuild fallback on this path); start Docker Desktop." : " \xB7 RUN/DEPLOY: local `bag dev` runs the agent IN-PROCESS by default\n (`tsx src/
|
|
9794
|
+
const deployLine = destination === "platform" ? " \xB7 DEPLOY (managed platform): builds + pushes the arm64 twak image\n (Node + the twak CLI) FROM YOUR MACHINE \u2014 local Docker is\n REQUIRED (no CodeBuild fallback on this path); start Docker Desktop." : " \xB7 RUN/DEPLOY: local `bag dev` runs the agent IN-PROCESS by default\n (`tsx src/unifiedMain.ts`, no Docker); `bag dev --container` runs it via\n `agentcore dev` in Docker for image parity. DEPLOY builds the twak\n container image (Node + the twak CLI) via AWS CodeBuild \u2014\n Docker is optional locally. `bag init` already configured\n build=Container + a Dockerfile.";
|
|
9669
9795
|
printOut(
|
|
9670
9796
|
`
|
|
9671
9797
|
NOTE \u2014 wallet.kind = "twak" (Trust Wallet Agent Kit, CLI >= ${TWAK_CLI_VERSION}):
|
|
@@ -9772,9 +9898,9 @@ function entrypointHint(faces) {
|
|
|
9772
9898
|
return "app/agent/src/mcpMain.ts = MCP entrypoint (build your value here)";
|
|
9773
9899
|
}
|
|
9774
9900
|
if (faces.length === 1 && hasX402Face(faces)) {
|
|
9775
|
-
return "app/agent/src/
|
|
9901
|
+
return "app/agent/src/unifiedMain.ts = X402-only runtime entrypoint (build your value here)";
|
|
9776
9902
|
}
|
|
9777
|
-
return "app/agent/src/
|
|
9903
|
+
return "app/agent/src/unifiedMain.ts + executor.ts = A2A entrypoint (build your value here)";
|
|
9778
9904
|
}
|
|
9779
9905
|
function hasVendoredTarballs(agentDir) {
|
|
9780
9906
|
const vendor = path23.join(agentDir, "vendor");
|
|
@@ -9822,18 +9948,17 @@ function printCompactNextSteps(name, o = {}) {
|
|
|
9822
9948
|
" pnpm install # one-time: install the agent dependencies"
|
|
9823
9949
|
);
|
|
9824
9950
|
}
|
|
9951
|
+
printOut(" bag doctor # verify config + env before funding");
|
|
9952
|
+
printOut(" bag dev # run the Agent locally");
|
|
9825
9953
|
if (destination === "platform") {
|
|
9826
|
-
printOut(" bag dev # run the Agent locally");
|
|
9827
9954
|
printOut(
|
|
9828
9955
|
" bag deploy --provider bnb # Agent \u2192 managed platform (48h testnet trial)"
|
|
9829
9956
|
);
|
|
9830
9957
|
} else if (runtime === "azure-foundry") {
|
|
9831
|
-
printOut(" bag dev # run the Agent locally");
|
|
9832
9958
|
printOut(
|
|
9833
9959
|
" bag deploy --provider azure # Agent \u2192 Azure AI Foundry (delegated to bnbagent-deploy; browser login, no azd)"
|
|
9834
9960
|
);
|
|
9835
9961
|
} else {
|
|
9836
|
-
printOut(" agentcore dev # run the Agent locally on AgentCore");
|
|
9837
9962
|
printOut(" bag deploy --provider aws # Agent \u2192 AgentCore");
|
|
9838
9963
|
}
|
|
9839
9964
|
printOut("");
|
|
@@ -9963,19 +10088,7 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9963
10088
|
printOut(" # is `auto/free` (Free) \u2014 no funding required to start.");
|
|
9964
10089
|
printOut(" bag llm activate");
|
|
9965
10090
|
printOut("");
|
|
9966
|
-
|
|
9967
|
-
" # 4. (optional) fund the wallet \u2014 only when you need paid model / deploy / publish:"
|
|
9968
|
-
);
|
|
9969
|
-
printOut(
|
|
9970
|
-
" # testnet: send testnet BNB (gas) + testnet U to the address above"
|
|
9971
|
-
);
|
|
9972
|
-
printOut(" # mainnet: swap a small amount via PancakeSwap:");
|
|
9973
|
-
printOut(
|
|
9974
|
-
" # https://pancakeswap.finance/swap?outputCurrency=0xcE24439F2D9C6a2289F741120FE202248B666666"
|
|
9975
|
-
);
|
|
9976
|
-
printOut(" # Then: bag llm topup --amount N (allocate paid credits)");
|
|
9977
|
-
printOut("");
|
|
9978
|
-
nextStep = 5;
|
|
10091
|
+
nextStep = 4;
|
|
9979
10092
|
} else {
|
|
9980
10093
|
const keyEnv = PROVIDER_KEY_ENV[provider];
|
|
9981
10094
|
if (keyEnv) {
|
|
@@ -9987,6 +10100,26 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9987
10100
|
}
|
|
9988
10101
|
nextStep = 4;
|
|
9989
10102
|
}
|
|
10103
|
+
printOut(` # ${nextStep}. verify + run the agent locally (no funds needed)`);
|
|
10104
|
+
printOut(" bag doctor # diagnose config + env; fix FAILs before deploy");
|
|
10105
|
+
printOut(" bag dev # serve the Agent locally for a smoke test");
|
|
10106
|
+
nextStep += 1;
|
|
10107
|
+
if (provider === "pieverse-llm") {
|
|
10108
|
+
printOut("");
|
|
10109
|
+
printOut(
|
|
10110
|
+
` # ${nextStep}. (optional) fund the wallet \u2014 only when you need paid model / deploy / publish:`
|
|
10111
|
+
);
|
|
10112
|
+
printOut(
|
|
10113
|
+
" # testnet: send testnet BNB (gas) + testnet U to the address above"
|
|
10114
|
+
);
|
|
10115
|
+
printOut(" # mainnet: swap a small amount via PancakeSwap:");
|
|
10116
|
+
printOut(
|
|
10117
|
+
" # https://pancakeswap.finance/swap?outputCurrency=0xcE24439F2D9C6a2289F741120FE202248B666666"
|
|
10118
|
+
);
|
|
10119
|
+
printOut(" # Then: bag llm topup --amount N (allocate paid credits)");
|
|
10120
|
+
nextStep += 1;
|
|
10121
|
+
}
|
|
10122
|
+
printOut("");
|
|
9990
10123
|
printOut(
|
|
9991
10124
|
` # ${nextStep}. review ERC-8183 pricing in studio.toml [payments.erc8183]`
|
|
9992
10125
|
);
|
|
@@ -9994,10 +10127,6 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9994
10127
|
" # (price was selected at init; `bag config set payments.erc8183.price 0` explicitly switches to FREE)"
|
|
9995
10128
|
);
|
|
9996
10129
|
nextStep += 1;
|
|
9997
|
-
printOut(` # ${nextStep}. verify + run the agent locally`);
|
|
9998
|
-
printOut(" bag doctor");
|
|
9999
|
-
printOut(" bag dev");
|
|
10000
|
-
nextStep += 1;
|
|
10001
10130
|
if (destination === "platform") {
|
|
10002
10131
|
printOut(
|
|
10003
10132
|
` # ${nextStep}. deploy: app/agent \u2192 managed platform (48h testnet trial)`
|
|
@@ -10298,6 +10427,11 @@ function runtimeEnvKeysCore(cfg, resolvable) {
|
|
|
10298
10427
|
if (resolvable("RPC_URL")) {
|
|
10299
10428
|
keys.push("RPC_URL");
|
|
10300
10429
|
}
|
|
10430
|
+
const runtimeName = String(tableOf8(cfg, "stack").runtime ?? "agentcore");
|
|
10431
|
+
const publicUrlKeys = runtimeName === "azure-foundry" ? ["BNBAGENT_PUBLIC_URL"] : ["BNBAGENT_PUBLIC_URL", "AGENT_PUBLIC_URL"];
|
|
10432
|
+
for (const key of publicUrlKeys) {
|
|
10433
|
+
if (resolvable(key)) keys.push(key);
|
|
10434
|
+
}
|
|
10301
10435
|
for (const key of PAYMASTER_URL_ENV_KEYS) {
|
|
10302
10436
|
if (resolvable(key)) keys.push(key);
|
|
10303
10437
|
}
|
|
@@ -10306,8 +10440,7 @@ function runtimeEnvKeysCore(cfg, resolvable) {
|
|
|
10306
10440
|
if (resolvable(key)) keys.push(key);
|
|
10307
10441
|
}
|
|
10308
10442
|
}
|
|
10309
|
-
|
|
10310
|
-
if (runtime === "agentcore" && x402SellerUsesB402(cfg)) {
|
|
10443
|
+
if (X402_CAPABLE_RUNTIMES.has(runtimeName) && x402SellerUsesB402(cfg)) {
|
|
10311
10444
|
for (const key of B402_RUNTIME_KEYS) {
|
|
10312
10445
|
if (resolvable(key)) keys.push(key);
|
|
10313
10446
|
}
|
|
@@ -10413,8 +10546,12 @@ function agentFaces(workspaceRoot) {
|
|
|
10413
10546
|
const cfg = loadAgentToml2(workspaceRoot);
|
|
10414
10547
|
return stackFaces(tableOf9(cfg, "stack"), tableOf9(cfg, "payments"));
|
|
10415
10548
|
}
|
|
10416
|
-
function localEntryFile(faces) {
|
|
10417
|
-
|
|
10549
|
+
function localEntryFile(faces, agentDir) {
|
|
10550
|
+
const stem2 = entryStemOf(faces);
|
|
10551
|
+
const candidates = [stem2, ...LEGACY_ENTRY_STEMS[stem2]].map(
|
|
10552
|
+
(s) => `src/${s}.ts`
|
|
10553
|
+
);
|
|
10554
|
+
return candidates.find((c2) => isFile10(path24.join(agentDir, c2))) ?? candidates[0];
|
|
10418
10555
|
}
|
|
10419
10556
|
function defaultAgentPort(faces) {
|
|
10420
10557
|
return devPortOf(faces);
|
|
@@ -10786,11 +10923,11 @@ async function cmdDev(opts) {
|
|
|
10786
10923
|
const agentPort = opts.port ?? defaultAgentPort(faces);
|
|
10787
10924
|
const runtime = agentRuntime(workspaceRoot);
|
|
10788
10925
|
const container = Boolean(opts.container);
|
|
10789
|
-
const entryFile = localEntryFile(faces);
|
|
10926
|
+
const entryFile = localEntryFile(faces, agentDir);
|
|
10790
10927
|
const agentFile = path24.join(agentDir, entryFile);
|
|
10791
10928
|
if (!isFile10(agentFile)) {
|
|
10792
10929
|
printErr(
|
|
10793
|
-
`error: Agent entrypoint file ${agentFile} does not exist. [stack] faces = [${faces.join(", ")}], so the entrypoint is ${entryFile} (A2A/X402-only \u2192 src/
|
|
10930
|
+
`error: Agent entrypoint file ${agentFile} does not exist. [stack] faces = [${faces.join(", ")}], so the entrypoint is ${entryFile} (A2A/X402-only \u2192 src/unifiedMain.ts, MCP \u2192 src/mcpMain.ts, A2A+MCP \u2192 src/dualMain.ts; legacy src/main.ts scaffolds still run). Run \`bag init\` to scaffold the workspace.`
|
|
10794
10931
|
);
|
|
10795
10932
|
return 2;
|
|
10796
10933
|
}
|
|
@@ -10929,7 +11066,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10929
11066
|
printOut(
|
|
10930
11067
|
`bag dev: starting Agent in-process (\`tsx ${args.join(" ")}\` on :${agentPort}, no Docker \u2014 the entrypoint self-serves; cwd=${agentDir}, runner=${runner2})`
|
|
10931
11068
|
);
|
|
10932
|
-
if (runtime === RUNTIME_AZURE_FOUNDRY) {
|
|
11069
|
+
if (runtime === RUNTIME_AZURE_FOUNDRY && isFile10(path24.join(agentDir, "src/foundryMain.ts"))) {
|
|
10933
11070
|
printOut(
|
|
10934
11071
|
"bag dev: azure-foundry serves this local A2A/MCP entrypoint in-process; src/foundryMain.ts is the deploy-only Foundry host (the entrypoint `bag doctor` reports) and never runs here."
|
|
10935
11072
|
);
|
|
@@ -11102,7 +11239,10 @@ async function checkAgentPackagePresent(root, target) {
|
|
|
11102
11239
|
const cfg = loadAgentToml(root);
|
|
11103
11240
|
const faces = stackFaces(tableOf2(cfg, "stack"), tableOf2(cfg, "payments"));
|
|
11104
11241
|
const stem2 = entryStemOf(faces);
|
|
11105
|
-
const
|
|
11242
|
+
const effectiveStem = [stem2, ...LEGACY_ENTRY_STEMS[stem2]].find(
|
|
11243
|
+
(s) => isFile11(path25.join(agentRoot2, `src/${s}.ts`))
|
|
11244
|
+
) ?? stem2;
|
|
11245
|
+
const sourceEntries = [`src/${effectiveStem}.ts`];
|
|
11106
11246
|
if (stem2 === "dualMain") {
|
|
11107
11247
|
sourceEntries.push("src/mcpMain.ts");
|
|
11108
11248
|
}
|
|
@@ -11120,7 +11260,7 @@ async function checkAgentPackagePresent(root, target) {
|
|
|
11120
11260
|
}
|
|
11121
11261
|
];
|
|
11122
11262
|
}
|
|
11123
|
-
const distEntries = [`dist/${
|
|
11263
|
+
const distEntries = [`dist/${effectiveStem}.js`];
|
|
11124
11264
|
if (stem2 === "dualMain") {
|
|
11125
11265
|
distEntries.push("dist/mcpMain.js");
|
|
11126
11266
|
}
|
|
@@ -11600,12 +11740,12 @@ function x402SellerRailChecks(agentRoot2, cfg, target) {
|
|
|
11600
11740
|
}
|
|
11601
11741
|
const destination = String(tableOf2(cfg, "deploy").destination ?? "self");
|
|
11602
11742
|
const stackRuntime2 = String(tableOf2(cfg, "stack").runtime ?? "agentcore");
|
|
11603
|
-
if (rails.x402 && (free || credentials.complete) &&
|
|
11604
|
-
const blocking = target
|
|
11743
|
+
if (rails.x402 && (free || credentials.complete) && !target.startsWith("platform") && !(X402_CAPABLE_RUNTIMES.has(target) && X402_CAPABLE_RUNTIMES.has(stackRuntime2))) {
|
|
11744
|
+
const blocking = !X402_CAPABLE_RUNTIMES.has(target) ? target : stackRuntime2;
|
|
11605
11745
|
out.push({
|
|
11606
11746
|
level: Level.WARNING,
|
|
11607
11747
|
name: "x402_forced_dormant_runtime",
|
|
11608
|
-
message: `x402 pricing is ready, but the ${blocking} runtime has no x402 path; this target is forced dormant. Deploy to AgentCore (managed platform or self-hosted) to activate the rail.`,
|
|
11748
|
+
message: `x402 pricing is ready, but the ${blocking} runtime has no x402 path; this target is forced dormant. Deploy to AgentCore or Azure Foundry (managed platform or self-hosted) to activate the rail.`,
|
|
11609
11749
|
details: { destination, target, stackRuntime: stackRuntime2 }
|
|
11610
11750
|
});
|
|
11611
11751
|
}
|
|
@@ -11656,7 +11796,7 @@ async function checkCommerceReady(root, target) {
|
|
|
11656
11796
|
return out;
|
|
11657
11797
|
}
|
|
11658
11798
|
async function checkDeployCliRunnable(_root, target) {
|
|
11659
|
-
if (target !== "agentcore") {
|
|
11799
|
+
if (target !== "agentcore" && target !== "platform" && target !== "platform-azure") {
|
|
11660
11800
|
return [];
|
|
11661
11801
|
}
|
|
11662
11802
|
const override = (process.env.BNBAGENT_DEPLOY_COMMAND ?? "").trim();
|
|
@@ -13062,7 +13202,11 @@ import {
|
|
|
13062
13202
|
findSubProjectRoot as findSubProjectRoot13,
|
|
13063
13203
|
loadStudioToml as loadStudioToml17
|
|
13064
13204
|
} from "@bnbagent/studio-runtime/config";
|
|
13065
|
-
import {
|
|
13205
|
+
import {
|
|
13206
|
+
BSC_TESTNET_FAUCET_DOCS_URL,
|
|
13207
|
+
BSC_TESTNET_TBNB_TELEGRAM_FAUCET,
|
|
13208
|
+
BSC_TESTNET_U_FAUCET_URL as BSC_TESTNET_U_FAUCET_URL2
|
|
13209
|
+
} from "@bnbagent/studio-runtime/networks";
|
|
13066
13210
|
|
|
13067
13211
|
// src/cli/_deploy/checks/warning.ts
|
|
13068
13212
|
import * as crypto4 from "crypto";
|
|
@@ -13372,7 +13516,10 @@ var checkPlatformEntrypointPresent = async (root, _target) => {
|
|
|
13372
13516
|
const data = loadAgent(root);
|
|
13373
13517
|
const faces = stackFaces(tableOf11(data, "stack"), tableOf11(data, "payments"));
|
|
13374
13518
|
const stem2 = entryStemOf(faces);
|
|
13375
|
-
const
|
|
13519
|
+
const effectiveStem = [stem2, ...LEGACY_ENTRY_STEMS[stem2]].find(
|
|
13520
|
+
(s) => fs35.existsSync(path34.join(agentRoot(root), "src", `${s}.ts`))
|
|
13521
|
+
) ?? stem2;
|
|
13522
|
+
const filenames = [`${effectiveStem}.ts`];
|
|
13376
13523
|
if (stem2 === "dualMain") filenames.push("mcpMain.ts");
|
|
13377
13524
|
const filename = filenames.find(
|
|
13378
13525
|
(candidate) => !fs35.existsSync(path34.join(agentRoot(root), "src", candidate))
|
|
@@ -13536,8 +13683,14 @@ var checkPlatformFundingHint = async (_root, _target) => [
|
|
|
13536
13683
|
{
|
|
13537
13684
|
level: Level.INFO,
|
|
13538
13685
|
name: "platform_funding_hint",
|
|
13539
|
-
message: `testnet trial \u2014 keep a little tBNB for gas and testnet $U for commerce.
|
|
13540
|
-
details: {
|
|
13686
|
+
message: `testnet trial \u2014 keep a little tBNB for gas and testnet $U for commerce. tBNB: message ${BSC_TESTNET_TBNB_TELEGRAM_FAUCET} (more options: ${BSC_TESTNET_FAUCET_DOCS_URL}) \xB7 $U: ${BSC_TESTNET_U_FAUCET_URL2}`,
|
|
13687
|
+
details: {
|
|
13688
|
+
faucets: [
|
|
13689
|
+
BSC_TESTNET_TBNB_TELEGRAM_FAUCET,
|
|
13690
|
+
BSC_TESTNET_FAUCET_DOCS_URL,
|
|
13691
|
+
BSC_TESTNET_U_FAUCET_URL2
|
|
13692
|
+
]
|
|
13693
|
+
}
|
|
13541
13694
|
}
|
|
13542
13695
|
];
|
|
13543
13696
|
var criticalChecks = [
|
|
@@ -13546,6 +13699,7 @@ var criticalChecks = [
|
|
|
13546
13699
|
checkPlatformTestnetOnly,
|
|
13547
13700
|
checkPlatformSlugValid,
|
|
13548
13701
|
checkPlatformLoggedIn,
|
|
13702
|
+
checkDeployCliRunnable,
|
|
13549
13703
|
checkPlatformDockerAvailable,
|
|
13550
13704
|
checkPlatformStorageEndpoint,
|
|
13551
13705
|
checkTwakCustomContractsUnsupported,
|
|
@@ -14308,7 +14462,7 @@ async function platformAgent(opts) {
|
|
|
14308
14462
|
const root = opts.root;
|
|
14309
14463
|
const backend = opts.backend ?? "aws";
|
|
14310
14464
|
const isTty = opts.isTty ?? stdinIsTty;
|
|
14311
|
-
const
|
|
14465
|
+
const ask2 = opts.promptUser ?? promptUser;
|
|
14312
14466
|
warn(
|
|
14313
14467
|
`note: deploying to the BNB Chain managed platform (backend=${backend}) \u2014 a 48h TESTNET trial sandbox (network is forced to bsc-testnet; the runtime is auto-reclaimed at 48h). Not a production seller.`
|
|
14314
14468
|
);
|
|
@@ -14317,12 +14471,6 @@ async function platformAgent(opts) {
|
|
|
14317
14471
|
const cfg2 = loadAgentCfg(root);
|
|
14318
14472
|
const faces2 = stackFaces(tableOf12(cfg2, "stack"), tableOf12(cfg2, "payments"));
|
|
14319
14473
|
const protocol2 = nativeProtocolOf(faces2);
|
|
14320
|
-
if (hasX402Face(faces2)) {
|
|
14321
|
-
warn(
|
|
14322
|
-
"error: x402 publication is not supported on the managed Azure backend. No build or upload was started."
|
|
14323
|
-
);
|
|
14324
|
-
return 1;
|
|
14325
|
-
}
|
|
14326
14474
|
const runtimeProfile = protocol2 === "A2A" ? "foundry-responses-v1" : "foundry-invocations-v1";
|
|
14327
14475
|
const capability = await platformCmd(["capabilities"], { json: true });
|
|
14328
14476
|
const platform = isJsonObject(capability.data.platform) ? capability.data.platform : {};
|
|
@@ -14336,6 +14484,12 @@ async function platformAgent(opts) {
|
|
|
14336
14484
|
);
|
|
14337
14485
|
return capability.code || 1;
|
|
14338
14486
|
}
|
|
14487
|
+
if (hasX402Face(faces2) && azure.x402 !== true) {
|
|
14488
|
+
warn(
|
|
14489
|
+
"error: this platform deployment does not accept x402 publication on the managed Azure backend yet. No build or upload was started. Deploy without the X402 face, or self-host the x402 gateway (`bag deploy --provider azure` + docs/guides/self-hosted-x402-gateway-azure.md)."
|
|
14490
|
+
);
|
|
14491
|
+
return 1;
|
|
14492
|
+
}
|
|
14339
14493
|
}
|
|
14340
14494
|
const campaignProbe = opts.campaignActive ?? (async () => null);
|
|
14341
14495
|
const trialRes = await platformCmd(["trial"], { json: true });
|
|
@@ -14364,7 +14518,7 @@ async function platformAgent(opts) {
|
|
|
14364
14518
|
const rc = await termsConsentGate(root, {
|
|
14365
14519
|
acceptRisk: opts.acceptRisk ?? false,
|
|
14366
14520
|
isTty,
|
|
14367
|
-
promptUser:
|
|
14521
|
+
promptUser: ask2
|
|
14368
14522
|
});
|
|
14369
14523
|
if (rc !== null) {
|
|
14370
14524
|
return rc;
|
|
@@ -14375,7 +14529,7 @@ async function platformAgent(opts) {
|
|
|
14375
14529
|
const confirm = opts.confirmPackaging ?? ((r, p) => confirmPackagingDefault(r, p, {
|
|
14376
14530
|
acceptRisk: opts.acceptRisk ?? false,
|
|
14377
14531
|
isTty,
|
|
14378
|
-
promptUser:
|
|
14532
|
+
promptUser: ask2
|
|
14379
14533
|
}));
|
|
14380
14534
|
const rc = await confirm(root, packaging);
|
|
14381
14535
|
if (rc !== null && rc !== 0) {
|
|
@@ -16861,12 +17015,13 @@ import { pieverseKeyHash as pieverseKeyHash4 } from "@bnbagent/studio-runtime/ll
|
|
|
16861
17015
|
import {
|
|
16862
17016
|
BSC_MAINNET_MIN_BNB,
|
|
16863
17017
|
BSC_MAINNET_MIN_U,
|
|
16864
|
-
BSC_TESTNET_FAUCET_URLS as BSC_TESTNET_FAUCET_URLS3,
|
|
16865
17018
|
BSC_TESTNET_MIN_BNB,
|
|
16866
17019
|
BSC_TESTNET_MIN_U,
|
|
17020
|
+
BSC_TESTNET_U_FAUCET_URL as BSC_TESTNET_U_FAUCET_URL3,
|
|
16867
17021
|
ERC8183_SUBMIT_GAS_RESERVE_BNB,
|
|
16868
17022
|
fromRaw as fromRaw3,
|
|
16869
|
-
getNetwork as getNetwork9
|
|
17023
|
+
getNetwork as getNetwork9,
|
|
17024
|
+
tbnbFaucetHint as tbnbFaucetHint3
|
|
16870
17025
|
} from "@bnbagent/studio-runtime/networks";
|
|
16871
17026
|
import { listModels as listModels2 } from "@bnbagent/studio-runtime/pieverse";
|
|
16872
17027
|
import * as walletRt5 from "@bnbagent/studio-runtime/wallet";
|
|
@@ -16971,6 +17126,9 @@ async function cmdDoctor(opts) {
|
|
|
16971
17126
|
checks.push(...await check8004(projectRoot, data, opts.network));
|
|
16972
17127
|
const destination = String(tableOf14(data, "deploy").destination ?? "self").trim().toLowerCase();
|
|
16973
17128
|
checks.push(...await checkDeployTools(data, destination));
|
|
17129
|
+
checks.push(
|
|
17130
|
+
...await checkPlatformZipBundle(data, destination, projectRoot)
|
|
17131
|
+
);
|
|
16974
17132
|
checks.push(...checkAgentsMdSkillTrigger(projectRoot));
|
|
16975
17133
|
printChecks(checks);
|
|
16976
17134
|
return checks.some((c2) => c2.status === FAIL) ? 1 : 0;
|
|
@@ -17053,16 +17211,12 @@ function checkAppMain(projectRootArg2) {
|
|
|
17053
17211
|
}
|
|
17054
17212
|
}
|
|
17055
17213
|
const stack = tableOf14(config, "stack");
|
|
17214
|
+
const faces = stackFaces(stack, tableOf14(config, "payments"));
|
|
17215
|
+
const stem2 = entryStemOf(faces);
|
|
17056
17216
|
const runtime = String(stack.runtime ?? "").toLowerCase();
|
|
17057
|
-
|
|
17058
|
-
|
|
17059
|
-
|
|
17060
|
-
} else if (runtime === "agentcore") {
|
|
17061
|
-
const faces = stackFaces(stack, tableOf14(config, "payments"));
|
|
17062
|
-
entrypoint = `src/${entryStemOf(faces)}.ts`;
|
|
17063
|
-
} else {
|
|
17064
|
-
entrypoint = "src/main.ts";
|
|
17065
|
-
}
|
|
17217
|
+
const legacyStems = runtime === "azure-foundry" && stem2 === "unifiedMain" ? ["foundryMain", "main"] : LEGACY_ENTRY_STEMS[stem2];
|
|
17218
|
+
const candidates = [stem2, ...legacyStems].map((s) => `src/${s}.ts`);
|
|
17219
|
+
const entrypoint = candidates.find((c2) => isFile17(path39.join(agentDir, c2))) ?? candidates[0];
|
|
17066
17220
|
const entryFile = path39.join(agentDir, entrypoint);
|
|
17067
17221
|
if (!isFile17(entryFile)) {
|
|
17068
17222
|
return [
|
|
@@ -17073,7 +17227,7 @@ function checkAppMain(projectRootArg2) {
|
|
|
17073
17227
|
}
|
|
17074
17228
|
];
|
|
17075
17229
|
}
|
|
17076
|
-
const detail =
|
|
17230
|
+
const detail = entrypoint === "src/foundryMain.ts" ? `${entrypoint} (deploy entrypoint; \`bag dev\` serves src/main.ts or src/mcpMain.ts locally)` : entrypoint;
|
|
17077
17231
|
return [{ name: "agent entrypoint", status: PASS, detail }];
|
|
17078
17232
|
}
|
|
17079
17233
|
function checkAgentcoreName(projectRoot) {
|
|
@@ -17851,7 +18005,8 @@ async function checkBalances(projectRoot, data, networkOverride) {
|
|
|
17851
18005
|
const isMainnet = name === "bsc-mainnet";
|
|
17852
18006
|
const minBnb = isTestnet ? BSC_TESTNET_MIN_BNB : isMainnet ? BSC_MAINNET_MIN_BNB : 0;
|
|
17853
18007
|
const minBnbWei = BigInt(Math.round(minBnb * 1e6)) * 10n ** 12n;
|
|
17854
|
-
const
|
|
18008
|
+
const bnbFaucetHint = isTestnet ? ` \u2014 ${tbnbFaucetHint3(address)}` : "";
|
|
18009
|
+
const uFaucetHint = isTestnet ? ` \u2014 $U faucet: ${BSC_TESTNET_U_FAUCET_URL3}` : "";
|
|
17855
18010
|
const bnbRaw = await readNativeBalanceRaw(address, name);
|
|
17856
18011
|
const reserve = ERC8183_SUBMIT_GAS_RESERVE_BNB;
|
|
17857
18012
|
const reserveHint = ` (each on-chain action reserves \u2248 ${reserve} BNB worst-case)`;
|
|
@@ -17872,7 +18027,7 @@ async function checkBalances(projectRoot, data, networkOverride) {
|
|
|
17872
18027
|
out.push({
|
|
17873
18028
|
name: "wallet BNB balance",
|
|
17874
18029
|
status: WARN,
|
|
17875
|
-
detail: `${bnbRaw} wei @ ${address} \u2014 need \u2265 ${minBnb} BNB on ${name} for 8183 escrow / ERC-8004 register${reserveHint}${
|
|
18030
|
+
detail: `${bnbRaw} wei @ ${address} \u2014 need \u2265 ${minBnb} BNB on ${name} for 8183 escrow / ERC-8004 register${reserveHint}${bnbFaucetHint}`
|
|
17876
18031
|
});
|
|
17877
18032
|
}
|
|
17878
18033
|
const uToken = net2.tokens.U;
|
|
@@ -17898,7 +18053,7 @@ async function checkBalances(projectRoot, data, networkOverride) {
|
|
|
17898
18053
|
out.push({
|
|
17899
18054
|
name: "wallet U balance",
|
|
17900
18055
|
status: WARN,
|
|
17901
|
-
detail: `${uRaw} raw @ ${address} \u2014 need \u2265 ${minU} U on ${name} for one auto-topup chunk${
|
|
18056
|
+
detail: `${uRaw} raw @ ${address} \u2014 need \u2265 ${minU} U on ${name} for one auto-topup chunk${uFaucetHint}`
|
|
17902
18057
|
});
|
|
17903
18058
|
}
|
|
17904
18059
|
return out;
|
|
@@ -18047,11 +18202,7 @@ async function checkDeployTools(data, destination) {
|
|
|
18047
18202
|
});
|
|
18048
18203
|
if (destination === "platform") {
|
|
18049
18204
|
const out = [
|
|
18050
|
-
|
|
18051
|
-
name: "deploy: bnbagent-deploy",
|
|
18052
|
-
status: INFO,
|
|
18053
|
-
detail: "[deploy].destination='platform' also delegates to bnbagent-deploy (bunx); `bag deploy prepare` verifies it."
|
|
18054
|
-
},
|
|
18205
|
+
emit2(await checkBunx()),
|
|
18055
18206
|
{
|
|
18056
18207
|
name: "deploy: AWS credentials",
|
|
18057
18208
|
status: INFO,
|
|
@@ -18081,6 +18232,49 @@ async function checkDeployTools(data, destination) {
|
|
|
18081
18232
|
}
|
|
18082
18233
|
return (await deployChecks()).map(emit2);
|
|
18083
18234
|
}
|
|
18235
|
+
async function checkPlatformZipBundle(data, destination, projectRootArg2) {
|
|
18236
|
+
if (destination !== "platform" || platformPackagingRequiresContainer(data)) {
|
|
18237
|
+
return [];
|
|
18238
|
+
}
|
|
18239
|
+
let projectRoot = projectRootArg2;
|
|
18240
|
+
const parent = path39.dirname(projectRoot);
|
|
18241
|
+
if (isFile17(path39.join(parent, "agent", "studio.toml"))) {
|
|
18242
|
+
projectRoot = parent;
|
|
18243
|
+
}
|
|
18244
|
+
const agentDir = path39.join(projectRoot, "agent");
|
|
18245
|
+
if (!isFile17(path39.join(agentDir, "studio.toml"))) {
|
|
18246
|
+
return [];
|
|
18247
|
+
}
|
|
18248
|
+
if (!fs39.existsSync(path39.join(agentDir, "node_modules"))) {
|
|
18249
|
+
return [
|
|
18250
|
+
{
|
|
18251
|
+
name: "deploy: zip bundle",
|
|
18252
|
+
status: INFO,
|
|
18253
|
+
detail: "skipped \u2014 dependencies not installed yet (run `pnpm install`); re-run `bag doctor` to dry-run the zip bundle."
|
|
18254
|
+
}
|
|
18255
|
+
];
|
|
18256
|
+
}
|
|
18257
|
+
const stack = tableOf14(data, "stack");
|
|
18258
|
+
const faces = stackFaces(stack, tableOf14(data, "payments"));
|
|
18259
|
+
try {
|
|
18260
|
+
await dryRunBundle(agentDir, { protocols: faces });
|
|
18261
|
+
} catch (exc) {
|
|
18262
|
+
return [
|
|
18263
|
+
{
|
|
18264
|
+
name: "deploy: zip bundle",
|
|
18265
|
+
status: WARN,
|
|
18266
|
+
detail: errMsg3(exc)
|
|
18267
|
+
}
|
|
18268
|
+
];
|
|
18269
|
+
}
|
|
18270
|
+
return [
|
|
18271
|
+
{
|
|
18272
|
+
name: "deploy: zip bundle",
|
|
18273
|
+
status: PASS,
|
|
18274
|
+
detail: "esbuild dry run OK \u2014 the agent bundles for the platform ZIP runtime."
|
|
18275
|
+
}
|
|
18276
|
+
];
|
|
18277
|
+
}
|
|
18084
18278
|
function checkAgentsMdSkillTrigger(projectRoot) {
|
|
18085
18279
|
const ws = findStudioWorkspaceRoot4(projectRoot);
|
|
18086
18280
|
if (ws === null) {
|
|
@@ -18259,9 +18453,9 @@ import {
|
|
|
18259
18453
|
updateServiceEndpoint as updateServiceEndpoint2
|
|
18260
18454
|
} from "@bnbagent/studio-runtime/erc8004";
|
|
18261
18455
|
import {
|
|
18262
|
-
BSC_TESTNET_FAUCET_URLS as BSC_TESTNET_FAUCET_URLS4,
|
|
18263
18456
|
fromRaw as fromRaw4,
|
|
18264
|
-
getNetwork as getNetwork10
|
|
18457
|
+
getNetwork as getNetwork10,
|
|
18458
|
+
tbnbFaucetHint as tbnbFaucetHint4
|
|
18265
18459
|
} from "@bnbagent/studio-runtime/networks";
|
|
18266
18460
|
import * as walletRt6 from "@bnbagent/studio-runtime/wallet";
|
|
18267
18461
|
import { Option as Option5 } from "commander";
|
|
@@ -18423,8 +18617,7 @@ async function precheckRegisterGas(wallet, network) {
|
|
|
18423
18617
|
if (balance >= REGISTER_MIN_BNB) {
|
|
18424
18618
|
return null;
|
|
18425
18619
|
}
|
|
18426
|
-
|
|
18427
|
-
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}`;
|
|
18620
|
+
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 \u2014 ${tbnbFaucetHint4(wallet.address)}`;
|
|
18428
18621
|
}
|
|
18429
18622
|
function syncAgentRegistry(agentId, op) {
|
|
18430
18623
|
try {
|
|
@@ -19374,7 +19567,7 @@ async function promptInstallScope() {
|
|
|
19374
19567
|
}
|
|
19375
19568
|
function printNextSteps2() {
|
|
19376
19569
|
printOut(
|
|
19377
|
-
"\nNext: `bag init
|
|
19570
|
+
"\nNext: `bag init myagent` to scaffold a single seller agent project.\nIn your IDE, type /bnbagent-studio to drive any studio task \u2014 the one\ninstalled skill routes everything (its playbooks load on demand).\nSee `bag --help` for the full command surface, or https://github.com/bnb-chain/bnbagent-studio for docs."
|
|
19378
19571
|
);
|
|
19379
19572
|
}
|
|
19380
19573
|
async function installInteractive(flags) {
|
|
@@ -21183,6 +21376,10 @@ async function main(argv) {
|
|
|
21183
21376
|
if (err instanceof CliExit) {
|
|
21184
21377
|
return err.code;
|
|
21185
21378
|
}
|
|
21379
|
+
if (err instanceof Error && err.name === "PromptCancelled") {
|
|
21380
|
+
process.stderr.write("cancelled.\n");
|
|
21381
|
+
return 130;
|
|
21382
|
+
}
|
|
21186
21383
|
if (isCommanderExit(err)) {
|
|
21187
21384
|
return err.exitCode;
|
|
21188
21385
|
}
|