@bnbagent/studio-cli 0.0.13-alpha.6 → 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.
- package/dist/bag.js +354 -72
- package/dist/{chunk-LEBIBQWN.js → chunk-NTDWVEW2.js} +59 -17
- package/dist/{deployCli-H65YVV3V.js → deployCli-ZESBUWQB.js} +3 -1
- package/package.json +4 -3
- package/recipes/agent/code/{{PKG}}/signing.ts.tmpl +2 -2
- package/recipes/agent/recipe.toml +1 -1
- package/recipes/mpp-buyer/recipe.toml +1 -1
- package/recipes/runtimes/agentcore/code/{{PKG}}/dualMain.ts.tmpl +2 -0
- package/recipes/runtimes/agentcore/code/{{PKG}}/executor.ts.tmpl +14 -6
- package/recipes/runtimes/agentcore/code/{{PKG}}/mcpMain.ts.tmpl +63 -30
- package/recipes/runtimes/agentcore/code/{{PKG}}/requestLimits.ts.tmpl +178 -0
- package/recipes/runtimes/agentcore/code/{{PKG}}/sellerCore.ts.tmpl +3 -0
- package/recipes/runtimes/agentcore/code/{{PKG}}/unifiedMain.ts.tmpl +2 -0
- package/recipes/runtimes/agentcore/recipe.toml +1 -1
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/executor.ts.tmpl +14 -6
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/mcpMain.ts.tmpl +63 -30
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/requestLimits.ts.tmpl +178 -0
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/sellerCore.ts.tmpl +3 -0
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/unifiedMain.ts.tmpl +2 -0
- package/recipes/runtimes/azure-foundry/recipe.toml +1 -1
- package/recipes/wallet/recipe.toml +0 -1
- package/recipes/x402-buyer/recipe.toml +1 -1
- package/skills/references/bnbagent-studio-adding-to-project.md +1 -1
- package/skills/references/bnbagent-studio-operating.md +1 -1
- package/skills/references/bnbagent-studio-selling-via-b402.md +3 -3
- 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-
|
|
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-
|
|
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 (
|
|
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(
|
|
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`,
|
|
@@ -2467,7 +2513,7 @@ function isErc8183AmountKey(parts) {
|
|
|
2467
2513
|
return parts.length === 3 && parts[0] === "payments" && parts[1] === "erc8183" && ["price", "min_price", "max_price"].includes(parts[2]);
|
|
2468
2514
|
}
|
|
2469
2515
|
function isB402PriceKey(parts) {
|
|
2470
|
-
return parts.length === 3 && parts[0] === "payments" && parts[1] === "x402_seller" && parts[2] === "price_usd";
|
|
2516
|
+
return parts.length === 3 && parts[0] === "payments" && (parts[1] === "b402_seller" || parts[1] === "x402_seller") && parts[2] === "price_usd";
|
|
2471
2517
|
}
|
|
2472
2518
|
function coerceKnownValue(parts, rawValue, typeFlag) {
|
|
2473
2519
|
if (!isErc8183AmountKey(parts) && !isB402PriceKey(parts)) {
|
|
@@ -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
|
|
3235
|
-
import { writePrivate as
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
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 =
|
|
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:
|
|
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 =
|
|
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:
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
7514
|
+
requireConfirmed(
|
|
7515
|
+
await admin.approveX402SignatureChecker(restored),
|
|
7516
|
+
"approve x402 signature checker"
|
|
7517
|
+
);
|
|
7309
7518
|
try {
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
9007
|
-
fs23.mkdirSync(path22.dirname(envLocal), { recursive: true });
|
|
9008
|
-
fs23.
|
|
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 =
|
|
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
|
-
|
|
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 = {
|
|
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=${
|
|
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
|
-
|
|
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 .
|
|
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("
|
|
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: "
|
|
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: `
|
|
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
|
|
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 (
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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:
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
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:
|
|
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 =
|
|
23417
|
+
const network = getNetwork13(networkName);
|
|
23136
23418
|
const uToken = network.token("U");
|
|
23137
23419
|
let matched;
|
|
23138
23420
|
try {
|