@bnbagent/studio-cli 0.0.6-alpha.5 → 0.0.6-alpha.7
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 +665 -315
- package/package.json +3 -3
- package/recipes/agent/recipe.toml +1 -1
- package/recipes/runtimes/agentcore/recipe.toml +1 -1
- package/recipes/runtimes/azure-foundry/recipe.toml +1 -1
- package/recipes/x402-buyer/recipe.toml +1 -1
- package/skills/bnbagent-studio.md +1 -1
- package/skills/references/bnbagent-studio-adding-to-project.md +6 -6
- package/skills/references/bnbagent-studio-operating.md +1 -2
- package/skills/references/bnbagent-studio-scaffolding-agent.md +8 -9
- package/skills/references/bnbagent-studio-selling-via-8183.md +3 -4
- package/skills/references/bnbagent-studio-use-aws-agentcore.md +12 -14
- package/skills/references/bnbagent-studio-using-twak-wallet.md +3 -0
package/dist/bag.js
CHANGED
|
@@ -2722,6 +2722,11 @@ function client(networkName) {
|
|
|
2722
2722
|
const net2 = getNetwork(networkName);
|
|
2723
2723
|
return createPublicClient({ transport: http(net2.rpcUrl) });
|
|
2724
2724
|
}
|
|
2725
|
+
async function readChainIdAt(rpcUrl) {
|
|
2726
|
+
return createPublicClient({
|
|
2727
|
+
transport: http(rpcUrl, { retryCount: 0, timeout: 5e3 })
|
|
2728
|
+
}).getChainId();
|
|
2729
|
+
}
|
|
2725
2730
|
async function readNativeBalanceRaw(address, networkName) {
|
|
2726
2731
|
return client(networkName).getBalance({
|
|
2727
2732
|
address: getAddress(address)
|
|
@@ -3192,44 +3197,6 @@ function relocateKeys(src, target, label) {
|
|
|
3192
3197
|
return true;
|
|
3193
3198
|
}
|
|
3194
3199
|
|
|
3195
|
-
// src/cli/_twakContractTargets.ts
|
|
3196
|
-
import { resolveNetwork } from "@bnbagent/sdk";
|
|
3197
|
-
var CONTRACT_OVERRIDES = [
|
|
3198
|
-
["ERC8004_REGISTRY_ADDRESS", "registryContract"],
|
|
3199
|
-
["ERC8183_COMMERCE_ADDRESS", "commerceContract"],
|
|
3200
|
-
["ERC8183_ROUTER_ADDRESS", "routerContract"],
|
|
3201
|
-
["ERC8183_POLICY_ADDRESS", "policyContract"]
|
|
3202
|
-
];
|
|
3203
|
-
function twakCustomContractOverrides(networkName, env = process.env) {
|
|
3204
|
-
let network;
|
|
3205
|
-
try {
|
|
3206
|
-
network = resolveNetwork(networkName);
|
|
3207
|
-
} catch {
|
|
3208
|
-
return [];
|
|
3209
|
-
}
|
|
3210
|
-
const erc8183 = erc8183ContractOverrideState(env);
|
|
3211
|
-
const out = [];
|
|
3212
|
-
for (const [envKey, field] of CONTRACT_OVERRIDES) {
|
|
3213
|
-
if (envKey.startsWith("ERC8183_") && erc8183.mode !== "custom") {
|
|
3214
|
-
continue;
|
|
3215
|
-
}
|
|
3216
|
-
const configured = env[envKey]?.trim() ?? "";
|
|
3217
|
-
if (!/^0x[0-9a-fA-F]{40}$/u.test(configured)) {
|
|
3218
|
-
continue;
|
|
3219
|
-
}
|
|
3220
|
-
const canonical = network[field];
|
|
3221
|
-
if (configured.toLowerCase() !== canonical.toLowerCase()) {
|
|
3222
|
-
out.push({ envKey, configured, canonical });
|
|
3223
|
-
}
|
|
3224
|
-
}
|
|
3225
|
-
return out;
|
|
3226
|
-
}
|
|
3227
|
-
function twakUnsupportedContractOverrides(networkName, env = process.env) {
|
|
3228
|
-
return twakCustomContractOverrides(networkName, env).filter(
|
|
3229
|
-
(item) => item.envKey.startsWith("ERC8183_")
|
|
3230
|
-
);
|
|
3231
|
-
}
|
|
3232
|
-
|
|
3233
3200
|
// src/cli/init.ts
|
|
3234
3201
|
import * as fs23 from "fs";
|
|
3235
3202
|
import * as os4 from "os";
|
|
@@ -3498,6 +3465,46 @@ import * as fs15 from "fs";
|
|
|
3498
3465
|
import * as path14 from "path";
|
|
3499
3466
|
import { envLocalPath as envLocalPath7 } from "@bnbagent/studio-runtime/config";
|
|
3500
3467
|
import { resolveTwakHome } from "@bnbagent/studio-runtime/wallet";
|
|
3468
|
+
|
|
3469
|
+
// src/cli/_twakContractTargets.ts
|
|
3470
|
+
import { resolveNetwork } from "@bnbagent/sdk";
|
|
3471
|
+
var CONTRACT_OVERRIDES = [
|
|
3472
|
+
["ERC8004_REGISTRY_ADDRESS", "registryContract"],
|
|
3473
|
+
["ERC8183_COMMERCE_ADDRESS", "commerceContract"],
|
|
3474
|
+
["ERC8183_ROUTER_ADDRESS", "routerContract"],
|
|
3475
|
+
["ERC8183_POLICY_ADDRESS", "policyContract"]
|
|
3476
|
+
];
|
|
3477
|
+
function twakCustomContractOverrides(networkName, env = process.env) {
|
|
3478
|
+
let network;
|
|
3479
|
+
try {
|
|
3480
|
+
network = resolveNetwork(networkName);
|
|
3481
|
+
} catch {
|
|
3482
|
+
return [];
|
|
3483
|
+
}
|
|
3484
|
+
const erc8183 = erc8183ContractOverrideState(env);
|
|
3485
|
+
const out = [];
|
|
3486
|
+
for (const [envKey, field] of CONTRACT_OVERRIDES) {
|
|
3487
|
+
if (envKey.startsWith("ERC8183_") && erc8183.mode !== "custom") {
|
|
3488
|
+
continue;
|
|
3489
|
+
}
|
|
3490
|
+
const configured = env[envKey]?.trim() ?? "";
|
|
3491
|
+
if (!/^0x[0-9a-fA-F]{40}$/u.test(configured)) {
|
|
3492
|
+
continue;
|
|
3493
|
+
}
|
|
3494
|
+
const canonical = network[field];
|
|
3495
|
+
if (configured.toLowerCase() !== canonical.toLowerCase()) {
|
|
3496
|
+
out.push({ envKey, configured, canonical });
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
return out;
|
|
3500
|
+
}
|
|
3501
|
+
function twakUnsupportedContractOverrides(networkName, env = process.env) {
|
|
3502
|
+
return twakCustomContractOverrides(networkName, env).filter(
|
|
3503
|
+
(item) => item.envKey.startsWith("ERC8183_")
|
|
3504
|
+
);
|
|
3505
|
+
}
|
|
3506
|
+
|
|
3507
|
+
// src/cli/_deploy/checks/twak.ts
|
|
3501
3508
|
var AGENTCORE_DESCRIPTOR = path14.join("agentcore", "agentcore.json");
|
|
3502
3509
|
function isTwak(data) {
|
|
3503
3510
|
return tableOf2(data, "wallet").kind === "twak";
|
|
@@ -4277,6 +4284,7 @@ import {
|
|
|
4277
4284
|
import { getNetwork as getNetwork4 } from "@bnbagent/studio-runtime/networks";
|
|
4278
4285
|
import * as pieverseRt from "@bnbagent/studio-runtime/pieverse";
|
|
4279
4286
|
import {
|
|
4287
|
+
PieverseKeyNotFoundError,
|
|
4280
4288
|
PieversePolicy,
|
|
4281
4289
|
RetryPolicy,
|
|
4282
4290
|
allocateWithSettleRetry,
|
|
@@ -4410,7 +4418,10 @@ function registerLlm(program) {
|
|
|
4410
4418
|
).option(
|
|
4411
4419
|
"--network <name>",
|
|
4412
4420
|
"Override [llm.pieverse].network (e.g. bsc-mainnet, bsc-testnet)."
|
|
4413
|
-
).option("--name <name>", "Key name (default: bnbagent-studio-default).").
|
|
4421
|
+
).option("--name <name>", "Key name (default: bnbagent-studio-default).").option(
|
|
4422
|
+
"--replace",
|
|
4423
|
+
"Ignore any existing key and mint a fresh one, overwriting PIEVERSE_LLM_API_KEY in .studio/.env.local. Use when the key you inherited (e.g. from a shared env file) no longer exists in Pieverse. The old key is left untouched on the Pieverse side."
|
|
4424
|
+
).action(
|
|
4414
4425
|
act(
|
|
4415
4426
|
(opts) => cmdActivate(opts)
|
|
4416
4427
|
)
|
|
@@ -4619,9 +4630,20 @@ async function cmdActivate(opts) {
|
|
|
4619
4630
|
return 2;
|
|
4620
4631
|
}
|
|
4621
4632
|
const pvCfg = loadPieverseConfig(cfg);
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
const
|
|
4633
|
+
const replace = opts.replace === true;
|
|
4634
|
+
let existingHash = !replace && pvCfg.key_hash ? String(pvCfg.key_hash) : null;
|
|
4635
|
+
const envFileValue = replace ? null : getEnvVar(envLocalPath9(root), PIEVERSE_ENV_KEY);
|
|
4636
|
+
const existingEnv = replace ? null : envFileValue || process.env[PIEVERSE_ENV_KEY];
|
|
4637
|
+
if (replace) {
|
|
4638
|
+
printOut(
|
|
4639
|
+
`\u2192 --replace: ignoring any existing ${PIEVERSE_ENV_KEY} and minting a fresh key\u2026`
|
|
4640
|
+
);
|
|
4641
|
+
if (process.env[PIEVERSE_ENV_KEY]) {
|
|
4642
|
+
printErr(
|
|
4643
|
+
`warning: ${PIEVERSE_ENV_KEY} is also exported in this shell. The new key goes to .studio/.env.local, which \`bag\` prefers, but \`unset ${PIEVERSE_ENV_KEY}\` to keep the two from diverging.`
|
|
4644
|
+
);
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4625
4647
|
if (!existingHash && existingEnv) {
|
|
4626
4648
|
const derivedHash = pieverseKeyHash(existingEnv);
|
|
4627
4649
|
printOut(
|
|
@@ -4630,15 +4652,24 @@ async function cmdActivate(opts) {
|
|
|
4630
4652
|
try {
|
|
4631
4653
|
await withSiweRetry(wallet, (token) => inspectKey(token, derivedHash));
|
|
4632
4654
|
} catch (exc) {
|
|
4655
|
+
if (!(exc instanceof PieverseKeyNotFoundError)) {
|
|
4656
|
+
printErr(
|
|
4657
|
+
`error: could not verify the existing ${PIEVERSE_ENV_KEY} against Pieverse: ${errMessage(
|
|
4658
|
+
exc
|
|
4659
|
+
)}
|
|
4660
|
+
The existing key was kept and no new key was created. This looks like a transport or login failure rather than a missing key \u2014 retry \`bag llm activate\` once Pieverse is reachable.`
|
|
4661
|
+
);
|
|
4662
|
+
return 2;
|
|
4663
|
+
}
|
|
4633
4664
|
const sources = [
|
|
4634
4665
|
envFileValue ? `.studio/.env.local (a ${PIEVERSE_ENV_KEY}= line)` : "",
|
|
4635
4666
|
process.env[PIEVERSE_ENV_KEY] ? "the shell environment" : ""
|
|
4636
4667
|
].filter(Boolean).join(" and ");
|
|
4637
4668
|
printErr(
|
|
4638
|
-
`error: ${PIEVERSE_ENV_KEY} already exists but
|
|
4669
|
+
`error: ${PIEVERSE_ENV_KEY} already exists but Pieverse does not know its key_hash: ${errMessage(
|
|
4639
4670
|
exc
|
|
4640
4671
|
)}
|
|
4641
|
-
The existing key was kept and no new key was created. The key comes from ${sources}
|
|
4672
|
+
The existing key was kept and no new key was created. The key comes from ${sources}. Re-run \`bag llm activate --replace\` to mint a fresh key and overwrite .studio/.env.local (then \`unset ${PIEVERSE_ENV_KEY}\` if you also exported it in this shell). (\`bag llm rotate\` replaces a key that is still valid in Pieverse; it cannot recover this one.)`
|
|
4642
4673
|
);
|
|
4643
4674
|
return 2;
|
|
4644
4675
|
}
|
|
@@ -9858,6 +9889,57 @@ function isDir4(p) {
|
|
|
9858
9889
|
}
|
|
9859
9890
|
}
|
|
9860
9891
|
|
|
9892
|
+
// src/cli/_runtimeEnvKeys.ts
|
|
9893
|
+
function tableOf8(cfg, key) {
|
|
9894
|
+
const v = cfg[key];
|
|
9895
|
+
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
9896
|
+
}
|
|
9897
|
+
function runtimeEnvKeysCore(cfg, resolvable) {
|
|
9898
|
+
const walletKind2 = tableOf8(cfg, "wallet").kind ?? "evm-local";
|
|
9899
|
+
let keys;
|
|
9900
|
+
if (walletKind2 === "twak") {
|
|
9901
|
+
keys = ["TWAK_WALLET_PASSWORD"];
|
|
9902
|
+
for (const k of ["TWAK_ACCESS_ID", "TWAK_HMAC_SECRET"]) {
|
|
9903
|
+
if (resolvable(k)) {
|
|
9904
|
+
keys.push(k);
|
|
9905
|
+
}
|
|
9906
|
+
}
|
|
9907
|
+
} else if (walletKind2 === "altana") {
|
|
9908
|
+
keys = [];
|
|
9909
|
+
} else {
|
|
9910
|
+
keys = ["WALLET_PASSWORD"];
|
|
9911
|
+
}
|
|
9912
|
+
const provider = tableOf8(cfg, "llm").provider;
|
|
9913
|
+
const providerKey = typeof provider === "string" ? PROVIDER_KEY_ENV[provider] : null;
|
|
9914
|
+
if (providerKey) {
|
|
9915
|
+
keys.push(providerKey);
|
|
9916
|
+
}
|
|
9917
|
+
const storageKind2 = String(
|
|
9918
|
+
tableOf8(cfg, "storage").kind ?? "local"
|
|
9919
|
+
).toLowerCase();
|
|
9920
|
+
if (storageKind2 === "ipfs") {
|
|
9921
|
+
keys.push("STORAGE_API_URL");
|
|
9922
|
+
if (resolvable("STORAGE_API_KEY")) {
|
|
9923
|
+
keys.push("STORAGE_API_KEY");
|
|
9924
|
+
}
|
|
9925
|
+
}
|
|
9926
|
+
if (resolvable("RPC_URL")) {
|
|
9927
|
+
keys.push("RPC_URL");
|
|
9928
|
+
}
|
|
9929
|
+
if (commerceRails(cfg).erc8183) {
|
|
9930
|
+
for (const key of ERC8183_ADDRESS_OVERRIDE_KEYS) {
|
|
9931
|
+
if (resolvable(key)) keys.push(key);
|
|
9932
|
+
}
|
|
9933
|
+
}
|
|
9934
|
+
const runtime = String(tableOf8(cfg, "stack").runtime ?? "agentcore");
|
|
9935
|
+
if (runtime === "agentcore" && x402SellerUsesB402(cfg)) {
|
|
9936
|
+
for (const key of B402_RUNTIME_KEYS) {
|
|
9937
|
+
if (resolvable(key)) keys.push(key);
|
|
9938
|
+
}
|
|
9939
|
+
}
|
|
9940
|
+
return keys;
|
|
9941
|
+
}
|
|
9942
|
+
|
|
9861
9943
|
// src/cli/dev.ts
|
|
9862
9944
|
var DEFAULT_AGENT_HOST = "127.0.0.1";
|
|
9863
9945
|
var AGENTCORE_BIN = "agentcore";
|
|
@@ -9944,17 +10026,17 @@ function loadAgentToml2(workspaceRoot) {
|
|
|
9944
10026
|
return {};
|
|
9945
10027
|
}
|
|
9946
10028
|
}
|
|
9947
|
-
function
|
|
10029
|
+
function tableOf9(data, key) {
|
|
9948
10030
|
const v = data[key];
|
|
9949
10031
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
9950
10032
|
}
|
|
9951
10033
|
function agentRuntime(workspaceRoot) {
|
|
9952
|
-
const runtime =
|
|
10034
|
+
const runtime = tableOf9(loadAgentToml2(workspaceRoot), "stack").runtime;
|
|
9953
10035
|
return typeof runtime === "string" && runtime.trim() ? runtime.trim() : RUNTIME_AGENTCORE;
|
|
9954
10036
|
}
|
|
9955
10037
|
function agentFaces(workspaceRoot) {
|
|
9956
10038
|
const cfg = loadAgentToml2(workspaceRoot);
|
|
9957
|
-
return stackFaces(
|
|
10039
|
+
return stackFaces(tableOf9(cfg, "stack"), tableOf9(cfg, "payments"));
|
|
9958
10040
|
}
|
|
9959
10041
|
function localEntryFile(faces) {
|
|
9960
10042
|
return `src/${entryStemOf(faces)}.ts`;
|
|
@@ -9969,7 +10051,7 @@ function storageKind(agentDir) {
|
|
|
9969
10051
|
} catch {
|
|
9970
10052
|
return "local";
|
|
9971
10053
|
}
|
|
9972
|
-
const kind =
|
|
10054
|
+
const kind = tableOf9(data, "storage").kind;
|
|
9973
10055
|
return typeof kind === "string" && kind.trim() ? kind.trim() : "local";
|
|
9974
10056
|
}
|
|
9975
10057
|
function networkNameOf(agentDir) {
|
|
@@ -9979,7 +10061,7 @@ function networkNameOf(agentDir) {
|
|
|
9979
10061
|
} catch {
|
|
9980
10062
|
return "bsc-testnet";
|
|
9981
10063
|
}
|
|
9982
|
-
const name =
|
|
10064
|
+
const name = tableOf9(data, "network").default;
|
|
9983
10065
|
return typeof name === "string" && name.trim() ? name.trim() : "bsc-testnet";
|
|
9984
10066
|
}
|
|
9985
10067
|
function walletKindOf(agentDir) {
|
|
@@ -9989,12 +10071,12 @@ function walletKindOf(agentDir) {
|
|
|
9989
10071
|
} catch {
|
|
9990
10072
|
return "evm-local";
|
|
9991
10073
|
}
|
|
9992
|
-
const kind =
|
|
10074
|
+
const kind = tableOf9(data, "wallet").kind;
|
|
9993
10075
|
return typeof kind === "string" && kind.trim() ? kind.trim() : "evm-local";
|
|
9994
10076
|
}
|
|
9995
10077
|
function altanaSessionForRuntime(agentDir) {
|
|
9996
10078
|
const cfg = loadStudioToml11(path23.join(agentDir, "studio.toml"));
|
|
9997
|
-
const wallet =
|
|
10079
|
+
const wallet = tableOf9(cfg, "wallet");
|
|
9998
10080
|
const configured = String(
|
|
9999
10081
|
wallet.session_file ?? ".studio/wallets/altana-session.json"
|
|
10000
10082
|
);
|
|
@@ -10089,48 +10171,7 @@ function runtimeEnvKeys(agentDir) {
|
|
|
10089
10171
|
} catch {
|
|
10090
10172
|
cfg = {};
|
|
10091
10173
|
}
|
|
10092
|
-
|
|
10093
|
-
const kind = tableOf8(cfg, "wallet").kind;
|
|
10094
|
-
let keys;
|
|
10095
|
-
if (kind === "twak") {
|
|
10096
|
-
keys = ["TWAK_WALLET_PASSWORD"];
|
|
10097
|
-
for (const k of ["TWAK_ACCESS_ID", "TWAK_HMAC_SECRET"]) {
|
|
10098
|
-
if (resolvable(k)) {
|
|
10099
|
-
keys.push(k);
|
|
10100
|
-
}
|
|
10101
|
-
}
|
|
10102
|
-
} else if (kind === "altana") {
|
|
10103
|
-
keys = [];
|
|
10104
|
-
} else {
|
|
10105
|
-
keys = ["WALLET_PASSWORD"];
|
|
10106
|
-
}
|
|
10107
|
-
const provider = tableOf8(cfg, "llm").provider;
|
|
10108
|
-
const providerKey = typeof provider === "string" ? PROVIDER_KEY_ENV[provider] : null;
|
|
10109
|
-
if (providerKey) {
|
|
10110
|
-
keys.push(providerKey);
|
|
10111
|
-
}
|
|
10112
|
-
const sk = String(tableOf8(cfg, "storage").kind ?? "local").toLowerCase();
|
|
10113
|
-
if (sk === "ipfs") {
|
|
10114
|
-
keys.push("STORAGE_API_URL");
|
|
10115
|
-
if (resolvable("STORAGE_API_KEY")) {
|
|
10116
|
-
keys.push("STORAGE_API_KEY");
|
|
10117
|
-
}
|
|
10118
|
-
}
|
|
10119
|
-
if (resolvable("RPC_URL")) {
|
|
10120
|
-
keys.push("RPC_URL");
|
|
10121
|
-
}
|
|
10122
|
-
if (commerceRails(cfg).erc8183) {
|
|
10123
|
-
for (const key of ERC8183_ADDRESS_OVERRIDE_KEYS) {
|
|
10124
|
-
if (resolvable(key)) keys.push(key);
|
|
10125
|
-
}
|
|
10126
|
-
}
|
|
10127
|
-
const runtime = String(tableOf8(cfg, "stack").runtime ?? "agentcore");
|
|
10128
|
-
if (runtime === "agentcore" && x402SellerUsesB402(cfg)) {
|
|
10129
|
-
for (const key of B402_RUNTIME_KEYS) {
|
|
10130
|
-
if (resolvable(key)) keys.push(key);
|
|
10131
|
-
}
|
|
10132
|
-
}
|
|
10133
|
-
return keys;
|
|
10174
|
+
return runtimeEnvKeysCore(cfg, (key) => Boolean(process.env[key]));
|
|
10134
10175
|
}
|
|
10135
10176
|
function compactJson(text2) {
|
|
10136
10177
|
try {
|
|
@@ -10142,7 +10183,7 @@ function compactJson(text2) {
|
|
|
10142
10183
|
function readTwakFiles(agentDir) {
|
|
10143
10184
|
let walletCfg = {};
|
|
10144
10185
|
try {
|
|
10145
|
-
walletCfg =
|
|
10186
|
+
walletCfg = tableOf9(
|
|
10146
10187
|
loadStudioToml11(path23.join(agentDir, "studio.toml")),
|
|
10147
10188
|
"wallet"
|
|
10148
10189
|
);
|
|
@@ -10552,7 +10593,7 @@ function networkBanner(agentDir) {
|
|
|
10552
10593
|
} catch {
|
|
10553
10594
|
return null;
|
|
10554
10595
|
}
|
|
10555
|
-
const name =
|
|
10596
|
+
const name = tableOf9(data, "network").default;
|
|
10556
10597
|
if (typeof name !== "string" || !name.trim()) {
|
|
10557
10598
|
return null;
|
|
10558
10599
|
}
|
|
@@ -10605,49 +10646,7 @@ function runtimeEnvKeys2(agentRoot2) {
|
|
|
10605
10646
|
cfg = {};
|
|
10606
10647
|
}
|
|
10607
10648
|
const resolvable = (key) => Boolean(process.env[key] || getEnvVar(envLocalPath11(agentRoot2), key));
|
|
10608
|
-
|
|
10609
|
-
let keys;
|
|
10610
|
-
if (walletKind2 === "twak") {
|
|
10611
|
-
keys = ["TWAK_WALLET_PASSWORD"];
|
|
10612
|
-
for (const k of ["TWAK_ACCESS_ID", "TWAK_HMAC_SECRET"]) {
|
|
10613
|
-
if (resolvable(k)) {
|
|
10614
|
-
keys.push(k);
|
|
10615
|
-
}
|
|
10616
|
-
}
|
|
10617
|
-
} else if (walletKind2 === "altana") {
|
|
10618
|
-
keys = [];
|
|
10619
|
-
} else {
|
|
10620
|
-
keys = ["WALLET_PASSWORD"];
|
|
10621
|
-
}
|
|
10622
|
-
const provider = tableOf2(cfg, "llm").provider;
|
|
10623
|
-
const providerKey = typeof provider === "string" ? PROVIDER_KEY_ENV[provider] : null;
|
|
10624
|
-
if (providerKey) {
|
|
10625
|
-
keys.push(providerKey);
|
|
10626
|
-
}
|
|
10627
|
-
const storageKind2 = String(
|
|
10628
|
-
tableOf2(cfg, "storage").kind ?? "local"
|
|
10629
|
-
).toLowerCase();
|
|
10630
|
-
if (storageKind2 === "ipfs") {
|
|
10631
|
-
keys.push("STORAGE_API_URL");
|
|
10632
|
-
if (resolvable("STORAGE_API_KEY")) {
|
|
10633
|
-
keys.push("STORAGE_API_KEY");
|
|
10634
|
-
}
|
|
10635
|
-
}
|
|
10636
|
-
if (resolvable("RPC_URL")) {
|
|
10637
|
-
keys.push("RPC_URL");
|
|
10638
|
-
}
|
|
10639
|
-
if (commerceRails(cfg).erc8183) {
|
|
10640
|
-
for (const key of ERC8183_ADDRESS_OVERRIDE_KEYS) {
|
|
10641
|
-
if (resolvable(key)) keys.push(key);
|
|
10642
|
-
}
|
|
10643
|
-
}
|
|
10644
|
-
const runtime = String(tableOf2(cfg, "stack").runtime ?? "agentcore");
|
|
10645
|
-
if (runtime === "agentcore" && x402SellerUsesB402(cfg)) {
|
|
10646
|
-
for (const key of B402_RUNTIME_KEYS) {
|
|
10647
|
-
if (resolvable(key)) keys.push(key);
|
|
10648
|
-
}
|
|
10649
|
-
}
|
|
10650
|
-
return keys;
|
|
10649
|
+
return runtimeEnvKeysCore(cfg, resolvable);
|
|
10651
10650
|
}
|
|
10652
10651
|
var require2 = createRequire(import.meta.url);
|
|
10653
10652
|
async function checkAgentcoreJsonPresent(root, target) {
|
|
@@ -11391,6 +11390,84 @@ async function checkAwsTargetsPopulated(root, target) {
|
|
|
11391
11390
|
}
|
|
11392
11391
|
];
|
|
11393
11392
|
}
|
|
11393
|
+
var AGENTCORE_AGENT_QUOTA_CODE = "L-F4575653";
|
|
11394
|
+
function awsJson(stdout) {
|
|
11395
|
+
try {
|
|
11396
|
+
const parsed = JSON.parse(stdout);
|
|
11397
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
11398
|
+
} catch {
|
|
11399
|
+
return null;
|
|
11400
|
+
}
|
|
11401
|
+
}
|
|
11402
|
+
async function checkAgentcoreQuotaHeadroom(root, target) {
|
|
11403
|
+
if (target !== "agentcore") {
|
|
11404
|
+
return [];
|
|
11405
|
+
}
|
|
11406
|
+
const [, region] = readAwsTarget(root);
|
|
11407
|
+
if (!region || !await whichBin("aws")) {
|
|
11408
|
+
return [];
|
|
11409
|
+
}
|
|
11410
|
+
const quotaRes = await runCapture("aws", [
|
|
11411
|
+
"service-quotas",
|
|
11412
|
+
"get-service-quota",
|
|
11413
|
+
"--service-code",
|
|
11414
|
+
"bedrock-agentcore",
|
|
11415
|
+
"--quota-code",
|
|
11416
|
+
AGENTCORE_AGENT_QUOTA_CODE,
|
|
11417
|
+
"--region",
|
|
11418
|
+
region,
|
|
11419
|
+
"--output",
|
|
11420
|
+
"json"
|
|
11421
|
+
]);
|
|
11422
|
+
if (quotaRes.code !== 0) {
|
|
11423
|
+
return [];
|
|
11424
|
+
}
|
|
11425
|
+
const quota = awsJson(quotaRes.stdout)?.Quota;
|
|
11426
|
+
const limit = typeof quota?.Value === "number" ? quota.Value : null;
|
|
11427
|
+
if (limit === null) {
|
|
11428
|
+
return [];
|
|
11429
|
+
}
|
|
11430
|
+
const listRes = await runCapture("aws", [
|
|
11431
|
+
"bedrock-agentcore-control",
|
|
11432
|
+
"list-agent-runtimes",
|
|
11433
|
+
"--region",
|
|
11434
|
+
region,
|
|
11435
|
+
"--output",
|
|
11436
|
+
"json"
|
|
11437
|
+
]);
|
|
11438
|
+
if (listRes.code !== 0) {
|
|
11439
|
+
return [];
|
|
11440
|
+
}
|
|
11441
|
+
const runtimes = awsJson(listRes.stdout)?.agentRuntimes;
|
|
11442
|
+
if (!Array.isArray(runtimes)) {
|
|
11443
|
+
return [];
|
|
11444
|
+
}
|
|
11445
|
+
const used = runtimes.length;
|
|
11446
|
+
const details = {
|
|
11447
|
+
used,
|
|
11448
|
+
limit,
|
|
11449
|
+
region,
|
|
11450
|
+
quota_code: AGENTCORE_AGENT_QUOTA_CODE
|
|
11451
|
+
};
|
|
11452
|
+
if (used < limit) {
|
|
11453
|
+
return [
|
|
11454
|
+
{
|
|
11455
|
+
level: Level.INFO,
|
|
11456
|
+
name: "agentcore_quota_headroom",
|
|
11457
|
+
message: `AgentCore runtimes: ${used}/${limit} used in ${region}.`,
|
|
11458
|
+
details
|
|
11459
|
+
}
|
|
11460
|
+
];
|
|
11461
|
+
}
|
|
11462
|
+
return [
|
|
11463
|
+
{
|
|
11464
|
+
level: Level.CRITICAL,
|
|
11465
|
+
name: "agentcore_quota_headroom",
|
|
11466
|
+
message: `AgentCore runtimes: ${used}/${limit} used in ${region} \u2014 no slots left, so the deploy would fail with \`maxAgents limit exceeded\` AFTER pushing the image and creating the secret, M2M client, and execution role (all orphans). Delete a runtime you no longer need (\`bag deploy destroy\` in its workspace) or request a quota increase for ${AGENTCORE_AGENT_QUOTA_CODE} ("Total Agents per Account") in the Service Quotas console.`,
|
|
11467
|
+
details
|
|
11468
|
+
}
|
|
11469
|
+
];
|
|
11470
|
+
}
|
|
11394
11471
|
var allChecks = [
|
|
11395
11472
|
checkAgentcoreJsonPresent,
|
|
11396
11473
|
checkAgentcoreAuthorizerKeyLegacy,
|
|
@@ -11415,7 +11492,8 @@ var allChecks = [
|
|
|
11415
11492
|
checkCommerceReady,
|
|
11416
11493
|
checkDeployCliRunnable,
|
|
11417
11494
|
checkRuntimeSecretsInjected,
|
|
11418
|
-
checkAwsTargetsPopulated
|
|
11495
|
+
checkAwsTargetsPopulated,
|
|
11496
|
+
checkAgentcoreQuotaHeadroom
|
|
11419
11497
|
];
|
|
11420
11498
|
|
|
11421
11499
|
// src/cli/_deploy/secrets.ts
|
|
@@ -11436,17 +11514,17 @@ function loadTomlOr(agentRoot2) {
|
|
|
11436
11514
|
return {};
|
|
11437
11515
|
}
|
|
11438
11516
|
}
|
|
11439
|
-
function
|
|
11517
|
+
function tableOf10(cfg, key) {
|
|
11440
11518
|
const v = cfg[key];
|
|
11441
11519
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
11442
11520
|
}
|
|
11443
11521
|
function deployWalletKind(agentRoot2) {
|
|
11444
|
-
const kind =
|
|
11522
|
+
const kind = tableOf10(loadTomlOr(agentRoot2), "wallet").kind;
|
|
11445
11523
|
return kind ? String(kind) : "evm-local";
|
|
11446
11524
|
}
|
|
11447
11525
|
function resolveKeystoreDir3(agentRoot2) {
|
|
11448
11526
|
const rel = String(
|
|
11449
|
-
|
|
11527
|
+
tableOf10(loadTomlOr(agentRoot2), "wallet").keystore_dir ?? ".studio/wallets"
|
|
11450
11528
|
);
|
|
11451
11529
|
return path25.resolve(path25.isAbsolute(rel) ? rel : path25.join(agentRoot2, rel));
|
|
11452
11530
|
}
|
|
@@ -11461,7 +11539,7 @@ function readKeystoreJson(agentRoot2) {
|
|
|
11461
11539
|
if (names.length === 0) {
|
|
11462
11540
|
return null;
|
|
11463
11541
|
}
|
|
11464
|
-
const address =
|
|
11542
|
+
const address = tableOf10(loadTomlOr(agentRoot2), "wallet").address;
|
|
11465
11543
|
let chosen = null;
|
|
11466
11544
|
if (typeof address === "string" && address) {
|
|
11467
11545
|
for (const n of names) {
|
|
@@ -11699,6 +11777,12 @@ function cognitoPackageJson() {
|
|
|
11699
11777
|
function readme() {
|
|
11700
11778
|
return `# Cognito M2M client for the AgentCore A2A inbound OAuth2 authorizer
|
|
11701
11779
|
|
|
11780
|
+
> **DEPRECATED.** \`bag deploy --provider aws\` now provisions its own user pool
|
|
11781
|
+
> and M2M client, and overwrites the values wired from this stack. Deploying
|
|
11782
|
+
> this app leaves a second, unused pool behind that you have to clean up
|
|
11783
|
+
> yourself. Keep it only if you need to own the pool out of band; otherwise run
|
|
11784
|
+
> \`bag deploy --provider aws\` and hand buyers the credentials it prints.
|
|
11785
|
+
|
|
11702
11786
|
AgentCore A2A endpoints REQUIRE inbound auth (there is no anonymous mode). This
|
|
11703
11787
|
seller uses **OAuth2 via Cognito** \u2014 NOT SigV4, because external buyers cannot
|
|
11704
11788
|
obtain your AWS IAM credentials. Cognito has no public machine-to-machine
|
|
@@ -11739,12 +11823,11 @@ This reads the local \`cdk-outputs.json\` and patches:
|
|
|
11739
11823
|
| \`Scope\` | \`agentcore.json\` \u2192 \`envVars[] OAUTH_SCOPE\` (+ \`.studio/.env.local\` for local dev) |
|
|
11740
11824
|
|
|
11741
11825
|
\`OAUTH_TOKEN_URL\` / \`OAUTH_SCOPE\` are read by the emitted agent card from
|
|
11742
|
-
the environment, so the
|
|
11743
|
-
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11747
|
-
custom outputs path.)
|
|
11826
|
+
the environment, so the agent card advertises the OAuth2 security scheme buyers
|
|
11827
|
+
must use. **A \`bag deploy\` run replaces both values (and the authorizer) with
|
|
11828
|
+
the pool it provisions itself**, so this wiring only takes effect for local
|
|
11829
|
+
\`bag dev\`. (\`bag deploy provision-cognito --wire <file>\` accepts a custom
|
|
11830
|
+
outputs path.)
|
|
11748
11831
|
|
|
11749
11832
|
## Issue buyer credentials
|
|
11750
11833
|
|
|
@@ -11795,7 +11878,8 @@ function wireSummary(r) {
|
|
|
11795
11878
|
allowedClients = [${r.clientId}]
|
|
11796
11879
|
- ${path26.basename(r.agentcoreJson)}: envVars[] OAUTH_TOKEN_URL + OAUTH_SCOPE (reach the runtime so the agent card advertises oauth2)
|
|
11797
11880
|
- ${r.envLocal}: same pair, for local \`bag dev\`
|
|
11798
|
-
\u2192 \`bag deploy
|
|
11881
|
+
\u2192 NOTE: a \`bag deploy\` run provisions its own pool and overwrites these
|
|
11882
|
+
values with the ones it issued. This wiring only feeds local \`bag dev\`.`;
|
|
11799
11883
|
}
|
|
11800
11884
|
function flattenCdkOutputs(raw) {
|
|
11801
11885
|
const flat = {};
|
|
@@ -11823,6 +11907,49 @@ function upsertDescriptorEnvvars(cfg, values) {
|
|
|
11823
11907
|
}
|
|
11824
11908
|
}
|
|
11825
11909
|
}
|
|
11910
|
+
function syncDescriptorOauthFacts(workspaceRoot, facts) {
|
|
11911
|
+
const acj = path26.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
11912
|
+
let cfg;
|
|
11913
|
+
try {
|
|
11914
|
+
cfg = JSON.parse(fs27.readFileSync(acj, "utf-8"));
|
|
11915
|
+
} catch {
|
|
11916
|
+
return;
|
|
11917
|
+
}
|
|
11918
|
+
const envValues = {};
|
|
11919
|
+
if (facts.tokenUrl) {
|
|
11920
|
+
envValues.OAUTH_TOKEN_URL = facts.tokenUrl;
|
|
11921
|
+
}
|
|
11922
|
+
if (facts.scope) {
|
|
11923
|
+
envValues.OAUTH_SCOPE = facts.scope;
|
|
11924
|
+
}
|
|
11925
|
+
const authorizer = facts.discoveryUrl && facts.clientId ? {
|
|
11926
|
+
customJwtAuthorizer: {
|
|
11927
|
+
discoveryUrl: facts.discoveryUrl,
|
|
11928
|
+
allowedClients: [facts.clientId]
|
|
11929
|
+
}
|
|
11930
|
+
} : null;
|
|
11931
|
+
if (Object.keys(envValues).length === 0 && authorizer === null) {
|
|
11932
|
+
return;
|
|
11933
|
+
}
|
|
11934
|
+
if (Object.keys(envValues).length > 0) {
|
|
11935
|
+
upsertDescriptorEnvvars(cfg, envValues);
|
|
11936
|
+
}
|
|
11937
|
+
if (authorizer !== null && Array.isArray(cfg.runtimes)) {
|
|
11938
|
+
for (const rt of cfg.runtimes) {
|
|
11939
|
+
if (rt !== null && typeof rt === "object") {
|
|
11940
|
+
const r = rt;
|
|
11941
|
+
r.authorizerType = "CUSTOM_JWT";
|
|
11942
|
+
r.authorizerConfiguration = authorizer;
|
|
11943
|
+
}
|
|
11944
|
+
}
|
|
11945
|
+
}
|
|
11946
|
+
try {
|
|
11947
|
+
fs27.writeFileSync(acj, `${JSON.stringify(cfg, null, 2)}
|
|
11948
|
+
`, "utf-8");
|
|
11949
|
+
} catch {
|
|
11950
|
+
return;
|
|
11951
|
+
}
|
|
11952
|
+
}
|
|
11826
11953
|
function upsertEnv(envLocal, values) {
|
|
11827
11954
|
let lines = [];
|
|
11828
11955
|
try {
|
|
@@ -12503,7 +12630,7 @@ import * as fs33 from "fs";
|
|
|
12503
12630
|
import * as path32 from "path";
|
|
12504
12631
|
import { envLocalPath as envLocalPath14 } from "@bnbagent/studio-runtime/config";
|
|
12505
12632
|
import { show } from "@bnbagent/studio-runtime/erc8004";
|
|
12506
|
-
import { getNetwork as getNetwork8 } from "@bnbagent/studio-runtime/networks";
|
|
12633
|
+
import { DEFAULT_RPC, getNetwork as getNetwork8 } from "@bnbagent/studio-runtime/networks";
|
|
12507
12634
|
import * as walletRt3 from "@bnbagent/studio-runtime/wallet";
|
|
12508
12635
|
var TBNB_MIN_WEI = 7n * 10n ** 15n;
|
|
12509
12636
|
function isFile13(p) {
|
|
@@ -12665,6 +12792,51 @@ async function checkRpcUrlSetForRuntime(root, _target) {
|
|
|
12665
12792
|
}
|
|
12666
12793
|
];
|
|
12667
12794
|
}
|
|
12795
|
+
async function checkRuntimeRpcReachable(root, _target) {
|
|
12796
|
+
const netName = tableOf2(loadAgentToml(root), "network").default;
|
|
12797
|
+
if (!netName || typeof netName !== "string") {
|
|
12798
|
+
return [];
|
|
12799
|
+
}
|
|
12800
|
+
const expected = getNetwork8(netName).chainId;
|
|
12801
|
+
const configured = process.env.RPC_URL || getEnvVar(envLocalPath14(root), "RPC_URL") || "";
|
|
12802
|
+
const rpcUrl = configured || DEFAULT_RPC[netName] || "";
|
|
12803
|
+
if (!rpcUrl) {
|
|
12804
|
+
return [];
|
|
12805
|
+
}
|
|
12806
|
+
const source = configured ? "RPC_URL" : "the runtime default";
|
|
12807
|
+
let actual;
|
|
12808
|
+
try {
|
|
12809
|
+
actual = await readChainIdAt(rpcUrl);
|
|
12810
|
+
} catch (exc) {
|
|
12811
|
+
return [
|
|
12812
|
+
{
|
|
12813
|
+
level: Level.WARNING,
|
|
12814
|
+
name: "runtime_rpc_reachable",
|
|
12815
|
+
message: `the RPC endpoint the deployed runtime will use (${rpcUrl}, from ${source}) did not answer eth_chainId (${exc instanceof Error ? exc.message.split("\n")[0] : String(exc)}). The seller's first chain read (e.g. notify_funded verification) will fail in the cloud until a working endpoint is set.`,
|
|
12816
|
+
fixCmd: "bag env set RPC_URL <working-endpoint>",
|
|
12817
|
+
details: { rpc_url: rpcUrl, source, network: netName }
|
|
12818
|
+
}
|
|
12819
|
+
];
|
|
12820
|
+
}
|
|
12821
|
+
if (actual !== expected) {
|
|
12822
|
+
return [
|
|
12823
|
+
{
|
|
12824
|
+
level: Level.WARNING,
|
|
12825
|
+
name: "runtime_rpc_reachable",
|
|
12826
|
+
message: `the RPC endpoint the deployed runtime will use (${rpcUrl}, from ${source}) answered chain_id=${actual}; expected ${expected} for ${netName}.`,
|
|
12827
|
+
fixCmd: "bag env set RPC_URL <endpoint-on-the-right-chain>",
|
|
12828
|
+
details: {
|
|
12829
|
+
rpc_url: rpcUrl,
|
|
12830
|
+
source,
|
|
12831
|
+
network: netName,
|
|
12832
|
+
expected,
|
|
12833
|
+
actual
|
|
12834
|
+
}
|
|
12835
|
+
}
|
|
12836
|
+
];
|
|
12837
|
+
}
|
|
12838
|
+
return [];
|
|
12839
|
+
}
|
|
12668
12840
|
async function checkInstalledRecipesUnchanged(root, _target) {
|
|
12669
12841
|
const manifest = path32.join(root, ".studio", "recipes", "manifest.json");
|
|
12670
12842
|
let data;
|
|
@@ -12705,59 +12877,6 @@ async function checkInstalledRecipesUnchanged(root, _target) {
|
|
|
12705
12877
|
}
|
|
12706
12878
|
return [];
|
|
12707
12879
|
}
|
|
12708
|
-
function agentcoreAuthorizer(root) {
|
|
12709
|
-
const descriptor = path32.join(root, "agentcore", "agentcore.json");
|
|
12710
|
-
let data;
|
|
12711
|
-
try {
|
|
12712
|
-
data = JSON.parse(fs33.readFileSync(descriptor, "utf-8"));
|
|
12713
|
-
} catch {
|
|
12714
|
-
return null;
|
|
12715
|
-
}
|
|
12716
|
-
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
12717
|
-
return null;
|
|
12718
|
-
}
|
|
12719
|
-
const runtimes = data.runtimes;
|
|
12720
|
-
if (!Array.isArray(runtimes)) {
|
|
12721
|
-
return null;
|
|
12722
|
-
}
|
|
12723
|
-
for (const rt of runtimes) {
|
|
12724
|
-
if (rt === null || typeof rt !== "object") {
|
|
12725
|
-
continue;
|
|
12726
|
-
}
|
|
12727
|
-
const auth = rt.authorizerConfiguration;
|
|
12728
|
-
if (auth !== null && typeof auth === "object" && !Array.isArray(auth)) {
|
|
12729
|
-
const jwt = auth.customJwtAuthorizer ?? auth.customJWTAuthorizer;
|
|
12730
|
-
if (jwt !== null && typeof jwt === "object" && !Array.isArray(jwt)) {
|
|
12731
|
-
return jwt;
|
|
12732
|
-
}
|
|
12733
|
-
}
|
|
12734
|
-
}
|
|
12735
|
-
return null;
|
|
12736
|
-
}
|
|
12737
|
-
async function checkCognitoAuthorizerConfigured(root, target) {
|
|
12738
|
-
if (target !== "agentcore") {
|
|
12739
|
-
return [];
|
|
12740
|
-
}
|
|
12741
|
-
const jwt = agentcoreAuthorizer(root);
|
|
12742
|
-
const discovery = jwt?.discoveryUrl;
|
|
12743
|
-
const clients = jwt?.allowedClients;
|
|
12744
|
-
const configured = Boolean(discovery) && Array.isArray(clients) && clients.length > 0;
|
|
12745
|
-
if (configured) {
|
|
12746
|
-
return [];
|
|
12747
|
-
}
|
|
12748
|
-
return [
|
|
12749
|
-
{
|
|
12750
|
-
level: Level.WARNING,
|
|
12751
|
-
name: "cognito_authorizer_configured",
|
|
12752
|
-
message: "no Cognito authorizer configured in agentcore.json (authorizerConfiguration.customJwtAuthorizer.discoveryUrl/allowedClients) \u2192 the A2A endpoint will require SigV4/AWS creds; external buyers can't reach it. Run `bag deploy provision-cognito`, then paste the CDK outputs into the authorizer.",
|
|
12753
|
-
fixCmd: "bag deploy provision-cognito",
|
|
12754
|
-
details: {
|
|
12755
|
-
discovery_url_set: Boolean(discovery),
|
|
12756
|
-
allowed_clients: Array.isArray(clients) ? clients : []
|
|
12757
|
-
}
|
|
12758
|
-
}
|
|
12759
|
-
];
|
|
12760
|
-
}
|
|
12761
12880
|
async function checkStorageLocalNotDeployable(root, _target) {
|
|
12762
12881
|
const storage = loadAgentToml(root).storage;
|
|
12763
12882
|
if (storage === null || typeof storage !== "object" || Array.isArray(storage) || String(storage.kind ?? "").toLowerCase() !== "local") {
|
|
@@ -12780,14 +12899,14 @@ var allChecks4 = [
|
|
|
12780
12899
|
checkAgentUriDataUriOrHttps,
|
|
12781
12900
|
checkNetworkMatchesChainId,
|
|
12782
12901
|
checkRpcUrlSetForRuntime,
|
|
12902
|
+
checkRuntimeRpcReachable,
|
|
12783
12903
|
checkInstalledRecipesUnchanged,
|
|
12784
|
-
checkCognitoAuthorizerConfigured,
|
|
12785
12904
|
checkStorageLocalNotDeployable
|
|
12786
12905
|
];
|
|
12787
12906
|
|
|
12788
12907
|
// src/cli/_deploy/checks/platform.ts
|
|
12789
12908
|
var SLUG_RE = /^[a-z][a-z0-9-]{1,40}$/;
|
|
12790
|
-
function
|
|
12909
|
+
function tableOf11(data, key) {
|
|
12791
12910
|
const value = data[key];
|
|
12792
12911
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
12793
12912
|
}
|
|
@@ -12802,16 +12921,16 @@ function loadAgent(root) {
|
|
|
12802
12921
|
}
|
|
12803
12922
|
}
|
|
12804
12923
|
function platformArtifact(data) {
|
|
12805
|
-
const walletKind2 = String(
|
|
12924
|
+
const walletKind2 = String(tableOf11(data, "wallet").kind ?? "evm-local").trim().toLowerCase();
|
|
12806
12925
|
if (walletKind2 === "twak") return "container";
|
|
12807
|
-
const deploy =
|
|
12926
|
+
const deploy = tableOf11(data, "deploy");
|
|
12808
12927
|
const explicit = String(deploy.platform_artifact ?? "").toLowerCase();
|
|
12809
12928
|
if (explicit) return explicit;
|
|
12810
12929
|
return String(deploy.packaging ?? "").toLowerCase() === "container" ? "container" : "zip";
|
|
12811
12930
|
}
|
|
12812
12931
|
var checkPlatformEntrypointPresent = async (root, _target) => {
|
|
12813
12932
|
const data = loadAgent(root);
|
|
12814
|
-
const faces = stackFaces(
|
|
12933
|
+
const faces = stackFaces(tableOf11(data, "stack"), tableOf11(data, "payments"));
|
|
12815
12934
|
const stem2 = entryStemOf(faces);
|
|
12816
12935
|
const filenames = [`${stem2}.ts`];
|
|
12817
12936
|
if (stem2 === "dualMain") filenames.push("mcpMain.ts");
|
|
@@ -12831,7 +12950,7 @@ var checkPlatformEntrypointPresent = async (root, _target) => {
|
|
|
12831
12950
|
};
|
|
12832
12951
|
var checkPlatformKeystoreNotInArtifact = async (root, _target) => {
|
|
12833
12952
|
const data = loadAgent(root);
|
|
12834
|
-
const wallet =
|
|
12953
|
+
const wallet = tableOf11(data, "wallet");
|
|
12835
12954
|
if (String(wallet.kind ?? "evm-local") === "twak") return [];
|
|
12836
12955
|
const agent = path33.resolve(agentRoot(root));
|
|
12837
12956
|
const configured = String(wallet.keystore_dir ?? ".studio/wallets");
|
|
@@ -12855,7 +12974,7 @@ var checkPlatformKeystoreNotInArtifact = async (root, _target) => {
|
|
|
12855
12974
|
];
|
|
12856
12975
|
};
|
|
12857
12976
|
var checkPlatformTestnetOnly = async (root, _target) => {
|
|
12858
|
-
const network = String(
|
|
12977
|
+
const network = String(tableOf11(loadAgent(root), "network").default ?? "").trim().toLowerCase();
|
|
12859
12978
|
if (!network || network === "bsc-testnet") return [];
|
|
12860
12979
|
return [
|
|
12861
12980
|
{
|
|
@@ -12868,7 +12987,7 @@ var checkPlatformTestnetOnly = async (root, _target) => {
|
|
|
12868
12987
|
];
|
|
12869
12988
|
};
|
|
12870
12989
|
var checkPlatformSlugValid = async (root, _target) => {
|
|
12871
|
-
const platform =
|
|
12990
|
+
const platform = tableOf11(tableOf11(loadAgent(root), "deploy"), "platform");
|
|
12872
12991
|
const slug = String(platform.slug ?? "").trim();
|
|
12873
12992
|
if (!slug || SLUG_RE.test(slug)) return [];
|
|
12874
12993
|
return [
|
|
@@ -12926,7 +13045,7 @@ var checkPlatformStorageEndpoint = async (root, _target) => {
|
|
|
12926
13045
|
};
|
|
12927
13046
|
var checkPlatformMcpSyncTimeout = async (root, _target) => {
|
|
12928
13047
|
const data = loadAgent(root);
|
|
12929
|
-
const faces = stackFaces(
|
|
13048
|
+
const faces = stackFaces(tableOf11(data, "stack"), tableOf11(data, "payments"));
|
|
12930
13049
|
if (!hasMcpFace(faces)) return [];
|
|
12931
13050
|
const dual = hasA2aFace(faces);
|
|
12932
13051
|
return [
|
|
@@ -12939,8 +13058,8 @@ var checkPlatformMcpSyncTimeout = async (root, _target) => {
|
|
|
12939
13058
|
];
|
|
12940
13059
|
};
|
|
12941
13060
|
var checkPlatformX402MerchantsMainnet = async (root, _target) => {
|
|
12942
|
-
const merchants =
|
|
12943
|
-
|
|
13061
|
+
const merchants = tableOf11(
|
|
13062
|
+
tableOf11(tableOf11(loadAgent(root), "payments"), "x402"),
|
|
12944
13063
|
"merchants"
|
|
12945
13064
|
);
|
|
12946
13065
|
const names = Object.keys(merchants).sort();
|
|
@@ -13001,7 +13120,8 @@ var warningChecks = [
|
|
|
13001
13120
|
checkPlatformX402MerchantsMainnet,
|
|
13002
13121
|
checkWalletBalancesAllZero,
|
|
13003
13122
|
checkWalletTbnbBalanceSufficient,
|
|
13004
|
-
checkWalletUBalanceNonzero
|
|
13123
|
+
checkWalletUBalanceNonzero,
|
|
13124
|
+
checkRuntimeRpcReachable
|
|
13005
13125
|
];
|
|
13006
13126
|
var infoChecks = [
|
|
13007
13127
|
checkPlatformTrialStatus,
|
|
@@ -13234,6 +13354,7 @@ function baseResult(endpoint, runtime, overrides) {
|
|
|
13234
13354
|
studioTomlUpdated: false,
|
|
13235
13355
|
runtime,
|
|
13236
13356
|
note: null,
|
|
13357
|
+
warning: null,
|
|
13237
13358
|
error: null,
|
|
13238
13359
|
exitCode: 0,
|
|
13239
13360
|
...overrides
|
|
@@ -13273,15 +13394,15 @@ async function runVerify(opts) {
|
|
|
13273
13394
|
exitCode: 1
|
|
13274
13395
|
});
|
|
13275
13396
|
}
|
|
13276
|
-
const
|
|
13397
|
+
const tableOf17 = (key) => {
|
|
13277
13398
|
const v = data[key];
|
|
13278
13399
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
13279
13400
|
};
|
|
13280
|
-
const network = opts.network || String(
|
|
13401
|
+
const network = opts.network || String(tableOf17("network").default ?? "bsc-testnet");
|
|
13281
13402
|
const protocol = nativeProtocolOf(
|
|
13282
|
-
stackFaces(
|
|
13403
|
+
stackFaces(tableOf17("stack"), tableOf17("payments"))
|
|
13283
13404
|
);
|
|
13284
|
-
const identity =
|
|
13405
|
+
const identity = tableOf17("identity");
|
|
13285
13406
|
const existingAgentId = identity.agent_id;
|
|
13286
13407
|
const accessDescription = accessSummaryForAgentcore(root, { protocol });
|
|
13287
13408
|
let agentId = null;
|
|
@@ -13289,6 +13410,7 @@ async function runVerify(opts) {
|
|
|
13289
13410
|
let action = "none";
|
|
13290
13411
|
let registerError = null;
|
|
13291
13412
|
let postWriteError = null;
|
|
13413
|
+
let postWriteWarning = null;
|
|
13292
13414
|
let registerNote = null;
|
|
13293
13415
|
let identityPendingReason = null;
|
|
13294
13416
|
let registerExitCode = 0;
|
|
@@ -13321,9 +13443,8 @@ async function runVerify(opts) {
|
|
|
13321
13443
|
const cause = e.cause !== null && typeof e.cause === "object" ? e.cause : null;
|
|
13322
13444
|
const relayTxHash = typeof cause?.txHash === "string" ? cause.txHash : e.txHash;
|
|
13323
13445
|
action = "register_partial";
|
|
13324
|
-
|
|
13446
|
+
postWriteWarning = relayTxHash ? `ERC-8004 register created agent_id=${e.agentId}, but setAgentURI relay tx_hash=${relayTxHash} was not observed by the chain RPC. Run \`bag erc8004 clear-pending\` to reconcile, then retry \`bag erc8004 update-endpoint\`.` : `ERC-8004 register created agent_id=${e.agentId}, but the setAgentURI relay submission was not observed by the chain RPC. Run \`bag erc8004 clear-pending\` to reconcile, then retry \`bag erc8004 update-endpoint\`.`;
|
|
13325
13447
|
identityPendingReason = "setAgentURI relay submission unverified; run bag erc8004 clear-pending before retrying";
|
|
13326
|
-
registerExitCode = 1;
|
|
13327
13448
|
} else if (e.txHash) {
|
|
13328
13449
|
action = "register_pending";
|
|
13329
13450
|
registerNote = `ERC-8004 register created agent_id=${e.agentId}; setAgentURI tx pending (${e.txHash}). Check the tx before retrying \`bag erc8004 update-endpoint\`.`;
|
|
@@ -13417,6 +13538,7 @@ async function runVerify(opts) {
|
|
|
13417
13538
|
action,
|
|
13418
13539
|
studioTomlUpdated,
|
|
13419
13540
|
note: notes.length > 0 ? notes.join(" | ") : null,
|
|
13541
|
+
warning: postWriteWarning,
|
|
13420
13542
|
error: postWriteError,
|
|
13421
13543
|
exitCode: registerExitCode
|
|
13422
13544
|
});
|
|
@@ -13436,10 +13558,16 @@ var WALLET_SECTION = "wallet";
|
|
|
13436
13558
|
var KEYSTORE_JSON_ENV2 = "WALLET_KEYSTORE_JSON";
|
|
13437
13559
|
var TWAK_WALLET_JSON_ENV2 = "TWAK_WALLET_JSON";
|
|
13438
13560
|
var WALLET_MATERIAL_KEYS = [KEYSTORE_JSON_ENV2, TWAK_WALLET_JSON_ENV2];
|
|
13561
|
+
var RETIRED_AGENT_STATES = /* @__PURE__ */ new Set([
|
|
13562
|
+
"deleted",
|
|
13563
|
+
"retired",
|
|
13564
|
+
"removed",
|
|
13565
|
+
"reclaiming"
|
|
13566
|
+
]);
|
|
13439
13567
|
function isJsonObject(value) {
|
|
13440
13568
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
13441
13569
|
}
|
|
13442
|
-
function
|
|
13570
|
+
function tableOf12(cfg, key) {
|
|
13443
13571
|
const value = cfg[key];
|
|
13444
13572
|
return isJsonObject(value) ? value : {};
|
|
13445
13573
|
}
|
|
@@ -13474,7 +13602,7 @@ function loadAgentCfg(root) {
|
|
|
13474
13602
|
}
|
|
13475
13603
|
}
|
|
13476
13604
|
function platformCfg(root) {
|
|
13477
|
-
return
|
|
13605
|
+
return tableOf12(tableOf12(loadAgentCfg(root), "deploy"), "platform");
|
|
13478
13606
|
}
|
|
13479
13607
|
function patchTomlKv2(tomlPath, section, key, value) {
|
|
13480
13608
|
let text2 = fs36.readFileSync(tomlPath, "utf-8");
|
|
@@ -13494,6 +13622,32 @@ function recordPlatformKv(root, key, value) {
|
|
|
13494
13622
|
} catch {
|
|
13495
13623
|
}
|
|
13496
13624
|
}
|
|
13625
|
+
function retiredAgentReason(agent) {
|
|
13626
|
+
const candidates = [agent];
|
|
13627
|
+
for (const key of ["agent", "data"]) {
|
|
13628
|
+
const nested = agent[key];
|
|
13629
|
+
if (isJsonObject(nested)) {
|
|
13630
|
+
candidates.push(nested);
|
|
13631
|
+
}
|
|
13632
|
+
}
|
|
13633
|
+
for (const item of candidates) {
|
|
13634
|
+
for (const key of [
|
|
13635
|
+
"state",
|
|
13636
|
+
"status",
|
|
13637
|
+
"lifecycle_state",
|
|
13638
|
+
"lifecycleState"
|
|
13639
|
+
]) {
|
|
13640
|
+
const value = item[key];
|
|
13641
|
+
if (typeof value === "string" && RETIRED_AGENT_STATES.has(value.toLowerCase())) {
|
|
13642
|
+
return value.toLowerCase();
|
|
13643
|
+
}
|
|
13644
|
+
}
|
|
13645
|
+
if (item.deleted_at || item.deletedAt) {
|
|
13646
|
+
return "deleted";
|
|
13647
|
+
}
|
|
13648
|
+
}
|
|
13649
|
+
return null;
|
|
13650
|
+
}
|
|
13497
13651
|
function suggestNextSlug(slug) {
|
|
13498
13652
|
const m = /(\d+)$/.exec(slug);
|
|
13499
13653
|
let next;
|
|
@@ -13504,12 +13658,45 @@ function suggestNextSlug(slug) {
|
|
|
13504
13658
|
}
|
|
13505
13659
|
return next.slice(0, 41);
|
|
13506
13660
|
}
|
|
13661
|
+
async function retiredSlugPreflight(slug, platformCmd) {
|
|
13662
|
+
let res;
|
|
13663
|
+
try {
|
|
13664
|
+
res = await platformCmd(["list"], {
|
|
13665
|
+
slug: "studio-platform",
|
|
13666
|
+
json: true,
|
|
13667
|
+
quiet: true
|
|
13668
|
+
});
|
|
13669
|
+
} catch {
|
|
13670
|
+
return null;
|
|
13671
|
+
}
|
|
13672
|
+
if (res.code !== 0 || !isJsonObject(res.data)) {
|
|
13673
|
+
return null;
|
|
13674
|
+
}
|
|
13675
|
+
const candidates = [res.data];
|
|
13676
|
+
for (const key of ["agents", "data", "items", "records"]) {
|
|
13677
|
+
const nested = res.data[key];
|
|
13678
|
+
if (Array.isArray(nested)) {
|
|
13679
|
+
candidates.push(...nested);
|
|
13680
|
+
}
|
|
13681
|
+
}
|
|
13682
|
+
for (const entry of candidates) {
|
|
13683
|
+
if (!isJsonObject(entry)) {
|
|
13684
|
+
continue;
|
|
13685
|
+
}
|
|
13686
|
+
const entrySlug = String(entry.slug ?? entry.name ?? "").toLowerCase();
|
|
13687
|
+
if (entrySlug !== slug.toLowerCase()) {
|
|
13688
|
+
continue;
|
|
13689
|
+
}
|
|
13690
|
+
return retiredAgentReason(entry);
|
|
13691
|
+
}
|
|
13692
|
+
return null;
|
|
13693
|
+
}
|
|
13507
13694
|
function clearIdentityEndpointIfMatches(root, oldUrl) {
|
|
13508
13695
|
if (!oldUrl) {
|
|
13509
13696
|
return;
|
|
13510
13697
|
}
|
|
13511
13698
|
const cfg = loadAgentCfg(root);
|
|
13512
|
-
if (String(
|
|
13699
|
+
if (String(tableOf12(cfg, "identity").endpoint ?? "") !== String(oldUrl)) {
|
|
13513
13700
|
return;
|
|
13514
13701
|
}
|
|
13515
13702
|
const tomlPath = agentTomlPath2(root);
|
|
@@ -13528,7 +13715,7 @@ function persistedPackaging2(agentRoot2) {
|
|
|
13528
13715
|
}
|
|
13529
13716
|
try {
|
|
13530
13717
|
const cfg = loadStudioToml19(tomlPath);
|
|
13531
|
-
const value =
|
|
13718
|
+
const value = tableOf12(cfg, "deploy").packaging;
|
|
13532
13719
|
return value ? String(value) : null;
|
|
13533
13720
|
} catch {
|
|
13534
13721
|
return null;
|
|
@@ -13539,7 +13726,7 @@ function resolvePlatformArtifact2(agentRoot2) {
|
|
|
13539
13726
|
if (isFile14(tomlPath)) {
|
|
13540
13727
|
try {
|
|
13541
13728
|
const cfg = loadStudioToml19(tomlPath);
|
|
13542
|
-
const explicit =
|
|
13729
|
+
const explicit = tableOf12(cfg, "deploy").platform_artifact;
|
|
13543
13730
|
if (explicit) {
|
|
13544
13731
|
return String(explicit);
|
|
13545
13732
|
}
|
|
@@ -13551,7 +13738,7 @@ function resolvePlatformArtifact2(agentRoot2) {
|
|
|
13551
13738
|
function platformPackaging(root) {
|
|
13552
13739
|
const agentRoot2 = findSubProjectRoot15("agent", root);
|
|
13553
13740
|
const platformArtifact2 = agentRoot2 !== null ? resolvePlatformArtifact2(agentRoot2) : "zip";
|
|
13554
|
-
const walletKind2 = agentRoot2 !== null ? String(
|
|
13741
|
+
const walletKind2 = agentRoot2 !== null ? String(tableOf12(loadCfgAt(agentRoot2), "wallet").kind ?? "evm-local") : "evm-local";
|
|
13555
13742
|
if (walletKind2 === "twak") {
|
|
13556
13743
|
return "container";
|
|
13557
13744
|
}
|
|
@@ -13569,7 +13756,7 @@ function recordExposedAddress(root, address) {
|
|
|
13569
13756
|
if (tomlPath === null) {
|
|
13570
13757
|
return;
|
|
13571
13758
|
}
|
|
13572
|
-
const existing =
|
|
13759
|
+
const existing = tableOf12(
|
|
13573
13760
|
loadAgentCfg(root),
|
|
13574
13761
|
WALLET_SECTION
|
|
13575
13762
|
).platform_exposed_addresses;
|
|
@@ -13589,7 +13776,7 @@ function utcStamp() {
|
|
|
13589
13776
|
function buyerAccess(root) {
|
|
13590
13777
|
const base = bnbPlatformApiUrl();
|
|
13591
13778
|
const cfg = loadAgentCfg(root);
|
|
13592
|
-
const faces = stackFaces(
|
|
13779
|
+
const faces = stackFaces(tableOf12(cfg, "stack"), tableOf12(cfg, "payments"));
|
|
13593
13780
|
const protocol = nativeProtocolOf(faces);
|
|
13594
13781
|
const rawAgentId = platformCfg(root).agent_id;
|
|
13595
13782
|
const agentId = typeof rawAgentId === "string" && rawAgentId ? rawAgentId : null;
|
|
@@ -13633,7 +13820,7 @@ function resolveSlug(root) {
|
|
|
13633
13820
|
if (typeof recorded === "string" && recorded) {
|
|
13634
13821
|
return recorded;
|
|
13635
13822
|
}
|
|
13636
|
-
let name = String(
|
|
13823
|
+
let name = String(tableOf12(loadAgentCfg(root), "project").name ?? "");
|
|
13637
13824
|
name = name.replace(/-(agent|service)$/, "");
|
|
13638
13825
|
if (!name) {
|
|
13639
13826
|
name = path36.basename(findWorkspaceRoot6(root) ?? root);
|
|
@@ -13713,6 +13900,11 @@ async function platformAgent(opts) {
|
|
|
13713
13900
|
}
|
|
13714
13901
|
const secrets = await (opts.collectRuntimeSecrets ?? collectRuntimeSecrets)(root);
|
|
13715
13902
|
walletWarning(root, secrets);
|
|
13903
|
+
if (Object.keys(secrets).length > 0) {
|
|
13904
|
+
warn(
|
|
13905
|
+
`note: runtime secret keys handed to the platform: ${Object.keys(secrets).sort().join(", ")} (names only \u2014 values not printed).`
|
|
13906
|
+
);
|
|
13907
|
+
}
|
|
13716
13908
|
if (!opts.skipPrepare && opts.runPrepareGate) {
|
|
13717
13909
|
const rc = await opts.runPrepareGate(root, opts.force ?? false);
|
|
13718
13910
|
if (rc !== null && rc !== 0) {
|
|
@@ -13723,6 +13915,18 @@ async function platformAgent(opts) {
|
|
|
13723
13915
|
}
|
|
13724
13916
|
}
|
|
13725
13917
|
const slug = resolveSlug(root);
|
|
13918
|
+
{
|
|
13919
|
+
const reason = await retiredSlugPreflight(slug, platformCmd);
|
|
13920
|
+
if (reason !== null) {
|
|
13921
|
+
const next = suggestNextSlug(slug);
|
|
13922
|
+
warn(
|
|
13923
|
+
`error: the slug '${slug}' is ${reason} on the platform \u2014 deploys to it always fail (destroyed slugs are permanently retired). Pick a new slug:
|
|
13924
|
+
bag config set deploy.platform.slug ${next}
|
|
13925
|
+
then re-run the deploy.`
|
|
13926
|
+
);
|
|
13927
|
+
return 1;
|
|
13928
|
+
}
|
|
13929
|
+
}
|
|
13726
13930
|
const agentDir = findSubProjectRoot15("agent", root);
|
|
13727
13931
|
if (agentDir === null) {
|
|
13728
13932
|
warn(
|
|
@@ -13731,7 +13935,7 @@ async function platformAgent(opts) {
|
|
|
13731
13935
|
return 1;
|
|
13732
13936
|
}
|
|
13733
13937
|
const cfg = loadAgentCfg(root);
|
|
13734
|
-
const faces = stackFaces(
|
|
13938
|
+
const faces = stackFaces(tableOf12(cfg, "stack"), tableOf12(cfg, "payments"));
|
|
13735
13939
|
const protocol = nativeProtocolOf(faces);
|
|
13736
13940
|
const runDeploy = opts.runDelegatedDeploy ?? (async (o) => withDeployFiles(
|
|
13737
13941
|
o.root,
|
|
@@ -13845,8 +14049,8 @@ async function confirmPackagingDefault(root, packaging, deps) {
|
|
|
13845
14049
|
return null;
|
|
13846
14050
|
}
|
|
13847
14051
|
const cfg = loadAgentCfg(root);
|
|
13848
|
-
const walletKind2 = String(
|
|
13849
|
-
const destination = String(
|
|
14052
|
+
const walletKind2 = String(tableOf12(cfg, "wallet").kind ?? "evm-local");
|
|
14053
|
+
const destination = String(tableOf12(cfg, "deploy").destination ?? "platform");
|
|
13850
14054
|
const answer = await deps.promptUser(
|
|
13851
14055
|
`This project will deploy as a ${packaging} package (wallet.kind=${walletKind2}, destination=${destination}). Continue? [Y/n] `
|
|
13852
14056
|
);
|
|
@@ -13860,7 +14064,7 @@ function walletWarning(root, secrets) {
|
|
|
13860
14064
|
if (!WALLET_MATERIAL_KEYS.some((k) => k in secrets)) {
|
|
13861
14065
|
return;
|
|
13862
14066
|
}
|
|
13863
|
-
const address =
|
|
14067
|
+
const address = tableOf12(loadAgentCfg(root), "wallet").address;
|
|
13864
14068
|
const who = typeof address === "string" && address ? `key (address ${address})` : "signing key";
|
|
13865
14069
|
warn(
|
|
13866
14070
|
`
|
|
@@ -13906,7 +14110,7 @@ function recordShippedWallet(root, secrets) {
|
|
|
13906
14110
|
if (!WALLET_MATERIAL_KEYS.some((k) => k in secrets)) {
|
|
13907
14111
|
return;
|
|
13908
14112
|
}
|
|
13909
|
-
const address =
|
|
14113
|
+
const address = tableOf12(loadAgentCfg(root), "wallet").address;
|
|
13910
14114
|
if (typeof address === "string" && address) {
|
|
13911
14115
|
recordExposedAddress(root, address);
|
|
13912
14116
|
}
|
|
@@ -13938,7 +14142,7 @@ function printAccessNextSteps(root, _invokeUrl) {
|
|
|
13938
14142
|
}
|
|
13939
14143
|
if (!x402Only) {
|
|
13940
14144
|
emit(
|
|
13941
|
-
" mint buyer creds: bag platform invoke-client new (prints client_id + client_secret to POST to the client_credentials token endpoint above)"
|
|
14145
|
+
" mint buyer creds: bag platform invoke-client new (prints client_id + client_secret to POST to the client_credentials token endpoint above \u2014 credentials go in the form BODY; HTTP Basic auth is not accepted)"
|
|
13942
14146
|
);
|
|
13943
14147
|
} else {
|
|
13944
14148
|
emit(" protocol discovery is suppressed for this X402-only deployment.");
|
|
@@ -13989,6 +14193,8 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
13989
14193
|
const agentIdNote = agentId ?? "<not registered yet \u2014 run `bag platform invoke-client new` to get one>";
|
|
13990
14194
|
const tokenSteps = ` 1) run \`bag platform invoke-client new\` -> client_id + client_secret (secret shown ONCE).
|
|
13991
14195
|
2) POST client_credentials to ${tokenUrl} with scope \`${scope}\` -> access_token.
|
|
14196
|
+
Send client_id + client_secret in the application/x-www-form-urlencoded BODY \u2014
|
|
14197
|
+
this endpoint does NOT accept HTTP Basic auth (\`curl -u\` fails with oauth.invalid_request).
|
|
13992
14198
|
3) send \`Authorization: Bearer <token>\`.`;
|
|
13993
14199
|
const agentCfg = loadAgentCfg(agentRoot2);
|
|
13994
14200
|
const rails = commerceRails(agentCfg);
|
|
@@ -13999,7 +14205,10 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
13999
14205
|
if (hasA2aFace(faces)) {
|
|
14000
14206
|
endpoints.push(
|
|
14001
14207
|
` [A2A] Agent card: ${cardUrl}
|
|
14002
|
-
Invoke (JSON-RPC message/send): ${a2aInvokeUrl}
|
|
14208
|
+
Invoke (JSON-RPC message/send): ${a2aInvokeUrl}
|
|
14209
|
+
When composing agent-card URLs in code, build them with \`new URL(base)\` +
|
|
14210
|
+
\`url.pathname = ... \` (keeps any querystring intact) \u2014 never string-concatenate
|
|
14211
|
+
\`\${base}/.well-known/agent-card.json\`; that breaks on URLs that carry a querystring.`
|
|
14003
14212
|
);
|
|
14004
14213
|
}
|
|
14005
14214
|
if (hasMcpFace(faces)) {
|
|
@@ -14204,7 +14413,8 @@ async function platformDestroy(opts) {
|
|
|
14204
14413
|
return 1;
|
|
14205
14414
|
}
|
|
14206
14415
|
const oldInvokeUrl = recorded.invoke_url;
|
|
14207
|
-
|
|
14416
|
+
const nextSlug = suggestNextSlug(slug);
|
|
14417
|
+
recordPlatformKv(root, "slug", nextSlug);
|
|
14208
14418
|
recordPlatformKv(root, "deployment_id", "");
|
|
14209
14419
|
recordPlatformKv(root, "invoke_url", "");
|
|
14210
14420
|
recordPlatformKv(root, "agent_id", "");
|
|
@@ -14215,11 +14425,10 @@ async function platformDestroy(opts) {
|
|
|
14215
14425
|
);
|
|
14216
14426
|
emit(`\u2713 deleted platform agent ${slug} (deployment + transmitted secret).`);
|
|
14217
14427
|
emit(
|
|
14218
|
-
|
|
14428
|
+
`note: the on-chain ERC-8004 identity is unchanged; its endpoint will go stale. Destroyed slugs are permanently retired, so the local slug was advanced to '${nextSlug}' \u2014 the next deploy uses it automatically. Your local keystore (.studio/wallets/) was left untouched.`
|
|
14219
14429
|
);
|
|
14220
14430
|
emit(
|
|
14221
|
-
`
|
|
14222
|
-
bag config set deploy.platform.slug ${suggestNextSlug(slug)}
|
|
14431
|
+
` Redeploy THIS project (uses '${nextSlug}', or pick your own with \`bag config set deploy.platform.slug <name>\`):
|
|
14223
14432
|
bag deploy --provider bnb`
|
|
14224
14433
|
);
|
|
14225
14434
|
return 0;
|
|
@@ -14267,7 +14476,7 @@ function isDir7(p) {
|
|
|
14267
14476
|
function errMsg2(exc) {
|
|
14268
14477
|
return exc instanceof Error ? exc.message : String(exc);
|
|
14269
14478
|
}
|
|
14270
|
-
function
|
|
14479
|
+
function tableOf13(cfg, key) {
|
|
14271
14480
|
const v = cfg[key];
|
|
14272
14481
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
14273
14482
|
}
|
|
@@ -14439,8 +14648,8 @@ function registerDeploy(program) {
|
|
|
14439
14648
|
p.command("fix-gitignore").description(
|
|
14440
14649
|
"Ensure the workspace .gitignore excludes .studio/ (the agent's .env.local + keystore)."
|
|
14441
14650
|
).option("--project-root <path>", "Override project root.").action(act((opts) => cmdFixGitignore(opts)));
|
|
14442
|
-
p.command("provision-cognito").description(
|
|
14443
|
-
"Emit an AWS CDK app under agentcore/cognito/ that provisions a Cognito M2M client for the AgentCore
|
|
14651
|
+
p.command("provision-cognito", { hidden: true }).description(
|
|
14652
|
+
"DEPRECATED \u2014 `bag deploy` provisions inbound OAuth by itself. Emit an AWS CDK app under agentcore/cognito/ that provisions a Cognito M2M client for the AgentCore inbound OAuth2 authorizer (studio writes IaC + prints steps; you run `cdk deploy`)."
|
|
14444
14653
|
).option("--project-root <path>", "Override project root.").option(
|
|
14445
14654
|
"--wire [outputsFile]",
|
|
14446
14655
|
"After you `cdk deploy --outputs-file <file>`, wire those outputs into agentcore.json + .studio/.env.local (default file: agentcore/cognito/cdk-outputs.json). Pure local file I/O \u2014 studio never calls AWS."
|
|
@@ -14479,7 +14688,7 @@ function readStackRuntime(root) {
|
|
|
14479
14688
|
if (cfg === null) {
|
|
14480
14689
|
return null;
|
|
14481
14690
|
}
|
|
14482
|
-
const runtime =
|
|
14691
|
+
const runtime = tableOf13(cfg, "stack").runtime;
|
|
14483
14692
|
return runtime ? String(runtime) : null;
|
|
14484
14693
|
}
|
|
14485
14694
|
function agentNetworkDefault(root) {
|
|
@@ -14487,24 +14696,29 @@ function agentNetworkDefault(root) {
|
|
|
14487
14696
|
if (cfg === null) {
|
|
14488
14697
|
return "";
|
|
14489
14698
|
}
|
|
14490
|
-
return String(
|
|
14699
|
+
return String(tableOf13(cfg, "network").default ?? "").toLowerCase();
|
|
14491
14700
|
}
|
|
14492
14701
|
function agentDeployDestination(root) {
|
|
14493
14702
|
const cfg = loadAgentCfg2(root);
|
|
14494
14703
|
if (cfg === null) {
|
|
14495
14704
|
return "self";
|
|
14496
14705
|
}
|
|
14497
|
-
const dest = String(
|
|
14706
|
+
const dest = String(tableOf13(cfg, "deploy").destination ?? "").trim().toLowerCase();
|
|
14498
14707
|
return dest || "self";
|
|
14499
14708
|
}
|
|
14500
14709
|
function resolveTarget(opts, root, destination = agentDeployDestination(root)) {
|
|
14501
14710
|
const explicit = opts.runtime ?? opts.target;
|
|
14502
|
-
if (explicit) {
|
|
14503
|
-
return explicit;
|
|
14504
|
-
}
|
|
14505
14711
|
if (destination === "platform") {
|
|
14712
|
+
if (explicit && explicit !== "platform") {
|
|
14713
|
+
printErr(
|
|
14714
|
+
`warning: --runtime=${explicit} ignored \u2014 studio.toml has [deploy].destination = 'platform', which selects the managed deploy path and its own checks. Use --provider bnb|aws to pick where this agent deploys.`
|
|
14715
|
+
);
|
|
14716
|
+
}
|
|
14506
14717
|
return "platform";
|
|
14507
14718
|
}
|
|
14719
|
+
if (explicit) {
|
|
14720
|
+
return explicit;
|
|
14721
|
+
}
|
|
14508
14722
|
return readStackRuntime(root) ?? "agentcore";
|
|
14509
14723
|
}
|
|
14510
14724
|
function validateRuntimeAgainstStack(target, force, root) {
|
|
@@ -14711,6 +14925,12 @@ function writeAgentDeployState(workspaceRoot, arn, record = {}, destination = "s
|
|
|
14711
14925
|
if (scope) {
|
|
14712
14926
|
setEnvVar(envLocalPath16(agentRoot2), "OAUTH_SCOPE", scope);
|
|
14713
14927
|
}
|
|
14928
|
+
syncDescriptorOauthFacts(workspaceRoot, {
|
|
14929
|
+
tokenUrl,
|
|
14930
|
+
scope,
|
|
14931
|
+
discoveryUrl,
|
|
14932
|
+
clientId
|
|
14933
|
+
});
|
|
14714
14934
|
if (persistedPackaging(agentRoot2) === null) {
|
|
14715
14935
|
patchTomlKv(
|
|
14716
14936
|
tomlPath,
|
|
@@ -14976,6 +15196,17 @@ async function refreshLocalDeployDependencies(root) {
|
|
|
14976
15196
|
return 1;
|
|
14977
15197
|
}
|
|
14978
15198
|
}
|
|
15199
|
+
function partialDeployCleanupNote(workspaceRoot) {
|
|
15200
|
+
const project = projectName(workspaceRoot);
|
|
15201
|
+
return [
|
|
15202
|
+
"note: a deploy that fails partway can leave these behind (they are reused by a successful retry, so clean up only if you are giving up):",
|
|
15203
|
+
` - ECR image bnbagent/${project}`,
|
|
15204
|
+
` - Secrets Manager bnbagent/${project}/runtime`,
|
|
15205
|
+
` - Cognito M2M client bnbagent-${project}`,
|
|
15206
|
+
` - IAM role bnbagent-${project}-runtime`,
|
|
15207
|
+
" `bag deploy destroy --provider aws --execute` removes the runtime, secret, and M2M client; add --purge for the ECR repository and log groups. The IAM role is deleted with the runtime it was created for."
|
|
15208
|
+
].join("\n");
|
|
15209
|
+
}
|
|
14979
15210
|
async function cmdAgent(opts, agentcoreArgs) {
|
|
14980
15211
|
let rc = applyProjectRoot(opts.projectRoot);
|
|
14981
15212
|
if (rc !== null) {
|
|
@@ -15187,6 +15418,7 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15187
15418
|
printErr(
|
|
15188
15419
|
"note: the pinned bnbagent-deploy adapter automatically restores an owned runtime secret that is inside its recovery window. If AWS denies that operation, update the deployer policy to include secretsmanager:RestoreSecret."
|
|
15189
15420
|
);
|
|
15421
|
+
printErr(partialDeployCleanupNote(workspaceRoot));
|
|
15190
15422
|
return code;
|
|
15191
15423
|
}
|
|
15192
15424
|
const record = recordOf2(data);
|
|
@@ -15246,13 +15478,13 @@ function recordedEndpoint(root) {
|
|
|
15246
15478
|
if (cfg === null) {
|
|
15247
15479
|
return null;
|
|
15248
15480
|
}
|
|
15249
|
-
const url =
|
|
15481
|
+
const url = tableOf13(cfg, "identity").endpoint;
|
|
15250
15482
|
return url ? String(url) : null;
|
|
15251
15483
|
}
|
|
15252
15484
|
function recordedAgentId(agentRoot2) {
|
|
15253
15485
|
try {
|
|
15254
15486
|
const cfg = loadStudioToml20(path37.join(agentRoot2, "studio.toml"));
|
|
15255
|
-
const val =
|
|
15487
|
+
const val = tableOf13(cfg, "identity").agent_id;
|
|
15256
15488
|
return val !== void 0 && val !== null && val !== "" ? String(val) : null;
|
|
15257
15489
|
} catch {
|
|
15258
15490
|
return null;
|
|
@@ -15261,7 +15493,7 @@ function recordedAgentId(agentRoot2) {
|
|
|
15261
15493
|
function recordedRuntimeArn(agentRoot2) {
|
|
15262
15494
|
try {
|
|
15263
15495
|
const cfg = loadStudioToml20(path37.join(agentRoot2, "studio.toml"));
|
|
15264
|
-
const val =
|
|
15496
|
+
const val = tableOf13(cfg, "deploy").runtime_arn;
|
|
15265
15497
|
return val ? String(val) : null;
|
|
15266
15498
|
} catch {
|
|
15267
15499
|
return null;
|
|
@@ -15270,7 +15502,7 @@ function recordedRuntimeArn(agentRoot2) {
|
|
|
15270
15502
|
function recordedOauthClientId(agentRoot2) {
|
|
15271
15503
|
try {
|
|
15272
15504
|
const cfg = loadStudioToml20(path37.join(agentRoot2, "studio.toml"));
|
|
15273
|
-
const val =
|
|
15505
|
+
const val = tableOf13(cfg, "deploy").oauth_client_id;
|
|
15274
15506
|
return val ? String(val) : null;
|
|
15275
15507
|
} catch {
|
|
15276
15508
|
return null;
|
|
@@ -15279,7 +15511,7 @@ function recordedOauthClientId(agentRoot2) {
|
|
|
15279
15511
|
function agentFacesOf(agentRoot2) {
|
|
15280
15512
|
try {
|
|
15281
15513
|
const cfg = loadStudioToml20(path37.join(agentRoot2, "studio.toml"));
|
|
15282
|
-
return stackFaces(
|
|
15514
|
+
return stackFaces(tableOf13(cfg, "stack"), tableOf13(cfg, "payments"));
|
|
15283
15515
|
} catch {
|
|
15284
15516
|
return ["A2A"];
|
|
15285
15517
|
}
|
|
@@ -15372,7 +15604,10 @@ async function printAgentClientPrompt2(root, destination, opts = {}) {
|
|
|
15372
15604
|
and POST it to the invoke URL above.` : ` [A2A] Invoke (JSON-RPC message/send, POST-only): ${a2aInvokeUrl}
|
|
15373
15605
|
NOTE: this AgentCore endpoint is POST-only and serves NO
|
|
15374
15606
|
GET-able agent card. Skip A2A discovery (do NOT fetch
|
|
15375
|
-
/.well-known/agent-card.json) \u2014 ${a2aPayloadPhrase} straight to the invoke URL above
|
|
15607
|
+
/.well-known/agent-card.json) \u2014 ${a2aPayloadPhrase} straight to the invoke URL above.
|
|
15608
|
+
The invoke URL carries a querystring (?qualifier=...): never
|
|
15609
|
+
string-concatenate extra path segments onto it \u2014 that produces
|
|
15610
|
+
an invalid URL and an HTTP 405.`;
|
|
15376
15611
|
const lines = [
|
|
15377
15612
|
"",
|
|
15378
15613
|
CLIENT_PROMPT_RULE2,
|
|
@@ -15526,6 +15761,7 @@ function verifyToJson(r) {
|
|
|
15526
15761
|
studio_toml_updated: r.studioTomlUpdated,
|
|
15527
15762
|
runtime: r.runtime,
|
|
15528
15763
|
note: r.note,
|
|
15764
|
+
warning: r.warning,
|
|
15529
15765
|
error: r.error,
|
|
15530
15766
|
exit_code: r.exitCode
|
|
15531
15767
|
};
|
|
@@ -15567,12 +15803,15 @@ function renderVerifyHuman(r, deployment, liveStatus) {
|
|
|
15567
15803
|
if (r.note) {
|
|
15568
15804
|
printOut(`note: ${r.note}`);
|
|
15569
15805
|
}
|
|
15806
|
+
if (r.warning) {
|
|
15807
|
+
printOut(`warning: ${r.warning}`);
|
|
15808
|
+
}
|
|
15570
15809
|
if (r.error) {
|
|
15571
15810
|
printOut(`error: ${r.error}`);
|
|
15572
15811
|
}
|
|
15573
15812
|
}
|
|
15574
15813
|
function deployCliError(data) {
|
|
15575
|
-
const error =
|
|
15814
|
+
const error = tableOf13(data, "error");
|
|
15576
15815
|
const message = String(error.message ?? "").trim();
|
|
15577
15816
|
return message || null;
|
|
15578
15817
|
}
|
|
@@ -15914,6 +16153,7 @@ async function cmdFixGitignore(opts) {
|
|
|
15914
16153
|
printOut(`${marker} ${result.name}: ${result.message}`);
|
|
15915
16154
|
return 0;
|
|
15916
16155
|
}
|
|
16156
|
+
var PROVISION_COGNITO_DEPRECATION = "warning: `bag deploy provision-cognito` is deprecated and will be removed.\n `bag deploy` provisions the inbound OAuth user pool and M2M client on its\n own; the pool this CDK app stands up is never used by a deploy, and both\n the stack and its client are billable orphans you have to clean up.\n Run `bag deploy --provider aws` directly instead.";
|
|
15917
16157
|
async function cmdProvisionCognito(opts) {
|
|
15918
16158
|
const rc = applyProjectRoot(opts.projectRoot, false);
|
|
15919
16159
|
if (rc !== null) {
|
|
@@ -15921,6 +16161,7 @@ async function cmdProvisionCognito(opts) {
|
|
|
15921
16161
|
}
|
|
15922
16162
|
const root = resolveProjectRoot2(opts.projectRoot);
|
|
15923
16163
|
const workspaceRoot = deployWorkspaceRoot2(root);
|
|
16164
|
+
printOut(PROVISION_COGNITO_DEPRECATION);
|
|
15924
16165
|
if (opts.wire !== void 0 && opts.wire !== false) {
|
|
15925
16166
|
const outputsFile = typeof opts.wire === "string" && opts.wire ? opts.wire : null;
|
|
15926
16167
|
try {
|
|
@@ -15987,7 +16228,7 @@ var SECRET_ENV_KEYS = [
|
|
|
15987
16228
|
"TWAK_ACCESS_ID",
|
|
15988
16229
|
"TWAK_HMAC_SECRET"
|
|
15989
16230
|
];
|
|
15990
|
-
function
|
|
16231
|
+
function tableOf14(cfg, key) {
|
|
15991
16232
|
const v = cfg[key];
|
|
15992
16233
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
15993
16234
|
}
|
|
@@ -16064,7 +16305,7 @@ async function cmdDoctor(opts) {
|
|
|
16064
16305
|
checks.push(...await checkBalances(projectRoot, data, opts.network));
|
|
16065
16306
|
checks.push(...await checkPieverseMainnetU(projectRoot, data));
|
|
16066
16307
|
checks.push(...await check8004(projectRoot, data, opts.network));
|
|
16067
|
-
const destination = String(
|
|
16308
|
+
const destination = String(tableOf14(data, "deploy").destination ?? "self").trim().toLowerCase();
|
|
16068
16309
|
checks.push(...await checkDeployTools(data, destination));
|
|
16069
16310
|
checks.push(...checkAgentsMdSkillTrigger(projectRoot));
|
|
16070
16311
|
printChecks(checks);
|
|
@@ -16147,13 +16388,13 @@ function checkAppMain(projectRootArg) {
|
|
|
16147
16388
|
config = {};
|
|
16148
16389
|
}
|
|
16149
16390
|
}
|
|
16150
|
-
const stack =
|
|
16391
|
+
const stack = tableOf14(config, "stack");
|
|
16151
16392
|
const runtime = String(stack.runtime ?? "").toLowerCase();
|
|
16152
16393
|
let entrypoint;
|
|
16153
16394
|
if (runtime === "azure-foundry") {
|
|
16154
16395
|
entrypoint = "src/foundryMain.ts";
|
|
16155
16396
|
} else if (runtime === "agentcore") {
|
|
16156
|
-
const faces = stackFaces(stack,
|
|
16397
|
+
const faces = stackFaces(stack, tableOf14(config, "payments"));
|
|
16157
16398
|
entrypoint = `src/${entryStemOf(faces)}.ts`;
|
|
16158
16399
|
} else {
|
|
16159
16400
|
entrypoint = "src/main.ts";
|
|
@@ -16224,7 +16465,7 @@ function anchoredKeystoreDir(projectRoot, walletCfg) {
|
|
|
16224
16465
|
return path38.isAbsolute(rel) ? rel : path38.join(projectRoot, rel);
|
|
16225
16466
|
}
|
|
16226
16467
|
async function checkWallet(projectRoot, data) {
|
|
16227
|
-
const walletCfg =
|
|
16468
|
+
const walletCfg = tableOf14(data, "wallet");
|
|
16228
16469
|
if (walletCfg.kind === "twak") {
|
|
16229
16470
|
return checkWalletTwak(walletCfg, projectRoot, data);
|
|
16230
16471
|
}
|
|
@@ -16396,7 +16637,7 @@ async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
|
16396
16637
|
detail: `not on PATH \u2014 npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
16397
16638
|
});
|
|
16398
16639
|
}
|
|
16399
|
-
const networkName = String(
|
|
16640
|
+
const networkName = String(tableOf14(data, "network").default ?? "bsc-testnet");
|
|
16400
16641
|
const unsupportedTargets = twakUnsupportedContractOverrides(networkName);
|
|
16401
16642
|
if (unsupportedTargets.length > 0) {
|
|
16402
16643
|
out.push({
|
|
@@ -16442,7 +16683,7 @@ async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
|
16442
16683
|
return out;
|
|
16443
16684
|
}
|
|
16444
16685
|
function checkPassword(data) {
|
|
16445
|
-
const walletKind2 = String(
|
|
16686
|
+
const walletKind2 = String(tableOf14(data, "wallet").kind ?? "evm-local");
|
|
16446
16687
|
if (walletKind2 === "twak") {
|
|
16447
16688
|
if (process.env.TWAK_WALLET_PASSWORD) {
|
|
16448
16689
|
return [
|
|
@@ -16478,7 +16719,7 @@ function checkPassword(data) {
|
|
|
16478
16719
|
];
|
|
16479
16720
|
}
|
|
16480
16721
|
async function checkLlm(data, projectRoot) {
|
|
16481
|
-
const llmCfg =
|
|
16722
|
+
const llmCfg = tableOf14(data, "llm");
|
|
16482
16723
|
const provider = llmCfg.provider ? String(llmCfg.provider) : null;
|
|
16483
16724
|
if (!provider) {
|
|
16484
16725
|
return [{ name: "[llm] provider", status: WARN, detail: "not configured" }];
|
|
@@ -16523,8 +16764,8 @@ async function checkLlm(data, projectRoot) {
|
|
|
16523
16764
|
return out;
|
|
16524
16765
|
}
|
|
16525
16766
|
async function checkPieverse(data, apiKey) {
|
|
16526
|
-
const llmCfg =
|
|
16527
|
-
const pvCfg =
|
|
16767
|
+
const llmCfg = tableOf14(data, "llm");
|
|
16768
|
+
const pvCfg = tableOf14(llmCfg, "pieverse");
|
|
16528
16769
|
const keyHash = pvCfg.key_hash ? String(pvCfg.key_hash) : null;
|
|
16529
16770
|
const hasEnv = Boolean(apiKey);
|
|
16530
16771
|
const out = [];
|
|
@@ -16594,8 +16835,8 @@ async function checkPieverse(data, apiKey) {
|
|
|
16594
16835
|
});
|
|
16595
16836
|
}
|
|
16596
16837
|
try {
|
|
16597
|
-
const policy = pieversePolicyFromToml(
|
|
16598
|
-
const budget = policyFromToml(
|
|
16838
|
+
const policy = pieversePolicyFromToml(tableOf14(llmCfg, "auto_renew"));
|
|
16839
|
+
const budget = policyFromToml(tableOf14(data, "budget"));
|
|
16599
16840
|
let detail;
|
|
16600
16841
|
if (policy.enabled) {
|
|
16601
16842
|
const allocateDetail = `enabled: allocates $${policy.topupChunkUsd.toFixed(2)} from Account Balance when key < $${policy.minBalanceUsd.toFixed(2)}.`;
|
|
@@ -16615,7 +16856,7 @@ async function checkPieverse(data, apiKey) {
|
|
|
16615
16856
|
return out;
|
|
16616
16857
|
}
|
|
16617
16858
|
async function checkNetwork(data, networkOverride) {
|
|
16618
|
-
const netName = networkOverride ||
|
|
16859
|
+
const netName = networkOverride || tableOf14(data, "network").default;
|
|
16619
16860
|
if (!netName) {
|
|
16620
16861
|
return [
|
|
16621
16862
|
{
|
|
@@ -16660,7 +16901,7 @@ async function checkNetwork(data, networkOverride) {
|
|
|
16660
16901
|
}
|
|
16661
16902
|
}
|
|
16662
16903
|
function checkCurrency(data) {
|
|
16663
|
-
const payments =
|
|
16904
|
+
const payments = tableOf14(data, "payments");
|
|
16664
16905
|
const pay = payments.erc8183;
|
|
16665
16906
|
if (pay === null || typeof pay !== "object" || Array.isArray(pay)) {
|
|
16666
16907
|
return [];
|
|
@@ -16678,7 +16919,7 @@ function checkCurrency(data) {
|
|
|
16678
16919
|
return [];
|
|
16679
16920
|
}
|
|
16680
16921
|
function checkErc8183Pricing(data) {
|
|
16681
|
-
const payValue =
|
|
16922
|
+
const payValue = tableOf14(data, "payments").erc8183;
|
|
16682
16923
|
if (payValue === null || typeof payValue !== "object" || Array.isArray(payValue)) {
|
|
16683
16924
|
return [];
|
|
16684
16925
|
}
|
|
@@ -16758,7 +16999,7 @@ function checkErc8183Pricing(data) {
|
|
|
16758
16999
|
];
|
|
16759
17000
|
}
|
|
16760
17001
|
function checkPriceBounds(data) {
|
|
16761
|
-
const payValue =
|
|
17002
|
+
const payValue = tableOf14(data, "payments").erc8183;
|
|
16762
17003
|
if (payValue === null || typeof payValue !== "object" || Array.isArray(payValue)) {
|
|
16763
17004
|
return [];
|
|
16764
17005
|
}
|
|
@@ -16776,7 +17017,7 @@ function checkPriceBounds(data) {
|
|
|
16776
17017
|
return [];
|
|
16777
17018
|
}
|
|
16778
17019
|
function checkX402Seller(data, agentRoot2) {
|
|
16779
|
-
const payments =
|
|
17020
|
+
const payments = tableOf14(data, "payments");
|
|
16780
17021
|
const sellerValue = payments.x402_seller;
|
|
16781
17022
|
if (sellerValue === null || typeof sellerValue !== "object" || Array.isArray(sellerValue)) {
|
|
16782
17023
|
return [];
|
|
@@ -16793,7 +17034,7 @@ function checkX402Seller(data, agentRoot2) {
|
|
|
16793
17034
|
}
|
|
16794
17035
|
];
|
|
16795
17036
|
}
|
|
16796
|
-
const runtime = String(
|
|
17037
|
+
const runtime = String(tableOf14(data, "stack").runtime ?? "agentcore");
|
|
16797
17038
|
const hasErc8183 = payments.erc8183 !== null && typeof payments.erc8183 === "object" && !Array.isArray(payments.erc8183);
|
|
16798
17039
|
const fallbackStatus = hasErc8183 ? WARN : FAIL;
|
|
16799
17040
|
if (pricing.kind === "free") {
|
|
@@ -16828,7 +17069,7 @@ function checkX402Seller(data, agentRoot2) {
|
|
|
16828
17069
|
detail: `PAID \u2014 $${pricing.priceUsd} per request through B402.`
|
|
16829
17070
|
}
|
|
16830
17071
|
];
|
|
16831
|
-
const walletKind2 = String(
|
|
17072
|
+
const walletKind2 = String(tableOf14(data, "wallet").kind ?? "evm-local");
|
|
16832
17073
|
if (!["evm-local", "twak"].includes(walletKind2)) {
|
|
16833
17074
|
out.push({
|
|
16834
17075
|
name: "x402 payout wallet",
|
|
@@ -16854,7 +17095,7 @@ function checkX402Seller(data, agentRoot2) {
|
|
|
16854
17095
|
return out;
|
|
16855
17096
|
}
|
|
16856
17097
|
function checkStorage(data) {
|
|
16857
|
-
const kind = String(
|
|
17098
|
+
const kind = String(tableOf14(data, "storage").kind ?? "local").toLowerCase();
|
|
16858
17099
|
if (kind === "ipfs") {
|
|
16859
17100
|
if (!process.env.STORAGE_API_URL) {
|
|
16860
17101
|
return [
|
|
@@ -16900,7 +17141,7 @@ function checkStorage(data) {
|
|
|
16900
17141
|
];
|
|
16901
17142
|
}
|
|
16902
17143
|
function balanceAddress(projectRoot, data) {
|
|
16903
|
-
const walletCfg =
|
|
17144
|
+
const walletCfg = tableOf14(data, "wallet");
|
|
16904
17145
|
if (walletCfg.kind === "twak" || walletCfg.kind === "altana") {
|
|
16905
17146
|
const addr = String(walletCfg.address ?? "").trim();
|
|
16906
17147
|
return addr || null;
|
|
@@ -16922,7 +17163,7 @@ function balanceAddress(projectRoot, data) {
|
|
|
16922
17163
|
return provider.address;
|
|
16923
17164
|
}
|
|
16924
17165
|
async function checkBalances(projectRoot, data, networkOverride) {
|
|
16925
|
-
const netName = networkOverride ||
|
|
17166
|
+
const netName = networkOverride || tableOf14(data, "network").default;
|
|
16926
17167
|
if (!netName) {
|
|
16927
17168
|
return [];
|
|
16928
17169
|
}
|
|
@@ -16999,11 +17240,11 @@ async function checkBalances(projectRoot, data, networkOverride) {
|
|
|
16999
17240
|
}
|
|
17000
17241
|
}
|
|
17001
17242
|
async function checkPieverseMainnetU(projectRoot, data) {
|
|
17002
|
-
const llmCfg =
|
|
17243
|
+
const llmCfg = tableOf14(data, "llm");
|
|
17003
17244
|
if (llmCfg.provider !== "pieverse-llm") {
|
|
17004
17245
|
return [];
|
|
17005
17246
|
}
|
|
17006
|
-
const pvCfg =
|
|
17247
|
+
const pvCfg = tableOf14(llmCfg, "pieverse");
|
|
17007
17248
|
const pvNetwork = String(pvCfg.network ?? "bsc-mainnet");
|
|
17008
17249
|
if (pvNetwork === "bsc-testnet") {
|
|
17009
17250
|
return [
|
|
@@ -17016,7 +17257,7 @@ async function checkPieverseMainnetU(projectRoot, data) {
|
|
|
17016
17257
|
}
|
|
17017
17258
|
const modelName = String(llmCfg.model ?? "");
|
|
17018
17259
|
const isFreeModel2 = modelName.includes("auto/free");
|
|
17019
|
-
const budgetEnabled =
|
|
17260
|
+
const budgetEnabled = tableOf14(data, "budget").enabled === true;
|
|
17020
17261
|
if (isFreeModel2 && !budgetEnabled) {
|
|
17021
17262
|
return [
|
|
17022
17263
|
{
|
|
@@ -17026,7 +17267,7 @@ async function checkPieverseMainnetU(projectRoot, data) {
|
|
|
17026
17267
|
}
|
|
17027
17268
|
];
|
|
17028
17269
|
}
|
|
17029
|
-
const autoRenew =
|
|
17270
|
+
const autoRenew = tableOf14(llmCfg, "auto_renew");
|
|
17030
17271
|
const chunk = typeof autoRenew.topup_chunk_usd === "number" ? autoRenew.topup_chunk_usd : 1;
|
|
17031
17272
|
const threshold = chunk * 2;
|
|
17032
17273
|
try {
|
|
@@ -17071,7 +17312,7 @@ async function check8004(projectRoot, data, networkOverride) {
|
|
|
17071
17312
|
if (!process.env.WALLET_PASSWORD) {
|
|
17072
17313
|
return [];
|
|
17073
17314
|
}
|
|
17074
|
-
const walletCfg =
|
|
17315
|
+
const walletCfg = tableOf14(data, "wallet");
|
|
17075
17316
|
if (!isLocalEvmWallet(walletCfg)) {
|
|
17076
17317
|
return [];
|
|
17077
17318
|
}
|
|
@@ -17080,7 +17321,7 @@ async function check8004(projectRoot, data, networkOverride) {
|
|
|
17080
17321
|
return [];
|
|
17081
17322
|
}
|
|
17082
17323
|
const network = String(
|
|
17083
|
-
networkOverride ||
|
|
17324
|
+
networkOverride || tableOf14(data, "network").default || "bsc-testnet"
|
|
17084
17325
|
);
|
|
17085
17326
|
try {
|
|
17086
17327
|
const wallet = walletRt5.getWallet();
|
|
@@ -17113,11 +17354,11 @@ async function check8004(projectRoot, data, networkOverride) {
|
|
|
17113
17354
|
}
|
|
17114
17355
|
}
|
|
17115
17356
|
function platformPackagingRequiresContainer(data) {
|
|
17116
|
-
const walletKind2 = String(
|
|
17357
|
+
const walletKind2 = String(tableOf14(data, "wallet").kind ?? "evm-local").trim().toLowerCase();
|
|
17117
17358
|
if (walletKind2 === "twak") {
|
|
17118
17359
|
return true;
|
|
17119
17360
|
}
|
|
17120
|
-
const deployCfg =
|
|
17361
|
+
const deployCfg = tableOf14(data, "deploy");
|
|
17121
17362
|
let platformArtifact2 = String(deployCfg.platform_artifact ?? "").trim().toLowerCase();
|
|
17122
17363
|
if (!platformArtifact2) {
|
|
17123
17364
|
const packaging = String(deployCfg.packaging ?? "").trim().toLowerCase();
|
|
@@ -17153,7 +17394,7 @@ async function checkDeployTools(data, destination) {
|
|
|
17153
17394
|
detail: "[deploy].platform_artifact='zip' uses the managed platform's ZIP runtime; local Docker is not required."
|
|
17154
17395
|
});
|
|
17155
17396
|
}
|
|
17156
|
-
const walletKind2 = String(
|
|
17397
|
+
const walletKind2 = String(tableOf14(data, "wallet").kind ?? "").trim().toLowerCase();
|
|
17157
17398
|
if (walletKind2 === "twak") {
|
|
17158
17399
|
out.push(emit2(await checkTwak()));
|
|
17159
17400
|
} else {
|
|
@@ -17437,7 +17678,7 @@ function registerErc8004(program) {
|
|
|
17437
17678
|
)
|
|
17438
17679
|
);
|
|
17439
17680
|
}
|
|
17440
|
-
function
|
|
17681
|
+
function tableOf15(cfg, key) {
|
|
17441
17682
|
const v = cfg[key];
|
|
17442
17683
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
17443
17684
|
}
|
|
@@ -17460,7 +17701,7 @@ function resolveNetwork2(override) {
|
|
|
17460
17701
|
return override;
|
|
17461
17702
|
}
|
|
17462
17703
|
const cfg = loadAgentCfg3();
|
|
17463
|
-
const net2 = cfg === null ? void 0 :
|
|
17704
|
+
const net2 = cfg === null ? void 0 : tableOf15(cfg, "network").default;
|
|
17464
17705
|
return net2 ? String(net2) : "bsc-testnet";
|
|
17465
17706
|
}
|
|
17466
17707
|
function resolveProtocol(override) {
|
|
@@ -17471,7 +17712,7 @@ function resolveProtocol(override) {
|
|
|
17471
17712
|
if (cfg === null) {
|
|
17472
17713
|
return "A2A";
|
|
17473
17714
|
}
|
|
17474
|
-
const faces = stackFaces(
|
|
17715
|
+
const faces = stackFaces(tableOf15(cfg, "stack"), tableOf15(cfg, "payments"));
|
|
17475
17716
|
if (faces.length === 1 && hasX402Face(faces)) {
|
|
17476
17717
|
printErr(
|
|
17477
17718
|
"warning: this X402-only project has no public ERC-8004 protocol face; A2A is only the internal AgentCore protocol declaration."
|
|
@@ -17481,13 +17722,13 @@ function resolveProtocol(override) {
|
|
|
17481
17722
|
}
|
|
17482
17723
|
function recordedEndpoint2() {
|
|
17483
17724
|
const cfg = loadAgentCfg3();
|
|
17484
|
-
const endpoint = cfg === null ? void 0 :
|
|
17725
|
+
const endpoint = cfg === null ? void 0 : tableOf15(cfg, "identity").endpoint;
|
|
17485
17726
|
return endpoint ? String(endpoint) : null;
|
|
17486
17727
|
}
|
|
17487
17728
|
var REGISTER_MIN_BNB = 2e-3;
|
|
17488
17729
|
function walletSelfPaysGas() {
|
|
17489
17730
|
const cfg = loadAgentCfg3();
|
|
17490
|
-
if (cfg !== null &&
|
|
17731
|
+
if (cfg !== null && tableOf15(cfg, "wallet").gasless) {
|
|
17491
17732
|
return false;
|
|
17492
17733
|
}
|
|
17493
17734
|
return true;
|
|
@@ -17527,7 +17768,7 @@ function syncAgentRegistry(agentId, op) {
|
|
|
17527
17768
|
function loadIdentityBlock(agentRoot2) {
|
|
17528
17769
|
try {
|
|
17529
17770
|
return {
|
|
17530
|
-
...
|
|
17771
|
+
...tableOf15(
|
|
17531
17772
|
loadStudioToml22(path40.join(agentRoot2, "studio.toml")),
|
|
17532
17773
|
"identity"
|
|
17533
17774
|
)
|
|
@@ -17630,7 +17871,7 @@ function printPartialRegister(exc) {
|
|
|
17630
17871
|
}
|
|
17631
17872
|
async function cmdRegister2(opts) {
|
|
17632
17873
|
const cfg = loadAgentCfg3();
|
|
17633
|
-
const destination = cfg === null ? "" : String(
|
|
17874
|
+
const destination = cfg === null ? "" : String(tableOf15(cfg, "deploy").destination ?? "").trim().toLowerCase();
|
|
17634
17875
|
if (destination === "platform") {
|
|
17635
17876
|
printErr(
|
|
17636
17877
|
"error: this is a platform-destination project \u2014 ERC-8004 registration is relayed GASLESSLY by the BNB Chain operator, not broadcast from your local wallet.\n Use: bag deploy verify --endpoint <your-invoke-url>\n(`bag erc8004 register` always self-pays gas from the local wallet, which fails on the zero-balance throwaway wallet the trial uses.)"
|
|
@@ -17934,7 +18175,12 @@ function registerErc8183(program) {
|
|
|
17934
18175
|
"--agent-id <id>",
|
|
17935
18176
|
"ERC-8004 agent_id (resolves provider + negotiates).",
|
|
17936
18177
|
(v) => Number.parseInt(v, 10)
|
|
17937
|
-
).argument("[task]", "Task description (or use --task).").option("--task <text>", "Task description (alternative to positional).").
|
|
18178
|
+
).argument("[task]", "Task description (or use --task).").option("--task <text>", "Task description (alternative to positional).").addOption(
|
|
18179
|
+
new Option6(
|
|
18180
|
+
"--quote-json <json|path>",
|
|
18181
|
+
"A seller's signed quote envelope (the negotiate response JSON, inline or a file path) to anchor on-chain. Use with --provider for sellers whose negotiate step ran out-of-band (e.g. an OAuth-gated AgentCore seller)."
|
|
18182
|
+
).conflicts("agentId")
|
|
18183
|
+
).option(
|
|
17938
18184
|
"--budget-u <amount>",
|
|
17939
18185
|
"Max U to spend (default: negotiated or policy)."
|
|
17940
18186
|
).option(
|
|
@@ -18061,6 +18307,35 @@ async function cmdList3(opts) {
|
|
|
18061
18307
|
}
|
|
18062
18308
|
return 0;
|
|
18063
18309
|
}
|
|
18310
|
+
function parseQuoteEnvelope(raw) {
|
|
18311
|
+
const trimmed = raw.trim();
|
|
18312
|
+
let text2 = trimmed;
|
|
18313
|
+
if (!trimmed.startsWith("{")) {
|
|
18314
|
+
try {
|
|
18315
|
+
text2 = fs40.readFileSync(trimmed, "utf-8");
|
|
18316
|
+
} catch (exc) {
|
|
18317
|
+
throw new Error(
|
|
18318
|
+
`--quote-json is neither inline JSON nor a readable file: ${errMsg5(exc)}`
|
|
18319
|
+
);
|
|
18320
|
+
}
|
|
18321
|
+
}
|
|
18322
|
+
let parsed;
|
|
18323
|
+
try {
|
|
18324
|
+
parsed = JSON.parse(text2);
|
|
18325
|
+
} catch (exc) {
|
|
18326
|
+
throw new Error(`--quote-json is not valid JSON: ${errMsg5(exc)}`);
|
|
18327
|
+
}
|
|
18328
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
18329
|
+
throw new Error("--quote-json must decode to a JSON object.");
|
|
18330
|
+
}
|
|
18331
|
+
const envelope = parsed;
|
|
18332
|
+
if (!envelope.negotiation_hash || !envelope.provider_sig) {
|
|
18333
|
+
throw new Error(
|
|
18334
|
+
"--quote-json is not a signed quote envelope: it must carry `negotiation_hash` and `provider_sig` (the seller's negotiate response). Re-run the negotiate step and pass its full response body."
|
|
18335
|
+
);
|
|
18336
|
+
}
|
|
18337
|
+
return envelope;
|
|
18338
|
+
}
|
|
18064
18339
|
async function cmdBuy(taskPositional, opts) {
|
|
18065
18340
|
const rc = applyProjectRoot2(opts.projectRoot);
|
|
18066
18341
|
if (rc !== null) {
|
|
@@ -18070,6 +18345,15 @@ async function cmdBuy(taskPositional, opts) {
|
|
|
18070
18345
|
printErr("error: one of --provider / --agent-id is required");
|
|
18071
18346
|
return 2;
|
|
18072
18347
|
}
|
|
18348
|
+
let negotiationEnvelope = null;
|
|
18349
|
+
if (opts.quoteJson !== void 0) {
|
|
18350
|
+
try {
|
|
18351
|
+
negotiationEnvelope = parseQuoteEnvelope(opts.quoteJson);
|
|
18352
|
+
} catch (exc) {
|
|
18353
|
+
printErr(`error: ${errMsg5(exc)}`);
|
|
18354
|
+
return 2;
|
|
18355
|
+
}
|
|
18356
|
+
}
|
|
18073
18357
|
if (taskPositional !== void 0 && opts.task !== void 0) {
|
|
18074
18358
|
printErr(
|
|
18075
18359
|
"error: pass the task once (either positional or --task, not both)"
|
|
@@ -18077,19 +18361,20 @@ async function cmdBuy(taskPositional, opts) {
|
|
|
18077
18361
|
return 2;
|
|
18078
18362
|
}
|
|
18079
18363
|
const task = taskPositional ?? opts.task;
|
|
18080
|
-
if (task === void 0) {
|
|
18081
|
-
printErr("error: task is required");
|
|
18364
|
+
if (task === void 0 && negotiationEnvelope === null) {
|
|
18365
|
+
printErr("error: task is required (or pass --quote-json)");
|
|
18082
18366
|
return 2;
|
|
18083
18367
|
}
|
|
18084
18368
|
let r;
|
|
18085
18369
|
try {
|
|
18086
|
-
r = await buyWorkflow(opts.provider ?? null, task, {
|
|
18370
|
+
r = await buyWorkflow(opts.provider ?? null, task ?? "", {
|
|
18087
18371
|
agentId: opts.agentId ?? null,
|
|
18088
18372
|
budgetU: opts.budgetU ?? null,
|
|
18089
18373
|
deadlineMinutes: opts.deadlineMin,
|
|
18090
18374
|
network: opts.network ?? null,
|
|
18091
18375
|
negotiate: opts.negotiate,
|
|
18092
|
-
protocol: opts.protocol
|
|
18376
|
+
protocol: opts.protocol,
|
|
18377
|
+
negotiationEnvelope
|
|
18093
18378
|
});
|
|
18094
18379
|
} catch (exc) {
|
|
18095
18380
|
printErr(`error: ${errMsg5(exc)}`);
|
|
@@ -19328,6 +19613,9 @@ function registerX402(program) {
|
|
|
19328
19613
|
).option("--method <verb>", "HTTP verb to send (default: GET).", "GET").option(
|
|
19329
19614
|
"--json <body>",
|
|
19330
19615
|
"JSON body to send with the request (a string parsed as JSON)."
|
|
19616
|
+
).option(
|
|
19617
|
+
"--local-dev",
|
|
19618
|
+
"DEV ONLY: skip the host allowlist for a localhost/127.0.0.1 target."
|
|
19331
19619
|
).action(
|
|
19332
19620
|
act(
|
|
19333
19621
|
(url, opts) => cmdQuote(url, opts)
|
|
@@ -19343,6 +19631,9 @@ function registerX402(program) {
|
|
|
19343
19631
|
).option("--method <verb>", "HTTP verb to send (default: GET).", "GET").option(
|
|
19344
19632
|
"--json <body>",
|
|
19345
19633
|
"JSON body to send with the request (a string parsed as JSON)."
|
|
19634
|
+
).option(
|
|
19635
|
+
"--local-dev",
|
|
19636
|
+
"DEV ONLY: for a localhost/127.0.0.1 target, skip the host allowlist and accept the challenge's payTo as the recipient (printed loudly)."
|
|
19346
19637
|
).action(
|
|
19347
19638
|
act(
|
|
19348
19639
|
(url, opts) => cmdBuy2(url, opts)
|
|
@@ -19394,6 +19685,23 @@ function hostOf(url) {
|
|
|
19394
19685
|
return "";
|
|
19395
19686
|
}
|
|
19396
19687
|
}
|
|
19688
|
+
function isLoopbackHost(host) {
|
|
19689
|
+
const h = host.toLowerCase().replace(/^\[|\]$/g, "");
|
|
19690
|
+
return h === "localhost" || h === "127.0.0.1" || h === "::1";
|
|
19691
|
+
}
|
|
19692
|
+
function printLocalDevHint(url) {
|
|
19693
|
+
printErr("hint: local dev seller detected. One command sets up everything:");
|
|
19694
|
+
printErr(` bag x402 trust ${url.split("?")[0]}`);
|
|
19695
|
+
printErr(
|
|
19696
|
+
" (adds the host to the allowlist AND pins the seller's payTo as the trusted recipient)"
|
|
19697
|
+
);
|
|
19698
|
+
printErr(
|
|
19699
|
+
"Or configure both by hand in studio.toml [payments.x402]: add the host to allowed_hosts and set expected_recipient."
|
|
19700
|
+
);
|
|
19701
|
+
printErr(
|
|
19702
|
+
"For a throwaway check you can also pass --local-dev to `bag x402 buy`/`quote` (loopback targets only)."
|
|
19703
|
+
);
|
|
19704
|
+
}
|
|
19397
19705
|
function checkHostAllowed(url, allowedHosts) {
|
|
19398
19706
|
const host = hostOf(url);
|
|
19399
19707
|
const allowedLower = new Set(
|
|
@@ -19401,7 +19709,7 @@ function checkHostAllowed(url, allowedHosts) {
|
|
|
19401
19709
|
);
|
|
19402
19710
|
return allowedLower.has(host);
|
|
19403
19711
|
}
|
|
19404
|
-
function
|
|
19712
|
+
function tableOf16(cfg, key) {
|
|
19405
19713
|
const v = cfg[key];
|
|
19406
19714
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
19407
19715
|
}
|
|
@@ -19440,7 +19748,7 @@ function resolveNetwork3(cfg, override) {
|
|
|
19440
19748
|
if (override) {
|
|
19441
19749
|
return override;
|
|
19442
19750
|
}
|
|
19443
|
-
const net2 =
|
|
19751
|
+
const net2 = tableOf16(cfg, "network").default;
|
|
19444
19752
|
return net2 ? String(net2) : "bsc-mainnet";
|
|
19445
19753
|
}
|
|
19446
19754
|
function parseJsonBody(raw) {
|
|
@@ -19466,8 +19774,11 @@ function resolveWallet2() {
|
|
|
19466
19774
|
return null;
|
|
19467
19775
|
}
|
|
19468
19776
|
}
|
|
19469
|
-
function printScopeError(host) {
|
|
19777
|
+
function printScopeError(host, url) {
|
|
19470
19778
|
printErr(`error: ${SCOPE_NOTE.replace("{host}", host)}`);
|
|
19779
|
+
if (url !== void 0 && isLoopbackHost(host)) {
|
|
19780
|
+
printLocalDevHint(url);
|
|
19781
|
+
}
|
|
19471
19782
|
}
|
|
19472
19783
|
async function cmdSellInit(priceFlag) {
|
|
19473
19784
|
const loaded = loadSellerConfig();
|
|
@@ -19484,7 +19795,7 @@ async function cmdSellInit(priceFlag) {
|
|
|
19484
19795
|
return 2;
|
|
19485
19796
|
}
|
|
19486
19797
|
const free = x402SellerPricingState({ price_usd: priceUsd }).kind === "free";
|
|
19487
|
-
const walletKind2 = String(
|
|
19798
|
+
const walletKind2 = String(tableOf16(cfg, "wallet").kind ?? "evm-local");
|
|
19488
19799
|
if (!free && !["evm-local", "twak"].includes(walletKind2)) {
|
|
19489
19800
|
printErr(
|
|
19490
19801
|
`error: the b402 seller rail supports wallet.kind evm-local or twak only; '${walletKind2}' cannot act as the b402 payout wallet.`
|
|
@@ -19644,8 +19955,12 @@ async function cmdQuote(url, opts) {
|
|
|
19644
19955
|
printErr(`error: ${errMsg6(exc)}`);
|
|
19645
19956
|
return 2;
|
|
19646
19957
|
}
|
|
19647
|
-
if (!
|
|
19648
|
-
|
|
19958
|
+
if (opts.localDev && !isLoopbackHost(hostOf(url))) {
|
|
19959
|
+
printErr("error: --local-dev applies to localhost/127.0.0.1 targets only.");
|
|
19960
|
+
return 2;
|
|
19961
|
+
}
|
|
19962
|
+
if (!opts.localDev && !checkHostAllowed(url, hosts)) {
|
|
19963
|
+
printScopeError(hostOf(url) || url, url);
|
|
19649
19964
|
return 1;
|
|
19650
19965
|
}
|
|
19651
19966
|
let body;
|
|
@@ -19653,7 +19968,7 @@ async function cmdQuote(url, opts) {
|
|
|
19653
19968
|
body = await quoteUrl(url, {
|
|
19654
19969
|
method: opts.method,
|
|
19655
19970
|
jsonBody,
|
|
19656
|
-
allowedHosts: hosts
|
|
19971
|
+
allowedHosts: opts.localDev ? null : hosts
|
|
19657
19972
|
});
|
|
19658
19973
|
} catch (exc) {
|
|
19659
19974
|
printX402Error(exc);
|
|
@@ -19687,8 +20002,12 @@ async function cmdBuy2(url, opts) {
|
|
|
19687
20002
|
return 1;
|
|
19688
20003
|
}
|
|
19689
20004
|
const [, cfg, hosts] = loaded;
|
|
19690
|
-
if (!
|
|
19691
|
-
|
|
20005
|
+
if (opts.localDev && !isLoopbackHost(hostOf(url))) {
|
|
20006
|
+
printErr("error: --local-dev applies to localhost/127.0.0.1 targets only.");
|
|
20007
|
+
return 2;
|
|
20008
|
+
}
|
|
20009
|
+
if (!opts.localDev && !checkHostAllowed(url, hosts)) {
|
|
20010
|
+
printScopeError(hostOf(url) || url, url);
|
|
19692
20011
|
return 1;
|
|
19693
20012
|
}
|
|
19694
20013
|
let jsonBody;
|
|
@@ -19699,6 +20018,24 @@ async function cmdBuy2(url, opts) {
|
|
|
19699
20018
|
return 2;
|
|
19700
20019
|
}
|
|
19701
20020
|
const networkName = resolveNetwork3(cfg, opts.network);
|
|
20021
|
+
let localDevExpectedTo = null;
|
|
20022
|
+
if (opts.localDev) {
|
|
20023
|
+
let challenge;
|
|
20024
|
+
try {
|
|
20025
|
+
challenge = await quoteUrl(url, { method: opts.method, jsonBody });
|
|
20026
|
+
} catch (exc) {
|
|
20027
|
+
printX402Error(exc);
|
|
20028
|
+
return 1;
|
|
20029
|
+
}
|
|
20030
|
+
const selected2 = selectPayable(challenge, networkName);
|
|
20031
|
+
if (selected2 === null) {
|
|
20032
|
+
return 1;
|
|
20033
|
+
}
|
|
20034
|
+
localDevExpectedTo = String(selected2[0].payTo);
|
|
20035
|
+
printOut(
|
|
20036
|
+
`\u26A0 DEV-ONLY --local-dev: accepting the challenge's payTo ${localDevExpectedTo} as the recipient without a configured pin. Never use this outside your own machine.`
|
|
20037
|
+
);
|
|
20038
|
+
}
|
|
19702
20039
|
const wallet = resolveWallet2();
|
|
19703
20040
|
if (wallet === null) {
|
|
19704
20041
|
return 1;
|
|
@@ -19743,7 +20080,8 @@ async function cmdBuy2(url, opts) {
|
|
|
19743
20080
|
networkName,
|
|
19744
20081
|
method: opts.method,
|
|
19745
20082
|
jsonBody,
|
|
19746
|
-
allowedHosts: hosts
|
|
20083
|
+
allowedHosts: opts.localDev ? null : hosts,
|
|
20084
|
+
expectedTo: localDevExpectedTo
|
|
19747
20085
|
});
|
|
19748
20086
|
if (r.paidUsd !== null) {
|
|
19749
20087
|
h.extraContext.paid_usd = r.paidUsd;
|
|
@@ -19756,6 +20094,9 @@ async function cmdBuy2(url, opts) {
|
|
|
19756
20094
|
);
|
|
19757
20095
|
} catch (exc) {
|
|
19758
20096
|
printX402Error(exc);
|
|
20097
|
+
if (errName4(exc) === "X402RecipientRequiredError" && isLoopbackHost(hostOf(url))) {
|
|
20098
|
+
printLocalDevHint(url);
|
|
20099
|
+
}
|
|
19759
20100
|
return 1;
|
|
19760
20101
|
}
|
|
19761
20102
|
const paidUsd = result.paidUsd ?? 0;
|
|
@@ -19869,10 +20210,19 @@ async function cmdTrust(merchant, opts) {
|
|
|
19869
20210
|
if (merchant.includes("://")) {
|
|
19870
20211
|
probeUrl = merchant;
|
|
19871
20212
|
host = hostOf(probeUrl);
|
|
19872
|
-
|
|
19873
|
-
|
|
20213
|
+
const plainHttp = probeUrl.toLowerCase().startsWith("http://");
|
|
20214
|
+
const localDevHttp = plainHttp && isLoopbackHost(host);
|
|
20215
|
+
if (!probeUrl.toLowerCase().startsWith("https://") && !localDevHttp || !host) {
|
|
20216
|
+
printErr(
|
|
20217
|
+
"error: trust-by-URL needs an absolute https:// URL (plain http:// is allowed only for localhost/127.0.0.1 dev sellers)."
|
|
20218
|
+
);
|
|
19874
20219
|
return 1;
|
|
19875
20220
|
}
|
|
20221
|
+
if (localDevHttp) {
|
|
20222
|
+
printOut(
|
|
20223
|
+
"\u26A0 DEV-ONLY: trusting a plain-http loopback seller. http:// carries no transport integrity \u2014 never trust it beyond your own machine."
|
|
20224
|
+
);
|
|
20225
|
+
}
|
|
19876
20226
|
methodHint = null;
|
|
19877
20227
|
} else {
|
|
19878
20228
|
rec = RECOMMENDED_MERCHANTS[merchant.toLowerCase()] ?? null;
|
|
@@ -19952,7 +20302,7 @@ The merchant may have rotated its address (or the response was tampered with). U
|
|
|
19952
20302
|
" \u26A0 MAINNET: calls spend real $U from the agent wallet. The cap above and [budget].max_per_day_usd bound the exposure."
|
|
19953
20303
|
);
|
|
19954
20304
|
}
|
|
19955
|
-
const projectDefault =
|
|
20305
|
+
const projectDefault = tableOf16(cfg, "network").default;
|
|
19956
20306
|
if (projectDefault && String(projectDefault) !== networkName) {
|
|
19957
20307
|
printOut(
|
|
19958
20308
|
` note: your project default is ${projectDefault}; this paid capability settles on ${networkName} independently of it.`
|
|
@@ -20033,7 +20383,7 @@ function buildProgram() {
|
|
|
20033
20383
|
return program;
|
|
20034
20384
|
}
|
|
20035
20385
|
function cliVersion() {
|
|
20036
|
-
return "0.0.6-alpha.
|
|
20386
|
+
return "0.0.6-alpha.7";
|
|
20037
20387
|
}
|
|
20038
20388
|
|
|
20039
20389
|
// src/cli/updateCheck.ts
|