@bnbagent/studio-cli 0.0.6-alpha.7 → 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 +920 -723
- 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 -110
- package/skills/references/bnbagent-studio-scaffolding-agent.md +134 -400
- package/skills/references/bnbagent-studio-selling-via-8183.md +87 -171
- package/skills/references/bnbagent-studio-selling-via-b402.md +39 -131
- package/skills/references/bnbagent-studio-use-aws-agentcore.md +42 -141
- 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,
|
|
@@ -4548,7 +4720,7 @@ function loadFullCfg() {
|
|
|
4548
4720
|
}
|
|
4549
4721
|
let cfg;
|
|
4550
4722
|
try {
|
|
4551
|
-
cfg = loadStudioToml8(
|
|
4723
|
+
cfg = loadStudioToml8(path18.join(root, "studio.toml"));
|
|
4552
4724
|
} catch (exc) {
|
|
4553
4725
|
printErr(`error: failed to parse studio.toml: ${errMessage(exc)}`);
|
|
4554
4726
|
return null;
|
|
@@ -4910,9 +5082,9 @@ Retry: re-run \`bag llm activate\` \u2014 key_hash is saved so it will pick up w
|
|
|
4910
5082
|
return 0;
|
|
4911
5083
|
}
|
|
4912
5084
|
function updateStudioTomlSection(root, section, updates) {
|
|
4913
|
-
const tomlPath =
|
|
4914
|
-
const text2 =
|
|
4915
|
-
|
|
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");
|
|
4916
5088
|
}
|
|
4917
5089
|
function cumulativeTopupsUsd() {
|
|
4918
5090
|
let total = 0;
|
|
@@ -5461,8 +5633,8 @@ function normalizeNodeDeps(deps) {
|
|
|
5461
5633
|
}
|
|
5462
5634
|
|
|
5463
5635
|
// src/cli/recipes/loader.ts
|
|
5464
|
-
import * as
|
|
5465
|
-
import * as
|
|
5636
|
+
import * as fs20 from "fs";
|
|
5637
|
+
import * as path19 from "path";
|
|
5466
5638
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
5467
5639
|
import { parse as parse5 } from "smol-toml";
|
|
5468
5640
|
var PLACEHOLDER_RE = /\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
|
|
@@ -5471,12 +5643,12 @@ function bundledRecipesRoot() {
|
|
|
5471
5643
|
if (override) {
|
|
5472
5644
|
return override;
|
|
5473
5645
|
}
|
|
5474
|
-
let dir =
|
|
5646
|
+
let dir = path19.dirname(fileURLToPath3(import.meta.url));
|
|
5475
5647
|
for (; ; ) {
|
|
5476
|
-
if (
|
|
5477
|
-
return
|
|
5648
|
+
if (fs20.existsSync(path19.join(dir, "package.json"))) {
|
|
5649
|
+
return path19.join(dir, "recipes");
|
|
5478
5650
|
}
|
|
5479
|
-
const parent =
|
|
5651
|
+
const parent = path19.dirname(dir);
|
|
5480
5652
|
if (parent === dir) {
|
|
5481
5653
|
throw new Error("cannot locate the studio-cli package root");
|
|
5482
5654
|
}
|
|
@@ -5500,24 +5672,24 @@ function defaultMode(recipe) {
|
|
|
5500
5672
|
}
|
|
5501
5673
|
function listRecipes(root) {
|
|
5502
5674
|
const base = root ?? bundledRecipesRoot();
|
|
5503
|
-
if (!
|
|
5675
|
+
if (!fs20.existsSync(base)) {
|
|
5504
5676
|
return [];
|
|
5505
5677
|
}
|
|
5506
|
-
return
|
|
5507
|
-
(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()
|
|
5508
5680
|
).sort();
|
|
5509
5681
|
}
|
|
5510
5682
|
var RecipeModeError = class extends Error {
|
|
5511
5683
|
};
|
|
5512
5684
|
function loadRecipe(name, opts = {}) {
|
|
5513
5685
|
const base = opts.root ?? bundledRecipesRoot();
|
|
5514
|
-
const recipeDir =
|
|
5515
|
-
const tomlPath =
|
|
5516
|
-
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()) {
|
|
5517
5689
|
throw new Error(`Recipe '${name}' not found at ${tomlPath}`);
|
|
5518
5690
|
}
|
|
5519
|
-
const metadata = parse5(
|
|
5520
|
-
const allFiles = collectTemplateFiles(
|
|
5691
|
+
const metadata = parse5(fs20.readFileSync(tomlPath, "utf-8"));
|
|
5692
|
+
const allFiles = collectTemplateFiles(path19.join(recipeDir, "code"));
|
|
5521
5693
|
const modesMeta = metaTable(metadata, "modes");
|
|
5522
5694
|
const mode = opts.mode ?? null;
|
|
5523
5695
|
if (Object.keys(modesMeta).length === 0) {
|
|
@@ -5564,22 +5736,22 @@ function modeFiles(modesMeta, modeName) {
|
|
|
5564
5736
|
return Array.isArray(files) ? files.filter((f) => typeof f === "string") : [];
|
|
5565
5737
|
}
|
|
5566
5738
|
function collectTemplateFiles(codeDir) {
|
|
5567
|
-
if (!
|
|
5739
|
+
if (!fs20.existsSync(codeDir) || !fs20.statSync(codeDir).isDirectory()) {
|
|
5568
5740
|
return [];
|
|
5569
5741
|
}
|
|
5570
5742
|
const out = [];
|
|
5571
5743
|
const walk = (dir) => {
|
|
5572
|
-
for (const name of
|
|
5573
|
-
const full =
|
|
5574
|
-
if (
|
|
5744
|
+
for (const name of fs20.readdirSync(dir).sort()) {
|
|
5745
|
+
const full = path19.join(dir, name);
|
|
5746
|
+
if (fs20.statSync(full).isDirectory()) {
|
|
5575
5747
|
walk(full);
|
|
5576
5748
|
} else {
|
|
5577
|
-
const rel =
|
|
5749
|
+
const rel = path19.relative(codeDir, full);
|
|
5578
5750
|
const target = rel.endsWith(".tmpl") ? rel.slice(0, -".tmpl".length) : rel;
|
|
5579
5751
|
out.push({
|
|
5580
5752
|
// Recipes use forward slashes regardless of host OS.
|
|
5581
|
-
targetPath: target.split(
|
|
5582
|
-
content:
|
|
5753
|
+
targetPath: target.split(path19.sep).join("/"),
|
|
5754
|
+
content: fs20.readFileSync(full, "utf-8")
|
|
5583
5755
|
});
|
|
5584
5756
|
}
|
|
5585
5757
|
}
|
|
@@ -5646,9 +5818,9 @@ function renderRecipe(recipe, opts = {}) {
|
|
|
5646
5818
|
|
|
5647
5819
|
// src/cli/skillsInstaller.ts
|
|
5648
5820
|
import * as crypto3 from "crypto";
|
|
5649
|
-
import * as
|
|
5821
|
+
import * as fs21 from "fs";
|
|
5650
5822
|
import * as os2 from "os";
|
|
5651
|
-
import * as
|
|
5823
|
+
import * as path20 from "path";
|
|
5652
5824
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
5653
5825
|
var SUPPORTED_TARGETS = ["claude-code", "cursor"];
|
|
5654
5826
|
var SUPPORTED_SCOPES = ["user", "project"];
|
|
@@ -5695,14 +5867,14 @@ var HIDDEN_SKILL_NAMES = /* @__PURE__ */ new Set([
|
|
|
5695
5867
|
]);
|
|
5696
5868
|
function isDir3(p) {
|
|
5697
5869
|
try {
|
|
5698
|
-
return
|
|
5870
|
+
return fs21.statSync(p).isDirectory();
|
|
5699
5871
|
} catch {
|
|
5700
5872
|
return false;
|
|
5701
5873
|
}
|
|
5702
5874
|
}
|
|
5703
|
-
function
|
|
5875
|
+
function isFile7(p) {
|
|
5704
5876
|
try {
|
|
5705
|
-
return
|
|
5877
|
+
return fs21.statSync(p).isFile();
|
|
5706
5878
|
} catch {
|
|
5707
5879
|
return false;
|
|
5708
5880
|
}
|
|
@@ -5712,15 +5884,15 @@ function sha256(text2) {
|
|
|
5712
5884
|
}
|
|
5713
5885
|
function resolveSkillsSource() {
|
|
5714
5886
|
const pkgRoot = packageRoot2();
|
|
5715
|
-
return pkgRoot !== null ?
|
|
5887
|
+
return pkgRoot !== null ? path20.join(pkgRoot, "skills") : path20.join(path20.dirname(fileURLToPath4(import.meta.url)), "skills");
|
|
5716
5888
|
}
|
|
5717
5889
|
function packageRoot2() {
|
|
5718
|
-
let dir =
|
|
5890
|
+
let dir = path20.dirname(fileURLToPath4(import.meta.url));
|
|
5719
5891
|
for (; ; ) {
|
|
5720
|
-
if (
|
|
5892
|
+
if (fs21.existsSync(path20.join(dir, "package.json"))) {
|
|
5721
5893
|
return dir;
|
|
5722
5894
|
}
|
|
5723
|
-
const parent =
|
|
5895
|
+
const parent = path20.dirname(dir);
|
|
5724
5896
|
if (parent === dir) {
|
|
5725
5897
|
return null;
|
|
5726
5898
|
}
|
|
@@ -5732,18 +5904,18 @@ function listSourceSkills(source) {
|
|
|
5732
5904
|
if (!isDir3(source)) {
|
|
5733
5905
|
return [];
|
|
5734
5906
|
}
|
|
5735
|
-
return
|
|
5736
|
-
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) &&
|
|
5737
|
-
).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));
|
|
5738
5910
|
}
|
|
5739
5911
|
function listSourceReferences(source) {
|
|
5740
|
-
const refs =
|
|
5912
|
+
const refs = path20.join(source, "references");
|
|
5741
5913
|
if (!isDir3(refs)) {
|
|
5742
5914
|
return [];
|
|
5743
5915
|
}
|
|
5744
|
-
return
|
|
5745
|
-
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) &&
|
|
5746
|
-
).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));
|
|
5747
5919
|
}
|
|
5748
5920
|
function stem(fileName) {
|
|
5749
5921
|
return fileName.replace(/\.[^.]+$/, "");
|
|
@@ -5751,15 +5923,15 @@ function stem(fileName) {
|
|
|
5751
5923
|
function whichSync(name) {
|
|
5752
5924
|
const pathEnv = process.env.PATH ?? "";
|
|
5753
5925
|
const exts = process.platform === "win32" ? ["", ".cmd", ".exe", ".bat"] : [""];
|
|
5754
|
-
for (const dir of pathEnv.split(
|
|
5926
|
+
for (const dir of pathEnv.split(path20.delimiter)) {
|
|
5755
5927
|
if (!dir) {
|
|
5756
5928
|
continue;
|
|
5757
5929
|
}
|
|
5758
5930
|
for (const ext of exts) {
|
|
5759
|
-
const candidate =
|
|
5931
|
+
const candidate = path20.join(dir, name + ext);
|
|
5760
5932
|
try {
|
|
5761
|
-
|
|
5762
|
-
if (
|
|
5933
|
+
fs21.accessSync(candidate, fs21.constants.X_OK);
|
|
5934
|
+
if (fs21.statSync(candidate).isFile()) {
|
|
5763
5935
|
return candidate;
|
|
5764
5936
|
}
|
|
5765
5937
|
} catch {
|
|
@@ -5770,14 +5942,14 @@ function whichSync(name) {
|
|
|
5770
5942
|
}
|
|
5771
5943
|
function claudeCodeInstalled(opts = {}) {
|
|
5772
5944
|
const home = opts.home ?? os2.homedir();
|
|
5773
|
-
if (isDir3(
|
|
5945
|
+
if (isDir3(path20.join(home, ".claude"))) {
|
|
5774
5946
|
return true;
|
|
5775
5947
|
}
|
|
5776
5948
|
return (opts.which ?? whichSync)("claude") !== null;
|
|
5777
5949
|
}
|
|
5778
5950
|
function cursorInstalled(opts = {}) {
|
|
5779
5951
|
const home = opts.home ?? os2.homedir();
|
|
5780
|
-
if (isDir3(
|
|
5952
|
+
if (isDir3(path20.join(home, ".cursor"))) {
|
|
5781
5953
|
return true;
|
|
5782
5954
|
}
|
|
5783
5955
|
return (opts.which ?? whichSync)("cursor") !== null;
|
|
@@ -5800,9 +5972,9 @@ function anySkillsInstalled(opts = {}) {
|
|
|
5800
5972
|
for (const target of detectTargets(opts)) {
|
|
5801
5973
|
const tdir = resolveTargetDir({ target, scope: "user", home: opts.home });
|
|
5802
5974
|
for (const skill of sources) {
|
|
5803
|
-
const name = stem(
|
|
5804
|
-
const rel = target === "claude-code" ?
|
|
5805
|
-
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))) {
|
|
5806
5978
|
return true;
|
|
5807
5979
|
}
|
|
5808
5980
|
}
|
|
@@ -5827,7 +5999,7 @@ function resolveTargetDir(opts) {
|
|
|
5827
5999
|
}
|
|
5828
6000
|
const base = scope === "user" ? opts.home ?? os2.homedir() : opts.projectRoot ?? process.cwd();
|
|
5829
6001
|
const [d1, d2] = TARGET_SUBDIR[target];
|
|
5830
|
-
return
|
|
6002
|
+
return path20.join(base, d1, d2);
|
|
5831
6003
|
}
|
|
5832
6004
|
function splitFrontmatter(text2) {
|
|
5833
6005
|
const lines = text2.split("\n");
|
|
@@ -5885,16 +6057,16 @@ function iterRenderedPayloads(src, target) {
|
|
|
5885
6057
|
for (const skill of listSourceSkills(src)) {
|
|
5886
6058
|
payloads.push(
|
|
5887
6059
|
renderSkillPayload(
|
|
5888
|
-
|
|
5889
|
-
stem(
|
|
6060
|
+
fs21.readFileSync(skill, "utf-8"),
|
|
6061
|
+
stem(path20.basename(skill)),
|
|
5890
6062
|
target
|
|
5891
6063
|
)
|
|
5892
6064
|
);
|
|
5893
6065
|
}
|
|
5894
6066
|
for (const ref of listSourceReferences(src)) {
|
|
5895
6067
|
payloads.push([
|
|
5896
|
-
`${ROUTER_SKILL_NAME}/references/${
|
|
5897
|
-
|
|
6068
|
+
`${ROUTER_SKILL_NAME}/references/${path20.basename(ref)}`,
|
|
6069
|
+
fs21.readFileSync(ref, "utf-8")
|
|
5898
6070
|
]);
|
|
5899
6071
|
}
|
|
5900
6072
|
return payloads;
|
|
@@ -5906,7 +6078,7 @@ function packageVersion() {
|
|
|
5906
6078
|
return "unknown";
|
|
5907
6079
|
}
|
|
5908
6080
|
const pkg = JSON.parse(
|
|
5909
|
-
|
|
6081
|
+
fs21.readFileSync(path20.join(root, "package.json"), "utf-8")
|
|
5910
6082
|
);
|
|
5911
6083
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
5912
6084
|
} catch {
|
|
@@ -5925,11 +6097,11 @@ function contentKey(payloads) {
|
|
|
5925
6097
|
return h.digest("hex");
|
|
5926
6098
|
}
|
|
5927
6099
|
function metaPath(tdir) {
|
|
5928
|
-
return
|
|
6100
|
+
return path20.join(tdir, ROUTER_SKILL_NAME, META_FILENAME);
|
|
5929
6101
|
}
|
|
5930
6102
|
function loadMeta(tdir) {
|
|
5931
6103
|
try {
|
|
5932
|
-
const data = JSON.parse(
|
|
6104
|
+
const data = JSON.parse(fs21.readFileSync(metaPath(tdir), "utf-8"));
|
|
5933
6105
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
5934
6106
|
} catch {
|
|
5935
6107
|
return null;
|
|
@@ -5946,15 +6118,15 @@ function writeMeta(tdir, payloads) {
|
|
|
5946
6118
|
package_version: packageVersion()
|
|
5947
6119
|
};
|
|
5948
6120
|
const p = metaPath(tdir);
|
|
5949
|
-
|
|
5950
|
-
|
|
6121
|
+
fs21.mkdirSync(path20.dirname(p), { recursive: true });
|
|
6122
|
+
fs21.writeFileSync(p, `${JSON.stringify(meta, null, 2)}
|
|
5951
6123
|
`);
|
|
5952
6124
|
}
|
|
5953
6125
|
function installedMarker(tdir, target) {
|
|
5954
6126
|
if (target === "cursor") {
|
|
5955
|
-
return
|
|
6127
|
+
return path20.join(tdir, `${ROUTER_SKILL_NAME}.mdc`);
|
|
5956
6128
|
}
|
|
5957
|
-
return
|
|
6129
|
+
return path20.join(tdir, ROUTER_SKILL_NAME, "SKILL.md");
|
|
5958
6130
|
}
|
|
5959
6131
|
function syncInstalledSkills(opts = {}) {
|
|
5960
6132
|
const src = opts.source ?? SKILLS_SOURCE;
|
|
@@ -5968,7 +6140,7 @@ function syncInstalledSkills(opts = {}) {
|
|
|
5968
6140
|
home: opts.home,
|
|
5969
6141
|
projectRoot: opts.projectRoot
|
|
5970
6142
|
});
|
|
5971
|
-
if (!
|
|
6143
|
+
if (!isFile7(installedMarker(tdir, target))) {
|
|
5972
6144
|
continue;
|
|
5973
6145
|
}
|
|
5974
6146
|
if (payloads === null) {
|
|
@@ -5991,15 +6163,15 @@ function syncOneDir(tdir, payloads) {
|
|
|
5991
6163
|
const wrote = [];
|
|
5992
6164
|
const keptEdited = [];
|
|
5993
6165
|
for (const [rel, content] of payloads) {
|
|
5994
|
-
const dest =
|
|
6166
|
+
const dest = path20.join(tdir, rel);
|
|
5995
6167
|
const newHash = sha256(content);
|
|
5996
|
-
const cur =
|
|
6168
|
+
const cur = isFile7(dest) ? sha256(fs21.readFileSync(dest, "utf-8")) : null;
|
|
5997
6169
|
if (cur === newHash) {
|
|
5998
6170
|
continue;
|
|
5999
6171
|
}
|
|
6000
6172
|
if (cur === null || cur === recordedFiles[rel]) {
|
|
6001
|
-
|
|
6002
|
-
|
|
6173
|
+
fs21.mkdirSync(path20.dirname(dest), { recursive: true });
|
|
6174
|
+
fs21.writeFileSync(dest, content);
|
|
6003
6175
|
wrote.push(rel);
|
|
6004
6176
|
} else {
|
|
6005
6177
|
keptEdited.push(rel);
|
|
@@ -6010,15 +6182,15 @@ function syncOneDir(tdir, payloads) {
|
|
|
6010
6182
|
if (shipped.has(rel)) {
|
|
6011
6183
|
continue;
|
|
6012
6184
|
}
|
|
6013
|
-
const dest =
|
|
6185
|
+
const dest = path20.join(tdir, rel);
|
|
6014
6186
|
try {
|
|
6015
|
-
if (
|
|
6016
|
-
|
|
6187
|
+
if (isFile7(dest) && sha256(fs21.readFileSync(dest, "utf-8")) === recorded) {
|
|
6188
|
+
fs21.unlinkSync(dest);
|
|
6017
6189
|
wrote.push(`removed ${rel}`);
|
|
6018
|
-
let parent =
|
|
6019
|
-
while (parent !== tdir && isDir3(parent) &&
|
|
6020
|
-
|
|
6021
|
-
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);
|
|
6022
6194
|
}
|
|
6023
6195
|
}
|
|
6024
6196
|
} catch {
|
|
@@ -6048,45 +6220,45 @@ function installSkills(opts) {
|
|
|
6048
6220
|
projectRoot: opts.projectRoot,
|
|
6049
6221
|
home: opts.home
|
|
6050
6222
|
});
|
|
6051
|
-
|
|
6223
|
+
fs21.mkdirSync(tdir, { recursive: true });
|
|
6052
6224
|
const installed = [];
|
|
6053
6225
|
const skipped = [];
|
|
6054
6226
|
for (const skill of skillFiles) {
|
|
6055
|
-
const skillName = stem(
|
|
6056
|
-
const srcText =
|
|
6227
|
+
const skillName = stem(path20.basename(skill));
|
|
6228
|
+
const srcText = fs21.readFileSync(skill, "utf-8");
|
|
6057
6229
|
const [relPath, content] = renderSkillPayload(srcText, skillName, target);
|
|
6058
|
-
const dest =
|
|
6059
|
-
|
|
6060
|
-
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)) {
|
|
6061
6233
|
skipped.push(skillName);
|
|
6062
6234
|
} else {
|
|
6063
|
-
|
|
6235
|
+
fs21.writeFileSync(dest, content);
|
|
6064
6236
|
installed.push(skillName);
|
|
6065
6237
|
}
|
|
6066
6238
|
if (target === "claude-code") {
|
|
6067
|
-
const legacyFlat =
|
|
6068
|
-
if (
|
|
6069
|
-
|
|
6239
|
+
const legacyFlat = path20.join(tdir, path20.basename(skill));
|
|
6240
|
+
if (isFile7(legacyFlat)) {
|
|
6241
|
+
fs21.unlinkSync(legacyFlat);
|
|
6070
6242
|
}
|
|
6071
6243
|
}
|
|
6072
6244
|
}
|
|
6073
6245
|
for (const ref of listSourceReferences(src)) {
|
|
6074
|
-
const rel = `${ROUTER_SKILL_NAME}/references/${
|
|
6075
|
-
const dest =
|
|
6076
|
-
|
|
6077
|
-
const content =
|
|
6078
|
-
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)) {
|
|
6079
6251
|
skipped.push(rel);
|
|
6080
6252
|
} else {
|
|
6081
|
-
|
|
6253
|
+
fs21.writeFileSync(dest, content);
|
|
6082
6254
|
installed.push(rel);
|
|
6083
6255
|
}
|
|
6084
6256
|
}
|
|
6085
|
-
if (isDir3(
|
|
6257
|
+
if (isDir3(path20.join(tdir, ROUTER_SKILL_NAME))) {
|
|
6086
6258
|
writeMeta(tdir, iterRenderedPayloads(src, target));
|
|
6087
6259
|
}
|
|
6088
|
-
const legacy = target === "claude-code" ? LEGACY_SKILL_NAMES.filter((name) => isDir3(
|
|
6089
|
-
(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`))
|
|
6090
6262
|
);
|
|
6091
6263
|
return {
|
|
6092
6264
|
target,
|
|
@@ -6112,9 +6284,9 @@ function acceptChoices(option, accepted, advertised) {
|
|
|
6112
6284
|
}
|
|
6113
6285
|
|
|
6114
6286
|
// src/cli/wallet.ts
|
|
6115
|
-
import * as
|
|
6287
|
+
import * as fs23 from "fs";
|
|
6116
6288
|
import * as os3 from "os";
|
|
6117
|
-
import * as
|
|
6289
|
+
import * as path22 from "path";
|
|
6118
6290
|
import { EVMWalletProvider, SigningPolicy } from "@bnbagent/sdk";
|
|
6119
6291
|
import {
|
|
6120
6292
|
envLocalPath as envLocalPath10,
|
|
@@ -6124,14 +6296,16 @@ import {
|
|
|
6124
6296
|
import { buildPolicy, buildWallet } from "@bnbagent/studio-runtime/wallet";
|
|
6125
6297
|
|
|
6126
6298
|
// src/cli/walletSession.ts
|
|
6127
|
-
import * as
|
|
6128
|
-
import * as
|
|
6299
|
+
import * as fs22 from "fs";
|
|
6300
|
+
import * as path21 from "path";
|
|
6301
|
+
import { pathToFileURL } from "url";
|
|
6129
6302
|
import { AltanaWalletProvider } from "@bnbagent/sdk";
|
|
6130
6303
|
import { getAddress as deployedAddresses } from "@bnbagent/sdk/networks";
|
|
6131
6304
|
import {
|
|
6132
6305
|
defaultAgentPermissions,
|
|
6133
6306
|
deserializeSession,
|
|
6134
|
-
serializeSession
|
|
6307
|
+
serializeSession,
|
|
6308
|
+
setAltanaSdkImporter
|
|
6135
6309
|
} from "@bnbagent/sdk/wallets";
|
|
6136
6310
|
import { auditedOp as auditedOp2 } from "@bnbagent/studio-runtime/audit";
|
|
6137
6311
|
import { loadStudioToml as loadStudioToml9 } from "@bnbagent/studio-runtime/config";
|
|
@@ -6139,7 +6313,8 @@ import { getNetwork as getNetwork5, toRaw as toRaw2 } from "@bnbagent/studio-run
|
|
|
6139
6313
|
import { writePrivate } from "@bnbagent/studio-runtime/secretWrite";
|
|
6140
6314
|
import {
|
|
6141
6315
|
ALTANA_NETWORK_BY_STUDIO,
|
|
6142
|
-
PASSWORD_ENV
|
|
6316
|
+
PASSWORD_ENV,
|
|
6317
|
+
resolveProjectAltanaSdkEntry as resolveProjectAltanaSdkEntry2
|
|
6143
6318
|
} from "@bnbagent/studio-runtime/wallet";
|
|
6144
6319
|
var defaultAdminFactory = (opts) => AltanaWalletProvider.adminFromKeystore(opts);
|
|
6145
6320
|
var adminFactory = defaultAdminFactory;
|
|
@@ -6148,13 +6323,17 @@ function tableOf7(value) {
|
|
|
6148
6323
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
6149
6324
|
}
|
|
6150
6325
|
function loadContext(projectRoot) {
|
|
6151
|
-
const cfg = loadStudioToml9(
|
|
6326
|
+
const cfg = loadStudioToml9(path21.join(projectRoot, "studio.toml"));
|
|
6152
6327
|
const walletCfg = tableOf7(cfg.wallet);
|
|
6153
6328
|
if (String(walletCfg.kind ?? "evm-local") !== "altana") {
|
|
6154
6329
|
throw new Error(
|
|
6155
6330
|
`wallet session commands require [wallet].kind='altana' (got ${JSON.stringify(walletCfg.kind ?? "evm-local")}).`
|
|
6156
6331
|
);
|
|
6157
6332
|
}
|
|
6333
|
+
const sdkEntry = resolveProjectAltanaSdkEntry2(projectRoot);
|
|
6334
|
+
setAltanaSdkImporter(
|
|
6335
|
+
sdkEntry === null ? null : () => import(pathToFileURL(sdkEntry).href)
|
|
6336
|
+
);
|
|
6158
6337
|
const networkName = String(tableOf7(cfg.network).default ?? "bsc-testnet");
|
|
6159
6338
|
const altanaNetwork = ALTANA_NETWORK_BY_STUDIO[networkName];
|
|
6160
6339
|
if (altanaNetwork === void 0) {
|
|
@@ -6170,7 +6349,7 @@ function loadContext(projectRoot) {
|
|
|
6170
6349
|
}
|
|
6171
6350
|
const resolvePath = (value, fallback) => {
|
|
6172
6351
|
const configured = String(value ?? fallback);
|
|
6173
|
-
return
|
|
6352
|
+
return path21.isAbsolute(configured) ? configured : path21.join(projectRoot, configured);
|
|
6174
6353
|
};
|
|
6175
6354
|
return {
|
|
6176
6355
|
projectRoot,
|
|
@@ -6234,7 +6413,7 @@ function parseSessionEnvelope(serialized) {
|
|
|
6234
6413
|
function readSession(ctx) {
|
|
6235
6414
|
let serialized;
|
|
6236
6415
|
try {
|
|
6237
|
-
serialized =
|
|
6416
|
+
serialized = fs22.readFileSync(ctx.sessionFile, "utf8");
|
|
6238
6417
|
} catch {
|
|
6239
6418
|
throw new Error(
|
|
6240
6419
|
`no Altana session file at ${ctx.sessionFile} \u2014 run \`bag wallet session grant\`.`
|
|
@@ -6243,8 +6422,8 @@ function readSession(ctx) {
|
|
|
6243
6422
|
return { serialized, envelope: parseSessionEnvelope(serialized) };
|
|
6244
6423
|
}
|
|
6245
6424
|
function writeSession(ctx, session) {
|
|
6246
|
-
|
|
6247
|
-
|
|
6425
|
+
fs22.mkdirSync(path21.dirname(ctx.sessionFile), { recursive: true, mode: 448 });
|
|
6426
|
+
fs22.chmodSync(path21.dirname(ctx.sessionFile), 448);
|
|
6248
6427
|
writePrivate(ctx.sessionFile, serializeSession(session));
|
|
6249
6428
|
}
|
|
6250
6429
|
function sessionKeyFingerprint(publicKey) {
|
|
@@ -6355,7 +6534,7 @@ async function cmdSessionGrant(opts) {
|
|
|
6355
6534
|
"--budget-u"
|
|
6356
6535
|
);
|
|
6357
6536
|
let existing = null;
|
|
6358
|
-
if (
|
|
6537
|
+
if (fs22.existsSync(ctx.sessionFile)) {
|
|
6359
6538
|
existing = readSession(ctx).envelope;
|
|
6360
6539
|
if (!opts.force) {
|
|
6361
6540
|
throw new Error(
|
|
@@ -6473,7 +6652,7 @@ async function cmdSessionRevoke(opts) {
|
|
|
6473
6652
|
await admin.revokeSession(envelope.publicKey);
|
|
6474
6653
|
}
|
|
6475
6654
|
);
|
|
6476
|
-
|
|
6655
|
+
fs22.unlinkSync(ctx.sessionFile);
|
|
6477
6656
|
printErr(`\u2713 Altana session revoked and removed: ${ctx.sessionFile}`);
|
|
6478
6657
|
return 0;
|
|
6479
6658
|
}
|
|
@@ -6597,8 +6776,8 @@ var ProjectRootNotFound = class extends Error {
|
|
|
6597
6776
|
};
|
|
6598
6777
|
function resolveWalletProjectRoot(argRoot) {
|
|
6599
6778
|
if (argRoot != null) {
|
|
6600
|
-
const root2 =
|
|
6601
|
-
if (!
|
|
6779
|
+
const root2 = path22.resolve(argRoot);
|
|
6780
|
+
if (!isFile8(path22.join(root2, "studio.toml"))) {
|
|
6602
6781
|
throw new ProjectRootNotFound(
|
|
6603
6782
|
`No studio.toml found under --project-root ${root2}`
|
|
6604
6783
|
);
|
|
@@ -6613,15 +6792,15 @@ function resolveWalletProjectRoot(argRoot) {
|
|
|
6613
6792
|
}
|
|
6614
6793
|
return root;
|
|
6615
6794
|
}
|
|
6616
|
-
function
|
|
6795
|
+
function isFile8(p) {
|
|
6617
6796
|
try {
|
|
6618
|
-
return
|
|
6797
|
+
return fs23.statSync(p).isFile();
|
|
6619
6798
|
} catch {
|
|
6620
6799
|
return false;
|
|
6621
6800
|
}
|
|
6622
6801
|
}
|
|
6623
6802
|
function loadWalletCfg(projectRoot) {
|
|
6624
|
-
const data = loadStudioToml10(
|
|
6803
|
+
const data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
6625
6804
|
const wallet = data.wallet;
|
|
6626
6805
|
return wallet !== null && typeof wallet === "object" && !Array.isArray(wallet) ? wallet : {};
|
|
6627
6806
|
}
|
|
@@ -6631,7 +6810,7 @@ function walletKind(walletCfg) {
|
|
|
6631
6810
|
function projectNetwork(projectRoot) {
|
|
6632
6811
|
let data;
|
|
6633
6812
|
try {
|
|
6634
|
-
data = loadStudioToml10(
|
|
6813
|
+
data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
6635
6814
|
} catch {
|
|
6636
6815
|
return "bsc-testnet";
|
|
6637
6816
|
}
|
|
@@ -6670,12 +6849,12 @@ function requireDurablePassword(projectRoot) {
|
|
|
6670
6849
|
return password;
|
|
6671
6850
|
}
|
|
6672
6851
|
function persistAddress(projectRoot, address) {
|
|
6673
|
-
const tomlPath =
|
|
6674
|
-
if (!
|
|
6852
|
+
const tomlPath = path22.join(projectRoot, "studio.toml");
|
|
6853
|
+
if (!isFile8(tomlPath)) {
|
|
6675
6854
|
return;
|
|
6676
6855
|
}
|
|
6677
|
-
const text2 =
|
|
6678
|
-
|
|
6856
|
+
const text2 = fs23.readFileSync(tomlPath, "utf-8");
|
|
6857
|
+
fs23.writeFileSync(
|
|
6679
6858
|
tomlPath,
|
|
6680
6859
|
updateSection(text2, "wallet", { address }),
|
|
6681
6860
|
"utf-8"
|
|
@@ -6691,7 +6870,7 @@ function resolveKeystoreDir2(projectRoot, cliOverride, walletCfg) {
|
|
|
6691
6870
|
} else {
|
|
6692
6871
|
d = ".studio/wallets";
|
|
6693
6872
|
}
|
|
6694
|
-
return
|
|
6873
|
+
return path22.isAbsolute(d) ? d : path22.join(projectRoot, d);
|
|
6695
6874
|
}
|
|
6696
6875
|
async function resolvePrivateKeyArg(raw) {
|
|
6697
6876
|
if (raw === void 0 || raw === false) {
|
|
@@ -6806,7 +6985,7 @@ async function cmdNew(opts) {
|
|
|
6806
6985
|
projectRoot = process.cwd();
|
|
6807
6986
|
}
|
|
6808
6987
|
let walletCfg = {};
|
|
6809
|
-
if (
|
|
6988
|
+
if (isFile8(path22.join(projectRoot, "studio.toml"))) {
|
|
6810
6989
|
walletCfg = loadWalletCfg(projectRoot);
|
|
6811
6990
|
}
|
|
6812
6991
|
const kind = walletKind(walletCfg);
|
|
@@ -6820,7 +6999,7 @@ async function cmdNew(opts) {
|
|
|
6820
6999
|
opts.keystoreDir,
|
|
6821
7000
|
walletCfg
|
|
6822
7001
|
);
|
|
6823
|
-
|
|
7002
|
+
fs23.mkdirSync(keystoreDir, { recursive: true });
|
|
6824
7003
|
const provider = new EVMWalletProvider({
|
|
6825
7004
|
password,
|
|
6826
7005
|
...privateKey !== null ? { privateKey } : {},
|
|
@@ -6830,7 +7009,7 @@ async function cmdNew(opts) {
|
|
|
6830
7009
|
persistAddress(projectRoot, provider.address);
|
|
6831
7010
|
if (kind === "altana") {
|
|
6832
7011
|
printErr(
|
|
6833
|
-
"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."
|
|
6834
7013
|
);
|
|
6835
7014
|
}
|
|
6836
7015
|
return 0;
|
|
@@ -6844,11 +7023,11 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6844
7023
|
return 1;
|
|
6845
7024
|
}
|
|
6846
7025
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
6847
|
-
if (!
|
|
7026
|
+
if (!isFile8(walletFile)) {
|
|
6848
7027
|
let createCmd = "twak wallet create --password <your-password> --no-keychain";
|
|
6849
7028
|
let setupCmd = "twak setup";
|
|
6850
7029
|
if (walletCfg.twak_home) {
|
|
6851
|
-
const home =
|
|
7030
|
+
const home = path22.dirname(path22.dirname(walletFile));
|
|
6852
7031
|
createCmd = `HOME=${home} ${createCmd}`;
|
|
6853
7032
|
setupCmd = `HOME=${home} ${setupCmd}`;
|
|
6854
7033
|
}
|
|
@@ -6874,23 +7053,23 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6874
7053
|
return 0;
|
|
6875
7054
|
}
|
|
6876
7055
|
function ensureTwakCredentials(walletFile, homeDir) {
|
|
6877
|
-
const twakDir =
|
|
6878
|
-
const target =
|
|
6879
|
-
if (
|
|
7056
|
+
const twakDir = path22.dirname(walletFile);
|
|
7057
|
+
const target = path22.join(twakDir, "credentials.json");
|
|
7058
|
+
if (isFile8(target)) {
|
|
6880
7059
|
return true;
|
|
6881
7060
|
}
|
|
6882
|
-
const machine =
|
|
6883
|
-
if (
|
|
7061
|
+
const machine = path22.join(os3.homedir(), ".twak", "credentials.json");
|
|
7062
|
+
if (path22.resolve(machine) === path22.resolve(target) || !isFile8(machine)) {
|
|
6884
7063
|
printErr(
|
|
6885
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.`
|
|
6886
7065
|
);
|
|
6887
7066
|
return false;
|
|
6888
7067
|
}
|
|
6889
|
-
|
|
6890
|
-
|
|
7068
|
+
fs23.mkdirSync(twakDir, { recursive: true });
|
|
7069
|
+
fs23.writeFileSync(target, fs23.readFileSync(machine, "utf-8"), { mode: 384 });
|
|
6891
7070
|
try {
|
|
6892
|
-
|
|
6893
|
-
|
|
7071
|
+
fs23.chmodSync(twakDir, 448);
|
|
7072
|
+
fs23.chmodSync(target, 384);
|
|
6894
7073
|
} catch {
|
|
6895
7074
|
}
|
|
6896
7075
|
printErr(`note: copied NaaS credentials from ${machine} into ${twakDir}.`);
|
|
@@ -6902,10 +7081,10 @@ async function resolveTwakInitPassword(opts) {
|
|
|
6902
7081
|
throw new CliExit(2);
|
|
6903
7082
|
}
|
|
6904
7083
|
if (opts.passwordFile) {
|
|
6905
|
-
const file =
|
|
7084
|
+
const file = path22.resolve(opts.passwordFile);
|
|
6906
7085
|
let mode;
|
|
6907
7086
|
try {
|
|
6908
|
-
mode =
|
|
7087
|
+
mode = fs23.statSync(file).mode;
|
|
6909
7088
|
} catch {
|
|
6910
7089
|
printErr(`error: cannot read --password-file ${file}.`);
|
|
6911
7090
|
throw new CliExit(2);
|
|
@@ -6916,7 +7095,7 @@ async function resolveTwakInitPassword(opts) {
|
|
|
6916
7095
|
);
|
|
6917
7096
|
throw new CliExit(2);
|
|
6918
7097
|
}
|
|
6919
|
-
const password = (
|
|
7098
|
+
const password = (fs23.readFileSync(file, "utf-8").split(/\r?\n/)[0] ?? "").trim();
|
|
6920
7099
|
if (!password) {
|
|
6921
7100
|
printErr(`error: --password-file ${file} is empty.`);
|
|
6922
7101
|
throw new CliExit(2);
|
|
@@ -6969,15 +7148,15 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6969
7148
|
return 1;
|
|
6970
7149
|
}
|
|
6971
7150
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
6972
|
-
if (
|
|
7151
|
+
if (isFile8(walletFile)) {
|
|
6973
7152
|
printErr(
|
|
6974
7153
|
`error: a twak wallet already exists at ${walletFile} \u2014 nothing to create. Run \`bag wallet new\` to adopt its address into studio.toml.`
|
|
6975
7154
|
);
|
|
6976
7155
|
return 1;
|
|
6977
7156
|
}
|
|
6978
7157
|
const password = await resolveTwakInitPassword(opts);
|
|
6979
|
-
const homeDir =
|
|
6980
|
-
|
|
7158
|
+
const homeDir = path22.dirname(path22.dirname(walletFile));
|
|
7159
|
+
fs23.mkdirSync(homeDir, { recursive: true });
|
|
6981
7160
|
if (!ensureTwakCredentials(walletFile, homeDir)) {
|
|
6982
7161
|
return 1;
|
|
6983
7162
|
}
|
|
@@ -6999,7 +7178,7 @@ ${password}
|
|
|
6999
7178
|
timeoutMs: 12e4
|
|
7000
7179
|
}
|
|
7001
7180
|
);
|
|
7002
|
-
if (create.code !== 0 || !
|
|
7181
|
+
if (create.code !== 0 || !isFile8(walletFile)) {
|
|
7003
7182
|
const detail = `${create.stderr}
|
|
7004
7183
|
${create.stdout}`.trim();
|
|
7005
7184
|
printErr(
|
|
@@ -7014,14 +7193,14 @@ ${detail}` : `error: \`twak wallet create --no-keychain\` did not produce ${wall
|
|
|
7014
7193
|
return 1;
|
|
7015
7194
|
}
|
|
7016
7195
|
try {
|
|
7017
|
-
|
|
7196
|
+
fs23.chmodSync(walletFile, 384);
|
|
7018
7197
|
} catch {
|
|
7019
7198
|
}
|
|
7020
7199
|
if (!process.env.TWAK_WALLET_PASSWORD) {
|
|
7021
7200
|
process.env.TWAK_WALLET_PASSWORD = password;
|
|
7022
7201
|
}
|
|
7023
7202
|
printErr(
|
|
7024
|
-
`\u2713 twak wallet created under ${
|
|
7203
|
+
`\u2713 twak wallet created under ${path22.dirname(walletFile)} (no keychain)`
|
|
7025
7204
|
);
|
|
7026
7205
|
printErr(
|
|
7027
7206
|
"next: persist TWAK_WALLET_PASSWORD in .studio/.env.local so deploys and non-interactive signing can unlock it."
|
|
@@ -7058,7 +7237,7 @@ function cmdShow5(projectRootArg) {
|
|
|
7058
7237
|
...walletCfg.address ? { address: String(walletCfg.address) } : {}
|
|
7059
7238
|
});
|
|
7060
7239
|
const address = provider.address;
|
|
7061
|
-
const keystorePath =
|
|
7240
|
+
const keystorePath = path22.join(keystoreDir, `${address}.json`);
|
|
7062
7241
|
printOut(`address: ${address}`);
|
|
7063
7242
|
printOut(`source: ${kind}`);
|
|
7064
7243
|
printOut(`keystore_dir: ${keystoreDir}`);
|
|
@@ -7067,14 +7246,14 @@ function cmdShow5(projectRootArg) {
|
|
|
7067
7246
|
const configured = String(
|
|
7068
7247
|
walletCfg.session_file ?? ".studio/wallets/altana-session.json"
|
|
7069
7248
|
);
|
|
7070
|
-
const sessionFile =
|
|
7249
|
+
const sessionFile = path22.isAbsolute(configured) ? configured : path22.join(projectRoot, configured);
|
|
7071
7250
|
printOut(`session_file: ${sessionFile}`);
|
|
7072
|
-
if (!
|
|
7251
|
+
if (!isFile8(sessionFile)) {
|
|
7073
7252
|
printOut("session_status: missing (run `bag wallet session grant`)");
|
|
7074
7253
|
} else {
|
|
7075
7254
|
let envelope;
|
|
7076
7255
|
try {
|
|
7077
|
-
envelope = JSON.parse(
|
|
7256
|
+
envelope = JSON.parse(fs23.readFileSync(sessionFile, "utf8"));
|
|
7078
7257
|
} catch {
|
|
7079
7258
|
throw new Error(`invalid Altana session JSON at ${sessionFile}`);
|
|
7080
7259
|
}
|
|
@@ -7100,7 +7279,7 @@ function cmdList2(projectRootArg) {
|
|
|
7100
7279
|
const keystoreDir = resolveKeystoreDir2(projectRoot, null, walletCfg);
|
|
7101
7280
|
let entries;
|
|
7102
7281
|
try {
|
|
7103
|
-
entries =
|
|
7282
|
+
entries = fs23.readdirSync(keystoreDir).sort();
|
|
7104
7283
|
} catch {
|
|
7105
7284
|
return 0;
|
|
7106
7285
|
}
|
|
@@ -7112,7 +7291,7 @@ function cmdList2(projectRootArg) {
|
|
|
7112
7291
|
let data;
|
|
7113
7292
|
try {
|
|
7114
7293
|
data = JSON.parse(
|
|
7115
|
-
|
|
7294
|
+
fs23.readFileSync(path22.join(keystoreDir, child), "utf-8")
|
|
7116
7295
|
);
|
|
7117
7296
|
} catch {
|
|
7118
7297
|
continue;
|
|
@@ -7163,7 +7342,7 @@ async function cmdSign(msg, projectRootArg) {
|
|
|
7163
7342
|
}
|
|
7164
7343
|
async function cmdBalance(opts) {
|
|
7165
7344
|
const projectRoot = resolveWalletProjectRoot(opts.projectRoot);
|
|
7166
|
-
const data = loadStudioToml10(
|
|
7345
|
+
const data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
7167
7346
|
const walletCfg = data.wallet !== null && typeof data.wallet === "object" ? data.wallet : {};
|
|
7168
7347
|
let address;
|
|
7169
7348
|
const kind = walletKind(walletCfg);
|
|
@@ -7290,10 +7469,10 @@ var PROVIDER_KEY_ENV = {
|
|
|
7290
7469
|
"pieverse-llm": "PIEVERSE_LLM_API_KEY"
|
|
7291
7470
|
};
|
|
7292
7471
|
function renderAgentcoreProject(target, name) {
|
|
7293
|
-
const acDir =
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7472
|
+
const acDir = path23.join(target, "agentcore");
|
|
7473
|
+
fs24.mkdirSync(acDir, { recursive: true });
|
|
7474
|
+
fs24.writeFileSync(
|
|
7475
|
+
path23.join(acDir, "agentcore.json"),
|
|
7297
7476
|
`${JSON.stringify(
|
|
7298
7477
|
{
|
|
7299
7478
|
$schema: "https://schema.agentcore.aws.dev/v1/agentcore.json",
|
|
@@ -7307,7 +7486,7 @@ function renderAgentcoreProject(target, name) {
|
|
|
7307
7486
|
)}
|
|
7308
7487
|
`
|
|
7309
7488
|
);
|
|
7310
|
-
|
|
7489
|
+
fs24.writeFileSync(path23.join(acDir, "aws-targets.json"), "[]\n");
|
|
7311
7490
|
}
|
|
7312
7491
|
var AGENTS_MD_MARKER = "# bnbagent-studio additions (ERC-8183 seller)";
|
|
7313
7492
|
var AGENTS_MD_STUDIO_SECTION = `
|
|
@@ -7351,30 +7530,30 @@ every intent to the right playbook via its references.
|
|
|
7351
7530
|
and state the tradeoff.
|
|
7352
7531
|
`;
|
|
7353
7532
|
function appendAgentsMdStudioSection(target) {
|
|
7354
|
-
const agentsMd =
|
|
7533
|
+
const agentsMd = path23.join(target, "AGENTS.md");
|
|
7355
7534
|
let existing = "";
|
|
7356
7535
|
try {
|
|
7357
|
-
existing =
|
|
7536
|
+
existing = fs24.readFileSync(agentsMd, "utf-8");
|
|
7358
7537
|
} catch {
|
|
7359
7538
|
existing = "";
|
|
7360
7539
|
}
|
|
7361
7540
|
if (existing.includes(AGENTS_MD_MARKER)) {
|
|
7362
7541
|
return;
|
|
7363
7542
|
}
|
|
7364
|
-
|
|
7543
|
+
fs24.writeFileSync(
|
|
7365
7544
|
agentsMd,
|
|
7366
7545
|
`${existing.replace(/\n+$/, "")}
|
|
7367
7546
|
${AGENTS_MD_STUDIO_SECTION}`
|
|
7368
7547
|
);
|
|
7369
7548
|
}
|
|
7370
7549
|
function seedAwsTargets(target) {
|
|
7371
|
-
const p =
|
|
7372
|
-
if (!
|
|
7550
|
+
const p = path23.join(target, "agentcore", "aws-targets.json");
|
|
7551
|
+
if (!isFile9(p)) {
|
|
7373
7552
|
return;
|
|
7374
7553
|
}
|
|
7375
7554
|
let data;
|
|
7376
7555
|
try {
|
|
7377
|
-
data = JSON.parse(
|
|
7556
|
+
data = JSON.parse(fs24.readFileSync(p, "utf-8"));
|
|
7378
7557
|
} catch {
|
|
7379
7558
|
return;
|
|
7380
7559
|
}
|
|
@@ -7385,7 +7564,7 @@ function seedAwsTargets(target) {
|
|
|
7385
7564
|
{ name: "default", account: AWS_ACCOUNT_PLACEHOLDER, region: "us-east-1" }
|
|
7386
7565
|
];
|
|
7387
7566
|
try {
|
|
7388
|
-
|
|
7567
|
+
fs24.writeFileSync(p, `${JSON.stringify(skeleton, null, 2)}
|
|
7389
7568
|
`);
|
|
7390
7569
|
} catch {
|
|
7391
7570
|
return;
|
|
@@ -7408,13 +7587,13 @@ function registerAgentcoreRuntime(target, name, opts = {}) {
|
|
|
7408
7587
|
const protocol = nativeProtocolOf(faces);
|
|
7409
7588
|
const stem2 = entryStemOf(faces);
|
|
7410
7589
|
const isContainer = opts.packaging === "container" || walletKind2 === "twak";
|
|
7411
|
-
const cfgPath =
|
|
7412
|
-
if (!
|
|
7590
|
+
const cfgPath = path23.join(target, "agentcore", "agentcore.json");
|
|
7591
|
+
if (!isFile9(cfgPath)) {
|
|
7413
7592
|
return;
|
|
7414
7593
|
}
|
|
7415
7594
|
let cfg;
|
|
7416
7595
|
try {
|
|
7417
|
-
const parsed = JSON.parse(
|
|
7596
|
+
const parsed = JSON.parse(fs24.readFileSync(cfgPath, "utf-8"));
|
|
7418
7597
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7419
7598
|
return;
|
|
7420
7599
|
}
|
|
@@ -7453,7 +7632,7 @@ function registerAgentcoreRuntime(target, name, opts = {}) {
|
|
|
7453
7632
|
runtimes.push(runtime);
|
|
7454
7633
|
cfg.runtimes = runtimes;
|
|
7455
7634
|
try {
|
|
7456
|
-
|
|
7635
|
+
fs24.writeFileSync(cfgPath, `${JSON.stringify(cfg, null, 2)}
|
|
7457
7636
|
`);
|
|
7458
7637
|
} catch {
|
|
7459
7638
|
return;
|
|
@@ -7590,12 +7769,12 @@ function registerInit(program) {
|
|
|
7590
7769
|
);
|
|
7591
7770
|
}
|
|
7592
7771
|
function enclosingProjectRoot(start) {
|
|
7593
|
-
let current =
|
|
7772
|
+
let current = path23.resolve(start);
|
|
7594
7773
|
for (; ; ) {
|
|
7595
|
-
if (
|
|
7774
|
+
if (isFile9(path23.join(current, APP_DIR, AGENT_PKG, "studio.toml"))) {
|
|
7596
7775
|
return current;
|
|
7597
7776
|
}
|
|
7598
|
-
const parent =
|
|
7777
|
+
const parent = path23.dirname(current);
|
|
7599
7778
|
if (parent === current) {
|
|
7600
7779
|
return null;
|
|
7601
7780
|
}
|
|
@@ -7603,8 +7782,8 @@ function enclosingProjectRoot(start) {
|
|
|
7603
7782
|
}
|
|
7604
7783
|
}
|
|
7605
7784
|
async function cmdInit(nameArg, opts) {
|
|
7606
|
-
const target =
|
|
7607
|
-
let projectName2 =
|
|
7785
|
+
const target = path23.resolve(process.cwd(), nameArg);
|
|
7786
|
+
let projectName2 = path23.basename(target);
|
|
7608
7787
|
if (!projectName2) {
|
|
7609
7788
|
printErr(
|
|
7610
7789
|
`error: cannot derive a project name from '${nameArg}' (path has no basename).`
|
|
@@ -7689,15 +7868,15 @@ async function cmdInit(nameArg, opts) {
|
|
|
7689
7868
|
return 2;
|
|
7690
7869
|
}
|
|
7691
7870
|
}
|
|
7692
|
-
const enclosing = enclosingProjectRoot(
|
|
7871
|
+
const enclosing = enclosingProjectRoot(path23.dirname(target));
|
|
7693
7872
|
if (enclosing !== null) {
|
|
7694
7873
|
printErr(
|
|
7695
|
-
`error: ${
|
|
7696
|
-
\`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.`
|
|
7697
7876
|
);
|
|
7698
7877
|
return 2;
|
|
7699
7878
|
}
|
|
7700
|
-
if (
|
|
7879
|
+
if (fs24.existsSync(target) && !opts.force) {
|
|
7701
7880
|
printErr(`error: ${target} already exists. Use --force to overwrite.`);
|
|
7702
7881
|
return 2;
|
|
7703
7882
|
}
|
|
@@ -7716,20 +7895,14 @@ async function cmdInit(nameArg, opts) {
|
|
|
7716
7895
|
destination = "self";
|
|
7717
7896
|
runtime = "agentcore";
|
|
7718
7897
|
}
|
|
7719
|
-
if (destination === "platform" && walletKind2 === "altana") {
|
|
7720
|
-
printErr(
|
|
7721
|
-
"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."
|
|
7722
|
-
);
|
|
7723
|
-
return 2;
|
|
7724
|
-
}
|
|
7725
7898
|
if (destination === "self" && runtime === "azure-foundry" && (!hasA2aFace(faces) || hasMcpFace(faces))) {
|
|
7726
7899
|
printErr(
|
|
7727
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."
|
|
7728
7901
|
);
|
|
7729
7902
|
return 2;
|
|
7730
7903
|
}
|
|
7731
|
-
if (
|
|
7732
|
-
|
|
7904
|
+
if (fs24.existsSync(target)) {
|
|
7905
|
+
fs24.rmSync(target, { recursive: true, force: true });
|
|
7733
7906
|
}
|
|
7734
7907
|
if (destination === "platform") {
|
|
7735
7908
|
printCampaignIntro();
|
|
@@ -7774,7 +7947,7 @@ async function cmdInit(nameArg, opts) {
|
|
|
7774
7947
|
}
|
|
7775
7948
|
}
|
|
7776
7949
|
try {
|
|
7777
|
-
|
|
7950
|
+
fs24.mkdirSync(target, { recursive: true });
|
|
7778
7951
|
if (runtime === "agentcore") {
|
|
7779
7952
|
renderAgentcoreProject(target, projectName2);
|
|
7780
7953
|
}
|
|
@@ -7790,7 +7963,7 @@ async function cmdInit(nameArg, opts) {
|
|
|
7790
7963
|
printErr(
|
|
7791
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.`
|
|
7792
7965
|
);
|
|
7793
|
-
|
|
7966
|
+
fs24.rmSync(target, { recursive: true, force: true });
|
|
7794
7967
|
return 2;
|
|
7795
7968
|
}
|
|
7796
7969
|
const ides = resolveEmitIdes(opts.ide);
|
|
@@ -7833,9 +8006,9 @@ async function cmdInit(nameArg, opts) {
|
|
|
7833
8006
|
});
|
|
7834
8007
|
seedAwsTargets(target);
|
|
7835
8008
|
}
|
|
7836
|
-
const agentDir =
|
|
7837
|
-
|
|
7838
|
-
|
|
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"), "");
|
|
7839
8012
|
const skipInstall = opts.install === false || opts.venv === false;
|
|
7840
8013
|
let provisioned = false;
|
|
7841
8014
|
let installFailed = false;
|
|
@@ -7964,64 +8137,64 @@ function derivePackaging(walletKind2, destination, platformArtifact2 = "zip", ru
|
|
|
7964
8137
|
}
|
|
7965
8138
|
function scaffold(target, name, o) {
|
|
7966
8139
|
const packageManagerVersion = pnpmVersion();
|
|
7967
|
-
|
|
7968
|
-
|
|
8140
|
+
fs24.writeFileSync(
|
|
8141
|
+
path23.join(target, "package.json"),
|
|
7969
8142
|
renderWorkspacePackageJson(name, packageManagerVersion)
|
|
7970
8143
|
);
|
|
7971
|
-
|
|
7972
|
-
|
|
8144
|
+
fs24.writeFileSync(
|
|
8145
|
+
path23.join(target, "pnpm-workspace.yaml"),
|
|
7973
8146
|
renderPnpmWorkspaceYaml()
|
|
7974
8147
|
);
|
|
7975
|
-
|
|
7976
|
-
if (!
|
|
7977
|
-
|
|
7978
|
-
|
|
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"),
|
|
7979
8152
|
renderWorkspaceReadme(name, o.destination)
|
|
7980
8153
|
);
|
|
7981
8154
|
}
|
|
7982
8155
|
appendAgentsMdStudioSection(target);
|
|
7983
|
-
const appRoot =
|
|
7984
|
-
|
|
7985
|
-
const agentRoot2 =
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
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"),
|
|
7989
8162
|
renderAgentPnpmWorkspaceYaml()
|
|
7990
8163
|
);
|
|
7991
8164
|
if (o.walletKind === "evm-local" || o.walletKind === "altana") {
|
|
7992
|
-
|
|
8165
|
+
fs24.mkdirSync(path23.join(target, ".studio", "wallets"), { recursive: true });
|
|
7993
8166
|
} else if (o.walletKind === "twak") {
|
|
7994
8167
|
let homeDir;
|
|
7995
8168
|
let label;
|
|
7996
8169
|
if (o.twakHome === void 0 || o.twakHome === DEDICATED_TWAK_HOME_REL) {
|
|
7997
|
-
homeDir =
|
|
8170
|
+
homeDir = path23.join(target, ".studio", "twak");
|
|
7998
8171
|
label = ".studio/twak";
|
|
7999
8172
|
} else {
|
|
8000
|
-
homeDir =
|
|
8173
|
+
homeDir = path23.isAbsolute(o.twakHome) ? o.twakHome : path23.resolve(agentRoot2, o.twakHome);
|
|
8001
8174
|
label = o.twakHome;
|
|
8002
8175
|
}
|
|
8003
|
-
|
|
8176
|
+
fs24.mkdirSync(homeDir, { recursive: true });
|
|
8004
8177
|
if (ensureTwakKeychain(homeDir)) {
|
|
8005
8178
|
printOut(
|
|
8006
8179
|
`\u2713 isolated twak keychain ready under ${label} (macOS) \u2014 no manual \`security\` setup needed`
|
|
8007
8180
|
);
|
|
8008
8181
|
}
|
|
8009
8182
|
}
|
|
8010
|
-
|
|
8011
|
-
|
|
8183
|
+
fs24.writeFileSync(
|
|
8184
|
+
path23.join(agentRoot2, "package.json"),
|
|
8012
8185
|
renderAgentPackageJson(name, o.runtime, o.provider, o.faces, o.walletKind)
|
|
8013
8186
|
);
|
|
8014
|
-
|
|
8015
|
-
|
|
8187
|
+
fs24.writeFileSync(
|
|
8188
|
+
path23.join(agentRoot2, "tsconfig.json"),
|
|
8016
8189
|
renderAgentTsconfig()
|
|
8017
8190
|
);
|
|
8018
|
-
|
|
8019
|
-
|
|
8191
|
+
fs24.writeFileSync(
|
|
8192
|
+
path23.join(agentRoot2, "studio.toml"),
|
|
8020
8193
|
renderAgentStudioToml(name, o)
|
|
8021
8194
|
);
|
|
8022
|
-
const envLocal =
|
|
8023
|
-
|
|
8024
|
-
|
|
8195
|
+
const envLocal = path23.join(target, ".studio", ".env.local");
|
|
8196
|
+
fs24.mkdirSync(path23.dirname(envLocal), { recursive: true });
|
|
8197
|
+
fs24.writeFileSync(
|
|
8025
8198
|
envLocal,
|
|
8026
8199
|
renderAgentEnvLocal(
|
|
8027
8200
|
o.provider,
|
|
@@ -8032,9 +8205,9 @@ function scaffold(target, name, o) {
|
|
|
8032
8205
|
o.network
|
|
8033
8206
|
)
|
|
8034
8207
|
);
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8208
|
+
fs24.writeFileSync(path23.join(agentRoot2, ".gitignore"), renderAgentGitignore());
|
|
8209
|
+
fs24.writeFileSync(
|
|
8210
|
+
path23.join(agentRoot2, "README.md"),
|
|
8038
8211
|
renderAgentReadme(name, o.faces, o.destination)
|
|
8039
8212
|
);
|
|
8040
8213
|
const packaging = derivePackaging(
|
|
@@ -8070,18 +8243,18 @@ function emitRecipe(base, name, opts = {}) {
|
|
|
8070
8243
|
const recipe = loadRecipe(name, { mode: opts.mode ?? null });
|
|
8071
8244
|
for (const rf of recipe.files) {
|
|
8072
8245
|
const targetPath = substitutePlaceholders(rf.targetPath, opts.context);
|
|
8073
|
-
const basename16 =
|
|
8074
|
-
const dst = basename16 === "Dockerfile" || basename16 === ".dockerignore" ?
|
|
8075
|
-
|
|
8076
|
-
|
|
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));
|
|
8077
8250
|
}
|
|
8078
8251
|
}
|
|
8079
8252
|
function readRecipeNodeDeps(recipeName, group) {
|
|
8080
|
-
const tomlPath =
|
|
8081
|
-
if (!
|
|
8253
|
+
const tomlPath = path23.join(bundledRecipesRoot(), recipeName, "recipe.toml");
|
|
8254
|
+
if (!isFile9(tomlPath)) {
|
|
8082
8255
|
return [];
|
|
8083
8256
|
}
|
|
8084
|
-
const meta = parseToml(
|
|
8257
|
+
const meta = parseToml(fs24.readFileSync(tomlPath, "utf-8"));
|
|
8085
8258
|
const depsSection = meta.dependencies !== null && typeof meta.dependencies === "object" ? meta.dependencies : {};
|
|
8086
8259
|
const collect = (v) => Array.isArray(v) ? v.filter((d) => typeof d === "string") : [];
|
|
8087
8260
|
const deps = collect(depsSection.node);
|
|
@@ -8666,7 +8839,7 @@ bag deploy --provider aws
|
|
|
8666
8839
|
`;
|
|
8667
8840
|
}
|
|
8668
8841
|
function emitProviderSkills(target, provider, ides) {
|
|
8669
|
-
const skillDir =
|
|
8842
|
+
const skillDir = path23.join(
|
|
8670
8843
|
bundledRecipesRoot(),
|
|
8671
8844
|
"providers",
|
|
8672
8845
|
provider,
|
|
@@ -8676,34 +8849,34 @@ function emitProviderSkills(target, provider, ides) {
|
|
|
8676
8849
|
return;
|
|
8677
8850
|
}
|
|
8678
8851
|
let emittedCursor = false;
|
|
8679
|
-
for (const md of
|
|
8680
|
-
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");
|
|
8681
8854
|
const stem2 = md.replace(/\.md$/, "");
|
|
8682
8855
|
for (const ide of ides) {
|
|
8683
8856
|
const [relPath, content] = renderSkillPayload(srcText, stem2, ide);
|
|
8684
|
-
const base = ide === "claude-code" ?
|
|
8685
|
-
const dst =
|
|
8686
|
-
|
|
8687
|
-
|
|
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);
|
|
8688
8861
|
if (ide === "cursor") {
|
|
8689
8862
|
emittedCursor = true;
|
|
8690
8863
|
}
|
|
8691
8864
|
}
|
|
8692
8865
|
}
|
|
8693
8866
|
if (emittedCursor) {
|
|
8694
|
-
ensureCursorGitignore(
|
|
8867
|
+
ensureCursorGitignore(path23.join(target, ".gitignore"));
|
|
8695
8868
|
}
|
|
8696
8869
|
}
|
|
8697
8870
|
function ensureCursorGitignore(gitignore) {
|
|
8698
|
-
if (!
|
|
8871
|
+
if (!isFile9(gitignore)) {
|
|
8699
8872
|
return;
|
|
8700
8873
|
}
|
|
8701
|
-
const text2 =
|
|
8874
|
+
const text2 = fs24.readFileSync(gitignore, "utf-8");
|
|
8702
8875
|
if (text2.includes(".cursor/rules/")) {
|
|
8703
8876
|
return;
|
|
8704
8877
|
}
|
|
8705
8878
|
const addition = "\n# Cursor rules emitted at init (regeneratable via `bag skills install --target cursor`).\n.cursor/rules/\n";
|
|
8706
|
-
|
|
8879
|
+
fs24.writeFileSync(gitignore, `${text2.replace(/\n+$/, "")}
|
|
8707
8880
|
${addition}`);
|
|
8708
8881
|
}
|
|
8709
8882
|
async function resolveWalletKind(flagValue, isTty) {
|
|
@@ -8881,11 +9054,11 @@ async function promptPassword() {
|
|
|
8881
9054
|
return first;
|
|
8882
9055
|
}
|
|
8883
9056
|
function readWalletAddress(studioToml) {
|
|
8884
|
-
if (!
|
|
9057
|
+
if (!isFile9(studioToml)) {
|
|
8885
9058
|
return null;
|
|
8886
9059
|
}
|
|
8887
9060
|
try {
|
|
8888
|
-
const data = parseToml(
|
|
9061
|
+
const data = parseToml(fs24.readFileSync(studioToml, "utf-8"));
|
|
8889
9062
|
const wallet = data.wallet;
|
|
8890
9063
|
if (wallet !== null && typeof wallet === "object") {
|
|
8891
9064
|
const addr = wallet.address;
|
|
@@ -8988,7 +9161,7 @@ async function runOnboarding(o) {
|
|
|
8988
9161
|
if (password === null) {
|
|
8989
9162
|
return false;
|
|
8990
9163
|
}
|
|
8991
|
-
const agentRoot2 =
|
|
9164
|
+
const agentRoot2 = path23.join(o.workspaceRoot, APP_DIR, AGENT_PKG);
|
|
8992
9165
|
const { envLocalPath: envLocalPath19 } = await import("@bnbagent/studio-runtime/config");
|
|
8993
9166
|
setEnvVar(envLocalPath19(agentRoot2), "WALLET_PASSWORD", password);
|
|
8994
9167
|
const savedCwd = process.cwd();
|
|
@@ -9016,7 +9189,7 @@ async function runOnboarding(o) {
|
|
|
9016
9189
|
);
|
|
9017
9190
|
return false;
|
|
9018
9191
|
}
|
|
9019
|
-
address = readWalletAddress(
|
|
9192
|
+
address = readWalletAddress(path23.join(agentRoot2, "studio.toml"));
|
|
9020
9193
|
if (o.walletKind !== "altana" || o.provider !== "pieverse-llm") {
|
|
9021
9194
|
await onboardProviderActivation(agentRoot2, o.provider, o.model);
|
|
9022
9195
|
}
|
|
@@ -9035,7 +9208,7 @@ async function runOnboarding(o) {
|
|
|
9035
9208
|
await printFaucetHint(o.network, address);
|
|
9036
9209
|
if (o.walletKind === "altana") {
|
|
9037
9210
|
printOut(
|
|
9038
|
-
"Altana next step: fund about 0.
|
|
9211
|
+
"Altana next step: fund about 0.05 tBNB for bootstrap/registration, then run `bag wallet session grant`."
|
|
9039
9212
|
);
|
|
9040
9213
|
}
|
|
9041
9214
|
}
|
|
@@ -9045,9 +9218,9 @@ async function onboardProviderActivation(agentRoot2, provider, model) {
|
|
|
9045
9218
|
if (provider === "pieverse-llm") {
|
|
9046
9219
|
const chosenModel = model ?? await promptPieverseModel();
|
|
9047
9220
|
if (model === void 0) {
|
|
9048
|
-
const tomlPath =
|
|
9049
|
-
const text2 =
|
|
9050
|
-
|
|
9221
|
+
const tomlPath = path23.join(agentRoot2, "studio.toml");
|
|
9222
|
+
const text2 = fs24.readFileSync(tomlPath, "utf-8");
|
|
9223
|
+
fs24.writeFileSync(
|
|
9051
9224
|
tomlPath,
|
|
9052
9225
|
updateSection(text2, "llm", { model: chosenModel })
|
|
9053
9226
|
);
|
|
@@ -9083,8 +9256,8 @@ set ${keyEnv}= in .studio/.env.local before running \`bag dev\`.`
|
|
|
9083
9256
|
}
|
|
9084
9257
|
}
|
|
9085
9258
|
async function runOnboardingTwak(o) {
|
|
9086
|
-
const agentRoot2 =
|
|
9087
|
-
const studioToml =
|
|
9259
|
+
const agentRoot2 = path23.join(o.workspaceRoot, APP_DIR, AGENT_PKG);
|
|
9260
|
+
const studioToml = path23.join(agentRoot2, "studio.toml");
|
|
9088
9261
|
if (await whichTwak() === null) {
|
|
9089
9262
|
printErr(
|
|
9090
9263
|
`
|
|
@@ -9100,7 +9273,7 @@ you, so you never type the password on a command line, and adopts the address):
|
|
|
9100
9273
|
}
|
|
9101
9274
|
let walletCfg = {};
|
|
9102
9275
|
try {
|
|
9103
|
-
const data = parseToml(
|
|
9276
|
+
const data = parseToml(fs24.readFileSync(studioToml, "utf-8"));
|
|
9104
9277
|
if (data.wallet !== null && typeof data.wallet === "object") {
|
|
9105
9278
|
walletCfg = data.wallet;
|
|
9106
9279
|
}
|
|
@@ -9109,16 +9282,16 @@ you, so you never type the password on a command line, and adopts the address):
|
|
|
9109
9282
|
}
|
|
9110
9283
|
const { twakWalletFile: twakWalletFile2 } = await import("./_twak-4XF4H5PL.js");
|
|
9111
9284
|
let projectWallet = twakWalletFile2(walletCfg, agentRoot2);
|
|
9112
|
-
const machineWallet =
|
|
9113
|
-
if (!o.twakHomePinned &&
|
|
9285
|
+
const machineWallet = path23.join(os4.homedir(), ".twak", "wallet.json");
|
|
9286
|
+
if (!o.twakHomePinned && isFile9(machineWallet) && realpathIfExists(projectWallet) !== realpathIfExists(machineWallet)) {
|
|
9114
9287
|
if (await promptUseMachineTwakWallet(machineWallet)) {
|
|
9115
9288
|
projectWallet = adoptMachineTwakWallet(machineWallet, o.workspaceRoot);
|
|
9116
9289
|
}
|
|
9117
9290
|
}
|
|
9118
|
-
if (!
|
|
9119
|
-
const homeDir =
|
|
9291
|
+
if (!isFile9(projectWallet)) {
|
|
9292
|
+
const homeDir = path23.dirname(path23.dirname(projectWallet));
|
|
9120
9293
|
try {
|
|
9121
|
-
|
|
9294
|
+
fs24.mkdirSync(homeDir, { recursive: true });
|
|
9122
9295
|
} catch {
|
|
9123
9296
|
}
|
|
9124
9297
|
printErr(
|
|
@@ -9173,9 +9346,9 @@ Guide: the bnbagent-studio-using-twak-wallet.md reference (installed by \`bag sk
|
|
|
9173
9346
|
}
|
|
9174
9347
|
function realpathIfExists(p) {
|
|
9175
9348
|
try {
|
|
9176
|
-
return
|
|
9349
|
+
return fs24.realpathSync(p);
|
|
9177
9350
|
} catch {
|
|
9178
|
-
return
|
|
9351
|
+
return path23.resolve(p);
|
|
9179
9352
|
}
|
|
9180
9353
|
}
|
|
9181
9354
|
async function promptUseMachineTwakWallet(machineWallet) {
|
|
@@ -9188,39 +9361,39 @@ Found an existing twak wallet: ${machineWallet}`);
|
|
|
9188
9361
|
return answer === "y" || answer === "yes";
|
|
9189
9362
|
}
|
|
9190
9363
|
function adoptMachineTwakWallet(machineWallet, workspaceRoot) {
|
|
9191
|
-
const homeDir =
|
|
9192
|
-
const twakDir =
|
|
9193
|
-
|
|
9364
|
+
const homeDir = path23.join(workspaceRoot, ".studio", "twak");
|
|
9365
|
+
const twakDir = path23.join(homeDir, ".twak");
|
|
9366
|
+
fs24.mkdirSync(twakDir, { recursive: true });
|
|
9194
9367
|
try {
|
|
9195
|
-
|
|
9196
|
-
|
|
9368
|
+
fs24.chmodSync(homeDir, 448);
|
|
9369
|
+
fs24.chmodSync(twakDir, 448);
|
|
9197
9370
|
} catch {
|
|
9198
9371
|
}
|
|
9199
9372
|
for (const name of ["wallet.json", "credentials.json"]) {
|
|
9200
|
-
const src =
|
|
9201
|
-
if (
|
|
9202
|
-
const dst =
|
|
9203
|
-
|
|
9204
|
-
|
|
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);
|
|
9205
9378
|
}
|
|
9206
9379
|
}
|
|
9207
|
-
return
|
|
9380
|
+
return path23.join(twakDir, "wallet.json");
|
|
9208
9381
|
}
|
|
9209
9382
|
function normalizeTwakHome(raw) {
|
|
9210
|
-
const expanded = raw.startsWith("~") ?
|
|
9211
|
-
if (!
|
|
9383
|
+
const expanded = raw.startsWith("~") ? path23.join(os4.homedir(), raw.slice(1)) : raw;
|
|
9384
|
+
if (!path23.isAbsolute(expanded)) {
|
|
9212
9385
|
return { home: raw };
|
|
9213
9386
|
}
|
|
9214
|
-
const
|
|
9387
|
+
const isFile20 = (p) => {
|
|
9215
9388
|
try {
|
|
9216
|
-
return
|
|
9389
|
+
return fs24.statSync(p).isFile();
|
|
9217
9390
|
} catch {
|
|
9218
9391
|
return false;
|
|
9219
9392
|
}
|
|
9220
9393
|
};
|
|
9221
|
-
if (
|
|
9222
|
-
const parent =
|
|
9223
|
-
if (
|
|
9394
|
+
if (path23.basename(expanded) === ".twak") {
|
|
9395
|
+
const parent = path23.dirname(expanded);
|
|
9396
|
+
if (isFile20(path23.join(expanded, "wallet.json"))) {
|
|
9224
9397
|
return {
|
|
9225
9398
|
home: parent,
|
|
9226
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).`
|
|
@@ -9230,15 +9403,15 @@ function normalizeTwakHome(raw) {
|
|
|
9230
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.`
|
|
9231
9404
|
};
|
|
9232
9405
|
}
|
|
9233
|
-
if (
|
|
9406
|
+
if (isFile20(path23.join(expanded, "wallet.json")) && !isFile20(path23.join(expanded, ".twak", "wallet.json"))) {
|
|
9234
9407
|
return {
|
|
9235
|
-
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.`
|
|
9236
9409
|
};
|
|
9237
9410
|
}
|
|
9238
|
-
if (!
|
|
9411
|
+
if (!isFile20(path23.join(expanded, ".twak", "wallet.json"))) {
|
|
9239
9412
|
return {
|
|
9240
9413
|
home: raw,
|
|
9241
|
-
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.`
|
|
9242
9415
|
};
|
|
9243
9416
|
}
|
|
9244
9417
|
return { home: raw };
|
|
@@ -9248,7 +9421,7 @@ function twakHomeIsMainHome(twakHome) {
|
|
|
9248
9421
|
return false;
|
|
9249
9422
|
}
|
|
9250
9423
|
try {
|
|
9251
|
-
const expanded = twakHome.startsWith("~") ?
|
|
9424
|
+
const expanded = twakHome.startsWith("~") ? path23.join(os4.homedir(), twakHome.slice(1)) : twakHome;
|
|
9252
9425
|
return realpathIfExists(expanded) === realpathIfExists(os4.homedir());
|
|
9253
9426
|
} catch {
|
|
9254
9427
|
return false;
|
|
@@ -9339,8 +9512,10 @@ NOTE \u2014 wallet.kind = "altana" (bounded runtime session):
|
|
|
9339
9512
|
.studio/wallets/. WALLET_PASSWORD is used only by wallet/session commands.
|
|
9340
9513
|
\xB7 RUNTIME: fund the admin address, then run \`bag wallet session grant\`.
|
|
9341
9514
|
The Agent receives only .studio/wallets/altana-session.json.
|
|
9342
|
-
\xB7 DEPLOY:
|
|
9343
|
-
|
|
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.`
|
|
9344
9519
|
);
|
|
9345
9520
|
}
|
|
9346
9521
|
function printPlatformWalletSuggestion() {
|
|
@@ -9398,11 +9573,11 @@ function entrypointHint(faces) {
|
|
|
9398
9573
|
return "app/agent/src/main.ts + executor.ts = A2A entrypoint (build your value here)";
|
|
9399
9574
|
}
|
|
9400
9575
|
function hasVendoredTarballs(agentDir) {
|
|
9401
|
-
const vendor =
|
|
9576
|
+
const vendor = path23.join(agentDir, "vendor");
|
|
9402
9577
|
if (!isDir4(vendor)) {
|
|
9403
9578
|
return false;
|
|
9404
9579
|
}
|
|
9405
|
-
return
|
|
9580
|
+
return fs24.readdirSync(vendor).some((n) => n.endsWith(".tgz"));
|
|
9406
9581
|
}
|
|
9407
9582
|
function printCompactNextSteps(name, o = {}) {
|
|
9408
9583
|
const faces = o.faces ?? normalizeProtocolFaces(o.protocol ?? "A2A");
|
|
@@ -9430,7 +9605,7 @@ function printCompactNextSteps(name, o = {}) {
|
|
|
9430
9605
|
}
|
|
9431
9606
|
if (walletKind2 === "altana") {
|
|
9432
9607
|
printOut(
|
|
9433
|
-
" bag wallet session grant # after funding ~0.
|
|
9608
|
+
" bag wallet session grant # after funding ~0.05 tBNB: create the bounded runtime session"
|
|
9434
9609
|
);
|
|
9435
9610
|
if (o.provider === "pieverse-llm") {
|
|
9436
9611
|
printOut(
|
|
@@ -9554,7 +9729,7 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9554
9729
|
printOut(" # bag auto-loads it; never pass it on argv");
|
|
9555
9730
|
printOut(" (cd app/agent && bag wallet new)");
|
|
9556
9731
|
printOut(
|
|
9557
|
-
" # 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"
|
|
9558
9733
|
);
|
|
9559
9734
|
printOut(" (cd app/agent && bag wallet session grant)");
|
|
9560
9735
|
printOut(
|
|
@@ -9652,11 +9827,11 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9652
9827
|
);
|
|
9653
9828
|
}
|
|
9654
9829
|
function loadTomlSafe(p) {
|
|
9655
|
-
if (!
|
|
9830
|
+
if (!isFile9(p)) {
|
|
9656
9831
|
return {};
|
|
9657
9832
|
}
|
|
9658
9833
|
try {
|
|
9659
|
-
return parseToml(
|
|
9834
|
+
return parseToml(fs24.readFileSync(p, "utf-8"));
|
|
9660
9835
|
} catch {
|
|
9661
9836
|
return {};
|
|
9662
9837
|
}
|
|
@@ -9676,7 +9851,7 @@ function weiToU(raw) {
|
|
|
9676
9851
|
}
|
|
9677
9852
|
}
|
|
9678
9853
|
function printConfigSummary(agentRoot2) {
|
|
9679
|
-
const agent = loadTomlSafe(
|
|
9854
|
+
const agent = loadTomlSafe(path23.join(agentRoot2, "studio.toml"));
|
|
9680
9855
|
if (Object.keys(agent).length === 0) {
|
|
9681
9856
|
return;
|
|
9682
9857
|
}
|
|
@@ -9874,16 +10049,16 @@ function printConfigSummary(agentRoot2) {
|
|
|
9874
10049
|
printOut("");
|
|
9875
10050
|
}
|
|
9876
10051
|
}
|
|
9877
|
-
function
|
|
10052
|
+
function isFile9(p) {
|
|
9878
10053
|
try {
|
|
9879
|
-
return
|
|
10054
|
+
return fs24.statSync(p).isFile();
|
|
9880
10055
|
} catch {
|
|
9881
10056
|
return false;
|
|
9882
10057
|
}
|
|
9883
10058
|
}
|
|
9884
10059
|
function isDir4(p) {
|
|
9885
10060
|
try {
|
|
9886
|
-
return
|
|
10061
|
+
return fs24.statSync(p).isDirectory();
|
|
9887
10062
|
} catch {
|
|
9888
10063
|
return false;
|
|
9889
10064
|
}
|
|
@@ -9947,9 +10122,9 @@ var RUNTIME_AGENTCORE = "agentcore";
|
|
|
9947
10122
|
var RUNTIME_AZURE_FOUNDRY = "azure-foundry";
|
|
9948
10123
|
var MIN_NODE_MAJOR = 22;
|
|
9949
10124
|
var CONTAINER_RUNTIMES = ["docker", "podman", "finch"];
|
|
9950
|
-
function
|
|
10125
|
+
function isFile10(p) {
|
|
9951
10126
|
try {
|
|
9952
|
-
return
|
|
10127
|
+
return fs25.statSync(p).isFile();
|
|
9953
10128
|
} catch {
|
|
9954
10129
|
return false;
|
|
9955
10130
|
}
|
|
@@ -9981,8 +10156,8 @@ async function nodeMajor() {
|
|
|
9981
10156
|
return /^\d+$/.test(head) ? Number.parseInt(head, 10) : null;
|
|
9982
10157
|
}
|
|
9983
10158
|
function workspaceBase(root) {
|
|
9984
|
-
for (const base of [
|
|
9985
|
-
if (
|
|
10159
|
+
for (const base of [path24.join(root, "app"), root]) {
|
|
10160
|
+
if (isFile10(path24.join(base, "agent", "studio.toml"))) {
|
|
9986
10161
|
return base;
|
|
9987
10162
|
}
|
|
9988
10163
|
}
|
|
@@ -9990,7 +10165,7 @@ function workspaceBase(root) {
|
|
|
9990
10165
|
}
|
|
9991
10166
|
function resolveWorkspaceRoot(argRoot) {
|
|
9992
10167
|
if (argRoot !== null) {
|
|
9993
|
-
const root =
|
|
10168
|
+
const root = path24.resolve(argRoot);
|
|
9994
10169
|
const base = workspaceBase(root);
|
|
9995
10170
|
if (base === null) {
|
|
9996
10171
|
printErr(
|
|
@@ -10000,13 +10175,13 @@ function resolveWorkspaceRoot(argRoot) {
|
|
|
10000
10175
|
}
|
|
10001
10176
|
return base;
|
|
10002
10177
|
}
|
|
10003
|
-
let current =
|
|
10178
|
+
let current = path24.resolve(process.cwd());
|
|
10004
10179
|
for (; ; ) {
|
|
10005
10180
|
const base = workspaceBase(current);
|
|
10006
10181
|
if (base !== null) {
|
|
10007
10182
|
return base;
|
|
10008
10183
|
}
|
|
10009
|
-
const parent =
|
|
10184
|
+
const parent = path24.dirname(current);
|
|
10010
10185
|
if (parent === current) {
|
|
10011
10186
|
break;
|
|
10012
10187
|
}
|
|
@@ -10020,7 +10195,7 @@ function resolveWorkspaceRoot(argRoot) {
|
|
|
10020
10195
|
function loadAgentToml2(workspaceRoot) {
|
|
10021
10196
|
try {
|
|
10022
10197
|
return loadStudioToml11(
|
|
10023
|
-
|
|
10198
|
+
path24.join(workspaceRoot, "agent", "studio.toml")
|
|
10024
10199
|
);
|
|
10025
10200
|
} catch {
|
|
10026
10201
|
return {};
|
|
@@ -10047,7 +10222,7 @@ function defaultAgentPort(faces) {
|
|
|
10047
10222
|
function storageKind(agentDir) {
|
|
10048
10223
|
let data;
|
|
10049
10224
|
try {
|
|
10050
|
-
data = loadStudioToml11(
|
|
10225
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10051
10226
|
} catch {
|
|
10052
10227
|
return "local";
|
|
10053
10228
|
}
|
|
@@ -10057,7 +10232,7 @@ function storageKind(agentDir) {
|
|
|
10057
10232
|
function networkNameOf(agentDir) {
|
|
10058
10233
|
let data;
|
|
10059
10234
|
try {
|
|
10060
|
-
data = loadStudioToml11(
|
|
10235
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10061
10236
|
} catch {
|
|
10062
10237
|
return "bsc-testnet";
|
|
10063
10238
|
}
|
|
@@ -10067,7 +10242,7 @@ function networkNameOf(agentDir) {
|
|
|
10067
10242
|
function walletKindOf(agentDir) {
|
|
10068
10243
|
let data;
|
|
10069
10244
|
try {
|
|
10070
|
-
data = loadStudioToml11(
|
|
10245
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10071
10246
|
} catch {
|
|
10072
10247
|
return "evm-local";
|
|
10073
10248
|
}
|
|
@@ -10075,18 +10250,18 @@ function walletKindOf(agentDir) {
|
|
|
10075
10250
|
return typeof kind === "string" && kind.trim() ? kind.trim() : "evm-local";
|
|
10076
10251
|
}
|
|
10077
10252
|
function altanaSessionForRuntime(agentDir) {
|
|
10078
|
-
const cfg = loadStudioToml11(
|
|
10253
|
+
const cfg = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10079
10254
|
const wallet = tableOf9(cfg, "wallet");
|
|
10080
10255
|
const configured = String(
|
|
10081
10256
|
wallet.session_file ?? ".studio/wallets/altana-session.json"
|
|
10082
10257
|
);
|
|
10083
|
-
const sessionFile =
|
|
10084
|
-
if (!
|
|
10258
|
+
const sessionFile = path24.isAbsolute(configured) ? configured : path24.join(agentDir, configured);
|
|
10259
|
+
if (!isFile10(sessionFile)) {
|
|
10085
10260
|
throw new Error(
|
|
10086
10261
|
`no Altana session at ${sessionFile} \u2014 run \`bag wallet session grant\` first.`
|
|
10087
10262
|
);
|
|
10088
10263
|
}
|
|
10089
|
-
const serialized =
|
|
10264
|
+
const serialized = fs25.readFileSync(sessionFile, "utf8");
|
|
10090
10265
|
let envelope;
|
|
10091
10266
|
try {
|
|
10092
10267
|
envelope = JSON.parse(serialized);
|
|
@@ -10115,10 +10290,10 @@ function altanaSessionForRuntime(agentDir) {
|
|
|
10115
10290
|
}
|
|
10116
10291
|
var KEY_LINE_RE = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/;
|
|
10117
10292
|
function loadEnvFileForDev(p) {
|
|
10118
|
-
if (!
|
|
10293
|
+
if (!isFile10(p)) {
|
|
10119
10294
|
return;
|
|
10120
10295
|
}
|
|
10121
|
-
for (const line of
|
|
10296
|
+
for (const line of fs25.readFileSync(p, "utf-8").split(/\r?\n/)) {
|
|
10122
10297
|
if (!line || line.trimStart().startsWith("#")) {
|
|
10123
10298
|
continue;
|
|
10124
10299
|
}
|
|
@@ -10139,20 +10314,20 @@ function ensureStoragePath(projectRoot) {
|
|
|
10139
10314
|
const raw = process.env.STORAGE_LOCAL_PATH;
|
|
10140
10315
|
let resolved;
|
|
10141
10316
|
if (raw) {
|
|
10142
|
-
resolved =
|
|
10143
|
-
raw.startsWith("~") ?
|
|
10317
|
+
resolved = path24.resolve(
|
|
10318
|
+
raw.startsWith("~") ? path24.join(os5.homedir(), raw.slice(1)) : raw
|
|
10144
10319
|
);
|
|
10145
10320
|
} else {
|
|
10146
|
-
resolved =
|
|
10147
|
-
|
|
10321
|
+
resolved = path24.resolve(
|
|
10322
|
+
path24.join(
|
|
10148
10323
|
os5.homedir(),
|
|
10149
10324
|
".bag",
|
|
10150
10325
|
"deliverables",
|
|
10151
|
-
|
|
10326
|
+
path24.basename(projectRoot)
|
|
10152
10327
|
)
|
|
10153
10328
|
);
|
|
10154
10329
|
}
|
|
10155
|
-
|
|
10330
|
+
fs25.mkdirSync(resolved, { recursive: true });
|
|
10156
10331
|
process.env.STORAGE_LOCAL_PATH = resolved;
|
|
10157
10332
|
}
|
|
10158
10333
|
function ipfsPreflight(agentDir) {
|
|
@@ -10167,7 +10342,7 @@ function ipfsPreflight(agentDir) {
|
|
|
10167
10342
|
function runtimeEnvKeys(agentDir) {
|
|
10168
10343
|
let cfg = {};
|
|
10169
10344
|
try {
|
|
10170
|
-
cfg = loadStudioToml11(
|
|
10345
|
+
cfg = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10171
10346
|
} catch {
|
|
10172
10347
|
cfg = {};
|
|
10173
10348
|
}
|
|
@@ -10184,7 +10359,7 @@ function readTwakFiles(agentDir) {
|
|
|
10184
10359
|
let walletCfg = {};
|
|
10185
10360
|
try {
|
|
10186
10361
|
walletCfg = tableOf9(
|
|
10187
|
-
loadStudioToml11(
|
|
10362
|
+
loadStudioToml11(path24.join(agentDir, "studio.toml")),
|
|
10188
10363
|
"wallet"
|
|
10189
10364
|
);
|
|
10190
10365
|
} catch {
|
|
@@ -10192,9 +10367,9 @@ function readTwakFiles(agentDir) {
|
|
|
10192
10367
|
}
|
|
10193
10368
|
const twakDir = twakHomeDir(walletCfg, agentDir);
|
|
10194
10369
|
const read = (name) => {
|
|
10195
|
-
const p =
|
|
10370
|
+
const p = path24.join(twakDir, name);
|
|
10196
10371
|
try {
|
|
10197
|
-
return
|
|
10372
|
+
return fs25.readFileSync(p, "utf-8");
|
|
10198
10373
|
} catch {
|
|
10199
10374
|
return null;
|
|
10200
10375
|
}
|
|
@@ -10202,19 +10377,19 @@ function readTwakFiles(agentDir) {
|
|
|
10202
10377
|
return [read("wallet.json"), read("credentials.json")];
|
|
10203
10378
|
}
|
|
10204
10379
|
function ensureAgentcoreEnvGitignored(agentcoreDir) {
|
|
10205
|
-
const gi =
|
|
10380
|
+
const gi = path24.join(agentcoreDir, ".gitignore");
|
|
10206
10381
|
const entry = ".env.local";
|
|
10207
|
-
if (
|
|
10208
|
-
const text2 =
|
|
10382
|
+
if (isFile10(gi)) {
|
|
10383
|
+
const text2 = fs25.readFileSync(gi, "utf-8");
|
|
10209
10384
|
const lines = new Set(text2.split("\n").map((l) => l.trim()));
|
|
10210
10385
|
if (lines.has(entry)) {
|
|
10211
10386
|
return;
|
|
10212
10387
|
}
|
|
10213
|
-
const
|
|
10214
|
-
|
|
10388
|
+
const sep7 = text2.endsWith("\n") || text2 === "" ? "" : "\n";
|
|
10389
|
+
fs25.writeFileSync(gi, `${text2}${sep7}${entry}
|
|
10215
10390
|
`);
|
|
10216
10391
|
} else {
|
|
10217
|
-
|
|
10392
|
+
fs25.writeFileSync(gi, `${entry}
|
|
10218
10393
|
`);
|
|
10219
10394
|
}
|
|
10220
10395
|
}
|
|
@@ -10237,8 +10412,8 @@ function writeAgentcoreEnvLocal(agentcoreRoot, agentDir) {
|
|
|
10237
10412
|
} else if (walletKindOf(agentDir) === "altana") {
|
|
10238
10413
|
bundle.ALTANA_SESSION = altanaSessionForRuntime(agentDir);
|
|
10239
10414
|
}
|
|
10240
|
-
const envPath =
|
|
10241
|
-
const prior =
|
|
10415
|
+
const envPath = path24.join(agentcoreRoot, "agentcore", ".env.local");
|
|
10416
|
+
const prior = isFile10(envPath) ? fs25.readFileSync(envPath, "utf-8") : "";
|
|
10242
10417
|
const merged = {};
|
|
10243
10418
|
for (const line of prior.split("\n")) {
|
|
10244
10419
|
if (!line || line.trimStart().startsWith("#")) {
|
|
@@ -10253,14 +10428,14 @@ function writeAgentcoreEnvLocal(agentcoreRoot, agentDir) {
|
|
|
10253
10428
|
Object.assign(merged, bundle);
|
|
10254
10429
|
const content = Object.entries(merged).map(([k, v]) => `${k}=${v}
|
|
10255
10430
|
`).join("");
|
|
10256
|
-
|
|
10257
|
-
ensureAgentcoreEnvGitignored(
|
|
10431
|
+
fs25.mkdirSync(path24.dirname(envPath), { recursive: true });
|
|
10432
|
+
ensureAgentcoreEnvGitignored(path24.dirname(envPath));
|
|
10258
10433
|
writePrivate2(envPath, content);
|
|
10259
10434
|
return [envPath, content !== prior];
|
|
10260
10435
|
}
|
|
10261
10436
|
function agentcoreProjectRoot2(workspaceRoot) {
|
|
10262
|
-
for (const candidate of [
|
|
10263
|
-
if (
|
|
10437
|
+
for (const candidate of [path24.dirname(workspaceRoot), workspaceRoot]) {
|
|
10438
|
+
if (isFile10(path24.join(candidate, "agentcore", "agentcore.json"))) {
|
|
10264
10439
|
return candidate;
|
|
10265
10440
|
}
|
|
10266
10441
|
}
|
|
@@ -10269,8 +10444,8 @@ function agentcoreProjectRoot2(workspaceRoot) {
|
|
|
10269
10444
|
function loadAgentcoreConfig(projectRoot) {
|
|
10270
10445
|
try {
|
|
10271
10446
|
const cfg = JSON.parse(
|
|
10272
|
-
|
|
10273
|
-
|
|
10447
|
+
fs25.readFileSync(
|
|
10448
|
+
path24.join(projectRoot, "agentcore", "agentcore.json"),
|
|
10274
10449
|
"utf-8"
|
|
10275
10450
|
)
|
|
10276
10451
|
);
|
|
@@ -10360,7 +10535,7 @@ async function cmdDev(opts) {
|
|
|
10360
10535
|
if (workspaceRoot === null) {
|
|
10361
10536
|
return 2;
|
|
10362
10537
|
}
|
|
10363
|
-
const agentDir =
|
|
10538
|
+
const agentDir = path24.join(workspaceRoot, "agent");
|
|
10364
10539
|
migrateEnvLocal(agentDir);
|
|
10365
10540
|
migrateKeystoreOutOfCodelocation(agentDir);
|
|
10366
10541
|
const { envLocalPath: envLocalPath19 } = await import("@bnbagent/studio-runtime/config");
|
|
@@ -10396,8 +10571,8 @@ async function cmdDev(opts) {
|
|
|
10396
10571
|
const runtime = agentRuntime(workspaceRoot);
|
|
10397
10572
|
const container = Boolean(opts.container);
|
|
10398
10573
|
const entryFile = localEntryFile(faces);
|
|
10399
|
-
const agentFile =
|
|
10400
|
-
if (!
|
|
10574
|
+
const agentFile = path24.join(agentDir, entryFile);
|
|
10575
|
+
if (!isFile10(agentFile)) {
|
|
10401
10576
|
printErr(
|
|
10402
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.`
|
|
10403
10578
|
);
|
|
@@ -10475,7 +10650,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10475
10650
|
}
|
|
10476
10651
|
let launch;
|
|
10477
10652
|
if (runtime === RUNTIME_AGENTCORE && container) {
|
|
10478
|
-
const root =
|
|
10653
|
+
const root = path24.resolve(agentcoreRoot);
|
|
10479
10654
|
try {
|
|
10480
10655
|
const vendored = await vendorLocalTarballs(agentDir);
|
|
10481
10656
|
if (vendored.length > 0) {
|
|
@@ -10490,7 +10665,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10490
10665
|
}
|
|
10491
10666
|
const [envPath, changed] = writeAgentcoreEnvLocal(root, agentDir);
|
|
10492
10667
|
printOut(
|
|
10493
|
-
`bag dev: wrote ${
|
|
10668
|
+
`bag dev: wrote ${path24.relative(root, envPath)} (runtime secrets + materialized wallet for the container).`
|
|
10494
10669
|
);
|
|
10495
10670
|
if (changed && process.env.BAG_DEV_ENV_WARNED !== "1") {
|
|
10496
10671
|
printErr(
|
|
@@ -10567,7 +10742,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10567
10742
|
}
|
|
10568
10743
|
if (hasX402Face(faces)) {
|
|
10569
10744
|
const free = x402SellerIsFree(
|
|
10570
|
-
loadStudioToml11(
|
|
10745
|
+
loadStudioToml11(path24.join(agentDir, "studio.toml"))
|
|
10571
10746
|
);
|
|
10572
10747
|
printOut(
|
|
10573
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)`
|
|
@@ -10578,9 +10753,9 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10578
10753
|
}
|
|
10579
10754
|
function tsxRunner(agentDir, workspaceBaseDir) {
|
|
10580
10755
|
const bin = process.platform === "win32" ? "tsx.cmd" : "tsx";
|
|
10581
|
-
for (const dir of [agentDir,
|
|
10582
|
-
const candidate =
|
|
10583
|
-
if (
|
|
10756
|
+
for (const dir of [agentDir, path24.dirname(workspaceBaseDir)]) {
|
|
10757
|
+
const candidate = path24.join(dir, "node_modules", ".bin", bin);
|
|
10758
|
+
if (isFile10(candidate)) {
|
|
10584
10759
|
return candidate;
|
|
10585
10760
|
}
|
|
10586
10761
|
}
|
|
@@ -10589,7 +10764,7 @@ function tsxRunner(agentDir, workspaceBaseDir) {
|
|
|
10589
10764
|
function networkBanner(agentDir) {
|
|
10590
10765
|
let data;
|
|
10591
10766
|
try {
|
|
10592
|
-
data = loadStudioToml11(
|
|
10767
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10593
10768
|
} catch {
|
|
10594
10769
|
return null;
|
|
10595
10770
|
}
|
|
@@ -10606,34 +10781,34 @@ function networkBanner(agentDir) {
|
|
|
10606
10781
|
}
|
|
10607
10782
|
|
|
10608
10783
|
// src/cli/_deploy/checks/critical.ts
|
|
10609
|
-
import * as
|
|
10784
|
+
import * as fs26 from "fs";
|
|
10610
10785
|
import { createRequire } from "module";
|
|
10611
|
-
import * as
|
|
10786
|
+
import * as path25 from "path";
|
|
10612
10787
|
import { envLocalPath as envLocalPath11, loadStudioToml as loadStudioToml12 } from "@bnbagent/studio-runtime/config";
|
|
10613
10788
|
import { pieverseKeyHash as pieverseKeyHash2 } from "@bnbagent/studio-runtime/llm";
|
|
10614
10789
|
var AGENTCORE_DESCRIPTOR2 = "agentcore/agentcore.json";
|
|
10615
|
-
function
|
|
10790
|
+
function isFile11(p) {
|
|
10616
10791
|
try {
|
|
10617
|
-
return
|
|
10792
|
+
return fs26.statSync(p).isFile();
|
|
10618
10793
|
} catch {
|
|
10619
10794
|
return false;
|
|
10620
10795
|
}
|
|
10621
10796
|
}
|
|
10622
10797
|
function isDir5(p) {
|
|
10623
10798
|
try {
|
|
10624
|
-
return
|
|
10799
|
+
return fs26.statSync(p).isDirectory();
|
|
10625
10800
|
} catch {
|
|
10626
10801
|
return false;
|
|
10627
10802
|
}
|
|
10628
10803
|
}
|
|
10629
10804
|
function keystoreDirOf(root, data) {
|
|
10630
10805
|
const rel = String(tableOf2(data, "wallet").keystore_dir ?? ".studio/wallets");
|
|
10631
|
-
const dir =
|
|
10632
|
-
return
|
|
10806
|
+
const dir = path25.isAbsolute(rel) ? rel : path25.join(agentRootOf(root), rel);
|
|
10807
|
+
return path25.resolve(dir);
|
|
10633
10808
|
}
|
|
10634
10809
|
function keystoreJsonFiles2(dir) {
|
|
10635
10810
|
try {
|
|
10636
|
-
return
|
|
10811
|
+
return fs26.readdirSync(dir).filter((n) => n.endsWith(".json")).sort();
|
|
10637
10812
|
} catch {
|
|
10638
10813
|
return [];
|
|
10639
10814
|
}
|
|
@@ -10641,7 +10816,7 @@ function keystoreJsonFiles2(dir) {
|
|
|
10641
10816
|
function runtimeEnvKeys2(agentRoot2) {
|
|
10642
10817
|
let cfg = {};
|
|
10643
10818
|
try {
|
|
10644
|
-
cfg = loadStudioToml12(
|
|
10819
|
+
cfg = loadStudioToml12(path25.join(agentRoot2, "studio.toml"));
|
|
10645
10820
|
} catch {
|
|
10646
10821
|
cfg = {};
|
|
10647
10822
|
}
|
|
@@ -10653,8 +10828,8 @@ async function checkAgentcoreJsonPresent(root, target) {
|
|
|
10653
10828
|
if (target !== "agentcore") {
|
|
10654
10829
|
return [];
|
|
10655
10830
|
}
|
|
10656
|
-
const descriptor =
|
|
10657
|
-
if (
|
|
10831
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
10832
|
+
if (isFile11(descriptor)) {
|
|
10658
10833
|
return [];
|
|
10659
10834
|
}
|
|
10660
10835
|
return [
|
|
@@ -10670,10 +10845,10 @@ async function checkAgentcoreAuthorizerKeyLegacy(root, target) {
|
|
|
10670
10845
|
if (target !== "agentcore") {
|
|
10671
10846
|
return [];
|
|
10672
10847
|
}
|
|
10673
|
-
const descriptor =
|
|
10848
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
10674
10849
|
let data;
|
|
10675
10850
|
try {
|
|
10676
|
-
data = JSON.parse(
|
|
10851
|
+
data = JSON.parse(fs26.readFileSync(descriptor, "utf-8"));
|
|
10677
10852
|
} catch {
|
|
10678
10853
|
return [];
|
|
10679
10854
|
}
|
|
@@ -10713,10 +10888,10 @@ async function checkAgentPackagePresent(root, target) {
|
|
|
10713
10888
|
sourceEntries.push("src/mcpMain.ts");
|
|
10714
10889
|
}
|
|
10715
10890
|
const missingSource = sourceEntries.find(
|
|
10716
|
-
(entry) => !
|
|
10891
|
+
(entry) => !isFile11(path25.join(agentRoot2, entry))
|
|
10717
10892
|
);
|
|
10718
10893
|
if (missingSource !== void 0) {
|
|
10719
|
-
const epPath =
|
|
10894
|
+
const epPath = path25.join(agentRoot2, missingSource);
|
|
10720
10895
|
return [
|
|
10721
10896
|
{
|
|
10722
10897
|
level: Level.CRITICAL,
|
|
@@ -10731,10 +10906,10 @@ async function checkAgentPackagePresent(root, target) {
|
|
|
10731
10906
|
distEntries.push("dist/mcpMain.js");
|
|
10732
10907
|
}
|
|
10733
10908
|
const missingDist = distEntries.find(
|
|
10734
|
-
(entry) => !
|
|
10909
|
+
(entry) => !isFile11(path25.join(agentRoot2, entry))
|
|
10735
10910
|
);
|
|
10736
10911
|
if (missingDist !== void 0) {
|
|
10737
|
-
const distPath =
|
|
10912
|
+
const distPath = path25.join(agentRoot2, missingDist);
|
|
10738
10913
|
return [
|
|
10739
10914
|
{
|
|
10740
10915
|
level: Level.WARNING,
|
|
@@ -10759,8 +10934,8 @@ async function checkKeystoreNotInsideAgent(root, target) {
|
|
|
10759
10934
|
if (!isDir5(keystoreDir) || keystoreJsonFiles2(keystoreDir).length === 0) {
|
|
10760
10935
|
return [];
|
|
10761
10936
|
}
|
|
10762
|
-
const agentDir =
|
|
10763
|
-
const inside2 = keystoreDir === agentDir || keystoreDir.startsWith(agentDir +
|
|
10937
|
+
const agentDir = path25.resolve(agentRootOf(root));
|
|
10938
|
+
const inside2 = keystoreDir === agentDir || keystoreDir.startsWith(agentDir + path25.sep);
|
|
10764
10939
|
if (!inside2) {
|
|
10765
10940
|
return [];
|
|
10766
10941
|
}
|
|
@@ -10779,6 +10954,9 @@ async function checkLocalKeystoreExists(root, _target) {
|
|
|
10779
10954
|
if (walletCfg.kind === "twak") {
|
|
10780
10955
|
return [];
|
|
10781
10956
|
}
|
|
10957
|
+
if (walletCfg.kind === "altana") {
|
|
10958
|
+
return [];
|
|
10959
|
+
}
|
|
10782
10960
|
const signer = walletCfg.signer ?? "local";
|
|
10783
10961
|
if (signer !== "local") {
|
|
10784
10962
|
return [];
|
|
@@ -10797,7 +10975,11 @@ async function checkLocalKeystoreExists(root, _target) {
|
|
|
10797
10975
|
];
|
|
10798
10976
|
}
|
|
10799
10977
|
async function checkWalletPasswordEnvSet(root, _target) {
|
|
10800
|
-
|
|
10978
|
+
const kind = tableOf2(loadAgentToml(root), "wallet").kind;
|
|
10979
|
+
if (kind === "twak") {
|
|
10980
|
+
return [];
|
|
10981
|
+
}
|
|
10982
|
+
if (kind === "altana") {
|
|
10801
10983
|
return [];
|
|
10802
10984
|
}
|
|
10803
10985
|
if (process.env.WALLET_PASSWORD) {
|
|
@@ -10836,18 +11018,18 @@ async function checkLlmProviderKeySet(root, _target) {
|
|
|
10836
11018
|
function gitignoreLines(p) {
|
|
10837
11019
|
try {
|
|
10838
11020
|
return new Set(
|
|
10839
|
-
|
|
11021
|
+
fs26.readFileSync(p, "utf-8").split(/\r?\n/).map((l) => l.trim())
|
|
10840
11022
|
);
|
|
10841
11023
|
} catch {
|
|
10842
11024
|
return null;
|
|
10843
11025
|
}
|
|
10844
11026
|
}
|
|
10845
11027
|
function agentcoreEnvLocalIgnored(ws) {
|
|
10846
|
-
const wsLines = gitignoreLines(
|
|
11028
|
+
const wsLines = gitignoreLines(path25.join(ws, ".gitignore"));
|
|
10847
11029
|
if (wsLines?.has("agentcore/.env.local")) {
|
|
10848
11030
|
return true;
|
|
10849
11031
|
}
|
|
10850
|
-
const acLines = gitignoreLines(
|
|
11032
|
+
const acLines = gitignoreLines(path25.join(ws, "agentcore", ".gitignore"));
|
|
10851
11033
|
return acLines?.has(".env.local") ?? false;
|
|
10852
11034
|
}
|
|
10853
11035
|
function studioIgnored(lines) {
|
|
@@ -10858,8 +11040,8 @@ function studioIgnored(lines) {
|
|
|
10858
11040
|
}
|
|
10859
11041
|
async function checkGitignoreExcludesSecrets(root, _target) {
|
|
10860
11042
|
const out = [];
|
|
10861
|
-
const ws =
|
|
10862
|
-
const gi =
|
|
11043
|
+
const ws = path25.dirname(path25.dirname(envLocalPath11(root)));
|
|
11044
|
+
const gi = path25.join(ws, ".gitignore");
|
|
10863
11045
|
const lines = gitignoreLines(gi);
|
|
10864
11046
|
if (lines === null) {
|
|
10865
11047
|
return [
|
|
@@ -10881,7 +11063,7 @@ async function checkGitignoreExcludesSecrets(root, _target) {
|
|
|
10881
11063
|
details: { missing: [".studio/"] }
|
|
10882
11064
|
});
|
|
10883
11065
|
}
|
|
10884
|
-
if (isDir5(
|
|
11066
|
+
if (isDir5(path25.join(ws, "agentcore")) && !agentcoreEnvLocalIgnored(ws)) {
|
|
10885
11067
|
out.push({
|
|
10886
11068
|
level: Level.CRITICAL,
|
|
10887
11069
|
name: "gitignore_excludes_secrets",
|
|
@@ -10898,16 +11080,16 @@ function installedRuntimeVersion() {
|
|
|
10898
11080
|
}
|
|
10899
11081
|
try {
|
|
10900
11082
|
const entry = require2.resolve("@bnbagent/studio-runtime");
|
|
10901
|
-
let dir =
|
|
11083
|
+
let dir = path25.dirname(entry);
|
|
10902
11084
|
for (let i = 0; i < 10; i++) {
|
|
10903
|
-
const pkgPath =
|
|
10904
|
-
if (
|
|
10905
|
-
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"));
|
|
10906
11088
|
if (pkg.name === "@bnbagent/studio-runtime") {
|
|
10907
11089
|
return typeof pkg.version === "string" ? pkg.version : null;
|
|
10908
11090
|
}
|
|
10909
11091
|
}
|
|
10910
|
-
const parent =
|
|
11092
|
+
const parent = path25.dirname(dir);
|
|
10911
11093
|
if (parent === dir) {
|
|
10912
11094
|
break;
|
|
10913
11095
|
}
|
|
@@ -11191,9 +11373,9 @@ function x402SellerRailChecks(agentRoot2, cfg, target) {
|
|
|
11191
11373
|
details: { destination, target, stackRuntime: stackRuntime2 }
|
|
11192
11374
|
});
|
|
11193
11375
|
}
|
|
11194
|
-
const dockerfile =
|
|
11195
|
-
if (rails.x402 &&
|
|
11196
|
-
const source =
|
|
11376
|
+
const dockerfile = path25.join(agentRoot2, "Dockerfile");
|
|
11377
|
+
if (rails.x402 && isFile11(dockerfile)) {
|
|
11378
|
+
const source = fs26.readFileSync(dockerfile, "utf8");
|
|
11197
11379
|
if (!/^\s*FROM\s+node:22(?:[.-]|\s|$)/im.test(source)) {
|
|
11198
11380
|
out.push({
|
|
11199
11381
|
level: Level.WARNING,
|
|
@@ -11266,10 +11448,10 @@ async function checkDeployCliRunnable(_root, target) {
|
|
|
11266
11448
|
];
|
|
11267
11449
|
}
|
|
11268
11450
|
function agentcoreEnvVars(root) {
|
|
11269
|
-
const descriptor =
|
|
11451
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
11270
11452
|
let data;
|
|
11271
11453
|
try {
|
|
11272
|
-
data = JSON.parse(
|
|
11454
|
+
data = JSON.parse(fs26.readFileSync(descriptor, "utf-8"));
|
|
11273
11455
|
} catch {
|
|
11274
11456
|
return [];
|
|
11275
11457
|
}
|
|
@@ -11351,7 +11533,7 @@ async function checkRuntimeSecretsInjected(root, target) {
|
|
|
11351
11533
|
}
|
|
11352
11534
|
];
|
|
11353
11535
|
}
|
|
11354
|
-
const lines = gitignoreLines(
|
|
11536
|
+
const lines = gitignoreLines(path25.join(root, ".gitignore"));
|
|
11355
11537
|
let tracked = true;
|
|
11356
11538
|
if (lines !== null) {
|
|
11357
11539
|
for (const p of ["agentcore/agentcore.json", "agentcore/", "/agentcore/"]) {
|
|
@@ -11376,7 +11558,7 @@ async function checkAwsTargetsPopulated(root, target) {
|
|
|
11376
11558
|
if (target !== "agentcore") {
|
|
11377
11559
|
return [];
|
|
11378
11560
|
}
|
|
11379
|
-
const p =
|
|
11561
|
+
const p = path25.join(root, "agentcore", "aws-targets.json");
|
|
11380
11562
|
const [account, region] = readAwsTarget(root);
|
|
11381
11563
|
if (account && region) {
|
|
11382
11564
|
return [];
|
|
@@ -11485,6 +11667,10 @@ var allChecks = [
|
|
|
11485
11667
|
checkTwakPasswordEnvSet,
|
|
11486
11668
|
checkTwakCredentialsAvailable,
|
|
11487
11669
|
checkTwakDockerAvailable,
|
|
11670
|
+
// altana-kind checks (every one early-returns for other kinds).
|
|
11671
|
+
checkAltanaSessionReady,
|
|
11672
|
+
checkAltanaSdkResolvable,
|
|
11673
|
+
checkAltanaSessionNotInsideAgent,
|
|
11488
11674
|
checkLlmProviderKeySet,
|
|
11489
11675
|
checkGitignoreExcludesSecrets,
|
|
11490
11676
|
checkInstalledBnbagentStudioMatches,
|
|
@@ -11500,16 +11686,16 @@ var allChecks = [
|
|
|
11500
11686
|
var KEYSTORE_JSON_ENV = "WALLET_KEYSTORE_JSON";
|
|
11501
11687
|
var TWAK_WALLET_JSON_ENV = "TWAK_WALLET_JSON";
|
|
11502
11688
|
var TWAK_CREDENTIALS_JSON_ENV = "TWAK_CREDENTIALS_JSON";
|
|
11503
|
-
function
|
|
11689
|
+
function isFile12(p) {
|
|
11504
11690
|
try {
|
|
11505
|
-
return
|
|
11691
|
+
return fs27.statSync(p).isFile();
|
|
11506
11692
|
} catch {
|
|
11507
11693
|
return false;
|
|
11508
11694
|
}
|
|
11509
11695
|
}
|
|
11510
11696
|
function loadTomlOr(agentRoot2) {
|
|
11511
11697
|
try {
|
|
11512
|
-
return loadStudioToml13(
|
|
11698
|
+
return loadStudioToml13(path26.join(agentRoot2, "studio.toml"));
|
|
11513
11699
|
} catch {
|
|
11514
11700
|
return {};
|
|
11515
11701
|
}
|
|
@@ -11526,13 +11712,13 @@ function resolveKeystoreDir3(agentRoot2) {
|
|
|
11526
11712
|
const rel = String(
|
|
11527
11713
|
tableOf10(loadTomlOr(agentRoot2), "wallet").keystore_dir ?? ".studio/wallets"
|
|
11528
11714
|
);
|
|
11529
|
-
return
|
|
11715
|
+
return path26.resolve(path26.isAbsolute(rel) ? rel : path26.join(agentRoot2, rel));
|
|
11530
11716
|
}
|
|
11531
11717
|
function readKeystoreJson(agentRoot2) {
|
|
11532
11718
|
const keystoreDir = resolveKeystoreDir3(agentRoot2);
|
|
11533
11719
|
let names;
|
|
11534
11720
|
try {
|
|
11535
|
-
names =
|
|
11721
|
+
names = fs27.readdirSync(keystoreDir).filter((n) => n.endsWith(".json")).sort();
|
|
11536
11722
|
} catch {
|
|
11537
11723
|
return null;
|
|
11538
11724
|
}
|
|
@@ -11554,9 +11740,9 @@ function readKeystoreJson(agentRoot2) {
|
|
|
11554
11740
|
);
|
|
11555
11741
|
}
|
|
11556
11742
|
}
|
|
11557
|
-
const file =
|
|
11743
|
+
const file = path26.join(keystoreDir, chosen ?? names[0]);
|
|
11558
11744
|
try {
|
|
11559
|
-
return
|
|
11745
|
+
return fs27.readFileSync(file, "utf-8");
|
|
11560
11746
|
} catch {
|
|
11561
11747
|
return null;
|
|
11562
11748
|
}
|
|
@@ -11565,10 +11751,10 @@ function readEnvLocal(agentRoot2) {
|
|
|
11565
11751
|
const values = {};
|
|
11566
11752
|
try {
|
|
11567
11753
|
const file = envLocalPath12(agentRoot2);
|
|
11568
|
-
if (!
|
|
11754
|
+
if (!isFile12(file)) {
|
|
11569
11755
|
return values;
|
|
11570
11756
|
}
|
|
11571
|
-
for (const rawLine of
|
|
11757
|
+
for (const rawLine of fs27.readFileSync(file, "utf-8").split(/\r?\n/)) {
|
|
11572
11758
|
const line = rawLine.trim();
|
|
11573
11759
|
if (!line || line.startsWith("#")) {
|
|
11574
11760
|
continue;
|
|
@@ -11590,11 +11776,6 @@ function readEnvLocal(agentRoot2) {
|
|
|
11590
11776
|
}
|
|
11591
11777
|
function collectRuntimeSecretsDetailed(root) {
|
|
11592
11778
|
const agentRoot2 = findSubProjectRoot8("agent", root) ?? root;
|
|
11593
|
-
if (deployWalletKind(agentRoot2) === "altana") {
|
|
11594
|
-
throw new Error(
|
|
11595
|
-
"Altana deployment is deferred: refusing to collect either the admin keystore or runtime session for a deploy target."
|
|
11596
|
-
);
|
|
11597
|
-
}
|
|
11598
11779
|
const secretKeys = runtimeEnvKeys2(agentRoot2);
|
|
11599
11780
|
const fileValues = readEnvLocal(agentRoot2);
|
|
11600
11781
|
const payload = {};
|
|
@@ -11607,7 +11788,8 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11607
11788
|
sources[k] = fromFile ? ".studio/.env.local" : "process.env";
|
|
11608
11789
|
}
|
|
11609
11790
|
}
|
|
11610
|
-
|
|
11791
|
+
const walletKind2 = deployWalletKind(agentRoot2);
|
|
11792
|
+
if (walletKind2 === "twak") {
|
|
11611
11793
|
const [walletJson, credentialsJson] = readTwakFiles(agentRoot2);
|
|
11612
11794
|
if (walletJson) {
|
|
11613
11795
|
payload[TWAK_WALLET_JSON_ENV] = walletJson;
|
|
@@ -11617,6 +11799,9 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11617
11799
|
payload[TWAK_CREDENTIALS_JSON_ENV] = credentialsJson;
|
|
11618
11800
|
sources[TWAK_CREDENTIALS_JSON_ENV] = "wallet-file";
|
|
11619
11801
|
}
|
|
11802
|
+
} else if (walletKind2 === "altana") {
|
|
11803
|
+
payload[ALTANA_SESSION_ENV] = altanaSessionForRuntime(agentRoot2);
|
|
11804
|
+
sources[ALTANA_SESSION_ENV] = "wallet-file";
|
|
11620
11805
|
} else {
|
|
11621
11806
|
const keystoreJson = readKeystoreJson(agentRoot2);
|
|
11622
11807
|
if (keystoreJson) {
|
|
@@ -11624,7 +11809,7 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11624
11809
|
sources[KEYSTORE_JSON_ENV] = "wallet-file";
|
|
11625
11810
|
}
|
|
11626
11811
|
}
|
|
11627
|
-
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)) {
|
|
11628
11813
|
printErr(
|
|
11629
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.`
|
|
11630
11815
|
);
|
|
@@ -11656,12 +11841,12 @@ var SCOPE_NAME = "invoke";
|
|
|
11656
11841
|
var SCOPE = `${RESOURCE_SERVER_ID}/${SCOPE_NAME}`;
|
|
11657
11842
|
var COGNITO_OUTPUTS_FILE = "agentcore/cognito/cdk-outputs.json";
|
|
11658
11843
|
function emitNextSteps(result) {
|
|
11659
|
-
return `\u2713 wrote Cognito CDK app to ${
|
|
11660
|
-
- ${
|
|
11661
|
-
- ${
|
|
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)
|
|
11662
11847
|
|
|
11663
11848
|
Next steps:
|
|
11664
|
-
1. cd ${
|
|
11849
|
+
1. cd ${path27.dirname(result.appPath)}
|
|
11665
11850
|
2. npm install # aws-cdk-lib + constructs + the cdk CLI (local)
|
|
11666
11851
|
3. npx cdk deploy --outputs-file cdk-outputs.json # YOU run this (the only AWS step)
|
|
11667
11852
|
4. bag deploy provision-cognito --wire # studio reads cdk-outputs.json \u2192
|
|
@@ -11857,26 +12042,26 @@ function emitCognitoCdk(workspaceRoot, opts = {}) {
|
|
|
11857
12042
|
regionHint = null;
|
|
11858
12043
|
}
|
|
11859
12044
|
}
|
|
11860
|
-
const outDir =
|
|
11861
|
-
|
|
11862
|
-
const appPath =
|
|
11863
|
-
const readmePath =
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
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"),
|
|
11868
12053
|
cognitoPackageJson(),
|
|
11869
12054
|
"utf-8"
|
|
11870
12055
|
);
|
|
11871
|
-
|
|
12056
|
+
fs28.writeFileSync(readmePath, readme(), "utf-8");
|
|
11872
12057
|
return { appPath, readmePath };
|
|
11873
12058
|
}
|
|
11874
12059
|
function wireSummary(r) {
|
|
11875
12060
|
return `\u2713 wired Cognito authorizer from the CDK outputs (no AWS call \u2014 read a local file):
|
|
11876
|
-
- ${
|
|
12061
|
+
- ${path27.basename(r.agentcoreJson)}: authorizerConfiguration.customJwtAuthorizer
|
|
11877
12062
|
discoveryUrl = ${r.discoveryUrl}
|
|
11878
12063
|
allowedClients = [${r.clientId}]
|
|
11879
|
-
- ${
|
|
12064
|
+
- ${path27.basename(r.agentcoreJson)}: envVars[] OAUTH_TOKEN_URL + OAUTH_SCOPE (reach the runtime so the agent card advertises oauth2)
|
|
11880
12065
|
- ${r.envLocal}: same pair, for local \`bag dev\`
|
|
11881
12066
|
\u2192 NOTE: a \`bag deploy\` run provisions its own pool and overwrites these
|
|
11882
12067
|
values with the ones it issued. This wiring only feeds local \`bag dev\`.`;
|
|
@@ -11908,10 +12093,10 @@ function upsertDescriptorEnvvars(cfg, values) {
|
|
|
11908
12093
|
}
|
|
11909
12094
|
}
|
|
11910
12095
|
function syncDescriptorOauthFacts(workspaceRoot, facts) {
|
|
11911
|
-
const acj =
|
|
12096
|
+
const acj = path27.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
11912
12097
|
let cfg;
|
|
11913
12098
|
try {
|
|
11914
|
-
cfg = JSON.parse(
|
|
12099
|
+
cfg = JSON.parse(fs28.readFileSync(acj, "utf-8"));
|
|
11915
12100
|
} catch {
|
|
11916
12101
|
return;
|
|
11917
12102
|
}
|
|
@@ -11944,7 +12129,7 @@ function syncDescriptorOauthFacts(workspaceRoot, facts) {
|
|
|
11944
12129
|
}
|
|
11945
12130
|
}
|
|
11946
12131
|
try {
|
|
11947
|
-
|
|
12132
|
+
fs28.writeFileSync(acj, `${JSON.stringify(cfg, null, 2)}
|
|
11948
12133
|
`, "utf-8");
|
|
11949
12134
|
} catch {
|
|
11950
12135
|
return;
|
|
@@ -11953,8 +12138,8 @@ function syncDescriptorOauthFacts(workspaceRoot, facts) {
|
|
|
11953
12138
|
function upsertEnv(envLocal, values) {
|
|
11954
12139
|
let lines = [];
|
|
11955
12140
|
try {
|
|
11956
|
-
if (
|
|
11957
|
-
lines =
|
|
12141
|
+
if (fs28.statSync(envLocal).isFile()) {
|
|
12142
|
+
lines = fs28.readFileSync(envLocal, "utf-8").split(/\r?\n/);
|
|
11958
12143
|
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
11959
12144
|
lines.pop();
|
|
11960
12145
|
}
|
|
@@ -11973,19 +12158,19 @@ function upsertEnv(envLocal, values) {
|
|
|
11973
12158
|
lines.push(repl);
|
|
11974
12159
|
}
|
|
11975
12160
|
}
|
|
11976
|
-
|
|
11977
|
-
|
|
12161
|
+
fs28.mkdirSync(path27.dirname(envLocal), { recursive: true });
|
|
12162
|
+
fs28.writeFileSync(envLocal, `${lines.join("\n")}
|
|
11978
12163
|
`, {
|
|
11979
12164
|
encoding: "utf-8",
|
|
11980
12165
|
mode: 384
|
|
11981
12166
|
});
|
|
11982
|
-
|
|
12167
|
+
fs28.chmodSync(envLocal, 384);
|
|
11983
12168
|
}
|
|
11984
12169
|
function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
11985
|
-
const outPath = outputsFile ??
|
|
12170
|
+
const outPath = outputsFile ?? path27.join(workspaceRoot, COGNITO_OUTPUTS_FILE);
|
|
11986
12171
|
let exists = false;
|
|
11987
12172
|
try {
|
|
11988
|
-
exists =
|
|
12173
|
+
exists = fs28.statSync(outPath).isFile();
|
|
11989
12174
|
} catch {
|
|
11990
12175
|
exists = false;
|
|
11991
12176
|
}
|
|
@@ -11995,7 +12180,7 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
11995
12180
|
);
|
|
11996
12181
|
}
|
|
11997
12182
|
const outs = flattenCdkOutputs(
|
|
11998
|
-
JSON.parse(
|
|
12183
|
+
JSON.parse(fs28.readFileSync(outPath, "utf-8"))
|
|
11999
12184
|
);
|
|
12000
12185
|
for (const key of ["DiscoveryUrl", "AppClientId", "TokenUrl", "Scope"]) {
|
|
12001
12186
|
if (outs[key] === void 0) {
|
|
@@ -12008,8 +12193,8 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
12008
12193
|
const clientId = String(outs.AppClientId);
|
|
12009
12194
|
const tokenUrl = String(outs.TokenUrl);
|
|
12010
12195
|
const scope = String(outs.Scope);
|
|
12011
|
-
const acj =
|
|
12012
|
-
const cfg = JSON.parse(
|
|
12196
|
+
const acj = path27.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
12197
|
+
const cfg = JSON.parse(fs28.readFileSync(acj, "utf-8"));
|
|
12013
12198
|
const runtimes = cfg.runtimes;
|
|
12014
12199
|
if (!Array.isArray(runtimes) || runtimes.length === 0) {
|
|
12015
12200
|
throw new Error(
|
|
@@ -12032,7 +12217,7 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
12032
12217
|
OAUTH_TOKEN_URL: tokenUrl,
|
|
12033
12218
|
OAUTH_SCOPE: scope
|
|
12034
12219
|
});
|
|
12035
|
-
|
|
12220
|
+
fs28.writeFileSync(acj, `${JSON.stringify(cfg, null, 2)}
|
|
12036
12221
|
`, "utf-8");
|
|
12037
12222
|
const envLocal = envLocalPath13(workspaceRoot);
|
|
12038
12223
|
upsertEnv(envLocal, { OAUTH_TOKEN_URL: tokenUrl, OAUTH_SCOPE: scope });
|
|
@@ -12047,13 +12232,13 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
12047
12232
|
}
|
|
12048
12233
|
|
|
12049
12234
|
// src/cli/_deploy/destroy.ts
|
|
12050
|
-
import * as
|
|
12051
|
-
import * as
|
|
12235
|
+
import * as fs30 from "fs";
|
|
12236
|
+
import * as path29 from "path";
|
|
12052
12237
|
import { findSubProjectRoot as findSubProjectRoot10 } from "@bnbagent/studio-runtime/config";
|
|
12053
12238
|
|
|
12054
12239
|
// src/cli/_deploy/status.ts
|
|
12055
|
-
import * as
|
|
12056
|
-
import * as
|
|
12240
|
+
import * as fs29 from "fs";
|
|
12241
|
+
import * as path28 from "path";
|
|
12057
12242
|
import {
|
|
12058
12243
|
APP_DIR as APP_DIR2,
|
|
12059
12244
|
findSubProjectRoot as findSubProjectRoot9,
|
|
@@ -12068,20 +12253,20 @@ function loadToml(p) {
|
|
|
12068
12253
|
}
|
|
12069
12254
|
}
|
|
12070
12255
|
function projectName(workspaceRoot) {
|
|
12071
|
-
const descriptor =
|
|
12256
|
+
const descriptor = path28.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
12072
12257
|
try {
|
|
12073
|
-
const data = JSON.parse(
|
|
12258
|
+
const data = JSON.parse(fs29.readFileSync(descriptor, "utf-8"));
|
|
12074
12259
|
if (data !== null && typeof data === "object" && data.name) {
|
|
12075
12260
|
return String(data.name);
|
|
12076
12261
|
}
|
|
12077
12262
|
} catch {
|
|
12078
12263
|
}
|
|
12079
|
-
return
|
|
12264
|
+
return path28.basename(workspaceRoot);
|
|
12080
12265
|
}
|
|
12081
12266
|
async function runStatus(opts = {}) {
|
|
12082
|
-
const start = opts.projectRoot ?
|
|
12267
|
+
const start = opts.projectRoot ? path28.resolve(opts.projectRoot) : void 0;
|
|
12083
12268
|
const agentRoot2 = findSubProjectRoot9("agent", start);
|
|
12084
|
-
const agentData = agentRoot2 !== null ? loadToml(
|
|
12269
|
+
const agentData = agentRoot2 !== null ? loadToml(path28.join(agentRoot2, "studio.toml")) : {};
|
|
12085
12270
|
const deployRaw = agentData.deploy;
|
|
12086
12271
|
const deploy = deployRaw !== null && typeof deployRaw === "object" && !Array.isArray(deployRaw) ? { ...deployRaw } : {};
|
|
12087
12272
|
const runtimeArn = deploy.runtime_arn ? String(deploy.runtime_arn) : null;
|
|
@@ -12094,8 +12279,8 @@ async function runStatus(opts = {}) {
|
|
|
12094
12279
|
}
|
|
12095
12280
|
const onchainEndpoint = identity.endpoint ? String(identity.endpoint) : null;
|
|
12096
12281
|
const agentReachable = null;
|
|
12097
|
-
const workspaceBase2 = findWorkspaceRoot5(start) ?? (agentRoot2 !== null ?
|
|
12098
|
-
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;
|
|
12099
12284
|
let region = null;
|
|
12100
12285
|
let account = null;
|
|
12101
12286
|
let secretId = null;
|
|
@@ -12163,9 +12348,9 @@ function nullRecordedState(workspaceRoot) {
|
|
|
12163
12348
|
if (agentRoot2 === null) {
|
|
12164
12349
|
return;
|
|
12165
12350
|
}
|
|
12166
|
-
const ap =
|
|
12351
|
+
const ap = path29.join(agentRoot2, "studio.toml");
|
|
12167
12352
|
try {
|
|
12168
|
-
if (!
|
|
12353
|
+
if (!fs30.statSync(ap).isFile()) {
|
|
12169
12354
|
return;
|
|
12170
12355
|
}
|
|
12171
12356
|
} catch {
|
|
@@ -12229,8 +12414,8 @@ async function runDestroy(opts) {
|
|
|
12229
12414
|
}
|
|
12230
12415
|
|
|
12231
12416
|
// src/cli/_deploy/packaging.ts
|
|
12232
|
-
import * as
|
|
12233
|
-
import * as
|
|
12417
|
+
import * as fs31 from "fs";
|
|
12418
|
+
import * as path30 from "path";
|
|
12234
12419
|
import {
|
|
12235
12420
|
findSubProjectRoot as findSubProjectRoot11,
|
|
12236
12421
|
loadStudioToml as loadStudioToml15
|
|
@@ -12239,9 +12424,9 @@ function agentRootOf2(root) {
|
|
|
12239
12424
|
return findSubProjectRoot11("agent", root);
|
|
12240
12425
|
}
|
|
12241
12426
|
function agentTable(agentRoot2, key) {
|
|
12242
|
-
const tomlPath =
|
|
12427
|
+
const tomlPath = path30.join(agentRoot2, "studio.toml");
|
|
12243
12428
|
try {
|
|
12244
|
-
if (!
|
|
12429
|
+
if (!fs31.statSync(tomlPath).isFile()) {
|
|
12245
12430
|
return {};
|
|
12246
12431
|
}
|
|
12247
12432
|
} catch {
|
|
@@ -12308,10 +12493,10 @@ function checkPackagingDrift(root, destination, walletKind2, force) {
|
|
|
12308
12493
|
);
|
|
12309
12494
|
return 1;
|
|
12310
12495
|
}
|
|
12311
|
-
const dockerfile =
|
|
12496
|
+
const dockerfile = path30.join(agentRoot2, "Dockerfile");
|
|
12312
12497
|
let dockerfilePresent = false;
|
|
12313
12498
|
try {
|
|
12314
|
-
dockerfilePresent =
|
|
12499
|
+
dockerfilePresent = fs31.statSync(dockerfile).isFile();
|
|
12315
12500
|
} catch {
|
|
12316
12501
|
dockerfilePresent = false;
|
|
12317
12502
|
}
|
|
@@ -12352,7 +12537,7 @@ function deployWalletKindSafe(root) {
|
|
|
12352
12537
|
}
|
|
12353
12538
|
let cfg;
|
|
12354
12539
|
try {
|
|
12355
|
-
cfg = loadStudioToml15(
|
|
12540
|
+
cfg = loadStudioToml15(path30.join(agentRoot2, "studio.toml"));
|
|
12356
12541
|
} catch {
|
|
12357
12542
|
return "evm-local";
|
|
12358
12543
|
}
|
|
@@ -12365,22 +12550,22 @@ function deployWalletKindSafe(root) {
|
|
|
12365
12550
|
import { findStudioWorkspaceRoot as findStudioWorkspaceRoot2 } from "@bnbagent/studio-runtime/config";
|
|
12366
12551
|
|
|
12367
12552
|
// src/cli/_deploy/checks/blocked.ts
|
|
12368
|
-
import * as
|
|
12369
|
-
import * as
|
|
12553
|
+
import * as fs32 from "fs";
|
|
12554
|
+
import * as path31 from "path";
|
|
12370
12555
|
import {
|
|
12371
12556
|
findSubProjectRoot as findSubProjectRoot12,
|
|
12372
12557
|
loadStudioToml as loadStudioToml16
|
|
12373
12558
|
} from "@bnbagent/studio-runtime/config";
|
|
12374
|
-
function
|
|
12559
|
+
function isFile13(p) {
|
|
12375
12560
|
try {
|
|
12376
|
-
return
|
|
12561
|
+
return fs32.statSync(p).isFile();
|
|
12377
12562
|
} catch {
|
|
12378
12563
|
return false;
|
|
12379
12564
|
}
|
|
12380
12565
|
}
|
|
12381
12566
|
function isDir6(p) {
|
|
12382
12567
|
try {
|
|
12383
|
-
return
|
|
12568
|
+
return fs32.statSync(p).isDirectory();
|
|
12384
12569
|
} catch {
|
|
12385
12570
|
return false;
|
|
12386
12571
|
}
|
|
@@ -12391,8 +12576,8 @@ async function checkStudioTomlPresent(root, _target) {
|
|
|
12391
12576
|
agent: findSubProjectRoot12("agent", root)
|
|
12392
12577
|
};
|
|
12393
12578
|
for (const [side, subRoot] of Object.entries(layers)) {
|
|
12394
|
-
const tomlPath = subRoot === null ? null :
|
|
12395
|
-
if (tomlPath === null || !
|
|
12579
|
+
const tomlPath = subRoot === null ? null : path31.join(subRoot, "studio.toml");
|
|
12580
|
+
if (tomlPath === null || !isFile13(tomlPath)) {
|
|
12396
12581
|
out.push({
|
|
12397
12582
|
level: Level.BLOCKED,
|
|
12398
12583
|
name: "studio_toml_present",
|
|
@@ -12416,8 +12601,8 @@ async function checkStudioTomlPresent(root, _target) {
|
|
|
12416
12601
|
return out;
|
|
12417
12602
|
}
|
|
12418
12603
|
async function checkCwdIsProjectRoot(root, _target) {
|
|
12419
|
-
const cwd =
|
|
12420
|
-
const rr =
|
|
12604
|
+
const cwd = path31.resolve(process.cwd());
|
|
12605
|
+
const rr = path31.resolve(root);
|
|
12421
12606
|
if (cwd !== rr) {
|
|
12422
12607
|
return [
|
|
12423
12608
|
{
|
|
@@ -12431,7 +12616,7 @@ async function checkCwdIsProjectRoot(root, _target) {
|
|
|
12431
12616
|
return [];
|
|
12432
12617
|
}
|
|
12433
12618
|
async function checkNoSecretInGitHistory(root, _target) {
|
|
12434
|
-
if (!isDir6(
|
|
12619
|
+
if (!isDir6(path31.join(root, ".git"))) {
|
|
12435
12620
|
return [];
|
|
12436
12621
|
}
|
|
12437
12622
|
const needles = [".env.local", "WALLET_PASSWORD"];
|
|
@@ -12469,8 +12654,8 @@ var allChecks2 = [
|
|
|
12469
12654
|
];
|
|
12470
12655
|
|
|
12471
12656
|
// src/cli/_deploy/checks/info.ts
|
|
12472
|
-
import * as
|
|
12473
|
-
import * as
|
|
12657
|
+
import * as fs33 from "fs";
|
|
12658
|
+
import * as path32 from "path";
|
|
12474
12659
|
async function checkPreviousDeployStatus(root, _target) {
|
|
12475
12660
|
const deploy = tableOf2(loadAgentToml(root), "deploy");
|
|
12476
12661
|
const last = deploy.last_deploy_at;
|
|
@@ -12494,10 +12679,10 @@ async function checkPreviousDeployStatus(root, _target) {
|
|
|
12494
12679
|
];
|
|
12495
12680
|
}
|
|
12496
12681
|
async function checkInstalledRecipesList(root, _target) {
|
|
12497
|
-
const manifest =
|
|
12682
|
+
const manifest = path32.join(root, ".studio", "recipes", "manifest.json");
|
|
12498
12683
|
let exists = false;
|
|
12499
12684
|
try {
|
|
12500
|
-
exists =
|
|
12685
|
+
exists = fs33.statSync(manifest).isFile();
|
|
12501
12686
|
} catch {
|
|
12502
12687
|
exists = false;
|
|
12503
12688
|
}
|
|
@@ -12513,7 +12698,7 @@ async function checkInstalledRecipesList(root, _target) {
|
|
|
12513
12698
|
}
|
|
12514
12699
|
let data;
|
|
12515
12700
|
try {
|
|
12516
|
-
data = JSON.parse(
|
|
12701
|
+
data = JSON.parse(fs33.readFileSync(manifest, "utf-8"));
|
|
12517
12702
|
} catch {
|
|
12518
12703
|
return [
|
|
12519
12704
|
{
|
|
@@ -12616,8 +12801,8 @@ var allChecks3 = [
|
|
|
12616
12801
|
];
|
|
12617
12802
|
|
|
12618
12803
|
// src/cli/_deploy/checks/platform.ts
|
|
12619
|
-
import * as
|
|
12620
|
-
import * as
|
|
12804
|
+
import * as fs35 from "fs";
|
|
12805
|
+
import * as path34 from "path";
|
|
12621
12806
|
import {
|
|
12622
12807
|
findSubProjectRoot as findSubProjectRoot13,
|
|
12623
12808
|
loadStudioToml as loadStudioToml17
|
|
@@ -12626,16 +12811,16 @@ import { BSC_TESTNET_FAUCET_URLS } from "@bnbagent/studio-runtime/networks";
|
|
|
12626
12811
|
|
|
12627
12812
|
// src/cli/_deploy/checks/warning.ts
|
|
12628
12813
|
import * as crypto4 from "crypto";
|
|
12629
|
-
import * as
|
|
12630
|
-
import * as
|
|
12814
|
+
import * as fs34 from "fs";
|
|
12815
|
+
import * as path33 from "path";
|
|
12631
12816
|
import { envLocalPath as envLocalPath14 } from "@bnbagent/studio-runtime/config";
|
|
12632
12817
|
import { show } from "@bnbagent/studio-runtime/erc8004";
|
|
12633
12818
|
import { DEFAULT_RPC, getNetwork as getNetwork8 } from "@bnbagent/studio-runtime/networks";
|
|
12634
12819
|
import * as walletRt3 from "@bnbagent/studio-runtime/wallet";
|
|
12635
12820
|
var TBNB_MIN_WEI = 7n * 10n ** 15n;
|
|
12636
|
-
function
|
|
12821
|
+
function isFile14(p) {
|
|
12637
12822
|
try {
|
|
12638
|
-
return
|
|
12823
|
+
return fs34.statSync(p).isFile();
|
|
12639
12824
|
} catch {
|
|
12640
12825
|
return false;
|
|
12641
12826
|
}
|
|
@@ -12838,10 +13023,10 @@ async function checkRuntimeRpcReachable(root, _target) {
|
|
|
12838
13023
|
return [];
|
|
12839
13024
|
}
|
|
12840
13025
|
async function checkInstalledRecipesUnchanged(root, _target) {
|
|
12841
|
-
const manifest =
|
|
13026
|
+
const manifest = path33.join(root, ".studio", "recipes", "manifest.json");
|
|
12842
13027
|
let data;
|
|
12843
13028
|
try {
|
|
12844
|
-
data = JSON.parse(
|
|
13029
|
+
data = JSON.parse(fs34.readFileSync(manifest, "utf-8"));
|
|
12845
13030
|
} catch {
|
|
12846
13031
|
return [];
|
|
12847
13032
|
}
|
|
@@ -12856,11 +13041,11 @@ async function checkInstalledRecipesUnchanged(root, _target) {
|
|
|
12856
13041
|
if (!rel || !expected || typeof rel !== "string") {
|
|
12857
13042
|
continue;
|
|
12858
13043
|
}
|
|
12859
|
-
const p =
|
|
12860
|
-
if (!
|
|
13044
|
+
const p = path33.join(root, rel);
|
|
13045
|
+
if (!isFile14(p)) {
|
|
12861
13046
|
continue;
|
|
12862
13047
|
}
|
|
12863
|
-
const actual = crypto4.createHash("sha256").update(
|
|
13048
|
+
const actual = crypto4.createHash("sha256").update(fs34.readFileSync(p)).digest("hex");
|
|
12864
13049
|
if (actual !== expected) {
|
|
12865
13050
|
stale.push(rel);
|
|
12866
13051
|
}
|
|
@@ -12911,11 +13096,11 @@ function tableOf11(data, key) {
|
|
|
12911
13096
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
12912
13097
|
}
|
|
12913
13098
|
function agentRoot(root) {
|
|
12914
|
-
return findSubProjectRoot13("agent", root) ??
|
|
13099
|
+
return findSubProjectRoot13("agent", root) ?? path34.join(root, "app", "agent");
|
|
12915
13100
|
}
|
|
12916
13101
|
function loadAgent(root) {
|
|
12917
13102
|
try {
|
|
12918
|
-
return loadStudioToml17(
|
|
13103
|
+
return loadStudioToml17(path34.join(agentRoot(root), "studio.toml"));
|
|
12919
13104
|
} catch {
|
|
12920
13105
|
return {};
|
|
12921
13106
|
}
|
|
@@ -12935,10 +13120,10 @@ var checkPlatformEntrypointPresent = async (root, _target) => {
|
|
|
12935
13120
|
const filenames = [`${stem2}.ts`];
|
|
12936
13121
|
if (stem2 === "dualMain") filenames.push("mcpMain.ts");
|
|
12937
13122
|
const filename = filenames.find(
|
|
12938
|
-
(candidate) => !
|
|
13123
|
+
(candidate) => !fs35.existsSync(path34.join(agentRoot(root), "src", candidate))
|
|
12939
13124
|
);
|
|
12940
13125
|
if (filename === void 0) return [];
|
|
12941
|
-
const expected =
|
|
13126
|
+
const expected = path34.join(agentRoot(root), "src", filename);
|
|
12942
13127
|
return [
|
|
12943
13128
|
{
|
|
12944
13129
|
level: Level.CRITICAL,
|
|
@@ -12952,18 +13137,18 @@ var checkPlatformKeystoreNotInArtifact = async (root, _target) => {
|
|
|
12952
13137
|
const data = loadAgent(root);
|
|
12953
13138
|
const wallet = tableOf11(data, "wallet");
|
|
12954
13139
|
if (String(wallet.kind ?? "evm-local") === "twak") return [];
|
|
12955
|
-
const agent =
|
|
13140
|
+
const agent = path34.resolve(agentRoot(root));
|
|
12956
13141
|
const configured = String(wallet.keystore_dir ?? ".studio/wallets");
|
|
12957
|
-
const keystore =
|
|
13142
|
+
const keystore = path34.resolve(agent, configured);
|
|
12958
13143
|
let jsonFiles;
|
|
12959
13144
|
try {
|
|
12960
|
-
jsonFiles =
|
|
13145
|
+
jsonFiles = fs35.readdirSync(keystore).filter((name) => name.endsWith(".json"));
|
|
12961
13146
|
} catch {
|
|
12962
13147
|
return [];
|
|
12963
13148
|
}
|
|
12964
13149
|
if (jsonFiles.length === 0) return [];
|
|
12965
|
-
const rel =
|
|
12966
|
-
if (rel.startsWith("..") ||
|
|
13150
|
+
const rel = path34.relative(agent, keystore);
|
|
13151
|
+
if (rel.startsWith("..") || path34.isAbsolute(rel)) return [];
|
|
12967
13152
|
return [
|
|
12968
13153
|
{
|
|
12969
13154
|
level: Level.CRITICAL,
|
|
@@ -13190,7 +13375,7 @@ async function runProducers(producers, root, target) {
|
|
|
13190
13375
|
}
|
|
13191
13376
|
|
|
13192
13377
|
// src/cli/_deploy/verify.ts
|
|
13193
|
-
import * as
|
|
13378
|
+
import * as path36 from "path";
|
|
13194
13379
|
import {
|
|
13195
13380
|
findSubProjectRoot as findSubProjectRoot14,
|
|
13196
13381
|
loadStudioToml as loadStudioToml18
|
|
@@ -13203,11 +13388,11 @@ import {
|
|
|
13203
13388
|
import * as walletRt4 from "@bnbagent/studio-runtime/wallet";
|
|
13204
13389
|
|
|
13205
13390
|
// src/cli/_identity.ts
|
|
13206
|
-
import * as
|
|
13207
|
-
import * as
|
|
13391
|
+
import * as fs36 from "fs";
|
|
13392
|
+
import * as path35 from "path";
|
|
13208
13393
|
function writeIdentityBlock(root, identity) {
|
|
13209
|
-
const p =
|
|
13210
|
-
const text2 =
|
|
13394
|
+
const p = path35.join(root, "studio.toml");
|
|
13395
|
+
const text2 = fs36.readFileSync(p, "utf-8");
|
|
13211
13396
|
const lines = text2.split(/\r?\n/);
|
|
13212
13397
|
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
13213
13398
|
lines.pop();
|
|
@@ -13246,7 +13431,7 @@ function writeIdentityBlock(root, identity) {
|
|
|
13246
13431
|
}
|
|
13247
13432
|
}
|
|
13248
13433
|
out.push("");
|
|
13249
|
-
|
|
13434
|
+
fs36.writeFileSync(p, out.join("\n"), "utf-8");
|
|
13250
13435
|
}
|
|
13251
13436
|
|
|
13252
13437
|
// src/cli/_deploy/verify.ts
|
|
@@ -13364,7 +13549,7 @@ async function runVerify(opts) {
|
|
|
13364
13549
|
const endpoint = opts.endpoint;
|
|
13365
13550
|
const runtime = opts.runtime ?? "agentcore";
|
|
13366
13551
|
const skipRegister = opts.skipRegister ?? false;
|
|
13367
|
-
const start = opts.projectRoot ?
|
|
13552
|
+
const start = opts.projectRoot ? path36.resolve(opts.projectRoot) : void 0;
|
|
13368
13553
|
const root = findSubProjectRoot14("agent", start);
|
|
13369
13554
|
if (root === null) {
|
|
13370
13555
|
return baseResult(endpoint, runtime, {
|
|
@@ -13384,7 +13569,7 @@ async function runVerify(opts) {
|
|
|
13384
13569
|
}
|
|
13385
13570
|
let data;
|
|
13386
13571
|
try {
|
|
13387
|
-
data = loadStudioToml18(
|
|
13572
|
+
data = loadStudioToml18(path36.join(root, "studio.toml"));
|
|
13388
13573
|
} catch (exc) {
|
|
13389
13574
|
return baseResult(endpoint, runtime, {
|
|
13390
13575
|
awsAccount,
|
|
@@ -13545,8 +13730,8 @@ async function runVerify(opts) {
|
|
|
13545
13730
|
}
|
|
13546
13731
|
|
|
13547
13732
|
// src/cli/_hosted/deployOps.ts
|
|
13548
|
-
import * as
|
|
13549
|
-
import * as
|
|
13733
|
+
import * as fs37 from "fs";
|
|
13734
|
+
import * as path37 from "path";
|
|
13550
13735
|
import {
|
|
13551
13736
|
envLocalPath as envLocalPath15,
|
|
13552
13737
|
findSubProjectRoot as findSubProjectRoot15,
|
|
@@ -13557,7 +13742,12 @@ var PLATFORM_SECTION = "deploy.platform";
|
|
|
13557
13742
|
var WALLET_SECTION = "wallet";
|
|
13558
13743
|
var KEYSTORE_JSON_ENV2 = "WALLET_KEYSTORE_JSON";
|
|
13559
13744
|
var TWAK_WALLET_JSON_ENV2 = "TWAK_WALLET_JSON";
|
|
13560
|
-
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
|
+
];
|
|
13561
13751
|
var RETIRED_AGENT_STATES = /* @__PURE__ */ new Set([
|
|
13562
13752
|
"deleted",
|
|
13563
13753
|
"retired",
|
|
@@ -13587,8 +13777,8 @@ function agentTomlPath2(root) {
|
|
|
13587
13777
|
if (agentRoot2 === null) {
|
|
13588
13778
|
return null;
|
|
13589
13779
|
}
|
|
13590
|
-
const tomlPath =
|
|
13591
|
-
return
|
|
13780
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13781
|
+
return isFile15(tomlPath) ? tomlPath : null;
|
|
13592
13782
|
}
|
|
13593
13783
|
function loadAgentCfg(root) {
|
|
13594
13784
|
const tomlPath = agentTomlPath2(root);
|
|
@@ -13605,12 +13795,12 @@ function platformCfg(root) {
|
|
|
13605
13795
|
return tableOf12(tableOf12(loadAgentCfg(root), "deploy"), "platform");
|
|
13606
13796
|
}
|
|
13607
13797
|
function patchTomlKv2(tomlPath, section, key, value) {
|
|
13608
|
-
let text2 =
|
|
13798
|
+
let text2 = fs37.readFileSync(tomlPath, "utf-8");
|
|
13609
13799
|
if (!hasSection(text2, section)) {
|
|
13610
13800
|
text2 = addSection(text2, section);
|
|
13611
13801
|
}
|
|
13612
13802
|
text2 = hasKey(text2, section, key) ? setExistingKey(text2, section, key, value) : addKeyToSection(text2, section, key, value);
|
|
13613
|
-
|
|
13803
|
+
fs37.writeFileSync(tomlPath, text2);
|
|
13614
13804
|
}
|
|
13615
13805
|
function recordPlatformKv(root, key, value) {
|
|
13616
13806
|
const tomlPath = agentTomlPath2(root);
|
|
@@ -13709,8 +13899,8 @@ function clearIdentityEndpointIfMatches(root, oldUrl) {
|
|
|
13709
13899
|
}
|
|
13710
13900
|
}
|
|
13711
13901
|
function persistedPackaging2(agentRoot2) {
|
|
13712
|
-
const tomlPath =
|
|
13713
|
-
if (!
|
|
13902
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13903
|
+
if (!isFile15(tomlPath)) {
|
|
13714
13904
|
return null;
|
|
13715
13905
|
}
|
|
13716
13906
|
try {
|
|
@@ -13722,8 +13912,8 @@ function persistedPackaging2(agentRoot2) {
|
|
|
13722
13912
|
}
|
|
13723
13913
|
}
|
|
13724
13914
|
function resolvePlatformArtifact2(agentRoot2) {
|
|
13725
|
-
const tomlPath =
|
|
13726
|
-
if (
|
|
13915
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13916
|
+
if (isFile15(tomlPath)) {
|
|
13727
13917
|
try {
|
|
13728
13918
|
const cfg = loadStudioToml19(tomlPath);
|
|
13729
13919
|
const explicit = tableOf12(cfg, "deploy").platform_artifact;
|
|
@@ -13746,7 +13936,7 @@ function platformPackaging(root) {
|
|
|
13746
13936
|
}
|
|
13747
13937
|
function loadCfgAt(agentRoot2) {
|
|
13748
13938
|
try {
|
|
13749
|
-
return loadStudioToml19(
|
|
13939
|
+
return loadStudioToml19(path37.join(agentRoot2, "studio.toml"));
|
|
13750
13940
|
} catch {
|
|
13751
13941
|
return {};
|
|
13752
13942
|
}
|
|
@@ -13823,7 +14013,7 @@ function resolveSlug(root) {
|
|
|
13823
14013
|
let name = String(tableOf12(loadAgentCfg(root), "project").name ?? "");
|
|
13824
14014
|
name = name.replace(/-(agent|service)$/, "");
|
|
13825
14015
|
if (!name) {
|
|
13826
|
-
name =
|
|
14016
|
+
name = path37.basename(findWorkspaceRoot6(root) ?? root);
|
|
13827
14017
|
}
|
|
13828
14018
|
let base = name.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
13829
14019
|
base = base || "agent";
|
|
@@ -14065,6 +14255,19 @@ function walletWarning(root, secrets) {
|
|
|
14065
14255
|
return;
|
|
14066
14256
|
}
|
|
14067
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
|
+
}
|
|
14068
14271
|
const who = typeof address === "string" && address ? `key (address ${address})` : "signing key";
|
|
14069
14272
|
warn(
|
|
14070
14273
|
`
|
|
@@ -14281,15 +14484,15 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
14281
14484
|
}
|
|
14282
14485
|
function persistDeploySummary(root, text2) {
|
|
14283
14486
|
try {
|
|
14284
|
-
if (!
|
|
14487
|
+
if (!fs37.statSync(path37.resolve(root)).isDirectory()) {
|
|
14285
14488
|
return null;
|
|
14286
14489
|
}
|
|
14287
|
-
const p =
|
|
14288
|
-
|
|
14490
|
+
const p = path37.join(
|
|
14491
|
+
path37.dirname(envLocalPath15(root)),
|
|
14289
14492
|
"last-deploy-summary.txt"
|
|
14290
14493
|
);
|
|
14291
|
-
|
|
14292
|
-
|
|
14494
|
+
fs37.mkdirSync(path37.dirname(p), { recursive: true });
|
|
14495
|
+
fs37.writeFileSync(p, `${text2}
|
|
14293
14496
|
`);
|
|
14294
14497
|
return p;
|
|
14295
14498
|
} catch {
|
|
@@ -14444,9 +14647,9 @@ async function deletePlatformAgent(slug, deps = {}) {
|
|
|
14444
14647
|
}
|
|
14445
14648
|
return 0;
|
|
14446
14649
|
}
|
|
14447
|
-
function
|
|
14650
|
+
function isFile15(p) {
|
|
14448
14651
|
try {
|
|
14449
|
-
return
|
|
14652
|
+
return fs37.statSync(p).isFile();
|
|
14450
14653
|
} catch {
|
|
14451
14654
|
return false;
|
|
14452
14655
|
}
|
|
@@ -14459,16 +14662,16 @@ var ADVERTISED_DEPLOY_RUNTIME_TARGETS = ["agentcore"];
|
|
|
14459
14662
|
// src/cli/deploy.ts
|
|
14460
14663
|
var TARGET_CHOICES = [...DEPLOY_RUNTIME_TARGETS];
|
|
14461
14664
|
var ADVERTISED_TARGET_CHOICES = [...ADVERTISED_DEPLOY_RUNTIME_TARGETS];
|
|
14462
|
-
function
|
|
14665
|
+
function isFile16(p) {
|
|
14463
14666
|
try {
|
|
14464
|
-
return
|
|
14667
|
+
return fs38.statSync(p).isFile();
|
|
14465
14668
|
} catch {
|
|
14466
14669
|
return false;
|
|
14467
14670
|
}
|
|
14468
14671
|
}
|
|
14469
14672
|
function isDir7(p) {
|
|
14470
14673
|
try {
|
|
14471
|
-
return
|
|
14674
|
+
return fs38.statSync(p).isDirectory();
|
|
14472
14675
|
} catch {
|
|
14473
14676
|
return false;
|
|
14474
14677
|
}
|
|
@@ -14485,8 +14688,8 @@ function loadAgentCfg2(root) {
|
|
|
14485
14688
|
if (agentRoot2 === null) {
|
|
14486
14689
|
return null;
|
|
14487
14690
|
}
|
|
14488
|
-
const tomlPath =
|
|
14489
|
-
if (!
|
|
14691
|
+
const tomlPath = path38.join(agentRoot2, "studio.toml");
|
|
14692
|
+
if (!isFile16(tomlPath)) {
|
|
14490
14693
|
return null;
|
|
14491
14694
|
}
|
|
14492
14695
|
try {
|
|
@@ -14663,9 +14866,9 @@ function applyProjectRoot(projectRoot, requireToml = true) {
|
|
|
14663
14866
|
if (projectRoot === void 0) {
|
|
14664
14867
|
return null;
|
|
14665
14868
|
}
|
|
14666
|
-
const p =
|
|
14869
|
+
const p = path38.resolve(projectRoot);
|
|
14667
14870
|
const agentRoot2 = findSubProjectRoot16("agent", p);
|
|
14668
|
-
if (requireToml && !
|
|
14871
|
+
if (requireToml && !isFile16(path38.join(p, "studio.toml")) && (agentRoot2 === null || !isFile16(path38.join(agentRoot2, "studio.toml")))) {
|
|
14669
14872
|
printErr(`error: no studio.toml under --project-root ${p}`);
|
|
14670
14873
|
return 2;
|
|
14671
14874
|
}
|
|
@@ -14677,7 +14880,7 @@ function applyProjectRoot(projectRoot, requireToml = true) {
|
|
|
14677
14880
|
return null;
|
|
14678
14881
|
}
|
|
14679
14882
|
function resolveProjectRoot2(_projectRoot) {
|
|
14680
|
-
const cwd =
|
|
14883
|
+
const cwd = path38.resolve(process.cwd());
|
|
14681
14884
|
return findStudioWorkspaceRoot3(cwd) ?? cwd;
|
|
14682
14885
|
}
|
|
14683
14886
|
function deployWorkspaceRoot2(root) {
|
|
@@ -14743,7 +14946,7 @@ function validateRuntimeAgainstStack(target, force, root) {
|
|
|
14743
14946
|
async function cmdPrepare(opts) {
|
|
14744
14947
|
let root;
|
|
14745
14948
|
if (opts.projectRoot !== void 0) {
|
|
14746
|
-
const p =
|
|
14949
|
+
const p = path38.resolve(opts.projectRoot);
|
|
14747
14950
|
if (!isDir7(p)) {
|
|
14748
14951
|
printErr(`error: --project-root ${p} is not a directory`);
|
|
14749
14952
|
return 2;
|
|
@@ -14751,7 +14954,7 @@ async function cmdPrepare(opts) {
|
|
|
14751
14954
|
process.chdir(p);
|
|
14752
14955
|
root = findStudioWorkspaceRoot3(p) ?? p;
|
|
14753
14956
|
} else {
|
|
14754
|
-
const cwd =
|
|
14957
|
+
const cwd = path38.resolve(process.cwd());
|
|
14755
14958
|
root = findStudioWorkspaceRoot3(cwd) ?? cwd;
|
|
14756
14959
|
}
|
|
14757
14960
|
const target = resolveTarget(opts, root);
|
|
@@ -14893,8 +15096,8 @@ function writeAgentDeployState(workspaceRoot, arn, record = {}, destination = "s
|
|
|
14893
15096
|
if (agentRoot2 === null) {
|
|
14894
15097
|
return;
|
|
14895
15098
|
}
|
|
14896
|
-
const tomlPath =
|
|
14897
|
-
if (!
|
|
15099
|
+
const tomlPath = path38.join(agentRoot2, "studio.toml");
|
|
15100
|
+
if (!isFile16(tomlPath)) {
|
|
14898
15101
|
return;
|
|
14899
15102
|
}
|
|
14900
15103
|
try {
|
|
@@ -14972,10 +15175,10 @@ package and at the repo root).
|
|
|
14972
15175
|
`;
|
|
14973
15176
|
function iamNoticeTomlPath(root) {
|
|
14974
15177
|
const agentRoot2 = findSubProjectRoot16("agent", root) ?? root;
|
|
14975
|
-
return
|
|
15178
|
+
return path38.join(agentRoot2, "studio.toml");
|
|
14976
15179
|
}
|
|
14977
15180
|
function iamNoticeAccepted(tomlPath) {
|
|
14978
|
-
if (!
|
|
15181
|
+
if (!isFile16(tomlPath)) {
|
|
14979
15182
|
return false;
|
|
14980
15183
|
}
|
|
14981
15184
|
let data;
|
|
@@ -15026,7 +15229,7 @@ async function iamNoticeGate(root, acceptRisk) {
|
|
|
15026
15229
|
return 1;
|
|
15027
15230
|
}
|
|
15028
15231
|
async function buildAgentProject(agentRoot2, packaging) {
|
|
15029
|
-
if (!
|
|
15232
|
+
if (!isFile16(path38.join(agentRoot2, "package.json"))) {
|
|
15030
15233
|
printErr(
|
|
15031
15234
|
`warning: no package.json under ${agentRoot2} \u2014 skipping the agent \`pnpm build\`; bnbagent-deploy will package whatever dist/ holds.`
|
|
15032
15235
|
);
|
|
@@ -15217,12 +15420,6 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15217
15420
|
const packagingDestination = opts.to ?? opts.destination ?? agentDeployDestination(root);
|
|
15218
15421
|
const driftAgentRoot = findSubProjectRoot16("agent", root) ?? root;
|
|
15219
15422
|
const driftKind = deployWalletKind(driftAgentRoot);
|
|
15220
|
-
if (driftKind === "altana") {
|
|
15221
|
-
printErr(
|
|
15222
|
-
"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."
|
|
15223
|
-
);
|
|
15224
|
-
return 2;
|
|
15225
|
-
}
|
|
15226
15423
|
rc = checkPackagingDrift(
|
|
15227
15424
|
root,
|
|
15228
15425
|
packagingDestination,
|
|
@@ -15365,7 +15562,7 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15365
15562
|
packagingDestination,
|
|
15366
15563
|
resolvePlatformArtifact(agentRoot2)
|
|
15367
15564
|
) === "container" ? "container" : "zip";
|
|
15368
|
-
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";
|
|
15369
15566
|
if (secretsMode === "envvars") {
|
|
15370
15567
|
printErr(
|
|
15371
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.`
|
|
@@ -15483,7 +15680,7 @@ function recordedEndpoint(root) {
|
|
|
15483
15680
|
}
|
|
15484
15681
|
function recordedAgentId(agentRoot2) {
|
|
15485
15682
|
try {
|
|
15486
|
-
const cfg = loadStudioToml20(
|
|
15683
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15487
15684
|
const val = tableOf13(cfg, "identity").agent_id;
|
|
15488
15685
|
return val !== void 0 && val !== null && val !== "" ? String(val) : null;
|
|
15489
15686
|
} catch {
|
|
@@ -15492,7 +15689,7 @@ function recordedAgentId(agentRoot2) {
|
|
|
15492
15689
|
}
|
|
15493
15690
|
function recordedRuntimeArn(agentRoot2) {
|
|
15494
15691
|
try {
|
|
15495
|
-
const cfg = loadStudioToml20(
|
|
15692
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15496
15693
|
const val = tableOf13(cfg, "deploy").runtime_arn;
|
|
15497
15694
|
return val ? String(val) : null;
|
|
15498
15695
|
} catch {
|
|
@@ -15501,7 +15698,7 @@ function recordedRuntimeArn(agentRoot2) {
|
|
|
15501
15698
|
}
|
|
15502
15699
|
function recordedOauthClientId(agentRoot2) {
|
|
15503
15700
|
try {
|
|
15504
|
-
const cfg = loadStudioToml20(
|
|
15701
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15505
15702
|
const val = tableOf13(cfg, "deploy").oauth_client_id;
|
|
15506
15703
|
return val ? String(val) : null;
|
|
15507
15704
|
} catch {
|
|
@@ -15510,7 +15707,7 @@ function recordedOauthClientId(agentRoot2) {
|
|
|
15510
15707
|
}
|
|
15511
15708
|
function agentFacesOf(agentRoot2) {
|
|
15512
15709
|
try {
|
|
15513
|
-
const cfg = loadStudioToml20(
|
|
15710
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15514
15711
|
return stackFaces(tableOf13(cfg, "stack"), tableOf13(cfg, "payments"));
|
|
15515
15712
|
} catch {
|
|
15516
15713
|
return ["A2A"];
|
|
@@ -15662,15 +15859,15 @@ async function printAgentClientPrompt2(root, destination, opts = {}) {
|
|
|
15662
15859
|
}
|
|
15663
15860
|
function persistDeploySummary2(root, text2) {
|
|
15664
15861
|
try {
|
|
15665
|
-
if (!
|
|
15862
|
+
if (!fs38.statSync(path38.resolve(root)).isDirectory()) {
|
|
15666
15863
|
return null;
|
|
15667
15864
|
}
|
|
15668
|
-
const p =
|
|
15669
|
-
|
|
15865
|
+
const p = path38.join(
|
|
15866
|
+
path38.dirname(envLocalPath16(root)),
|
|
15670
15867
|
"last-deploy-summary.txt"
|
|
15671
15868
|
);
|
|
15672
|
-
|
|
15673
|
-
|
|
15869
|
+
fs38.mkdirSync(path38.dirname(p), { recursive: true });
|
|
15870
|
+
fs38.writeFileSync(p, `${text2}
|
|
15674
15871
|
`, "utf-8");
|
|
15675
15872
|
return p;
|
|
15676
15873
|
} catch {
|
|
@@ -16067,9 +16264,9 @@ async function cmdDestroy(opts) {
|
|
|
16067
16264
|
return 2;
|
|
16068
16265
|
}
|
|
16069
16266
|
const answer = await promptUser(
|
|
16070
|
-
`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: `
|
|
16071
16268
|
);
|
|
16072
|
-
if (answer.trim() !==
|
|
16269
|
+
if (answer.trim() !== path38.basename(workspaceRoot)) {
|
|
16073
16270
|
printErr(
|
|
16074
16271
|
"error: confirmation did not match the project name; aborting."
|
|
16075
16272
|
);
|
|
@@ -16185,8 +16382,8 @@ async function cmdProvisionCognito(opts) {
|
|
|
16185
16382
|
|
|
16186
16383
|
// src/cli/doctor.ts
|
|
16187
16384
|
import * as crypto5 from "crypto";
|
|
16188
|
-
import * as
|
|
16189
|
-
import * as
|
|
16385
|
+
import * as fs39 from "fs";
|
|
16386
|
+
import * as path39 from "path";
|
|
16190
16387
|
import { EVMWalletProvider as EVMWalletProvider2 } from "@bnbagent/sdk";
|
|
16191
16388
|
import {
|
|
16192
16389
|
envLocalPath as envLocalPath17,
|
|
@@ -16232,23 +16429,23 @@ function tableOf14(cfg, key) {
|
|
|
16232
16429
|
const v = cfg[key];
|
|
16233
16430
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
16234
16431
|
}
|
|
16235
|
-
function
|
|
16432
|
+
function isFile17(p) {
|
|
16236
16433
|
try {
|
|
16237
|
-
return
|
|
16434
|
+
return fs39.statSync(p).isFile();
|
|
16238
16435
|
} catch {
|
|
16239
16436
|
return false;
|
|
16240
16437
|
}
|
|
16241
16438
|
}
|
|
16242
16439
|
function isDir8(p) {
|
|
16243
16440
|
try {
|
|
16244
|
-
return
|
|
16441
|
+
return fs39.statSync(p).isDirectory();
|
|
16245
16442
|
} catch {
|
|
16246
16443
|
return false;
|
|
16247
16444
|
}
|
|
16248
16445
|
}
|
|
16249
16446
|
function keystoreJsons(dir) {
|
|
16250
16447
|
try {
|
|
16251
|
-
return
|
|
16448
|
+
return fs39.readdirSync(dir).filter((f) => f.endsWith(".json")).sort();
|
|
16252
16449
|
} catch {
|
|
16253
16450
|
return [];
|
|
16254
16451
|
}
|
|
@@ -16277,7 +16474,7 @@ async function cmdDoctor(opts) {
|
|
|
16277
16474
|
if (opts.checkEnv) {
|
|
16278
16475
|
return runCheckEnv(projectRoot);
|
|
16279
16476
|
}
|
|
16280
|
-
const tomlPath =
|
|
16477
|
+
const tomlPath = path39.join(projectRoot, "studio.toml");
|
|
16281
16478
|
let data;
|
|
16282
16479
|
try {
|
|
16283
16480
|
data = loadStudioToml21(tomlPath);
|
|
@@ -16313,8 +16510,8 @@ async function cmdDoctor(opts) {
|
|
|
16313
16510
|
}
|
|
16314
16511
|
function resolveProjectRoot3(argRoot) {
|
|
16315
16512
|
if (argRoot !== void 0) {
|
|
16316
|
-
const root2 =
|
|
16317
|
-
if (!
|
|
16513
|
+
const root2 = path39.resolve(argRoot);
|
|
16514
|
+
if (!isFile17(path39.join(root2, "studio.toml"))) {
|
|
16318
16515
|
printErr(`error: no studio.toml under --project-root ${root2}`);
|
|
16319
16516
|
return null;
|
|
16320
16517
|
}
|
|
@@ -16328,15 +16525,15 @@ function resolveProjectRoot3(argRoot) {
|
|
|
16328
16525
|
return root;
|
|
16329
16526
|
}
|
|
16330
16527
|
function runCheckEnv(projectRoot) {
|
|
16331
|
-
const agentDir = workspaceLayers(projectRoot) ??
|
|
16528
|
+
const agentDir = workspaceLayers(projectRoot) ?? path39.join(projectRoot, "agent");
|
|
16332
16529
|
const envPath = envLocalPath17(agentDir);
|
|
16333
16530
|
printOut(`bag doctor --check-env: ${envPath}`);
|
|
16334
|
-
if (!
|
|
16335
|
-
printOut(` (no ${
|
|
16531
|
+
if (!isFile17(envPath)) {
|
|
16532
|
+
printOut(` (no ${path39.basename(envPath)} found \u2014 nothing to report)`);
|
|
16336
16533
|
return 0;
|
|
16337
16534
|
}
|
|
16338
16535
|
const values = {};
|
|
16339
|
-
for (const rawLine of
|
|
16536
|
+
for (const rawLine of fs39.readFileSync(envPath, "utf-8").split(/\r?\n/)) {
|
|
16340
16537
|
const line = rawLine.trim();
|
|
16341
16538
|
if (!line || line.startsWith("#") || !line.includes("=")) {
|
|
16342
16539
|
continue;
|
|
@@ -16363,25 +16560,25 @@ function runCheckEnv(projectRoot) {
|
|
|
16363
16560
|
return 0;
|
|
16364
16561
|
}
|
|
16365
16562
|
function workspaceLayers(projectRoot) {
|
|
16366
|
-
const parent =
|
|
16367
|
-
if (
|
|
16368
|
-
return
|
|
16563
|
+
const parent = path39.dirname(projectRoot);
|
|
16564
|
+
if (isFile17(path39.join(parent, "agent", "studio.toml"))) {
|
|
16565
|
+
return path39.join(parent, "agent");
|
|
16369
16566
|
}
|
|
16370
|
-
if (
|
|
16371
|
-
return
|
|
16567
|
+
if (isFile17(path39.join(projectRoot, "agent", "studio.toml"))) {
|
|
16568
|
+
return path39.join(projectRoot, "agent");
|
|
16372
16569
|
}
|
|
16373
16570
|
return null;
|
|
16374
16571
|
}
|
|
16375
16572
|
function checkAppMain(projectRootArg) {
|
|
16376
16573
|
let projectRoot = projectRootArg;
|
|
16377
|
-
const parent =
|
|
16378
|
-
if (
|
|
16574
|
+
const parent = path39.dirname(projectRoot);
|
|
16575
|
+
if (isFile17(path39.join(parent, "agent", "studio.toml"))) {
|
|
16379
16576
|
projectRoot = parent;
|
|
16380
16577
|
}
|
|
16381
|
-
const agentDir =
|
|
16578
|
+
const agentDir = path39.join(projectRoot, "agent");
|
|
16382
16579
|
let config = {};
|
|
16383
|
-
const tomlPath =
|
|
16384
|
-
if (
|
|
16580
|
+
const tomlPath = path39.join(agentDir, "studio.toml");
|
|
16581
|
+
if (isFile17(tomlPath)) {
|
|
16385
16582
|
try {
|
|
16386
16583
|
config = loadStudioToml21(tomlPath);
|
|
16387
16584
|
} catch {
|
|
@@ -16399,8 +16596,8 @@ function checkAppMain(projectRootArg) {
|
|
|
16399
16596
|
} else {
|
|
16400
16597
|
entrypoint = "src/main.ts";
|
|
16401
16598
|
}
|
|
16402
|
-
const entryFile =
|
|
16403
|
-
if (!
|
|
16599
|
+
const entryFile = path39.join(agentDir, entrypoint);
|
|
16600
|
+
if (!isFile17(entryFile)) {
|
|
16404
16601
|
return [
|
|
16405
16602
|
{
|
|
16406
16603
|
name: "agent entrypoint",
|
|
@@ -16415,12 +16612,12 @@ function checkAppMain(projectRootArg) {
|
|
|
16415
16612
|
function checkAgentcoreName(projectRoot) {
|
|
16416
16613
|
let cfgPath = null;
|
|
16417
16614
|
for (const candidate of [
|
|
16418
|
-
|
|
16419
|
-
|
|
16615
|
+
path39.dirname(path39.dirname(projectRoot)),
|
|
16616
|
+
path39.dirname(projectRoot),
|
|
16420
16617
|
projectRoot
|
|
16421
16618
|
]) {
|
|
16422
|
-
const p =
|
|
16423
|
-
if (
|
|
16619
|
+
const p = path39.join(candidate, "agentcore", "agentcore.json");
|
|
16620
|
+
if (isFile17(p)) {
|
|
16424
16621
|
cfgPath = p;
|
|
16425
16622
|
break;
|
|
16426
16623
|
}
|
|
@@ -16430,7 +16627,7 @@ function checkAgentcoreName(projectRoot) {
|
|
|
16430
16627
|
}
|
|
16431
16628
|
let cfg;
|
|
16432
16629
|
try {
|
|
16433
|
-
cfg = JSON.parse(
|
|
16630
|
+
cfg = JSON.parse(fs39.readFileSync(cfgPath, "utf-8"));
|
|
16434
16631
|
} catch {
|
|
16435
16632
|
return [];
|
|
16436
16633
|
}
|
|
@@ -16462,7 +16659,7 @@ function isLocalEvmWallet(walletCfg) {
|
|
|
16462
16659
|
}
|
|
16463
16660
|
function anchoredKeystoreDir(projectRoot, walletCfg) {
|
|
16464
16661
|
const rel = String(walletCfg.keystore_dir ?? ".studio/wallets");
|
|
16465
|
-
return
|
|
16662
|
+
return path39.isAbsolute(rel) ? rel : path39.join(projectRoot, rel);
|
|
16466
16663
|
}
|
|
16467
16664
|
async function checkWallet(projectRoot, data) {
|
|
16468
16665
|
const walletCfg = tableOf14(data, "wallet");
|
|
@@ -16508,8 +16705,8 @@ async function checkWallet(projectRoot, data) {
|
|
|
16508
16705
|
}
|
|
16509
16706
|
const address = String(walletCfg.address ?? "").trim();
|
|
16510
16707
|
if (address) {
|
|
16511
|
-
const expected =
|
|
16512
|
-
if (!
|
|
16708
|
+
const expected = path39.join(keystoreDir, `${address}.json`);
|
|
16709
|
+
if (!isFile17(expected)) {
|
|
16513
16710
|
out.push({
|
|
16514
16711
|
name: "[wallet] address \u2194 keystore",
|
|
16515
16712
|
status: FAIL,
|
|
@@ -16519,7 +16716,7 @@ async function checkWallet(projectRoot, data) {
|
|
|
16519
16716
|
out.push({
|
|
16520
16717
|
name: "[wallet] address \u2194 keystore",
|
|
16521
16718
|
status: PASS,
|
|
16522
|
-
detail: `${address} matches ${
|
|
16719
|
+
detail: `${address} matches ${path39.basename(expected)}`
|
|
16523
16720
|
});
|
|
16524
16721
|
}
|
|
16525
16722
|
}
|
|
@@ -16536,9 +16733,9 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16536
16733
|
detail: "no [wallet].address \u2014 run `bag wallet new` first"
|
|
16537
16734
|
});
|
|
16538
16735
|
} else {
|
|
16539
|
-
const expected =
|
|
16736
|
+
const expected = path39.join(keystoreDir, `${address}.json`);
|
|
16540
16737
|
out.push(
|
|
16541
|
-
|
|
16738
|
+
isFile17(expected) ? {
|
|
16542
16739
|
name: "[wallet] Altana admin",
|
|
16543
16740
|
status: PASS,
|
|
16544
16741
|
detail: `${address} matches ${expected}`
|
|
@@ -16552,8 +16749,8 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16552
16749
|
const configured = String(
|
|
16553
16750
|
walletCfg.session_file ?? ".studio/wallets/altana-session.json"
|
|
16554
16751
|
);
|
|
16555
|
-
const sessionFile =
|
|
16556
|
-
if (!
|
|
16752
|
+
const sessionFile = path39.isAbsolute(configured) ? configured : path39.join(projectRoot, configured);
|
|
16753
|
+
if (!isFile17(sessionFile)) {
|
|
16557
16754
|
out.push({
|
|
16558
16755
|
name: "[wallet] Altana session",
|
|
16559
16756
|
status: FAIL,
|
|
@@ -16563,7 +16760,7 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16563
16760
|
}
|
|
16564
16761
|
let envelope;
|
|
16565
16762
|
try {
|
|
16566
|
-
envelope = JSON.parse(
|
|
16763
|
+
envelope = JSON.parse(fs39.readFileSync(sessionFile, "utf8"));
|
|
16567
16764
|
} catch {
|
|
16568
16765
|
out.push({
|
|
16569
16766
|
name: "[wallet] Altana session",
|
|
@@ -16589,7 +16786,7 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16589
16786
|
status: remaining <= 0 ? FAIL : remaining < 3 * 24 * 60 * 60 ? WARN : PASS,
|
|
16590
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\``
|
|
16591
16788
|
});
|
|
16592
|
-
if ((
|
|
16789
|
+
if ((fs39.statSync(sessionFile).mode & 63) !== 0) {
|
|
16593
16790
|
out.push({
|
|
16594
16791
|
name: "[wallet] Altana session permissions",
|
|
16595
16792
|
status: WARN,
|
|
@@ -16647,7 +16844,7 @@ async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
|
16647
16844
|
});
|
|
16648
16845
|
}
|
|
16649
16846
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
16650
|
-
if (
|
|
16847
|
+
if (isFile17(walletFile)) {
|
|
16651
16848
|
out.push({
|
|
16652
16849
|
name: "[wallet] twak wallet",
|
|
16653
16850
|
status: PASS,
|
|
@@ -16657,7 +16854,7 @@ async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
|
16657
16854
|
let createCmd = "twak wallet create --password <pw> --no-keychain";
|
|
16658
16855
|
let setupCmd = "twak setup";
|
|
16659
16856
|
if (walletCfg.twak_home) {
|
|
16660
|
-
const home =
|
|
16857
|
+
const home = path39.dirname(path39.dirname(walletFile));
|
|
16661
16858
|
createCmd = `HOME=${home} ${createCmd}`;
|
|
16662
16859
|
setupCmd = `HOME=${home} ${setupCmd}`;
|
|
16663
16860
|
}
|
|
@@ -17413,11 +17610,11 @@ function checkAgentsMdSkillTrigger(projectRoot) {
|
|
|
17413
17610
|
if (ws === null) {
|
|
17414
17611
|
return [];
|
|
17415
17612
|
}
|
|
17416
|
-
const agentsMd =
|
|
17613
|
+
const agentsMd = path39.join(ws, "AGENTS.md");
|
|
17417
17614
|
const line = "For any bnbagent-studio task (deploy, sell, operate, debug), load the `/bnbagent-studio` skill first.";
|
|
17418
17615
|
let text2;
|
|
17419
17616
|
try {
|
|
17420
|
-
text2 =
|
|
17617
|
+
text2 = isFile17(agentsMd) ? fs39.readFileSync(agentsMd, "utf-8") : null;
|
|
17421
17618
|
} catch {
|
|
17422
17619
|
return [];
|
|
17423
17620
|
}
|
|
@@ -17454,8 +17651,8 @@ function printChecks(checks) {
|
|
|
17454
17651
|
}
|
|
17455
17652
|
|
|
17456
17653
|
// src/cli/env.ts
|
|
17457
|
-
import * as
|
|
17458
|
-
import * as
|
|
17654
|
+
import * as fs40 from "fs";
|
|
17655
|
+
import * as path40 from "path";
|
|
17459
17656
|
var SECRET_KEY_PARTS = ["PASSWORD", "SECRET", "TOKEN", "API_KEY"];
|
|
17460
17657
|
var WALLET_PASSWORD_KEYS = /* @__PURE__ */ new Set([
|
|
17461
17658
|
"WALLET_PASSWORD",
|
|
@@ -17501,8 +17698,8 @@ function resolveEnvPath(fileArg, rootArg) {
|
|
|
17501
17698
|
return [fileArg, null];
|
|
17502
17699
|
}
|
|
17503
17700
|
if (rootArg !== void 0) {
|
|
17504
|
-
const root2 =
|
|
17505
|
-
if (!
|
|
17701
|
+
const root2 = path40.resolve(rootArg);
|
|
17702
|
+
if (!fs40.existsSync(path40.join(root2, "studio.toml"))) {
|
|
17506
17703
|
return [null, `error: no studio.toml under --project-root ${root2}`];
|
|
17507
17704
|
}
|
|
17508
17705
|
return [envLocalPath(root2), null];
|
|
@@ -17513,7 +17710,7 @@ function resolveEnvPath(fileArg, rootArg) {
|
|
|
17513
17710
|
}
|
|
17514
17711
|
const target = envLocalPath(root);
|
|
17515
17712
|
let note = null;
|
|
17516
|
-
if (
|
|
17713
|
+
if (path40.dirname(path40.dirname(target)) !== path40.resolve(process.cwd())) {
|
|
17517
17714
|
note = `\u2192 writing to ${target} (workspace .studio/, where \`bag dev\` reads)`;
|
|
17518
17715
|
}
|
|
17519
17716
|
return [target, note];
|
|
@@ -17570,7 +17767,7 @@ function cmdGet2(key, fileArg, rootArg) {
|
|
|
17570
17767
|
}
|
|
17571
17768
|
|
|
17572
17769
|
// src/cli/erc8004.ts
|
|
17573
|
-
import * as
|
|
17770
|
+
import * as path41 from "path";
|
|
17574
17771
|
import { auditedOp as auditedOp3 } from "@bnbagent/studio-runtime/audit";
|
|
17575
17772
|
import {
|
|
17576
17773
|
findProjectRoot as findProjectRoot5,
|
|
@@ -17580,7 +17777,7 @@ import {
|
|
|
17580
17777
|
import {
|
|
17581
17778
|
getMetadata,
|
|
17582
17779
|
register as register2,
|
|
17583
|
-
resolve as
|
|
17780
|
+
resolve as resolve21,
|
|
17584
17781
|
setMetadata,
|
|
17585
17782
|
show as show2,
|
|
17586
17783
|
updateServiceEndpoint as updateServiceEndpoint2
|
|
@@ -17691,7 +17888,7 @@ function loadAgentCfg3() {
|
|
|
17691
17888
|
return null;
|
|
17692
17889
|
}
|
|
17693
17890
|
try {
|
|
17694
|
-
return loadStudioToml22(
|
|
17891
|
+
return loadStudioToml22(path41.join(root, "studio.toml"));
|
|
17695
17892
|
} catch {
|
|
17696
17893
|
return null;
|
|
17697
17894
|
}
|
|
@@ -17769,7 +17966,7 @@ function loadIdentityBlock(agentRoot2) {
|
|
|
17769
17966
|
try {
|
|
17770
17967
|
return {
|
|
17771
17968
|
...tableOf15(
|
|
17772
|
-
loadStudioToml22(
|
|
17969
|
+
loadStudioToml22(path41.join(agentRoot2, "studio.toml")),
|
|
17773
17970
|
"identity"
|
|
17774
17971
|
)
|
|
17775
17972
|
};
|
|
@@ -18108,7 +18305,7 @@ async function cmdResolve(agentId, networkArg) {
|
|
|
18108
18305
|
const wallet = walletRt6.getWallet();
|
|
18109
18306
|
let uri;
|
|
18110
18307
|
try {
|
|
18111
|
-
uri = await
|
|
18308
|
+
uri = await resolve21(agentId, {
|
|
18112
18309
|
wallet,
|
|
18113
18310
|
network: resolveNetwork2(networkArg)
|
|
18114
18311
|
});
|
|
@@ -18121,8 +18318,8 @@ async function cmdResolve(agentId, networkArg) {
|
|
|
18121
18318
|
}
|
|
18122
18319
|
|
|
18123
18320
|
// src/cli/erc8183.ts
|
|
18124
|
-
import * as
|
|
18125
|
-
import * as
|
|
18321
|
+
import * as fs41 from "fs";
|
|
18322
|
+
import * as path42 from "path";
|
|
18126
18323
|
import { JobStatus } from "@bnbagent/sdk";
|
|
18127
18324
|
import {
|
|
18128
18325
|
buyWorkflow,
|
|
@@ -18226,8 +18423,8 @@ function applyProjectRoot2(root) {
|
|
|
18226
18423
|
if (root === void 0) {
|
|
18227
18424
|
return null;
|
|
18228
18425
|
}
|
|
18229
|
-
const p =
|
|
18230
|
-
if (!
|
|
18426
|
+
const p = path42.resolve(root);
|
|
18427
|
+
if (!fs41.existsSync(path42.join(p, "studio.toml"))) {
|
|
18231
18428
|
printErr(`error: no studio.toml under --project-root ${p}`);
|
|
18232
18429
|
return 2;
|
|
18233
18430
|
}
|
|
@@ -18312,7 +18509,7 @@ function parseQuoteEnvelope(raw) {
|
|
|
18312
18509
|
let text2 = trimmed;
|
|
18313
18510
|
if (!trimmed.startsWith("{")) {
|
|
18314
18511
|
try {
|
|
18315
|
-
text2 =
|
|
18512
|
+
text2 = fs41.readFileSync(trimmed, "utf-8");
|
|
18316
18513
|
} catch (exc) {
|
|
18317
18514
|
throw new Error(
|
|
18318
18515
|
`--quote-json is neither inline JSON nor a readable file: ${errMsg5(exc)}`
|
|
@@ -18492,9 +18689,9 @@ async function cmdSettle(jobId, opts) {
|
|
|
18492
18689
|
}
|
|
18493
18690
|
|
|
18494
18691
|
// src/cli/skills.ts
|
|
18495
|
-
import * as
|
|
18692
|
+
import * as fs42 from "fs";
|
|
18496
18693
|
import * as os6 from "os";
|
|
18497
|
-
import * as
|
|
18694
|
+
import * as path43 from "path";
|
|
18498
18695
|
import { Option as Option7 } from "commander";
|
|
18499
18696
|
function registerSkills(program) {
|
|
18500
18697
|
const skills = program.command("skills").description("Install Claude Code skills into the host IDE.").action(
|
|
@@ -18540,7 +18737,7 @@ function cmdList4() {
|
|
|
18540
18737
|
for (const p of listSourceSkills(
|
|
18541
18738
|
SKILLS_SOURCE
|
|
18542
18739
|
)) {
|
|
18543
|
-
printOut(
|
|
18740
|
+
printOut(path43.basename(p));
|
|
18544
18741
|
}
|
|
18545
18742
|
const refs = listSourceReferences(
|
|
18546
18743
|
SKILLS_SOURCE
|
|
@@ -18551,7 +18748,7 @@ function cmdList4() {
|
|
|
18551
18748
|
references (installed under ${ROUTER_SKILL_NAME}/references/, loaded on demand by the skills above):`
|
|
18552
18749
|
);
|
|
18553
18750
|
for (const p of refs) {
|
|
18554
|
-
printOut(` ${
|
|
18751
|
+
printOut(` ${path43.basename(p)}`);
|
|
18555
18752
|
}
|
|
18556
18753
|
}
|
|
18557
18754
|
return 0;
|
|
@@ -18763,7 +18960,7 @@ function installTargets(targets, scope) {
|
|
|
18763
18960
|
);
|
|
18764
18961
|
for (const name of result.legacyPresent) {
|
|
18765
18962
|
const leaf = result.target === "cursor" ? `${name}.mdc` : name;
|
|
18766
|
-
printErr(` - ${
|
|
18963
|
+
printErr(` - ${path43.join(result.targetDir, leaf)}`);
|
|
18767
18964
|
}
|
|
18768
18965
|
printErr(
|
|
18769
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."
|
|
@@ -18776,19 +18973,19 @@ function studioSkillNames() {
|
|
|
18776
18973
|
for (const p of listSourceSkills(
|
|
18777
18974
|
SKILLS_SOURCE
|
|
18778
18975
|
)) {
|
|
18779
|
-
names.add(
|
|
18976
|
+
names.add(path43.basename(p).replace(/\.md$/, ""));
|
|
18780
18977
|
}
|
|
18781
18978
|
for (const name of LEGACY_SKILL_NAMES) {
|
|
18782
18979
|
names.add(name);
|
|
18783
18980
|
}
|
|
18784
|
-
const providersRoot =
|
|
18981
|
+
const providersRoot = path43.join(bundledRecipesRoot(), "providers");
|
|
18785
18982
|
if (isDir9(providersRoot)) {
|
|
18786
|
-
for (const provider of
|
|
18787
|
-
const skillDir =
|
|
18983
|
+
for (const provider of fs42.readdirSync(providersRoot)) {
|
|
18984
|
+
const skillDir = path43.join(providersRoot, provider, "skills");
|
|
18788
18985
|
if (!isDir9(skillDir)) {
|
|
18789
18986
|
continue;
|
|
18790
18987
|
}
|
|
18791
|
-
for (const md of
|
|
18988
|
+
for (const md of fs42.readdirSync(skillDir)) {
|
|
18792
18989
|
if (md.endsWith(".md")) {
|
|
18793
18990
|
names.add(md.replace(/\.md$/, ""));
|
|
18794
18991
|
}
|
|
@@ -18799,14 +18996,14 @@ function studioSkillNames() {
|
|
|
18799
18996
|
}
|
|
18800
18997
|
function isDir9(p) {
|
|
18801
18998
|
try {
|
|
18802
|
-
return
|
|
18999
|
+
return fs42.statSync(p).isDirectory();
|
|
18803
19000
|
} catch {
|
|
18804
19001
|
return false;
|
|
18805
19002
|
}
|
|
18806
19003
|
}
|
|
18807
|
-
function
|
|
19004
|
+
function isFile18(p) {
|
|
18808
19005
|
try {
|
|
18809
|
-
return
|
|
19006
|
+
return fs42.statSync(p).isFile();
|
|
18810
19007
|
} catch {
|
|
18811
19008
|
return false;
|
|
18812
19009
|
}
|
|
@@ -18820,26 +19017,26 @@ function findInstalledSkills(knownNames) {
|
|
|
18820
19017
|
if (!isDir9(root)) {
|
|
18821
19018
|
return;
|
|
18822
19019
|
}
|
|
18823
|
-
const resolved =
|
|
18824
|
-
if (!roots.some((r) =>
|
|
19020
|
+
const resolved = fs42.realpathSync(root);
|
|
19021
|
+
if (!roots.some((r) => fs42.realpathSync(r) === resolved)) {
|
|
18825
19022
|
roots.push(root);
|
|
18826
19023
|
}
|
|
18827
19024
|
};
|
|
18828
|
-
addRoot(
|
|
18829
|
-
addRoot(
|
|
18830
|
-
addRoot(
|
|
18831
|
-
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"));
|
|
18832
19029
|
for (const root of roots) {
|
|
18833
|
-
const isCursor =
|
|
19030
|
+
const isCursor = path43.basename(root) === "rules" && path43.basename(path43.dirname(root)) === ".cursor";
|
|
18834
19031
|
for (const name of [...knownNames].sort()) {
|
|
18835
|
-
const target =
|
|
18836
|
-
if (isCursor &&
|
|
19032
|
+
const target = path43.join(root, isCursor ? `${name}.mdc` : name);
|
|
19033
|
+
if (isCursor && isFile18(target)) {
|
|
18837
19034
|
found.push(target);
|
|
18838
19035
|
} else if (!isCursor && isDir9(target)) {
|
|
18839
19036
|
found.push(target);
|
|
18840
19037
|
}
|
|
18841
|
-
if (isCursor && isDir9(
|
|
18842
|
-
found.push(
|
|
19038
|
+
if (isCursor && isDir9(path43.join(root, name))) {
|
|
19039
|
+
found.push(path43.join(root, name));
|
|
18843
19040
|
}
|
|
18844
19041
|
}
|
|
18845
19042
|
}
|
|
@@ -18867,7 +19064,7 @@ async function cmdUninstall(flags) {
|
|
|
18867
19064
|
}
|
|
18868
19065
|
}
|
|
18869
19066
|
for (const p of installed) {
|
|
18870
|
-
|
|
19067
|
+
fs42.rmSync(p, { recursive: true, force: true });
|
|
18871
19068
|
printOut(` removed: ${p}`);
|
|
18872
19069
|
}
|
|
18873
19070
|
}
|
|
@@ -18906,7 +19103,7 @@ function registerUninstall(program) {
|
|
|
18906
19103
|
}
|
|
18907
19104
|
|
|
18908
19105
|
// src/cli/platform.ts
|
|
18909
|
-
import * as
|
|
19106
|
+
import * as path44 from "path";
|
|
18910
19107
|
import {
|
|
18911
19108
|
STUDIO_TOML as STUDIO_TOML2,
|
|
18912
19109
|
findSubProjectRoot as findSubProjectRoot18,
|
|
@@ -19109,7 +19306,7 @@ function localPlatformCfg() {
|
|
|
19109
19306
|
if (agentRoot2 === null) {
|
|
19110
19307
|
return [null, {}];
|
|
19111
19308
|
}
|
|
19112
|
-
const tomlPath =
|
|
19309
|
+
const tomlPath = path44.join(agentRoot2, STUDIO_TOML2);
|
|
19113
19310
|
let cfg;
|
|
19114
19311
|
try {
|
|
19115
19312
|
cfg = loadStudioToml23(tomlPath);
|
|
@@ -19182,8 +19379,8 @@ function formatRemaining(seconds) {
|
|
|
19182
19379
|
}
|
|
19183
19380
|
|
|
19184
19381
|
// src/cli/recipe.ts
|
|
19185
|
-
import * as
|
|
19186
|
-
import * as
|
|
19382
|
+
import * as fs43 from "fs";
|
|
19383
|
+
import * as path45 from "path";
|
|
19187
19384
|
import { parse as parse6 } from "smol-toml";
|
|
19188
19385
|
function registerRecipe(program) {
|
|
19189
19386
|
const p = program.command("recipe").description("Print recipe code/files (agent / wallet / 8004).");
|
|
@@ -19313,7 +19510,7 @@ function resolvePkgContext(explicit) {
|
|
|
19313
19510
|
let data;
|
|
19314
19511
|
try {
|
|
19315
19512
|
data = parse6(
|
|
19316
|
-
|
|
19513
|
+
fs43.readFileSync(path45.join(projectRoot, "studio.toml"), "utf-8")
|
|
19317
19514
|
);
|
|
19318
19515
|
} catch {
|
|
19319
19516
|
return [null, null];
|
|
@@ -19331,8 +19528,8 @@ function resolvePkgContext(explicit) {
|
|
|
19331
19528
|
}
|
|
19332
19529
|
|
|
19333
19530
|
// src/cli/scan.ts
|
|
19334
|
-
import * as
|
|
19335
|
-
import * as
|
|
19531
|
+
import * as fs44 from "fs";
|
|
19532
|
+
import * as path46 from "path";
|
|
19336
19533
|
import { Option as Option8 } from "commander";
|
|
19337
19534
|
import { parse as parse7 } from "smol-toml";
|
|
19338
19535
|
function registerScan(program) {
|
|
@@ -19349,7 +19546,7 @@ function registerScan(program) {
|
|
|
19349
19546
|
"note: `--json` is deprecated (JSON is the default output); ignoring."
|
|
19350
19547
|
);
|
|
19351
19548
|
}
|
|
19352
|
-
const root =
|
|
19549
|
+
const root = path46.resolve(opts.path ?? process.cwd());
|
|
19353
19550
|
const report = scanProject(root);
|
|
19354
19551
|
if (opts.text) {
|
|
19355
19552
|
process.stdout.write(formatText(report));
|
|
@@ -19361,26 +19558,26 @@ function registerScan(program) {
|
|
|
19361
19558
|
})
|
|
19362
19559
|
);
|
|
19363
19560
|
}
|
|
19364
|
-
function
|
|
19561
|
+
function isFile19(p) {
|
|
19365
19562
|
try {
|
|
19366
|
-
return
|
|
19563
|
+
return fs44.statSync(p).isFile();
|
|
19367
19564
|
} catch {
|
|
19368
19565
|
return false;
|
|
19369
19566
|
}
|
|
19370
19567
|
}
|
|
19371
19568
|
function isDir10(p) {
|
|
19372
19569
|
try {
|
|
19373
|
-
return
|
|
19570
|
+
return fs44.statSync(p).isDirectory();
|
|
19374
19571
|
} catch {
|
|
19375
19572
|
return false;
|
|
19376
19573
|
}
|
|
19377
19574
|
}
|
|
19378
19575
|
function layerBase(root) {
|
|
19379
|
-
return isDir10(
|
|
19576
|
+
return isDir10(path46.join(root, "app", "agent")) ? path46.join(root, "app") : root;
|
|
19380
19577
|
}
|
|
19381
19578
|
function safeReadJson(p) {
|
|
19382
19579
|
try {
|
|
19383
|
-
const data = JSON.parse(
|
|
19580
|
+
const data = JSON.parse(fs44.readFileSync(p, "utf-8"));
|
|
19384
19581
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
19385
19582
|
} catch {
|
|
19386
19583
|
return null;
|
|
@@ -19388,7 +19585,7 @@ function safeReadJson(p) {
|
|
|
19388
19585
|
}
|
|
19389
19586
|
function safeReadToml(p) {
|
|
19390
19587
|
try {
|
|
19391
|
-
return parse7(
|
|
19588
|
+
return parse7(fs44.readFileSync(p, "utf-8"));
|
|
19392
19589
|
} catch {
|
|
19393
19590
|
return null;
|
|
19394
19591
|
}
|
|
@@ -19418,33 +19615,33 @@ function resolvePackageName(projectName2, root) {
|
|
|
19418
19615
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(candidate)) {
|
|
19419
19616
|
return null;
|
|
19420
19617
|
}
|
|
19421
|
-
if (!isDir10(
|
|
19618
|
+
if (!isDir10(path46.join(root, candidate))) {
|
|
19422
19619
|
return null;
|
|
19423
19620
|
}
|
|
19424
19621
|
return candidate;
|
|
19425
19622
|
}
|
|
19426
19623
|
function inferLayout(root) {
|
|
19427
|
-
const agentDir =
|
|
19428
|
-
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"));
|
|
19429
19626
|
return {
|
|
19430
19627
|
has_agent: hasAgent,
|
|
19431
|
-
has_agent_descriptor:
|
|
19432
|
-
|
|
19628
|
+
has_agent_descriptor: isFile19(
|
|
19629
|
+
path46.join(root, "agentcore", "agentcore.json")
|
|
19433
19630
|
),
|
|
19434
19631
|
role: hasAgent ? "agent" : "none"
|
|
19435
19632
|
};
|
|
19436
19633
|
}
|
|
19437
19634
|
function inferPackageManager(root, hasPackageJson) {
|
|
19438
|
-
if (
|
|
19635
|
+
if (isFile19(path46.join(root, "pnpm-lock.yaml"))) {
|
|
19439
19636
|
return "pnpm";
|
|
19440
19637
|
}
|
|
19441
|
-
if (
|
|
19638
|
+
if (isFile19(path46.join(root, "yarn.lock"))) {
|
|
19442
19639
|
return "yarn";
|
|
19443
19640
|
}
|
|
19444
|
-
if (
|
|
19641
|
+
if (isFile19(path46.join(root, "bun.lockb"))) {
|
|
19445
19642
|
return "bun";
|
|
19446
19643
|
}
|
|
19447
|
-
if (
|
|
19644
|
+
if (isFile19(path46.join(root, "package-lock.json"))) {
|
|
19448
19645
|
return "npm";
|
|
19449
19646
|
}
|
|
19450
19647
|
if (hasPackageJson) {
|
|
@@ -19457,7 +19654,7 @@ function inferRecipes(root, studioData, layout) {
|
|
|
19457
19654
|
if (layout.has_agent) {
|
|
19458
19655
|
recipes.push("agent");
|
|
19459
19656
|
}
|
|
19460
|
-
const walletsDir =
|
|
19657
|
+
const walletsDir = path46.join(root, ".studio", "wallets");
|
|
19461
19658
|
const walletSection = studioData?.wallet;
|
|
19462
19659
|
const hasWalletSection = walletSection !== null && typeof walletSection === "object" && !Array.isArray(walletSection);
|
|
19463
19660
|
if (isDir10(walletsDir) && hasWalletSection) {
|
|
@@ -19466,13 +19663,13 @@ function inferRecipes(root, studioData, layout) {
|
|
|
19466
19663
|
return recipes;
|
|
19467
19664
|
}
|
|
19468
19665
|
function scanProject(root) {
|
|
19469
|
-
const studioToml =
|
|
19470
|
-
const packageJson =
|
|
19471
|
-
const agentcoreJson =
|
|
19472
|
-
const hasStudioToml =
|
|
19473
|
-
const hasPackageJson =
|
|
19474
|
-
const hasAgentcoreJson =
|
|
19475
|
-
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"));
|
|
19476
19673
|
const pkgData = hasPackageJson ? safeReadJson(packageJson) : null;
|
|
19477
19674
|
const studioData = hasStudioToml ? safeReadToml(studioToml) : null;
|
|
19478
19675
|
const rawName = pkgData?.name;
|
|
@@ -19529,8 +19726,8 @@ function formatText(report) {
|
|
|
19529
19726
|
}
|
|
19530
19727
|
|
|
19531
19728
|
// src/cli/x402.ts
|
|
19532
|
-
import * as
|
|
19533
|
-
import * as
|
|
19729
|
+
import * as fs45 from "fs";
|
|
19730
|
+
import * as path47 from "path";
|
|
19534
19731
|
import { auditedOp as auditedOp4 } from "@bnbagent/studio-runtime/audit";
|
|
19535
19732
|
import {
|
|
19536
19733
|
envLocalPath as envLocalPath18,
|
|
@@ -19724,7 +19921,7 @@ function loadX402Policy() {
|
|
|
19724
19921
|
}
|
|
19725
19922
|
let cfg;
|
|
19726
19923
|
try {
|
|
19727
|
-
cfg = loadStudioToml24(
|
|
19924
|
+
cfg = loadStudioToml24(path47.join(root, "studio.toml"));
|
|
19728
19925
|
} catch (exc) {
|
|
19729
19926
|
printErr(`error: failed to parse studio.toml: ${errMsg6(exc)}`);
|
|
19730
19927
|
return null;
|
|
@@ -19738,7 +19935,7 @@ function loadSellerConfig() {
|
|
|
19738
19935
|
return null;
|
|
19739
19936
|
}
|
|
19740
19937
|
try {
|
|
19741
|
-
return [root, loadStudioToml24(
|
|
19938
|
+
return [root, loadStudioToml24(path47.join(root, "studio.toml"))];
|
|
19742
19939
|
} catch (exc) {
|
|
19743
19940
|
printErr(`error: failed to parse studio.toml: ${errMsg6(exc)}`);
|
|
19744
19941
|
return null;
|
|
@@ -19784,8 +19981,8 @@ async function cmdSellInit(priceFlag) {
|
|
|
19784
19981
|
const loaded = loadSellerConfig();
|
|
19785
19982
|
if (loaded === null) return 1;
|
|
19786
19983
|
const [root, cfg] = loaded;
|
|
19787
|
-
const tomlPath =
|
|
19788
|
-
const original =
|
|
19984
|
+
const tomlPath = path47.join(root, "studio.toml");
|
|
19985
|
+
const original = fs45.readFileSync(tomlPath, "utf8");
|
|
19789
19986
|
const sellerExists = hasSection(original, "payments.x402_seller");
|
|
19790
19987
|
let priceUsd;
|
|
19791
19988
|
try {
|
|
@@ -19803,7 +20000,7 @@ async function cmdSellInit(priceFlag) {
|
|
|
19803
20000
|
return 1;
|
|
19804
20001
|
}
|
|
19805
20002
|
if (!sellerExists) {
|
|
19806
|
-
|
|
20003
|
+
fs45.writeFileSync(
|
|
19807
20004
|
tomlPath,
|
|
19808
20005
|
updateSection(original, "payments.x402_seller", {
|
|
19809
20006
|
enabled: true,
|
|
@@ -19815,7 +20012,7 @@ async function cmdSellInit(priceFlag) {
|
|
|
19815
20012
|
"utf8"
|
|
19816
20013
|
);
|
|
19817
20014
|
} else if (priceFlag !== void 0) {
|
|
19818
|
-
|
|
20015
|
+
fs45.writeFileSync(
|
|
19819
20016
|
tomlPath,
|
|
19820
20017
|
updateSection(original, "payments.x402_seller", {
|
|
19821
20018
|
price_usd: priceUsd
|
|
@@ -20184,14 +20381,14 @@ async function confirmOrAbort(prompt, assumeYes) {
|
|
|
20184
20381
|
return answer === "y" || answer === "yes";
|
|
20185
20382
|
}
|
|
20186
20383
|
function writeMerchantEntry(tomlPath, fields) {
|
|
20187
|
-
const text2 =
|
|
20384
|
+
const text2 = fs45.readFileSync(tomlPath, "utf-8");
|
|
20188
20385
|
const entries = {
|
|
20189
20386
|
domain: fields.domain,
|
|
20190
20387
|
pay_to: fields.payTo,
|
|
20191
20388
|
per_call_cap_usd: fields.capUsd,
|
|
20192
20389
|
verified: fields.verified
|
|
20193
20390
|
};
|
|
20194
|
-
|
|
20391
|
+
fs45.writeFileSync(
|
|
20195
20392
|
tomlPath,
|
|
20196
20393
|
updateSection(text2, `payments.x402.merchants.${fields.key}`, entries),
|
|
20197
20394
|
"utf-8"
|
|
@@ -20320,7 +20517,7 @@ The merchant may have rotated its address (or the response was tampered with). U
|
|
|
20320
20517
|
printOut("aborted \u2014 nothing written.");
|
|
20321
20518
|
return 1;
|
|
20322
20519
|
}
|
|
20323
|
-
const tomlPath =
|
|
20520
|
+
const tomlPath = path47.join(root, "studio.toml");
|
|
20324
20521
|
try {
|
|
20325
20522
|
writeMerchantEntry(tomlPath, {
|
|
20326
20523
|
key,
|
|
@@ -20383,23 +20580,23 @@ function buildProgram() {
|
|
|
20383
20580
|
return program;
|
|
20384
20581
|
}
|
|
20385
20582
|
function cliVersion() {
|
|
20386
|
-
return "0.0.6-alpha.
|
|
20583
|
+
return "0.0.6-alpha.8";
|
|
20387
20584
|
}
|
|
20388
20585
|
|
|
20389
20586
|
// src/cli/updateCheck.ts
|
|
20390
|
-
import * as
|
|
20587
|
+
import * as fs46 from "fs";
|
|
20391
20588
|
import * as os7 from "os";
|
|
20392
|
-
import * as
|
|
20589
|
+
import * as path48 from "path";
|
|
20393
20590
|
var PACKAGE = "@bnbagent/studio-cli";
|
|
20394
20591
|
var REGISTRY_LATEST_URL = `https://registry.npmjs.org/${PACKAGE}/latest`;
|
|
20395
20592
|
var CHECK_INTERVAL_SECONDS = 24 * 3600;
|
|
20396
20593
|
var TIMEOUT_MS = 2e3;
|
|
20397
20594
|
function cachePath(home) {
|
|
20398
|
-
return
|
|
20595
|
+
return path48.join(home, ".bag", "update-check.json");
|
|
20399
20596
|
}
|
|
20400
20597
|
function loadCache(home) {
|
|
20401
20598
|
try {
|
|
20402
|
-
const data = JSON.parse(
|
|
20599
|
+
const data = JSON.parse(fs46.readFileSync(cachePath(home), "utf-8"));
|
|
20403
20600
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : {};
|
|
20404
20601
|
} catch {
|
|
20405
20602
|
return {};
|
|
@@ -20408,8 +20605,8 @@ function loadCache(home) {
|
|
|
20408
20605
|
function saveCache(state, home) {
|
|
20409
20606
|
try {
|
|
20410
20607
|
const p = cachePath(home);
|
|
20411
|
-
|
|
20412
|
-
|
|
20608
|
+
fs46.mkdirSync(path48.dirname(p), { recursive: true });
|
|
20609
|
+
fs46.writeFileSync(p, `${JSON.stringify(state, null, 2)}
|
|
20413
20610
|
`);
|
|
20414
20611
|
} catch {
|
|
20415
20612
|
}
|