@bnbagent/studio-cli 0.0.6-alpha.6 → 0.0.6-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DISCLAIMER.md +6 -27
- package/README.md +6 -13
- package/dist/bag.js +1121 -795
- package/dist/{chunk-VEOOFDSF.js → chunk-JZAW6HMV.js} +74 -5
- package/dist/{deployCli-EEK75T67.js → deployCli-AJ25A4VK.js} +1 -1
- package/package.json +2 -2
- package/recipes/providers/pieverse-llm/skills/funding-pieverse-llm.md +32 -64
- package/skills/bnbagent-studio.md +29 -74
- package/skills/references/bnbagent-studio-adding-to-project.md +58 -169
- package/skills/references/bnbagent-studio-buying-from-bazaar.md +43 -104
- package/skills/references/bnbagent-studio-buying-via-8183.md +38 -112
- package/skills/references/bnbagent-studio-extending-signing.md +47 -50
- package/skills/references/bnbagent-studio-operating.md +58 -111
- package/skills/references/bnbagent-studio-scaffolding-agent.md +136 -403
- package/skills/references/bnbagent-studio-selling-via-8183.md +87 -172
- package/skills/references/bnbagent-studio-selling-via-b402.md +39 -131
- package/skills/references/bnbagent-studio-use-aws-agentcore.md +43 -144
- package/skills/references/bnbagent-studio-use-azure-foundry.md +34 -95
- package/skills/references/bnbagent-studio-use-bnb-trial.md +12 -36
- package/skills/references/bnbagent-studio-using-altana-wallet.md +11 -28
- package/skills/references/bnbagent-studio-using-twak-wallet.md +102 -210
- package/skills/references/bnbagent-studio-wiring-llm-tools.md +71 -150
package/dist/bag.js
CHANGED
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
x402SellerIsFree,
|
|
45
45
|
x402SellerPricingState,
|
|
46
46
|
x402SellerUsesB402
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-JZAW6HMV.js";
|
|
48
48
|
import {
|
|
49
49
|
TWAK_CLI_MIN_VERSION,
|
|
50
50
|
TWAK_CLI_VERSION,
|
|
@@ -106,7 +106,7 @@ import {
|
|
|
106
106
|
var CAMPAIGN_DOC_URL = "https://www.bnbchain.org/en/blog/bnb-agent-studio-is-live-on-bnb-chain-ai-agents-from-one-prompt";
|
|
107
107
|
var CAMPAIGN_CHECK_TIMEOUT_MS = 6e3;
|
|
108
108
|
async function fetchCampaignActive() {
|
|
109
|
-
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-
|
|
109
|
+
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-AJ25A4VK.js");
|
|
110
110
|
const controller = new AbortController();
|
|
111
111
|
const timer = setTimeout(() => controller.abort(), CAMPAIGN_CHECK_TIMEOUT_MS);
|
|
112
112
|
try {
|
|
@@ -2090,11 +2090,11 @@ async function devAgentResponding(port = 9e3, timeoutMs = 500) {
|
|
|
2090
2090
|
}
|
|
2091
2091
|
}
|
|
2092
2092
|
function devPortInUse(port = 9e3, timeoutMs = 250) {
|
|
2093
|
-
return new Promise((
|
|
2093
|
+
return new Promise((resolve24) => {
|
|
2094
2094
|
const socket = new net.Socket();
|
|
2095
2095
|
const done = (result) => {
|
|
2096
2096
|
socket.destroy();
|
|
2097
|
-
|
|
2097
|
+
resolve24(result);
|
|
2098
2098
|
};
|
|
2099
2099
|
socket.setTimeout(timeoutMs);
|
|
2100
2100
|
socket.once("connect", () => done(true));
|
|
@@ -2551,8 +2551,8 @@ function cmdListKeys(projectRoot) {
|
|
|
2551
2551
|
}
|
|
2552
2552
|
|
|
2553
2553
|
// src/cli/deploy.ts
|
|
2554
|
-
import * as
|
|
2555
|
-
import * as
|
|
2554
|
+
import * as fs38 from "fs";
|
|
2555
|
+
import * as path38 from "path";
|
|
2556
2556
|
import {
|
|
2557
2557
|
envLocalPath as envLocalPath16,
|
|
2558
2558
|
findStudioWorkspaceRoot as findStudioWorkspaceRoot3,
|
|
@@ -2994,23 +2994,24 @@ function hasIpfsEndpointFinding(result) {
|
|
|
2994
2994
|
}
|
|
2995
2995
|
|
|
2996
2996
|
// src/cli/_deploy/cognitoCdk.ts
|
|
2997
|
-
import * as
|
|
2998
|
-
import * as
|
|
2997
|
+
import * as fs28 from "fs";
|
|
2998
|
+
import * as path27 from "path";
|
|
2999
2999
|
import { envLocalPath as envLocalPath13 } from "@bnbagent/studio-runtime/config";
|
|
3000
3000
|
|
|
3001
3001
|
// src/cli/_deploy/secrets.ts
|
|
3002
|
-
import * as
|
|
3003
|
-
import * as
|
|
3002
|
+
import * as fs27 from "fs";
|
|
3003
|
+
import * as path26 from "path";
|
|
3004
3004
|
import {
|
|
3005
3005
|
envLocalPath as envLocalPath12,
|
|
3006
3006
|
findSubProjectRoot as findSubProjectRoot8,
|
|
3007
3007
|
loadStudioToml as loadStudioToml13
|
|
3008
3008
|
} from "@bnbagent/studio-runtime/config";
|
|
3009
|
+
import { ALTANA_SESSION_ENV } from "@bnbagent/studio-runtime/wallet";
|
|
3009
3010
|
|
|
3010
3011
|
// src/cli/dev.ts
|
|
3011
|
-
import * as
|
|
3012
|
+
import * as fs25 from "fs";
|
|
3012
3013
|
import * as os5 from "os";
|
|
3013
|
-
import * as
|
|
3014
|
+
import * as path24 from "path";
|
|
3014
3015
|
import { loadStudioToml as loadStudioToml11 } from "@bnbagent/studio-runtime/config";
|
|
3015
3016
|
import { getNetwork as getNetwork7 } from "@bnbagent/studio-runtime/networks";
|
|
3016
3017
|
import { writePrivate as writePrivate2 } from "@bnbagent/studio-runtime/secretWrite";
|
|
@@ -3198,9 +3199,9 @@ function relocateKeys(src, target, label) {
|
|
|
3198
3199
|
}
|
|
3199
3200
|
|
|
3200
3201
|
// src/cli/init.ts
|
|
3201
|
-
import * as
|
|
3202
|
+
import * as fs24 from "fs";
|
|
3202
3203
|
import * as os4 from "os";
|
|
3203
|
-
import * as
|
|
3204
|
+
import * as path23 from "path";
|
|
3204
3205
|
import { getNetwork as getNetwork6 } from "@bnbagent/studio-runtime/networks";
|
|
3205
3206
|
import { ensureTwakKeychain } from "@bnbagent/studio-runtime/wallet";
|
|
3206
3207
|
import { Option as Option2 } from "commander";
|
|
@@ -3451,8 +3452,8 @@ function pnpmVersion() {
|
|
|
3451
3452
|
|
|
3452
3453
|
// src/cli/_runtime/azureFoundry.ts
|
|
3453
3454
|
import * as crypto2 from "crypto";
|
|
3454
|
-
import * as
|
|
3455
|
-
import * as
|
|
3455
|
+
import * as fs18 from "fs";
|
|
3456
|
+
import * as path17 from "path";
|
|
3456
3457
|
import {
|
|
3457
3458
|
findStudioWorkspaceRoot,
|
|
3458
3459
|
findSubProjectRoot as findSubProjectRoot7,
|
|
@@ -3460,9 +3461,177 @@ import {
|
|
|
3460
3461
|
} from "@bnbagent/studio-runtime/config";
|
|
3461
3462
|
import { resolveProviderConfig } from "@bnbagent/studio-runtime/llm";
|
|
3462
3463
|
|
|
3463
|
-
// src/cli/_deploy/checks/
|
|
3464
|
+
// src/cli/_deploy/checks/altana.ts
|
|
3464
3465
|
import * as fs15 from "fs";
|
|
3465
3466
|
import * as path14 from "path";
|
|
3467
|
+
import { resolveProjectAltanaSdkEntry } from "@bnbagent/studio-runtime/wallet";
|
|
3468
|
+
var EXPIRY_WARN_SECONDS = 7 * 24 * 60 * 60;
|
|
3469
|
+
function isAltana(data) {
|
|
3470
|
+
return tableOf2(data, "wallet").kind === "altana";
|
|
3471
|
+
}
|
|
3472
|
+
function isFile4(p) {
|
|
3473
|
+
try {
|
|
3474
|
+
return fs15.statSync(p).isFile();
|
|
3475
|
+
} catch {
|
|
3476
|
+
return false;
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
function sessionFileOf(root, walletCfg) {
|
|
3480
|
+
const configured = String(
|
|
3481
|
+
walletCfg.session_file ?? ".studio/wallets/altana-session.json"
|
|
3482
|
+
);
|
|
3483
|
+
return path14.isAbsolute(configured) ? configured : path14.join(agentRootOf(root), configured);
|
|
3484
|
+
}
|
|
3485
|
+
function checkAltanaSessionReady(root, _target) {
|
|
3486
|
+
const data = loadAgentToml(root);
|
|
3487
|
+
if (!isAltana(data)) {
|
|
3488
|
+
return [];
|
|
3489
|
+
}
|
|
3490
|
+
const walletCfg = tableOf2(data, "wallet");
|
|
3491
|
+
const sessionFile = sessionFileOf(root, walletCfg);
|
|
3492
|
+
if (!isFile4(sessionFile)) {
|
|
3493
|
+
return [
|
|
3494
|
+
{
|
|
3495
|
+
level: Level.CRITICAL,
|
|
3496
|
+
name: "altana_session_exists",
|
|
3497
|
+
message: `no Altana session at ${sessionFile} (wallet.kind='altana') \u2014 the deployed runtime receives ONLY the bounded session (never the admin keystore) and cannot sign without one.`,
|
|
3498
|
+
fixCmd: "bag wallet session grant",
|
|
3499
|
+
details: { session_file: sessionFile }
|
|
3500
|
+
}
|
|
3501
|
+
];
|
|
3502
|
+
}
|
|
3503
|
+
let envelope;
|
|
3504
|
+
try {
|
|
3505
|
+
envelope = JSON.parse(fs15.readFileSync(sessionFile, "utf8"));
|
|
3506
|
+
} catch {
|
|
3507
|
+
return [
|
|
3508
|
+
{
|
|
3509
|
+
level: Level.CRITICAL,
|
|
3510
|
+
name: "altana_session_valid",
|
|
3511
|
+
message: `invalid Altana session JSON at ${sessionFile} \u2014 revoke and grant a fresh session.`,
|
|
3512
|
+
fixCmd: "bag wallet session grant --force",
|
|
3513
|
+
details: { session_file: sessionFile }
|
|
3514
|
+
}
|
|
3515
|
+
];
|
|
3516
|
+
}
|
|
3517
|
+
const anchored = String(walletCfg.address ?? "").trim();
|
|
3518
|
+
if (!anchored) {
|
|
3519
|
+
return [
|
|
3520
|
+
{
|
|
3521
|
+
level: Level.CRITICAL,
|
|
3522
|
+
name: "altana_session_valid",
|
|
3523
|
+
message: "no [wallet].address anchored in app/agent/studio.toml \u2014 the session cannot be verified against the project identity; deploy refuses identity drift.",
|
|
3524
|
+
details: { session_file: sessionFile }
|
|
3525
|
+
}
|
|
3526
|
+
];
|
|
3527
|
+
}
|
|
3528
|
+
const sessionAddress = String(envelope.walletAddress ?? "");
|
|
3529
|
+
if (envelope.version !== 1 || typeof envelope.publicKey !== "string" || !envelope.publicKey.startsWith("0x") || typeof envelope.expiry !== "number") {
|
|
3530
|
+
return [
|
|
3531
|
+
{
|
|
3532
|
+
level: Level.CRITICAL,
|
|
3533
|
+
name: "altana_session_valid",
|
|
3534
|
+
message: `invalid Altana session envelope at ${sessionFile} \u2014 revoke and grant a fresh session.`,
|
|
3535
|
+
fixCmd: "bag wallet session grant --force",
|
|
3536
|
+
details: { session_file: sessionFile }
|
|
3537
|
+
}
|
|
3538
|
+
];
|
|
3539
|
+
}
|
|
3540
|
+
if (sessionAddress.toLowerCase() !== anchored.toLowerCase()) {
|
|
3541
|
+
return [
|
|
3542
|
+
{
|
|
3543
|
+
level: Level.CRITICAL,
|
|
3544
|
+
name: "altana_session_valid",
|
|
3545
|
+
message: `the Altana session at ${sessionFile} was granted for ${sessionAddress}, but studio.toml anchors [wallet].address = ${anchored} \u2014 deploying would ship a DIFFERENT identity than the one registered on-chain. Restore the right session or re-anchor, then re-grant.`,
|
|
3546
|
+
details: { anchored, session_address: sessionAddress }
|
|
3547
|
+
}
|
|
3548
|
+
];
|
|
3549
|
+
}
|
|
3550
|
+
const out = [];
|
|
3551
|
+
const remaining = envelope.expiry - Math.floor(Date.now() / 1e3);
|
|
3552
|
+
if (remaining <= 0) {
|
|
3553
|
+
out.push({
|
|
3554
|
+
level: Level.CRITICAL,
|
|
3555
|
+
name: "altana_session_expiry",
|
|
3556
|
+
message: `the Altana session expired at ${new Date(envelope.expiry * 1e3).toISOString()} \u2014 the deployed runtime would refuse to load it at cold start. Re-grant with \`bag wallet session grant --force\`, then redeploy.`,
|
|
3557
|
+
fixCmd: "bag wallet session grant --force",
|
|
3558
|
+
details: { expiry: envelope.expiry }
|
|
3559
|
+
});
|
|
3560
|
+
} else if (remaining < EXPIRY_WARN_SECONDS) {
|
|
3561
|
+
out.push({
|
|
3562
|
+
level: Level.WARNING,
|
|
3563
|
+
name: "altana_session_expiry",
|
|
3564
|
+
message: `the Altana session expires ${new Date(envelope.expiry * 1e3).toISOString()} (< 7 days). When it lapses the DEPLOYED agent dies at cold start and recovery needs a re-grant AND a redeploy (\`bag wallet session grant --force\`, then \`bag deploy\`). Consider re-granting now.`,
|
|
3565
|
+
details: { expiry: envelope.expiry, remaining_seconds: remaining }
|
|
3566
|
+
});
|
|
3567
|
+
}
|
|
3568
|
+
try {
|
|
3569
|
+
if (process.platform !== "win32" && (fs15.statSync(sessionFile).mode & 63) !== 0) {
|
|
3570
|
+
out.push({
|
|
3571
|
+
level: Level.WARNING,
|
|
3572
|
+
name: "altana_session_permissions",
|
|
3573
|
+
message: `${sessionFile} is readable by group/others and contains the raw session private key; run chmod 600.`,
|
|
3574
|
+
details: { session_file: sessionFile }
|
|
3575
|
+
});
|
|
3576
|
+
}
|
|
3577
|
+
} catch {
|
|
3578
|
+
}
|
|
3579
|
+
return out;
|
|
3580
|
+
}
|
|
3581
|
+
function checkAltanaSdkResolvable(root, _target) {
|
|
3582
|
+
const data = loadAgentToml(root);
|
|
3583
|
+
if (!isAltana(data)) {
|
|
3584
|
+
return [];
|
|
3585
|
+
}
|
|
3586
|
+
const agentRoot2 = agentRootOf(root);
|
|
3587
|
+
let entry = null;
|
|
3588
|
+
let failure = null;
|
|
3589
|
+
try {
|
|
3590
|
+
entry = resolveProjectAltanaSdkEntry(agentRoot2);
|
|
3591
|
+
} catch (error) {
|
|
3592
|
+
failure = error instanceof Error ? error.message : String(error);
|
|
3593
|
+
}
|
|
3594
|
+
if (entry !== null) {
|
|
3595
|
+
return [];
|
|
3596
|
+
}
|
|
3597
|
+
return [
|
|
3598
|
+
{
|
|
3599
|
+
level: Level.CRITICAL,
|
|
3600
|
+
name: "altana_sdk_resolvable",
|
|
3601
|
+
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.`,
|
|
3602
|
+
fixCmd: "pnpm add @altananetwork/sdk@0.5.1",
|
|
3603
|
+
details: failure ? { error: failure } : {}
|
|
3604
|
+
}
|
|
3605
|
+
];
|
|
3606
|
+
}
|
|
3607
|
+
function checkAltanaSessionNotInsideAgent(root, _target) {
|
|
3608
|
+
const data = loadAgentToml(root);
|
|
3609
|
+
if (!isAltana(data)) {
|
|
3610
|
+
return [];
|
|
3611
|
+
}
|
|
3612
|
+
const sessionFile = path14.resolve(
|
|
3613
|
+
sessionFileOf(root, tableOf2(data, "wallet"))
|
|
3614
|
+
);
|
|
3615
|
+
if (!isFile4(sessionFile)) {
|
|
3616
|
+
return [];
|
|
3617
|
+
}
|
|
3618
|
+
const agentDir = path14.resolve(agentRootOf(root));
|
|
3619
|
+
if (!sessionFile.startsWith(agentDir + path14.sep)) {
|
|
3620
|
+
return [];
|
|
3621
|
+
}
|
|
3622
|
+
return [
|
|
3623
|
+
{
|
|
3624
|
+
level: Level.CRITICAL,
|
|
3625
|
+
name: "altana_session_not_inside_agent",
|
|
3626
|
+
message: `the Altana session file ${sessionFile} is INSIDE the deploy artifact root (${agentDir}) \u2014 it contains the raw session private key and would ship in the artifact. Move it to <workspace>/.studio/wallets and set [wallet].session_file = "../../.studio/wallets/altana-session.json" (deploy injects it as the ALTANA_SESSION secret instead).`,
|
|
3627
|
+
details: { session_file: sessionFile, agent_dir: agentDir }
|
|
3628
|
+
}
|
|
3629
|
+
];
|
|
3630
|
+
}
|
|
3631
|
+
|
|
3632
|
+
// src/cli/_deploy/checks/twak.ts
|
|
3633
|
+
import * as fs16 from "fs";
|
|
3634
|
+
import * as path15 from "path";
|
|
3466
3635
|
import { envLocalPath as envLocalPath7 } from "@bnbagent/studio-runtime/config";
|
|
3467
3636
|
import { resolveTwakHome } from "@bnbagent/studio-runtime/wallet";
|
|
3468
3637
|
|
|
@@ -3505,13 +3674,13 @@ function twakUnsupportedContractOverrides(networkName, env = process.env) {
|
|
|
3505
3674
|
}
|
|
3506
3675
|
|
|
3507
3676
|
// src/cli/_deploy/checks/twak.ts
|
|
3508
|
-
var AGENTCORE_DESCRIPTOR =
|
|
3677
|
+
var AGENTCORE_DESCRIPTOR = path15.join("agentcore", "agentcore.json");
|
|
3509
3678
|
function isTwak(data) {
|
|
3510
3679
|
return tableOf2(data, "wallet").kind === "twak";
|
|
3511
3680
|
}
|
|
3512
|
-
function
|
|
3681
|
+
function isFile5(p) {
|
|
3513
3682
|
try {
|
|
3514
|
-
return
|
|
3683
|
+
return fs16.statSync(p).isFile();
|
|
3515
3684
|
} catch {
|
|
3516
3685
|
return false;
|
|
3517
3686
|
}
|
|
@@ -3524,13 +3693,13 @@ async function checkTwakRequiresContainer(root, target) {
|
|
|
3524
3693
|
if (!isTwak(data)) {
|
|
3525
3694
|
return [];
|
|
3526
3695
|
}
|
|
3527
|
-
const descriptor =
|
|
3528
|
-
if (!
|
|
3696
|
+
const descriptor = path15.join(root, AGENTCORE_DESCRIPTOR);
|
|
3697
|
+
if (!isFile5(descriptor)) {
|
|
3529
3698
|
return [];
|
|
3530
3699
|
}
|
|
3531
3700
|
let cfg;
|
|
3532
3701
|
try {
|
|
3533
|
-
cfg = JSON.parse(
|
|
3702
|
+
cfg = JSON.parse(fs16.readFileSync(descriptor, "utf-8"));
|
|
3534
3703
|
} catch {
|
|
3535
3704
|
return [];
|
|
3536
3705
|
}
|
|
@@ -3553,8 +3722,8 @@ async function checkTwakRequiresContainer(root, target) {
|
|
|
3553
3722
|
}
|
|
3554
3723
|
];
|
|
3555
3724
|
}
|
|
3556
|
-
const dockerfile =
|
|
3557
|
-
if (!
|
|
3725
|
+
const dockerfile = path15.join(agentRootOf(root), "Dockerfile");
|
|
3726
|
+
if (!isFile5(dockerfile)) {
|
|
3558
3727
|
return [
|
|
3559
3728
|
{
|
|
3560
3729
|
level: Level.BLOCKED,
|
|
@@ -3637,10 +3806,10 @@ async function checkTwakWalletExists(root, _target) {
|
|
|
3637
3806
|
const agentRoot2 = agentRootOf(root);
|
|
3638
3807
|
const walletCfg = tableOf2(data, "wallet");
|
|
3639
3808
|
const walletFile = twakWalletFile(walletCfg, agentRoot2);
|
|
3640
|
-
if (!
|
|
3809
|
+
if (!isFile5(walletFile)) {
|
|
3641
3810
|
let createCmd = "twak wallet create --password <pw> --no-keychain";
|
|
3642
3811
|
if (walletCfg.twak_home) {
|
|
3643
|
-
createCmd = `HOME=${
|
|
3812
|
+
createCmd = `HOME=${path15.dirname(path15.dirname(walletFile))} ${createCmd}`;
|
|
3644
3813
|
}
|
|
3645
3814
|
return [
|
|
3646
3815
|
{
|
|
@@ -3762,13 +3931,13 @@ async function checkTwakCredentialsAvailable(root, _target) {
|
|
|
3762
3931
|
}
|
|
3763
3932
|
const agentRoot2 = agentRootOf(root);
|
|
3764
3933
|
const walletCfg = tableOf2(data, "wallet");
|
|
3765
|
-
const credentialsFile =
|
|
3766
|
-
|
|
3934
|
+
const credentialsFile = path15.join(
|
|
3935
|
+
path15.dirname(twakWalletFile(walletCfg, agentRoot2)),
|
|
3767
3936
|
"credentials.json"
|
|
3768
3937
|
);
|
|
3769
3938
|
const envLocal = envLocalPath7(agentRoot2);
|
|
3770
3939
|
const resolvable = (key) => Boolean(process.env[key] || getEnvVar(envLocal, key));
|
|
3771
|
-
if (
|
|
3940
|
+
if (isFile5(credentialsFile)) {
|
|
3772
3941
|
return [];
|
|
3773
3942
|
}
|
|
3774
3943
|
if (resolvable("TWAK_ACCESS_ID") && resolvable("TWAK_HMAC_SECRET")) {
|
|
@@ -3785,21 +3954,21 @@ async function checkTwakCredentialsAvailable(root, _target) {
|
|
|
3785
3954
|
}
|
|
3786
3955
|
|
|
3787
3956
|
// src/cli/_deploy/fixes.ts
|
|
3788
|
-
import * as
|
|
3789
|
-
import * as
|
|
3957
|
+
import * as fs17 from "fs";
|
|
3958
|
+
import * as path16 from "path";
|
|
3790
3959
|
import { envLocalPath as envLocalPath8 } from "@bnbagent/studio-runtime/config";
|
|
3791
3960
|
function fixGitignore(root) {
|
|
3792
|
-
const ws =
|
|
3793
|
-
const gi =
|
|
3961
|
+
const ws = path16.dirname(path16.dirname(envLocalPath8(root)));
|
|
3962
|
+
const gi = path16.join(ws, ".gitignore");
|
|
3794
3963
|
const required = [".studio/"];
|
|
3795
3964
|
let exists = false;
|
|
3796
3965
|
try {
|
|
3797
|
-
exists =
|
|
3966
|
+
exists = fs17.statSync(gi).isFile();
|
|
3798
3967
|
} catch {
|
|
3799
3968
|
exists = false;
|
|
3800
3969
|
}
|
|
3801
3970
|
if (!exists) {
|
|
3802
|
-
|
|
3971
|
+
fs17.writeFileSync(gi, `${required.join("\n")}
|
|
3803
3972
|
`, "utf-8");
|
|
3804
3973
|
return {
|
|
3805
3974
|
name: "fix-gitignore",
|
|
@@ -3807,7 +3976,7 @@ function fixGitignore(root) {
|
|
|
3807
3976
|
message: `created .gitignore with ${required.length} entries`
|
|
3808
3977
|
};
|
|
3809
3978
|
}
|
|
3810
|
-
let text2 =
|
|
3979
|
+
let text2 = fs17.readFileSync(gi, "utf-8");
|
|
3811
3980
|
const existing = new Set(text2.split(/\r?\n/).map((l) => l.trim()));
|
|
3812
3981
|
const appended = required.filter((r) => !existing.has(r));
|
|
3813
3982
|
if (appended.length === 0) {
|
|
@@ -3822,7 +3991,7 @@ function fixGitignore(root) {
|
|
|
3822
3991
|
}
|
|
3823
3992
|
text2 += `${appended.join("\n")}
|
|
3824
3993
|
`;
|
|
3825
|
-
|
|
3994
|
+
fs17.writeFileSync(gi, text2, "utf-8");
|
|
3826
3995
|
return {
|
|
3827
3996
|
name: "fix-gitignore",
|
|
3828
3997
|
changed: true,
|
|
@@ -3830,10 +3999,10 @@ function fixGitignore(root) {
|
|
|
3830
3999
|
};
|
|
3831
4000
|
}
|
|
3832
4001
|
function patchTomlKv(tomlPath, section, key, value) {
|
|
3833
|
-
const text2 =
|
|
4002
|
+
const text2 = fs17.readFileSync(tomlPath, "utf-8");
|
|
3834
4003
|
const updated = updateSection(text2, section, { [key]: value });
|
|
3835
4004
|
if (updated !== text2) {
|
|
3836
|
-
|
|
4005
|
+
fs17.writeFileSync(tomlPath, updated, "utf-8");
|
|
3837
4006
|
}
|
|
3838
4007
|
}
|
|
3839
4008
|
|
|
@@ -3864,9 +4033,9 @@ var HOSTED_AGENT_REGIONS = /* @__PURE__ */ new Set([
|
|
|
3864
4033
|
"spaincentral",
|
|
3865
4034
|
"australiaeast"
|
|
3866
4035
|
]);
|
|
3867
|
-
function
|
|
4036
|
+
function isFile6(p) {
|
|
3868
4037
|
try {
|
|
3869
|
-
return
|
|
4038
|
+
return fs18.statSync(p).isFile();
|
|
3870
4039
|
} catch {
|
|
3871
4040
|
return false;
|
|
3872
4041
|
}
|
|
@@ -3883,8 +4052,8 @@ function loadStudioCfg(workspaceRoot) {
|
|
|
3883
4052
|
if (agentRoot2 === null) {
|
|
3884
4053
|
return {};
|
|
3885
4054
|
}
|
|
3886
|
-
const tomlPath =
|
|
3887
|
-
if (!
|
|
4055
|
+
const tomlPath = path17.join(agentRoot2, "studio.toml");
|
|
4056
|
+
if (!isFile6(tomlPath)) {
|
|
3888
4057
|
return {};
|
|
3889
4058
|
}
|
|
3890
4059
|
try {
|
|
@@ -3896,7 +4065,7 @@ function loadStudioCfg(workspaceRoot) {
|
|
|
3896
4065
|
function recordAzureDeployment(root, data, endpoint) {
|
|
3897
4066
|
const agentRoot2 = findSubProjectRoot7("agent", deployWorkspaceRoot(root));
|
|
3898
4067
|
if (agentRoot2 === null) return;
|
|
3899
|
-
const tomlPath =
|
|
4068
|
+
const tomlPath = path17.join(agentRoot2, "studio.toml");
|
|
3900
4069
|
try {
|
|
3901
4070
|
const name = String(data.id ?? tableOf4(data, "record").id ?? "").trim();
|
|
3902
4071
|
if (name) {
|
|
@@ -3914,7 +4083,7 @@ function recordAzureDeployment(root, data, endpoint) {
|
|
|
3914
4083
|
function clearAzureEndpoint(root) {
|
|
3915
4084
|
const agentRoot2 = findSubProjectRoot7("agent", deployWorkspaceRoot(root));
|
|
3916
4085
|
if (agentRoot2 === null) return;
|
|
3917
|
-
const tomlPath =
|
|
4086
|
+
const tomlPath = path17.join(agentRoot2, "studio.toml");
|
|
3918
4087
|
try {
|
|
3919
4088
|
for (const key of [
|
|
3920
4089
|
"agent_endpoint",
|
|
@@ -4033,7 +4202,7 @@ async function destroyAzureFoundry(opts) {
|
|
|
4033
4202
|
const extra = opts.purge ? " --purge" : "";
|
|
4034
4203
|
printOut("=== bag deploy destroy \u2014 teardown plan (dry-run) ===\n");
|
|
4035
4204
|
printOut(
|
|
4036
|
-
`project: ${
|
|
4205
|
+
`project: ${path17.basename(workspaceRoot)} (runtime: azure-foundry)
|
|
4037
4206
|
`
|
|
4038
4207
|
);
|
|
4039
4208
|
printOut("--- Agent (Foundry Hosted Agent) ---");
|
|
@@ -4076,8 +4245,8 @@ function agentTomlPath(root) {
|
|
|
4076
4245
|
if (agentRoot2 === null) {
|
|
4077
4246
|
return null;
|
|
4078
4247
|
}
|
|
4079
|
-
const tomlPath =
|
|
4080
|
-
return
|
|
4248
|
+
const tomlPath = path17.join(agentRoot2, "studio.toml");
|
|
4249
|
+
return isFile6(tomlPath) ? tomlPath : null;
|
|
4081
4250
|
}
|
|
4082
4251
|
function checkAzureBlock(root) {
|
|
4083
4252
|
const tomlPath = agentTomlPath(root);
|
|
@@ -4210,7 +4379,7 @@ var checkEntrypointAndDockerfile = async (root, _target) => {
|
|
|
4210
4379
|
];
|
|
4211
4380
|
}
|
|
4212
4381
|
const entry = "src/foundryMain.ts";
|
|
4213
|
-
if (!
|
|
4382
|
+
if (!isFile6(path17.join(agentRoot2, entry))) {
|
|
4214
4383
|
findings.push({
|
|
4215
4384
|
level: "CRITICAL",
|
|
4216
4385
|
name: "azure_agent_entrypoint",
|
|
@@ -4218,7 +4387,7 @@ var checkEntrypointAndDockerfile = async (root, _target) => {
|
|
|
4218
4387
|
details: { entrypoint: entry }
|
|
4219
4388
|
});
|
|
4220
4389
|
}
|
|
4221
|
-
if (!
|
|
4390
|
+
if (!isFile6(path17.join(agentRoot2, "Dockerfile"))) {
|
|
4222
4391
|
findings.push({
|
|
4223
4392
|
level: "CRITICAL",
|
|
4224
4393
|
name: "azure_dockerfile_present",
|
|
@@ -4264,12 +4433,15 @@ var azureFoundryChecks = [
|
|
|
4264
4433
|
checkEntrypointAndDockerfile,
|
|
4265
4434
|
checkLlmExternalProviderReady,
|
|
4266
4435
|
checkTwakPasswordEnvSet,
|
|
4267
|
-
checkTwakCredentialsAvailable
|
|
4436
|
+
checkTwakCredentialsAvailable,
|
|
4437
|
+
checkAltanaSessionReady,
|
|
4438
|
+
checkAltanaSdkResolvable,
|
|
4439
|
+
checkAltanaSessionNotInsideAgent
|
|
4268
4440
|
];
|
|
4269
4441
|
|
|
4270
4442
|
// src/cli/llm.ts
|
|
4271
|
-
import * as
|
|
4272
|
-
import * as
|
|
4443
|
+
import * as fs19 from "fs";
|
|
4444
|
+
import * as path18 from "path";
|
|
4273
4445
|
import { query as auditQuery, auditedOp } from "@bnbagent/studio-runtime/audit";
|
|
4274
4446
|
import {
|
|
4275
4447
|
envLocalPath as envLocalPath9,
|
|
@@ -4284,6 +4456,7 @@ import {
|
|
|
4284
4456
|
import { getNetwork as getNetwork4 } from "@bnbagent/studio-runtime/networks";
|
|
4285
4457
|
import * as pieverseRt from "@bnbagent/studio-runtime/pieverse";
|
|
4286
4458
|
import {
|
|
4459
|
+
PieverseKeyNotFoundError,
|
|
4287
4460
|
PieversePolicy,
|
|
4288
4461
|
RetryPolicy,
|
|
4289
4462
|
allocateWithSettleRetry,
|
|
@@ -4417,7 +4590,10 @@ function registerLlm(program) {
|
|
|
4417
4590
|
).option(
|
|
4418
4591
|
"--network <name>",
|
|
4419
4592
|
"Override [llm.pieverse].network (e.g. bsc-mainnet, bsc-testnet)."
|
|
4420
|
-
).option("--name <name>", "Key name (default: bnbagent-studio-default).").
|
|
4593
|
+
).option("--name <name>", "Key name (default: bnbagent-studio-default).").option(
|
|
4594
|
+
"--replace",
|
|
4595
|
+
"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."
|
|
4596
|
+
).action(
|
|
4421
4597
|
act(
|
|
4422
4598
|
(opts) => cmdActivate(opts)
|
|
4423
4599
|
)
|
|
@@ -4544,7 +4720,7 @@ function loadFullCfg() {
|
|
|
4544
4720
|
}
|
|
4545
4721
|
let cfg;
|
|
4546
4722
|
try {
|
|
4547
|
-
cfg = loadStudioToml8(
|
|
4723
|
+
cfg = loadStudioToml8(path18.join(root, "studio.toml"));
|
|
4548
4724
|
} catch (exc) {
|
|
4549
4725
|
printErr(`error: failed to parse studio.toml: ${errMessage(exc)}`);
|
|
4550
4726
|
return null;
|
|
@@ -4626,9 +4802,20 @@ async function cmdActivate(opts) {
|
|
|
4626
4802
|
return 2;
|
|
4627
4803
|
}
|
|
4628
4804
|
const pvCfg = loadPieverseConfig(cfg);
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
const
|
|
4805
|
+
const replace = opts.replace === true;
|
|
4806
|
+
let existingHash = !replace && pvCfg.key_hash ? String(pvCfg.key_hash) : null;
|
|
4807
|
+
const envFileValue = replace ? null : getEnvVar(envLocalPath9(root), PIEVERSE_ENV_KEY);
|
|
4808
|
+
const existingEnv = replace ? null : envFileValue || process.env[PIEVERSE_ENV_KEY];
|
|
4809
|
+
if (replace) {
|
|
4810
|
+
printOut(
|
|
4811
|
+
`\u2192 --replace: ignoring any existing ${PIEVERSE_ENV_KEY} and minting a fresh key\u2026`
|
|
4812
|
+
);
|
|
4813
|
+
if (process.env[PIEVERSE_ENV_KEY]) {
|
|
4814
|
+
printErr(
|
|
4815
|
+
`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.`
|
|
4816
|
+
);
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4632
4819
|
if (!existingHash && existingEnv) {
|
|
4633
4820
|
const derivedHash = pieverseKeyHash(existingEnv);
|
|
4634
4821
|
printOut(
|
|
@@ -4637,15 +4824,24 @@ async function cmdActivate(opts) {
|
|
|
4637
4824
|
try {
|
|
4638
4825
|
await withSiweRetry(wallet, (token) => inspectKey(token, derivedHash));
|
|
4639
4826
|
} catch (exc) {
|
|
4827
|
+
if (!(exc instanceof PieverseKeyNotFoundError)) {
|
|
4828
|
+
printErr(
|
|
4829
|
+
`error: could not verify the existing ${PIEVERSE_ENV_KEY} against Pieverse: ${errMessage(
|
|
4830
|
+
exc
|
|
4831
|
+
)}
|
|
4832
|
+
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.`
|
|
4833
|
+
);
|
|
4834
|
+
return 2;
|
|
4835
|
+
}
|
|
4640
4836
|
const sources = [
|
|
4641
4837
|
envFileValue ? `.studio/.env.local (a ${PIEVERSE_ENV_KEY}= line)` : "",
|
|
4642
4838
|
process.env[PIEVERSE_ENV_KEY] ? "the shell environment" : ""
|
|
4643
4839
|
].filter(Boolean).join(" and ");
|
|
4644
4840
|
printErr(
|
|
4645
|
-
`error: ${PIEVERSE_ENV_KEY} already exists but
|
|
4841
|
+
`error: ${PIEVERSE_ENV_KEY} already exists but Pieverse does not know its key_hash: ${errMessage(
|
|
4646
4842
|
exc
|
|
4647
4843
|
)}
|
|
4648
|
-
The existing key was kept and no new key was created. The key comes from ${sources}
|
|
4844
|
+
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.)`
|
|
4649
4845
|
);
|
|
4650
4846
|
return 2;
|
|
4651
4847
|
}
|
|
@@ -4886,9 +5082,9 @@ Retry: re-run \`bag llm activate\` \u2014 key_hash is saved so it will pick up w
|
|
|
4886
5082
|
return 0;
|
|
4887
5083
|
}
|
|
4888
5084
|
function updateStudioTomlSection(root, section, updates) {
|
|
4889
|
-
const tomlPath =
|
|
4890
|
-
const text2 =
|
|
4891
|
-
|
|
5085
|
+
const tomlPath = path18.join(root, "studio.toml");
|
|
5086
|
+
const text2 = fs19.readFileSync(tomlPath, "utf-8");
|
|
5087
|
+
fs19.writeFileSync(tomlPath, updateSection(text2, section, updates), "utf-8");
|
|
4892
5088
|
}
|
|
4893
5089
|
function cumulativeTopupsUsd() {
|
|
4894
5090
|
let total = 0;
|
|
@@ -5437,8 +5633,8 @@ function normalizeNodeDeps(deps) {
|
|
|
5437
5633
|
}
|
|
5438
5634
|
|
|
5439
5635
|
// src/cli/recipes/loader.ts
|
|
5440
|
-
import * as
|
|
5441
|
-
import * as
|
|
5636
|
+
import * as fs20 from "fs";
|
|
5637
|
+
import * as path19 from "path";
|
|
5442
5638
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
5443
5639
|
import { parse as parse5 } from "smol-toml";
|
|
5444
5640
|
var PLACEHOLDER_RE = /\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
|
|
@@ -5447,12 +5643,12 @@ function bundledRecipesRoot() {
|
|
|
5447
5643
|
if (override) {
|
|
5448
5644
|
return override;
|
|
5449
5645
|
}
|
|
5450
|
-
let dir =
|
|
5646
|
+
let dir = path19.dirname(fileURLToPath3(import.meta.url));
|
|
5451
5647
|
for (; ; ) {
|
|
5452
|
-
if (
|
|
5453
|
-
return
|
|
5648
|
+
if (fs20.existsSync(path19.join(dir, "package.json"))) {
|
|
5649
|
+
return path19.join(dir, "recipes");
|
|
5454
5650
|
}
|
|
5455
|
-
const parent =
|
|
5651
|
+
const parent = path19.dirname(dir);
|
|
5456
5652
|
if (parent === dir) {
|
|
5457
5653
|
throw new Error("cannot locate the studio-cli package root");
|
|
5458
5654
|
}
|
|
@@ -5476,24 +5672,24 @@ function defaultMode(recipe) {
|
|
|
5476
5672
|
}
|
|
5477
5673
|
function listRecipes(root) {
|
|
5478
5674
|
const base = root ?? bundledRecipesRoot();
|
|
5479
|
-
if (!
|
|
5675
|
+
if (!fs20.existsSync(base)) {
|
|
5480
5676
|
return [];
|
|
5481
5677
|
}
|
|
5482
|
-
return
|
|
5483
|
-
(name) => !name.startsWith("_") &&
|
|
5678
|
+
return fs20.readdirSync(base).filter(
|
|
5679
|
+
(name) => !name.startsWith("_") && fs20.existsSync(path19.join(base, name, "recipe.toml")) && fs20.statSync(path19.join(base, name)).isDirectory()
|
|
5484
5680
|
).sort();
|
|
5485
5681
|
}
|
|
5486
5682
|
var RecipeModeError = class extends Error {
|
|
5487
5683
|
};
|
|
5488
5684
|
function loadRecipe(name, opts = {}) {
|
|
5489
5685
|
const base = opts.root ?? bundledRecipesRoot();
|
|
5490
|
-
const recipeDir =
|
|
5491
|
-
const tomlPath =
|
|
5492
|
-
if (!
|
|
5686
|
+
const recipeDir = path19.join(base, name);
|
|
5687
|
+
const tomlPath = path19.join(recipeDir, "recipe.toml");
|
|
5688
|
+
if (!fs20.existsSync(tomlPath) || !fs20.statSync(tomlPath).isFile()) {
|
|
5493
5689
|
throw new Error(`Recipe '${name}' not found at ${tomlPath}`);
|
|
5494
5690
|
}
|
|
5495
|
-
const metadata = parse5(
|
|
5496
|
-
const allFiles = collectTemplateFiles(
|
|
5691
|
+
const metadata = parse5(fs20.readFileSync(tomlPath, "utf-8"));
|
|
5692
|
+
const allFiles = collectTemplateFiles(path19.join(recipeDir, "code"));
|
|
5497
5693
|
const modesMeta = metaTable(metadata, "modes");
|
|
5498
5694
|
const mode = opts.mode ?? null;
|
|
5499
5695
|
if (Object.keys(modesMeta).length === 0) {
|
|
@@ -5540,22 +5736,22 @@ function modeFiles(modesMeta, modeName) {
|
|
|
5540
5736
|
return Array.isArray(files) ? files.filter((f) => typeof f === "string") : [];
|
|
5541
5737
|
}
|
|
5542
5738
|
function collectTemplateFiles(codeDir) {
|
|
5543
|
-
if (!
|
|
5739
|
+
if (!fs20.existsSync(codeDir) || !fs20.statSync(codeDir).isDirectory()) {
|
|
5544
5740
|
return [];
|
|
5545
5741
|
}
|
|
5546
5742
|
const out = [];
|
|
5547
5743
|
const walk = (dir) => {
|
|
5548
|
-
for (const name of
|
|
5549
|
-
const full =
|
|
5550
|
-
if (
|
|
5744
|
+
for (const name of fs20.readdirSync(dir).sort()) {
|
|
5745
|
+
const full = path19.join(dir, name);
|
|
5746
|
+
if (fs20.statSync(full).isDirectory()) {
|
|
5551
5747
|
walk(full);
|
|
5552
5748
|
} else {
|
|
5553
|
-
const rel =
|
|
5749
|
+
const rel = path19.relative(codeDir, full);
|
|
5554
5750
|
const target = rel.endsWith(".tmpl") ? rel.slice(0, -".tmpl".length) : rel;
|
|
5555
5751
|
out.push({
|
|
5556
5752
|
// Recipes use forward slashes regardless of host OS.
|
|
5557
|
-
targetPath: target.split(
|
|
5558
|
-
content:
|
|
5753
|
+
targetPath: target.split(path19.sep).join("/"),
|
|
5754
|
+
content: fs20.readFileSync(full, "utf-8")
|
|
5559
5755
|
});
|
|
5560
5756
|
}
|
|
5561
5757
|
}
|
|
@@ -5622,9 +5818,9 @@ function renderRecipe(recipe, opts = {}) {
|
|
|
5622
5818
|
|
|
5623
5819
|
// src/cli/skillsInstaller.ts
|
|
5624
5820
|
import * as crypto3 from "crypto";
|
|
5625
|
-
import * as
|
|
5821
|
+
import * as fs21 from "fs";
|
|
5626
5822
|
import * as os2 from "os";
|
|
5627
|
-
import * as
|
|
5823
|
+
import * as path20 from "path";
|
|
5628
5824
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
5629
5825
|
var SUPPORTED_TARGETS = ["claude-code", "cursor"];
|
|
5630
5826
|
var SUPPORTED_SCOPES = ["user", "project"];
|
|
@@ -5671,14 +5867,14 @@ var HIDDEN_SKILL_NAMES = /* @__PURE__ */ new Set([
|
|
|
5671
5867
|
]);
|
|
5672
5868
|
function isDir3(p) {
|
|
5673
5869
|
try {
|
|
5674
|
-
return
|
|
5870
|
+
return fs21.statSync(p).isDirectory();
|
|
5675
5871
|
} catch {
|
|
5676
5872
|
return false;
|
|
5677
5873
|
}
|
|
5678
5874
|
}
|
|
5679
|
-
function
|
|
5875
|
+
function isFile7(p) {
|
|
5680
5876
|
try {
|
|
5681
|
-
return
|
|
5877
|
+
return fs21.statSync(p).isFile();
|
|
5682
5878
|
} catch {
|
|
5683
5879
|
return false;
|
|
5684
5880
|
}
|
|
@@ -5688,15 +5884,15 @@ function sha256(text2) {
|
|
|
5688
5884
|
}
|
|
5689
5885
|
function resolveSkillsSource() {
|
|
5690
5886
|
const pkgRoot = packageRoot2();
|
|
5691
|
-
return pkgRoot !== null ?
|
|
5887
|
+
return pkgRoot !== null ? path20.join(pkgRoot, "skills") : path20.join(path20.dirname(fileURLToPath4(import.meta.url)), "skills");
|
|
5692
5888
|
}
|
|
5693
5889
|
function packageRoot2() {
|
|
5694
|
-
let dir =
|
|
5890
|
+
let dir = path20.dirname(fileURLToPath4(import.meta.url));
|
|
5695
5891
|
for (; ; ) {
|
|
5696
|
-
if (
|
|
5892
|
+
if (fs21.existsSync(path20.join(dir, "package.json"))) {
|
|
5697
5893
|
return dir;
|
|
5698
5894
|
}
|
|
5699
|
-
const parent =
|
|
5895
|
+
const parent = path20.dirname(dir);
|
|
5700
5896
|
if (parent === dir) {
|
|
5701
5897
|
return null;
|
|
5702
5898
|
}
|
|
@@ -5708,18 +5904,18 @@ function listSourceSkills(source) {
|
|
|
5708
5904
|
if (!isDir3(source)) {
|
|
5709
5905
|
return [];
|
|
5710
5906
|
}
|
|
5711
|
-
return
|
|
5712
|
-
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) &&
|
|
5713
|
-
).sort().map((name) =>
|
|
5907
|
+
return fs21.readdirSync(source).filter(
|
|
5908
|
+
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) && isFile7(path20.join(source, name))
|
|
5909
|
+
).sort().map((name) => path20.join(source, name));
|
|
5714
5910
|
}
|
|
5715
5911
|
function listSourceReferences(source) {
|
|
5716
|
-
const refs =
|
|
5912
|
+
const refs = path20.join(source, "references");
|
|
5717
5913
|
if (!isDir3(refs)) {
|
|
5718
5914
|
return [];
|
|
5719
5915
|
}
|
|
5720
|
-
return
|
|
5721
|
-
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) &&
|
|
5722
|
-
).sort().map((name) =>
|
|
5916
|
+
return fs21.readdirSync(refs).filter(
|
|
5917
|
+
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) && isFile7(path20.join(refs, name))
|
|
5918
|
+
).sort().map((name) => path20.join(refs, name));
|
|
5723
5919
|
}
|
|
5724
5920
|
function stem(fileName) {
|
|
5725
5921
|
return fileName.replace(/\.[^.]+$/, "");
|
|
@@ -5727,15 +5923,15 @@ function stem(fileName) {
|
|
|
5727
5923
|
function whichSync(name) {
|
|
5728
5924
|
const pathEnv = process.env.PATH ?? "";
|
|
5729
5925
|
const exts = process.platform === "win32" ? ["", ".cmd", ".exe", ".bat"] : [""];
|
|
5730
|
-
for (const dir of pathEnv.split(
|
|
5926
|
+
for (const dir of pathEnv.split(path20.delimiter)) {
|
|
5731
5927
|
if (!dir) {
|
|
5732
5928
|
continue;
|
|
5733
5929
|
}
|
|
5734
5930
|
for (const ext of exts) {
|
|
5735
|
-
const candidate =
|
|
5931
|
+
const candidate = path20.join(dir, name + ext);
|
|
5736
5932
|
try {
|
|
5737
|
-
|
|
5738
|
-
if (
|
|
5933
|
+
fs21.accessSync(candidate, fs21.constants.X_OK);
|
|
5934
|
+
if (fs21.statSync(candidate).isFile()) {
|
|
5739
5935
|
return candidate;
|
|
5740
5936
|
}
|
|
5741
5937
|
} catch {
|
|
@@ -5746,14 +5942,14 @@ function whichSync(name) {
|
|
|
5746
5942
|
}
|
|
5747
5943
|
function claudeCodeInstalled(opts = {}) {
|
|
5748
5944
|
const home = opts.home ?? os2.homedir();
|
|
5749
|
-
if (isDir3(
|
|
5945
|
+
if (isDir3(path20.join(home, ".claude"))) {
|
|
5750
5946
|
return true;
|
|
5751
5947
|
}
|
|
5752
5948
|
return (opts.which ?? whichSync)("claude") !== null;
|
|
5753
5949
|
}
|
|
5754
5950
|
function cursorInstalled(opts = {}) {
|
|
5755
5951
|
const home = opts.home ?? os2.homedir();
|
|
5756
|
-
if (isDir3(
|
|
5952
|
+
if (isDir3(path20.join(home, ".cursor"))) {
|
|
5757
5953
|
return true;
|
|
5758
5954
|
}
|
|
5759
5955
|
return (opts.which ?? whichSync)("cursor") !== null;
|
|
@@ -5776,9 +5972,9 @@ function anySkillsInstalled(opts = {}) {
|
|
|
5776
5972
|
for (const target of detectTargets(opts)) {
|
|
5777
5973
|
const tdir = resolveTargetDir({ target, scope: "user", home: opts.home });
|
|
5778
5974
|
for (const skill of sources) {
|
|
5779
|
-
const name = stem(
|
|
5780
|
-
const rel = target === "claude-code" ?
|
|
5781
|
-
if (
|
|
5975
|
+
const name = stem(path20.basename(skill));
|
|
5976
|
+
const rel = target === "claude-code" ? path20.join(name, "SKILL.md") : `${name}.mdc`;
|
|
5977
|
+
if (isFile7(path20.join(tdir, rel))) {
|
|
5782
5978
|
return true;
|
|
5783
5979
|
}
|
|
5784
5980
|
}
|
|
@@ -5803,7 +5999,7 @@ function resolveTargetDir(opts) {
|
|
|
5803
5999
|
}
|
|
5804
6000
|
const base = scope === "user" ? opts.home ?? os2.homedir() : opts.projectRoot ?? process.cwd();
|
|
5805
6001
|
const [d1, d2] = TARGET_SUBDIR[target];
|
|
5806
|
-
return
|
|
6002
|
+
return path20.join(base, d1, d2);
|
|
5807
6003
|
}
|
|
5808
6004
|
function splitFrontmatter(text2) {
|
|
5809
6005
|
const lines = text2.split("\n");
|
|
@@ -5861,16 +6057,16 @@ function iterRenderedPayloads(src, target) {
|
|
|
5861
6057
|
for (const skill of listSourceSkills(src)) {
|
|
5862
6058
|
payloads.push(
|
|
5863
6059
|
renderSkillPayload(
|
|
5864
|
-
|
|
5865
|
-
stem(
|
|
6060
|
+
fs21.readFileSync(skill, "utf-8"),
|
|
6061
|
+
stem(path20.basename(skill)),
|
|
5866
6062
|
target
|
|
5867
6063
|
)
|
|
5868
6064
|
);
|
|
5869
6065
|
}
|
|
5870
6066
|
for (const ref of listSourceReferences(src)) {
|
|
5871
6067
|
payloads.push([
|
|
5872
|
-
`${ROUTER_SKILL_NAME}/references/${
|
|
5873
|
-
|
|
6068
|
+
`${ROUTER_SKILL_NAME}/references/${path20.basename(ref)}`,
|
|
6069
|
+
fs21.readFileSync(ref, "utf-8")
|
|
5874
6070
|
]);
|
|
5875
6071
|
}
|
|
5876
6072
|
return payloads;
|
|
@@ -5882,7 +6078,7 @@ function packageVersion() {
|
|
|
5882
6078
|
return "unknown";
|
|
5883
6079
|
}
|
|
5884
6080
|
const pkg = JSON.parse(
|
|
5885
|
-
|
|
6081
|
+
fs21.readFileSync(path20.join(root, "package.json"), "utf-8")
|
|
5886
6082
|
);
|
|
5887
6083
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
5888
6084
|
} catch {
|
|
@@ -5901,11 +6097,11 @@ function contentKey(payloads) {
|
|
|
5901
6097
|
return h.digest("hex");
|
|
5902
6098
|
}
|
|
5903
6099
|
function metaPath(tdir) {
|
|
5904
|
-
return
|
|
6100
|
+
return path20.join(tdir, ROUTER_SKILL_NAME, META_FILENAME);
|
|
5905
6101
|
}
|
|
5906
6102
|
function loadMeta(tdir) {
|
|
5907
6103
|
try {
|
|
5908
|
-
const data = JSON.parse(
|
|
6104
|
+
const data = JSON.parse(fs21.readFileSync(metaPath(tdir), "utf-8"));
|
|
5909
6105
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
5910
6106
|
} catch {
|
|
5911
6107
|
return null;
|
|
@@ -5922,15 +6118,15 @@ function writeMeta(tdir, payloads) {
|
|
|
5922
6118
|
package_version: packageVersion()
|
|
5923
6119
|
};
|
|
5924
6120
|
const p = metaPath(tdir);
|
|
5925
|
-
|
|
5926
|
-
|
|
6121
|
+
fs21.mkdirSync(path20.dirname(p), { recursive: true });
|
|
6122
|
+
fs21.writeFileSync(p, `${JSON.stringify(meta, null, 2)}
|
|
5927
6123
|
`);
|
|
5928
6124
|
}
|
|
5929
6125
|
function installedMarker(tdir, target) {
|
|
5930
6126
|
if (target === "cursor") {
|
|
5931
|
-
return
|
|
6127
|
+
return path20.join(tdir, `${ROUTER_SKILL_NAME}.mdc`);
|
|
5932
6128
|
}
|
|
5933
|
-
return
|
|
6129
|
+
return path20.join(tdir, ROUTER_SKILL_NAME, "SKILL.md");
|
|
5934
6130
|
}
|
|
5935
6131
|
function syncInstalledSkills(opts = {}) {
|
|
5936
6132
|
const src = opts.source ?? SKILLS_SOURCE;
|
|
@@ -5944,7 +6140,7 @@ function syncInstalledSkills(opts = {}) {
|
|
|
5944
6140
|
home: opts.home,
|
|
5945
6141
|
projectRoot: opts.projectRoot
|
|
5946
6142
|
});
|
|
5947
|
-
if (!
|
|
6143
|
+
if (!isFile7(installedMarker(tdir, target))) {
|
|
5948
6144
|
continue;
|
|
5949
6145
|
}
|
|
5950
6146
|
if (payloads === null) {
|
|
@@ -5967,15 +6163,15 @@ function syncOneDir(tdir, payloads) {
|
|
|
5967
6163
|
const wrote = [];
|
|
5968
6164
|
const keptEdited = [];
|
|
5969
6165
|
for (const [rel, content] of payloads) {
|
|
5970
|
-
const dest =
|
|
6166
|
+
const dest = path20.join(tdir, rel);
|
|
5971
6167
|
const newHash = sha256(content);
|
|
5972
|
-
const cur =
|
|
6168
|
+
const cur = isFile7(dest) ? sha256(fs21.readFileSync(dest, "utf-8")) : null;
|
|
5973
6169
|
if (cur === newHash) {
|
|
5974
6170
|
continue;
|
|
5975
6171
|
}
|
|
5976
6172
|
if (cur === null || cur === recordedFiles[rel]) {
|
|
5977
|
-
|
|
5978
|
-
|
|
6173
|
+
fs21.mkdirSync(path20.dirname(dest), { recursive: true });
|
|
6174
|
+
fs21.writeFileSync(dest, content);
|
|
5979
6175
|
wrote.push(rel);
|
|
5980
6176
|
} else {
|
|
5981
6177
|
keptEdited.push(rel);
|
|
@@ -5986,15 +6182,15 @@ function syncOneDir(tdir, payloads) {
|
|
|
5986
6182
|
if (shipped.has(rel)) {
|
|
5987
6183
|
continue;
|
|
5988
6184
|
}
|
|
5989
|
-
const dest =
|
|
6185
|
+
const dest = path20.join(tdir, rel);
|
|
5990
6186
|
try {
|
|
5991
|
-
if (
|
|
5992
|
-
|
|
6187
|
+
if (isFile7(dest) && sha256(fs21.readFileSync(dest, "utf-8")) === recorded) {
|
|
6188
|
+
fs21.unlinkSync(dest);
|
|
5993
6189
|
wrote.push(`removed ${rel}`);
|
|
5994
|
-
let parent =
|
|
5995
|
-
while (parent !== tdir && isDir3(parent) &&
|
|
5996
|
-
|
|
5997
|
-
parent =
|
|
6190
|
+
let parent = path20.dirname(dest);
|
|
6191
|
+
while (parent !== tdir && isDir3(parent) && fs21.readdirSync(parent).length === 0) {
|
|
6192
|
+
fs21.rmdirSync(parent);
|
|
6193
|
+
parent = path20.dirname(parent);
|
|
5998
6194
|
}
|
|
5999
6195
|
}
|
|
6000
6196
|
} catch {
|
|
@@ -6024,45 +6220,45 @@ function installSkills(opts) {
|
|
|
6024
6220
|
projectRoot: opts.projectRoot,
|
|
6025
6221
|
home: opts.home
|
|
6026
6222
|
});
|
|
6027
|
-
|
|
6223
|
+
fs21.mkdirSync(tdir, { recursive: true });
|
|
6028
6224
|
const installed = [];
|
|
6029
6225
|
const skipped = [];
|
|
6030
6226
|
for (const skill of skillFiles) {
|
|
6031
|
-
const skillName = stem(
|
|
6032
|
-
const srcText =
|
|
6227
|
+
const skillName = stem(path20.basename(skill));
|
|
6228
|
+
const srcText = fs21.readFileSync(skill, "utf-8");
|
|
6033
6229
|
const [relPath, content] = renderSkillPayload(srcText, skillName, target);
|
|
6034
|
-
const dest =
|
|
6035
|
-
|
|
6036
|
-
if (
|
|
6230
|
+
const dest = path20.join(tdir, relPath);
|
|
6231
|
+
fs21.mkdirSync(path20.dirname(dest), { recursive: true });
|
|
6232
|
+
if (isFile7(dest) && sha256(fs21.readFileSync(dest, "utf-8")) === sha256(content)) {
|
|
6037
6233
|
skipped.push(skillName);
|
|
6038
6234
|
} else {
|
|
6039
|
-
|
|
6235
|
+
fs21.writeFileSync(dest, content);
|
|
6040
6236
|
installed.push(skillName);
|
|
6041
6237
|
}
|
|
6042
6238
|
if (target === "claude-code") {
|
|
6043
|
-
const legacyFlat =
|
|
6044
|
-
if (
|
|
6045
|
-
|
|
6239
|
+
const legacyFlat = path20.join(tdir, path20.basename(skill));
|
|
6240
|
+
if (isFile7(legacyFlat)) {
|
|
6241
|
+
fs21.unlinkSync(legacyFlat);
|
|
6046
6242
|
}
|
|
6047
6243
|
}
|
|
6048
6244
|
}
|
|
6049
6245
|
for (const ref of listSourceReferences(src)) {
|
|
6050
|
-
const rel = `${ROUTER_SKILL_NAME}/references/${
|
|
6051
|
-
const dest =
|
|
6052
|
-
|
|
6053
|
-
const content =
|
|
6054
|
-
if (
|
|
6246
|
+
const rel = `${ROUTER_SKILL_NAME}/references/${path20.basename(ref)}`;
|
|
6247
|
+
const dest = path20.join(tdir, rel);
|
|
6248
|
+
fs21.mkdirSync(path20.dirname(dest), { recursive: true });
|
|
6249
|
+
const content = fs21.readFileSync(ref, "utf-8");
|
|
6250
|
+
if (isFile7(dest) && sha256(fs21.readFileSync(dest, "utf-8")) === sha256(content)) {
|
|
6055
6251
|
skipped.push(rel);
|
|
6056
6252
|
} else {
|
|
6057
|
-
|
|
6253
|
+
fs21.writeFileSync(dest, content);
|
|
6058
6254
|
installed.push(rel);
|
|
6059
6255
|
}
|
|
6060
6256
|
}
|
|
6061
|
-
if (isDir3(
|
|
6257
|
+
if (isDir3(path20.join(tdir, ROUTER_SKILL_NAME))) {
|
|
6062
6258
|
writeMeta(tdir, iterRenderedPayloads(src, target));
|
|
6063
6259
|
}
|
|
6064
|
-
const legacy = target === "claude-code" ? LEGACY_SKILL_NAMES.filter((name) => isDir3(
|
|
6065
|
-
(name) =>
|
|
6260
|
+
const legacy = target === "claude-code" ? LEGACY_SKILL_NAMES.filter((name) => isDir3(path20.join(tdir, name))) : LEGACY_SKILL_NAMES.filter(
|
|
6261
|
+
(name) => isFile7(path20.join(tdir, `${name}.mdc`))
|
|
6066
6262
|
);
|
|
6067
6263
|
return {
|
|
6068
6264
|
target,
|
|
@@ -6088,9 +6284,9 @@ function acceptChoices(option, accepted, advertised) {
|
|
|
6088
6284
|
}
|
|
6089
6285
|
|
|
6090
6286
|
// src/cli/wallet.ts
|
|
6091
|
-
import * as
|
|
6287
|
+
import * as fs23 from "fs";
|
|
6092
6288
|
import * as os3 from "os";
|
|
6093
|
-
import * as
|
|
6289
|
+
import * as path22 from "path";
|
|
6094
6290
|
import { EVMWalletProvider, SigningPolicy } from "@bnbagent/sdk";
|
|
6095
6291
|
import {
|
|
6096
6292
|
envLocalPath as envLocalPath10,
|
|
@@ -6100,14 +6296,16 @@ import {
|
|
|
6100
6296
|
import { buildPolicy, buildWallet } from "@bnbagent/studio-runtime/wallet";
|
|
6101
6297
|
|
|
6102
6298
|
// src/cli/walletSession.ts
|
|
6103
|
-
import * as
|
|
6104
|
-
import * as
|
|
6299
|
+
import * as fs22 from "fs";
|
|
6300
|
+
import * as path21 from "path";
|
|
6301
|
+
import { pathToFileURL } from "url";
|
|
6105
6302
|
import { AltanaWalletProvider } from "@bnbagent/sdk";
|
|
6106
6303
|
import { getAddress as deployedAddresses } from "@bnbagent/sdk/networks";
|
|
6107
6304
|
import {
|
|
6108
6305
|
defaultAgentPermissions,
|
|
6109
6306
|
deserializeSession,
|
|
6110
|
-
serializeSession
|
|
6307
|
+
serializeSession,
|
|
6308
|
+
setAltanaSdkImporter
|
|
6111
6309
|
} from "@bnbagent/sdk/wallets";
|
|
6112
6310
|
import { auditedOp as auditedOp2 } from "@bnbagent/studio-runtime/audit";
|
|
6113
6311
|
import { loadStudioToml as loadStudioToml9 } from "@bnbagent/studio-runtime/config";
|
|
@@ -6115,7 +6313,8 @@ import { getNetwork as getNetwork5, toRaw as toRaw2 } from "@bnbagent/studio-run
|
|
|
6115
6313
|
import { writePrivate } from "@bnbagent/studio-runtime/secretWrite";
|
|
6116
6314
|
import {
|
|
6117
6315
|
ALTANA_NETWORK_BY_STUDIO,
|
|
6118
|
-
PASSWORD_ENV
|
|
6316
|
+
PASSWORD_ENV,
|
|
6317
|
+
resolveProjectAltanaSdkEntry as resolveProjectAltanaSdkEntry2
|
|
6119
6318
|
} from "@bnbagent/studio-runtime/wallet";
|
|
6120
6319
|
var defaultAdminFactory = (opts) => AltanaWalletProvider.adminFromKeystore(opts);
|
|
6121
6320
|
var adminFactory = defaultAdminFactory;
|
|
@@ -6124,13 +6323,17 @@ function tableOf7(value) {
|
|
|
6124
6323
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
6125
6324
|
}
|
|
6126
6325
|
function loadContext(projectRoot) {
|
|
6127
|
-
const cfg = loadStudioToml9(
|
|
6326
|
+
const cfg = loadStudioToml9(path21.join(projectRoot, "studio.toml"));
|
|
6128
6327
|
const walletCfg = tableOf7(cfg.wallet);
|
|
6129
6328
|
if (String(walletCfg.kind ?? "evm-local") !== "altana") {
|
|
6130
6329
|
throw new Error(
|
|
6131
6330
|
`wallet session commands require [wallet].kind='altana' (got ${JSON.stringify(walletCfg.kind ?? "evm-local")}).`
|
|
6132
6331
|
);
|
|
6133
6332
|
}
|
|
6333
|
+
const sdkEntry = resolveProjectAltanaSdkEntry2(projectRoot);
|
|
6334
|
+
setAltanaSdkImporter(
|
|
6335
|
+
sdkEntry === null ? null : () => import(pathToFileURL(sdkEntry).href)
|
|
6336
|
+
);
|
|
6134
6337
|
const networkName = String(tableOf7(cfg.network).default ?? "bsc-testnet");
|
|
6135
6338
|
const altanaNetwork = ALTANA_NETWORK_BY_STUDIO[networkName];
|
|
6136
6339
|
if (altanaNetwork === void 0) {
|
|
@@ -6146,7 +6349,7 @@ function loadContext(projectRoot) {
|
|
|
6146
6349
|
}
|
|
6147
6350
|
const resolvePath = (value, fallback) => {
|
|
6148
6351
|
const configured = String(value ?? fallback);
|
|
6149
|
-
return
|
|
6352
|
+
return path21.isAbsolute(configured) ? configured : path21.join(projectRoot, configured);
|
|
6150
6353
|
};
|
|
6151
6354
|
return {
|
|
6152
6355
|
projectRoot,
|
|
@@ -6210,7 +6413,7 @@ function parseSessionEnvelope(serialized) {
|
|
|
6210
6413
|
function readSession(ctx) {
|
|
6211
6414
|
let serialized;
|
|
6212
6415
|
try {
|
|
6213
|
-
serialized =
|
|
6416
|
+
serialized = fs22.readFileSync(ctx.sessionFile, "utf8");
|
|
6214
6417
|
} catch {
|
|
6215
6418
|
throw new Error(
|
|
6216
6419
|
`no Altana session file at ${ctx.sessionFile} \u2014 run \`bag wallet session grant\`.`
|
|
@@ -6219,8 +6422,8 @@ function readSession(ctx) {
|
|
|
6219
6422
|
return { serialized, envelope: parseSessionEnvelope(serialized) };
|
|
6220
6423
|
}
|
|
6221
6424
|
function writeSession(ctx, session) {
|
|
6222
|
-
|
|
6223
|
-
|
|
6425
|
+
fs22.mkdirSync(path21.dirname(ctx.sessionFile), { recursive: true, mode: 448 });
|
|
6426
|
+
fs22.chmodSync(path21.dirname(ctx.sessionFile), 448);
|
|
6224
6427
|
writePrivate(ctx.sessionFile, serializeSession(session));
|
|
6225
6428
|
}
|
|
6226
6429
|
function sessionKeyFingerprint(publicKey) {
|
|
@@ -6331,7 +6534,7 @@ async function cmdSessionGrant(opts) {
|
|
|
6331
6534
|
"--budget-u"
|
|
6332
6535
|
);
|
|
6333
6536
|
let existing = null;
|
|
6334
|
-
if (
|
|
6537
|
+
if (fs22.existsSync(ctx.sessionFile)) {
|
|
6335
6538
|
existing = readSession(ctx).envelope;
|
|
6336
6539
|
if (!opts.force) {
|
|
6337
6540
|
throw new Error(
|
|
@@ -6449,7 +6652,7 @@ async function cmdSessionRevoke(opts) {
|
|
|
6449
6652
|
await admin.revokeSession(envelope.publicKey);
|
|
6450
6653
|
}
|
|
6451
6654
|
);
|
|
6452
|
-
|
|
6655
|
+
fs22.unlinkSync(ctx.sessionFile);
|
|
6453
6656
|
printErr(`\u2713 Altana session revoked and removed: ${ctx.sessionFile}`);
|
|
6454
6657
|
return 0;
|
|
6455
6658
|
}
|
|
@@ -6573,8 +6776,8 @@ var ProjectRootNotFound = class extends Error {
|
|
|
6573
6776
|
};
|
|
6574
6777
|
function resolveWalletProjectRoot(argRoot) {
|
|
6575
6778
|
if (argRoot != null) {
|
|
6576
|
-
const root2 =
|
|
6577
|
-
if (!
|
|
6779
|
+
const root2 = path22.resolve(argRoot);
|
|
6780
|
+
if (!isFile8(path22.join(root2, "studio.toml"))) {
|
|
6578
6781
|
throw new ProjectRootNotFound(
|
|
6579
6782
|
`No studio.toml found under --project-root ${root2}`
|
|
6580
6783
|
);
|
|
@@ -6589,15 +6792,15 @@ function resolveWalletProjectRoot(argRoot) {
|
|
|
6589
6792
|
}
|
|
6590
6793
|
return root;
|
|
6591
6794
|
}
|
|
6592
|
-
function
|
|
6795
|
+
function isFile8(p) {
|
|
6593
6796
|
try {
|
|
6594
|
-
return
|
|
6797
|
+
return fs23.statSync(p).isFile();
|
|
6595
6798
|
} catch {
|
|
6596
6799
|
return false;
|
|
6597
6800
|
}
|
|
6598
6801
|
}
|
|
6599
6802
|
function loadWalletCfg(projectRoot) {
|
|
6600
|
-
const data = loadStudioToml10(
|
|
6803
|
+
const data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
6601
6804
|
const wallet = data.wallet;
|
|
6602
6805
|
return wallet !== null && typeof wallet === "object" && !Array.isArray(wallet) ? wallet : {};
|
|
6603
6806
|
}
|
|
@@ -6607,7 +6810,7 @@ function walletKind(walletCfg) {
|
|
|
6607
6810
|
function projectNetwork(projectRoot) {
|
|
6608
6811
|
let data;
|
|
6609
6812
|
try {
|
|
6610
|
-
data = loadStudioToml10(
|
|
6813
|
+
data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
6611
6814
|
} catch {
|
|
6612
6815
|
return "bsc-testnet";
|
|
6613
6816
|
}
|
|
@@ -6646,12 +6849,12 @@ function requireDurablePassword(projectRoot) {
|
|
|
6646
6849
|
return password;
|
|
6647
6850
|
}
|
|
6648
6851
|
function persistAddress(projectRoot, address) {
|
|
6649
|
-
const tomlPath =
|
|
6650
|
-
if (!
|
|
6852
|
+
const tomlPath = path22.join(projectRoot, "studio.toml");
|
|
6853
|
+
if (!isFile8(tomlPath)) {
|
|
6651
6854
|
return;
|
|
6652
6855
|
}
|
|
6653
|
-
const text2 =
|
|
6654
|
-
|
|
6856
|
+
const text2 = fs23.readFileSync(tomlPath, "utf-8");
|
|
6857
|
+
fs23.writeFileSync(
|
|
6655
6858
|
tomlPath,
|
|
6656
6859
|
updateSection(text2, "wallet", { address }),
|
|
6657
6860
|
"utf-8"
|
|
@@ -6667,7 +6870,7 @@ function resolveKeystoreDir2(projectRoot, cliOverride, walletCfg) {
|
|
|
6667
6870
|
} else {
|
|
6668
6871
|
d = ".studio/wallets";
|
|
6669
6872
|
}
|
|
6670
|
-
return
|
|
6873
|
+
return path22.isAbsolute(d) ? d : path22.join(projectRoot, d);
|
|
6671
6874
|
}
|
|
6672
6875
|
async function resolvePrivateKeyArg(raw) {
|
|
6673
6876
|
if (raw === void 0 || raw === false) {
|
|
@@ -6782,7 +6985,7 @@ async function cmdNew(opts) {
|
|
|
6782
6985
|
projectRoot = process.cwd();
|
|
6783
6986
|
}
|
|
6784
6987
|
let walletCfg = {};
|
|
6785
|
-
if (
|
|
6988
|
+
if (isFile8(path22.join(projectRoot, "studio.toml"))) {
|
|
6786
6989
|
walletCfg = loadWalletCfg(projectRoot);
|
|
6787
6990
|
}
|
|
6788
6991
|
const kind = walletKind(walletCfg);
|
|
@@ -6796,7 +6999,7 @@ async function cmdNew(opts) {
|
|
|
6796
6999
|
opts.keystoreDir,
|
|
6797
7000
|
walletCfg
|
|
6798
7001
|
);
|
|
6799
|
-
|
|
7002
|
+
fs23.mkdirSync(keystoreDir, { recursive: true });
|
|
6800
7003
|
const provider = new EVMWalletProvider({
|
|
6801
7004
|
password,
|
|
6802
7005
|
...privateKey !== null ? { privateKey } : {},
|
|
@@ -6806,7 +7009,7 @@ async function cmdNew(opts) {
|
|
|
6806
7009
|
persistAddress(projectRoot, provider.address);
|
|
6807
7010
|
if (kind === "altana") {
|
|
6808
7011
|
printErr(
|
|
6809
|
-
"Altana admin keystore created. Fund this address with about 0.
|
|
7012
|
+
"Altana admin keystore created. Fund this address with about 0.05 tBNB for testnet bootstrap/registration, then run `bag wallet session grant` to create the bounded runtime session."
|
|
6810
7013
|
);
|
|
6811
7014
|
}
|
|
6812
7015
|
return 0;
|
|
@@ -6820,11 +7023,11 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6820
7023
|
return 1;
|
|
6821
7024
|
}
|
|
6822
7025
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
6823
|
-
if (!
|
|
7026
|
+
if (!isFile8(walletFile)) {
|
|
6824
7027
|
let createCmd = "twak wallet create --password <your-password> --no-keychain";
|
|
6825
7028
|
let setupCmd = "twak setup";
|
|
6826
7029
|
if (walletCfg.twak_home) {
|
|
6827
|
-
const home =
|
|
7030
|
+
const home = path22.dirname(path22.dirname(walletFile));
|
|
6828
7031
|
createCmd = `HOME=${home} ${createCmd}`;
|
|
6829
7032
|
setupCmd = `HOME=${home} ${setupCmd}`;
|
|
6830
7033
|
}
|
|
@@ -6850,23 +7053,23 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6850
7053
|
return 0;
|
|
6851
7054
|
}
|
|
6852
7055
|
function ensureTwakCredentials(walletFile, homeDir) {
|
|
6853
|
-
const twakDir =
|
|
6854
|
-
const target =
|
|
6855
|
-
if (
|
|
7056
|
+
const twakDir = path22.dirname(walletFile);
|
|
7057
|
+
const target = path22.join(twakDir, "credentials.json");
|
|
7058
|
+
if (isFile8(target)) {
|
|
6856
7059
|
return true;
|
|
6857
7060
|
}
|
|
6858
|
-
const machine =
|
|
6859
|
-
if (
|
|
7061
|
+
const machine = path22.join(os3.homedir(), ".twak", "credentials.json");
|
|
7062
|
+
if (path22.resolve(machine) === path22.resolve(target) || !isFile8(machine)) {
|
|
6860
7063
|
printErr(
|
|
6861
7064
|
`error: no Trust Wallet NaaS credentials for this wallet home \u2014 ${target} is missing. Get an Access ID + HMAC secret from https://portal.trustwallet.com/dashboard/apps, run \`HOME=${homeDir} twak setup\` once, then re-run this command.`
|
|
6862
7065
|
);
|
|
6863
7066
|
return false;
|
|
6864
7067
|
}
|
|
6865
|
-
|
|
6866
|
-
|
|
7068
|
+
fs23.mkdirSync(twakDir, { recursive: true });
|
|
7069
|
+
fs23.writeFileSync(target, fs23.readFileSync(machine, "utf-8"), { mode: 384 });
|
|
6867
7070
|
try {
|
|
6868
|
-
|
|
6869
|
-
|
|
7071
|
+
fs23.chmodSync(twakDir, 448);
|
|
7072
|
+
fs23.chmodSync(target, 384);
|
|
6870
7073
|
} catch {
|
|
6871
7074
|
}
|
|
6872
7075
|
printErr(`note: copied NaaS credentials from ${machine} into ${twakDir}.`);
|
|
@@ -6878,10 +7081,10 @@ async function resolveTwakInitPassword(opts) {
|
|
|
6878
7081
|
throw new CliExit(2);
|
|
6879
7082
|
}
|
|
6880
7083
|
if (opts.passwordFile) {
|
|
6881
|
-
const file =
|
|
7084
|
+
const file = path22.resolve(opts.passwordFile);
|
|
6882
7085
|
let mode;
|
|
6883
7086
|
try {
|
|
6884
|
-
mode =
|
|
7087
|
+
mode = fs23.statSync(file).mode;
|
|
6885
7088
|
} catch {
|
|
6886
7089
|
printErr(`error: cannot read --password-file ${file}.`);
|
|
6887
7090
|
throw new CliExit(2);
|
|
@@ -6892,7 +7095,7 @@ async function resolveTwakInitPassword(opts) {
|
|
|
6892
7095
|
);
|
|
6893
7096
|
throw new CliExit(2);
|
|
6894
7097
|
}
|
|
6895
|
-
const password = (
|
|
7098
|
+
const password = (fs23.readFileSync(file, "utf-8").split(/\r?\n/)[0] ?? "").trim();
|
|
6896
7099
|
if (!password) {
|
|
6897
7100
|
printErr(`error: --password-file ${file} is empty.`);
|
|
6898
7101
|
throw new CliExit(2);
|
|
@@ -6945,15 +7148,15 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6945
7148
|
return 1;
|
|
6946
7149
|
}
|
|
6947
7150
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
6948
|
-
if (
|
|
7151
|
+
if (isFile8(walletFile)) {
|
|
6949
7152
|
printErr(
|
|
6950
7153
|
`error: a twak wallet already exists at ${walletFile} \u2014 nothing to create. Run \`bag wallet new\` to adopt its address into studio.toml.`
|
|
6951
7154
|
);
|
|
6952
7155
|
return 1;
|
|
6953
7156
|
}
|
|
6954
7157
|
const password = await resolveTwakInitPassword(opts);
|
|
6955
|
-
const homeDir =
|
|
6956
|
-
|
|
7158
|
+
const homeDir = path22.dirname(path22.dirname(walletFile));
|
|
7159
|
+
fs23.mkdirSync(homeDir, { recursive: true });
|
|
6957
7160
|
if (!ensureTwakCredentials(walletFile, homeDir)) {
|
|
6958
7161
|
return 1;
|
|
6959
7162
|
}
|
|
@@ -6975,7 +7178,7 @@ ${password}
|
|
|
6975
7178
|
timeoutMs: 12e4
|
|
6976
7179
|
}
|
|
6977
7180
|
);
|
|
6978
|
-
if (create.code !== 0 || !
|
|
7181
|
+
if (create.code !== 0 || !isFile8(walletFile)) {
|
|
6979
7182
|
const detail = `${create.stderr}
|
|
6980
7183
|
${create.stdout}`.trim();
|
|
6981
7184
|
printErr(
|
|
@@ -6990,14 +7193,14 @@ ${detail}` : `error: \`twak wallet create --no-keychain\` did not produce ${wall
|
|
|
6990
7193
|
return 1;
|
|
6991
7194
|
}
|
|
6992
7195
|
try {
|
|
6993
|
-
|
|
7196
|
+
fs23.chmodSync(walletFile, 384);
|
|
6994
7197
|
} catch {
|
|
6995
7198
|
}
|
|
6996
7199
|
if (!process.env.TWAK_WALLET_PASSWORD) {
|
|
6997
7200
|
process.env.TWAK_WALLET_PASSWORD = password;
|
|
6998
7201
|
}
|
|
6999
7202
|
printErr(
|
|
7000
|
-
`\u2713 twak wallet created under ${
|
|
7203
|
+
`\u2713 twak wallet created under ${path22.dirname(walletFile)} (no keychain)`
|
|
7001
7204
|
);
|
|
7002
7205
|
printErr(
|
|
7003
7206
|
"next: persist TWAK_WALLET_PASSWORD in .studio/.env.local so deploys and non-interactive signing can unlock it."
|
|
@@ -7034,7 +7237,7 @@ function cmdShow5(projectRootArg) {
|
|
|
7034
7237
|
...walletCfg.address ? { address: String(walletCfg.address) } : {}
|
|
7035
7238
|
});
|
|
7036
7239
|
const address = provider.address;
|
|
7037
|
-
const keystorePath =
|
|
7240
|
+
const keystorePath = path22.join(keystoreDir, `${address}.json`);
|
|
7038
7241
|
printOut(`address: ${address}`);
|
|
7039
7242
|
printOut(`source: ${kind}`);
|
|
7040
7243
|
printOut(`keystore_dir: ${keystoreDir}`);
|
|
@@ -7043,14 +7246,14 @@ function cmdShow5(projectRootArg) {
|
|
|
7043
7246
|
const configured = String(
|
|
7044
7247
|
walletCfg.session_file ?? ".studio/wallets/altana-session.json"
|
|
7045
7248
|
);
|
|
7046
|
-
const sessionFile =
|
|
7249
|
+
const sessionFile = path22.isAbsolute(configured) ? configured : path22.join(projectRoot, configured);
|
|
7047
7250
|
printOut(`session_file: ${sessionFile}`);
|
|
7048
|
-
if (!
|
|
7251
|
+
if (!isFile8(sessionFile)) {
|
|
7049
7252
|
printOut("session_status: missing (run `bag wallet session grant`)");
|
|
7050
7253
|
} else {
|
|
7051
7254
|
let envelope;
|
|
7052
7255
|
try {
|
|
7053
|
-
envelope = JSON.parse(
|
|
7256
|
+
envelope = JSON.parse(fs23.readFileSync(sessionFile, "utf8"));
|
|
7054
7257
|
} catch {
|
|
7055
7258
|
throw new Error(`invalid Altana session JSON at ${sessionFile}`);
|
|
7056
7259
|
}
|
|
@@ -7076,7 +7279,7 @@ function cmdList2(projectRootArg) {
|
|
|
7076
7279
|
const keystoreDir = resolveKeystoreDir2(projectRoot, null, walletCfg);
|
|
7077
7280
|
let entries;
|
|
7078
7281
|
try {
|
|
7079
|
-
entries =
|
|
7282
|
+
entries = fs23.readdirSync(keystoreDir).sort();
|
|
7080
7283
|
} catch {
|
|
7081
7284
|
return 0;
|
|
7082
7285
|
}
|
|
@@ -7088,7 +7291,7 @@ function cmdList2(projectRootArg) {
|
|
|
7088
7291
|
let data;
|
|
7089
7292
|
try {
|
|
7090
7293
|
data = JSON.parse(
|
|
7091
|
-
|
|
7294
|
+
fs23.readFileSync(path22.join(keystoreDir, child), "utf-8")
|
|
7092
7295
|
);
|
|
7093
7296
|
} catch {
|
|
7094
7297
|
continue;
|
|
@@ -7139,7 +7342,7 @@ async function cmdSign(msg, projectRootArg) {
|
|
|
7139
7342
|
}
|
|
7140
7343
|
async function cmdBalance(opts) {
|
|
7141
7344
|
const projectRoot = resolveWalletProjectRoot(opts.projectRoot);
|
|
7142
|
-
const data = loadStudioToml10(
|
|
7345
|
+
const data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
7143
7346
|
const walletCfg = data.wallet !== null && typeof data.wallet === "object" ? data.wallet : {};
|
|
7144
7347
|
let address;
|
|
7145
7348
|
const kind = walletKind(walletCfg);
|
|
@@ -7266,10 +7469,10 @@ var PROVIDER_KEY_ENV = {
|
|
|
7266
7469
|
"pieverse-llm": "PIEVERSE_LLM_API_KEY"
|
|
7267
7470
|
};
|
|
7268
7471
|
function renderAgentcoreProject(target, name) {
|
|
7269
|
-
const acDir =
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7472
|
+
const acDir = path23.join(target, "agentcore");
|
|
7473
|
+
fs24.mkdirSync(acDir, { recursive: true });
|
|
7474
|
+
fs24.writeFileSync(
|
|
7475
|
+
path23.join(acDir, "agentcore.json"),
|
|
7273
7476
|
`${JSON.stringify(
|
|
7274
7477
|
{
|
|
7275
7478
|
$schema: "https://schema.agentcore.aws.dev/v1/agentcore.json",
|
|
@@ -7283,7 +7486,7 @@ function renderAgentcoreProject(target, name) {
|
|
|
7283
7486
|
)}
|
|
7284
7487
|
`
|
|
7285
7488
|
);
|
|
7286
|
-
|
|
7489
|
+
fs24.writeFileSync(path23.join(acDir, "aws-targets.json"), "[]\n");
|
|
7287
7490
|
}
|
|
7288
7491
|
var AGENTS_MD_MARKER = "# bnbagent-studio additions (ERC-8183 seller)";
|
|
7289
7492
|
var AGENTS_MD_STUDIO_SECTION = `
|
|
@@ -7327,30 +7530,30 @@ every intent to the right playbook via its references.
|
|
|
7327
7530
|
and state the tradeoff.
|
|
7328
7531
|
`;
|
|
7329
7532
|
function appendAgentsMdStudioSection(target) {
|
|
7330
|
-
const agentsMd =
|
|
7533
|
+
const agentsMd = path23.join(target, "AGENTS.md");
|
|
7331
7534
|
let existing = "";
|
|
7332
7535
|
try {
|
|
7333
|
-
existing =
|
|
7536
|
+
existing = fs24.readFileSync(agentsMd, "utf-8");
|
|
7334
7537
|
} catch {
|
|
7335
7538
|
existing = "";
|
|
7336
7539
|
}
|
|
7337
7540
|
if (existing.includes(AGENTS_MD_MARKER)) {
|
|
7338
7541
|
return;
|
|
7339
7542
|
}
|
|
7340
|
-
|
|
7543
|
+
fs24.writeFileSync(
|
|
7341
7544
|
agentsMd,
|
|
7342
7545
|
`${existing.replace(/\n+$/, "")}
|
|
7343
7546
|
${AGENTS_MD_STUDIO_SECTION}`
|
|
7344
7547
|
);
|
|
7345
7548
|
}
|
|
7346
7549
|
function seedAwsTargets(target) {
|
|
7347
|
-
const p =
|
|
7348
|
-
if (!
|
|
7550
|
+
const p = path23.join(target, "agentcore", "aws-targets.json");
|
|
7551
|
+
if (!isFile9(p)) {
|
|
7349
7552
|
return;
|
|
7350
7553
|
}
|
|
7351
7554
|
let data;
|
|
7352
7555
|
try {
|
|
7353
|
-
data = JSON.parse(
|
|
7556
|
+
data = JSON.parse(fs24.readFileSync(p, "utf-8"));
|
|
7354
7557
|
} catch {
|
|
7355
7558
|
return;
|
|
7356
7559
|
}
|
|
@@ -7361,7 +7564,7 @@ function seedAwsTargets(target) {
|
|
|
7361
7564
|
{ name: "default", account: AWS_ACCOUNT_PLACEHOLDER, region: "us-east-1" }
|
|
7362
7565
|
];
|
|
7363
7566
|
try {
|
|
7364
|
-
|
|
7567
|
+
fs24.writeFileSync(p, `${JSON.stringify(skeleton, null, 2)}
|
|
7365
7568
|
`);
|
|
7366
7569
|
} catch {
|
|
7367
7570
|
return;
|
|
@@ -7384,13 +7587,13 @@ function registerAgentcoreRuntime(target, name, opts = {}) {
|
|
|
7384
7587
|
const protocol = nativeProtocolOf(faces);
|
|
7385
7588
|
const stem2 = entryStemOf(faces);
|
|
7386
7589
|
const isContainer = opts.packaging === "container" || walletKind2 === "twak";
|
|
7387
|
-
const cfgPath =
|
|
7388
|
-
if (!
|
|
7590
|
+
const cfgPath = path23.join(target, "agentcore", "agentcore.json");
|
|
7591
|
+
if (!isFile9(cfgPath)) {
|
|
7389
7592
|
return;
|
|
7390
7593
|
}
|
|
7391
7594
|
let cfg;
|
|
7392
7595
|
try {
|
|
7393
|
-
const parsed = JSON.parse(
|
|
7596
|
+
const parsed = JSON.parse(fs24.readFileSync(cfgPath, "utf-8"));
|
|
7394
7597
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7395
7598
|
return;
|
|
7396
7599
|
}
|
|
@@ -7429,7 +7632,7 @@ function registerAgentcoreRuntime(target, name, opts = {}) {
|
|
|
7429
7632
|
runtimes.push(runtime);
|
|
7430
7633
|
cfg.runtimes = runtimes;
|
|
7431
7634
|
try {
|
|
7432
|
-
|
|
7635
|
+
fs24.writeFileSync(cfgPath, `${JSON.stringify(cfg, null, 2)}
|
|
7433
7636
|
`);
|
|
7434
7637
|
} catch {
|
|
7435
7638
|
return;
|
|
@@ -7566,12 +7769,12 @@ function registerInit(program) {
|
|
|
7566
7769
|
);
|
|
7567
7770
|
}
|
|
7568
7771
|
function enclosingProjectRoot(start) {
|
|
7569
|
-
let current =
|
|
7772
|
+
let current = path23.resolve(start);
|
|
7570
7773
|
for (; ; ) {
|
|
7571
|
-
if (
|
|
7774
|
+
if (isFile9(path23.join(current, APP_DIR, AGENT_PKG, "studio.toml"))) {
|
|
7572
7775
|
return current;
|
|
7573
7776
|
}
|
|
7574
|
-
const parent =
|
|
7777
|
+
const parent = path23.dirname(current);
|
|
7575
7778
|
if (parent === current) {
|
|
7576
7779
|
return null;
|
|
7577
7780
|
}
|
|
@@ -7579,8 +7782,8 @@ function enclosingProjectRoot(start) {
|
|
|
7579
7782
|
}
|
|
7580
7783
|
}
|
|
7581
7784
|
async function cmdInit(nameArg, opts) {
|
|
7582
|
-
const target =
|
|
7583
|
-
let projectName2 =
|
|
7785
|
+
const target = path23.resolve(process.cwd(), nameArg);
|
|
7786
|
+
let projectName2 = path23.basename(target);
|
|
7584
7787
|
if (!projectName2) {
|
|
7585
7788
|
printErr(
|
|
7586
7789
|
`error: cannot derive a project name from '${nameArg}' (path has no basename).`
|
|
@@ -7665,15 +7868,15 @@ async function cmdInit(nameArg, opts) {
|
|
|
7665
7868
|
return 2;
|
|
7666
7869
|
}
|
|
7667
7870
|
}
|
|
7668
|
-
const enclosing = enclosingProjectRoot(
|
|
7871
|
+
const enclosing = enclosingProjectRoot(path23.dirname(target));
|
|
7669
7872
|
if (enclosing !== null) {
|
|
7670
7873
|
printErr(
|
|
7671
|
-
`error: ${
|
|
7672
|
-
\`bag init\` resolves the new project relative to the current directory, so running it here would nest a second scaffold inside ${
|
|
7874
|
+
`error: ${path23.dirname(target)} is inside an existing bag project (${enclosing}).
|
|
7875
|
+
\`bag init\` resolves the new project relative to the current directory, so running it here would nest a second scaffold inside ${path23.basename(enclosing)}/. cd to a directory OUTSIDE any project and retry.`
|
|
7673
7876
|
);
|
|
7674
7877
|
return 2;
|
|
7675
7878
|
}
|
|
7676
|
-
if (
|
|
7879
|
+
if (fs24.existsSync(target) && !opts.force) {
|
|
7677
7880
|
printErr(`error: ${target} already exists. Use --force to overwrite.`);
|
|
7678
7881
|
return 2;
|
|
7679
7882
|
}
|
|
@@ -7692,20 +7895,14 @@ async function cmdInit(nameArg, opts) {
|
|
|
7692
7895
|
destination = "self";
|
|
7693
7896
|
runtime = "agentcore";
|
|
7694
7897
|
}
|
|
7695
|
-
if (destination === "platform" && walletKind2 === "altana") {
|
|
7696
|
-
printErr(
|
|
7697
|
-
"error: Altana (wallet.kind='altana') is not supported by the managed platform; the runtime needs a bounded local session, never the admin key. Use --destination self."
|
|
7698
|
-
);
|
|
7699
|
-
return 2;
|
|
7700
|
-
}
|
|
7701
7898
|
if (destination === "self" && runtime === "azure-foundry" && (!hasA2aFace(faces) || hasMcpFace(faces))) {
|
|
7702
7899
|
printErr(
|
|
7703
7900
|
"error: azure-foundry supports protocol A2A only as its native face (X402 is optional) and does not support an MCP face. Foundry is delegated through its invocations container contract (:8088, /readiness, /invocations), not the native MCP /mcp transport. Use --protocols A2A (optionally with X402), or use --runtime agentcore for MCP."
|
|
7704
7901
|
);
|
|
7705
7902
|
return 2;
|
|
7706
7903
|
}
|
|
7707
|
-
if (
|
|
7708
|
-
|
|
7904
|
+
if (fs24.existsSync(target)) {
|
|
7905
|
+
fs24.rmSync(target, { recursive: true, force: true });
|
|
7709
7906
|
}
|
|
7710
7907
|
if (destination === "platform") {
|
|
7711
7908
|
printCampaignIntro();
|
|
@@ -7750,7 +7947,7 @@ async function cmdInit(nameArg, opts) {
|
|
|
7750
7947
|
}
|
|
7751
7948
|
}
|
|
7752
7949
|
try {
|
|
7753
|
-
|
|
7950
|
+
fs24.mkdirSync(target, { recursive: true });
|
|
7754
7951
|
if (runtime === "agentcore") {
|
|
7755
7952
|
renderAgentcoreProject(target, projectName2);
|
|
7756
7953
|
}
|
|
@@ -7766,7 +7963,7 @@ async function cmdInit(nameArg, opts) {
|
|
|
7766
7963
|
printErr(
|
|
7767
7964
|
`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.`
|
|
7768
7965
|
);
|
|
7769
|
-
|
|
7966
|
+
fs24.rmSync(target, { recursive: true, force: true });
|
|
7770
7967
|
return 2;
|
|
7771
7968
|
}
|
|
7772
7969
|
const ides = resolveEmitIdes(opts.ide);
|
|
@@ -7809,9 +8006,9 @@ async function cmdInit(nameArg, opts) {
|
|
|
7809
8006
|
});
|
|
7810
8007
|
seedAwsTargets(target);
|
|
7811
8008
|
}
|
|
7812
|
-
const agentDir =
|
|
7813
|
-
|
|
7814
|
-
|
|
8009
|
+
const agentDir = path23.join(target, APP_DIR, AGENT_PKG);
|
|
8010
|
+
fs24.mkdirSync(path23.join(agentDir, "vendor"), { recursive: true });
|
|
8011
|
+
fs24.writeFileSync(path23.join(agentDir, "vendor", ".gitkeep"), "");
|
|
7815
8012
|
const skipInstall = opts.install === false || opts.venv === false;
|
|
7816
8013
|
let provisioned = false;
|
|
7817
8014
|
let installFailed = false;
|
|
@@ -7940,64 +8137,64 @@ function derivePackaging(walletKind2, destination, platformArtifact2 = "zip", ru
|
|
|
7940
8137
|
}
|
|
7941
8138
|
function scaffold(target, name, o) {
|
|
7942
8139
|
const packageManagerVersion = pnpmVersion();
|
|
7943
|
-
|
|
7944
|
-
|
|
8140
|
+
fs24.writeFileSync(
|
|
8141
|
+
path23.join(target, "package.json"),
|
|
7945
8142
|
renderWorkspacePackageJson(name, packageManagerVersion)
|
|
7946
8143
|
);
|
|
7947
|
-
|
|
7948
|
-
|
|
8144
|
+
fs24.writeFileSync(
|
|
8145
|
+
path23.join(target, "pnpm-workspace.yaml"),
|
|
7949
8146
|
renderPnpmWorkspaceYaml()
|
|
7950
8147
|
);
|
|
7951
|
-
|
|
7952
|
-
if (!
|
|
7953
|
-
|
|
7954
|
-
|
|
8148
|
+
fs24.writeFileSync(path23.join(target, ".gitignore"), renderWorkspaceGitignore());
|
|
8149
|
+
if (!isFile9(path23.join(target, "README.md"))) {
|
|
8150
|
+
fs24.writeFileSync(
|
|
8151
|
+
path23.join(target, "README.md"),
|
|
7955
8152
|
renderWorkspaceReadme(name, o.destination)
|
|
7956
8153
|
);
|
|
7957
8154
|
}
|
|
7958
8155
|
appendAgentsMdStudioSection(target);
|
|
7959
|
-
const appRoot =
|
|
7960
|
-
|
|
7961
|
-
const agentRoot2 =
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
8156
|
+
const appRoot = path23.join(target, APP_DIR);
|
|
8157
|
+
fs24.mkdirSync(appRoot, { recursive: true });
|
|
8158
|
+
const agentRoot2 = path23.join(appRoot, AGENT_PKG);
|
|
8159
|
+
fs24.mkdirSync(agentRoot2, { recursive: true });
|
|
8160
|
+
fs24.writeFileSync(
|
|
8161
|
+
path23.join(agentRoot2, "pnpm-workspace.yaml"),
|
|
7965
8162
|
renderAgentPnpmWorkspaceYaml()
|
|
7966
8163
|
);
|
|
7967
8164
|
if (o.walletKind === "evm-local" || o.walletKind === "altana") {
|
|
7968
|
-
|
|
8165
|
+
fs24.mkdirSync(path23.join(target, ".studio", "wallets"), { recursive: true });
|
|
7969
8166
|
} else if (o.walletKind === "twak") {
|
|
7970
8167
|
let homeDir;
|
|
7971
8168
|
let label;
|
|
7972
8169
|
if (o.twakHome === void 0 || o.twakHome === DEDICATED_TWAK_HOME_REL) {
|
|
7973
|
-
homeDir =
|
|
8170
|
+
homeDir = path23.join(target, ".studio", "twak");
|
|
7974
8171
|
label = ".studio/twak";
|
|
7975
8172
|
} else {
|
|
7976
|
-
homeDir =
|
|
8173
|
+
homeDir = path23.isAbsolute(o.twakHome) ? o.twakHome : path23.resolve(agentRoot2, o.twakHome);
|
|
7977
8174
|
label = o.twakHome;
|
|
7978
8175
|
}
|
|
7979
|
-
|
|
8176
|
+
fs24.mkdirSync(homeDir, { recursive: true });
|
|
7980
8177
|
if (ensureTwakKeychain(homeDir)) {
|
|
7981
8178
|
printOut(
|
|
7982
8179
|
`\u2713 isolated twak keychain ready under ${label} (macOS) \u2014 no manual \`security\` setup needed`
|
|
7983
8180
|
);
|
|
7984
8181
|
}
|
|
7985
8182
|
}
|
|
7986
|
-
|
|
7987
|
-
|
|
8183
|
+
fs24.writeFileSync(
|
|
8184
|
+
path23.join(agentRoot2, "package.json"),
|
|
7988
8185
|
renderAgentPackageJson(name, o.runtime, o.provider, o.faces, o.walletKind)
|
|
7989
8186
|
);
|
|
7990
|
-
|
|
7991
|
-
|
|
8187
|
+
fs24.writeFileSync(
|
|
8188
|
+
path23.join(agentRoot2, "tsconfig.json"),
|
|
7992
8189
|
renderAgentTsconfig()
|
|
7993
8190
|
);
|
|
7994
|
-
|
|
7995
|
-
|
|
8191
|
+
fs24.writeFileSync(
|
|
8192
|
+
path23.join(agentRoot2, "studio.toml"),
|
|
7996
8193
|
renderAgentStudioToml(name, o)
|
|
7997
8194
|
);
|
|
7998
|
-
const envLocal =
|
|
7999
|
-
|
|
8000
|
-
|
|
8195
|
+
const envLocal = path23.join(target, ".studio", ".env.local");
|
|
8196
|
+
fs24.mkdirSync(path23.dirname(envLocal), { recursive: true });
|
|
8197
|
+
fs24.writeFileSync(
|
|
8001
8198
|
envLocal,
|
|
8002
8199
|
renderAgentEnvLocal(
|
|
8003
8200
|
o.provider,
|
|
@@ -8008,9 +8205,9 @@ function scaffold(target, name, o) {
|
|
|
8008
8205
|
o.network
|
|
8009
8206
|
)
|
|
8010
8207
|
);
|
|
8011
|
-
|
|
8012
|
-
|
|
8013
|
-
|
|
8208
|
+
fs24.writeFileSync(path23.join(agentRoot2, ".gitignore"), renderAgentGitignore());
|
|
8209
|
+
fs24.writeFileSync(
|
|
8210
|
+
path23.join(agentRoot2, "README.md"),
|
|
8014
8211
|
renderAgentReadme(name, o.faces, o.destination)
|
|
8015
8212
|
);
|
|
8016
8213
|
const packaging = derivePackaging(
|
|
@@ -8046,18 +8243,18 @@ function emitRecipe(base, name, opts = {}) {
|
|
|
8046
8243
|
const recipe = loadRecipe(name, { mode: opts.mode ?? null });
|
|
8047
8244
|
for (const rf of recipe.files) {
|
|
8048
8245
|
const targetPath = substitutePlaceholders(rf.targetPath, opts.context);
|
|
8049
|
-
const basename16 =
|
|
8050
|
-
const dst = basename16 === "Dockerfile" || basename16 === ".dockerignore" ?
|
|
8051
|
-
|
|
8052
|
-
|
|
8246
|
+
const basename16 = path23.posix.basename(targetPath);
|
|
8247
|
+
const dst = basename16 === "Dockerfile" || basename16 === ".dockerignore" ? path23.join(base, basename16) : path23.join(base, targetPath);
|
|
8248
|
+
fs24.mkdirSync(path23.dirname(dst), { recursive: true });
|
|
8249
|
+
fs24.writeFileSync(dst, substitutePlaceholders(rf.content, opts.context));
|
|
8053
8250
|
}
|
|
8054
8251
|
}
|
|
8055
8252
|
function readRecipeNodeDeps(recipeName, group) {
|
|
8056
|
-
const tomlPath =
|
|
8057
|
-
if (!
|
|
8253
|
+
const tomlPath = path23.join(bundledRecipesRoot(), recipeName, "recipe.toml");
|
|
8254
|
+
if (!isFile9(tomlPath)) {
|
|
8058
8255
|
return [];
|
|
8059
8256
|
}
|
|
8060
|
-
const meta = parseToml(
|
|
8257
|
+
const meta = parseToml(fs24.readFileSync(tomlPath, "utf-8"));
|
|
8061
8258
|
const depsSection = meta.dependencies !== null && typeof meta.dependencies === "object" ? meta.dependencies : {};
|
|
8062
8259
|
const collect = (v) => Array.isArray(v) ? v.filter((d) => typeof d === "string") : [];
|
|
8063
8260
|
const deps = collect(depsSection.node);
|
|
@@ -8642,7 +8839,7 @@ bag deploy --provider aws
|
|
|
8642
8839
|
`;
|
|
8643
8840
|
}
|
|
8644
8841
|
function emitProviderSkills(target, provider, ides) {
|
|
8645
|
-
const skillDir =
|
|
8842
|
+
const skillDir = path23.join(
|
|
8646
8843
|
bundledRecipesRoot(),
|
|
8647
8844
|
"providers",
|
|
8648
8845
|
provider,
|
|
@@ -8652,34 +8849,34 @@ function emitProviderSkills(target, provider, ides) {
|
|
|
8652
8849
|
return;
|
|
8653
8850
|
}
|
|
8654
8851
|
let emittedCursor = false;
|
|
8655
|
-
for (const md of
|
|
8656
|
-
const srcText =
|
|
8852
|
+
for (const md of fs24.readdirSync(skillDir).filter((n) => n.endsWith(".md")).sort()) {
|
|
8853
|
+
const srcText = fs24.readFileSync(path23.join(skillDir, md), "utf-8");
|
|
8657
8854
|
const stem2 = md.replace(/\.md$/, "");
|
|
8658
8855
|
for (const ide of ides) {
|
|
8659
8856
|
const [relPath, content] = renderSkillPayload(srcText, stem2, ide);
|
|
8660
|
-
const base = ide === "claude-code" ?
|
|
8661
|
-
const dst =
|
|
8662
|
-
|
|
8663
|
-
|
|
8857
|
+
const base = ide === "claude-code" ? path23.join(target, ".claude", "skills") : path23.join(target, ".cursor", "rules");
|
|
8858
|
+
const dst = path23.join(base, relPath);
|
|
8859
|
+
fs24.mkdirSync(path23.dirname(dst), { recursive: true });
|
|
8860
|
+
fs24.writeFileSync(dst, content);
|
|
8664
8861
|
if (ide === "cursor") {
|
|
8665
8862
|
emittedCursor = true;
|
|
8666
8863
|
}
|
|
8667
8864
|
}
|
|
8668
8865
|
}
|
|
8669
8866
|
if (emittedCursor) {
|
|
8670
|
-
ensureCursorGitignore(
|
|
8867
|
+
ensureCursorGitignore(path23.join(target, ".gitignore"));
|
|
8671
8868
|
}
|
|
8672
8869
|
}
|
|
8673
8870
|
function ensureCursorGitignore(gitignore) {
|
|
8674
|
-
if (!
|
|
8871
|
+
if (!isFile9(gitignore)) {
|
|
8675
8872
|
return;
|
|
8676
8873
|
}
|
|
8677
|
-
const text2 =
|
|
8874
|
+
const text2 = fs24.readFileSync(gitignore, "utf-8");
|
|
8678
8875
|
if (text2.includes(".cursor/rules/")) {
|
|
8679
8876
|
return;
|
|
8680
8877
|
}
|
|
8681
8878
|
const addition = "\n# Cursor rules emitted at init (regeneratable via `bag skills install --target cursor`).\n.cursor/rules/\n";
|
|
8682
|
-
|
|
8879
|
+
fs24.writeFileSync(gitignore, `${text2.replace(/\n+$/, "")}
|
|
8683
8880
|
${addition}`);
|
|
8684
8881
|
}
|
|
8685
8882
|
async function resolveWalletKind(flagValue, isTty) {
|
|
@@ -8857,11 +9054,11 @@ async function promptPassword() {
|
|
|
8857
9054
|
return first;
|
|
8858
9055
|
}
|
|
8859
9056
|
function readWalletAddress(studioToml) {
|
|
8860
|
-
if (!
|
|
9057
|
+
if (!isFile9(studioToml)) {
|
|
8861
9058
|
return null;
|
|
8862
9059
|
}
|
|
8863
9060
|
try {
|
|
8864
|
-
const data = parseToml(
|
|
9061
|
+
const data = parseToml(fs24.readFileSync(studioToml, "utf-8"));
|
|
8865
9062
|
const wallet = data.wallet;
|
|
8866
9063
|
if (wallet !== null && typeof wallet === "object") {
|
|
8867
9064
|
const addr = wallet.address;
|
|
@@ -8964,7 +9161,7 @@ async function runOnboarding(o) {
|
|
|
8964
9161
|
if (password === null) {
|
|
8965
9162
|
return false;
|
|
8966
9163
|
}
|
|
8967
|
-
const agentRoot2 =
|
|
9164
|
+
const agentRoot2 = path23.join(o.workspaceRoot, APP_DIR, AGENT_PKG);
|
|
8968
9165
|
const { envLocalPath: envLocalPath19 } = await import("@bnbagent/studio-runtime/config");
|
|
8969
9166
|
setEnvVar(envLocalPath19(agentRoot2), "WALLET_PASSWORD", password);
|
|
8970
9167
|
const savedCwd = process.cwd();
|
|
@@ -8992,7 +9189,7 @@ async function runOnboarding(o) {
|
|
|
8992
9189
|
);
|
|
8993
9190
|
return false;
|
|
8994
9191
|
}
|
|
8995
|
-
address = readWalletAddress(
|
|
9192
|
+
address = readWalletAddress(path23.join(agentRoot2, "studio.toml"));
|
|
8996
9193
|
if (o.walletKind !== "altana" || o.provider !== "pieverse-llm") {
|
|
8997
9194
|
await onboardProviderActivation(agentRoot2, o.provider, o.model);
|
|
8998
9195
|
}
|
|
@@ -9011,7 +9208,7 @@ async function runOnboarding(o) {
|
|
|
9011
9208
|
await printFaucetHint(o.network, address);
|
|
9012
9209
|
if (o.walletKind === "altana") {
|
|
9013
9210
|
printOut(
|
|
9014
|
-
"Altana next step: fund about 0.
|
|
9211
|
+
"Altana next step: fund about 0.05 tBNB for bootstrap/registration, then run `bag wallet session grant`."
|
|
9015
9212
|
);
|
|
9016
9213
|
}
|
|
9017
9214
|
}
|
|
@@ -9021,9 +9218,9 @@ async function onboardProviderActivation(agentRoot2, provider, model) {
|
|
|
9021
9218
|
if (provider === "pieverse-llm") {
|
|
9022
9219
|
const chosenModel = model ?? await promptPieverseModel();
|
|
9023
9220
|
if (model === void 0) {
|
|
9024
|
-
const tomlPath =
|
|
9025
|
-
const text2 =
|
|
9026
|
-
|
|
9221
|
+
const tomlPath = path23.join(agentRoot2, "studio.toml");
|
|
9222
|
+
const text2 = fs24.readFileSync(tomlPath, "utf-8");
|
|
9223
|
+
fs24.writeFileSync(
|
|
9027
9224
|
tomlPath,
|
|
9028
9225
|
updateSection(text2, "llm", { model: chosenModel })
|
|
9029
9226
|
);
|
|
@@ -9059,8 +9256,8 @@ set ${keyEnv}= in .studio/.env.local before running \`bag dev\`.`
|
|
|
9059
9256
|
}
|
|
9060
9257
|
}
|
|
9061
9258
|
async function runOnboardingTwak(o) {
|
|
9062
|
-
const agentRoot2 =
|
|
9063
|
-
const studioToml =
|
|
9259
|
+
const agentRoot2 = path23.join(o.workspaceRoot, APP_DIR, AGENT_PKG);
|
|
9260
|
+
const studioToml = path23.join(agentRoot2, "studio.toml");
|
|
9064
9261
|
if (await whichTwak() === null) {
|
|
9065
9262
|
printErr(
|
|
9066
9263
|
`
|
|
@@ -9076,7 +9273,7 @@ you, so you never type the password on a command line, and adopts the address):
|
|
|
9076
9273
|
}
|
|
9077
9274
|
let walletCfg = {};
|
|
9078
9275
|
try {
|
|
9079
|
-
const data = parseToml(
|
|
9276
|
+
const data = parseToml(fs24.readFileSync(studioToml, "utf-8"));
|
|
9080
9277
|
if (data.wallet !== null && typeof data.wallet === "object") {
|
|
9081
9278
|
walletCfg = data.wallet;
|
|
9082
9279
|
}
|
|
@@ -9085,16 +9282,16 @@ you, so you never type the password on a command line, and adopts the address):
|
|
|
9085
9282
|
}
|
|
9086
9283
|
const { twakWalletFile: twakWalletFile2 } = await import("./_twak-4XF4H5PL.js");
|
|
9087
9284
|
let projectWallet = twakWalletFile2(walletCfg, agentRoot2);
|
|
9088
|
-
const machineWallet =
|
|
9089
|
-
if (!o.twakHomePinned &&
|
|
9285
|
+
const machineWallet = path23.join(os4.homedir(), ".twak", "wallet.json");
|
|
9286
|
+
if (!o.twakHomePinned && isFile9(machineWallet) && realpathIfExists(projectWallet) !== realpathIfExists(machineWallet)) {
|
|
9090
9287
|
if (await promptUseMachineTwakWallet(machineWallet)) {
|
|
9091
9288
|
projectWallet = adoptMachineTwakWallet(machineWallet, o.workspaceRoot);
|
|
9092
9289
|
}
|
|
9093
9290
|
}
|
|
9094
|
-
if (!
|
|
9095
|
-
const homeDir =
|
|
9291
|
+
if (!isFile9(projectWallet)) {
|
|
9292
|
+
const homeDir = path23.dirname(path23.dirname(projectWallet));
|
|
9096
9293
|
try {
|
|
9097
|
-
|
|
9294
|
+
fs24.mkdirSync(homeDir, { recursive: true });
|
|
9098
9295
|
} catch {
|
|
9099
9296
|
}
|
|
9100
9297
|
printErr(
|
|
@@ -9149,9 +9346,9 @@ Guide: the bnbagent-studio-using-twak-wallet.md reference (installed by \`bag sk
|
|
|
9149
9346
|
}
|
|
9150
9347
|
function realpathIfExists(p) {
|
|
9151
9348
|
try {
|
|
9152
|
-
return
|
|
9349
|
+
return fs24.realpathSync(p);
|
|
9153
9350
|
} catch {
|
|
9154
|
-
return
|
|
9351
|
+
return path23.resolve(p);
|
|
9155
9352
|
}
|
|
9156
9353
|
}
|
|
9157
9354
|
async function promptUseMachineTwakWallet(machineWallet) {
|
|
@@ -9164,39 +9361,39 @@ Found an existing twak wallet: ${machineWallet}`);
|
|
|
9164
9361
|
return answer === "y" || answer === "yes";
|
|
9165
9362
|
}
|
|
9166
9363
|
function adoptMachineTwakWallet(machineWallet, workspaceRoot) {
|
|
9167
|
-
const homeDir =
|
|
9168
|
-
const twakDir =
|
|
9169
|
-
|
|
9364
|
+
const homeDir = path23.join(workspaceRoot, ".studio", "twak");
|
|
9365
|
+
const twakDir = path23.join(homeDir, ".twak");
|
|
9366
|
+
fs24.mkdirSync(twakDir, { recursive: true });
|
|
9170
9367
|
try {
|
|
9171
|
-
|
|
9172
|
-
|
|
9368
|
+
fs24.chmodSync(homeDir, 448);
|
|
9369
|
+
fs24.chmodSync(twakDir, 448);
|
|
9173
9370
|
} catch {
|
|
9174
9371
|
}
|
|
9175
9372
|
for (const name of ["wallet.json", "credentials.json"]) {
|
|
9176
|
-
const src =
|
|
9177
|
-
if (
|
|
9178
|
-
const dst =
|
|
9179
|
-
|
|
9180
|
-
|
|
9373
|
+
const src = path23.join(path23.dirname(machineWallet), name);
|
|
9374
|
+
if (isFile9(src)) {
|
|
9375
|
+
const dst = path23.join(twakDir, name);
|
|
9376
|
+
fs24.writeFileSync(dst, fs24.readFileSync(src, "utf-8"), { mode: 384 });
|
|
9377
|
+
fs24.chmodSync(dst, 384);
|
|
9181
9378
|
}
|
|
9182
9379
|
}
|
|
9183
|
-
return
|
|
9380
|
+
return path23.join(twakDir, "wallet.json");
|
|
9184
9381
|
}
|
|
9185
9382
|
function normalizeTwakHome(raw) {
|
|
9186
|
-
const expanded = raw.startsWith("~") ?
|
|
9187
|
-
if (!
|
|
9383
|
+
const expanded = raw.startsWith("~") ? path23.join(os4.homedir(), raw.slice(1)) : raw;
|
|
9384
|
+
if (!path23.isAbsolute(expanded)) {
|
|
9188
9385
|
return { home: raw };
|
|
9189
9386
|
}
|
|
9190
|
-
const
|
|
9387
|
+
const isFile20 = (p) => {
|
|
9191
9388
|
try {
|
|
9192
|
-
return
|
|
9389
|
+
return fs24.statSync(p).isFile();
|
|
9193
9390
|
} catch {
|
|
9194
9391
|
return false;
|
|
9195
9392
|
}
|
|
9196
9393
|
};
|
|
9197
|
-
if (
|
|
9198
|
-
const parent =
|
|
9199
|
-
if (
|
|
9394
|
+
if (path23.basename(expanded) === ".twak") {
|
|
9395
|
+
const parent = path23.dirname(expanded);
|
|
9396
|
+
if (isFile20(path23.join(expanded, "wallet.json"))) {
|
|
9200
9397
|
return {
|
|
9201
9398
|
home: parent,
|
|
9202
9399
|
note: `note: --twak-home points at the .twak wallet directory itself; using its parent '${parent}' as the wallet home (the runtime resolves <twak_home>/.twak/wallet.json).`
|
|
@@ -9206,15 +9403,15 @@ function normalizeTwakHome(raw) {
|
|
|
9206
9403
|
error: `error: --twak-home must name the HOME-STYLE PARENT directory (the one that contains .twak/wallet.json), not a .twak directory itself. '${raw}' holds no wallet.json, so it cannot be auto-corrected \u2014 pass '${parent}' to adopt an existing wallet, or omit --twak-home to use the project-dedicated .studio/twak.`
|
|
9207
9404
|
};
|
|
9208
9405
|
}
|
|
9209
|
-
if (
|
|
9406
|
+
if (isFile20(path23.join(expanded, "wallet.json")) && !isFile20(path23.join(expanded, ".twak", "wallet.json"))) {
|
|
9210
9407
|
return {
|
|
9211
|
-
error: `error: --twak-home '${raw}' looks like a twak WALLET directory (it contains wallet.json directly). Pass its parent '${
|
|
9408
|
+
error: `error: --twak-home '${raw}' looks like a twak WALLET directory (it contains wallet.json directly). Pass its parent '${path23.dirname(expanded)}' instead \u2014 the runtime resolves <twak_home>/.twak/wallet.json.`
|
|
9212
9409
|
};
|
|
9213
9410
|
}
|
|
9214
|
-
if (!
|
|
9411
|
+
if (!isFile20(path23.join(expanded, ".twak", "wallet.json"))) {
|
|
9215
9412
|
return {
|
|
9216
9413
|
home: raw,
|
|
9217
|
-
note: `note: no wallet found at ${
|
|
9414
|
+
note: `note: no wallet found at ${path23.join(raw, ".twak", "wallet.json")} \u2014 treating --twak-home as a NEW project wallet home; \`bag wallet new\` will guide wallet creation.`
|
|
9218
9415
|
};
|
|
9219
9416
|
}
|
|
9220
9417
|
return { home: raw };
|
|
@@ -9224,7 +9421,7 @@ function twakHomeIsMainHome(twakHome) {
|
|
|
9224
9421
|
return false;
|
|
9225
9422
|
}
|
|
9226
9423
|
try {
|
|
9227
|
-
const expanded = twakHome.startsWith("~") ?
|
|
9424
|
+
const expanded = twakHome.startsWith("~") ? path23.join(os4.homedir(), twakHome.slice(1)) : twakHome;
|
|
9228
9425
|
return realpathIfExists(expanded) === realpathIfExists(os4.homedir());
|
|
9229
9426
|
} catch {
|
|
9230
9427
|
return false;
|
|
@@ -9315,8 +9512,10 @@ NOTE \u2014 wallet.kind = "altana" (bounded runtime session):
|
|
|
9315
9512
|
.studio/wallets/. WALLET_PASSWORD is used only by wallet/session commands.
|
|
9316
9513
|
\xB7 RUNTIME: fund the admin address, then run \`bag wallet session grant\`.
|
|
9317
9514
|
The Agent receives only .studio/wallets/altana-session.json.
|
|
9318
|
-
\xB7 DEPLOY:
|
|
9319
|
-
|
|
9515
|
+
\xB7 DEPLOY: \`bag deploy\` ships ONLY the bounded session (as the
|
|
9516
|
+
ALTANA_SESSION runtime secret) \u2014 the admin keystore and WALLET_PASSWORD
|
|
9517
|
+
never leave this machine. When the session expires, re-grant with
|
|
9518
|
+
\`bag wallet session grant --force\` and redeploy.`
|
|
9320
9519
|
);
|
|
9321
9520
|
}
|
|
9322
9521
|
function printPlatformWalletSuggestion() {
|
|
@@ -9374,11 +9573,11 @@ function entrypointHint(faces) {
|
|
|
9374
9573
|
return "app/agent/src/main.ts + executor.ts = A2A entrypoint (build your value here)";
|
|
9375
9574
|
}
|
|
9376
9575
|
function hasVendoredTarballs(agentDir) {
|
|
9377
|
-
const vendor =
|
|
9576
|
+
const vendor = path23.join(agentDir, "vendor");
|
|
9378
9577
|
if (!isDir4(vendor)) {
|
|
9379
9578
|
return false;
|
|
9380
9579
|
}
|
|
9381
|
-
return
|
|
9580
|
+
return fs24.readdirSync(vendor).some((n) => n.endsWith(".tgz"));
|
|
9382
9581
|
}
|
|
9383
9582
|
function printCompactNextSteps(name, o = {}) {
|
|
9384
9583
|
const faces = o.faces ?? normalizeProtocolFaces(o.protocol ?? "A2A");
|
|
@@ -9406,7 +9605,7 @@ function printCompactNextSteps(name, o = {}) {
|
|
|
9406
9605
|
}
|
|
9407
9606
|
if (walletKind2 === "altana") {
|
|
9408
9607
|
printOut(
|
|
9409
|
-
" bag wallet session grant # after funding ~0.
|
|
9608
|
+
" bag wallet session grant # after funding ~0.05 tBNB: create the bounded runtime session"
|
|
9410
9609
|
);
|
|
9411
9610
|
if (o.provider === "pieverse-llm") {
|
|
9412
9611
|
printOut(
|
|
@@ -9530,7 +9729,7 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9530
9729
|
printOut(" # bag auto-loads it; never pass it on argv");
|
|
9531
9730
|
printOut(" (cd app/agent && bag wallet new)");
|
|
9532
9731
|
printOut(
|
|
9533
|
-
" # 2. fund the printed address with ~0.
|
|
9732
|
+
" # 2. fund the printed address with ~0.05 tBNB for bootstrap/registration + U, then grant one bounded runtime session"
|
|
9534
9733
|
);
|
|
9535
9734
|
printOut(" (cd app/agent && bag wallet session grant)");
|
|
9536
9735
|
printOut(
|
|
@@ -9628,11 +9827,11 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9628
9827
|
);
|
|
9629
9828
|
}
|
|
9630
9829
|
function loadTomlSafe(p) {
|
|
9631
|
-
if (!
|
|
9830
|
+
if (!isFile9(p)) {
|
|
9632
9831
|
return {};
|
|
9633
9832
|
}
|
|
9634
9833
|
try {
|
|
9635
|
-
return parseToml(
|
|
9834
|
+
return parseToml(fs24.readFileSync(p, "utf-8"));
|
|
9636
9835
|
} catch {
|
|
9637
9836
|
return {};
|
|
9638
9837
|
}
|
|
@@ -9652,7 +9851,7 @@ function weiToU(raw) {
|
|
|
9652
9851
|
}
|
|
9653
9852
|
}
|
|
9654
9853
|
function printConfigSummary(agentRoot2) {
|
|
9655
|
-
const agent = loadTomlSafe(
|
|
9854
|
+
const agent = loadTomlSafe(path23.join(agentRoot2, "studio.toml"));
|
|
9656
9855
|
if (Object.keys(agent).length === 0) {
|
|
9657
9856
|
return;
|
|
9658
9857
|
}
|
|
@@ -9850,16 +10049,16 @@ function printConfigSummary(agentRoot2) {
|
|
|
9850
10049
|
printOut("");
|
|
9851
10050
|
}
|
|
9852
10051
|
}
|
|
9853
|
-
function
|
|
10052
|
+
function isFile9(p) {
|
|
9854
10053
|
try {
|
|
9855
|
-
return
|
|
10054
|
+
return fs24.statSync(p).isFile();
|
|
9856
10055
|
} catch {
|
|
9857
10056
|
return false;
|
|
9858
10057
|
}
|
|
9859
10058
|
}
|
|
9860
10059
|
function isDir4(p) {
|
|
9861
10060
|
try {
|
|
9862
|
-
return
|
|
10061
|
+
return fs24.statSync(p).isDirectory();
|
|
9863
10062
|
} catch {
|
|
9864
10063
|
return false;
|
|
9865
10064
|
}
|
|
@@ -9923,9 +10122,9 @@ var RUNTIME_AGENTCORE = "agentcore";
|
|
|
9923
10122
|
var RUNTIME_AZURE_FOUNDRY = "azure-foundry";
|
|
9924
10123
|
var MIN_NODE_MAJOR = 22;
|
|
9925
10124
|
var CONTAINER_RUNTIMES = ["docker", "podman", "finch"];
|
|
9926
|
-
function
|
|
10125
|
+
function isFile10(p) {
|
|
9927
10126
|
try {
|
|
9928
|
-
return
|
|
10127
|
+
return fs25.statSync(p).isFile();
|
|
9929
10128
|
} catch {
|
|
9930
10129
|
return false;
|
|
9931
10130
|
}
|
|
@@ -9957,8 +10156,8 @@ async function nodeMajor() {
|
|
|
9957
10156
|
return /^\d+$/.test(head) ? Number.parseInt(head, 10) : null;
|
|
9958
10157
|
}
|
|
9959
10158
|
function workspaceBase(root) {
|
|
9960
|
-
for (const base of [
|
|
9961
|
-
if (
|
|
10159
|
+
for (const base of [path24.join(root, "app"), root]) {
|
|
10160
|
+
if (isFile10(path24.join(base, "agent", "studio.toml"))) {
|
|
9962
10161
|
return base;
|
|
9963
10162
|
}
|
|
9964
10163
|
}
|
|
@@ -9966,7 +10165,7 @@ function workspaceBase(root) {
|
|
|
9966
10165
|
}
|
|
9967
10166
|
function resolveWorkspaceRoot(argRoot) {
|
|
9968
10167
|
if (argRoot !== null) {
|
|
9969
|
-
const root =
|
|
10168
|
+
const root = path24.resolve(argRoot);
|
|
9970
10169
|
const base = workspaceBase(root);
|
|
9971
10170
|
if (base === null) {
|
|
9972
10171
|
printErr(
|
|
@@ -9976,13 +10175,13 @@ function resolveWorkspaceRoot(argRoot) {
|
|
|
9976
10175
|
}
|
|
9977
10176
|
return base;
|
|
9978
10177
|
}
|
|
9979
|
-
let current =
|
|
10178
|
+
let current = path24.resolve(process.cwd());
|
|
9980
10179
|
for (; ; ) {
|
|
9981
10180
|
const base = workspaceBase(current);
|
|
9982
10181
|
if (base !== null) {
|
|
9983
10182
|
return base;
|
|
9984
10183
|
}
|
|
9985
|
-
const parent =
|
|
10184
|
+
const parent = path24.dirname(current);
|
|
9986
10185
|
if (parent === current) {
|
|
9987
10186
|
break;
|
|
9988
10187
|
}
|
|
@@ -9996,7 +10195,7 @@ function resolveWorkspaceRoot(argRoot) {
|
|
|
9996
10195
|
function loadAgentToml2(workspaceRoot) {
|
|
9997
10196
|
try {
|
|
9998
10197
|
return loadStudioToml11(
|
|
9999
|
-
|
|
10198
|
+
path24.join(workspaceRoot, "agent", "studio.toml")
|
|
10000
10199
|
);
|
|
10001
10200
|
} catch {
|
|
10002
10201
|
return {};
|
|
@@ -10023,7 +10222,7 @@ function defaultAgentPort(faces) {
|
|
|
10023
10222
|
function storageKind(agentDir) {
|
|
10024
10223
|
let data;
|
|
10025
10224
|
try {
|
|
10026
|
-
data = loadStudioToml11(
|
|
10225
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10027
10226
|
} catch {
|
|
10028
10227
|
return "local";
|
|
10029
10228
|
}
|
|
@@ -10033,7 +10232,7 @@ function storageKind(agentDir) {
|
|
|
10033
10232
|
function networkNameOf(agentDir) {
|
|
10034
10233
|
let data;
|
|
10035
10234
|
try {
|
|
10036
|
-
data = loadStudioToml11(
|
|
10235
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10037
10236
|
} catch {
|
|
10038
10237
|
return "bsc-testnet";
|
|
10039
10238
|
}
|
|
@@ -10043,7 +10242,7 @@ function networkNameOf(agentDir) {
|
|
|
10043
10242
|
function walletKindOf(agentDir) {
|
|
10044
10243
|
let data;
|
|
10045
10244
|
try {
|
|
10046
|
-
data = loadStudioToml11(
|
|
10245
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10047
10246
|
} catch {
|
|
10048
10247
|
return "evm-local";
|
|
10049
10248
|
}
|
|
@@ -10051,18 +10250,18 @@ function walletKindOf(agentDir) {
|
|
|
10051
10250
|
return typeof kind === "string" && kind.trim() ? kind.trim() : "evm-local";
|
|
10052
10251
|
}
|
|
10053
10252
|
function altanaSessionForRuntime(agentDir) {
|
|
10054
|
-
const cfg = loadStudioToml11(
|
|
10253
|
+
const cfg = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10055
10254
|
const wallet = tableOf9(cfg, "wallet");
|
|
10056
10255
|
const configured = String(
|
|
10057
10256
|
wallet.session_file ?? ".studio/wallets/altana-session.json"
|
|
10058
10257
|
);
|
|
10059
|
-
const sessionFile =
|
|
10060
|
-
if (!
|
|
10258
|
+
const sessionFile = path24.isAbsolute(configured) ? configured : path24.join(agentDir, configured);
|
|
10259
|
+
if (!isFile10(sessionFile)) {
|
|
10061
10260
|
throw new Error(
|
|
10062
10261
|
`no Altana session at ${sessionFile} \u2014 run \`bag wallet session grant\` first.`
|
|
10063
10262
|
);
|
|
10064
10263
|
}
|
|
10065
|
-
const serialized =
|
|
10264
|
+
const serialized = fs25.readFileSync(sessionFile, "utf8");
|
|
10066
10265
|
let envelope;
|
|
10067
10266
|
try {
|
|
10068
10267
|
envelope = JSON.parse(serialized);
|
|
@@ -10091,10 +10290,10 @@ function altanaSessionForRuntime(agentDir) {
|
|
|
10091
10290
|
}
|
|
10092
10291
|
var KEY_LINE_RE = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/;
|
|
10093
10292
|
function loadEnvFileForDev(p) {
|
|
10094
|
-
if (!
|
|
10293
|
+
if (!isFile10(p)) {
|
|
10095
10294
|
return;
|
|
10096
10295
|
}
|
|
10097
|
-
for (const line of
|
|
10296
|
+
for (const line of fs25.readFileSync(p, "utf-8").split(/\r?\n/)) {
|
|
10098
10297
|
if (!line || line.trimStart().startsWith("#")) {
|
|
10099
10298
|
continue;
|
|
10100
10299
|
}
|
|
@@ -10115,20 +10314,20 @@ function ensureStoragePath(projectRoot) {
|
|
|
10115
10314
|
const raw = process.env.STORAGE_LOCAL_PATH;
|
|
10116
10315
|
let resolved;
|
|
10117
10316
|
if (raw) {
|
|
10118
|
-
resolved =
|
|
10119
|
-
raw.startsWith("~") ?
|
|
10317
|
+
resolved = path24.resolve(
|
|
10318
|
+
raw.startsWith("~") ? path24.join(os5.homedir(), raw.slice(1)) : raw
|
|
10120
10319
|
);
|
|
10121
10320
|
} else {
|
|
10122
|
-
resolved =
|
|
10123
|
-
|
|
10321
|
+
resolved = path24.resolve(
|
|
10322
|
+
path24.join(
|
|
10124
10323
|
os5.homedir(),
|
|
10125
10324
|
".bag",
|
|
10126
10325
|
"deliverables",
|
|
10127
|
-
|
|
10326
|
+
path24.basename(projectRoot)
|
|
10128
10327
|
)
|
|
10129
10328
|
);
|
|
10130
10329
|
}
|
|
10131
|
-
|
|
10330
|
+
fs25.mkdirSync(resolved, { recursive: true });
|
|
10132
10331
|
process.env.STORAGE_LOCAL_PATH = resolved;
|
|
10133
10332
|
}
|
|
10134
10333
|
function ipfsPreflight(agentDir) {
|
|
@@ -10143,7 +10342,7 @@ function ipfsPreflight(agentDir) {
|
|
|
10143
10342
|
function runtimeEnvKeys(agentDir) {
|
|
10144
10343
|
let cfg = {};
|
|
10145
10344
|
try {
|
|
10146
|
-
cfg = loadStudioToml11(
|
|
10345
|
+
cfg = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10147
10346
|
} catch {
|
|
10148
10347
|
cfg = {};
|
|
10149
10348
|
}
|
|
@@ -10160,7 +10359,7 @@ function readTwakFiles(agentDir) {
|
|
|
10160
10359
|
let walletCfg = {};
|
|
10161
10360
|
try {
|
|
10162
10361
|
walletCfg = tableOf9(
|
|
10163
|
-
loadStudioToml11(
|
|
10362
|
+
loadStudioToml11(path24.join(agentDir, "studio.toml")),
|
|
10164
10363
|
"wallet"
|
|
10165
10364
|
);
|
|
10166
10365
|
} catch {
|
|
@@ -10168,9 +10367,9 @@ function readTwakFiles(agentDir) {
|
|
|
10168
10367
|
}
|
|
10169
10368
|
const twakDir = twakHomeDir(walletCfg, agentDir);
|
|
10170
10369
|
const read = (name) => {
|
|
10171
|
-
const p =
|
|
10370
|
+
const p = path24.join(twakDir, name);
|
|
10172
10371
|
try {
|
|
10173
|
-
return
|
|
10372
|
+
return fs25.readFileSync(p, "utf-8");
|
|
10174
10373
|
} catch {
|
|
10175
10374
|
return null;
|
|
10176
10375
|
}
|
|
@@ -10178,19 +10377,19 @@ function readTwakFiles(agentDir) {
|
|
|
10178
10377
|
return [read("wallet.json"), read("credentials.json")];
|
|
10179
10378
|
}
|
|
10180
10379
|
function ensureAgentcoreEnvGitignored(agentcoreDir) {
|
|
10181
|
-
const gi =
|
|
10380
|
+
const gi = path24.join(agentcoreDir, ".gitignore");
|
|
10182
10381
|
const entry = ".env.local";
|
|
10183
|
-
if (
|
|
10184
|
-
const text2 =
|
|
10382
|
+
if (isFile10(gi)) {
|
|
10383
|
+
const text2 = fs25.readFileSync(gi, "utf-8");
|
|
10185
10384
|
const lines = new Set(text2.split("\n").map((l) => l.trim()));
|
|
10186
10385
|
if (lines.has(entry)) {
|
|
10187
10386
|
return;
|
|
10188
10387
|
}
|
|
10189
|
-
const
|
|
10190
|
-
|
|
10388
|
+
const sep7 = text2.endsWith("\n") || text2 === "" ? "" : "\n";
|
|
10389
|
+
fs25.writeFileSync(gi, `${text2}${sep7}${entry}
|
|
10191
10390
|
`);
|
|
10192
10391
|
} else {
|
|
10193
|
-
|
|
10392
|
+
fs25.writeFileSync(gi, `${entry}
|
|
10194
10393
|
`);
|
|
10195
10394
|
}
|
|
10196
10395
|
}
|
|
@@ -10213,8 +10412,8 @@ function writeAgentcoreEnvLocal(agentcoreRoot, agentDir) {
|
|
|
10213
10412
|
} else if (walletKindOf(agentDir) === "altana") {
|
|
10214
10413
|
bundle.ALTANA_SESSION = altanaSessionForRuntime(agentDir);
|
|
10215
10414
|
}
|
|
10216
|
-
const envPath =
|
|
10217
|
-
const prior =
|
|
10415
|
+
const envPath = path24.join(agentcoreRoot, "agentcore", ".env.local");
|
|
10416
|
+
const prior = isFile10(envPath) ? fs25.readFileSync(envPath, "utf-8") : "";
|
|
10218
10417
|
const merged = {};
|
|
10219
10418
|
for (const line of prior.split("\n")) {
|
|
10220
10419
|
if (!line || line.trimStart().startsWith("#")) {
|
|
@@ -10229,14 +10428,14 @@ function writeAgentcoreEnvLocal(agentcoreRoot, agentDir) {
|
|
|
10229
10428
|
Object.assign(merged, bundle);
|
|
10230
10429
|
const content = Object.entries(merged).map(([k, v]) => `${k}=${v}
|
|
10231
10430
|
`).join("");
|
|
10232
|
-
|
|
10233
|
-
ensureAgentcoreEnvGitignored(
|
|
10431
|
+
fs25.mkdirSync(path24.dirname(envPath), { recursive: true });
|
|
10432
|
+
ensureAgentcoreEnvGitignored(path24.dirname(envPath));
|
|
10234
10433
|
writePrivate2(envPath, content);
|
|
10235
10434
|
return [envPath, content !== prior];
|
|
10236
10435
|
}
|
|
10237
10436
|
function agentcoreProjectRoot2(workspaceRoot) {
|
|
10238
|
-
for (const candidate of [
|
|
10239
|
-
if (
|
|
10437
|
+
for (const candidate of [path24.dirname(workspaceRoot), workspaceRoot]) {
|
|
10438
|
+
if (isFile10(path24.join(candidate, "agentcore", "agentcore.json"))) {
|
|
10240
10439
|
return candidate;
|
|
10241
10440
|
}
|
|
10242
10441
|
}
|
|
@@ -10245,8 +10444,8 @@ function agentcoreProjectRoot2(workspaceRoot) {
|
|
|
10245
10444
|
function loadAgentcoreConfig(projectRoot) {
|
|
10246
10445
|
try {
|
|
10247
10446
|
const cfg = JSON.parse(
|
|
10248
|
-
|
|
10249
|
-
|
|
10447
|
+
fs25.readFileSync(
|
|
10448
|
+
path24.join(projectRoot, "agentcore", "agentcore.json"),
|
|
10250
10449
|
"utf-8"
|
|
10251
10450
|
)
|
|
10252
10451
|
);
|
|
@@ -10336,7 +10535,7 @@ async function cmdDev(opts) {
|
|
|
10336
10535
|
if (workspaceRoot === null) {
|
|
10337
10536
|
return 2;
|
|
10338
10537
|
}
|
|
10339
|
-
const agentDir =
|
|
10538
|
+
const agentDir = path24.join(workspaceRoot, "agent");
|
|
10340
10539
|
migrateEnvLocal(agentDir);
|
|
10341
10540
|
migrateKeystoreOutOfCodelocation(agentDir);
|
|
10342
10541
|
const { envLocalPath: envLocalPath19 } = await import("@bnbagent/studio-runtime/config");
|
|
@@ -10372,8 +10571,8 @@ async function cmdDev(opts) {
|
|
|
10372
10571
|
const runtime = agentRuntime(workspaceRoot);
|
|
10373
10572
|
const container = Boolean(opts.container);
|
|
10374
10573
|
const entryFile = localEntryFile(faces);
|
|
10375
|
-
const agentFile =
|
|
10376
|
-
if (!
|
|
10574
|
+
const agentFile = path24.join(agentDir, entryFile);
|
|
10575
|
+
if (!isFile10(agentFile)) {
|
|
10377
10576
|
printErr(
|
|
10378
10577
|
`error: Agent entrypoint file ${agentFile} does not exist. [stack] faces = [${faces.join(", ")}], so the entrypoint is ${entryFile} (A2A/X402-only \u2192 src/main.ts, MCP \u2192 src/mcpMain.ts, A2A+MCP \u2192 src/dualMain.ts). Run \`bag init\` to scaffold the workspace.`
|
|
10379
10578
|
);
|
|
@@ -10451,7 +10650,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10451
10650
|
}
|
|
10452
10651
|
let launch;
|
|
10453
10652
|
if (runtime === RUNTIME_AGENTCORE && container) {
|
|
10454
|
-
const root =
|
|
10653
|
+
const root = path24.resolve(agentcoreRoot);
|
|
10455
10654
|
try {
|
|
10456
10655
|
const vendored = await vendorLocalTarballs(agentDir);
|
|
10457
10656
|
if (vendored.length > 0) {
|
|
@@ -10466,7 +10665,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10466
10665
|
}
|
|
10467
10666
|
const [envPath, changed] = writeAgentcoreEnvLocal(root, agentDir);
|
|
10468
10667
|
printOut(
|
|
10469
|
-
`bag dev: wrote ${
|
|
10668
|
+
`bag dev: wrote ${path24.relative(root, envPath)} (runtime secrets + materialized wallet for the container).`
|
|
10470
10669
|
);
|
|
10471
10670
|
if (changed && process.env.BAG_DEV_ENV_WARNED !== "1") {
|
|
10472
10671
|
printErr(
|
|
@@ -10543,7 +10742,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10543
10742
|
}
|
|
10544
10743
|
if (hasX402Face(faces)) {
|
|
10545
10744
|
const free = x402SellerIsFree(
|
|
10546
|
-
loadStudioToml11(
|
|
10745
|
+
loadStudioToml11(path24.join(agentDir, "studio.toml"))
|
|
10547
10746
|
);
|
|
10548
10747
|
printOut(
|
|
10549
10748
|
free ? `bag dev: x402 seller at http://localhost:${agentPort}/x402 (FREE \u2014 anonymous passthrough; B402 bypassed)` : `bag dev: x402 seller at http://localhost:${agentPort}/x402 (PAID \u2014 active when B402 credentials are configured)`
|
|
@@ -10554,9 +10753,9 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10554
10753
|
}
|
|
10555
10754
|
function tsxRunner(agentDir, workspaceBaseDir) {
|
|
10556
10755
|
const bin = process.platform === "win32" ? "tsx.cmd" : "tsx";
|
|
10557
|
-
for (const dir of [agentDir,
|
|
10558
|
-
const candidate =
|
|
10559
|
-
if (
|
|
10756
|
+
for (const dir of [agentDir, path24.dirname(workspaceBaseDir)]) {
|
|
10757
|
+
const candidate = path24.join(dir, "node_modules", ".bin", bin);
|
|
10758
|
+
if (isFile10(candidate)) {
|
|
10560
10759
|
return candidate;
|
|
10561
10760
|
}
|
|
10562
10761
|
}
|
|
@@ -10565,7 +10764,7 @@ function tsxRunner(agentDir, workspaceBaseDir) {
|
|
|
10565
10764
|
function networkBanner(agentDir) {
|
|
10566
10765
|
let data;
|
|
10567
10766
|
try {
|
|
10568
|
-
data = loadStudioToml11(
|
|
10767
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10569
10768
|
} catch {
|
|
10570
10769
|
return null;
|
|
10571
10770
|
}
|
|
@@ -10582,34 +10781,34 @@ function networkBanner(agentDir) {
|
|
|
10582
10781
|
}
|
|
10583
10782
|
|
|
10584
10783
|
// src/cli/_deploy/checks/critical.ts
|
|
10585
|
-
import * as
|
|
10784
|
+
import * as fs26 from "fs";
|
|
10586
10785
|
import { createRequire } from "module";
|
|
10587
|
-
import * as
|
|
10786
|
+
import * as path25 from "path";
|
|
10588
10787
|
import { envLocalPath as envLocalPath11, loadStudioToml as loadStudioToml12 } from "@bnbagent/studio-runtime/config";
|
|
10589
10788
|
import { pieverseKeyHash as pieverseKeyHash2 } from "@bnbagent/studio-runtime/llm";
|
|
10590
10789
|
var AGENTCORE_DESCRIPTOR2 = "agentcore/agentcore.json";
|
|
10591
|
-
function
|
|
10790
|
+
function isFile11(p) {
|
|
10592
10791
|
try {
|
|
10593
|
-
return
|
|
10792
|
+
return fs26.statSync(p).isFile();
|
|
10594
10793
|
} catch {
|
|
10595
10794
|
return false;
|
|
10596
10795
|
}
|
|
10597
10796
|
}
|
|
10598
10797
|
function isDir5(p) {
|
|
10599
10798
|
try {
|
|
10600
|
-
return
|
|
10799
|
+
return fs26.statSync(p).isDirectory();
|
|
10601
10800
|
} catch {
|
|
10602
10801
|
return false;
|
|
10603
10802
|
}
|
|
10604
10803
|
}
|
|
10605
10804
|
function keystoreDirOf(root, data) {
|
|
10606
10805
|
const rel = String(tableOf2(data, "wallet").keystore_dir ?? ".studio/wallets");
|
|
10607
|
-
const dir =
|
|
10608
|
-
return
|
|
10806
|
+
const dir = path25.isAbsolute(rel) ? rel : path25.join(agentRootOf(root), rel);
|
|
10807
|
+
return path25.resolve(dir);
|
|
10609
10808
|
}
|
|
10610
10809
|
function keystoreJsonFiles2(dir) {
|
|
10611
10810
|
try {
|
|
10612
|
-
return
|
|
10811
|
+
return fs26.readdirSync(dir).filter((n) => n.endsWith(".json")).sort();
|
|
10613
10812
|
} catch {
|
|
10614
10813
|
return [];
|
|
10615
10814
|
}
|
|
@@ -10617,7 +10816,7 @@ function keystoreJsonFiles2(dir) {
|
|
|
10617
10816
|
function runtimeEnvKeys2(agentRoot2) {
|
|
10618
10817
|
let cfg = {};
|
|
10619
10818
|
try {
|
|
10620
|
-
cfg = loadStudioToml12(
|
|
10819
|
+
cfg = loadStudioToml12(path25.join(agentRoot2, "studio.toml"));
|
|
10621
10820
|
} catch {
|
|
10622
10821
|
cfg = {};
|
|
10623
10822
|
}
|
|
@@ -10629,8 +10828,8 @@ async function checkAgentcoreJsonPresent(root, target) {
|
|
|
10629
10828
|
if (target !== "agentcore") {
|
|
10630
10829
|
return [];
|
|
10631
10830
|
}
|
|
10632
|
-
const descriptor =
|
|
10633
|
-
if (
|
|
10831
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
10832
|
+
if (isFile11(descriptor)) {
|
|
10634
10833
|
return [];
|
|
10635
10834
|
}
|
|
10636
10835
|
return [
|
|
@@ -10646,10 +10845,10 @@ async function checkAgentcoreAuthorizerKeyLegacy(root, target) {
|
|
|
10646
10845
|
if (target !== "agentcore") {
|
|
10647
10846
|
return [];
|
|
10648
10847
|
}
|
|
10649
|
-
const descriptor =
|
|
10848
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
10650
10849
|
let data;
|
|
10651
10850
|
try {
|
|
10652
|
-
data = JSON.parse(
|
|
10851
|
+
data = JSON.parse(fs26.readFileSync(descriptor, "utf-8"));
|
|
10653
10852
|
} catch {
|
|
10654
10853
|
return [];
|
|
10655
10854
|
}
|
|
@@ -10689,10 +10888,10 @@ async function checkAgentPackagePresent(root, target) {
|
|
|
10689
10888
|
sourceEntries.push("src/mcpMain.ts");
|
|
10690
10889
|
}
|
|
10691
10890
|
const missingSource = sourceEntries.find(
|
|
10692
|
-
(entry) => !
|
|
10891
|
+
(entry) => !isFile11(path25.join(agentRoot2, entry))
|
|
10693
10892
|
);
|
|
10694
10893
|
if (missingSource !== void 0) {
|
|
10695
|
-
const epPath =
|
|
10894
|
+
const epPath = path25.join(agentRoot2, missingSource);
|
|
10696
10895
|
return [
|
|
10697
10896
|
{
|
|
10698
10897
|
level: Level.CRITICAL,
|
|
@@ -10707,10 +10906,10 @@ async function checkAgentPackagePresent(root, target) {
|
|
|
10707
10906
|
distEntries.push("dist/mcpMain.js");
|
|
10708
10907
|
}
|
|
10709
10908
|
const missingDist = distEntries.find(
|
|
10710
|
-
(entry) => !
|
|
10909
|
+
(entry) => !isFile11(path25.join(agentRoot2, entry))
|
|
10711
10910
|
);
|
|
10712
10911
|
if (missingDist !== void 0) {
|
|
10713
|
-
const distPath =
|
|
10912
|
+
const distPath = path25.join(agentRoot2, missingDist);
|
|
10714
10913
|
return [
|
|
10715
10914
|
{
|
|
10716
10915
|
level: Level.WARNING,
|
|
@@ -10735,8 +10934,8 @@ async function checkKeystoreNotInsideAgent(root, target) {
|
|
|
10735
10934
|
if (!isDir5(keystoreDir) || keystoreJsonFiles2(keystoreDir).length === 0) {
|
|
10736
10935
|
return [];
|
|
10737
10936
|
}
|
|
10738
|
-
const agentDir =
|
|
10739
|
-
const inside2 = keystoreDir === agentDir || keystoreDir.startsWith(agentDir +
|
|
10937
|
+
const agentDir = path25.resolve(agentRootOf(root));
|
|
10938
|
+
const inside2 = keystoreDir === agentDir || keystoreDir.startsWith(agentDir + path25.sep);
|
|
10740
10939
|
if (!inside2) {
|
|
10741
10940
|
return [];
|
|
10742
10941
|
}
|
|
@@ -10755,6 +10954,9 @@ async function checkLocalKeystoreExists(root, _target) {
|
|
|
10755
10954
|
if (walletCfg.kind === "twak") {
|
|
10756
10955
|
return [];
|
|
10757
10956
|
}
|
|
10957
|
+
if (walletCfg.kind === "altana") {
|
|
10958
|
+
return [];
|
|
10959
|
+
}
|
|
10758
10960
|
const signer = walletCfg.signer ?? "local";
|
|
10759
10961
|
if (signer !== "local") {
|
|
10760
10962
|
return [];
|
|
@@ -10773,7 +10975,11 @@ async function checkLocalKeystoreExists(root, _target) {
|
|
|
10773
10975
|
];
|
|
10774
10976
|
}
|
|
10775
10977
|
async function checkWalletPasswordEnvSet(root, _target) {
|
|
10776
|
-
|
|
10978
|
+
const kind = tableOf2(loadAgentToml(root), "wallet").kind;
|
|
10979
|
+
if (kind === "twak") {
|
|
10980
|
+
return [];
|
|
10981
|
+
}
|
|
10982
|
+
if (kind === "altana") {
|
|
10777
10983
|
return [];
|
|
10778
10984
|
}
|
|
10779
10985
|
if (process.env.WALLET_PASSWORD) {
|
|
@@ -10812,18 +11018,18 @@ async function checkLlmProviderKeySet(root, _target) {
|
|
|
10812
11018
|
function gitignoreLines(p) {
|
|
10813
11019
|
try {
|
|
10814
11020
|
return new Set(
|
|
10815
|
-
|
|
11021
|
+
fs26.readFileSync(p, "utf-8").split(/\r?\n/).map((l) => l.trim())
|
|
10816
11022
|
);
|
|
10817
11023
|
} catch {
|
|
10818
11024
|
return null;
|
|
10819
11025
|
}
|
|
10820
11026
|
}
|
|
10821
11027
|
function agentcoreEnvLocalIgnored(ws) {
|
|
10822
|
-
const wsLines = gitignoreLines(
|
|
11028
|
+
const wsLines = gitignoreLines(path25.join(ws, ".gitignore"));
|
|
10823
11029
|
if (wsLines?.has("agentcore/.env.local")) {
|
|
10824
11030
|
return true;
|
|
10825
11031
|
}
|
|
10826
|
-
const acLines = gitignoreLines(
|
|
11032
|
+
const acLines = gitignoreLines(path25.join(ws, "agentcore", ".gitignore"));
|
|
10827
11033
|
return acLines?.has(".env.local") ?? false;
|
|
10828
11034
|
}
|
|
10829
11035
|
function studioIgnored(lines) {
|
|
@@ -10834,8 +11040,8 @@ function studioIgnored(lines) {
|
|
|
10834
11040
|
}
|
|
10835
11041
|
async function checkGitignoreExcludesSecrets(root, _target) {
|
|
10836
11042
|
const out = [];
|
|
10837
|
-
const ws =
|
|
10838
|
-
const gi =
|
|
11043
|
+
const ws = path25.dirname(path25.dirname(envLocalPath11(root)));
|
|
11044
|
+
const gi = path25.join(ws, ".gitignore");
|
|
10839
11045
|
const lines = gitignoreLines(gi);
|
|
10840
11046
|
if (lines === null) {
|
|
10841
11047
|
return [
|
|
@@ -10857,7 +11063,7 @@ async function checkGitignoreExcludesSecrets(root, _target) {
|
|
|
10857
11063
|
details: { missing: [".studio/"] }
|
|
10858
11064
|
});
|
|
10859
11065
|
}
|
|
10860
|
-
if (isDir5(
|
|
11066
|
+
if (isDir5(path25.join(ws, "agentcore")) && !agentcoreEnvLocalIgnored(ws)) {
|
|
10861
11067
|
out.push({
|
|
10862
11068
|
level: Level.CRITICAL,
|
|
10863
11069
|
name: "gitignore_excludes_secrets",
|
|
@@ -10874,16 +11080,16 @@ function installedRuntimeVersion() {
|
|
|
10874
11080
|
}
|
|
10875
11081
|
try {
|
|
10876
11082
|
const entry = require2.resolve("@bnbagent/studio-runtime");
|
|
10877
|
-
let dir =
|
|
11083
|
+
let dir = path25.dirname(entry);
|
|
10878
11084
|
for (let i = 0; i < 10; i++) {
|
|
10879
|
-
const pkgPath =
|
|
10880
|
-
if (
|
|
10881
|
-
const pkg = JSON.parse(
|
|
11085
|
+
const pkgPath = path25.join(dir, "package.json");
|
|
11086
|
+
if (isFile11(pkgPath)) {
|
|
11087
|
+
const pkg = JSON.parse(fs26.readFileSync(pkgPath, "utf-8"));
|
|
10882
11088
|
if (pkg.name === "@bnbagent/studio-runtime") {
|
|
10883
11089
|
return typeof pkg.version === "string" ? pkg.version : null;
|
|
10884
11090
|
}
|
|
10885
11091
|
}
|
|
10886
|
-
const parent =
|
|
11092
|
+
const parent = path25.dirname(dir);
|
|
10887
11093
|
if (parent === dir) {
|
|
10888
11094
|
break;
|
|
10889
11095
|
}
|
|
@@ -11167,9 +11373,9 @@ function x402SellerRailChecks(agentRoot2, cfg, target) {
|
|
|
11167
11373
|
details: { destination, target, stackRuntime: stackRuntime2 }
|
|
11168
11374
|
});
|
|
11169
11375
|
}
|
|
11170
|
-
const dockerfile =
|
|
11171
|
-
if (rails.x402 &&
|
|
11172
|
-
const source =
|
|
11376
|
+
const dockerfile = path25.join(agentRoot2, "Dockerfile");
|
|
11377
|
+
if (rails.x402 && isFile11(dockerfile)) {
|
|
11378
|
+
const source = fs26.readFileSync(dockerfile, "utf8");
|
|
11173
11379
|
if (!/^\s*FROM\s+node:22(?:[.-]|\s|$)/im.test(source)) {
|
|
11174
11380
|
out.push({
|
|
11175
11381
|
level: Level.WARNING,
|
|
@@ -11242,10 +11448,10 @@ async function checkDeployCliRunnable(_root, target) {
|
|
|
11242
11448
|
];
|
|
11243
11449
|
}
|
|
11244
11450
|
function agentcoreEnvVars(root) {
|
|
11245
|
-
const descriptor =
|
|
11451
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
11246
11452
|
let data;
|
|
11247
11453
|
try {
|
|
11248
|
-
data = JSON.parse(
|
|
11454
|
+
data = JSON.parse(fs26.readFileSync(descriptor, "utf-8"));
|
|
11249
11455
|
} catch {
|
|
11250
11456
|
return [];
|
|
11251
11457
|
}
|
|
@@ -11327,7 +11533,7 @@ async function checkRuntimeSecretsInjected(root, target) {
|
|
|
11327
11533
|
}
|
|
11328
11534
|
];
|
|
11329
11535
|
}
|
|
11330
|
-
const lines = gitignoreLines(
|
|
11536
|
+
const lines = gitignoreLines(path25.join(root, ".gitignore"));
|
|
11331
11537
|
let tracked = true;
|
|
11332
11538
|
if (lines !== null) {
|
|
11333
11539
|
for (const p of ["agentcore/agentcore.json", "agentcore/", "/agentcore/"]) {
|
|
@@ -11352,7 +11558,7 @@ async function checkAwsTargetsPopulated(root, target) {
|
|
|
11352
11558
|
if (target !== "agentcore") {
|
|
11353
11559
|
return [];
|
|
11354
11560
|
}
|
|
11355
|
-
const p =
|
|
11561
|
+
const p = path25.join(root, "agentcore", "aws-targets.json");
|
|
11356
11562
|
const [account, region] = readAwsTarget(root);
|
|
11357
11563
|
if (account && region) {
|
|
11358
11564
|
return [];
|
|
@@ -11366,6 +11572,84 @@ async function checkAwsTargetsPopulated(root, target) {
|
|
|
11366
11572
|
}
|
|
11367
11573
|
];
|
|
11368
11574
|
}
|
|
11575
|
+
var AGENTCORE_AGENT_QUOTA_CODE = "L-F4575653";
|
|
11576
|
+
function awsJson(stdout) {
|
|
11577
|
+
try {
|
|
11578
|
+
const parsed = JSON.parse(stdout);
|
|
11579
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
11580
|
+
} catch {
|
|
11581
|
+
return null;
|
|
11582
|
+
}
|
|
11583
|
+
}
|
|
11584
|
+
async function checkAgentcoreQuotaHeadroom(root, target) {
|
|
11585
|
+
if (target !== "agentcore") {
|
|
11586
|
+
return [];
|
|
11587
|
+
}
|
|
11588
|
+
const [, region] = readAwsTarget(root);
|
|
11589
|
+
if (!region || !await whichBin("aws")) {
|
|
11590
|
+
return [];
|
|
11591
|
+
}
|
|
11592
|
+
const quotaRes = await runCapture("aws", [
|
|
11593
|
+
"service-quotas",
|
|
11594
|
+
"get-service-quota",
|
|
11595
|
+
"--service-code",
|
|
11596
|
+
"bedrock-agentcore",
|
|
11597
|
+
"--quota-code",
|
|
11598
|
+
AGENTCORE_AGENT_QUOTA_CODE,
|
|
11599
|
+
"--region",
|
|
11600
|
+
region,
|
|
11601
|
+
"--output",
|
|
11602
|
+
"json"
|
|
11603
|
+
]);
|
|
11604
|
+
if (quotaRes.code !== 0) {
|
|
11605
|
+
return [];
|
|
11606
|
+
}
|
|
11607
|
+
const quota = awsJson(quotaRes.stdout)?.Quota;
|
|
11608
|
+
const limit = typeof quota?.Value === "number" ? quota.Value : null;
|
|
11609
|
+
if (limit === null) {
|
|
11610
|
+
return [];
|
|
11611
|
+
}
|
|
11612
|
+
const listRes = await runCapture("aws", [
|
|
11613
|
+
"bedrock-agentcore-control",
|
|
11614
|
+
"list-agent-runtimes",
|
|
11615
|
+
"--region",
|
|
11616
|
+
region,
|
|
11617
|
+
"--output",
|
|
11618
|
+
"json"
|
|
11619
|
+
]);
|
|
11620
|
+
if (listRes.code !== 0) {
|
|
11621
|
+
return [];
|
|
11622
|
+
}
|
|
11623
|
+
const runtimes = awsJson(listRes.stdout)?.agentRuntimes;
|
|
11624
|
+
if (!Array.isArray(runtimes)) {
|
|
11625
|
+
return [];
|
|
11626
|
+
}
|
|
11627
|
+
const used = runtimes.length;
|
|
11628
|
+
const details = {
|
|
11629
|
+
used,
|
|
11630
|
+
limit,
|
|
11631
|
+
region,
|
|
11632
|
+
quota_code: AGENTCORE_AGENT_QUOTA_CODE
|
|
11633
|
+
};
|
|
11634
|
+
if (used < limit) {
|
|
11635
|
+
return [
|
|
11636
|
+
{
|
|
11637
|
+
level: Level.INFO,
|
|
11638
|
+
name: "agentcore_quota_headroom",
|
|
11639
|
+
message: `AgentCore runtimes: ${used}/${limit} used in ${region}.`,
|
|
11640
|
+
details
|
|
11641
|
+
}
|
|
11642
|
+
];
|
|
11643
|
+
}
|
|
11644
|
+
return [
|
|
11645
|
+
{
|
|
11646
|
+
level: Level.CRITICAL,
|
|
11647
|
+
name: "agentcore_quota_headroom",
|
|
11648
|
+
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.`,
|
|
11649
|
+
details
|
|
11650
|
+
}
|
|
11651
|
+
];
|
|
11652
|
+
}
|
|
11369
11653
|
var allChecks = [
|
|
11370
11654
|
checkAgentcoreJsonPresent,
|
|
11371
11655
|
checkAgentcoreAuthorizerKeyLegacy,
|
|
@@ -11383,6 +11667,10 @@ var allChecks = [
|
|
|
11383
11667
|
checkTwakPasswordEnvSet,
|
|
11384
11668
|
checkTwakCredentialsAvailable,
|
|
11385
11669
|
checkTwakDockerAvailable,
|
|
11670
|
+
// altana-kind checks (every one early-returns for other kinds).
|
|
11671
|
+
checkAltanaSessionReady,
|
|
11672
|
+
checkAltanaSdkResolvable,
|
|
11673
|
+
checkAltanaSessionNotInsideAgent,
|
|
11386
11674
|
checkLlmProviderKeySet,
|
|
11387
11675
|
checkGitignoreExcludesSecrets,
|
|
11388
11676
|
checkInstalledBnbagentStudioMatches,
|
|
@@ -11390,23 +11678,24 @@ var allChecks = [
|
|
|
11390
11678
|
checkCommerceReady,
|
|
11391
11679
|
checkDeployCliRunnable,
|
|
11392
11680
|
checkRuntimeSecretsInjected,
|
|
11393
|
-
checkAwsTargetsPopulated
|
|
11681
|
+
checkAwsTargetsPopulated,
|
|
11682
|
+
checkAgentcoreQuotaHeadroom
|
|
11394
11683
|
];
|
|
11395
11684
|
|
|
11396
11685
|
// src/cli/_deploy/secrets.ts
|
|
11397
11686
|
var KEYSTORE_JSON_ENV = "WALLET_KEYSTORE_JSON";
|
|
11398
11687
|
var TWAK_WALLET_JSON_ENV = "TWAK_WALLET_JSON";
|
|
11399
11688
|
var TWAK_CREDENTIALS_JSON_ENV = "TWAK_CREDENTIALS_JSON";
|
|
11400
|
-
function
|
|
11689
|
+
function isFile12(p) {
|
|
11401
11690
|
try {
|
|
11402
|
-
return
|
|
11691
|
+
return fs27.statSync(p).isFile();
|
|
11403
11692
|
} catch {
|
|
11404
11693
|
return false;
|
|
11405
11694
|
}
|
|
11406
11695
|
}
|
|
11407
11696
|
function loadTomlOr(agentRoot2) {
|
|
11408
11697
|
try {
|
|
11409
|
-
return loadStudioToml13(
|
|
11698
|
+
return loadStudioToml13(path26.join(agentRoot2, "studio.toml"));
|
|
11410
11699
|
} catch {
|
|
11411
11700
|
return {};
|
|
11412
11701
|
}
|
|
@@ -11423,13 +11712,13 @@ function resolveKeystoreDir3(agentRoot2) {
|
|
|
11423
11712
|
const rel = String(
|
|
11424
11713
|
tableOf10(loadTomlOr(agentRoot2), "wallet").keystore_dir ?? ".studio/wallets"
|
|
11425
11714
|
);
|
|
11426
|
-
return
|
|
11715
|
+
return path26.resolve(path26.isAbsolute(rel) ? rel : path26.join(agentRoot2, rel));
|
|
11427
11716
|
}
|
|
11428
11717
|
function readKeystoreJson(agentRoot2) {
|
|
11429
11718
|
const keystoreDir = resolveKeystoreDir3(agentRoot2);
|
|
11430
11719
|
let names;
|
|
11431
11720
|
try {
|
|
11432
|
-
names =
|
|
11721
|
+
names = fs27.readdirSync(keystoreDir).filter((n) => n.endsWith(".json")).sort();
|
|
11433
11722
|
} catch {
|
|
11434
11723
|
return null;
|
|
11435
11724
|
}
|
|
@@ -11451,9 +11740,9 @@ function readKeystoreJson(agentRoot2) {
|
|
|
11451
11740
|
);
|
|
11452
11741
|
}
|
|
11453
11742
|
}
|
|
11454
|
-
const file =
|
|
11743
|
+
const file = path26.join(keystoreDir, chosen ?? names[0]);
|
|
11455
11744
|
try {
|
|
11456
|
-
return
|
|
11745
|
+
return fs27.readFileSync(file, "utf-8");
|
|
11457
11746
|
} catch {
|
|
11458
11747
|
return null;
|
|
11459
11748
|
}
|
|
@@ -11462,10 +11751,10 @@ function readEnvLocal(agentRoot2) {
|
|
|
11462
11751
|
const values = {};
|
|
11463
11752
|
try {
|
|
11464
11753
|
const file = envLocalPath12(agentRoot2);
|
|
11465
|
-
if (!
|
|
11754
|
+
if (!isFile12(file)) {
|
|
11466
11755
|
return values;
|
|
11467
11756
|
}
|
|
11468
|
-
for (const rawLine of
|
|
11757
|
+
for (const rawLine of fs27.readFileSync(file, "utf-8").split(/\r?\n/)) {
|
|
11469
11758
|
const line = rawLine.trim();
|
|
11470
11759
|
if (!line || line.startsWith("#")) {
|
|
11471
11760
|
continue;
|
|
@@ -11487,11 +11776,6 @@ function readEnvLocal(agentRoot2) {
|
|
|
11487
11776
|
}
|
|
11488
11777
|
function collectRuntimeSecretsDetailed(root) {
|
|
11489
11778
|
const agentRoot2 = findSubProjectRoot8("agent", root) ?? root;
|
|
11490
|
-
if (deployWalletKind(agentRoot2) === "altana") {
|
|
11491
|
-
throw new Error(
|
|
11492
|
-
"Altana deployment is deferred: refusing to collect either the admin keystore or runtime session for a deploy target."
|
|
11493
|
-
);
|
|
11494
|
-
}
|
|
11495
11779
|
const secretKeys = runtimeEnvKeys2(agentRoot2);
|
|
11496
11780
|
const fileValues = readEnvLocal(agentRoot2);
|
|
11497
11781
|
const payload = {};
|
|
@@ -11504,7 +11788,8 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11504
11788
|
sources[k] = fromFile ? ".studio/.env.local" : "process.env";
|
|
11505
11789
|
}
|
|
11506
11790
|
}
|
|
11507
|
-
|
|
11791
|
+
const walletKind2 = deployWalletKind(agentRoot2);
|
|
11792
|
+
if (walletKind2 === "twak") {
|
|
11508
11793
|
const [walletJson, credentialsJson] = readTwakFiles(agentRoot2);
|
|
11509
11794
|
if (walletJson) {
|
|
11510
11795
|
payload[TWAK_WALLET_JSON_ENV] = walletJson;
|
|
@@ -11514,6 +11799,9 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11514
11799
|
payload[TWAK_CREDENTIALS_JSON_ENV] = credentialsJson;
|
|
11515
11800
|
sources[TWAK_CREDENTIALS_JSON_ENV] = "wallet-file";
|
|
11516
11801
|
}
|
|
11802
|
+
} else if (walletKind2 === "altana") {
|
|
11803
|
+
payload[ALTANA_SESSION_ENV] = altanaSessionForRuntime(agentRoot2);
|
|
11804
|
+
sources[ALTANA_SESSION_ENV] = "wallet-file";
|
|
11517
11805
|
} else {
|
|
11518
11806
|
const keystoreJson = readKeystoreJson(agentRoot2);
|
|
11519
11807
|
if (keystoreJson) {
|
|
@@ -11521,7 +11809,7 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11521
11809
|
sources[KEYSTORE_JSON_ENV] = "wallet-file";
|
|
11522
11810
|
}
|
|
11523
11811
|
}
|
|
11524
|
-
if (!(KEYSTORE_JSON_ENV in payload) && !(TWAK_WALLET_JSON_ENV in payload)) {
|
|
11812
|
+
if (walletKind2 !== "altana" && !(KEYSTORE_JSON_ENV in payload) && !(TWAK_WALLET_JSON_ENV in payload)) {
|
|
11525
11813
|
printErr(
|
|
11526
11814
|
`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.`
|
|
11527
11815
|
);
|
|
@@ -11553,12 +11841,12 @@ var SCOPE_NAME = "invoke";
|
|
|
11553
11841
|
var SCOPE = `${RESOURCE_SERVER_ID}/${SCOPE_NAME}`;
|
|
11554
11842
|
var COGNITO_OUTPUTS_FILE = "agentcore/cognito/cdk-outputs.json";
|
|
11555
11843
|
function emitNextSteps(result) {
|
|
11556
|
-
return `\u2713 wrote Cognito CDK app to ${
|
|
11557
|
-
- ${
|
|
11558
|
-
- ${
|
|
11844
|
+
return `\u2713 wrote Cognito CDK app to ${path27.dirname(result.appPath)}
|
|
11845
|
+
- ${path27.basename(result.appPath)} (CognitoStack: user pool + resource server + M2M client)
|
|
11846
|
+
- ${path27.basename(result.readmePath)} (deploy + wiring instructions)
|
|
11559
11847
|
|
|
11560
11848
|
Next steps:
|
|
11561
|
-
1. cd ${
|
|
11849
|
+
1. cd ${path27.dirname(result.appPath)}
|
|
11562
11850
|
2. npm install # aws-cdk-lib + constructs + the cdk CLI (local)
|
|
11563
11851
|
3. npx cdk deploy --outputs-file cdk-outputs.json # YOU run this (the only AWS step)
|
|
11564
11852
|
4. bag deploy provision-cognito --wire # studio reads cdk-outputs.json \u2192
|
|
@@ -11674,6 +11962,12 @@ function cognitoPackageJson() {
|
|
|
11674
11962
|
function readme() {
|
|
11675
11963
|
return `# Cognito M2M client for the AgentCore A2A inbound OAuth2 authorizer
|
|
11676
11964
|
|
|
11965
|
+
> **DEPRECATED.** \`bag deploy --provider aws\` now provisions its own user pool
|
|
11966
|
+
> and M2M client, and overwrites the values wired from this stack. Deploying
|
|
11967
|
+
> this app leaves a second, unused pool behind that you have to clean up
|
|
11968
|
+
> yourself. Keep it only if you need to own the pool out of band; otherwise run
|
|
11969
|
+
> \`bag deploy --provider aws\` and hand buyers the credentials it prints.
|
|
11970
|
+
|
|
11677
11971
|
AgentCore A2A endpoints REQUIRE inbound auth (there is no anonymous mode). This
|
|
11678
11972
|
seller uses **OAuth2 via Cognito** \u2014 NOT SigV4, because external buyers cannot
|
|
11679
11973
|
obtain your AWS IAM credentials. Cognito has no public machine-to-machine
|
|
@@ -11714,12 +12008,11 @@ This reads the local \`cdk-outputs.json\` and patches:
|
|
|
11714
12008
|
| \`Scope\` | \`agentcore.json\` \u2192 \`envVars[] OAUTH_SCOPE\` (+ \`.studio/.env.local\` for local dev) |
|
|
11715
12009
|
|
|
11716
12010
|
\`OAUTH_TOKEN_URL\` / \`OAUTH_SCOPE\` are read by the emitted agent card from
|
|
11717
|
-
the environment, so the
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
|
|
11722
|
-
custom outputs path.)
|
|
12011
|
+
the environment, so the agent card advertises the OAuth2 security scheme buyers
|
|
12012
|
+
must use. **A \`bag deploy\` run replaces both values (and the authorizer) with
|
|
12013
|
+
the pool it provisions itself**, so this wiring only takes effect for local
|
|
12014
|
+
\`bag dev\`. (\`bag deploy provision-cognito --wire <file>\` accepts a custom
|
|
12015
|
+
outputs path.)
|
|
11723
12016
|
|
|
11724
12017
|
## Issue buyer credentials
|
|
11725
12018
|
|
|
@@ -11749,28 +12042,29 @@ function emitCognitoCdk(workspaceRoot, opts = {}) {
|
|
|
11749
12042
|
regionHint = null;
|
|
11750
12043
|
}
|
|
11751
12044
|
}
|
|
11752
|
-
const outDir =
|
|
11753
|
-
|
|
11754
|
-
const appPath =
|
|
11755
|
-
const readmePath =
|
|
11756
|
-
|
|
11757
|
-
|
|
11758
|
-
|
|
11759
|
-
|
|
12045
|
+
const outDir = path27.join(workspaceRoot, COGNITO_DIR);
|
|
12046
|
+
fs28.mkdirSync(outDir, { recursive: true });
|
|
12047
|
+
const appPath = path27.join(outDir, "app.ts");
|
|
12048
|
+
const readmePath = path27.join(outDir, "README.md");
|
|
12049
|
+
fs28.writeFileSync(appPath, appTs(regionHint), "utf-8");
|
|
12050
|
+
fs28.writeFileSync(path27.join(outDir, "cdk.json"), cdkJson(), "utf-8");
|
|
12051
|
+
fs28.writeFileSync(
|
|
12052
|
+
path27.join(outDir, "package.json"),
|
|
11760
12053
|
cognitoPackageJson(),
|
|
11761
12054
|
"utf-8"
|
|
11762
12055
|
);
|
|
11763
|
-
|
|
12056
|
+
fs28.writeFileSync(readmePath, readme(), "utf-8");
|
|
11764
12057
|
return { appPath, readmePath };
|
|
11765
12058
|
}
|
|
11766
12059
|
function wireSummary(r) {
|
|
11767
12060
|
return `\u2713 wired Cognito authorizer from the CDK outputs (no AWS call \u2014 read a local file):
|
|
11768
|
-
- ${
|
|
12061
|
+
- ${path27.basename(r.agentcoreJson)}: authorizerConfiguration.customJwtAuthorizer
|
|
11769
12062
|
discoveryUrl = ${r.discoveryUrl}
|
|
11770
12063
|
allowedClients = [${r.clientId}]
|
|
11771
|
-
- ${
|
|
12064
|
+
- ${path27.basename(r.agentcoreJson)}: envVars[] OAUTH_TOKEN_URL + OAUTH_SCOPE (reach the runtime so the agent card advertises oauth2)
|
|
11772
12065
|
- ${r.envLocal}: same pair, for local \`bag dev\`
|
|
11773
|
-
\u2192 \`bag deploy
|
|
12066
|
+
\u2192 NOTE: a \`bag deploy\` run provisions its own pool and overwrites these
|
|
12067
|
+
values with the ones it issued. This wiring only feeds local \`bag dev\`.`;
|
|
11774
12068
|
}
|
|
11775
12069
|
function flattenCdkOutputs(raw) {
|
|
11776
12070
|
const flat = {};
|
|
@@ -11798,11 +12092,54 @@ function upsertDescriptorEnvvars(cfg, values) {
|
|
|
11798
12092
|
}
|
|
11799
12093
|
}
|
|
11800
12094
|
}
|
|
12095
|
+
function syncDescriptorOauthFacts(workspaceRoot, facts) {
|
|
12096
|
+
const acj = path27.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
12097
|
+
let cfg;
|
|
12098
|
+
try {
|
|
12099
|
+
cfg = JSON.parse(fs28.readFileSync(acj, "utf-8"));
|
|
12100
|
+
} catch {
|
|
12101
|
+
return;
|
|
12102
|
+
}
|
|
12103
|
+
const envValues = {};
|
|
12104
|
+
if (facts.tokenUrl) {
|
|
12105
|
+
envValues.OAUTH_TOKEN_URL = facts.tokenUrl;
|
|
12106
|
+
}
|
|
12107
|
+
if (facts.scope) {
|
|
12108
|
+
envValues.OAUTH_SCOPE = facts.scope;
|
|
12109
|
+
}
|
|
12110
|
+
const authorizer = facts.discoveryUrl && facts.clientId ? {
|
|
12111
|
+
customJwtAuthorizer: {
|
|
12112
|
+
discoveryUrl: facts.discoveryUrl,
|
|
12113
|
+
allowedClients: [facts.clientId]
|
|
12114
|
+
}
|
|
12115
|
+
} : null;
|
|
12116
|
+
if (Object.keys(envValues).length === 0 && authorizer === null) {
|
|
12117
|
+
return;
|
|
12118
|
+
}
|
|
12119
|
+
if (Object.keys(envValues).length > 0) {
|
|
12120
|
+
upsertDescriptorEnvvars(cfg, envValues);
|
|
12121
|
+
}
|
|
12122
|
+
if (authorizer !== null && Array.isArray(cfg.runtimes)) {
|
|
12123
|
+
for (const rt of cfg.runtimes) {
|
|
12124
|
+
if (rt !== null && typeof rt === "object") {
|
|
12125
|
+
const r = rt;
|
|
12126
|
+
r.authorizerType = "CUSTOM_JWT";
|
|
12127
|
+
r.authorizerConfiguration = authorizer;
|
|
12128
|
+
}
|
|
12129
|
+
}
|
|
12130
|
+
}
|
|
12131
|
+
try {
|
|
12132
|
+
fs28.writeFileSync(acj, `${JSON.stringify(cfg, null, 2)}
|
|
12133
|
+
`, "utf-8");
|
|
12134
|
+
} catch {
|
|
12135
|
+
return;
|
|
12136
|
+
}
|
|
12137
|
+
}
|
|
11801
12138
|
function upsertEnv(envLocal, values) {
|
|
11802
12139
|
let lines = [];
|
|
11803
12140
|
try {
|
|
11804
|
-
if (
|
|
11805
|
-
lines =
|
|
12141
|
+
if (fs28.statSync(envLocal).isFile()) {
|
|
12142
|
+
lines = fs28.readFileSync(envLocal, "utf-8").split(/\r?\n/);
|
|
11806
12143
|
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
11807
12144
|
lines.pop();
|
|
11808
12145
|
}
|
|
@@ -11821,19 +12158,19 @@ function upsertEnv(envLocal, values) {
|
|
|
11821
12158
|
lines.push(repl);
|
|
11822
12159
|
}
|
|
11823
12160
|
}
|
|
11824
|
-
|
|
11825
|
-
|
|
12161
|
+
fs28.mkdirSync(path27.dirname(envLocal), { recursive: true });
|
|
12162
|
+
fs28.writeFileSync(envLocal, `${lines.join("\n")}
|
|
11826
12163
|
`, {
|
|
11827
12164
|
encoding: "utf-8",
|
|
11828
12165
|
mode: 384
|
|
11829
12166
|
});
|
|
11830
|
-
|
|
12167
|
+
fs28.chmodSync(envLocal, 384);
|
|
11831
12168
|
}
|
|
11832
12169
|
function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
11833
|
-
const outPath = outputsFile ??
|
|
12170
|
+
const outPath = outputsFile ?? path27.join(workspaceRoot, COGNITO_OUTPUTS_FILE);
|
|
11834
12171
|
let exists = false;
|
|
11835
12172
|
try {
|
|
11836
|
-
exists =
|
|
12173
|
+
exists = fs28.statSync(outPath).isFile();
|
|
11837
12174
|
} catch {
|
|
11838
12175
|
exists = false;
|
|
11839
12176
|
}
|
|
@@ -11843,7 +12180,7 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
11843
12180
|
);
|
|
11844
12181
|
}
|
|
11845
12182
|
const outs = flattenCdkOutputs(
|
|
11846
|
-
JSON.parse(
|
|
12183
|
+
JSON.parse(fs28.readFileSync(outPath, "utf-8"))
|
|
11847
12184
|
);
|
|
11848
12185
|
for (const key of ["DiscoveryUrl", "AppClientId", "TokenUrl", "Scope"]) {
|
|
11849
12186
|
if (outs[key] === void 0) {
|
|
@@ -11856,8 +12193,8 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
11856
12193
|
const clientId = String(outs.AppClientId);
|
|
11857
12194
|
const tokenUrl = String(outs.TokenUrl);
|
|
11858
12195
|
const scope = String(outs.Scope);
|
|
11859
|
-
const acj =
|
|
11860
|
-
const cfg = JSON.parse(
|
|
12196
|
+
const acj = path27.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
12197
|
+
const cfg = JSON.parse(fs28.readFileSync(acj, "utf-8"));
|
|
11861
12198
|
const runtimes = cfg.runtimes;
|
|
11862
12199
|
if (!Array.isArray(runtimes) || runtimes.length === 0) {
|
|
11863
12200
|
throw new Error(
|
|
@@ -11880,7 +12217,7 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
11880
12217
|
OAUTH_TOKEN_URL: tokenUrl,
|
|
11881
12218
|
OAUTH_SCOPE: scope
|
|
11882
12219
|
});
|
|
11883
|
-
|
|
12220
|
+
fs28.writeFileSync(acj, `${JSON.stringify(cfg, null, 2)}
|
|
11884
12221
|
`, "utf-8");
|
|
11885
12222
|
const envLocal = envLocalPath13(workspaceRoot);
|
|
11886
12223
|
upsertEnv(envLocal, { OAUTH_TOKEN_URL: tokenUrl, OAUTH_SCOPE: scope });
|
|
@@ -11895,13 +12232,13 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
11895
12232
|
}
|
|
11896
12233
|
|
|
11897
12234
|
// src/cli/_deploy/destroy.ts
|
|
11898
|
-
import * as
|
|
11899
|
-
import * as
|
|
12235
|
+
import * as fs30 from "fs";
|
|
12236
|
+
import * as path29 from "path";
|
|
11900
12237
|
import { findSubProjectRoot as findSubProjectRoot10 } from "@bnbagent/studio-runtime/config";
|
|
11901
12238
|
|
|
11902
12239
|
// src/cli/_deploy/status.ts
|
|
11903
|
-
import * as
|
|
11904
|
-
import * as
|
|
12240
|
+
import * as fs29 from "fs";
|
|
12241
|
+
import * as path28 from "path";
|
|
11905
12242
|
import {
|
|
11906
12243
|
APP_DIR as APP_DIR2,
|
|
11907
12244
|
findSubProjectRoot as findSubProjectRoot9,
|
|
@@ -11916,20 +12253,20 @@ function loadToml(p) {
|
|
|
11916
12253
|
}
|
|
11917
12254
|
}
|
|
11918
12255
|
function projectName(workspaceRoot) {
|
|
11919
|
-
const descriptor =
|
|
12256
|
+
const descriptor = path28.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
11920
12257
|
try {
|
|
11921
|
-
const data = JSON.parse(
|
|
12258
|
+
const data = JSON.parse(fs29.readFileSync(descriptor, "utf-8"));
|
|
11922
12259
|
if (data !== null && typeof data === "object" && data.name) {
|
|
11923
12260
|
return String(data.name);
|
|
11924
12261
|
}
|
|
11925
12262
|
} catch {
|
|
11926
12263
|
}
|
|
11927
|
-
return
|
|
12264
|
+
return path28.basename(workspaceRoot);
|
|
11928
12265
|
}
|
|
11929
12266
|
async function runStatus(opts = {}) {
|
|
11930
|
-
const start = opts.projectRoot ?
|
|
12267
|
+
const start = opts.projectRoot ? path28.resolve(opts.projectRoot) : void 0;
|
|
11931
12268
|
const agentRoot2 = findSubProjectRoot9("agent", start);
|
|
11932
|
-
const agentData = agentRoot2 !== null ? loadToml(
|
|
12269
|
+
const agentData = agentRoot2 !== null ? loadToml(path28.join(agentRoot2, "studio.toml")) : {};
|
|
11933
12270
|
const deployRaw = agentData.deploy;
|
|
11934
12271
|
const deploy = deployRaw !== null && typeof deployRaw === "object" && !Array.isArray(deployRaw) ? { ...deployRaw } : {};
|
|
11935
12272
|
const runtimeArn = deploy.runtime_arn ? String(deploy.runtime_arn) : null;
|
|
@@ -11942,8 +12279,8 @@ async function runStatus(opts = {}) {
|
|
|
11942
12279
|
}
|
|
11943
12280
|
const onchainEndpoint = identity.endpoint ? String(identity.endpoint) : null;
|
|
11944
12281
|
const agentReachable = null;
|
|
11945
|
-
const workspaceBase2 = findWorkspaceRoot5(start) ?? (agentRoot2 !== null ?
|
|
11946
|
-
const workspaceRoot = workspaceBase2 !== null &&
|
|
12282
|
+
const workspaceBase2 = findWorkspaceRoot5(start) ?? (agentRoot2 !== null ? path28.dirname(agentRoot2) : null);
|
|
12283
|
+
const workspaceRoot = workspaceBase2 !== null && path28.basename(workspaceBase2) === APP_DIR2 ? path28.dirname(workspaceBase2) : workspaceBase2;
|
|
11947
12284
|
let region = null;
|
|
11948
12285
|
let account = null;
|
|
11949
12286
|
let secretId = null;
|
|
@@ -12011,9 +12348,9 @@ function nullRecordedState(workspaceRoot) {
|
|
|
12011
12348
|
if (agentRoot2 === null) {
|
|
12012
12349
|
return;
|
|
12013
12350
|
}
|
|
12014
|
-
const ap =
|
|
12351
|
+
const ap = path29.join(agentRoot2, "studio.toml");
|
|
12015
12352
|
try {
|
|
12016
|
-
if (!
|
|
12353
|
+
if (!fs30.statSync(ap).isFile()) {
|
|
12017
12354
|
return;
|
|
12018
12355
|
}
|
|
12019
12356
|
} catch {
|
|
@@ -12077,8 +12414,8 @@ async function runDestroy(opts) {
|
|
|
12077
12414
|
}
|
|
12078
12415
|
|
|
12079
12416
|
// src/cli/_deploy/packaging.ts
|
|
12080
|
-
import * as
|
|
12081
|
-
import * as
|
|
12417
|
+
import * as fs31 from "fs";
|
|
12418
|
+
import * as path30 from "path";
|
|
12082
12419
|
import {
|
|
12083
12420
|
findSubProjectRoot as findSubProjectRoot11,
|
|
12084
12421
|
loadStudioToml as loadStudioToml15
|
|
@@ -12087,9 +12424,9 @@ function agentRootOf2(root) {
|
|
|
12087
12424
|
return findSubProjectRoot11("agent", root);
|
|
12088
12425
|
}
|
|
12089
12426
|
function agentTable(agentRoot2, key) {
|
|
12090
|
-
const tomlPath =
|
|
12427
|
+
const tomlPath = path30.join(agentRoot2, "studio.toml");
|
|
12091
12428
|
try {
|
|
12092
|
-
if (!
|
|
12429
|
+
if (!fs31.statSync(tomlPath).isFile()) {
|
|
12093
12430
|
return {};
|
|
12094
12431
|
}
|
|
12095
12432
|
} catch {
|
|
@@ -12156,10 +12493,10 @@ function checkPackagingDrift(root, destination, walletKind2, force) {
|
|
|
12156
12493
|
);
|
|
12157
12494
|
return 1;
|
|
12158
12495
|
}
|
|
12159
|
-
const dockerfile =
|
|
12496
|
+
const dockerfile = path30.join(agentRoot2, "Dockerfile");
|
|
12160
12497
|
let dockerfilePresent = false;
|
|
12161
12498
|
try {
|
|
12162
|
-
dockerfilePresent =
|
|
12499
|
+
dockerfilePresent = fs31.statSync(dockerfile).isFile();
|
|
12163
12500
|
} catch {
|
|
12164
12501
|
dockerfilePresent = false;
|
|
12165
12502
|
}
|
|
@@ -12200,7 +12537,7 @@ function deployWalletKindSafe(root) {
|
|
|
12200
12537
|
}
|
|
12201
12538
|
let cfg;
|
|
12202
12539
|
try {
|
|
12203
|
-
cfg = loadStudioToml15(
|
|
12540
|
+
cfg = loadStudioToml15(path30.join(agentRoot2, "studio.toml"));
|
|
12204
12541
|
} catch {
|
|
12205
12542
|
return "evm-local";
|
|
12206
12543
|
}
|
|
@@ -12213,22 +12550,22 @@ function deployWalletKindSafe(root) {
|
|
|
12213
12550
|
import { findStudioWorkspaceRoot as findStudioWorkspaceRoot2 } from "@bnbagent/studio-runtime/config";
|
|
12214
12551
|
|
|
12215
12552
|
// src/cli/_deploy/checks/blocked.ts
|
|
12216
|
-
import * as
|
|
12217
|
-
import * as
|
|
12553
|
+
import * as fs32 from "fs";
|
|
12554
|
+
import * as path31 from "path";
|
|
12218
12555
|
import {
|
|
12219
12556
|
findSubProjectRoot as findSubProjectRoot12,
|
|
12220
12557
|
loadStudioToml as loadStudioToml16
|
|
12221
12558
|
} from "@bnbagent/studio-runtime/config";
|
|
12222
|
-
function
|
|
12559
|
+
function isFile13(p) {
|
|
12223
12560
|
try {
|
|
12224
|
-
return
|
|
12561
|
+
return fs32.statSync(p).isFile();
|
|
12225
12562
|
} catch {
|
|
12226
12563
|
return false;
|
|
12227
12564
|
}
|
|
12228
12565
|
}
|
|
12229
12566
|
function isDir6(p) {
|
|
12230
12567
|
try {
|
|
12231
|
-
return
|
|
12568
|
+
return fs32.statSync(p).isDirectory();
|
|
12232
12569
|
} catch {
|
|
12233
12570
|
return false;
|
|
12234
12571
|
}
|
|
@@ -12239,8 +12576,8 @@ async function checkStudioTomlPresent(root, _target) {
|
|
|
12239
12576
|
agent: findSubProjectRoot12("agent", root)
|
|
12240
12577
|
};
|
|
12241
12578
|
for (const [side, subRoot] of Object.entries(layers)) {
|
|
12242
|
-
const tomlPath = subRoot === null ? null :
|
|
12243
|
-
if (tomlPath === null || !
|
|
12579
|
+
const tomlPath = subRoot === null ? null : path31.join(subRoot, "studio.toml");
|
|
12580
|
+
if (tomlPath === null || !isFile13(tomlPath)) {
|
|
12244
12581
|
out.push({
|
|
12245
12582
|
level: Level.BLOCKED,
|
|
12246
12583
|
name: "studio_toml_present",
|
|
@@ -12264,8 +12601,8 @@ async function checkStudioTomlPresent(root, _target) {
|
|
|
12264
12601
|
return out;
|
|
12265
12602
|
}
|
|
12266
12603
|
async function checkCwdIsProjectRoot(root, _target) {
|
|
12267
|
-
const cwd =
|
|
12268
|
-
const rr =
|
|
12604
|
+
const cwd = path31.resolve(process.cwd());
|
|
12605
|
+
const rr = path31.resolve(root);
|
|
12269
12606
|
if (cwd !== rr) {
|
|
12270
12607
|
return [
|
|
12271
12608
|
{
|
|
@@ -12279,7 +12616,7 @@ async function checkCwdIsProjectRoot(root, _target) {
|
|
|
12279
12616
|
return [];
|
|
12280
12617
|
}
|
|
12281
12618
|
async function checkNoSecretInGitHistory(root, _target) {
|
|
12282
|
-
if (!isDir6(
|
|
12619
|
+
if (!isDir6(path31.join(root, ".git"))) {
|
|
12283
12620
|
return [];
|
|
12284
12621
|
}
|
|
12285
12622
|
const needles = [".env.local", "WALLET_PASSWORD"];
|
|
@@ -12317,8 +12654,8 @@ var allChecks2 = [
|
|
|
12317
12654
|
];
|
|
12318
12655
|
|
|
12319
12656
|
// src/cli/_deploy/checks/info.ts
|
|
12320
|
-
import * as
|
|
12321
|
-
import * as
|
|
12657
|
+
import * as fs33 from "fs";
|
|
12658
|
+
import * as path32 from "path";
|
|
12322
12659
|
async function checkPreviousDeployStatus(root, _target) {
|
|
12323
12660
|
const deploy = tableOf2(loadAgentToml(root), "deploy");
|
|
12324
12661
|
const last = deploy.last_deploy_at;
|
|
@@ -12342,10 +12679,10 @@ async function checkPreviousDeployStatus(root, _target) {
|
|
|
12342
12679
|
];
|
|
12343
12680
|
}
|
|
12344
12681
|
async function checkInstalledRecipesList(root, _target) {
|
|
12345
|
-
const manifest =
|
|
12682
|
+
const manifest = path32.join(root, ".studio", "recipes", "manifest.json");
|
|
12346
12683
|
let exists = false;
|
|
12347
12684
|
try {
|
|
12348
|
-
exists =
|
|
12685
|
+
exists = fs33.statSync(manifest).isFile();
|
|
12349
12686
|
} catch {
|
|
12350
12687
|
exists = false;
|
|
12351
12688
|
}
|
|
@@ -12361,7 +12698,7 @@ async function checkInstalledRecipesList(root, _target) {
|
|
|
12361
12698
|
}
|
|
12362
12699
|
let data;
|
|
12363
12700
|
try {
|
|
12364
|
-
data = JSON.parse(
|
|
12701
|
+
data = JSON.parse(fs33.readFileSync(manifest, "utf-8"));
|
|
12365
12702
|
} catch {
|
|
12366
12703
|
return [
|
|
12367
12704
|
{
|
|
@@ -12464,8 +12801,8 @@ var allChecks3 = [
|
|
|
12464
12801
|
];
|
|
12465
12802
|
|
|
12466
12803
|
// src/cli/_deploy/checks/platform.ts
|
|
12467
|
-
import * as
|
|
12468
|
-
import * as
|
|
12804
|
+
import * as fs35 from "fs";
|
|
12805
|
+
import * as path34 from "path";
|
|
12469
12806
|
import {
|
|
12470
12807
|
findSubProjectRoot as findSubProjectRoot13,
|
|
12471
12808
|
loadStudioToml as loadStudioToml17
|
|
@@ -12474,16 +12811,16 @@ import { BSC_TESTNET_FAUCET_URLS } from "@bnbagent/studio-runtime/networks";
|
|
|
12474
12811
|
|
|
12475
12812
|
// src/cli/_deploy/checks/warning.ts
|
|
12476
12813
|
import * as crypto4 from "crypto";
|
|
12477
|
-
import * as
|
|
12478
|
-
import * as
|
|
12814
|
+
import * as fs34 from "fs";
|
|
12815
|
+
import * as path33 from "path";
|
|
12479
12816
|
import { envLocalPath as envLocalPath14 } from "@bnbagent/studio-runtime/config";
|
|
12480
12817
|
import { show } from "@bnbagent/studio-runtime/erc8004";
|
|
12481
12818
|
import { DEFAULT_RPC, getNetwork as getNetwork8 } from "@bnbagent/studio-runtime/networks";
|
|
12482
12819
|
import * as walletRt3 from "@bnbagent/studio-runtime/wallet";
|
|
12483
12820
|
var TBNB_MIN_WEI = 7n * 10n ** 15n;
|
|
12484
|
-
function
|
|
12821
|
+
function isFile14(p) {
|
|
12485
12822
|
try {
|
|
12486
|
-
return
|
|
12823
|
+
return fs34.statSync(p).isFile();
|
|
12487
12824
|
} catch {
|
|
12488
12825
|
return false;
|
|
12489
12826
|
}
|
|
@@ -12686,10 +13023,10 @@ async function checkRuntimeRpcReachable(root, _target) {
|
|
|
12686
13023
|
return [];
|
|
12687
13024
|
}
|
|
12688
13025
|
async function checkInstalledRecipesUnchanged(root, _target) {
|
|
12689
|
-
const manifest =
|
|
13026
|
+
const manifest = path33.join(root, ".studio", "recipes", "manifest.json");
|
|
12690
13027
|
let data;
|
|
12691
13028
|
try {
|
|
12692
|
-
data = JSON.parse(
|
|
13029
|
+
data = JSON.parse(fs34.readFileSync(manifest, "utf-8"));
|
|
12693
13030
|
} catch {
|
|
12694
13031
|
return [];
|
|
12695
13032
|
}
|
|
@@ -12704,11 +13041,11 @@ async function checkInstalledRecipesUnchanged(root, _target) {
|
|
|
12704
13041
|
if (!rel || !expected || typeof rel !== "string") {
|
|
12705
13042
|
continue;
|
|
12706
13043
|
}
|
|
12707
|
-
const p =
|
|
12708
|
-
if (!
|
|
13044
|
+
const p = path33.join(root, rel);
|
|
13045
|
+
if (!isFile14(p)) {
|
|
12709
13046
|
continue;
|
|
12710
13047
|
}
|
|
12711
|
-
const actual = crypto4.createHash("sha256").update(
|
|
13048
|
+
const actual = crypto4.createHash("sha256").update(fs34.readFileSync(p)).digest("hex");
|
|
12712
13049
|
if (actual !== expected) {
|
|
12713
13050
|
stale.push(rel);
|
|
12714
13051
|
}
|
|
@@ -12725,59 +13062,6 @@ async function checkInstalledRecipesUnchanged(root, _target) {
|
|
|
12725
13062
|
}
|
|
12726
13063
|
return [];
|
|
12727
13064
|
}
|
|
12728
|
-
function agentcoreAuthorizer(root) {
|
|
12729
|
-
const descriptor = path32.join(root, "agentcore", "agentcore.json");
|
|
12730
|
-
let data;
|
|
12731
|
-
try {
|
|
12732
|
-
data = JSON.parse(fs33.readFileSync(descriptor, "utf-8"));
|
|
12733
|
-
} catch {
|
|
12734
|
-
return null;
|
|
12735
|
-
}
|
|
12736
|
-
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
12737
|
-
return null;
|
|
12738
|
-
}
|
|
12739
|
-
const runtimes = data.runtimes;
|
|
12740
|
-
if (!Array.isArray(runtimes)) {
|
|
12741
|
-
return null;
|
|
12742
|
-
}
|
|
12743
|
-
for (const rt of runtimes) {
|
|
12744
|
-
if (rt === null || typeof rt !== "object") {
|
|
12745
|
-
continue;
|
|
12746
|
-
}
|
|
12747
|
-
const auth = rt.authorizerConfiguration;
|
|
12748
|
-
if (auth !== null && typeof auth === "object" && !Array.isArray(auth)) {
|
|
12749
|
-
const jwt = auth.customJwtAuthorizer ?? auth.customJWTAuthorizer;
|
|
12750
|
-
if (jwt !== null && typeof jwt === "object" && !Array.isArray(jwt)) {
|
|
12751
|
-
return jwt;
|
|
12752
|
-
}
|
|
12753
|
-
}
|
|
12754
|
-
}
|
|
12755
|
-
return null;
|
|
12756
|
-
}
|
|
12757
|
-
async function checkCognitoAuthorizerConfigured(root, target) {
|
|
12758
|
-
if (target !== "agentcore") {
|
|
12759
|
-
return [];
|
|
12760
|
-
}
|
|
12761
|
-
const jwt = agentcoreAuthorizer(root);
|
|
12762
|
-
const discovery = jwt?.discoveryUrl;
|
|
12763
|
-
const clients = jwt?.allowedClients;
|
|
12764
|
-
const configured = Boolean(discovery) && Array.isArray(clients) && clients.length > 0;
|
|
12765
|
-
if (configured) {
|
|
12766
|
-
return [];
|
|
12767
|
-
}
|
|
12768
|
-
return [
|
|
12769
|
-
{
|
|
12770
|
-
level: Level.WARNING,
|
|
12771
|
-
name: "cognito_authorizer_configured",
|
|
12772
|
-
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.",
|
|
12773
|
-
fixCmd: "bag deploy provision-cognito",
|
|
12774
|
-
details: {
|
|
12775
|
-
discovery_url_set: Boolean(discovery),
|
|
12776
|
-
allowed_clients: Array.isArray(clients) ? clients : []
|
|
12777
|
-
}
|
|
12778
|
-
}
|
|
12779
|
-
];
|
|
12780
|
-
}
|
|
12781
13065
|
async function checkStorageLocalNotDeployable(root, _target) {
|
|
12782
13066
|
const storage = loadAgentToml(root).storage;
|
|
12783
13067
|
if (storage === null || typeof storage !== "object" || Array.isArray(storage) || String(storage.kind ?? "").toLowerCase() !== "local") {
|
|
@@ -12802,7 +13086,6 @@ var allChecks4 = [
|
|
|
12802
13086
|
checkRpcUrlSetForRuntime,
|
|
12803
13087
|
checkRuntimeRpcReachable,
|
|
12804
13088
|
checkInstalledRecipesUnchanged,
|
|
12805
|
-
checkCognitoAuthorizerConfigured,
|
|
12806
13089
|
checkStorageLocalNotDeployable
|
|
12807
13090
|
];
|
|
12808
13091
|
|
|
@@ -12813,11 +13096,11 @@ function tableOf11(data, key) {
|
|
|
12813
13096
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
12814
13097
|
}
|
|
12815
13098
|
function agentRoot(root) {
|
|
12816
|
-
return findSubProjectRoot13("agent", root) ??
|
|
13099
|
+
return findSubProjectRoot13("agent", root) ?? path34.join(root, "app", "agent");
|
|
12817
13100
|
}
|
|
12818
13101
|
function loadAgent(root) {
|
|
12819
13102
|
try {
|
|
12820
|
-
return loadStudioToml17(
|
|
13103
|
+
return loadStudioToml17(path34.join(agentRoot(root), "studio.toml"));
|
|
12821
13104
|
} catch {
|
|
12822
13105
|
return {};
|
|
12823
13106
|
}
|
|
@@ -12837,10 +13120,10 @@ var checkPlatformEntrypointPresent = async (root, _target) => {
|
|
|
12837
13120
|
const filenames = [`${stem2}.ts`];
|
|
12838
13121
|
if (stem2 === "dualMain") filenames.push("mcpMain.ts");
|
|
12839
13122
|
const filename = filenames.find(
|
|
12840
|
-
(candidate) => !
|
|
13123
|
+
(candidate) => !fs35.existsSync(path34.join(agentRoot(root), "src", candidate))
|
|
12841
13124
|
);
|
|
12842
13125
|
if (filename === void 0) return [];
|
|
12843
|
-
const expected =
|
|
13126
|
+
const expected = path34.join(agentRoot(root), "src", filename);
|
|
12844
13127
|
return [
|
|
12845
13128
|
{
|
|
12846
13129
|
level: Level.CRITICAL,
|
|
@@ -12854,18 +13137,18 @@ var checkPlatformKeystoreNotInArtifact = async (root, _target) => {
|
|
|
12854
13137
|
const data = loadAgent(root);
|
|
12855
13138
|
const wallet = tableOf11(data, "wallet");
|
|
12856
13139
|
if (String(wallet.kind ?? "evm-local") === "twak") return [];
|
|
12857
|
-
const agent =
|
|
13140
|
+
const agent = path34.resolve(agentRoot(root));
|
|
12858
13141
|
const configured = String(wallet.keystore_dir ?? ".studio/wallets");
|
|
12859
|
-
const keystore =
|
|
13142
|
+
const keystore = path34.resolve(agent, configured);
|
|
12860
13143
|
let jsonFiles;
|
|
12861
13144
|
try {
|
|
12862
|
-
jsonFiles =
|
|
13145
|
+
jsonFiles = fs35.readdirSync(keystore).filter((name) => name.endsWith(".json"));
|
|
12863
13146
|
} catch {
|
|
12864
13147
|
return [];
|
|
12865
13148
|
}
|
|
12866
13149
|
if (jsonFiles.length === 0) return [];
|
|
12867
|
-
const rel =
|
|
12868
|
-
if (rel.startsWith("..") ||
|
|
13150
|
+
const rel = path34.relative(agent, keystore);
|
|
13151
|
+
if (rel.startsWith("..") || path34.isAbsolute(rel)) return [];
|
|
12869
13152
|
return [
|
|
12870
13153
|
{
|
|
12871
13154
|
level: Level.CRITICAL,
|
|
@@ -13092,7 +13375,7 @@ async function runProducers(producers, root, target) {
|
|
|
13092
13375
|
}
|
|
13093
13376
|
|
|
13094
13377
|
// src/cli/_deploy/verify.ts
|
|
13095
|
-
import * as
|
|
13378
|
+
import * as path36 from "path";
|
|
13096
13379
|
import {
|
|
13097
13380
|
findSubProjectRoot as findSubProjectRoot14,
|
|
13098
13381
|
loadStudioToml as loadStudioToml18
|
|
@@ -13105,11 +13388,11 @@ import {
|
|
|
13105
13388
|
import * as walletRt4 from "@bnbagent/studio-runtime/wallet";
|
|
13106
13389
|
|
|
13107
13390
|
// src/cli/_identity.ts
|
|
13108
|
-
import * as
|
|
13109
|
-
import * as
|
|
13391
|
+
import * as fs36 from "fs";
|
|
13392
|
+
import * as path35 from "path";
|
|
13110
13393
|
function writeIdentityBlock(root, identity) {
|
|
13111
|
-
const p =
|
|
13112
|
-
const text2 =
|
|
13394
|
+
const p = path35.join(root, "studio.toml");
|
|
13395
|
+
const text2 = fs36.readFileSync(p, "utf-8");
|
|
13113
13396
|
const lines = text2.split(/\r?\n/);
|
|
13114
13397
|
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
13115
13398
|
lines.pop();
|
|
@@ -13148,7 +13431,7 @@ function writeIdentityBlock(root, identity) {
|
|
|
13148
13431
|
}
|
|
13149
13432
|
}
|
|
13150
13433
|
out.push("");
|
|
13151
|
-
|
|
13434
|
+
fs36.writeFileSync(p, out.join("\n"), "utf-8");
|
|
13152
13435
|
}
|
|
13153
13436
|
|
|
13154
13437
|
// src/cli/_deploy/verify.ts
|
|
@@ -13256,6 +13539,7 @@ function baseResult(endpoint, runtime, overrides) {
|
|
|
13256
13539
|
studioTomlUpdated: false,
|
|
13257
13540
|
runtime,
|
|
13258
13541
|
note: null,
|
|
13542
|
+
warning: null,
|
|
13259
13543
|
error: null,
|
|
13260
13544
|
exitCode: 0,
|
|
13261
13545
|
...overrides
|
|
@@ -13265,7 +13549,7 @@ async function runVerify(opts) {
|
|
|
13265
13549
|
const endpoint = opts.endpoint;
|
|
13266
13550
|
const runtime = opts.runtime ?? "agentcore";
|
|
13267
13551
|
const skipRegister = opts.skipRegister ?? false;
|
|
13268
|
-
const start = opts.projectRoot ?
|
|
13552
|
+
const start = opts.projectRoot ? path36.resolve(opts.projectRoot) : void 0;
|
|
13269
13553
|
const root = findSubProjectRoot14("agent", start);
|
|
13270
13554
|
if (root === null) {
|
|
13271
13555
|
return baseResult(endpoint, runtime, {
|
|
@@ -13285,7 +13569,7 @@ async function runVerify(opts) {
|
|
|
13285
13569
|
}
|
|
13286
13570
|
let data;
|
|
13287
13571
|
try {
|
|
13288
|
-
data = loadStudioToml18(
|
|
13572
|
+
data = loadStudioToml18(path36.join(root, "studio.toml"));
|
|
13289
13573
|
} catch (exc) {
|
|
13290
13574
|
return baseResult(endpoint, runtime, {
|
|
13291
13575
|
awsAccount,
|
|
@@ -13311,6 +13595,7 @@ async function runVerify(opts) {
|
|
|
13311
13595
|
let action = "none";
|
|
13312
13596
|
let registerError = null;
|
|
13313
13597
|
let postWriteError = null;
|
|
13598
|
+
let postWriteWarning = null;
|
|
13314
13599
|
let registerNote = null;
|
|
13315
13600
|
let identityPendingReason = null;
|
|
13316
13601
|
let registerExitCode = 0;
|
|
@@ -13343,9 +13628,8 @@ async function runVerify(opts) {
|
|
|
13343
13628
|
const cause = e.cause !== null && typeof e.cause === "object" ? e.cause : null;
|
|
13344
13629
|
const relayTxHash = typeof cause?.txHash === "string" ? cause.txHash : e.txHash;
|
|
13345
13630
|
action = "register_partial";
|
|
13346
|
-
|
|
13631
|
+
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\`.`;
|
|
13347
13632
|
identityPendingReason = "setAgentURI relay submission unverified; run bag erc8004 clear-pending before retrying";
|
|
13348
|
-
registerExitCode = 1;
|
|
13349
13633
|
} else if (e.txHash) {
|
|
13350
13634
|
action = "register_pending";
|
|
13351
13635
|
registerNote = `ERC-8004 register created agent_id=${e.agentId}; setAgentURI tx pending (${e.txHash}). Check the tx before retrying \`bag erc8004 update-endpoint\`.`;
|
|
@@ -13439,14 +13723,15 @@ async function runVerify(opts) {
|
|
|
13439
13723
|
action,
|
|
13440
13724
|
studioTomlUpdated,
|
|
13441
13725
|
note: notes.length > 0 ? notes.join(" | ") : null,
|
|
13726
|
+
warning: postWriteWarning,
|
|
13442
13727
|
error: postWriteError,
|
|
13443
13728
|
exitCode: registerExitCode
|
|
13444
13729
|
});
|
|
13445
13730
|
}
|
|
13446
13731
|
|
|
13447
13732
|
// src/cli/_hosted/deployOps.ts
|
|
13448
|
-
import * as
|
|
13449
|
-
import * as
|
|
13733
|
+
import * as fs37 from "fs";
|
|
13734
|
+
import * as path37 from "path";
|
|
13450
13735
|
import {
|
|
13451
13736
|
envLocalPath as envLocalPath15,
|
|
13452
13737
|
findSubProjectRoot as findSubProjectRoot15,
|
|
@@ -13457,7 +13742,12 @@ var PLATFORM_SECTION = "deploy.platform";
|
|
|
13457
13742
|
var WALLET_SECTION = "wallet";
|
|
13458
13743
|
var KEYSTORE_JSON_ENV2 = "WALLET_KEYSTORE_JSON";
|
|
13459
13744
|
var TWAK_WALLET_JSON_ENV2 = "TWAK_WALLET_JSON";
|
|
13460
|
-
var
|
|
13745
|
+
var ALTANA_SESSION_ENV2 = "ALTANA_SESSION";
|
|
13746
|
+
var WALLET_MATERIAL_KEYS = [
|
|
13747
|
+
KEYSTORE_JSON_ENV2,
|
|
13748
|
+
TWAK_WALLET_JSON_ENV2,
|
|
13749
|
+
ALTANA_SESSION_ENV2
|
|
13750
|
+
];
|
|
13461
13751
|
var RETIRED_AGENT_STATES = /* @__PURE__ */ new Set([
|
|
13462
13752
|
"deleted",
|
|
13463
13753
|
"retired",
|
|
@@ -13487,8 +13777,8 @@ function agentTomlPath2(root) {
|
|
|
13487
13777
|
if (agentRoot2 === null) {
|
|
13488
13778
|
return null;
|
|
13489
13779
|
}
|
|
13490
|
-
const tomlPath =
|
|
13491
|
-
return
|
|
13780
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13781
|
+
return isFile15(tomlPath) ? tomlPath : null;
|
|
13492
13782
|
}
|
|
13493
13783
|
function loadAgentCfg(root) {
|
|
13494
13784
|
const tomlPath = agentTomlPath2(root);
|
|
@@ -13505,12 +13795,12 @@ function platformCfg(root) {
|
|
|
13505
13795
|
return tableOf12(tableOf12(loadAgentCfg(root), "deploy"), "platform");
|
|
13506
13796
|
}
|
|
13507
13797
|
function patchTomlKv2(tomlPath, section, key, value) {
|
|
13508
|
-
let text2 =
|
|
13798
|
+
let text2 = fs37.readFileSync(tomlPath, "utf-8");
|
|
13509
13799
|
if (!hasSection(text2, section)) {
|
|
13510
13800
|
text2 = addSection(text2, section);
|
|
13511
13801
|
}
|
|
13512
13802
|
text2 = hasKey(text2, section, key) ? setExistingKey(text2, section, key, value) : addKeyToSection(text2, section, key, value);
|
|
13513
|
-
|
|
13803
|
+
fs37.writeFileSync(tomlPath, text2);
|
|
13514
13804
|
}
|
|
13515
13805
|
function recordPlatformKv(root, key, value) {
|
|
13516
13806
|
const tomlPath = agentTomlPath2(root);
|
|
@@ -13609,8 +13899,8 @@ function clearIdentityEndpointIfMatches(root, oldUrl) {
|
|
|
13609
13899
|
}
|
|
13610
13900
|
}
|
|
13611
13901
|
function persistedPackaging2(agentRoot2) {
|
|
13612
|
-
const tomlPath =
|
|
13613
|
-
if (!
|
|
13902
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13903
|
+
if (!isFile15(tomlPath)) {
|
|
13614
13904
|
return null;
|
|
13615
13905
|
}
|
|
13616
13906
|
try {
|
|
@@ -13622,8 +13912,8 @@ function persistedPackaging2(agentRoot2) {
|
|
|
13622
13912
|
}
|
|
13623
13913
|
}
|
|
13624
13914
|
function resolvePlatformArtifact2(agentRoot2) {
|
|
13625
|
-
const tomlPath =
|
|
13626
|
-
if (
|
|
13915
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13916
|
+
if (isFile15(tomlPath)) {
|
|
13627
13917
|
try {
|
|
13628
13918
|
const cfg = loadStudioToml19(tomlPath);
|
|
13629
13919
|
const explicit = tableOf12(cfg, "deploy").platform_artifact;
|
|
@@ -13646,7 +13936,7 @@ function platformPackaging(root) {
|
|
|
13646
13936
|
}
|
|
13647
13937
|
function loadCfgAt(agentRoot2) {
|
|
13648
13938
|
try {
|
|
13649
|
-
return loadStudioToml19(
|
|
13939
|
+
return loadStudioToml19(path37.join(agentRoot2, "studio.toml"));
|
|
13650
13940
|
} catch {
|
|
13651
13941
|
return {};
|
|
13652
13942
|
}
|
|
@@ -13723,7 +14013,7 @@ function resolveSlug(root) {
|
|
|
13723
14013
|
let name = String(tableOf12(loadAgentCfg(root), "project").name ?? "");
|
|
13724
14014
|
name = name.replace(/-(agent|service)$/, "");
|
|
13725
14015
|
if (!name) {
|
|
13726
|
-
name =
|
|
14016
|
+
name = path37.basename(findWorkspaceRoot6(root) ?? root);
|
|
13727
14017
|
}
|
|
13728
14018
|
let base = name.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
13729
14019
|
base = base || "agent";
|
|
@@ -13965,6 +14255,19 @@ function walletWarning(root, secrets) {
|
|
|
13965
14255
|
return;
|
|
13966
14256
|
}
|
|
13967
14257
|
const address = tableOf12(loadAgentCfg(root), "wallet").address;
|
|
14258
|
+
if (ALTANA_SESSION_ENV2 in secrets) {
|
|
14259
|
+
const who2 = typeof address === "string" && address ? ` (wallet ${address})` : "";
|
|
14260
|
+
warn(
|
|
14261
|
+
`
|
|
14262
|
+
!!! session exposure (platform trial) !!!
|
|
14263
|
+
This project's bounded Altana session${who2} will be transmitted to the BNB Chain operator's Secrets Manager so the trial runtime can sign on testnet. The session is budget-limited, expiring, and revocable \u2014 the admin keystore and WALLET_PASSWORD never ship.
|
|
14264
|
+
If the current budget or expiry is wider than you want an operator-held key to carry, stop and grant a tighter one first:
|
|
14265
|
+
bag wallet session grant --force --budget-u <small> --expiry-days <short>
|
|
14266
|
+
You can revoke it on-chain at any time with \`bag wallet session revoke\`.
|
|
14267
|
+
`
|
|
14268
|
+
);
|
|
14269
|
+
return;
|
|
14270
|
+
}
|
|
13968
14271
|
const who = typeof address === "string" && address ? `key (address ${address})` : "signing key";
|
|
13969
14272
|
warn(
|
|
13970
14273
|
`
|
|
@@ -14181,15 +14484,15 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
14181
14484
|
}
|
|
14182
14485
|
function persistDeploySummary(root, text2) {
|
|
14183
14486
|
try {
|
|
14184
|
-
if (!
|
|
14487
|
+
if (!fs37.statSync(path37.resolve(root)).isDirectory()) {
|
|
14185
14488
|
return null;
|
|
14186
14489
|
}
|
|
14187
|
-
const p =
|
|
14188
|
-
|
|
14490
|
+
const p = path37.join(
|
|
14491
|
+
path37.dirname(envLocalPath15(root)),
|
|
14189
14492
|
"last-deploy-summary.txt"
|
|
14190
14493
|
);
|
|
14191
|
-
|
|
14192
|
-
|
|
14494
|
+
fs37.mkdirSync(path37.dirname(p), { recursive: true });
|
|
14495
|
+
fs37.writeFileSync(p, `${text2}
|
|
14193
14496
|
`);
|
|
14194
14497
|
return p;
|
|
14195
14498
|
} catch {
|
|
@@ -14344,9 +14647,9 @@ async function deletePlatformAgent(slug, deps = {}) {
|
|
|
14344
14647
|
}
|
|
14345
14648
|
return 0;
|
|
14346
14649
|
}
|
|
14347
|
-
function
|
|
14650
|
+
function isFile15(p) {
|
|
14348
14651
|
try {
|
|
14349
|
-
return
|
|
14652
|
+
return fs37.statSync(p).isFile();
|
|
14350
14653
|
} catch {
|
|
14351
14654
|
return false;
|
|
14352
14655
|
}
|
|
@@ -14359,16 +14662,16 @@ var ADVERTISED_DEPLOY_RUNTIME_TARGETS = ["agentcore"];
|
|
|
14359
14662
|
// src/cli/deploy.ts
|
|
14360
14663
|
var TARGET_CHOICES = [...DEPLOY_RUNTIME_TARGETS];
|
|
14361
14664
|
var ADVERTISED_TARGET_CHOICES = [...ADVERTISED_DEPLOY_RUNTIME_TARGETS];
|
|
14362
|
-
function
|
|
14665
|
+
function isFile16(p) {
|
|
14363
14666
|
try {
|
|
14364
|
-
return
|
|
14667
|
+
return fs38.statSync(p).isFile();
|
|
14365
14668
|
} catch {
|
|
14366
14669
|
return false;
|
|
14367
14670
|
}
|
|
14368
14671
|
}
|
|
14369
14672
|
function isDir7(p) {
|
|
14370
14673
|
try {
|
|
14371
|
-
return
|
|
14674
|
+
return fs38.statSync(p).isDirectory();
|
|
14372
14675
|
} catch {
|
|
14373
14676
|
return false;
|
|
14374
14677
|
}
|
|
@@ -14385,8 +14688,8 @@ function loadAgentCfg2(root) {
|
|
|
14385
14688
|
if (agentRoot2 === null) {
|
|
14386
14689
|
return null;
|
|
14387
14690
|
}
|
|
14388
|
-
const tomlPath =
|
|
14389
|
-
if (!
|
|
14691
|
+
const tomlPath = path38.join(agentRoot2, "studio.toml");
|
|
14692
|
+
if (!isFile16(tomlPath)) {
|
|
14390
14693
|
return null;
|
|
14391
14694
|
}
|
|
14392
14695
|
try {
|
|
@@ -14548,8 +14851,8 @@ function registerDeploy(program) {
|
|
|
14548
14851
|
p.command("fix-gitignore").description(
|
|
14549
14852
|
"Ensure the workspace .gitignore excludes .studio/ (the agent's .env.local + keystore)."
|
|
14550
14853
|
).option("--project-root <path>", "Override project root.").action(act((opts) => cmdFixGitignore(opts)));
|
|
14551
|
-
p.command("provision-cognito").description(
|
|
14552
|
-
"Emit an AWS CDK app under agentcore/cognito/ that provisions a Cognito M2M client for the AgentCore
|
|
14854
|
+
p.command("provision-cognito", { hidden: true }).description(
|
|
14855
|
+
"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`)."
|
|
14553
14856
|
).option("--project-root <path>", "Override project root.").option(
|
|
14554
14857
|
"--wire [outputsFile]",
|
|
14555
14858
|
"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."
|
|
@@ -14563,9 +14866,9 @@ function applyProjectRoot(projectRoot, requireToml = true) {
|
|
|
14563
14866
|
if (projectRoot === void 0) {
|
|
14564
14867
|
return null;
|
|
14565
14868
|
}
|
|
14566
|
-
const p =
|
|
14869
|
+
const p = path38.resolve(projectRoot);
|
|
14567
14870
|
const agentRoot2 = findSubProjectRoot16("agent", p);
|
|
14568
|
-
if (requireToml && !
|
|
14871
|
+
if (requireToml && !isFile16(path38.join(p, "studio.toml")) && (agentRoot2 === null || !isFile16(path38.join(agentRoot2, "studio.toml")))) {
|
|
14569
14872
|
printErr(`error: no studio.toml under --project-root ${p}`);
|
|
14570
14873
|
return 2;
|
|
14571
14874
|
}
|
|
@@ -14577,7 +14880,7 @@ function applyProjectRoot(projectRoot, requireToml = true) {
|
|
|
14577
14880
|
return null;
|
|
14578
14881
|
}
|
|
14579
14882
|
function resolveProjectRoot2(_projectRoot) {
|
|
14580
|
-
const cwd =
|
|
14883
|
+
const cwd = path38.resolve(process.cwd());
|
|
14581
14884
|
return findStudioWorkspaceRoot3(cwd) ?? cwd;
|
|
14582
14885
|
}
|
|
14583
14886
|
function deployWorkspaceRoot2(root) {
|
|
@@ -14608,12 +14911,17 @@ function agentDeployDestination(root) {
|
|
|
14608
14911
|
}
|
|
14609
14912
|
function resolveTarget(opts, root, destination = agentDeployDestination(root)) {
|
|
14610
14913
|
const explicit = opts.runtime ?? opts.target;
|
|
14611
|
-
if (explicit) {
|
|
14612
|
-
return explicit;
|
|
14613
|
-
}
|
|
14614
14914
|
if (destination === "platform") {
|
|
14915
|
+
if (explicit && explicit !== "platform") {
|
|
14916
|
+
printErr(
|
|
14917
|
+
`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.`
|
|
14918
|
+
);
|
|
14919
|
+
}
|
|
14615
14920
|
return "platform";
|
|
14616
14921
|
}
|
|
14922
|
+
if (explicit) {
|
|
14923
|
+
return explicit;
|
|
14924
|
+
}
|
|
14617
14925
|
return readStackRuntime(root) ?? "agentcore";
|
|
14618
14926
|
}
|
|
14619
14927
|
function validateRuntimeAgainstStack(target, force, root) {
|
|
@@ -14638,7 +14946,7 @@ function validateRuntimeAgainstStack(target, force, root) {
|
|
|
14638
14946
|
async function cmdPrepare(opts) {
|
|
14639
14947
|
let root;
|
|
14640
14948
|
if (opts.projectRoot !== void 0) {
|
|
14641
|
-
const p =
|
|
14949
|
+
const p = path38.resolve(opts.projectRoot);
|
|
14642
14950
|
if (!isDir7(p)) {
|
|
14643
14951
|
printErr(`error: --project-root ${p} is not a directory`);
|
|
14644
14952
|
return 2;
|
|
@@ -14646,7 +14954,7 @@ async function cmdPrepare(opts) {
|
|
|
14646
14954
|
process.chdir(p);
|
|
14647
14955
|
root = findStudioWorkspaceRoot3(p) ?? p;
|
|
14648
14956
|
} else {
|
|
14649
|
-
const cwd =
|
|
14957
|
+
const cwd = path38.resolve(process.cwd());
|
|
14650
14958
|
root = findStudioWorkspaceRoot3(cwd) ?? cwd;
|
|
14651
14959
|
}
|
|
14652
14960
|
const target = resolveTarget(opts, root);
|
|
@@ -14788,8 +15096,8 @@ function writeAgentDeployState(workspaceRoot, arn, record = {}, destination = "s
|
|
|
14788
15096
|
if (agentRoot2 === null) {
|
|
14789
15097
|
return;
|
|
14790
15098
|
}
|
|
14791
|
-
const tomlPath =
|
|
14792
|
-
if (!
|
|
15099
|
+
const tomlPath = path38.join(agentRoot2, "studio.toml");
|
|
15100
|
+
if (!isFile16(tomlPath)) {
|
|
14793
15101
|
return;
|
|
14794
15102
|
}
|
|
14795
15103
|
try {
|
|
@@ -14820,6 +15128,12 @@ function writeAgentDeployState(workspaceRoot, arn, record = {}, destination = "s
|
|
|
14820
15128
|
if (scope) {
|
|
14821
15129
|
setEnvVar(envLocalPath16(agentRoot2), "OAUTH_SCOPE", scope);
|
|
14822
15130
|
}
|
|
15131
|
+
syncDescriptorOauthFacts(workspaceRoot, {
|
|
15132
|
+
tokenUrl,
|
|
15133
|
+
scope,
|
|
15134
|
+
discoveryUrl,
|
|
15135
|
+
clientId
|
|
15136
|
+
});
|
|
14823
15137
|
if (persistedPackaging(agentRoot2) === null) {
|
|
14824
15138
|
patchTomlKv(
|
|
14825
15139
|
tomlPath,
|
|
@@ -14861,10 +15175,10 @@ package and at the repo root).
|
|
|
14861
15175
|
`;
|
|
14862
15176
|
function iamNoticeTomlPath(root) {
|
|
14863
15177
|
const agentRoot2 = findSubProjectRoot16("agent", root) ?? root;
|
|
14864
|
-
return
|
|
15178
|
+
return path38.join(agentRoot2, "studio.toml");
|
|
14865
15179
|
}
|
|
14866
15180
|
function iamNoticeAccepted(tomlPath) {
|
|
14867
|
-
if (!
|
|
15181
|
+
if (!isFile16(tomlPath)) {
|
|
14868
15182
|
return false;
|
|
14869
15183
|
}
|
|
14870
15184
|
let data;
|
|
@@ -14915,7 +15229,7 @@ async function iamNoticeGate(root, acceptRisk) {
|
|
|
14915
15229
|
return 1;
|
|
14916
15230
|
}
|
|
14917
15231
|
async function buildAgentProject(agentRoot2, packaging) {
|
|
14918
|
-
if (!
|
|
15232
|
+
if (!isFile16(path38.join(agentRoot2, "package.json"))) {
|
|
14919
15233
|
printErr(
|
|
14920
15234
|
`warning: no package.json under ${agentRoot2} \u2014 skipping the agent \`pnpm build\`; bnbagent-deploy will package whatever dist/ holds.`
|
|
14921
15235
|
);
|
|
@@ -15085,6 +15399,17 @@ async function refreshLocalDeployDependencies(root) {
|
|
|
15085
15399
|
return 1;
|
|
15086
15400
|
}
|
|
15087
15401
|
}
|
|
15402
|
+
function partialDeployCleanupNote(workspaceRoot) {
|
|
15403
|
+
const project = projectName(workspaceRoot);
|
|
15404
|
+
return [
|
|
15405
|
+
"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):",
|
|
15406
|
+
` - ECR image bnbagent/${project}`,
|
|
15407
|
+
` - Secrets Manager bnbagent/${project}/runtime`,
|
|
15408
|
+
` - Cognito M2M client bnbagent-${project}`,
|
|
15409
|
+
` - IAM role bnbagent-${project}-runtime`,
|
|
15410
|
+
" `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."
|
|
15411
|
+
].join("\n");
|
|
15412
|
+
}
|
|
15088
15413
|
async function cmdAgent(opts, agentcoreArgs) {
|
|
15089
15414
|
let rc = applyProjectRoot(opts.projectRoot);
|
|
15090
15415
|
if (rc !== null) {
|
|
@@ -15095,12 +15420,6 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15095
15420
|
const packagingDestination = opts.to ?? opts.destination ?? agentDeployDestination(root);
|
|
15096
15421
|
const driftAgentRoot = findSubProjectRoot16("agent", root) ?? root;
|
|
15097
15422
|
const driftKind = deployWalletKind(driftAgentRoot);
|
|
15098
|
-
if (driftKind === "altana") {
|
|
15099
|
-
printErr(
|
|
15100
|
-
"error: Altana deployment is deferred in this release. `bag dev` uses the bounded session locally, but no deploy adapter may receive the admin key or an unreviewed session transport. No packaging or external deploy calls were started."
|
|
15101
|
-
);
|
|
15102
|
-
return 2;
|
|
15103
|
-
}
|
|
15104
15423
|
rc = checkPackagingDrift(
|
|
15105
15424
|
root,
|
|
15106
15425
|
packagingDestination,
|
|
@@ -15243,7 +15562,7 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15243
15562
|
packagingDestination,
|
|
15244
15563
|
resolvePlatformArtifact(agentRoot2)
|
|
15245
15564
|
) === "container" ? "container" : "zip";
|
|
15246
|
-
const walletBlurb = walletKind2 === "twak" ? "the encrypted twak wallet as TWAK_WALLET_JSON" : "the encrypted keystore as WALLET_KEYSTORE_JSON";
|
|
15565
|
+
const walletBlurb = walletKind2 === "twak" ? "the encrypted twak wallet as TWAK_WALLET_JSON" : walletKind2 === "altana" ? "the bounded Altana session as ALTANA_SESSION \u2014 the admin keystore and WALLET_PASSWORD never ship" : "the encrypted keystore as WALLET_KEYSTORE_JSON";
|
|
15247
15566
|
if (secretsMode === "envvars") {
|
|
15248
15567
|
printErr(
|
|
15249
15568
|
`note: --secrets-mode envvars inlines the runtime secrets (incl. ${walletBlurb}) as PLAINTEXT runtime env vars in the deploy spec \u2014 testnet only, refused on mainnet.`
|
|
@@ -15296,6 +15615,7 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15296
15615
|
printErr(
|
|
15297
15616
|
"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."
|
|
15298
15617
|
);
|
|
15618
|
+
printErr(partialDeployCleanupNote(workspaceRoot));
|
|
15299
15619
|
return code;
|
|
15300
15620
|
}
|
|
15301
15621
|
const record = recordOf2(data);
|
|
@@ -15360,7 +15680,7 @@ function recordedEndpoint(root) {
|
|
|
15360
15680
|
}
|
|
15361
15681
|
function recordedAgentId(agentRoot2) {
|
|
15362
15682
|
try {
|
|
15363
|
-
const cfg = loadStudioToml20(
|
|
15683
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15364
15684
|
const val = tableOf13(cfg, "identity").agent_id;
|
|
15365
15685
|
return val !== void 0 && val !== null && val !== "" ? String(val) : null;
|
|
15366
15686
|
} catch {
|
|
@@ -15369,7 +15689,7 @@ function recordedAgentId(agentRoot2) {
|
|
|
15369
15689
|
}
|
|
15370
15690
|
function recordedRuntimeArn(agentRoot2) {
|
|
15371
15691
|
try {
|
|
15372
|
-
const cfg = loadStudioToml20(
|
|
15692
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15373
15693
|
const val = tableOf13(cfg, "deploy").runtime_arn;
|
|
15374
15694
|
return val ? String(val) : null;
|
|
15375
15695
|
} catch {
|
|
@@ -15378,7 +15698,7 @@ function recordedRuntimeArn(agentRoot2) {
|
|
|
15378
15698
|
}
|
|
15379
15699
|
function recordedOauthClientId(agentRoot2) {
|
|
15380
15700
|
try {
|
|
15381
|
-
const cfg = loadStudioToml20(
|
|
15701
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15382
15702
|
const val = tableOf13(cfg, "deploy").oauth_client_id;
|
|
15383
15703
|
return val ? String(val) : null;
|
|
15384
15704
|
} catch {
|
|
@@ -15387,7 +15707,7 @@ function recordedOauthClientId(agentRoot2) {
|
|
|
15387
15707
|
}
|
|
15388
15708
|
function agentFacesOf(agentRoot2) {
|
|
15389
15709
|
try {
|
|
15390
|
-
const cfg = loadStudioToml20(
|
|
15710
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15391
15711
|
return stackFaces(tableOf13(cfg, "stack"), tableOf13(cfg, "payments"));
|
|
15392
15712
|
} catch {
|
|
15393
15713
|
return ["A2A"];
|
|
@@ -15539,15 +15859,15 @@ async function printAgentClientPrompt2(root, destination, opts = {}) {
|
|
|
15539
15859
|
}
|
|
15540
15860
|
function persistDeploySummary2(root, text2) {
|
|
15541
15861
|
try {
|
|
15542
|
-
if (!
|
|
15862
|
+
if (!fs38.statSync(path38.resolve(root)).isDirectory()) {
|
|
15543
15863
|
return null;
|
|
15544
15864
|
}
|
|
15545
|
-
const p =
|
|
15546
|
-
|
|
15865
|
+
const p = path38.join(
|
|
15866
|
+
path38.dirname(envLocalPath16(root)),
|
|
15547
15867
|
"last-deploy-summary.txt"
|
|
15548
15868
|
);
|
|
15549
|
-
|
|
15550
|
-
|
|
15869
|
+
fs38.mkdirSync(path38.dirname(p), { recursive: true });
|
|
15870
|
+
fs38.writeFileSync(p, `${text2}
|
|
15551
15871
|
`, "utf-8");
|
|
15552
15872
|
return p;
|
|
15553
15873
|
} catch {
|
|
@@ -15638,6 +15958,7 @@ function verifyToJson(r) {
|
|
|
15638
15958
|
studio_toml_updated: r.studioTomlUpdated,
|
|
15639
15959
|
runtime: r.runtime,
|
|
15640
15960
|
note: r.note,
|
|
15961
|
+
warning: r.warning,
|
|
15641
15962
|
error: r.error,
|
|
15642
15963
|
exit_code: r.exitCode
|
|
15643
15964
|
};
|
|
@@ -15679,6 +16000,9 @@ function renderVerifyHuman(r, deployment, liveStatus) {
|
|
|
15679
16000
|
if (r.note) {
|
|
15680
16001
|
printOut(`note: ${r.note}`);
|
|
15681
16002
|
}
|
|
16003
|
+
if (r.warning) {
|
|
16004
|
+
printOut(`warning: ${r.warning}`);
|
|
16005
|
+
}
|
|
15682
16006
|
if (r.error) {
|
|
15683
16007
|
printOut(`error: ${r.error}`);
|
|
15684
16008
|
}
|
|
@@ -15940,9 +16264,9 @@ async function cmdDestroy(opts) {
|
|
|
15940
16264
|
return 2;
|
|
15941
16265
|
}
|
|
15942
16266
|
const answer = await promptUser(
|
|
15943
|
-
`This delegates the teardown of "${
|
|
16267
|
+
`This delegates the teardown of "${path38.basename(workspaceRoot)}" (Foundry hosted agent + the resources its deploy record tracks) to bnbagent-deploy. Type the project name to proceed: `
|
|
15944
16268
|
);
|
|
15945
|
-
if (answer.trim() !==
|
|
16269
|
+
if (answer.trim() !== path38.basename(workspaceRoot)) {
|
|
15946
16270
|
printErr(
|
|
15947
16271
|
"error: confirmation did not match the project name; aborting."
|
|
15948
16272
|
);
|
|
@@ -16026,6 +16350,7 @@ async function cmdFixGitignore(opts) {
|
|
|
16026
16350
|
printOut(`${marker} ${result.name}: ${result.message}`);
|
|
16027
16351
|
return 0;
|
|
16028
16352
|
}
|
|
16353
|
+
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.";
|
|
16029
16354
|
async function cmdProvisionCognito(opts) {
|
|
16030
16355
|
const rc = applyProjectRoot(opts.projectRoot, false);
|
|
16031
16356
|
if (rc !== null) {
|
|
@@ -16033,6 +16358,7 @@ async function cmdProvisionCognito(opts) {
|
|
|
16033
16358
|
}
|
|
16034
16359
|
const root = resolveProjectRoot2(opts.projectRoot);
|
|
16035
16360
|
const workspaceRoot = deployWorkspaceRoot2(root);
|
|
16361
|
+
printOut(PROVISION_COGNITO_DEPRECATION);
|
|
16036
16362
|
if (opts.wire !== void 0 && opts.wire !== false) {
|
|
16037
16363
|
const outputsFile = typeof opts.wire === "string" && opts.wire ? opts.wire : null;
|
|
16038
16364
|
try {
|
|
@@ -16056,8 +16382,8 @@ async function cmdProvisionCognito(opts) {
|
|
|
16056
16382
|
|
|
16057
16383
|
// src/cli/doctor.ts
|
|
16058
16384
|
import * as crypto5 from "crypto";
|
|
16059
|
-
import * as
|
|
16060
|
-
import * as
|
|
16385
|
+
import * as fs39 from "fs";
|
|
16386
|
+
import * as path39 from "path";
|
|
16061
16387
|
import { EVMWalletProvider as EVMWalletProvider2 } from "@bnbagent/sdk";
|
|
16062
16388
|
import {
|
|
16063
16389
|
envLocalPath as envLocalPath17,
|
|
@@ -16103,23 +16429,23 @@ function tableOf14(cfg, key) {
|
|
|
16103
16429
|
const v = cfg[key];
|
|
16104
16430
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
16105
16431
|
}
|
|
16106
|
-
function
|
|
16432
|
+
function isFile17(p) {
|
|
16107
16433
|
try {
|
|
16108
|
-
return
|
|
16434
|
+
return fs39.statSync(p).isFile();
|
|
16109
16435
|
} catch {
|
|
16110
16436
|
return false;
|
|
16111
16437
|
}
|
|
16112
16438
|
}
|
|
16113
16439
|
function isDir8(p) {
|
|
16114
16440
|
try {
|
|
16115
|
-
return
|
|
16441
|
+
return fs39.statSync(p).isDirectory();
|
|
16116
16442
|
} catch {
|
|
16117
16443
|
return false;
|
|
16118
16444
|
}
|
|
16119
16445
|
}
|
|
16120
16446
|
function keystoreJsons(dir) {
|
|
16121
16447
|
try {
|
|
16122
|
-
return
|
|
16448
|
+
return fs39.readdirSync(dir).filter((f) => f.endsWith(".json")).sort();
|
|
16123
16449
|
} catch {
|
|
16124
16450
|
return [];
|
|
16125
16451
|
}
|
|
@@ -16148,7 +16474,7 @@ async function cmdDoctor(opts) {
|
|
|
16148
16474
|
if (opts.checkEnv) {
|
|
16149
16475
|
return runCheckEnv(projectRoot);
|
|
16150
16476
|
}
|
|
16151
|
-
const tomlPath =
|
|
16477
|
+
const tomlPath = path39.join(projectRoot, "studio.toml");
|
|
16152
16478
|
let data;
|
|
16153
16479
|
try {
|
|
16154
16480
|
data = loadStudioToml21(tomlPath);
|
|
@@ -16184,8 +16510,8 @@ async function cmdDoctor(opts) {
|
|
|
16184
16510
|
}
|
|
16185
16511
|
function resolveProjectRoot3(argRoot) {
|
|
16186
16512
|
if (argRoot !== void 0) {
|
|
16187
|
-
const root2 =
|
|
16188
|
-
if (!
|
|
16513
|
+
const root2 = path39.resolve(argRoot);
|
|
16514
|
+
if (!isFile17(path39.join(root2, "studio.toml"))) {
|
|
16189
16515
|
printErr(`error: no studio.toml under --project-root ${root2}`);
|
|
16190
16516
|
return null;
|
|
16191
16517
|
}
|
|
@@ -16199,15 +16525,15 @@ function resolveProjectRoot3(argRoot) {
|
|
|
16199
16525
|
return root;
|
|
16200
16526
|
}
|
|
16201
16527
|
function runCheckEnv(projectRoot) {
|
|
16202
|
-
const agentDir = workspaceLayers(projectRoot) ??
|
|
16528
|
+
const agentDir = workspaceLayers(projectRoot) ?? path39.join(projectRoot, "agent");
|
|
16203
16529
|
const envPath = envLocalPath17(agentDir);
|
|
16204
16530
|
printOut(`bag doctor --check-env: ${envPath}`);
|
|
16205
|
-
if (!
|
|
16206
|
-
printOut(` (no ${
|
|
16531
|
+
if (!isFile17(envPath)) {
|
|
16532
|
+
printOut(` (no ${path39.basename(envPath)} found \u2014 nothing to report)`);
|
|
16207
16533
|
return 0;
|
|
16208
16534
|
}
|
|
16209
16535
|
const values = {};
|
|
16210
|
-
for (const rawLine of
|
|
16536
|
+
for (const rawLine of fs39.readFileSync(envPath, "utf-8").split(/\r?\n/)) {
|
|
16211
16537
|
const line = rawLine.trim();
|
|
16212
16538
|
if (!line || line.startsWith("#") || !line.includes("=")) {
|
|
16213
16539
|
continue;
|
|
@@ -16234,25 +16560,25 @@ function runCheckEnv(projectRoot) {
|
|
|
16234
16560
|
return 0;
|
|
16235
16561
|
}
|
|
16236
16562
|
function workspaceLayers(projectRoot) {
|
|
16237
|
-
const parent =
|
|
16238
|
-
if (
|
|
16239
|
-
return
|
|
16563
|
+
const parent = path39.dirname(projectRoot);
|
|
16564
|
+
if (isFile17(path39.join(parent, "agent", "studio.toml"))) {
|
|
16565
|
+
return path39.join(parent, "agent");
|
|
16240
16566
|
}
|
|
16241
|
-
if (
|
|
16242
|
-
return
|
|
16567
|
+
if (isFile17(path39.join(projectRoot, "agent", "studio.toml"))) {
|
|
16568
|
+
return path39.join(projectRoot, "agent");
|
|
16243
16569
|
}
|
|
16244
16570
|
return null;
|
|
16245
16571
|
}
|
|
16246
16572
|
function checkAppMain(projectRootArg) {
|
|
16247
16573
|
let projectRoot = projectRootArg;
|
|
16248
|
-
const parent =
|
|
16249
|
-
if (
|
|
16574
|
+
const parent = path39.dirname(projectRoot);
|
|
16575
|
+
if (isFile17(path39.join(parent, "agent", "studio.toml"))) {
|
|
16250
16576
|
projectRoot = parent;
|
|
16251
16577
|
}
|
|
16252
|
-
const agentDir =
|
|
16578
|
+
const agentDir = path39.join(projectRoot, "agent");
|
|
16253
16579
|
let config = {};
|
|
16254
|
-
const tomlPath =
|
|
16255
|
-
if (
|
|
16580
|
+
const tomlPath = path39.join(agentDir, "studio.toml");
|
|
16581
|
+
if (isFile17(tomlPath)) {
|
|
16256
16582
|
try {
|
|
16257
16583
|
config = loadStudioToml21(tomlPath);
|
|
16258
16584
|
} catch {
|
|
@@ -16270,8 +16596,8 @@ function checkAppMain(projectRootArg) {
|
|
|
16270
16596
|
} else {
|
|
16271
16597
|
entrypoint = "src/main.ts";
|
|
16272
16598
|
}
|
|
16273
|
-
const entryFile =
|
|
16274
|
-
if (!
|
|
16599
|
+
const entryFile = path39.join(agentDir, entrypoint);
|
|
16600
|
+
if (!isFile17(entryFile)) {
|
|
16275
16601
|
return [
|
|
16276
16602
|
{
|
|
16277
16603
|
name: "agent entrypoint",
|
|
@@ -16286,12 +16612,12 @@ function checkAppMain(projectRootArg) {
|
|
|
16286
16612
|
function checkAgentcoreName(projectRoot) {
|
|
16287
16613
|
let cfgPath = null;
|
|
16288
16614
|
for (const candidate of [
|
|
16289
|
-
|
|
16290
|
-
|
|
16615
|
+
path39.dirname(path39.dirname(projectRoot)),
|
|
16616
|
+
path39.dirname(projectRoot),
|
|
16291
16617
|
projectRoot
|
|
16292
16618
|
]) {
|
|
16293
|
-
const p =
|
|
16294
|
-
if (
|
|
16619
|
+
const p = path39.join(candidate, "agentcore", "agentcore.json");
|
|
16620
|
+
if (isFile17(p)) {
|
|
16295
16621
|
cfgPath = p;
|
|
16296
16622
|
break;
|
|
16297
16623
|
}
|
|
@@ -16301,7 +16627,7 @@ function checkAgentcoreName(projectRoot) {
|
|
|
16301
16627
|
}
|
|
16302
16628
|
let cfg;
|
|
16303
16629
|
try {
|
|
16304
|
-
cfg = JSON.parse(
|
|
16630
|
+
cfg = JSON.parse(fs39.readFileSync(cfgPath, "utf-8"));
|
|
16305
16631
|
} catch {
|
|
16306
16632
|
return [];
|
|
16307
16633
|
}
|
|
@@ -16333,7 +16659,7 @@ function isLocalEvmWallet(walletCfg) {
|
|
|
16333
16659
|
}
|
|
16334
16660
|
function anchoredKeystoreDir(projectRoot, walletCfg) {
|
|
16335
16661
|
const rel = String(walletCfg.keystore_dir ?? ".studio/wallets");
|
|
16336
|
-
return
|
|
16662
|
+
return path39.isAbsolute(rel) ? rel : path39.join(projectRoot, rel);
|
|
16337
16663
|
}
|
|
16338
16664
|
async function checkWallet(projectRoot, data) {
|
|
16339
16665
|
const walletCfg = tableOf14(data, "wallet");
|
|
@@ -16379,8 +16705,8 @@ async function checkWallet(projectRoot, data) {
|
|
|
16379
16705
|
}
|
|
16380
16706
|
const address = String(walletCfg.address ?? "").trim();
|
|
16381
16707
|
if (address) {
|
|
16382
|
-
const expected =
|
|
16383
|
-
if (!
|
|
16708
|
+
const expected = path39.join(keystoreDir, `${address}.json`);
|
|
16709
|
+
if (!isFile17(expected)) {
|
|
16384
16710
|
out.push({
|
|
16385
16711
|
name: "[wallet] address \u2194 keystore",
|
|
16386
16712
|
status: FAIL,
|
|
@@ -16390,7 +16716,7 @@ async function checkWallet(projectRoot, data) {
|
|
|
16390
16716
|
out.push({
|
|
16391
16717
|
name: "[wallet] address \u2194 keystore",
|
|
16392
16718
|
status: PASS,
|
|
16393
|
-
detail: `${address} matches ${
|
|
16719
|
+
detail: `${address} matches ${path39.basename(expected)}`
|
|
16394
16720
|
});
|
|
16395
16721
|
}
|
|
16396
16722
|
}
|
|
@@ -16407,9 +16733,9 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16407
16733
|
detail: "no [wallet].address \u2014 run `bag wallet new` first"
|
|
16408
16734
|
});
|
|
16409
16735
|
} else {
|
|
16410
|
-
const expected =
|
|
16736
|
+
const expected = path39.join(keystoreDir, `${address}.json`);
|
|
16411
16737
|
out.push(
|
|
16412
|
-
|
|
16738
|
+
isFile17(expected) ? {
|
|
16413
16739
|
name: "[wallet] Altana admin",
|
|
16414
16740
|
status: PASS,
|
|
16415
16741
|
detail: `${address} matches ${expected}`
|
|
@@ -16423,8 +16749,8 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16423
16749
|
const configured = String(
|
|
16424
16750
|
walletCfg.session_file ?? ".studio/wallets/altana-session.json"
|
|
16425
16751
|
);
|
|
16426
|
-
const sessionFile =
|
|
16427
|
-
if (!
|
|
16752
|
+
const sessionFile = path39.isAbsolute(configured) ? configured : path39.join(projectRoot, configured);
|
|
16753
|
+
if (!isFile17(sessionFile)) {
|
|
16428
16754
|
out.push({
|
|
16429
16755
|
name: "[wallet] Altana session",
|
|
16430
16756
|
status: FAIL,
|
|
@@ -16434,7 +16760,7 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16434
16760
|
}
|
|
16435
16761
|
let envelope;
|
|
16436
16762
|
try {
|
|
16437
|
-
envelope = JSON.parse(
|
|
16763
|
+
envelope = JSON.parse(fs39.readFileSync(sessionFile, "utf8"));
|
|
16438
16764
|
} catch {
|
|
16439
16765
|
out.push({
|
|
16440
16766
|
name: "[wallet] Altana session",
|
|
@@ -16460,7 +16786,7 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16460
16786
|
status: remaining <= 0 ? FAIL : remaining < 3 * 24 * 60 * 60 ? WARN : PASS,
|
|
16461
16787
|
detail: remaining > 0 ? `${String(envelope.publicKey)} active until ${new Date(expiry * 1e3).toISOString()}` : `expired at ${new Date(expiry * 1e3).toISOString()} \u2014 run \`bag wallet session grant --force\``
|
|
16462
16788
|
});
|
|
16463
|
-
if ((
|
|
16789
|
+
if ((fs39.statSync(sessionFile).mode & 63) !== 0) {
|
|
16464
16790
|
out.push({
|
|
16465
16791
|
name: "[wallet] Altana session permissions",
|
|
16466
16792
|
status: WARN,
|
|
@@ -16518,7 +16844,7 @@ async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
|
16518
16844
|
});
|
|
16519
16845
|
}
|
|
16520
16846
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
16521
|
-
if (
|
|
16847
|
+
if (isFile17(walletFile)) {
|
|
16522
16848
|
out.push({
|
|
16523
16849
|
name: "[wallet] twak wallet",
|
|
16524
16850
|
status: PASS,
|
|
@@ -16528,7 +16854,7 @@ async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
|
16528
16854
|
let createCmd = "twak wallet create --password <pw> --no-keychain";
|
|
16529
16855
|
let setupCmd = "twak setup";
|
|
16530
16856
|
if (walletCfg.twak_home) {
|
|
16531
|
-
const home =
|
|
16857
|
+
const home = path39.dirname(path39.dirname(walletFile));
|
|
16532
16858
|
createCmd = `HOME=${home} ${createCmd}`;
|
|
16533
16859
|
setupCmd = `HOME=${home} ${setupCmd}`;
|
|
16534
16860
|
}
|
|
@@ -17284,11 +17610,11 @@ function checkAgentsMdSkillTrigger(projectRoot) {
|
|
|
17284
17610
|
if (ws === null) {
|
|
17285
17611
|
return [];
|
|
17286
17612
|
}
|
|
17287
|
-
const agentsMd =
|
|
17613
|
+
const agentsMd = path39.join(ws, "AGENTS.md");
|
|
17288
17614
|
const line = "For any bnbagent-studio task (deploy, sell, operate, debug), load the `/bnbagent-studio` skill first.";
|
|
17289
17615
|
let text2;
|
|
17290
17616
|
try {
|
|
17291
|
-
text2 =
|
|
17617
|
+
text2 = isFile17(agentsMd) ? fs39.readFileSync(agentsMd, "utf-8") : null;
|
|
17292
17618
|
} catch {
|
|
17293
17619
|
return [];
|
|
17294
17620
|
}
|
|
@@ -17325,8 +17651,8 @@ function printChecks(checks) {
|
|
|
17325
17651
|
}
|
|
17326
17652
|
|
|
17327
17653
|
// src/cli/env.ts
|
|
17328
|
-
import * as
|
|
17329
|
-
import * as
|
|
17654
|
+
import * as fs40 from "fs";
|
|
17655
|
+
import * as path40 from "path";
|
|
17330
17656
|
var SECRET_KEY_PARTS = ["PASSWORD", "SECRET", "TOKEN", "API_KEY"];
|
|
17331
17657
|
var WALLET_PASSWORD_KEYS = /* @__PURE__ */ new Set([
|
|
17332
17658
|
"WALLET_PASSWORD",
|
|
@@ -17372,8 +17698,8 @@ function resolveEnvPath(fileArg, rootArg) {
|
|
|
17372
17698
|
return [fileArg, null];
|
|
17373
17699
|
}
|
|
17374
17700
|
if (rootArg !== void 0) {
|
|
17375
|
-
const root2 =
|
|
17376
|
-
if (!
|
|
17701
|
+
const root2 = path40.resolve(rootArg);
|
|
17702
|
+
if (!fs40.existsSync(path40.join(root2, "studio.toml"))) {
|
|
17377
17703
|
return [null, `error: no studio.toml under --project-root ${root2}`];
|
|
17378
17704
|
}
|
|
17379
17705
|
return [envLocalPath(root2), null];
|
|
@@ -17384,7 +17710,7 @@ function resolveEnvPath(fileArg, rootArg) {
|
|
|
17384
17710
|
}
|
|
17385
17711
|
const target = envLocalPath(root);
|
|
17386
17712
|
let note = null;
|
|
17387
|
-
if (
|
|
17713
|
+
if (path40.dirname(path40.dirname(target)) !== path40.resolve(process.cwd())) {
|
|
17388
17714
|
note = `\u2192 writing to ${target} (workspace .studio/, where \`bag dev\` reads)`;
|
|
17389
17715
|
}
|
|
17390
17716
|
return [target, note];
|
|
@@ -17441,7 +17767,7 @@ function cmdGet2(key, fileArg, rootArg) {
|
|
|
17441
17767
|
}
|
|
17442
17768
|
|
|
17443
17769
|
// src/cli/erc8004.ts
|
|
17444
|
-
import * as
|
|
17770
|
+
import * as path41 from "path";
|
|
17445
17771
|
import { auditedOp as auditedOp3 } from "@bnbagent/studio-runtime/audit";
|
|
17446
17772
|
import {
|
|
17447
17773
|
findProjectRoot as findProjectRoot5,
|
|
@@ -17451,7 +17777,7 @@ import {
|
|
|
17451
17777
|
import {
|
|
17452
17778
|
getMetadata,
|
|
17453
17779
|
register as register2,
|
|
17454
|
-
resolve as
|
|
17780
|
+
resolve as resolve21,
|
|
17455
17781
|
setMetadata,
|
|
17456
17782
|
show as show2,
|
|
17457
17783
|
updateServiceEndpoint as updateServiceEndpoint2
|
|
@@ -17562,7 +17888,7 @@ function loadAgentCfg3() {
|
|
|
17562
17888
|
return null;
|
|
17563
17889
|
}
|
|
17564
17890
|
try {
|
|
17565
|
-
return loadStudioToml22(
|
|
17891
|
+
return loadStudioToml22(path41.join(root, "studio.toml"));
|
|
17566
17892
|
} catch {
|
|
17567
17893
|
return null;
|
|
17568
17894
|
}
|
|
@@ -17640,7 +17966,7 @@ function loadIdentityBlock(agentRoot2) {
|
|
|
17640
17966
|
try {
|
|
17641
17967
|
return {
|
|
17642
17968
|
...tableOf15(
|
|
17643
|
-
loadStudioToml22(
|
|
17969
|
+
loadStudioToml22(path41.join(agentRoot2, "studio.toml")),
|
|
17644
17970
|
"identity"
|
|
17645
17971
|
)
|
|
17646
17972
|
};
|
|
@@ -17979,7 +18305,7 @@ async function cmdResolve(agentId, networkArg) {
|
|
|
17979
18305
|
const wallet = walletRt6.getWallet();
|
|
17980
18306
|
let uri;
|
|
17981
18307
|
try {
|
|
17982
|
-
uri = await
|
|
18308
|
+
uri = await resolve21(agentId, {
|
|
17983
18309
|
wallet,
|
|
17984
18310
|
network: resolveNetwork2(networkArg)
|
|
17985
18311
|
});
|
|
@@ -17992,8 +18318,8 @@ async function cmdResolve(agentId, networkArg) {
|
|
|
17992
18318
|
}
|
|
17993
18319
|
|
|
17994
18320
|
// src/cli/erc8183.ts
|
|
17995
|
-
import * as
|
|
17996
|
-
import * as
|
|
18321
|
+
import * as fs41 from "fs";
|
|
18322
|
+
import * as path42 from "path";
|
|
17997
18323
|
import { JobStatus } from "@bnbagent/sdk";
|
|
17998
18324
|
import {
|
|
17999
18325
|
buyWorkflow,
|
|
@@ -18097,8 +18423,8 @@ function applyProjectRoot2(root) {
|
|
|
18097
18423
|
if (root === void 0) {
|
|
18098
18424
|
return null;
|
|
18099
18425
|
}
|
|
18100
|
-
const p =
|
|
18101
|
-
if (!
|
|
18426
|
+
const p = path42.resolve(root);
|
|
18427
|
+
if (!fs41.existsSync(path42.join(p, "studio.toml"))) {
|
|
18102
18428
|
printErr(`error: no studio.toml under --project-root ${p}`);
|
|
18103
18429
|
return 2;
|
|
18104
18430
|
}
|
|
@@ -18183,7 +18509,7 @@ function parseQuoteEnvelope(raw) {
|
|
|
18183
18509
|
let text2 = trimmed;
|
|
18184
18510
|
if (!trimmed.startsWith("{")) {
|
|
18185
18511
|
try {
|
|
18186
|
-
text2 =
|
|
18512
|
+
text2 = fs41.readFileSync(trimmed, "utf-8");
|
|
18187
18513
|
} catch (exc) {
|
|
18188
18514
|
throw new Error(
|
|
18189
18515
|
`--quote-json is neither inline JSON nor a readable file: ${errMsg5(exc)}`
|
|
@@ -18363,9 +18689,9 @@ async function cmdSettle(jobId, opts) {
|
|
|
18363
18689
|
}
|
|
18364
18690
|
|
|
18365
18691
|
// src/cli/skills.ts
|
|
18366
|
-
import * as
|
|
18692
|
+
import * as fs42 from "fs";
|
|
18367
18693
|
import * as os6 from "os";
|
|
18368
|
-
import * as
|
|
18694
|
+
import * as path43 from "path";
|
|
18369
18695
|
import { Option as Option7 } from "commander";
|
|
18370
18696
|
function registerSkills(program) {
|
|
18371
18697
|
const skills = program.command("skills").description("Install Claude Code skills into the host IDE.").action(
|
|
@@ -18411,7 +18737,7 @@ function cmdList4() {
|
|
|
18411
18737
|
for (const p of listSourceSkills(
|
|
18412
18738
|
SKILLS_SOURCE
|
|
18413
18739
|
)) {
|
|
18414
|
-
printOut(
|
|
18740
|
+
printOut(path43.basename(p));
|
|
18415
18741
|
}
|
|
18416
18742
|
const refs = listSourceReferences(
|
|
18417
18743
|
SKILLS_SOURCE
|
|
@@ -18422,7 +18748,7 @@ function cmdList4() {
|
|
|
18422
18748
|
references (installed under ${ROUTER_SKILL_NAME}/references/, loaded on demand by the skills above):`
|
|
18423
18749
|
);
|
|
18424
18750
|
for (const p of refs) {
|
|
18425
|
-
printOut(` ${
|
|
18751
|
+
printOut(` ${path43.basename(p)}`);
|
|
18426
18752
|
}
|
|
18427
18753
|
}
|
|
18428
18754
|
return 0;
|
|
@@ -18634,7 +18960,7 @@ function installTargets(targets, scope) {
|
|
|
18634
18960
|
);
|
|
18635
18961
|
for (const name of result.legacyPresent) {
|
|
18636
18962
|
const leaf = result.target === "cursor" ? `${name}.mdc` : name;
|
|
18637
|
-
printErr(` - ${
|
|
18963
|
+
printErr(` - ${path43.join(result.targetDir, leaf)}`);
|
|
18638
18964
|
}
|
|
18639
18965
|
printErr(
|
|
18640
18966
|
"\nThese are NOT auto-deleted (studio never touches user resources).\nRemove with `rm -rf <path>` once you confirm none of them are\ncarrying local edits you want to keep."
|
|
@@ -18647,19 +18973,19 @@ function studioSkillNames() {
|
|
|
18647
18973
|
for (const p of listSourceSkills(
|
|
18648
18974
|
SKILLS_SOURCE
|
|
18649
18975
|
)) {
|
|
18650
|
-
names.add(
|
|
18976
|
+
names.add(path43.basename(p).replace(/\.md$/, ""));
|
|
18651
18977
|
}
|
|
18652
18978
|
for (const name of LEGACY_SKILL_NAMES) {
|
|
18653
18979
|
names.add(name);
|
|
18654
18980
|
}
|
|
18655
|
-
const providersRoot =
|
|
18981
|
+
const providersRoot = path43.join(bundledRecipesRoot(), "providers");
|
|
18656
18982
|
if (isDir9(providersRoot)) {
|
|
18657
|
-
for (const provider of
|
|
18658
|
-
const skillDir =
|
|
18983
|
+
for (const provider of fs42.readdirSync(providersRoot)) {
|
|
18984
|
+
const skillDir = path43.join(providersRoot, provider, "skills");
|
|
18659
18985
|
if (!isDir9(skillDir)) {
|
|
18660
18986
|
continue;
|
|
18661
18987
|
}
|
|
18662
|
-
for (const md of
|
|
18988
|
+
for (const md of fs42.readdirSync(skillDir)) {
|
|
18663
18989
|
if (md.endsWith(".md")) {
|
|
18664
18990
|
names.add(md.replace(/\.md$/, ""));
|
|
18665
18991
|
}
|
|
@@ -18670,14 +18996,14 @@ function studioSkillNames() {
|
|
|
18670
18996
|
}
|
|
18671
18997
|
function isDir9(p) {
|
|
18672
18998
|
try {
|
|
18673
|
-
return
|
|
18999
|
+
return fs42.statSync(p).isDirectory();
|
|
18674
19000
|
} catch {
|
|
18675
19001
|
return false;
|
|
18676
19002
|
}
|
|
18677
19003
|
}
|
|
18678
|
-
function
|
|
19004
|
+
function isFile18(p) {
|
|
18679
19005
|
try {
|
|
18680
|
-
return
|
|
19006
|
+
return fs42.statSync(p).isFile();
|
|
18681
19007
|
} catch {
|
|
18682
19008
|
return false;
|
|
18683
19009
|
}
|
|
@@ -18691,26 +19017,26 @@ function findInstalledSkills(knownNames) {
|
|
|
18691
19017
|
if (!isDir9(root)) {
|
|
18692
19018
|
return;
|
|
18693
19019
|
}
|
|
18694
|
-
const resolved =
|
|
18695
|
-
if (!roots.some((r) =>
|
|
19020
|
+
const resolved = fs42.realpathSync(root);
|
|
19021
|
+
if (!roots.some((r) => fs42.realpathSync(r) === resolved)) {
|
|
18696
19022
|
roots.push(root);
|
|
18697
19023
|
}
|
|
18698
19024
|
};
|
|
18699
|
-
addRoot(
|
|
18700
|
-
addRoot(
|
|
18701
|
-
addRoot(
|
|
18702
|
-
addRoot(
|
|
19025
|
+
addRoot(path43.join(home, ".claude", "skills"));
|
|
19026
|
+
addRoot(path43.join(home, ".cursor", "rules"));
|
|
19027
|
+
addRoot(path43.join(cwd, ".claude", "skills"));
|
|
19028
|
+
addRoot(path43.join(cwd, ".cursor", "rules"));
|
|
18703
19029
|
for (const root of roots) {
|
|
18704
|
-
const isCursor =
|
|
19030
|
+
const isCursor = path43.basename(root) === "rules" && path43.basename(path43.dirname(root)) === ".cursor";
|
|
18705
19031
|
for (const name of [...knownNames].sort()) {
|
|
18706
|
-
const target =
|
|
18707
|
-
if (isCursor &&
|
|
19032
|
+
const target = path43.join(root, isCursor ? `${name}.mdc` : name);
|
|
19033
|
+
if (isCursor && isFile18(target)) {
|
|
18708
19034
|
found.push(target);
|
|
18709
19035
|
} else if (!isCursor && isDir9(target)) {
|
|
18710
19036
|
found.push(target);
|
|
18711
19037
|
}
|
|
18712
|
-
if (isCursor && isDir9(
|
|
18713
|
-
found.push(
|
|
19038
|
+
if (isCursor && isDir9(path43.join(root, name))) {
|
|
19039
|
+
found.push(path43.join(root, name));
|
|
18714
19040
|
}
|
|
18715
19041
|
}
|
|
18716
19042
|
}
|
|
@@ -18738,7 +19064,7 @@ async function cmdUninstall(flags) {
|
|
|
18738
19064
|
}
|
|
18739
19065
|
}
|
|
18740
19066
|
for (const p of installed) {
|
|
18741
|
-
|
|
19067
|
+
fs42.rmSync(p, { recursive: true, force: true });
|
|
18742
19068
|
printOut(` removed: ${p}`);
|
|
18743
19069
|
}
|
|
18744
19070
|
}
|
|
@@ -18777,7 +19103,7 @@ function registerUninstall(program) {
|
|
|
18777
19103
|
}
|
|
18778
19104
|
|
|
18779
19105
|
// src/cli/platform.ts
|
|
18780
|
-
import * as
|
|
19106
|
+
import * as path44 from "path";
|
|
18781
19107
|
import {
|
|
18782
19108
|
STUDIO_TOML as STUDIO_TOML2,
|
|
18783
19109
|
findSubProjectRoot as findSubProjectRoot18,
|
|
@@ -18980,7 +19306,7 @@ function localPlatformCfg() {
|
|
|
18980
19306
|
if (agentRoot2 === null) {
|
|
18981
19307
|
return [null, {}];
|
|
18982
19308
|
}
|
|
18983
|
-
const tomlPath =
|
|
19309
|
+
const tomlPath = path44.join(agentRoot2, STUDIO_TOML2);
|
|
18984
19310
|
let cfg;
|
|
18985
19311
|
try {
|
|
18986
19312
|
cfg = loadStudioToml23(tomlPath);
|
|
@@ -19053,8 +19379,8 @@ function formatRemaining(seconds) {
|
|
|
19053
19379
|
}
|
|
19054
19380
|
|
|
19055
19381
|
// src/cli/recipe.ts
|
|
19056
|
-
import * as
|
|
19057
|
-
import * as
|
|
19382
|
+
import * as fs43 from "fs";
|
|
19383
|
+
import * as path45 from "path";
|
|
19058
19384
|
import { parse as parse6 } from "smol-toml";
|
|
19059
19385
|
function registerRecipe(program) {
|
|
19060
19386
|
const p = program.command("recipe").description("Print recipe code/files (agent / wallet / 8004).");
|
|
@@ -19184,7 +19510,7 @@ function resolvePkgContext(explicit) {
|
|
|
19184
19510
|
let data;
|
|
19185
19511
|
try {
|
|
19186
19512
|
data = parse6(
|
|
19187
|
-
|
|
19513
|
+
fs43.readFileSync(path45.join(projectRoot, "studio.toml"), "utf-8")
|
|
19188
19514
|
);
|
|
19189
19515
|
} catch {
|
|
19190
19516
|
return [null, null];
|
|
@@ -19202,8 +19528,8 @@ function resolvePkgContext(explicit) {
|
|
|
19202
19528
|
}
|
|
19203
19529
|
|
|
19204
19530
|
// src/cli/scan.ts
|
|
19205
|
-
import * as
|
|
19206
|
-
import * as
|
|
19531
|
+
import * as fs44 from "fs";
|
|
19532
|
+
import * as path46 from "path";
|
|
19207
19533
|
import { Option as Option8 } from "commander";
|
|
19208
19534
|
import { parse as parse7 } from "smol-toml";
|
|
19209
19535
|
function registerScan(program) {
|
|
@@ -19220,7 +19546,7 @@ function registerScan(program) {
|
|
|
19220
19546
|
"note: `--json` is deprecated (JSON is the default output); ignoring."
|
|
19221
19547
|
);
|
|
19222
19548
|
}
|
|
19223
|
-
const root =
|
|
19549
|
+
const root = path46.resolve(opts.path ?? process.cwd());
|
|
19224
19550
|
const report = scanProject(root);
|
|
19225
19551
|
if (opts.text) {
|
|
19226
19552
|
process.stdout.write(formatText(report));
|
|
@@ -19232,26 +19558,26 @@ function registerScan(program) {
|
|
|
19232
19558
|
})
|
|
19233
19559
|
);
|
|
19234
19560
|
}
|
|
19235
|
-
function
|
|
19561
|
+
function isFile19(p) {
|
|
19236
19562
|
try {
|
|
19237
|
-
return
|
|
19563
|
+
return fs44.statSync(p).isFile();
|
|
19238
19564
|
} catch {
|
|
19239
19565
|
return false;
|
|
19240
19566
|
}
|
|
19241
19567
|
}
|
|
19242
19568
|
function isDir10(p) {
|
|
19243
19569
|
try {
|
|
19244
|
-
return
|
|
19570
|
+
return fs44.statSync(p).isDirectory();
|
|
19245
19571
|
} catch {
|
|
19246
19572
|
return false;
|
|
19247
19573
|
}
|
|
19248
19574
|
}
|
|
19249
19575
|
function layerBase(root) {
|
|
19250
|
-
return isDir10(
|
|
19576
|
+
return isDir10(path46.join(root, "app", "agent")) ? path46.join(root, "app") : root;
|
|
19251
19577
|
}
|
|
19252
19578
|
function safeReadJson(p) {
|
|
19253
19579
|
try {
|
|
19254
|
-
const data = JSON.parse(
|
|
19580
|
+
const data = JSON.parse(fs44.readFileSync(p, "utf-8"));
|
|
19255
19581
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
19256
19582
|
} catch {
|
|
19257
19583
|
return null;
|
|
@@ -19259,7 +19585,7 @@ function safeReadJson(p) {
|
|
|
19259
19585
|
}
|
|
19260
19586
|
function safeReadToml(p) {
|
|
19261
19587
|
try {
|
|
19262
|
-
return parse7(
|
|
19588
|
+
return parse7(fs44.readFileSync(p, "utf-8"));
|
|
19263
19589
|
} catch {
|
|
19264
19590
|
return null;
|
|
19265
19591
|
}
|
|
@@ -19289,33 +19615,33 @@ function resolvePackageName(projectName2, root) {
|
|
|
19289
19615
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(candidate)) {
|
|
19290
19616
|
return null;
|
|
19291
19617
|
}
|
|
19292
|
-
if (!isDir10(
|
|
19618
|
+
if (!isDir10(path46.join(root, candidate))) {
|
|
19293
19619
|
return null;
|
|
19294
19620
|
}
|
|
19295
19621
|
return candidate;
|
|
19296
19622
|
}
|
|
19297
19623
|
function inferLayout(root) {
|
|
19298
|
-
const agentDir =
|
|
19299
|
-
const hasAgent =
|
|
19624
|
+
const agentDir = path46.join(layerBase(root), "agent");
|
|
19625
|
+
const hasAgent = isFile19(path46.join(agentDir, "main.ts")) || isFile19(path46.join(agentDir, "main.py"));
|
|
19300
19626
|
return {
|
|
19301
19627
|
has_agent: hasAgent,
|
|
19302
|
-
has_agent_descriptor:
|
|
19303
|
-
|
|
19628
|
+
has_agent_descriptor: isFile19(
|
|
19629
|
+
path46.join(root, "agentcore", "agentcore.json")
|
|
19304
19630
|
),
|
|
19305
19631
|
role: hasAgent ? "agent" : "none"
|
|
19306
19632
|
};
|
|
19307
19633
|
}
|
|
19308
19634
|
function inferPackageManager(root, hasPackageJson) {
|
|
19309
|
-
if (
|
|
19635
|
+
if (isFile19(path46.join(root, "pnpm-lock.yaml"))) {
|
|
19310
19636
|
return "pnpm";
|
|
19311
19637
|
}
|
|
19312
|
-
if (
|
|
19638
|
+
if (isFile19(path46.join(root, "yarn.lock"))) {
|
|
19313
19639
|
return "yarn";
|
|
19314
19640
|
}
|
|
19315
|
-
if (
|
|
19641
|
+
if (isFile19(path46.join(root, "bun.lockb"))) {
|
|
19316
19642
|
return "bun";
|
|
19317
19643
|
}
|
|
19318
|
-
if (
|
|
19644
|
+
if (isFile19(path46.join(root, "package-lock.json"))) {
|
|
19319
19645
|
return "npm";
|
|
19320
19646
|
}
|
|
19321
19647
|
if (hasPackageJson) {
|
|
@@ -19328,7 +19654,7 @@ function inferRecipes(root, studioData, layout) {
|
|
|
19328
19654
|
if (layout.has_agent) {
|
|
19329
19655
|
recipes.push("agent");
|
|
19330
19656
|
}
|
|
19331
|
-
const walletsDir =
|
|
19657
|
+
const walletsDir = path46.join(root, ".studio", "wallets");
|
|
19332
19658
|
const walletSection = studioData?.wallet;
|
|
19333
19659
|
const hasWalletSection = walletSection !== null && typeof walletSection === "object" && !Array.isArray(walletSection);
|
|
19334
19660
|
if (isDir10(walletsDir) && hasWalletSection) {
|
|
@@ -19337,13 +19663,13 @@ function inferRecipes(root, studioData, layout) {
|
|
|
19337
19663
|
return recipes;
|
|
19338
19664
|
}
|
|
19339
19665
|
function scanProject(root) {
|
|
19340
|
-
const studioToml =
|
|
19341
|
-
const packageJson =
|
|
19342
|
-
const agentcoreJson =
|
|
19343
|
-
const hasStudioToml =
|
|
19344
|
-
const hasPackageJson =
|
|
19345
|
-
const hasAgentcoreJson =
|
|
19346
|
-
const hasDotStudioDir = isDir10(
|
|
19666
|
+
const studioToml = path46.join(root, "studio.toml");
|
|
19667
|
+
const packageJson = path46.join(root, "package.json");
|
|
19668
|
+
const agentcoreJson = path46.join(root, "agentcore", "agentcore.json");
|
|
19669
|
+
const hasStudioToml = isFile19(studioToml);
|
|
19670
|
+
const hasPackageJson = isFile19(packageJson);
|
|
19671
|
+
const hasAgentcoreJson = isFile19(agentcoreJson);
|
|
19672
|
+
const hasDotStudioDir = isDir10(path46.join(root, ".studio"));
|
|
19347
19673
|
const pkgData = hasPackageJson ? safeReadJson(packageJson) : null;
|
|
19348
19674
|
const studioData = hasStudioToml ? safeReadToml(studioToml) : null;
|
|
19349
19675
|
const rawName = pkgData?.name;
|
|
@@ -19400,8 +19726,8 @@ function formatText(report) {
|
|
|
19400
19726
|
}
|
|
19401
19727
|
|
|
19402
19728
|
// src/cli/x402.ts
|
|
19403
|
-
import * as
|
|
19404
|
-
import * as
|
|
19729
|
+
import * as fs45 from "fs";
|
|
19730
|
+
import * as path47 from "path";
|
|
19405
19731
|
import { auditedOp as auditedOp4 } from "@bnbagent/studio-runtime/audit";
|
|
19406
19732
|
import {
|
|
19407
19733
|
envLocalPath as envLocalPath18,
|
|
@@ -19595,7 +19921,7 @@ function loadX402Policy() {
|
|
|
19595
19921
|
}
|
|
19596
19922
|
let cfg;
|
|
19597
19923
|
try {
|
|
19598
|
-
cfg = loadStudioToml24(
|
|
19924
|
+
cfg = loadStudioToml24(path47.join(root, "studio.toml"));
|
|
19599
19925
|
} catch (exc) {
|
|
19600
19926
|
printErr(`error: failed to parse studio.toml: ${errMsg6(exc)}`);
|
|
19601
19927
|
return null;
|
|
@@ -19609,7 +19935,7 @@ function loadSellerConfig() {
|
|
|
19609
19935
|
return null;
|
|
19610
19936
|
}
|
|
19611
19937
|
try {
|
|
19612
|
-
return [root, loadStudioToml24(
|
|
19938
|
+
return [root, loadStudioToml24(path47.join(root, "studio.toml"))];
|
|
19613
19939
|
} catch (exc) {
|
|
19614
19940
|
printErr(`error: failed to parse studio.toml: ${errMsg6(exc)}`);
|
|
19615
19941
|
return null;
|
|
@@ -19655,8 +19981,8 @@ async function cmdSellInit(priceFlag) {
|
|
|
19655
19981
|
const loaded = loadSellerConfig();
|
|
19656
19982
|
if (loaded === null) return 1;
|
|
19657
19983
|
const [root, cfg] = loaded;
|
|
19658
|
-
const tomlPath =
|
|
19659
|
-
const original =
|
|
19984
|
+
const tomlPath = path47.join(root, "studio.toml");
|
|
19985
|
+
const original = fs45.readFileSync(tomlPath, "utf8");
|
|
19660
19986
|
const sellerExists = hasSection(original, "payments.x402_seller");
|
|
19661
19987
|
let priceUsd;
|
|
19662
19988
|
try {
|
|
@@ -19674,7 +20000,7 @@ async function cmdSellInit(priceFlag) {
|
|
|
19674
20000
|
return 1;
|
|
19675
20001
|
}
|
|
19676
20002
|
if (!sellerExists) {
|
|
19677
|
-
|
|
20003
|
+
fs45.writeFileSync(
|
|
19678
20004
|
tomlPath,
|
|
19679
20005
|
updateSection(original, "payments.x402_seller", {
|
|
19680
20006
|
enabled: true,
|
|
@@ -19686,7 +20012,7 @@ async function cmdSellInit(priceFlag) {
|
|
|
19686
20012
|
"utf8"
|
|
19687
20013
|
);
|
|
19688
20014
|
} else if (priceFlag !== void 0) {
|
|
19689
|
-
|
|
20015
|
+
fs45.writeFileSync(
|
|
19690
20016
|
tomlPath,
|
|
19691
20017
|
updateSection(original, "payments.x402_seller", {
|
|
19692
20018
|
price_usd: priceUsd
|
|
@@ -20055,14 +20381,14 @@ async function confirmOrAbort(prompt, assumeYes) {
|
|
|
20055
20381
|
return answer === "y" || answer === "yes";
|
|
20056
20382
|
}
|
|
20057
20383
|
function writeMerchantEntry(tomlPath, fields) {
|
|
20058
|
-
const text2 =
|
|
20384
|
+
const text2 = fs45.readFileSync(tomlPath, "utf-8");
|
|
20059
20385
|
const entries = {
|
|
20060
20386
|
domain: fields.domain,
|
|
20061
20387
|
pay_to: fields.payTo,
|
|
20062
20388
|
per_call_cap_usd: fields.capUsd,
|
|
20063
20389
|
verified: fields.verified
|
|
20064
20390
|
};
|
|
20065
|
-
|
|
20391
|
+
fs45.writeFileSync(
|
|
20066
20392
|
tomlPath,
|
|
20067
20393
|
updateSection(text2, `payments.x402.merchants.${fields.key}`, entries),
|
|
20068
20394
|
"utf-8"
|
|
@@ -20191,7 +20517,7 @@ The merchant may have rotated its address (or the response was tampered with). U
|
|
|
20191
20517
|
printOut("aborted \u2014 nothing written.");
|
|
20192
20518
|
return 1;
|
|
20193
20519
|
}
|
|
20194
|
-
const tomlPath =
|
|
20520
|
+
const tomlPath = path47.join(root, "studio.toml");
|
|
20195
20521
|
try {
|
|
20196
20522
|
writeMerchantEntry(tomlPath, {
|
|
20197
20523
|
key,
|
|
@@ -20254,23 +20580,23 @@ function buildProgram() {
|
|
|
20254
20580
|
return program;
|
|
20255
20581
|
}
|
|
20256
20582
|
function cliVersion() {
|
|
20257
|
-
return "0.0.6-alpha.
|
|
20583
|
+
return "0.0.6-alpha.8";
|
|
20258
20584
|
}
|
|
20259
20585
|
|
|
20260
20586
|
// src/cli/updateCheck.ts
|
|
20261
|
-
import * as
|
|
20587
|
+
import * as fs46 from "fs";
|
|
20262
20588
|
import * as os7 from "os";
|
|
20263
|
-
import * as
|
|
20589
|
+
import * as path48 from "path";
|
|
20264
20590
|
var PACKAGE = "@bnbagent/studio-cli";
|
|
20265
20591
|
var REGISTRY_LATEST_URL = `https://registry.npmjs.org/${PACKAGE}/latest`;
|
|
20266
20592
|
var CHECK_INTERVAL_SECONDS = 24 * 3600;
|
|
20267
20593
|
var TIMEOUT_MS = 2e3;
|
|
20268
20594
|
function cachePath(home) {
|
|
20269
|
-
return
|
|
20595
|
+
return path48.join(home, ".bag", "update-check.json");
|
|
20270
20596
|
}
|
|
20271
20597
|
function loadCache(home) {
|
|
20272
20598
|
try {
|
|
20273
|
-
const data = JSON.parse(
|
|
20599
|
+
const data = JSON.parse(fs46.readFileSync(cachePath(home), "utf-8"));
|
|
20274
20600
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : {};
|
|
20275
20601
|
} catch {
|
|
20276
20602
|
return {};
|
|
@@ -20279,8 +20605,8 @@ function loadCache(home) {
|
|
|
20279
20605
|
function saveCache(state, home) {
|
|
20280
20606
|
try {
|
|
20281
20607
|
const p = cachePath(home);
|
|
20282
|
-
|
|
20283
|
-
|
|
20608
|
+
fs46.mkdirSync(path48.dirname(p), { recursive: true });
|
|
20609
|
+
fs46.writeFileSync(p, `${JSON.stringify(state, null, 2)}
|
|
20284
20610
|
`);
|
|
20285
20611
|
} catch {
|
|
20286
20612
|
}
|