@bnbagent/studio-cli 0.0.13-alpha.7 → 0.0.13-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/bag.js +353 -71
  2. package/dist/{chunk-YZ4WH5MD.js → chunk-NTDWVEW2.js} +59 -17
  3. package/dist/{deployCli-A4EW5FTF.js → deployCli-ZESBUWQB.js} +3 -1
  4. package/package.json +4 -3
  5. package/recipes/agent/code/{{PKG}}/signing.ts.tmpl +2 -2
  6. package/recipes/agent/recipe.toml +1 -1
  7. package/recipes/mpp-buyer/recipe.toml +1 -1
  8. package/recipes/runtimes/agentcore/code/{{PKG}}/dualMain.ts.tmpl +2 -0
  9. package/recipes/runtimes/agentcore/code/{{PKG}}/executor.ts.tmpl +14 -6
  10. package/recipes/runtimes/agentcore/code/{{PKG}}/mcpMain.ts.tmpl +63 -30
  11. package/recipes/runtimes/agentcore/code/{{PKG}}/requestLimits.ts.tmpl +178 -0
  12. package/recipes/runtimes/agentcore/code/{{PKG}}/sellerCore.ts.tmpl +3 -0
  13. package/recipes/runtimes/agentcore/code/{{PKG}}/unifiedMain.ts.tmpl +2 -0
  14. package/recipes/runtimes/agentcore/recipe.toml +1 -1
  15. package/recipes/runtimes/azure-foundry/code/{{PKG}}/executor.ts.tmpl +14 -6
  16. package/recipes/runtimes/azure-foundry/code/{{PKG}}/mcpMain.ts.tmpl +63 -30
  17. package/recipes/runtimes/azure-foundry/code/{{PKG}}/requestLimits.ts.tmpl +178 -0
  18. package/recipes/runtimes/azure-foundry/code/{{PKG}}/sellerCore.ts.tmpl +3 -0
  19. package/recipes/runtimes/azure-foundry/code/{{PKG}}/unifiedMain.ts.tmpl +2 -0
  20. package/recipes/runtimes/azure-foundry/recipe.toml +1 -1
  21. package/recipes/wallet/recipe.toml +0 -1
  22. package/recipes/x402-buyer/recipe.toml +1 -1
  23. package/skills/references/bnbagent-studio-selling-via-b402.md +1 -1
  24. package/skills/references/bnbagent-studio-using-altana-wallet.md +3 -2
package/dist/bag.js CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  checkTwak,
20
20
  commerceRails,
21
21
  deployChecks,
22
+ deployCommandOverrideAllowed,
22
23
  deployEndpointValue,
23
24
  devPortOf,
24
25
  dryRunBundle,
