@bnbagent/studio-cli 0.0.6-alpha.2 → 0.0.6-alpha.3
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 +218 -82
- package/dist/{chunk-6EYSXRFD.js → chunk-A7NAGZHR.js} +16 -1
- package/dist/{deployCli-3U2FESF4.js → deployCli-264UE6KB.js} +1 -1
- package/package.json +3 -3
- package/recipes/runtimes/agentcore/code/{{PKG}}/dualMain.ts.tmpl +6 -3
- package/recipes/runtimes/agentcore/code/{{PKG}}/main.ts.tmpl +6 -3
- package/recipes/runtimes/agentcore/code/{{PKG}}/mcpMain.ts.tmpl +7 -5
- package/recipes/runtimes/agentcore/code/{{PKG}}/sellerCore.ts.tmpl +3 -2
- package/skills/bnbagent-studio.md +8 -10
- package/skills/references/bnbagent-studio-adding-to-project.md +1 -1
- package/skills/references/bnbagent-studio-operating.md +4 -5
- package/skills/references/bnbagent-studio-scaffolding-agent.md +1 -1
- package/skills/references/bnbagent-studio-selling-via-8183.md +5 -5
- package/skills/references/bnbagent-studio-selling-via-b402.md +1 -1
- package/skills/references/bnbagent-studio-use-azure-foundry.md +1 -1
- package/skills/references/bnbagent-studio-use-bnb-trial.md +2 -2
- package/skills/references/bnbagent-studio-using-twak-wallet.md +10 -8
package/dist/bag.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
B402_RUNTIME_KEYS,
|
|
4
4
|
CliExit,
|
|
5
5
|
DEFAULT_B402_PRICE_USD,
|
|
6
|
+
DEFAULT_B402_TESTNET_BASE_URL,
|
|
6
7
|
act,
|
|
7
8
|
agentcoreFlavor,
|
|
8
9
|
b402Credentials,
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
hasA2aFace,
|
|
20
21
|
hasMcpFace,
|
|
21
22
|
hasX402Face,
|
|
23
|
+
isB402TestnetBaseUrl,
|
|
22
24
|
nativeProtocolOf,
|
|
23
25
|
normalizeB402PriceUsd,
|
|
24
26
|
normalizeProtocolFaces,
|
|
@@ -40,7 +42,7 @@ import {
|
|
|
40
42
|
x402SellerIsFree,
|
|
41
43
|
x402SellerPricingState,
|
|
42
44
|
x402SellerUsesB402
|
|
43
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-A7NAGZHR.js";
|
|
44
46
|
import {
|
|
45
47
|
TWAK_CLI_MIN_VERSION,
|
|
46
48
|
TWAK_CLI_VERSION,
|
|
@@ -102,7 +104,7 @@ import {
|
|
|
102
104
|
var CAMPAIGN_DOC_URL = "https://www.bnbchain.org/en/blog/bnb-agent-studio-is-live-on-bnb-chain-ai-agents-from-one-prompt";
|
|
103
105
|
var CAMPAIGN_CHECK_TIMEOUT_MS = 6e3;
|
|
104
106
|
async function fetchCampaignActive() {
|
|
105
|
-
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-
|
|
107
|
+
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-264UE6KB.js");
|
|
106
108
|
const controller = new AbortController();
|
|
107
109
|
const timer = setTimeout(() => controller.abort(), CAMPAIGN_CHECK_TIMEOUT_MS);
|
|
108
110
|
try {
|
|
@@ -2483,7 +2485,7 @@ async function cmdSet(key, rawValue, typeFlag, projectRoot) {
|
|
|
2483
2485
|
const contracts = erc8183ContractOverrideState();
|
|
2484
2486
|
if (contracts.mode === "custom") {
|
|
2485
2487
|
printOut(
|
|
2486
|
-
"ERC-8183 contracts: custom
|
|
2488
|
+
"ERC-8183 contracts: custom contract stack selected with all three address overrides."
|
|
2487
2489
|
);
|
|
2488
2490
|
} else if (contracts.mode === "partial") {
|
|
2489
2491
|
printErr(
|
|
@@ -3197,6 +3199,9 @@ function packageRoot() {
|
|
|
3197
3199
|
}
|
|
3198
3200
|
}
|
|
3199
3201
|
function pnpmVersion() {
|
|
3202
|
+
if ("10.24.0") {
|
|
3203
|
+
return "10.24.0";
|
|
3204
|
+
}
|
|
3200
3205
|
const file = path12.join(packageRoot(), "package.json");
|
|
3201
3206
|
const pkg = JSON.parse(fs13.readFileSync(file, "utf-8"));
|
|
3202
3207
|
const value = String(pkg.packageManager ?? "");
|
|
@@ -3225,6 +3230,46 @@ import * as fs14 from "fs";
|
|
|
3225
3230
|
import * as path13 from "path";
|
|
3226
3231
|
import { envLocalPath as envLocalPath7 } from "@bnbagent/studio-runtime/config";
|
|
3227
3232
|
import { resolveTwakHome } from "@bnbagent/studio-runtime/wallet";
|
|
3233
|
+
|
|
3234
|
+
// src/cli/_twakContractTargets.ts
|
|
3235
|
+
import { resolveNetwork } from "@bnbagent/sdk";
|
|
3236
|
+
var CONTRACT_OVERRIDES = [
|
|
3237
|
+
["ERC8004_REGISTRY_ADDRESS", "registryContract"],
|
|
3238
|
+
["ERC8183_COMMERCE_ADDRESS", "commerceContract"],
|
|
3239
|
+
["ERC8183_ROUTER_ADDRESS", "routerContract"],
|
|
3240
|
+
["ERC8183_POLICY_ADDRESS", "policyContract"]
|
|
3241
|
+
];
|
|
3242
|
+
function twakCustomContractOverrides(networkName, env = process.env) {
|
|
3243
|
+
let network;
|
|
3244
|
+
try {
|
|
3245
|
+
network = resolveNetwork(networkName);
|
|
3246
|
+
} catch {
|
|
3247
|
+
return [];
|
|
3248
|
+
}
|
|
3249
|
+
const erc8183 = erc8183ContractOverrideState(env);
|
|
3250
|
+
const out = [];
|
|
3251
|
+
for (const [envKey, field] of CONTRACT_OVERRIDES) {
|
|
3252
|
+
if (envKey.startsWith("ERC8183_") && erc8183.mode !== "custom") {
|
|
3253
|
+
continue;
|
|
3254
|
+
}
|
|
3255
|
+
const configured = env[envKey]?.trim() ?? "";
|
|
3256
|
+
if (!/^0x[0-9a-fA-F]{40}$/u.test(configured)) {
|
|
3257
|
+
continue;
|
|
3258
|
+
}
|
|
3259
|
+
const canonical = network[field];
|
|
3260
|
+
if (configured.toLowerCase() !== canonical.toLowerCase()) {
|
|
3261
|
+
out.push({ envKey, configured, canonical });
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
return out;
|
|
3265
|
+
}
|
|
3266
|
+
function twakUnsupportedContractOverrides(networkName, env = process.env) {
|
|
3267
|
+
return twakCustomContractOverrides(networkName, env).filter(
|
|
3268
|
+
(item) => item.envKey.startsWith("ERC8183_")
|
|
3269
|
+
);
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
// src/cli/_deploy/checks/twak.ts
|
|
3228
3273
|
var AGENTCORE_DESCRIPTOR = path13.join("agentcore", "agentcore.json");
|
|
3229
3274
|
function isTwak(data) {
|
|
3230
3275
|
return tableOf2(data, "wallet").kind === "twak";
|
|
@@ -3329,6 +3374,26 @@ async function checkTwakCliPresent(root, _target) {
|
|
|
3329
3374
|
}
|
|
3330
3375
|
return [];
|
|
3331
3376
|
}
|
|
3377
|
+
function checkTwakCustomContractsUnsupported(root, _target) {
|
|
3378
|
+
const data = loadAgentToml(root);
|
|
3379
|
+
if (!isTwak(data)) {
|
|
3380
|
+
return [];
|
|
3381
|
+
}
|
|
3382
|
+
const networkName = String(tableOf2(data, "network").default ?? "bsc-testnet");
|
|
3383
|
+
const overrides = twakUnsupportedContractOverrides(networkName);
|
|
3384
|
+
if (overrides.length === 0) {
|
|
3385
|
+
return [];
|
|
3386
|
+
}
|
|
3387
|
+
const keys = overrides.map((item) => item.envKey);
|
|
3388
|
+
return [
|
|
3389
|
+
{
|
|
3390
|
+
level: Level.CRITICAL,
|
|
3391
|
+
name: "twak_custom_contracts_unsupported",
|
|
3392
|
+
message: `wallet.kind='twak' cannot use the selected custom ERC-8183 targets (${keys.join(", ")}): twak v0.20.0 has no Commerce/Router/Policy address option and would otherwise execute against the wrong canonical contracts. Use wallet.kind='evm-local' for custom ERC-8183 contracts, or remove the overrides and use the canonical stack. ERC8004_REGISTRY_ADDRESS is supported.`,
|
|
3393
|
+
details: { network: networkName, override_keys: keys }
|
|
3394
|
+
}
|
|
3395
|
+
];
|
|
3396
|
+
}
|
|
3332
3397
|
async function checkTwakWalletExists(root, _target) {
|
|
3333
3398
|
const data = loadAgentToml(root);
|
|
3334
3399
|
if (!isTwak(data)) {
|
|
@@ -5361,7 +5426,9 @@ var LEGACY_SKILL_NAMES = [
|
|
|
5361
5426
|
];
|
|
5362
5427
|
var ROUTER_SKILL_NAME = "bnbagent-studio";
|
|
5363
5428
|
var META_FILENAME = ".bag-meta.json";
|
|
5364
|
-
var HIDDEN_SKILL_NAMES = /* @__PURE__ */ new Set(
|
|
5429
|
+
var HIDDEN_SKILL_NAMES = /* @__PURE__ */ new Set([
|
|
5430
|
+
"bnbagent-studio-use-azure-foundry"
|
|
5431
|
+
]);
|
|
5365
5432
|
function isDir3(p) {
|
|
5366
5433
|
try {
|
|
5367
5434
|
return fs19.statSync(p).isDirectory();
|
|
@@ -5767,6 +5834,19 @@ function installSkills(opts) {
|
|
|
5767
5834
|
};
|
|
5768
5835
|
}
|
|
5769
5836
|
|
|
5837
|
+
// src/cli/utils/options.ts
|
|
5838
|
+
import { InvalidArgumentError } from "commander";
|
|
5839
|
+
function acceptChoices(option, accepted, advertised) {
|
|
5840
|
+
return option.argParser((value) => {
|
|
5841
|
+
if (!accepted.includes(value)) {
|
|
5842
|
+
throw new InvalidArgumentError(
|
|
5843
|
+
`Allowed choices are ${advertised.join(", ")}.`
|
|
5844
|
+
);
|
|
5845
|
+
}
|
|
5846
|
+
return value;
|
|
5847
|
+
});
|
|
5848
|
+
}
|
|
5849
|
+
|
|
5770
5850
|
// src/cli/wallet.ts
|
|
5771
5851
|
import * as fs21 from "fs";
|
|
5772
5852
|
import * as path20 from "path";
|
|
@@ -6876,7 +6956,7 @@ var SUPPORTED_STORAGE_PROVIDERS = ["ipfs", "local"];
|
|
|
6876
6956
|
var SUPPORTED_DESTINATIONS = ["self", "platform"];
|
|
6877
6957
|
var RUNTIMES = {
|
|
6878
6958
|
agentcore: { label: "AWS Bedrock AgentCore", hidden: false },
|
|
6879
|
-
"azure-foundry": { label: "Azure AI Foundry", hidden:
|
|
6959
|
+
"azure-foundry": { label: "Azure AI Foundry", hidden: true }
|
|
6880
6960
|
};
|
|
6881
6961
|
var SUPPORTED_RUNTIMES = Object.keys(RUNTIMES);
|
|
6882
6962
|
var APP_DIR = "app";
|
|
@@ -6953,7 +7033,7 @@ every intent to the right playbook via its references.
|
|
|
6953
7033
|
lives in \`src/signing.ts\`.
|
|
6954
7034
|
4. **The quote path is deterministic** (fixed list price, clamp + sign).
|
|
6955
7035
|
Never put an LLM in the quote path.
|
|
6956
|
-
5. **Deploy with \`bag deploy --provider bnb|aws
|
|
7036
|
+
5. **Deploy with \`bag deploy --provider bnb|aws\`.** Every deploy or
|
|
6957
7037
|
redeploy requires a visible provider choice. Studio runs its local business
|
|
6958
7038
|
gates, then delegates cloud credentials, secrets, packaging and lifecycle
|
|
6959
7039
|
calls to the pinned bnbagent-deploy CLI. Do not bypass this boundary with
|
|
@@ -7095,7 +7175,7 @@ function validateProjectName(basename16) {
|
|
|
7095
7175
|
}
|
|
7096
7176
|
if (safe !== basename16) {
|
|
7097
7177
|
throw new Error(
|
|
7098
|
-
`Project name '${basename16}' is not a valid AgentCore runtime name: the default runtime (AWS Bedrock AgentCore) requires ASCII letters and digits only ('-', '_', '.' and other characters are not allowed) \u2014 this is an AgentCore naming constraint, not a general bag restriction. Re-run with an alphanumeric name, e.g. \`bag init ${safe}
|
|
7178
|
+
`Project name '${basename16}' is not a valid AgentCore runtime name: the default runtime (AWS Bedrock AgentCore) requires ASCII letters and digits only ('-', '_', '.' and other characters are not allowed) \u2014 this is an AgentCore naming constraint, not a general bag restriction. Re-run with an alphanumeric name, e.g. \`bag init ${safe}\`.`
|
|
7099
7179
|
);
|
|
7100
7180
|
}
|
|
7101
7181
|
return basename16;
|
|
@@ -7108,21 +7188,15 @@ function registerInit(program) {
|
|
|
7108
7188
|
"<name>",
|
|
7109
7189
|
"Project directory name (created in cwd). Becomes the AgentCore runtime name: ASCII alphanumerics only, must start with a letter, \u226423 chars. Names with '-'/'_'/'.' are rejected (not auto-renamed)."
|
|
7110
7190
|
).addOption(
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
"azure-foundry only: Azure AI Foundry account (resource) name used by the delegated deploy."
|
|
7119
|
-
)
|
|
7120
|
-
).addOption(
|
|
7121
|
-
new Option2(
|
|
7122
|
-
"--azure-project <name>",
|
|
7123
|
-
"azure-foundry only: Azure AI Foundry project name used by the delegated deploy."
|
|
7191
|
+
acceptChoices(
|
|
7192
|
+
new Option2(
|
|
7193
|
+
"--runtime <name>",
|
|
7194
|
+
`Runtime / deploy target to scaffold for (choices: ${visibleRuntimes.join(", ")}); recorded in studio.toml [stack].runtime.`
|
|
7195
|
+
).default("agentcore"),
|
|
7196
|
+
SUPPORTED_RUNTIMES,
|
|
7197
|
+
visibleRuntimes
|
|
7124
7198
|
)
|
|
7125
|
-
).addOption(
|
|
7199
|
+
).addOption(new Option2("--azure-account <name>").hideHelp()).addOption(new Option2("--azure-project <name>").hideHelp()).addOption(
|
|
7126
7200
|
new Option2(
|
|
7127
7201
|
"--destination <dest>",
|
|
7128
7202
|
"Where the agent deploys; recorded in studio.toml [deploy].destination (default: platform while the trial campaign runs; self once it has ended, or when a non-agentcore --runtime or --network bsc-mainnet is passed). 'platform' is a 48h testnet trial on the BNB Chain managed platform (forces runtime=agentcore + bsc-testnet; a trial wallet key is transmitted to the operator \u2014 run `bag wallet new` for a throwaway). 'self' deploys to YOUR own cloud."
|
|
@@ -7582,9 +7656,10 @@ function derivePackaging(walletKind2, destination, platformArtifact2 = "zip", ru
|
|
|
7582
7656
|
return "codezip";
|
|
7583
7657
|
}
|
|
7584
7658
|
function scaffold(target, name, o) {
|
|
7659
|
+
const packageManagerVersion = pnpmVersion();
|
|
7585
7660
|
fs22.writeFileSync(
|
|
7586
7661
|
path21.join(target, "package.json"),
|
|
7587
|
-
renderWorkspacePackageJson(name)
|
|
7662
|
+
renderWorkspacePackageJson(name, packageManagerVersion)
|
|
7588
7663
|
);
|
|
7589
7664
|
fs22.writeFileSync(
|
|
7590
7665
|
path21.join(target, "pnpm-workspace.yaml"),
|
|
@@ -7646,7 +7721,8 @@ function scaffold(target, name, o) {
|
|
|
7646
7721
|
o.storageProvider,
|
|
7647
7722
|
o.walletKind,
|
|
7648
7723
|
o.rails,
|
|
7649
|
-
o.b402Price
|
|
7724
|
+
o.b402Price,
|
|
7725
|
+
o.network
|
|
7650
7726
|
)
|
|
7651
7727
|
);
|
|
7652
7728
|
fs22.writeFileSync(path21.join(agentRoot2, ".gitignore"), renderAgentGitignore());
|
|
@@ -7667,7 +7743,7 @@ function scaffold(target, name, o) {
|
|
|
7667
7743
|
const runtimeCtx = {
|
|
7668
7744
|
PKG: AGENT_SRC,
|
|
7669
7745
|
TWAK_CLI_VERSION,
|
|
7670
|
-
PNPM_VERSION:
|
|
7746
|
+
PNPM_VERSION: packageManagerVersion,
|
|
7671
7747
|
DEPLOYMENT_TYPE: isContainer ? "container" : "direct_code_deploy",
|
|
7672
7748
|
ENTRYPOINT: o.runtime === "azure-foundry" ? a2aEntry : `dist/${stem2}.js`,
|
|
7673
7749
|
// Foundry Hosted Agents have a provider-level container contract that is
|
|
@@ -7756,11 +7832,12 @@ ${deployLine}
|
|
|
7756
7832
|
In Claude Code / Cursor, type \`/bnbagent-studio\` \u2014 the skill drives every step.
|
|
7757
7833
|
`;
|
|
7758
7834
|
}
|
|
7759
|
-
function renderWorkspacePackageJson(name) {
|
|
7835
|
+
function renderWorkspacePackageJson(name, packageManagerVersion) {
|
|
7760
7836
|
return `${JSON.stringify(
|
|
7761
7837
|
{
|
|
7762
7838
|
name: `${name}-workspace`,
|
|
7763
|
-
private: true
|
|
7839
|
+
private: true,
|
|
7840
|
+
packageManager: `pnpm@${packageManagerVersion}`
|
|
7764
7841
|
// NOT a publishable package — the agent lives at app/agent (see
|
|
7765
7842
|
// pnpm-workspace.yaml); this root only anchors the pnpm workspace.
|
|
7766
7843
|
},
|
|
@@ -8078,7 +8155,7 @@ ${pieverseSection}${erc8183Section}
|
|
|
8078
8155
|
${storageSection}
|
|
8079
8156
|
${x402Section}${x402SellerSection}${budgetSection}${azureSection}`;
|
|
8080
8157
|
}
|
|
8081
|
-
function renderAgentEnvLocal(provider, storageProvider, walletKind2, rails, b402Price) {
|
|
8158
|
+
function renderAgentEnvLocal(provider, storageProvider, walletKind2, rails, b402Price, network) {
|
|
8082
8159
|
const keyEnv = PROVIDER_KEY_ENV[provider];
|
|
8083
8160
|
const lines = [
|
|
8084
8161
|
"# \u26A0\uFE0F SECRETS \u2014 do NOT paste this file into issue trackers, logs, or AI chats.",
|
|
@@ -8142,11 +8219,12 @@ function renderAgentEnvLocal(provider, storageProvider, walletKind2, rails, b402
|
|
|
8142
8219
|
}
|
|
8143
8220
|
if (rails === "b402" || rails === "both") {
|
|
8144
8221
|
const free = x402SellerPricingState({ price_usd: b402Price }).kind === "free";
|
|
8222
|
+
const baseUrl = !free && network === "bsc-testnet" ? DEFAULT_B402_TESTNET_BASE_URL : "";
|
|
8145
8223
|
lines.push(
|
|
8146
8224
|
"",
|
|
8147
8225
|
"# B402 merchant credentials (issued per environment after manual approval).",
|
|
8148
8226
|
free ? "# FREE price 0 does not use these credentials; leave them empty until switching to PAID." : "# PAID requires all four; all absent = dormant, partial = boot error.",
|
|
8149
|
-
|
|
8227
|
+
`B402_BASE_URL=${baseUrl}`,
|
|
8150
8228
|
"B402_CLIENT_ID=",
|
|
8151
8229
|
"B402_ACCESS_TOKEN=",
|
|
8152
8230
|
"B402_PRIVATE_KEY=",
|
|
@@ -8156,7 +8234,7 @@ function renderAgentEnvLocal(provider, storageProvider, walletKind2, rails, b402
|
|
|
8156
8234
|
if (rails === "8183" || rails === "both") {
|
|
8157
8235
|
lines.push(
|
|
8158
8236
|
"",
|
|
8159
|
-
"# Optional ERC-8183 contract-stack override
|
|
8237
|
+
"# Optional ERC-8183 custom contract-stack override. Set all three",
|
|
8160
8238
|
"# together; partial overrides can mix incompatible deployments.",
|
|
8161
8239
|
"# Required for price=0 while canonical contracts reject zero funding.",
|
|
8162
8240
|
"# ERC8183_COMMERCE_ADDRESS=",
|
|
@@ -9415,7 +9493,7 @@ function printConfigSummary(agentRoot2) {
|
|
|
9415
9493
|
` pricing : FREE \u2014 ${weiToU(String(price))} per job; zero token escrow`
|
|
9416
9494
|
);
|
|
9417
9495
|
printOut(
|
|
9418
|
-
contractOverrides.mode === "custom" ? " contracts: custom
|
|
9496
|
+
contractOverrides.mode === "custom" ? " contracts: custom stack selected (all three address overrides)" : " contracts: configure all three ERC8183_*_ADDRESS overrides before deploy"
|
|
9419
9497
|
);
|
|
9420
9498
|
} else {
|
|
9421
9499
|
printOut(
|
|
@@ -9455,7 +9533,7 @@ function printConfigSummary(agentRoot2) {
|
|
|
9455
9533
|
}
|
|
9456
9534
|
if (hasErc8183 && isFreePrice && contractOverrides.mode !== "custom") {
|
|
9457
9535
|
todo.push(
|
|
9458
|
-
"ERC8183_COMMERCE_ADDRESS / ROUTER_ADDRESS / POLICY_ADDRESS \u2014 select one zero-price-compatible
|
|
9536
|
+
"ERC8183_COMMERCE_ADDRESS / ROUTER_ADDRESS / POLICY_ADDRESS \u2014 select one zero-price-compatible custom contract stack"
|
|
9459
9537
|
);
|
|
9460
9538
|
}
|
|
9461
9539
|
if (hasX402Seller && !isFreeX402) {
|
|
@@ -10647,14 +10725,14 @@ function erc8183RailChecks(cfg) {
|
|
|
10647
10725
|
out.push({
|
|
10648
10726
|
level: Level.CRITICAL,
|
|
10649
10727
|
name: "commerce_zero_price_contract_unsupported",
|
|
10650
|
-
message: "ERC-8183 pricing is FREE (zero token escrow), but the canonical contract stack rejects zero funding. Set ERC8183_COMMERCE_ADDRESS, ERC8183_ROUTER_ADDRESS, and ERC8183_POLICY_ADDRESS together to a zero-price-compatible
|
|
10728
|
+
message: "ERC-8183 pricing is FREE (zero token escrow), but the canonical contract stack rejects zero funding. Set ERC8183_COMMERCE_ADDRESS, ERC8183_ROUTER_ADDRESS, and ERC8183_POLICY_ADDRESS together to a zero-price-compatible custom stack.",
|
|
10651
10729
|
details: { effective_wei: "0", contract_profile: "canonical" }
|
|
10652
10730
|
});
|
|
10653
10731
|
} else if (contracts.mode === "custom") {
|
|
10654
10732
|
out.push({
|
|
10655
10733
|
level: Level.INFO,
|
|
10656
10734
|
name: "commerce_zero_price_enabled",
|
|
10657
|
-
message: "ERC-8183 pricing is FREE \u2014 buyers fund 0 token units with zero token escrow; a complete custom
|
|
10735
|
+
message: "ERC-8183 pricing is FREE \u2014 buyers fund 0 token units with zero token escrow; a complete custom contract stack is selected.",
|
|
10658
10736
|
details: { effective_wei: "0", contract_profile: "custom" }
|
|
10659
10737
|
});
|
|
10660
10738
|
}
|
|
@@ -10776,7 +10854,7 @@ function x402SellerRailChecks(agentRoot2, cfg, target) {
|
|
|
10776
10854
|
const network = String(
|
|
10777
10855
|
tableOf2(cfg, "network").default ?? "bsc-mainnet"
|
|
10778
10856
|
).toLowerCase();
|
|
10779
|
-
const testUrl =
|
|
10857
|
+
const testUrl = isB402TestnetBaseUrl(credentials.baseUrl);
|
|
10780
10858
|
const testNetwork = network.includes("testnet");
|
|
10781
10859
|
if (testUrl !== testNetwork) {
|
|
10782
10860
|
out.push({
|
|
@@ -11009,6 +11087,7 @@ var allChecks = [
|
|
|
11009
11087
|
// gates on the LEVEL, not on which module produced it.
|
|
11010
11088
|
checkTwakRequiresContainer,
|
|
11011
11089
|
checkTwakCliPresent,
|
|
11090
|
+
checkTwakCustomContractsUnsupported,
|
|
11012
11091
|
checkTwakWalletExists,
|
|
11013
11092
|
checkTwakPasswordEnvSet,
|
|
11014
11093
|
checkTwakCredentialsAvailable,
|
|
@@ -12151,14 +12230,15 @@ async function checkWalletTbnbBalanceSufficient(root, _target) {
|
|
|
12151
12230
|
return [];
|
|
12152
12231
|
}
|
|
12153
12232
|
const isTwak2 = tableOf2(data, "wallet").kind === "twak";
|
|
12154
|
-
|
|
12233
|
+
const customContracts = isTwak2 && twakCustomContractOverrides(netName).length > 0;
|
|
12234
|
+
if (isTwak2 && netName === "bsc-testnet" && !customContracts) {
|
|
12155
12235
|
return [];
|
|
12156
12236
|
}
|
|
12157
12237
|
const bal = await readNativeBalanceRaw(address, netName);
|
|
12158
12238
|
if (bal >= TBNB_MIN_WEI) {
|
|
12159
12239
|
return [];
|
|
12160
12240
|
}
|
|
12161
|
-
const gasNote = isTwak2 ? " (twak: x402 topups are gasless and ERC-8004 registry writes are gas-sponsored, but mainnet ERC-8183 fund/settle self-pay gas)" : "";
|
|
12241
|
+
const gasNote = isTwak2 ? netName === "bsc-testnet" ? " (twak: custom contract sponsorship depends on the paymaster policy; keep fallback tBNB)" : " (twak: x402 topups are gasless and ERC-8004 registry writes are gas-sponsored, but mainnet ERC-8183 fund/settle self-pay gas)" : "";
|
|
12162
12242
|
return [
|
|
12163
12243
|
{
|
|
12164
12244
|
level: Level.WARNING,
|
|
@@ -12691,6 +12771,21 @@ var PROVIDER_LABELS = {
|
|
|
12691
12771
|
aws: "AWS AgentCore",
|
|
12692
12772
|
azure: "Azure Foundry"
|
|
12693
12773
|
};
|
|
12774
|
+
var PROVIDER_MENU_ORDER = [
|
|
12775
|
+
"bnb",
|
|
12776
|
+
"aws",
|
|
12777
|
+
"azure"
|
|
12778
|
+
];
|
|
12779
|
+
var PROVIDER_SHORT_LABELS = {
|
|
12780
|
+
bnb: "BNB",
|
|
12781
|
+
aws: "AWS",
|
|
12782
|
+
azure: "Azure"
|
|
12783
|
+
};
|
|
12784
|
+
function providerDigit(provider) {
|
|
12785
|
+
return PROVIDER_MENU_ORDER.indexOf(provider) + 1;
|
|
12786
|
+
}
|
|
12787
|
+
var ADVERTISED_PROVIDERS = ["bnb", "aws"];
|
|
12788
|
+
var ADVERTISED_PROVIDERS_HELP = ADVERTISED_PROVIDERS.join("|");
|
|
12694
12789
|
function tableOf10(data, key) {
|
|
12695
12790
|
const value = data[key];
|
|
12696
12791
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -12783,7 +12878,7 @@ function unavailableProvidersForProject(root) {
|
|
|
12783
12878
|
return {};
|
|
12784
12879
|
}
|
|
12785
12880
|
if (runtime === "azure-foundry") {
|
|
12786
|
-
const reason = "this project uses
|
|
12881
|
+
const reason = "this project uses a different container adapter; scaffold an agentcore project before selecting BNB or AWS";
|
|
12787
12882
|
return {
|
|
12788
12883
|
bnb: reason,
|
|
12789
12884
|
aws: reason,
|
|
@@ -12814,9 +12909,12 @@ function unavailableReason(opts, provider) {
|
|
|
12814
12909
|
}
|
|
12815
12910
|
return opts.unavailable?.[provider] ?? null;
|
|
12816
12911
|
}
|
|
12912
|
+
function providerPromptHint() {
|
|
12913
|
+
return PROVIDER_MENU_ORDER.filter((p) => ADVERTISED_PROVIDERS.includes(p)).map((p) => `${providerDigit(p)}=${PROVIDER_SHORT_LABELS[p]}`).join(", ");
|
|
12914
|
+
}
|
|
12817
12915
|
async function promptProvider(opts) {
|
|
12818
12916
|
for (; ; ) {
|
|
12819
|
-
const answer = (await opts.prompt(
|
|
12917
|
+
const answer = (await opts.prompt(`Provider [${providerPromptHint()}]: `)).trim().toLowerCase();
|
|
12820
12918
|
const provider = answer === "1" || answer === "bnb" ? "bnb" : answer === "2" || answer === "aws" ? "aws" : answer === "3" || answer === "azure" ? "azure" : null;
|
|
12821
12919
|
if (provider === null) {
|
|
12822
12920
|
if (answer === "" || answer === "q" || answer === "cancel") {
|
|
@@ -14042,9 +14140,11 @@ function isFile14(p) {
|
|
|
14042
14140
|
|
|
14043
14141
|
// src/cli/_runtime/base.ts
|
|
14044
14142
|
var DEPLOY_RUNTIME_TARGETS = ["agentcore", "azure-foundry"];
|
|
14143
|
+
var ADVERTISED_DEPLOY_RUNTIME_TARGETS = ["agentcore"];
|
|
14045
14144
|
|
|
14046
14145
|
// src/cli/deploy.ts
|
|
14047
14146
|
var TARGET_CHOICES = [...DEPLOY_RUNTIME_TARGETS];
|
|
14147
|
+
var ADVERTISED_TARGET_CHOICES = [...ADVERTISED_DEPLOY_RUNTIME_TARGETS];
|
|
14048
14148
|
function isFile15(p) {
|
|
14049
14149
|
try {
|
|
14050
14150
|
return fs37.statSync(p).isFile();
|
|
@@ -14084,17 +14184,33 @@ function loadAgentCfg2(root) {
|
|
|
14084
14184
|
function registerDeploy(program) {
|
|
14085
14185
|
program.enablePositionalOptions();
|
|
14086
14186
|
const p = program.command("deploy").description(
|
|
14087
|
-
"Deploy the agent after explicitly selecting BNB
|
|
14088
|
-
);
|
|
14089
|
-
const runtimeOption = () =>
|
|
14090
|
-
|
|
14091
|
-
|
|
14092
|
-
|
|
14093
|
-
|
|
14094
|
-
|
|
14095
|
-
|
|
14096
|
-
|
|
14097
|
-
)
|
|
14187
|
+
"Deploy the agent after explicitly selecting BNB or AWS; lifecycle subcommands inspect recorded deployments."
|
|
14188
|
+
);
|
|
14189
|
+
const runtimeOption = () => acceptChoices(
|
|
14190
|
+
new Option4(
|
|
14191
|
+
"--runtime <name>",
|
|
14192
|
+
"Deploy runtime to validate against (default: studio.toml [stack].runtime, else agentcore)."
|
|
14193
|
+
),
|
|
14194
|
+
TARGET_CHOICES,
|
|
14195
|
+
ADVERTISED_TARGET_CHOICES
|
|
14196
|
+
);
|
|
14197
|
+
const targetAlias = () => acceptChoices(
|
|
14198
|
+
new Option4(
|
|
14199
|
+
"--target <name>",
|
|
14200
|
+
"Deprecated alias of --runtime."
|
|
14201
|
+
).hideHelp(),
|
|
14202
|
+
TARGET_CHOICES,
|
|
14203
|
+
ADVERTISED_TARGET_CHOICES
|
|
14204
|
+
);
|
|
14205
|
+
const providerOption = () => acceptChoices(
|
|
14206
|
+
new Option4(
|
|
14207
|
+
"--provider <provider>",
|
|
14208
|
+
"Provider: bnb or aws. Required for non-interactive deploy; lifecycle commands need it only when multiple records exist."
|
|
14209
|
+
),
|
|
14210
|
+
// Unadvertised providers stay parseable (see ADVERTISED_PROVIDERS).
|
|
14211
|
+
PROVIDER_MENU_ORDER,
|
|
14212
|
+
ADVERTISED_PROVIDERS
|
|
14213
|
+
);
|
|
14098
14214
|
p.addOption(providerOption()).option("--project-root <path>", "Override project root.").option("--skip-prepare", "Skip non-storage local readiness checks.").option(
|
|
14099
14215
|
"--force-deploy-broken-storage",
|
|
14100
14216
|
"DANGEROUS: bypass fatal deliverable-storage checks."
|
|
@@ -14103,7 +14219,7 @@ function registerDeploy(program) {
|
|
|
14103
14219
|
).option("--accept-risk", "Accept provider risk/terms disclosures.").option("--yes", "Confirm the selected deployment plan non-interactively.").option(
|
|
14104
14220
|
"--allow-multiple",
|
|
14105
14221
|
"Allow creating a deployment while another provider remains active."
|
|
14106
|
-
).option("--skip-smoke", "Skip
|
|
14222
|
+
).option("--skip-smoke", "Skip the delegated post-deploy smoke check.").action(act((opts) => cmdDeploy(opts, [])));
|
|
14107
14223
|
p.command("prepare").description("Run the deploy-readiness sweep on this project.").addOption(runtimeOption()).addOption(targetAlias()).option("--project-root <path>", "Override project root.").option("--json", "Emit JSON instead of a table.").option(
|
|
14108
14224
|
"--ignore-warnings",
|
|
14109
14225
|
"Exit 0 even if WARNING-level checks fire (still fails on BLOCKED/CRITICAL)."
|
|
@@ -14142,7 +14258,7 @@ function registerDeploy(program) {
|
|
|
14142
14258
|
"Allow creating a deployment while another provider remains active."
|
|
14143
14259
|
).option(
|
|
14144
14260
|
"--skip-smoke",
|
|
14145
|
-
"
|
|
14261
|
+
"Skip the post-deploy smoke check (omit `--smoke` from the delegated bnbagent-deploy invocation)."
|
|
14146
14262
|
).argument(
|
|
14147
14263
|
"[agentcoreArgs...]",
|
|
14148
14264
|
"Extra args passed straight through to `bnbagent-deploy deploy` (put after `--`)."
|
|
@@ -14200,7 +14316,7 @@ function registerDeploy(program) {
|
|
|
14200
14316
|
(opts) => cmdDestroy(opts)
|
|
14201
14317
|
)
|
|
14202
14318
|
);
|
|
14203
|
-
p.command("logs").description("Show the selected deployment's logs via bnbagent-deploy.").option("--project-root <path>", "Override project root.").addOption(providerOption()).option("--since <dur>", "Lower bound, e.g. 5m/2h/1d (default 10m).", "10m").option("--follow", "Stream new lines (poll ~3s).").option("--limit <n>", "Number of recent lines (
|
|
14319
|
+
p.command("logs").description("Show the selected deployment's logs via bnbagent-deploy.").option("--project-root <path>", "Override project root.").addOption(providerOption()).option("--since <dur>", "Lower bound, e.g. 5m/2h/1d (default 10m).", "10m").option("--follow", "Stream new lines (poll ~3s).").option("--limit <n>", "Number of recent lines (default 50).").option("--session <id>", "Container session id.").addOption(
|
|
14204
14320
|
new Option4(
|
|
14205
14321
|
"--job <id>",
|
|
14206
14322
|
"Deprecated Studio direct-CloudWatch filter."
|
|
@@ -14652,14 +14768,18 @@ function renderProviderSelection(deployments, trial, unavailable) {
|
|
|
14652
14768
|
}
|
|
14653
14769
|
const remaining = formatTrialRemaining(trial.remainingSeconds);
|
|
14654
14770
|
const bnbDetail = unavailable.bnb ? `unavailable \u2014 ${unavailable.bnb}` : trial.state === "expired" ? `unavailable \u2014 trial expired${trial.expiresAt ? ` ${trial.expiresAt}` : ""}` : trial.state === "active" ? `active${remaining ? ` \u2014 ${remaining} remaining` : ""}${trial.expiresAt ? ` \xB7 expires ${trial.expiresAt}` : ""}` : trial.state === "available" ? "available \u2014 free 48h testnet; starts on first successful deploy" : "login required to check trial eligibility";
|
|
14771
|
+
const detail = {
|
|
14772
|
+
bnb: bnbDetail,
|
|
14773
|
+
aws: unavailable.aws ? `unavailable \u2014 ${unavailable.aws}` : "deploy to your AWS account",
|
|
14774
|
+
azure: unavailable.azure ? `unavailable \u2014 ${unavailable.azure}` : "deploy to your Azure account"
|
|
14775
|
+
};
|
|
14655
14776
|
printOut("Deployment providers");
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14659
|
-
)
|
|
14660
|
-
|
|
14661
|
-
|
|
14662
|
-
);
|
|
14777
|
+
for (const provider of PROVIDER_MENU_ORDER) {
|
|
14778
|
+
if (!ADVERTISED_PROVIDERS.includes(provider)) continue;
|
|
14779
|
+
printOut(
|
|
14780
|
+
` ${providerDigit(provider)}. ${PROVIDER_LABELS[provider].padEnd(18)}${detail[provider]}`
|
|
14781
|
+
);
|
|
14782
|
+
}
|
|
14663
14783
|
}
|
|
14664
14784
|
async function cmdDeploy(opts, deployArgs) {
|
|
14665
14785
|
const rc = applyProjectRoot(opts.projectRoot);
|
|
@@ -14684,7 +14804,7 @@ async function cmdDeploy(opts, deployArgs) {
|
|
|
14684
14804
|
});
|
|
14685
14805
|
if (selection.kind === "selection_required") {
|
|
14686
14806
|
printErr(
|
|
14687
|
-
|
|
14807
|
+
`error: deployment provider must be selected explicitly in a non-interactive terminal; pass --provider ${ADVERTISED_PROVIDERS_HELP} --yes`
|
|
14688
14808
|
);
|
|
14689
14809
|
return selection.exitCode;
|
|
14690
14810
|
}
|
|
@@ -15107,7 +15227,7 @@ async function printAccessNextSteps2(root, runtime, opts = {}) {
|
|
|
15107
15227
|
return;
|
|
15108
15228
|
}
|
|
15109
15229
|
printOut(
|
|
15110
|
-
" Azure Foundry buyer access is in Preview \u2014 see
|
|
15230
|
+
" Azure Foundry buyer access is in Preview \u2014 see docs/guides/foundry-a2a-access.md in the bnbagent-studio repo. The per-agent A2A card URL and OAuth scope are confirmed only after a live deploy."
|
|
15111
15231
|
);
|
|
15112
15232
|
}
|
|
15113
15233
|
var CLIENT_PROMPT_RULE2 = "\u2500".repeat(62);
|
|
@@ -15381,7 +15501,9 @@ async function cmdStatus2(opts) {
|
|
|
15381
15501
|
printOut(JSON.stringify({ deployments: [] }, null, 2));
|
|
15382
15502
|
} else {
|
|
15383
15503
|
printOut(`No recorded deployments${detail}.`);
|
|
15384
|
-
printOut(
|
|
15504
|
+
printOut(
|
|
15505
|
+
`Start one with \`bag deploy --provider ${ADVERTISED_PROVIDERS_HELP}\`.`
|
|
15506
|
+
);
|
|
15385
15507
|
}
|
|
15386
15508
|
return opts.provider ? 2 : 0;
|
|
15387
15509
|
}
|
|
@@ -15538,13 +15660,13 @@ async function selectRecordedForLifecycle(root, requested, operation) {
|
|
|
15538
15660
|
if (deployments.length === 1 && soleDeployment) return soleDeployment;
|
|
15539
15661
|
if (deployments.length === 0) {
|
|
15540
15662
|
printErr(
|
|
15541
|
-
|
|
15663
|
+
`error: no deployment is recorded; run \`bag deploy --provider ${ADVERTISED_PROVIDERS_HELP}\` first`
|
|
15542
15664
|
);
|
|
15543
15665
|
return 2;
|
|
15544
15666
|
}
|
|
15545
15667
|
if (!stdinIsTty()) {
|
|
15546
15668
|
printErr(
|
|
15547
|
-
`error: multiple deployments are active; non-interactive \`${operation}\` requires --provider
|
|
15669
|
+
`error: multiple deployments are active; non-interactive \`${operation}\` requires --provider ${ADVERTISED_PROVIDERS_HELP}`
|
|
15548
15670
|
);
|
|
15549
15671
|
return 2;
|
|
15550
15672
|
}
|
|
@@ -15997,7 +16119,7 @@ function anchoredKeystoreDir(projectRoot, walletCfg) {
|
|
|
15997
16119
|
async function checkWallet(projectRoot, data) {
|
|
15998
16120
|
const walletCfg = tableOf13(data, "wallet");
|
|
15999
16121
|
if (walletCfg.kind === "twak") {
|
|
16000
|
-
return checkWalletTwak(walletCfg, projectRoot);
|
|
16122
|
+
return checkWalletTwak(walletCfg, projectRoot, data);
|
|
16001
16123
|
}
|
|
16002
16124
|
if (walletCfg.kind === "altana") {
|
|
16003
16125
|
return checkWalletAltana(walletCfg, projectRoot);
|
|
@@ -16142,7 +16264,7 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16142
16264
|
}
|
|
16143
16265
|
return out;
|
|
16144
16266
|
}
|
|
16145
|
-
async function checkWalletTwak(walletCfg, projectRoot) {
|
|
16267
|
+
async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
16146
16268
|
const out = [];
|
|
16147
16269
|
if (await whichTwak() !== null) {
|
|
16148
16270
|
const version = await twakInstalledVersion();
|
|
@@ -16167,6 +16289,15 @@ async function checkWalletTwak(walletCfg, projectRoot) {
|
|
|
16167
16289
|
detail: `not on PATH \u2014 npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
16168
16290
|
});
|
|
16169
16291
|
}
|
|
16292
|
+
const networkName = String(tableOf13(data, "network").default ?? "bsc-testnet");
|
|
16293
|
+
const unsupportedTargets = twakUnsupportedContractOverrides(networkName);
|
|
16294
|
+
if (unsupportedTargets.length > 0) {
|
|
16295
|
+
out.push({
|
|
16296
|
+
name: "[wallet] twak contract targets",
|
|
16297
|
+
status: FAIL,
|
|
16298
|
+
detail: `twak v0.20.0 cannot target custom ERC-8183 contracts (${unsupportedTargets.map((item) => item.envKey).join(", ")}) and would use canonical contracts instead. Use wallet.kind='evm-local' for custom ERC-8183 contracts, or remove the overrides. ERC8004_REGISTRY_ADDRESS is supported.`
|
|
16299
|
+
});
|
|
16300
|
+
}
|
|
16170
16301
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
16171
16302
|
if (isFile16(walletFile)) {
|
|
16172
16303
|
out.push({
|
|
@@ -16507,7 +16638,7 @@ function checkErc8183Pricing(data) {
|
|
|
16507
16638
|
{
|
|
16508
16639
|
name: "erc8183 pricing",
|
|
16509
16640
|
status: PASS,
|
|
16510
|
-
detail: "FREE \u2014 zero token escrow; custom
|
|
16641
|
+
detail: "FREE \u2014 zero token escrow; custom contract stack selected with all three ERC-8183 address overrides."
|
|
16511
16642
|
}
|
|
16512
16643
|
];
|
|
16513
16644
|
}
|
|
@@ -16515,7 +16646,7 @@ function checkErc8183Pricing(data) {
|
|
|
16515
16646
|
{
|
|
16516
16647
|
name: "erc8183 pricing",
|
|
16517
16648
|
status: FAIL,
|
|
16518
|
-
detail: "FREE \u2014 zero token escrow, but the canonical ERC-8183 contracts reject zero funding. Set ERC8183_COMMERCE_ADDRESS, ERC8183_ROUTER_ADDRESS, and ERC8183_POLICY_ADDRESS together to a zero-price-compatible
|
|
16649
|
+
detail: "FREE \u2014 zero token escrow, but the canonical ERC-8183 contracts reject zero funding. Set ERC8183_COMMERCE_ADDRESS, ERC8183_ROUTER_ADDRESS, and ERC8183_POLICY_ADDRESS together to a zero-price-compatible custom stack."
|
|
16519
16650
|
}
|
|
16520
16651
|
];
|
|
16521
16652
|
}
|
|
@@ -17217,7 +17348,7 @@ function loadAgentCfg3() {
|
|
|
17217
17348
|
return null;
|
|
17218
17349
|
}
|
|
17219
17350
|
}
|
|
17220
|
-
function
|
|
17351
|
+
function resolveNetwork2(override) {
|
|
17221
17352
|
if (override) {
|
|
17222
17353
|
return override;
|
|
17223
17354
|
}
|
|
@@ -17407,7 +17538,7 @@ async function cmdRegister2(opts) {
|
|
|
17407
17538
|
return 2;
|
|
17408
17539
|
}
|
|
17409
17540
|
const wallet = walletRt6.getWallet();
|
|
17410
|
-
const network =
|
|
17541
|
+
const network = resolveNetwork2(opts.network);
|
|
17411
17542
|
const gasErr = await precheckRegisterGas(wallet, network);
|
|
17412
17543
|
if (gasErr !== null) {
|
|
17413
17544
|
printErr(`error: ${gasErr}`);
|
|
@@ -17495,7 +17626,7 @@ async function cmdUpdateEndpoint(opts) {
|
|
|
17495
17626
|
return 2;
|
|
17496
17627
|
}
|
|
17497
17628
|
const wallet = walletRt6.getWallet();
|
|
17498
|
-
const network =
|
|
17629
|
+
const network = resolveNetwork2(opts.network);
|
|
17499
17630
|
const protocol = resolveProtocol(opts.protocol);
|
|
17500
17631
|
let accessDescription = null;
|
|
17501
17632
|
const agentRoot2 = findProjectRoot5();
|
|
@@ -17538,7 +17669,7 @@ async function cmdUpdateEndpoint(opts) {
|
|
|
17538
17669
|
}
|
|
17539
17670
|
async function cmdUpdateMetadata(opts) {
|
|
17540
17671
|
const wallet = walletRt6.getWallet();
|
|
17541
|
-
const network =
|
|
17672
|
+
const network = resolveNetwork2(opts.network);
|
|
17542
17673
|
let txHash;
|
|
17543
17674
|
try {
|
|
17544
17675
|
txHash = await setMetadata(wallet, opts.key, opts.value, {
|
|
@@ -17570,7 +17701,7 @@ async function cmdClearPending(opts) {
|
|
|
17570
17701
|
}
|
|
17571
17702
|
const pendingTx = identity.pending_tx ? String(identity.pending_tx) : null;
|
|
17572
17703
|
if (pendingTx !== null && !opts.force) {
|
|
17573
|
-
const network =
|
|
17704
|
+
const network = resolveNetwork2(opts.network);
|
|
17574
17705
|
let seen;
|
|
17575
17706
|
try {
|
|
17576
17707
|
seen = await readTransactionSeen(pendingTx, network);
|
|
@@ -17601,7 +17732,7 @@ async function cmdGetMetadata(opts) {
|
|
|
17601
17732
|
let value;
|
|
17602
17733
|
try {
|
|
17603
17734
|
value = await getMetadata(wallet, opts.key, {
|
|
17604
|
-
network:
|
|
17735
|
+
network: resolveNetwork2(opts.network)
|
|
17605
17736
|
});
|
|
17606
17737
|
} catch (exc) {
|
|
17607
17738
|
printOut(`error: ${errMsg4(exc)}`);
|
|
@@ -17614,7 +17745,7 @@ async function cmdShow6(networkArg) {
|
|
|
17614
17745
|
const wallet = walletRt6.getWallet();
|
|
17615
17746
|
let record;
|
|
17616
17747
|
try {
|
|
17617
|
-
record = await show2(wallet, { network:
|
|
17748
|
+
record = await show2(wallet, { network: resolveNetwork2(networkArg) });
|
|
17618
17749
|
} catch (exc) {
|
|
17619
17750
|
printOut(`error: ${errMsg4(exc)}`);
|
|
17620
17751
|
return errName2(exc) === "NotRegisteredError" ? 2 : 1;
|
|
@@ -17631,7 +17762,7 @@ async function cmdResolve(agentId, networkArg) {
|
|
|
17631
17762
|
try {
|
|
17632
17763
|
uri = await resolve20(agentId, {
|
|
17633
17764
|
wallet,
|
|
17634
|
-
network:
|
|
17765
|
+
network: resolveNetwork2(networkArg)
|
|
17635
17766
|
});
|
|
17636
17767
|
} catch (exc) {
|
|
17637
17768
|
printOut(`error: ${errMsg4(exc)}`);
|
|
@@ -19198,7 +19329,7 @@ function loadSellerConfig() {
|
|
|
19198
19329
|
return null;
|
|
19199
19330
|
}
|
|
19200
19331
|
}
|
|
19201
|
-
function
|
|
19332
|
+
function resolveNetwork3(cfg, override) {
|
|
19202
19333
|
if (override) {
|
|
19203
19334
|
return override;
|
|
19204
19335
|
}
|
|
@@ -19276,7 +19407,12 @@ async function cmdSellInit(priceFlag) {
|
|
|
19276
19407
|
}
|
|
19277
19408
|
const envPath = envLocalPath17(root);
|
|
19278
19409
|
for (const key of B402_ENV_KEYS) {
|
|
19279
|
-
|
|
19410
|
+
const existing = getEnvVar(envPath, key);
|
|
19411
|
+
if (key === "B402_BASE_URL" && !free && resolveNetwork3(cfg).toLowerCase() === "bsc-testnet" && !process.env.B402_BASE_URL && !existing) {
|
|
19412
|
+
setEnvVar(envPath, key, DEFAULT_B402_TESTNET_BASE_URL);
|
|
19413
|
+
} else if (existing === null) {
|
|
19414
|
+
setEnvVar(envPath, key, "");
|
|
19415
|
+
}
|
|
19280
19416
|
}
|
|
19281
19417
|
printOut(
|
|
19282
19418
|
free ? "\u2713 x402 seller config is ready in FREE mode; B402 credentials are not required." : "\u2713 x402 seller config and B402 placeholders are ready for PAID mode."
|
|
@@ -19355,7 +19491,7 @@ async function cmdSellStatus(probe) {
|
|
|
19355
19491
|
printOut("B402 probe: skipped (rail disabled or credentials incomplete)");
|
|
19356
19492
|
return 0;
|
|
19357
19493
|
}
|
|
19358
|
-
const networkName =
|
|
19494
|
+
const networkName = resolveNetwork3(cfg);
|
|
19359
19495
|
const network = caip2(getNetwork11(networkName).chainId);
|
|
19360
19496
|
const token = SELLER_TOKENS[network];
|
|
19361
19497
|
if (!token) {
|
|
@@ -19449,7 +19585,7 @@ async function cmdBuy2(url, opts) {
|
|
|
19449
19585
|
printErr(`error: ${errMsg6(exc)}`);
|
|
19450
19586
|
return 2;
|
|
19451
19587
|
}
|
|
19452
|
-
const networkName =
|
|
19588
|
+
const networkName = resolveNetwork3(cfg, opts.network);
|
|
19453
19589
|
const wallet = resolveWallet2();
|
|
19454
19590
|
if (wallet === null) {
|
|
19455
19591
|
return 1;
|
|
@@ -19638,7 +19774,7 @@ async function cmdTrust(merchant, opts) {
|
|
|
19638
19774
|
host = rec.domain;
|
|
19639
19775
|
methodHint = rec.probeMethod;
|
|
19640
19776
|
}
|
|
19641
|
-
const networkName = opts.network || (rec ? rec.network :
|
|
19777
|
+
const networkName = opts.network || (rec ? rec.network : resolveNetwork3(cfg, null));
|
|
19642
19778
|
const probed = await probeChallenge(probeUrl, methodHint);
|
|
19643
19779
|
if (probed === null) {
|
|
19644
19780
|
return 1;
|
|
@@ -19784,7 +19920,7 @@ function buildProgram() {
|
|
|
19784
19920
|
return program;
|
|
19785
19921
|
}
|
|
19786
19922
|
function cliVersion() {
|
|
19787
|
-
return "0.0.6-alpha.
|
|
19923
|
+
return "0.0.6-alpha.3";
|
|
19788
19924
|
}
|
|
19789
19925
|
|
|
19790
19926
|
// src/cli/updateCheck.ts
|
|
@@ -295,6 +295,7 @@ function mb(n) {
|
|
|
295
295
|
|
|
296
296
|
// src/cli/_x402SellerConfig.ts
|
|
297
297
|
var DEFAULT_B402_PRICE_USD = "0.01";
|
|
298
|
+
var DEFAULT_B402_TESTNET_BASE_URL = "https://qacb.sdtaop.com";
|
|
298
299
|
var PRICE_USD_RE = /^(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
299
300
|
var ZERO_PRICE_USD_RE = /^0(?:\.0+)?$/;
|
|
300
301
|
function x402SellerPricingState(seller) {
|
|
@@ -317,6 +318,14 @@ function normalizeB402PriceUsd(value) {
|
|
|
317
318
|
}
|
|
318
319
|
return normalized;
|
|
319
320
|
}
|
|
321
|
+
function isB402TestnetBaseUrl(value) {
|
|
322
|
+
try {
|
|
323
|
+
const url = new URL(value);
|
|
324
|
+
if (url.origin === DEFAULT_B402_TESTNET_BASE_URL) return true;
|
|
325
|
+
} catch {
|
|
326
|
+
}
|
|
327
|
+
return /sandbox|test/.test(value.toLowerCase());
|
|
328
|
+
}
|
|
320
329
|
function x402SellerUsesB402(cfg) {
|
|
321
330
|
const payments = table2(cfg.payments);
|
|
322
331
|
const seller = table2(payments.x402_seller);
|
|
@@ -649,10 +658,14 @@ function b402Credentials(agentRoot) {
|
|
|
649
658
|
if (value) values.set(key, value);
|
|
650
659
|
}
|
|
651
660
|
const privateKey = values.has("B402_PRIVATE_KEY") || values.has("B402_PRIVATE_KEY_B64");
|
|
661
|
+
const onlyDefaultBaseUrl = values.size === 1 && values.get("B402_BASE_URL")?.replace(/\/+$/, "") === DEFAULT_B402_TESTNET_BASE_URL;
|
|
652
662
|
return {
|
|
653
663
|
presentKeys: [...values.keys()],
|
|
654
664
|
complete: values.has("B402_BASE_URL") && values.has("B402_CLIENT_ID") && values.has("B402_ACCESS_TOKEN") && privateKey,
|
|
655
|
-
|
|
665
|
+
// The testnet facilitator URL is a non-secret platform default. On its own it must not turn an
|
|
666
|
+
// otherwise dormant rail into a "partial credentials" deployment failure. Any custom URL or
|
|
667
|
+
// merchant credential still preserves the existing partial/unused checks.
|
|
668
|
+
any: values.size > 0 && !onlyDefaultBaseUrl,
|
|
656
669
|
bothPrivateKeyFormats: values.has("B402_PRIVATE_KEY") && values.has("B402_PRIVATE_KEY_B64"),
|
|
657
670
|
baseUrl: values.get("B402_BASE_URL") ?? null
|
|
658
671
|
};
|
|
@@ -1079,8 +1092,10 @@ export {
|
|
|
1079
1092
|
devPortOf,
|
|
1080
1093
|
recipeModeOf,
|
|
1081
1094
|
DEFAULT_B402_PRICE_USD,
|
|
1095
|
+
DEFAULT_B402_TESTNET_BASE_URL,
|
|
1082
1096
|
x402SellerPricingState,
|
|
1083
1097
|
normalizeB402PriceUsd,
|
|
1098
|
+
isB402TestnetBaseUrl,
|
|
1084
1099
|
x402SellerUsesB402,
|
|
1085
1100
|
x402SellerIsFree,
|
|
1086
1101
|
whichBin,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bnbagent/studio-cli",
|
|
3
|
-
"version": "0.0.6-alpha.
|
|
3
|
+
"version": "0.0.6-alpha.3",
|
|
4
4
|
"description": "The `bag` CLI: scaffold, run, deploy, and monetize a single seller agent on BNB Chain (ERC-8004 identity, ERC-8183 commerce, x402 payments).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"bag": "./dist/bag.js"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@bnbagent/sdk": "0.5.0-alpha.
|
|
28
|
+
"@bnbagent/sdk": "0.5.0-alpha.2",
|
|
29
29
|
"ai": "^7.0.29",
|
|
30
30
|
"archiver": "^8.0.0",
|
|
31
31
|
"commander": "^15.0.0",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"tar": "^7.4.0",
|
|
38
38
|
"viem": "^2.54.0",
|
|
39
39
|
"yaml": "^2.9.0",
|
|
40
|
-
"@bnbagent/studio-runtime": "0.0.6-alpha.
|
|
40
|
+
"@bnbagent/studio-runtime": "0.0.6-alpha.3"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@a2a-js/sdk": "^0.3.14",
|
|
@@ -159,8 +159,9 @@ function defaultNetwork(): string {
|
|
|
159
159
|
// the ONLY automatic signing path outside signing.ts — it is budget-gated and
|
|
160
160
|
// is NOT an LLM tool. It rides transparently into the delivery step.
|
|
161
161
|
//
|
|
162
|
-
// The LLM runs
|
|
163
|
-
//
|
|
162
|
+
// The LLM runs only in an authorized value step: verified ERC-8183 delivery
|
|
163
|
+
// or x402 work after its payment/free gate. `negotiate` is rule-based and
|
|
164
|
+
// never touches the LLM. The read-only chain tools are
|
|
164
165
|
// attached so the work can read on-chain context if it needs to — drop them
|
|
165
166
|
// from `tools.ts` if your work doesn't read chain. Signing / settle are NEVER
|
|
166
167
|
// tools — they are fixed code in signing.ts, triggered by the A2A skills,
|
|
@@ -178,7 +179,9 @@ export function buildRunWork(): RunWork {
|
|
|
178
179
|
const result = await generateText({
|
|
179
180
|
model,
|
|
180
181
|
system:
|
|
181
|
-
"You are a seller agent.
|
|
182
|
+
"You are a seller agent. The runtime has already authorized this task " +
|
|
183
|
+
"through its configured commerce rail. Complete the user's task now; " +
|
|
184
|
+
"do not ask for a job ID or additional payment. " +
|
|
182
185
|
"Be concrete and concise. Use the read-only chain tools when on-chain " +
|
|
183
186
|
"context helps. If a paid-data tool such as `buy_with_x402` is available " +
|
|
184
187
|
"to you, USE IT to fetch the data a task needs — those merchants (e.g. " +
|
|
@@ -150,8 +150,9 @@ function defaultNetwork(): string {
|
|
|
150
150
|
// the ONLY automatic signing path outside signing.ts — it is budget-gated and
|
|
151
151
|
// is NOT an LLM tool. It rides transparently into the delivery step.
|
|
152
152
|
//
|
|
153
|
-
// The LLM runs
|
|
154
|
-
//
|
|
153
|
+
// The LLM runs only in an authorized value step: verified ERC-8183 delivery
|
|
154
|
+
// or x402 work after its payment/free gate. `negotiate` is rule-based and
|
|
155
|
+
// never touches the LLM. The read-only chain tools are
|
|
155
156
|
// attached so the work can read on-chain context if it needs to — drop them
|
|
156
157
|
// from `tools.ts` if your work doesn't read chain. Signing / settle are NEVER
|
|
157
158
|
// tools — they are fixed code in signing.ts, triggered by the A2A skills,
|
|
@@ -169,7 +170,9 @@ export function buildRunWork(): RunWork {
|
|
|
169
170
|
const result = await generateText({
|
|
170
171
|
model,
|
|
171
172
|
system:
|
|
172
|
-
"You are a seller agent.
|
|
173
|
+
"You are a seller agent. The runtime has already authorized this task " +
|
|
174
|
+
"through its configured commerce rail. Complete the user's task now; " +
|
|
175
|
+
"do not ask for a job ID or additional payment. " +
|
|
173
176
|
"Be concrete and concise. Use the read-only chain tools when on-chain " +
|
|
174
177
|
"context helps. If a paid-data tool such as `buy_with_x402` is available " +
|
|
175
178
|
"to you, USE IT to fetch the data a task needs — those merchants (e.g. " +
|
|
@@ -184,10 +184,10 @@ function flatQuery(query: Record<string, unknown>): Record<string, string> {
|
|
|
184
184
|
return out;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// ── LLM work hook (lazy: built on first
|
|
188
|
-
// Deferred construction keeps
|
|
189
|
-
//
|
|
190
|
-
//
|
|
187
|
+
// ── LLM work hook (lazy: built on first authorized task) ─────────────────────
|
|
188
|
+
// Deferred construction keeps negotiate and unpaid x402 quote paths from
|
|
189
|
+
// building the model, and keeps this module importable without the provider
|
|
190
|
+
// env until a deliverable is actually produced.
|
|
191
191
|
type RunLlm = (prompt: string) => Promise<string>;
|
|
192
192
|
let cachedRunLlm: RunLlm | null = null;
|
|
193
193
|
|
|
@@ -200,7 +200,9 @@ async function runLlm(prompt: string): Promise<string> {
|
|
|
200
200
|
const result = await generateText({
|
|
201
201
|
model,
|
|
202
202
|
system:
|
|
203
|
-
"You are a seller agent.
|
|
203
|
+
"You are a seller agent. The runtime has already authorized this task " +
|
|
204
|
+
"through its configured commerce rail. Complete the user's task now; " +
|
|
205
|
+
"do not ask for a job ID or additional payment. " +
|
|
204
206
|
"Be concrete and concise. Use the read-only chain tools when on-chain " +
|
|
205
207
|
"context helps. If a paid-data tool such as `buy_with_x402` is " +
|
|
206
208
|
"available to you, USE IT to fetch the data a task needs — those " +
|
|
@@ -105,8 +105,9 @@ async function withTimeout<T>(
|
|
|
105
105
|
* The LLM work hook: produce the deliverable text for a prompt.
|
|
106
106
|
*
|
|
107
107
|
* Built in `main.ts` from the AI SDK (`generateText` + the read-only chain
|
|
108
|
-
* tools); called
|
|
109
|
-
*
|
|
108
|
+
* tools); called by verified ERC-8183 delivery and, through the runtime
|
|
109
|
+
* adapter, by x402 only after its commerce gate. `abortSignal` is wired to
|
|
110
|
+
* the delivery timeout so a hung LLM call is actually cancelled.
|
|
110
111
|
*/
|
|
111
112
|
export type RunWork = (
|
|
112
113
|
prompt: string,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bnbagent-studio
|
|
3
|
-
description: The single entry point for bnbagent-studio — a TypeScript CLI (`bag`) for building a blockchain SELLER agent that earns $U on BNB Chain via ERC-8004 + ERC-8183 + x402 (Pieverse LLM inside). Load this skill whenever the user works in a bnbagent-studio / `bag` project, or wants to create/scaffold, deploy, run, debug, operate, or monetize such a seller agent (composable A2A, MCP, and X402 faces; BNB Chain trial
|
|
3
|
+
description: The single entry point for bnbagent-studio — a TypeScript CLI (`bag`) for building a blockchain SELLER agent that earns $U on BNB Chain via ERC-8004 + ERC-8183 + x402 (Pieverse LLM inside). Load this skill whenever the user works in a bnbagent-studio / `bag` project, or wants to create/scaffold, deploy, run, debug, operate, or monetize such a seller agent (composable A2A, MCP, and X402 faces; BNB Chain trial or AWS AgentCore). All detailed playbooks ship as references/ files inside this skill — route via the decision tree in the body. When invoked with arguments, treat them as the user's intent and route the same way.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# bnbagent-studio (the single entry point)
|
|
@@ -10,15 +10,13 @@ ERC-8004 / ERC-8183 / Pieverse LLM) into a TypeScript agent project, then deploy
|
|
|
10
10
|
as a **single blockchain seller runtime**. A2A, MCP, and X402 are composable
|
|
11
11
|
public faces selected with `--protocols`; A2A is the default. `bag deploy` uses
|
|
12
12
|
**scheme C**: every new deploy
|
|
13
|
-
or redeploy explicitly selects BNB
|
|
13
|
+
or redeploy explicitly selects BNB or AWS; a recorded deployment is
|
|
14
14
|
used only to offer an explicit update action, never as a silent default. BNB is
|
|
15
|
-
a 48h testnet trial and is disabled after expiry. AWS
|
|
15
|
+
a 48h testnet trial and is disabled after expiry. AWS deploys into the
|
|
16
16
|
user's own account. All cloud lifecycle calls go through the pinned
|
|
17
|
-
`@bnbagent/deploy-cli`; never require `aws
|
|
18
|
-
BNB/AWS share the agentcore scaffold
|
|
19
|
-
|
|
20
|
-
Invocations contract is not the native MCP transport). Treat an incompatible provider row as unavailable—do not
|
|
21
|
-
force through it or mutate the scaffold during deploy.
|
|
17
|
+
`@bnbagent/deploy-cli`; never require the `aws` CLI.
|
|
18
|
+
BNB/AWS share the agentcore scaffold. Treat an incompatible provider row as
|
|
19
|
+
unavailable—do not force through it or mutate the scaffold during deploy.
|
|
22
20
|
|
|
23
21
|
Invoked as `/bnbagent-studio <ask>`? Treat `<ask>` as the user's intent and
|
|
24
22
|
route it through the decision tree below, exactly like a natural-language ask.
|
|
@@ -57,7 +55,7 @@ not answer from memory.
|
|
|
57
55
|
| Run / debug / dev / doctor / RPC / balance / incident triage | `references/bnbagent-studio-operating.md` |
|
|
58
56
|
| Implement what the Agent sells, tune pricing, publish over A2A and/or MCP, defend disputes (seller flow) | `references/bnbagent-studio-selling-via-8183.md` |
|
|
59
57
|
| Sell one paid or FREE HTTP request through the B402-backed x402 rail (pricing choice; paid merchant application, RSA key, credentials, IP allowlist, activation) | `references/bnbagent-studio-selling-via-b402.md` |
|
|
60
|
-
| Deploy / redeploy / status / logs / destroy | Run `bag deploy` and explicitly choose a provider. Non-interactive deploy requires `--provider bnb\|aws
|
|
58
|
+
| Deploy / redeploy / status / logs / destroy | Run `bag deploy` and explicitly choose a provider. Non-interactive deploy requires `--provider bnb\|aws --yes` (and `--allow-multiple` when keeping another provider active). Read `references/bnbagent-studio-use-bnb-trial.md` or `references/bnbagent-studio-use-aws-agentcore.md` for the selected provider. `bag deploy status` lists every recorded provider; multi-deployment logs/verify/destroy require `--provider`. |
|
|
61
59
|
| Wire chain-read tools into the Agent's LLM (AI SDK `tool()` wrappers, or any TS agent framework) | `references/bnbagent-studio-wiring-llm-tools.md` |
|
|
62
60
|
| Buy a service from another ERC-8183 seller via CLI — incl. testing your own seller from the buyer side (v2/internal — NOT the v1 seller product flow) | `references/bnbagent-studio-buying-via-8183.md` |
|
|
63
61
|
| Give the agent a PAID x402 capability — CMC market data / Binance Bazaar (B402) merchants / any pay-per-call API (`bag x402 trust`, x402-buyer recipe, 402 buyer errors) | `references/bnbagent-studio-buying-from-bazaar.md` |
|
|
@@ -99,7 +97,7 @@ prices retain the paid merchant flow.
|
|
|
99
97
|
|
|
100
98
|
## CLI groups at a glance
|
|
101
99
|
|
|
102
|
-
`init`, `scan`, `recipe`, `skills`, `wallet`, `erc8004`, `erc8183`, `x402`, `agents`, `config`, `env`, `dev`, `doctor`, `audit`, `deploy`, `platform`, `llm`, `bundle`, `budget` — see `bag --help` for details. `bag deploy [--provider bnb\|aws
|
|
100
|
+
`init`, `scan`, `recipe`, `skills`, `wallet`, `erc8004`, `erc8183`, `x402`, `agents`, `config`, `env`, `dev`, `doctor`, `audit`, `deploy`, `platform`, `llm`, `bundle`, `budget` — see `bag --help` for details. `bag deploy [--provider bnb\|aws]` is the primary deploy command; `prepare`, `verify`, `status`, `info`, `destroy`, `logs`, `fix-gitignore`, and `provision-cognito` remain lifecycle subcommands (`deploy agent` is a deprecated compatibility alias). Provider deploy/status/logs/destroy and deploy-time credential validation are delegated to pinned `@bnbagent/deploy-cli@0.4.14`.
|
|
103
101
|
|
|
104
102
|
## Tool surface
|
|
105
103
|
|
|
@@ -171,7 +171,7 @@ refill with `bag llm topup` or enable the budget with `bag budget enable`.
|
|
|
171
171
|
|
|
172
172
|
## Step 5 — Deploy the agent
|
|
173
173
|
|
|
174
|
-
`bag deploy` always asks the operator to choose BNB
|
|
174
|
+
`bag deploy` always asks the operator to choose BNB or AWS; it never
|
|
175
175
|
silently reuses `[deploy].destination` or the last provider.
|
|
176
176
|
|
|
177
177
|
**Platform scaffold** (the bare-init default while the campaign runs) — one
|
|
@@ -27,7 +27,6 @@ directory (Claude Code: `~/.claude/skills/bnbagent-studio/references/`; Cursor:
|
|
|
27
27
|
the file when the topic comes up — don't answer from memory:
|
|
28
28
|
- `bnbagent-studio-use-aws-agentcore.md` — the delegated AgentCore lifecycle (`bag deploy --provider aws` / `status` / `logs` / `verify` / `destroy`, `provision-cognito`) + AWS prerequisites
|
|
29
29
|
- `bnbagent-studio-use-bnb-trial.md` — GitHub device login, 48h eligibility, staging verification, and the delegated BNB trial lifecycle
|
|
30
|
-
- `bnbagent-studio-use-azure-foundry.md` — the delegated Azure Foundry lifecycle (`bag deploy --provider azure`; no `az`/`azd` CLI)
|
|
31
30
|
- `bnbagent-studio-using-twak-wallet.md` — `[wallet].kind = "twak"` create / fund / SIWE-bind / container deploy / limitations
|
|
32
31
|
- `bnbagent-studio-extending-signing.md` — `PolicyViolation` / `X402PolicyError` diagnosis + extending the EIP-712 allowlist
|
|
33
32
|
- `bnbagent-studio-adding-to-project.md` — adding the seller runtime to an existing TypeScript project
|
|
@@ -55,8 +54,8 @@ For seller job-lifecycle decisions (settle / submit / dispute defense), read
|
|
|
55
54
|
| "submit work for job X" | **seller action** — read `bnbagent-studio-selling-via-8183.md` (same directory) for the submit/dispute flow |
|
|
56
55
|
| "tx not confirming" | Read BscScan link from prior tx output + check `eth_getTransactionCount` |
|
|
57
56
|
| "wallet balance is wrong" | Check both tBNB (gas) and U (token); see balance section |
|
|
58
|
-
| "is it deployed?" / "deploy status" | `bag deploy status` lists every locally recorded BNB/AWS
|
|
59
|
-
| "deploy logs" / "verify" / "tear it down" | With one recorded deployment, `bag deploy {logs,verify,destroy}` selects it automatically. With multiple, choose interactively or pass `--provider bnb\|aws
|
|
57
|
+
| "is it deployed?" / "deploy status" | `bag deploy status` lists every locally recorded BNB/AWS deployment and asks `bnbagent-deploy` for live state; add `--no-probe` for record-only output |
|
|
58
|
+
| "deploy logs" / "verify" / "tear it down" | With one recorded deployment, `bag deploy {logs,verify,destroy}` selects it automatically. With multiple, choose interactively or pass `--provider bnb\|aws` in automation. Cloud calls always go through `bnbagent-deploy`. `bag platform credit` shows the BNB trial countdown. |
|
|
60
59
|
|
|
61
60
|
## Common ops procedures
|
|
62
61
|
|
|
@@ -161,7 +160,7 @@ testnet U pays ERC-8183 jobs, mainnet U pays the Pieverse LLM auto-renew.
|
|
|
161
160
|
Same wallet address on both chains.
|
|
162
161
|
|
|
163
162
|
`bag doctor` prints ERC-8183 pricing as `PAID` or `FREE`. FREE is not ready on
|
|
164
|
-
the canonical contract stack: select one zero-price-compatible
|
|
163
|
+
the canonical contract stack: select one zero-price-compatible custom stack
|
|
165
164
|
by setting `ERC8183_COMMERCE_ADDRESS`, `ERC8183_ROUTER_ADDRESS`, and
|
|
166
165
|
`ERC8183_POLICY_ADDRESS` together. A partial set fails because it can mix
|
|
167
166
|
incompatible commerce, router, and policy deployments.
|
|
@@ -216,7 +215,7 @@ covered in `bnbagent-studio-selling-via-8183.md` (same directory).
|
|
|
216
215
|
| `notify_funded` replies `{"status":"rejected","reason":...}` | `verifySignedJob` failed synchronously in the ack — a **permanent** failure | `reason` names it: not our signature / tampered terms / underfunded / expired (or `error` for a malformed `job_id`). The job is refused outright; re-fund/re-notify with a correct, fully-funded job |
|
|
217
216
|
| Job stays `FUNDED`, never reaches `SUBMITTED` after an `accepted` ack | Background delivery failed (`runWork` / `submitResult` raised) — **not** visible in the A2A reply | The ack only confirms verify passed; delivery runs in the background. Observe the failure via the chain (job never leaves `FUNDED`) + CloudWatch logs; a later `notify_funded` re-attempts it via the sweep |
|
|
218
217
|
| `ERC8183JobOps` has no such export from `@bnbagent/sdk` | package.json pinned an old `@bnbagent/sdk` (missing class) | Bump the dependency and reinstall |
|
|
219
|
-
| FREE price fails doctor/prepare on canonical contracts | `price = "0"` is selected without a zero-price-compatible stack | Set all three `ERC8183_*_ADDRESS` overrides from
|
|
218
|
+
| FREE price fails doctor/prepare on canonical contracts | `price = "0"` is selected without a zero-price-compatible stack | Set all three `ERC8183_*_ADDRESS` overrides from one compatible custom deployment, then rerun `bag doctor` and `bag deploy prepare` |
|
|
220
219
|
| ERC-8183 contract override is incomplete | Only one or two of commerce/router/policy were selected | Set or remove all three together; never mix stacks |
|
|
221
220
|
| `/x402` is public without a 402 challenge | `payments.x402_seller.price_usd = "0"` selected anonymous FREE passthrough | If payment is intended, set a positive decimal price, configure the complete B402 credential set, rerun `bag doctor`, and redeploy |
|
|
222
221
|
| B402 credentials are missing but x402 reports FREE | Expected: FREE bypasses B402 and does not synchronize its secrets | No credential fix is needed; change to a positive price only when the route should charge |
|
|
@@ -235,7 +235,7 @@ Step 6b when `storage=ipfs`):
|
|
|
235
235
|
`--erc8183-price 0` only when the user explicitly chose FREE; omitting the
|
|
236
236
|
flag preserves the paid 0.1 U default. FREE additionally requires all three
|
|
237
237
|
`ERC8183_COMMERCE_ADDRESS`, `ERC8183_ROUTER_ADDRESS`, and
|
|
238
|
-
`ERC8183_POLICY_ADDRESS` values from one zero-price-compatible
|
|
238
|
+
`ERC8183_POLICY_ADDRESS` values from one zero-price-compatible custom
|
|
239
239
|
stack; set them with `bag env set` after scaffolding. For B402, pass
|
|
240
240
|
`--b402-price 0` only after the user explicitly accepts an unrestricted
|
|
241
241
|
anonymous FREE `/x402` endpoint. FREE bypasses B402 verify/settle and needs
|
|
@@ -115,16 +115,16 @@ string:
|
|
|
115
115
|
|
|
116
116
|
```bash
|
|
117
117
|
bag config set payments.erc8183.price 0
|
|
118
|
-
bag env set ERC8183_COMMERCE_ADDRESS <
|
|
119
|
-
bag env set ERC8183_ROUTER_ADDRESS <
|
|
120
|
-
bag env set ERC8183_POLICY_ADDRESS <
|
|
118
|
+
bag env set ERC8183_COMMERCE_ADDRESS <commerce-address>
|
|
119
|
+
bag env set ERC8183_ROUTER_ADDRESS <router-address>
|
|
120
|
+
bag env set ERC8183_POLICY_ADDRESS <policy-address>
|
|
121
121
|
bag doctor
|
|
122
122
|
bag deploy prepare
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
Take all three addresses from the same
|
|
125
|
+
Take all three addresses from the same compatible custom deployment.
|
|
126
126
|
Doctor/prepare reject canonical or partial contract selection for FREE and
|
|
127
|
-
announce `zero token escrow` only when the complete custom
|
|
127
|
+
announce `zero token escrow` only when the complete custom stack is selected.
|
|
128
128
|
|
|
129
129
|
## Stage 3 — LLM credit continuity (Pieverse projects only)
|
|
130
130
|
|
|
@@ -7,7 +7,7 @@ description: When the user wants to deploy or operate an A2A bnbagent-studio pro
|
|
|
7
7
|
|
|
8
8
|
# bnbagent-studio-use-azure-foundry
|
|
9
9
|
|
|
10
|
-
> **Preview.** Azure Foundry support is fully wired
|
|
10
|
+
> **Preview — not advertised in this release.** Azure Foundry support is fully wired but hidden from the `--runtime` menu and the deploy provider menu; these steps still work if you select `azure-foundry` / `--provider azure` explicitly. The most recent end-to-end live verification predates the TypeScript rewrite — treat your first deploy as a verification run.
|
|
11
11
|
|
|
12
12
|
Procedure for deploying and operating the seller Agent on **Azure AI
|
|
13
13
|
Foundry Hosted Agents** (`[stack].runtime = "azure-foundry"`). ALL cloud
|
|
@@ -13,7 +13,7 @@ keep `bsc-testnet`, and explain that the runtime signing material is transmitted
|
|
|
13
13
|
to the operator's managed secret store for the trial. Never use a mainnet key.
|
|
14
14
|
|
|
15
15
|
All auth and cloud lifecycle work must cross the pinned
|
|
16
|
-
`@bnbagent/deploy-cli@0.4.14` boundary. Do not call AWS
|
|
16
|
+
`@bnbagent/deploy-cli@0.4.14` boundary. Do not call the AWS CLI or platform
|
|
17
17
|
REST routes directly.
|
|
18
18
|
|
|
19
19
|
## Select and authenticate
|
|
@@ -35,7 +35,7 @@ Before offering BNB, inspect the trial result:
|
|
|
35
35
|
- `available`: selectable; explain that the 48h clock starts on first success.
|
|
36
36
|
- `active`: selectable; show remaining time and expiry immediately.
|
|
37
37
|
- `expired`: show the row and expiry, but mark it unavailable and do not select
|
|
38
|
-
it. AWS
|
|
38
|
+
it. AWS remains independently available when compatible with the
|
|
39
39
|
project scaffold.
|
|
40
40
|
- unknown/auth required: explain that eligibility cannot be confirmed until
|
|
41
41
|
login; the delegated deploy rechecks before building.
|
|
@@ -173,11 +173,11 @@ Two assets, two different rules:
|
|
|
173
173
|
settles), so topping up burns no BNB. A twak wallet is also a supported
|
|
174
174
|
b402 **seller** payout wallet (`bag init --wallet-kind twak --rails b402`);
|
|
175
175
|
receiving needs no signature or gas either.
|
|
176
|
-
- **BNB (gas)** — **testnet
|
|
177
|
-
Testnet: the SDK forwards MegaFuel's
|
|
178
|
-
twak >= 0.20.0)
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
- **BNB (gas)** — **testnet canonical contracts normally use sponsorship;
|
|
177
|
+
mainnet needs a little for ERC-8183.** Testnet: the SDK forwards MegaFuel's
|
|
178
|
+
testnet paymaster (`--paymaster-url`, twak >= 0.20.0). Sponsorship still
|
|
179
|
+
depends on the paymaster policy covering the target contract and method;
|
|
180
|
+
keep a little tBNB (~0.007) as fallback. Mainnet: x402 stays gasless and `bag 8004
|
|
181
181
|
register` is gas-sponsored by twak internally (Trust gateway — studio
|
|
182
182
|
passes no paymaster flag), but **`8183 settle` / `fund` self-pay gas**, so
|
|
183
183
|
keep ~0.007 BNB on the wallet for them.
|
|
@@ -203,8 +203,8 @@ spending limit nothing can bypass. Studio's daily caps
|
|
|
203
203
|
(persisted to `.studio/spend-ledger.json`), best-effort in the deployed
|
|
204
204
|
runtime (in-memory, resets on cold start).
|
|
205
205
|
|
|
206
|
-
Testnet faucet: https://www.bnbchain.org/en/testnet-faucet (tBNB
|
|
207
|
-
Mainnet: U via PancakeSwap
|
|
206
|
+
Testnet faucet: https://www.bnbchain.org/en/testnet-faucet (tBNB fallback).
|
|
207
|
+
Mainnet: U via PancakeSwap; keep BNB for ERC-8183 fund/settle.
|
|
208
208
|
|
|
209
209
|
## 4. SIWE binding (Pieverse) — ALWAYS bind before paying
|
|
210
210
|
|
|
@@ -244,7 +244,9 @@ registers a `Container` runtime and `app/agent/Dockerfile` builds the image
|
|
|
244
244
|
|---|---|---|
|
|
245
245
|
| ~~Seller `submit` unavailable~~ | ~~REQ-1~~ RESOLVED in v0.19.0 | `submit --opt-params` works — verified on-chain. |
|
|
246
246
|
| ~~Seller `quote` signing broken~~ | ~~S-11 regression in v0.19.0~~ RESOLVED in v0.19.1 | v0.19.0 hex-decoded `0x…` messages and signed the bytes, so provider_sig never verified (testnet also rejected `sign-message --chain bsctestnet`). v0.19.1 signs the literal text (EIP-191): `sign_quote` works on both wallet kinds. |
|
|
247
|
-
| ~~
|
|
247
|
+
| ~~No testnet paymaster URL~~ | ~~REQ-2~~ RESOLVED in v0.20.0 | twak accepts `--paymaster-url`; the SDK forwards MegaFuel's testnet endpoint on eligible writes. Actual sponsorship depends on the paymaster policy covering the target and method (the relay itself is flaky — see the BUG-029 warning in §3). The CLI floor is **0.20.0**. |
|
|
248
|
+
| Custom ERC-8004 registry | supported | Set `ERC8004_REGISTRY_ADDRESS`; the SDK requires the intent target and env override to match before invoking twak. Sponsorship still depends on paymaster policy coverage, so keep fallback tBNB. |
|
|
249
|
+
| Custom ERC-8183 targets unavailable | upstream feature request | twak v0.20.0 has no Commerce/Router/Policy address option. Studio doctor/prepare and the SDK fail closed instead of silently executing on canonical contracts; use `evm-local` for a custom ERC-8183 deployment. |
|
|
248
250
|
| No generic EIP-712 signing | P0 (won't fix) | `[wallet.signing]` is ignored; payments go through the delegated payer's own prechecks + `--max-payment`. Endpoints needing an `Authorization` header *and* x402 are unavailable (e.g. `bag llm key new --initial-usd > 0` — use `--initial-usd 0` + topup + allocate instead, same end state). |
|
|
249
251
|
| No wallet import | S-6 | Switching wallet kinds changes your address → re-run `bag 8004 register` (new on-chain identity). |
|
|
250
252
|
| Programmatic wallet creation forces password onto argv | S-8 | Bridged by `bag wallet twak-init` (password via stdin / 0600 file / hidden prompt — never argv); the manual twak commands remain a fallback. |
|