@bnbagent/studio-cli 0.0.6-alpha.7 → 0.0.6-alpha.9
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 +965 -740
- 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 +43 -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,
|
|
@@ -4361,7 +4533,17 @@ function printUBalanceShortfall(walletAddress, currentRaw, neededRaw, neededUsd,
|
|
|
4361
4533
|
function writeEnvLocal(key, value, envPath = ".env.local") {
|
|
4362
4534
|
return setEnvVar(envPath, key, value);
|
|
4363
4535
|
}
|
|
4536
|
+
function ensureSiweCapable(wallet) {
|
|
4537
|
+
const probe = wallet.supports;
|
|
4538
|
+
if (typeof probe !== "function") return;
|
|
4539
|
+
if (probe.call(wallet, "sign.message")) return;
|
|
4540
|
+
const kind = wallet.kind;
|
|
4541
|
+
throw new PieverseCliError(
|
|
4542
|
+
`the ${kind ? `'${kind}' ` : ""}wallet cannot log in to Pieverse: SIWE requires an EIP-191 personal-sign ('sign.message'), which this wallet kind never supports. Pieverse LLM is not usable with this wallet \u2014 set [llm].provider in studio.toml to 'openrouter', 'openai', or 'anthropic' (with the matching API key in .studio/.env.local), or use an 'evm-local' or 'twak' wallet.`
|
|
4543
|
+
);
|
|
4544
|
+
}
|
|
4364
4545
|
async function withSiweRetry(wallet, call, opts = {}) {
|
|
4546
|
+
ensureSiweCapable(wallet);
|
|
4365
4547
|
let token = opts.sessionToken ?? await siweLogin(wallet);
|
|
4366
4548
|
try {
|
|
4367
4549
|
return await call(token);
|
|
@@ -4548,7 +4730,7 @@ function loadFullCfg() {
|
|
|
4548
4730
|
}
|
|
4549
4731
|
let cfg;
|
|
4550
4732
|
try {
|
|
4551
|
-
cfg = loadStudioToml8(
|
|
4733
|
+
cfg = loadStudioToml8(path18.join(root, "studio.toml"));
|
|
4552
4734
|
} catch (exc) {
|
|
4553
4735
|
printErr(`error: failed to parse studio.toml: ${errMessage(exc)}`);
|
|
4554
4736
|
return null;
|
|
@@ -4629,6 +4811,15 @@ async function cmdActivate(opts) {
|
|
|
4629
4811
|
if (wallet === null) {
|
|
4630
4812
|
return 2;
|
|
4631
4813
|
}
|
|
4814
|
+
try {
|
|
4815
|
+
ensureSiweCapable(wallet);
|
|
4816
|
+
} catch (exc) {
|
|
4817
|
+
if (exc instanceof PieverseCliError) {
|
|
4818
|
+
printErr(`error: ${exc.message}`);
|
|
4819
|
+
return 2;
|
|
4820
|
+
}
|
|
4821
|
+
throw exc;
|
|
4822
|
+
}
|
|
4632
4823
|
const pvCfg = loadPieverseConfig(cfg);
|
|
4633
4824
|
const replace = opts.replace === true;
|
|
4634
4825
|
let existingHash = !replace && pvCfg.key_hash ? String(pvCfg.key_hash) : null;
|
|
@@ -4652,6 +4843,10 @@ async function cmdActivate(opts) {
|
|
|
4652
4843
|
try {
|
|
4653
4844
|
await withSiweRetry(wallet, (token) => inspectKey(token, derivedHash));
|
|
4654
4845
|
} catch (exc) {
|
|
4846
|
+
if (exc instanceof PieverseCliError) {
|
|
4847
|
+
printErr(`error: ${exc.message}`);
|
|
4848
|
+
return 2;
|
|
4849
|
+
}
|
|
4655
4850
|
if (!(exc instanceof PieverseKeyNotFoundError)) {
|
|
4656
4851
|
printErr(
|
|
4657
4852
|
`error: could not verify the existing ${PIEVERSE_ENV_KEY} against Pieverse: ${errMessage(
|
|
@@ -4910,9 +5105,9 @@ Retry: re-run \`bag llm activate\` \u2014 key_hash is saved so it will pick up w
|
|
|
4910
5105
|
return 0;
|
|
4911
5106
|
}
|
|
4912
5107
|
function updateStudioTomlSection(root, section, updates) {
|
|
4913
|
-
const tomlPath =
|
|
4914
|
-
const text2 =
|
|
4915
|
-
|
|
5108
|
+
const tomlPath = path18.join(root, "studio.toml");
|
|
5109
|
+
const text2 = fs19.readFileSync(tomlPath, "utf-8");
|
|
5110
|
+
fs19.writeFileSync(tomlPath, updateSection(text2, section, updates), "utf-8");
|
|
4916
5111
|
}
|
|
4917
5112
|
function cumulativeTopupsUsd() {
|
|
4918
5113
|
let total = 0;
|
|
@@ -5461,8 +5656,8 @@ function normalizeNodeDeps(deps) {
|
|
|
5461
5656
|
}
|
|
5462
5657
|
|
|
5463
5658
|
// src/cli/recipes/loader.ts
|
|
5464
|
-
import * as
|
|
5465
|
-
import * as
|
|
5659
|
+
import * as fs20 from "fs";
|
|
5660
|
+
import * as path19 from "path";
|
|
5466
5661
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
5467
5662
|
import { parse as parse5 } from "smol-toml";
|
|
5468
5663
|
var PLACEHOLDER_RE = /\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
|
|
@@ -5471,12 +5666,12 @@ function bundledRecipesRoot() {
|
|
|
5471
5666
|
if (override) {
|
|
5472
5667
|
return override;
|
|
5473
5668
|
}
|
|
5474
|
-
let dir =
|
|
5669
|
+
let dir = path19.dirname(fileURLToPath3(import.meta.url));
|
|
5475
5670
|
for (; ; ) {
|
|
5476
|
-
if (
|
|
5477
|
-
return
|
|
5671
|
+
if (fs20.existsSync(path19.join(dir, "package.json"))) {
|
|
5672
|
+
return path19.join(dir, "recipes");
|
|
5478
5673
|
}
|
|
5479
|
-
const parent =
|
|
5674
|
+
const parent = path19.dirname(dir);
|
|
5480
5675
|
if (parent === dir) {
|
|
5481
5676
|
throw new Error("cannot locate the studio-cli package root");
|
|
5482
5677
|
}
|
|
@@ -5500,24 +5695,24 @@ function defaultMode(recipe) {
|
|
|
5500
5695
|
}
|
|
5501
5696
|
function listRecipes(root) {
|
|
5502
5697
|
const base = root ?? bundledRecipesRoot();
|
|
5503
|
-
if (!
|
|
5698
|
+
if (!fs20.existsSync(base)) {
|
|
5504
5699
|
return [];
|
|
5505
5700
|
}
|
|
5506
|
-
return
|
|
5507
|
-
(name) => !name.startsWith("_") &&
|
|
5701
|
+
return fs20.readdirSync(base).filter(
|
|
5702
|
+
(name) => !name.startsWith("_") && fs20.existsSync(path19.join(base, name, "recipe.toml")) && fs20.statSync(path19.join(base, name)).isDirectory()
|
|
5508
5703
|
).sort();
|
|
5509
5704
|
}
|
|
5510
5705
|
var RecipeModeError = class extends Error {
|
|
5511
5706
|
};
|
|
5512
5707
|
function loadRecipe(name, opts = {}) {
|
|
5513
5708
|
const base = opts.root ?? bundledRecipesRoot();
|
|
5514
|
-
const recipeDir =
|
|
5515
|
-
const tomlPath =
|
|
5516
|
-
if (!
|
|
5709
|
+
const recipeDir = path19.join(base, name);
|
|
5710
|
+
const tomlPath = path19.join(recipeDir, "recipe.toml");
|
|
5711
|
+
if (!fs20.existsSync(tomlPath) || !fs20.statSync(tomlPath).isFile()) {
|
|
5517
5712
|
throw new Error(`Recipe '${name}' not found at ${tomlPath}`);
|
|
5518
5713
|
}
|
|
5519
|
-
const metadata = parse5(
|
|
5520
|
-
const allFiles = collectTemplateFiles(
|
|
5714
|
+
const metadata = parse5(fs20.readFileSync(tomlPath, "utf-8"));
|
|
5715
|
+
const allFiles = collectTemplateFiles(path19.join(recipeDir, "code"));
|
|
5521
5716
|
const modesMeta = metaTable(metadata, "modes");
|
|
5522
5717
|
const mode = opts.mode ?? null;
|
|
5523
5718
|
if (Object.keys(modesMeta).length === 0) {
|
|
@@ -5564,22 +5759,22 @@ function modeFiles(modesMeta, modeName) {
|
|
|
5564
5759
|
return Array.isArray(files) ? files.filter((f) => typeof f === "string") : [];
|
|
5565
5760
|
}
|
|
5566
5761
|
function collectTemplateFiles(codeDir) {
|
|
5567
|
-
if (!
|
|
5762
|
+
if (!fs20.existsSync(codeDir) || !fs20.statSync(codeDir).isDirectory()) {
|
|
5568
5763
|
return [];
|
|
5569
5764
|
}
|
|
5570
5765
|
const out = [];
|
|
5571
5766
|
const walk = (dir) => {
|
|
5572
|
-
for (const name of
|
|
5573
|
-
const full =
|
|
5574
|
-
if (
|
|
5767
|
+
for (const name of fs20.readdirSync(dir).sort()) {
|
|
5768
|
+
const full = path19.join(dir, name);
|
|
5769
|
+
if (fs20.statSync(full).isDirectory()) {
|
|
5575
5770
|
walk(full);
|
|
5576
5771
|
} else {
|
|
5577
|
-
const rel =
|
|
5772
|
+
const rel = path19.relative(codeDir, full);
|
|
5578
5773
|
const target = rel.endsWith(".tmpl") ? rel.slice(0, -".tmpl".length) : rel;
|
|
5579
5774
|
out.push({
|
|
5580
5775
|
// Recipes use forward slashes regardless of host OS.
|
|
5581
|
-
targetPath: target.split(
|
|
5582
|
-
content:
|
|
5776
|
+
targetPath: target.split(path19.sep).join("/"),
|
|
5777
|
+
content: fs20.readFileSync(full, "utf-8")
|
|
5583
5778
|
});
|
|
5584
5779
|
}
|
|
5585
5780
|
}
|
|
@@ -5646,9 +5841,9 @@ function renderRecipe(recipe, opts = {}) {
|
|
|
5646
5841
|
|
|
5647
5842
|
// src/cli/skillsInstaller.ts
|
|
5648
5843
|
import * as crypto3 from "crypto";
|
|
5649
|
-
import * as
|
|
5844
|
+
import * as fs21 from "fs";
|
|
5650
5845
|
import * as os2 from "os";
|
|
5651
|
-
import * as
|
|
5846
|
+
import * as path20 from "path";
|
|
5652
5847
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
5653
5848
|
var SUPPORTED_TARGETS = ["claude-code", "cursor"];
|
|
5654
5849
|
var SUPPORTED_SCOPES = ["user", "project"];
|
|
@@ -5695,14 +5890,14 @@ var HIDDEN_SKILL_NAMES = /* @__PURE__ */ new Set([
|
|
|
5695
5890
|
]);
|
|
5696
5891
|
function isDir3(p) {
|
|
5697
5892
|
try {
|
|
5698
|
-
return
|
|
5893
|
+
return fs21.statSync(p).isDirectory();
|
|
5699
5894
|
} catch {
|
|
5700
5895
|
return false;
|
|
5701
5896
|
}
|
|
5702
5897
|
}
|
|
5703
|
-
function
|
|
5898
|
+
function isFile7(p) {
|
|
5704
5899
|
try {
|
|
5705
|
-
return
|
|
5900
|
+
return fs21.statSync(p).isFile();
|
|
5706
5901
|
} catch {
|
|
5707
5902
|
return false;
|
|
5708
5903
|
}
|
|
@@ -5712,15 +5907,15 @@ function sha256(text2) {
|
|
|
5712
5907
|
}
|
|
5713
5908
|
function resolveSkillsSource() {
|
|
5714
5909
|
const pkgRoot = packageRoot2();
|
|
5715
|
-
return pkgRoot !== null ?
|
|
5910
|
+
return pkgRoot !== null ? path20.join(pkgRoot, "skills") : path20.join(path20.dirname(fileURLToPath4(import.meta.url)), "skills");
|
|
5716
5911
|
}
|
|
5717
5912
|
function packageRoot2() {
|
|
5718
|
-
let dir =
|
|
5913
|
+
let dir = path20.dirname(fileURLToPath4(import.meta.url));
|
|
5719
5914
|
for (; ; ) {
|
|
5720
|
-
if (
|
|
5915
|
+
if (fs21.existsSync(path20.join(dir, "package.json"))) {
|
|
5721
5916
|
return dir;
|
|
5722
5917
|
}
|
|
5723
|
-
const parent =
|
|
5918
|
+
const parent = path20.dirname(dir);
|
|
5724
5919
|
if (parent === dir) {
|
|
5725
5920
|
return null;
|
|
5726
5921
|
}
|
|
@@ -5732,18 +5927,18 @@ function listSourceSkills(source) {
|
|
|
5732
5927
|
if (!isDir3(source)) {
|
|
5733
5928
|
return [];
|
|
5734
5929
|
}
|
|
5735
|
-
return
|
|
5736
|
-
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) &&
|
|
5737
|
-
).sort().map((name) =>
|
|
5930
|
+
return fs21.readdirSync(source).filter(
|
|
5931
|
+
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) && isFile7(path20.join(source, name))
|
|
5932
|
+
).sort().map((name) => path20.join(source, name));
|
|
5738
5933
|
}
|
|
5739
5934
|
function listSourceReferences(source) {
|
|
5740
|
-
const refs =
|
|
5935
|
+
const refs = path20.join(source, "references");
|
|
5741
5936
|
if (!isDir3(refs)) {
|
|
5742
5937
|
return [];
|
|
5743
5938
|
}
|
|
5744
|
-
return
|
|
5745
|
-
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) &&
|
|
5746
|
-
).sort().map((name) =>
|
|
5939
|
+
return fs21.readdirSync(refs).filter(
|
|
5940
|
+
(name) => name.endsWith(".md") && !name.startsWith("_") && !HIDDEN_SKILL_NAMES.has(stem(name)) && isFile7(path20.join(refs, name))
|
|
5941
|
+
).sort().map((name) => path20.join(refs, name));
|
|
5747
5942
|
}
|
|
5748
5943
|
function stem(fileName) {
|
|
5749
5944
|
return fileName.replace(/\.[^.]+$/, "");
|
|
@@ -5751,15 +5946,15 @@ function stem(fileName) {
|
|
|
5751
5946
|
function whichSync(name) {
|
|
5752
5947
|
const pathEnv = process.env.PATH ?? "";
|
|
5753
5948
|
const exts = process.platform === "win32" ? ["", ".cmd", ".exe", ".bat"] : [""];
|
|
5754
|
-
for (const dir of pathEnv.split(
|
|
5949
|
+
for (const dir of pathEnv.split(path20.delimiter)) {
|
|
5755
5950
|
if (!dir) {
|
|
5756
5951
|
continue;
|
|
5757
5952
|
}
|
|
5758
5953
|
for (const ext of exts) {
|
|
5759
|
-
const candidate =
|
|
5954
|
+
const candidate = path20.join(dir, name + ext);
|
|
5760
5955
|
try {
|
|
5761
|
-
|
|
5762
|
-
if (
|
|
5956
|
+
fs21.accessSync(candidate, fs21.constants.X_OK);
|
|
5957
|
+
if (fs21.statSync(candidate).isFile()) {
|
|
5763
5958
|
return candidate;
|
|
5764
5959
|
}
|
|
5765
5960
|
} catch {
|
|
@@ -5770,14 +5965,14 @@ function whichSync(name) {
|
|
|
5770
5965
|
}
|
|
5771
5966
|
function claudeCodeInstalled(opts = {}) {
|
|
5772
5967
|
const home = opts.home ?? os2.homedir();
|
|
5773
|
-
if (isDir3(
|
|
5968
|
+
if (isDir3(path20.join(home, ".claude"))) {
|
|
5774
5969
|
return true;
|
|
5775
5970
|
}
|
|
5776
5971
|
return (opts.which ?? whichSync)("claude") !== null;
|
|
5777
5972
|
}
|
|
5778
5973
|
function cursorInstalled(opts = {}) {
|
|
5779
5974
|
const home = opts.home ?? os2.homedir();
|
|
5780
|
-
if (isDir3(
|
|
5975
|
+
if (isDir3(path20.join(home, ".cursor"))) {
|
|
5781
5976
|
return true;
|
|
5782
5977
|
}
|
|
5783
5978
|
return (opts.which ?? whichSync)("cursor") !== null;
|
|
@@ -5800,9 +5995,9 @@ function anySkillsInstalled(opts = {}) {
|
|
|
5800
5995
|
for (const target of detectTargets(opts)) {
|
|
5801
5996
|
const tdir = resolveTargetDir({ target, scope: "user", home: opts.home });
|
|
5802
5997
|
for (const skill of sources) {
|
|
5803
|
-
const name = stem(
|
|
5804
|
-
const rel = target === "claude-code" ?
|
|
5805
|
-
if (
|
|
5998
|
+
const name = stem(path20.basename(skill));
|
|
5999
|
+
const rel = target === "claude-code" ? path20.join(name, "SKILL.md") : `${name}.mdc`;
|
|
6000
|
+
if (isFile7(path20.join(tdir, rel))) {
|
|
5806
6001
|
return true;
|
|
5807
6002
|
}
|
|
5808
6003
|
}
|
|
@@ -5827,7 +6022,7 @@ function resolveTargetDir(opts) {
|
|
|
5827
6022
|
}
|
|
5828
6023
|
const base = scope === "user" ? opts.home ?? os2.homedir() : opts.projectRoot ?? process.cwd();
|
|
5829
6024
|
const [d1, d2] = TARGET_SUBDIR[target];
|
|
5830
|
-
return
|
|
6025
|
+
return path20.join(base, d1, d2);
|
|
5831
6026
|
}
|
|
5832
6027
|
function splitFrontmatter(text2) {
|
|
5833
6028
|
const lines = text2.split("\n");
|
|
@@ -5885,16 +6080,16 @@ function iterRenderedPayloads(src, target) {
|
|
|
5885
6080
|
for (const skill of listSourceSkills(src)) {
|
|
5886
6081
|
payloads.push(
|
|
5887
6082
|
renderSkillPayload(
|
|
5888
|
-
|
|
5889
|
-
stem(
|
|
6083
|
+
fs21.readFileSync(skill, "utf-8"),
|
|
6084
|
+
stem(path20.basename(skill)),
|
|
5890
6085
|
target
|
|
5891
6086
|
)
|
|
5892
6087
|
);
|
|
5893
6088
|
}
|
|
5894
6089
|
for (const ref of listSourceReferences(src)) {
|
|
5895
6090
|
payloads.push([
|
|
5896
|
-
`${ROUTER_SKILL_NAME}/references/${
|
|
5897
|
-
|
|
6091
|
+
`${ROUTER_SKILL_NAME}/references/${path20.basename(ref)}`,
|
|
6092
|
+
fs21.readFileSync(ref, "utf-8")
|
|
5898
6093
|
]);
|
|
5899
6094
|
}
|
|
5900
6095
|
return payloads;
|
|
@@ -5906,7 +6101,7 @@ function packageVersion() {
|
|
|
5906
6101
|
return "unknown";
|
|
5907
6102
|
}
|
|
5908
6103
|
const pkg = JSON.parse(
|
|
5909
|
-
|
|
6104
|
+
fs21.readFileSync(path20.join(root, "package.json"), "utf-8")
|
|
5910
6105
|
);
|
|
5911
6106
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
5912
6107
|
} catch {
|
|
@@ -5925,11 +6120,11 @@ function contentKey(payloads) {
|
|
|
5925
6120
|
return h.digest("hex");
|
|
5926
6121
|
}
|
|
5927
6122
|
function metaPath(tdir) {
|
|
5928
|
-
return
|
|
6123
|
+
return path20.join(tdir, ROUTER_SKILL_NAME, META_FILENAME);
|
|
5929
6124
|
}
|
|
5930
6125
|
function loadMeta(tdir) {
|
|
5931
6126
|
try {
|
|
5932
|
-
const data = JSON.parse(
|
|
6127
|
+
const data = JSON.parse(fs21.readFileSync(metaPath(tdir), "utf-8"));
|
|
5933
6128
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
5934
6129
|
} catch {
|
|
5935
6130
|
return null;
|
|
@@ -5946,15 +6141,15 @@ function writeMeta(tdir, payloads) {
|
|
|
5946
6141
|
package_version: packageVersion()
|
|
5947
6142
|
};
|
|
5948
6143
|
const p = metaPath(tdir);
|
|
5949
|
-
|
|
5950
|
-
|
|
6144
|
+
fs21.mkdirSync(path20.dirname(p), { recursive: true });
|
|
6145
|
+
fs21.writeFileSync(p, `${JSON.stringify(meta, null, 2)}
|
|
5951
6146
|
`);
|
|
5952
6147
|
}
|
|
5953
6148
|
function installedMarker(tdir, target) {
|
|
5954
6149
|
if (target === "cursor") {
|
|
5955
|
-
return
|
|
6150
|
+
return path20.join(tdir, `${ROUTER_SKILL_NAME}.mdc`);
|
|
5956
6151
|
}
|
|
5957
|
-
return
|
|
6152
|
+
return path20.join(tdir, ROUTER_SKILL_NAME, "SKILL.md");
|
|
5958
6153
|
}
|
|
5959
6154
|
function syncInstalledSkills(opts = {}) {
|
|
5960
6155
|
const src = opts.source ?? SKILLS_SOURCE;
|
|
@@ -5968,7 +6163,7 @@ function syncInstalledSkills(opts = {}) {
|
|
|
5968
6163
|
home: opts.home,
|
|
5969
6164
|
projectRoot: opts.projectRoot
|
|
5970
6165
|
});
|
|
5971
|
-
if (!
|
|
6166
|
+
if (!isFile7(installedMarker(tdir, target))) {
|
|
5972
6167
|
continue;
|
|
5973
6168
|
}
|
|
5974
6169
|
if (payloads === null) {
|
|
@@ -5991,15 +6186,15 @@ function syncOneDir(tdir, payloads) {
|
|
|
5991
6186
|
const wrote = [];
|
|
5992
6187
|
const keptEdited = [];
|
|
5993
6188
|
for (const [rel, content] of payloads) {
|
|
5994
|
-
const dest =
|
|
6189
|
+
const dest = path20.join(tdir, rel);
|
|
5995
6190
|
const newHash = sha256(content);
|
|
5996
|
-
const cur =
|
|
6191
|
+
const cur = isFile7(dest) ? sha256(fs21.readFileSync(dest, "utf-8")) : null;
|
|
5997
6192
|
if (cur === newHash) {
|
|
5998
6193
|
continue;
|
|
5999
6194
|
}
|
|
6000
6195
|
if (cur === null || cur === recordedFiles[rel]) {
|
|
6001
|
-
|
|
6002
|
-
|
|
6196
|
+
fs21.mkdirSync(path20.dirname(dest), { recursive: true });
|
|
6197
|
+
fs21.writeFileSync(dest, content);
|
|
6003
6198
|
wrote.push(rel);
|
|
6004
6199
|
} else {
|
|
6005
6200
|
keptEdited.push(rel);
|
|
@@ -6010,15 +6205,15 @@ function syncOneDir(tdir, payloads) {
|
|
|
6010
6205
|
if (shipped.has(rel)) {
|
|
6011
6206
|
continue;
|
|
6012
6207
|
}
|
|
6013
|
-
const dest =
|
|
6208
|
+
const dest = path20.join(tdir, rel);
|
|
6014
6209
|
try {
|
|
6015
|
-
if (
|
|
6016
|
-
|
|
6210
|
+
if (isFile7(dest) && sha256(fs21.readFileSync(dest, "utf-8")) === recorded) {
|
|
6211
|
+
fs21.unlinkSync(dest);
|
|
6017
6212
|
wrote.push(`removed ${rel}`);
|
|
6018
|
-
let parent =
|
|
6019
|
-
while (parent !== tdir && isDir3(parent) &&
|
|
6020
|
-
|
|
6021
|
-
parent =
|
|
6213
|
+
let parent = path20.dirname(dest);
|
|
6214
|
+
while (parent !== tdir && isDir3(parent) && fs21.readdirSync(parent).length === 0) {
|
|
6215
|
+
fs21.rmdirSync(parent);
|
|
6216
|
+
parent = path20.dirname(parent);
|
|
6022
6217
|
}
|
|
6023
6218
|
}
|
|
6024
6219
|
} catch {
|
|
@@ -6048,45 +6243,45 @@ function installSkills(opts) {
|
|
|
6048
6243
|
projectRoot: opts.projectRoot,
|
|
6049
6244
|
home: opts.home
|
|
6050
6245
|
});
|
|
6051
|
-
|
|
6246
|
+
fs21.mkdirSync(tdir, { recursive: true });
|
|
6052
6247
|
const installed = [];
|
|
6053
6248
|
const skipped = [];
|
|
6054
6249
|
for (const skill of skillFiles) {
|
|
6055
|
-
const skillName = stem(
|
|
6056
|
-
const srcText =
|
|
6250
|
+
const skillName = stem(path20.basename(skill));
|
|
6251
|
+
const srcText = fs21.readFileSync(skill, "utf-8");
|
|
6057
6252
|
const [relPath, content] = renderSkillPayload(srcText, skillName, target);
|
|
6058
|
-
const dest =
|
|
6059
|
-
|
|
6060
|
-
if (
|
|
6253
|
+
const dest = path20.join(tdir, relPath);
|
|
6254
|
+
fs21.mkdirSync(path20.dirname(dest), { recursive: true });
|
|
6255
|
+
if (isFile7(dest) && sha256(fs21.readFileSync(dest, "utf-8")) === sha256(content)) {
|
|
6061
6256
|
skipped.push(skillName);
|
|
6062
6257
|
} else {
|
|
6063
|
-
|
|
6258
|
+
fs21.writeFileSync(dest, content);
|
|
6064
6259
|
installed.push(skillName);
|
|
6065
6260
|
}
|
|
6066
6261
|
if (target === "claude-code") {
|
|
6067
|
-
const legacyFlat =
|
|
6068
|
-
if (
|
|
6069
|
-
|
|
6262
|
+
const legacyFlat = path20.join(tdir, path20.basename(skill));
|
|
6263
|
+
if (isFile7(legacyFlat)) {
|
|
6264
|
+
fs21.unlinkSync(legacyFlat);
|
|
6070
6265
|
}
|
|
6071
6266
|
}
|
|
6072
6267
|
}
|
|
6073
6268
|
for (const ref of listSourceReferences(src)) {
|
|
6074
|
-
const rel = `${ROUTER_SKILL_NAME}/references/${
|
|
6075
|
-
const dest =
|
|
6076
|
-
|
|
6077
|
-
const content =
|
|
6078
|
-
if (
|
|
6269
|
+
const rel = `${ROUTER_SKILL_NAME}/references/${path20.basename(ref)}`;
|
|
6270
|
+
const dest = path20.join(tdir, rel);
|
|
6271
|
+
fs21.mkdirSync(path20.dirname(dest), { recursive: true });
|
|
6272
|
+
const content = fs21.readFileSync(ref, "utf-8");
|
|
6273
|
+
if (isFile7(dest) && sha256(fs21.readFileSync(dest, "utf-8")) === sha256(content)) {
|
|
6079
6274
|
skipped.push(rel);
|
|
6080
6275
|
} else {
|
|
6081
|
-
|
|
6276
|
+
fs21.writeFileSync(dest, content);
|
|
6082
6277
|
installed.push(rel);
|
|
6083
6278
|
}
|
|
6084
6279
|
}
|
|
6085
|
-
if (isDir3(
|
|
6280
|
+
if (isDir3(path20.join(tdir, ROUTER_SKILL_NAME))) {
|
|
6086
6281
|
writeMeta(tdir, iterRenderedPayloads(src, target));
|
|
6087
6282
|
}
|
|
6088
|
-
const legacy = target === "claude-code" ? LEGACY_SKILL_NAMES.filter((name) => isDir3(
|
|
6089
|
-
(name) =>
|
|
6283
|
+
const legacy = target === "claude-code" ? LEGACY_SKILL_NAMES.filter((name) => isDir3(path20.join(tdir, name))) : LEGACY_SKILL_NAMES.filter(
|
|
6284
|
+
(name) => isFile7(path20.join(tdir, `${name}.mdc`))
|
|
6090
6285
|
);
|
|
6091
6286
|
return {
|
|
6092
6287
|
target,
|
|
@@ -6112,9 +6307,9 @@ function acceptChoices(option, accepted, advertised) {
|
|
|
6112
6307
|
}
|
|
6113
6308
|
|
|
6114
6309
|
// src/cli/wallet.ts
|
|
6115
|
-
import * as
|
|
6310
|
+
import * as fs23 from "fs";
|
|
6116
6311
|
import * as os3 from "os";
|
|
6117
|
-
import * as
|
|
6312
|
+
import * as path22 from "path";
|
|
6118
6313
|
import { EVMWalletProvider, SigningPolicy } from "@bnbagent/sdk";
|
|
6119
6314
|
import {
|
|
6120
6315
|
envLocalPath as envLocalPath10,
|
|
@@ -6124,14 +6319,16 @@ import {
|
|
|
6124
6319
|
import { buildPolicy, buildWallet } from "@bnbagent/studio-runtime/wallet";
|
|
6125
6320
|
|
|
6126
6321
|
// src/cli/walletSession.ts
|
|
6127
|
-
import * as
|
|
6128
|
-
import * as
|
|
6322
|
+
import * as fs22 from "fs";
|
|
6323
|
+
import * as path21 from "path";
|
|
6324
|
+
import { pathToFileURL } from "url";
|
|
6129
6325
|
import { AltanaWalletProvider } from "@bnbagent/sdk";
|
|
6130
6326
|
import { getAddress as deployedAddresses } from "@bnbagent/sdk/networks";
|
|
6131
6327
|
import {
|
|
6132
6328
|
defaultAgentPermissions,
|
|
6133
6329
|
deserializeSession,
|
|
6134
|
-
serializeSession
|
|
6330
|
+
serializeSession,
|
|
6331
|
+
setAltanaSdkImporter
|
|
6135
6332
|
} from "@bnbagent/sdk/wallets";
|
|
6136
6333
|
import { auditedOp as auditedOp2 } from "@bnbagent/studio-runtime/audit";
|
|
6137
6334
|
import { loadStudioToml as loadStudioToml9 } from "@bnbagent/studio-runtime/config";
|
|
@@ -6139,7 +6336,8 @@ import { getNetwork as getNetwork5, toRaw as toRaw2 } from "@bnbagent/studio-run
|
|
|
6139
6336
|
import { writePrivate } from "@bnbagent/studio-runtime/secretWrite";
|
|
6140
6337
|
import {
|
|
6141
6338
|
ALTANA_NETWORK_BY_STUDIO,
|
|
6142
|
-
PASSWORD_ENV
|
|
6339
|
+
PASSWORD_ENV,
|
|
6340
|
+
resolveProjectAltanaSdkEntry as resolveProjectAltanaSdkEntry2
|
|
6143
6341
|
} from "@bnbagent/studio-runtime/wallet";
|
|
6144
6342
|
var defaultAdminFactory = (opts) => AltanaWalletProvider.adminFromKeystore(opts);
|
|
6145
6343
|
var adminFactory = defaultAdminFactory;
|
|
@@ -6148,13 +6346,17 @@ function tableOf7(value) {
|
|
|
6148
6346
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
6149
6347
|
}
|
|
6150
6348
|
function loadContext(projectRoot) {
|
|
6151
|
-
const cfg = loadStudioToml9(
|
|
6349
|
+
const cfg = loadStudioToml9(path21.join(projectRoot, "studio.toml"));
|
|
6152
6350
|
const walletCfg = tableOf7(cfg.wallet);
|
|
6153
6351
|
if (String(walletCfg.kind ?? "evm-local") !== "altana") {
|
|
6154
6352
|
throw new Error(
|
|
6155
6353
|
`wallet session commands require [wallet].kind='altana' (got ${JSON.stringify(walletCfg.kind ?? "evm-local")}).`
|
|
6156
6354
|
);
|
|
6157
6355
|
}
|
|
6356
|
+
const sdkEntry = resolveProjectAltanaSdkEntry2(projectRoot);
|
|
6357
|
+
setAltanaSdkImporter(
|
|
6358
|
+
sdkEntry === null ? null : () => import(pathToFileURL(sdkEntry).href)
|
|
6359
|
+
);
|
|
6158
6360
|
const networkName = String(tableOf7(cfg.network).default ?? "bsc-testnet");
|
|
6159
6361
|
const altanaNetwork = ALTANA_NETWORK_BY_STUDIO[networkName];
|
|
6160
6362
|
if (altanaNetwork === void 0) {
|
|
@@ -6170,7 +6372,7 @@ function loadContext(projectRoot) {
|
|
|
6170
6372
|
}
|
|
6171
6373
|
const resolvePath = (value, fallback) => {
|
|
6172
6374
|
const configured = String(value ?? fallback);
|
|
6173
|
-
return
|
|
6375
|
+
return path21.isAbsolute(configured) ? configured : path21.join(projectRoot, configured);
|
|
6174
6376
|
};
|
|
6175
6377
|
return {
|
|
6176
6378
|
projectRoot,
|
|
@@ -6234,7 +6436,7 @@ function parseSessionEnvelope(serialized) {
|
|
|
6234
6436
|
function readSession(ctx) {
|
|
6235
6437
|
let serialized;
|
|
6236
6438
|
try {
|
|
6237
|
-
serialized =
|
|
6439
|
+
serialized = fs22.readFileSync(ctx.sessionFile, "utf8");
|
|
6238
6440
|
} catch {
|
|
6239
6441
|
throw new Error(
|
|
6240
6442
|
`no Altana session file at ${ctx.sessionFile} \u2014 run \`bag wallet session grant\`.`
|
|
@@ -6243,8 +6445,8 @@ function readSession(ctx) {
|
|
|
6243
6445
|
return { serialized, envelope: parseSessionEnvelope(serialized) };
|
|
6244
6446
|
}
|
|
6245
6447
|
function writeSession(ctx, session) {
|
|
6246
|
-
|
|
6247
|
-
|
|
6448
|
+
fs22.mkdirSync(path21.dirname(ctx.sessionFile), { recursive: true, mode: 448 });
|
|
6449
|
+
fs22.chmodSync(path21.dirname(ctx.sessionFile), 448);
|
|
6248
6450
|
writePrivate(ctx.sessionFile, serializeSession(session));
|
|
6249
6451
|
}
|
|
6250
6452
|
function sessionKeyFingerprint(publicKey) {
|
|
@@ -6355,7 +6557,7 @@ async function cmdSessionGrant(opts) {
|
|
|
6355
6557
|
"--budget-u"
|
|
6356
6558
|
);
|
|
6357
6559
|
let existing = null;
|
|
6358
|
-
if (
|
|
6560
|
+
if (fs22.existsSync(ctx.sessionFile)) {
|
|
6359
6561
|
existing = readSession(ctx).envelope;
|
|
6360
6562
|
if (!opts.force) {
|
|
6361
6563
|
throw new Error(
|
|
@@ -6473,7 +6675,7 @@ async function cmdSessionRevoke(opts) {
|
|
|
6473
6675
|
await admin.revokeSession(envelope.publicKey);
|
|
6474
6676
|
}
|
|
6475
6677
|
);
|
|
6476
|
-
|
|
6678
|
+
fs22.unlinkSync(ctx.sessionFile);
|
|
6477
6679
|
printErr(`\u2713 Altana session revoked and removed: ${ctx.sessionFile}`);
|
|
6478
6680
|
return 0;
|
|
6479
6681
|
}
|
|
@@ -6597,8 +6799,8 @@ var ProjectRootNotFound = class extends Error {
|
|
|
6597
6799
|
};
|
|
6598
6800
|
function resolveWalletProjectRoot(argRoot) {
|
|
6599
6801
|
if (argRoot != null) {
|
|
6600
|
-
const root2 =
|
|
6601
|
-
if (!
|
|
6802
|
+
const root2 = path22.resolve(argRoot);
|
|
6803
|
+
if (!isFile8(path22.join(root2, "studio.toml"))) {
|
|
6602
6804
|
throw new ProjectRootNotFound(
|
|
6603
6805
|
`No studio.toml found under --project-root ${root2}`
|
|
6604
6806
|
);
|
|
@@ -6613,15 +6815,15 @@ function resolveWalletProjectRoot(argRoot) {
|
|
|
6613
6815
|
}
|
|
6614
6816
|
return root;
|
|
6615
6817
|
}
|
|
6616
|
-
function
|
|
6818
|
+
function isFile8(p) {
|
|
6617
6819
|
try {
|
|
6618
|
-
return
|
|
6820
|
+
return fs23.statSync(p).isFile();
|
|
6619
6821
|
} catch {
|
|
6620
6822
|
return false;
|
|
6621
6823
|
}
|
|
6622
6824
|
}
|
|
6623
6825
|
function loadWalletCfg(projectRoot) {
|
|
6624
|
-
const data = loadStudioToml10(
|
|
6826
|
+
const data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
6625
6827
|
const wallet = data.wallet;
|
|
6626
6828
|
return wallet !== null && typeof wallet === "object" && !Array.isArray(wallet) ? wallet : {};
|
|
6627
6829
|
}
|
|
@@ -6631,7 +6833,7 @@ function walletKind(walletCfg) {
|
|
|
6631
6833
|
function projectNetwork(projectRoot) {
|
|
6632
6834
|
let data;
|
|
6633
6835
|
try {
|
|
6634
|
-
data = loadStudioToml10(
|
|
6836
|
+
data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
6635
6837
|
} catch {
|
|
6636
6838
|
return "bsc-testnet";
|
|
6637
6839
|
}
|
|
@@ -6670,12 +6872,12 @@ function requireDurablePassword(projectRoot) {
|
|
|
6670
6872
|
return password;
|
|
6671
6873
|
}
|
|
6672
6874
|
function persistAddress(projectRoot, address) {
|
|
6673
|
-
const tomlPath =
|
|
6674
|
-
if (!
|
|
6875
|
+
const tomlPath = path22.join(projectRoot, "studio.toml");
|
|
6876
|
+
if (!isFile8(tomlPath)) {
|
|
6675
6877
|
return;
|
|
6676
6878
|
}
|
|
6677
|
-
const text2 =
|
|
6678
|
-
|
|
6879
|
+
const text2 = fs23.readFileSync(tomlPath, "utf-8");
|
|
6880
|
+
fs23.writeFileSync(
|
|
6679
6881
|
tomlPath,
|
|
6680
6882
|
updateSection(text2, "wallet", { address }),
|
|
6681
6883
|
"utf-8"
|
|
@@ -6691,7 +6893,7 @@ function resolveKeystoreDir2(projectRoot, cliOverride, walletCfg) {
|
|
|
6691
6893
|
} else {
|
|
6692
6894
|
d = ".studio/wallets";
|
|
6693
6895
|
}
|
|
6694
|
-
return
|
|
6896
|
+
return path22.isAbsolute(d) ? d : path22.join(projectRoot, d);
|
|
6695
6897
|
}
|
|
6696
6898
|
async function resolvePrivateKeyArg(raw) {
|
|
6697
6899
|
if (raw === void 0 || raw === false) {
|
|
@@ -6806,7 +7008,7 @@ async function cmdNew(opts) {
|
|
|
6806
7008
|
projectRoot = process.cwd();
|
|
6807
7009
|
}
|
|
6808
7010
|
let walletCfg = {};
|
|
6809
|
-
if (
|
|
7011
|
+
if (isFile8(path22.join(projectRoot, "studio.toml"))) {
|
|
6810
7012
|
walletCfg = loadWalletCfg(projectRoot);
|
|
6811
7013
|
}
|
|
6812
7014
|
const kind = walletKind(walletCfg);
|
|
@@ -6820,7 +7022,7 @@ async function cmdNew(opts) {
|
|
|
6820
7022
|
opts.keystoreDir,
|
|
6821
7023
|
walletCfg
|
|
6822
7024
|
);
|
|
6823
|
-
|
|
7025
|
+
fs23.mkdirSync(keystoreDir, { recursive: true });
|
|
6824
7026
|
const provider = new EVMWalletProvider({
|
|
6825
7027
|
password,
|
|
6826
7028
|
...privateKey !== null ? { privateKey } : {},
|
|
@@ -6830,7 +7032,7 @@ async function cmdNew(opts) {
|
|
|
6830
7032
|
persistAddress(projectRoot, provider.address);
|
|
6831
7033
|
if (kind === "altana") {
|
|
6832
7034
|
printErr(
|
|
6833
|
-
"Altana admin keystore created. Fund this address with about 0.
|
|
7035
|
+
"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
7036
|
);
|
|
6835
7037
|
}
|
|
6836
7038
|
return 0;
|
|
@@ -6844,11 +7046,11 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6844
7046
|
return 1;
|
|
6845
7047
|
}
|
|
6846
7048
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
6847
|
-
if (!
|
|
7049
|
+
if (!isFile8(walletFile)) {
|
|
6848
7050
|
let createCmd = "twak wallet create --password <your-password> --no-keychain";
|
|
6849
7051
|
let setupCmd = "twak setup";
|
|
6850
7052
|
if (walletCfg.twak_home) {
|
|
6851
|
-
const home =
|
|
7053
|
+
const home = path22.dirname(path22.dirname(walletFile));
|
|
6852
7054
|
createCmd = `HOME=${home} ${createCmd}`;
|
|
6853
7055
|
setupCmd = `HOME=${home} ${setupCmd}`;
|
|
6854
7056
|
}
|
|
@@ -6874,23 +7076,23 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6874
7076
|
return 0;
|
|
6875
7077
|
}
|
|
6876
7078
|
function ensureTwakCredentials(walletFile, homeDir) {
|
|
6877
|
-
const twakDir =
|
|
6878
|
-
const target =
|
|
6879
|
-
if (
|
|
7079
|
+
const twakDir = path22.dirname(walletFile);
|
|
7080
|
+
const target = path22.join(twakDir, "credentials.json");
|
|
7081
|
+
if (isFile8(target)) {
|
|
6880
7082
|
return true;
|
|
6881
7083
|
}
|
|
6882
|
-
const machine =
|
|
6883
|
-
if (
|
|
7084
|
+
const machine = path22.join(os3.homedir(), ".twak", "credentials.json");
|
|
7085
|
+
if (path22.resolve(machine) === path22.resolve(target) || !isFile8(machine)) {
|
|
6884
7086
|
printErr(
|
|
6885
7087
|
`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
7088
|
);
|
|
6887
7089
|
return false;
|
|
6888
7090
|
}
|
|
6889
|
-
|
|
6890
|
-
|
|
7091
|
+
fs23.mkdirSync(twakDir, { recursive: true });
|
|
7092
|
+
fs23.writeFileSync(target, fs23.readFileSync(machine, "utf-8"), { mode: 384 });
|
|
6891
7093
|
try {
|
|
6892
|
-
|
|
6893
|
-
|
|
7094
|
+
fs23.chmodSync(twakDir, 448);
|
|
7095
|
+
fs23.chmodSync(target, 384);
|
|
6894
7096
|
} catch {
|
|
6895
7097
|
}
|
|
6896
7098
|
printErr(`note: copied NaaS credentials from ${machine} into ${twakDir}.`);
|
|
@@ -6902,10 +7104,10 @@ async function resolveTwakInitPassword(opts) {
|
|
|
6902
7104
|
throw new CliExit(2);
|
|
6903
7105
|
}
|
|
6904
7106
|
if (opts.passwordFile) {
|
|
6905
|
-
const file =
|
|
7107
|
+
const file = path22.resolve(opts.passwordFile);
|
|
6906
7108
|
let mode;
|
|
6907
7109
|
try {
|
|
6908
|
-
mode =
|
|
7110
|
+
mode = fs23.statSync(file).mode;
|
|
6909
7111
|
} catch {
|
|
6910
7112
|
printErr(`error: cannot read --password-file ${file}.`);
|
|
6911
7113
|
throw new CliExit(2);
|
|
@@ -6916,7 +7118,7 @@ async function resolveTwakInitPassword(opts) {
|
|
|
6916
7118
|
);
|
|
6917
7119
|
throw new CliExit(2);
|
|
6918
7120
|
}
|
|
6919
|
-
const password = (
|
|
7121
|
+
const password = (fs23.readFileSync(file, "utf-8").split(/\r?\n/)[0] ?? "").trim();
|
|
6920
7122
|
if (!password) {
|
|
6921
7123
|
printErr(`error: --password-file ${file} is empty.`);
|
|
6922
7124
|
throw new CliExit(2);
|
|
@@ -6969,15 +7171,15 @@ Install it (Node >=22): npm install -g @trustwallet/cli@${TWAK_CLI_VERSION}`
|
|
|
6969
7171
|
return 1;
|
|
6970
7172
|
}
|
|
6971
7173
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
6972
|
-
if (
|
|
7174
|
+
if (isFile8(walletFile)) {
|
|
6973
7175
|
printErr(
|
|
6974
7176
|
`error: a twak wallet already exists at ${walletFile} \u2014 nothing to create. Run \`bag wallet new\` to adopt its address into studio.toml.`
|
|
6975
7177
|
);
|
|
6976
7178
|
return 1;
|
|
6977
7179
|
}
|
|
6978
7180
|
const password = await resolveTwakInitPassword(opts);
|
|
6979
|
-
const homeDir =
|
|
6980
|
-
|
|
7181
|
+
const homeDir = path22.dirname(path22.dirname(walletFile));
|
|
7182
|
+
fs23.mkdirSync(homeDir, { recursive: true });
|
|
6981
7183
|
if (!ensureTwakCredentials(walletFile, homeDir)) {
|
|
6982
7184
|
return 1;
|
|
6983
7185
|
}
|
|
@@ -6999,7 +7201,7 @@ ${password}
|
|
|
6999
7201
|
timeoutMs: 12e4
|
|
7000
7202
|
}
|
|
7001
7203
|
);
|
|
7002
|
-
if (create.code !== 0 || !
|
|
7204
|
+
if (create.code !== 0 || !isFile8(walletFile)) {
|
|
7003
7205
|
const detail = `${create.stderr}
|
|
7004
7206
|
${create.stdout}`.trim();
|
|
7005
7207
|
printErr(
|
|
@@ -7014,14 +7216,14 @@ ${detail}` : `error: \`twak wallet create --no-keychain\` did not produce ${wall
|
|
|
7014
7216
|
return 1;
|
|
7015
7217
|
}
|
|
7016
7218
|
try {
|
|
7017
|
-
|
|
7219
|
+
fs23.chmodSync(walletFile, 384);
|
|
7018
7220
|
} catch {
|
|
7019
7221
|
}
|
|
7020
7222
|
if (!process.env.TWAK_WALLET_PASSWORD) {
|
|
7021
7223
|
process.env.TWAK_WALLET_PASSWORD = password;
|
|
7022
7224
|
}
|
|
7023
7225
|
printErr(
|
|
7024
|
-
`\u2713 twak wallet created under ${
|
|
7226
|
+
`\u2713 twak wallet created under ${path22.dirname(walletFile)} (no keychain)`
|
|
7025
7227
|
);
|
|
7026
7228
|
printErr(
|
|
7027
7229
|
"next: persist TWAK_WALLET_PASSWORD in .studio/.env.local so deploys and non-interactive signing can unlock it."
|
|
@@ -7058,7 +7260,7 @@ function cmdShow5(projectRootArg) {
|
|
|
7058
7260
|
...walletCfg.address ? { address: String(walletCfg.address) } : {}
|
|
7059
7261
|
});
|
|
7060
7262
|
const address = provider.address;
|
|
7061
|
-
const keystorePath =
|
|
7263
|
+
const keystorePath = path22.join(keystoreDir, `${address}.json`);
|
|
7062
7264
|
printOut(`address: ${address}`);
|
|
7063
7265
|
printOut(`source: ${kind}`);
|
|
7064
7266
|
printOut(`keystore_dir: ${keystoreDir}`);
|
|
@@ -7067,14 +7269,14 @@ function cmdShow5(projectRootArg) {
|
|
|
7067
7269
|
const configured = String(
|
|
7068
7270
|
walletCfg.session_file ?? ".studio/wallets/altana-session.json"
|
|
7069
7271
|
);
|
|
7070
|
-
const sessionFile =
|
|
7272
|
+
const sessionFile = path22.isAbsolute(configured) ? configured : path22.join(projectRoot, configured);
|
|
7071
7273
|
printOut(`session_file: ${sessionFile}`);
|
|
7072
|
-
if (!
|
|
7274
|
+
if (!isFile8(sessionFile)) {
|
|
7073
7275
|
printOut("session_status: missing (run `bag wallet session grant`)");
|
|
7074
7276
|
} else {
|
|
7075
7277
|
let envelope;
|
|
7076
7278
|
try {
|
|
7077
|
-
envelope = JSON.parse(
|
|
7279
|
+
envelope = JSON.parse(fs23.readFileSync(sessionFile, "utf8"));
|
|
7078
7280
|
} catch {
|
|
7079
7281
|
throw new Error(`invalid Altana session JSON at ${sessionFile}`);
|
|
7080
7282
|
}
|
|
@@ -7100,7 +7302,7 @@ function cmdList2(projectRootArg) {
|
|
|
7100
7302
|
const keystoreDir = resolveKeystoreDir2(projectRoot, null, walletCfg);
|
|
7101
7303
|
let entries;
|
|
7102
7304
|
try {
|
|
7103
|
-
entries =
|
|
7305
|
+
entries = fs23.readdirSync(keystoreDir).sort();
|
|
7104
7306
|
} catch {
|
|
7105
7307
|
return 0;
|
|
7106
7308
|
}
|
|
@@ -7112,7 +7314,7 @@ function cmdList2(projectRootArg) {
|
|
|
7112
7314
|
let data;
|
|
7113
7315
|
try {
|
|
7114
7316
|
data = JSON.parse(
|
|
7115
|
-
|
|
7317
|
+
fs23.readFileSync(path22.join(keystoreDir, child), "utf-8")
|
|
7116
7318
|
);
|
|
7117
7319
|
} catch {
|
|
7118
7320
|
continue;
|
|
@@ -7163,7 +7365,7 @@ async function cmdSign(msg, projectRootArg) {
|
|
|
7163
7365
|
}
|
|
7164
7366
|
async function cmdBalance(opts) {
|
|
7165
7367
|
const projectRoot = resolveWalletProjectRoot(opts.projectRoot);
|
|
7166
|
-
const data = loadStudioToml10(
|
|
7368
|
+
const data = loadStudioToml10(path22.join(projectRoot, "studio.toml"));
|
|
7167
7369
|
const walletCfg = data.wallet !== null && typeof data.wallet === "object" ? data.wallet : {};
|
|
7168
7370
|
let address;
|
|
7169
7371
|
const kind = walletKind(walletCfg);
|
|
@@ -7290,10 +7492,10 @@ var PROVIDER_KEY_ENV = {
|
|
|
7290
7492
|
"pieverse-llm": "PIEVERSE_LLM_API_KEY"
|
|
7291
7493
|
};
|
|
7292
7494
|
function renderAgentcoreProject(target, name) {
|
|
7293
|
-
const acDir =
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7495
|
+
const acDir = path23.join(target, "agentcore");
|
|
7496
|
+
fs24.mkdirSync(acDir, { recursive: true });
|
|
7497
|
+
fs24.writeFileSync(
|
|
7498
|
+
path23.join(acDir, "agentcore.json"),
|
|
7297
7499
|
`${JSON.stringify(
|
|
7298
7500
|
{
|
|
7299
7501
|
$schema: "https://schema.agentcore.aws.dev/v1/agentcore.json",
|
|
@@ -7307,7 +7509,7 @@ function renderAgentcoreProject(target, name) {
|
|
|
7307
7509
|
)}
|
|
7308
7510
|
`
|
|
7309
7511
|
);
|
|
7310
|
-
|
|
7512
|
+
fs24.writeFileSync(path23.join(acDir, "aws-targets.json"), "[]\n");
|
|
7311
7513
|
}
|
|
7312
7514
|
var AGENTS_MD_MARKER = "# bnbagent-studio additions (ERC-8183 seller)";
|
|
7313
7515
|
var AGENTS_MD_STUDIO_SECTION = `
|
|
@@ -7351,30 +7553,30 @@ every intent to the right playbook via its references.
|
|
|
7351
7553
|
and state the tradeoff.
|
|
7352
7554
|
`;
|
|
7353
7555
|
function appendAgentsMdStudioSection(target) {
|
|
7354
|
-
const agentsMd =
|
|
7556
|
+
const agentsMd = path23.join(target, "AGENTS.md");
|
|
7355
7557
|
let existing = "";
|
|
7356
7558
|
try {
|
|
7357
|
-
existing =
|
|
7559
|
+
existing = fs24.readFileSync(agentsMd, "utf-8");
|
|
7358
7560
|
} catch {
|
|
7359
7561
|
existing = "";
|
|
7360
7562
|
}
|
|
7361
7563
|
if (existing.includes(AGENTS_MD_MARKER)) {
|
|
7362
7564
|
return;
|
|
7363
7565
|
}
|
|
7364
|
-
|
|
7566
|
+
fs24.writeFileSync(
|
|
7365
7567
|
agentsMd,
|
|
7366
7568
|
`${existing.replace(/\n+$/, "")}
|
|
7367
7569
|
${AGENTS_MD_STUDIO_SECTION}`
|
|
7368
7570
|
);
|
|
7369
7571
|
}
|
|
7370
7572
|
function seedAwsTargets(target) {
|
|
7371
|
-
const p =
|
|
7372
|
-
if (!
|
|
7573
|
+
const p = path23.join(target, "agentcore", "aws-targets.json");
|
|
7574
|
+
if (!isFile9(p)) {
|
|
7373
7575
|
return;
|
|
7374
7576
|
}
|
|
7375
7577
|
let data;
|
|
7376
7578
|
try {
|
|
7377
|
-
data = JSON.parse(
|
|
7579
|
+
data = JSON.parse(fs24.readFileSync(p, "utf-8"));
|
|
7378
7580
|
} catch {
|
|
7379
7581
|
return;
|
|
7380
7582
|
}
|
|
@@ -7385,7 +7587,7 @@ function seedAwsTargets(target) {
|
|
|
7385
7587
|
{ name: "default", account: AWS_ACCOUNT_PLACEHOLDER, region: "us-east-1" }
|
|
7386
7588
|
];
|
|
7387
7589
|
try {
|
|
7388
|
-
|
|
7590
|
+
fs24.writeFileSync(p, `${JSON.stringify(skeleton, null, 2)}
|
|
7389
7591
|
`);
|
|
7390
7592
|
} catch {
|
|
7391
7593
|
return;
|
|
@@ -7408,13 +7610,13 @@ function registerAgentcoreRuntime(target, name, opts = {}) {
|
|
|
7408
7610
|
const protocol = nativeProtocolOf(faces);
|
|
7409
7611
|
const stem2 = entryStemOf(faces);
|
|
7410
7612
|
const isContainer = opts.packaging === "container" || walletKind2 === "twak";
|
|
7411
|
-
const cfgPath =
|
|
7412
|
-
if (!
|
|
7613
|
+
const cfgPath = path23.join(target, "agentcore", "agentcore.json");
|
|
7614
|
+
if (!isFile9(cfgPath)) {
|
|
7413
7615
|
return;
|
|
7414
7616
|
}
|
|
7415
7617
|
let cfg;
|
|
7416
7618
|
try {
|
|
7417
|
-
const parsed = JSON.parse(
|
|
7619
|
+
const parsed = JSON.parse(fs24.readFileSync(cfgPath, "utf-8"));
|
|
7418
7620
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7419
7621
|
return;
|
|
7420
7622
|
}
|
|
@@ -7453,7 +7655,7 @@ function registerAgentcoreRuntime(target, name, opts = {}) {
|
|
|
7453
7655
|
runtimes.push(runtime);
|
|
7454
7656
|
cfg.runtimes = runtimes;
|
|
7455
7657
|
try {
|
|
7456
|
-
|
|
7658
|
+
fs24.writeFileSync(cfgPath, `${JSON.stringify(cfg, null, 2)}
|
|
7457
7659
|
`);
|
|
7458
7660
|
} catch {
|
|
7459
7661
|
return;
|
|
@@ -7590,12 +7792,12 @@ function registerInit(program) {
|
|
|
7590
7792
|
);
|
|
7591
7793
|
}
|
|
7592
7794
|
function enclosingProjectRoot(start) {
|
|
7593
|
-
let current =
|
|
7795
|
+
let current = path23.resolve(start);
|
|
7594
7796
|
for (; ; ) {
|
|
7595
|
-
if (
|
|
7797
|
+
if (isFile9(path23.join(current, APP_DIR, AGENT_PKG, "studio.toml"))) {
|
|
7596
7798
|
return current;
|
|
7597
7799
|
}
|
|
7598
|
-
const parent =
|
|
7800
|
+
const parent = path23.dirname(current);
|
|
7599
7801
|
if (parent === current) {
|
|
7600
7802
|
return null;
|
|
7601
7803
|
}
|
|
@@ -7603,8 +7805,8 @@ function enclosingProjectRoot(start) {
|
|
|
7603
7805
|
}
|
|
7604
7806
|
}
|
|
7605
7807
|
async function cmdInit(nameArg, opts) {
|
|
7606
|
-
const target =
|
|
7607
|
-
let projectName2 =
|
|
7808
|
+
const target = path23.resolve(process.cwd(), nameArg);
|
|
7809
|
+
let projectName2 = path23.basename(target);
|
|
7608
7810
|
if (!projectName2) {
|
|
7609
7811
|
printErr(
|
|
7610
7812
|
`error: cannot derive a project name from '${nameArg}' (path has no basename).`
|
|
@@ -7650,6 +7852,9 @@ async function cmdInit(nameArg, opts) {
|
|
|
7650
7852
|
opts.llmProviderSource,
|
|
7651
7853
|
isTty
|
|
7652
7854
|
);
|
|
7855
|
+
if (llmProvider === null) {
|
|
7856
|
+
return 2;
|
|
7857
|
+
}
|
|
7653
7858
|
let rails = await resolveRails(opts.rails, isTty);
|
|
7654
7859
|
if (hasX402Face(faces) && rails === "8183") {
|
|
7655
7860
|
rails = "both";
|
|
@@ -7689,15 +7894,15 @@ async function cmdInit(nameArg, opts) {
|
|
|
7689
7894
|
return 2;
|
|
7690
7895
|
}
|
|
7691
7896
|
}
|
|
7692
|
-
const enclosing = enclosingProjectRoot(
|
|
7897
|
+
const enclosing = enclosingProjectRoot(path23.dirname(target));
|
|
7693
7898
|
if (enclosing !== null) {
|
|
7694
7899
|
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 ${
|
|
7900
|
+
`error: ${path23.dirname(target)} is inside an existing bag project (${enclosing}).
|
|
7901
|
+
\`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
7902
|
);
|
|
7698
7903
|
return 2;
|
|
7699
7904
|
}
|
|
7700
|
-
if (
|
|
7905
|
+
if (fs24.existsSync(target) && !opts.force) {
|
|
7701
7906
|
printErr(`error: ${target} already exists. Use --force to overwrite.`);
|
|
7702
7907
|
return 2;
|
|
7703
7908
|
}
|
|
@@ -7716,20 +7921,14 @@ async function cmdInit(nameArg, opts) {
|
|
|
7716
7921
|
destination = "self";
|
|
7717
7922
|
runtime = "agentcore";
|
|
7718
7923
|
}
|
|
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
7924
|
if (destination === "self" && runtime === "azure-foundry" && (!hasA2aFace(faces) || hasMcpFace(faces))) {
|
|
7726
7925
|
printErr(
|
|
7727
7926
|
"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
7927
|
);
|
|
7729
7928
|
return 2;
|
|
7730
7929
|
}
|
|
7731
|
-
if (
|
|
7732
|
-
|
|
7930
|
+
if (fs24.existsSync(target)) {
|
|
7931
|
+
fs24.rmSync(target, { recursive: true, force: true });
|
|
7733
7932
|
}
|
|
7734
7933
|
if (destination === "platform") {
|
|
7735
7934
|
printCampaignIntro();
|
|
@@ -7774,7 +7973,7 @@ async function cmdInit(nameArg, opts) {
|
|
|
7774
7973
|
}
|
|
7775
7974
|
}
|
|
7776
7975
|
try {
|
|
7777
|
-
|
|
7976
|
+
fs24.mkdirSync(target, { recursive: true });
|
|
7778
7977
|
if (runtime === "agentcore") {
|
|
7779
7978
|
renderAgentcoreProject(target, projectName2);
|
|
7780
7979
|
}
|
|
@@ -7790,7 +7989,7 @@ async function cmdInit(nameArg, opts) {
|
|
|
7790
7989
|
printErr(
|
|
7791
7990
|
`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
7991
|
);
|
|
7793
|
-
|
|
7992
|
+
fs24.rmSync(target, { recursive: true, force: true });
|
|
7794
7993
|
return 2;
|
|
7795
7994
|
}
|
|
7796
7995
|
const ides = resolveEmitIdes(opts.ide);
|
|
@@ -7833,9 +8032,9 @@ async function cmdInit(nameArg, opts) {
|
|
|
7833
8032
|
});
|
|
7834
8033
|
seedAwsTargets(target);
|
|
7835
8034
|
}
|
|
7836
|
-
const agentDir =
|
|
7837
|
-
|
|
7838
|
-
|
|
8035
|
+
const agentDir = path23.join(target, APP_DIR, AGENT_PKG);
|
|
8036
|
+
fs24.mkdirSync(path23.join(agentDir, "vendor"), { recursive: true });
|
|
8037
|
+
fs24.writeFileSync(path23.join(agentDir, "vendor", ".gitkeep"), "");
|
|
7839
8038
|
const skipInstall = opts.install === false || opts.venv === false;
|
|
7840
8039
|
let provisioned = false;
|
|
7841
8040
|
let installFailed = false;
|
|
@@ -7964,64 +8163,64 @@ function derivePackaging(walletKind2, destination, platformArtifact2 = "zip", ru
|
|
|
7964
8163
|
}
|
|
7965
8164
|
function scaffold(target, name, o) {
|
|
7966
8165
|
const packageManagerVersion = pnpmVersion();
|
|
7967
|
-
|
|
7968
|
-
|
|
8166
|
+
fs24.writeFileSync(
|
|
8167
|
+
path23.join(target, "package.json"),
|
|
7969
8168
|
renderWorkspacePackageJson(name, packageManagerVersion)
|
|
7970
8169
|
);
|
|
7971
|
-
|
|
7972
|
-
|
|
8170
|
+
fs24.writeFileSync(
|
|
8171
|
+
path23.join(target, "pnpm-workspace.yaml"),
|
|
7973
8172
|
renderPnpmWorkspaceYaml()
|
|
7974
8173
|
);
|
|
7975
|
-
|
|
7976
|
-
if (!
|
|
7977
|
-
|
|
7978
|
-
|
|
8174
|
+
fs24.writeFileSync(path23.join(target, ".gitignore"), renderWorkspaceGitignore());
|
|
8175
|
+
if (!isFile9(path23.join(target, "README.md"))) {
|
|
8176
|
+
fs24.writeFileSync(
|
|
8177
|
+
path23.join(target, "README.md"),
|
|
7979
8178
|
renderWorkspaceReadme(name, o.destination)
|
|
7980
8179
|
);
|
|
7981
8180
|
}
|
|
7982
8181
|
appendAgentsMdStudioSection(target);
|
|
7983
|
-
const appRoot =
|
|
7984
|
-
|
|
7985
|
-
const agentRoot2 =
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
8182
|
+
const appRoot = path23.join(target, APP_DIR);
|
|
8183
|
+
fs24.mkdirSync(appRoot, { recursive: true });
|
|
8184
|
+
const agentRoot2 = path23.join(appRoot, AGENT_PKG);
|
|
8185
|
+
fs24.mkdirSync(agentRoot2, { recursive: true });
|
|
8186
|
+
fs24.writeFileSync(
|
|
8187
|
+
path23.join(agentRoot2, "pnpm-workspace.yaml"),
|
|
7989
8188
|
renderAgentPnpmWorkspaceYaml()
|
|
7990
8189
|
);
|
|
7991
8190
|
if (o.walletKind === "evm-local" || o.walletKind === "altana") {
|
|
7992
|
-
|
|
8191
|
+
fs24.mkdirSync(path23.join(target, ".studio", "wallets"), { recursive: true });
|
|
7993
8192
|
} else if (o.walletKind === "twak") {
|
|
7994
8193
|
let homeDir;
|
|
7995
8194
|
let label;
|
|
7996
8195
|
if (o.twakHome === void 0 || o.twakHome === DEDICATED_TWAK_HOME_REL) {
|
|
7997
|
-
homeDir =
|
|
8196
|
+
homeDir = path23.join(target, ".studio", "twak");
|
|
7998
8197
|
label = ".studio/twak";
|
|
7999
8198
|
} else {
|
|
8000
|
-
homeDir =
|
|
8199
|
+
homeDir = path23.isAbsolute(o.twakHome) ? o.twakHome : path23.resolve(agentRoot2, o.twakHome);
|
|
8001
8200
|
label = o.twakHome;
|
|
8002
8201
|
}
|
|
8003
|
-
|
|
8202
|
+
fs24.mkdirSync(homeDir, { recursive: true });
|
|
8004
8203
|
if (ensureTwakKeychain(homeDir)) {
|
|
8005
8204
|
printOut(
|
|
8006
8205
|
`\u2713 isolated twak keychain ready under ${label} (macOS) \u2014 no manual \`security\` setup needed`
|
|
8007
8206
|
);
|
|
8008
8207
|
}
|
|
8009
8208
|
}
|
|
8010
|
-
|
|
8011
|
-
|
|
8209
|
+
fs24.writeFileSync(
|
|
8210
|
+
path23.join(agentRoot2, "package.json"),
|
|
8012
8211
|
renderAgentPackageJson(name, o.runtime, o.provider, o.faces, o.walletKind)
|
|
8013
8212
|
);
|
|
8014
|
-
|
|
8015
|
-
|
|
8213
|
+
fs24.writeFileSync(
|
|
8214
|
+
path23.join(agentRoot2, "tsconfig.json"),
|
|
8016
8215
|
renderAgentTsconfig()
|
|
8017
8216
|
);
|
|
8018
|
-
|
|
8019
|
-
|
|
8217
|
+
fs24.writeFileSync(
|
|
8218
|
+
path23.join(agentRoot2, "studio.toml"),
|
|
8020
8219
|
renderAgentStudioToml(name, o)
|
|
8021
8220
|
);
|
|
8022
|
-
const envLocal =
|
|
8023
|
-
|
|
8024
|
-
|
|
8221
|
+
const envLocal = path23.join(target, ".studio", ".env.local");
|
|
8222
|
+
fs24.mkdirSync(path23.dirname(envLocal), { recursive: true });
|
|
8223
|
+
fs24.writeFileSync(
|
|
8025
8224
|
envLocal,
|
|
8026
8225
|
renderAgentEnvLocal(
|
|
8027
8226
|
o.provider,
|
|
@@ -8032,9 +8231,9 @@ function scaffold(target, name, o) {
|
|
|
8032
8231
|
o.network
|
|
8033
8232
|
)
|
|
8034
8233
|
);
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8234
|
+
fs24.writeFileSync(path23.join(agentRoot2, ".gitignore"), renderAgentGitignore());
|
|
8235
|
+
fs24.writeFileSync(
|
|
8236
|
+
path23.join(agentRoot2, "README.md"),
|
|
8038
8237
|
renderAgentReadme(name, o.faces, o.destination)
|
|
8039
8238
|
);
|
|
8040
8239
|
const packaging = derivePackaging(
|
|
@@ -8070,18 +8269,18 @@ function emitRecipe(base, name, opts = {}) {
|
|
|
8070
8269
|
const recipe = loadRecipe(name, { mode: opts.mode ?? null });
|
|
8071
8270
|
for (const rf of recipe.files) {
|
|
8072
8271
|
const targetPath = substitutePlaceholders(rf.targetPath, opts.context);
|
|
8073
|
-
const basename16 =
|
|
8074
|
-
const dst = basename16 === "Dockerfile" || basename16 === ".dockerignore" ?
|
|
8075
|
-
|
|
8076
|
-
|
|
8272
|
+
const basename16 = path23.posix.basename(targetPath);
|
|
8273
|
+
const dst = basename16 === "Dockerfile" || basename16 === ".dockerignore" ? path23.join(base, basename16) : path23.join(base, targetPath);
|
|
8274
|
+
fs24.mkdirSync(path23.dirname(dst), { recursive: true });
|
|
8275
|
+
fs24.writeFileSync(dst, substitutePlaceholders(rf.content, opts.context));
|
|
8077
8276
|
}
|
|
8078
8277
|
}
|
|
8079
8278
|
function readRecipeNodeDeps(recipeName, group) {
|
|
8080
|
-
const tomlPath =
|
|
8081
|
-
if (!
|
|
8279
|
+
const tomlPath = path23.join(bundledRecipesRoot(), recipeName, "recipe.toml");
|
|
8280
|
+
if (!isFile9(tomlPath)) {
|
|
8082
8281
|
return [];
|
|
8083
8282
|
}
|
|
8084
|
-
const meta = parseToml(
|
|
8283
|
+
const meta = parseToml(fs24.readFileSync(tomlPath, "utf-8"));
|
|
8085
8284
|
const depsSection = meta.dependencies !== null && typeof meta.dependencies === "object" ? meta.dependencies : {};
|
|
8086
8285
|
const collect = (v) => Array.isArray(v) ? v.filter((d) => typeof d === "string") : [];
|
|
8087
8286
|
const deps = collect(depsSection.node);
|
|
@@ -8666,7 +8865,7 @@ bag deploy --provider aws
|
|
|
8666
8865
|
`;
|
|
8667
8866
|
}
|
|
8668
8867
|
function emitProviderSkills(target, provider, ides) {
|
|
8669
|
-
const skillDir =
|
|
8868
|
+
const skillDir = path23.join(
|
|
8670
8869
|
bundledRecipesRoot(),
|
|
8671
8870
|
"providers",
|
|
8672
8871
|
provider,
|
|
@@ -8676,34 +8875,34 @@ function emitProviderSkills(target, provider, ides) {
|
|
|
8676
8875
|
return;
|
|
8677
8876
|
}
|
|
8678
8877
|
let emittedCursor = false;
|
|
8679
|
-
for (const md of
|
|
8680
|
-
const srcText =
|
|
8878
|
+
for (const md of fs24.readdirSync(skillDir).filter((n) => n.endsWith(".md")).sort()) {
|
|
8879
|
+
const srcText = fs24.readFileSync(path23.join(skillDir, md), "utf-8");
|
|
8681
8880
|
const stem2 = md.replace(/\.md$/, "");
|
|
8682
8881
|
for (const ide of ides) {
|
|
8683
8882
|
const [relPath, content] = renderSkillPayload(srcText, stem2, ide);
|
|
8684
|
-
const base = ide === "claude-code" ?
|
|
8685
|
-
const dst =
|
|
8686
|
-
|
|
8687
|
-
|
|
8883
|
+
const base = ide === "claude-code" ? path23.join(target, ".claude", "skills") : path23.join(target, ".cursor", "rules");
|
|
8884
|
+
const dst = path23.join(base, relPath);
|
|
8885
|
+
fs24.mkdirSync(path23.dirname(dst), { recursive: true });
|
|
8886
|
+
fs24.writeFileSync(dst, content);
|
|
8688
8887
|
if (ide === "cursor") {
|
|
8689
8888
|
emittedCursor = true;
|
|
8690
8889
|
}
|
|
8691
8890
|
}
|
|
8692
8891
|
}
|
|
8693
8892
|
if (emittedCursor) {
|
|
8694
|
-
ensureCursorGitignore(
|
|
8893
|
+
ensureCursorGitignore(path23.join(target, ".gitignore"));
|
|
8695
8894
|
}
|
|
8696
8895
|
}
|
|
8697
8896
|
function ensureCursorGitignore(gitignore) {
|
|
8698
|
-
if (!
|
|
8897
|
+
if (!isFile9(gitignore)) {
|
|
8699
8898
|
return;
|
|
8700
8899
|
}
|
|
8701
|
-
const text2 =
|
|
8900
|
+
const text2 = fs24.readFileSync(gitignore, "utf-8");
|
|
8702
8901
|
if (text2.includes(".cursor/rules/")) {
|
|
8703
8902
|
return;
|
|
8704
8903
|
}
|
|
8705
8904
|
const addition = "\n# Cursor rules emitted at init (regeneratable via `bag skills install --target cursor`).\n.cursor/rules/\n";
|
|
8706
|
-
|
|
8905
|
+
fs24.writeFileSync(gitignore, `${text2.replace(/\n+$/, "")}
|
|
8707
8906
|
${addition}`);
|
|
8708
8907
|
}
|
|
8709
8908
|
async function resolveWalletKind(flagValue, isTty) {
|
|
@@ -8729,8 +8928,9 @@ async function resolveLlmProviderForWallet(walletKind2, configuredProvider, valu
|
|
|
8729
8928
|
if (explicitlyConfigured) {
|
|
8730
8929
|
if (configuredProvider === "pieverse-llm") {
|
|
8731
8930
|
printErr(
|
|
8732
|
-
"
|
|
8931
|
+
"error: --wallet-kind altana cannot be combined with --llm-provider pieverse-llm: `bag llm activate` and paid-model runtime credit renewal both require SIWE message signing, which Altana intentionally does not expose \u2014 activation can never succeed. Use --llm-provider openrouter, openai, or anthropic (each needs only an API key)."
|
|
8733
8932
|
);
|
|
8933
|
+
return null;
|
|
8734
8934
|
}
|
|
8735
8935
|
return configuredProvider;
|
|
8736
8936
|
}
|
|
@@ -8881,11 +9081,11 @@ async function promptPassword() {
|
|
|
8881
9081
|
return first;
|
|
8882
9082
|
}
|
|
8883
9083
|
function readWalletAddress(studioToml) {
|
|
8884
|
-
if (!
|
|
9084
|
+
if (!isFile9(studioToml)) {
|
|
8885
9085
|
return null;
|
|
8886
9086
|
}
|
|
8887
9087
|
try {
|
|
8888
|
-
const data = parseToml(
|
|
9088
|
+
const data = parseToml(fs24.readFileSync(studioToml, "utf-8"));
|
|
8889
9089
|
const wallet = data.wallet;
|
|
8890
9090
|
if (wallet !== null && typeof wallet === "object") {
|
|
8891
9091
|
const addr = wallet.address;
|
|
@@ -8988,7 +9188,7 @@ async function runOnboarding(o) {
|
|
|
8988
9188
|
if (password === null) {
|
|
8989
9189
|
return false;
|
|
8990
9190
|
}
|
|
8991
|
-
const agentRoot2 =
|
|
9191
|
+
const agentRoot2 = path23.join(o.workspaceRoot, APP_DIR, AGENT_PKG);
|
|
8992
9192
|
const { envLocalPath: envLocalPath19 } = await import("@bnbagent/studio-runtime/config");
|
|
8993
9193
|
setEnvVar(envLocalPath19(agentRoot2), "WALLET_PASSWORD", password);
|
|
8994
9194
|
const savedCwd = process.cwd();
|
|
@@ -9016,7 +9216,7 @@ async function runOnboarding(o) {
|
|
|
9016
9216
|
);
|
|
9017
9217
|
return false;
|
|
9018
9218
|
}
|
|
9019
|
-
address = readWalletAddress(
|
|
9219
|
+
address = readWalletAddress(path23.join(agentRoot2, "studio.toml"));
|
|
9020
9220
|
if (o.walletKind !== "altana" || o.provider !== "pieverse-llm") {
|
|
9021
9221
|
await onboardProviderActivation(agentRoot2, o.provider, o.model);
|
|
9022
9222
|
}
|
|
@@ -9035,7 +9235,7 @@ async function runOnboarding(o) {
|
|
|
9035
9235
|
await printFaucetHint(o.network, address);
|
|
9036
9236
|
if (o.walletKind === "altana") {
|
|
9037
9237
|
printOut(
|
|
9038
|
-
"Altana next step: fund about 0.
|
|
9238
|
+
"Altana next step: fund about 0.05 tBNB for bootstrap/registration, then run `bag wallet session grant`."
|
|
9039
9239
|
);
|
|
9040
9240
|
}
|
|
9041
9241
|
}
|
|
@@ -9045,9 +9245,9 @@ async function onboardProviderActivation(agentRoot2, provider, model) {
|
|
|
9045
9245
|
if (provider === "pieverse-llm") {
|
|
9046
9246
|
const chosenModel = model ?? await promptPieverseModel();
|
|
9047
9247
|
if (model === void 0) {
|
|
9048
|
-
const tomlPath =
|
|
9049
|
-
const text2 =
|
|
9050
|
-
|
|
9248
|
+
const tomlPath = path23.join(agentRoot2, "studio.toml");
|
|
9249
|
+
const text2 = fs24.readFileSync(tomlPath, "utf-8");
|
|
9250
|
+
fs24.writeFileSync(
|
|
9051
9251
|
tomlPath,
|
|
9052
9252
|
updateSection(text2, "llm", { model: chosenModel })
|
|
9053
9253
|
);
|
|
@@ -9083,8 +9283,8 @@ set ${keyEnv}= in .studio/.env.local before running \`bag dev\`.`
|
|
|
9083
9283
|
}
|
|
9084
9284
|
}
|
|
9085
9285
|
async function runOnboardingTwak(o) {
|
|
9086
|
-
const agentRoot2 =
|
|
9087
|
-
const studioToml =
|
|
9286
|
+
const agentRoot2 = path23.join(o.workspaceRoot, APP_DIR, AGENT_PKG);
|
|
9287
|
+
const studioToml = path23.join(agentRoot2, "studio.toml");
|
|
9088
9288
|
if (await whichTwak() === null) {
|
|
9089
9289
|
printErr(
|
|
9090
9290
|
`
|
|
@@ -9100,7 +9300,7 @@ you, so you never type the password on a command line, and adopts the address):
|
|
|
9100
9300
|
}
|
|
9101
9301
|
let walletCfg = {};
|
|
9102
9302
|
try {
|
|
9103
|
-
const data = parseToml(
|
|
9303
|
+
const data = parseToml(fs24.readFileSync(studioToml, "utf-8"));
|
|
9104
9304
|
if (data.wallet !== null && typeof data.wallet === "object") {
|
|
9105
9305
|
walletCfg = data.wallet;
|
|
9106
9306
|
}
|
|
@@ -9109,16 +9309,16 @@ you, so you never type the password on a command line, and adopts the address):
|
|
|
9109
9309
|
}
|
|
9110
9310
|
const { twakWalletFile: twakWalletFile2 } = await import("./_twak-4XF4H5PL.js");
|
|
9111
9311
|
let projectWallet = twakWalletFile2(walletCfg, agentRoot2);
|
|
9112
|
-
const machineWallet =
|
|
9113
|
-
if (!o.twakHomePinned &&
|
|
9312
|
+
const machineWallet = path23.join(os4.homedir(), ".twak", "wallet.json");
|
|
9313
|
+
if (!o.twakHomePinned && isFile9(machineWallet) && realpathIfExists(projectWallet) !== realpathIfExists(machineWallet)) {
|
|
9114
9314
|
if (await promptUseMachineTwakWallet(machineWallet)) {
|
|
9115
9315
|
projectWallet = adoptMachineTwakWallet(machineWallet, o.workspaceRoot);
|
|
9116
9316
|
}
|
|
9117
9317
|
}
|
|
9118
|
-
if (!
|
|
9119
|
-
const homeDir =
|
|
9318
|
+
if (!isFile9(projectWallet)) {
|
|
9319
|
+
const homeDir = path23.dirname(path23.dirname(projectWallet));
|
|
9120
9320
|
try {
|
|
9121
|
-
|
|
9321
|
+
fs24.mkdirSync(homeDir, { recursive: true });
|
|
9122
9322
|
} catch {
|
|
9123
9323
|
}
|
|
9124
9324
|
printErr(
|
|
@@ -9173,9 +9373,9 @@ Guide: the bnbagent-studio-using-twak-wallet.md reference (installed by \`bag sk
|
|
|
9173
9373
|
}
|
|
9174
9374
|
function realpathIfExists(p) {
|
|
9175
9375
|
try {
|
|
9176
|
-
return
|
|
9376
|
+
return fs24.realpathSync(p);
|
|
9177
9377
|
} catch {
|
|
9178
|
-
return
|
|
9378
|
+
return path23.resolve(p);
|
|
9179
9379
|
}
|
|
9180
9380
|
}
|
|
9181
9381
|
async function promptUseMachineTwakWallet(machineWallet) {
|
|
@@ -9188,39 +9388,39 @@ Found an existing twak wallet: ${machineWallet}`);
|
|
|
9188
9388
|
return answer === "y" || answer === "yes";
|
|
9189
9389
|
}
|
|
9190
9390
|
function adoptMachineTwakWallet(machineWallet, workspaceRoot) {
|
|
9191
|
-
const homeDir =
|
|
9192
|
-
const twakDir =
|
|
9193
|
-
|
|
9391
|
+
const homeDir = path23.join(workspaceRoot, ".studio", "twak");
|
|
9392
|
+
const twakDir = path23.join(homeDir, ".twak");
|
|
9393
|
+
fs24.mkdirSync(twakDir, { recursive: true });
|
|
9194
9394
|
try {
|
|
9195
|
-
|
|
9196
|
-
|
|
9395
|
+
fs24.chmodSync(homeDir, 448);
|
|
9396
|
+
fs24.chmodSync(twakDir, 448);
|
|
9197
9397
|
} catch {
|
|
9198
9398
|
}
|
|
9199
9399
|
for (const name of ["wallet.json", "credentials.json"]) {
|
|
9200
|
-
const src =
|
|
9201
|
-
if (
|
|
9202
|
-
const dst =
|
|
9203
|
-
|
|
9204
|
-
|
|
9400
|
+
const src = path23.join(path23.dirname(machineWallet), name);
|
|
9401
|
+
if (isFile9(src)) {
|
|
9402
|
+
const dst = path23.join(twakDir, name);
|
|
9403
|
+
fs24.writeFileSync(dst, fs24.readFileSync(src, "utf-8"), { mode: 384 });
|
|
9404
|
+
fs24.chmodSync(dst, 384);
|
|
9205
9405
|
}
|
|
9206
9406
|
}
|
|
9207
|
-
return
|
|
9407
|
+
return path23.join(twakDir, "wallet.json");
|
|
9208
9408
|
}
|
|
9209
9409
|
function normalizeTwakHome(raw) {
|
|
9210
|
-
const expanded = raw.startsWith("~") ?
|
|
9211
|
-
if (!
|
|
9410
|
+
const expanded = raw.startsWith("~") ? path23.join(os4.homedir(), raw.slice(1)) : raw;
|
|
9411
|
+
if (!path23.isAbsolute(expanded)) {
|
|
9212
9412
|
return { home: raw };
|
|
9213
9413
|
}
|
|
9214
|
-
const
|
|
9414
|
+
const isFile20 = (p) => {
|
|
9215
9415
|
try {
|
|
9216
|
-
return
|
|
9416
|
+
return fs24.statSync(p).isFile();
|
|
9217
9417
|
} catch {
|
|
9218
9418
|
return false;
|
|
9219
9419
|
}
|
|
9220
9420
|
};
|
|
9221
|
-
if (
|
|
9222
|
-
const parent =
|
|
9223
|
-
if (
|
|
9421
|
+
if (path23.basename(expanded) === ".twak") {
|
|
9422
|
+
const parent = path23.dirname(expanded);
|
|
9423
|
+
if (isFile20(path23.join(expanded, "wallet.json"))) {
|
|
9224
9424
|
return {
|
|
9225
9425
|
home: parent,
|
|
9226
9426
|
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 +9430,15 @@ function normalizeTwakHome(raw) {
|
|
|
9230
9430
|
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
9431
|
};
|
|
9232
9432
|
}
|
|
9233
|
-
if (
|
|
9433
|
+
if (isFile20(path23.join(expanded, "wallet.json")) && !isFile20(path23.join(expanded, ".twak", "wallet.json"))) {
|
|
9234
9434
|
return {
|
|
9235
|
-
error: `error: --twak-home '${raw}' looks like a twak WALLET directory (it contains wallet.json directly). Pass its parent '${
|
|
9435
|
+
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
9436
|
};
|
|
9237
9437
|
}
|
|
9238
|
-
if (!
|
|
9438
|
+
if (!isFile20(path23.join(expanded, ".twak", "wallet.json"))) {
|
|
9239
9439
|
return {
|
|
9240
9440
|
home: raw,
|
|
9241
|
-
note: `note: no wallet found at ${
|
|
9441
|
+
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
9442
|
};
|
|
9243
9443
|
}
|
|
9244
9444
|
return { home: raw };
|
|
@@ -9248,7 +9448,7 @@ function twakHomeIsMainHome(twakHome) {
|
|
|
9248
9448
|
return false;
|
|
9249
9449
|
}
|
|
9250
9450
|
try {
|
|
9251
|
-
const expanded = twakHome.startsWith("~") ?
|
|
9451
|
+
const expanded = twakHome.startsWith("~") ? path23.join(os4.homedir(), twakHome.slice(1)) : twakHome;
|
|
9252
9452
|
return realpathIfExists(expanded) === realpathIfExists(os4.homedir());
|
|
9253
9453
|
} catch {
|
|
9254
9454
|
return false;
|
|
@@ -9339,8 +9539,10 @@ NOTE \u2014 wallet.kind = "altana" (bounded runtime session):
|
|
|
9339
9539
|
.studio/wallets/. WALLET_PASSWORD is used only by wallet/session commands.
|
|
9340
9540
|
\xB7 RUNTIME: fund the admin address, then run \`bag wallet session grant\`.
|
|
9341
9541
|
The Agent receives only .studio/wallets/altana-session.json.
|
|
9342
|
-
\xB7 DEPLOY:
|
|
9343
|
-
|
|
9542
|
+
\xB7 DEPLOY: \`bag deploy\` ships ONLY the bounded session (as the
|
|
9543
|
+
ALTANA_SESSION runtime secret) \u2014 the admin keystore and WALLET_PASSWORD
|
|
9544
|
+
never leave this machine. When the session expires, re-grant with
|
|
9545
|
+
\`bag wallet session grant --force\` and redeploy.`
|
|
9344
9546
|
);
|
|
9345
9547
|
}
|
|
9346
9548
|
function printPlatformWalletSuggestion() {
|
|
@@ -9398,11 +9600,11 @@ function entrypointHint(faces) {
|
|
|
9398
9600
|
return "app/agent/src/main.ts + executor.ts = A2A entrypoint (build your value here)";
|
|
9399
9601
|
}
|
|
9400
9602
|
function hasVendoredTarballs(agentDir) {
|
|
9401
|
-
const vendor =
|
|
9603
|
+
const vendor = path23.join(agentDir, "vendor");
|
|
9402
9604
|
if (!isDir4(vendor)) {
|
|
9403
9605
|
return false;
|
|
9404
9606
|
}
|
|
9405
|
-
return
|
|
9607
|
+
return fs24.readdirSync(vendor).some((n) => n.endsWith(".tgz"));
|
|
9406
9608
|
}
|
|
9407
9609
|
function printCompactNextSteps(name, o = {}) {
|
|
9408
9610
|
const faces = o.faces ?? normalizeProtocolFaces(o.protocol ?? "A2A");
|
|
@@ -9430,7 +9632,7 @@ function printCompactNextSteps(name, o = {}) {
|
|
|
9430
9632
|
}
|
|
9431
9633
|
if (walletKind2 === "altana") {
|
|
9432
9634
|
printOut(
|
|
9433
|
-
" bag wallet session grant # after funding ~0.
|
|
9635
|
+
" bag wallet session grant # after funding ~0.05 tBNB: create the bounded runtime session"
|
|
9434
9636
|
);
|
|
9435
9637
|
if (o.provider === "pieverse-llm") {
|
|
9436
9638
|
printOut(
|
|
@@ -9554,7 +9756,7 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9554
9756
|
printOut(" # bag auto-loads it; never pass it on argv");
|
|
9555
9757
|
printOut(" (cd app/agent && bag wallet new)");
|
|
9556
9758
|
printOut(
|
|
9557
|
-
" # 2. fund the printed address with ~0.
|
|
9759
|
+
" # 2. fund the printed address with ~0.05 tBNB for bootstrap/registration + U, then grant one bounded runtime session"
|
|
9558
9760
|
);
|
|
9559
9761
|
printOut(" (cd app/agent && bag wallet session grant)");
|
|
9560
9762
|
printOut(
|
|
@@ -9576,20 +9778,7 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9576
9778
|
}
|
|
9577
9779
|
printOut("");
|
|
9578
9780
|
let nextStep;
|
|
9579
|
-
if (provider === "pieverse-llm"
|
|
9580
|
-
printOut(
|
|
9581
|
-
" # Pieverse `bag llm activate` needs generic SIWE message signing, which"
|
|
9582
|
-
);
|
|
9583
|
-
printOut(
|
|
9584
|
-
" # Altana intentionally does not expose. Runtime paid-model credit renewal"
|
|
9585
|
-
);
|
|
9586
|
-
printOut(
|
|
9587
|
-
" # needs the same SIWE flow, so an existing key works only with auto/free."
|
|
9588
|
-
);
|
|
9589
|
-
printOut(" # Use openrouter/openai/anthropic for paid models.");
|
|
9590
|
-
printOut("");
|
|
9591
|
-
nextStep = 3;
|
|
9592
|
-
} else if (provider === "pieverse-llm") {
|
|
9781
|
+
if (provider === "pieverse-llm") {
|
|
9593
9782
|
printOut(" # 3. activate Pieverse LLM (zero-deposit by default)");
|
|
9594
9783
|
printOut(
|
|
9595
9784
|
" # SIWE login + create API key with $0 allocation. Default model"
|
|
@@ -9652,11 +9841,11 @@ function printNextSteps(name, provider, o = {}) {
|
|
|
9652
9841
|
);
|
|
9653
9842
|
}
|
|
9654
9843
|
function loadTomlSafe(p) {
|
|
9655
|
-
if (!
|
|
9844
|
+
if (!isFile9(p)) {
|
|
9656
9845
|
return {};
|
|
9657
9846
|
}
|
|
9658
9847
|
try {
|
|
9659
|
-
return parseToml(
|
|
9848
|
+
return parseToml(fs24.readFileSync(p, "utf-8"));
|
|
9660
9849
|
} catch {
|
|
9661
9850
|
return {};
|
|
9662
9851
|
}
|
|
@@ -9676,7 +9865,7 @@ function weiToU(raw) {
|
|
|
9676
9865
|
}
|
|
9677
9866
|
}
|
|
9678
9867
|
function printConfigSummary(agentRoot2) {
|
|
9679
|
-
const agent = loadTomlSafe(
|
|
9868
|
+
const agent = loadTomlSafe(path23.join(agentRoot2, "studio.toml"));
|
|
9680
9869
|
if (Object.keys(agent).length === 0) {
|
|
9681
9870
|
return;
|
|
9682
9871
|
}
|
|
@@ -9874,16 +10063,16 @@ function printConfigSummary(agentRoot2) {
|
|
|
9874
10063
|
printOut("");
|
|
9875
10064
|
}
|
|
9876
10065
|
}
|
|
9877
|
-
function
|
|
10066
|
+
function isFile9(p) {
|
|
9878
10067
|
try {
|
|
9879
|
-
return
|
|
10068
|
+
return fs24.statSync(p).isFile();
|
|
9880
10069
|
} catch {
|
|
9881
10070
|
return false;
|
|
9882
10071
|
}
|
|
9883
10072
|
}
|
|
9884
10073
|
function isDir4(p) {
|
|
9885
10074
|
try {
|
|
9886
|
-
return
|
|
10075
|
+
return fs24.statSync(p).isDirectory();
|
|
9887
10076
|
} catch {
|
|
9888
10077
|
return false;
|
|
9889
10078
|
}
|
|
@@ -9947,9 +10136,9 @@ var RUNTIME_AGENTCORE = "agentcore";
|
|
|
9947
10136
|
var RUNTIME_AZURE_FOUNDRY = "azure-foundry";
|
|
9948
10137
|
var MIN_NODE_MAJOR = 22;
|
|
9949
10138
|
var CONTAINER_RUNTIMES = ["docker", "podman", "finch"];
|
|
9950
|
-
function
|
|
10139
|
+
function isFile10(p) {
|
|
9951
10140
|
try {
|
|
9952
|
-
return
|
|
10141
|
+
return fs25.statSync(p).isFile();
|
|
9953
10142
|
} catch {
|
|
9954
10143
|
return false;
|
|
9955
10144
|
}
|
|
@@ -9981,8 +10170,8 @@ async function nodeMajor() {
|
|
|
9981
10170
|
return /^\d+$/.test(head) ? Number.parseInt(head, 10) : null;
|
|
9982
10171
|
}
|
|
9983
10172
|
function workspaceBase(root) {
|
|
9984
|
-
for (const base of [
|
|
9985
|
-
if (
|
|
10173
|
+
for (const base of [path24.join(root, "app"), root]) {
|
|
10174
|
+
if (isFile10(path24.join(base, "agent", "studio.toml"))) {
|
|
9986
10175
|
return base;
|
|
9987
10176
|
}
|
|
9988
10177
|
}
|
|
@@ -9990,7 +10179,7 @@ function workspaceBase(root) {
|
|
|
9990
10179
|
}
|
|
9991
10180
|
function resolveWorkspaceRoot(argRoot) {
|
|
9992
10181
|
if (argRoot !== null) {
|
|
9993
|
-
const root =
|
|
10182
|
+
const root = path24.resolve(argRoot);
|
|
9994
10183
|
const base = workspaceBase(root);
|
|
9995
10184
|
if (base === null) {
|
|
9996
10185
|
printErr(
|
|
@@ -10000,13 +10189,13 @@ function resolveWorkspaceRoot(argRoot) {
|
|
|
10000
10189
|
}
|
|
10001
10190
|
return base;
|
|
10002
10191
|
}
|
|
10003
|
-
let current =
|
|
10192
|
+
let current = path24.resolve(process.cwd());
|
|
10004
10193
|
for (; ; ) {
|
|
10005
10194
|
const base = workspaceBase(current);
|
|
10006
10195
|
if (base !== null) {
|
|
10007
10196
|
return base;
|
|
10008
10197
|
}
|
|
10009
|
-
const parent =
|
|
10198
|
+
const parent = path24.dirname(current);
|
|
10010
10199
|
if (parent === current) {
|
|
10011
10200
|
break;
|
|
10012
10201
|
}
|
|
@@ -10020,7 +10209,7 @@ function resolveWorkspaceRoot(argRoot) {
|
|
|
10020
10209
|
function loadAgentToml2(workspaceRoot) {
|
|
10021
10210
|
try {
|
|
10022
10211
|
return loadStudioToml11(
|
|
10023
|
-
|
|
10212
|
+
path24.join(workspaceRoot, "agent", "studio.toml")
|
|
10024
10213
|
);
|
|
10025
10214
|
} catch {
|
|
10026
10215
|
return {};
|
|
@@ -10047,7 +10236,7 @@ function defaultAgentPort(faces) {
|
|
|
10047
10236
|
function storageKind(agentDir) {
|
|
10048
10237
|
let data;
|
|
10049
10238
|
try {
|
|
10050
|
-
data = loadStudioToml11(
|
|
10239
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10051
10240
|
} catch {
|
|
10052
10241
|
return "local";
|
|
10053
10242
|
}
|
|
@@ -10057,7 +10246,7 @@ function storageKind(agentDir) {
|
|
|
10057
10246
|
function networkNameOf(agentDir) {
|
|
10058
10247
|
let data;
|
|
10059
10248
|
try {
|
|
10060
|
-
data = loadStudioToml11(
|
|
10249
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10061
10250
|
} catch {
|
|
10062
10251
|
return "bsc-testnet";
|
|
10063
10252
|
}
|
|
@@ -10067,7 +10256,7 @@ function networkNameOf(agentDir) {
|
|
|
10067
10256
|
function walletKindOf(agentDir) {
|
|
10068
10257
|
let data;
|
|
10069
10258
|
try {
|
|
10070
|
-
data = loadStudioToml11(
|
|
10259
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10071
10260
|
} catch {
|
|
10072
10261
|
return "evm-local";
|
|
10073
10262
|
}
|
|
@@ -10075,18 +10264,18 @@ function walletKindOf(agentDir) {
|
|
|
10075
10264
|
return typeof kind === "string" && kind.trim() ? kind.trim() : "evm-local";
|
|
10076
10265
|
}
|
|
10077
10266
|
function altanaSessionForRuntime(agentDir) {
|
|
10078
|
-
const cfg = loadStudioToml11(
|
|
10267
|
+
const cfg = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10079
10268
|
const wallet = tableOf9(cfg, "wallet");
|
|
10080
10269
|
const configured = String(
|
|
10081
10270
|
wallet.session_file ?? ".studio/wallets/altana-session.json"
|
|
10082
10271
|
);
|
|
10083
|
-
const sessionFile =
|
|
10084
|
-
if (!
|
|
10272
|
+
const sessionFile = path24.isAbsolute(configured) ? configured : path24.join(agentDir, configured);
|
|
10273
|
+
if (!isFile10(sessionFile)) {
|
|
10085
10274
|
throw new Error(
|
|
10086
10275
|
`no Altana session at ${sessionFile} \u2014 run \`bag wallet session grant\` first.`
|
|
10087
10276
|
);
|
|
10088
10277
|
}
|
|
10089
|
-
const serialized =
|
|
10278
|
+
const serialized = fs25.readFileSync(sessionFile, "utf8");
|
|
10090
10279
|
let envelope;
|
|
10091
10280
|
try {
|
|
10092
10281
|
envelope = JSON.parse(serialized);
|
|
@@ -10115,10 +10304,10 @@ function altanaSessionForRuntime(agentDir) {
|
|
|
10115
10304
|
}
|
|
10116
10305
|
var KEY_LINE_RE = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/;
|
|
10117
10306
|
function loadEnvFileForDev(p) {
|
|
10118
|
-
if (!
|
|
10307
|
+
if (!isFile10(p)) {
|
|
10119
10308
|
return;
|
|
10120
10309
|
}
|
|
10121
|
-
for (const line of
|
|
10310
|
+
for (const line of fs25.readFileSync(p, "utf-8").split(/\r?\n/)) {
|
|
10122
10311
|
if (!line || line.trimStart().startsWith("#")) {
|
|
10123
10312
|
continue;
|
|
10124
10313
|
}
|
|
@@ -10139,20 +10328,20 @@ function ensureStoragePath(projectRoot) {
|
|
|
10139
10328
|
const raw = process.env.STORAGE_LOCAL_PATH;
|
|
10140
10329
|
let resolved;
|
|
10141
10330
|
if (raw) {
|
|
10142
|
-
resolved =
|
|
10143
|
-
raw.startsWith("~") ?
|
|
10331
|
+
resolved = path24.resolve(
|
|
10332
|
+
raw.startsWith("~") ? path24.join(os5.homedir(), raw.slice(1)) : raw
|
|
10144
10333
|
);
|
|
10145
10334
|
} else {
|
|
10146
|
-
resolved =
|
|
10147
|
-
|
|
10335
|
+
resolved = path24.resolve(
|
|
10336
|
+
path24.join(
|
|
10148
10337
|
os5.homedir(),
|
|
10149
10338
|
".bag",
|
|
10150
10339
|
"deliverables",
|
|
10151
|
-
|
|
10340
|
+
path24.basename(projectRoot)
|
|
10152
10341
|
)
|
|
10153
10342
|
);
|
|
10154
10343
|
}
|
|
10155
|
-
|
|
10344
|
+
fs25.mkdirSync(resolved, { recursive: true });
|
|
10156
10345
|
process.env.STORAGE_LOCAL_PATH = resolved;
|
|
10157
10346
|
}
|
|
10158
10347
|
function ipfsPreflight(agentDir) {
|
|
@@ -10167,7 +10356,7 @@ function ipfsPreflight(agentDir) {
|
|
|
10167
10356
|
function runtimeEnvKeys(agentDir) {
|
|
10168
10357
|
let cfg = {};
|
|
10169
10358
|
try {
|
|
10170
|
-
cfg = loadStudioToml11(
|
|
10359
|
+
cfg = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10171
10360
|
} catch {
|
|
10172
10361
|
cfg = {};
|
|
10173
10362
|
}
|
|
@@ -10184,7 +10373,7 @@ function readTwakFiles(agentDir) {
|
|
|
10184
10373
|
let walletCfg = {};
|
|
10185
10374
|
try {
|
|
10186
10375
|
walletCfg = tableOf9(
|
|
10187
|
-
loadStudioToml11(
|
|
10376
|
+
loadStudioToml11(path24.join(agentDir, "studio.toml")),
|
|
10188
10377
|
"wallet"
|
|
10189
10378
|
);
|
|
10190
10379
|
} catch {
|
|
@@ -10192,9 +10381,9 @@ function readTwakFiles(agentDir) {
|
|
|
10192
10381
|
}
|
|
10193
10382
|
const twakDir = twakHomeDir(walletCfg, agentDir);
|
|
10194
10383
|
const read = (name) => {
|
|
10195
|
-
const p =
|
|
10384
|
+
const p = path24.join(twakDir, name);
|
|
10196
10385
|
try {
|
|
10197
|
-
return
|
|
10386
|
+
return fs25.readFileSync(p, "utf-8");
|
|
10198
10387
|
} catch {
|
|
10199
10388
|
return null;
|
|
10200
10389
|
}
|
|
@@ -10202,19 +10391,19 @@ function readTwakFiles(agentDir) {
|
|
|
10202
10391
|
return [read("wallet.json"), read("credentials.json")];
|
|
10203
10392
|
}
|
|
10204
10393
|
function ensureAgentcoreEnvGitignored(agentcoreDir) {
|
|
10205
|
-
const gi =
|
|
10394
|
+
const gi = path24.join(agentcoreDir, ".gitignore");
|
|
10206
10395
|
const entry = ".env.local";
|
|
10207
|
-
if (
|
|
10208
|
-
const text2 =
|
|
10396
|
+
if (isFile10(gi)) {
|
|
10397
|
+
const text2 = fs25.readFileSync(gi, "utf-8");
|
|
10209
10398
|
const lines = new Set(text2.split("\n").map((l) => l.trim()));
|
|
10210
10399
|
if (lines.has(entry)) {
|
|
10211
10400
|
return;
|
|
10212
10401
|
}
|
|
10213
|
-
const
|
|
10214
|
-
|
|
10402
|
+
const sep7 = text2.endsWith("\n") || text2 === "" ? "" : "\n";
|
|
10403
|
+
fs25.writeFileSync(gi, `${text2}${sep7}${entry}
|
|
10215
10404
|
`);
|
|
10216
10405
|
} else {
|
|
10217
|
-
|
|
10406
|
+
fs25.writeFileSync(gi, `${entry}
|
|
10218
10407
|
`);
|
|
10219
10408
|
}
|
|
10220
10409
|
}
|
|
@@ -10237,8 +10426,8 @@ function writeAgentcoreEnvLocal(agentcoreRoot, agentDir) {
|
|
|
10237
10426
|
} else if (walletKindOf(agentDir) === "altana") {
|
|
10238
10427
|
bundle.ALTANA_SESSION = altanaSessionForRuntime(agentDir);
|
|
10239
10428
|
}
|
|
10240
|
-
const envPath =
|
|
10241
|
-
const prior =
|
|
10429
|
+
const envPath = path24.join(agentcoreRoot, "agentcore", ".env.local");
|
|
10430
|
+
const prior = isFile10(envPath) ? fs25.readFileSync(envPath, "utf-8") : "";
|
|
10242
10431
|
const merged = {};
|
|
10243
10432
|
for (const line of prior.split("\n")) {
|
|
10244
10433
|
if (!line || line.trimStart().startsWith("#")) {
|
|
@@ -10253,14 +10442,14 @@ function writeAgentcoreEnvLocal(agentcoreRoot, agentDir) {
|
|
|
10253
10442
|
Object.assign(merged, bundle);
|
|
10254
10443
|
const content = Object.entries(merged).map(([k, v]) => `${k}=${v}
|
|
10255
10444
|
`).join("");
|
|
10256
|
-
|
|
10257
|
-
ensureAgentcoreEnvGitignored(
|
|
10445
|
+
fs25.mkdirSync(path24.dirname(envPath), { recursive: true });
|
|
10446
|
+
ensureAgentcoreEnvGitignored(path24.dirname(envPath));
|
|
10258
10447
|
writePrivate2(envPath, content);
|
|
10259
10448
|
return [envPath, content !== prior];
|
|
10260
10449
|
}
|
|
10261
10450
|
function agentcoreProjectRoot2(workspaceRoot) {
|
|
10262
|
-
for (const candidate of [
|
|
10263
|
-
if (
|
|
10451
|
+
for (const candidate of [path24.dirname(workspaceRoot), workspaceRoot]) {
|
|
10452
|
+
if (isFile10(path24.join(candidate, "agentcore", "agentcore.json"))) {
|
|
10264
10453
|
return candidate;
|
|
10265
10454
|
}
|
|
10266
10455
|
}
|
|
@@ -10269,8 +10458,8 @@ function agentcoreProjectRoot2(workspaceRoot) {
|
|
|
10269
10458
|
function loadAgentcoreConfig(projectRoot) {
|
|
10270
10459
|
try {
|
|
10271
10460
|
const cfg = JSON.parse(
|
|
10272
|
-
|
|
10273
|
-
|
|
10461
|
+
fs25.readFileSync(
|
|
10462
|
+
path24.join(projectRoot, "agentcore", "agentcore.json"),
|
|
10274
10463
|
"utf-8"
|
|
10275
10464
|
)
|
|
10276
10465
|
);
|
|
@@ -10360,7 +10549,7 @@ async function cmdDev(opts) {
|
|
|
10360
10549
|
if (workspaceRoot === null) {
|
|
10361
10550
|
return 2;
|
|
10362
10551
|
}
|
|
10363
|
-
const agentDir =
|
|
10552
|
+
const agentDir = path24.join(workspaceRoot, "agent");
|
|
10364
10553
|
migrateEnvLocal(agentDir);
|
|
10365
10554
|
migrateKeystoreOutOfCodelocation(agentDir);
|
|
10366
10555
|
const { envLocalPath: envLocalPath19 } = await import("@bnbagent/studio-runtime/config");
|
|
@@ -10396,8 +10585,8 @@ async function cmdDev(opts) {
|
|
|
10396
10585
|
const runtime = agentRuntime(workspaceRoot);
|
|
10397
10586
|
const container = Boolean(opts.container);
|
|
10398
10587
|
const entryFile = localEntryFile(faces);
|
|
10399
|
-
const agentFile =
|
|
10400
|
-
if (!
|
|
10588
|
+
const agentFile = path24.join(agentDir, entryFile);
|
|
10589
|
+
if (!isFile10(agentFile)) {
|
|
10401
10590
|
printErr(
|
|
10402
10591
|
`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
10592
|
);
|
|
@@ -10475,7 +10664,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10475
10664
|
}
|
|
10476
10665
|
let launch;
|
|
10477
10666
|
if (runtime === RUNTIME_AGENTCORE && container) {
|
|
10478
|
-
const root =
|
|
10667
|
+
const root = path24.resolve(agentcoreRoot);
|
|
10479
10668
|
try {
|
|
10480
10669
|
const vendored = await vendorLocalTarballs(agentDir);
|
|
10481
10670
|
if (vendored.length > 0) {
|
|
@@ -10490,7 +10679,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10490
10679
|
}
|
|
10491
10680
|
const [envPath, changed] = writeAgentcoreEnvLocal(root, agentDir);
|
|
10492
10681
|
printOut(
|
|
10493
|
-
`bag dev: wrote ${
|
|
10682
|
+
`bag dev: wrote ${path24.relative(root, envPath)} (runtime secrets + materialized wallet for the container).`
|
|
10494
10683
|
);
|
|
10495
10684
|
if (changed && process.env.BAG_DEV_ENV_WARNED !== "1") {
|
|
10496
10685
|
printErr(
|
|
@@ -10567,7 +10756,7 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10567
10756
|
}
|
|
10568
10757
|
if (hasX402Face(faces)) {
|
|
10569
10758
|
const free = x402SellerIsFree(
|
|
10570
|
-
loadStudioToml11(
|
|
10759
|
+
loadStudioToml11(path24.join(agentDir, "studio.toml"))
|
|
10571
10760
|
);
|
|
10572
10761
|
printOut(
|
|
10573
10762
|
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 +10767,9 @@ Switch to Node \u226522 so it wins on PATH, then reopen the shell and retry. Ver
|
|
|
10578
10767
|
}
|
|
10579
10768
|
function tsxRunner(agentDir, workspaceBaseDir) {
|
|
10580
10769
|
const bin = process.platform === "win32" ? "tsx.cmd" : "tsx";
|
|
10581
|
-
for (const dir of [agentDir,
|
|
10582
|
-
const candidate =
|
|
10583
|
-
if (
|
|
10770
|
+
for (const dir of [agentDir, path24.dirname(workspaceBaseDir)]) {
|
|
10771
|
+
const candidate = path24.join(dir, "node_modules", ".bin", bin);
|
|
10772
|
+
if (isFile10(candidate)) {
|
|
10584
10773
|
return candidate;
|
|
10585
10774
|
}
|
|
10586
10775
|
}
|
|
@@ -10589,7 +10778,7 @@ function tsxRunner(agentDir, workspaceBaseDir) {
|
|
|
10589
10778
|
function networkBanner(agentDir) {
|
|
10590
10779
|
let data;
|
|
10591
10780
|
try {
|
|
10592
|
-
data = loadStudioToml11(
|
|
10781
|
+
data = loadStudioToml11(path24.join(agentDir, "studio.toml"));
|
|
10593
10782
|
} catch {
|
|
10594
10783
|
return null;
|
|
10595
10784
|
}
|
|
@@ -10606,34 +10795,34 @@ function networkBanner(agentDir) {
|
|
|
10606
10795
|
}
|
|
10607
10796
|
|
|
10608
10797
|
// src/cli/_deploy/checks/critical.ts
|
|
10609
|
-
import * as
|
|
10798
|
+
import * as fs26 from "fs";
|
|
10610
10799
|
import { createRequire } from "module";
|
|
10611
|
-
import * as
|
|
10800
|
+
import * as path25 from "path";
|
|
10612
10801
|
import { envLocalPath as envLocalPath11, loadStudioToml as loadStudioToml12 } from "@bnbagent/studio-runtime/config";
|
|
10613
10802
|
import { pieverseKeyHash as pieverseKeyHash2 } from "@bnbagent/studio-runtime/llm";
|
|
10614
10803
|
var AGENTCORE_DESCRIPTOR2 = "agentcore/agentcore.json";
|
|
10615
|
-
function
|
|
10804
|
+
function isFile11(p) {
|
|
10616
10805
|
try {
|
|
10617
|
-
return
|
|
10806
|
+
return fs26.statSync(p).isFile();
|
|
10618
10807
|
} catch {
|
|
10619
10808
|
return false;
|
|
10620
10809
|
}
|
|
10621
10810
|
}
|
|
10622
10811
|
function isDir5(p) {
|
|
10623
10812
|
try {
|
|
10624
|
-
return
|
|
10813
|
+
return fs26.statSync(p).isDirectory();
|
|
10625
10814
|
} catch {
|
|
10626
10815
|
return false;
|
|
10627
10816
|
}
|
|
10628
10817
|
}
|
|
10629
10818
|
function keystoreDirOf(root, data) {
|
|
10630
10819
|
const rel = String(tableOf2(data, "wallet").keystore_dir ?? ".studio/wallets");
|
|
10631
|
-
const dir =
|
|
10632
|
-
return
|
|
10820
|
+
const dir = path25.isAbsolute(rel) ? rel : path25.join(agentRootOf(root), rel);
|
|
10821
|
+
return path25.resolve(dir);
|
|
10633
10822
|
}
|
|
10634
10823
|
function keystoreJsonFiles2(dir) {
|
|
10635
10824
|
try {
|
|
10636
|
-
return
|
|
10825
|
+
return fs26.readdirSync(dir).filter((n) => n.endsWith(".json")).sort();
|
|
10637
10826
|
} catch {
|
|
10638
10827
|
return [];
|
|
10639
10828
|
}
|
|
@@ -10641,7 +10830,7 @@ function keystoreJsonFiles2(dir) {
|
|
|
10641
10830
|
function runtimeEnvKeys2(agentRoot2) {
|
|
10642
10831
|
let cfg = {};
|
|
10643
10832
|
try {
|
|
10644
|
-
cfg = loadStudioToml12(
|
|
10833
|
+
cfg = loadStudioToml12(path25.join(agentRoot2, "studio.toml"));
|
|
10645
10834
|
} catch {
|
|
10646
10835
|
cfg = {};
|
|
10647
10836
|
}
|
|
@@ -10653,8 +10842,8 @@ async function checkAgentcoreJsonPresent(root, target) {
|
|
|
10653
10842
|
if (target !== "agentcore") {
|
|
10654
10843
|
return [];
|
|
10655
10844
|
}
|
|
10656
|
-
const descriptor =
|
|
10657
|
-
if (
|
|
10845
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
10846
|
+
if (isFile11(descriptor)) {
|
|
10658
10847
|
return [];
|
|
10659
10848
|
}
|
|
10660
10849
|
return [
|
|
@@ -10670,10 +10859,10 @@ async function checkAgentcoreAuthorizerKeyLegacy(root, target) {
|
|
|
10670
10859
|
if (target !== "agentcore") {
|
|
10671
10860
|
return [];
|
|
10672
10861
|
}
|
|
10673
|
-
const descriptor =
|
|
10862
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
10674
10863
|
let data;
|
|
10675
10864
|
try {
|
|
10676
|
-
data = JSON.parse(
|
|
10865
|
+
data = JSON.parse(fs26.readFileSync(descriptor, "utf-8"));
|
|
10677
10866
|
} catch {
|
|
10678
10867
|
return [];
|
|
10679
10868
|
}
|
|
@@ -10713,10 +10902,10 @@ async function checkAgentPackagePresent(root, target) {
|
|
|
10713
10902
|
sourceEntries.push("src/mcpMain.ts");
|
|
10714
10903
|
}
|
|
10715
10904
|
const missingSource = sourceEntries.find(
|
|
10716
|
-
(entry) => !
|
|
10905
|
+
(entry) => !isFile11(path25.join(agentRoot2, entry))
|
|
10717
10906
|
);
|
|
10718
10907
|
if (missingSource !== void 0) {
|
|
10719
|
-
const epPath =
|
|
10908
|
+
const epPath = path25.join(agentRoot2, missingSource);
|
|
10720
10909
|
return [
|
|
10721
10910
|
{
|
|
10722
10911
|
level: Level.CRITICAL,
|
|
@@ -10731,10 +10920,10 @@ async function checkAgentPackagePresent(root, target) {
|
|
|
10731
10920
|
distEntries.push("dist/mcpMain.js");
|
|
10732
10921
|
}
|
|
10733
10922
|
const missingDist = distEntries.find(
|
|
10734
|
-
(entry) => !
|
|
10923
|
+
(entry) => !isFile11(path25.join(agentRoot2, entry))
|
|
10735
10924
|
);
|
|
10736
10925
|
if (missingDist !== void 0) {
|
|
10737
|
-
const distPath =
|
|
10926
|
+
const distPath = path25.join(agentRoot2, missingDist);
|
|
10738
10927
|
return [
|
|
10739
10928
|
{
|
|
10740
10929
|
level: Level.WARNING,
|
|
@@ -10759,8 +10948,8 @@ async function checkKeystoreNotInsideAgent(root, target) {
|
|
|
10759
10948
|
if (!isDir5(keystoreDir) || keystoreJsonFiles2(keystoreDir).length === 0) {
|
|
10760
10949
|
return [];
|
|
10761
10950
|
}
|
|
10762
|
-
const agentDir =
|
|
10763
|
-
const inside2 = keystoreDir === agentDir || keystoreDir.startsWith(agentDir +
|
|
10951
|
+
const agentDir = path25.resolve(agentRootOf(root));
|
|
10952
|
+
const inside2 = keystoreDir === agentDir || keystoreDir.startsWith(agentDir + path25.sep);
|
|
10764
10953
|
if (!inside2) {
|
|
10765
10954
|
return [];
|
|
10766
10955
|
}
|
|
@@ -10779,6 +10968,9 @@ async function checkLocalKeystoreExists(root, _target) {
|
|
|
10779
10968
|
if (walletCfg.kind === "twak") {
|
|
10780
10969
|
return [];
|
|
10781
10970
|
}
|
|
10971
|
+
if (walletCfg.kind === "altana") {
|
|
10972
|
+
return [];
|
|
10973
|
+
}
|
|
10782
10974
|
const signer = walletCfg.signer ?? "local";
|
|
10783
10975
|
if (signer !== "local") {
|
|
10784
10976
|
return [];
|
|
@@ -10797,7 +10989,11 @@ async function checkLocalKeystoreExists(root, _target) {
|
|
|
10797
10989
|
];
|
|
10798
10990
|
}
|
|
10799
10991
|
async function checkWalletPasswordEnvSet(root, _target) {
|
|
10800
|
-
|
|
10992
|
+
const kind = tableOf2(loadAgentToml(root), "wallet").kind;
|
|
10993
|
+
if (kind === "twak") {
|
|
10994
|
+
return [];
|
|
10995
|
+
}
|
|
10996
|
+
if (kind === "altana") {
|
|
10801
10997
|
return [];
|
|
10802
10998
|
}
|
|
10803
10999
|
if (process.env.WALLET_PASSWORD) {
|
|
@@ -10836,18 +11032,18 @@ async function checkLlmProviderKeySet(root, _target) {
|
|
|
10836
11032
|
function gitignoreLines(p) {
|
|
10837
11033
|
try {
|
|
10838
11034
|
return new Set(
|
|
10839
|
-
|
|
11035
|
+
fs26.readFileSync(p, "utf-8").split(/\r?\n/).map((l) => l.trim())
|
|
10840
11036
|
);
|
|
10841
11037
|
} catch {
|
|
10842
11038
|
return null;
|
|
10843
11039
|
}
|
|
10844
11040
|
}
|
|
10845
11041
|
function agentcoreEnvLocalIgnored(ws) {
|
|
10846
|
-
const wsLines = gitignoreLines(
|
|
11042
|
+
const wsLines = gitignoreLines(path25.join(ws, ".gitignore"));
|
|
10847
11043
|
if (wsLines?.has("agentcore/.env.local")) {
|
|
10848
11044
|
return true;
|
|
10849
11045
|
}
|
|
10850
|
-
const acLines = gitignoreLines(
|
|
11046
|
+
const acLines = gitignoreLines(path25.join(ws, "agentcore", ".gitignore"));
|
|
10851
11047
|
return acLines?.has(".env.local") ?? false;
|
|
10852
11048
|
}
|
|
10853
11049
|
function studioIgnored(lines) {
|
|
@@ -10858,8 +11054,8 @@ function studioIgnored(lines) {
|
|
|
10858
11054
|
}
|
|
10859
11055
|
async function checkGitignoreExcludesSecrets(root, _target) {
|
|
10860
11056
|
const out = [];
|
|
10861
|
-
const ws =
|
|
10862
|
-
const gi =
|
|
11057
|
+
const ws = path25.dirname(path25.dirname(envLocalPath11(root)));
|
|
11058
|
+
const gi = path25.join(ws, ".gitignore");
|
|
10863
11059
|
const lines = gitignoreLines(gi);
|
|
10864
11060
|
if (lines === null) {
|
|
10865
11061
|
return [
|
|
@@ -10881,7 +11077,7 @@ async function checkGitignoreExcludesSecrets(root, _target) {
|
|
|
10881
11077
|
details: { missing: [".studio/"] }
|
|
10882
11078
|
});
|
|
10883
11079
|
}
|
|
10884
|
-
if (isDir5(
|
|
11080
|
+
if (isDir5(path25.join(ws, "agentcore")) && !agentcoreEnvLocalIgnored(ws)) {
|
|
10885
11081
|
out.push({
|
|
10886
11082
|
level: Level.CRITICAL,
|
|
10887
11083
|
name: "gitignore_excludes_secrets",
|
|
@@ -10898,16 +11094,16 @@ function installedRuntimeVersion() {
|
|
|
10898
11094
|
}
|
|
10899
11095
|
try {
|
|
10900
11096
|
const entry = require2.resolve("@bnbagent/studio-runtime");
|
|
10901
|
-
let dir =
|
|
11097
|
+
let dir = path25.dirname(entry);
|
|
10902
11098
|
for (let i = 0; i < 10; i++) {
|
|
10903
|
-
const pkgPath =
|
|
10904
|
-
if (
|
|
10905
|
-
const pkg = JSON.parse(
|
|
11099
|
+
const pkgPath = path25.join(dir, "package.json");
|
|
11100
|
+
if (isFile11(pkgPath)) {
|
|
11101
|
+
const pkg = JSON.parse(fs26.readFileSync(pkgPath, "utf-8"));
|
|
10906
11102
|
if (pkg.name === "@bnbagent/studio-runtime") {
|
|
10907
11103
|
return typeof pkg.version === "string" ? pkg.version : null;
|
|
10908
11104
|
}
|
|
10909
11105
|
}
|
|
10910
|
-
const parent =
|
|
11106
|
+
const parent = path25.dirname(dir);
|
|
10911
11107
|
if (parent === dir) {
|
|
10912
11108
|
break;
|
|
10913
11109
|
}
|
|
@@ -11191,9 +11387,9 @@ function x402SellerRailChecks(agentRoot2, cfg, target) {
|
|
|
11191
11387
|
details: { destination, target, stackRuntime: stackRuntime2 }
|
|
11192
11388
|
});
|
|
11193
11389
|
}
|
|
11194
|
-
const dockerfile =
|
|
11195
|
-
if (rails.x402 &&
|
|
11196
|
-
const source =
|
|
11390
|
+
const dockerfile = path25.join(agentRoot2, "Dockerfile");
|
|
11391
|
+
if (rails.x402 && isFile11(dockerfile)) {
|
|
11392
|
+
const source = fs26.readFileSync(dockerfile, "utf8");
|
|
11197
11393
|
if (!/^\s*FROM\s+node:22(?:[.-]|\s|$)/im.test(source)) {
|
|
11198
11394
|
out.push({
|
|
11199
11395
|
level: Level.WARNING,
|
|
@@ -11266,10 +11462,10 @@ async function checkDeployCliRunnable(_root, target) {
|
|
|
11266
11462
|
];
|
|
11267
11463
|
}
|
|
11268
11464
|
function agentcoreEnvVars(root) {
|
|
11269
|
-
const descriptor =
|
|
11465
|
+
const descriptor = path25.join(root, AGENTCORE_DESCRIPTOR2);
|
|
11270
11466
|
let data;
|
|
11271
11467
|
try {
|
|
11272
|
-
data = JSON.parse(
|
|
11468
|
+
data = JSON.parse(fs26.readFileSync(descriptor, "utf-8"));
|
|
11273
11469
|
} catch {
|
|
11274
11470
|
return [];
|
|
11275
11471
|
}
|
|
@@ -11351,7 +11547,7 @@ async function checkRuntimeSecretsInjected(root, target) {
|
|
|
11351
11547
|
}
|
|
11352
11548
|
];
|
|
11353
11549
|
}
|
|
11354
|
-
const lines = gitignoreLines(
|
|
11550
|
+
const lines = gitignoreLines(path25.join(root, ".gitignore"));
|
|
11355
11551
|
let tracked = true;
|
|
11356
11552
|
if (lines !== null) {
|
|
11357
11553
|
for (const p of ["agentcore/agentcore.json", "agentcore/", "/agentcore/"]) {
|
|
@@ -11376,7 +11572,7 @@ async function checkAwsTargetsPopulated(root, target) {
|
|
|
11376
11572
|
if (target !== "agentcore") {
|
|
11377
11573
|
return [];
|
|
11378
11574
|
}
|
|
11379
|
-
const p =
|
|
11575
|
+
const p = path25.join(root, "agentcore", "aws-targets.json");
|
|
11380
11576
|
const [account, region] = readAwsTarget(root);
|
|
11381
11577
|
if (account && region) {
|
|
11382
11578
|
return [];
|
|
@@ -11459,12 +11655,18 @@ async function checkAgentcoreQuotaHeadroom(root, target) {
|
|
|
11459
11655
|
}
|
|
11460
11656
|
];
|
|
11461
11657
|
}
|
|
11658
|
+
const quotaRunbook = `Raising ${AGENTCORE_AGENT_QUOTA_CODE} ("Total Agents per Account") is a manual AWS step \u2014 \`bag\` cannot request it for you:
|
|
11659
|
+
1. Open the AWS Service Quotas console (service "Amazon Bedrock AgentCore", region ${region}) and request an increase; low requests may need an AWS support case, and a first request can be rejected.
|
|
11660
|
+
2. Check where an earlier request stands: aws service-quotas list-requested-service-quota-change-history --service-code bedrock-agentcore --region ${region}
|
|
11661
|
+
3. While the increase is pending, deploy to the managed platform instead: bag deploy --provider bnb`;
|
|
11662
|
+
const message = limit <= 0 ? `AgentCore quota is 0 in ${region} (new accounts can start at zero), so ANY deploy would fail with \`maxAgents limit exceeded\` AFTER pushing the image and creating the secret, M2M client, and execution role (all orphans). ${quotaRunbook}` : `AgentCore runtimes: ${used}/${limit} used in ${region} \u2014 no slots left, so the deploy would fail with \`maxAgents limit exceeded\` AFTER pushing the image and creating the secret, M2M client, and execution role (all orphans). Delete a runtime you no longer need (\`bag deploy destroy\` in its workspace), or raise the quota. ${quotaRunbook}`;
|
|
11462
11663
|
return [
|
|
11463
11664
|
{
|
|
11464
11665
|
level: Level.CRITICAL,
|
|
11465
11666
|
name: "agentcore_quota_headroom",
|
|
11466
|
-
message
|
|
11467
|
-
details
|
|
11667
|
+
message,
|
|
11668
|
+
details,
|
|
11669
|
+
fixCmd: `# raise ${AGENTCORE_AGENT_QUOTA_CODE} in the AWS Service Quotas console (manual), or deploy with: bag deploy --provider bnb`
|
|
11468
11670
|
}
|
|
11469
11671
|
];
|
|
11470
11672
|
}
|
|
@@ -11485,6 +11687,10 @@ var allChecks = [
|
|
|
11485
11687
|
checkTwakPasswordEnvSet,
|
|
11486
11688
|
checkTwakCredentialsAvailable,
|
|
11487
11689
|
checkTwakDockerAvailable,
|
|
11690
|
+
// altana-kind checks (every one early-returns for other kinds).
|
|
11691
|
+
checkAltanaSessionReady,
|
|
11692
|
+
checkAltanaSdkResolvable,
|
|
11693
|
+
checkAltanaSessionNotInsideAgent,
|
|
11488
11694
|
checkLlmProviderKeySet,
|
|
11489
11695
|
checkGitignoreExcludesSecrets,
|
|
11490
11696
|
checkInstalledBnbagentStudioMatches,
|
|
@@ -11500,16 +11706,16 @@ var allChecks = [
|
|
|
11500
11706
|
var KEYSTORE_JSON_ENV = "WALLET_KEYSTORE_JSON";
|
|
11501
11707
|
var TWAK_WALLET_JSON_ENV = "TWAK_WALLET_JSON";
|
|
11502
11708
|
var TWAK_CREDENTIALS_JSON_ENV = "TWAK_CREDENTIALS_JSON";
|
|
11503
|
-
function
|
|
11709
|
+
function isFile12(p) {
|
|
11504
11710
|
try {
|
|
11505
|
-
return
|
|
11711
|
+
return fs27.statSync(p).isFile();
|
|
11506
11712
|
} catch {
|
|
11507
11713
|
return false;
|
|
11508
11714
|
}
|
|
11509
11715
|
}
|
|
11510
11716
|
function loadTomlOr(agentRoot2) {
|
|
11511
11717
|
try {
|
|
11512
|
-
return loadStudioToml13(
|
|
11718
|
+
return loadStudioToml13(path26.join(agentRoot2, "studio.toml"));
|
|
11513
11719
|
} catch {
|
|
11514
11720
|
return {};
|
|
11515
11721
|
}
|
|
@@ -11526,13 +11732,13 @@ function resolveKeystoreDir3(agentRoot2) {
|
|
|
11526
11732
|
const rel = String(
|
|
11527
11733
|
tableOf10(loadTomlOr(agentRoot2), "wallet").keystore_dir ?? ".studio/wallets"
|
|
11528
11734
|
);
|
|
11529
|
-
return
|
|
11735
|
+
return path26.resolve(path26.isAbsolute(rel) ? rel : path26.join(agentRoot2, rel));
|
|
11530
11736
|
}
|
|
11531
11737
|
function readKeystoreJson(agentRoot2) {
|
|
11532
11738
|
const keystoreDir = resolveKeystoreDir3(agentRoot2);
|
|
11533
11739
|
let names;
|
|
11534
11740
|
try {
|
|
11535
|
-
names =
|
|
11741
|
+
names = fs27.readdirSync(keystoreDir).filter((n) => n.endsWith(".json")).sort();
|
|
11536
11742
|
} catch {
|
|
11537
11743
|
return null;
|
|
11538
11744
|
}
|
|
@@ -11554,9 +11760,9 @@ function readKeystoreJson(agentRoot2) {
|
|
|
11554
11760
|
);
|
|
11555
11761
|
}
|
|
11556
11762
|
}
|
|
11557
|
-
const file =
|
|
11763
|
+
const file = path26.join(keystoreDir, chosen ?? names[0]);
|
|
11558
11764
|
try {
|
|
11559
|
-
return
|
|
11765
|
+
return fs27.readFileSync(file, "utf-8");
|
|
11560
11766
|
} catch {
|
|
11561
11767
|
return null;
|
|
11562
11768
|
}
|
|
@@ -11565,10 +11771,10 @@ function readEnvLocal(agentRoot2) {
|
|
|
11565
11771
|
const values = {};
|
|
11566
11772
|
try {
|
|
11567
11773
|
const file = envLocalPath12(agentRoot2);
|
|
11568
|
-
if (!
|
|
11774
|
+
if (!isFile12(file)) {
|
|
11569
11775
|
return values;
|
|
11570
11776
|
}
|
|
11571
|
-
for (const rawLine of
|
|
11777
|
+
for (const rawLine of fs27.readFileSync(file, "utf-8").split(/\r?\n/)) {
|
|
11572
11778
|
const line = rawLine.trim();
|
|
11573
11779
|
if (!line || line.startsWith("#")) {
|
|
11574
11780
|
continue;
|
|
@@ -11590,11 +11796,6 @@ function readEnvLocal(agentRoot2) {
|
|
|
11590
11796
|
}
|
|
11591
11797
|
function collectRuntimeSecretsDetailed(root) {
|
|
11592
11798
|
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
11799
|
const secretKeys = runtimeEnvKeys2(agentRoot2);
|
|
11599
11800
|
const fileValues = readEnvLocal(agentRoot2);
|
|
11600
11801
|
const payload = {};
|
|
@@ -11607,7 +11808,8 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11607
11808
|
sources[k] = fromFile ? ".studio/.env.local" : "process.env";
|
|
11608
11809
|
}
|
|
11609
11810
|
}
|
|
11610
|
-
|
|
11811
|
+
const walletKind2 = deployWalletKind(agentRoot2);
|
|
11812
|
+
if (walletKind2 === "twak") {
|
|
11611
11813
|
const [walletJson, credentialsJson] = readTwakFiles(agentRoot2);
|
|
11612
11814
|
if (walletJson) {
|
|
11613
11815
|
payload[TWAK_WALLET_JSON_ENV] = walletJson;
|
|
@@ -11617,6 +11819,9 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11617
11819
|
payload[TWAK_CREDENTIALS_JSON_ENV] = credentialsJson;
|
|
11618
11820
|
sources[TWAK_CREDENTIALS_JSON_ENV] = "wallet-file";
|
|
11619
11821
|
}
|
|
11822
|
+
} else if (walletKind2 === "altana") {
|
|
11823
|
+
payload[ALTANA_SESSION_ENV] = altanaSessionForRuntime(agentRoot2);
|
|
11824
|
+
sources[ALTANA_SESSION_ENV] = "wallet-file";
|
|
11620
11825
|
} else {
|
|
11621
11826
|
const keystoreJson = readKeystoreJson(agentRoot2);
|
|
11622
11827
|
if (keystoreJson) {
|
|
@@ -11624,7 +11829,7 @@ function collectRuntimeSecretsDetailed(root) {
|
|
|
11624
11829
|
sources[KEYSTORE_JSON_ENV] = "wallet-file";
|
|
11625
11830
|
}
|
|
11626
11831
|
}
|
|
11627
|
-
if (!(KEYSTORE_JSON_ENV in payload) && !(TWAK_WALLET_JSON_ENV in payload)) {
|
|
11832
|
+
if (walletKind2 !== "altana" && !(KEYSTORE_JSON_ENV in payload) && !(TWAK_WALLET_JSON_ENV in payload)) {
|
|
11628
11833
|
printErr(
|
|
11629
11834
|
`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
11835
|
);
|
|
@@ -11656,12 +11861,12 @@ var SCOPE_NAME = "invoke";
|
|
|
11656
11861
|
var SCOPE = `${RESOURCE_SERVER_ID}/${SCOPE_NAME}`;
|
|
11657
11862
|
var COGNITO_OUTPUTS_FILE = "agentcore/cognito/cdk-outputs.json";
|
|
11658
11863
|
function emitNextSteps(result) {
|
|
11659
|
-
return `\u2713 wrote Cognito CDK app to ${
|
|
11660
|
-
- ${
|
|
11661
|
-
- ${
|
|
11864
|
+
return `\u2713 wrote Cognito CDK app to ${path27.dirname(result.appPath)}
|
|
11865
|
+
- ${path27.basename(result.appPath)} (CognitoStack: user pool + resource server + M2M client)
|
|
11866
|
+
- ${path27.basename(result.readmePath)} (deploy + wiring instructions)
|
|
11662
11867
|
|
|
11663
11868
|
Next steps:
|
|
11664
|
-
1. cd ${
|
|
11869
|
+
1. cd ${path27.dirname(result.appPath)}
|
|
11665
11870
|
2. npm install # aws-cdk-lib + constructs + the cdk CLI (local)
|
|
11666
11871
|
3. npx cdk deploy --outputs-file cdk-outputs.json # YOU run this (the only AWS step)
|
|
11667
11872
|
4. bag deploy provision-cognito --wire # studio reads cdk-outputs.json \u2192
|
|
@@ -11857,26 +12062,26 @@ function emitCognitoCdk(workspaceRoot, opts = {}) {
|
|
|
11857
12062
|
regionHint = null;
|
|
11858
12063
|
}
|
|
11859
12064
|
}
|
|
11860
|
-
const outDir =
|
|
11861
|
-
|
|
11862
|
-
const appPath =
|
|
11863
|
-
const readmePath =
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
12065
|
+
const outDir = path27.join(workspaceRoot, COGNITO_DIR);
|
|
12066
|
+
fs28.mkdirSync(outDir, { recursive: true });
|
|
12067
|
+
const appPath = path27.join(outDir, "app.ts");
|
|
12068
|
+
const readmePath = path27.join(outDir, "README.md");
|
|
12069
|
+
fs28.writeFileSync(appPath, appTs(regionHint), "utf-8");
|
|
12070
|
+
fs28.writeFileSync(path27.join(outDir, "cdk.json"), cdkJson(), "utf-8");
|
|
12071
|
+
fs28.writeFileSync(
|
|
12072
|
+
path27.join(outDir, "package.json"),
|
|
11868
12073
|
cognitoPackageJson(),
|
|
11869
12074
|
"utf-8"
|
|
11870
12075
|
);
|
|
11871
|
-
|
|
12076
|
+
fs28.writeFileSync(readmePath, readme(), "utf-8");
|
|
11872
12077
|
return { appPath, readmePath };
|
|
11873
12078
|
}
|
|
11874
12079
|
function wireSummary(r) {
|
|
11875
12080
|
return `\u2713 wired Cognito authorizer from the CDK outputs (no AWS call \u2014 read a local file):
|
|
11876
|
-
- ${
|
|
12081
|
+
- ${path27.basename(r.agentcoreJson)}: authorizerConfiguration.customJwtAuthorizer
|
|
11877
12082
|
discoveryUrl = ${r.discoveryUrl}
|
|
11878
12083
|
allowedClients = [${r.clientId}]
|
|
11879
|
-
- ${
|
|
12084
|
+
- ${path27.basename(r.agentcoreJson)}: envVars[] OAUTH_TOKEN_URL + OAUTH_SCOPE (reach the runtime so the agent card advertises oauth2)
|
|
11880
12085
|
- ${r.envLocal}: same pair, for local \`bag dev\`
|
|
11881
12086
|
\u2192 NOTE: a \`bag deploy\` run provisions its own pool and overwrites these
|
|
11882
12087
|
values with the ones it issued. This wiring only feeds local \`bag dev\`.`;
|
|
@@ -11908,10 +12113,10 @@ function upsertDescriptorEnvvars(cfg, values) {
|
|
|
11908
12113
|
}
|
|
11909
12114
|
}
|
|
11910
12115
|
function syncDescriptorOauthFacts(workspaceRoot, facts) {
|
|
11911
|
-
const acj =
|
|
12116
|
+
const acj = path27.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
11912
12117
|
let cfg;
|
|
11913
12118
|
try {
|
|
11914
|
-
cfg = JSON.parse(
|
|
12119
|
+
cfg = JSON.parse(fs28.readFileSync(acj, "utf-8"));
|
|
11915
12120
|
} catch {
|
|
11916
12121
|
return;
|
|
11917
12122
|
}
|
|
@@ -11944,7 +12149,7 @@ function syncDescriptorOauthFacts(workspaceRoot, facts) {
|
|
|
11944
12149
|
}
|
|
11945
12150
|
}
|
|
11946
12151
|
try {
|
|
11947
|
-
|
|
12152
|
+
fs28.writeFileSync(acj, `${JSON.stringify(cfg, null, 2)}
|
|
11948
12153
|
`, "utf-8");
|
|
11949
12154
|
} catch {
|
|
11950
12155
|
return;
|
|
@@ -11953,8 +12158,8 @@ function syncDescriptorOauthFacts(workspaceRoot, facts) {
|
|
|
11953
12158
|
function upsertEnv(envLocal, values) {
|
|
11954
12159
|
let lines = [];
|
|
11955
12160
|
try {
|
|
11956
|
-
if (
|
|
11957
|
-
lines =
|
|
12161
|
+
if (fs28.statSync(envLocal).isFile()) {
|
|
12162
|
+
lines = fs28.readFileSync(envLocal, "utf-8").split(/\r?\n/);
|
|
11958
12163
|
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
11959
12164
|
lines.pop();
|
|
11960
12165
|
}
|
|
@@ -11973,19 +12178,19 @@ function upsertEnv(envLocal, values) {
|
|
|
11973
12178
|
lines.push(repl);
|
|
11974
12179
|
}
|
|
11975
12180
|
}
|
|
11976
|
-
|
|
11977
|
-
|
|
12181
|
+
fs28.mkdirSync(path27.dirname(envLocal), { recursive: true });
|
|
12182
|
+
fs28.writeFileSync(envLocal, `${lines.join("\n")}
|
|
11978
12183
|
`, {
|
|
11979
12184
|
encoding: "utf-8",
|
|
11980
12185
|
mode: 384
|
|
11981
12186
|
});
|
|
11982
|
-
|
|
12187
|
+
fs28.chmodSync(envLocal, 384);
|
|
11983
12188
|
}
|
|
11984
12189
|
function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
11985
|
-
const outPath = outputsFile ??
|
|
12190
|
+
const outPath = outputsFile ?? path27.join(workspaceRoot, COGNITO_OUTPUTS_FILE);
|
|
11986
12191
|
let exists = false;
|
|
11987
12192
|
try {
|
|
11988
|
-
exists =
|
|
12193
|
+
exists = fs28.statSync(outPath).isFile();
|
|
11989
12194
|
} catch {
|
|
11990
12195
|
exists = false;
|
|
11991
12196
|
}
|
|
@@ -11995,7 +12200,7 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
11995
12200
|
);
|
|
11996
12201
|
}
|
|
11997
12202
|
const outs = flattenCdkOutputs(
|
|
11998
|
-
JSON.parse(
|
|
12203
|
+
JSON.parse(fs28.readFileSync(outPath, "utf-8"))
|
|
11999
12204
|
);
|
|
12000
12205
|
for (const key of ["DiscoveryUrl", "AppClientId", "TokenUrl", "Scope"]) {
|
|
12001
12206
|
if (outs[key] === void 0) {
|
|
@@ -12008,8 +12213,8 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
12008
12213
|
const clientId = String(outs.AppClientId);
|
|
12009
12214
|
const tokenUrl = String(outs.TokenUrl);
|
|
12010
12215
|
const scope = String(outs.Scope);
|
|
12011
|
-
const acj =
|
|
12012
|
-
const cfg = JSON.parse(
|
|
12216
|
+
const acj = path27.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
12217
|
+
const cfg = JSON.parse(fs28.readFileSync(acj, "utf-8"));
|
|
12013
12218
|
const runtimes = cfg.runtimes;
|
|
12014
12219
|
if (!Array.isArray(runtimes) || runtimes.length === 0) {
|
|
12015
12220
|
throw new Error(
|
|
@@ -12032,7 +12237,7 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
12032
12237
|
OAUTH_TOKEN_URL: tokenUrl,
|
|
12033
12238
|
OAUTH_SCOPE: scope
|
|
12034
12239
|
});
|
|
12035
|
-
|
|
12240
|
+
fs28.writeFileSync(acj, `${JSON.stringify(cfg, null, 2)}
|
|
12036
12241
|
`, "utf-8");
|
|
12037
12242
|
const envLocal = envLocalPath13(workspaceRoot);
|
|
12038
12243
|
upsertEnv(envLocal, { OAUTH_TOKEN_URL: tokenUrl, OAUTH_SCOPE: scope });
|
|
@@ -12047,13 +12252,13 @@ function wireCognitoOutputs(workspaceRoot, outputsFile = null) {
|
|
|
12047
12252
|
}
|
|
12048
12253
|
|
|
12049
12254
|
// src/cli/_deploy/destroy.ts
|
|
12050
|
-
import * as
|
|
12051
|
-
import * as
|
|
12255
|
+
import * as fs30 from "fs";
|
|
12256
|
+
import * as path29 from "path";
|
|
12052
12257
|
import { findSubProjectRoot as findSubProjectRoot10 } from "@bnbagent/studio-runtime/config";
|
|
12053
12258
|
|
|
12054
12259
|
// src/cli/_deploy/status.ts
|
|
12055
|
-
import * as
|
|
12056
|
-
import * as
|
|
12260
|
+
import * as fs29 from "fs";
|
|
12261
|
+
import * as path28 from "path";
|
|
12057
12262
|
import {
|
|
12058
12263
|
APP_DIR as APP_DIR2,
|
|
12059
12264
|
findSubProjectRoot as findSubProjectRoot9,
|
|
@@ -12068,20 +12273,20 @@ function loadToml(p) {
|
|
|
12068
12273
|
}
|
|
12069
12274
|
}
|
|
12070
12275
|
function projectName(workspaceRoot) {
|
|
12071
|
-
const descriptor =
|
|
12276
|
+
const descriptor = path28.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
12072
12277
|
try {
|
|
12073
|
-
const data = JSON.parse(
|
|
12278
|
+
const data = JSON.parse(fs29.readFileSync(descriptor, "utf-8"));
|
|
12074
12279
|
if (data !== null && typeof data === "object" && data.name) {
|
|
12075
12280
|
return String(data.name);
|
|
12076
12281
|
}
|
|
12077
12282
|
} catch {
|
|
12078
12283
|
}
|
|
12079
|
-
return
|
|
12284
|
+
return path28.basename(workspaceRoot);
|
|
12080
12285
|
}
|
|
12081
12286
|
async function runStatus(opts = {}) {
|
|
12082
|
-
const start = opts.projectRoot ?
|
|
12287
|
+
const start = opts.projectRoot ? path28.resolve(opts.projectRoot) : void 0;
|
|
12083
12288
|
const agentRoot2 = findSubProjectRoot9("agent", start);
|
|
12084
|
-
const agentData = agentRoot2 !== null ? loadToml(
|
|
12289
|
+
const agentData = agentRoot2 !== null ? loadToml(path28.join(agentRoot2, "studio.toml")) : {};
|
|
12085
12290
|
const deployRaw = agentData.deploy;
|
|
12086
12291
|
const deploy = deployRaw !== null && typeof deployRaw === "object" && !Array.isArray(deployRaw) ? { ...deployRaw } : {};
|
|
12087
12292
|
const runtimeArn = deploy.runtime_arn ? String(deploy.runtime_arn) : null;
|
|
@@ -12094,8 +12299,8 @@ async function runStatus(opts = {}) {
|
|
|
12094
12299
|
}
|
|
12095
12300
|
const onchainEndpoint = identity.endpoint ? String(identity.endpoint) : null;
|
|
12096
12301
|
const agentReachable = null;
|
|
12097
|
-
const workspaceBase2 = findWorkspaceRoot5(start) ?? (agentRoot2 !== null ?
|
|
12098
|
-
const workspaceRoot = workspaceBase2 !== null &&
|
|
12302
|
+
const workspaceBase2 = findWorkspaceRoot5(start) ?? (agentRoot2 !== null ? path28.dirname(agentRoot2) : null);
|
|
12303
|
+
const workspaceRoot = workspaceBase2 !== null && path28.basename(workspaceBase2) === APP_DIR2 ? path28.dirname(workspaceBase2) : workspaceBase2;
|
|
12099
12304
|
let region = null;
|
|
12100
12305
|
let account = null;
|
|
12101
12306
|
let secretId = null;
|
|
@@ -12163,9 +12368,9 @@ function nullRecordedState(workspaceRoot) {
|
|
|
12163
12368
|
if (agentRoot2 === null) {
|
|
12164
12369
|
return;
|
|
12165
12370
|
}
|
|
12166
|
-
const ap =
|
|
12371
|
+
const ap = path29.join(agentRoot2, "studio.toml");
|
|
12167
12372
|
try {
|
|
12168
|
-
if (!
|
|
12373
|
+
if (!fs30.statSync(ap).isFile()) {
|
|
12169
12374
|
return;
|
|
12170
12375
|
}
|
|
12171
12376
|
} catch {
|
|
@@ -12229,8 +12434,8 @@ async function runDestroy(opts) {
|
|
|
12229
12434
|
}
|
|
12230
12435
|
|
|
12231
12436
|
// src/cli/_deploy/packaging.ts
|
|
12232
|
-
import * as
|
|
12233
|
-
import * as
|
|
12437
|
+
import * as fs31 from "fs";
|
|
12438
|
+
import * as path30 from "path";
|
|
12234
12439
|
import {
|
|
12235
12440
|
findSubProjectRoot as findSubProjectRoot11,
|
|
12236
12441
|
loadStudioToml as loadStudioToml15
|
|
@@ -12239,9 +12444,9 @@ function agentRootOf2(root) {
|
|
|
12239
12444
|
return findSubProjectRoot11("agent", root);
|
|
12240
12445
|
}
|
|
12241
12446
|
function agentTable(agentRoot2, key) {
|
|
12242
|
-
const tomlPath =
|
|
12447
|
+
const tomlPath = path30.join(agentRoot2, "studio.toml");
|
|
12243
12448
|
try {
|
|
12244
|
-
if (!
|
|
12449
|
+
if (!fs31.statSync(tomlPath).isFile()) {
|
|
12245
12450
|
return {};
|
|
12246
12451
|
}
|
|
12247
12452
|
} catch {
|
|
@@ -12308,10 +12513,10 @@ function checkPackagingDrift(root, destination, walletKind2, force) {
|
|
|
12308
12513
|
);
|
|
12309
12514
|
return 1;
|
|
12310
12515
|
}
|
|
12311
|
-
const dockerfile =
|
|
12516
|
+
const dockerfile = path30.join(agentRoot2, "Dockerfile");
|
|
12312
12517
|
let dockerfilePresent = false;
|
|
12313
12518
|
try {
|
|
12314
|
-
dockerfilePresent =
|
|
12519
|
+
dockerfilePresent = fs31.statSync(dockerfile).isFile();
|
|
12315
12520
|
} catch {
|
|
12316
12521
|
dockerfilePresent = false;
|
|
12317
12522
|
}
|
|
@@ -12352,7 +12557,7 @@ function deployWalletKindSafe(root) {
|
|
|
12352
12557
|
}
|
|
12353
12558
|
let cfg;
|
|
12354
12559
|
try {
|
|
12355
|
-
cfg = loadStudioToml15(
|
|
12560
|
+
cfg = loadStudioToml15(path30.join(agentRoot2, "studio.toml"));
|
|
12356
12561
|
} catch {
|
|
12357
12562
|
return "evm-local";
|
|
12358
12563
|
}
|
|
@@ -12365,22 +12570,22 @@ function deployWalletKindSafe(root) {
|
|
|
12365
12570
|
import { findStudioWorkspaceRoot as findStudioWorkspaceRoot2 } from "@bnbagent/studio-runtime/config";
|
|
12366
12571
|
|
|
12367
12572
|
// src/cli/_deploy/checks/blocked.ts
|
|
12368
|
-
import * as
|
|
12369
|
-
import * as
|
|
12573
|
+
import * as fs32 from "fs";
|
|
12574
|
+
import * as path31 from "path";
|
|
12370
12575
|
import {
|
|
12371
12576
|
findSubProjectRoot as findSubProjectRoot12,
|
|
12372
12577
|
loadStudioToml as loadStudioToml16
|
|
12373
12578
|
} from "@bnbagent/studio-runtime/config";
|
|
12374
|
-
function
|
|
12579
|
+
function isFile13(p) {
|
|
12375
12580
|
try {
|
|
12376
|
-
return
|
|
12581
|
+
return fs32.statSync(p).isFile();
|
|
12377
12582
|
} catch {
|
|
12378
12583
|
return false;
|
|
12379
12584
|
}
|
|
12380
12585
|
}
|
|
12381
12586
|
function isDir6(p) {
|
|
12382
12587
|
try {
|
|
12383
|
-
return
|
|
12588
|
+
return fs32.statSync(p).isDirectory();
|
|
12384
12589
|
} catch {
|
|
12385
12590
|
return false;
|
|
12386
12591
|
}
|
|
@@ -12391,8 +12596,8 @@ async function checkStudioTomlPresent(root, _target) {
|
|
|
12391
12596
|
agent: findSubProjectRoot12("agent", root)
|
|
12392
12597
|
};
|
|
12393
12598
|
for (const [side, subRoot] of Object.entries(layers)) {
|
|
12394
|
-
const tomlPath = subRoot === null ? null :
|
|
12395
|
-
if (tomlPath === null || !
|
|
12599
|
+
const tomlPath = subRoot === null ? null : path31.join(subRoot, "studio.toml");
|
|
12600
|
+
if (tomlPath === null || !isFile13(tomlPath)) {
|
|
12396
12601
|
out.push({
|
|
12397
12602
|
level: Level.BLOCKED,
|
|
12398
12603
|
name: "studio_toml_present",
|
|
@@ -12416,8 +12621,8 @@ async function checkStudioTomlPresent(root, _target) {
|
|
|
12416
12621
|
return out;
|
|
12417
12622
|
}
|
|
12418
12623
|
async function checkCwdIsProjectRoot(root, _target) {
|
|
12419
|
-
const cwd =
|
|
12420
|
-
const rr =
|
|
12624
|
+
const cwd = path31.resolve(process.cwd());
|
|
12625
|
+
const rr = path31.resolve(root);
|
|
12421
12626
|
if (cwd !== rr) {
|
|
12422
12627
|
return [
|
|
12423
12628
|
{
|
|
@@ -12431,7 +12636,7 @@ async function checkCwdIsProjectRoot(root, _target) {
|
|
|
12431
12636
|
return [];
|
|
12432
12637
|
}
|
|
12433
12638
|
async function checkNoSecretInGitHistory(root, _target) {
|
|
12434
|
-
if (!isDir6(
|
|
12639
|
+
if (!isDir6(path31.join(root, ".git"))) {
|
|
12435
12640
|
return [];
|
|
12436
12641
|
}
|
|
12437
12642
|
const needles = [".env.local", "WALLET_PASSWORD"];
|
|
@@ -12469,8 +12674,8 @@ var allChecks2 = [
|
|
|
12469
12674
|
];
|
|
12470
12675
|
|
|
12471
12676
|
// src/cli/_deploy/checks/info.ts
|
|
12472
|
-
import * as
|
|
12473
|
-
import * as
|
|
12677
|
+
import * as fs33 from "fs";
|
|
12678
|
+
import * as path32 from "path";
|
|
12474
12679
|
async function checkPreviousDeployStatus(root, _target) {
|
|
12475
12680
|
const deploy = tableOf2(loadAgentToml(root), "deploy");
|
|
12476
12681
|
const last = deploy.last_deploy_at;
|
|
@@ -12494,10 +12699,10 @@ async function checkPreviousDeployStatus(root, _target) {
|
|
|
12494
12699
|
];
|
|
12495
12700
|
}
|
|
12496
12701
|
async function checkInstalledRecipesList(root, _target) {
|
|
12497
|
-
const manifest =
|
|
12702
|
+
const manifest = path32.join(root, ".studio", "recipes", "manifest.json");
|
|
12498
12703
|
let exists = false;
|
|
12499
12704
|
try {
|
|
12500
|
-
exists =
|
|
12705
|
+
exists = fs33.statSync(manifest).isFile();
|
|
12501
12706
|
} catch {
|
|
12502
12707
|
exists = false;
|
|
12503
12708
|
}
|
|
@@ -12513,7 +12718,7 @@ async function checkInstalledRecipesList(root, _target) {
|
|
|
12513
12718
|
}
|
|
12514
12719
|
let data;
|
|
12515
12720
|
try {
|
|
12516
|
-
data = JSON.parse(
|
|
12721
|
+
data = JSON.parse(fs33.readFileSync(manifest, "utf-8"));
|
|
12517
12722
|
} catch {
|
|
12518
12723
|
return [
|
|
12519
12724
|
{
|
|
@@ -12616,8 +12821,8 @@ var allChecks3 = [
|
|
|
12616
12821
|
];
|
|
12617
12822
|
|
|
12618
12823
|
// src/cli/_deploy/checks/platform.ts
|
|
12619
|
-
import * as
|
|
12620
|
-
import * as
|
|
12824
|
+
import * as fs35 from "fs";
|
|
12825
|
+
import * as path34 from "path";
|
|
12621
12826
|
import {
|
|
12622
12827
|
findSubProjectRoot as findSubProjectRoot13,
|
|
12623
12828
|
loadStudioToml as loadStudioToml17
|
|
@@ -12626,16 +12831,16 @@ import { BSC_TESTNET_FAUCET_URLS } from "@bnbagent/studio-runtime/networks";
|
|
|
12626
12831
|
|
|
12627
12832
|
// src/cli/_deploy/checks/warning.ts
|
|
12628
12833
|
import * as crypto4 from "crypto";
|
|
12629
|
-
import * as
|
|
12630
|
-
import * as
|
|
12834
|
+
import * as fs34 from "fs";
|
|
12835
|
+
import * as path33 from "path";
|
|
12631
12836
|
import { envLocalPath as envLocalPath14 } from "@bnbagent/studio-runtime/config";
|
|
12632
12837
|
import { show } from "@bnbagent/studio-runtime/erc8004";
|
|
12633
12838
|
import { DEFAULT_RPC, getNetwork as getNetwork8 } from "@bnbagent/studio-runtime/networks";
|
|
12634
12839
|
import * as walletRt3 from "@bnbagent/studio-runtime/wallet";
|
|
12635
12840
|
var TBNB_MIN_WEI = 7n * 10n ** 15n;
|
|
12636
|
-
function
|
|
12841
|
+
function isFile14(p) {
|
|
12637
12842
|
try {
|
|
12638
|
-
return
|
|
12843
|
+
return fs34.statSync(p).isFile();
|
|
12639
12844
|
} catch {
|
|
12640
12845
|
return false;
|
|
12641
12846
|
}
|
|
@@ -12838,10 +13043,10 @@ async function checkRuntimeRpcReachable(root, _target) {
|
|
|
12838
13043
|
return [];
|
|
12839
13044
|
}
|
|
12840
13045
|
async function checkInstalledRecipesUnchanged(root, _target) {
|
|
12841
|
-
const manifest =
|
|
13046
|
+
const manifest = path33.join(root, ".studio", "recipes", "manifest.json");
|
|
12842
13047
|
let data;
|
|
12843
13048
|
try {
|
|
12844
|
-
data = JSON.parse(
|
|
13049
|
+
data = JSON.parse(fs34.readFileSync(manifest, "utf-8"));
|
|
12845
13050
|
} catch {
|
|
12846
13051
|
return [];
|
|
12847
13052
|
}
|
|
@@ -12856,11 +13061,11 @@ async function checkInstalledRecipesUnchanged(root, _target) {
|
|
|
12856
13061
|
if (!rel || !expected || typeof rel !== "string") {
|
|
12857
13062
|
continue;
|
|
12858
13063
|
}
|
|
12859
|
-
const p =
|
|
12860
|
-
if (!
|
|
13064
|
+
const p = path33.join(root, rel);
|
|
13065
|
+
if (!isFile14(p)) {
|
|
12861
13066
|
continue;
|
|
12862
13067
|
}
|
|
12863
|
-
const actual = crypto4.createHash("sha256").update(
|
|
13068
|
+
const actual = crypto4.createHash("sha256").update(fs34.readFileSync(p)).digest("hex");
|
|
12864
13069
|
if (actual !== expected) {
|
|
12865
13070
|
stale.push(rel);
|
|
12866
13071
|
}
|
|
@@ -12911,11 +13116,11 @@ function tableOf11(data, key) {
|
|
|
12911
13116
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
12912
13117
|
}
|
|
12913
13118
|
function agentRoot(root) {
|
|
12914
|
-
return findSubProjectRoot13("agent", root) ??
|
|
13119
|
+
return findSubProjectRoot13("agent", root) ?? path34.join(root, "app", "agent");
|
|
12915
13120
|
}
|
|
12916
13121
|
function loadAgent(root) {
|
|
12917
13122
|
try {
|
|
12918
|
-
return loadStudioToml17(
|
|
13123
|
+
return loadStudioToml17(path34.join(agentRoot(root), "studio.toml"));
|
|
12919
13124
|
} catch {
|
|
12920
13125
|
return {};
|
|
12921
13126
|
}
|
|
@@ -12935,10 +13140,10 @@ var checkPlatformEntrypointPresent = async (root, _target) => {
|
|
|
12935
13140
|
const filenames = [`${stem2}.ts`];
|
|
12936
13141
|
if (stem2 === "dualMain") filenames.push("mcpMain.ts");
|
|
12937
13142
|
const filename = filenames.find(
|
|
12938
|
-
(candidate) => !
|
|
13143
|
+
(candidate) => !fs35.existsSync(path34.join(agentRoot(root), "src", candidate))
|
|
12939
13144
|
);
|
|
12940
13145
|
if (filename === void 0) return [];
|
|
12941
|
-
const expected =
|
|
13146
|
+
const expected = path34.join(agentRoot(root), "src", filename);
|
|
12942
13147
|
return [
|
|
12943
13148
|
{
|
|
12944
13149
|
level: Level.CRITICAL,
|
|
@@ -12952,18 +13157,18 @@ var checkPlatformKeystoreNotInArtifact = async (root, _target) => {
|
|
|
12952
13157
|
const data = loadAgent(root);
|
|
12953
13158
|
const wallet = tableOf11(data, "wallet");
|
|
12954
13159
|
if (String(wallet.kind ?? "evm-local") === "twak") return [];
|
|
12955
|
-
const agent =
|
|
13160
|
+
const agent = path34.resolve(agentRoot(root));
|
|
12956
13161
|
const configured = String(wallet.keystore_dir ?? ".studio/wallets");
|
|
12957
|
-
const keystore =
|
|
13162
|
+
const keystore = path34.resolve(agent, configured);
|
|
12958
13163
|
let jsonFiles;
|
|
12959
13164
|
try {
|
|
12960
|
-
jsonFiles =
|
|
13165
|
+
jsonFiles = fs35.readdirSync(keystore).filter((name) => name.endsWith(".json"));
|
|
12961
13166
|
} catch {
|
|
12962
13167
|
return [];
|
|
12963
13168
|
}
|
|
12964
13169
|
if (jsonFiles.length === 0) return [];
|
|
12965
|
-
const rel =
|
|
12966
|
-
if (rel.startsWith("..") ||
|
|
13170
|
+
const rel = path34.relative(agent, keystore);
|
|
13171
|
+
if (rel.startsWith("..") || path34.isAbsolute(rel)) return [];
|
|
12967
13172
|
return [
|
|
12968
13173
|
{
|
|
12969
13174
|
level: Level.CRITICAL,
|
|
@@ -13190,7 +13395,7 @@ async function runProducers(producers, root, target) {
|
|
|
13190
13395
|
}
|
|
13191
13396
|
|
|
13192
13397
|
// src/cli/_deploy/verify.ts
|
|
13193
|
-
import * as
|
|
13398
|
+
import * as path36 from "path";
|
|
13194
13399
|
import {
|
|
13195
13400
|
findSubProjectRoot as findSubProjectRoot14,
|
|
13196
13401
|
loadStudioToml as loadStudioToml18
|
|
@@ -13203,11 +13408,11 @@ import {
|
|
|
13203
13408
|
import * as walletRt4 from "@bnbagent/studio-runtime/wallet";
|
|
13204
13409
|
|
|
13205
13410
|
// src/cli/_identity.ts
|
|
13206
|
-
import * as
|
|
13207
|
-
import * as
|
|
13411
|
+
import * as fs36 from "fs";
|
|
13412
|
+
import * as path35 from "path";
|
|
13208
13413
|
function writeIdentityBlock(root, identity) {
|
|
13209
|
-
const p =
|
|
13210
|
-
const text2 =
|
|
13414
|
+
const p = path35.join(root, "studio.toml");
|
|
13415
|
+
const text2 = fs36.readFileSync(p, "utf-8");
|
|
13211
13416
|
const lines = text2.split(/\r?\n/);
|
|
13212
13417
|
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
13213
13418
|
lines.pop();
|
|
@@ -13246,7 +13451,7 @@ function writeIdentityBlock(root, identity) {
|
|
|
13246
13451
|
}
|
|
13247
13452
|
}
|
|
13248
13453
|
out.push("");
|
|
13249
|
-
|
|
13454
|
+
fs36.writeFileSync(p, out.join("\n"), "utf-8");
|
|
13250
13455
|
}
|
|
13251
13456
|
|
|
13252
13457
|
// src/cli/_deploy/verify.ts
|
|
@@ -13364,7 +13569,7 @@ async function runVerify(opts) {
|
|
|
13364
13569
|
const endpoint = opts.endpoint;
|
|
13365
13570
|
const runtime = opts.runtime ?? "agentcore";
|
|
13366
13571
|
const skipRegister = opts.skipRegister ?? false;
|
|
13367
|
-
const start = opts.projectRoot ?
|
|
13572
|
+
const start = opts.projectRoot ? path36.resolve(opts.projectRoot) : void 0;
|
|
13368
13573
|
const root = findSubProjectRoot14("agent", start);
|
|
13369
13574
|
if (root === null) {
|
|
13370
13575
|
return baseResult(endpoint, runtime, {
|
|
@@ -13384,7 +13589,7 @@ async function runVerify(opts) {
|
|
|
13384
13589
|
}
|
|
13385
13590
|
let data;
|
|
13386
13591
|
try {
|
|
13387
|
-
data = loadStudioToml18(
|
|
13592
|
+
data = loadStudioToml18(path36.join(root, "studio.toml"));
|
|
13388
13593
|
} catch (exc) {
|
|
13389
13594
|
return baseResult(endpoint, runtime, {
|
|
13390
13595
|
awsAccount,
|
|
@@ -13545,8 +13750,8 @@ async function runVerify(opts) {
|
|
|
13545
13750
|
}
|
|
13546
13751
|
|
|
13547
13752
|
// src/cli/_hosted/deployOps.ts
|
|
13548
|
-
import * as
|
|
13549
|
-
import * as
|
|
13753
|
+
import * as fs37 from "fs";
|
|
13754
|
+
import * as path37 from "path";
|
|
13550
13755
|
import {
|
|
13551
13756
|
envLocalPath as envLocalPath15,
|
|
13552
13757
|
findSubProjectRoot as findSubProjectRoot15,
|
|
@@ -13557,7 +13762,12 @@ var PLATFORM_SECTION = "deploy.platform";
|
|
|
13557
13762
|
var WALLET_SECTION = "wallet";
|
|
13558
13763
|
var KEYSTORE_JSON_ENV2 = "WALLET_KEYSTORE_JSON";
|
|
13559
13764
|
var TWAK_WALLET_JSON_ENV2 = "TWAK_WALLET_JSON";
|
|
13560
|
-
var
|
|
13765
|
+
var ALTANA_SESSION_ENV2 = "ALTANA_SESSION";
|
|
13766
|
+
var WALLET_MATERIAL_KEYS = [
|
|
13767
|
+
KEYSTORE_JSON_ENV2,
|
|
13768
|
+
TWAK_WALLET_JSON_ENV2,
|
|
13769
|
+
ALTANA_SESSION_ENV2
|
|
13770
|
+
];
|
|
13561
13771
|
var RETIRED_AGENT_STATES = /* @__PURE__ */ new Set([
|
|
13562
13772
|
"deleted",
|
|
13563
13773
|
"retired",
|
|
@@ -13587,8 +13797,8 @@ function agentTomlPath2(root) {
|
|
|
13587
13797
|
if (agentRoot2 === null) {
|
|
13588
13798
|
return null;
|
|
13589
13799
|
}
|
|
13590
|
-
const tomlPath =
|
|
13591
|
-
return
|
|
13800
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13801
|
+
return isFile15(tomlPath) ? tomlPath : null;
|
|
13592
13802
|
}
|
|
13593
13803
|
function loadAgentCfg(root) {
|
|
13594
13804
|
const tomlPath = agentTomlPath2(root);
|
|
@@ -13605,12 +13815,12 @@ function platformCfg(root) {
|
|
|
13605
13815
|
return tableOf12(tableOf12(loadAgentCfg(root), "deploy"), "platform");
|
|
13606
13816
|
}
|
|
13607
13817
|
function patchTomlKv2(tomlPath, section, key, value) {
|
|
13608
|
-
let text2 =
|
|
13818
|
+
let text2 = fs37.readFileSync(tomlPath, "utf-8");
|
|
13609
13819
|
if (!hasSection(text2, section)) {
|
|
13610
13820
|
text2 = addSection(text2, section);
|
|
13611
13821
|
}
|
|
13612
13822
|
text2 = hasKey(text2, section, key) ? setExistingKey(text2, section, key, value) : addKeyToSection(text2, section, key, value);
|
|
13613
|
-
|
|
13823
|
+
fs37.writeFileSync(tomlPath, text2);
|
|
13614
13824
|
}
|
|
13615
13825
|
function recordPlatformKv(root, key, value) {
|
|
13616
13826
|
const tomlPath = agentTomlPath2(root);
|
|
@@ -13709,8 +13919,8 @@ function clearIdentityEndpointIfMatches(root, oldUrl) {
|
|
|
13709
13919
|
}
|
|
13710
13920
|
}
|
|
13711
13921
|
function persistedPackaging2(agentRoot2) {
|
|
13712
|
-
const tomlPath =
|
|
13713
|
-
if (!
|
|
13922
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13923
|
+
if (!isFile15(tomlPath)) {
|
|
13714
13924
|
return null;
|
|
13715
13925
|
}
|
|
13716
13926
|
try {
|
|
@@ -13722,8 +13932,8 @@ function persistedPackaging2(agentRoot2) {
|
|
|
13722
13932
|
}
|
|
13723
13933
|
}
|
|
13724
13934
|
function resolvePlatformArtifact2(agentRoot2) {
|
|
13725
|
-
const tomlPath =
|
|
13726
|
-
if (
|
|
13935
|
+
const tomlPath = path37.join(agentRoot2, "studio.toml");
|
|
13936
|
+
if (isFile15(tomlPath)) {
|
|
13727
13937
|
try {
|
|
13728
13938
|
const cfg = loadStudioToml19(tomlPath);
|
|
13729
13939
|
const explicit = tableOf12(cfg, "deploy").platform_artifact;
|
|
@@ -13746,7 +13956,7 @@ function platformPackaging(root) {
|
|
|
13746
13956
|
}
|
|
13747
13957
|
function loadCfgAt(agentRoot2) {
|
|
13748
13958
|
try {
|
|
13749
|
-
return loadStudioToml19(
|
|
13959
|
+
return loadStudioToml19(path37.join(agentRoot2, "studio.toml"));
|
|
13750
13960
|
} catch {
|
|
13751
13961
|
return {};
|
|
13752
13962
|
}
|
|
@@ -13823,7 +14033,7 @@ function resolveSlug(root) {
|
|
|
13823
14033
|
let name = String(tableOf12(loadAgentCfg(root), "project").name ?? "");
|
|
13824
14034
|
name = name.replace(/-(agent|service)$/, "");
|
|
13825
14035
|
if (!name) {
|
|
13826
|
-
name =
|
|
14036
|
+
name = path37.basename(findWorkspaceRoot6(root) ?? root);
|
|
13827
14037
|
}
|
|
13828
14038
|
let base = name.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
13829
14039
|
base = base || "agent";
|
|
@@ -14065,6 +14275,19 @@ function walletWarning(root, secrets) {
|
|
|
14065
14275
|
return;
|
|
14066
14276
|
}
|
|
14067
14277
|
const address = tableOf12(loadAgentCfg(root), "wallet").address;
|
|
14278
|
+
if (ALTANA_SESSION_ENV2 in secrets) {
|
|
14279
|
+
const who2 = typeof address === "string" && address ? ` (wallet ${address})` : "";
|
|
14280
|
+
warn(
|
|
14281
|
+
`
|
|
14282
|
+
!!! session exposure (platform trial) !!!
|
|
14283
|
+
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.
|
|
14284
|
+
If the current budget or expiry is wider than you want an operator-held key to carry, stop and grant a tighter one first:
|
|
14285
|
+
bag wallet session grant --force --budget-u <small> --expiry-days <short>
|
|
14286
|
+
You can revoke it on-chain at any time with \`bag wallet session revoke\`.
|
|
14287
|
+
`
|
|
14288
|
+
);
|
|
14289
|
+
return;
|
|
14290
|
+
}
|
|
14068
14291
|
const who = typeof address === "string" && address ? `key (address ${address})` : "signing key";
|
|
14069
14292
|
warn(
|
|
14070
14293
|
`
|
|
@@ -14281,15 +14504,15 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
14281
14504
|
}
|
|
14282
14505
|
function persistDeploySummary(root, text2) {
|
|
14283
14506
|
try {
|
|
14284
|
-
if (!
|
|
14507
|
+
if (!fs37.statSync(path37.resolve(root)).isDirectory()) {
|
|
14285
14508
|
return null;
|
|
14286
14509
|
}
|
|
14287
|
-
const p =
|
|
14288
|
-
|
|
14510
|
+
const p = path37.join(
|
|
14511
|
+
path37.dirname(envLocalPath15(root)),
|
|
14289
14512
|
"last-deploy-summary.txt"
|
|
14290
14513
|
);
|
|
14291
|
-
|
|
14292
|
-
|
|
14514
|
+
fs37.mkdirSync(path37.dirname(p), { recursive: true });
|
|
14515
|
+
fs37.writeFileSync(p, `${text2}
|
|
14293
14516
|
`);
|
|
14294
14517
|
return p;
|
|
14295
14518
|
} catch {
|
|
@@ -14444,9 +14667,9 @@ async function deletePlatformAgent(slug, deps = {}) {
|
|
|
14444
14667
|
}
|
|
14445
14668
|
return 0;
|
|
14446
14669
|
}
|
|
14447
|
-
function
|
|
14670
|
+
function isFile15(p) {
|
|
14448
14671
|
try {
|
|
14449
|
-
return
|
|
14672
|
+
return fs37.statSync(p).isFile();
|
|
14450
14673
|
} catch {
|
|
14451
14674
|
return false;
|
|
14452
14675
|
}
|
|
@@ -14459,16 +14682,16 @@ var ADVERTISED_DEPLOY_RUNTIME_TARGETS = ["agentcore"];
|
|
|
14459
14682
|
// src/cli/deploy.ts
|
|
14460
14683
|
var TARGET_CHOICES = [...DEPLOY_RUNTIME_TARGETS];
|
|
14461
14684
|
var ADVERTISED_TARGET_CHOICES = [...ADVERTISED_DEPLOY_RUNTIME_TARGETS];
|
|
14462
|
-
function
|
|
14685
|
+
function isFile16(p) {
|
|
14463
14686
|
try {
|
|
14464
|
-
return
|
|
14687
|
+
return fs38.statSync(p).isFile();
|
|
14465
14688
|
} catch {
|
|
14466
14689
|
return false;
|
|
14467
14690
|
}
|
|
14468
14691
|
}
|
|
14469
14692
|
function isDir7(p) {
|
|
14470
14693
|
try {
|
|
14471
|
-
return
|
|
14694
|
+
return fs38.statSync(p).isDirectory();
|
|
14472
14695
|
} catch {
|
|
14473
14696
|
return false;
|
|
14474
14697
|
}
|
|
@@ -14485,8 +14708,8 @@ function loadAgentCfg2(root) {
|
|
|
14485
14708
|
if (agentRoot2 === null) {
|
|
14486
14709
|
return null;
|
|
14487
14710
|
}
|
|
14488
|
-
const tomlPath =
|
|
14489
|
-
if (!
|
|
14711
|
+
const tomlPath = path38.join(agentRoot2, "studio.toml");
|
|
14712
|
+
if (!isFile16(tomlPath)) {
|
|
14490
14713
|
return null;
|
|
14491
14714
|
}
|
|
14492
14715
|
try {
|
|
@@ -14663,9 +14886,9 @@ function applyProjectRoot(projectRoot, requireToml = true) {
|
|
|
14663
14886
|
if (projectRoot === void 0) {
|
|
14664
14887
|
return null;
|
|
14665
14888
|
}
|
|
14666
|
-
const p =
|
|
14889
|
+
const p = path38.resolve(projectRoot);
|
|
14667
14890
|
const agentRoot2 = findSubProjectRoot16("agent", p);
|
|
14668
|
-
if (requireToml && !
|
|
14891
|
+
if (requireToml && !isFile16(path38.join(p, "studio.toml")) && (agentRoot2 === null || !isFile16(path38.join(agentRoot2, "studio.toml")))) {
|
|
14669
14892
|
printErr(`error: no studio.toml under --project-root ${p}`);
|
|
14670
14893
|
return 2;
|
|
14671
14894
|
}
|
|
@@ -14677,7 +14900,7 @@ function applyProjectRoot(projectRoot, requireToml = true) {
|
|
|
14677
14900
|
return null;
|
|
14678
14901
|
}
|
|
14679
14902
|
function resolveProjectRoot2(_projectRoot) {
|
|
14680
|
-
const cwd =
|
|
14903
|
+
const cwd = path38.resolve(process.cwd());
|
|
14681
14904
|
return findStudioWorkspaceRoot3(cwd) ?? cwd;
|
|
14682
14905
|
}
|
|
14683
14906
|
function deployWorkspaceRoot2(root) {
|
|
@@ -14743,7 +14966,7 @@ function validateRuntimeAgainstStack(target, force, root) {
|
|
|
14743
14966
|
async function cmdPrepare(opts) {
|
|
14744
14967
|
let root;
|
|
14745
14968
|
if (opts.projectRoot !== void 0) {
|
|
14746
|
-
const p =
|
|
14969
|
+
const p = path38.resolve(opts.projectRoot);
|
|
14747
14970
|
if (!isDir7(p)) {
|
|
14748
14971
|
printErr(`error: --project-root ${p} is not a directory`);
|
|
14749
14972
|
return 2;
|
|
@@ -14751,7 +14974,7 @@ async function cmdPrepare(opts) {
|
|
|
14751
14974
|
process.chdir(p);
|
|
14752
14975
|
root = findStudioWorkspaceRoot3(p) ?? p;
|
|
14753
14976
|
} else {
|
|
14754
|
-
const cwd =
|
|
14977
|
+
const cwd = path38.resolve(process.cwd());
|
|
14755
14978
|
root = findStudioWorkspaceRoot3(cwd) ?? cwd;
|
|
14756
14979
|
}
|
|
14757
14980
|
const target = resolveTarget(opts, root);
|
|
@@ -14893,8 +15116,8 @@ function writeAgentDeployState(workspaceRoot, arn, record = {}, destination = "s
|
|
|
14893
15116
|
if (agentRoot2 === null) {
|
|
14894
15117
|
return;
|
|
14895
15118
|
}
|
|
14896
|
-
const tomlPath =
|
|
14897
|
-
if (!
|
|
15119
|
+
const tomlPath = path38.join(agentRoot2, "studio.toml");
|
|
15120
|
+
if (!isFile16(tomlPath)) {
|
|
14898
15121
|
return;
|
|
14899
15122
|
}
|
|
14900
15123
|
try {
|
|
@@ -14972,10 +15195,10 @@ package and at the repo root).
|
|
|
14972
15195
|
`;
|
|
14973
15196
|
function iamNoticeTomlPath(root) {
|
|
14974
15197
|
const agentRoot2 = findSubProjectRoot16("agent", root) ?? root;
|
|
14975
|
-
return
|
|
15198
|
+
return path38.join(agentRoot2, "studio.toml");
|
|
14976
15199
|
}
|
|
14977
15200
|
function iamNoticeAccepted(tomlPath) {
|
|
14978
|
-
if (!
|
|
15201
|
+
if (!isFile16(tomlPath)) {
|
|
14979
15202
|
return false;
|
|
14980
15203
|
}
|
|
14981
15204
|
let data;
|
|
@@ -15026,7 +15249,7 @@ async function iamNoticeGate(root, acceptRisk) {
|
|
|
15026
15249
|
return 1;
|
|
15027
15250
|
}
|
|
15028
15251
|
async function buildAgentProject(agentRoot2, packaging) {
|
|
15029
|
-
if (!
|
|
15252
|
+
if (!isFile16(path38.join(agentRoot2, "package.json"))) {
|
|
15030
15253
|
printErr(
|
|
15031
15254
|
`warning: no package.json under ${agentRoot2} \u2014 skipping the agent \`pnpm build\`; bnbagent-deploy will package whatever dist/ holds.`
|
|
15032
15255
|
);
|
|
@@ -15217,12 +15440,6 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15217
15440
|
const packagingDestination = opts.to ?? opts.destination ?? agentDeployDestination(root);
|
|
15218
15441
|
const driftAgentRoot = findSubProjectRoot16("agent", root) ?? root;
|
|
15219
15442
|
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
15443
|
rc = checkPackagingDrift(
|
|
15227
15444
|
root,
|
|
15228
15445
|
packagingDestination,
|
|
@@ -15365,7 +15582,7 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15365
15582
|
packagingDestination,
|
|
15366
15583
|
resolvePlatformArtifact(agentRoot2)
|
|
15367
15584
|
) === "container" ? "container" : "zip";
|
|
15368
|
-
const walletBlurb = walletKind2 === "twak" ? "the encrypted twak wallet as TWAK_WALLET_JSON" : "the encrypted keystore as WALLET_KEYSTORE_JSON";
|
|
15585
|
+
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
15586
|
if (secretsMode === "envvars") {
|
|
15370
15587
|
printErr(
|
|
15371
15588
|
`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 +15700,7 @@ function recordedEndpoint(root) {
|
|
|
15483
15700
|
}
|
|
15484
15701
|
function recordedAgentId(agentRoot2) {
|
|
15485
15702
|
try {
|
|
15486
|
-
const cfg = loadStudioToml20(
|
|
15703
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15487
15704
|
const val = tableOf13(cfg, "identity").agent_id;
|
|
15488
15705
|
return val !== void 0 && val !== null && val !== "" ? String(val) : null;
|
|
15489
15706
|
} catch {
|
|
@@ -15492,7 +15709,7 @@ function recordedAgentId(agentRoot2) {
|
|
|
15492
15709
|
}
|
|
15493
15710
|
function recordedRuntimeArn(agentRoot2) {
|
|
15494
15711
|
try {
|
|
15495
|
-
const cfg = loadStudioToml20(
|
|
15712
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15496
15713
|
const val = tableOf13(cfg, "deploy").runtime_arn;
|
|
15497
15714
|
return val ? String(val) : null;
|
|
15498
15715
|
} catch {
|
|
@@ -15501,7 +15718,7 @@ function recordedRuntimeArn(agentRoot2) {
|
|
|
15501
15718
|
}
|
|
15502
15719
|
function recordedOauthClientId(agentRoot2) {
|
|
15503
15720
|
try {
|
|
15504
|
-
const cfg = loadStudioToml20(
|
|
15721
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15505
15722
|
const val = tableOf13(cfg, "deploy").oauth_client_id;
|
|
15506
15723
|
return val ? String(val) : null;
|
|
15507
15724
|
} catch {
|
|
@@ -15510,7 +15727,7 @@ function recordedOauthClientId(agentRoot2) {
|
|
|
15510
15727
|
}
|
|
15511
15728
|
function agentFacesOf(agentRoot2) {
|
|
15512
15729
|
try {
|
|
15513
|
-
const cfg = loadStudioToml20(
|
|
15730
|
+
const cfg = loadStudioToml20(path38.join(agentRoot2, "studio.toml"));
|
|
15514
15731
|
return stackFaces(tableOf13(cfg, "stack"), tableOf13(cfg, "payments"));
|
|
15515
15732
|
} catch {
|
|
15516
15733
|
return ["A2A"];
|
|
@@ -15662,15 +15879,15 @@ async function printAgentClientPrompt2(root, destination, opts = {}) {
|
|
|
15662
15879
|
}
|
|
15663
15880
|
function persistDeploySummary2(root, text2) {
|
|
15664
15881
|
try {
|
|
15665
|
-
if (!
|
|
15882
|
+
if (!fs38.statSync(path38.resolve(root)).isDirectory()) {
|
|
15666
15883
|
return null;
|
|
15667
15884
|
}
|
|
15668
|
-
const p =
|
|
15669
|
-
|
|
15885
|
+
const p = path38.join(
|
|
15886
|
+
path38.dirname(envLocalPath16(root)),
|
|
15670
15887
|
"last-deploy-summary.txt"
|
|
15671
15888
|
);
|
|
15672
|
-
|
|
15673
|
-
|
|
15889
|
+
fs38.mkdirSync(path38.dirname(p), { recursive: true });
|
|
15890
|
+
fs38.writeFileSync(p, `${text2}
|
|
15674
15891
|
`, "utf-8");
|
|
15675
15892
|
return p;
|
|
15676
15893
|
} catch {
|
|
@@ -16067,9 +16284,9 @@ async function cmdDestroy(opts) {
|
|
|
16067
16284
|
return 2;
|
|
16068
16285
|
}
|
|
16069
16286
|
const answer = await promptUser(
|
|
16070
|
-
`This delegates the teardown of "${
|
|
16287
|
+
`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
16288
|
);
|
|
16072
|
-
if (answer.trim() !==
|
|
16289
|
+
if (answer.trim() !== path38.basename(workspaceRoot)) {
|
|
16073
16290
|
printErr(
|
|
16074
16291
|
"error: confirmation did not match the project name; aborting."
|
|
16075
16292
|
);
|
|
@@ -16185,8 +16402,8 @@ async function cmdProvisionCognito(opts) {
|
|
|
16185
16402
|
|
|
16186
16403
|
// src/cli/doctor.ts
|
|
16187
16404
|
import * as crypto5 from "crypto";
|
|
16188
|
-
import * as
|
|
16189
|
-
import * as
|
|
16405
|
+
import * as fs39 from "fs";
|
|
16406
|
+
import * as path39 from "path";
|
|
16190
16407
|
import { EVMWalletProvider as EVMWalletProvider2 } from "@bnbagent/sdk";
|
|
16191
16408
|
import {
|
|
16192
16409
|
envLocalPath as envLocalPath17,
|
|
@@ -16232,23 +16449,23 @@ function tableOf14(cfg, key) {
|
|
|
16232
16449
|
const v = cfg[key];
|
|
16233
16450
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
16234
16451
|
}
|
|
16235
|
-
function
|
|
16452
|
+
function isFile17(p) {
|
|
16236
16453
|
try {
|
|
16237
|
-
return
|
|
16454
|
+
return fs39.statSync(p).isFile();
|
|
16238
16455
|
} catch {
|
|
16239
16456
|
return false;
|
|
16240
16457
|
}
|
|
16241
16458
|
}
|
|
16242
16459
|
function isDir8(p) {
|
|
16243
16460
|
try {
|
|
16244
|
-
return
|
|
16461
|
+
return fs39.statSync(p).isDirectory();
|
|
16245
16462
|
} catch {
|
|
16246
16463
|
return false;
|
|
16247
16464
|
}
|
|
16248
16465
|
}
|
|
16249
16466
|
function keystoreJsons(dir) {
|
|
16250
16467
|
try {
|
|
16251
|
-
return
|
|
16468
|
+
return fs39.readdirSync(dir).filter((f) => f.endsWith(".json")).sort();
|
|
16252
16469
|
} catch {
|
|
16253
16470
|
return [];
|
|
16254
16471
|
}
|
|
@@ -16277,7 +16494,7 @@ async function cmdDoctor(opts) {
|
|
|
16277
16494
|
if (opts.checkEnv) {
|
|
16278
16495
|
return runCheckEnv(projectRoot);
|
|
16279
16496
|
}
|
|
16280
|
-
const tomlPath =
|
|
16497
|
+
const tomlPath = path39.join(projectRoot, "studio.toml");
|
|
16281
16498
|
let data;
|
|
16282
16499
|
try {
|
|
16283
16500
|
data = loadStudioToml21(tomlPath);
|
|
@@ -16313,8 +16530,8 @@ async function cmdDoctor(opts) {
|
|
|
16313
16530
|
}
|
|
16314
16531
|
function resolveProjectRoot3(argRoot) {
|
|
16315
16532
|
if (argRoot !== void 0) {
|
|
16316
|
-
const root2 =
|
|
16317
|
-
if (!
|
|
16533
|
+
const root2 = path39.resolve(argRoot);
|
|
16534
|
+
if (!isFile17(path39.join(root2, "studio.toml"))) {
|
|
16318
16535
|
printErr(`error: no studio.toml under --project-root ${root2}`);
|
|
16319
16536
|
return null;
|
|
16320
16537
|
}
|
|
@@ -16328,15 +16545,15 @@ function resolveProjectRoot3(argRoot) {
|
|
|
16328
16545
|
return root;
|
|
16329
16546
|
}
|
|
16330
16547
|
function runCheckEnv(projectRoot) {
|
|
16331
|
-
const agentDir = workspaceLayers(projectRoot) ??
|
|
16548
|
+
const agentDir = workspaceLayers(projectRoot) ?? path39.join(projectRoot, "agent");
|
|
16332
16549
|
const envPath = envLocalPath17(agentDir);
|
|
16333
16550
|
printOut(`bag doctor --check-env: ${envPath}`);
|
|
16334
|
-
if (!
|
|
16335
|
-
printOut(` (no ${
|
|
16551
|
+
if (!isFile17(envPath)) {
|
|
16552
|
+
printOut(` (no ${path39.basename(envPath)} found \u2014 nothing to report)`);
|
|
16336
16553
|
return 0;
|
|
16337
16554
|
}
|
|
16338
16555
|
const values = {};
|
|
16339
|
-
for (const rawLine of
|
|
16556
|
+
for (const rawLine of fs39.readFileSync(envPath, "utf-8").split(/\r?\n/)) {
|
|
16340
16557
|
const line = rawLine.trim();
|
|
16341
16558
|
if (!line || line.startsWith("#") || !line.includes("=")) {
|
|
16342
16559
|
continue;
|
|
@@ -16363,25 +16580,25 @@ function runCheckEnv(projectRoot) {
|
|
|
16363
16580
|
return 0;
|
|
16364
16581
|
}
|
|
16365
16582
|
function workspaceLayers(projectRoot) {
|
|
16366
|
-
const parent =
|
|
16367
|
-
if (
|
|
16368
|
-
return
|
|
16583
|
+
const parent = path39.dirname(projectRoot);
|
|
16584
|
+
if (isFile17(path39.join(parent, "agent", "studio.toml"))) {
|
|
16585
|
+
return path39.join(parent, "agent");
|
|
16369
16586
|
}
|
|
16370
|
-
if (
|
|
16371
|
-
return
|
|
16587
|
+
if (isFile17(path39.join(projectRoot, "agent", "studio.toml"))) {
|
|
16588
|
+
return path39.join(projectRoot, "agent");
|
|
16372
16589
|
}
|
|
16373
16590
|
return null;
|
|
16374
16591
|
}
|
|
16375
16592
|
function checkAppMain(projectRootArg) {
|
|
16376
16593
|
let projectRoot = projectRootArg;
|
|
16377
|
-
const parent =
|
|
16378
|
-
if (
|
|
16594
|
+
const parent = path39.dirname(projectRoot);
|
|
16595
|
+
if (isFile17(path39.join(parent, "agent", "studio.toml"))) {
|
|
16379
16596
|
projectRoot = parent;
|
|
16380
16597
|
}
|
|
16381
|
-
const agentDir =
|
|
16598
|
+
const agentDir = path39.join(projectRoot, "agent");
|
|
16382
16599
|
let config = {};
|
|
16383
|
-
const tomlPath =
|
|
16384
|
-
if (
|
|
16600
|
+
const tomlPath = path39.join(agentDir, "studio.toml");
|
|
16601
|
+
if (isFile17(tomlPath)) {
|
|
16385
16602
|
try {
|
|
16386
16603
|
config = loadStudioToml21(tomlPath);
|
|
16387
16604
|
} catch {
|
|
@@ -16399,8 +16616,8 @@ function checkAppMain(projectRootArg) {
|
|
|
16399
16616
|
} else {
|
|
16400
16617
|
entrypoint = "src/main.ts";
|
|
16401
16618
|
}
|
|
16402
|
-
const entryFile =
|
|
16403
|
-
if (!
|
|
16619
|
+
const entryFile = path39.join(agentDir, entrypoint);
|
|
16620
|
+
if (!isFile17(entryFile)) {
|
|
16404
16621
|
return [
|
|
16405
16622
|
{
|
|
16406
16623
|
name: "agent entrypoint",
|
|
@@ -16415,12 +16632,12 @@ function checkAppMain(projectRootArg) {
|
|
|
16415
16632
|
function checkAgentcoreName(projectRoot) {
|
|
16416
16633
|
let cfgPath = null;
|
|
16417
16634
|
for (const candidate of [
|
|
16418
|
-
|
|
16419
|
-
|
|
16635
|
+
path39.dirname(path39.dirname(projectRoot)),
|
|
16636
|
+
path39.dirname(projectRoot),
|
|
16420
16637
|
projectRoot
|
|
16421
16638
|
]) {
|
|
16422
|
-
const p =
|
|
16423
|
-
if (
|
|
16639
|
+
const p = path39.join(candidate, "agentcore", "agentcore.json");
|
|
16640
|
+
if (isFile17(p)) {
|
|
16424
16641
|
cfgPath = p;
|
|
16425
16642
|
break;
|
|
16426
16643
|
}
|
|
@@ -16430,7 +16647,7 @@ function checkAgentcoreName(projectRoot) {
|
|
|
16430
16647
|
}
|
|
16431
16648
|
let cfg;
|
|
16432
16649
|
try {
|
|
16433
|
-
cfg = JSON.parse(
|
|
16650
|
+
cfg = JSON.parse(fs39.readFileSync(cfgPath, "utf-8"));
|
|
16434
16651
|
} catch {
|
|
16435
16652
|
return [];
|
|
16436
16653
|
}
|
|
@@ -16462,7 +16679,7 @@ function isLocalEvmWallet(walletCfg) {
|
|
|
16462
16679
|
}
|
|
16463
16680
|
function anchoredKeystoreDir(projectRoot, walletCfg) {
|
|
16464
16681
|
const rel = String(walletCfg.keystore_dir ?? ".studio/wallets");
|
|
16465
|
-
return
|
|
16682
|
+
return path39.isAbsolute(rel) ? rel : path39.join(projectRoot, rel);
|
|
16466
16683
|
}
|
|
16467
16684
|
async function checkWallet(projectRoot, data) {
|
|
16468
16685
|
const walletCfg = tableOf14(data, "wallet");
|
|
@@ -16508,8 +16725,8 @@ async function checkWallet(projectRoot, data) {
|
|
|
16508
16725
|
}
|
|
16509
16726
|
const address = String(walletCfg.address ?? "").trim();
|
|
16510
16727
|
if (address) {
|
|
16511
|
-
const expected =
|
|
16512
|
-
if (!
|
|
16728
|
+
const expected = path39.join(keystoreDir, `${address}.json`);
|
|
16729
|
+
if (!isFile17(expected)) {
|
|
16513
16730
|
out.push({
|
|
16514
16731
|
name: "[wallet] address \u2194 keystore",
|
|
16515
16732
|
status: FAIL,
|
|
@@ -16519,7 +16736,7 @@ async function checkWallet(projectRoot, data) {
|
|
|
16519
16736
|
out.push({
|
|
16520
16737
|
name: "[wallet] address \u2194 keystore",
|
|
16521
16738
|
status: PASS,
|
|
16522
|
-
detail: `${address} matches ${
|
|
16739
|
+
detail: `${address} matches ${path39.basename(expected)}`
|
|
16523
16740
|
});
|
|
16524
16741
|
}
|
|
16525
16742
|
}
|
|
@@ -16536,9 +16753,9 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16536
16753
|
detail: "no [wallet].address \u2014 run `bag wallet new` first"
|
|
16537
16754
|
});
|
|
16538
16755
|
} else {
|
|
16539
|
-
const expected =
|
|
16756
|
+
const expected = path39.join(keystoreDir, `${address}.json`);
|
|
16540
16757
|
out.push(
|
|
16541
|
-
|
|
16758
|
+
isFile17(expected) ? {
|
|
16542
16759
|
name: "[wallet] Altana admin",
|
|
16543
16760
|
status: PASS,
|
|
16544
16761
|
detail: `${address} matches ${expected}`
|
|
@@ -16552,8 +16769,8 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16552
16769
|
const configured = String(
|
|
16553
16770
|
walletCfg.session_file ?? ".studio/wallets/altana-session.json"
|
|
16554
16771
|
);
|
|
16555
|
-
const sessionFile =
|
|
16556
|
-
if (!
|
|
16772
|
+
const sessionFile = path39.isAbsolute(configured) ? configured : path39.join(projectRoot, configured);
|
|
16773
|
+
if (!isFile17(sessionFile)) {
|
|
16557
16774
|
out.push({
|
|
16558
16775
|
name: "[wallet] Altana session",
|
|
16559
16776
|
status: FAIL,
|
|
@@ -16563,7 +16780,7 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16563
16780
|
}
|
|
16564
16781
|
let envelope;
|
|
16565
16782
|
try {
|
|
16566
|
-
envelope = JSON.parse(
|
|
16783
|
+
envelope = JSON.parse(fs39.readFileSync(sessionFile, "utf8"));
|
|
16567
16784
|
} catch {
|
|
16568
16785
|
out.push({
|
|
16569
16786
|
name: "[wallet] Altana session",
|
|
@@ -16589,7 +16806,7 @@ function checkWalletAltana(walletCfg, projectRoot) {
|
|
|
16589
16806
|
status: remaining <= 0 ? FAIL : remaining < 3 * 24 * 60 * 60 ? WARN : PASS,
|
|
16590
16807
|
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
16808
|
});
|
|
16592
|
-
if ((
|
|
16809
|
+
if ((fs39.statSync(sessionFile).mode & 63) !== 0) {
|
|
16593
16810
|
out.push({
|
|
16594
16811
|
name: "[wallet] Altana session permissions",
|
|
16595
16812
|
status: WARN,
|
|
@@ -16647,7 +16864,7 @@ async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
|
16647
16864
|
});
|
|
16648
16865
|
}
|
|
16649
16866
|
const walletFile = twakWalletFile(walletCfg, projectRoot);
|
|
16650
|
-
if (
|
|
16867
|
+
if (isFile17(walletFile)) {
|
|
16651
16868
|
out.push({
|
|
16652
16869
|
name: "[wallet] twak wallet",
|
|
16653
16870
|
status: PASS,
|
|
@@ -16657,7 +16874,7 @@ async function checkWalletTwak(walletCfg, projectRoot, data = {}) {
|
|
|
16657
16874
|
let createCmd = "twak wallet create --password <pw> --no-keychain";
|
|
16658
16875
|
let setupCmd = "twak setup";
|
|
16659
16876
|
if (walletCfg.twak_home) {
|
|
16660
|
-
const home =
|
|
16877
|
+
const home = path39.dirname(path39.dirname(walletFile));
|
|
16661
16878
|
createCmd = `HOME=${home} ${createCmd}`;
|
|
16662
16879
|
setupCmd = `HOME=${home} ${setupCmd}`;
|
|
16663
16880
|
}
|
|
@@ -16759,6 +16976,14 @@ async function checkLlm(data, projectRoot) {
|
|
|
16759
16976
|
});
|
|
16760
16977
|
}
|
|
16761
16978
|
if (provider === "pieverse-llm") {
|
|
16979
|
+
const walletKind2 = String(tableOf14(data, "wallet").kind ?? "");
|
|
16980
|
+
if (walletKind2 === "altana") {
|
|
16981
|
+
out.push({
|
|
16982
|
+
name: "pieverse wallet compatibility",
|
|
16983
|
+
status: FAIL,
|
|
16984
|
+
detail: "wallet kind 'altana' cannot log in to Pieverse (SIWE needs EIP-191 'sign.message', which altana never exposes) \u2014 `bag llm activate` will always fail. Set [llm].provider to 'openrouter', 'openai', or 'anthropic' in studio.toml."
|
|
16985
|
+
});
|
|
16986
|
+
}
|
|
16762
16987
|
out.push(...await checkPieverse(data, keyValue));
|
|
16763
16988
|
}
|
|
16764
16989
|
return out;
|
|
@@ -17413,11 +17638,11 @@ function checkAgentsMdSkillTrigger(projectRoot) {
|
|
|
17413
17638
|
if (ws === null) {
|
|
17414
17639
|
return [];
|
|
17415
17640
|
}
|
|
17416
|
-
const agentsMd =
|
|
17641
|
+
const agentsMd = path39.join(ws, "AGENTS.md");
|
|
17417
17642
|
const line = "For any bnbagent-studio task (deploy, sell, operate, debug), load the `/bnbagent-studio` skill first.";
|
|
17418
17643
|
let text2;
|
|
17419
17644
|
try {
|
|
17420
|
-
text2 =
|
|
17645
|
+
text2 = isFile17(agentsMd) ? fs39.readFileSync(agentsMd, "utf-8") : null;
|
|
17421
17646
|
} catch {
|
|
17422
17647
|
return [];
|
|
17423
17648
|
}
|
|
@@ -17454,8 +17679,8 @@ function printChecks(checks) {
|
|
|
17454
17679
|
}
|
|
17455
17680
|
|
|
17456
17681
|
// src/cli/env.ts
|
|
17457
|
-
import * as
|
|
17458
|
-
import * as
|
|
17682
|
+
import * as fs40 from "fs";
|
|
17683
|
+
import * as path40 from "path";
|
|
17459
17684
|
var SECRET_KEY_PARTS = ["PASSWORD", "SECRET", "TOKEN", "API_KEY"];
|
|
17460
17685
|
var WALLET_PASSWORD_KEYS = /* @__PURE__ */ new Set([
|
|
17461
17686
|
"WALLET_PASSWORD",
|
|
@@ -17501,8 +17726,8 @@ function resolveEnvPath(fileArg, rootArg) {
|
|
|
17501
17726
|
return [fileArg, null];
|
|
17502
17727
|
}
|
|
17503
17728
|
if (rootArg !== void 0) {
|
|
17504
|
-
const root2 =
|
|
17505
|
-
if (!
|
|
17729
|
+
const root2 = path40.resolve(rootArg);
|
|
17730
|
+
if (!fs40.existsSync(path40.join(root2, "studio.toml"))) {
|
|
17506
17731
|
return [null, `error: no studio.toml under --project-root ${root2}`];
|
|
17507
17732
|
}
|
|
17508
17733
|
return [envLocalPath(root2), null];
|
|
@@ -17513,7 +17738,7 @@ function resolveEnvPath(fileArg, rootArg) {
|
|
|
17513
17738
|
}
|
|
17514
17739
|
const target = envLocalPath(root);
|
|
17515
17740
|
let note = null;
|
|
17516
|
-
if (
|
|
17741
|
+
if (path40.dirname(path40.dirname(target)) !== path40.resolve(process.cwd())) {
|
|
17517
17742
|
note = `\u2192 writing to ${target} (workspace .studio/, where \`bag dev\` reads)`;
|
|
17518
17743
|
}
|
|
17519
17744
|
return [target, note];
|
|
@@ -17570,7 +17795,7 @@ function cmdGet2(key, fileArg, rootArg) {
|
|
|
17570
17795
|
}
|
|
17571
17796
|
|
|
17572
17797
|
// src/cli/erc8004.ts
|
|
17573
|
-
import * as
|
|
17798
|
+
import * as path41 from "path";
|
|
17574
17799
|
import { auditedOp as auditedOp3 } from "@bnbagent/studio-runtime/audit";
|
|
17575
17800
|
import {
|
|
17576
17801
|
findProjectRoot as findProjectRoot5,
|
|
@@ -17580,7 +17805,7 @@ import {
|
|
|
17580
17805
|
import {
|
|
17581
17806
|
getMetadata,
|
|
17582
17807
|
register as register2,
|
|
17583
|
-
resolve as
|
|
17808
|
+
resolve as resolve21,
|
|
17584
17809
|
setMetadata,
|
|
17585
17810
|
show as show2,
|
|
17586
17811
|
updateServiceEndpoint as updateServiceEndpoint2
|
|
@@ -17691,7 +17916,7 @@ function loadAgentCfg3() {
|
|
|
17691
17916
|
return null;
|
|
17692
17917
|
}
|
|
17693
17918
|
try {
|
|
17694
|
-
return loadStudioToml22(
|
|
17919
|
+
return loadStudioToml22(path41.join(root, "studio.toml"));
|
|
17695
17920
|
} catch {
|
|
17696
17921
|
return null;
|
|
17697
17922
|
}
|
|
@@ -17769,7 +17994,7 @@ function loadIdentityBlock(agentRoot2) {
|
|
|
17769
17994
|
try {
|
|
17770
17995
|
return {
|
|
17771
17996
|
...tableOf15(
|
|
17772
|
-
loadStudioToml22(
|
|
17997
|
+
loadStudioToml22(path41.join(agentRoot2, "studio.toml")),
|
|
17773
17998
|
"identity"
|
|
17774
17999
|
)
|
|
17775
18000
|
};
|
|
@@ -18108,7 +18333,7 @@ async function cmdResolve(agentId, networkArg) {
|
|
|
18108
18333
|
const wallet = walletRt6.getWallet();
|
|
18109
18334
|
let uri;
|
|
18110
18335
|
try {
|
|
18111
|
-
uri = await
|
|
18336
|
+
uri = await resolve21(agentId, {
|
|
18112
18337
|
wallet,
|
|
18113
18338
|
network: resolveNetwork2(networkArg)
|
|
18114
18339
|
});
|
|
@@ -18121,8 +18346,8 @@ async function cmdResolve(agentId, networkArg) {
|
|
|
18121
18346
|
}
|
|
18122
18347
|
|
|
18123
18348
|
// src/cli/erc8183.ts
|
|
18124
|
-
import * as
|
|
18125
|
-
import * as
|
|
18349
|
+
import * as fs41 from "fs";
|
|
18350
|
+
import * as path42 from "path";
|
|
18126
18351
|
import { JobStatus } from "@bnbagent/sdk";
|
|
18127
18352
|
import {
|
|
18128
18353
|
buyWorkflow,
|
|
@@ -18226,8 +18451,8 @@ function applyProjectRoot2(root) {
|
|
|
18226
18451
|
if (root === void 0) {
|
|
18227
18452
|
return null;
|
|
18228
18453
|
}
|
|
18229
|
-
const p =
|
|
18230
|
-
if (!
|
|
18454
|
+
const p = path42.resolve(root);
|
|
18455
|
+
if (!fs41.existsSync(path42.join(p, "studio.toml"))) {
|
|
18231
18456
|
printErr(`error: no studio.toml under --project-root ${p}`);
|
|
18232
18457
|
return 2;
|
|
18233
18458
|
}
|
|
@@ -18312,7 +18537,7 @@ function parseQuoteEnvelope(raw) {
|
|
|
18312
18537
|
let text2 = trimmed;
|
|
18313
18538
|
if (!trimmed.startsWith("{")) {
|
|
18314
18539
|
try {
|
|
18315
|
-
text2 =
|
|
18540
|
+
text2 = fs41.readFileSync(trimmed, "utf-8");
|
|
18316
18541
|
} catch (exc) {
|
|
18317
18542
|
throw new Error(
|
|
18318
18543
|
`--quote-json is neither inline JSON nor a readable file: ${errMsg5(exc)}`
|
|
@@ -18492,9 +18717,9 @@ async function cmdSettle(jobId, opts) {
|
|
|
18492
18717
|
}
|
|
18493
18718
|
|
|
18494
18719
|
// src/cli/skills.ts
|
|
18495
|
-
import * as
|
|
18720
|
+
import * as fs42 from "fs";
|
|
18496
18721
|
import * as os6 from "os";
|
|
18497
|
-
import * as
|
|
18722
|
+
import * as path43 from "path";
|
|
18498
18723
|
import { Option as Option7 } from "commander";
|
|
18499
18724
|
function registerSkills(program) {
|
|
18500
18725
|
const skills = program.command("skills").description("Install Claude Code skills into the host IDE.").action(
|
|
@@ -18540,7 +18765,7 @@ function cmdList4() {
|
|
|
18540
18765
|
for (const p of listSourceSkills(
|
|
18541
18766
|
SKILLS_SOURCE
|
|
18542
18767
|
)) {
|
|
18543
|
-
printOut(
|
|
18768
|
+
printOut(path43.basename(p));
|
|
18544
18769
|
}
|
|
18545
18770
|
const refs = listSourceReferences(
|
|
18546
18771
|
SKILLS_SOURCE
|
|
@@ -18551,7 +18776,7 @@ function cmdList4() {
|
|
|
18551
18776
|
references (installed under ${ROUTER_SKILL_NAME}/references/, loaded on demand by the skills above):`
|
|
18552
18777
|
);
|
|
18553
18778
|
for (const p of refs) {
|
|
18554
|
-
printOut(` ${
|
|
18779
|
+
printOut(` ${path43.basename(p)}`);
|
|
18555
18780
|
}
|
|
18556
18781
|
}
|
|
18557
18782
|
return 0;
|
|
@@ -18763,7 +18988,7 @@ function installTargets(targets, scope) {
|
|
|
18763
18988
|
);
|
|
18764
18989
|
for (const name of result.legacyPresent) {
|
|
18765
18990
|
const leaf = result.target === "cursor" ? `${name}.mdc` : name;
|
|
18766
|
-
printErr(` - ${
|
|
18991
|
+
printErr(` - ${path43.join(result.targetDir, leaf)}`);
|
|
18767
18992
|
}
|
|
18768
18993
|
printErr(
|
|
18769
18994
|
"\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 +19001,19 @@ function studioSkillNames() {
|
|
|
18776
19001
|
for (const p of listSourceSkills(
|
|
18777
19002
|
SKILLS_SOURCE
|
|
18778
19003
|
)) {
|
|
18779
|
-
names.add(
|
|
19004
|
+
names.add(path43.basename(p).replace(/\.md$/, ""));
|
|
18780
19005
|
}
|
|
18781
19006
|
for (const name of LEGACY_SKILL_NAMES) {
|
|
18782
19007
|
names.add(name);
|
|
18783
19008
|
}
|
|
18784
|
-
const providersRoot =
|
|
19009
|
+
const providersRoot = path43.join(bundledRecipesRoot(), "providers");
|
|
18785
19010
|
if (isDir9(providersRoot)) {
|
|
18786
|
-
for (const provider of
|
|
18787
|
-
const skillDir =
|
|
19011
|
+
for (const provider of fs42.readdirSync(providersRoot)) {
|
|
19012
|
+
const skillDir = path43.join(providersRoot, provider, "skills");
|
|
18788
19013
|
if (!isDir9(skillDir)) {
|
|
18789
19014
|
continue;
|
|
18790
19015
|
}
|
|
18791
|
-
for (const md of
|
|
19016
|
+
for (const md of fs42.readdirSync(skillDir)) {
|
|
18792
19017
|
if (md.endsWith(".md")) {
|
|
18793
19018
|
names.add(md.replace(/\.md$/, ""));
|
|
18794
19019
|
}
|
|
@@ -18799,14 +19024,14 @@ function studioSkillNames() {
|
|
|
18799
19024
|
}
|
|
18800
19025
|
function isDir9(p) {
|
|
18801
19026
|
try {
|
|
18802
|
-
return
|
|
19027
|
+
return fs42.statSync(p).isDirectory();
|
|
18803
19028
|
} catch {
|
|
18804
19029
|
return false;
|
|
18805
19030
|
}
|
|
18806
19031
|
}
|
|
18807
|
-
function
|
|
19032
|
+
function isFile18(p) {
|
|
18808
19033
|
try {
|
|
18809
|
-
return
|
|
19034
|
+
return fs42.statSync(p).isFile();
|
|
18810
19035
|
} catch {
|
|
18811
19036
|
return false;
|
|
18812
19037
|
}
|
|
@@ -18820,26 +19045,26 @@ function findInstalledSkills(knownNames) {
|
|
|
18820
19045
|
if (!isDir9(root)) {
|
|
18821
19046
|
return;
|
|
18822
19047
|
}
|
|
18823
|
-
const resolved =
|
|
18824
|
-
if (!roots.some((r) =>
|
|
19048
|
+
const resolved = fs42.realpathSync(root);
|
|
19049
|
+
if (!roots.some((r) => fs42.realpathSync(r) === resolved)) {
|
|
18825
19050
|
roots.push(root);
|
|
18826
19051
|
}
|
|
18827
19052
|
};
|
|
18828
|
-
addRoot(
|
|
18829
|
-
addRoot(
|
|
18830
|
-
addRoot(
|
|
18831
|
-
addRoot(
|
|
19053
|
+
addRoot(path43.join(home, ".claude", "skills"));
|
|
19054
|
+
addRoot(path43.join(home, ".cursor", "rules"));
|
|
19055
|
+
addRoot(path43.join(cwd, ".claude", "skills"));
|
|
19056
|
+
addRoot(path43.join(cwd, ".cursor", "rules"));
|
|
18832
19057
|
for (const root of roots) {
|
|
18833
|
-
const isCursor =
|
|
19058
|
+
const isCursor = path43.basename(root) === "rules" && path43.basename(path43.dirname(root)) === ".cursor";
|
|
18834
19059
|
for (const name of [...knownNames].sort()) {
|
|
18835
|
-
const target =
|
|
18836
|
-
if (isCursor &&
|
|
19060
|
+
const target = path43.join(root, isCursor ? `${name}.mdc` : name);
|
|
19061
|
+
if (isCursor && isFile18(target)) {
|
|
18837
19062
|
found.push(target);
|
|
18838
19063
|
} else if (!isCursor && isDir9(target)) {
|
|
18839
19064
|
found.push(target);
|
|
18840
19065
|
}
|
|
18841
|
-
if (isCursor && isDir9(
|
|
18842
|
-
found.push(
|
|
19066
|
+
if (isCursor && isDir9(path43.join(root, name))) {
|
|
19067
|
+
found.push(path43.join(root, name));
|
|
18843
19068
|
}
|
|
18844
19069
|
}
|
|
18845
19070
|
}
|
|
@@ -18867,7 +19092,7 @@ async function cmdUninstall(flags) {
|
|
|
18867
19092
|
}
|
|
18868
19093
|
}
|
|
18869
19094
|
for (const p of installed) {
|
|
18870
|
-
|
|
19095
|
+
fs42.rmSync(p, { recursive: true, force: true });
|
|
18871
19096
|
printOut(` removed: ${p}`);
|
|
18872
19097
|
}
|
|
18873
19098
|
}
|
|
@@ -18906,7 +19131,7 @@ function registerUninstall(program) {
|
|
|
18906
19131
|
}
|
|
18907
19132
|
|
|
18908
19133
|
// src/cli/platform.ts
|
|
18909
|
-
import * as
|
|
19134
|
+
import * as path44 from "path";
|
|
18910
19135
|
import {
|
|
18911
19136
|
STUDIO_TOML as STUDIO_TOML2,
|
|
18912
19137
|
findSubProjectRoot as findSubProjectRoot18,
|
|
@@ -19109,7 +19334,7 @@ function localPlatformCfg() {
|
|
|
19109
19334
|
if (agentRoot2 === null) {
|
|
19110
19335
|
return [null, {}];
|
|
19111
19336
|
}
|
|
19112
|
-
const tomlPath =
|
|
19337
|
+
const tomlPath = path44.join(agentRoot2, STUDIO_TOML2);
|
|
19113
19338
|
let cfg;
|
|
19114
19339
|
try {
|
|
19115
19340
|
cfg = loadStudioToml23(tomlPath);
|
|
@@ -19182,8 +19407,8 @@ function formatRemaining(seconds) {
|
|
|
19182
19407
|
}
|
|
19183
19408
|
|
|
19184
19409
|
// src/cli/recipe.ts
|
|
19185
|
-
import * as
|
|
19186
|
-
import * as
|
|
19410
|
+
import * as fs43 from "fs";
|
|
19411
|
+
import * as path45 from "path";
|
|
19187
19412
|
import { parse as parse6 } from "smol-toml";
|
|
19188
19413
|
function registerRecipe(program) {
|
|
19189
19414
|
const p = program.command("recipe").description("Print recipe code/files (agent / wallet / 8004).");
|
|
@@ -19313,7 +19538,7 @@ function resolvePkgContext(explicit) {
|
|
|
19313
19538
|
let data;
|
|
19314
19539
|
try {
|
|
19315
19540
|
data = parse6(
|
|
19316
|
-
|
|
19541
|
+
fs43.readFileSync(path45.join(projectRoot, "studio.toml"), "utf-8")
|
|
19317
19542
|
);
|
|
19318
19543
|
} catch {
|
|
19319
19544
|
return [null, null];
|
|
@@ -19331,8 +19556,8 @@ function resolvePkgContext(explicit) {
|
|
|
19331
19556
|
}
|
|
19332
19557
|
|
|
19333
19558
|
// src/cli/scan.ts
|
|
19334
|
-
import * as
|
|
19335
|
-
import * as
|
|
19559
|
+
import * as fs44 from "fs";
|
|
19560
|
+
import * as path46 from "path";
|
|
19336
19561
|
import { Option as Option8 } from "commander";
|
|
19337
19562
|
import { parse as parse7 } from "smol-toml";
|
|
19338
19563
|
function registerScan(program) {
|
|
@@ -19349,7 +19574,7 @@ function registerScan(program) {
|
|
|
19349
19574
|
"note: `--json` is deprecated (JSON is the default output); ignoring."
|
|
19350
19575
|
);
|
|
19351
19576
|
}
|
|
19352
|
-
const root =
|
|
19577
|
+
const root = path46.resolve(opts.path ?? process.cwd());
|
|
19353
19578
|
const report = scanProject(root);
|
|
19354
19579
|
if (opts.text) {
|
|
19355
19580
|
process.stdout.write(formatText(report));
|
|
@@ -19361,26 +19586,26 @@ function registerScan(program) {
|
|
|
19361
19586
|
})
|
|
19362
19587
|
);
|
|
19363
19588
|
}
|
|
19364
|
-
function
|
|
19589
|
+
function isFile19(p) {
|
|
19365
19590
|
try {
|
|
19366
|
-
return
|
|
19591
|
+
return fs44.statSync(p).isFile();
|
|
19367
19592
|
} catch {
|
|
19368
19593
|
return false;
|
|
19369
19594
|
}
|
|
19370
19595
|
}
|
|
19371
19596
|
function isDir10(p) {
|
|
19372
19597
|
try {
|
|
19373
|
-
return
|
|
19598
|
+
return fs44.statSync(p).isDirectory();
|
|
19374
19599
|
} catch {
|
|
19375
19600
|
return false;
|
|
19376
19601
|
}
|
|
19377
19602
|
}
|
|
19378
19603
|
function layerBase(root) {
|
|
19379
|
-
return isDir10(
|
|
19604
|
+
return isDir10(path46.join(root, "app", "agent")) ? path46.join(root, "app") : root;
|
|
19380
19605
|
}
|
|
19381
19606
|
function safeReadJson(p) {
|
|
19382
19607
|
try {
|
|
19383
|
-
const data = JSON.parse(
|
|
19608
|
+
const data = JSON.parse(fs44.readFileSync(p, "utf-8"));
|
|
19384
19609
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
19385
19610
|
} catch {
|
|
19386
19611
|
return null;
|
|
@@ -19388,7 +19613,7 @@ function safeReadJson(p) {
|
|
|
19388
19613
|
}
|
|
19389
19614
|
function safeReadToml(p) {
|
|
19390
19615
|
try {
|
|
19391
|
-
return parse7(
|
|
19616
|
+
return parse7(fs44.readFileSync(p, "utf-8"));
|
|
19392
19617
|
} catch {
|
|
19393
19618
|
return null;
|
|
19394
19619
|
}
|
|
@@ -19418,33 +19643,33 @@ function resolvePackageName(projectName2, root) {
|
|
|
19418
19643
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(candidate)) {
|
|
19419
19644
|
return null;
|
|
19420
19645
|
}
|
|
19421
|
-
if (!isDir10(
|
|
19646
|
+
if (!isDir10(path46.join(root, candidate))) {
|
|
19422
19647
|
return null;
|
|
19423
19648
|
}
|
|
19424
19649
|
return candidate;
|
|
19425
19650
|
}
|
|
19426
19651
|
function inferLayout(root) {
|
|
19427
|
-
const agentDir =
|
|
19428
|
-
const hasAgent =
|
|
19652
|
+
const agentDir = path46.join(layerBase(root), "agent");
|
|
19653
|
+
const hasAgent = isFile19(path46.join(agentDir, "main.ts")) || isFile19(path46.join(agentDir, "main.py"));
|
|
19429
19654
|
return {
|
|
19430
19655
|
has_agent: hasAgent,
|
|
19431
|
-
has_agent_descriptor:
|
|
19432
|
-
|
|
19656
|
+
has_agent_descriptor: isFile19(
|
|
19657
|
+
path46.join(root, "agentcore", "agentcore.json")
|
|
19433
19658
|
),
|
|
19434
19659
|
role: hasAgent ? "agent" : "none"
|
|
19435
19660
|
};
|
|
19436
19661
|
}
|
|
19437
19662
|
function inferPackageManager(root, hasPackageJson) {
|
|
19438
|
-
if (
|
|
19663
|
+
if (isFile19(path46.join(root, "pnpm-lock.yaml"))) {
|
|
19439
19664
|
return "pnpm";
|
|
19440
19665
|
}
|
|
19441
|
-
if (
|
|
19666
|
+
if (isFile19(path46.join(root, "yarn.lock"))) {
|
|
19442
19667
|
return "yarn";
|
|
19443
19668
|
}
|
|
19444
|
-
if (
|
|
19669
|
+
if (isFile19(path46.join(root, "bun.lockb"))) {
|
|
19445
19670
|
return "bun";
|
|
19446
19671
|
}
|
|
19447
|
-
if (
|
|
19672
|
+
if (isFile19(path46.join(root, "package-lock.json"))) {
|
|
19448
19673
|
return "npm";
|
|
19449
19674
|
}
|
|
19450
19675
|
if (hasPackageJson) {
|
|
@@ -19457,7 +19682,7 @@ function inferRecipes(root, studioData, layout) {
|
|
|
19457
19682
|
if (layout.has_agent) {
|
|
19458
19683
|
recipes.push("agent");
|
|
19459
19684
|
}
|
|
19460
|
-
const walletsDir =
|
|
19685
|
+
const walletsDir = path46.join(root, ".studio", "wallets");
|
|
19461
19686
|
const walletSection = studioData?.wallet;
|
|
19462
19687
|
const hasWalletSection = walletSection !== null && typeof walletSection === "object" && !Array.isArray(walletSection);
|
|
19463
19688
|
if (isDir10(walletsDir) && hasWalletSection) {
|
|
@@ -19466,13 +19691,13 @@ function inferRecipes(root, studioData, layout) {
|
|
|
19466
19691
|
return recipes;
|
|
19467
19692
|
}
|
|
19468
19693
|
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(
|
|
19694
|
+
const studioToml = path46.join(root, "studio.toml");
|
|
19695
|
+
const packageJson = path46.join(root, "package.json");
|
|
19696
|
+
const agentcoreJson = path46.join(root, "agentcore", "agentcore.json");
|
|
19697
|
+
const hasStudioToml = isFile19(studioToml);
|
|
19698
|
+
const hasPackageJson = isFile19(packageJson);
|
|
19699
|
+
const hasAgentcoreJson = isFile19(agentcoreJson);
|
|
19700
|
+
const hasDotStudioDir = isDir10(path46.join(root, ".studio"));
|
|
19476
19701
|
const pkgData = hasPackageJson ? safeReadJson(packageJson) : null;
|
|
19477
19702
|
const studioData = hasStudioToml ? safeReadToml(studioToml) : null;
|
|
19478
19703
|
const rawName = pkgData?.name;
|
|
@@ -19529,8 +19754,8 @@ function formatText(report) {
|
|
|
19529
19754
|
}
|
|
19530
19755
|
|
|
19531
19756
|
// src/cli/x402.ts
|
|
19532
|
-
import * as
|
|
19533
|
-
import * as
|
|
19757
|
+
import * as fs45 from "fs";
|
|
19758
|
+
import * as path47 from "path";
|
|
19534
19759
|
import { auditedOp as auditedOp4 } from "@bnbagent/studio-runtime/audit";
|
|
19535
19760
|
import {
|
|
19536
19761
|
envLocalPath as envLocalPath18,
|
|
@@ -19724,7 +19949,7 @@ function loadX402Policy() {
|
|
|
19724
19949
|
}
|
|
19725
19950
|
let cfg;
|
|
19726
19951
|
try {
|
|
19727
|
-
cfg = loadStudioToml24(
|
|
19952
|
+
cfg = loadStudioToml24(path47.join(root, "studio.toml"));
|
|
19728
19953
|
} catch (exc) {
|
|
19729
19954
|
printErr(`error: failed to parse studio.toml: ${errMsg6(exc)}`);
|
|
19730
19955
|
return null;
|
|
@@ -19738,7 +19963,7 @@ function loadSellerConfig() {
|
|
|
19738
19963
|
return null;
|
|
19739
19964
|
}
|
|
19740
19965
|
try {
|
|
19741
|
-
return [root, loadStudioToml24(
|
|
19966
|
+
return [root, loadStudioToml24(path47.join(root, "studio.toml"))];
|
|
19742
19967
|
} catch (exc) {
|
|
19743
19968
|
printErr(`error: failed to parse studio.toml: ${errMsg6(exc)}`);
|
|
19744
19969
|
return null;
|
|
@@ -19784,8 +20009,8 @@ async function cmdSellInit(priceFlag) {
|
|
|
19784
20009
|
const loaded = loadSellerConfig();
|
|
19785
20010
|
if (loaded === null) return 1;
|
|
19786
20011
|
const [root, cfg] = loaded;
|
|
19787
|
-
const tomlPath =
|
|
19788
|
-
const original =
|
|
20012
|
+
const tomlPath = path47.join(root, "studio.toml");
|
|
20013
|
+
const original = fs45.readFileSync(tomlPath, "utf8");
|
|
19789
20014
|
const sellerExists = hasSection(original, "payments.x402_seller");
|
|
19790
20015
|
let priceUsd;
|
|
19791
20016
|
try {
|
|
@@ -19803,7 +20028,7 @@ async function cmdSellInit(priceFlag) {
|
|
|
19803
20028
|
return 1;
|
|
19804
20029
|
}
|
|
19805
20030
|
if (!sellerExists) {
|
|
19806
|
-
|
|
20031
|
+
fs45.writeFileSync(
|
|
19807
20032
|
tomlPath,
|
|
19808
20033
|
updateSection(original, "payments.x402_seller", {
|
|
19809
20034
|
enabled: true,
|
|
@@ -19815,7 +20040,7 @@ async function cmdSellInit(priceFlag) {
|
|
|
19815
20040
|
"utf8"
|
|
19816
20041
|
);
|
|
19817
20042
|
} else if (priceFlag !== void 0) {
|
|
19818
|
-
|
|
20043
|
+
fs45.writeFileSync(
|
|
19819
20044
|
tomlPath,
|
|
19820
20045
|
updateSection(original, "payments.x402_seller", {
|
|
19821
20046
|
price_usd: priceUsd
|
|
@@ -20184,14 +20409,14 @@ async function confirmOrAbort(prompt, assumeYes) {
|
|
|
20184
20409
|
return answer === "y" || answer === "yes";
|
|
20185
20410
|
}
|
|
20186
20411
|
function writeMerchantEntry(tomlPath, fields) {
|
|
20187
|
-
const text2 =
|
|
20412
|
+
const text2 = fs45.readFileSync(tomlPath, "utf-8");
|
|
20188
20413
|
const entries = {
|
|
20189
20414
|
domain: fields.domain,
|
|
20190
20415
|
pay_to: fields.payTo,
|
|
20191
20416
|
per_call_cap_usd: fields.capUsd,
|
|
20192
20417
|
verified: fields.verified
|
|
20193
20418
|
};
|
|
20194
|
-
|
|
20419
|
+
fs45.writeFileSync(
|
|
20195
20420
|
tomlPath,
|
|
20196
20421
|
updateSection(text2, `payments.x402.merchants.${fields.key}`, entries),
|
|
20197
20422
|
"utf-8"
|
|
@@ -20320,7 +20545,7 @@ The merchant may have rotated its address (or the response was tampered with). U
|
|
|
20320
20545
|
printOut("aborted \u2014 nothing written.");
|
|
20321
20546
|
return 1;
|
|
20322
20547
|
}
|
|
20323
|
-
const tomlPath =
|
|
20548
|
+
const tomlPath = path47.join(root, "studio.toml");
|
|
20324
20549
|
try {
|
|
20325
20550
|
writeMerchantEntry(tomlPath, {
|
|
20326
20551
|
key,
|
|
@@ -20383,23 +20608,23 @@ function buildProgram() {
|
|
|
20383
20608
|
return program;
|
|
20384
20609
|
}
|
|
20385
20610
|
function cliVersion() {
|
|
20386
|
-
return "0.0.6-alpha.
|
|
20611
|
+
return "0.0.6-alpha.9";
|
|
20387
20612
|
}
|
|
20388
20613
|
|
|
20389
20614
|
// src/cli/updateCheck.ts
|
|
20390
|
-
import * as
|
|
20615
|
+
import * as fs46 from "fs";
|
|
20391
20616
|
import * as os7 from "os";
|
|
20392
|
-
import * as
|
|
20617
|
+
import * as path48 from "path";
|
|
20393
20618
|
var PACKAGE = "@bnbagent/studio-cli";
|
|
20394
20619
|
var REGISTRY_LATEST_URL = `https://registry.npmjs.org/${PACKAGE}/latest`;
|
|
20395
20620
|
var CHECK_INTERVAL_SECONDS = 24 * 3600;
|
|
20396
20621
|
var TIMEOUT_MS = 2e3;
|
|
20397
20622
|
function cachePath(home) {
|
|
20398
|
-
return
|
|
20623
|
+
return path48.join(home, ".bag", "update-check.json");
|
|
20399
20624
|
}
|
|
20400
20625
|
function loadCache(home) {
|
|
20401
20626
|
try {
|
|
20402
|
-
const data = JSON.parse(
|
|
20627
|
+
const data = JSON.parse(fs46.readFileSync(cachePath(home), "utf-8"));
|
|
20403
20628
|
return data !== null && typeof data === "object" && !Array.isArray(data) ? data : {};
|
|
20404
20629
|
} catch {
|
|
20405
20630
|
return {};
|
|
@@ -20408,8 +20633,8 @@ function loadCache(home) {
|
|
|
20408
20633
|
function saveCache(state, home) {
|
|
20409
20634
|
try {
|
|
20410
20635
|
const p = cachePath(home);
|
|
20411
|
-
|
|
20412
|
-
|
|
20636
|
+
fs46.mkdirSync(path48.dirname(p), { recursive: true });
|
|
20637
|
+
fs46.writeFileSync(p, `${JSON.stringify(state, null, 2)}
|
|
20413
20638
|
`);
|
|
20414
20639
|
} catch {
|
|
20415
20640
|
}
|