@@ -55,7 +56,7 @@ import {
55
56
  x402SellerIsFree,
56
57
  x402SellerPricingState,
57
58
  x402SellerUsesB402
58
- } from "./chunk-YZ4WH5MD.js";
59
+ } from "./chunk-NTDWVEW2.js";
59
60
  import {
60
61
  TWAK_CLI_MIN_VERSION,
61
62
  TWAK_CLI_VERSION,
@@ -233,7 +234,7 @@ import {
233
234
  var CAMPAIGN_DOC_URL = "https://www.bnbchain.org/en/blog/bnb-agent-studio-is-live-on-bnb-chain-ai-agents-from-one-prompt";
234
235
  var CAMPAIGN_CHECK_TIMEOUT_MS = 6e3;
235
236
  async function fetchCampaignActive() {
236
- const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-A4EW5FTF.js");
237
+ const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-ZESBUWQB.js");
237
238
  const controller = new AbortController();
238
239
  const timer = setTimeout(() => controller.abort(), CAMPAIGN_CHECK_TIMEOUT_MS);
239
240
  try {
@@ -1808,7 +1809,7 @@ async function vendorLocalTarballs(agentDir, opts = {}) {
1808
1809
  if (local === null) {
1809
1810
  continue;
1810
1811
  }
1811
- if (!opts.force && await publishedOnRegistry(pkgName, local.version)) {
1812
+ if (opts.force === false && await publishedOnRegistry(pkgName, local.version)) {
1812
1813
  continue;
1813
1814
  }
1814
1815
  fs7.mkdirSync(vendorDir, { recursive: true });
@@ -2012,7 +2013,12 @@ async function createBundle(opts = {}) {
2012
2013
  fs8.mkdirSync(stagingRoot, { recursive: true });
2013
2014
  try {
2014
2015
  printOut(`\u2192 Staging seller workspace at ${stagedWorkspace}\u2026`);
2015
- copyWorkspace(workspaceRoot, stagedWorkspace, outputDir);
2016
+ copyWorkspace(
2017
+ workspaceRoot,
2018
+ stagedWorkspace,
2019
+ outputDir,
2020
+ configuredBundleSecretPaths(agentRoot2)
2021
+ );
2016
2022
  printOut("\u2192 Generating .studio/.env.local.example (values stripped)\u2026");
2017
2023
  writeEnvExample(agentRoot2, stagedWorkspace);
2018
2024
  printOut("\u2192 Packing @bnbagent/sdk + @bnbagent/studio-runtime\u2026");
@@ -2079,17 +2085,37 @@ function excludedName(name) {
2079
2085
  const lowerName = name.toLowerCase();
2080
2086
  return EXCLUDED_NAMES.has(lowerName) || CREDENTIAL_FILE_NAMES.has(lowerName) || lowerName.startsWith(".env") || lowerName.endsWith(".egg-info") || lowerName.startsWith(".venv-");
2081
2087
  }
2088
+ function configuredBundleSecretPaths(agentRoot2) {
2089
+ const cfg = loadStudioToml2(path7.join(agentRoot2, "studio.toml"));
2090
+ const wallet = cfg.wallet !== null && typeof cfg.wallet === "object" && !Array.isArray(cfg.wallet) ? cfg.wallet : {};
2091
+ return ["keystore_dir", "twak_home", "session_file"].map((key) => wallet[key]).filter(
2092
+ (value) => Boolean(typeof value === "string" && value.trim())
2093
+ ).map(
2094
+ (value) => path7.resolve(
2095
+ path7.isAbsolute(value) ? value : path7.join(agentRoot2, value)
2096
+ )
2097
+ );
2098
+ }
2082
2099
  function inside(child, parent) {
2083
2100
  const rel = path7.relative(parent, child);
2084
2101
  return rel === "" || !rel.startsWith("..") && !path7.isAbsolute(rel);
2085
2102
  }
2086
- function copyWorkspace(sourceRoot, destinationRoot, outputDir) {
2103
+ function copyWorkspace(sourceRoot, destinationRoot, outputDir, excludedSecretPaths = []) {
2087
2104
  const source = path7.resolve(sourceRoot);
2088
2105
  const excludedOutput = outputDir ? path7.resolve(outputDir) : null;
2106
+ const secretPaths = excludedSecretPaths.map((value) => path7.resolve(value));
2107
+ if (secretPaths.includes(source)) {
2108
+ throw new Error(
2109
+ "refusing to bundle: a configured wallet secret path resolves to the workspace root"
2110
+ );
2111
+ }
2089
2112
  const copy = (src, dst) => {
2090
2113
  if (excludedOutput !== null && inside(src, excludedOutput)) {
2091
2114
  return;
2092
2115
  }
2116
+ if (src !== source && secretPaths.some((secret) => inside(src, secret))) {
2117
+ return;
2118
+ }
2093
2119
  const name = path7.basename(src);
2094
2120
  if (src !== source && excludedName(name)) {
2095
2121
  return;
@@ -2203,11 +2229,31 @@ function findStagedLeak(stagedWorkspace) {
2203
2229
  });
2204
2230
  if (unsafeExample) return `non-empty env example ${rel}`;
2205
2231
  }
2232
+ if (stat.isFile()) {
2233
+ const bytes = fs8.readFileSync(full);
2234
+ if (bytes.includes(0)) continue;
2235
+ const text2 = bytes.toString("utf-8");
2236
+ if (looksLikeKeystore(text2)) return `keystore content in ${rel}`;
2237
+ if (/(?:^|[^0-9a-f])0x[0-9a-f]{64}(?![0-9a-f])/iu.test(text2)) {
2238
+ return `private-key content in ${rel}`;
2239
+ }
2240
+ }
2206
2241
  }
2207
2242
  return null;
2208
2243
  };
2209
2244
  return walk(root);
2210
2245
  }
2246
+ function looksLikeKeystore(text2) {
2247
+ try {
2248
+ const value = JSON.parse(text2);
2249
+ const crypto6 = value.crypto;
2250
+ return Boolean(
2251
+ value.version === 3 && typeof value.address === "string" && crypto6 !== null && typeof crypto6 === "object" && typeof crypto6.ciphertext === "string" && typeof crypto6.kdf === "string"
2252
+ );
2253
+ } catch {
2254
+ return false;
2255
+ }
2256
+ }
2211
2257
  function writeInstallMd(stagedWorkspace, projectName2) {
2212
2258
  const lines = [
2213
2259
  `# ${projectName2} \u2014 install and operate`,
@@ -3231,8 +3277,8 @@ import * as fs24 from "fs";
3231
3277
  import * as os5 from "os";
3232
3278
  import * as path23 from "path";
3233
3279
  import { loadStudioToml as loadStudioToml11 } from "@bnbagent/studio-runtime/config";
3234
- import { getNetwork as getNetwork7 } from "@bnbagent/studio-runtime/networks";
3235
- import { writePrivate as writePrivate2 } from "@bnbagent/studio-runtime/secretWrite";
3280
+ import { getNetwork as getNetwork8 } from "@bnbagent/studio-runtime/networks";
3281
+ import { writePrivate as writePrivate3 } from "@bnbagent/studio-runtime/secretWrite";
3236
3282
  import { Option as Option3 } from "commander";
3237
3283
 
3238
3284
  // src/cli/_migrations.ts
@@ -3380,6 +3426,58 @@ function migrateKeystoreOutOfCodelocation(start) {
3380
3426
  }
3381
3427
  }
3382
3428
  }
3429
+ function excludeConfiguredWalletPathsFromDockerContext(start) {
3430
+ const agentRoot2 = findSubProjectRoot5("agent", start);
3431
+ if (agentRoot2 === null) return;
3432
+ const cfg = loadStudioToml5(path11.join(agentRoot2, "studio.toml"));
3433
+ const wallet = cfg.wallet !== null && typeof cfg.wallet === "object" && !Array.isArray(cfg.wallet) ? cfg.wallet : {};
3434
+ const patterns = /* @__PURE__ */ new Set();
3435
+ for (const [key, directory] of [
3436
+ ["keystore_dir", true],
3437
+ ["twak_home", true],
3438
+ ["session_file", false]
3439
+ ]) {
3440
+ const configured = wallet[key];
3441
+ if (typeof configured !== "string" || !configured.trim()) continue;
3442
+ if (/\r|\n|[*?[\]]/u.test(configured)) {
3443
+ throw new Error(
3444
+ `[wallet].${key} contains characters that cannot be represented safely in .dockerignore; move the wallet path outside app/agent before deploy`
3445
+ );
3446
+ }
3447
+ const resolved = path11.resolve(
3448
+ path11.isAbsolute(configured) ? configured : path11.join(agentRoot2, configured)
3449
+ );
3450
+ const rel = path11.relative(agentRoot2, resolved);
3451
+ if (rel === "") {
3452
+ throw new Error(
3453
+ `[wallet].${key} resolves to the deploy codeLocation; move wallet material outside app/agent before deploy`
3454
+ );
3455
+ }
3456
+ if (rel === ".." || rel.startsWith(`..${path11.sep}`) || path11.isAbsolute(rel)) {
3457
+ continue;
3458
+ }
3459
+ const normalized = rel.split(path11.sep).join("/");
3460
+ patterns.add(`/${normalized}${directory ? "/" : ""}`);
3461
+ }
3462
+ if (patterns.size === 0) return;
3463
+ const dockerignore = path11.join(agentRoot2, ".dockerignore");
3464
+ let text2 = "";
3465
+ try {
3466
+ text2 = fs12.readFileSync(dockerignore, "utf-8");
3467
+ } catch {
3468
+ }
3469
+ const additions = [...patterns].filter(
3470
+ (pattern) => !text2.split(/\r?\n/u).includes(pattern)
3471
+ );
3472
+ if (additions.length === 0) return;
3473
+ const separator = text2.length === 0 || text2.endsWith("\n") ? "" : "\n";
3474
+ fs12.writeFileSync(
3475
+ dockerignore,
3476
+ `${text2}${separator}# Configured wallet paths (managed by bag deploy)
3477
+ ${additions.join("\n")}
3478
+ `
3479
+ );
3480
+ }
3383
3481
  function relocateKeys(src, target, label) {
3384
3482
  fs12.mkdirSync(target, { recursive: true });
3385
3483
  if (keystoreJsonFiles(target).length > 0) {
@@ -3421,10 +3519,11 @@ import * as fs23 from "fs";
3421
3519
  import * as os4 from "os";
3422
3520
  import * as path22 from "path";
3423
3521
  import {
3424
- getNetwork as getNetwork6,
3522
+ getNetwork as getNetwork7,
3425
3523
  tbnbFaucetHint as tbnbFaucetHint3,
3426
3524
  uFaucetHint as uFaucetHint3
3427
3525
  } from "@bnbagent/studio-runtime/networks";
3526
+ import { writePrivate as writePrivate2 } from "@bnbagent/studio-runtime/secretWrite";
3428
3527
  import { ensureTwakKeychain } from "@bnbagent/studio-runtime/wallet";
3429
3528
  import { Option as Option2 } from "commander";
3430
3529
  import { parse as parseToml } from "smol-toml";
@@ -3701,7 +3800,12 @@ import { resolveProviderConfig } from "@bnbagent/studio-runtime/llm";
3701
3800
  // src/cli/_deploy/checks/altana.ts
3702
3801
  import * as fs14 from "fs";
3703
3802
  import * as path13 from "path";
3704
- import { resolveProjectAltanaSdkEntry } from "@bnbagent/studio-runtime/wallet";
3803
+ import { getAddress as deployedAddresses } from "@bnbagent/sdk/networks";
3804
+ import { getNetwork as getNetwork3 } from "@bnbagent/studio-runtime/networks";
3805
+ import {
3806
+ inspectAltanaSessionPermissions,
3807
+ resolveProjectAltanaSdkEntry
3808
+ } from "@bnbagent/studio-runtime/wallet";
3705
3809
  var EXPIRY_WARN_SECONDS = 7 * 24 * 60 * 60;
3706
3810
  function isAltana(data) {
3707
3811
  return tableOf2(data, "wallet").kind === "altana";
@@ -3804,6 +3908,28 @@ function checkAltanaSessionReady(root, _target) {
3804
3908
  }
3805
3909
  ];
3806
3910
  }
3911
+ const networkName = String(tableOf2(data, "network").default ?? "bsc-testnet");
3912
+ const chainId = getNetwork3(networkName).chainId;
3913
+ const deployment = deployedAddresses(chainId);
3914
+ const permissionInspection = inspectAltanaSessionPermissions(
3915
+ tableOf2(envelope, "permissions"),
3916
+ chainId
3917
+ );
3918
+ if (!permissionInspection.current) {
3919
+ return [
3920
+ {
3921
+ level: Level.CRITICAL,
3922
+ name: "altana_session_permissions_current",
3923
+ message: `the Altana session at ${sessionFile} does not match the selector-bound @bnbagent/sdk@0.5.4 permission set; older sessions may include target-wide calls or payment-token approve authority that outlives revocation. Revoke and grant a fresh session before deploying.`,
3924
+ fixCmd: "bag wallet session grant --force",
3925
+ details: {
3926
+ required_policy: deployment.policy.toLowerCase(),
3927
+ expected_call_count: permissionInspection.expectedCallCount,
3928
+ actual_call_count: permissionInspection.actualCallCount
3929
+ }
3930
+ }
3931
+ ];
3932
+ }
3807
3933
  const out = [];
3808
3934
  const remaining = envelope.expiry - Math.floor(Date.now() / 1e3);
3809
3935
  if (remaining <= 0) {
@@ -4980,7 +5106,7 @@ import {
4980
5106
  resolveModel,
4981
5107
  resolveProviderConfig as resolveProviderConfig2
4982
5108
  } from "@bnbagent/studio-runtime/llm";
4983
- import { getNetwork as getNetwork4 } from "@bnbagent/studio-runtime/networks";
5109
+ import { getNetwork as getNetwork5 } from "@bnbagent/studio-runtime/networks";
4984
5110
  import * as pieverseRt from "@bnbagent/studio-runtime/pieverse";
4985
5111
  import {
4986
5112
  PieverseKeyNotFoundError,
@@ -5001,7 +5127,7 @@ import { generateText } from "ai";
5001
5127
  // src/cli/_pieverseHelpers.ts
5002
5128
  import {
5003
5129
  fromRaw as fromRaw2,
5004
- getNetwork as getNetwork3,
5130
+ getNetwork as getNetwork4,
5005
5131
  uFaucetHint
5006
5132
  } from "@bnbagent/studio-runtime/networks";
5007
5133
  import {
@@ -5043,7 +5169,7 @@ function resolvePieverseNetwork(cfg, networkOverride) {
5043
5169
  return projectDefault ? String(projectDefault) : "bsc-mainnet";
5044
5170
  }
5045
5171
  function printUBalanceShortfall(walletAddress, currentRaw, neededRaw, neededUsd, networkName) {
5046
- const net2 = getNetwork3(networkName);
5172
+ const net2 = getNetwork4(networkName);
5047
5173
  const u = net2.token("U");
5048
5174
  const currentH = fromRaw2(currentRaw, u.decimals);
5049
5175
  const neededH = fromRaw2(neededRaw, u.decimals);
@@ -5585,7 +5711,7 @@ Retry: re-run \`bag llm activate\` \u2014 no state was persisted yet.`
5585
5711
  await auditedOp(
5586
5712
  "llm_activate",
5587
5713
  {
5588
- chainId: getNetwork4(networkName).chainId,
5714
+ chainId: getNetwork5(networkName).chainId,
5589
5715
  asset: "U",
5590
5716
  amount: String(opts.initialUsd),
5591
5717
  agentAddr: wallet.address,
@@ -5873,7 +5999,7 @@ async function cmdTopup(opts) {
5873
5999
  const networkName = resolvePieverseNetwork(cfg, opts.network);
5874
6000
  let netChainId;
5875
6001
  try {
5876
- netChainId = getNetwork4(networkName).chainId;
6002
+ netChainId = getNetwork5(networkName).chainId;
5877
6003
  } catch {
5878
6004
  netChainId = null;
5879
6005
  }
@@ -5925,7 +6051,7 @@ async function cmdTopup(opts) {
5925
6051
  result = await auditedOp(
5926
6052
  "cli_topup",
5927
6053
  {
5928
- chainId: getNetwork4(networkName).chainId,
6054
+ chainId: getNetwork5(networkName).chainId,
5929
6055
  asset: "U",
5930
6056
  amount: String(opts.amount),
5931
6057
  agentAddr: wallet.address,
@@ -6849,7 +6975,7 @@ import * as fs21 from "fs";
6849
6975
  import * as path20 from "path";
6850
6976
  import { pathToFileURL } from "url";
6851
6977
  import { AltanaWalletProvider } from "@bnbagent/sdk";
6852
- import { getAddress as deployedAddresses } from "@bnbagent/sdk/networks";
6978
+ import { getAddress as deployedAddresses2 } from "@bnbagent/sdk/networks";
6853
6979
  import {
6854
6980
  defaultAgentPermissions,
6855
6981
  deserializeSession,
@@ -6860,7 +6986,7 @@ import { auditedOp as auditedOp2 } from "@bnbagent/studio-runtime/audit";
6860
6986
  import { loadStudioToml as loadStudioToml9 } from "@bnbagent/studio-runtime/config";
6861
6987
  import {
6862
6988
  fromRaw as fromRaw3,
6863
- getNetwork as getNetwork5,
6989
+ getNetwork as getNetwork6,
6864
6990
  tbnbFaucetHint,
6865
6991
  toRaw as toRaw2
6866
6992
  } from "@bnbagent/studio-runtime/networks";
@@ -6868,6 +6994,7 @@ import { writePrivate } from "@bnbagent/studio-runtime/secretWrite";
6868
6994
  import {
6869
6995
  ALTANA_NETWORK_BY_STUDIO,
6870
6996
  PASSWORD_ENV,
6997
+ inspectAltanaSessionPermissions as inspectAltanaSessionPermissions2,
6871
6998
  resolveProjectAltanaSdkEntry as resolveProjectAltanaSdkEntry2
6872
6999
  } from "@bnbagent/studio-runtime/wallet";
6873
7000
  var defaultAdminFactory = (opts) => AltanaWalletProvider.adminFromKeystore(opts);
@@ -6909,7 +7036,7 @@ function loadContext(projectRoot) {
6909
7036
  projectRoot,
6910
7037
  walletCfg,
6911
7038
  networkName,
6912
- network: getNetwork5(networkName),
7039
+ network: getNetwork6(networkName),
6913
7040
  altanaNetwork,
6914
7041
  sessionFile: resolvePath(
6915
7042
  walletCfg.session_file,
@@ -6984,6 +7111,7 @@ function withRelayGasDiagnosis(ctx, admin) {
6984
7111
  approveX402SignatureChecker: guard(
6985
7112
  admin.approveX402SignatureChecker.bind(admin)
6986
7113
  ),
7114
+ setErc8183Allowance: guard(admin.setErc8183Allowance.bind(admin)),
6987
7115
  setPermit2Allowance: guard(admin.setPermit2Allowance.bind(admin))
6988
7116
  };
6989
7117
  }
@@ -7034,6 +7162,60 @@ function readSession(ctx) {
7034
7162
  }
7035
7163
  return { serialized, envelope: parseSessionEnvelope(serialized) };
7036
7164
  }
7165
+ function encodedBigInt(value) {
7166
+ if (typeof value === "bigint") return value;
7167
+ if (typeof value === "string" && /^\d+$/u.test(value)) return BigInt(value);
7168
+ const encoded = tableOf7(value).$bigint;
7169
+ return typeof encoded === "string" && /^\d+$/u.test(encoded) ? BigInt(encoded) : null;
7170
+ }
7171
+ function sessionTokenLimit(envelope, token) {
7172
+ const spend = envelope.permissions.spend;
7173
+ if (!Array.isArray(spend)) {
7174
+ throw new Error(
7175
+ "saved Altana session has no token spend permissions; grant a fresh session with --force"
7176
+ );
7177
+ }
7178
+ for (const cap of spend) {
7179
+ const record = tableOf7(cap);
7180
+ if (String(record.token ?? "").toLowerCase() !== token.toLowerCase()) {
7181
+ continue;
7182
+ }
7183
+ const limit = encodedBigInt(record.limit);
7184
+ if (limit !== null && limit > 0n) return limit;
7185
+ }
7186
+ throw new Error(
7187
+ `saved Altana session has no positive spend cap for ${token}; grant a fresh session with --force`
7188
+ );
7189
+ }
7190
+ function requireCurrentSessionPermissions(envelope, chainId) {
7191
+ if (!inspectAltanaSessionPermissions2(envelope.permissions, chainId).current) {
7192
+ throw new Error(
7193
+ "saved Altana session does not match the selector-bound @bnbagent/sdk@0.5.4 permission set; revoke and grant a fresh session with --force"
7194
+ );
7195
+ }
7196
+ }
7197
+ async function clearCommerceAllowanceAndRevoke(admin, ctx, publicKey) {
7198
+ const deployment = deployedAddresses2(ctx.network.chainId);
7199
+ requireConfirmed(
7200
+ await admin.setErc8183Allowance(
7201
+ deployment.paymentToken,
7202
+ deployment.commerceProxy,
7203
+ 0n
7204
+ ),
7205
+ "zero ERC-8183 Commerce allowance"
7206
+ );
7207
+ requireConfirmed(
7208
+ await admin.revokeSession(publicKey),
7209
+ "revoke Altana session"
7210
+ );
7211
+ }
7212
+ function requireConfirmed(result, operation) {
7213
+ if (result.status !== "CONFIRMED") {
7214
+ throw new Error(
7215
+ `${operation} returned ${result.status} (callsId ${result.callsId}); on-chain inclusion is not confirmed`
7216
+ );
7217
+ }
7218
+ }
7037
7219
  function writeSession(ctx, session) {
7038
7220
  fs21.mkdirSync(path20.dirname(ctx.sessionFile), { recursive: true, mode: 448 });
7039
7221
  fs21.chmodSync(path20.dirname(ctx.sessionFile), 448);
@@ -7112,9 +7294,12 @@ async function cmdSessionGrant(opts) {
7112
7294
  "--approve-only cannot be combined with grant/replacement options."
7113
7295
  );
7114
7296
  }
7115
- const { serialized } = readSession(ctx);
7297
+ const { serialized, envelope } = readSession(ctx);
7116
7298
  const restored = await sessionDeserializer(serialized);
7117
7299
  const admin2 = buildAdmin(ctx);
7300
+ const deployment = deployedAddresses2(ctx.network.chainId);
7301
+ const tokenLimit2 = sessionTokenLimit(envelope, deployment.paymentToken);
7302
+ requireCurrentSessionPermissions(envelope, ctx.network.chainId);
7118
7303
  await auditedOp2(
7119
7304
  "session_grant",
7120
7305
  {
@@ -7130,13 +7315,24 @@ async function cmdSessionGrant(opts) {
7130
7315
  },
7131
7316
  async () => {
7132
7317
  await requireAltanaAdminGas(ctx);
7133
- await admin2.approveQuoteSignatureChecker(
7134
- restored,
7135
- deployedAddresses(ctx.network.chainId).commerceProxy
7318
+ requireConfirmed(
7319
+ await admin2.setErc8183Allowance(
7320
+ deployment.paymentToken,
7321
+ deployment.commerceProxy,
7322
+ tokenLimit2
7323
+ ),
7324
+ "set bounded ERC-8183 Commerce allowance"
7325
+ );
7326
+ requireConfirmed(
7327
+ await admin2.approveQuoteSignatureChecker(
7328
+ restored,
7329
+ deployment.commerceProxy
7330
+ ),
7331
+ "approve ERC-8183 quote checker"
7136
7332
  );
7137
7333
  }
7138
7334
  );
7139
- printErr("\u2713 Altana ERC-8183 quote checker approval repaired.");
7335
+ printErr("\u2713 Altana ERC-8183 allowance and quote checker repaired.");
7140
7336
  printOut(restored.publicKey);
7141
7337
  return 0;
7142
7338
  }
@@ -7177,7 +7373,7 @@ async function cmdSessionGrant(opts) {
7177
7373
  await requireAltanaAdminGas(ctx);
7178
7374
  if (existing !== null) {
7179
7375
  printErr(`Revoking existing Altana session ${existing.publicKey}\u2026`);
7180
- await admin.revokeSession(existing.publicKey);
7376
+ await clearCommerceAllowanceAndRevoke(admin, ctx, existing.publicKey);
7181
7377
  printErr("\u2713 existing session revoked; replacement may proceed.");
7182
7378
  }
7183
7379
  const g = await admin.grantSession({
@@ -7197,13 +7393,22 @@ async function cmdSessionGrant(opts) {
7197
7393
  h.extraContext.expiry = g.expiry;
7198
7394
  writeSession(ctx, g);
7199
7395
  try {
7200
- await admin.approveQuoteSignatureChecker(
7201
- g,
7202
- deployedAddresses(ctx.network.chainId).commerceProxy
7396
+ const deployment = deployedAddresses2(ctx.network.chainId);
7397
+ requireConfirmed(
7398
+ await admin.setErc8183Allowance(
7399
+ deployment.paymentToken,
7400
+ deployment.commerceProxy,
7401
+ tokenLimit
7402
+ ),
7403
+ "set bounded ERC-8183 Commerce allowance"
7404
+ );
7405
+ requireConfirmed(
7406
+ await admin.approveQuoteSignatureChecker(g, deployment.commerceProxy),
7407
+ "approve ERC-8183 quote checker"
7203
7408
  );
7204
7409
  } catch (error) {
7205
7410
  throw new Error(
7206
- `session was granted and safely persisted at ${ctx.sessionFile}, but ERC-8183 quote checker approval failed: ${error instanceof Error ? error.message : String(error)}. Repair without paying for another grant: bag wallet session grant --approve-only`,
7411
+ `session was granted and safely persisted at ${ctx.sessionFile}, but ERC-8183 allowance/checker setup failed: ${error instanceof Error ? error.message : String(error)}. Repair without paying for another grant: bag wallet session grant --approve-only`,
7207
7412
  { cause: error }
7208
7413
  );
7209
7414
  }
@@ -7265,7 +7470,7 @@ async function cmdSessionRevoke(opts) {
7265
7470
  },
7266
7471
  async () => {
7267
7472
  await requireAltanaAdminGas(ctx);
7268
- await admin.revokeSession(envelope.publicKey);
7473
+ await clearCommerceAllowanceAndRevoke(admin, ctx, envelope.publicKey);
7269
7474
  }
7270
7475
  );
7271
7476
  fs21.unlinkSync(ctx.sessionFile);
@@ -7282,6 +7487,7 @@ async function cmdSessionX402Setup(opts) {
7282
7487
  "--allowance-u"
7283
7488
  );
7284
7489
  const { serialized, envelope } = readSession(ctx);
7490
+ requireCurrentSessionPermissions(envelope, ctx.network.chainId);
7285
7491
  if (!await confirmed(
7286
7492
  `Authorize x402 for session ${envelope.publicKey} with a ${opts.allowanceU} U Permit2 ceiling?`,
7287
7493
  Boolean(opts.yes)
@@ -7305,11 +7511,17 @@ async function cmdSessionX402Setup(opts) {
7305
7511
  },
7306
7512
  async () => {
7307
7513
  await requireAltanaAdminGas(ctx);
7308
- await admin.approveX402SignatureChecker(restored);
7514
+ requireConfirmed(
7515
+ await admin.approveX402SignatureChecker(restored),
7516
+ "approve x402 signature checker"
7517
+ );
7309
7518
  try {
7310
- await admin.setPermit2Allowance(
7311
- deployedAddresses(ctx.network.chainId).paymentToken,
7312
- allowance
7519
+ requireConfirmed(
7520
+ await admin.setPermit2Allowance(
7521
+ deployedAddresses2(ctx.network.chainId).paymentToken,
7522
+ allowance
7523
+ ),
7524
+ "set bounded Permit2 allowance"
7313
7525
  );
7314
7526
  } catch (error) {
7315
7527
  throw new Error(
@@ -7346,7 +7558,7 @@ function registerWalletSession(walletCommand) {
7346
7558
  "Session lifetime in whole days (recommended: 30)."
7347
7559
  ).option("--no-register", "Grant without KeyStore registry visibility.").option("--force", "Revoke the existing session before replacement.").option(
7348
7560
  "--approve-only",
7349
- "Repair quote-checker approval for the saved session."
7561
+ "Repair the bounded ERC-8183 allowance and quote-checker approval."
7350
7562
  ).option("--yes", "Accept the displayed choices without prompts.").option("--project-root <path>", "Override project root.").action(act(wrap((opts) => cmdSessionGrant(opts))));
7351
7563
  session.command("status").description("Read the saved session envelope without loading its signer.").option("--project-root <path>", "Override project root.").action(
7352
7564
  act(
@@ -8972,8 +9184,13 @@ function scaffold(target, name, o) {
8972
9184
  path22.join(agentRoot2, "pnpm-workspace.yaml"),
8973
9185
  renderAgentPnpmWorkspaceYaml()
8974
9186
  );
9187
+ const studioRoot = path22.join(target, ".studio");
9188
+ fs23.mkdirSync(studioRoot, { recursive: true, mode: 448 });
9189
+ fs23.chmodSync(studioRoot, 448);
8975
9190
  if (o.walletKind === "evm-local" || o.walletKind === "altana") {
8976
- fs23.mkdirSync(path22.join(target, ".studio", "wallets"), { recursive: true });
9191
+ const walletsDir = path22.join(studioRoot, "wallets");
9192
+ fs23.mkdirSync(walletsDir, { recursive: true, mode: 448 });
9193
+ fs23.chmodSync(walletsDir, 448);
8977
9194
  } else if (o.walletKind === "twak") {
8978
9195
  let homeDir;
8979
9196
  let label;
@@ -8984,7 +9201,8 @@ function scaffold(target, name, o) {
8984
9201
  homeDir = path22.isAbsolute(o.twakHome) ? o.twakHome : path22.resolve(agentRoot2, o.twakHome);
8985
9202
  label = o.twakHome;
8986
9203
  }
8987
- fs23.mkdirSync(homeDir, { recursive: true });
9204
+ fs23.mkdirSync(homeDir, { recursive: true, mode: 448 });
9205
+ fs23.chmodSync(homeDir, 448);
8988
9206
  if (ensureTwakKeychain(homeDir)) {
8989
9207
  printOut(
8990
9208
  `\u2713 isolated twak keychain ready under ${label} (macOS) \u2014 no manual \`security\` setup needed`
@@ -9003,9 +9221,10 @@ function scaffold(target, name, o) {
9003
9221
  path22.join(agentRoot2, "studio.toml"),
9004
9222
  renderAgentStudioToml(name, o)
9005
9223
  );
9006
- const envLocal = path22.join(target, ".studio", ".env.local");
9007
- fs23.mkdirSync(path22.dirname(envLocal), { recursive: true });
9008
- fs23.writeFileSync(
9224
+ const envLocal = path22.join(studioRoot, ".env.local");
9225
+ fs23.mkdirSync(path22.dirname(envLocal), { recursive: true, mode: 448 });
9226
+ fs23.chmodSync(path22.dirname(envLocal), 448);
9227
+ writePrivate2(
9009
9228
  envLocal,
9010
9229
  renderAgentEnvLocal(
9011
9230
  o.provider,
@@ -9433,7 +9652,7 @@ function renderAgentStudioToml(name, o) {
9433
9652
  const azureSection = o.runtime === "azure-foundry" ? renderAzureSection(name, o.azureAccount, o.azureProject) : "";
9434
9653
  const deploySection = renderDeploySection(o.destination, o.platformArtifact);
9435
9654
  const walletSection = renderWalletSection(o.walletKind, o.twakHome);
9436
- const currencyAddr = getNetwork6(o.network).token("U").address;
9655
+ const currencyAddr = getNetwork7(o.network).token("U").address;
9437
9656
  const erc8183Section = o.rails === "8183" || o.rails === "both" ? `
9438
9657
  [payments.erc8183]
9439
9658
  # Read by the Agent: it quotes the FIXED \`price\`, CLAMPS it to [min,max],
@@ -11536,7 +11755,7 @@ function writeAgentcoreEnvLocal(agentcoreRoot, agentDir) {
11536
11755
  `).join("");
11537
11756
  fs24.mkdirSync(path23.dirname(envPath), { recursive: true });
11538
11757
  ensureAgentcoreEnvGitignored(path23.dirname(envPath));
11539
- writePrivate2(envPath, content);
11758
+ writePrivate3(envPath, content);
11540
11759
  return [envPath, content !== prior];
11541
11760
  }
11542
11761
  function agentcoreProjectRoot2(workspaceRoot) {
@@ -11802,7 +12021,11 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
11802
12021
  printOut(
11803
12022
  `bag dev: starting Agent via \`agentcore dev\` on :${agentPort} (runtime=${runtimeName ?? "<default>"}, cwd=${root}); ${console2}`
11804
12023
  );
11805
- const launchEnv = { ...process.env, AGENT_PORT: String(agentPort) };
12024
+ const launchEnv = {
12025
+ ...process.env,
12026
+ NODE_ENV: process.env.NODE_ENV?.trim() || "development",
12027
+ AGENT_PORT: String(agentPort)
12028
+ };
11806
12029
  if (walletKind2 === "altana") {
11807
12030
  Reflect.deleteProperty(launchEnv, "WALLET_PASSWORD");
11808
12031
  }
@@ -11815,6 +12038,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
11815
12038
  const args = opts.reload ? ["watch", entryFile] : [entryFile];
11816
12039
  const env = {
11817
12040
  ...process.env,
12041
+ NODE_ENV: process.env.NODE_ENV?.trim() || "development",
11818
12042
  AGENT_PORT: String(agentPort),
11819
12043
  AGENT_BIND_HOST: opts.host,
11820
12044
  AGENT_HOST: opts.host
@@ -11887,7 +12111,7 @@ function networkBanner(agentDir) {
11887
12111
  }
11888
12112
  const trimmed = name.trim();
11889
12113
  try {
11890
- return `network=${trimmed} (chainId=${getNetwork7(trimmed).chainId})`;
12114
+ return `network=${trimmed} (chainId=${getNetwork8(trimmed).chainId})`;
11891
12115
  } catch {
11892
12116
  return `network=${trimmed}`;
11893
12117
  }
@@ -12041,7 +12265,7 @@ async function checkAgentPackagePresent(root, target) {
12041
12265
  return [];
12042
12266
  }
12043
12267
  async function checkKeystoreNotInsideAgent(root, target) {
12044
- if (target !== "agentcore") {
12268
+ if (target !== "agentcore" && target !== "azure-foundry") {
12045
12269
  return [];
12046
12270
  }
12047
12271
  const data = loadAgentToml(root);
@@ -12157,11 +12381,31 @@ function agentcoreEnvLocalIgnored(ws) {
12157
12381
  return acLines?.has(".env.local") ?? false;
12158
12382
  }
12159
12383
  function studioIgnored(lines) {
12384
+ if (lines.has("!.studio/.env.local") || lines.has("!.studio/wallets/") || lines.has("!.studio/wallets")) {
12385
+ return false;
12386
+ }
12160
12387
  if (lines.has(".studio/") || lines.has(".studio")) {
12161
12388
  return true;
12162
12389
  }
12163
12390
  return lines.has(".studio/.env.local") && lines.has(".studio/wallets/");
12164
12391
  }
12392
+ async function gitSecretExposure(ws, ignoredPaths, trackedPaths = ignoredPaths) {
12393
+ const tracked = await runCapture("git", ["ls-files", "--", ...trackedPaths], {
12394
+ cwd: ws
12395
+ });
12396
+ if (tracked.code !== 0) return "unverifiable";
12397
+ if (tracked.stdout.trim()) return "tracked";
12398
+ for (const secretPath of ignoredPaths) {
12399
+ const ignored = await runCapture(
12400
+ "git",
12401
+ ["check-ignore", "--quiet", "--", secretPath],
12402
+ { cwd: ws }
12403
+ );
12404
+ if (ignored.code === 1) return "not-ignored";
12405
+ if (ignored.code !== 0) return "unverifiable";
12406
+ }
12407
+ return "safe";
12408
+ }
12165
12409
  async function checkGitignoreExcludesSecrets(root, _target) {
12166
12410
  const out = [];
12167
12411
  const ws = path24.dirname(path24.dirname(envLocalPath12(root)));
@@ -12178,11 +12422,40 @@ async function checkGitignoreExcludesSecrets(root, _target) {
12178
12422
  }
12179
12423
  ];
12180
12424
  }
12181
- if (!studioIgnored(lines)) {
12425
+ const gitProbe = await runCapture(
12426
+ "git",
12427
+ ["rev-parse", "--is-inside-work-tree"],
12428
+ { cwd: ws }
12429
+ );
12430
+ const isGitRepository = gitProbe.code === 0 && gitProbe.stdout.trim() === "true";
12431
+ const studioState = isGitRepository ? await gitSecretExposure(
12432
+ ws,
12433
+ [
12434
+ ".studio/.env.local",
12435
+ ".studio/wallets/__bnbagent_secret_probe__.json"
12436
+ ],
12437
+ [".studio/.env.local", ".studio/wallets/"]
12438
+ ) : fs25.existsSync(path24.join(ws, ".git")) ? "unverifiable" : studioIgnored(lines) ? "safe" : "not-ignored";
12439
+ if (studioState === "tracked") {
12440
+ out.push({
12441
+ level: Level.CRITICAL,
12442
+ name: "gitignore_excludes_secrets",
12443
+ message: ".studio secrets are already tracked by git; .gitignore cannot protect committed files. Remove them from the index and rotate any exposed credentials or wallet material.",
12444
+ details: { tracked: [".studio/.env.local", ".studio/wallets/"] }
12445
+ });
12446
+ } else if (studioState === "unverifiable") {
12447
+ out.push({
12448
+ level: Level.CRITICAL,
12449
+ name: "gitignore_excludes_secrets",
12450
+ message: "could not verify .studio secret exclusions with git check-ignore/git ls-files; refusing to treat the wallet and .env.local as protected",
12451
+ fixCmd: "bag deploy fix-gitignore",
12452
+ details: { paths: [".studio/.env.local", ".studio/wallets/"] }
12453
+ });
12454
+ } else if (studioState === "not-ignored") {
12182
12455
  out.push({
12183
12456
  level: Level.CRITICAL,
12184
12457
  name: "gitignore_excludes_secrets",
12185
- message: "workspace .gitignore does not ignore .studio/ \u2014 the agent's .env.local + keystore live there and could be committed",
12458
+ message: "workspace .studio secrets are not git-ignored \u2014 the agent's .env.local + keystore could be committed (gitignore negations are honoured)",
12186
12459
  fixCmd: "bag deploy fix-gitignore",
12187
12460
  details: { missing: [".studio/"] }
12188
12461
  });
@@ -12597,22 +12870,23 @@ async function checkDeployCliRunnable(_root, target) {
12597
12870
  }
12598
12871
  const override = (process.env.BNBAGENT_DEPLOY_COMMAND ?? "").trim();
12599
12872
  if (override) {
12873
+ const allowed = deployCommandOverrideAllowed();
12600
12874
  return [
12601
12875
  {
12602
- level: Level.INFO,
12876
+ level: allowed ? Level.INFO : Level.CRITICAL,
12603
12877
  name: "deploy_cli",
12604
- message: `deploy CLI overridden via BNBAGENT_DEPLOY_COMMAND (${override}).`,
12878
+ message: allowed ? `deploy CLI overridden for local development/test via BNBAGENT_DEPLOY_COMMAND (${override}).` : "BNBAGENT_DEPLOY_COMMAND is disabled outside local development/tests and in CI.",
12605
12879
  details: { override }
12606
12880
  }
12607
12881
  ];
12608
12882
  }
12609
- const found = await whichBin("bunx");
12883
+ const found = await whichBin("bun");
12610
12884
  if (!found) {
12611
12885
  return [
12612
12886
  {
12613
12887
  level: Level.CRITICAL,
12614
12888
  name: "deploy_cli",
12615
- message: "bunx not found on PATH; the delegated `bnbagent-deploy` run cannot start. Install Bun 1.3+ (https://bun.sh) or set BNBAGENT_DEPLOY_COMMAND.",
12889
+ message: "bun not found on PATH; the declared, lockfile-pinned `@bnbagent/deploy-cli` cannot start. Install Bun 1.3+ (https://bun.sh).",
12616
12890
  details: {}
12617
12891
  }
12618
12892
  ];
@@ -12621,7 +12895,7 @@ async function checkDeployCliRunnable(_root, target) {
12621
12895
  {
12622
12896
  level: Level.INFO,
12623
12897
  name: "deploy_cli",
12624
- message: `bunx at ${found}; deploys delegate to the pinned @bnbagent/deploy-cli.`,
12898
+ message: `bun at ${found}; deploys use the declared @bnbagent/deploy-cli dependency.`,
12625
12899
  details: { path: found }
12626
12900
  }
12627
12901
  ];
@@ -12966,6 +13240,10 @@ function readKeystoreJson(agentRoot2) {
12966
13240
  `[wallet].address ${address} does not match any keystore under ${keystoreDir}; refusing to deploy an unrelated signing key`
12967
13241
  );
12968
13242
  }
13243
+ } else if (names.length > 1) {
13244
+ throw new Error(
13245
+ `multiple keystores found under ${keystoreDir}; set [wallet].address to the intended signing wallet before deploy`
13246
+ );
12969
13247
  }
12970
13248
  const file = path25.join(keystoreDir, chosen ?? names[0]);
12971
13249
  try {
@@ -14061,7 +14339,7 @@ import { envLocalPath as envLocalPath15 } from "@bnbagent/studio-runtime/config"
14061
14339
  import { show } from "@bnbagent/studio-runtime/erc8004";
14062
14340
  import {
14063
14341
  DEFAULT_RPC,
14064
- getNetwork as getNetwork8,
14342
+ getNetwork as getNetwork9,
14065
14343
  tbnbFaucetHint as tbnbFaucetHint4,
14066
14344
  uFaucetHint as uFaucetHint4
14067
14345
  } from "@bnbagent/studio-runtime/networks";
@@ -14140,7 +14418,7 @@ async function checkWalletUBalanceNonzero(root, _target) {
14140
14418
  if (!netName || typeof netName !== "string") {
14141
14419
  return [];
14142
14420
  }
14143
- if (getNetwork8(netName).tokens.U === void 0) {
14421
+ if (getNetwork9(netName).tokens.U === void 0) {
14144
14422
  return [];
14145
14423
  }
14146
14424
  const bal = await readUBalanceRaw(address, netName);
@@ -14194,7 +14472,7 @@ async function checkNetworkMatchesChainId(root, _target) {
14194
14472
  if (!netName || typeof netName !== "string") {
14195
14473
  return [];
14196
14474
  }
14197
- const net2 = getNetwork8(netName);
14475
+ const net2 = getNetwork9(netName);
14198
14476
  const actual = await readChainId(netName);
14199
14477
  if (actual !== net2.chainId) {
14200
14478
  return [
@@ -14233,7 +14511,7 @@ async function checkRuntimeRpcReachable(root, _target) {
14233
14511
  if (!netName || typeof netName !== "string") {
14234
14512
  return [];
14235
14513
  }
14236
- const expected = getNetwork8(netName).chainId;
14514
+ const expected = getNetwork9(netName).chainId;
14237
14515
  const configured = process.env.RPC_URL || getEnvVar(envLocalPath15(root), "RPC_URL") || "";
14238
14516
  const rpcUrl = configured || DEFAULT_RPC[netName] || "";
14239
14517
  if (!rpcUrl) {
@@ -14612,6 +14890,7 @@ async function runPrepare(opts = {}) {
14612
14890
  checks.push(
14613
14891
  ...await runProducers(
14614
14892
  [
14893
+ checkKeystoreNotInsideAgent,
14615
14894
  checkLocalKeystoreExists,
14616
14895
  checkWalletPasswordEnvSet,
14617
14896
  checkLlmProviderKeySet,
@@ -16955,6 +17234,11 @@ async function cmdAgent(opts, agentcoreArgs) {
16955
17234
  if (rc !== null) {
16956
17235
  return rc;
16957
17236
  }
17237
+ migrateEnvLocal(root);
17238
+ migrateKeystoreOutOfCodelocation(root);
17239
+ if (target === "azure-foundry") {
17240
+ excludeConfiguredWalletPathsFromDockerContext(root);
17241
+ }
16958
17242
  if (target === "azure-foundry") {
16959
17243
  if (!opts.skipPrepare) {
16960
17244
  let result = await runPrepare({
@@ -17004,8 +17288,6 @@ async function cmdAgent(opts, agentcoreArgs) {
17004
17288
  await printAzureAgentClientPrompt(root);
17005
17289
  return 0;
17006
17290
  }
17007
- migrateEnvLocal(root);
17008
- migrateKeystoreOutOfCodelocation(root);
17009
17291
  const secretsMode = opts.secretsMode ?? "secretsmanager";
17010
17292
  if (secretsMode === "envvars" && agentNetworkDefault(root) === "bsc-mainnet") {
17011
17293
  printErr(
@@ -18329,7 +18611,7 @@ import {
18329
18611
  BSC_TESTNET_MIN_U,
18330
18612
  ERC8183_SUBMIT_GAS_RESERVE_BNB,
18331
18613
  fromRaw as fromRaw4,
18332
- getNetwork as getNetwork9,
18614
+ getNetwork as getNetwork10,
18333
18615
  tbnbFaucetHint as tbnbFaucetHint6,
18334
18616
  uFaucetHint as uFaucetHint6
18335
18617
  } from "@bnbagent/studio-runtime/networks";
@@ -18819,7 +19101,7 @@ async function checkWalletAltana(walletCfg, projectRoot, data) {
18819
19101
  networkName
18820
19102
  );
18821
19103
  if (allowanceRaw !== null) {
18822
- const uToken = getNetwork9(networkName).token("U");
19104
+ const uToken = getNetwork10(networkName).token("U");
18823
19105
  out.push(
18824
19106
  allowanceRaw > 0n ? {
18825
19107
  name: "[wallet] Altana x402 buying",
@@ -19120,7 +19402,7 @@ async function checkNetwork(data, networkOverride) {
19120
19402
  const name = String(netName);
19121
19403
  let rpcUrl;
19122
19404
  try {
19123
- rpcUrl = getNetwork9(name).rpcUrl;
19405
+ rpcUrl = getNetwork10(name).rpcUrl;
19124
19406
  } catch (exc) {
19125
19407
  return [{ name: "network reachable", status: FAIL, detail: errMsg3(exc) }];
19126
19408
  }
@@ -19528,7 +19810,7 @@ async function checkBalances(projectRoot, data, networkOverride) {
19528
19810
  if (address === null) {
19529
19811
  return [];
19530
19812
  }
19531
- const net2 = getNetwork9(name);
19813
+ const net2 = getNetwork10(name);
19532
19814
  const isTestnet = name === "bsc-testnet";
19533
19815
  const isMainnet = name === "bsc-mainnet";
19534
19816
  const minBnb = isTestnet ? BSC_TESTNET_MIN_BNB : isMainnet ? BSC_MAINNET_MIN_BNB : 0;
@@ -19627,7 +19909,7 @@ async function checkPieverseMainnetU(projectRoot, data) {
19627
19909
  const chunk = typeof autoRenew.topup_chunk_usd === "number" ? autoRenew.topup_chunk_usd : 1;
19628
19910
  const threshold = chunk * 2;
19629
19911
  try {
19630
- const net2 = getNetwork9(pvNetwork);
19912
+ const net2 = getNetwork10(pvNetwork);
19631
19913
  const uToken = net2.tokens.U;
19632
19914
  if (uToken === void 0) {
19633
19915
  return [];
@@ -20015,7 +20297,7 @@ import {
20015
20297
  } from "@bnbagent/studio-runtime/erc8004";
20016
20298
  import {
20017
20299
  fromRaw as fromRaw5,
20018
- getNetwork as getNetwork10,
20300
+ getNetwork as getNetwork11,
20019
20301
  tbnbFaucetHint as tbnbFaucetHint7
20020
20302
  } from "@bnbagent/studio-runtime/networks";
20021
20303
  import * as walletRt6 from "@bnbagent/studio-runtime/wallet";
@@ -20332,7 +20614,7 @@ async function cmdRegister2(opts) {
20332
20614
  agentId = await auditedOp3(
20333
20615
  "8004_register",
20334
20616
  {
20335
- chainId: getNetwork10(network).chainId,
20617
+ chainId: getNetwork11(network).chainId,
20336
20618
  asset: null,
20337
20619
  amount: null,
20338
20620
  agentAddr: wallet.address,
@@ -21345,7 +21627,7 @@ import {
21345
21627
  fetchMppWithPayment,
21346
21628
  quoteMppUrl
21347
21629
  } from "@bnbagent/studio-runtime/mpp";
21348
- import { getNetwork as getNetwork11 } from "@bnbagent/studio-runtime/networks";
21630
+ import { getNetwork as getNetwork12 } from "@bnbagent/studio-runtime/networks";
21349
21631
  import * as walletRt8 from "@bnbagent/studio-runtime/wallet";
21350
21632
  import {
21351
21633
  SELLER_TOKENS,
@@ -21599,7 +21881,7 @@ async function cmdBuy2(url, opts) {
21599
21881
  );
21600
21882
  return 1;
21601
21883
  }
21602
- const network = getNetwork11(networkName);
21884
+ const network = getNetwork12(networkName);
21603
21885
  const token = SELLER_TOKENS[caip2(network.chainId)];
21604
21886
  if (!token) {
21605
21887
  printErr(`error: MPP+B402 has no trusted buyer token on ${networkName}.`);
@@ -22469,7 +22751,7 @@ import {
22469
22751
  findProjectRoot as findProjectRoot7,
22470
22752
  loadStudioToml as loadStudioToml25
22471
22753
  } from "@bnbagent/studio-runtime/config";
22472
- import { fromRaw as fromRaw6, getNetwork as getNetwork12 } from "@bnbagent/studio-runtime/networks";
22754
+ import { fromRaw as fromRaw6, getNetwork as getNetwork13 } from "@bnbagent/studio-runtime/networks";
22473
22755
  import * as walletRt9 from "@bnbagent/studio-runtime/wallet";
22474
22756
  import {
22475
22757
  SELLER_TOKENS as SELLER_TOKENS2,
@@ -22855,7 +23137,7 @@ async function cmdSellStatus(probe2) {
22855
23137
  return 0;
22856
23138
  }
22857
23139
  const networkName = resolveNetwork4(cfg);
22858
- const network = caip22(getNetwork12(networkName).chainId);
23140
+ const network = caip22(getNetwork13(networkName).chainId);
22859
23141
  const token = SELLER_TOKENS2[network];
22860
23142
  if (!token) {
22861
23143
  printOut(`B402 probe: mismatch for ${network}; no pinned U token`);
@@ -23020,7 +23302,7 @@ async function cmdBuy3(url, opts) {
23020
23302
  return 1;
23021
23303
  }
23022
23304
  if (allowanceRaw !== null && allowanceRaw < neededRaw) {
23023
- const uToken = getNetwork12(networkName).token("U");
23305
+ const uToken = getNetwork13(networkName).token("U");
23024
23306
  printErr(
23025
23307
  `error: U\u2192Permit2 allowance ${fromRaw6(allowanceRaw, uToken.decimals)} U cannot cover max_usd $${opts.maxUsd.toFixed(2)}: b402 settles Altana payments by pulling through Permit2 (${PERMIT2_ADDRESS}).`
23026
23308
  );
@@ -23035,7 +23317,7 @@ async function cmdBuy3(url, opts) {
23035
23317
  result = await auditedOp4(
23036
23318
  "x402_buy",
23037
23319
  {
23038
- chainId: getNetwork12(networkName).chainId,
23320
+ chainId: getNetwork13(networkName).chainId,
23039
23321
  asset: "U",
23040
23322
  amount: String(opts.maxUsd),
23041
23323
  agentAddr: wallet.address,
@@ -23132,7 +23414,7 @@ async function probeChallenge(url, methodHint) {
23132
23414
  return null;
23133
23415
  }
23134
23416
  function selectPayable(challenge, networkName) {
23135
- const network = getNetwork12(networkName);
23417
+ const network = getNetwork13(networkName);
23136
23418
  const uToken = network.token("U");
23137
23419
  let matched;
23138
23420
  try {