@bnbagent/studio-cli 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bag.js +490 -276
- package/dist/{chunk-ODCZKKZJ.js → chunk-YFEM4564.js} +7 -2
- package/dist/{deployCli-VM5TYKQX.js → deployCli-NJFCWBSF.js} +1 -1
- package/package.json +2 -2
- package/recipes/runtimes/azure-foundry/code/{{PKG}}/foundryMain.ts.tmpl +125 -3
- package/recipes/runtimes/azure-foundry/recipe.toml +3 -3
- package/skills/bnbagent-studio.md +1 -1
- package/skills/references/bnbagent-studio-use-aws-agentcore.md +1 -1
- package/skills/references/bnbagent-studio-use-azure-foundry.md +13 -5
- package/skills/references/bnbagent-studio-use-bnb-trial.md +1 -1
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-YFEM4564.js";
|
|
48
48
|
import {
|
|
49
49
|
TWAK_CLI_MIN_VERSION,
|
|
50
50
|
TWAK_CLI_VERSION,
|
|
@@ -222,7 +222,7 @@ import {
|
|
|
222
222
|
var CAMPAIGN_DOC_URL = "https://www.bnbchain.org/en/blog/bnb-agent-studio-is-live-on-bnb-chain-ai-agents-from-one-prompt";
|
|
223
223
|
var CAMPAIGN_CHECK_TIMEOUT_MS = 6e3;
|
|
224
224
|
async function fetchCampaignActive() {
|
|
225
|
-
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-
|
|
225
|
+
const { bnbPlatformApiUrl: bnbPlatformApiUrl2 } = await import("./deployCli-NJFCWBSF.js");
|
|
226
226
|
const controller = new AbortController();
|
|
227
227
|
const timer = setTimeout(() => controller.abort(), CAMPAIGN_CHECK_TIMEOUT_MS);
|
|
228
228
|
try {
|
|
@@ -437,10 +437,56 @@ function findAgentRoot(start) {
|
|
|
437
437
|
// src/cli/program.ts
|
|
438
438
|
import { Command } from "commander";
|
|
439
439
|
|
|
440
|
-
// src/cli/
|
|
440
|
+
// src/cli/_packageMetadata.ts
|
|
441
441
|
import * as fs3 from "fs";
|
|
442
|
-
import * as os from "os";
|
|
443
442
|
import * as path2 from "path";
|
|
443
|
+
import { fileURLToPath } from "url";
|
|
444
|
+
function packageRoot() {
|
|
445
|
+
let dir = path2.dirname(fileURLToPath(import.meta.url));
|
|
446
|
+
for (; ; ) {
|
|
447
|
+
const packageJson = path2.join(dir, "package.json");
|
|
448
|
+
if (fs3.existsSync(packageJson)) return dir;
|
|
449
|
+
const parent = path2.dirname(dir);
|
|
450
|
+
if (parent === dir) {
|
|
451
|
+
throw new Error("cannot locate the studio-cli package root");
|
|
452
|
+
}
|
|
453
|
+
dir = parent;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
function studioCliVersion() {
|
|
457
|
+
if ("0.0.10") {
|
|
458
|
+
return "0.0.10";
|
|
459
|
+
}
|
|
460
|
+
const file = path2.join(packageRoot(), "package.json");
|
|
461
|
+
const pkg = JSON.parse(fs3.readFileSync(file, "utf-8"));
|
|
462
|
+
const value = String(pkg.version ?? "");
|
|
463
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(value)) {
|
|
464
|
+
throw new Error(
|
|
465
|
+
`studio-cli package.json must contain a valid version in ${file}`
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
return value;
|
|
469
|
+
}
|
|
470
|
+
function pnpmVersion() {
|
|
471
|
+
if ("10.24.0") {
|
|
472
|
+
return "10.24.0";
|
|
473
|
+
}
|
|
474
|
+
const file = path2.join(packageRoot(), "package.json");
|
|
475
|
+
const pkg = JSON.parse(fs3.readFileSync(file, "utf-8"));
|
|
476
|
+
const value = String(pkg.packageManager ?? "");
|
|
477
|
+
const match = /^pnpm@(.+)$/u.exec(value);
|
|
478
|
+
if (!match?.[1]) {
|
|
479
|
+
throw new Error(
|
|
480
|
+
`studio-cli packageManager must pin pnpm (expected "pnpm@<version>" in ${file})`
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
return match[1];
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// src/cli/agents.ts
|
|
487
|
+
import * as fs4 from "fs";
|
|
488
|
+
import * as os from "os";
|
|
489
|
+
import * as path3 from "path";
|
|
444
490
|
import { parse, stringify } from "smol-toml";
|
|
445
491
|
|
|
446
492
|
// src/cli/utils/prompt.ts
|
|
@@ -506,18 +552,18 @@ function stdinIsTty() {
|
|
|
506
552
|
// src/cli/agents.ts
|
|
507
553
|
var SCHEMA_VERSION = "1";
|
|
508
554
|
function registryPath() {
|
|
509
|
-
return
|
|
555
|
+
return path3.join(os.homedir(), ".bnbagent-studio", "projects.toml");
|
|
510
556
|
}
|
|
511
557
|
var RegistryCorruptError = class extends Error {
|
|
512
558
|
};
|
|
513
559
|
function loadDoc() {
|
|
514
560
|
const file = registryPath();
|
|
515
|
-
if (!
|
|
561
|
+
if (!fs4.existsSync(file)) {
|
|
516
562
|
return { schema_version: SCHEMA_VERSION, projects: [] };
|
|
517
563
|
}
|
|
518
564
|
let text2;
|
|
519
565
|
try {
|
|
520
|
-
text2 =
|
|
566
|
+
text2 = fs4.readFileSync(file, "utf-8");
|
|
521
567
|
} catch (exc) {
|
|
522
568
|
throw new RegistryCorruptError(`cannot read ${file}: ${exc}`);
|
|
523
569
|
}
|
|
@@ -538,7 +584,7 @@ function loadDoc() {
|
|
|
538
584
|
}
|
|
539
585
|
function saveDoc(doc) {
|
|
540
586
|
const file = registryPath();
|
|
541
|
-
|
|
587
|
+
fs4.mkdirSync(path3.dirname(file), { recursive: true });
|
|
542
588
|
const projects = doc.projects.map((entry) => {
|
|
543
589
|
const out = {};
|
|
544
590
|
for (const [k, v] of Object.entries(entry)) {
|
|
@@ -548,7 +594,7 @@ function saveDoc(doc) {
|
|
|
548
594
|
}
|
|
549
595
|
return out;
|
|
550
596
|
});
|
|
551
|
-
|
|
597
|
+
fs4.writeFileSync(
|
|
552
598
|
file,
|
|
553
599
|
`${stringify({ schema_version: doc.schema_version, projects })}
|
|
554
600
|
`,
|
|
@@ -557,24 +603,24 @@ function saveDoc(doc) {
|
|
|
557
603
|
}
|
|
558
604
|
function isFile(p) {
|
|
559
605
|
try {
|
|
560
|
-
return
|
|
606
|
+
return fs4.statSync(p).isFile();
|
|
561
607
|
} catch {
|
|
562
608
|
return false;
|
|
563
609
|
}
|
|
564
610
|
}
|
|
565
611
|
function isDir(p) {
|
|
566
612
|
try {
|
|
567
|
-
return
|
|
613
|
+
return fs4.statSync(p).isDirectory();
|
|
568
614
|
} catch {
|
|
569
615
|
return false;
|
|
570
616
|
}
|
|
571
617
|
}
|
|
572
618
|
function agentSubprojectRoot(projectRoot) {
|
|
573
619
|
for (const candidate of [
|
|
574
|
-
|
|
575
|
-
|
|
620
|
+
path3.join(projectRoot, "app", "agent"),
|
|
621
|
+
path3.join(projectRoot, "agent")
|
|
576
622
|
]) {
|
|
577
|
-
if (isFile(
|
|
623
|
+
if (isFile(path3.join(candidate, "studio.toml"))) {
|
|
578
624
|
return candidate;
|
|
579
625
|
}
|
|
580
626
|
}
|
|
@@ -582,9 +628,9 @@ function agentSubprojectRoot(projectRoot) {
|
|
|
582
628
|
}
|
|
583
629
|
function projectStudioToml(projectRoot) {
|
|
584
630
|
const candidates = [
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
631
|
+
path3.join(projectRoot, "studio.toml"),
|
|
632
|
+
path3.join(projectRoot, "app", "agent", "studio.toml"),
|
|
633
|
+
path3.join(projectRoot, "agent", "studio.toml")
|
|
588
634
|
];
|
|
589
635
|
return candidates.find(isFile) ?? null;
|
|
590
636
|
}
|
|
@@ -595,14 +641,14 @@ function readStudioToml(projectRoot) {
|
|
|
595
641
|
`no studio.toml at ${projectRoot}, ${projectRoot}/app/agent, or ${projectRoot}/agent`
|
|
596
642
|
);
|
|
597
643
|
}
|
|
598
|
-
return parse(
|
|
644
|
+
return parse(fs4.readFileSync(studioToml, "utf-8"));
|
|
599
645
|
}
|
|
600
646
|
function scanWalletAddress(projectRoot) {
|
|
601
|
-
const walletsDir =
|
|
647
|
+
const walletsDir = path3.join(projectRoot, ".studio", "wallets");
|
|
602
648
|
if (!isDir(walletsDir)) {
|
|
603
649
|
return null;
|
|
604
650
|
}
|
|
605
|
-
for (const child of
|
|
651
|
+
for (const child of fs4.readdirSync(walletsDir).sort()) {
|
|
606
652
|
if (!child.endsWith(".json")) {
|
|
607
653
|
continue;
|
|
608
654
|
}
|
|
@@ -617,13 +663,13 @@ function expandUser(p) {
|
|
|
617
663
|
if (p === "~") {
|
|
618
664
|
return os.homedir();
|
|
619
665
|
}
|
|
620
|
-
if (p.startsWith(`~${
|
|
621
|
-
return
|
|
666
|
+
if (p.startsWith(`~${path3.sep}`) || p.startsWith("~/")) {
|
|
667
|
+
return path3.join(os.homedir(), p.slice(2));
|
|
622
668
|
}
|
|
623
669
|
return p;
|
|
624
670
|
}
|
|
625
671
|
function normalizePath(p) {
|
|
626
|
-
return
|
|
672
|
+
return path3.resolve(expandUser(p));
|
|
627
673
|
}
|
|
628
674
|
function nowIso() {
|
|
629
675
|
const d = /* @__PURE__ */ new Date();
|
|
@@ -644,13 +690,13 @@ function registerProject(projectRootArg2, opts = {}) {
|
|
|
644
690
|
}
|
|
645
691
|
const cfg = readStudioToml(projectRoot);
|
|
646
692
|
const agentRoot2 = agentSubprojectRoot(projectRoot);
|
|
647
|
-
const resolvedName = opts.name ?? (tableOf(cfg, "project").name ||
|
|
693
|
+
const resolvedName = opts.name ?? (tableOf(cfg, "project").name || path3.basename(projectRoot));
|
|
648
694
|
const network = tableOf(cfg, "network").default || "bsc-testnet";
|
|
649
695
|
const walletAddress = scanWalletAddress(agentRoot2);
|
|
650
696
|
const llmProvider = tableOf(cfg, "llm").provider || null;
|
|
651
697
|
const workspaceRoot = findWorkspaceRoot(projectRoot) ?? projectRoot;
|
|
652
|
-
const cloud =
|
|
653
|
-
|
|
698
|
+
const cloud = fs4.existsSync(
|
|
699
|
+
path3.join(workspaceRoot, "agentcore", "agentcore.json")
|
|
654
700
|
) ? "agentcore" : null;
|
|
655
701
|
const entryData = {
|
|
656
702
|
name: resolvedName,
|
|
@@ -731,7 +777,7 @@ function listProjects() {
|
|
|
731
777
|
}
|
|
732
778
|
}
|
|
733
779
|
if (e.cloud === null) {
|
|
734
|
-
if (
|
|
780
|
+
if (fs4.existsSync(path3.join(p, "agentcore", "agentcore.json"))) {
|
|
735
781
|
e.cloud = "agentcore";
|
|
736
782
|
changed = true;
|
|
737
783
|
}
|
|
@@ -1036,8 +1082,8 @@ function cmdRegister(pathArg, name, agentId) {
|
|
|
1036
1082
|
}
|
|
1037
1083
|
|
|
1038
1084
|
// src/cli/audit.ts
|
|
1039
|
-
import * as
|
|
1040
|
-
import * as
|
|
1085
|
+
import * as fs5 from "fs";
|
|
1086
|
+
import * as path4 from "path";
|
|
1041
1087
|
|
|
1042
1088
|
// src/cli/_auditRead.ts
|
|
1043
1089
|
import {
|
|
@@ -1114,17 +1160,17 @@ function parseSince(s) {
|
|
|
1114
1160
|
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}T${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}.000Z`;
|
|
1115
1161
|
}
|
|
1116
1162
|
function resolveProjectRoot(argRoot) {
|
|
1117
|
-
const root = argRoot !== void 0 ?
|
|
1118
|
-
if (
|
|
1163
|
+
const root = argRoot !== void 0 ? path4.resolve(argRoot) : process.cwd();
|
|
1164
|
+
if (fs5.existsSync(path4.join(root, "studio.toml"))) {
|
|
1119
1165
|
return root;
|
|
1120
1166
|
}
|
|
1121
1167
|
let current = root;
|
|
1122
1168
|
for (; ; ) {
|
|
1123
|
-
const parent =
|
|
1169
|
+
const parent = path4.dirname(current);
|
|
1124
1170
|
if (parent === current) {
|
|
1125
1171
|
return null;
|
|
1126
1172
|
}
|
|
1127
|
-
if (
|
|
1173
|
+
if (fs5.existsSync(path4.join(parent, "studio.toml"))) {
|
|
1128
1174
|
return parent;
|
|
1129
1175
|
}
|
|
1130
1176
|
current = parent;
|
|
@@ -1200,18 +1246,18 @@ function cmdShow2(txHash, opts) {
|
|
|
1200
1246
|
}
|
|
1201
1247
|
|
|
1202
1248
|
// src/cli/budget.ts
|
|
1203
|
-
import * as
|
|
1204
|
-
import * as
|
|
1249
|
+
import * as fs7 from "fs";
|
|
1250
|
+
import * as path6 from "path";
|
|
1205
1251
|
import { BudgetPolicy } from "@bnbagent/studio-runtime/pieverse";
|
|
1206
1252
|
import { parse as parse3 } from "smol-toml";
|
|
1207
1253
|
|
|
1208
1254
|
// src/cli/_projectRoot.ts
|
|
1209
|
-
import * as
|
|
1210
|
-
import * as
|
|
1255
|
+
import * as fs6 from "fs";
|
|
1256
|
+
import * as path5 from "path";
|
|
1211
1257
|
function resolveProjectRootArg(argRoot) {
|
|
1212
1258
|
if (argRoot !== void 0) {
|
|
1213
|
-
const root2 =
|
|
1214
|
-
if (!
|
|
1259
|
+
const root2 = path5.resolve(argRoot);
|
|
1260
|
+
if (!fs6.existsSync(path5.join(root2, "studio.toml"))) {
|
|
1215
1261
|
printErr(`error: no studio.toml under --project-root ${root2}`);
|
|
1216
1262
|
return null;
|
|
1217
1263
|
}
|
|
@@ -1486,7 +1532,7 @@ function registerBudget(program) {
|
|
|
1486
1532
|
}
|
|
1487
1533
|
function loadPolicy(root) {
|
|
1488
1534
|
const cfg = parse3(
|
|
1489
|
-
|
|
1535
|
+
fs7.readFileSync(path6.join(root, "studio.toml"), "utf-8")
|
|
1490
1536
|
);
|
|
1491
1537
|
const budget = cfg.budget;
|
|
1492
1538
|
return policyFromToml(
|
|
@@ -1494,9 +1540,9 @@ function loadPolicy(root) {
|
|
|
1494
1540
|
);
|
|
1495
1541
|
}
|
|
1496
1542
|
function writeSection(root, updates) {
|
|
1497
|
-
const tomlPath =
|
|
1498
|
-
const text2 =
|
|
1499
|
-
|
|
1543
|
+
const tomlPath = path6.join(root, "studio.toml");
|
|
1544
|
+
const text2 = fs7.readFileSync(tomlPath, "utf-8");
|
|
1545
|
+
fs7.writeFileSync(tomlPath, updateSection(text2, "budget", updates), "utf-8");
|
|
1500
1546
|
}
|
|
1501
1547
|
function setBudgetEnabled(on) {
|
|
1502
1548
|
return on ? cmdEnable({}) : cmdDisable(void 0);
|
|
@@ -1543,16 +1589,16 @@ function cmdShow3(projectRoot) {
|
|
|
1543
1589
|
return 0;
|
|
1544
1590
|
}
|
|
1545
1591
|
function printSpendLedger(root) {
|
|
1546
|
-
const ledgerPath =
|
|
1592
|
+
const ledgerPath = path6.join(root, ".studio", "spend-ledger.json");
|
|
1547
1593
|
printOut("");
|
|
1548
1594
|
printOut("spend ledger (.studio/spend-ledger.json):");
|
|
1549
|
-
if (!
|
|
1595
|
+
if (!fs7.existsSync(ledgerPath)) {
|
|
1550
1596
|
printOut(" (no ledger yet)");
|
|
1551
1597
|
return;
|
|
1552
1598
|
}
|
|
1553
1599
|
let entries;
|
|
1554
1600
|
try {
|
|
1555
|
-
const raw = JSON.parse(
|
|
1601
|
+
const raw = JSON.parse(fs7.readFileSync(ledgerPath, "utf-8"));
|
|
1556
1602
|
entries = Array.isArray(raw.entries) ? raw.entries : [];
|
|
1557
1603
|
} catch (exc) {
|
|
1558
1604
|
printOut(
|
|
@@ -1643,8 +1689,8 @@ function cmdDisable(projectRoot) {
|
|
|
1643
1689
|
}
|
|
1644
1690
|
|
|
1645
1691
|
// src/cli/bundle.ts
|
|
1646
|
-
import * as
|
|
1647
|
-
import * as
|
|
1692
|
+
import * as fs9 from "fs";
|
|
1693
|
+
import * as path8 from "path";
|
|
1648
1694
|
import {
|
|
1649
1695
|
envLocalPath as envLocalPath4,
|
|
1650
1696
|
findSubProjectRoot as findSubProjectRoot2,
|
|
@@ -1655,29 +1701,29 @@ import * as tar from "tar";
|
|
|
1655
1701
|
|
|
1656
1702
|
// src/cli/_vendorTarball.ts
|
|
1657
1703
|
import * as crypto from "crypto";
|
|
1658
|
-
import * as
|
|
1659
|
-
import * as
|
|
1660
|
-
import { fileURLToPath } from "url";
|
|
1704
|
+
import * as fs8 from "fs";
|
|
1705
|
+
import * as path7 from "path";
|
|
1706
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1661
1707
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
1662
1708
|
var VENDORED_PACKAGES = [
|
|
1663
1709
|
"@bnbagent/sdk",
|
|
1664
1710
|
"@bnbagent/studio-runtime"
|
|
1665
1711
|
];
|
|
1666
1712
|
function installedSourceRoot(pkgName) {
|
|
1667
|
-
let dir =
|
|
1713
|
+
let dir = path7.dirname(fileURLToPath2(import.meta.url));
|
|
1668
1714
|
for (; ; ) {
|
|
1669
|
-
const candidate =
|
|
1670
|
-
const packageJson =
|
|
1671
|
-
if (
|
|
1715
|
+
const candidate = path7.join(dir, "node_modules", ...pkgName.split("/"));
|
|
1716
|
+
const packageJson = path7.join(candidate, "package.json");
|
|
1717
|
+
if (fs8.existsSync(packageJson)) {
|
|
1672
1718
|
try {
|
|
1673
|
-
const real =
|
|
1674
|
-
const pkg = JSON.parse(
|
|
1675
|
-
return typeof pkg.version === "string" ? { root:
|
|
1719
|
+
const real = fs8.realpathSync(packageJson);
|
|
1720
|
+
const pkg = JSON.parse(fs8.readFileSync(real, "utf-8"));
|
|
1721
|
+
return typeof pkg.version === "string" ? { root: path7.dirname(real), version: pkg.version } : null;
|
|
1676
1722
|
} catch {
|
|
1677
1723
|
return null;
|
|
1678
1724
|
}
|
|
1679
1725
|
}
|
|
1680
|
-
const parent =
|
|
1726
|
+
const parent = path7.dirname(dir);
|
|
1681
1727
|
if (parent === dir) {
|
|
1682
1728
|
return null;
|
|
1683
1729
|
}
|
|
@@ -1690,7 +1736,7 @@ function localSourceRoot(pkgName) {
|
|
|
1690
1736
|
if (installed === null) {
|
|
1691
1737
|
return null;
|
|
1692
1738
|
}
|
|
1693
|
-
if (installed.root.split(
|
|
1739
|
+
if (installed.root.split(path7.sep).includes("node_modules")) {
|
|
1694
1740
|
return null;
|
|
1695
1741
|
}
|
|
1696
1742
|
return installed;
|
|
@@ -1706,17 +1752,17 @@ async function publishedOnRegistry(name, version) {
|
|
|
1706
1752
|
function contentTag(sourceRoot) {
|
|
1707
1753
|
const h = crypto.createHash("sha256");
|
|
1708
1754
|
const files = [];
|
|
1709
|
-
const srcDir =
|
|
1755
|
+
const srcDir = path7.join(sourceRoot, "src");
|
|
1710
1756
|
const walk = (dir) => {
|
|
1711
1757
|
let names;
|
|
1712
1758
|
try {
|
|
1713
|
-
names =
|
|
1759
|
+
names = fs8.readdirSync(dir).sort();
|
|
1714
1760
|
} catch {
|
|
1715
1761
|
return;
|
|
1716
1762
|
}
|
|
1717
1763
|
for (const name of names) {
|
|
1718
|
-
const full =
|
|
1719
|
-
const st =
|
|
1764
|
+
const full = path7.join(dir, name);
|
|
1765
|
+
const st = fs8.statSync(full);
|
|
1720
1766
|
if (st.isDirectory()) {
|
|
1721
1767
|
walk(full);
|
|
1722
1768
|
} else if (st.isFile()) {
|
|
@@ -1725,20 +1771,20 @@ function contentTag(sourceRoot) {
|
|
|
1725
1771
|
}
|
|
1726
1772
|
};
|
|
1727
1773
|
walk(srcDir);
|
|
1728
|
-
const pkgJson =
|
|
1729
|
-
if (
|
|
1774
|
+
const pkgJson = path7.join(sourceRoot, "package.json");
|
|
1775
|
+
if (fs8.existsSync(pkgJson)) {
|
|
1730
1776
|
files.push(pkgJson);
|
|
1731
1777
|
}
|
|
1732
1778
|
for (const f of files) {
|
|
1733
|
-
h.update(
|
|
1734
|
-
h.update(
|
|
1779
|
+
h.update(path7.relative(sourceRoot, f));
|
|
1780
|
+
h.update(fs8.readFileSync(f));
|
|
1735
1781
|
}
|
|
1736
1782
|
return h.digest("hex").slice(0, 8);
|
|
1737
1783
|
}
|
|
1738
1784
|
function readManifest(vendorDir) {
|
|
1739
1785
|
try {
|
|
1740
1786
|
const data = JSON.parse(
|
|
1741
|
-
|
|
1787
|
+
fs8.readFileSync(path7.join(vendorDir, MANIFEST_NAME), "utf-8")
|
|
1742
1788
|
);
|
|
1743
1789
|
return data !== null && typeof data === "object" ? data : {};
|
|
1744
1790
|
} catch {
|
|
@@ -1746,8 +1792,8 @@ function readManifest(vendorDir) {
|
|
|
1746
1792
|
}
|
|
1747
1793
|
}
|
|
1748
1794
|
function writeManifest(vendorDir, manifest) {
|
|
1749
|
-
|
|
1750
|
-
|
|
1795
|
+
fs8.writeFileSync(
|
|
1796
|
+
path7.join(vendorDir, MANIFEST_NAME),
|
|
1751
1797
|
`${JSON.stringify(manifest, null, 2)}
|
|
1752
1798
|
`
|
|
1753
1799
|
);
|
|
@@ -1756,26 +1802,26 @@ function tarballPrefix(pkgName) {
|
|
|
1756
1802
|
return `${pkgName.replace(/^@/, "").replace(/\//g, "-")}-`;
|
|
1757
1803
|
}
|
|
1758
1804
|
function sha256File(p) {
|
|
1759
|
-
return crypto.createHash("sha256").update(
|
|
1805
|
+
return crypto.createHash("sha256").update(fs8.readFileSync(p)).digest("hex");
|
|
1760
1806
|
}
|
|
1761
1807
|
function rewriteDepToTarball(agentDir, pkgName, tarballName) {
|
|
1762
|
-
const pkgJsonPath =
|
|
1763
|
-
if (!
|
|
1808
|
+
const pkgJsonPath = path7.join(agentDir, "package.json");
|
|
1809
|
+
if (!fs8.existsSync(pkgJsonPath)) {
|
|
1764
1810
|
return;
|
|
1765
1811
|
}
|
|
1766
|
-
const pkg = JSON.parse(
|
|
1812
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
|
|
1767
1813
|
if (!pkg.dependencies || !(pkgName in pkg.dependencies)) {
|
|
1768
1814
|
return;
|
|
1769
1815
|
}
|
|
1770
1816
|
pkg.dependencies[pkgName] = `file:vendor/${tarballName}`;
|
|
1771
|
-
|
|
1817
|
+
fs8.writeFileSync(pkgJsonPath, `${JSON.stringify(pkg, null, 2)}
|
|
1772
1818
|
`);
|
|
1773
1819
|
}
|
|
1774
1820
|
async function vendorLocalTarballs(agentDir, opts = {}) {
|
|
1775
1821
|
const packages = opts.packages ?? VENDORED_PACKAGES;
|
|
1776
1822
|
const resolveLocal = opts.resolveLocal ?? localSourceRoot;
|
|
1777
1823
|
const required = new Set(opts.requiredPackages ?? []);
|
|
1778
|
-
const vendorDir =
|
|
1824
|
+
const vendorDir = path7.join(agentDir, "vendor");
|
|
1779
1825
|
const vendored = [];
|
|
1780
1826
|
for (const pkgName of packages) {
|
|
1781
1827
|
const local = resolveLocal(pkgName);
|
|
@@ -1785,19 +1831,19 @@ async function vendorLocalTarballs(agentDir, opts = {}) {
|
|
|
1785
1831
|
if (!opts.force && await publishedOnRegistry(pkgName, local.version)) {
|
|
1786
1832
|
continue;
|
|
1787
1833
|
}
|
|
1788
|
-
|
|
1834
|
+
fs8.mkdirSync(vendorDir, { recursive: true });
|
|
1789
1835
|
const manifest = readManifest(vendorDir);
|
|
1790
1836
|
const tag = contentTag(local.root);
|
|
1791
1837
|
const prior = manifest[pkgName];
|
|
1792
|
-
if (prior !== void 0 && prior.sourceTag === tag &&
|
|
1838
|
+
if (prior !== void 0 && prior.sourceTag === tag && fs8.existsSync(path7.join(vendorDir, prior.tarball))) {
|
|
1793
1839
|
rewriteDepToTarball(agentDir, pkgName, prior.tarball);
|
|
1794
1840
|
vendored.push(pkgName);
|
|
1795
1841
|
continue;
|
|
1796
1842
|
}
|
|
1797
1843
|
const prefix = tarballPrefix(pkgName);
|
|
1798
|
-
for (const name of
|
|
1844
|
+
for (const name of fs8.readdirSync(vendorDir)) {
|
|
1799
1845
|
if (name.startsWith(prefix) && name.endsWith(".tgz")) {
|
|
1800
|
-
|
|
1846
|
+
fs8.rmSync(path7.join(vendorDir, name), { force: true });
|
|
1801
1847
|
}
|
|
1802
1848
|
}
|
|
1803
1849
|
const result = await runCapture(
|
|
@@ -1816,8 +1862,8 @@ ${result.stderr.trim()}` : ""}`;
|
|
|
1816
1862
|
}
|
|
1817
1863
|
const lines = result.stdout.split("\n").filter((l) => l.trim());
|
|
1818
1864
|
const packed = lines[lines.length - 1]?.trim();
|
|
1819
|
-
const tarballPath = packed &&
|
|
1820
|
-
if (!tarballPath || !
|
|
1865
|
+
const tarballPath = packed && fs8.existsSync(packed) ? packed : packed ? path7.join(vendorDir, path7.basename(packed)) : null;
|
|
1866
|
+
if (!tarballPath || !fs8.existsSync(tarballPath)) {
|
|
1821
1867
|
const message = `pnpm pack for ${pkgName} reported no tarball`;
|
|
1822
1868
|
if (required.has(pkgName)) {
|
|
1823
1869
|
throw new Error(message);
|
|
@@ -1825,7 +1871,7 @@ ${result.stderr.trim()}` : ""}`;
|
|
|
1825
1871
|
printErr(`warning: ${message}; skipping.`);
|
|
1826
1872
|
continue;
|
|
1827
1873
|
}
|
|
1828
|
-
const tarballName =
|
|
1874
|
+
const tarballName = path7.basename(tarballPath);
|
|
1829
1875
|
manifest[pkgName] = {
|
|
1830
1876
|
version: local.version,
|
|
1831
1877
|
sha256: sha256File(tarballPath),
|
|
@@ -1860,20 +1906,20 @@ async function provisionInstall(workspaceRoot) {
|
|
|
1860
1906
|
return true;
|
|
1861
1907
|
}
|
|
1862
1908
|
function applyWorkspaceVendorOverrides(workspaceRoot, agentDir) {
|
|
1863
|
-
const manifest = readManifest(
|
|
1909
|
+
const manifest = readManifest(path7.join(agentDir, "vendor"));
|
|
1864
1910
|
const entries = Object.entries(manifest);
|
|
1865
1911
|
if (entries.length === 0) {
|
|
1866
1912
|
return;
|
|
1867
1913
|
}
|
|
1868
|
-
const workspacePath =
|
|
1914
|
+
const workspacePath = path7.join(workspaceRoot, "pnpm-workspace.yaml");
|
|
1869
1915
|
const workspaceDoc = parseYaml(
|
|
1870
|
-
|
|
1916
|
+
fs8.existsSync(workspacePath) ? fs8.readFileSync(workspacePath, "utf-8") : "packages:\n - app/agent\n"
|
|
1871
1917
|
);
|
|
1872
1918
|
const workspace = workspaceDoc ?? {};
|
|
1873
1919
|
const existingOverrides = workspace.overrides !== null && typeof workspace.overrides === "object" && !Array.isArray(workspace.overrides) ? workspace.overrides : {};
|
|
1874
|
-
const pkgPath =
|
|
1875
|
-
const pkg = JSON.parse(
|
|
1876
|
-
const relVendor =
|
|
1920
|
+
const pkgPath = path7.join(workspaceRoot, "package.json");
|
|
1921
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
1922
|
+
const relVendor = path7.relative(workspaceRoot, path7.join(agentDir, "vendor")).split(path7.sep).join("/");
|
|
1877
1923
|
const overrides = {
|
|
1878
1924
|
...existingOverrides,
|
|
1879
1925
|
...pkg.pnpm?.overrides ?? {}
|
|
@@ -1882,10 +1928,10 @@ function applyWorkspaceVendorOverrides(workspaceRoot, agentDir) {
|
|
|
1882
1928
|
overrides[name] = `file:${relVendor}/${entry.tarball}`;
|
|
1883
1929
|
}
|
|
1884
1930
|
workspace.overrides = overrides;
|
|
1885
|
-
|
|
1886
|
-
const agentWorkspacePath =
|
|
1931
|
+
fs8.writeFileSync(workspacePath, stringifyYaml(workspace));
|
|
1932
|
+
const agentWorkspacePath = path7.join(agentDir, "pnpm-workspace.yaml");
|
|
1887
1933
|
const agentWorkspaceDoc = parseYaml(
|
|
1888
|
-
|
|
1934
|
+
fs8.existsSync(agentWorkspacePath) ? fs8.readFileSync(agentWorkspacePath, "utf-8") : "packages:\n - .\nallowBuilds:\n esbuild: true\n"
|
|
1889
1935
|
);
|
|
1890
1936
|
const agentWorkspace = agentWorkspaceDoc ?? {};
|
|
1891
1937
|
const agentOverrides = agentWorkspace.overrides !== null && typeof agentWorkspace.overrides === "object" && !Array.isArray(agentWorkspace.overrides) ? agentWorkspace.overrides : {};
|
|
@@ -1893,9 +1939,9 @@ function applyWorkspaceVendorOverrides(workspaceRoot, agentDir) {
|
|
|
1893
1939
|
agentOverrides[name] = `file:vendor/${entry.tarball}`;
|
|
1894
1940
|
}
|
|
1895
1941
|
agentWorkspace.overrides = agentOverrides;
|
|
1896
|
-
|
|
1942
|
+
fs8.writeFileSync(agentWorkspacePath, stringifyYaml(agentWorkspace));
|
|
1897
1943
|
pkg.pnpm = { ...pkg.pnpm ?? {}, overrides };
|
|
1898
|
-
|
|
1944
|
+
fs8.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
1899
1945
|
`);
|
|
1900
1946
|
}
|
|
1901
1947
|
|
|
@@ -1930,7 +1976,7 @@ function registerBundle(program) {
|
|
|
1930
1976
|
act(async (opts) => {
|
|
1931
1977
|
try {
|
|
1932
1978
|
const result = await createBundle(opts);
|
|
1933
|
-
const sizeKb =
|
|
1979
|
+
const sizeKb = fs9.statSync(result.archivePath).size / 1024;
|
|
1934
1980
|
printOut("");
|
|
1935
1981
|
printOut(
|
|
1936
1982
|
`\u2713 bundle ready: ${result.archivePath} (${sizeKb.toFixed(1)} KB)`
|
|
@@ -1952,7 +1998,7 @@ function registerBundle(program) {
|
|
|
1952
1998
|
);
|
|
1953
1999
|
}
|
|
1954
2000
|
async function createBundle(opts = {}) {
|
|
1955
|
-
const start =
|
|
2001
|
+
const start = path8.resolve(opts.projectRoot ?? process.cwd());
|
|
1956
2002
|
const agentRoot2 = resolveAgentRoot(start);
|
|
1957
2003
|
if (agentRoot2 === null) {
|
|
1958
2004
|
throw new Error(
|
|
@@ -1962,24 +2008,24 @@ async function createBundle(opts = {}) {
|
|
|
1962
2008
|
const workspaceRoot = trueWorkspaceRoot(agentRoot2);
|
|
1963
2009
|
const projectName2 = readProjectName(agentRoot2);
|
|
1964
2010
|
const safeName = projectName2.replace(/[^A-Za-z0-9._-]+/g, "-");
|
|
1965
|
-
const outputDir =
|
|
1966
|
-
opts.output ??
|
|
2011
|
+
const outputDir = path8.resolve(
|
|
2012
|
+
opts.output ?? path8.join(workspaceRoot, "dist")
|
|
1967
2013
|
);
|
|
1968
|
-
|
|
2014
|
+
fs9.mkdirSync(outputDir, { recursive: true });
|
|
1969
2015
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1970
2016
|
const archiveBase = `${safeName}-bundle-${stamp}`;
|
|
1971
|
-
const stagingRoot =
|
|
1972
|
-
const stagedWorkspace =
|
|
2017
|
+
const stagingRoot = path8.join(outputDir, `.${archiveBase}.staging`);
|
|
2018
|
+
const stagedWorkspace = path8.join(stagingRoot, safeName);
|
|
1973
2019
|
if (stagedWorkspace === stagingRoot || !inside(stagedWorkspace, stagingRoot)) {
|
|
1974
2020
|
throw new Error(
|
|
1975
2021
|
`unsafe project name ${JSON.stringify(projectName2)} escapes the bundle staging directory`
|
|
1976
2022
|
);
|
|
1977
2023
|
}
|
|
1978
|
-
const agentRel =
|
|
1979
|
-
const stagedAgent =
|
|
1980
|
-
const archivePath =
|
|
1981
|
-
|
|
1982
|
-
|
|
2024
|
+
const agentRel = path8.relative(workspaceRoot, agentRoot2);
|
|
2025
|
+
const stagedAgent = path8.join(stagedWorkspace, agentRel);
|
|
2026
|
+
const archivePath = path8.join(outputDir, `${archiveBase}.tar.gz`);
|
|
2027
|
+
fs9.rmSync(stagingRoot, { recursive: true, force: true });
|
|
2028
|
+
fs9.mkdirSync(stagingRoot, { recursive: true });
|
|
1983
2029
|
try {
|
|
1984
2030
|
printOut(`\u2192 Staging seller workspace at ${stagedWorkspace}\u2026`);
|
|
1985
2031
|
copyWorkspace(workspaceRoot, stagedWorkspace, outputDir);
|
|
@@ -2018,26 +2064,26 @@ async function createBundle(opts = {}) {
|
|
|
2018
2064
|
[safeName]
|
|
2019
2065
|
);
|
|
2020
2066
|
} finally {
|
|
2021
|
-
|
|
2067
|
+
fs9.rmSync(stagingRoot, { recursive: true, force: true });
|
|
2022
2068
|
}
|
|
2023
2069
|
return { archivePath, projectName: projectName2 };
|
|
2024
2070
|
}
|
|
2025
2071
|
function resolveAgentRoot(start) {
|
|
2026
2072
|
const found = findSubProjectRoot2("agent", start);
|
|
2027
|
-
if (found !== null &&
|
|
2073
|
+
if (found !== null && fs9.existsSync(path8.join(found, "studio.toml"))) {
|
|
2028
2074
|
return found;
|
|
2029
2075
|
}
|
|
2030
|
-
return
|
|
2076
|
+
return fs9.existsSync(path8.join(start, "studio.toml")) ? start : null;
|
|
2031
2077
|
}
|
|
2032
2078
|
function trueWorkspaceRoot(agentRoot2) {
|
|
2033
2079
|
const found = findWorkspaceRoot2(agentRoot2);
|
|
2034
2080
|
if (found === null) {
|
|
2035
2081
|
return agentRoot2;
|
|
2036
2082
|
}
|
|
2037
|
-
return
|
|
2083
|
+
return path8.basename(found) === "app" ? path8.dirname(found) : found;
|
|
2038
2084
|
}
|
|
2039
2085
|
function readProjectName(agentRoot2) {
|
|
2040
|
-
const cfg = loadStudioToml2(
|
|
2086
|
+
const cfg = loadStudioToml2(path8.join(agentRoot2, "studio.toml"));
|
|
2041
2087
|
const project = cfg.project;
|
|
2042
2088
|
const name = project !== null && typeof project === "object" && !Array.isArray(project) ? project.name : null;
|
|
2043
2089
|
if (!name) {
|
|
@@ -2050,58 +2096,58 @@ function excludedName(name) {
|
|
|
2050
2096
|
return EXCLUDED_NAMES.has(lowerName) || CREDENTIAL_FILE_NAMES.has(lowerName) || lowerName.startsWith(".env") || lowerName.endsWith(".egg-info") || lowerName.startsWith(".venv-");
|
|
2051
2097
|
}
|
|
2052
2098
|
function inside(child, parent) {
|
|
2053
|
-
const rel =
|
|
2054
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
2099
|
+
const rel = path8.relative(parent, child);
|
|
2100
|
+
return rel === "" || !rel.startsWith("..") && !path8.isAbsolute(rel);
|
|
2055
2101
|
}
|
|
2056
2102
|
function copyWorkspace(sourceRoot, destinationRoot, outputDir) {
|
|
2057
|
-
const source =
|
|
2058
|
-
const excludedOutput = outputDir ?
|
|
2103
|
+
const source = path8.resolve(sourceRoot);
|
|
2104
|
+
const excludedOutput = outputDir ? path8.resolve(outputDir) : null;
|
|
2059
2105
|
const copy = (src, dst) => {
|
|
2060
2106
|
if (excludedOutput !== null && inside(src, excludedOutput)) {
|
|
2061
2107
|
return;
|
|
2062
2108
|
}
|
|
2063
|
-
const name =
|
|
2109
|
+
const name = path8.basename(src);
|
|
2064
2110
|
if (src !== source && excludedName(name)) {
|
|
2065
2111
|
return;
|
|
2066
2112
|
}
|
|
2067
|
-
const stat =
|
|
2113
|
+
const stat = fs9.lstatSync(src);
|
|
2068
2114
|
if (stat.isSymbolicLink()) {
|
|
2069
|
-
const link =
|
|
2070
|
-
const lexicalTarget =
|
|
2115
|
+
const link = fs9.readlinkSync(src);
|
|
2116
|
+
const lexicalTarget = path8.resolve(path8.dirname(src), link);
|
|
2071
2117
|
let resolvedTarget = lexicalTarget;
|
|
2072
2118
|
try {
|
|
2073
|
-
resolvedTarget =
|
|
2119
|
+
resolvedTarget = fs9.realpathSync(lexicalTarget);
|
|
2074
2120
|
} catch {
|
|
2075
2121
|
}
|
|
2076
2122
|
if (!inside(resolvedTarget, source)) {
|
|
2077
2123
|
throw new Error(
|
|
2078
|
-
`refusing to bundle symlink ${
|
|
2124
|
+
`refusing to bundle symlink ${path8.relative(source, src)} \u2192 ${link}: its target escapes the project tree (possible secret leak).`
|
|
2079
2125
|
);
|
|
2080
2126
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2127
|
+
fs9.mkdirSync(path8.dirname(dst), { recursive: true });
|
|
2128
|
+
fs9.symlinkSync(link, dst);
|
|
2083
2129
|
return;
|
|
2084
2130
|
}
|
|
2085
2131
|
if (stat.isDirectory()) {
|
|
2086
|
-
|
|
2087
|
-
for (const child of
|
|
2088
|
-
copy(
|
|
2132
|
+
fs9.mkdirSync(dst, { recursive: true, mode: stat.mode & 511 });
|
|
2133
|
+
for (const child of fs9.readdirSync(src).sort()) {
|
|
2134
|
+
copy(path8.join(src, child), path8.join(dst, child));
|
|
2089
2135
|
}
|
|
2090
2136
|
return;
|
|
2091
2137
|
}
|
|
2092
2138
|
if (stat.isFile()) {
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2139
|
+
fs9.mkdirSync(path8.dirname(dst), { recursive: true });
|
|
2140
|
+
fs9.copyFileSync(src, dst);
|
|
2141
|
+
fs9.chmodSync(dst, stat.mode & 511);
|
|
2096
2142
|
}
|
|
2097
2143
|
};
|
|
2098
2144
|
copy(source, destinationRoot);
|
|
2099
2145
|
}
|
|
2100
2146
|
function writeEnvExample(agentRoot2, stagedWorkspace) {
|
|
2101
2147
|
const sourceEnv = envLocalPath4(agentRoot2);
|
|
2102
|
-
const targetDir =
|
|
2103
|
-
const target =
|
|
2104
|
-
|
|
2148
|
+
const targetDir = path8.join(stagedWorkspace, ".studio");
|
|
2149
|
+
const target = path8.join(targetDir, ".env.local.example");
|
|
2150
|
+
fs9.mkdirSync(targetDir, { recursive: true, mode: 448 });
|
|
2105
2151
|
const header = [
|
|
2106
2152
|
"# Copy to .studio/.env.local and fill in values.",
|
|
2107
2153
|
"# Generated by `bag bundle`; secret values were stripped.",
|
|
@@ -2109,7 +2155,7 @@ function writeEnvExample(agentRoot2, stagedWorkspace) {
|
|
|
2109
2155
|
];
|
|
2110
2156
|
let lines;
|
|
2111
2157
|
try {
|
|
2112
|
-
lines =
|
|
2158
|
+
lines = fs9.readFileSync(sourceEnv, "utf-8").split(/\r?\n/);
|
|
2113
2159
|
} catch {
|
|
2114
2160
|
lines = [
|
|
2115
2161
|
"WALLET_PASSWORD=",
|
|
@@ -2127,29 +2173,29 @@ function writeEnvExample(agentRoot2, stagedWorkspace) {
|
|
|
2127
2173
|
const match = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line);
|
|
2128
2174
|
return match ? `${match[1]}=` : "# omitted unrecognized dotenv entry";
|
|
2129
2175
|
});
|
|
2130
|
-
|
|
2176
|
+
fs9.writeFileSync(target, `${[...header, ...stripped].join("\n")}
|
|
2131
2177
|
`, {
|
|
2132
2178
|
mode: 384
|
|
2133
2179
|
});
|
|
2134
2180
|
}
|
|
2135
2181
|
function findStagedLeak(stagedWorkspace) {
|
|
2136
|
-
const root =
|
|
2182
|
+
const root = path8.resolve(stagedWorkspace);
|
|
2137
2183
|
const walk = (dir) => {
|
|
2138
|
-
for (const name of
|
|
2139
|
-
const full =
|
|
2140
|
-
const rel =
|
|
2141
|
-
const stat =
|
|
2184
|
+
for (const name of fs9.readdirSync(dir).sort()) {
|
|
2185
|
+
const full = path8.join(dir, name);
|
|
2186
|
+
const rel = path8.relative(root, full);
|
|
2187
|
+
const stat = fs9.lstatSync(full);
|
|
2142
2188
|
const lowerName = name.toLowerCase();
|
|
2143
2189
|
if (stat.isSymbolicLink()) {
|
|
2144
|
-
const link =
|
|
2145
|
-
const target =
|
|
2190
|
+
const link = fs9.readlinkSync(full);
|
|
2191
|
+
const target = path8.resolve(path8.dirname(full), link);
|
|
2146
2192
|
if (!inside(target, root)) {
|
|
2147
2193
|
return `escaping symlink ${rel} \u2192 ${link}`;
|
|
2148
2194
|
}
|
|
2149
2195
|
continue;
|
|
2150
2196
|
}
|
|
2151
2197
|
if (stat.isDirectory()) {
|
|
2152
|
-
if (lowerName === "wallets" &&
|
|
2198
|
+
if (lowerName === "wallets" && path8.basename(path8.dirname(full)).toLowerCase() === ".studio") {
|
|
2153
2199
|
return `wallet directory ${rel}`;
|
|
2154
2200
|
}
|
|
2155
2201
|
const nested = walk(full);
|
|
@@ -2167,7 +2213,7 @@ function findStagedLeak(stagedWorkspace) {
|
|
|
2167
2213
|
"# omitted source comment",
|
|
2168
2214
|
"# omitted unrecognized dotenv entry"
|
|
2169
2215
|
]);
|
|
2170
|
-
const unsafeExample =
|
|
2216
|
+
const unsafeExample = fs9.readFileSync(full, "utf-8").split(/\r?\n/u).some((line) => {
|
|
2171
2217
|
if (!line.trim() || safeFixedLines.has(line)) return false;
|
|
2172
2218
|
return !/^#?\s*[A-Za-z_][A-Za-z0-9_]*=$/u.test(line);
|
|
2173
2219
|
});
|
|
@@ -2218,12 +2264,12 @@ function writeInstallMd(stagedWorkspace, projectName2) {
|
|
|
2218
2264
|
"- `node_modules/`, build outputs, caches, and repository history",
|
|
2219
2265
|
""
|
|
2220
2266
|
];
|
|
2221
|
-
|
|
2267
|
+
fs9.writeFileSync(path8.join(stagedWorkspace, "INSTALL.md"), lines.join("\n"));
|
|
2222
2268
|
}
|
|
2223
2269
|
|
|
2224
2270
|
// src/cli/config.ts
|
|
2225
|
-
import * as
|
|
2226
|
-
import * as
|
|
2271
|
+
import * as fs10 from "fs";
|
|
2272
|
+
import * as path9 from "path";
|
|
2227
2273
|
import { NegotiationHandler } from "@bnbagent/sdk/erc8183";
|
|
2228
2274
|
import { Option } from "commander";
|
|
2229
2275
|
import { parse as parse4 } from "smol-toml";
|
|
@@ -2489,8 +2535,8 @@ function cmdShow4(asJson, projectRoot) {
|
|
|
2489
2535
|
if (root === null) {
|
|
2490
2536
|
return 2;
|
|
2491
2537
|
}
|
|
2492
|
-
const tomlPath =
|
|
2493
|
-
const text2 =
|
|
2538
|
+
const tomlPath = path9.join(root, "studio.toml");
|
|
2539
|
+
const text2 = fs10.readFileSync(tomlPath, "utf-8");
|
|
2494
2540
|
if (asJson) {
|
|
2495
2541
|
printOut(sortedJson(parse4(text2)));
|
|
2496
2542
|
} else {
|
|
@@ -2506,7 +2552,7 @@ function cmdGet(key, projectRoot) {
|
|
|
2506
2552
|
if (root === null) {
|
|
2507
2553
|
return 2;
|
|
2508
2554
|
}
|
|
2509
|
-
const doc = parse4(
|
|
2555
|
+
const doc = parse4(fs10.readFileSync(path9.join(root, "studio.toml"), "utf-8"));
|
|
2510
2556
|
let val;
|
|
2511
2557
|
try {
|
|
2512
2558
|
val = navigate(doc, splitKey(key));
|
|
@@ -2528,8 +2574,8 @@ async function cmdSet(key, rawValue, typeFlag, projectRoot) {
|
|
|
2528
2574
|
if (root === null) {
|
|
2529
2575
|
return 2;
|
|
2530
2576
|
}
|
|
2531
|
-
const tomlPath =
|
|
2532
|
-
const text2 =
|
|
2577
|
+
const tomlPath = path9.join(root, "studio.toml");
|
|
2578
|
+
const text2 = fs10.readFileSync(tomlPath, "utf-8");
|
|
2533
2579
|
let parts;
|
|
2534
2580
|
try {
|
|
2535
2581
|
parts = splitKey(key);
|
|
@@ -2550,7 +2596,7 @@ async function cmdSet(key, rawValue, typeFlag, projectRoot) {
|
|
|
2550
2596
|
return 2;
|
|
2551
2597
|
}
|
|
2552
2598
|
const updatedText = setDottedKey(text2, parts, value);
|
|
2553
|
-
|
|
2599
|
+
fs10.writeFileSync(tomlPath, updatedText, "utf-8");
|
|
2554
2600
|
printOut(`set ${key} = ${JSON.stringify(plainValue(value))}`);
|
|
2555
2601
|
if (parts.length === 3 && parts[0] === "payments" && parts[1] === "erc8183" && parts[2] === "price") {
|
|
2556
2602
|
const updated = parse4(updatedText);
|
|
@@ -2623,7 +2669,7 @@ function cmdListKeys(projectRoot) {
|
|
|
2623
2669
|
if (root === null) {
|
|
2624
2670
|
return 2;
|
|
2625
2671
|
}
|
|
2626
|
-
const doc = parse4(
|
|
2672
|
+
const doc = parse4(fs10.readFileSync(path9.join(root, "studio.toml"), "utf-8"));
|
|
2627
2673
|
const leaves = iterLeaves(doc, []);
|
|
2628
2674
|
leaves.sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
|
|
2629
2675
|
for (const [k, v] of leaves) {
|
|
@@ -2645,8 +2691,8 @@ import { pieverseKeyHash as pieverseKeyHash3 } from "@bnbagent/studio-runtime/ll
|
|
|
2645
2691
|
import { Option as Option4 } from "commander";
|
|
2646
2692
|
|
|
2647
2693
|
// src/cli/_agentcoreAccess.ts
|
|
2648
|
-
import * as
|
|
2649
|
-
import * as
|
|
2694
|
+
import * as fs11 from "fs";
|
|
2695
|
+
import * as path10 from "path";
|
|
2650
2696
|
import {
|
|
2651
2697
|
envLocalPath as envLocalPath5,
|
|
2652
2698
|
findWorkspaceRoot as findWorkspaceRoot3,
|
|
@@ -2655,7 +2701,7 @@ import {
|
|
|
2655
2701
|
var GUIDE_URL = "https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/agentcore-a2a-access.md";
|
|
2656
2702
|
function isFile2(p) {
|
|
2657
2703
|
try {
|
|
2658
|
-
return
|
|
2704
|
+
return fs11.statSync(p).isFile();
|
|
2659
2705
|
} catch {
|
|
2660
2706
|
return false;
|
|
2661
2707
|
}
|
|
@@ -2670,13 +2716,13 @@ function envValue(entries, key) {
|
|
|
2670
2716
|
return null;
|
|
2671
2717
|
}
|
|
2672
2718
|
function descriptorEnv(workspaceRoot) {
|
|
2673
|
-
const descriptor =
|
|
2719
|
+
const descriptor = path10.join(workspaceRoot, "agentcore", "agentcore.json");
|
|
2674
2720
|
if (!isFile2(descriptor)) {
|
|
2675
2721
|
return [];
|
|
2676
2722
|
}
|
|
2677
2723
|
let data;
|
|
2678
2724
|
try {
|
|
2679
|
-
data = JSON.parse(
|
|
2725
|
+
data = JSON.parse(fs11.readFileSync(descriptor, "utf-8"));
|
|
2680
2726
|
} catch {
|
|
2681
2727
|
return [];
|
|
2682
2728
|
}
|
|
@@ -2695,8 +2741,8 @@ function descriptorEnv(workspaceRoot) {
|
|
|
2695
2741
|
return Array.isArray(env) ? env : [];
|
|
2696
2742
|
}
|
|
2697
2743
|
function agentcoreProjectRoot(workspaceRoot) {
|
|
2698
|
-
for (const candidate of [
|
|
2699
|
-
if (isFile2(
|
|
2744
|
+
for (const candidate of [path10.dirname(workspaceRoot), workspaceRoot]) {
|
|
2745
|
+
if (isFile2(path10.join(candidate, "agentcore", "agentcore.json"))) {
|
|
2700
2746
|
return candidate;
|
|
2701
2747
|
}
|
|
2702
2748
|
}
|
|
@@ -2708,7 +2754,7 @@ function dotenvValue(filePath, key) {
|
|
|
2708
2754
|
}
|
|
2709
2755
|
let lines;
|
|
2710
2756
|
try {
|
|
2711
|
-
lines =
|
|
2757
|
+
lines = fs11.readFileSync(filePath, "utf-8").split(/\r?\n/);
|
|
2712
2758
|
} catch {
|
|
2713
2759
|
return null;
|
|
2714
2760
|
}
|
|
@@ -2741,7 +2787,7 @@ function oauthFacts(workspaceRoot, agentRoot2) {
|
|
|
2741
2787
|
function accessSummaryForAgentcore(agentRoot2, opts = {}) {
|
|
2742
2788
|
let data;
|
|
2743
2789
|
try {
|
|
2744
|
-
data = loadStudioToml3(
|
|
2790
|
+
data = loadStudioToml3(path10.join(agentRoot2, "studio.toml"));
|
|
2745
2791
|
} catch {
|
|
2746
2792
|
return null;
|
|
2747
2793
|
}
|
|
@@ -2774,8 +2820,8 @@ import {
|
|
|
2774
2820
|
} from "@bnbagent/studio-runtime/config";
|
|
2775
2821
|
|
|
2776
2822
|
// src/cli/_deploy/checks/_wallet.ts
|
|
2777
|
-
import * as
|
|
2778
|
-
import * as
|
|
2823
|
+
import * as fs12 from "fs";
|
|
2824
|
+
import * as path11 from "path";
|
|
2779
2825
|
import {
|
|
2780
2826
|
findSubProjectRoot as findSubProjectRoot3,
|
|
2781
2827
|
loadStudioToml as loadStudioToml4
|
|
@@ -2882,16 +2928,16 @@ async function checkUBalance(walletAddress, neededUsd, networkName) {
|
|
|
2882
2928
|
|
|
2883
2929
|
// src/cli/_deploy/checks/_wallet.ts
|
|
2884
2930
|
function agentRootOf(root) {
|
|
2885
|
-
return findSubProjectRoot3("agent", root) ??
|
|
2931
|
+
return findSubProjectRoot3("agent", root) ?? path11.join(root, "app", "agent");
|
|
2886
2932
|
}
|
|
2887
2933
|
function tableOf2(data, key) {
|
|
2888
2934
|
const v = data[key];
|
|
2889
2935
|
return v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
2890
2936
|
}
|
|
2891
2937
|
function loadAgentToml(root) {
|
|
2892
|
-
const p =
|
|
2938
|
+
const p = path11.join(agentRootOf(root), "studio.toml");
|
|
2893
2939
|
try {
|
|
2894
|
-
if (!
|
|
2940
|
+
if (!fs12.statSync(p).isFile()) {
|
|
2895
2941
|
return {};
|
|
2896
2942
|
}
|
|
2897
2943
|
} catch {
|
|
@@ -2905,7 +2951,7 @@ function loadAgentToml(root) {
|
|
|
2905
2951
|
}
|
|
2906
2952
|
function keystoreJsonPresent(dir) {
|
|
2907
2953
|
try {
|
|
2908
|
-
return
|
|
2954
|
+
return fs12.statSync(dir).isDirectory() && fs12.readdirSync(dir).some((n) => n.endsWith(".json"));
|
|
2909
2955
|
} catch {
|
|
2910
2956
|
return false;
|
|
2911
2957
|
}
|
|
@@ -2926,7 +2972,7 @@ function canBuildWallet(root, data) {
|
|
|
2926
2972
|
return false;
|
|
2927
2973
|
}
|
|
2928
2974
|
const rel = String(walletCfg.keystore_dir ?? ".studio/wallets");
|
|
2929
|
-
const keystoreDir =
|
|
2975
|
+
const keystoreDir = path11.isAbsolute(rel) ? rel : path11.join(agentRootOf(root), rel);
|
|
2930
2976
|
return keystoreJsonPresent(keystoreDir);
|
|
2931
2977
|
}
|
|
2932
2978
|
function walletAddressForChecks(root, data) {
|
|
@@ -3100,8 +3146,8 @@ import { writePrivate as writePrivate2 } from "@bnbagent/studio-runtime/secretWr
|
|
|
3100
3146
|
import { Option as Option3 } from "commander";
|
|
3101
3147
|
|
|
3102
3148
|
// src/cli/_migrations.ts
|
|
3103
|
-
import * as
|
|
3104
|
-
import * as
|
|
3149
|
+
import * as fs13 from "fs";
|
|
3150
|
+
import * as path12 from "path";
|
|
3105
3151
|
import {
|
|
3106
3152
|
envLocalPath as envLocalPath7,
|
|
3107
3153
|
findSubProjectRoot as findSubProjectRoot5,
|
|
@@ -3109,59 +3155,59 @@ import {
|
|
|
3109
3155
|
} from "@bnbagent/studio-runtime/config";
|
|
3110
3156
|
function isFile3(p) {
|
|
3111
3157
|
try {
|
|
3112
|
-
return
|
|
3158
|
+
return fs13.statSync(p).isFile();
|
|
3113
3159
|
} catch {
|
|
3114
3160
|
return false;
|
|
3115
3161
|
}
|
|
3116
3162
|
}
|
|
3117
3163
|
function isDir2(p) {
|
|
3118
3164
|
try {
|
|
3119
|
-
return
|
|
3165
|
+
return fs13.statSync(p).isDirectory();
|
|
3120
3166
|
} catch {
|
|
3121
3167
|
return false;
|
|
3122
3168
|
}
|
|
3123
3169
|
}
|
|
3124
3170
|
function realpathOr(p) {
|
|
3125
3171
|
try {
|
|
3126
|
-
return
|
|
3172
|
+
return fs13.realpathSync(p);
|
|
3127
3173
|
} catch {
|
|
3128
|
-
return
|
|
3174
|
+
return path12.resolve(p);
|
|
3129
3175
|
}
|
|
3130
3176
|
}
|
|
3131
3177
|
function keystoreJsonFiles(dir) {
|
|
3132
3178
|
if (!isDir2(dir)) {
|
|
3133
3179
|
return [];
|
|
3134
3180
|
}
|
|
3135
|
-
return
|
|
3181
|
+
return fs13.readdirSync(dir).filter((n) => n.endsWith(".json")).sort();
|
|
3136
3182
|
}
|
|
3137
3183
|
function migrateEnvLocal(start) {
|
|
3138
3184
|
try {
|
|
3139
3185
|
const target = envLocalPath7(start);
|
|
3140
|
-
const ws =
|
|
3186
|
+
const ws = path12.dirname(path12.dirname(target));
|
|
3141
3187
|
const agentRoot2 = findSubProjectRoot5("agent", start);
|
|
3142
3188
|
const sources = [];
|
|
3143
3189
|
if (agentRoot2 !== null) {
|
|
3144
|
-
sources.push(
|
|
3190
|
+
sources.push(path12.join(agentRoot2, ".env.local"));
|
|
3145
3191
|
}
|
|
3146
|
-
sources.push(
|
|
3192
|
+
sources.push(path12.join(ws, ".bag-env-stash", ".env.local"));
|
|
3147
3193
|
for (const src of sources) {
|
|
3148
|
-
if (!isFile3(src) ||
|
|
3194
|
+
if (!isFile3(src) || path12.resolve(src) === path12.resolve(target)) {
|
|
3149
3195
|
continue;
|
|
3150
3196
|
}
|
|
3151
|
-
if (
|
|
3197
|
+
if (fs13.existsSync(target)) {
|
|
3152
3198
|
printErr(
|
|
3153
3199
|
`note: both ${src} and ${target} exist; left ${src} untouched. Secrets now live in .studio/.env.local \u2014 reconcile and remove the old file.`
|
|
3154
3200
|
);
|
|
3155
3201
|
continue;
|
|
3156
3202
|
}
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3203
|
+
fs13.mkdirSync(path12.dirname(target), { recursive: true });
|
|
3204
|
+
fs13.renameSync(src, target);
|
|
3205
|
+
fs13.chmodSync(target, 384);
|
|
3160
3206
|
printErr(
|
|
3161
3207
|
`note: migrated ${src} -> ${target} (secrets now live outside the deploy codeLocation).`
|
|
3162
3208
|
);
|
|
3163
3209
|
}
|
|
3164
|
-
|
|
3210
|
+
fs13.rmSync(path12.join(ws, ".bag-env-stash"), {
|
|
3165
3211
|
recursive: true,
|
|
3166
3212
|
force: true
|
|
3167
3213
|
});
|
|
@@ -3171,7 +3217,7 @@ function migrateEnvLocal(start) {
|
|
|
3171
3217
|
var KEYSTORE_WALLET_KINDS = /* @__PURE__ */ new Set(["evm-local", "altana"]);
|
|
3172
3218
|
function readWalletKind(agentRoot2) {
|
|
3173
3219
|
try {
|
|
3174
|
-
const wallet = loadStudioToml5(
|
|
3220
|
+
const wallet = loadStudioToml5(path12.join(agentRoot2, "studio.toml")).wallet;
|
|
3175
3221
|
if (wallet !== null && typeof wallet === "object") {
|
|
3176
3222
|
const kind = wallet.kind;
|
|
3177
3223
|
if (typeof kind === "string" && kind.trim()) {
|
|
@@ -3185,7 +3231,7 @@ function readWalletKind(agentRoot2) {
|
|
|
3185
3231
|
function resolveKeystoreDir(agentRoot2) {
|
|
3186
3232
|
let rel = ".studio/wallets";
|
|
3187
3233
|
try {
|
|
3188
|
-
const data = loadStudioToml5(
|
|
3234
|
+
const data = loadStudioToml5(path12.join(agentRoot2, "studio.toml"));
|
|
3189
3235
|
const wallet = data.wallet;
|
|
3190
3236
|
if (wallet !== null && typeof wallet === "object") {
|
|
3191
3237
|
const v = wallet.keystore_dir;
|
|
@@ -3195,24 +3241,24 @@ function resolveKeystoreDir(agentRoot2) {
|
|
|
3195
3241
|
}
|
|
3196
3242
|
} catch {
|
|
3197
3243
|
}
|
|
3198
|
-
return
|
|
3244
|
+
return path12.isAbsolute(rel) ? rel : path12.join(agentRoot2, rel);
|
|
3199
3245
|
}
|
|
3200
3246
|
function migrateKeystoreOutOfCodelocation(start) {
|
|
3201
3247
|
const agentRoot2 = findSubProjectRoot5("agent", start);
|
|
3202
3248
|
if (agentRoot2 === null) {
|
|
3203
3249
|
return;
|
|
3204
3250
|
}
|
|
3205
|
-
const ws =
|
|
3206
|
-
const target =
|
|
3207
|
-
const stash =
|
|
3251
|
+
const ws = path12.dirname(path12.dirname(envLocalPath7(start)));
|
|
3252
|
+
const target = path12.join(ws, ".studio", "wallets");
|
|
3253
|
+
const stash = path12.join(ws, ".bag-keystore-stash");
|
|
3208
3254
|
if (isDir2(stash)) {
|
|
3209
|
-
for (const name of
|
|
3210
|
-
const sub =
|
|
3255
|
+
for (const name of fs13.readdirSync(stash).sort()) {
|
|
3256
|
+
const sub = path12.join(stash, name);
|
|
3211
3257
|
if (isDir2(sub) && keystoreJsonFiles(sub).length > 0) {
|
|
3212
3258
|
relocateKeys(sub, target, "stashed keystore");
|
|
3213
3259
|
}
|
|
3214
3260
|
}
|
|
3215
|
-
|
|
3261
|
+
fs13.rmSync(stash, { recursive: true, force: true });
|
|
3216
3262
|
}
|
|
3217
3263
|
if (!KEYSTORE_WALLET_KINDS.has(readWalletKind(agentRoot2))) {
|
|
3218
3264
|
return;
|
|
@@ -3220,7 +3266,7 @@ function migrateKeystoreOutOfCodelocation(start) {
|
|
|
3220
3266
|
const src = resolveKeystoreDir(agentRoot2);
|
|
3221
3267
|
const srcReal = realpathOr(src);
|
|
3222
3268
|
const agentReal = realpathOr(agentRoot2);
|
|
3223
|
-
if (srcReal !== agentReal && !srcReal.startsWith(agentReal +
|
|
3269
|
+
if (srcReal !== agentReal && !srcReal.startsWith(agentReal + path12.sep)) {
|
|
3224
3270
|
return;
|
|
3225
3271
|
}
|
|
3226
3272
|
if (srcReal === realpathOr(target)) {
|
|
@@ -3231,13 +3277,13 @@ function migrateKeystoreOutOfCodelocation(start) {
|
|
|
3231
3277
|
return;
|
|
3232
3278
|
}
|
|
3233
3279
|
}
|
|
3234
|
-
const rel =
|
|
3235
|
-
const tomlPath =
|
|
3280
|
+
const rel = path12.relative(agentRoot2, target).split(path12.sep).join("/");
|
|
3281
|
+
const tomlPath = path12.join(agentRoot2, "studio.toml");
|
|
3236
3282
|
if (isFile3(tomlPath)) {
|
|
3237
|
-
const text2 =
|
|
3283
|
+
const text2 = fs13.readFileSync(tomlPath, "utf-8");
|
|
3238
3284
|
const updated = updateSection(text2, "wallet", { keystore_dir: rel });
|
|
3239
3285
|
if (updated !== text2) {
|
|
3240
|
-
|
|
3286
|
+
fs13.writeFileSync(tomlPath, updated);
|
|
3241
3287
|
printErr(
|
|
3242
3288
|
`note: updated [wallet].keystore_dir -> ${rel} in studio.toml (keystore now lives at the workspace root, outside the codeLocation).`
|
|
3243
3289
|
);
|
|
@@ -3245,7 +3291,7 @@ function migrateKeystoreOutOfCodelocation(start) {
|
|
|
3245
3291
|
}
|
|
3246
3292
|
}
|
|
3247
3293
|
function relocateKeys(src, target, label) {
|
|
3248
|
-
|
|
3294
|
+
fs13.mkdirSync(target, { recursive: true });
|
|
3249
3295
|
if (keystoreJsonFiles(target).length > 0) {
|
|
3250
3296
|
printErr(
|
|
3251
3297
|
`note: both a ${label} at ${src} and keys at ${target} exist; left ${src} untouched for manual review (never overwritten).`
|
|
@@ -3253,15 +3299,15 @@ function relocateKeys(src, target, label) {
|
|
|
3253
3299
|
return false;
|
|
3254
3300
|
}
|
|
3255
3301
|
try {
|
|
3256
|
-
for (const name of
|
|
3257
|
-
const f =
|
|
3258
|
-
if (
|
|
3259
|
-
|
|
3302
|
+
for (const name of fs13.readdirSync(src)) {
|
|
3303
|
+
const f = path12.join(src, name);
|
|
3304
|
+
if (fs13.statSync(f).isFile()) {
|
|
3305
|
+
fs13.copyFileSync(f, path12.join(target, name));
|
|
3260
3306
|
}
|
|
3261
3307
|
}
|
|
3262
3308
|
for (const name of keystoreJsonFiles(src)) {
|
|
3263
|
-
const a =
|
|
3264
|
-
const b =
|
|
3309
|
+
const a = fs13.readFileSync(path12.join(src, name));
|
|
3310
|
+
const b = fs13.readFileSync(path12.join(target, name));
|
|
3265
3311
|
if (!a.equals(b)) {
|
|
3266
3312
|
throw new Error(`verification mismatch for ${name}`);
|
|
3267
3313
|
}
|
|
@@ -3273,7 +3319,7 @@ function relocateKeys(src, target, label) {
|
|
|
3273
3319
|
);
|
|
3274
3320
|
return false;
|
|
3275
3321
|
}
|
|
3276
|
-
|
|
3322
|
+
fs13.rmSync(src, { recursive: true, force: true });
|
|
3277
3323
|
printErr(
|
|
3278
3324
|
`note: migrated ${label} ${src} -> ${target} (now outside the deploy codeLocation).`
|
|
3279
3325
|
);
|
|
@@ -3290,8 +3336,8 @@ import { Option as Option2 } from "commander";
|
|
|
3290
3336
|
import { parse as parseToml } from "smol-toml";
|
|
3291
3337
|
|
|
3292
3338
|
// src/cli/_deploy/providers.ts
|
|
3293
|
-
import * as
|
|
3294
|
-
import * as
|
|
3339
|
+
import * as fs14 from "fs";
|
|
3340
|
+
import * as path13 from "path";
|
|
3295
3341
|
import {
|
|
3296
3342
|
findSubProjectRoot as findSubProjectRoot6,
|
|
3297
3343
|
findWorkspaceRoot as findWorkspaceRoot4,
|
|
@@ -3334,8 +3380,8 @@ function text(value) {
|
|
|
3334
3380
|
function descriptorName(workspaceRoot) {
|
|
3335
3381
|
try {
|
|
3336
3382
|
const data = JSON.parse(
|
|
3337
|
-
|
|
3338
|
-
|
|
3383
|
+
fs14.readFileSync(
|
|
3384
|
+
path13.join(workspaceRoot, "agentcore", "agentcore.json"),
|
|
3339
3385
|
"utf-8"
|
|
3340
3386
|
)
|
|
3341
3387
|
);
|
|
@@ -3345,16 +3391,16 @@ function descriptorName(workspaceRoot) {
|
|
|
3345
3391
|
}
|
|
3346
3392
|
}
|
|
3347
3393
|
function discoverRecordedDeployments(root) {
|
|
3348
|
-
const workspaceRoot = findWorkspaceRoot4(root) ??
|
|
3394
|
+
const workspaceRoot = findWorkspaceRoot4(root) ?? path13.resolve(root);
|
|
3349
3395
|
const agentRoot2 = findSubProjectRoot6("agent", workspaceRoot);
|
|
3350
3396
|
if (agentRoot2 === null) return [];
|
|
3351
3397
|
let config;
|
|
3352
3398
|
try {
|
|
3353
|
-
config = loadStudioToml6(
|
|
3399
|
+
config = loadStudioToml6(path13.join(agentRoot2, "studio.toml"));
|
|
3354
3400
|
} catch {
|
|
3355
3401
|
return [];
|
|
3356
3402
|
}
|
|
3357
|
-
const projectName2 = descriptorName(workspaceRoot) ?? text(tableOf3(config, "project").name) ??
|
|
3403
|
+
const projectName2 = descriptorName(workspaceRoot) ?? text(tableOf3(config, "project").name) ?? path13.basename(workspaceRoot);
|
|
3358
3404
|
const deploy = tableOf3(config, "deploy");
|
|
3359
3405
|
const platform = tableOf3(deploy, "platform");
|
|
3360
3406
|
const azure = tableOf3(config, "azure");
|
|
@@ -3400,13 +3446,13 @@ function discoverRecordedDeployments(root) {
|
|
|
3400
3446
|
return found;
|
|
3401
3447
|
}
|
|
3402
3448
|
function unavailableProvidersForProject(root) {
|
|
3403
|
-
const workspaceRoot = findWorkspaceRoot4(root) ??
|
|
3449
|
+
const workspaceRoot = findWorkspaceRoot4(root) ?? path13.resolve(root);
|
|
3404
3450
|
const agentRoot2 = findSubProjectRoot6("agent", workspaceRoot);
|
|
3405
3451
|
if (agentRoot2 === null) return {};
|
|
3406
3452
|
let runtime = "agentcore";
|
|
3407
3453
|
let azureProtocolUnsupported = false;
|
|
3408
3454
|
try {
|
|
3409
|
-
const cfg = loadStudioToml6(
|
|
3455
|
+
const cfg = loadStudioToml6(path13.join(agentRoot2, "studio.toml"));
|
|
3410
3456
|
runtime = text(tableOf3(cfg, "stack").runtime) ?? "agentcore";
|
|
3411
3457
|
const faces = stackFaces(tableOf3(cfg, "stack"), tableOf3(cfg, "payments"));
|
|
3412
3458
|
azureProtocolUnsupported = !hasA2aFace(faces) || hasMcpFace(faces);
|
|
@@ -3415,11 +3461,12 @@ function unavailableProvidersForProject(root) {
|
|
|
3415
3461
|
}
|
|
3416
3462
|
if (runtime === "azure-foundry") {
|
|
3417
3463
|
const reason = "this project uses a different container adapter; scaffold an agentcore project before selecting this provider";
|
|
3464
|
+
const azureProtocolReason = "Azure Foundry deploy currently supports A2A projects only; use an A2A azure-foundry scaffold or AgentCore for MCP";
|
|
3418
3465
|
return {
|
|
3419
|
-
bnb: reason,
|
|
3420
3466
|
aws: reason,
|
|
3421
3467
|
...azureProtocolUnsupported ? {
|
|
3422
|
-
|
|
3468
|
+
bnb: azureProtocolReason,
|
|
3469
|
+
azure: azureProtocolReason
|
|
3423
3470
|
} : {}
|
|
3424
3471
|
};
|
|
3425
3472
|
}
|
|
@@ -3500,38 +3547,6 @@ async function selectDeployProvider(opts) {
|
|
|
3500
3547
|
return promptProvider(opts);
|
|
3501
3548
|
}
|
|
3502
3549
|
|
|
3503
|
-
// src/cli/_packageMetadata.ts
|
|
3504
|
-
import * as fs14 from "fs";
|
|
3505
|
-
import * as path13 from "path";
|
|
3506
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3507
|
-
function packageRoot() {
|
|
3508
|
-
let dir = path13.dirname(fileURLToPath2(import.meta.url));
|
|
3509
|
-
for (; ; ) {
|
|
3510
|
-
const packageJson = path13.join(dir, "package.json");
|
|
3511
|
-
if (fs14.existsSync(packageJson)) return dir;
|
|
3512
|
-
const parent = path13.dirname(dir);
|
|
3513
|
-
if (parent === dir) {
|
|
3514
|
-
throw new Error("cannot locate the studio-cli package root");
|
|
3515
|
-
}
|
|
3516
|
-
dir = parent;
|
|
3517
|
-
}
|
|
3518
|
-
}
|
|
3519
|
-
function pnpmVersion() {
|
|
3520
|
-
if ("10.24.0") {
|
|
3521
|
-
return "10.24.0";
|
|
3522
|
-
}
|
|
3523
|
-
const file = path13.join(packageRoot(), "package.json");
|
|
3524
|
-
const pkg = JSON.parse(fs14.readFileSync(file, "utf-8"));
|
|
3525
|
-
const value = String(pkg.packageManager ?? "");
|
|
3526
|
-
const match = /^pnpm@(.+)$/u.exec(value);
|
|
3527
|
-
if (!match?.[1]) {
|
|
3528
|
-
throw new Error(
|
|
3529
|
-
`studio-cli packageManager must pin pnpm (expected "pnpm@<version>" in ${file})`
|
|
3530
|
-
);
|
|
3531
|
-
}
|
|
3532
|
-
return match[1];
|
|
3533
|
-
}
|
|
3534
|
-
|
|
3535
3550
|
// src/cli/_runtime/azureFoundry.ts
|
|
3536
3551
|
import * as crypto2 from "crypto";
|
|
3537
3552
|
import * as fs18 from "fs";
|
|
@@ -4545,6 +4560,18 @@ var azureFoundryChecks = [
|
|
|
4545
4560
|
checkAltanaSdkResolvable,
|
|
4546
4561
|
checkAltanaSessionNotInsideAgent
|
|
4547
4562
|
];
|
|
4563
|
+
var managedAzureFoundryChecks = [
|
|
4564
|
+
checkStackRuntimeAzure,
|
|
4565
|
+
checkEntrypointAndDockerfile,
|
|
4566
|
+
checkLlmExternalProviderReady,
|
|
4567
|
+
checkTwakCustomContractsUnsupported,
|
|
4568
|
+
checkTwakPasswordEnvSet,
|
|
4569
|
+
checkTwakCredentialsAvailable,
|
|
4570
|
+
checkAltanaCustomContractsUnsupported,
|
|
4571
|
+
checkAltanaSessionReady,
|
|
4572
|
+
checkAltanaSdkResolvable,
|
|
4573
|
+
checkAltanaSessionNotInsideAgent
|
|
4574
|
+
];
|
|
4548
4575
|
|
|
4549
4576
|
// src/cli/llm.ts
|
|
4550
4577
|
import * as fs19 from "fs";
|
|
@@ -13425,8 +13452,9 @@ var checkPlatformLoggedIn = async (_root, _target) => {
|
|
|
13425
13452
|
}
|
|
13426
13453
|
];
|
|
13427
13454
|
};
|
|
13428
|
-
var checkPlatformDockerAvailable = async (root,
|
|
13429
|
-
if (platformArtifact(loadAgent(root)) !== "container")
|
|
13455
|
+
var checkPlatformDockerAvailable = async (root, target) => {
|
|
13456
|
+
if (target !== "platform-azure" && platformArtifact(loadAgent(root)) !== "container")
|
|
13457
|
+
return [];
|
|
13430
13458
|
const docker = await whichBin("docker");
|
|
13431
13459
|
if (docker === null) {
|
|
13432
13460
|
return [
|
|
@@ -13563,6 +13591,17 @@ async function runPrepare(opts = {}) {
|
|
|
13563
13591
|
}
|
|
13564
13592
|
return new CheckResult(checks, target);
|
|
13565
13593
|
}
|
|
13594
|
+
if (target === "platform-azure") {
|
|
13595
|
+
checks.push(...await runProducers(criticalChecks, root, target));
|
|
13596
|
+
checks.push(
|
|
13597
|
+
...await runProducers(managedAzureFoundryChecks, root, target)
|
|
13598
|
+
);
|
|
13599
|
+
checks.push(...await runProducers(warningChecks, root, target));
|
|
13600
|
+
if (includeInfo) {
|
|
13601
|
+
checks.push(...await runProducers(infoChecks, root, target));
|
|
13602
|
+
}
|
|
13603
|
+
return new CheckResult(checks, target);
|
|
13604
|
+
}
|
|
13566
13605
|
if (target === "azure-foundry") {
|
|
13567
13606
|
checks.push(
|
|
13568
13607
|
...await runProducers(
|
|
@@ -14267,12 +14306,37 @@ function trialLine(trial) {
|
|
|
14267
14306
|
}
|
|
14268
14307
|
async function platformAgent(opts) {
|
|
14269
14308
|
const root = opts.root;
|
|
14309
|
+
const backend = opts.backend ?? "aws";
|
|
14270
14310
|
const isTty = opts.isTty ?? stdinIsTty;
|
|
14271
14311
|
const ask = opts.promptUser ?? promptUser;
|
|
14272
14312
|
warn(
|
|
14273
|
-
|
|
14313
|
+
`note: deploying to the BNB Chain managed platform (backend=${backend}) \u2014 a 48h TESTNET trial sandbox (network is forced to bsc-testnet; the runtime is auto-reclaimed at 48h). Not a production seller.`
|
|
14274
14314
|
);
|
|
14275
14315
|
const platformCmd = opts.runPlatformCommand ?? runPlatformAccountCommand;
|
|
14316
|
+
if (backend === "azure") {
|
|
14317
|
+
const cfg2 = loadAgentCfg(root);
|
|
14318
|
+
const faces2 = stackFaces(tableOf12(cfg2, "stack"), tableOf12(cfg2, "payments"));
|
|
14319
|
+
const protocol2 = nativeProtocolOf(faces2);
|
|
14320
|
+
if (hasX402Face(faces2)) {
|
|
14321
|
+
warn(
|
|
14322
|
+
"error: x402 publication is not supported on the managed Azure backend. No build or upload was started."
|
|
14323
|
+
);
|
|
14324
|
+
return 1;
|
|
14325
|
+
}
|
|
14326
|
+
const runtimeProfile = protocol2 === "A2A" ? "foundry-responses-v1" : "foundry-invocations-v1";
|
|
14327
|
+
const capability = await platformCmd(["capabilities"], { json: true });
|
|
14328
|
+
const platform = isJsonObject(capability.data.platform) ? capability.data.platform : {};
|
|
14329
|
+
const backends = isJsonObject(platform.backends) ? platform.backends : {};
|
|
14330
|
+
const azure = isJsonObject(backends.azure) ? backends.azure : {};
|
|
14331
|
+
const profiles = Array.isArray(azure.runtimeProfiles) ? azure.runtimeProfiles.map(String) : [];
|
|
14332
|
+
const protocols = Array.isArray(azure.protocols) ? azure.protocols.map(String) : [];
|
|
14333
|
+
if (capability.code !== 0 || azure.enabled !== true || !profiles.includes(runtimeProfile) || !protocols.includes(protocol2)) {
|
|
14334
|
+
warn(
|
|
14335
|
+
`error: the managed platform does not currently accept Azure ${runtimeProfile}/${protocol2}. No build or upload was started.`
|
|
14336
|
+
);
|
|
14337
|
+
return capability.code || 1;
|
|
14338
|
+
}
|
|
14339
|
+
}
|
|
14276
14340
|
const campaignProbe = opts.campaignActive ?? (async () => null);
|
|
14277
14341
|
const trialRes = await platformCmd(["trial"], { json: true });
|
|
14278
14342
|
if (trialRes.code !== 0) {
|
|
@@ -14306,7 +14370,7 @@ async function platformAgent(opts) {
|
|
|
14306
14370
|
return rc;
|
|
14307
14371
|
}
|
|
14308
14372
|
}
|
|
14309
|
-
const packaging = platformPackaging(root);
|
|
14373
|
+
const packaging = backend === "azure" ? "container" : platformPackaging(root);
|
|
14310
14374
|
{
|
|
14311
14375
|
const confirm = opts.confirmPackaging ?? ((r, p) => confirmPackagingDefault(r, p, {
|
|
14312
14376
|
acceptRisk: opts.acceptRisk ?? false,
|
|
@@ -14376,7 +14440,8 @@ then re-run the deploy.`
|
|
|
14376
14440
|
secrets,
|
|
14377
14441
|
slug,
|
|
14378
14442
|
cwd: agentDir,
|
|
14379
|
-
extraArgs: opts.extraArgs ?? []
|
|
14443
|
+
extraArgs: opts.extraArgs ?? [],
|
|
14444
|
+
backend
|
|
14380
14445
|
});
|
|
14381
14446
|
if (res.code !== 0) {
|
|
14382
14447
|
warn(
|
|
@@ -14405,7 +14470,7 @@ then re-run the deploy.`
|
|
|
14405
14470
|
trial = trialFromJson(post.data);
|
|
14406
14471
|
}
|
|
14407
14472
|
}
|
|
14408
|
-
recordDeployState(root, slug, dep);
|
|
14473
|
+
recordDeployState(root, slug, dep, backend);
|
|
14409
14474
|
recordShippedWallet(root, secrets);
|
|
14410
14475
|
refreshTrialCache(root, {
|
|
14411
14476
|
expiresAt: trial.expiresAt,
|
|
@@ -14416,7 +14481,7 @@ then re-run the deploy.`
|
|
|
14416
14481
|
` : "";
|
|
14417
14482
|
emit(
|
|
14418
14483
|
`
|
|
14419
|
-
\u2713 deployed to the platform (slug=${slug}).
|
|
14484
|
+
\u2713 deployed to the platform (backend=${backend}, slug=${slug}).
|
|
14420
14485
|
deployment: ${dep.deploymentId}
|
|
14421
14486
|
invoke URL: ${dep.invokeUrl || "<pending \u2014 see `bag deploy status`>"}
|
|
14422
14487
|
${trialLine(trial)}
|
|
@@ -14433,7 +14498,7 @@ async function termsConsentGate(root, deps) {
|
|
|
14433
14498
|
return null;
|
|
14434
14499
|
}
|
|
14435
14500
|
warn(
|
|
14436
|
-
"=== Platform trial terms (first deploy) ===\nThis deploys into
|
|
14501
|
+
"=== Platform trial terms (first deploy) ===\nThis deploys into a BNB Chain operator-managed cloud account as a 48h testnet trial. A runtime signing key (your configured or a throwaway wallet) is transmitted to the operator's managed secret channel for the runtime to sign with \u2014 testnet-scoped, auto-reclaimed at 48h. By proceeding you accept these trial terms."
|
|
14437
14502
|
);
|
|
14438
14503
|
if (deps.acceptRisk) {
|
|
14439
14504
|
return stampTerms(root) ? null : 1;
|
|
@@ -14490,7 +14555,7 @@ function walletWarning(root, secrets) {
|
|
|
14490
14555
|
warn(
|
|
14491
14556
|
`
|
|
14492
14557
|
[expected \xB7 bounded Altana session]
|
|
14493
|
-
This project's bounded Altana session${who2} will be transmitted
|
|
14558
|
+
This project's bounded Altana session${who2} will be transmitted through the BNB Chain operator's managed secret channel 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.
|
|
14494
14559
|
If the current budget or expiry is wider than you want an operator-held key to carry, stop and grant a tighter one first:
|
|
14495
14560
|
bag wallet session grant --force --budget-u <small> --expiry-days <short>
|
|
14496
14561
|
You can revoke it on-chain at any time with \`bag wallet session revoke\`.
|
|
@@ -14502,16 +14567,17 @@ function walletWarning(root, secrets) {
|
|
|
14502
14567
|
warn(
|
|
14503
14568
|
`
|
|
14504
14569
|
!!! wallet exposure (platform trial) !!!
|
|
14505
|
-
This project's wallet ${who} will be transmitted
|
|
14570
|
+
This project's wallet ${who} will be transmitted through the BNB Chain operator's managed secret channel so the trial runtime can sign on testnet \u2014 expected for the platform trial, and testnet-scoped.
|
|
14506
14571
|
If this address is one you also use elsewhere (especially on mainnet), stop and deploy with a fresh throwaway instead:
|
|
14507
14572
|
bag wallet new
|
|
14508
14573
|
Otherwise proceed. Reusing this address on mainnet later is discouraged.
|
|
14509
14574
|
`
|
|
14510
14575
|
);
|
|
14511
14576
|
}
|
|
14512
|
-
function recordDeployState(root, slug, dep) {
|
|
14577
|
+
function recordDeployState(root, slug, dep, backend = "aws") {
|
|
14513
14578
|
recordPlatformKv(root, "slug", slug);
|
|
14514
14579
|
recordPlatformKv(root, "deployment_id", dep.deploymentId);
|
|
14580
|
+
recordPlatformKv(root, "backend", backend);
|
|
14515
14581
|
if (dep.agentId) {
|
|
14516
14582
|
recordPlatformKv(root, "agent_id", dep.agentId);
|
|
14517
14583
|
}
|
|
@@ -14617,6 +14683,7 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
14617
14683
|
const base = access.base;
|
|
14618
14684
|
const tokenUrl = access.tokenUrl;
|
|
14619
14685
|
const deploymentId = String(platformCfg(root).deployment_id || "n/a");
|
|
14686
|
+
const managedBackend = platformCfg(root).backend === "azure" ? "azure" : "aws";
|
|
14620
14687
|
const selftestLine = "- Quick self-test (operator): run `bag deploy info --with-curl`";
|
|
14621
14688
|
const rt = agentId ? `${base}/v1/rt/${agentId}` : `${base}/v1/rt/<agentId>`;
|
|
14622
14689
|
const cardUrl = `${rt}/.well-known/agent-card.json`;
|
|
@@ -14696,7 +14763,7 @@ function printAgentClientPrompt(root, invokeUrl, status) {
|
|
|
14696
14763
|
"- The anonymous x402 route does not use the OAuth2 token flow shown for ERC-8183."
|
|
14697
14764
|
],
|
|
14698
14765
|
...!x402Only && hasA2aFace(faces) ? [
|
|
14699
|
-
'- A2A callers: send the payload as a DATA part, NOT text \u2014 parts:[{"kind":"data","data":{ ...payload above... }}]. A JSON string in a "text" part is rejected (the runtime only reads data parts, so no skill is parsed).'
|
|
14766
|
+
managedBackend === "azure" ? '- A2A callers: Foundry incoming A2A is text-only. Send the payload as a JSON-string TEXT part \u2014 parts:[{"kind":"text","text":"{\\"skill\\":\\"negotiate\\",...}"}].' : '- A2A callers: send the payload as a DATA part, NOT text \u2014 parts:[{"kind":"data","data":{ ...payload above... }}]. A JSON string in a "text" part is rejected (the runtime only reads data parts, so no skill is parsed).'
|
|
14700
14767
|
] : [],
|
|
14701
14768
|
"",
|
|
14702
14769
|
"YOUR TASK",
|
|
@@ -14892,6 +14959,9 @@ var ADVERTISED_DEPLOY_RUNTIME_TARGETS = ["agentcore"];
|
|
|
14892
14959
|
// src/cli/deploy.ts
|
|
14893
14960
|
var TARGET_CHOICES = [...DEPLOY_RUNTIME_TARGETS];
|
|
14894
14961
|
var ADVERTISED_TARGET_CHOICES = [...ADVERTISED_DEPLOY_RUNTIME_TARGETS];
|
|
14962
|
+
function runtimeSecretsForManagedBackend(backend) {
|
|
14963
|
+
return backend === "azure" ? collectAzureSecretPayload : collectRuntimeSecrets;
|
|
14964
|
+
}
|
|
14895
14965
|
function isFile16(p) {
|
|
14896
14966
|
try {
|
|
14897
14967
|
return fs38.statSync(p).isFile();
|
|
@@ -14958,7 +15028,12 @@ function registerDeploy(program) {
|
|
|
14958
15028
|
PROVIDER_MENU_ORDER,
|
|
14959
15029
|
ADVERTISED_PROVIDERS
|
|
14960
15030
|
);
|
|
14961
|
-
p.addOption(providerOption()).
|
|
15031
|
+
p.addOption(providerOption()).addOption(
|
|
15032
|
+
new Option4(
|
|
15033
|
+
"--backend <backend>",
|
|
15034
|
+
"Managed backend confirmation for --provider bnb (aws or azure). It must match [stack].runtime."
|
|
15035
|
+
).choices(["aws", "azure"])
|
|
15036
|
+
).option("--project-root <path>", "Override project root.").option("--skip-prepare", "Skip non-storage local readiness checks.").option(
|
|
14962
15037
|
"--force-deploy-broken-storage",
|
|
14963
15038
|
"DANGEROUS: bypass fatal deliverable-storage checks."
|
|
14964
15039
|
).option("--force", "Bypass explicitly forceable readiness checks.").addOption(
|
|
@@ -14976,7 +15051,12 @@ function registerDeploy(program) {
|
|
|
14976
15051
|
).action(act((opts) => cmdPrepare(opts)));
|
|
14977
15052
|
p.command("agent").description(
|
|
14978
15053
|
"Deprecated compatibility alias for `bag deploy`. Thin wrapper: gates on prepare, syncs runtime secrets, builds the agent (`pnpm build`), delegates to the platform CLI."
|
|
14979
|
-
).addOption(providerOption()).addOption(
|
|
15054
|
+
).addOption(providerOption()).addOption(
|
|
15055
|
+
new Option4(
|
|
15056
|
+
"--backend <backend>",
|
|
15057
|
+
"Managed backend confirmation for --provider bnb (aws or azure). It must match [stack].runtime."
|
|
15058
|
+
).choices(["aws", "azure"])
|
|
15059
|
+
).addOption(runtimeOption()).addOption(targetAlias()).addOption(
|
|
14980
15060
|
new Option4(
|
|
14981
15061
|
"--to <destination>",
|
|
14982
15062
|
"Deploy destination override: self (your own cloud) or platform (the managed BNB Chain trial). Default: studio.toml [deploy].destination, else self."
|
|
@@ -15038,10 +15118,10 @@ function registerDeploy(program) {
|
|
|
15038
15118
|
)
|
|
15039
15119
|
);
|
|
15040
15120
|
p.command("info").description(
|
|
15041
|
-
"Show the buyer-access surface for a platform
|
|
15121
|
+
"Show the buyer-access surface for a platform or Azure self-deploy."
|
|
15042
15122
|
).option("--project-root <path>", "Override project root.").option("--json", "Emit JSON instead of a table.").option(
|
|
15043
15123
|
"--with-curl",
|
|
15044
|
-
"Also print a copy-paste
|
|
15124
|
+
"Also print a copy-paste authentication + invoke curl chain."
|
|
15045
15125
|
).action(
|
|
15046
15126
|
act(
|
|
15047
15127
|
(opts) => cmdInfo(opts)
|
|
@@ -15665,6 +15745,37 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15665
15745
|
const root = resolveProjectRoot2(opts.projectRoot);
|
|
15666
15746
|
const destination = opts.provider ? opts.provider === "bnb" ? "platform" : "self" : opts.to ?? opts.destination ?? agentDeployDestination(root);
|
|
15667
15747
|
const packagingDestination = opts.to ?? opts.destination ?? agentDeployDestination(root);
|
|
15748
|
+
let managedBackend;
|
|
15749
|
+
if (destination === "platform") {
|
|
15750
|
+
const runtime = readStackRuntime(root) ?? "agentcore";
|
|
15751
|
+
managedBackend = runtime === "azure-foundry" ? "azure" : "aws";
|
|
15752
|
+
if (opts.backend && opts.backend !== managedBackend) {
|
|
15753
|
+
printErr(
|
|
15754
|
+
`error: --backend=${opts.backend} conflicts with [stack].runtime='${runtime}', which requires backend=${managedBackend}. --backend confirms the recipe target; it does not convert recipes across clouds.`
|
|
15755
|
+
);
|
|
15756
|
+
return 2;
|
|
15757
|
+
}
|
|
15758
|
+
if (managedBackend === "azure" && !opts.backend) {
|
|
15759
|
+
if (!stdinIsTty()) {
|
|
15760
|
+
printErr(
|
|
15761
|
+
"error: an azure-foundry project requires explicit --backend azure in a non-interactive terminal."
|
|
15762
|
+
);
|
|
15763
|
+
return 2;
|
|
15764
|
+
}
|
|
15765
|
+
const answer = await promptUser(
|
|
15766
|
+
"This azure-foundry project will use the managed Azure backend. Continue? [y/N] "
|
|
15767
|
+
);
|
|
15768
|
+
if (!["y", "yes"].includes(answer.trim().toLowerCase())) {
|
|
15769
|
+
printErr("cancelled: managed Azure backend was not confirmed.");
|
|
15770
|
+
return 2;
|
|
15771
|
+
}
|
|
15772
|
+
}
|
|
15773
|
+
} else if (opts.backend) {
|
|
15774
|
+
printErr(
|
|
15775
|
+
`error: --backend is accepted only with --provider bnb; --provider ${opts.provider ?? "self"} selects a user-owned cloud directly.`
|
|
15776
|
+
);
|
|
15777
|
+
return 2;
|
|
15778
|
+
}
|
|
15668
15779
|
if (destination === "platform") {
|
|
15669
15780
|
const networkGate = rejectPlatformMainnet(root);
|
|
15670
15781
|
if (networkGate !== null) return networkGate;
|
|
@@ -15691,14 +15802,15 @@ async function cmdAgent(opts, agentcoreArgs) {
|
|
|
15691
15802
|
}
|
|
15692
15803
|
return platformAgent({
|
|
15693
15804
|
root,
|
|
15805
|
+
backend: managedBackend,
|
|
15694
15806
|
acceptRisk: opts.acceptRisk,
|
|
15695
15807
|
skipPrepare: opts.skipPrepare,
|
|
15696
15808
|
force: opts.force,
|
|
15697
15809
|
// The deploy layer injects the shared secret collector + prepare gate
|
|
15698
15810
|
// so the self-deploy and platform secret/readiness surfaces never
|
|
15699
15811
|
// drift (the Python `_collect_runtime_secrets` / `run_prepare` share).
|
|
15700
|
-
collectRuntimeSecrets,
|
|
15701
|
-
runPrepareGate: platformPrepareGate(opts),
|
|
15812
|
+
collectRuntimeSecrets: runtimeSecretsForManagedBackend(managedBackend),
|
|
15813
|
+
runPrepareGate: platformPrepareGate(opts, managedBackend),
|
|
15702
15814
|
extraArgs: stripLeadingDdash2(agentcoreArgs)
|
|
15703
15815
|
});
|
|
15704
15816
|
}
|
|
@@ -15901,10 +16013,10 @@ function recordOf2(data) {
|
|
|
15901
16013
|
function stripLeadingDdash2(extra) {
|
|
15902
16014
|
return extra.length > 0 && extra[0] === "--" ? extra.slice(1) : extra;
|
|
15903
16015
|
}
|
|
15904
|
-
function platformPrepareGate(opts) {
|
|
16016
|
+
function platformPrepareGate(opts, backend = "aws") {
|
|
15905
16017
|
return async (root, force) => {
|
|
15906
16018
|
let result = await runPrepare({
|
|
15907
|
-
target: "platform",
|
|
16019
|
+
target: backend === "azure" ? "platform-azure" : "platform",
|
|
15908
16020
|
projectRoot: root,
|
|
15909
16021
|
includeInfo: false,
|
|
15910
16022
|
force
|
|
@@ -15968,6 +16080,7 @@ function agentProtocolOf(agentRoot2) {
|
|
|
15968
16080
|
return nativeProtocolOf(agentFacesOf(agentRoot2));
|
|
15969
16081
|
}
|
|
15970
16082
|
var GUIDE_URL2 = "https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/agentcore-a2a-access.md";
|
|
16083
|
+
var FOUNDRY_GUIDE_URL = "https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/foundry-a2a-access.md";
|
|
15971
16084
|
function oauthFactsForAgentcore(agentRoot2) {
|
|
15972
16085
|
const summary = accessSummaryForAgentcore(agentRoot2);
|
|
15973
16086
|
if (summary === null) {
|
|
@@ -16012,8 +16125,12 @@ async function printAccessNextSteps2(root, runtime, opts = {}) {
|
|
|
16012
16125
|
}
|
|
16013
16126
|
return;
|
|
16014
16127
|
}
|
|
16128
|
+
const invokeUrl = opts.invokeUrl ?? recordedEndpoint(root);
|
|
16129
|
+
if (invokeUrl) {
|
|
16130
|
+
printOut(` endpoint: ${invokeUrl}`);
|
|
16131
|
+
}
|
|
16015
16132
|
printOut(
|
|
16016
|
-
|
|
16133
|
+
` Azure Foundry access uses a Microsoft Entra bearer token. Run \`bag deploy info --with-curl\` for the exact endpoint, token resource, and Invocations request body; see ${FOUNDRY_GUIDE_URL}.`
|
|
16017
16134
|
);
|
|
16018
16135
|
}
|
|
16019
16136
|
var CLIENT_PROMPT_RULE2 = "\u2500".repeat(62);
|
|
@@ -16417,6 +16534,96 @@ Quick-verify x402 endpoint:
|
|
|
16417
16534
|
"\n Note: this only exercises `negotiate` (a read-only quote). To get a deliverable you must fund a job on-chain (ERC-8183 createJob -> registerJob -> setBudget -> fund), then call `notify_funded` with that job_id and poll the chain for SUBMITTED \u2014 see the emitted client prompt / `bnbagent-studio-buying-via-8183`."
|
|
16418
16535
|
);
|
|
16419
16536
|
}
|
|
16537
|
+
var AZURE_FOUNDRY_TOKEN_RESOURCE = "https://ai.azure.com";
|
|
16538
|
+
var AZURE_FOUNDRY_TOKEN_SCOPE = `${AZURE_FOUNDRY_TOKEN_RESOURCE}/.default`;
|
|
16539
|
+
function azureQuickVerifyBody() {
|
|
16540
|
+
return {
|
|
16541
|
+
input: JSON.stringify({
|
|
16542
|
+
skill: "negotiate",
|
|
16543
|
+
task_description: "Create a concise launch checklist",
|
|
16544
|
+
terms: {
|
|
16545
|
+
deliverables: "A 5-item checklist",
|
|
16546
|
+
quality_standards: "Clear and actionable"
|
|
16547
|
+
}
|
|
16548
|
+
})
|
|
16549
|
+
};
|
|
16550
|
+
}
|
|
16551
|
+
function printAzureInfo(deployment, opts) {
|
|
16552
|
+
const endpoint = deployment.endpoint;
|
|
16553
|
+
if (!endpoint) {
|
|
16554
|
+
if (opts.json) {
|
|
16555
|
+
printOut(
|
|
16556
|
+
JSON.stringify(
|
|
16557
|
+
{
|
|
16558
|
+
provider: "azure",
|
|
16559
|
+
target: deployment.target,
|
|
16560
|
+
name: deployment.name,
|
|
16561
|
+
endpoint: null,
|
|
16562
|
+
error: "No Azure invocation endpoint is recorded."
|
|
16563
|
+
},
|
|
16564
|
+
null,
|
|
16565
|
+
2
|
|
16566
|
+
)
|
|
16567
|
+
);
|
|
16568
|
+
} else {
|
|
16569
|
+
printErr(
|
|
16570
|
+
"Azure deployment is recorded but has no invocation endpoint. Run `bag deploy status --provider azure` and redeploy if the live endpoint cannot be recovered."
|
|
16571
|
+
);
|
|
16572
|
+
}
|
|
16573
|
+
return 1;
|
|
16574
|
+
}
|
|
16575
|
+
const body = azureQuickVerifyBody();
|
|
16576
|
+
if (opts.json) {
|
|
16577
|
+
printOut(
|
|
16578
|
+
JSON.stringify(
|
|
16579
|
+
{
|
|
16580
|
+
provider: "azure",
|
|
16581
|
+
target: deployment.target,
|
|
16582
|
+
name: deployment.name,
|
|
16583
|
+
deployment_id: deployment.deploymentId,
|
|
16584
|
+
endpoint,
|
|
16585
|
+
authentication: {
|
|
16586
|
+
type: "entra_bearer",
|
|
16587
|
+
resource: AZURE_FOUNDRY_TOKEN_RESOURCE,
|
|
16588
|
+
scope: AZURE_FOUNDRY_TOKEN_SCOPE
|
|
16589
|
+
},
|
|
16590
|
+
request: {
|
|
16591
|
+
method: "POST",
|
|
16592
|
+
content_type: "application/json",
|
|
16593
|
+
body
|
|
16594
|
+
}
|
|
16595
|
+
},
|
|
16596
|
+
null,
|
|
16597
|
+
2
|
|
16598
|
+
)
|
|
16599
|
+
);
|
|
16600
|
+
return 0;
|
|
16601
|
+
}
|
|
16602
|
+
printOut("bag deploy info \u2014 Azure Foundry self-deploy");
|
|
16603
|
+
printOut(` endpoint: ${endpoint}`);
|
|
16604
|
+
printOut(
|
|
16605
|
+
` authentication: Microsoft Entra bearer token (resource ${AZURE_FOUNDRY_TOKEN_RESOURCE}; SDK scope ${AZURE_FOUNDRY_TOKEN_SCOPE})`
|
|
16606
|
+
);
|
|
16607
|
+
printOut(" request: POST application/json");
|
|
16608
|
+
printOut(` body: ${JSON.stringify(body)}`);
|
|
16609
|
+
if (opts.withCurl) {
|
|
16610
|
+
printOut("\nQuick-verify curl:");
|
|
16611
|
+
printOut(
|
|
16612
|
+
` AZURE_TOKEN=$(az account get-access-token --resource ${AZURE_FOUNDRY_TOKEN_RESOURCE} --query accessToken -o tsv)`
|
|
16613
|
+
);
|
|
16614
|
+
printOut(` AZURE_ENDPOINT=${JSON.stringify(endpoint)}`);
|
|
16615
|
+
printOut(
|
|
16616
|
+
` curl -sS -X POST "$AZURE_ENDPOINT" \\
|
|
16617
|
+
-H "Authorization: Bearer $AZURE_TOKEN" \\
|
|
16618
|
+
-H "Content-Type: application/json" \\
|
|
16619
|
+
-d '${JSON.stringify(body)}'`
|
|
16620
|
+
);
|
|
16621
|
+
printOut(
|
|
16622
|
+
"\n The Azure CLI command is only a convenient way to mint a token for this curl. Deployment itself does not require az/azd; DefaultAzureCredential or ClientSecretCredential can mint the same scope in an application."
|
|
16623
|
+
);
|
|
16624
|
+
}
|
|
16625
|
+
return 0;
|
|
16626
|
+
}
|
|
16420
16627
|
async function cmdInfo(opts) {
|
|
16421
16628
|
const rc = applyProjectRoot(opts.projectRoot, false);
|
|
16422
16629
|
if (rc !== null) {
|
|
@@ -16424,7 +16631,8 @@ async function cmdInfo(opts) {
|
|
|
16424
16631
|
}
|
|
16425
16632
|
const root = resolveProjectRoot2(opts.projectRoot);
|
|
16426
16633
|
const workspaceRoot = deployWorkspaceRoot2(root);
|
|
16427
|
-
const
|
|
16634
|
+
const recorded = discoverRecordedDeployments(workspaceRoot);
|
|
16635
|
+
const hasBnbDeployment = recorded.some(
|
|
16428
16636
|
(deployment) => deployment.provider === "bnb"
|
|
16429
16637
|
);
|
|
16430
16638
|
if (hasBnbDeployment) {
|
|
@@ -16434,6 +16642,12 @@ async function cmdInfo(opts) {
|
|
|
16434
16642
|
}
|
|
16435
16643
|
return infoRc;
|
|
16436
16644
|
}
|
|
16645
|
+
const azureDeployment = recorded.find(
|
|
16646
|
+
(deployment) => deployment.provider === "azure"
|
|
16647
|
+
);
|
|
16648
|
+
if (azureDeployment) {
|
|
16649
|
+
return printAzureInfo(azureDeployment, opts);
|
|
16650
|
+
}
|
|
16437
16651
|
printErr(
|
|
16438
16652
|
"`bag deploy info` reports the platform buyer-access surface; this project has no recorded BNB deployment. Use `bag deploy status` to inspect recorded providers."
|
|
16439
16653
|
);
|
|
@@ -16571,10 +16785,10 @@ async function cmdLogs(opts) {
|
|
|
16571
16785
|
if (deployment.provider === "aws" && opts.since) {
|
|
16572
16786
|
argv.push("--since", opts.since);
|
|
16573
16787
|
}
|
|
16574
|
-
if (
|
|
16788
|
+
if (opts.limit) {
|
|
16575
16789
|
argv.push("--limit", opts.limit);
|
|
16576
16790
|
}
|
|
16577
|
-
if (
|
|
16791
|
+
if (opts.session) {
|
|
16578
16792
|
argv.push("--session", opts.session);
|
|
16579
16793
|
}
|
|
16580
16794
|
return runDeployCliStream(argv, {
|
|
@@ -20842,7 +21056,7 @@ function buildProgram() {
|
|
|
20842
21056
|
return program;
|
|
20843
21057
|
}
|
|
20844
21058
|
function cliVersion() {
|
|
20845
|
-
return
|
|
21059
|
+
return studioCliVersion();
|
|
20846
21060
|
}
|
|
20847
21061
|
|
|
20848
21062
|
// src/cli/updateCheck.ts
|