@bnbagent/studio-cli 0.0.12-alpha.6 → 0.0.12
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/README.md +2 -2
- package/dist/_agentcoreName-DZDWEYD3.js +0 -0
- package/dist/_twak-4XF4H5PL.js +0 -0
- package/dist/bag.js +49 -462
- package/dist/{chunk-JONVYGUR.js → chunk-RNWAADXU.js} +7 -77
- package/dist/chunk-RO726HJG.js +0 -0
- package/dist/chunk-U7IDQ3K5.js +0 -0
- package/dist/{deployCli-6T6OMOIZ.js → deployCli-RWRR6XWO.js} +1 -1
- package/package.json +13 -12
- 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/wallet/recipe.toml +2 -7
- package/recipes/x402-buyer/recipe.toml +1 -1
- package/skills/bnbagent-studio.md +1 -1
- package/skills/references/bnbagent-studio-buying-from-bazaar.md +1 -4
- package/skills/references/bnbagent-studio-extending-signing.md +1 -1
- package/skills/references/bnbagent-studio-operating.md +1 -1
- package/skills/references/bnbagent-studio-scaffolding-agent.md +1 -1
- package/skills/references/bnbagent-studio-selling-via-b402.md +2 -3
- package/skills/references/bnbagent-studio-using-altana-wallet.md +1 -3
- package/LICENSE +0 -201
package/dist/bag.js
CHANGED
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
x402SellerIsFree,
|
|
53
53
|
x402SellerPricingState,
|
|
54
54
|
x402SellerUsesB402
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-RNWAADXU.js";
|
|
56
56
|
import {
|
|
57
57
|
TWAK_CLI_MIN_VERSION,
|
|
58
58
|
TWAK_CLI_VERSION,
|
|
@@ -230,7 +230,7 @@ import {
|
|
|
230
230
|
var CAMPAIGN_DOC_URL = "https://www.bnbchain.org/en/blog/bnb-agent-studio-is-live-on-bnb-chain-ai-agents-from-one-prompt";
|
|
231
231
|
var CAMPAIGN_CHECK_TIMEOUT_MS = 6e3;
|
|
232
232
|
async function fetchCampaignActive() {
|
|
233
|
-
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-
|
|
233
|
+
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-RWRR6XWO.js");
|
|
234
234
|
const controller = new AbortController();
|
|
235
235
|
const timer = setTimeout(() => controller.abort(), CAMPAIGN_CHECK_TIMEOUT_MS);
|
|
236
236
|
try {
|
|
@@ -2823,19 +2823,6 @@ var ERC20_BALANCE_ABI = [
|
|
|
2823
2823
|
outputs: [{ name: "", type: "uint256" }]
|
|
2824
2824
|
}
|
|
2825
2825
|
];
|
|
2826
|
-
var ERC20_ALLOWANCE_ABI = [
|
|
2827
|
-
{
|
|
2828
|
-
type: "function",
|
|
2829
|
-
name: "allowance",
|
|
2830
|
-
stateMutability: "view",
|
|
2831
|
-
inputs: [
|
|
2832
|
-
{ name: "owner", type: "address" },
|
|
2833
|
-
{ name: "spender", type: "address" }
|
|
2834
|
-
],
|
|
2835
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
2836
|
-
}
|
|
2837
|
-
];
|
|
2838
|
-
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
2839
2826
|
function client(networkName) {
|
|
2840
2827
|
const net2 = getNetwork(networkName);
|
|
2841
2828
|
return createPublicClient({ transport: http(net2.rpcUrl) });
|
|
@@ -2864,20 +2851,6 @@ async function readUBalanceRaw(address, networkName) {
|
|
|
2864
2851
|
});
|
|
2865
2852
|
return raw;
|
|
2866
2853
|
}
|
|
2867
|
-
async function readUAllowanceRaw(owner, spender, networkName) {
|
|
2868
|
-
const net2 = getNetwork(networkName);
|
|
2869
|
-
const uToken = net2.tokens.U;
|
|
2870
|
-
if (uToken === void 0) {
|
|
2871
|
-
return null;
|
|
2872
|
-
}
|
|
2873
|
-
const raw = await client(networkName).readContract({
|
|
2874
|
-
address: getAddress(uToken.address),
|
|
2875
|
-
abi: ERC20_ALLOWANCE_ABI,
|
|
2876
|
-
functionName: "allowance",
|
|
2877
|
-
args: [getAddress(owner), getAddress(spender)]
|
|
2878
|
-
});
|
|
2879
|
-
return raw;
|
|
2880
|
-
}
|
|
2881
2854
|
async function readTransactionSeen(txHash, networkName) {
|
|
2882
2855
|
try {
|
|
2883
2856
|
await client(networkName).getTransaction({
|
|
@@ -2964,7 +2937,7 @@ function canBuildWallet(root, data) {
|
|
|
2964
2937
|
const cfg = data ?? loadAgentToml(root);
|
|
2965
2938
|
const walletCfg = tableOf2(cfg, "wallet");
|
|
2966
2939
|
const kind = walletCfg.kind;
|
|
2967
|
-
if (kind === "twak" || kind === "altana"
|
|
2940
|
+
if (kind === "twak" || kind === "altana") {
|
|
2968
2941
|
return false;
|
|
2969
2942
|
}
|
|
2970
2943
|
if (!process.env.WALLET_PASSWORD) {
|
|
@@ -2982,7 +2955,7 @@ function canBuildWallet(root, data) {
|
|
|
2982
2955
|
function walletAddressForChecks(root, data) {
|
|
2983
2956
|
const cfg = data ?? loadAgentToml(root);
|
|
2984
2957
|
const walletCfg = tableOf2(cfg, "wallet");
|
|
2985
|
-
if (walletCfg.kind === "twak" || walletCfg.kind === "altana"
|
|
2958
|
+
if (walletCfg.kind === "twak" || walletCfg.kind === "altana") {
|
|
2986
2959
|
const addr = String(walletCfg.address ?? "").trim();
|
|
2987
2960
|
return addr || null;
|
|
2988
2961
|
}
|
|
@@ -3756,7 +3729,7 @@ function checkAltanaSdkResolvable(root, _target) {
|
|
|
3756
3729
|
level: Level.CRITICAL,
|
|
3757
3730
|
name: "altana_sdk_resolvable",
|
|
3758
3731
|
message: `@altananetwork/sdk is not resolvable from the agent project${failure ? ` (${failure})` : ""} \u2014 the deployed runtime cannot build the Altana session wallet at cold start.`,
|
|
3759
|
-
fixCmd: "pnpm add @altananetwork/sdk@0.
|
|
3732
|
+
fixCmd: "pnpm add @altananetwork/sdk@0.5.1",
|
|
3760
3733
|
details: failure ? { error: failure } : {}
|
|
3761
3734
|
}
|
|
3762
3735
|
];
|
|
@@ -4735,28 +4708,6 @@ var managedAzureFoundryChecks = [
|
|
|
4735
4708
|
checkAltanaSessionNotInsideAgent
|
|
4736
4709
|
];
|
|
4737
4710
|
|
|
4738
|
-
// src/cli/_turnkeyGuidance.ts
|
|
4739
|
-
function turnkeySetupGuidance() {
|
|
4740
|
-
return `
|
|
4741
|
-
Turnkey setup (official CLI: https://docs.turnkey.com/sdks/cli):
|
|
4742
|
-
1. In the dashboard's top-right user menu, copy the Organization ID into
|
|
4743
|
-
TURNKEY_ORG_ID.
|
|
4744
|
-
2. Generate a P-256 API key locally, then register its public key under
|
|
4745
|
-
User Details -> Create API keys:
|
|
4746
|
-
turnkey generate api-key --organization "$TURNKEY_ORG_ID" --key-name bnbagent-studio
|
|
4747
|
-
Set TURNKEY_API_PUBLIC_KEY to the generated public key and
|
|
4748
|
-
TURNKEY_API_PRIVATE_KEY to its locally generated private key. Keep the
|
|
4749
|
-
private key out of argv, logs, and source control.
|
|
4750
|
-
3. Create a wallet and an Ethereum account:
|
|
4751
|
-
turnkey wallets create --name bnbagent-studio --key-name bnbagent-studio
|
|
4752
|
-
turnkey wallets accounts create --wallet bnbagent-studio --address-format ADDRESS_FORMAT_ETHEREUM --key-name bnbagent-studio
|
|
4753
|
-
4. Set TURNKEY_SIGN_WITH to the returned 0x Ethereum account address. It is
|
|
4754
|
-
not a Turnkey wallet id (UUID).
|
|
4755
|
-
5. Store all four TURNKEY_* values in the owner-only .studio/.env.local,
|
|
4756
|
-
then run \`(cd app/agent && bag wallet new)\` to validate and anchor the
|
|
4757
|
-
address. No signing key is created or downloaded by bag.`;
|
|
4758
|
-
}
|
|
4759
|
-
|
|
4760
4711
|
// src/cli/llm.ts
|
|
4761
4712
|
import * as fs18 from "fs";
|
|
4762
4713
|
import * as path17 from "path";
|
|
@@ -6636,7 +6587,6 @@ import {
|
|
|
6636
6587
|
} from "@bnbagent/studio-runtime/config";
|
|
6637
6588
|
import { tbnbFaucetHint as tbnbFaucetHint2 } from "@bnbagent/studio-runtime/networks";
|
|
6638
6589
|
import { buildPolicy, buildWallet } from "@bnbagent/studio-runtime/wallet";
|
|
6639
|
-
import { getAddress as toChecksumAddress } from "viem";
|
|
6640
6590
|
|
|
6641
6591
|
// src/cli/walletSession.ts
|
|
6642
6592
|
import * as fs21 from "fs";
|
|
@@ -7368,9 +7318,6 @@ async function cmdNew(opts) {
|
|
|
7368
7318
|
if (kind === "twak") {
|
|
7369
7319
|
return cmdNewTwak(projectRoot, walletCfg);
|
|
7370
7320
|
}
|
|
7371
|
-
if (kind === "turnkey") {
|
|
7372
|
-
return cmdNewTurnkey(projectRoot);
|
|
7373
|
-
}
|
|
7374
7321
|
const privateKey = await resolvePrivateKeyArg(opts.privateKey);
|
|
7375
7322
|
const password = requireDurablePassword(projectRoot);
|
|
7376
7323
|
const keystoreDir = resolveKeystoreDir2(
|
|
@@ -7434,28 +7381,6 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
7434
7381
|
printNextAfterNew(projectRoot, address);
|
|
7435
7382
|
return 0;
|
|
7436
7383
|
}
|
|
7437
|
-
function cmdNewTurnkey(projectRoot) {
|
|
7438
|
-
const signWith = String(process.env.TURNKEY_SIGN_WITH ?? "").trim();
|
|
7439
|
-
if (signWith === "") {
|
|
7440
|
-
printErr(
|
|
7441
|
-
`error: TURNKEY_SIGN_WITH is not set (wallet.kind = 'turnkey').
|
|
7442
|
-
${turnkeySetupGuidance()}`
|
|
7443
|
-
);
|
|
7444
|
-
return 1;
|
|
7445
|
-
}
|
|
7446
|
-
let address;
|
|
7447
|
-
try {
|
|
7448
|
-
address = toChecksumAddress(signWith);
|
|
7449
|
-
} catch {
|
|
7450
|
-
printErr(
|
|
7451
|
-
`error: TURNKEY_SIGN_WITH must be the wallet account's Ethereum address (0x + 40 hex chars), not a Turnkey wallet id \u2014 copy it from the dashboard wallet-account view. Got: '${signWith}'`
|
|
7452
|
-
);
|
|
7453
|
-
return 1;
|
|
7454
|
-
}
|
|
7455
|
-
printOut(address);
|
|
7456
|
-
persistAddress(projectRoot, address);
|
|
7457
|
-
return 0;
|
|
7458
|
-
}
|
|
7459
7384
|
function ensureTwakCredentials(walletFile, homeDir) {
|
|
7460
7385
|
const twakDir = path21.dirname(walletFile);
|
|
7461
7386
|
const target = path21.join(twakDir, "credentials.json");
|
|
@@ -7633,33 +7558,6 @@ function cmdShow5(projectRootArg2) {
|
|
|
7633
7558
|
);
|
|
7634
7559
|
return 0;
|
|
7635
7560
|
}
|
|
7636
|
-
if (kind === "turnkey") {
|
|
7637
|
-
const anchored = String(walletCfg.address ?? "").trim();
|
|
7638
|
-
const signWith = String(process.env.TURNKEY_SIGN_WITH ?? "").trim();
|
|
7639
|
-
const address2 = anchored || signWith;
|
|
7640
|
-
if (!address2) {
|
|
7641
|
-
throw new Error(
|
|
7642
|
-
"cannot resolve the Turnkey wallet address: no [wallet].address is anchored in studio.toml and TURNKEY_SIGN_WITH is not set \u2014 fill .studio/.env.local, then run `bag wallet new`."
|
|
7643
|
-
);
|
|
7644
|
-
}
|
|
7645
|
-
const requiredEnv = [
|
|
7646
|
-
"TURNKEY_API_PUBLIC_KEY",
|
|
7647
|
-
"TURNKEY_API_PRIVATE_KEY",
|
|
7648
|
-
"TURNKEY_ORG_ID",
|
|
7649
|
-
"TURNKEY_SIGN_WITH"
|
|
7650
|
-
];
|
|
7651
|
-
const present = requiredEnv.filter((key) => process.env[key]).length;
|
|
7652
|
-
const baseUrl = process.env.TURNKEY_API_BASE_URL || "https://api.turnkey.com";
|
|
7653
|
-
printOut(`address: ${address2}`);
|
|
7654
|
-
printOut("source: turnkey");
|
|
7655
|
-
printOut(
|
|
7656
|
-
`key_location: remote:turnkey (${baseUrl}; key held in AWS Nitro enclave, never leaves)`
|
|
7657
|
-
);
|
|
7658
|
-
printOut(
|
|
7659
|
-
`credentials: ${present}/${requiredEnv.length} TURNKEY_* env vars set`
|
|
7660
|
-
);
|
|
7661
|
-
return 0;
|
|
7662
|
-
}
|
|
7663
7561
|
const password = requirePassword2();
|
|
7664
7562
|
const keystoreDir = resolveKeystoreDir2(projectRoot, null, walletCfg);
|
|
7665
7563
|
const provider = new EVMWalletProvider({
|
|
@@ -7752,14 +7650,7 @@ async function cmdSign(msg, projectRootArg2) {
|
|
|
7752
7650
|
);
|
|
7753
7651
|
}
|
|
7754
7652
|
let provider;
|
|
7755
|
-
if (kind === "
|
|
7756
|
-
printErr(
|
|
7757
|
-
"note: Turnkey signatures are billed (free tier 25/month at 1 req/s; pay-as-you-go $0.10 each)."
|
|
7758
|
-
);
|
|
7759
|
-
provider = buildWallet(walletCfg, projectRoot, {
|
|
7760
|
-
network: projectNetwork(projectRoot)
|
|
7761
|
-
});
|
|
7762
|
-
} else if (kind === "twak") {
|
|
7653
|
+
if (kind === "twak") {
|
|
7763
7654
|
provider = twakProvider(projectRoot, walletCfg);
|
|
7764
7655
|
} else {
|
|
7765
7656
|
const password = requirePassword2();
|
|
@@ -7784,10 +7675,10 @@ async function cmdBalance(opts) {
|
|
|
7784
7675
|
const walletCfg = data.wallet !== null && typeof data.wallet === "object" ? data.wallet : {};
|
|
7785
7676
|
let address;
|
|
7786
7677
|
const kind = walletKind(walletCfg);
|
|
7787
|
-
if (kind === "twak" || kind === "altana"
|
|
7678
|
+
if (kind === "twak" || kind === "altana") {
|
|
7788
7679
|
address = String(walletCfg.address ?? "").trim();
|
|
7789
7680
|
if (!address) {
|
|
7790
|
-
const nextStep = kind === "twak" ? "(adopts the twak wallet's address) first." :
|
|
7681
|
+
const nextStep = kind === "twak" ? "(adopts the twak wallet's address) first." : "to create the Altana admin keystore first.";
|
|
7791
7682
|
throw new Error(
|
|
7792
7683
|
`no [wallet].address anchored in studio.toml \u2014 run bag wallet new ${nextStep}`
|
|
7793
7684
|
);
|
|
@@ -8153,7 +8044,7 @@ function registerInit(program) {
|
|
|
8153
8044
|
).addOption(
|
|
8154
8045
|
new Option2(
|
|
8155
8046
|
"--rails <rails>",
|
|
8156
|
-
"Commerce rail(s) to scaffold: 8183, b402, or both (default)."
|
|
8047
|
+
"Commerce rail(s) to scaffold: 8183, b402, or both (default; Altana defaults to 8183)."
|
|
8157
8048
|
).choices(["8183", "b402", "both"])
|
|
8158
8049
|
).option(
|
|
8159
8050
|
"--erc8183-price <base-units>",
|
|
@@ -8177,8 +8068,8 @@ function registerInit(program) {
|
|
|
8177
8068
|
).addOption(
|
|
8178
8069
|
new Option2(
|
|
8179
8070
|
"--wallet-kind <kind>",
|
|
8180
|
-
"Wallet backend for the Agent (default: evm-local = encrypted local keystore at the workspace root .studio/wallets/; CodeZip deploy). altana \u2014 encrypted local admin keystore plus a bounded runtime session; deploys ship ONLY the session (ALTANA_SESSION secret). twak \u2014 FULLY SUPPORTED, opt in: Trust Wallet Agent Kit CLI, self-custody encrypted mnemonic in a PROJECT-DEDICATED home (.studio/twak); deploys as a container image.
|
|
8181
|
-
).choices(["twak", "evm-local", "altana"
|
|
8071
|
+
"Wallet backend for the Agent (default: evm-local = encrypted local keystore at the workspace root .studio/wallets/; CodeZip deploy). altana \u2014 encrypted local admin keystore plus a bounded runtime session; deploys ship ONLY the session (ALTANA_SESSION secret). twak \u2014 FULLY SUPPORTED, opt in: Trust Wallet Agent Kit CLI, self-custody encrypted mnemonic in a PROJECT-DEDICATED home (.studio/twak); deploys as a container image."
|
|
8072
|
+
).choices(["twak", "evm-local", "altana"])
|
|
8182
8073
|
).option(
|
|
8183
8074
|
"--twak-home <path>",
|
|
8184
8075
|
"twak only: point this project at an EXISTING twak wallet home (the HOME-STYLE PARENT dir that contains .twak/wallet.json \u2014 NOT the .twak dir itself; a .twak path holding a wallet is auto-corrected to its parent) instead of the dedicated .studio/twak. Written to [wallet].twak_home."
|
|
@@ -8346,7 +8237,7 @@ async function cmdInitFlow(nameArg, opts) {
|
|
|
8346
8237
|
if (llmProvider === null) {
|
|
8347
8238
|
return 2;
|
|
8348
8239
|
}
|
|
8349
|
-
const inferredRails = opts.rails ?? (facesExplicit ? hasX402Face(faces) ? "both" : "8183" : void 0);
|
|
8240
|
+
const inferredRails = opts.rails ?? (facesExplicit ? hasX402Face(faces) ? "both" : "8183" : walletKind2 === "altana" ? "8183" : void 0);
|
|
8350
8241
|
let rails = await resolveRails(inferredRails, isTty);
|
|
8351
8242
|
if (!facesExplicit) {
|
|
8352
8243
|
faces = normalizeProtocolFaces(
|
|
@@ -8490,10 +8381,10 @@ async function cmdInitFlow(nameArg, opts) {
|
|
|
8490
8381
|
return 1;
|
|
8491
8382
|
}
|
|
8492
8383
|
const budgetFlag = opts.enableAutoTopup ? "enable" : opts.autoTopup === false ? "disable" : null;
|
|
8493
|
-
const budgetChoice =
|
|
8494
|
-
if ((rails === "b402" || rails === "both") && x402SellerPricingState({ price_usd: b402Price }).kind === "paid" && !["evm-local", "twak"
|
|
8384
|
+
const budgetChoice = llmProvider === "pieverse-llm" || budgetFlag !== null ? await resolveBudgetChoice(budgetFlag) : null;
|
|
8385
|
+
if ((rails === "b402" || rails === "both") && x402SellerPricingState({ price_usd: b402Price }).kind === "paid" && !["evm-local", "twak"].includes(walletKind2)) {
|
|
8495
8386
|
printErr(
|
|
8496
|
-
`error: the b402 seller rail supports wallet.kind evm-local
|
|
8387
|
+
`error: the b402 seller rail supports wallet.kind evm-local or twak only; '${walletKind2}' cannot act as the b402 payout wallet. Re-run with --rails 8183 or a supported --wallet-kind.`
|
|
8497
8388
|
);
|
|
8498
8389
|
fs23.rmSync(target, { recursive: true, force: true });
|
|
8499
8390
|
return 2;
|
|
@@ -8590,8 +8481,6 @@ async function cmdInitFlow(nameArg, opts) {
|
|
|
8590
8481
|
}
|
|
8591
8482
|
} else if (walletKind2 === "altana") {
|
|
8592
8483
|
printAltanaNotice();
|
|
8593
|
-
} else if (walletKind2 === "turnkey") {
|
|
8594
|
-
printTurnkeyNotice();
|
|
8595
8484
|
} else {
|
|
8596
8485
|
printEvmLocalNotice(
|
|
8597
8486
|
derivePackaging(walletKind2, destination, platformArtifact2, runtime)
|
|
@@ -8828,9 +8717,6 @@ function computeAgentNodeDeps(runtime, provider, protocols = "A2A", walletKind2
|
|
|
8828
8717
|
if (walletKind2 === "altana") {
|
|
8829
8718
|
raw.push(...readRecipeNodeDeps("wallet", "altana"));
|
|
8830
8719
|
}
|
|
8831
|
-
if (walletKind2 === "turnkey") {
|
|
8832
|
-
raw.push(...readRecipeNodeDeps("wallet", "turnkey"));
|
|
8833
|
-
}
|
|
8834
8720
|
const out = {};
|
|
8835
8721
|
const core = splitDep(coreRequirement());
|
|
8836
8722
|
for (const dep of raw) {
|
|
@@ -9004,18 +8890,6 @@ kind = "altana"
|
|
|
9004
8890
|
keystore_dir = "../../.studio/wallets"
|
|
9005
8891
|
session_file = "../../.studio/wallets/altana-session.json"
|
|
9006
8892
|
# address = "0x..." # filled by \`bag wallet new\`; session must match it`;
|
|
9007
|
-
}
|
|
9008
|
-
if (walletKind2 === "turnkey") {
|
|
9009
|
-
return `[wallet]
|
|
9010
|
-
# Turnkey remote signer. The key is generated and held in Turnkey's AWS Nitro
|
|
9011
|
-
# enclave \u2014 no key material ever exists in this project or its deploys. The
|
|
9012
|
-
# Agent signs via the Turnkey API using the TURNKEY_* credentials in
|
|
9013
|
-
# .studio/.env.local. Billing: every successful signature is billed (free
|
|
9014
|
-
# tier: 25 signatures/month at 1 request/second; pay-as-you-go $0.10 each).
|
|
9015
|
-
# PRODUCTION: use a NON-ROOT API user restricted by an explicit ALLOW
|
|
9016
|
-
# policy \u2014 a root user's API key bypasses ALL Turnkey server-side policies.
|
|
9017
|
-
kind = "turnkey"
|
|
9018
|
-
# address = "0x..." # filled by \`bag wallet new\` (adopts TURNKEY_SIGN_WITH)`;
|
|
9019
8893
|
}
|
|
9020
8894
|
return `[wallet]
|
|
9021
8895
|
# Local keystore signer. The Agent is the SOLE key-holder/signer.
|
|
@@ -9141,7 +9015,7 @@ agent_endpoint = ""
|
|
|
9141
9015
|
function renderAgentStudioToml(name, o) {
|
|
9142
9016
|
const model = o.model ?? PROVIDER_DEFAULT_MODEL[o.provider] ?? "";
|
|
9143
9017
|
const pieverseSection = o.provider === "pieverse-llm" ? renderPieverseSections() : "";
|
|
9144
|
-
const x402Section = o.provider === "pieverse-llm" ? renderX402Section() : "";
|
|
9018
|
+
const x402Section = o.provider === "pieverse-llm" && o.budgetChoice === "enable" ? renderX402Section() : "";
|
|
9145
9019
|
const x402SellerSection = o.rails === "b402" || o.rails === "both" || hasX402Face(o.faces) ? renderX402SellerSection(o.b402Price) : "";
|
|
9146
9020
|
const budgetSection = renderBudgetSection(o.budgetChoice);
|
|
9147
9021
|
const storageSection = renderAgentStorageSection(o.storageProvider);
|
|
@@ -9214,23 +9088,6 @@ function renderAgentEnvLocal(provider, storageProvider, walletKind2, rails, b402
|
|
|
9214
9088
|
"# TWAK_ACCESS_ID=",
|
|
9215
9089
|
"# TWAK_HMAC_SECRET="
|
|
9216
9090
|
);
|
|
9217
|
-
} else if (walletKind2 === "turnkey") {
|
|
9218
|
-
lines.push(
|
|
9219
|
-
"",
|
|
9220
|
-
"# Turnkey API credentials (dashboard \u2192 API keys). The P-256 API key",
|
|
9221
|
-
"# pair authenticates this Agent to the enclave; the wallet's signing",
|
|
9222
|
-
"# key never leaves Turnkey. Use a NON-ROOT API user + explicit ALLOW",
|
|
9223
|
-
"# policy in production (root keys bypass all Turnkey policies).",
|
|
9224
|
-
"TURNKEY_API_PUBLIC_KEY=",
|
|
9225
|
-
"TURNKEY_API_PRIVATE_KEY=",
|
|
9226
|
-
"# Organization id (dashboard \u2192 settings):",
|
|
9227
|
-
"TURNKEY_ORG_ID=",
|
|
9228
|
-
"# Account to sign with \u2014 MUST be the 0x Ethereum ADDRESS itself, not",
|
|
9229
|
-
"# a Turnkey wallet id. `bag wallet new` anchors it into studio.toml.",
|
|
9230
|
-
"TURNKEY_SIGN_WITH=",
|
|
9231
|
-
"# Optional API host override (default https://api.turnkey.com):",
|
|
9232
|
-
"# TURNKEY_API_BASE_URL="
|
|
9233
|
-
);
|
|
9234
9091
|
} else if (walletKind2 === "evm-local" || walletKind2 === "altana") {
|
|
9235
9092
|
lines.push(
|
|
9236
9093
|
"",
|
|
@@ -9345,7 +9202,7 @@ entrypoint code in \`src/signing.ts\` \u2014 never an LLM-callable tool.
|
|
|
9345
9202
|
${mode === "both" ? filesBoth : mode === "mcp" ? filesMcp : filesA2a}
|
|
9346
9203
|
${shared}
|
|
9347
9204
|
- \`.env.local\` \u2014 Agent secrets; on deploy they are sent to the **operator's**
|
|
9348
|
-
Secrets Manager (the scoped, consented commitment-#2 exception). ${walletKind2 === "altana" ? "Only the\n bounded session ships (as `ALTANA_SESSION`); tighten it with\n `bag wallet session grant --force` \u2014 do not create a new wallet." :
|
|
9205
|
+
Secrets Manager (the scoped, consented commitment-#2 exception). ${walletKind2 === "altana" ? "Only the\n bounded session ships (as `ALTANA_SESSION`); tighten it with\n `bag wallet session grant --force` \u2014 do not create a new wallet." : "Use a\n THROWAWAY testnet wallet \u2014 `(cd app/agent && bag wallet new)`."}
|
|
9349
9206
|
|
|
9350
9207
|
## Run locally
|
|
9351
9208
|
|
|
@@ -9454,12 +9311,12 @@ function ensureCursorGitignore(gitignore) {
|
|
|
9454
9311
|
${addition}`);
|
|
9455
9312
|
}
|
|
9456
9313
|
async function resolveWalletKind(flagValue, isTty) {
|
|
9457
|
-
if (flagValue === "evm-local" || flagValue === "twak" || flagValue === "altana"
|
|
9314
|
+
if (flagValue === "evm-local" || flagValue === "twak" || flagValue === "altana") {
|
|
9458
9315
|
return flagValue;
|
|
9459
9316
|
}
|
|
9460
9317
|
if (!isTty) {
|
|
9461
9318
|
printErr(
|
|
9462
|
-
"info: wallet backend defaulting to 'evm-local' (non-interactive). To choose explicitly, re-run with --wallet-kind evm-local or --wallet-kind twak
|
|
9319
|
+
"info: wallet backend defaulting to 'evm-local' (non-interactive). To choose explicitly, re-run with --wallet-kind evm-local or --wallet-kind twak or --wallet-kind altana."
|
|
9463
9320
|
);
|
|
9464
9321
|
return "evm-local";
|
|
9465
9322
|
}
|
|
@@ -9471,15 +9328,11 @@ async function resolveWalletKind(flagValue, isTty) {
|
|
|
9471
9328
|
" 2. twak \u2014 Trust Wallet CLI wallet; forces container packaging for deploys"
|
|
9472
9329
|
);
|
|
9473
9330
|
printOut(
|
|
9474
|
-
" 3. altana \u2014 bounded session signer; incompatible with pieverse-llm"
|
|
9475
|
-
);
|
|
9476
|
-
printOut(
|
|
9477
|
-
" 4. turnkey \u2014 remote signer; key held in Turnkey's AWS Nitro enclave; billable signatures"
|
|
9331
|
+
" 3. altana \u2014 bounded session signer; incompatible with pieverse-llm and paid b402 selling"
|
|
9478
9332
|
);
|
|
9479
|
-
const answer = (await promptUser("Wallet backend [1-
|
|
9333
|
+
const answer = (await promptUser("Wallet backend [1-3, Enter = evm-local]: ")).trim().toLowerCase();
|
|
9480
9334
|
if (answer === "2" || answer === "twak") return "twak";
|
|
9481
9335
|
if (answer === "3" || answer === "altana") return "altana";
|
|
9482
|
-
if (answer === "4" || answer === "turnkey") return "turnkey";
|
|
9483
9336
|
if (answer !== "" && answer !== "1" && answer !== "evm-local") {
|
|
9484
9337
|
printErr(`hint: unknown wallet backend '${answer}' \u2014 using evm-local.`);
|
|
9485
9338
|
}
|
|
@@ -9761,12 +9614,6 @@ async function runOnboarding(o) {
|
|
|
9761
9614
|
if (o.walletKind === "twak") {
|
|
9762
9615
|
return runOnboardingTwak(o);
|
|
9763
9616
|
}
|
|
9764
|
-
if (o.walletKind === "turnkey") {
|
|
9765
|
-
printOut(
|
|
9766
|
-
"turnkey onboarding: no local key is created. Fill the TURNKEY_* credentials in .studio/.env.local (Turnkey dashboard \u2192 API keys / settings / wallet account), then run `(cd app/agent && bag wallet new)` to adopt + anchor the signing address."
|
|
9767
|
-
);
|
|
9768
|
-
return false;
|
|
9769
|
-
}
|
|
9770
9617
|
const password = await promptPassword();
|
|
9771
9618
|
if (password === null) {
|
|
9772
9619
|
return false;
|
|
@@ -10136,33 +9983,7 @@ NOTE \u2014 wallet.kind = "altana" (bounded runtime session):
|
|
|
10136
9983
|
\`bag wallet session grant --force\` and redeploy.`
|
|
10137
9984
|
);
|
|
10138
9985
|
}
|
|
10139
|
-
function printTurnkeyNotice() {
|
|
10140
|
-
printOut(
|
|
10141
|
-
`
|
|
10142
|
-
NOTE \u2014 wallet.kind = "turnkey" (remote signer, keys in Turnkey's AWS Nitro enclave):
|
|
10143
|
-
\xB7 WALLET: no key material exists locally \u2014 the Agent signs via the TURNKEY_*
|
|
10144
|
-
API credentials in .studio/.env.local.
|
|
10145
|
-
${turnkeySetupGuidance()}
|
|
10146
|
-
\xB7 BILLING: every successful signature is billed (free tier: 25/month at
|
|
10147
|
-
1 request/second; pay-as-you-go $0.10 each) \u2014 budget accordingly.
|
|
10148
|
-
\xB7 PRODUCTION: use a NON-ROOT API user restricted by an explicit ALLOW policy;
|
|
10149
|
-
a root user's API key bypasses ALL Turnkey server-side policies.`
|
|
10150
|
-
);
|
|
10151
|
-
}
|
|
10152
9986
|
function printPlatformWalletSuggestion(walletKind2) {
|
|
10153
|
-
if (walletKind2 === "turnkey") {
|
|
10154
|
-
printOut(
|
|
10155
|
-
`
|
|
10156
|
-
NOTE \u2014 destination = "platform" (48h TESTNET TRIAL on the BNB Chain managed platform):
|
|
10157
|
-
\xB7 This is a sandbox, not a production seller \u2014 the runtime is auto-reclaimed at 48h.
|
|
10158
|
-
\xB7 To sign, ONLY the TURNKEY_* API credentials are transmitted to the operator's
|
|
10159
|
-
Secrets Manager on deploy \u2014 the signing key never leaves Turnkey's enclave.
|
|
10160
|
-
\xB7 Want a smaller blast radius? Use a NON-ROOT API user whose ALLOW policy
|
|
10161
|
-
covers only this Agent's operations, and revoke it from the Turnkey
|
|
10162
|
-
dashboard when the trial ends.`
|
|
10163
|
-
);
|
|
10164
|
-
return;
|
|
10165
|
-
}
|
|
10166
9987
|
if (walletKind2 === "altana") {
|
|
10167
9988
|
printOut(
|
|
10168
9989
|
`
|
|
@@ -10393,17 +10214,6 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
10393
10214
|
printOut(
|
|
10394
10215
|
" (cd app/agent && bag wallet session status) # local, secret-free summary"
|
|
10395
10216
|
);
|
|
10396
|
-
} else if (walletKind2 === "turnkey") {
|
|
10397
|
-
printOut(
|
|
10398
|
-
" # 1. edit .studio/.env.local and set the TURNKEY_* credentials (Turnkey dashboard \u2192 API keys / settings / wallet account)"
|
|
10399
|
-
);
|
|
10400
|
-
printOut(
|
|
10401
|
-
" # use a NON-ROOT API user + explicit ALLOW policy; TURNKEY_SIGN_WITH is the 0x ADDRESS, not a wallet id"
|
|
10402
|
-
);
|
|
10403
|
-
printOut(
|
|
10404
|
-
" # 2. adopt + anchor the Turnkey address (no local key is created):"
|
|
10405
|
-
);
|
|
10406
|
-
printOut(" (cd app/agent && bag wallet new)");
|
|
10407
10217
|
} else {
|
|
10408
10218
|
printOut(
|
|
10409
10219
|
" # 1. edit .studio/.env.local and set WALLET_PASSWORD (encrypts the keystore + signs all on-chain ops)"
|
|
@@ -10627,10 +10437,6 @@ function printConfigSummary(agentRoot2) {
|
|
|
10627
10437
|
".studio/wallets/altana-session.json"
|
|
10628
10438
|
)}`
|
|
10629
10439
|
);
|
|
10630
|
-
} else if (walletKind2 === "turnkey") {
|
|
10631
|
-
printOut(
|
|
10632
|
-
" wallet : Turnkey remote signer (key in AWS Nitro enclave; TURNKEY_* credentials in .studio/.env.local) \u2014 the sole signer; receives your $U"
|
|
10633
|
-
);
|
|
10634
10440
|
} else {
|
|
10635
10441
|
printOut(
|
|
10636
10442
|
` wallet : local keystore (${shown(
|
|
@@ -10751,16 +10557,6 @@ function runtimeEnvKeysCore(cfg, resolvable) {
|
|
|
10751
10557
|
}
|
|
10752
10558
|
} else if (walletKind2 === "altana") {
|
|
10753
10559
|
keys = [];
|
|
10754
|
-
} else if (walletKind2 === "turnkey") {
|
|
10755
|
-
keys = [
|
|
10756
|
-
"TURNKEY_API_PUBLIC_KEY",
|
|
10757
|
-
"TURNKEY_API_PRIVATE_KEY",
|
|
10758
|
-
"TURNKEY_ORG_ID",
|
|
10759
|
-
"TURNKEY_SIGN_WITH"
|
|
10760
|
-
];
|
|
10761
|
-
if (resolvable("TURNKEY_API_BASE_URL")) {
|
|
10762
|
-
keys.push("TURNKEY_API_BASE_URL");
|
|
10763
|
-
}
|
|
10764
10560
|
} else {
|
|
10765
10561
|
keys = ["WALLET_PASSWORD"];
|
|
10766
10562
|
}
|
|
@@ -11285,17 +11081,10 @@ async function cmdDev(opts) {
|
|
|
11285
11081
|
);
|
|
11286
11082
|
return 2;
|
|
11287
11083
|
}
|
|
11288
|
-
const
|
|
11289
|
-
|
|
11290
|
-
"TURNKEY_API_PRIVATE_KEY",
|
|
11291
|
-
"TURNKEY_ORG_ID",
|
|
11292
|
-
"TURNKEY_SIGN_WITH"
|
|
11293
|
-
] : ["WALLET_PASSWORD"];
|
|
11294
|
-
const missingWalletEnv = requiredWalletEnv.filter((key) => !process.env[key]);
|
|
11295
|
-
if (missingWalletEnv.length > 0) {
|
|
11296
|
-
const plural = missingWalletEnv.length > 1 ? "vars are" : "var is";
|
|
11084
|
+
const pwEnv = walletKind2 === "twak" ? "TWAK_WALLET_PASSWORD" : "WALLET_PASSWORD";
|
|
11085
|
+
if (walletKind2 !== "altana" && !process.env[pwEnv]) {
|
|
11297
11086
|
printErr(
|
|
11298
|
-
`error: ${
|
|
11087
|
+
`error: ${pwEnv} env var is required to run \`bag dev\` (the Agent is the sole signer). Set it in .studio/.env.local or your shell.`
|
|
11299
11088
|
);
|
|
11300
11089
|
return 2;
|
|
11301
11090
|
}
|
|
@@ -11676,9 +11465,6 @@ async function checkLocalKeystoreExists(root, _target) {
|
|
|
11676
11465
|
if (walletCfg.kind === "altana") {
|
|
11677
11466
|
return [];
|
|
11678
11467
|
}
|
|
11679
|
-
if (walletCfg.kind === "turnkey") {
|
|
11680
|
-
return [];
|
|
11681
|
-
}
|
|
11682
11468
|
const signer = walletCfg.signer ?? "local";
|
|
11683
11469
|
if (signer !== "local") {
|
|
11684
11470
|
return [];
|
|
@@ -11704,9 +11490,6 @@ async function checkWalletPasswordEnvSet(root, _target) {
|
|
|
11704
11490
|
if (kind === "altana") {
|
|
11705
11491
|
return [];
|
|
11706
11492
|
}
|
|
11707
|
-
if (kind === "turnkey") {
|
|
11708
|
-
return [];
|
|
11709
|
-
}
|
|
11710
11493
|
if (process.env.WALLET_PASSWORD) {
|
|
11711
11494
|
return [];
|
|
11712
11495
|
}
|
|
@@ -12049,11 +11832,11 @@ function x402SellerRailChecks(agentRoot2, cfg, target) {
|
|
|
12049
11832
|
}
|
|
12050
11833
|
}
|
|
12051
11834
|
const walletKind2 = String(tableOf2(cfg, "wallet").kind ?? "evm-local");
|
|
12052
|
-
if (paid && !["evm-local", "twak"
|
|
11835
|
+
if (paid && !["evm-local", "twak"].includes(walletKind2)) {
|
|
12053
11836
|
out.push({
|
|
12054
11837
|
level: Level.CRITICAL,
|
|
12055
11838
|
name: "x402_wallet_kind_unsupported",
|
|
12056
|
-
message: `[wallet].kind = "${walletKind2}" cannot run the b402 seller rail; supported kinds are evm-local
|
|
11839
|
+
message: `[wallet].kind = "${walletKind2}" cannot run the b402 seller rail; supported kinds are evm-local and twak.`,
|
|
12057
11840
|
details: { walletKind: walletKind2 }
|
|
12058
11841
|
});
|
|
12059
11842
|
}
|
|
@@ -12330,46 +12113,6 @@ function awsJson(stdout) {
|
|
|
12330
12113
|
return null;
|
|
12331
12114
|
}
|
|
12332
12115
|
}
|
|
12333
|
-
async function checkAwsAccountMatchesTarget(root, target) {
|
|
12334
|
-
if (target !== "agentcore") {
|
|
12335
|
-
return [];
|
|
12336
|
-
}
|
|
12337
|
-
const [targetAccount, region] = readAwsTarget(root);
|
|
12338
|
-
if (!targetAccount || !region || !await whichBin("aws")) {
|
|
12339
|
-
return [];
|
|
12340
|
-
}
|
|
12341
|
-
const identity = await runCapture("aws", [
|
|
12342
|
-
"sts",
|
|
12343
|
-
"get-caller-identity",
|
|
12344
|
-
"--region",
|
|
12345
|
-
region,
|
|
12346
|
-
"--output",
|
|
12347
|
-
"json"
|
|
12348
|
-
]);
|
|
12349
|
-
if (identity.code !== 0) {
|
|
12350
|
-
return [];
|
|
12351
|
-
}
|
|
12352
|
-
const rawAccount = awsJson(identity.stdout)?.Account;
|
|
12353
|
-
const credentialAccount = typeof rawAccount === "string" && /^\d{12}$/.test(rawAccount.trim()) ? rawAccount.trim() : null;
|
|
12354
|
-
if (credentialAccount === null || credentialAccount === targetAccount) {
|
|
12355
|
-
return [];
|
|
12356
|
-
}
|
|
12357
|
-
const targetPath = path24.join(root, "agentcore", "aws-targets.json");
|
|
12358
|
-
return [
|
|
12359
|
-
{
|
|
12360
|
-
level: Level.CRITICAL,
|
|
12361
|
-
name: "aws_account_mismatch",
|
|
12362
|
-
message: `active AWS credentials resolve to account ${credentialAccount}, but agentcore/aws-targets.json pins account ${targetAccount}. The delegated deploy rejects this mismatch before provisioning. Switch credentials, or update the local target file after confirming which account should own the deployment.`,
|
|
12363
|
-
details: {
|
|
12364
|
-
credential_account: credentialAccount,
|
|
12365
|
-
target_account: targetAccount,
|
|
12366
|
-
region,
|
|
12367
|
-
path: targetPath
|
|
12368
|
-
},
|
|
12369
|
-
fixCmd: `# edit agentcore/aws-targets.json and set the default account to ${credentialAccount}, or switch the active AWS credentials`
|
|
12370
|
-
}
|
|
12371
|
-
];
|
|
12372
|
-
}
|
|
12373
12116
|
async function checkAgentcoreQuotaHeadroom(root, target) {
|
|
12374
12117
|
if (target !== "agentcore") {
|
|
12375
12118
|
return [];
|
|
@@ -12475,7 +12218,6 @@ var allChecks = [
|
|
|
12475
12218
|
checkDeployCliRunnable,
|
|
12476
12219
|
checkRuntimeSecretsInjected,
|
|
12477
12220
|
checkAwsTargetsPopulated,
|
|
12478
|
-
checkAwsAccountMatchesTarget,
|
|
12479
12221
|
checkAgentcoreQuotaHeadroom
|
|
12480
12222
|
];
|
|
12481
12223
|
|
|
@@ -12611,7 +12353,7 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
12611
12353
|
sources[KEYSTORE_JSON_ENV] = "wallet-file";
|
|
12612
12354
|
}
|
|
12613
12355
|
}
|
|
12614
|
-
if (walletKind2 !== "altana" &&
|
|
12356
|
+
if (walletKind2 !== "altana" && !(KEYSTORE_JSON_ENV in payload) && !(TWAK_WALLET_JSON_ENV in payload)) {
|
|
12615
12357
|
printErr(
|
|
12616
12358
|
`WARNING: no wallet signing material found (${KEYSTORE_JSON_ENV} for evm-local / ${TWAK_WALLET_JSON_ENV} for twak). The deployed runtime won't be able to sign quotes or deliveries. Create/adopt a wallet first (e.g. \`bag wallet new\`) and redeploy.`
|
|
12617
12359
|
);
|
|
@@ -15287,15 +15029,6 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
15287
15029
|
);
|
|
15288
15030
|
}
|
|
15289
15031
|
const endpointBlock = endpoints.join("\n");
|
|
15290
|
-
const commerceShapeLines = hasA2aFace(faces) ? [
|
|
15291
|
-
"MESSAGE SHAPES (complete A2A JSON-RPC requests)",
|
|
15292
|
-
'- negotiate: {"jsonrpc":"2.0","id":"request-1","method":"message/send","params":{"message":{"messageId":"message-1","role":"user","parts":[{"kind":"data","data":{"skill":"negotiate","task_description":"<what you want done>","terms":{"deliverables":"...","quality_standards":"..."}}}]}}}',
|
|
15293
|
-
'- notify_funded: {"jsonrpc":"2.0","id":"request-2","method":"message/send","params":{"message":{"messageId":"message-2","role":"user","parts":[{"kind":"data","data":{"skill":"notify_funded","job_id":123}}]}}}'
|
|
15294
|
-
] : [
|
|
15295
|
-
"MCP TOOL ARGUMENTS",
|
|
15296
|
-
'- negotiate: {"task_description":"<what you want done>","terms":{"deliverables":"...","quality_standards":"..."}}',
|
|
15297
|
-
'- notify_funded: {"job_id":123}'
|
|
15298
|
-
];
|
|
15299
15032
|
const lines = [
|
|
15300
15033
|
"",
|
|
15301
15034
|
CLIENT_PROMPT_RULE,
|
|
@@ -15328,7 +15061,9 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
15328
15061
|
"- Remote ERC-8183 callers need an OAuth2 access token:",
|
|
15329
15062
|
tokenSteps,
|
|
15330
15063
|
"",
|
|
15331
|
-
|
|
15064
|
+
"MESSAGE SHAPES",
|
|
15065
|
+
'- negotiate: {"skill":"negotiate","task_description":"<what you want done>","terms":{"deliverables":"...","quality_standards":"..."}}',
|
|
15066
|
+
'- notify_funded: {"skill":"notify_funded","job_id":<int>}'
|
|
15332
15067
|
] : [
|
|
15333
15068
|
"- The anonymous x402 route does not use the OAuth2 token flow shown for ERC-8183."
|
|
15334
15069
|
],
|
|
@@ -16775,28 +16510,6 @@ async function printAgentClientPrompt2(root, destination, opts = {}) {
|
|
|
16775
16510
|
The invoke URL carries a querystring (?qualifier=...): never
|
|
16776
16511
|
string-concatenate extra path segments onto it \u2014 that produces
|
|
16777
16512
|
an invalid URL and an HTTP 405.`;
|
|
16778
|
-
const commerceShapeLines = hasA2aFace(faces) ? [
|
|
16779
|
-
"MESSAGE SHAPES (complete A2A JSON-RPC requests)",
|
|
16780
|
-
'- negotiate: {"jsonrpc":"2.0","id":"request-1","method":"message/send","params":{"message":{"messageId":"message-1","role":"user","parts":[{"kind":"data","data":{"skill":"negotiate","task_description":"<what you want done>","terms":{"deliverables":"...","quality_standards":"..."}}}]}}}',
|
|
16781
|
-
'- notify_funded: {"jsonrpc":"2.0","id":"request-2","method":"message/send","params":{"message":{"messageId":"message-2","role":"user","parts":[{"kind":"data","data":{"skill":"notify_funded","job_id":123}}]}}}'
|
|
16782
|
-
] : [
|
|
16783
|
-
"MCP TOOL ARGUMENTS",
|
|
16784
|
-
'- negotiate: {"task_description":"<what you want done>","terms":{"deliverables":"...","quality_standards":"..."}}',
|
|
16785
|
-
'- notify_funded: {"job_id":123}'
|
|
16786
|
-
];
|
|
16787
|
-
const mcpSessionLines = hasA2aFace(faces) && hasMcpFace(faces) ? [
|
|
16788
|
-
"",
|
|
16789
|
-
"MCP SESSION FLOW (A2A+MCP through envelope-v1)",
|
|
16790
|
-
" 1) Keep X-Amzn-Bedrock-AgentCore-Runtime-Session-Id on every outer InvokeAgentRuntime request; this is the outer AgentCore runtime session.",
|
|
16791
|
-
" 2) Send an envelope-v1 POST /mcp whose decoded body is the MCP initialize request, with no inner mcp-session-id header.",
|
|
16792
|
-
' 3) Decode the envelope response and read headers["mcp-session-id"]; this is the inner MCP session, separate from the outer header.',
|
|
16793
|
-
" 4) Send notifications/initialized, then tools/list or tools/call in new envelopes whose inner headers carry that same mcp-session-id."
|
|
16794
|
-
] : hasMcpFace(faces) ? [
|
|
16795
|
-
"",
|
|
16796
|
-
"MCP SESSION FLOW",
|
|
16797
|
-
" 1) Send initialize without mcp-session-id and capture the response mcp-session-id header.",
|
|
16798
|
-
" 2) Send notifications/initialized, then tools/list or tools/call with that header."
|
|
16799
|
-
] : [];
|
|
16800
16513
|
const lines = [
|
|
16801
16514
|
"",
|
|
16802
16515
|
CLIENT_PROMPT_RULE2,
|
|
@@ -16826,8 +16539,9 @@ async function printAgentClientPrompt2(root, destination, opts = {}) {
|
|
|
16826
16539
|
"- Remote ERC-8183 callers need an OAuth2 access token:",
|
|
16827
16540
|
tokenSteps,
|
|
16828
16541
|
"",
|
|
16829
|
-
|
|
16830
|
-
...
|
|
16542
|
+
"MESSAGE SHAPES",
|
|
16543
|
+
'- negotiate: {"skill":"negotiate","task_description":"<what you want done>","terms":{"deliverables":"...","quality_standards":"..."}}',
|
|
16544
|
+
'- notify_funded: {"skill":"notify_funded","job_id":<int>}'
|
|
16831
16545
|
] : [
|
|
16832
16546
|
"- The anonymous x402 route does not use the OAuth2 token flow shown for ERC-8183."
|
|
16833
16547
|
],
|
|
@@ -17724,8 +17438,7 @@ var SECRET_ENV_KEYS = [
|
|
|
17724
17438
|
"PIEVERSE_LLM_API_KEY",
|
|
17725
17439
|
"STORAGE_API_KEY",
|
|
17726
17440
|
"TWAK_ACCESS_ID",
|
|
17727
|
-
"TWAK_HMAC_SECRET"
|
|
17728
|
-
"TURNKEY_API_PRIVATE_KEY"
|
|
17441
|
+
"TWAK_HMAC_SECRET"
|
|
17729
17442
|
];
|
|
17730
17443
|
function tableOf14(cfg, key) {
|
|
17731
17444
|
const v = cfg[key];
|
|
@@ -17972,9 +17685,6 @@ async function checkWallet(projectRoot, data) {
|
|
|
17972
17685
|
if (walletCfg.kind === "altana") {
|
|
17973
17686
|
return checkWalletAltana(walletCfg, projectRoot, data);
|
|
17974
17687
|
}
|
|
17975
|
-
if (walletCfg.kind === "turnkey") {
|
|
17976
|
-
return checkWalletTurnkey(walletCfg);
|
|
17977
|
-
}
|
|
17978
17688
|
if (!isLocalEvmWallet(walletCfg)) {
|
|
17979
17689
|
return [
|
|
17980
17690
|
{
|
|
@@ -18028,59 +17738,7 @@ async function checkWallet(projectRoot, data) {
|
|
|
18028
17738
|
}
|
|
18029
17739
|
return out;
|
|
18030
17740
|
}
|
|
18031
|
-
|
|
18032
|
-
var TURNKEY_REQUIRED_ENV = [
|
|
18033
|
-
"TURNKEY_API_PUBLIC_KEY",
|
|
18034
|
-
"TURNKEY_API_PRIVATE_KEY",
|
|
18035
|
-
"TURNKEY_ORG_ID",
|
|
18036
|
-
"TURNKEY_SIGN_WITH"
|
|
18037
|
-
];
|
|
18038
|
-
function checkWalletTurnkey(walletCfg) {
|
|
18039
|
-
const out = [];
|
|
18040
|
-
const missing = TURNKEY_REQUIRED_ENV.filter((key) => !process.env[key]);
|
|
18041
|
-
out.push(
|
|
18042
|
-
missing.length === 0 ? {
|
|
18043
|
-
name: "[wallet] turnkey credentials",
|
|
18044
|
-
status: PASS,
|
|
18045
|
-
detail: "API key pair + org id + sign-with address set; reminder: production should use a non-root API user with an explicit ALLOW policy (root keys bypass all Turnkey policies)"
|
|
18046
|
-
} : {
|
|
18047
|
-
name: "[wallet] turnkey credentials",
|
|
18048
|
-
status: FAIL,
|
|
18049
|
-
detail: `missing: ${missing.join(", ")} \u2014 set them in .studio/.env.local (Turnkey dashboard \u2192 API keys / settings / wallet account)`
|
|
18050
|
-
}
|
|
18051
|
-
);
|
|
18052
|
-
const signWith = String(process.env.TURNKEY_SIGN_WITH ?? "").trim();
|
|
18053
|
-
if (signWith !== "" && !TURNKEY_ADDRESS_RE.test(signWith)) {
|
|
18054
|
-
out.push({
|
|
18055
|
-
name: "TURNKEY_SIGN_WITH format",
|
|
18056
|
-
status: FAIL,
|
|
18057
|
-
detail: "must be the wallet account's Ethereum address (0x + 40 hex chars), not a Turnkey wallet id \u2014 copy it from the dashboard wallet-account view"
|
|
18058
|
-
});
|
|
18059
|
-
}
|
|
18060
|
-
const anchored = String(walletCfg.address ?? "").trim();
|
|
18061
|
-
if (anchored === "") {
|
|
18062
|
-
out.push({
|
|
18063
|
-
name: "[wallet] address anchor",
|
|
18064
|
-
status: WARN,
|
|
18065
|
-
detail: "no [wallet].address \u2014 run `bag wallet new` to adopt TURNKEY_SIGN_WITH"
|
|
18066
|
-
});
|
|
18067
|
-
} else if (signWith !== "" && TURNKEY_ADDRESS_RE.test(signWith)) {
|
|
18068
|
-
const matches = anchored.toLowerCase() === signWith.toLowerCase();
|
|
18069
|
-
out.push(
|
|
18070
|
-
matches ? {
|
|
18071
|
-
name: "[wallet] address anchor",
|
|
18072
|
-
status: PASS,
|
|
18073
|
-
detail: `${anchored} matches TURNKEY_SIGN_WITH`
|
|
18074
|
-
} : {
|
|
18075
|
-
name: "[wallet] address anchor",
|
|
18076
|
-
status: FAIL,
|
|
18077
|
-
detail: `[wallet].address ${anchored} does not match TURNKEY_SIGN_WITH ${signWith} \u2014 stale anchor or different Turnkey credentials; fix .studio/.env.local, then re-run \`bag wallet new\``
|
|
18078
|
-
}
|
|
18079
|
-
);
|
|
18080
|
-
}
|
|
18081
|
-
return out;
|
|
18082
|
-
}
|
|
18083
|
-
async function checkWalletAltana(walletCfg, projectRoot, data) {
|
|
17741
|
+
function checkWalletAltana(walletCfg, projectRoot, data) {
|
|
18084
17742
|
const out = [];
|
|
18085
17743
|
const contracts = erc8183ContractOverrideState(
|
|
18086
17744
|
erc8183ContractEnvForProject(projectRoot)
|
|
@@ -18166,41 +17824,13 @@ async function checkWalletAltana(walletCfg, projectRoot, data) {
|
|
|
18166
17824
|
out.push({
|
|
18167
17825
|
name: "[wallet] Altana SDK",
|
|
18168
17826
|
status: entry === null ? FAIL : PASS,
|
|
18169
|
-
detail: entry === null ? "@altananetwork/sdk is not resolvable from this project \u2014 run `pnpm add @altananetwork/sdk@0.
|
|
17827
|
+
detail: entry === null ? "@altananetwork/sdk is not resolvable from this project \u2014 run `pnpm add @altananetwork/sdk@0.5.1`" : entry
|
|
18170
17828
|
});
|
|
18171
17829
|
} catch (error) {
|
|
18172
17830
|
out.push({
|
|
18173
17831
|
name: "[wallet] Altana SDK",
|
|
18174
17832
|
status: FAIL,
|
|
18175
|
-
detail: `${error instanceof Error ? error.message : String(error)} \u2014 run \`pnpm add @altananetwork/sdk@0.
|
|
18176
|
-
});
|
|
18177
|
-
}
|
|
18178
|
-
const networkName = String(tableOf14(data, "network").default ?? "bsc-mainnet");
|
|
18179
|
-
try {
|
|
18180
|
-
const allowanceRaw = await readUAllowanceRaw(
|
|
18181
|
-
address,
|
|
18182
|
-
PERMIT2_ADDRESS,
|
|
18183
|
-
networkName
|
|
18184
|
-
);
|
|
18185
|
-
if (allowanceRaw !== null) {
|
|
18186
|
-
const uToken = getNetwork9(networkName).token("U");
|
|
18187
|
-
out.push(
|
|
18188
|
-
allowanceRaw > 0n ? {
|
|
18189
|
-
name: "[wallet] Altana x402 buying",
|
|
18190
|
-
status: PASS,
|
|
18191
|
-
detail: `U\u2192Permit2 allowance ${fromRaw3(allowanceRaw, uToken.decimals)} U on ${networkName} (b402 permit2 rail armed)`
|
|
18192
|
-
} : {
|
|
18193
|
-
name: "[wallet] Altana x402 buying",
|
|
18194
|
-
status: WARN,
|
|
18195
|
-
detail: `no U\u2192Permit2 allowance on ${networkName} \u2014 outbound x402 buying is not armed; run \`bag wallet session x402-setup --allowance-u <amount>\` (admin key) if this agent should pay b402 merchants`
|
|
18196
|
-
}
|
|
18197
|
-
);
|
|
18198
|
-
}
|
|
18199
|
-
} catch (error) {
|
|
18200
|
-
out.push({
|
|
18201
|
-
name: "[wallet] Altana x402 buying",
|
|
18202
|
-
status: WARN,
|
|
18203
|
-
detail: `could not read the U\u2192Permit2 allowance on ${networkName}: ${error instanceof Error ? error.message : String(error)}`
|
|
17833
|
+
detail: `${error instanceof Error ? error.message : String(error)} \u2014 run \`pnpm add @altananetwork/sdk@0.5.1\``
|
|
18204
17834
|
});
|
|
18205
17835
|
}
|
|
18206
17836
|
return out;
|
|
@@ -18300,20 +17930,6 @@ function checkPassword(data) {
|
|
|
18300
17930
|
}
|
|
18301
17931
|
];
|
|
18302
17932
|
}
|
|
18303
|
-
if (walletKind2 === "turnkey") {
|
|
18304
|
-
const missing = TURNKEY_REQUIRED_ENV.filter((key) => !process.env[key]);
|
|
18305
|
-
return [
|
|
18306
|
-
missing.length === 0 ? {
|
|
18307
|
-
name: "TURNKEY_* env",
|
|
18308
|
-
status: PASS,
|
|
18309
|
-
detail: "all Turnkey credentials set (WALLET_PASSWORD is not used for this kind)"
|
|
18310
|
-
} : {
|
|
18311
|
-
name: "TURNKEY_* env",
|
|
18312
|
-
status: WARN,
|
|
18313
|
-
detail: `missing: ${missing.join(", ")} \u2014 signing will fail (set in .studio/.env.local)`
|
|
18314
|
-
}
|
|
18315
|
-
];
|
|
18316
|
-
}
|
|
18317
17933
|
if (process.env.WALLET_PASSWORD) {
|
|
18318
17934
|
return [{ name: "WALLET_PASSWORD env", status: PASS, detail: "set" }];
|
|
18319
17935
|
}
|
|
@@ -18682,11 +18298,11 @@ function checkX402Seller(data, agentRoot2) {
|
|
|
18682
18298
|
}
|
|
18683
18299
|
];
|
|
18684
18300
|
const walletKind2 = String(tableOf14(data, "wallet").kind ?? "evm-local");
|
|
18685
|
-
if (!["evm-local", "twak"
|
|
18301
|
+
if (!["evm-local", "twak"].includes(walletKind2)) {
|
|
18686
18302
|
out.push({
|
|
18687
18303
|
name: "x402 payout wallet",
|
|
18688
18304
|
status: FAIL,
|
|
18689
|
-
detail: `PAID B402 supports evm-local
|
|
18305
|
+
detail: `PAID B402 supports evm-local or twak, not ${walletKind2}.`
|
|
18690
18306
|
});
|
|
18691
18307
|
}
|
|
18692
18308
|
const credentials = b402Credentials(agentRoot2);
|
|
@@ -18760,7 +18376,7 @@ function checkStorage(data) {
|
|
|
18760
18376
|
}
|
|
18761
18377
|
function balanceAddress(projectRoot, data) {
|
|
18762
18378
|
const walletCfg = tableOf14(data, "wallet");
|
|
18763
|
-
if (walletCfg.kind === "twak" || walletCfg.kind === "altana"
|
|
18379
|
+
if (walletCfg.kind === "twak" || walletCfg.kind === "altana") {
|
|
18764
18380
|
const addr = String(walletCfg.address ?? "").trim();
|
|
18765
18381
|
return addr || null;
|
|
18766
18382
|
}
|
|
@@ -21486,9 +21102,9 @@ async function cmdSellInit(priceFlag) {
|
|
|
21486
21102
|
}
|
|
21487
21103
|
const free = x402SellerPricingState({ price_usd: priceUsd }).kind === "free";
|
|
21488
21104
|
const walletKind2 = String(tableOf16(cfg, "wallet").kind ?? "evm-local");
|
|
21489
|
-
if (!free && !["evm-local", "twak"
|
|
21105
|
+
if (!free && !["evm-local", "twak"].includes(walletKind2)) {
|
|
21490
21106
|
printErr(
|
|
21491
|
-
`error: the b402 seller rail supports wallet.kind evm-local
|
|
21107
|
+
`error: the b402 seller rail supports wallet.kind evm-local or twak only; '${walletKind2}' cannot act as the b402 payout wallet.`
|
|
21492
21108
|
);
|
|
21493
21109
|
return 1;
|
|
21494
21110
|
}
|
|
@@ -21614,21 +21230,16 @@ async function cmdSellStatus(probe) {
|
|
|
21614
21230
|
}
|
|
21615
21231
|
try {
|
|
21616
21232
|
const supported = await _probeB402Supported(process.env);
|
|
21617
|
-
const
|
|
21618
|
-
(kind) => kind.x402Version === 2 && kind.scheme === "exact" && kind.network === network && kind.extra.assetTransferMethod ===
|
|
21619
|
-
);
|
|
21620
|
-
const available = token.methods.filter(
|
|
21621
|
-
(method) => matching(method) !== void 0
|
|
21233
|
+
const methodKind = supported?.kinds.find(
|
|
21234
|
+
(kind) => kind.x402Version === 2 && kind.scheme === "exact" && kind.network === network && kind.extra.assetTransferMethod === "eip3009"
|
|
21622
21235
|
);
|
|
21623
|
-
if (
|
|
21624
|
-
|
|
21625
|
-
printOut(
|
|
21626
|
-
`B402 probe: exact U available for ${network} (${available.join(", ")})${missing.length > 0 ? ` \u2014 advertised but not offered by the facilitator: ${missing.join(", ")}` : ""}`
|
|
21627
|
-
);
|
|
21236
|
+
if (methodKind && methodKind.extra.name === token.eip712Name && methodKind.extra.version === token.eip712Version) {
|
|
21237
|
+
printOut(`B402 probe: exact/eip3009 U available for ${network}`);
|
|
21628
21238
|
return 0;
|
|
21629
21239
|
}
|
|
21240
|
+
const observed = methodKind ? `observed name=${String(methodKind.extra.name ?? "(missing)")} version=${String(methodKind.extra.version ?? "(missing)")}` : "no exact/eip3009 kind was returned";
|
|
21630
21241
|
printOut(
|
|
21631
|
-
`B402 probe: mismatch for ${network}; expected
|
|
21242
|
+
`B402 probe: mismatch for ${network}; expected name=${token.eip712Name} version=${token.eip712Version}; ${observed}. Check that the credentials belong to the matching B402 environment.`
|
|
21632
21243
|
);
|
|
21633
21244
|
} catch {
|
|
21634
21245
|
printOut(
|
|
@@ -21757,30 +21368,6 @@ async function cmdBuy2(url, opts) {
|
|
|
21757
21368
|
);
|
|
21758
21369
|
return 1;
|
|
21759
21370
|
}
|
|
21760
|
-
const buyWalletKind = String(tableOf16(cfg, "wallet").kind ?? "evm-local");
|
|
21761
|
-
if (buyWalletKind === "altana") {
|
|
21762
|
-
let allowanceRaw;
|
|
21763
|
-
try {
|
|
21764
|
-
allowanceRaw = await readUAllowanceRaw(
|
|
21765
|
-
wallet.address,
|
|
21766
|
-
PERMIT2_ADDRESS,
|
|
21767
|
-
networkName
|
|
21768
|
-
);
|
|
21769
|
-
} catch (exc) {
|
|
21770
|
-
printErr(`error: permit2 allowance check failed: ${errMsg6(exc)}`);
|
|
21771
|
-
return 1;
|
|
21772
|
-
}
|
|
21773
|
-
if (allowanceRaw !== null && allowanceRaw < neededRaw) {
|
|
21774
|
-
const uToken = getNetwork11(networkName).token("U");
|
|
21775
|
-
printErr(
|
|
21776
|
-
`error: U\u2192Permit2 allowance ${fromRaw5(allowanceRaw, uToken.decimals)} U cannot cover max_usd $${opts.maxUsd.toFixed(2)}: b402 settles Altana payments by pulling through Permit2 (${PERMIT2_ADDRESS}).`
|
|
21777
|
-
);
|
|
21778
|
-
printErr(
|
|
21779
|
-
"fix: bag wallet session x402-setup --allowance-u <amount> (admin key; approves the x402 signature checker and sets the bounded Permit2 allowance)"
|
|
21780
|
-
);
|
|
21781
|
-
return 1;
|
|
21782
|
-
}
|
|
21783
|
-
}
|
|
21784
21371
|
let result;
|
|
21785
21372
|
try {
|
|
21786
21373
|
result = await auditedOp4(
|
|
@@ -21820,7 +21407,7 @@ async function cmdBuy2(url, opts) {
|
|
|
21820
21407
|
}
|
|
21821
21408
|
const paidUsd = result.paidUsd ?? 0;
|
|
21822
21409
|
const envelope = result.txPaymentEnvelope ?? "";
|
|
21823
|
-
const envelopePreview = envelope ? `${envelope.slice(0, 40)}...` :
|
|
21410
|
+
const envelopePreview = envelope ? `${envelope.slice(0, 40)}...` : "(no payment \u2014 server did not 402)";
|
|
21824
21411
|
const ok = result.statusCode >= 200 && result.statusCode < 300;
|
|
21825
21412
|
if (result.paidUsd === null) {
|
|
21826
21413
|
if (ok) {
|