@wayai/cli 0.3.163 → 0.3.165
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/index.js +479 -381
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17455,40 +17455,214 @@ var init_expected = __esm({
|
|
|
17455
17455
|
}
|
|
17456
17456
|
});
|
|
17457
17457
|
|
|
17458
|
-
// src/lib/
|
|
17458
|
+
// src/lib/fs-safety.ts
|
|
17459
17459
|
import * as fs from "fs";
|
|
17460
17460
|
import * as path from "path";
|
|
17461
|
+
function fileHasBytes(abs, data) {
|
|
17462
|
+
let st;
|
|
17463
|
+
try {
|
|
17464
|
+
st = fs.lstatSync(abs);
|
|
17465
|
+
} catch {
|
|
17466
|
+
return false;
|
|
17467
|
+
}
|
|
17468
|
+
if (!st.isFile() || st.isSymbolicLink()) return false;
|
|
17469
|
+
try {
|
|
17470
|
+
return fs.readFileSync(abs).equals(data);
|
|
17471
|
+
} catch {
|
|
17472
|
+
return false;
|
|
17473
|
+
}
|
|
17474
|
+
}
|
|
17475
|
+
function realpathContained(root, abs) {
|
|
17476
|
+
let realRoot;
|
|
17477
|
+
let realAbs;
|
|
17478
|
+
try {
|
|
17479
|
+
realRoot = fs.realpathSync(root);
|
|
17480
|
+
realAbs = fs.realpathSync(abs);
|
|
17481
|
+
} catch {
|
|
17482
|
+
return false;
|
|
17483
|
+
}
|
|
17484
|
+
return realAbs === realRoot || realAbs.startsWith(realRoot + path.sep);
|
|
17485
|
+
}
|
|
17486
|
+
function mkdirTolerateRace(dir) {
|
|
17487
|
+
try {
|
|
17488
|
+
fs.mkdirSync(dir);
|
|
17489
|
+
return true;
|
|
17490
|
+
} catch (err) {
|
|
17491
|
+
if (err.code !== "EEXIST") throw err;
|
|
17492
|
+
let st;
|
|
17493
|
+
try {
|
|
17494
|
+
st = fs.lstatSync(dir);
|
|
17495
|
+
} catch {
|
|
17496
|
+
st = void 0;
|
|
17497
|
+
}
|
|
17498
|
+
return !!st?.isDirectory();
|
|
17499
|
+
}
|
|
17500
|
+
}
|
|
17501
|
+
function ensureRealSubdirNoSymlink(root, target, create) {
|
|
17502
|
+
const rootResolved = path.resolve(root);
|
|
17503
|
+
const targetResolved = path.resolve(target);
|
|
17504
|
+
if (targetResolved !== rootResolved && !targetResolved.startsWith(rootResolved + path.sep)) return false;
|
|
17505
|
+
try {
|
|
17506
|
+
if (!fs.lstatSync(rootResolved).isDirectory()) return false;
|
|
17507
|
+
} catch {
|
|
17508
|
+
return false;
|
|
17509
|
+
}
|
|
17510
|
+
const rel = path.relative(rootResolved, targetResolved);
|
|
17511
|
+
if (rel === "") return true;
|
|
17512
|
+
let cur = rootResolved;
|
|
17513
|
+
for (const segment of rel.split(path.sep)) {
|
|
17514
|
+
cur = path.join(cur, segment);
|
|
17515
|
+
let st;
|
|
17516
|
+
try {
|
|
17517
|
+
st = fs.lstatSync(cur);
|
|
17518
|
+
} catch {
|
|
17519
|
+
st = void 0;
|
|
17520
|
+
}
|
|
17521
|
+
if (st) {
|
|
17522
|
+
if (!st.isDirectory()) return false;
|
|
17523
|
+
} else if (create) {
|
|
17524
|
+
if (!mkdirTolerateRace(cur)) return false;
|
|
17525
|
+
} else {
|
|
17526
|
+
return true;
|
|
17527
|
+
}
|
|
17528
|
+
}
|
|
17529
|
+
return true;
|
|
17530
|
+
}
|
|
17531
|
+
function requireRealSubdirNoSymlink(root, target, create) {
|
|
17532
|
+
if (ensureRealSubdirNoSymlink(root, target, create)) return;
|
|
17533
|
+
throw expected(
|
|
17534
|
+
`${path.relative(path.dirname(root), target)} is reached through a symlink (or a file is in the way). The CLI never reads or writes workspace config through a symlink \u2014 make it a real directory.`
|
|
17535
|
+
);
|
|
17536
|
+
}
|
|
17537
|
+
function requireRealHubFolder(hubFolder, create) {
|
|
17538
|
+
if (!create) {
|
|
17539
|
+
try {
|
|
17540
|
+
fs.lstatSync(hubFolder);
|
|
17541
|
+
} catch {
|
|
17542
|
+
return;
|
|
17543
|
+
}
|
|
17544
|
+
}
|
|
17545
|
+
requireRealSubdirNoSymlink(path.dirname(hubFolder), hubFolder, create);
|
|
17546
|
+
for (const sub of HUB_MANAGED_SUBDIRS) {
|
|
17547
|
+
requireRealSubdirNoSymlink(hubFolder, path.join(hubFolder, sub), false);
|
|
17548
|
+
}
|
|
17549
|
+
for (const name of HUB_CONFIG_FILES) {
|
|
17550
|
+
let st;
|
|
17551
|
+
try {
|
|
17552
|
+
st = fs.lstatSync(path.join(hubFolder, name));
|
|
17553
|
+
} catch {
|
|
17554
|
+
continue;
|
|
17555
|
+
}
|
|
17556
|
+
if (!st.isFile()) {
|
|
17557
|
+
throw expected(
|
|
17558
|
+
`${path.join(path.basename(hubFolder), name)} is a symlink (or not a file). The CLI never reads or writes workspace config through a symlink \u2014 make it a real file.`
|
|
17559
|
+
);
|
|
17560
|
+
}
|
|
17561
|
+
}
|
|
17562
|
+
}
|
|
17563
|
+
function readRealFileOrThrow(root, abs) {
|
|
17564
|
+
let st;
|
|
17565
|
+
try {
|
|
17566
|
+
st = fs.lstatSync(abs);
|
|
17567
|
+
} catch {
|
|
17568
|
+
return null;
|
|
17569
|
+
}
|
|
17570
|
+
const bytes = st.isFile() ? readFileNoFollow(root, abs) : null;
|
|
17571
|
+
if (!bytes) {
|
|
17572
|
+
throw expected(
|
|
17573
|
+
`${path.relative(path.dirname(root), abs)} is a symlink (or reached through one). The CLI never reads or writes workspace config through a symlink \u2014 make it a real file.`
|
|
17574
|
+
);
|
|
17575
|
+
}
|
|
17576
|
+
return bytes.toString("utf-8");
|
|
17577
|
+
}
|
|
17578
|
+
function readFileNoFollow(root, abs) {
|
|
17579
|
+
if (!ensureRealSubdirNoSymlink(root, path.dirname(abs), false)) return null;
|
|
17580
|
+
try {
|
|
17581
|
+
if (!fs.lstatSync(abs).isFile()) return null;
|
|
17582
|
+
return fs.readFileSync(abs);
|
|
17583
|
+
} catch {
|
|
17584
|
+
return null;
|
|
17585
|
+
}
|
|
17586
|
+
}
|
|
17587
|
+
function writeFileNoFollow(root, abs, data) {
|
|
17588
|
+
const parent = path.dirname(abs);
|
|
17589
|
+
if (!ensureRealSubdirNoSymlink(root, parent, true)) return false;
|
|
17590
|
+
let st;
|
|
17591
|
+
try {
|
|
17592
|
+
st = fs.lstatSync(abs);
|
|
17593
|
+
} catch {
|
|
17594
|
+
}
|
|
17595
|
+
if (st?.isSymbolicLink()) fs.rmSync(abs);
|
|
17596
|
+
fs.writeFileSync(abs, data);
|
|
17597
|
+
return true;
|
|
17598
|
+
}
|
|
17599
|
+
function createFileNoFollow(root, abs, data) {
|
|
17600
|
+
if (!ensureRealSubdirNoSymlink(root, path.dirname(abs), true)) return "refused";
|
|
17601
|
+
try {
|
|
17602
|
+
fs.writeFileSync(abs, data, { flag: "wx" });
|
|
17603
|
+
} catch (err) {
|
|
17604
|
+
if (err.code === "EEXIST") return "exists";
|
|
17605
|
+
throw err;
|
|
17606
|
+
}
|
|
17607
|
+
return "created";
|
|
17608
|
+
}
|
|
17609
|
+
var HUB_MANAGED_SUBDIRS, HUB_CONFIG_FILES;
|
|
17610
|
+
var init_fs_safety = __esm({
|
|
17611
|
+
"src/lib/fs-safety.ts"() {
|
|
17612
|
+
"use strict";
|
|
17613
|
+
init_expected();
|
|
17614
|
+
HUB_MANAGED_SUBDIRS = ["agents", "evals", "journeys", "resources", "attachments"];
|
|
17615
|
+
HUB_CONFIG_FILES = ["hub.yaml", "wayai.yaml"];
|
|
17616
|
+
}
|
|
17617
|
+
});
|
|
17618
|
+
|
|
17619
|
+
// src/lib/layout.ts
|
|
17620
|
+
import * as fs2 from "fs";
|
|
17621
|
+
import * as path2 from "path";
|
|
17461
17622
|
function isDirectory(p) {
|
|
17462
17623
|
try {
|
|
17463
|
-
return
|
|
17624
|
+
return fs2.statSync(p).isDirectory();
|
|
17625
|
+
} catch {
|
|
17626
|
+
return false;
|
|
17627
|
+
}
|
|
17628
|
+
}
|
|
17629
|
+
function isRealDirectory(p) {
|
|
17630
|
+
try {
|
|
17631
|
+
return fs2.lstatSync(p).isDirectory();
|
|
17464
17632
|
} catch {
|
|
17465
17633
|
return false;
|
|
17466
17634
|
}
|
|
17467
17635
|
}
|
|
17468
17636
|
function resolveLayout(gitRoot, layout = WAYAI_LAYOUT) {
|
|
17469
|
-
const newWs =
|
|
17470
|
-
const legacyWs =
|
|
17471
|
-
const legacyOrg =
|
|
17472
|
-
const legacyExists =
|
|
17473
|
-
const basesDir =
|
|
17474
|
-
const hubsDir =
|
|
17475
|
-
const orgDir =
|
|
17637
|
+
const newWs = path2.join(gitRoot, layout.wsDir);
|
|
17638
|
+
const legacyWs = path2.join(gitRoot, layout.legacy.wsDir);
|
|
17639
|
+
const legacyOrg = path2.join(gitRoot, layout.legacy.orgAtRoot);
|
|
17640
|
+
const legacyExists = isRealDirectory(legacyWs) || isRealDirectory(legacyOrg);
|
|
17641
|
+
const basesDir = path2.join(newWs, layout.basesSubdir);
|
|
17642
|
+
const hubsDir = path2.join(newWs, layout.hubsSubdir);
|
|
17643
|
+
const orgDir = path2.join(newWs, layout.orgSubdir);
|
|
17476
17644
|
const newDisplacesLegacy = () => isDirectory(hubsDir) || isDirectory(orgDir) || isDirectory(basesDir);
|
|
17645
|
+
let resolved;
|
|
17477
17646
|
if (legacyExists && !newDisplacesLegacy()) {
|
|
17478
|
-
|
|
17647
|
+
resolved = { hubsDir: legacyWs, orgDir: legacyOrg, basesDir, isLegacy: true, legacyAlsoPresent: false };
|
|
17648
|
+
} else {
|
|
17649
|
+
resolved = { hubsDir, orgDir, basesDir, isLegacy: false, legacyAlsoPresent: legacyExists };
|
|
17650
|
+
}
|
|
17651
|
+
for (const dir of [resolved.hubsDir, resolved.orgDir, resolved.basesDir]) {
|
|
17652
|
+
requireRealSubdirNoSymlink(gitRoot, dir, false);
|
|
17479
17653
|
}
|
|
17480
|
-
return
|
|
17654
|
+
return resolved;
|
|
17481
17655
|
}
|
|
17482
17656
|
function resolveBasesDir(gitRoot) {
|
|
17483
17657
|
return resolveLayout(gitRoot).basesDir;
|
|
17484
17658
|
}
|
|
17485
17659
|
function hubsDirLabel(gitRoot) {
|
|
17486
|
-
if (!gitRoot) return
|
|
17487
|
-
return
|
|
17660
|
+
if (!gitRoot) return path2.join(WAYAI_LAYOUT.wsDir, WAYAI_LAYOUT.hubsSubdir);
|
|
17661
|
+
return path2.relative(gitRoot, resolveLayout(gitRoot).hubsDir);
|
|
17488
17662
|
}
|
|
17489
17663
|
function basesDirLabel(gitRoot) {
|
|
17490
|
-
if (!gitRoot) return
|
|
17491
|
-
return
|
|
17664
|
+
if (!gitRoot) return path2.join(WAYAI_LAYOUT.wsDir, WAYAI_LAYOUT.basesSubdir);
|
|
17665
|
+
return path2.relative(gitRoot, resolveLayout(gitRoot).basesDir);
|
|
17492
17666
|
}
|
|
17493
17667
|
function warnLayoutOnce(gitRoot) {
|
|
17494
17668
|
const r = resolveLayout(gitRoot);
|
|
@@ -17516,6 +17690,7 @@ var init_layout = __esm({
|
|
|
17516
17690
|
"src/lib/layout.ts"() {
|
|
17517
17691
|
"use strict";
|
|
17518
17692
|
init_dist();
|
|
17693
|
+
init_fs_safety();
|
|
17519
17694
|
WAYAI_LAYOUT = {
|
|
17520
17695
|
...WAYAI_WORKSPACE_LAYOUT,
|
|
17521
17696
|
legacy: { wsDir: "workspace", orgAtRoot: "org" }
|
|
@@ -17550,8 +17725,8 @@ __export(workspace_exports, {
|
|
|
17550
17725
|
scanWorkspaceHubs: () => scanWorkspaceHubs
|
|
17551
17726
|
});
|
|
17552
17727
|
import { execFileSync } from "child_process";
|
|
17553
|
-
import * as
|
|
17554
|
-
import * as
|
|
17728
|
+
import * as fs3 from "fs";
|
|
17729
|
+
import * as path3 from "path";
|
|
17555
17730
|
import * as yaml from "js-yaml";
|
|
17556
17731
|
function findGitRoot() {
|
|
17557
17732
|
try {
|
|
@@ -17566,8 +17741,8 @@ function findGitRoot() {
|
|
|
17566
17741
|
function findRepoRootSync() {
|
|
17567
17742
|
let current = process.cwd();
|
|
17568
17743
|
while (true) {
|
|
17569
|
-
if (
|
|
17570
|
-
const parent =
|
|
17744
|
+
if (fs3.existsSync(path3.join(current, ".git"))) return current;
|
|
17745
|
+
const parent = path3.dirname(current);
|
|
17571
17746
|
if (parent === current) return null;
|
|
17572
17747
|
current = parent;
|
|
17573
17748
|
}
|
|
@@ -17576,7 +17751,7 @@ function detectWorkspace() {
|
|
|
17576
17751
|
const gitRoot = findGitRoot();
|
|
17577
17752
|
if (!gitRoot) return null;
|
|
17578
17753
|
const { hubsDir } = resolveLayout(gitRoot);
|
|
17579
|
-
if (!
|
|
17754
|
+
if (!fs3.existsSync(hubsDir) || !fs3.statSync(hubsDir).isDirectory()) {
|
|
17580
17755
|
return null;
|
|
17581
17756
|
}
|
|
17582
17757
|
return { gitRoot, workspaceDir: hubsDir };
|
|
@@ -17592,9 +17767,9 @@ function resolveWorkspaceDir() {
|
|
|
17592
17767
|
return resolveLayout(gitRoot).hubsDir;
|
|
17593
17768
|
}
|
|
17594
17769
|
function readHubYaml(yamlPath) {
|
|
17595
|
-
if (!
|
|
17770
|
+
if (!fs3.existsSync(yamlPath)) return null;
|
|
17596
17771
|
try {
|
|
17597
|
-
const content =
|
|
17772
|
+
const content = fs3.readFileSync(yamlPath, "utf-8");
|
|
17598
17773
|
const config = yaml.load(content);
|
|
17599
17774
|
if (!config?.hub_id || !config.hub_environment) return null;
|
|
17600
17775
|
return { hubId: config.hub_id, hubEnvironment: config.hub_environment };
|
|
@@ -17605,9 +17780,9 @@ function readHubYaml(yamlPath) {
|
|
|
17605
17780
|
function scanWorkspaceHubs(workspaceDir) {
|
|
17606
17781
|
const hubs = [];
|
|
17607
17782
|
for (const top of safeReaddir(workspaceDir)) {
|
|
17608
|
-
const topDir =
|
|
17609
|
-
if (!
|
|
17610
|
-
const meta = readHubYaml(
|
|
17783
|
+
const topDir = path3.join(workspaceDir, top);
|
|
17784
|
+
if (!isRealDirectory(topDir)) continue;
|
|
17785
|
+
const meta = readHubYaml(path3.join(topDir, "hub.yaml")) || readHubYaml(path3.join(topDir, "wayai.yaml"));
|
|
17611
17786
|
if (meta) {
|
|
17612
17787
|
hubs.push({ hubFolder: topDir, hubId: meta.hubId, hubEnvironment: meta.hubEnvironment });
|
|
17613
17788
|
}
|
|
@@ -17621,9 +17796,9 @@ function filterPreviewHubs(hubs) {
|
|
|
17621
17796
|
return hubs.filter(isPreviewHub);
|
|
17622
17797
|
}
|
|
17623
17798
|
function readNewHubYaml(yamlPath) {
|
|
17624
|
-
if (!
|
|
17799
|
+
if (!fs3.existsSync(yamlPath)) return null;
|
|
17625
17800
|
try {
|
|
17626
|
-
const content =
|
|
17801
|
+
const content = fs3.readFileSync(yamlPath, "utf-8");
|
|
17627
17802
|
const config = yaml.load(content);
|
|
17628
17803
|
if (config?.hub_id) return null;
|
|
17629
17804
|
if (!config?.hub?.name) return null;
|
|
@@ -17635,9 +17810,9 @@ function readNewHubYaml(yamlPath) {
|
|
|
17635
17810
|
function scanNewHubs(workspaceDir) {
|
|
17636
17811
|
const hubs = [];
|
|
17637
17812
|
for (const top of safeReaddir(workspaceDir)) {
|
|
17638
|
-
const topDir =
|
|
17639
|
-
if (!
|
|
17640
|
-
const meta = readNewHubYaml(
|
|
17813
|
+
const topDir = path3.join(workspaceDir, top);
|
|
17814
|
+
if (!isRealDirectory(topDir)) continue;
|
|
17815
|
+
const meta = readNewHubYaml(path3.join(topDir, "hub.yaml")) || readNewHubYaml(path3.join(topDir, "wayai.yaml"));
|
|
17641
17816
|
if (meta) {
|
|
17642
17817
|
hubs.push({ hubFolder: topDir, hubName: meta.hubName, hubType: meta.hubType });
|
|
17643
17818
|
}
|
|
@@ -17657,22 +17832,22 @@ function resolveHubFolder(workspaceDir, hubId, hubName, hubEnvironment, previewL
|
|
|
17657
17832
|
if (match) return match.hubFolder;
|
|
17658
17833
|
}
|
|
17659
17834
|
const hubFolderSlug = getHubFolderSlug(hubName, hubEnvironment, hubId || "", previewLabel, branchName);
|
|
17660
|
-
return
|
|
17835
|
+
return path3.join(workspaceDir, hubFolderSlug);
|
|
17661
17836
|
}
|
|
17662
17837
|
function findLocalHubFolder(hubId) {
|
|
17663
17838
|
const workspace = detectWorkspace();
|
|
17664
17839
|
const gitRoot = findGitRoot();
|
|
17665
17840
|
const workspaceDir = workspace?.workspaceDir ?? (gitRoot ? resolveLayout(gitRoot).hubsDir : null);
|
|
17666
|
-
if (!workspaceDir || !
|
|
17841
|
+
if (!workspaceDir || !fs3.existsSync(workspaceDir)) return null;
|
|
17667
17842
|
const match = scanWorkspaceHubs(workspaceDir).find((h) => h.hubId === hubId);
|
|
17668
17843
|
return match ? match.hubFolder : null;
|
|
17669
17844
|
}
|
|
17670
17845
|
function getChangedHubs(workspaceDir) {
|
|
17671
17846
|
const gitRoot = findGitRoot();
|
|
17672
17847
|
if (!gitRoot) return [];
|
|
17673
|
-
const relWorkspace =
|
|
17674
|
-
const normalizedRel =
|
|
17675
|
-
if (normalizedRel.startsWith("..") ||
|
|
17848
|
+
const relWorkspace = path3.relative(gitRoot, workspaceDir);
|
|
17849
|
+
const normalizedRel = path3.normalize(relWorkspace);
|
|
17850
|
+
if (normalizedRel.startsWith("..") || path3.isAbsolute(normalizedRel)) {
|
|
17676
17851
|
return [];
|
|
17677
17852
|
}
|
|
17678
17853
|
let statusOutput;
|
|
@@ -17697,9 +17872,9 @@ function getChangedHubs(workspaceDir) {
|
|
|
17697
17872
|
if (hubFiles.length === 0) return [];
|
|
17698
17873
|
const hubFolders = /* @__PURE__ */ new Set();
|
|
17699
17874
|
for (const file of hubFiles) {
|
|
17700
|
-
const absFile =
|
|
17875
|
+
const absFile = path3.resolve(gitRoot, file);
|
|
17701
17876
|
if (file.endsWith("hub.yaml") || file.endsWith("wayai.yaml")) {
|
|
17702
|
-
hubFolders.add(
|
|
17877
|
+
hubFolders.add(path3.dirname(absFile));
|
|
17703
17878
|
} else if (file.includes("/agents/")) {
|
|
17704
17879
|
const agentsIndex = absFile.lastIndexOf("/agents/");
|
|
17705
17880
|
hubFolders.add(absFile.substring(0, agentsIndex));
|
|
@@ -17707,7 +17882,7 @@ function getChangedHubs(workspaceDir) {
|
|
|
17707
17882
|
}
|
|
17708
17883
|
const hubs = [];
|
|
17709
17884
|
for (const hubFolder of hubFolders) {
|
|
17710
|
-
const meta = readHubYaml(
|
|
17885
|
+
const meta = readHubYaml(path3.join(hubFolder, "hub.yaml")) || readHubYaml(path3.join(hubFolder, "wayai.yaml"));
|
|
17711
17886
|
if (meta) {
|
|
17712
17887
|
hubs.push({ hubFolder, hubId: meta.hubId, hubEnvironment: meta.hubEnvironment });
|
|
17713
17888
|
}
|
|
@@ -17742,19 +17917,19 @@ function resolveExplicitHubPath(hubPath) {
|
|
|
17742
17917
|
}
|
|
17743
17918
|
function findHubByFolderName(workspaceDir, hubFolderName) {
|
|
17744
17919
|
const all = scanWorkspaceHubs(workspaceDir);
|
|
17745
|
-
return all.find((h) =>
|
|
17920
|
+
return all.find((h) => path3.basename(h.hubFolder) === hubFolderName) ?? null;
|
|
17746
17921
|
}
|
|
17747
17922
|
function autoRenameHubFolder(currentFolder, hubName, hubEnvironment, hubId, previewLabel, branchName) {
|
|
17748
17923
|
const expectedSlug = getHubFolderSlug(hubName, hubEnvironment, hubId, previewLabel, branchName);
|
|
17749
|
-
const currentSlug =
|
|
17924
|
+
const currentSlug = path3.basename(currentFolder);
|
|
17750
17925
|
if (currentSlug === expectedSlug) return currentFolder;
|
|
17751
|
-
const targetFolder =
|
|
17752
|
-
if (
|
|
17926
|
+
const targetFolder = path3.join(path3.dirname(currentFolder), expectedSlug);
|
|
17927
|
+
if (fs3.existsSync(targetFolder)) {
|
|
17753
17928
|
console.warn(` Warning: skipping hub folder rename ${currentSlug} \u2192 ${expectedSlug} (target already exists)`);
|
|
17754
17929
|
return currentFolder;
|
|
17755
17930
|
}
|
|
17756
17931
|
try {
|
|
17757
|
-
|
|
17932
|
+
fs3.renameSync(currentFolder, targetFolder);
|
|
17758
17933
|
} catch (err) {
|
|
17759
17934
|
console.warn(` Warning: could not rename ${currentSlug} \u2192 ${expectedSlug}: ${err instanceof Error ? err.message : String(err)}`);
|
|
17760
17935
|
return currentFolder;
|
|
@@ -17765,28 +17940,28 @@ function autoRenameHubFolder(currentFolder, hubName, hubEnvironment, hubId, prev
|
|
|
17765
17940
|
}
|
|
17766
17941
|
function findEnclosingHubFolder(workspaceDir) {
|
|
17767
17942
|
let current = process.cwd();
|
|
17768
|
-
const stop =
|
|
17943
|
+
const stop = path3.resolve(workspaceDir);
|
|
17769
17944
|
while (true) {
|
|
17770
|
-
const meta = readHubYaml(
|
|
17945
|
+
const meta = readHubYaml(path3.join(current, "hub.yaml")) || readHubYaml(path3.join(current, "wayai.yaml"));
|
|
17771
17946
|
if (meta) {
|
|
17772
17947
|
return { hubFolder: current, hubId: meta.hubId, hubEnvironment: meta.hubEnvironment };
|
|
17773
17948
|
}
|
|
17774
17949
|
if (current === stop) return null;
|
|
17775
|
-
const parent =
|
|
17950
|
+
const parent = path3.dirname(current);
|
|
17776
17951
|
if (parent === current) return null;
|
|
17777
17952
|
current = parent;
|
|
17778
17953
|
}
|
|
17779
17954
|
}
|
|
17780
17955
|
function findEnclosingNewHubFolder(workspaceDir) {
|
|
17781
17956
|
let current = process.cwd();
|
|
17782
|
-
const stop =
|
|
17957
|
+
const stop = path3.resolve(workspaceDir);
|
|
17783
17958
|
while (true) {
|
|
17784
|
-
const meta = readNewHubYaml(
|
|
17959
|
+
const meta = readNewHubYaml(path3.join(current, "hub.yaml")) || readNewHubYaml(path3.join(current, "wayai.yaml"));
|
|
17785
17960
|
if (meta) {
|
|
17786
17961
|
return { hubFolder: current, hubName: meta.hubName, hubType: meta.hubType };
|
|
17787
17962
|
}
|
|
17788
17963
|
if (current === stop) return null;
|
|
17789
|
-
const parent =
|
|
17964
|
+
const parent = path3.dirname(current);
|
|
17790
17965
|
if (parent === current) return null;
|
|
17791
17966
|
current = parent;
|
|
17792
17967
|
}
|
|
@@ -17794,10 +17969,10 @@ function findEnclosingNewHubFolder(workspaceDir) {
|
|
|
17794
17969
|
function resolvePushTarget(workspaceDir, existingHubs, newHubs, selector) {
|
|
17795
17970
|
if (selector) {
|
|
17796
17971
|
const existingMatch = existingHubs.find(
|
|
17797
|
-
(h) => h.hubId === selector ||
|
|
17972
|
+
(h) => h.hubId === selector || path3.basename(h.hubFolder) === selector
|
|
17798
17973
|
);
|
|
17799
17974
|
if (existingMatch) return { ok: true, target: { kind: "existing", hub: existingMatch } };
|
|
17800
|
-
const newMatch = newHubs.find((h) =>
|
|
17975
|
+
const newMatch = newHubs.find((h) => path3.basename(h.hubFolder) === selector);
|
|
17801
17976
|
if (newMatch) return { ok: true, target: { kind: "new", hub: newMatch } };
|
|
17802
17977
|
return { ok: false, reason: "selector_miss" };
|
|
17803
17978
|
}
|
|
@@ -17813,10 +17988,10 @@ function resolvePushTarget(workspaceDir, existingHubs, newHubs, selector) {
|
|
|
17813
17988
|
}
|
|
17814
17989
|
function resolveNewHubForCreate(workspaceDir, existingHubs, newHubs, selector) {
|
|
17815
17990
|
if (selector) {
|
|
17816
|
-
const newMatch = newHubs.find((h) =>
|
|
17991
|
+
const newMatch = newHubs.find((h) => path3.basename(h.hubFolder) === selector);
|
|
17817
17992
|
if (newMatch) return { ok: true, hub: newMatch };
|
|
17818
17993
|
const existingMatch = existingHubs.find(
|
|
17819
|
-
(h) => h.hubId === selector ||
|
|
17994
|
+
(h) => h.hubId === selector || path3.basename(h.hubFolder) === selector
|
|
17820
17995
|
);
|
|
17821
17996
|
if (existingMatch) return { ok: false, reason: "exists", existing: existingMatch };
|
|
17822
17997
|
return { ok: false, reason: "selector_miss" };
|
|
@@ -17843,7 +18018,7 @@ function resolveActiveHubId(args2) {
|
|
|
17843
18018
|
const gitRoot = findGitRoot();
|
|
17844
18019
|
const workspaceDir = workspace?.workspaceDir ?? (gitRoot ? resolveLayout(gitRoot).hubsDir : null);
|
|
17845
18020
|
const wsLabel = hubsDirLabel(gitRoot);
|
|
17846
|
-
if (!workspaceDir || !
|
|
18021
|
+
if (!workspaceDir || !fs3.existsSync(workspaceDir)) {
|
|
17847
18022
|
if (selector && UUID_RE2.test(selector)) return selector;
|
|
17848
18023
|
console.error(`No ${wsLabel}/ directory found. Run \`wayai pull --hub <uuid>\` to fetch a hub, or pass --hub <uuid>.`);
|
|
17849
18024
|
process.exit(1);
|
|
@@ -17851,7 +18026,7 @@ function resolveActiveHubId(args2) {
|
|
|
17851
18026
|
const allHubs = scanWorkspaceHubs(workspaceDir);
|
|
17852
18027
|
if (selector) {
|
|
17853
18028
|
const match = allHubs.find(
|
|
17854
|
-
(h) => h.hubId === selector ||
|
|
18029
|
+
(h) => h.hubId === selector || path3.basename(h.hubFolder) === selector
|
|
17855
18030
|
);
|
|
17856
18031
|
if (match) return match.hubId;
|
|
17857
18032
|
if (UUID_RE2.test(selector)) return selector;
|
|
@@ -17868,7 +18043,7 @@ function resolveActiveHubId(args2) {
|
|
|
17868
18043
|
}
|
|
17869
18044
|
console.error(`Multiple hubs in ${wsLabel}/. Pass --hub <uuid|folder-name> or run from inside a hub folder:`);
|
|
17870
18045
|
for (const h of previewHubs) {
|
|
17871
|
-
console.error(` ${
|
|
18046
|
+
console.error(` ${path3.basename(h.hubFolder)} (${h.hubId})`);
|
|
17872
18047
|
}
|
|
17873
18048
|
process.exit(1);
|
|
17874
18049
|
}
|
|
@@ -17876,12 +18051,12 @@ function localHubEnvironment(hubId) {
|
|
|
17876
18051
|
const workspace = detectWorkspace();
|
|
17877
18052
|
const gitRoot = findGitRoot();
|
|
17878
18053
|
const workspaceDir = workspace?.workspaceDir ?? (gitRoot ? resolveLayout(gitRoot).hubsDir : null);
|
|
17879
|
-
if (!workspaceDir || !
|
|
18054
|
+
if (!workspaceDir || !fs3.existsSync(workspaceDir)) return null;
|
|
17880
18055
|
return scanWorkspaceHubs(workspaceDir).find((h) => h.hubId === hubId)?.hubEnvironment ?? null;
|
|
17881
18056
|
}
|
|
17882
18057
|
function safeReaddir(dir) {
|
|
17883
18058
|
try {
|
|
17884
|
-
return
|
|
18059
|
+
return fs3.readdirSync(dir).filter((entry) => !entry.startsWith("."));
|
|
17885
18060
|
} catch {
|
|
17886
18061
|
return [];
|
|
17887
18062
|
}
|
|
@@ -17895,19 +18070,19 @@ var init_workspace = __esm({
|
|
|
17895
18070
|
});
|
|
17896
18071
|
|
|
17897
18072
|
// src/lib/workspace-manifest.ts
|
|
17898
|
-
import * as
|
|
17899
|
-
import * as
|
|
18073
|
+
import * as fs4 from "fs";
|
|
18074
|
+
import * as path4 from "path";
|
|
17900
18075
|
import * as yaml2 from "js-yaml";
|
|
17901
18076
|
function workspaceManifestPath(gitRoot) {
|
|
17902
|
-
return
|
|
18077
|
+
return path4.join(gitRoot, WAYAI_LAYOUT.wsDir, WORKSPACE_MANIFEST_FILE);
|
|
17903
18078
|
}
|
|
17904
18079
|
function rootConfigPath(gitRoot) {
|
|
17905
|
-
return
|
|
18080
|
+
return path4.join(gitRoot, ROOT_CONFIG_FILE);
|
|
17906
18081
|
}
|
|
17907
18082
|
function loadYamlMapping(file) {
|
|
17908
18083
|
let raw;
|
|
17909
18084
|
try {
|
|
17910
|
-
raw =
|
|
18085
|
+
raw = fs4.readFileSync(file, "utf-8");
|
|
17911
18086
|
} catch (err) {
|
|
17912
18087
|
if (err.code === "ENOENT") return { kind: "absent" };
|
|
17913
18088
|
return { kind: "malformed", reason: err instanceof Error ? err.message : String(err) };
|
|
@@ -17950,8 +18125,7 @@ __export(repo_config_exports, {
|
|
|
17950
18125
|
resolveRepoConfig: () => resolveRepoConfig,
|
|
17951
18126
|
writeRepoConfig: () => writeRepoConfig
|
|
17952
18127
|
});
|
|
17953
|
-
import * as
|
|
17954
|
-
import * as path4 from "path";
|
|
18128
|
+
import * as path5 from "path";
|
|
17955
18129
|
import * as yaml3 from "js-yaml";
|
|
17956
18130
|
function noticeOnce(key, emit) {
|
|
17957
18131
|
if (noticed.has(key)) return;
|
|
@@ -17989,7 +18163,7 @@ function legacyFieldsIn(load11) {
|
|
|
17989
18163
|
if (load11.kind !== "ok") return [];
|
|
17990
18164
|
return LEGACY_FIELDS.filter((f) => load11.doc[f] !== void 0);
|
|
17991
18165
|
}
|
|
17992
|
-
function
|
|
18166
|
+
function resolve3(gitRoot) {
|
|
17993
18167
|
const manifestFile = workspaceManifestPath(gitRoot);
|
|
17994
18168
|
const manifest = declarationFrom(loadWorkspaceManifest(gitRoot));
|
|
17995
18169
|
if (manifest.kind === "invalid") {
|
|
@@ -18098,7 +18272,7 @@ function report(r, posture) {
|
|
|
18098
18272
|
function resolveRepoConfig(root) {
|
|
18099
18273
|
const gitRoot = root ?? findGitRoot();
|
|
18100
18274
|
if (!gitRoot) return null;
|
|
18101
|
-
const r =
|
|
18275
|
+
const r = resolve3(gitRoot);
|
|
18102
18276
|
report(r, "soft");
|
|
18103
18277
|
return r.kind === "ok" ? r.resolved : null;
|
|
18104
18278
|
}
|
|
@@ -18108,7 +18282,7 @@ function readRepoConfig(root) {
|
|
|
18108
18282
|
function readRepoConfigUnlessBlocked(root) {
|
|
18109
18283
|
const gitRoot = root ?? findGitRoot();
|
|
18110
18284
|
if (!gitRoot) return null;
|
|
18111
|
-
const r =
|
|
18285
|
+
const r = resolve3(gitRoot);
|
|
18112
18286
|
switch (r.kind) {
|
|
18113
18287
|
case "ok":
|
|
18114
18288
|
report(r, "soft");
|
|
@@ -18123,7 +18297,7 @@ function readRepoConfigUnlessBlocked(root) {
|
|
|
18123
18297
|
}
|
|
18124
18298
|
function requireRepoConfig(root) {
|
|
18125
18299
|
const gitRoot = root ?? findGitRoot();
|
|
18126
|
-
const r = gitRoot ?
|
|
18300
|
+
const r = gitRoot ? resolve3(gitRoot) : { kind: "none" };
|
|
18127
18301
|
report(r, "hard");
|
|
18128
18302
|
if (r.kind === "ok") return r.resolved.config;
|
|
18129
18303
|
return process.exit(1);
|
|
@@ -18131,7 +18305,7 @@ function requireRepoConfig(root) {
|
|
|
18131
18305
|
function readRepoScopeBlocker(root) {
|
|
18132
18306
|
const gitRoot = root ?? findGitRoot();
|
|
18133
18307
|
if (!gitRoot) return null;
|
|
18134
|
-
const r =
|
|
18308
|
+
const r = resolve3(gitRoot);
|
|
18135
18309
|
if (r.kind === "conflict") {
|
|
18136
18310
|
return {
|
|
18137
18311
|
kind: "conflict",
|
|
@@ -18168,6 +18342,7 @@ function writeRepoConfig(config, root) {
|
|
|
18168
18342
|
if (!gitRoot) {
|
|
18169
18343
|
throw expected("Not inside a git repository. Run `git init` first.");
|
|
18170
18344
|
}
|
|
18345
|
+
readRealFileOrThrow(gitRoot, workspaceManifestPath(gitRoot));
|
|
18171
18346
|
const stale = declarationFrom(loadYamlMapping(rootConfigPath(gitRoot)));
|
|
18172
18347
|
if (stale.kind === "declared" && stale.config.organization_id !== config.organization_id) {
|
|
18173
18348
|
throw expected(rebindRefusal(config.organization_id, stale.config.organization_id));
|
|
@@ -18183,12 +18358,8 @@ function writeRepoConfig(config, root) {
|
|
|
18183
18358
|
if (config.organization_name?.trim()) doc.organization_name = config.organization_name.trim();
|
|
18184
18359
|
Object.assign(doc, rest);
|
|
18185
18360
|
const file = workspaceManifestPath(gitRoot);
|
|
18186
|
-
|
|
18187
|
-
|
|
18188
|
-
file,
|
|
18189
|
-
yaml3.dump(doc, { lineWidth: -1, quotingType: '"', forceQuotes: false }),
|
|
18190
|
-
"utf-8"
|
|
18191
|
-
);
|
|
18361
|
+
requireRealSubdirNoSymlink(gitRoot, path5.dirname(file), true);
|
|
18362
|
+
writeFileNoFollow(gitRoot, file, Buffer.from(yaml3.dump(doc, { lineWidth: -1, quotingType: '"', forceQuotes: false }), "utf-8"));
|
|
18192
18363
|
return file;
|
|
18193
18364
|
}
|
|
18194
18365
|
var LEGACY_FIELDS, noticed, RECONCILE_REMEDY;
|
|
@@ -18196,6 +18367,7 @@ var init_repo_config = __esm({
|
|
|
18196
18367
|
"src/lib/repo-config.ts"() {
|
|
18197
18368
|
"use strict";
|
|
18198
18369
|
init_expected();
|
|
18370
|
+
init_fs_safety();
|
|
18199
18371
|
init_workspace();
|
|
18200
18372
|
init_utils();
|
|
18201
18373
|
init_workspace_manifest();
|
|
@@ -18210,7 +18382,7 @@ var init_repo_config = __esm({
|
|
|
18210
18382
|
|
|
18211
18383
|
// src/lib/utils.ts
|
|
18212
18384
|
import * as fs5 from "fs";
|
|
18213
|
-
import * as
|
|
18385
|
+
import * as path6 from "path";
|
|
18214
18386
|
import * as readline from "readline";
|
|
18215
18387
|
function prompt(question) {
|
|
18216
18388
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -18264,7 +18436,7 @@ function readStdin() {
|
|
|
18264
18436
|
}
|
|
18265
18437
|
function resolveHubYamlPath(hubFolder) {
|
|
18266
18438
|
for (const filename of ["hub.yaml", "wayai.yaml"]) {
|
|
18267
|
-
const yamlPath =
|
|
18439
|
+
const yamlPath = path6.join(hubFolder, filename);
|
|
18268
18440
|
if (fs5.existsSync(yamlPath)) return yamlPath;
|
|
18269
18441
|
}
|
|
18270
18442
|
return null;
|
|
@@ -18730,17 +18902,17 @@ var init_registry = __esm({
|
|
|
18730
18902
|
});
|
|
18731
18903
|
|
|
18732
18904
|
// src/lib/version-cache.ts
|
|
18733
|
-
import { existsSync as existsSync3, readFileSync as
|
|
18734
|
-
import { dirname as
|
|
18905
|
+
import { existsSync as existsSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
18906
|
+
import { dirname as dirname5, join as join7 } from "path";
|
|
18735
18907
|
import { homedir as homedir2 } from "os";
|
|
18736
18908
|
function getVersionCachePath(filename = CLI_CACHE_FILE) {
|
|
18737
|
-
return
|
|
18909
|
+
return join7(homedir2(), ".wayai", filename);
|
|
18738
18910
|
}
|
|
18739
18911
|
function readVersionCache(filename = CLI_CACHE_FILE) {
|
|
18740
18912
|
try {
|
|
18741
18913
|
const path35 = getVersionCachePath(filename);
|
|
18742
18914
|
if (!existsSync3(path35)) return null;
|
|
18743
|
-
const parsed = JSON.parse(
|
|
18915
|
+
const parsed = JSON.parse(readFileSync6(path35, "utf-8"));
|
|
18744
18916
|
if (typeof parsed.lastCheck !== "number") return null;
|
|
18745
18917
|
if (parsed.latest !== null && typeof parsed.latest !== "string") return null;
|
|
18746
18918
|
return parsed;
|
|
@@ -18761,7 +18933,7 @@ function isVersionCacheStale(filename = CLI_CACHE_FILE, maxAgeMs = MAX_AGE_24H_M
|
|
|
18761
18933
|
}
|
|
18762
18934
|
function writeVersionCache(filename, cache) {
|
|
18763
18935
|
const path35 = getVersionCachePath(filename);
|
|
18764
|
-
const dir =
|
|
18936
|
+
const dir = dirname5(path35);
|
|
18765
18937
|
if (!existsSync3(dir)) mkdirSync2(dir, { recursive: true });
|
|
18766
18938
|
writeFileSync2(path35, JSON.stringify(cache));
|
|
18767
18939
|
}
|
|
@@ -18780,8 +18952,8 @@ var init_version_cache = __esm({
|
|
|
18780
18952
|
});
|
|
18781
18953
|
|
|
18782
18954
|
// src/lib/skill-version.ts
|
|
18783
|
-
import { existsSync as existsSync4, readFileSync as
|
|
18784
|
-
import { join as
|
|
18955
|
+
import { existsSync as existsSync4, readFileSync as readFileSync7 } from "fs";
|
|
18956
|
+
import { join as join8 } from "path";
|
|
18785
18957
|
import * as yaml4 from "js-yaml";
|
|
18786
18958
|
function skillInstallPaths(skillName) {
|
|
18787
18959
|
return HARNESS_SKILL_DIRS.map((dir) => `${dir}/skills/${skillName}/${SKILL_FILENAME}`);
|
|
@@ -18802,11 +18974,11 @@ function parseFrontmatterVersion(content) {
|
|
|
18802
18974
|
function findInstalledSkills(projectRoot, paths = SKILL_INSTALL_PATHS) {
|
|
18803
18975
|
const found = [];
|
|
18804
18976
|
for (const rel of paths) {
|
|
18805
|
-
const path35 =
|
|
18977
|
+
const path35 = join8(projectRoot, rel);
|
|
18806
18978
|
if (!existsSync4(path35)) continue;
|
|
18807
18979
|
let version = null;
|
|
18808
18980
|
try {
|
|
18809
|
-
version = parseFrontmatterVersion(
|
|
18981
|
+
version = parseFrontmatterVersion(readFileSync7(path35, "utf-8"));
|
|
18810
18982
|
} catch {
|
|
18811
18983
|
}
|
|
18812
18984
|
found.push({ path: path35, version });
|
|
@@ -18841,13 +19013,13 @@ __export(config_exports, {
|
|
|
18841
19013
|
writeConfig: () => writeConfig
|
|
18842
19014
|
});
|
|
18843
19015
|
import * as fs6 from "fs";
|
|
18844
|
-
import * as
|
|
19016
|
+
import * as path7 from "path";
|
|
18845
19017
|
import * as os from "os";
|
|
18846
19018
|
function configDir() {
|
|
18847
|
-
return
|
|
19019
|
+
return path7.join(os.homedir(), ".wayai");
|
|
18848
19020
|
}
|
|
18849
19021
|
function configPath() {
|
|
18850
|
-
return
|
|
19022
|
+
return path7.join(configDir(), "config.json");
|
|
18851
19023
|
}
|
|
18852
19024
|
function getConfigPath() {
|
|
18853
19025
|
return configPath();
|
|
@@ -18900,13 +19072,13 @@ var init_config = __esm({
|
|
|
18900
19072
|
|
|
18901
19073
|
// src/lib/token-store.ts
|
|
18902
19074
|
import * as fs7 from "fs";
|
|
18903
|
-
import * as
|
|
19075
|
+
import * as path8 from "path";
|
|
18904
19076
|
import * as os2 from "os";
|
|
18905
19077
|
function configDir2() {
|
|
18906
|
-
return
|
|
19078
|
+
return path8.join(os2.homedir(), ".wayai");
|
|
18907
19079
|
}
|
|
18908
19080
|
function configPath2() {
|
|
18909
|
-
return
|
|
19081
|
+
return path8.join(configDir2(), "config.json");
|
|
18910
19082
|
}
|
|
18911
19083
|
function manualCleanupCommand(account) {
|
|
18912
19084
|
if (process.platform === "darwin") {
|
|
@@ -19406,26 +19578,26 @@ __export(skill_symlink_exports, {
|
|
|
19406
19578
|
healClaudeSkillLink: () => healClaudeSkillLink,
|
|
19407
19579
|
healSkillLinkForCommand: () => healSkillLinkForCommand
|
|
19408
19580
|
});
|
|
19409
|
-
import { existsSync as existsSync7, lstatSync, mkdirSync as mkdirSync5, rmSync, symlinkSync } from "fs";
|
|
19410
|
-
import { join as
|
|
19581
|
+
import { existsSync as existsSync7, lstatSync as lstatSync3, mkdirSync as mkdirSync5, rmSync as rmSync2, symlinkSync } from "fs";
|
|
19582
|
+
import { join as join11 } from "path";
|
|
19411
19583
|
function healClaudeSkillLink(root) {
|
|
19412
19584
|
try {
|
|
19413
|
-
const source =
|
|
19414
|
-
if (!existsSync7(
|
|
19415
|
-
const link =
|
|
19416
|
-
if (existsSync7(
|
|
19585
|
+
const source = join11(root, ".agents", "skills", SKILL_NAME);
|
|
19586
|
+
if (!existsSync7(join11(source, SKILL_FILENAME))) return false;
|
|
19587
|
+
const link = join11(root, ".claude", "skills", SKILL_NAME);
|
|
19588
|
+
if (existsSync7(join11(link, SKILL_FILENAME))) return false;
|
|
19417
19589
|
let entry = null;
|
|
19418
19590
|
try {
|
|
19419
|
-
entry =
|
|
19591
|
+
entry = lstatSync3(link);
|
|
19420
19592
|
} catch {
|
|
19421
19593
|
entry = null;
|
|
19422
19594
|
}
|
|
19423
19595
|
if (entry) {
|
|
19424
19596
|
if (!entry.isSymbolicLink()) return false;
|
|
19425
|
-
|
|
19597
|
+
rmSync2(link, { force: true });
|
|
19426
19598
|
}
|
|
19427
|
-
mkdirSync5(
|
|
19428
|
-
symlinkSync(
|
|
19599
|
+
mkdirSync5(join11(root, ".claude", "skills"), { recursive: true });
|
|
19600
|
+
symlinkSync(join11("..", "..", ".agents", "skills", SKILL_NAME), link, "dir");
|
|
19429
19601
|
return true;
|
|
19430
19602
|
} catch {
|
|
19431
19603
|
return false;
|
|
@@ -19709,7 +19881,7 @@ var init_base_id = __esm({
|
|
|
19709
19881
|
// src/lib/worktree-scope.ts
|
|
19710
19882
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
19711
19883
|
import * as fs8 from "fs";
|
|
19712
|
-
import * as
|
|
19884
|
+
import * as path9 from "path";
|
|
19713
19885
|
import * as yaml5 from "js-yaml";
|
|
19714
19886
|
function axisNoun(axis) {
|
|
19715
19887
|
return AXES[axis].noun;
|
|
@@ -19724,7 +19896,7 @@ function resolveGitDir() {
|
|
|
19724
19896
|
encoding: "utf-8",
|
|
19725
19897
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19726
19898
|
}).trim();
|
|
19727
|
-
gitDir = raw ?
|
|
19899
|
+
gitDir = raw ? path9.resolve(cwd, raw) : null;
|
|
19728
19900
|
} catch {
|
|
19729
19901
|
gitDir = null;
|
|
19730
19902
|
}
|
|
@@ -19733,12 +19905,12 @@ function resolveGitDir() {
|
|
|
19733
19905
|
}
|
|
19734
19906
|
function getScopePath() {
|
|
19735
19907
|
const gitDir = resolveGitDir();
|
|
19736
|
-
return gitDir ?
|
|
19908
|
+
return gitDir ? path9.join(gitDir, SCOPE_FILE) : null;
|
|
19737
19909
|
}
|
|
19738
19910
|
function legacyPaths() {
|
|
19739
19911
|
const gitDir = resolveGitDir();
|
|
19740
19912
|
if (!gitDir) return [];
|
|
19741
|
-
return AXIS_ORDER.flatMap((axis) => AXES[axis].legacyFiles).map((f) =>
|
|
19913
|
+
return AXIS_ORDER.flatMap((axis) => AXES[axis].legacyFiles).map((f) => path9.join(gitDir, f));
|
|
19742
19914
|
}
|
|
19743
19915
|
function emptyScope() {
|
|
19744
19916
|
return { hubs: [], bases: [] };
|
|
@@ -19762,7 +19934,7 @@ function readLegacyAxis(axis) {
|
|
|
19762
19934
|
for (const filename of legacyFiles) {
|
|
19763
19935
|
let raw;
|
|
19764
19936
|
try {
|
|
19765
|
-
raw = fs8.readFileSync(
|
|
19937
|
+
raw = fs8.readFileSync(path9.join(gitDir, filename), "utf-8");
|
|
19766
19938
|
} catch (err) {
|
|
19767
19939
|
if (err.code === "ENOENT") continue;
|
|
19768
19940
|
throw err;
|
|
@@ -19982,8 +20154,13 @@ function buildSkillState() {
|
|
|
19982
20154
|
}
|
|
19983
20155
|
function buildWorkspaceState(resolved) {
|
|
19984
20156
|
if (!resolved) return { scoped: false, path: null, hub_count: 0 };
|
|
19985
|
-
|
|
19986
|
-
|
|
20157
|
+
let hubCount = 0;
|
|
20158
|
+
try {
|
|
20159
|
+
const ws = detectWorkspace();
|
|
20160
|
+
hubCount = ws ? scanWorkspaceHubs(ws.workspaceDir).length : 0;
|
|
20161
|
+
} catch {
|
|
20162
|
+
hubCount = 0;
|
|
20163
|
+
}
|
|
19987
20164
|
return { scoped: true, path: resolved.path, hub_count: hubCount };
|
|
19988
20165
|
}
|
|
19989
20166
|
async function statusCommand(args2, pkg2) {
|
|
@@ -20221,12 +20398,12 @@ __export(init_exports, {
|
|
|
20221
20398
|
parseArgs: () => parseArgs3
|
|
20222
20399
|
});
|
|
20223
20400
|
import { mkdirSync as mkdirSync6 } from "fs";
|
|
20224
|
-
import
|
|
20401
|
+
import path10 from "path";
|
|
20225
20402
|
function ensureHubsDir(gitRoot) {
|
|
20226
20403
|
const hubsDir = resolveLayout(gitRoot).hubsDir;
|
|
20227
20404
|
if (isDirectory(hubsDir)) return null;
|
|
20228
20405
|
mkdirSync6(hubsDir, { recursive: true });
|
|
20229
|
-
return `${
|
|
20406
|
+
return `${path10.relative(gitRoot, hubsDir)}/`;
|
|
20230
20407
|
}
|
|
20231
20408
|
function parseArgs3(args2) {
|
|
20232
20409
|
let orgId;
|
|
@@ -20355,108 +20532,8 @@ var init_init = __esm({
|
|
|
20355
20532
|
}
|
|
20356
20533
|
});
|
|
20357
20534
|
|
|
20358
|
-
// src/lib/fs-safety.ts
|
|
20359
|
-
import * as fs9 from "fs";
|
|
20360
|
-
import * as path10 from "path";
|
|
20361
|
-
function fileHasBytes(abs, data) {
|
|
20362
|
-
let st;
|
|
20363
|
-
try {
|
|
20364
|
-
st = fs9.lstatSync(abs);
|
|
20365
|
-
} catch {
|
|
20366
|
-
return false;
|
|
20367
|
-
}
|
|
20368
|
-
if (!st.isFile() || st.isSymbolicLink()) return false;
|
|
20369
|
-
try {
|
|
20370
|
-
return fs9.readFileSync(abs).equals(data);
|
|
20371
|
-
} catch {
|
|
20372
|
-
return false;
|
|
20373
|
-
}
|
|
20374
|
-
}
|
|
20375
|
-
function realpathContained(root, abs) {
|
|
20376
|
-
let realRoot;
|
|
20377
|
-
let realAbs;
|
|
20378
|
-
try {
|
|
20379
|
-
realRoot = fs9.realpathSync(root);
|
|
20380
|
-
realAbs = fs9.realpathSync(abs);
|
|
20381
|
-
} catch {
|
|
20382
|
-
return false;
|
|
20383
|
-
}
|
|
20384
|
-
return realAbs === realRoot || realAbs.startsWith(realRoot + path10.sep);
|
|
20385
|
-
}
|
|
20386
|
-
function mkdirTolerateRace(dir) {
|
|
20387
|
-
try {
|
|
20388
|
-
fs9.mkdirSync(dir);
|
|
20389
|
-
return true;
|
|
20390
|
-
} catch (err) {
|
|
20391
|
-
if (err.code !== "EEXIST") throw err;
|
|
20392
|
-
let st;
|
|
20393
|
-
try {
|
|
20394
|
-
st = fs9.lstatSync(dir);
|
|
20395
|
-
} catch {
|
|
20396
|
-
st = void 0;
|
|
20397
|
-
}
|
|
20398
|
-
return !!st?.isDirectory();
|
|
20399
|
-
}
|
|
20400
|
-
}
|
|
20401
|
-
function ensureRealSubdirNoSymlink(root, target, create) {
|
|
20402
|
-
const rootResolved = path10.resolve(root);
|
|
20403
|
-
const targetResolved = path10.resolve(target);
|
|
20404
|
-
if (targetResolved !== rootResolved && !targetResolved.startsWith(rootResolved + path10.sep)) return false;
|
|
20405
|
-
try {
|
|
20406
|
-
if (!fs9.lstatSync(rootResolved).isDirectory()) return false;
|
|
20407
|
-
} catch {
|
|
20408
|
-
return false;
|
|
20409
|
-
}
|
|
20410
|
-
const rel = path10.relative(rootResolved, targetResolved);
|
|
20411
|
-
if (rel === "") return true;
|
|
20412
|
-
let cur = rootResolved;
|
|
20413
|
-
for (const segment of rel.split(path10.sep)) {
|
|
20414
|
-
cur = path10.join(cur, segment);
|
|
20415
|
-
let st;
|
|
20416
|
-
try {
|
|
20417
|
-
st = fs9.lstatSync(cur);
|
|
20418
|
-
} catch {
|
|
20419
|
-
st = void 0;
|
|
20420
|
-
}
|
|
20421
|
-
if (st) {
|
|
20422
|
-
if (!st.isDirectory()) return false;
|
|
20423
|
-
} else if (create) {
|
|
20424
|
-
if (!mkdirTolerateRace(cur)) return false;
|
|
20425
|
-
} else {
|
|
20426
|
-
return true;
|
|
20427
|
-
}
|
|
20428
|
-
}
|
|
20429
|
-
return true;
|
|
20430
|
-
}
|
|
20431
|
-
function readFileNoFollow(root, abs) {
|
|
20432
|
-
if (!ensureRealSubdirNoSymlink(root, path10.dirname(abs), false)) return null;
|
|
20433
|
-
try {
|
|
20434
|
-
if (!fs9.lstatSync(abs).isFile()) return null;
|
|
20435
|
-
return fs9.readFileSync(abs);
|
|
20436
|
-
} catch {
|
|
20437
|
-
return null;
|
|
20438
|
-
}
|
|
20439
|
-
}
|
|
20440
|
-
function writeFileNoFollow(root, abs, data) {
|
|
20441
|
-
const parent = path10.dirname(abs);
|
|
20442
|
-
if (!ensureRealSubdirNoSymlink(root, parent, true)) return false;
|
|
20443
|
-
let st;
|
|
20444
|
-
try {
|
|
20445
|
-
st = fs9.lstatSync(abs);
|
|
20446
|
-
} catch {
|
|
20447
|
-
}
|
|
20448
|
-
if (st?.isSymbolicLink()) fs9.rmSync(abs);
|
|
20449
|
-
fs9.writeFileSync(abs, data);
|
|
20450
|
-
return true;
|
|
20451
|
-
}
|
|
20452
|
-
var init_fs_safety = __esm({
|
|
20453
|
-
"src/lib/fs-safety.ts"() {
|
|
20454
|
-
"use strict";
|
|
20455
|
-
}
|
|
20456
|
-
});
|
|
20457
|
-
|
|
20458
20535
|
// src/lib/resource-files.ts
|
|
20459
|
-
import * as
|
|
20536
|
+
import * as fs9 from "fs";
|
|
20460
20537
|
import * as path11 from "path";
|
|
20461
20538
|
import * as crypto3 from "crypto";
|
|
20462
20539
|
function isBinaryFile(filename) {
|
|
@@ -20503,14 +20580,14 @@ function computeHash(data) {
|
|
|
20503
20580
|
}
|
|
20504
20581
|
function scanResourceFiles(dir, prefix = "") {
|
|
20505
20582
|
const files = [];
|
|
20506
|
-
const entries =
|
|
20583
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
20507
20584
|
for (const entry of entries) {
|
|
20508
20585
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
20509
20586
|
if (entry.isDirectory()) {
|
|
20510
20587
|
files.push(...scanResourceFiles(path11.join(dir, entry.name), relPath));
|
|
20511
20588
|
} else if (entry.isFile()) {
|
|
20512
20589
|
const fullPath = path11.join(dir, entry.name);
|
|
20513
|
-
const stat2 =
|
|
20590
|
+
const stat2 = fs9.statSync(fullPath);
|
|
20514
20591
|
if (stat2.size > MAX_RESOURCE_FILE_SIZE3) {
|
|
20515
20592
|
console.warn(` Warning: skipping ${relPath} (${(stat2.size / 1024 / 1024).toFixed(1)}MB exceeds 10MB limit)`);
|
|
20516
20593
|
continue;
|
|
@@ -20520,7 +20597,7 @@ function scanResourceFiles(dir, prefix = "") {
|
|
|
20520
20597
|
mime_type: guessMimeType(entry.name),
|
|
20521
20598
|
file_size: stat2.size
|
|
20522
20599
|
};
|
|
20523
|
-
const data =
|
|
20600
|
+
const data = fs9.readFileSync(fullPath);
|
|
20524
20601
|
fileEntry.hash = computeHash(data);
|
|
20525
20602
|
if (isBinaryFile(entry.name)) {
|
|
20526
20603
|
fileEntry.content_base64 = data.toString("base64");
|
|
@@ -20580,7 +20657,7 @@ function writeResourceFileTree(resDir, files, root, log) {
|
|
|
20580
20657
|
return;
|
|
20581
20658
|
}
|
|
20582
20659
|
if (files.length === 0) {
|
|
20583
|
-
if (
|
|
20660
|
+
if (fs9.existsSync(resDir)) cleanOrphanFiles(resDir, "", /* @__PURE__ */ new Set(), root, log);
|
|
20584
20661
|
return;
|
|
20585
20662
|
}
|
|
20586
20663
|
const writtenPaths = /* @__PURE__ */ new Set();
|
|
@@ -20601,18 +20678,18 @@ function writeResourceFileTree(resDir, files, root, log) {
|
|
|
20601
20678
|
writtenPaths.delete(file.path);
|
|
20602
20679
|
}
|
|
20603
20680
|
}
|
|
20604
|
-
if (
|
|
20681
|
+
if (fs9.existsSync(resDir)) cleanOrphanFiles(resDir, "", writtenPaths, root, log);
|
|
20605
20682
|
}
|
|
20606
20683
|
function cleanOrphanFiles(dir, prefix, writtenPaths, root, log) {
|
|
20607
|
-
const entries =
|
|
20684
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
20608
20685
|
for (const entry of entries) {
|
|
20609
20686
|
const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
20610
20687
|
const fullPath = path11.join(dir, entry.name);
|
|
20611
20688
|
if (entry.isDirectory()) {
|
|
20612
20689
|
cleanOrphanFiles(fullPath, relPath, writtenPaths, root, log);
|
|
20613
|
-
if (
|
|
20690
|
+
if (fs9.readdirSync(fullPath).length === 0) fs9.rmdirSync(fullPath);
|
|
20614
20691
|
} else if (!writtenPaths.has(relPath)) {
|
|
20615
|
-
|
|
20692
|
+
fs9.unlinkSync(fullPath);
|
|
20616
20693
|
if (log && root) log.removed.push(path11.relative(root, fullPath));
|
|
20617
20694
|
}
|
|
20618
20695
|
}
|
|
@@ -20633,8 +20710,8 @@ async function downloadBinaryFiles(resDir, files, root, log) {
|
|
|
20633
20710
|
}
|
|
20634
20711
|
if (file.hash) {
|
|
20635
20712
|
try {
|
|
20636
|
-
const st =
|
|
20637
|
-
if (st.isFile() && !st.isSymbolicLink() && computeHash(
|
|
20713
|
+
const st = fs9.lstatSync(filePath);
|
|
20714
|
+
if (st.isFile() && !st.isSymbolicLink() && computeHash(fs9.readFileSync(filePath)) === file.hash) continue;
|
|
20638
20715
|
} catch {
|
|
20639
20716
|
}
|
|
20640
20717
|
}
|
|
@@ -20688,7 +20765,7 @@ var init_resource_files = __esm({
|
|
|
20688
20765
|
});
|
|
20689
20766
|
|
|
20690
20767
|
// src/lib/eval-attachments.ts
|
|
20691
|
-
import * as
|
|
20768
|
+
import * as fs10 from "fs";
|
|
20692
20769
|
import * as path12 from "path";
|
|
20693
20770
|
function resolveTurnAttachments(hubFolder, turn, label, bytesByHash) {
|
|
20694
20771
|
const raw = turn.attachments;
|
|
@@ -20712,7 +20789,7 @@ function resolveTurnAttachments(hubFolder, turn, label, bytesByHash) {
|
|
|
20712
20789
|
}
|
|
20713
20790
|
let stat2;
|
|
20714
20791
|
try {
|
|
20715
|
-
stat2 =
|
|
20792
|
+
stat2 = fs10.statSync(abs);
|
|
20716
20793
|
} catch {
|
|
20717
20794
|
}
|
|
20718
20795
|
if (!stat2?.isFile()) {
|
|
@@ -20726,7 +20803,7 @@ function resolveTurnAttachments(hubFolder, turn, label, bytesByHash) {
|
|
|
20726
20803
|
`${label}: attachment "${entry}" is ${(stat2.size / 1024 / 1024).toFixed(1)}MB, over the 10MB limit.`
|
|
20727
20804
|
);
|
|
20728
20805
|
}
|
|
20729
|
-
const data =
|
|
20806
|
+
const data = fs10.readFileSync(abs);
|
|
20730
20807
|
const hash = computeHash(data);
|
|
20731
20808
|
const fileName = path12.basename(abs);
|
|
20732
20809
|
const mimeType = guessMimeType(fileName) ?? "application/octet-stream";
|
|
@@ -20834,16 +20911,16 @@ async function downloadEvalAttachments(hubFolder, downloads) {
|
|
|
20834
20911
|
console.warn(` Warning: ${ATTACHMENTS_DIR}/ is not reachable inside the hub folder without a symlink; skipping attachment sync.`);
|
|
20835
20912
|
return result;
|
|
20836
20913
|
}
|
|
20837
|
-
if (!
|
|
20914
|
+
if (!fs10.existsSync(attachDir)) return result;
|
|
20838
20915
|
for (const dl of downloads) {
|
|
20839
20916
|
const abs = path12.resolve(hubFolder, dl.relPath);
|
|
20840
20917
|
if (abs !== attachDir && !abs.startsWith(attachDir + path12.sep)) continue;
|
|
20841
20918
|
let existing;
|
|
20842
20919
|
try {
|
|
20843
|
-
existing =
|
|
20920
|
+
existing = fs10.lstatSync(abs);
|
|
20844
20921
|
} catch {
|
|
20845
20922
|
}
|
|
20846
|
-
if (existing?.isFile() && !existing.isSymbolicLink() && computeHash(
|
|
20923
|
+
if (existing?.isFile() && !existing.isSymbolicLink() && computeHash(fs10.readFileSync(abs)) === dl.hash) {
|
|
20847
20924
|
continue;
|
|
20848
20925
|
}
|
|
20849
20926
|
try {
|
|
@@ -20861,11 +20938,11 @@ async function downloadEvalAttachments(hubFolder, downloads) {
|
|
|
20861
20938
|
}
|
|
20862
20939
|
}
|
|
20863
20940
|
const keep = new Set(downloads.map((d) => path12.resolve(hubFolder, d.relPath)));
|
|
20864
|
-
for (const name of
|
|
20941
|
+
for (const name of fs10.readdirSync(attachDir)) {
|
|
20865
20942
|
const abs = path12.join(attachDir, name);
|
|
20866
|
-
const st =
|
|
20943
|
+
const st = fs10.lstatSync(abs);
|
|
20867
20944
|
if ((st.isFile() || st.isSymbolicLink()) && !keep.has(abs)) {
|
|
20868
|
-
|
|
20945
|
+
fs10.rmSync(abs);
|
|
20869
20946
|
result.removed.push(path12.relative(hubFolder, abs));
|
|
20870
20947
|
}
|
|
20871
20948
|
}
|
|
@@ -20883,15 +20960,16 @@ var init_eval_attachments = __esm({
|
|
|
20883
20960
|
});
|
|
20884
20961
|
|
|
20885
20962
|
// src/lib/parser.ts
|
|
20886
|
-
import * as
|
|
20963
|
+
import * as fs11 from "fs";
|
|
20887
20964
|
import * as path13 from "path";
|
|
20888
20965
|
import * as yaml6 from "js-yaml";
|
|
20889
20966
|
function parseHubFolder(hubFolder, opts) {
|
|
20967
|
+
requireRealHubFolder(hubFolder, false);
|
|
20890
20968
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
20891
20969
|
if (!yamlPath) {
|
|
20892
20970
|
throw expected(`hub.yaml not found in ${hubFolder}`);
|
|
20893
20971
|
}
|
|
20894
|
-
const yamlContent =
|
|
20972
|
+
const yamlContent = readRealFileOrThrow(hubFolder, yamlPath) ?? "";
|
|
20895
20973
|
let config;
|
|
20896
20974
|
try {
|
|
20897
20975
|
config = yaml6.load(yamlContent);
|
|
@@ -20919,8 +20997,8 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
20919
20997
|
if (typeof resolved.instructions === "string" && resolved.instructions.endsWith(".md")) {
|
|
20920
20998
|
const instrValue = resolved.instructions;
|
|
20921
20999
|
const instructionsPath = instrValue.startsWith("agents/") ? path13.join(hubFolder, instrValue) : path13.join(hubFolder, "agents", instrValue);
|
|
20922
|
-
if (
|
|
20923
|
-
resolved.instructions =
|
|
21000
|
+
if (fs11.existsSync(instructionsPath)) {
|
|
21001
|
+
resolved.instructions = fs11.readFileSync(instructionsPath, "utf-8");
|
|
20924
21002
|
} else {
|
|
20925
21003
|
throw expected(
|
|
20926
21004
|
`Agent instructions file not found: ${instructionsPath} (referenced by agent "${agent.name}")`
|
|
@@ -20928,8 +21006,8 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
20928
21006
|
}
|
|
20929
21007
|
} else if (resolved.instructions === void 0 && typeof agent.name === "string") {
|
|
20930
21008
|
const conventionPath = path13.join(hubFolder, "agents", `${slugify(agent.name)}.md`);
|
|
20931
|
-
if (
|
|
20932
|
-
resolved.instructions =
|
|
21009
|
+
if (fs11.existsSync(conventionPath)) {
|
|
21010
|
+
resolved.instructions = fs11.readFileSync(conventionPath, "utf-8");
|
|
20933
21011
|
}
|
|
20934
21012
|
}
|
|
20935
21013
|
return resolved;
|
|
@@ -20984,17 +21062,17 @@ function parseHubFolder(hubFolder, opts) {
|
|
|
20984
21062
|
}
|
|
20985
21063
|
function scanEvalYamlFiles(hubFolder, bytesByHash) {
|
|
20986
21064
|
const evalsDir = path13.join(hubFolder, "evals");
|
|
20987
|
-
if (!
|
|
21065
|
+
if (!fs11.existsSync(evalsDir)) return [];
|
|
20988
21066
|
const evals = [];
|
|
20989
21067
|
const seen = /* @__PURE__ */ new Set();
|
|
20990
|
-
const topEntries =
|
|
21068
|
+
const topEntries = fs11.readdirSync(evalsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
20991
21069
|
for (const entry of topEntries) {
|
|
20992
21070
|
if (entry.isFile() && entry.name.endsWith(".yaml")) {
|
|
20993
21071
|
collectEval(evals, seen, path13.join(evalsDir, entry.name), `evals/${entry.name}`, null, hubFolder, bytesByHash);
|
|
20994
21072
|
} else if (entry.isDirectory()) {
|
|
20995
21073
|
const setName = entry.name;
|
|
20996
21074
|
const setDir = path13.join(evalsDir, setName);
|
|
20997
|
-
const setEntries =
|
|
21075
|
+
const setEntries = fs11.readdirSync(setDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
20998
21076
|
for (const sub of setEntries) {
|
|
20999
21077
|
if (sub.isDirectory()) {
|
|
21000
21078
|
throw expected(
|
|
@@ -21023,7 +21101,7 @@ function collectEval(evals, seen, filePath, relPath, setName, hubFolder, bytesBy
|
|
|
21023
21101
|
evals.push(evalEntry);
|
|
21024
21102
|
}
|
|
21025
21103
|
function parseEvalYaml(filePath, relPath, setName, hubFolder, bytesByHash) {
|
|
21026
|
-
const content =
|
|
21104
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
21027
21105
|
let raw;
|
|
21028
21106
|
try {
|
|
21029
21107
|
raw = yaml6.load(content);
|
|
@@ -21126,10 +21204,10 @@ function parseFixtureField(raw, label, key) {
|
|
|
21126
21204
|
}
|
|
21127
21205
|
function scanJourneyYamlFiles(hubFolder, bytesByHash) {
|
|
21128
21206
|
const journeysDir = path13.join(hubFolder, "journeys");
|
|
21129
|
-
if (!
|
|
21207
|
+
if (!fs11.existsSync(journeysDir)) return [];
|
|
21130
21208
|
const journeys = [];
|
|
21131
21209
|
const seen = /* @__PURE__ */ new Set();
|
|
21132
|
-
const entries =
|
|
21210
|
+
const entries = fs11.readdirSync(journeysDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
21133
21211
|
for (const entry of entries) {
|
|
21134
21212
|
if (entry.isDirectory()) {
|
|
21135
21213
|
throw expected(
|
|
@@ -21150,7 +21228,7 @@ function scanJourneyYamlFiles(hubFolder, bytesByHash) {
|
|
|
21150
21228
|
return journeys;
|
|
21151
21229
|
}
|
|
21152
21230
|
function parseJourneyYaml(filePath, relPath, hubFolder, bytesByHash) {
|
|
21153
|
-
const content =
|
|
21231
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
21154
21232
|
let raw;
|
|
21155
21233
|
try {
|
|
21156
21234
|
raw = yaml6.load(content);
|
|
@@ -21206,13 +21284,13 @@ function parseJourneyYaml(filePath, relPath, hubFolder, bytesByHash) {
|
|
|
21206
21284
|
}
|
|
21207
21285
|
function scanAgentYamlFiles(hubFolder) {
|
|
21208
21286
|
const agentsDir = path13.join(hubFolder, "agents");
|
|
21209
|
-
if (!
|
|
21210
|
-
const yamlFiles =
|
|
21287
|
+
if (!fs11.existsSync(agentsDir)) return [];
|
|
21288
|
+
const yamlFiles = fs11.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml")).sort();
|
|
21211
21289
|
if (yamlFiles.length === 0) return [];
|
|
21212
21290
|
const agents = [];
|
|
21213
21291
|
for (const file of yamlFiles) {
|
|
21214
21292
|
const filePath = path13.join(agentsDir, file);
|
|
21215
|
-
const content =
|
|
21293
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
21216
21294
|
let agent;
|
|
21217
21295
|
try {
|
|
21218
21296
|
agent = yaml6.load(content);
|
|
@@ -21247,7 +21325,7 @@ function parseResources(hubFolder, configResources) {
|
|
|
21247
21325
|
if (res.skill_name) resource.skill_name = res.skill_name;
|
|
21248
21326
|
const resSlug = slugify(resource.name);
|
|
21249
21327
|
const resDir = path13.join(resourcesDir, resSlug);
|
|
21250
|
-
if (
|
|
21328
|
+
if (fs11.existsSync(resDir)) {
|
|
21251
21329
|
const files = scanResourceFiles(resDir, "");
|
|
21252
21330
|
if (files.length > 0) {
|
|
21253
21331
|
resource.files = files;
|
|
@@ -21264,6 +21342,7 @@ var init_parser = __esm({
|
|
|
21264
21342
|
init_resource_files();
|
|
21265
21343
|
init_eval_attachments();
|
|
21266
21344
|
init_expected();
|
|
21345
|
+
init_fs_safety();
|
|
21267
21346
|
}
|
|
21268
21347
|
});
|
|
21269
21348
|
|
|
@@ -21295,7 +21374,6 @@ var init_diff_display = __esm({
|
|
|
21295
21374
|
});
|
|
21296
21375
|
|
|
21297
21376
|
// src/lib/workspace-files.ts
|
|
21298
|
-
import * as fs13 from "fs";
|
|
21299
21377
|
import * as path14 from "path";
|
|
21300
21378
|
function perHubAgentsMd(hubFolderName) {
|
|
21301
21379
|
return [
|
|
@@ -21311,19 +21389,18 @@ function perHubAgentsMd(hubFolderName) {
|
|
|
21311
21389
|
""
|
|
21312
21390
|
].join("\n");
|
|
21313
21391
|
}
|
|
21314
|
-
function writeIfAbsent(filePath, content) {
|
|
21315
|
-
|
|
21316
|
-
fs13.writeFileSync(filePath, content, "utf-8");
|
|
21317
|
-
return path14.basename(filePath);
|
|
21392
|
+
function writeIfAbsent(root, filePath, content) {
|
|
21393
|
+
return createFileNoFollow(root, filePath, Buffer.from(content, "utf-8")) === "created" ? path14.basename(filePath) : null;
|
|
21318
21394
|
}
|
|
21319
21395
|
var init_workspace_files = __esm({
|
|
21320
21396
|
"src/lib/workspace-files.ts"() {
|
|
21321
21397
|
"use strict";
|
|
21398
|
+
init_fs_safety();
|
|
21322
21399
|
}
|
|
21323
21400
|
});
|
|
21324
21401
|
|
|
21325
21402
|
// src/lib/yaml-writer.ts
|
|
21326
|
-
import * as
|
|
21403
|
+
import * as fs12 from "fs";
|
|
21327
21404
|
import * as path15 from "path";
|
|
21328
21405
|
import * as yaml7 from "js-yaml";
|
|
21329
21406
|
function writeFileIfChanged(hubFolder, absPath, content, log) {
|
|
@@ -21374,11 +21451,11 @@ function buildEvalYamlObject(evalEntry, slug) {
|
|
|
21374
21451
|
function writeHubFolder(hubFolder, payload, options = {}) {
|
|
21375
21452
|
const log = { changed: [], removed: [] };
|
|
21376
21453
|
const agentsDir = path15.join(hubFolder, "agents");
|
|
21377
|
-
if (!
|
|
21378
|
-
|
|
21454
|
+
if (!fs12.existsSync(hubFolder)) {
|
|
21455
|
+
fs12.mkdirSync(hubFolder, { recursive: true });
|
|
21379
21456
|
}
|
|
21380
|
-
if (!
|
|
21381
|
-
|
|
21457
|
+
if (!fs12.existsSync(agentsDir)) {
|
|
21458
|
+
fs12.mkdirSync(agentsDir, { recursive: true });
|
|
21382
21459
|
}
|
|
21383
21460
|
const yamlPayload = buildYamlPayload(payload);
|
|
21384
21461
|
const agentFiles = extractAgentFiles(payload);
|
|
@@ -21386,14 +21463,15 @@ function writeHubFolder(hubFolder, payload, options = {}) {
|
|
|
21386
21463
|
writeFileIfChanged(hubFolder, path15.join(hubFolder, "hub.yaml"), yamlContent, log);
|
|
21387
21464
|
if (options.seedAgentContext ?? true) {
|
|
21388
21465
|
const seeded = writeIfAbsent(
|
|
21466
|
+
hubFolder,
|
|
21389
21467
|
path15.join(hubFolder, "AGENTS.md"),
|
|
21390
21468
|
perHubAgentsMd(path15.basename(hubFolder))
|
|
21391
21469
|
);
|
|
21392
21470
|
if (seeded) log.changed.push(seeded);
|
|
21393
21471
|
}
|
|
21394
21472
|
const oldYamlPath = path15.join(hubFolder, "wayai.yaml");
|
|
21395
|
-
if (
|
|
21396
|
-
|
|
21473
|
+
if (fs12.existsSync(oldYamlPath)) {
|
|
21474
|
+
fs12.unlinkSync(oldYamlPath);
|
|
21397
21475
|
log.removed.push(path15.relative(hubFolder, oldYamlPath));
|
|
21398
21476
|
}
|
|
21399
21477
|
const yamlSlugs = writeAgentYamlFiles(hubFolder, agentsDir, payload.agents || [], log);
|
|
@@ -21402,20 +21480,20 @@ function writeHubFolder(hubFolder, payload, options = {}) {
|
|
|
21402
21480
|
mdSlugs.add(slug);
|
|
21403
21481
|
writeFileIfChanged(hubFolder, path15.join(agentsDir, `${slug}.md`), content, log);
|
|
21404
21482
|
}
|
|
21405
|
-
const existingFiles =
|
|
21483
|
+
const existingFiles = fs12.readdirSync(agentsDir);
|
|
21406
21484
|
for (const file of existingFiles) {
|
|
21407
21485
|
if (file.endsWith(".yaml")) {
|
|
21408
21486
|
const slug = file.slice(0, -5);
|
|
21409
21487
|
if (!yamlSlugs.has(slug)) {
|
|
21410
21488
|
const orphan = path15.join(agentsDir, file);
|
|
21411
|
-
|
|
21489
|
+
fs12.unlinkSync(orphan);
|
|
21412
21490
|
log.removed.push(path15.relative(hubFolder, orphan));
|
|
21413
21491
|
}
|
|
21414
21492
|
} else if (file.endsWith(".md")) {
|
|
21415
21493
|
const slug = file.slice(0, -3);
|
|
21416
21494
|
if (!mdSlugs.has(slug)) {
|
|
21417
21495
|
const orphan = path15.join(agentsDir, file);
|
|
21418
|
-
|
|
21496
|
+
fs12.unlinkSync(orphan);
|
|
21419
21497
|
log.removed.push(path15.relative(hubFolder, orphan));
|
|
21420
21498
|
}
|
|
21421
21499
|
}
|
|
@@ -21426,12 +21504,13 @@ function writeHubFolder(hubFolder, payload, options = {}) {
|
|
|
21426
21504
|
return log;
|
|
21427
21505
|
}
|
|
21428
21506
|
function setPreviewLabelInHubYaml(hubFolder, label) {
|
|
21507
|
+
requireRealHubFolder(hubFolder, false);
|
|
21429
21508
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
21430
21509
|
if (!yamlPath) return;
|
|
21431
|
-
const obj = yaml7.load(
|
|
21510
|
+
const obj = yaml7.load(readRealFileOrThrow(hubFolder, yamlPath) ?? "") ?? {};
|
|
21432
21511
|
if (label) obj.preview_label = label;
|
|
21433
21512
|
else delete obj.preview_label;
|
|
21434
|
-
|
|
21513
|
+
writeFileNoFollow(hubFolder, yamlPath, Buffer.from(yaml7.dump(obj, YAML_DUMP_OPTIONS), "utf-8"));
|
|
21435
21514
|
}
|
|
21436
21515
|
function buildYamlPayload(payload) {
|
|
21437
21516
|
const result = {
|
|
@@ -21496,17 +21575,17 @@ function extractAgentFiles(payload) {
|
|
|
21496
21575
|
function writeEvalYamlFiles(hubFolder, evals, log) {
|
|
21497
21576
|
const evalsDir = path15.join(hubFolder, "evals");
|
|
21498
21577
|
if (evals.length === 0) {
|
|
21499
|
-
if (
|
|
21578
|
+
if (fs12.existsSync(evalsDir)) {
|
|
21500
21579
|
cleanEvalOrphans(hubFolder, evalsDir, /* @__PURE__ */ new Set(), log);
|
|
21501
21580
|
try {
|
|
21502
|
-
if (
|
|
21581
|
+
if (fs12.readdirSync(evalsDir).length === 0) fs12.rmdirSync(evalsDir);
|
|
21503
21582
|
} catch {
|
|
21504
21583
|
}
|
|
21505
21584
|
}
|
|
21506
21585
|
return;
|
|
21507
21586
|
}
|
|
21508
|
-
if (!
|
|
21509
|
-
|
|
21587
|
+
if (!fs12.existsSync(evalsDir)) {
|
|
21588
|
+
fs12.mkdirSync(evalsDir, { recursive: true });
|
|
21510
21589
|
}
|
|
21511
21590
|
const writtenRelPaths = /* @__PURE__ */ new Set();
|
|
21512
21591
|
for (const evalEntry of evals) {
|
|
@@ -21518,12 +21597,6 @@ function writeEvalYamlFiles(hubFolder, evals, log) {
|
|
|
21518
21597
|
console.warn(` Warning: skipping eval "${evalEntry.name}" (scenario set "${setName}" escapes evals/ \u2014 possible bad backend data)`);
|
|
21519
21598
|
continue;
|
|
21520
21599
|
}
|
|
21521
|
-
if (setName) {
|
|
21522
|
-
const setDir = path15.join(evalsDir, setName);
|
|
21523
|
-
if (!fs14.existsSync(setDir)) {
|
|
21524
|
-
fs14.mkdirSync(setDir, { recursive: true });
|
|
21525
|
-
}
|
|
21526
|
-
}
|
|
21527
21600
|
const yamlContent = yaml7.dump(buildEvalYamlObject(evalEntry, slug), YAML_DUMP_OPTIONS);
|
|
21528
21601
|
writeFileIfChanged(hubFolder, targetPath, yamlContent, log);
|
|
21529
21602
|
writtenRelPaths.add(relPath);
|
|
@@ -21531,31 +21604,31 @@ function writeEvalYamlFiles(hubFolder, evals, log) {
|
|
|
21531
21604
|
cleanEvalOrphans(hubFolder, evalsDir, writtenRelPaths, log);
|
|
21532
21605
|
}
|
|
21533
21606
|
function cleanEvalOrphans(hubFolder, evalsDir, writtenRelPaths, log) {
|
|
21534
|
-
const entries =
|
|
21607
|
+
const entries = fs12.readdirSync(evalsDir, { withFileTypes: true });
|
|
21535
21608
|
for (const entry of entries) {
|
|
21536
21609
|
const fullPath = path15.join(evalsDir, entry.name);
|
|
21537
21610
|
if (entry.isFile()) {
|
|
21538
21611
|
if (entry.name.endsWith(".yaml") && !writtenRelPaths.has(entry.name)) {
|
|
21539
|
-
|
|
21612
|
+
fs12.unlinkSync(fullPath);
|
|
21540
21613
|
log.removed.push(path15.relative(hubFolder, fullPath));
|
|
21541
21614
|
}
|
|
21542
21615
|
continue;
|
|
21543
21616
|
}
|
|
21544
21617
|
if (entry.isDirectory()) {
|
|
21545
21618
|
const setName = entry.name;
|
|
21546
|
-
const subEntries =
|
|
21619
|
+
const subEntries = fs12.readdirSync(fullPath, { withFileTypes: true });
|
|
21547
21620
|
for (const sub of subEntries) {
|
|
21548
21621
|
if (sub.isFile() && sub.name.endsWith(".yaml")) {
|
|
21549
21622
|
const relPath = `${setName}/${sub.name}`;
|
|
21550
21623
|
if (!writtenRelPaths.has(relPath)) {
|
|
21551
21624
|
const orphan = path15.join(fullPath, sub.name);
|
|
21552
|
-
|
|
21625
|
+
fs12.unlinkSync(orphan);
|
|
21553
21626
|
log.removed.push(path15.relative(hubFolder, orphan));
|
|
21554
21627
|
}
|
|
21555
21628
|
}
|
|
21556
21629
|
}
|
|
21557
21630
|
try {
|
|
21558
|
-
if (
|
|
21631
|
+
if (fs12.readdirSync(fullPath).length === 0) fs12.rmdirSync(fullPath);
|
|
21559
21632
|
} catch {
|
|
21560
21633
|
}
|
|
21561
21634
|
}
|
|
@@ -21594,17 +21667,17 @@ function buildJourneyYamlObject(journeyEntry, slug) {
|
|
|
21594
21667
|
function writeJourneyYamlFiles(hubFolder, journeys, log) {
|
|
21595
21668
|
const journeysDir = path15.join(hubFolder, "journeys");
|
|
21596
21669
|
if (journeys.length === 0) {
|
|
21597
|
-
if (
|
|
21670
|
+
if (fs12.existsSync(journeysDir)) {
|
|
21598
21671
|
cleanJourneyOrphans(hubFolder, journeysDir, /* @__PURE__ */ new Set(), log);
|
|
21599
21672
|
try {
|
|
21600
|
-
if (
|
|
21673
|
+
if (fs12.readdirSync(journeysDir).length === 0) fs12.rmdirSync(journeysDir);
|
|
21601
21674
|
} catch {
|
|
21602
21675
|
}
|
|
21603
21676
|
}
|
|
21604
21677
|
return;
|
|
21605
21678
|
}
|
|
21606
|
-
if (!
|
|
21607
|
-
|
|
21679
|
+
if (!fs12.existsSync(journeysDir)) {
|
|
21680
|
+
fs12.mkdirSync(journeysDir, { recursive: true });
|
|
21608
21681
|
}
|
|
21609
21682
|
const writtenFiles = /* @__PURE__ */ new Set();
|
|
21610
21683
|
const usedSlugs = /* @__PURE__ */ new Set();
|
|
@@ -21618,11 +21691,11 @@ function writeJourneyYamlFiles(hubFolder, journeys, log) {
|
|
|
21618
21691
|
cleanJourneyOrphans(hubFolder, journeysDir, writtenFiles, log);
|
|
21619
21692
|
}
|
|
21620
21693
|
function cleanJourneyOrphans(hubFolder, journeysDir, writtenFiles, log) {
|
|
21621
|
-
const entries =
|
|
21694
|
+
const entries = fs12.readdirSync(journeysDir, { withFileTypes: true });
|
|
21622
21695
|
for (const entry of entries) {
|
|
21623
21696
|
if (entry.isFile() && entry.name.endsWith(".yaml") && !writtenFiles.has(entry.name)) {
|
|
21624
21697
|
const orphan = path15.join(journeysDir, entry.name);
|
|
21625
|
-
|
|
21698
|
+
fs12.unlinkSync(orphan);
|
|
21626
21699
|
log.removed.push(path15.relative(hubFolder, orphan));
|
|
21627
21700
|
}
|
|
21628
21701
|
}
|
|
@@ -21636,12 +21709,12 @@ function writeResourceFiles(hubFolder, resources, log) {
|
|
|
21636
21709
|
const resDir = path15.join(resourcesDir, resSlug);
|
|
21637
21710
|
writeResourceFileTree(resDir, resource.files || [], hubFolder, log);
|
|
21638
21711
|
}
|
|
21639
|
-
if (
|
|
21640
|
-
const existingDirs =
|
|
21712
|
+
if (fs12.existsSync(resourcesDir)) {
|
|
21713
|
+
const existingDirs = fs12.readdirSync(resourcesDir, { withFileTypes: true });
|
|
21641
21714
|
for (const entry of existingDirs) {
|
|
21642
21715
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
21643
21716
|
const orphanDir = path15.join(resourcesDir, entry.name);
|
|
21644
|
-
|
|
21717
|
+
fs12.rmSync(orphanDir, { recursive: true, force: true });
|
|
21645
21718
|
log.removed.push(`${path15.relative(hubFolder, orphanDir)}/`);
|
|
21646
21719
|
}
|
|
21647
21720
|
}
|
|
@@ -21678,6 +21751,7 @@ async function materializeHubFolder(hubFolder, payload, options = {}) {
|
|
|
21678
21751
|
);
|
|
21679
21752
|
}
|
|
21680
21753
|
materialized.add(payload);
|
|
21754
|
+
requireRealHubFolder(hubFolder, true);
|
|
21681
21755
|
const attachmentDownloads = rewriteEvalAttachmentsToLocalPaths(payload);
|
|
21682
21756
|
const writeLog = writeHubFolder(hubFolder, payload, options);
|
|
21683
21757
|
const resourceDownloads = await downloadBinaryResourceFiles(hubFolder, payload);
|
|
@@ -21709,6 +21783,7 @@ var init_hub_materializer = __esm({
|
|
|
21709
21783
|
init_yaml_writer();
|
|
21710
21784
|
init_eval_attachments();
|
|
21711
21785
|
init_resource_files();
|
|
21786
|
+
init_fs_safety();
|
|
21712
21787
|
init_utils();
|
|
21713
21788
|
materialized = /* @__PURE__ */ new WeakSet();
|
|
21714
21789
|
}
|
|
@@ -21730,7 +21805,7 @@ var init_terminal_output = __esm({
|
|
|
21730
21805
|
});
|
|
21731
21806
|
|
|
21732
21807
|
// src/lib/base-workspace.ts
|
|
21733
|
-
import * as
|
|
21808
|
+
import * as fs13 from "fs";
|
|
21734
21809
|
import * as path17 from "path";
|
|
21735
21810
|
import * as yaml8 from "js-yaml";
|
|
21736
21811
|
function readBaseMeta(folder) {
|
|
@@ -21748,7 +21823,7 @@ function readBaseMeta(folder) {
|
|
|
21748
21823
|
function listBaseFolders(basesDir) {
|
|
21749
21824
|
let entries;
|
|
21750
21825
|
try {
|
|
21751
|
-
entries =
|
|
21826
|
+
entries = fs13.readdirSync(basesDir).filter((entry) => !entry.startsWith("."));
|
|
21752
21827
|
} catch {
|
|
21753
21828
|
return [];
|
|
21754
21829
|
}
|
|
@@ -21835,7 +21910,7 @@ function resolveBaseSelectorToId(gitRoot, selector) {
|
|
|
21835
21910
|
}
|
|
21836
21911
|
function hasBaseMetaFile(folder) {
|
|
21837
21912
|
try {
|
|
21838
|
-
return
|
|
21913
|
+
return fs13.lstatSync(path17.join(folder, BASE_META_FILE)).isFile();
|
|
21839
21914
|
} catch {
|
|
21840
21915
|
return false;
|
|
21841
21916
|
}
|
|
@@ -22148,7 +22223,7 @@ var init_client = __esm({
|
|
|
22148
22223
|
});
|
|
22149
22224
|
|
|
22150
22225
|
// src/data/helpers.ts
|
|
22151
|
-
import { readFileSync as
|
|
22226
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
22152
22227
|
function pathSegment(id, label = "id") {
|
|
22153
22228
|
if (!isPathSafeId(id)) {
|
|
22154
22229
|
throw expected(`Invalid ${label}: ${JSON.stringify(id)}. An id may use ${PATH_SAFE_ID_RULE}.`);
|
|
@@ -22176,7 +22251,7 @@ function parseData(data, flag) {
|
|
|
22176
22251
|
let text = data;
|
|
22177
22252
|
if (source !== void 0) {
|
|
22178
22253
|
try {
|
|
22179
|
-
text =
|
|
22254
|
+
text = readFileSync14(source, "utf-8");
|
|
22180
22255
|
} catch (e) {
|
|
22181
22256
|
throw expected(`${prefix}${source}: ${e instanceof Error ? e.message : "could not be read"}`);
|
|
22182
22257
|
}
|
|
@@ -22301,7 +22376,7 @@ var init_types2 = __esm({
|
|
|
22301
22376
|
});
|
|
22302
22377
|
|
|
22303
22378
|
// src/data/config-as-code/config-writer.ts
|
|
22304
|
-
import * as
|
|
22379
|
+
import * as fs14 from "fs";
|
|
22305
22380
|
import * as path19 from "path";
|
|
22306
22381
|
import * as yaml9 from "js-yaml";
|
|
22307
22382
|
function dump5(value) {
|
|
@@ -22336,14 +22411,14 @@ function pruneOrphans(folder, dir, keep, log) {
|
|
|
22336
22411
|
if (!ensureRealSubdirNoSymlink(folder, dir, false)) return;
|
|
22337
22412
|
let entries;
|
|
22338
22413
|
try {
|
|
22339
|
-
entries =
|
|
22414
|
+
entries = fs14.readdirSync(dir);
|
|
22340
22415
|
} catch {
|
|
22341
22416
|
return;
|
|
22342
22417
|
}
|
|
22343
22418
|
for (const file of entries) {
|
|
22344
22419
|
if (!file.endsWith(".yaml") || keep.has(file)) continue;
|
|
22345
22420
|
const abs = path19.join(dir, file);
|
|
22346
|
-
|
|
22421
|
+
fs14.rmSync(abs);
|
|
22347
22422
|
log.removed.push(path19.relative(folder, abs));
|
|
22348
22423
|
}
|
|
22349
22424
|
}
|
|
@@ -22357,7 +22432,7 @@ function metaFileObject(meta) {
|
|
|
22357
22432
|
function writeBaseFolder(folder, meta, config) {
|
|
22358
22433
|
const delta = { changed: [], removed: [] };
|
|
22359
22434
|
const parent = path19.dirname(folder);
|
|
22360
|
-
|
|
22435
|
+
fs14.mkdirSync(parent, { recursive: true });
|
|
22361
22436
|
if (!ensureRealSubdirNoSymlink(parent, folder, true)) {
|
|
22362
22437
|
throw expected(
|
|
22363
22438
|
`Refusing to write ${folder}: the path crosses a symlink. Remove it and pull again.`
|
|
@@ -22384,7 +22459,7 @@ function writeBaseFolder(folder, meta, config) {
|
|
|
22384
22459
|
for (const deprecated of DEPRECATED_ENTITY_DIRS) {
|
|
22385
22460
|
const dir = path19.join(folder, deprecated);
|
|
22386
22461
|
if (ensureRealSubdirNoSymlink(folder, dir, false)) {
|
|
22387
|
-
|
|
22462
|
+
fs14.rmSync(dir, { recursive: true, force: true });
|
|
22388
22463
|
}
|
|
22389
22464
|
}
|
|
22390
22465
|
return delta;
|
|
@@ -22536,7 +22611,7 @@ var init_api = __esm({
|
|
|
22536
22611
|
});
|
|
22537
22612
|
|
|
22538
22613
|
// src/data/config-as-code/config-parser.ts
|
|
22539
|
-
import * as
|
|
22614
|
+
import * as fs15 from "fs";
|
|
22540
22615
|
import * as path20 from "path";
|
|
22541
22616
|
import * as yaml10 from "js-yaml";
|
|
22542
22617
|
function readEntityDir(folder, dir) {
|
|
@@ -22545,7 +22620,7 @@ function readEntityDir(folder, dir) {
|
|
|
22545
22620
|
}
|
|
22546
22621
|
if (!isDirectory(dir)) return [];
|
|
22547
22622
|
const out = [];
|
|
22548
|
-
for (const file of
|
|
22623
|
+
for (const file of fs15.readdirSync(dir).sort()) {
|
|
22549
22624
|
if (!file.endsWith(".yaml")) continue;
|
|
22550
22625
|
const abs = path20.join(dir, file);
|
|
22551
22626
|
const bytes = readFileNoFollow(folder, abs);
|
|
@@ -22932,7 +23007,7 @@ __export(push_exports, {
|
|
|
22932
23007
|
shouldWarnIgnoredPreviewLabel: () => shouldWarnIgnoredPreviewLabel,
|
|
22933
23008
|
syncAfterPush: () => syncAfterPush
|
|
22934
23009
|
});
|
|
22935
|
-
import * as
|
|
23010
|
+
import * as fs16 from "fs";
|
|
22936
23011
|
import * as path22 from "path";
|
|
22937
23012
|
import * as yaml11 from "js-yaml";
|
|
22938
23013
|
function parseArgs5(args2) {
|
|
@@ -23041,13 +23116,14 @@ function printLocalFileChanges(delta) {
|
|
|
23041
23116
|
emit(delta.changed, "~");
|
|
23042
23117
|
}
|
|
23043
23118
|
async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, remoteConfig) {
|
|
23119
|
+
requireRealHubFolder(hubFolder, false);
|
|
23044
23120
|
const agentsDir = path22.join(hubFolder, "agents");
|
|
23045
23121
|
let agentsWithIds = [];
|
|
23046
|
-
if (
|
|
23047
|
-
const yamlFiles =
|
|
23122
|
+
if (fs16.existsSync(agentsDir)) {
|
|
23123
|
+
const yamlFiles = fs16.readdirSync(agentsDir).filter((f) => f.endsWith(".yaml"));
|
|
23048
23124
|
for (const file of yamlFiles) {
|
|
23049
23125
|
try {
|
|
23050
|
-
const content =
|
|
23126
|
+
const content = fs16.readFileSync(path22.join(agentsDir, file), "utf-8");
|
|
23051
23127
|
const agent = yaml11.load(content);
|
|
23052
23128
|
if (agent?.id && agent.name) {
|
|
23053
23129
|
agentsWithIds.push({ id: agent.id, name: agent.name });
|
|
@@ -23060,7 +23136,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
|
|
|
23060
23136
|
if (agentsWithIds.length === 0) {
|
|
23061
23137
|
const yamlPath = resolveHubYamlPath(hubFolder);
|
|
23062
23138
|
if (!yamlPath) return;
|
|
23063
|
-
const yamlContent =
|
|
23139
|
+
const yamlContent = readRealFileOrThrow(hubFolder, yamlPath) ?? "";
|
|
23064
23140
|
const config = yaml11.load(yamlContent);
|
|
23065
23141
|
agentsWithIds = (config.agents || []).filter((a) => !!a.id && !!a.name);
|
|
23066
23142
|
}
|
|
@@ -23092,18 +23168,18 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
|
|
|
23092
23168
|
}
|
|
23093
23169
|
}
|
|
23094
23170
|
if (renames.length === 0) return;
|
|
23095
|
-
if (!
|
|
23096
|
-
for (const file of
|
|
23171
|
+
if (!fs16.existsSync(agentsDir)) return;
|
|
23172
|
+
for (const file of fs16.readdirSync(agentsDir)) {
|
|
23097
23173
|
if (file.startsWith("__rename_temp_") && (file.endsWith(".md") || file.endsWith(".yaml"))) {
|
|
23098
23174
|
console.warn(` Warning: removing orphaned temp file agents/${file}`);
|
|
23099
|
-
|
|
23175
|
+
fs16.unlinkSync(path22.join(agentsDir, file));
|
|
23100
23176
|
}
|
|
23101
23177
|
}
|
|
23102
23178
|
const renameFileIfExists = (dir, oldName, newName) => {
|
|
23103
23179
|
const oldPath = path22.join(dir, oldName);
|
|
23104
23180
|
const newPath = path22.join(dir, newName);
|
|
23105
|
-
if (!
|
|
23106
|
-
|
|
23181
|
+
if (!fs16.existsSync(oldPath)) return false;
|
|
23182
|
+
fs16.renameSync(oldPath, newPath);
|
|
23107
23183
|
return true;
|
|
23108
23184
|
};
|
|
23109
23185
|
const oldSlugs = new Set(renames.map((r) => r.oldSlug));
|
|
@@ -23136,9 +23212,9 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
|
|
|
23136
23212
|
}
|
|
23137
23213
|
} else {
|
|
23138
23214
|
for (const { oldSlug, newSlug } of renames) {
|
|
23139
|
-
const hasOldFile = extensions.some((ext) =>
|
|
23215
|
+
const hasOldFile = extensions.some((ext) => fs16.existsSync(path22.join(agentsDir, `${oldSlug}${ext}`)));
|
|
23140
23216
|
if (!hasOldFile) continue;
|
|
23141
|
-
const hasNewFile = extensions.some((ext) =>
|
|
23217
|
+
const hasNewFile = extensions.some((ext) => fs16.existsSync(path22.join(agentsDir, `${newSlug}${ext}`)));
|
|
23142
23218
|
if (hasNewFile) {
|
|
23143
23219
|
console.warn(` Warning: skipping rename agents/${oldSlug}.* \u2192 agents/${newSlug}.* (target already exists)`);
|
|
23144
23220
|
continue;
|
|
@@ -23153,7 +23229,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
|
|
|
23153
23229
|
if (completedRenames.length === 0) return;
|
|
23154
23230
|
const mainYamlPath = resolveHubYamlPath(hubFolder);
|
|
23155
23231
|
if (mainYamlPath) {
|
|
23156
|
-
const mainYamlContent =
|
|
23232
|
+
const mainYamlContent = readRealFileOrThrow(hubFolder, mainYamlPath) ?? "";
|
|
23157
23233
|
const substitutionMap = /* @__PURE__ */ new Map();
|
|
23158
23234
|
for (const { oldSlug, newSlug } of completedRenames) {
|
|
23159
23235
|
substitutionMap.set(`agents/${oldSlug}.md`, `agents/${newSlug}.md`);
|
|
@@ -23164,7 +23240,7 @@ async function autoRenameAgentFiles(client, hubId, hubFolder, organizationId, re
|
|
|
23164
23240
|
(_match, prefix, pathMatch) => `${prefix}${substitutionMap.get(pathMatch) ?? pathMatch}`
|
|
23165
23241
|
);
|
|
23166
23242
|
if (updatedYaml !== mainYamlContent) {
|
|
23167
|
-
|
|
23243
|
+
writeFileNoFollow(hubFolder, mainYamlPath, Buffer.from(updatedYaml, "utf-8"));
|
|
23168
23244
|
console.log(` Updated instructions paths in ${path22.basename(mainYamlPath)}`);
|
|
23169
23245
|
}
|
|
23170
23246
|
}
|
|
@@ -23258,11 +23334,13 @@ New hub: "${newHub.hubName}" (${hubType})`);
|
|
|
23258
23334
|
return;
|
|
23259
23335
|
}
|
|
23260
23336
|
}
|
|
23337
|
+
requireRealHubFolder(newHub.hubFolder, false);
|
|
23261
23338
|
const hubYamlPath = resolveHubYamlPath(newHub.hubFolder);
|
|
23262
23339
|
if (!hubYamlPath) {
|
|
23263
23340
|
console.error(`hub.yaml not found in ${newHub.hubFolder}. Cannot proceed with hub creation.`);
|
|
23264
23341
|
process.exit(1);
|
|
23265
23342
|
}
|
|
23343
|
+
const content = readRealFileOrThrow(newHub.hubFolder, hubYamlPath) ?? "";
|
|
23266
23344
|
console.log("Creating hub...");
|
|
23267
23345
|
const createResult = await client.createHub(opts.organizationId, {
|
|
23268
23346
|
hubName: newHub.hubName,
|
|
@@ -23276,7 +23354,6 @@ New hub: "${newHub.hubName}" (${hubType})`);
|
|
|
23276
23354
|
process.exit(1);
|
|
23277
23355
|
}
|
|
23278
23356
|
console.log(`Hub created: ${createdHub.hub_name} (${hubId})`);
|
|
23279
|
-
const content = fs18.readFileSync(hubYamlPath, "utf-8");
|
|
23280
23357
|
const hasVersion = content.match(/^version:\s/m);
|
|
23281
23358
|
let updated;
|
|
23282
23359
|
if (hasVersion) {
|
|
@@ -23292,7 +23369,7 @@ hub_id: "${hubId}"
|
|
|
23292
23369
|
hub_environment: preview
|
|
23293
23370
|
${content}`;
|
|
23294
23371
|
}
|
|
23295
|
-
|
|
23372
|
+
writeFileNoFollow(newHub.hubFolder, hubYamlPath, Buffer.from(updated, "utf-8"));
|
|
23296
23373
|
seedScopeIfEmpty("hubs", hubId);
|
|
23297
23374
|
await pushSingleHub(client, hubId, newHub.hubFolder, opts.autoConfirm, opts.organizationId, { skipAgentRename: true });
|
|
23298
23375
|
}
|
|
@@ -23338,7 +23415,7 @@ async function pushCommand(args2) {
|
|
|
23338
23415
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
23339
23416
|
const workspaceDir = resolveWorkspaceDir();
|
|
23340
23417
|
const wsLabel = hubsDirLabel(gitRoot);
|
|
23341
|
-
if (!
|
|
23418
|
+
if (!fs16.existsSync(workspaceDir)) {
|
|
23342
23419
|
console.error(`No ${wsLabel}/ directory found. Run \`wayai pull\` first or create hub files in ${wsLabel}/<hub>/hub.yaml.`);
|
|
23343
23420
|
process.exit(1);
|
|
23344
23421
|
}
|
|
@@ -23382,6 +23459,7 @@ var init_push = __esm({
|
|
|
23382
23459
|
init_repo_config();
|
|
23383
23460
|
init_worktree_scope();
|
|
23384
23461
|
init_subtree_routing();
|
|
23462
|
+
init_fs_safety();
|
|
23385
23463
|
LOCAL_CHANGE_LIST_CAP = 20;
|
|
23386
23464
|
}
|
|
23387
23465
|
});
|
|
@@ -23394,7 +23472,7 @@ __export(pull_exports, {
|
|
|
23394
23472
|
resolveHubTarget: () => resolveHubTarget,
|
|
23395
23473
|
writeProductionMirror: () => writeProductionMirror2
|
|
23396
23474
|
});
|
|
23397
|
-
import * as
|
|
23475
|
+
import * as fs17 from "fs";
|
|
23398
23476
|
import * as path23 from "path";
|
|
23399
23477
|
function parseArgs6(args2) {
|
|
23400
23478
|
return { autoConfirm: args2.includes("--yes") || args2.includes("-y") };
|
|
@@ -23461,7 +23539,7 @@ async function pullCommand(args2) {
|
|
|
23461
23539
|
payload.preview_label,
|
|
23462
23540
|
payload.branch_name
|
|
23463
23541
|
);
|
|
23464
|
-
|
|
23542
|
+
fs17.mkdirSync(path23.dirname(hubFolder), { recursive: true });
|
|
23465
23543
|
console.log("Writing hub configuration...");
|
|
23466
23544
|
await materializeHubFolder(hubFolder, payload);
|
|
23467
23545
|
const finalFolder = autoRenameHubFolder(hubFolder, payload.hub.name, payload.hub_environment, payload.hub_id, payload.preview_label, payload.branch_name);
|
|
@@ -23515,7 +23593,7 @@ async function pullCommand(args2) {
|
|
|
23515
23593
|
}
|
|
23516
23594
|
async function writeProductionMirror2(workspaceDir, prodPayload) {
|
|
23517
23595
|
const folder = resolveHubFolder(workspaceDir, prodPayload.hub_id, prodPayload.hub.name, "production", null, null);
|
|
23518
|
-
|
|
23596
|
+
fs17.mkdirSync(path23.dirname(folder), { recursive: true });
|
|
23519
23597
|
await materializeHubFolder(folder, prodPayload, { seedAgentContext: false });
|
|
23520
23598
|
const finalFolder = autoRenameHubFolder(folder, prodPayload.hub.name, "production", prodPayload.hub_id, null, null);
|
|
23521
23599
|
prependMirrorMarker(finalFolder, prodPayload.hub_id);
|
|
@@ -23533,11 +23611,11 @@ async function mirrorLinkedProduction2(client, workspaceDir, productionHubId, or
|
|
|
23533
23611
|
function prependMirrorMarker(hubFolder, productionHubId) {
|
|
23534
23612
|
const hubYaml = path23.join(hubFolder, "hub.yaml");
|
|
23535
23613
|
try {
|
|
23536
|
-
const content =
|
|
23614
|
+
const content = fs17.readFileSync(hubYaml, "utf-8");
|
|
23537
23615
|
if (content.startsWith(MIRROR_MARKER_PREFIX2)) return;
|
|
23538
23616
|
const marker = `${MIRROR_MARKER_PREFIX2} ${productionHubId}. Edits are ignored; push is blocked. Edit the linked preview hub instead.
|
|
23539
23617
|
`;
|
|
23540
|
-
|
|
23618
|
+
fs17.writeFileSync(hubYaml, marker + content, "utf-8");
|
|
23541
23619
|
} catch {
|
|
23542
23620
|
}
|
|
23543
23621
|
}
|
|
@@ -23581,7 +23659,7 @@ __export(create_exports, {
|
|
|
23581
23659
|
createCommand: () => createCommand
|
|
23582
23660
|
});
|
|
23583
23661
|
import * as path24 from "path";
|
|
23584
|
-
import * as
|
|
23662
|
+
import * as fs18 from "fs";
|
|
23585
23663
|
function parseArgs7(args2) {
|
|
23586
23664
|
let autoConfirm = false;
|
|
23587
23665
|
let folderSelector;
|
|
@@ -23608,7 +23686,7 @@ async function createCommand(args2) {
|
|
|
23608
23686
|
const gitRoot = findGitRoot();
|
|
23609
23687
|
const wsLabel = hubsDirLabel(gitRoot);
|
|
23610
23688
|
if (gitRoot) warnLayoutOnce(gitRoot);
|
|
23611
|
-
if (!
|
|
23689
|
+
if (!fs18.existsSync(workspaceDir)) {
|
|
23612
23690
|
console.error(`No ${wsLabel}/ directory found. Create hub files in ${wsLabel}/<hub>/hub.yaml with \`hub: { name: ... }\` first.`);
|
|
23613
23691
|
process.exit(1);
|
|
23614
23692
|
}
|
|
@@ -23742,7 +23820,7 @@ var replicate_exports = {};
|
|
|
23742
23820
|
__export(replicate_exports, {
|
|
23743
23821
|
replicateCommand: () => replicateCommand
|
|
23744
23822
|
});
|
|
23745
|
-
import * as
|
|
23823
|
+
import * as fs19 from "fs";
|
|
23746
23824
|
import * as path25 from "path";
|
|
23747
23825
|
function parseArgs9(args2) {
|
|
23748
23826
|
let label;
|
|
@@ -23789,8 +23867,8 @@ async function replicateCommand(args2) {
|
|
|
23789
23867
|
payload.preview_label,
|
|
23790
23868
|
payload.branch_name
|
|
23791
23869
|
);
|
|
23792
|
-
const folderPreExisted =
|
|
23793
|
-
|
|
23870
|
+
const folderPreExisted = fs19.existsSync(hubFolder);
|
|
23871
|
+
fs19.mkdirSync(path25.dirname(hubFolder), { recursive: true });
|
|
23794
23872
|
const delta = await materializeHubFolder(hubFolder, payload);
|
|
23795
23873
|
hubFolder = autoRenameHubFolder(
|
|
23796
23874
|
hubFolder,
|
|
@@ -24217,7 +24295,7 @@ __export(migrate_exports, {
|
|
|
24217
24295
|
migrateCommand: () => migrateCommand
|
|
24218
24296
|
});
|
|
24219
24297
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
24220
|
-
import * as
|
|
24298
|
+
import * as fs20 from "fs";
|
|
24221
24299
|
import * as path29 from "path";
|
|
24222
24300
|
function isTracked(gitRoot, p) {
|
|
24223
24301
|
try {
|
|
@@ -24231,7 +24309,7 @@ function isTracked(gitRoot, p) {
|
|
|
24231
24309
|
}
|
|
24232
24310
|
}
|
|
24233
24311
|
function moveDir(gitRoot, from, to) {
|
|
24234
|
-
|
|
24312
|
+
fs20.mkdirSync(path29.dirname(to), { recursive: true });
|
|
24235
24313
|
if (isTracked(gitRoot, from)) {
|
|
24236
24314
|
try {
|
|
24237
24315
|
execFileSync3("git", ["mv", path29.relative(gitRoot, from), path29.relative(gitRoot, to)], {
|
|
@@ -24242,7 +24320,7 @@ function moveDir(gitRoot, from, to) {
|
|
|
24242
24320
|
} catch {
|
|
24243
24321
|
}
|
|
24244
24322
|
}
|
|
24245
|
-
|
|
24323
|
+
fs20.renameSync(from, to);
|
|
24246
24324
|
return "fs";
|
|
24247
24325
|
}
|
|
24248
24326
|
async function migrateCommand(_args) {
|
|
@@ -24257,8 +24335,11 @@ async function migrateCommand(_args) {
|
|
|
24257
24335
|
const legacyOrg = path29.join(gitRoot, WAYAI_LAYOUT.legacy.orgAtRoot);
|
|
24258
24336
|
const newHubs = path29.join(newWs, WAYAI_LAYOUT.hubsSubdir);
|
|
24259
24337
|
const newOrg = path29.join(newWs, WAYAI_LAYOUT.orgSubdir);
|
|
24260
|
-
|
|
24261
|
-
|
|
24338
|
+
requireRealSubdirNoSymlink(gitRoot, newHubs, false);
|
|
24339
|
+
requireRealSubdirNoSymlink(gitRoot, newOrg, false);
|
|
24340
|
+
readRealFileOrThrow(gitRoot, workspaceManifestPath(gitRoot));
|
|
24341
|
+
const hasLegacyWs = isRealDirectory(legacyWs);
|
|
24342
|
+
const hasLegacyOrg = isRealDirectory(legacyOrg);
|
|
24262
24343
|
const orgPlan = planOrgMigration(gitRoot);
|
|
24263
24344
|
if (orgPlan.kind === "refuse") {
|
|
24264
24345
|
console.error(orgPlan.message);
|
|
@@ -24322,6 +24403,7 @@ var init_migrate = __esm({
|
|
|
24322
24403
|
"use strict";
|
|
24323
24404
|
init_workspace();
|
|
24324
24405
|
init_layout();
|
|
24406
|
+
init_fs_safety();
|
|
24325
24407
|
init_repo_config();
|
|
24326
24408
|
init_workspace_manifest();
|
|
24327
24409
|
}
|
|
@@ -24405,12 +24487,12 @@ var send_message_exports = {};
|
|
|
24405
24487
|
__export(send_message_exports, {
|
|
24406
24488
|
sendMessageCommand: () => sendMessageCommand
|
|
24407
24489
|
});
|
|
24408
|
-
import * as
|
|
24490
|
+
import * as fs21 from "fs";
|
|
24409
24491
|
import * as path30 from "path";
|
|
24410
24492
|
function statAttachment(filePath) {
|
|
24411
24493
|
let stat2;
|
|
24412
24494
|
try {
|
|
24413
|
-
stat2 =
|
|
24495
|
+
stat2 = fs21.statSync(filePath);
|
|
24414
24496
|
} catch {
|
|
24415
24497
|
console.error(`Error: file not found: ${filePath}`);
|
|
24416
24498
|
process.exit(1);
|
|
@@ -24426,7 +24508,7 @@ function readAttachment(filePath, size) {
|
|
|
24426
24508
|
const ext = path30.extname(fileName).replace(/^\./, "");
|
|
24427
24509
|
return {
|
|
24428
24510
|
file_name: fileName,
|
|
24429
|
-
file_binary:
|
|
24511
|
+
file_binary: fs21.readFileSync(filePath).toString("base64"),
|
|
24430
24512
|
file_size: size,
|
|
24431
24513
|
...ext && { file_extension: ext }
|
|
24432
24514
|
};
|
|
@@ -26625,7 +26707,7 @@ var eval_capture_exports = {};
|
|
|
26625
26707
|
__export(eval_capture_exports, {
|
|
26626
26708
|
evalCaptureCommand: () => evalCaptureCommand
|
|
26627
26709
|
});
|
|
26628
|
-
import * as
|
|
26710
|
+
import * as fs22 from "fs";
|
|
26629
26711
|
import * as path31 from "path";
|
|
26630
26712
|
import * as yaml12 from "js-yaml";
|
|
26631
26713
|
function isValidSetName(name) {
|
|
@@ -26699,7 +26781,17 @@ async function evalCaptureCommand(args2) {
|
|
|
26699
26781
|
console.error(`Resolved path "${path31.relative(hubFolder, targetPath)}" escapes evals/. Aborting.`);
|
|
26700
26782
|
process.exit(1);
|
|
26701
26783
|
}
|
|
26702
|
-
if (
|
|
26784
|
+
if (!ensureRealSubdirNoSymlink(hubFolder, targetDir, false)) {
|
|
26785
|
+
console.error(`${path31.relative(hubFolder, targetDir)} is reached through a symlink. Aborting.`);
|
|
26786
|
+
process.exit(1);
|
|
26787
|
+
}
|
|
26788
|
+
let targetTaken = true;
|
|
26789
|
+
try {
|
|
26790
|
+
fs22.lstatSync(targetPath);
|
|
26791
|
+
} catch {
|
|
26792
|
+
targetTaken = false;
|
|
26793
|
+
}
|
|
26794
|
+
if (targetTaken) {
|
|
26703
26795
|
console.error(`File already exists: ${path31.relative(hubFolder, targetPath)}. Use --name to choose a different name.`);
|
|
26704
26796
|
process.exit(1);
|
|
26705
26797
|
}
|
|
@@ -26732,8 +26824,13 @@ async function evalCaptureCommand(args2) {
|
|
|
26732
26824
|
...captured.evaluator_instructions ? { evaluator_instructions: captured.evaluator_instructions } : {}
|
|
26733
26825
|
};
|
|
26734
26826
|
const yamlObj = buildEvalYamlObject(evalEntry, slug);
|
|
26735
|
-
|
|
26736
|
-
|
|
26827
|
+
const outcome = createFileNoFollow(hubFolder, targetPath, Buffer.from(yaml12.dump(yamlObj, YAML_DUMP_OPTIONS), "utf-8"));
|
|
26828
|
+
if (outcome !== "created") {
|
|
26829
|
+
console.error(
|
|
26830
|
+
`Could not write ${path31.relative(hubFolder, targetPath)} (${outcome === "exists" ? "it appeared meanwhile" : "its folder is reached through a symlink"}). The scenario was created on the platform as ${captured.eval_id} \u2014 run \`wayai pull\` to fetch it.`
|
|
26831
|
+
);
|
|
26832
|
+
process.exit(1);
|
|
26833
|
+
}
|
|
26737
26834
|
const relPath = path31.relative(process.cwd(), targetPath);
|
|
26738
26835
|
console.log(`
|
|
26739
26836
|
Wrote ${relPath}`);
|
|
@@ -26748,6 +26845,7 @@ var init_eval_capture = __esm({
|
|
|
26748
26845
|
init_workspace();
|
|
26749
26846
|
init_utils();
|
|
26750
26847
|
init_yaml_writer();
|
|
26848
|
+
init_fs_safety();
|
|
26751
26849
|
}
|
|
26752
26850
|
});
|
|
26753
26851
|
|
|
@@ -28105,23 +28203,21 @@ var init_set_connection_credential = __esm({
|
|
|
28105
28203
|
});
|
|
28106
28204
|
|
|
28107
28205
|
// src/lib/org-workspace.ts
|
|
28108
|
-
import * as
|
|
28206
|
+
import * as fs23 from "fs";
|
|
28109
28207
|
import * as path32 from "path";
|
|
28110
28208
|
import * as yaml13 from "js-yaml";
|
|
28111
28209
|
function getOrgDir(gitRoot) {
|
|
28112
28210
|
return resolveLayout(gitRoot).orgDir;
|
|
28113
28211
|
}
|
|
28114
28212
|
function orgManifestExists(orgDir) {
|
|
28115
|
-
return
|
|
28213
|
+
return fs23.existsSync(path32.join(orgDir, ORG_MANIFEST_NAME));
|
|
28116
28214
|
}
|
|
28117
28215
|
function parseOrgResources(orgDir) {
|
|
28118
|
-
const manifestPath = path32.join(orgDir, ORG_MANIFEST_NAME);
|
|
28119
|
-
let manifest = {};
|
|
28120
|
-
if (fs25.existsSync(manifestPath)) {
|
|
28121
|
-
manifest = yaml13.load(fs25.readFileSync(manifestPath, "utf-8")) ?? {};
|
|
28122
|
-
}
|
|
28123
|
-
const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
|
|
28124
28216
|
const resourcesDir = path32.join(orgDir, "resources");
|
|
28217
|
+
requireRealSubdirNoSymlink(orgDir, resourcesDir, false);
|
|
28218
|
+
const manifestText = readRealFileOrThrow(orgDir, path32.join(orgDir, ORG_MANIFEST_NAME));
|
|
28219
|
+
const manifest = (manifestText !== null ? yaml13.load(manifestText) : null) ?? {};
|
|
28220
|
+
const rawResources = Array.isArray(manifest.resources) ? manifest.resources : [];
|
|
28125
28221
|
const resources = rawResources.map((res) => {
|
|
28126
28222
|
const resource = { name: res.name };
|
|
28127
28223
|
if (res.id) resource.id = res.id;
|
|
@@ -28134,7 +28230,7 @@ function parseOrgResources(orgDir) {
|
|
|
28134
28230
|
if (Array.isArray(res.tags)) resource.tags = res.tags;
|
|
28135
28231
|
if (Array.isArray(res.folders)) resource.folders = res.folders;
|
|
28136
28232
|
const resDir = path32.join(resourcesDir, slugify(resource.name));
|
|
28137
|
-
if (
|
|
28233
|
+
if (fs23.existsSync(resDir)) {
|
|
28138
28234
|
const files = scanResourceFiles(resDir, "");
|
|
28139
28235
|
if (files.length > 0) resource.files = files;
|
|
28140
28236
|
}
|
|
@@ -28143,28 +28239,29 @@ function parseOrgResources(orgDir) {
|
|
|
28143
28239
|
return { version: 1, resources };
|
|
28144
28240
|
}
|
|
28145
28241
|
function writeOrgResources(orgDir, payload) {
|
|
28146
|
-
|
|
28242
|
+
fs23.mkdirSync(orgDir, { recursive: true });
|
|
28243
|
+
const resourcesDir = path32.join(orgDir, "resources");
|
|
28244
|
+
requireRealSubdirNoSymlink(orgDir, resourcesDir, false);
|
|
28147
28245
|
const resources = payload.resources ?? [];
|
|
28148
28246
|
const manifestResources = resources.map((r) => {
|
|
28149
28247
|
const { files: _files, ...rest } = r;
|
|
28150
28248
|
return rest;
|
|
28151
28249
|
});
|
|
28152
|
-
|
|
28250
|
+
writeFileNoFollow(
|
|
28251
|
+
orgDir,
|
|
28153
28252
|
path32.join(orgDir, ORG_MANIFEST_NAME),
|
|
28154
|
-
yaml13.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS),
|
|
28155
|
-
"utf-8"
|
|
28253
|
+
Buffer.from(yaml13.dump({ version: 1, resources: manifestResources }, YAML_DUMP_OPTIONS), "utf-8")
|
|
28156
28254
|
);
|
|
28157
|
-
const resourcesDir = path32.join(orgDir, "resources");
|
|
28158
28255
|
const currentSlugs = /* @__PURE__ */ new Set();
|
|
28159
28256
|
for (const resource of resources) {
|
|
28160
28257
|
const resSlug = slugify(resource.name);
|
|
28161
28258
|
currentSlugs.add(resSlug);
|
|
28162
28259
|
writeResourceFileTree(path32.join(resourcesDir, resSlug), resource.files || [], orgDir);
|
|
28163
28260
|
}
|
|
28164
|
-
if (
|
|
28165
|
-
for (const entry of
|
|
28261
|
+
if (fs23.existsSync(resourcesDir)) {
|
|
28262
|
+
for (const entry of fs23.readdirSync(resourcesDir, { withFileTypes: true })) {
|
|
28166
28263
|
if (entry.isDirectory() && !currentSlugs.has(entry.name)) {
|
|
28167
|
-
|
|
28264
|
+
fs23.rmSync(path32.join(resourcesDir, entry.name), { recursive: true, force: true });
|
|
28168
28265
|
}
|
|
28169
28266
|
}
|
|
28170
28267
|
}
|
|
@@ -28184,6 +28281,7 @@ var init_org_workspace = __esm({
|
|
|
28184
28281
|
"use strict";
|
|
28185
28282
|
init_utils();
|
|
28186
28283
|
init_layout();
|
|
28284
|
+
init_fs_safety();
|
|
28187
28285
|
init_resource_files();
|
|
28188
28286
|
init_yaml_writer();
|
|
28189
28287
|
ORG_MANIFEST_NAME = "resources.yaml";
|
|
@@ -28469,7 +28567,7 @@ var init_report_edit_args = __esm({
|
|
|
28469
28567
|
});
|
|
28470
28568
|
|
|
28471
28569
|
// src/lib/file-map.ts
|
|
28472
|
-
import * as
|
|
28570
|
+
import * as fs24 from "fs";
|
|
28473
28571
|
import * as path33 from "path";
|
|
28474
28572
|
function isSafeRelPath(rel) {
|
|
28475
28573
|
if (rel.length === 0 || rel.length > 300) return false;
|
|
@@ -28486,8 +28584,8 @@ function writeFileMap(targetDir, files) {
|
|
|
28486
28584
|
throw new Error(`Refusing to write unsafe path: ${rel}`);
|
|
28487
28585
|
}
|
|
28488
28586
|
const abs = path33.join(targetDir, rel);
|
|
28489
|
-
|
|
28490
|
-
|
|
28587
|
+
fs24.mkdirSync(path33.dirname(abs), { recursive: true });
|
|
28588
|
+
fs24.writeFileSync(abs, body, "utf-8");
|
|
28491
28589
|
written.push(rel);
|
|
28492
28590
|
}
|
|
28493
28591
|
return written;
|
|
@@ -28503,7 +28601,7 @@ var admin_exports = {};
|
|
|
28503
28601
|
__export(admin_exports, {
|
|
28504
28602
|
adminCommand: () => adminCommand
|
|
28505
28603
|
});
|
|
28506
|
-
import * as
|
|
28604
|
+
import * as fs25 from "fs";
|
|
28507
28605
|
import * as path34 from "path";
|
|
28508
28606
|
async function adminCommand(args2) {
|
|
28509
28607
|
const [group, ...afterGroup] = args2;
|
|
@@ -28819,7 +28917,7 @@ async function runArchiveRead(positional, flagArgs) {
|
|
|
28819
28917
|
exitOnApiError(err);
|
|
28820
28918
|
throw err;
|
|
28821
28919
|
}
|
|
28822
|
-
|
|
28920
|
+
fs25.writeFileSync(outPath, zip);
|
|
28823
28921
|
console.log(`Wrote ${zip.byteLength} bytes to ${outPath}`);
|
|
28824
28922
|
return;
|
|
28825
28923
|
}
|
|
@@ -28961,7 +29059,7 @@ async function runSkillInstall(positional) {
|
|
|
28961
29059
|
throw err;
|
|
28962
29060
|
}
|
|
28963
29061
|
const root = findGitRoot() ?? process.cwd();
|
|
28964
|
-
const present = HARNESS_SKILL_DIRS.filter((dir) =>
|
|
29062
|
+
const present = HARNESS_SKILL_DIRS.filter((dir) => fs25.existsSync(path34.join(root, dir)));
|
|
28965
29063
|
const targets = present.length > 0 ? present : HARNESS_SKILL_DIRS;
|
|
28966
29064
|
const fileCount = Object.keys(res.files).length;
|
|
28967
29065
|
const relDirs = targets.map((harness) => {
|
|
@@ -30519,7 +30617,7 @@ var init_actions = __esm({
|
|
|
30519
30617
|
|
|
30520
30618
|
// src/data/commands/attachments.ts
|
|
30521
30619
|
import { Command as Command2 } from "commander";
|
|
30522
|
-
import { readFileSync as
|
|
30620
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
30523
30621
|
function findAttachmentByFilename(attachments, filename) {
|
|
30524
30622
|
return attachments.find((a) => a.key.endsWith(`/${filename}`)) ?? null;
|
|
30525
30623
|
}
|
|
@@ -30560,7 +30658,7 @@ function buildAttachmentsCommand() {
|
|
|
30560
30658
|
printOutput(data, outputFormat(this));
|
|
30561
30659
|
return;
|
|
30562
30660
|
}
|
|
30563
|
-
const body =
|
|
30661
|
+
const body = readFileSync18(opts.file);
|
|
30564
30662
|
await client.upload(uploadPathFrom(data?.upload_url), body, opts.contentType);
|
|
30565
30663
|
printOutput({ ...data, uploaded: true }, outputFormat(this));
|
|
30566
30664
|
});
|
|
@@ -30960,7 +31058,7 @@ var init_import = __esm({
|
|
|
30960
31058
|
|
|
30961
31059
|
// src/data/commands/providers.ts
|
|
30962
31060
|
import { Command as Command5 } from "commander";
|
|
30963
|
-
import { writeFileSync as
|
|
31061
|
+
import { writeFileSync as writeFileSync9 } from "fs";
|
|
30964
31062
|
function providerSegment(provider) {
|
|
30965
31063
|
if (!VALID_PROVIDERS.includes(provider)) {
|
|
30966
31064
|
throw expected(`Unknown provider ${JSON.stringify(provider)}. Expected one of: ${VALID_PROVIDERS_HELP}.`);
|
|
@@ -30993,7 +31091,7 @@ function buildBasesProvidersCommand() {
|
|
|
30993
31091
|
);
|
|
30994
31092
|
if (opts.to) {
|
|
30995
31093
|
try {
|
|
30996
|
-
|
|
31094
|
+
writeFileSync9(opts.to, JSON.stringify(data, null, 2));
|
|
30997
31095
|
} catch (e) {
|
|
30998
31096
|
throw expected(`--to ${opts.to}: ${e instanceof Error ? e.message : "could not be written"}`);
|
|
30999
31097
|
}
|
|
@@ -31040,7 +31138,7 @@ var init_providers = __esm({
|
|
|
31040
31138
|
|
|
31041
31139
|
// src/data/commands/report.ts
|
|
31042
31140
|
import { Command as Command6 } from "commander";
|
|
31043
|
-
import { readFileSync as
|
|
31141
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
31044
31142
|
import { dirname as dirname12, join as join30 } from "path";
|
|
31045
31143
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
31046
31144
|
function resolveCliVersion() {
|
|
@@ -31049,7 +31147,7 @@ function resolveCliVersion() {
|
|
|
31049
31147
|
join30(here, "..", "..", "..", "package.json")
|
|
31050
31148
|
]) {
|
|
31051
31149
|
try {
|
|
31052
|
-
const version = JSON.parse(
|
|
31150
|
+
const version = JSON.parse(readFileSync19(candidate, "utf-8")).version;
|
|
31053
31151
|
if (typeof version === "string" && version) return version;
|
|
31054
31152
|
} catch {
|
|
31055
31153
|
}
|
|
@@ -31251,7 +31349,7 @@ var init_report2 = __esm({
|
|
|
31251
31349
|
|
|
31252
31350
|
// src/data/commands/credentials.ts
|
|
31253
31351
|
import { Command as Command7 } from "commander";
|
|
31254
|
-
import { readFileSync as
|
|
31352
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
31255
31353
|
function withValueSourceOptions(cmd, what) {
|
|
31256
31354
|
return cmd.option(
|
|
31257
31355
|
"--file <path>",
|
|
@@ -31264,7 +31362,7 @@ async function resolveValue(opts, label) {
|
|
|
31264
31362
|
throw expected("--file cannot be combined with --value-stdin or --value-prompt \u2014 pass one.");
|
|
31265
31363
|
}
|
|
31266
31364
|
try {
|
|
31267
|
-
return
|
|
31365
|
+
return readFileSync20(opts.file).toString("base64");
|
|
31268
31366
|
} catch (e) {
|
|
31269
31367
|
throw expected(`--file ${opts.file}: ${e instanceof Error ? e.message : "could not be read"}`);
|
|
31270
31368
|
}
|
|
@@ -31413,7 +31511,7 @@ var init_credentials = __esm({
|
|
|
31413
31511
|
|
|
31414
31512
|
// src/data/commands/sql.ts
|
|
31415
31513
|
import { Command as Command8 } from "commander";
|
|
31416
|
-
import { readFileSync as
|
|
31514
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
31417
31515
|
function buildBasesSqlCommand() {
|
|
31418
31516
|
return withBaseOption(new Command8("sql")).description("Execute a read-only SQL query against base data").argument("[query]", "SQL query (SELECT only)").option("--file <path>", "Read SQL from a file instead of the argument").option(
|
|
31419
31517
|
"--param <kv...>",
|
|
@@ -31423,7 +31521,7 @@ function buildBasesSqlCommand() {
|
|
|
31423
31521
|
let query;
|
|
31424
31522
|
if (opts.file) {
|
|
31425
31523
|
try {
|
|
31426
|
-
query =
|
|
31524
|
+
query = readFileSync21(opts.file, "utf-8").trim();
|
|
31427
31525
|
} catch (e) {
|
|
31428
31526
|
throw expected(`--file ${opts.file}: ${e instanceof Error ? e.message : "could not be read"}`);
|
|
31429
31527
|
}
|
|
@@ -32078,8 +32176,8 @@ var init_file_types = __esm({
|
|
|
32078
32176
|
|
|
32079
32177
|
// src/data/commands/files.ts
|
|
32080
32178
|
import { Command as Command12 } from "commander";
|
|
32081
|
-
import { readFileSync as
|
|
32082
|
-
import { basename as
|
|
32179
|
+
import { readFileSync as readFileSync22, writeFileSync as writeFileSync10 } from "fs";
|
|
32180
|
+
import { basename as basename19 } from "path";
|
|
32083
32181
|
function renderFileDiff(fileType, filePath, from, to, d) {
|
|
32084
32182
|
console.log(sanitizeTerminalText(`${fileType}/${filePath}: v${from} \u2192 v${to}`));
|
|
32085
32183
|
const md = d.metadata_delta;
|
|
@@ -32111,7 +32209,7 @@ function renderFileDiff(fileType, filePath, from, to, d) {
|
|
|
32111
32209
|
}
|
|
32112
32210
|
function downloadTarget(remotePath, to) {
|
|
32113
32211
|
if (to) return to;
|
|
32114
|
-
const derived =
|
|
32212
|
+
const derived = basename19(remotePath);
|
|
32115
32213
|
if (derived === "" || derived === "." || derived === "..") {
|
|
32116
32214
|
throw expected(
|
|
32117
32215
|
`Cannot derive a local filename from "${remotePath}" \u2014 pass --to <local> to name it.`
|
|
@@ -32127,7 +32225,7 @@ function buildFilesCommand() {
|
|
|
32127
32225
|
"Upload a local file to a path (e.g. wayai files put reports q3/summary.pdf --file ./summary.pdf)"
|
|
32128
32226
|
).requiredOption("--file <local>", "Local file to upload").option("--content-type <type>", "MIME type", "application/octet-stream").action(async function(fileType, filePath, opts) {
|
|
32129
32227
|
const base = pathSegment(requireBase(this), "--base");
|
|
32130
|
-
const body =
|
|
32228
|
+
const body = readFileSync22(opts.file);
|
|
32131
32229
|
const client = await createDataClient();
|
|
32132
32230
|
printOutput(
|
|
32133
32231
|
await client.upload(
|
|
@@ -32158,7 +32256,7 @@ function buildFilesCommand() {
|
|
|
32158
32256
|
const { bytes } = await client.download(
|
|
32159
32257
|
`/v1/${base}/files/${pathSegment(fileType, "file_type")}/${encoded}${versionQs ? `?${versionQs}` : ""}`
|
|
32160
32258
|
);
|
|
32161
|
-
|
|
32259
|
+
writeFileSync10(out, bytes);
|
|
32162
32260
|
console.log(`Downloaded to ${out}`);
|
|
32163
32261
|
});
|
|
32164
32262
|
files.command("history <file_type> <path>").description("List the content versions of a file (newest first)").option("--limit <n>", "Max versions to return").option("--offset <n>", "Pagination offset").action(async function(fileType, filePath, opts) {
|
|
@@ -33176,7 +33274,7 @@ init_errors2();
|
|
|
33176
33274
|
init_mask_secrets();
|
|
33177
33275
|
init_utils();
|
|
33178
33276
|
init_registry();
|
|
33179
|
-
import { readFileSync as
|
|
33277
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
33180
33278
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
33181
33279
|
import { dirname as dirname13, join as join31 } from "path";
|
|
33182
33280
|
|
|
@@ -33334,7 +33432,7 @@ Run \`wayai admin skill install\` to update.`);
|
|
|
33334
33432
|
|
|
33335
33433
|
// src/index.ts
|
|
33336
33434
|
var __dirname = dirname13(fileURLToPath3(import.meta.url));
|
|
33337
|
-
var pkg = JSON.parse(
|
|
33435
|
+
var pkg = JSON.parse(readFileSync23(join31(__dirname, "..", "package.json"), "utf-8"));
|
|
33338
33436
|
var [, , command, ...args] = process.argv;
|
|
33339
33437
|
var isBackgroundRefresh = command === REFRESH_COMMAND;
|
|
33340
33438
|
if (!isBackgroundRefresh) initSentry(command, pkg.version);
|