aiblueprint-cli 1.4.57 → 1.4.59
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/README.md +3 -0
- package/dist/cli.js +717 -228
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -33587,6 +33587,46 @@ async function mergeCodexConfigFile(sourceConfigPath, codexDir) {
|
|
|
33587
33587
|
// src/lib/configs-store.ts
|
|
33588
33588
|
var import_fs_extra7 = __toESM(require_lib4(), 1);
|
|
33589
33589
|
import path11 from "path";
|
|
33590
|
+
var COMMON_EXCLUDED_NAMES = new Set([
|
|
33591
|
+
".git",
|
|
33592
|
+
".DS_Store",
|
|
33593
|
+
"node_modules"
|
|
33594
|
+
]);
|
|
33595
|
+
var EXCLUDED_RUNTIME_PATHS = {
|
|
33596
|
+
".claude": new Set([
|
|
33597
|
+
"backups",
|
|
33598
|
+
"cache",
|
|
33599
|
+
"debug",
|
|
33600
|
+
"file-history",
|
|
33601
|
+
"logs",
|
|
33602
|
+
"output",
|
|
33603
|
+
"paste-cache",
|
|
33604
|
+
"plugins/cache",
|
|
33605
|
+
"projects",
|
|
33606
|
+
"session-env",
|
|
33607
|
+
"sessions",
|
|
33608
|
+
"stats-cache.json",
|
|
33609
|
+
"security.log"
|
|
33610
|
+
]),
|
|
33611
|
+
".codex": new Set([
|
|
33612
|
+
"archived_sessions",
|
|
33613
|
+
"browser/sessions",
|
|
33614
|
+
"cache",
|
|
33615
|
+
"log",
|
|
33616
|
+
"logs_2.sqlite",
|
|
33617
|
+
"logs_2.sqlite-shm",
|
|
33618
|
+
"logs_2.sqlite-wal",
|
|
33619
|
+
"models_cache.json",
|
|
33620
|
+
"plugins/cache",
|
|
33621
|
+
"sessions",
|
|
33622
|
+
"vendor_imports/skills-curated-cache.json"
|
|
33623
|
+
]),
|
|
33624
|
+
".agents": new Set([
|
|
33625
|
+
"cache",
|
|
33626
|
+
"logs",
|
|
33627
|
+
"sessions"
|
|
33628
|
+
])
|
|
33629
|
+
};
|
|
33590
33630
|
function getConfigStorePaths(rootDir) {
|
|
33591
33631
|
const baseDir = path11.join(rootDir, ".aiblueprint");
|
|
33592
33632
|
return {
|
|
@@ -33633,14 +33673,33 @@ async function hasContent(folderPath) {
|
|
|
33633
33673
|
const entries = await import_fs_extra7.default.readdir(folderPath);
|
|
33634
33674
|
return entries.some((entry) => entry !== ".DS_Store");
|
|
33635
33675
|
}
|
|
33636
|
-
|
|
33676
|
+
function normalizeRelativePath(relativePath) {
|
|
33677
|
+
return relativePath.split(path11.sep).join("/");
|
|
33678
|
+
}
|
|
33679
|
+
function shouldCopyManagedPath(folderName, sourceRoot, sourcePath) {
|
|
33680
|
+
const basename = path11.basename(sourcePath);
|
|
33681
|
+
if (COMMON_EXCLUDED_NAMES.has(basename))
|
|
33682
|
+
return false;
|
|
33683
|
+
const relativePath = normalizeRelativePath(path11.relative(sourceRoot, sourcePath));
|
|
33684
|
+
if (!relativePath)
|
|
33685
|
+
return true;
|
|
33686
|
+
const excludedPaths = EXCLUDED_RUNTIME_PATHS[folderName];
|
|
33687
|
+
if (excludedPaths.has(relativePath))
|
|
33688
|
+
return false;
|
|
33689
|
+
for (const excludedPath of excludedPaths) {
|
|
33690
|
+
if (relativePath.startsWith(`${excludedPath}/`))
|
|
33691
|
+
return false;
|
|
33692
|
+
}
|
|
33693
|
+
return true;
|
|
33694
|
+
}
|
|
33695
|
+
async function copyManagedFolder(name, source, destination) {
|
|
33637
33696
|
await import_fs_extra7.default.copy(source, destination, {
|
|
33638
33697
|
overwrite: true,
|
|
33639
33698
|
dereference: false,
|
|
33640
33699
|
filter: async (src) => {
|
|
33641
33700
|
try {
|
|
33642
33701
|
const stat = await import_fs_extra7.default.lstat(src);
|
|
33643
|
-
return !stat.isSymbolicLink();
|
|
33702
|
+
return !stat.isSymbolicLink() && shouldCopyManagedPath(name, source, src);
|
|
33644
33703
|
} catch {
|
|
33645
33704
|
return true;
|
|
33646
33705
|
}
|
|
@@ -33676,7 +33735,7 @@ async function snapshotByCopy(snapshotPath, folders, metadata) {
|
|
|
33676
33735
|
for (const folder of managedFolders(folders)) {
|
|
33677
33736
|
if (!await hasContent(folder.path))
|
|
33678
33737
|
continue;
|
|
33679
|
-
await copyManagedFolder(folder.path, path11.join(snapshotPath, folder.name));
|
|
33738
|
+
await copyManagedFolder(folder.name, folder.path, path11.join(snapshotPath, folder.name));
|
|
33680
33739
|
copied.push(folder.name);
|
|
33681
33740
|
}
|
|
33682
33741
|
if (copied.length === 0) {
|
|
@@ -33769,7 +33828,7 @@ async function restoreSnapshot(snapshotPath, folders) {
|
|
|
33769
33828
|
if (!await import_fs_extra7.default.pathExists(source))
|
|
33770
33829
|
continue;
|
|
33771
33830
|
await import_fs_extra7.default.ensureDir(path11.dirname(folder.path));
|
|
33772
|
-
await copyManagedFolder(source, folder.path);
|
|
33831
|
+
await copyManagedFolder(folder.name, source, folder.path);
|
|
33773
33832
|
restored.push(folder.name);
|
|
33774
33833
|
}
|
|
33775
33834
|
return restored;
|
|
@@ -34651,6 +34710,433 @@ async function symlinkCommand(params = {}) {
|
|
|
34651
34710
|
}
|
|
34652
34711
|
}
|
|
34653
34712
|
|
|
34713
|
+
// src/lib/agents-unifier.ts
|
|
34714
|
+
var import_fs_extra11 = __toESM(require_lib4(), 1);
|
|
34715
|
+
import crypto from "crypto";
|
|
34716
|
+
import os13 from "os";
|
|
34717
|
+
import path15 from "path";
|
|
34718
|
+
var IGNORED_ENTRY_NAMES = new Set([
|
|
34719
|
+
".DS_Store",
|
|
34720
|
+
".git",
|
|
34721
|
+
"node_modules"
|
|
34722
|
+
]);
|
|
34723
|
+
function uniqueByPath(candidates) {
|
|
34724
|
+
const seen = new Set;
|
|
34725
|
+
const unique = [];
|
|
34726
|
+
for (const candidate of candidates) {
|
|
34727
|
+
const resolved = path15.resolve(candidate.path);
|
|
34728
|
+
if (seen.has(resolved))
|
|
34729
|
+
continue;
|
|
34730
|
+
seen.add(resolved);
|
|
34731
|
+
unique.push({ ...candidate, path: resolved });
|
|
34732
|
+
}
|
|
34733
|
+
return unique;
|
|
34734
|
+
}
|
|
34735
|
+
function getContainerCandidates(options) {
|
|
34736
|
+
const folders = resolveFolders(options);
|
|
34737
|
+
const cursorDir = path15.join(folders.rootDir, ".cursor");
|
|
34738
|
+
const factoryDir = path15.join(folders.rootDir, ".factory");
|
|
34739
|
+
const opencodeDir = path15.join(folders.rootDir, ".config", "opencode");
|
|
34740
|
+
return uniqueByPath([
|
|
34741
|
+
{
|
|
34742
|
+
category: "skills",
|
|
34743
|
+
label: "agents-skills",
|
|
34744
|
+
path: path15.join(folders.agentsDir, "skills"),
|
|
34745
|
+
isDestination: true
|
|
34746
|
+
},
|
|
34747
|
+
{
|
|
34748
|
+
category: "skills",
|
|
34749
|
+
label: "claude-skills",
|
|
34750
|
+
path: path15.join(folders.claudeDir, "skills"),
|
|
34751
|
+
linkWhenMissing: true
|
|
34752
|
+
},
|
|
34753
|
+
{
|
|
34754
|
+
category: "skills",
|
|
34755
|
+
label: "codex-skills",
|
|
34756
|
+
path: path15.join(folders.codexDir, "skills"),
|
|
34757
|
+
linkWhenMissing: true
|
|
34758
|
+
},
|
|
34759
|
+
{
|
|
34760
|
+
category: "skills",
|
|
34761
|
+
label: "cursor-skills",
|
|
34762
|
+
path: path15.join(cursorDir, "skills"),
|
|
34763
|
+
linkWhenParentExists: true
|
|
34764
|
+
},
|
|
34765
|
+
{
|
|
34766
|
+
category: "skills",
|
|
34767
|
+
label: "cursor-skills-cursor",
|
|
34768
|
+
path: path15.join(cursorDir, "skills-cursor"),
|
|
34769
|
+
linkWhenParentExists: true
|
|
34770
|
+
},
|
|
34771
|
+
{
|
|
34772
|
+
category: "skills",
|
|
34773
|
+
label: "factory-skills",
|
|
34774
|
+
path: path15.join(factoryDir, "skills"),
|
|
34775
|
+
linkWhenParentExists: true
|
|
34776
|
+
},
|
|
34777
|
+
{
|
|
34778
|
+
category: "skills",
|
|
34779
|
+
label: "opencode-skill",
|
|
34780
|
+
path: path15.join(opencodeDir, "skill"),
|
|
34781
|
+
linkWhenParentExists: true
|
|
34782
|
+
},
|
|
34783
|
+
{
|
|
34784
|
+
category: "skills",
|
|
34785
|
+
label: "opencode-skills",
|
|
34786
|
+
path: path15.join(opencodeDir, "skills"),
|
|
34787
|
+
linkWhenParentExists: true
|
|
34788
|
+
},
|
|
34789
|
+
{
|
|
34790
|
+
category: "agents",
|
|
34791
|
+
label: "agents-agents",
|
|
34792
|
+
path: path15.join(folders.agentsDir, "agents"),
|
|
34793
|
+
isDestination: true
|
|
34794
|
+
},
|
|
34795
|
+
{
|
|
34796
|
+
category: "agents",
|
|
34797
|
+
label: "claude-agents",
|
|
34798
|
+
path: path15.join(folders.claudeDir, "agents"),
|
|
34799
|
+
linkWhenMissing: true
|
|
34800
|
+
},
|
|
34801
|
+
{
|
|
34802
|
+
category: "agents",
|
|
34803
|
+
label: "claude-agnets",
|
|
34804
|
+
path: path15.join(folders.claudeDir, "agnets")
|
|
34805
|
+
},
|
|
34806
|
+
{
|
|
34807
|
+
category: "agents",
|
|
34808
|
+
label: "codex-agents",
|
|
34809
|
+
path: path15.join(folders.codexDir, "agents"),
|
|
34810
|
+
linkWhenMissing: true
|
|
34811
|
+
},
|
|
34812
|
+
{
|
|
34813
|
+
category: "agents",
|
|
34814
|
+
label: "cursor-agents",
|
|
34815
|
+
path: path15.join(cursorDir, "agents"),
|
|
34816
|
+
linkWhenParentExists: true
|
|
34817
|
+
},
|
|
34818
|
+
{
|
|
34819
|
+
category: "agents",
|
|
34820
|
+
label: "factory-droids",
|
|
34821
|
+
path: path15.join(factoryDir, "droids"),
|
|
34822
|
+
linkWhenParentExists: true
|
|
34823
|
+
},
|
|
34824
|
+
{
|
|
34825
|
+
category: "agents",
|
|
34826
|
+
label: "opencode-agent",
|
|
34827
|
+
path: path15.join(opencodeDir, "agent"),
|
|
34828
|
+
linkWhenParentExists: true
|
|
34829
|
+
},
|
|
34830
|
+
{
|
|
34831
|
+
category: "agents",
|
|
34832
|
+
label: "opencode-agents",
|
|
34833
|
+
path: path15.join(opencodeDir, "agents"),
|
|
34834
|
+
linkWhenParentExists: true
|
|
34835
|
+
}
|
|
34836
|
+
]);
|
|
34837
|
+
}
|
|
34838
|
+
function shouldCollectEntry(category, entry) {
|
|
34839
|
+
if (IGNORED_ENTRY_NAMES.has(entry.name))
|
|
34840
|
+
return false;
|
|
34841
|
+
if (category === "skills" && entry.name === ".cursor-managed-skills-manifest.json") {
|
|
34842
|
+
return true;
|
|
34843
|
+
}
|
|
34844
|
+
return entry.isFile() || entry.isDirectory() || entry.isSymbolicLink();
|
|
34845
|
+
}
|
|
34846
|
+
async function pathExistsOrSymlink(targetPath) {
|
|
34847
|
+
const stat = await import_fs_extra11.default.lstat(targetPath).catch(() => null);
|
|
34848
|
+
return Boolean(stat);
|
|
34849
|
+
}
|
|
34850
|
+
async function realPathIfPossible(targetPath) {
|
|
34851
|
+
try {
|
|
34852
|
+
return await import_fs_extra11.default.realpath(targetPath);
|
|
34853
|
+
} catch {
|
|
34854
|
+
return null;
|
|
34855
|
+
}
|
|
34856
|
+
}
|
|
34857
|
+
function samePath(a, b) {
|
|
34858
|
+
return path15.resolve(a) === path15.resolve(b);
|
|
34859
|
+
}
|
|
34860
|
+
function hashString(value) {
|
|
34861
|
+
return crypto.createHash("sha256").update(value).digest("hex");
|
|
34862
|
+
}
|
|
34863
|
+
async function hashPath(targetPath) {
|
|
34864
|
+
const stat = await import_fs_extra11.default.lstat(targetPath);
|
|
34865
|
+
if (stat.isSymbolicLink()) {
|
|
34866
|
+
const linkTarget = await import_fs_extra11.default.readlink(targetPath);
|
|
34867
|
+
return hashString(`symlink:${linkTarget}`);
|
|
34868
|
+
}
|
|
34869
|
+
if (stat.isFile()) {
|
|
34870
|
+
const fileHash = crypto.createHash("sha256");
|
|
34871
|
+
fileHash.update("file:");
|
|
34872
|
+
fileHash.update(await import_fs_extra11.default.readFile(targetPath));
|
|
34873
|
+
return fileHash.digest("hex");
|
|
34874
|
+
}
|
|
34875
|
+
if (stat.isDirectory()) {
|
|
34876
|
+
const entries = (await import_fs_extra11.default.readdir(targetPath, { withFileTypes: true })).filter((entry) => !IGNORED_ENTRY_NAMES.has(entry.name)).sort((a, b) => a.name.localeCompare(b.name));
|
|
34877
|
+
const dirHash = crypto.createHash("sha256");
|
|
34878
|
+
dirHash.update("dir:");
|
|
34879
|
+
for (const entry of entries) {
|
|
34880
|
+
dirHash.update(entry.name);
|
|
34881
|
+
dirHash.update("\x00");
|
|
34882
|
+
dirHash.update(await hashPath(path15.join(targetPath, entry.name)));
|
|
34883
|
+
dirHash.update("\x00");
|
|
34884
|
+
}
|
|
34885
|
+
return dirHash.digest("hex");
|
|
34886
|
+
}
|
|
34887
|
+
return hashString(`other:${stat.mode}:${stat.size}`);
|
|
34888
|
+
}
|
|
34889
|
+
function suffixFromLabel(label) {
|
|
34890
|
+
return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "source";
|
|
34891
|
+
}
|
|
34892
|
+
function nameWithSuffix(name, suffix, index) {
|
|
34893
|
+
const parsed = path15.parse(name);
|
|
34894
|
+
const numberedSuffix = index === 1 ? suffix : `${suffix}-${index}`;
|
|
34895
|
+
if (parsed.ext && parsed.name) {
|
|
34896
|
+
return `${parsed.name}--${numberedSuffix}${parsed.ext}`;
|
|
34897
|
+
}
|
|
34898
|
+
return `${name}--${numberedSuffix}`;
|
|
34899
|
+
}
|
|
34900
|
+
async function findTargetName(destinationDir, originalName, label) {
|
|
34901
|
+
const suffix = suffixFromLabel(label);
|
|
34902
|
+
let index = 1;
|
|
34903
|
+
while (true) {
|
|
34904
|
+
const candidate = nameWithSuffix(originalName, suffix, index);
|
|
34905
|
+
if (!await pathExistsOrSymlink(path15.join(destinationDir, candidate))) {
|
|
34906
|
+
return candidate;
|
|
34907
|
+
}
|
|
34908
|
+
index++;
|
|
34909
|
+
}
|
|
34910
|
+
}
|
|
34911
|
+
async function addExistingDestinationHashes(destinationDir, knownHashes) {
|
|
34912
|
+
if (!await import_fs_extra11.default.pathExists(destinationDir))
|
|
34913
|
+
return;
|
|
34914
|
+
const entries = await import_fs_extra11.default.readdir(destinationDir, { withFileTypes: true });
|
|
34915
|
+
for (const entry of entries) {
|
|
34916
|
+
if (IGNORED_ENTRY_NAMES.has(entry.name))
|
|
34917
|
+
continue;
|
|
34918
|
+
const entryPath = path15.join(destinationDir, entry.name);
|
|
34919
|
+
knownHashes.set(await hashPath(entryPath), entry.name);
|
|
34920
|
+
}
|
|
34921
|
+
}
|
|
34922
|
+
async function importCategoryEntries(category, candidates, destinationDir, result) {
|
|
34923
|
+
await import_fs_extra11.default.ensureDir(destinationDir);
|
|
34924
|
+
const destinationRealPath = await realPathIfPossible(destinationDir);
|
|
34925
|
+
const knownHashes = new Map;
|
|
34926
|
+
await addExistingDestinationHashes(destinationDir, knownHashes);
|
|
34927
|
+
for (const candidate of candidates) {
|
|
34928
|
+
if (candidate.category !== category || candidate.isDestination)
|
|
34929
|
+
continue;
|
|
34930
|
+
const candidateStat = await import_fs_extra11.default.lstat(candidate.path).catch(() => null);
|
|
34931
|
+
if (!candidateStat)
|
|
34932
|
+
continue;
|
|
34933
|
+
const candidateRealPath = await realPathIfPossible(candidate.path);
|
|
34934
|
+
if (destinationRealPath && candidateRealPath && samePath(destinationRealPath, candidateRealPath)) {
|
|
34935
|
+
continue;
|
|
34936
|
+
}
|
|
34937
|
+
const entries = await import_fs_extra11.default.readdir(candidate.path, { withFileTypes: true }).catch(() => null);
|
|
34938
|
+
if (!entries) {
|
|
34939
|
+
result.skipped.push({
|
|
34940
|
+
category,
|
|
34941
|
+
path: candidate.path,
|
|
34942
|
+
reason: "Could not read directory"
|
|
34943
|
+
});
|
|
34944
|
+
continue;
|
|
34945
|
+
}
|
|
34946
|
+
for (const entry of entries) {
|
|
34947
|
+
if (!shouldCollectEntry(category, entry))
|
|
34948
|
+
continue;
|
|
34949
|
+
const sourcePath = path15.join(candidate.path, entry.name);
|
|
34950
|
+
const sourceHash = await hashPath(sourcePath);
|
|
34951
|
+
const existingName = knownHashes.get(sourceHash);
|
|
34952
|
+
if (existingName) {
|
|
34953
|
+
result.duplicates.push({
|
|
34954
|
+
category,
|
|
34955
|
+
name: entry.name,
|
|
34956
|
+
from: sourcePath,
|
|
34957
|
+
keptAs: path15.join(destinationDir, existingName)
|
|
34958
|
+
});
|
|
34959
|
+
continue;
|
|
34960
|
+
}
|
|
34961
|
+
let targetName = entry.name;
|
|
34962
|
+
let targetPath = path15.join(destinationDir, targetName);
|
|
34963
|
+
if (await pathExistsOrSymlink(targetPath)) {
|
|
34964
|
+
targetName = await findTargetName(destinationDir, entry.name, candidate.label);
|
|
34965
|
+
targetPath = path15.join(destinationDir, targetName);
|
|
34966
|
+
result.renamed.push({
|
|
34967
|
+
category,
|
|
34968
|
+
name: entry.name,
|
|
34969
|
+
from: sourcePath,
|
|
34970
|
+
to: targetPath,
|
|
34971
|
+
reason: "Same name with different content"
|
|
34972
|
+
});
|
|
34973
|
+
}
|
|
34974
|
+
await import_fs_extra11.default.copy(sourcePath, targetPath, {
|
|
34975
|
+
dereference: false,
|
|
34976
|
+
overwrite: false
|
|
34977
|
+
});
|
|
34978
|
+
knownHashes.set(sourceHash, targetName);
|
|
34979
|
+
result.imported.push({
|
|
34980
|
+
category,
|
|
34981
|
+
name: entry.name,
|
|
34982
|
+
from: sourcePath,
|
|
34983
|
+
to: targetPath
|
|
34984
|
+
});
|
|
34985
|
+
}
|
|
34986
|
+
}
|
|
34987
|
+
}
|
|
34988
|
+
function timestamp2(date = new Date) {
|
|
34989
|
+
return date.toISOString().replace(/\.\d{3}Z$/, "").replace(/[:T]/g, "-");
|
|
34990
|
+
}
|
|
34991
|
+
function safeRelativePath(rootDir, targetPath) {
|
|
34992
|
+
const relativePath = path15.relative(rootDir, targetPath);
|
|
34993
|
+
if (!relativePath || relativePath.startsWith("..") || path15.isAbsolute(relativePath)) {
|
|
34994
|
+
return path15.join("external", targetPath.replace(/[^a-zA-Z0-9._-]+/g, "-"));
|
|
34995
|
+
}
|
|
34996
|
+
return relativePath;
|
|
34997
|
+
}
|
|
34998
|
+
function createBackupPath(rootDir) {
|
|
34999
|
+
return path15.join(rootDir, ".aiblueprint", "backups", "agents-unify-sources", timestamp2());
|
|
35000
|
+
}
|
|
35001
|
+
async function ensureBackupPath(result) {
|
|
35002
|
+
if (!result.backupPath) {
|
|
35003
|
+
result.backupPath = createBackupPath(result.rootDir);
|
|
35004
|
+
await import_fs_extra11.default.ensureDir(result.backupPath);
|
|
35005
|
+
}
|
|
35006
|
+
return result.backupPath;
|
|
35007
|
+
}
|
|
35008
|
+
async function createDirectorySymlink(source, target) {
|
|
35009
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(target));
|
|
35010
|
+
if (os13.platform() === "win32") {
|
|
35011
|
+
await import_fs_extra11.default.symlink(source, target, "junction");
|
|
35012
|
+
return;
|
|
35013
|
+
}
|
|
35014
|
+
await import_fs_extra11.default.symlink(source, target, "dir");
|
|
35015
|
+
}
|
|
35016
|
+
async function shouldLinkMissingContainer(candidate) {
|
|
35017
|
+
if (candidate.linkWhenMissing)
|
|
35018
|
+
return true;
|
|
35019
|
+
if (!candidate.linkWhenParentExists)
|
|
35020
|
+
return false;
|
|
35021
|
+
return import_fs_extra11.default.pathExists(path15.dirname(candidate.path));
|
|
35022
|
+
}
|
|
35023
|
+
async function linkContainer(candidate, destinationDir, result) {
|
|
35024
|
+
if (candidate.isDestination || samePath(candidate.path, destinationDir)) {
|
|
35025
|
+
return;
|
|
35026
|
+
}
|
|
35027
|
+
const destinationRealPath = await realPathIfPossible(destinationDir);
|
|
35028
|
+
const stat = await import_fs_extra11.default.lstat(candidate.path).catch(() => null);
|
|
35029
|
+
if (!stat) {
|
|
35030
|
+
if (!await shouldLinkMissingContainer(candidate))
|
|
35031
|
+
return;
|
|
35032
|
+
await createDirectorySymlink(destinationDir, candidate.path);
|
|
35033
|
+
result.linked.push({
|
|
35034
|
+
category: candidate.category,
|
|
35035
|
+
from: candidate.path,
|
|
35036
|
+
to: destinationDir
|
|
35037
|
+
});
|
|
35038
|
+
return;
|
|
35039
|
+
}
|
|
35040
|
+
if (stat.isSymbolicLink()) {
|
|
35041
|
+
const existingRealPath = await realPathIfPossible(candidate.path);
|
|
35042
|
+
if (destinationRealPath && existingRealPath && samePath(destinationRealPath, existingRealPath)) {
|
|
35043
|
+
result.alreadyLinked.push({
|
|
35044
|
+
category: candidate.category,
|
|
35045
|
+
from: candidate.path,
|
|
35046
|
+
to: destinationDir
|
|
35047
|
+
});
|
|
35048
|
+
return;
|
|
35049
|
+
}
|
|
35050
|
+
await import_fs_extra11.default.remove(candidate.path);
|
|
35051
|
+
await createDirectorySymlink(destinationDir, candidate.path);
|
|
35052
|
+
result.linked.push({
|
|
35053
|
+
category: candidate.category,
|
|
35054
|
+
from: candidate.path,
|
|
35055
|
+
to: destinationDir
|
|
35056
|
+
});
|
|
35057
|
+
return;
|
|
35058
|
+
}
|
|
35059
|
+
const backupRoot = await ensureBackupPath(result);
|
|
35060
|
+
const backupTarget = path15.join(backupRoot, safeRelativePath(result.rootDir, candidate.path));
|
|
35061
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(backupTarget));
|
|
35062
|
+
await import_fs_extra11.default.move(candidate.path, backupTarget, { overwrite: false });
|
|
35063
|
+
await createDirectorySymlink(destinationDir, candidate.path);
|
|
35064
|
+
result.linked.push({
|
|
35065
|
+
category: candidate.category,
|
|
35066
|
+
from: candidate.path,
|
|
35067
|
+
to: destinationDir,
|
|
35068
|
+
movedToBackup: backupTarget
|
|
35069
|
+
});
|
|
35070
|
+
}
|
|
35071
|
+
async function unifyAgentsConfiguration(options = {}) {
|
|
35072
|
+
const folders = resolveFolders(options);
|
|
35073
|
+
const candidates = getContainerCandidates(options);
|
|
35074
|
+
const result = {
|
|
35075
|
+
rootDir: folders.rootDir,
|
|
35076
|
+
agentsDir: folders.agentsDir,
|
|
35077
|
+
backupPath: null,
|
|
35078
|
+
imported: [],
|
|
35079
|
+
duplicates: [],
|
|
35080
|
+
renamed: [],
|
|
35081
|
+
linked: [],
|
|
35082
|
+
alreadyLinked: [],
|
|
35083
|
+
skipped: []
|
|
35084
|
+
};
|
|
35085
|
+
const destinationByCategory = {
|
|
35086
|
+
skills: path15.join(folders.agentsDir, "skills"),
|
|
35087
|
+
agents: path15.join(folders.agentsDir, "agents")
|
|
35088
|
+
};
|
|
35089
|
+
await import_fs_extra11.default.ensureDir(folders.agentsDir);
|
|
35090
|
+
for (const category of ["skills", "agents"]) {
|
|
35091
|
+
await importCategoryEntries(category, candidates, destinationByCategory[category], result);
|
|
35092
|
+
}
|
|
35093
|
+
for (const candidate of candidates) {
|
|
35094
|
+
await linkContainer(candidate, destinationByCategory[candidate.category], result);
|
|
35095
|
+
}
|
|
35096
|
+
return result;
|
|
35097
|
+
}
|
|
35098
|
+
|
|
35099
|
+
// src/commands/agents-unify.ts
|
|
35100
|
+
function countByCategory(result, key, category) {
|
|
35101
|
+
return result[key].filter((entry) => entry.category === category).length;
|
|
35102
|
+
}
|
|
35103
|
+
function printCategorySummary(result, category) {
|
|
35104
|
+
const imported = countByCategory(result, "imported", category);
|
|
35105
|
+
const duplicates = countByCategory(result, "duplicates", category);
|
|
35106
|
+
const renamed = countByCategory(result, "renamed", category);
|
|
35107
|
+
const linked = countByCategory(result, "linked", category);
|
|
35108
|
+
const alreadyLinked = countByCategory(result, "alreadyLinked", category);
|
|
35109
|
+
console.log(source_default.gray(` ${category}: ${imported} imported, ${duplicates} duplicates skipped, ${renamed} renamed, ${linked} linked, ${alreadyLinked} already linked`));
|
|
35110
|
+
}
|
|
35111
|
+
async function agentsUnifyCommand(params = {}) {
|
|
35112
|
+
try {
|
|
35113
|
+
console.log(source_default.blue.bold(`
|
|
35114
|
+
AIBlueprint agents unify ${source_default.gray(`v${getVersion()}`)}
|
|
35115
|
+
`));
|
|
35116
|
+
console.log(source_default.gray("Centralizing reusable skills and agents into .agents"));
|
|
35117
|
+
const result = await unifyAgentsConfiguration(params);
|
|
35118
|
+
console.log(source_default.green(`
|
|
35119
|
+
Unify complete`));
|
|
35120
|
+
console.log(source_default.gray(` Shared folder: ${result.agentsDir}`));
|
|
35121
|
+
printCategorySummary(result, "skills");
|
|
35122
|
+
printCategorySummary(result, "agents");
|
|
35123
|
+
if (result.backupPath) {
|
|
35124
|
+
console.log(source_default.gray(` Source backups: ${result.backupPath}`));
|
|
35125
|
+
}
|
|
35126
|
+
if (result.skipped.length > 0) {
|
|
35127
|
+
console.log(source_default.yellow(`
|
|
35128
|
+
Skipped paths:`));
|
|
35129
|
+
for (const skipped of result.skipped) {
|
|
35130
|
+
console.log(source_default.yellow(` ${skipped.path}: ${skipped.reason}`));
|
|
35131
|
+
}
|
|
35132
|
+
}
|
|
35133
|
+
} catch (error) {
|
|
35134
|
+
console.error(source_default.red(`
|
|
35135
|
+
Agents unify failed:`), error);
|
|
35136
|
+
process.exit(1);
|
|
35137
|
+
}
|
|
35138
|
+
}
|
|
35139
|
+
|
|
34654
35140
|
// node_modules/@clack/core/dist/index.mjs
|
|
34655
35141
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
34656
35142
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
@@ -35367,12 +35853,12 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
35367
35853
|
};
|
|
35368
35854
|
|
|
35369
35855
|
// src/commands/pro.ts
|
|
35370
|
-
import
|
|
35856
|
+
import path18 from "path";
|
|
35371
35857
|
|
|
35372
35858
|
// src/lib/pro-installer.ts
|
|
35373
|
-
var
|
|
35374
|
-
import
|
|
35375
|
-
import
|
|
35859
|
+
var import_fs_extra12 = __toESM(require_lib4(), 1);
|
|
35860
|
+
import os14 from "os";
|
|
35861
|
+
import path16 from "path";
|
|
35376
35862
|
import { exec as exec3 } from "child_process";
|
|
35377
35863
|
import { promisify as promisify2 } from "util";
|
|
35378
35864
|
var execAsync2 = promisify2(exec3);
|
|
@@ -35380,9 +35866,9 @@ var PREMIUM_REPO = "Melvynx/aiblueprint-cli-premium";
|
|
|
35380
35866
|
var PREMIUM_BRANCH = "main";
|
|
35381
35867
|
var CONFIG_FOLDER_CANDIDATES2 = ["agents-config", "ai-coding", "claude-code-config", "ai-config"];
|
|
35382
35868
|
function routePath(relativePath) {
|
|
35383
|
-
const segments = relativePath.split(
|
|
35869
|
+
const segments = relativePath.split(path16.sep);
|
|
35384
35870
|
const first = segments[0];
|
|
35385
|
-
const rest = segments.slice(1).join(
|
|
35871
|
+
const rest = segments.slice(1).join(path16.sep);
|
|
35386
35872
|
if (first === "claude-config") {
|
|
35387
35873
|
return { kind: "claude", relativePath: rest };
|
|
35388
35874
|
}
|
|
@@ -35398,7 +35884,7 @@ function routePath(relativePath) {
|
|
|
35398
35884
|
return { kind: "claude", relativePath };
|
|
35399
35885
|
}
|
|
35400
35886
|
function getCacheRepoDir() {
|
|
35401
|
-
return
|
|
35887
|
+
return path16.join(os14.homedir(), ".config", "aiblueprint", "pro-repos", "aiblueprint-cli-premium");
|
|
35402
35888
|
}
|
|
35403
35889
|
async function execGitWithAuth(command, token, repoUrl, cwd) {
|
|
35404
35890
|
const authenticatedUrl = `https://x-access-token:${token}@${repoUrl.replace(/^https?:\/\//, "")}`;
|
|
@@ -35412,21 +35898,21 @@ async function execGitWithAuth(command, token, repoUrl, cwd) {
|
|
|
35412
35898
|
async function cloneOrUpdateRepo(token) {
|
|
35413
35899
|
const cacheDir = getCacheRepoDir();
|
|
35414
35900
|
const repoUrl = `https://github.com/${PREMIUM_REPO}.git`;
|
|
35415
|
-
if (await
|
|
35901
|
+
if (await import_fs_extra12.default.pathExists(path16.join(cacheDir, ".git"))) {
|
|
35416
35902
|
try {
|
|
35417
35903
|
await execGitWithAuth("pull", token, repoUrl, cacheDir);
|
|
35418
35904
|
} catch (error) {
|
|
35419
|
-
await
|
|
35420
|
-
await
|
|
35905
|
+
await import_fs_extra12.default.remove(cacheDir);
|
|
35906
|
+
await import_fs_extra12.default.ensureDir(path16.dirname(cacheDir));
|
|
35421
35907
|
await execGitWithAuth(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
35422
35908
|
}
|
|
35423
35909
|
} else {
|
|
35424
|
-
await
|
|
35910
|
+
await import_fs_extra12.default.ensureDir(path16.dirname(cacheDir));
|
|
35425
35911
|
await execGitWithAuth(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
35426
35912
|
}
|
|
35427
35913
|
for (const candidate of CONFIG_FOLDER_CANDIDATES2) {
|
|
35428
|
-
const candidatePath =
|
|
35429
|
-
if (await
|
|
35914
|
+
const candidatePath = path16.join(cacheDir, candidate);
|
|
35915
|
+
if (await import_fs_extra12.default.pathExists(candidatePath)) {
|
|
35430
35916
|
return candidatePath;
|
|
35431
35917
|
}
|
|
35432
35918
|
}
|
|
@@ -35434,38 +35920,38 @@ async function cloneOrUpdateRepo(token) {
|
|
|
35434
35920
|
}
|
|
35435
35921
|
async function copyConfigFromCache(cacheConfigDir, dest, onProgress) {
|
|
35436
35922
|
const walk = async (dir, baseDir = dir) => {
|
|
35437
|
-
const entries = await
|
|
35923
|
+
const entries = await import_fs_extra12.default.readdir(dir, { withFileTypes: true });
|
|
35438
35924
|
for (const entry of entries) {
|
|
35439
35925
|
if (entry.name === ".DS_Store" || entry.name === "node_modules")
|
|
35440
35926
|
continue;
|
|
35441
|
-
const sourcePath =
|
|
35442
|
-
const relativePath =
|
|
35927
|
+
const sourcePath = path16.join(dir, entry.name);
|
|
35928
|
+
const relativePath = path16.relative(baseDir, sourcePath);
|
|
35443
35929
|
const route = routePath(relativePath);
|
|
35444
35930
|
if (route.kind === "skip")
|
|
35445
35931
|
continue;
|
|
35446
35932
|
if (route.kind === "agents-category") {
|
|
35447
|
-
if (relativePath.split(
|
|
35933
|
+
if (relativePath.split(path16.sep).length === 1) {
|
|
35448
35934
|
await copyAgentCategory(sourcePath, route.category, dest.agentsDir, dest.claudeDir, onProgress);
|
|
35449
35935
|
}
|
|
35450
35936
|
continue;
|
|
35451
35937
|
}
|
|
35452
35938
|
const targetBase = route.kind === "claude" ? dest.claudeDir : dest.codexDir;
|
|
35453
|
-
const targetPath =
|
|
35939
|
+
const targetPath = path16.join(targetBase, route.relativePath);
|
|
35454
35940
|
if (entry.isDirectory()) {
|
|
35455
|
-
await
|
|
35941
|
+
await import_fs_extra12.default.ensureDir(targetPath);
|
|
35456
35942
|
onProgress?.(relativePath, "directory");
|
|
35457
35943
|
await walk(sourcePath, baseDir);
|
|
35458
35944
|
} else if (route.kind === "codex" && route.relativePath === "config.toml") {
|
|
35459
35945
|
await mergeCodexConfigFile(sourcePath, dest.codexDir);
|
|
35460
35946
|
onProgress?.(relativePath, "file");
|
|
35461
35947
|
} else if (isTextFile(entry.name)) {
|
|
35462
|
-
const content = await
|
|
35948
|
+
const content = await import_fs_extra12.default.readFile(sourcePath, "utf-8");
|
|
35463
35949
|
const replaced = replaceClaudePathPlaceholder(content, dest.claudeDir);
|
|
35464
|
-
await
|
|
35465
|
-
await
|
|
35950
|
+
await import_fs_extra12.default.ensureDir(path16.dirname(targetPath));
|
|
35951
|
+
await import_fs_extra12.default.writeFile(targetPath, replaced, "utf-8");
|
|
35466
35952
|
onProgress?.(relativePath, "file");
|
|
35467
35953
|
} else {
|
|
35468
|
-
await
|
|
35954
|
+
await import_fs_extra12.default.copy(sourcePath, targetPath, { overwrite: true });
|
|
35469
35955
|
onProgress?.(relativePath, "file");
|
|
35470
35956
|
}
|
|
35471
35957
|
}
|
|
@@ -35473,21 +35959,21 @@ async function copyConfigFromCache(cacheConfigDir, dest, onProgress) {
|
|
|
35473
35959
|
await walk(cacheConfigDir);
|
|
35474
35960
|
}
|
|
35475
35961
|
async function copyAgentCategory(sourceCategoryDir, category, agentsDir, claudeDir, onProgress) {
|
|
35476
|
-
const agentsCategoryDir =
|
|
35477
|
-
await
|
|
35478
|
-
const entries = await
|
|
35962
|
+
const agentsCategoryDir = path16.join(agentsDir, category);
|
|
35963
|
+
await import_fs_extra12.default.ensureDir(agentsCategoryDir);
|
|
35964
|
+
const entries = await import_fs_extra12.default.readdir(sourceCategoryDir, { withFileTypes: true });
|
|
35479
35965
|
for (const entry of entries) {
|
|
35480
35966
|
if (entry.name === ".DS_Store")
|
|
35481
35967
|
continue;
|
|
35482
|
-
const src =
|
|
35483
|
-
const dst =
|
|
35484
|
-
const claudeTop =
|
|
35485
|
-
const claudeStat = await
|
|
35968
|
+
const src = path16.join(sourceCategoryDir, entry.name);
|
|
35969
|
+
const dst = path16.join(agentsCategoryDir, entry.name);
|
|
35970
|
+
const claudeTop = path16.join(claudeDir, category, entry.name);
|
|
35971
|
+
const claudeStat = await import_fs_extra12.default.lstat(claudeTop).catch(() => null);
|
|
35486
35972
|
if (claudeStat && !claudeStat.isSymbolicLink()) {
|
|
35487
35973
|
onProgress?.(`${category}/${entry.name} (skipped - real dir in claude)`, "file");
|
|
35488
35974
|
continue;
|
|
35489
35975
|
}
|
|
35490
|
-
await
|
|
35976
|
+
await import_fs_extra12.default.copy(src, dst, { overwrite: true });
|
|
35491
35977
|
await applyPathPlaceholders(dst, claudeDir);
|
|
35492
35978
|
onProgress?.(`${category}/${entry.name}`, entry.isDirectory() ? "directory" : "file");
|
|
35493
35979
|
}
|
|
@@ -35506,8 +35992,8 @@ async function downloadFromPrivateGitHub(repo, branch, relativePath, targetPath,
|
|
|
35506
35992
|
return false;
|
|
35507
35993
|
}
|
|
35508
35994
|
const content = await response.arrayBuffer();
|
|
35509
|
-
await
|
|
35510
|
-
await
|
|
35995
|
+
await import_fs_extra12.default.ensureDir(path16.dirname(targetPath));
|
|
35996
|
+
await import_fs_extra12.default.writeFile(targetPath, Buffer.from(content));
|
|
35511
35997
|
return true;
|
|
35512
35998
|
} catch (error) {
|
|
35513
35999
|
console.error(`Error downloading ${relativePath}:`, error);
|
|
@@ -35532,10 +36018,10 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
|
|
|
35532
36018
|
console.error(`Unexpected response for directory ${dirPath}`);
|
|
35533
36019
|
return false;
|
|
35534
36020
|
}
|
|
35535
|
-
await
|
|
36021
|
+
await import_fs_extra12.default.ensureDir(targetDir);
|
|
35536
36022
|
for (const file of files) {
|
|
35537
36023
|
const relativePath = dirPath ? `${dirPath}/${file.name}` : file.name;
|
|
35538
|
-
const targetPath =
|
|
36024
|
+
const targetPath = path16.join(targetDir, file.name);
|
|
35539
36025
|
const displayPath = relativePath.replace(/^(agents-config|ai-coding|claude-code-config|ai-config)\//, "");
|
|
35540
36026
|
if (file.type === "file") {
|
|
35541
36027
|
onProgress?.(displayPath, "file");
|
|
@@ -35558,8 +36044,8 @@ async function installProConfigs(options) {
|
|
|
35558
36044
|
codexFolder,
|
|
35559
36045
|
agentsFolder
|
|
35560
36046
|
});
|
|
35561
|
-
await
|
|
35562
|
-
await
|
|
36047
|
+
await import_fs_extra12.default.ensureDir(claudeDir);
|
|
36048
|
+
await import_fs_extra12.default.ensureDir(agentsDir);
|
|
35563
36049
|
const dest = { claudeDir, codexDir, agentsDir };
|
|
35564
36050
|
try {
|
|
35565
36051
|
const cacheConfigDir = await cloneOrUpdateRepo(githubToken);
|
|
@@ -35569,7 +36055,7 @@ async function installProConfigs(options) {
|
|
|
35569
36055
|
} catch (error) {
|
|
35570
36056
|
console.warn("Git caching failed, falling back to API download");
|
|
35571
36057
|
}
|
|
35572
|
-
const tempDir =
|
|
36058
|
+
const tempDir = path16.join(os14.tmpdir(), `aiblueprint-premium-${Date.now()}`);
|
|
35573
36059
|
try {
|
|
35574
36060
|
let success = false;
|
|
35575
36061
|
for (const candidate of CONFIG_FOLDER_CANDIDATES2) {
|
|
@@ -35583,8 +36069,8 @@ async function installProConfigs(options) {
|
|
|
35583
36069
|
await copyConfigFromCache(tempDir, dest, onProgress);
|
|
35584
36070
|
await replacePathPlaceholdersInDir(claudeDir, claudeDir);
|
|
35585
36071
|
for (const category of AGENT_CATEGORIES) {
|
|
35586
|
-
const agentsCategoryDir =
|
|
35587
|
-
if (await
|
|
36072
|
+
const agentsCategoryDir = path16.join(agentsDir, category);
|
|
36073
|
+
if (await import_fs_extra12.default.pathExists(agentsCategoryDir)) {
|
|
35588
36074
|
await replacePathPlaceholdersInDir(agentsCategoryDir, claudeDir);
|
|
35589
36075
|
}
|
|
35590
36076
|
}
|
|
@@ -35593,7 +36079,7 @@ async function installProConfigs(options) {
|
|
|
35593
36079
|
throw new Error(`Failed to install premium configs: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
35594
36080
|
} finally {
|
|
35595
36081
|
try {
|
|
35596
|
-
await
|
|
36082
|
+
await import_fs_extra12.default.remove(tempDir);
|
|
35597
36083
|
} catch {}
|
|
35598
36084
|
}
|
|
35599
36085
|
}
|
|
@@ -35604,27 +36090,27 @@ async function syncAllAgentSymlinks(agentsDir, claudeDir) {
|
|
|
35604
36090
|
}
|
|
35605
36091
|
|
|
35606
36092
|
// src/lib/token-storage.ts
|
|
35607
|
-
var
|
|
35608
|
-
import
|
|
35609
|
-
import
|
|
36093
|
+
var import_fs_extra13 = __toESM(require_lib4(), 1);
|
|
36094
|
+
import os15 from "os";
|
|
36095
|
+
import path17 from "path";
|
|
35610
36096
|
function getConfigDir() {
|
|
35611
|
-
const platform =
|
|
36097
|
+
const platform = os15.platform();
|
|
35612
36098
|
if (platform === "win32") {
|
|
35613
|
-
const appData = process.env.APPDATA ||
|
|
35614
|
-
return
|
|
36099
|
+
const appData = process.env.APPDATA || path17.join(os15.homedir(), "AppData", "Roaming");
|
|
36100
|
+
return path17.join(appData, "aiblueprint");
|
|
35615
36101
|
} else {
|
|
35616
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
35617
|
-
return
|
|
36102
|
+
const configHome = process.env.XDG_CONFIG_HOME || path17.join(os15.homedir(), ".config");
|
|
36103
|
+
return path17.join(configHome, "aiblueprint");
|
|
35618
36104
|
}
|
|
35619
36105
|
}
|
|
35620
36106
|
function getTokenFilePath2() {
|
|
35621
|
-
return
|
|
36107
|
+
return path17.join(getConfigDir(), "token.txt");
|
|
35622
36108
|
}
|
|
35623
36109
|
async function saveToken(githubToken) {
|
|
35624
36110
|
const tokenFile = getTokenFilePath2();
|
|
35625
|
-
const configDir =
|
|
36111
|
+
const configDir = path17.dirname(tokenFile);
|
|
35626
36112
|
try {
|
|
35627
|
-
await
|
|
36113
|
+
await import_fs_extra13.default.ensureDir(configDir);
|
|
35628
36114
|
} catch (error) {
|
|
35629
36115
|
if (error.code === "EACCES") {
|
|
35630
36116
|
throw new Error(`Permission denied creating config directory: ${configDir}
|
|
@@ -35632,15 +36118,15 @@ async function saveToken(githubToken) {
|
|
|
35632
36118
|
}
|
|
35633
36119
|
throw error;
|
|
35634
36120
|
}
|
|
35635
|
-
await
|
|
36121
|
+
await import_fs_extra13.default.writeFile(tokenFile, githubToken, { mode: 384 });
|
|
35636
36122
|
}
|
|
35637
36123
|
async function getToken() {
|
|
35638
36124
|
const tokenFile = getTokenFilePath2();
|
|
35639
|
-
if (!await
|
|
36125
|
+
if (!await import_fs_extra13.default.pathExists(tokenFile)) {
|
|
35640
36126
|
return null;
|
|
35641
36127
|
}
|
|
35642
36128
|
try {
|
|
35643
|
-
const token = await
|
|
36129
|
+
const token = await import_fs_extra13.default.readFile(tokenFile, "utf-8");
|
|
35644
36130
|
return token.trim();
|
|
35645
36131
|
} catch (error) {
|
|
35646
36132
|
return null;
|
|
@@ -35649,12 +36135,12 @@ async function getToken() {
|
|
|
35649
36135
|
function getTokenInfo() {
|
|
35650
36136
|
return {
|
|
35651
36137
|
path: getTokenFilePath2(),
|
|
35652
|
-
platform:
|
|
36138
|
+
platform: os15.platform()
|
|
35653
36139
|
};
|
|
35654
36140
|
}
|
|
35655
36141
|
|
|
35656
36142
|
// src/commands/pro.ts
|
|
35657
|
-
var
|
|
36143
|
+
var import_fs_extra14 = __toESM(require_lib4(), 1);
|
|
35658
36144
|
var API_URL = "https://codeline.app/api/products";
|
|
35659
36145
|
var PRODUCT_IDS = ["prd_XJVgxVPbGG", "prd_NKabAkdOkw"];
|
|
35660
36146
|
async function countInstalledItems(claudeDir) {
|
|
@@ -35663,20 +36149,20 @@ async function countInstalledItems(claudeDir) {
|
|
|
35663
36149
|
skills: 0
|
|
35664
36150
|
};
|
|
35665
36151
|
try {
|
|
35666
|
-
const agentsDir =
|
|
35667
|
-
if (await
|
|
35668
|
-
const files = await
|
|
36152
|
+
const agentsDir = path18.join(claudeDir, "agents");
|
|
36153
|
+
if (await import_fs_extra14.default.pathExists(agentsDir)) {
|
|
36154
|
+
const files = await import_fs_extra14.default.readdir(agentsDir);
|
|
35669
36155
|
counts.agents = files.filter((f) => f.endsWith(".md")).length;
|
|
35670
36156
|
}
|
|
35671
36157
|
} catch (error) {
|
|
35672
36158
|
console.error("Failed to count agents:", error instanceof Error ? error.message : error);
|
|
35673
36159
|
}
|
|
35674
36160
|
try {
|
|
35675
|
-
const skillsDir =
|
|
35676
|
-
if (await
|
|
35677
|
-
const items = await
|
|
36161
|
+
const skillsDir = path18.join(claudeDir, "skills");
|
|
36162
|
+
if (await import_fs_extra14.default.pathExists(skillsDir)) {
|
|
36163
|
+
const items = await import_fs_extra14.default.readdir(skillsDir);
|
|
35678
36164
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
35679
|
-
const stat = await
|
|
36165
|
+
const stat = await import_fs_extra14.default.stat(path18.join(skillsDir, item));
|
|
35680
36166
|
return stat.isDirectory();
|
|
35681
36167
|
}));
|
|
35682
36168
|
counts.skills = dirs.filter(Boolean).length;
|
|
@@ -35884,9 +36370,9 @@ async function proUpdateCommand(options = {}) {
|
|
|
35884
36370
|
}
|
|
35885
36371
|
|
|
35886
36372
|
// src/lib/sync-utils.ts
|
|
35887
|
-
var
|
|
35888
|
-
import
|
|
35889
|
-
import
|
|
36373
|
+
var import_fs_extra15 = __toESM(require_lib4(), 1);
|
|
36374
|
+
import path19 from "path";
|
|
36375
|
+
import crypto2 from "crypto";
|
|
35890
36376
|
var PREMIUM_REPO2 = "Melvynx/aiblueprint-cli-premium";
|
|
35891
36377
|
var PREMIUM_BRANCH2 = "main";
|
|
35892
36378
|
var CONFIG_FOLDER_CANDIDATES3 = ["agents-config", "ai-coding", "claude-code-config", "ai-config"];
|
|
@@ -35894,7 +36380,7 @@ function computeFileSha(content) {
|
|
|
35894
36380
|
const size = content.length;
|
|
35895
36381
|
const header = `blob ${size}\x00`;
|
|
35896
36382
|
const fullContent = Buffer.concat([Buffer.from(header), content]);
|
|
35897
|
-
return
|
|
36383
|
+
return crypto2.createHash("sha1").update(fullContent).digest("hex");
|
|
35898
36384
|
}
|
|
35899
36385
|
var resolvedConfigFolder = null;
|
|
35900
36386
|
async function resolveRemoteConfigFolder(githubToken) {
|
|
@@ -35956,7 +36442,7 @@ async function listRemoteFilesRecursive(dirPath, githubToken, basePath = "") {
|
|
|
35956
36442
|
}
|
|
35957
36443
|
async function computeLocalFileSha(filePath) {
|
|
35958
36444
|
try {
|
|
35959
|
-
const content = await
|
|
36445
|
+
const content = await import_fs_extra15.default.readFile(filePath);
|
|
35960
36446
|
return computeFileSha(content);
|
|
35961
36447
|
} catch {
|
|
35962
36448
|
return null;
|
|
@@ -35964,15 +36450,15 @@ async function computeLocalFileSha(filePath) {
|
|
|
35964
36450
|
}
|
|
35965
36451
|
async function listLocalFiles(dir) {
|
|
35966
36452
|
const files = [];
|
|
35967
|
-
if (!await
|
|
36453
|
+
if (!await import_fs_extra15.default.pathExists(dir)) {
|
|
35968
36454
|
return files;
|
|
35969
36455
|
}
|
|
35970
|
-
const items = await
|
|
36456
|
+
const items = await import_fs_extra15.default.readdir(dir);
|
|
35971
36457
|
for (const item of items) {
|
|
35972
36458
|
if (item === "node_modules" || item === ".DS_Store")
|
|
35973
36459
|
continue;
|
|
35974
|
-
const fullPath =
|
|
35975
|
-
const stat = await
|
|
36460
|
+
const fullPath = path19.join(dir, item);
|
|
36461
|
+
const stat = await import_fs_extra15.default.stat(fullPath).catch(() => null);
|
|
35976
36462
|
if (!stat)
|
|
35977
36463
|
continue;
|
|
35978
36464
|
if (stat.isDirectory()) {
|
|
@@ -35987,13 +36473,13 @@ async function listLocalFiles(dir) {
|
|
|
35987
36473
|
}
|
|
35988
36474
|
async function listLocalFilesRecursive(dir, basePath) {
|
|
35989
36475
|
const files = [];
|
|
35990
|
-
const items = await
|
|
36476
|
+
const items = await import_fs_extra15.default.readdir(dir).catch(() => []);
|
|
35991
36477
|
for (const item of items) {
|
|
35992
36478
|
if (item === "node_modules" || item === ".DS_Store")
|
|
35993
36479
|
continue;
|
|
35994
|
-
const fullPath =
|
|
36480
|
+
const fullPath = path19.join(dir, item);
|
|
35995
36481
|
const relativePath = `${basePath}/${item}`;
|
|
35996
|
-
const stat = await
|
|
36482
|
+
const stat = await import_fs_extra15.default.stat(fullPath).catch(() => null);
|
|
35997
36483
|
if (!stat)
|
|
35998
36484
|
continue;
|
|
35999
36485
|
if (stat.isDirectory()) {
|
|
@@ -36007,14 +36493,14 @@ async function listLocalFilesRecursive(dir, basePath) {
|
|
|
36007
36493
|
return files;
|
|
36008
36494
|
}
|
|
36009
36495
|
async function listClaudeRealTopLevel(claudeCategoryDir) {
|
|
36010
|
-
if (!await
|
|
36496
|
+
if (!await import_fs_extra15.default.pathExists(claudeCategoryDir))
|
|
36011
36497
|
return [];
|
|
36012
|
-
const entries = await
|
|
36498
|
+
const entries = await import_fs_extra15.default.readdir(claudeCategoryDir).catch(() => []);
|
|
36013
36499
|
const real = [];
|
|
36014
36500
|
for (const name of entries) {
|
|
36015
36501
|
if (name === "node_modules" || name === ".DS_Store")
|
|
36016
36502
|
continue;
|
|
36017
|
-
const stat = await
|
|
36503
|
+
const stat = await import_fs_extra15.default.lstat(path19.join(claudeCategoryDir, name)).catch(() => null);
|
|
36018
36504
|
if (!stat)
|
|
36019
36505
|
continue;
|
|
36020
36506
|
if (stat.isDirectory())
|
|
@@ -36031,7 +36517,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
36031
36517
|
const items = [];
|
|
36032
36518
|
const useAgents = isAgentCategory(category);
|
|
36033
36519
|
const localBase = useAgents ? agentsDir : claudeDir;
|
|
36034
|
-
const localDir =
|
|
36520
|
+
const localDir = path19.join(localBase, category);
|
|
36035
36521
|
const remoteCategoryPath = getRemoteCategoryPath(category);
|
|
36036
36522
|
const remoteFiles = await listRemoteFilesRecursive(remoteCategoryPath, githubToken);
|
|
36037
36523
|
const localFiles = await listLocalFiles(localDir);
|
|
@@ -36045,7 +36531,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
36045
36531
|
}
|
|
36046
36532
|
const localSet = new Set(localFiles);
|
|
36047
36533
|
for (const [remotePath, { sha, isFolder }] of remoteSet) {
|
|
36048
|
-
const localPath =
|
|
36534
|
+
const localPath = path19.join(localDir, remotePath);
|
|
36049
36535
|
if (isFolder) {
|
|
36050
36536
|
continue;
|
|
36051
36537
|
}
|
|
@@ -36080,7 +36566,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
36080
36566
|
for (const localPath of localSet) {
|
|
36081
36567
|
agentsTopLevels.add(localPath.split("/")[0]);
|
|
36082
36568
|
}
|
|
36083
|
-
const claudeCategoryDir =
|
|
36569
|
+
const claudeCategoryDir = path19.join(claudeDir, category);
|
|
36084
36570
|
const claudeRealEntries = await listClaudeRealTopLevel(claudeCategoryDir);
|
|
36085
36571
|
for (const top of claudeRealEntries) {
|
|
36086
36572
|
if (!remoteTopLevels.has(top))
|
|
@@ -36139,13 +36625,13 @@ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken,
|
|
|
36139
36625
|
return false;
|
|
36140
36626
|
}
|
|
36141
36627
|
const content = await response.arrayBuffer();
|
|
36142
|
-
await
|
|
36628
|
+
await import_fs_extra15.default.ensureDir(path19.dirname(targetPath));
|
|
36143
36629
|
if (isTextFile(relativePath)) {
|
|
36144
36630
|
const textContent = Buffer.from(content).toString("utf-8");
|
|
36145
36631
|
const transformedContent = transformFileContent(textContent, claudeDir);
|
|
36146
|
-
await
|
|
36632
|
+
await import_fs_extra15.default.writeFile(targetPath, transformedContent, "utf-8");
|
|
36147
36633
|
} else {
|
|
36148
|
-
await
|
|
36634
|
+
await import_fs_extra15.default.writeFile(targetPath, Buffer.from(content));
|
|
36149
36635
|
}
|
|
36150
36636
|
return true;
|
|
36151
36637
|
} catch {
|
|
@@ -36161,27 +36647,27 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
36161
36647
|
for (const item of items) {
|
|
36162
36648
|
const useAgents = isAgentCategory(item.category);
|
|
36163
36649
|
const baseDir = useAgents ? agentsDir : claudeDir;
|
|
36164
|
-
const targetPath =
|
|
36650
|
+
const targetPath = path19.join(baseDir, item.relativePath);
|
|
36165
36651
|
if (item.status === "migration" && useAgents) {
|
|
36166
36652
|
const topName = item.name.split("/")[0];
|
|
36167
|
-
const agentsTop =
|
|
36168
|
-
const claudeTop =
|
|
36653
|
+
const agentsTop = path19.join(agentsDir, item.category, topName);
|
|
36654
|
+
const claudeTop = path19.join(claudeDir, item.category, topName);
|
|
36169
36655
|
try {
|
|
36170
|
-
const claudeStat = await
|
|
36656
|
+
const claudeStat = await import_fs_extra15.default.lstat(claudeTop).catch(() => null);
|
|
36171
36657
|
if (!claudeStat || claudeStat.isSymbolicLink()) {
|
|
36172
36658
|
onProgress?.(item.relativePath, "skipping (no real dir to migrate)");
|
|
36173
36659
|
failed++;
|
|
36174
36660
|
continue;
|
|
36175
36661
|
}
|
|
36176
|
-
const agentsExists = await
|
|
36662
|
+
const agentsExists = await import_fs_extra15.default.pathExists(agentsTop);
|
|
36177
36663
|
if (agentsExists) {
|
|
36178
36664
|
onProgress?.(item.relativePath, "skipping (already in .agents)");
|
|
36179
36665
|
failed++;
|
|
36180
36666
|
continue;
|
|
36181
36667
|
}
|
|
36182
36668
|
onProgress?.(item.relativePath, "moving to .agents");
|
|
36183
|
-
await
|
|
36184
|
-
await
|
|
36669
|
+
await import_fs_extra15.default.ensureDir(path19.dirname(agentsTop));
|
|
36670
|
+
await import_fs_extra15.default.move(claudeTop, agentsTop);
|
|
36185
36671
|
migrated++;
|
|
36186
36672
|
touchedAgentCategories.add(item.category);
|
|
36187
36673
|
} catch {
|
|
@@ -36191,8 +36677,8 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
36191
36677
|
}
|
|
36192
36678
|
if (useAgents) {
|
|
36193
36679
|
const topName = item.name.split("/")[0];
|
|
36194
|
-
const claudeTop =
|
|
36195
|
-
const claudeTopStat = await
|
|
36680
|
+
const claudeTop = path19.join(claudeDir, item.category, topName);
|
|
36681
|
+
const claudeTopStat = await import_fs_extra15.default.lstat(claudeTop).catch(() => null);
|
|
36196
36682
|
if (claudeTopStat && !claudeTopStat.isSymbolicLink()) {
|
|
36197
36683
|
onProgress?.(item.relativePath, "skipping (real dir in .claude)");
|
|
36198
36684
|
failed++;
|
|
@@ -36202,7 +36688,7 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
36202
36688
|
if (item.status === "deleted") {
|
|
36203
36689
|
onProgress?.(item.relativePath, "deleting");
|
|
36204
36690
|
try {
|
|
36205
|
-
await
|
|
36691
|
+
await import_fs_extra15.default.remove(targetPath);
|
|
36206
36692
|
deleted++;
|
|
36207
36693
|
if (useAgents)
|
|
36208
36694
|
touchedAgentCategories.add(item.category);
|
|
@@ -36540,20 +37026,20 @@ async function proSyncCommand(options = {}) {
|
|
|
36540
37026
|
}
|
|
36541
37027
|
|
|
36542
37028
|
// src/lib/backup-utils.ts
|
|
36543
|
-
var
|
|
36544
|
-
import
|
|
36545
|
-
import
|
|
36546
|
-
var BACKUP_BASE_DIR =
|
|
37029
|
+
var import_fs_extra16 = __toESM(require_lib4(), 1);
|
|
37030
|
+
import path20 from "path";
|
|
37031
|
+
import os16 from "os";
|
|
37032
|
+
var BACKUP_BASE_DIR = path20.join(os16.homedir(), ".config", "aiblueprint", "backup");
|
|
36547
37033
|
function formatDate(date) {
|
|
36548
37034
|
const pad = (n) => n.toString().padStart(2, "0");
|
|
36549
37035
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
|
|
36550
37036
|
}
|
|
36551
37037
|
async function listBackups() {
|
|
36552
|
-
const exists = await
|
|
37038
|
+
const exists = await import_fs_extra16.default.pathExists(BACKUP_BASE_DIR);
|
|
36553
37039
|
if (!exists) {
|
|
36554
37040
|
return [];
|
|
36555
37041
|
}
|
|
36556
|
-
const entries = await
|
|
37042
|
+
const entries = await import_fs_extra16.default.readdir(BACKUP_BASE_DIR, { withFileTypes: true });
|
|
36557
37043
|
const backups = [];
|
|
36558
37044
|
for (const entry of entries) {
|
|
36559
37045
|
if (!entry.isDirectory())
|
|
@@ -36565,7 +37051,7 @@ async function listBackups() {
|
|
|
36565
37051
|
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
|
|
36566
37052
|
backups.push({
|
|
36567
37053
|
name: entry.name,
|
|
36568
|
-
path:
|
|
37054
|
+
path: path20.join(BACKUP_BASE_DIR, entry.name),
|
|
36569
37055
|
date
|
|
36570
37056
|
});
|
|
36571
37057
|
}
|
|
@@ -36574,12 +37060,12 @@ async function listBackups() {
|
|
|
36574
37060
|
var AGENTS_BACKUP_SUBDIR = ".agents";
|
|
36575
37061
|
var CLAUDE_ITEMS = ["commands", "agents", "skills", "scripts", "settings.json"];
|
|
36576
37062
|
async function copyForBackup(sourcePath, destPath) {
|
|
36577
|
-
await
|
|
37063
|
+
await import_fs_extra16.default.copy(sourcePath, destPath, {
|
|
36578
37064
|
overwrite: true,
|
|
36579
37065
|
dereference: false,
|
|
36580
37066
|
filter: async (src) => {
|
|
36581
37067
|
try {
|
|
36582
|
-
const stat = await
|
|
37068
|
+
const stat = await import_fs_extra16.default.lstat(src);
|
|
36583
37069
|
return !stat.isSymbolicLink();
|
|
36584
37070
|
} catch {
|
|
36585
37071
|
return true;
|
|
@@ -36588,28 +37074,28 @@ async function copyForBackup(sourcePath, destPath) {
|
|
|
36588
37074
|
});
|
|
36589
37075
|
}
|
|
36590
37076
|
async function hasMeaningfulContent(dir) {
|
|
36591
|
-
if (!await
|
|
37077
|
+
if (!await import_fs_extra16.default.pathExists(dir))
|
|
36592
37078
|
return false;
|
|
36593
|
-
const files = await
|
|
37079
|
+
const files = await import_fs_extra16.default.readdir(dir);
|
|
36594
37080
|
return files.some((f) => f !== ".DS_Store");
|
|
36595
37081
|
}
|
|
36596
37082
|
async function loadBackup(backupPath, claudeDir, agentsDir) {
|
|
36597
|
-
const exists = await
|
|
37083
|
+
const exists = await import_fs_extra16.default.pathExists(backupPath);
|
|
36598
37084
|
if (!exists) {
|
|
36599
37085
|
throw new Error(`Backup not found: ${backupPath}`);
|
|
36600
37086
|
}
|
|
36601
|
-
await
|
|
37087
|
+
await import_fs_extra16.default.ensureDir(claudeDir);
|
|
36602
37088
|
for (const item of CLAUDE_ITEMS) {
|
|
36603
|
-
const sourcePath =
|
|
36604
|
-
const destPath =
|
|
36605
|
-
if (await
|
|
37089
|
+
const sourcePath = path20.join(backupPath, item);
|
|
37090
|
+
const destPath = path20.join(claudeDir, item);
|
|
37091
|
+
if (await import_fs_extra16.default.pathExists(sourcePath)) {
|
|
36606
37092
|
await copyForBackup(sourcePath, destPath);
|
|
36607
37093
|
}
|
|
36608
37094
|
}
|
|
36609
37095
|
if (agentsDir) {
|
|
36610
|
-
const agentsBackupPath =
|
|
36611
|
-
if (await
|
|
36612
|
-
await
|
|
37096
|
+
const agentsBackupPath = path20.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
37097
|
+
if (await import_fs_extra16.default.pathExists(agentsBackupPath)) {
|
|
37098
|
+
await import_fs_extra16.default.ensureDir(agentsDir);
|
|
36613
37099
|
await copyForBackup(agentsBackupPath, agentsDir);
|
|
36614
37100
|
}
|
|
36615
37101
|
}
|
|
@@ -36620,20 +37106,20 @@ async function createBackup(claudeDir, agentsDir) {
|
|
|
36620
37106
|
if (!claudeHasContent && !agentsHasContent) {
|
|
36621
37107
|
return null;
|
|
36622
37108
|
}
|
|
36623
|
-
const
|
|
36624
|
-
const backupPath =
|
|
36625
|
-
await
|
|
37109
|
+
const timestamp3 = formatDate(new Date);
|
|
37110
|
+
const backupPath = path20.join(BACKUP_BASE_DIR, timestamp3);
|
|
37111
|
+
await import_fs_extra16.default.ensureDir(backupPath);
|
|
36626
37112
|
if (claudeHasContent) {
|
|
36627
37113
|
for (const item of CLAUDE_ITEMS) {
|
|
36628
|
-
const sourcePath =
|
|
36629
|
-
const destPath =
|
|
36630
|
-
if (await
|
|
37114
|
+
const sourcePath = path20.join(claudeDir, item);
|
|
37115
|
+
const destPath = path20.join(backupPath, item);
|
|
37116
|
+
if (await import_fs_extra16.default.pathExists(sourcePath)) {
|
|
36631
37117
|
await copyForBackup(sourcePath, destPath);
|
|
36632
37118
|
}
|
|
36633
37119
|
}
|
|
36634
37120
|
}
|
|
36635
37121
|
if (agentsHasContent && agentsDir) {
|
|
36636
|
-
const destPath =
|
|
37122
|
+
const destPath = path20.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
36637
37123
|
await copyForBackup(agentsDir, destPath);
|
|
36638
37124
|
}
|
|
36639
37125
|
return backupPath;
|
|
@@ -36740,6 +37226,7 @@ function printSnapshots(title, snapshots) {
|
|
|
36740
37226
|
}
|
|
36741
37227
|
async function configsSaveCommand(name, options = {}) {
|
|
36742
37228
|
try {
|
|
37229
|
+
console.log(source_default.gray("Saving .claude, .codex, and .agents config files..."));
|
|
36743
37230
|
const snapshotPath = await saveNamedConfig(name, options);
|
|
36744
37231
|
console.log(source_default.green(`Saved config "${name}"`));
|
|
36745
37232
|
console.log(source_default.gray(snapshotPath));
|
|
@@ -36750,6 +37237,7 @@ async function configsSaveCommand(name, options = {}) {
|
|
|
36750
37237
|
}
|
|
36751
37238
|
async function configsLoadCommand(name, options = {}) {
|
|
36752
37239
|
try {
|
|
37240
|
+
console.log(source_default.gray(`Loading config "${name}"...`));
|
|
36753
37241
|
const result = await loadNamedConfig(name, options);
|
|
36754
37242
|
console.log(source_default.green(`Loaded config "${name}"`));
|
|
36755
37243
|
if (result.backupPath) {
|
|
@@ -36763,6 +37251,7 @@ async function configsLoadCommand(name, options = {}) {
|
|
|
36763
37251
|
}
|
|
36764
37252
|
async function configsUndoCommand(options = {}) {
|
|
36765
37253
|
try {
|
|
37254
|
+
console.log(source_default.gray("Restoring the previous config backup..."));
|
|
36766
37255
|
const result = await undoLastLoad(options);
|
|
36767
37256
|
console.log(source_default.green(`Undid last config load using backup "${result.backupName}"`));
|
|
36768
37257
|
if (result.backupPath) {
|
|
@@ -36784,6 +37273,7 @@ async function configsBackupsListCommand(options = {}) {
|
|
|
36784
37273
|
}
|
|
36785
37274
|
async function configsBackupsLoadCommand(name, options = {}) {
|
|
36786
37275
|
try {
|
|
37276
|
+
console.log(source_default.gray(`Loading backup "${name}"...`));
|
|
36787
37277
|
const result = await loadBackupSnapshot(name, options);
|
|
36788
37278
|
console.log(source_default.green(`Loaded backup "${name}"`));
|
|
36789
37279
|
if (result.backupPath) {
|
|
@@ -36797,6 +37287,7 @@ async function configsBackupsLoadCommand(name, options = {}) {
|
|
|
36797
37287
|
}
|
|
36798
37288
|
async function configsBackupsCreateCommand(reason, options = {}) {
|
|
36799
37289
|
try {
|
|
37290
|
+
console.log(source_default.gray("Creating config backup..."));
|
|
36800
37291
|
const backupPath = await createConfigBackup(options, reason ?? "Manual backup from configs backups create", "manual-backup", "manual");
|
|
36801
37292
|
if (!backupPath) {
|
|
36802
37293
|
console.log(source_default.gray("No .claude, .codex, or .agents configuration found to backup."));
|
|
@@ -36811,19 +37302,19 @@ async function configsBackupsCreateCommand(reason, options = {}) {
|
|
|
36811
37302
|
}
|
|
36812
37303
|
|
|
36813
37304
|
// src/commands/openclaw-pro.ts
|
|
36814
|
-
import
|
|
36815
|
-
import
|
|
37305
|
+
import os19 from "os";
|
|
37306
|
+
import path23 from "path";
|
|
36816
37307
|
|
|
36817
37308
|
// src/lib/openclaw-installer.ts
|
|
36818
|
-
var
|
|
36819
|
-
import
|
|
36820
|
-
import
|
|
37309
|
+
var import_fs_extra17 = __toESM(require_lib4(), 1);
|
|
37310
|
+
import os17 from "os";
|
|
37311
|
+
import path21 from "path";
|
|
36821
37312
|
import { exec as exec4 } from "child_process";
|
|
36822
37313
|
import { promisify as promisify3 } from "util";
|
|
36823
37314
|
var execAsync3 = promisify3(exec4);
|
|
36824
37315
|
var OPENCLAW_PRO_REPO = "Melvynx/openclawpro";
|
|
36825
37316
|
function getCacheRepoDir2() {
|
|
36826
|
-
return
|
|
37317
|
+
return path21.join(os17.homedir(), ".config", "openclaw", "pro-repos", "openclawpro");
|
|
36827
37318
|
}
|
|
36828
37319
|
async function execGitWithAuth2(command, token, repoUrl, cwd) {
|
|
36829
37320
|
const authenticatedUrl = `https://x-access-token:${token}@${repoUrl.replace(/^https?:\/\//, "")}`;
|
|
@@ -36837,33 +37328,33 @@ async function execGitWithAuth2(command, token, repoUrl, cwd) {
|
|
|
36837
37328
|
async function cloneOrUpdateRepo2(token) {
|
|
36838
37329
|
const cacheDir = getCacheRepoDir2();
|
|
36839
37330
|
const repoUrl = `https://github.com/${OPENCLAW_PRO_REPO}.git`;
|
|
36840
|
-
if (await
|
|
37331
|
+
if (await import_fs_extra17.default.pathExists(path21.join(cacheDir, ".git"))) {
|
|
36841
37332
|
try {
|
|
36842
37333
|
await execGitWithAuth2("pull", token, repoUrl, cacheDir);
|
|
36843
37334
|
} catch (error) {
|
|
36844
|
-
await
|
|
36845
|
-
await
|
|
37335
|
+
await import_fs_extra17.default.remove(cacheDir);
|
|
37336
|
+
await import_fs_extra17.default.ensureDir(path21.dirname(cacheDir));
|
|
36846
37337
|
await execGitWithAuth2(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
36847
37338
|
}
|
|
36848
37339
|
} else {
|
|
36849
|
-
await
|
|
37340
|
+
await import_fs_extra17.default.ensureDir(path21.dirname(cacheDir));
|
|
36850
37341
|
await execGitWithAuth2(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
36851
37342
|
}
|
|
36852
|
-
return
|
|
37343
|
+
return path21.join(cacheDir, "openclaw-config");
|
|
36853
37344
|
}
|
|
36854
37345
|
async function copyConfigFromCache2(cacheConfigDir, targetDir, onProgress) {
|
|
36855
37346
|
const walk = async (dir, baseDir = dir) => {
|
|
36856
|
-
const entries = await
|
|
37347
|
+
const entries = await import_fs_extra17.default.readdir(dir, { withFileTypes: true });
|
|
36857
37348
|
for (const entry of entries) {
|
|
36858
|
-
const sourcePath =
|
|
36859
|
-
const relativePath =
|
|
36860
|
-
const targetPath =
|
|
37349
|
+
const sourcePath = path21.join(dir, entry.name);
|
|
37350
|
+
const relativePath = path21.relative(baseDir, sourcePath);
|
|
37351
|
+
const targetPath = path21.join(targetDir, relativePath);
|
|
36861
37352
|
if (entry.isDirectory()) {
|
|
36862
|
-
await
|
|
37353
|
+
await import_fs_extra17.default.ensureDir(targetPath);
|
|
36863
37354
|
onProgress?.(relativePath, "directory");
|
|
36864
37355
|
await walk(sourcePath, baseDir);
|
|
36865
37356
|
} else {
|
|
36866
|
-
await
|
|
37357
|
+
await import_fs_extra17.default.copy(sourcePath, targetPath, { overwrite: true });
|
|
36867
37358
|
onProgress?.(relativePath, "file");
|
|
36868
37359
|
}
|
|
36869
37360
|
}
|
|
@@ -36872,7 +37363,7 @@ async function copyConfigFromCache2(cacheConfigDir, targetDir, onProgress) {
|
|
|
36872
37363
|
}
|
|
36873
37364
|
async function installOpenclawProConfigs(options) {
|
|
36874
37365
|
const { githubToken, openclawFolder, onProgress } = options;
|
|
36875
|
-
const targetFolder = openclawFolder ||
|
|
37366
|
+
const targetFolder = openclawFolder || path21.join(os17.homedir(), ".openclaw");
|
|
36876
37367
|
try {
|
|
36877
37368
|
const cacheConfigDir = await cloneOrUpdateRepo2(githubToken);
|
|
36878
37369
|
await copyConfigFromCache2(cacheConfigDir, targetFolder, onProgress);
|
|
@@ -36883,28 +37374,28 @@ async function installOpenclawProConfigs(options) {
|
|
|
36883
37374
|
}
|
|
36884
37375
|
|
|
36885
37376
|
// src/lib/openclaw-token-storage.ts
|
|
36886
|
-
var
|
|
36887
|
-
import
|
|
36888
|
-
import
|
|
37377
|
+
var import_fs_extra18 = __toESM(require_lib4(), 1);
|
|
37378
|
+
import os18 from "os";
|
|
37379
|
+
import path22 from "path";
|
|
36889
37380
|
function getConfigDir2() {
|
|
36890
|
-
const platform =
|
|
37381
|
+
const platform = os18.platform();
|
|
36891
37382
|
if (platform === "win32") {
|
|
36892
|
-
return
|
|
37383
|
+
return path22.join(process.env.APPDATA || os18.homedir(), "openclaw");
|
|
36893
37384
|
}
|
|
36894
|
-
return
|
|
37385
|
+
return path22.join(os18.homedir(), ".config", "openclaw");
|
|
36895
37386
|
}
|
|
36896
37387
|
function getTokenPath() {
|
|
36897
|
-
return
|
|
37388
|
+
return path22.join(getConfigDir2(), "token.txt");
|
|
36898
37389
|
}
|
|
36899
37390
|
async function saveOpenclawToken(githubToken) {
|
|
36900
37391
|
const configDir = getConfigDir2();
|
|
36901
|
-
await
|
|
36902
|
-
await
|
|
37392
|
+
await import_fs_extra18.default.ensureDir(configDir);
|
|
37393
|
+
await import_fs_extra18.default.writeFile(getTokenPath(), githubToken, { mode: 384 });
|
|
36903
37394
|
}
|
|
36904
37395
|
async function getOpenclawToken() {
|
|
36905
37396
|
const tokenPath = getTokenPath();
|
|
36906
|
-
if (await
|
|
36907
|
-
const token = await
|
|
37397
|
+
if (await import_fs_extra18.default.pathExists(tokenPath)) {
|
|
37398
|
+
const token = await import_fs_extra18.default.readFile(tokenPath, "utf8");
|
|
36908
37399
|
return token.trim();
|
|
36909
37400
|
}
|
|
36910
37401
|
return null;
|
|
@@ -36912,12 +37403,12 @@ async function getOpenclawToken() {
|
|
|
36912
37403
|
function getOpenclawTokenInfo() {
|
|
36913
37404
|
return {
|
|
36914
37405
|
path: getTokenPath(),
|
|
36915
|
-
platform:
|
|
37406
|
+
platform: os18.platform()
|
|
36916
37407
|
};
|
|
36917
37408
|
}
|
|
36918
37409
|
|
|
36919
37410
|
// src/commands/openclaw-pro.ts
|
|
36920
|
-
var
|
|
37411
|
+
var import_fs_extra19 = __toESM(require_lib4(), 1);
|
|
36921
37412
|
var API_URL2 = "https://codeline.app/api/products";
|
|
36922
37413
|
var OPENCLAW_PRODUCT_ID = "prd_t2GRwX3aH1";
|
|
36923
37414
|
var CLAUDE_CODE_TOOLS_INSTRUCTIONS = `
|
|
@@ -37024,7 +37515,7 @@ async function openclawProSetupCommand(options = {}) {
|
|
|
37024
37515
|
Se(source_default.red("❌ Not activated"));
|
|
37025
37516
|
process.exit(1);
|
|
37026
37517
|
}
|
|
37027
|
-
const openclawDir = options.folder ?
|
|
37518
|
+
const openclawDir = options.folder ? path23.resolve(options.folder) : path23.join(os19.homedir(), ".openclaw");
|
|
37028
37519
|
const spinner = Y2();
|
|
37029
37520
|
const onProgress = (file, type) => {
|
|
37030
37521
|
spinner.message(`Installing: ${source_default.cyan(file)} ${source_default.gray(`(${type})`)}`);
|
|
@@ -37037,23 +37528,23 @@ async function openclawProSetupCommand(options = {}) {
|
|
|
37037
37528
|
});
|
|
37038
37529
|
spinner.stop("OpenClaw Pro configurations installed");
|
|
37039
37530
|
let skillCount = 0;
|
|
37040
|
-
const skillsDir =
|
|
37041
|
-
if (await
|
|
37042
|
-
const items = await
|
|
37531
|
+
const skillsDir = path23.join(openclawDir, "skills");
|
|
37532
|
+
if (await import_fs_extra19.default.pathExists(skillsDir)) {
|
|
37533
|
+
const items = await import_fs_extra19.default.readdir(skillsDir);
|
|
37043
37534
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
37044
|
-
const stat = await
|
|
37535
|
+
const stat = await import_fs_extra19.default.stat(path23.join(skillsDir, item));
|
|
37045
37536
|
return stat.isDirectory();
|
|
37046
37537
|
}));
|
|
37047
37538
|
skillCount = dirs.filter(Boolean).length;
|
|
37048
37539
|
}
|
|
37049
37540
|
spinner.start("Setting up workspace TOOLS.md...");
|
|
37050
|
-
const workspaceDir =
|
|
37051
|
-
const toolsPath =
|
|
37052
|
-
await
|
|
37053
|
-
if (await
|
|
37054
|
-
const existingContent = await
|
|
37541
|
+
const workspaceDir = path23.join(openclawDir, "workspace");
|
|
37542
|
+
const toolsPath = path23.join(workspaceDir, "TOOLS.md");
|
|
37543
|
+
await import_fs_extra19.default.ensureDir(workspaceDir);
|
|
37544
|
+
if (await import_fs_extra19.default.pathExists(toolsPath)) {
|
|
37545
|
+
const existingContent = await import_fs_extra19.default.readFile(toolsPath, "utf-8");
|
|
37055
37546
|
if (!existingContent.includes("Claude Code CLI")) {
|
|
37056
|
-
await
|
|
37547
|
+
await import_fs_extra19.default.appendFile(toolsPath, `
|
|
37057
37548
|
|
|
37058
37549
|
` + CLAUDE_CODE_TOOLS_INSTRUCTIONS);
|
|
37059
37550
|
spinner.stop("TOOLS.md updated with Claude Code instructions");
|
|
@@ -37067,7 +37558,7 @@ Skills define _how_ tools work. This file is for _your_ specifics — the stuff
|
|
|
37067
37558
|
|
|
37068
37559
|
${CLAUDE_CODE_TOOLS_INSTRUCTIONS}
|
|
37069
37560
|
`;
|
|
37070
|
-
await
|
|
37561
|
+
await import_fs_extra19.default.writeFile(toolsPath, defaultToolsMd);
|
|
37071
37562
|
spinner.stop("TOOLS.md created with Claude Code instructions");
|
|
37072
37563
|
}
|
|
37073
37564
|
spinner.start("Creating claude-run wrapper...");
|
|
@@ -37078,9 +37569,9 @@ ${CLAUDE_CODE_TOOLS_INSTRUCTIONS}
|
|
|
37078
37569
|
script -q -c "claude $*" /dev/null
|
|
37079
37570
|
`;
|
|
37080
37571
|
const binDir = "/usr/local/bin";
|
|
37081
|
-
const wrapperPath =
|
|
37572
|
+
const wrapperPath = path23.join(binDir, "claude-run");
|
|
37082
37573
|
try {
|
|
37083
|
-
await
|
|
37574
|
+
await import_fs_extra19.default.writeFile(wrapperPath, claudeRunWrapper, { mode: 493 });
|
|
37084
37575
|
spinner.stop("claude-run wrapper created");
|
|
37085
37576
|
} catch {
|
|
37086
37577
|
spinner.stop("claude-run wrapper skipped (no write access to /usr/local/bin)");
|
|
@@ -37129,12 +37620,12 @@ async function openclawProUpdateCommand(options = {}) {
|
|
|
37129
37620
|
}
|
|
37130
37621
|
|
|
37131
37622
|
// src/commands/dynamic-scripts.ts
|
|
37132
|
-
import
|
|
37623
|
+
import path26 from "path";
|
|
37133
37624
|
import { homedir } from "os";
|
|
37134
37625
|
|
|
37135
37626
|
// src/lib/script-parser.ts
|
|
37136
|
-
var
|
|
37137
|
-
import
|
|
37627
|
+
var import_fs_extra20 = __toESM(require_lib4(), 1);
|
|
37628
|
+
import path24 from "path";
|
|
37138
37629
|
var EXCLUDED_SCRIPTS = ["test", "lint", "format", "start"];
|
|
37139
37630
|
var EXCLUDED_SUFFIXES = [":test", ":lint", ":test-fixtures", ":start"];
|
|
37140
37631
|
function shouldIncludeScript(scriptName) {
|
|
@@ -37145,12 +37636,12 @@ function shouldIncludeScript(scriptName) {
|
|
|
37145
37636
|
return true;
|
|
37146
37637
|
}
|
|
37147
37638
|
async function readScriptsPackageJson(claudeDir) {
|
|
37148
|
-
const packageJsonPath =
|
|
37639
|
+
const packageJsonPath = path24.join(claudeDir, "scripts", "package.json");
|
|
37149
37640
|
try {
|
|
37150
|
-
if (!await
|
|
37641
|
+
if (!await import_fs_extra20.default.pathExists(packageJsonPath)) {
|
|
37151
37642
|
return null;
|
|
37152
37643
|
}
|
|
37153
|
-
const content = await
|
|
37644
|
+
const content = await import_fs_extra20.default.readFile(packageJsonPath, "utf-8");
|
|
37154
37645
|
const parsed = JSON.parse(content);
|
|
37155
37646
|
return parsed.scripts || null;
|
|
37156
37647
|
} catch (error) {
|
|
@@ -37194,14 +37685,14 @@ function groupScriptsByPrefix(commands) {
|
|
|
37194
37685
|
}
|
|
37195
37686
|
|
|
37196
37687
|
// src/commands/script-runner.ts
|
|
37197
|
-
var
|
|
37688
|
+
var import_fs_extra21 = __toESM(require_lib4(), 1);
|
|
37198
37689
|
import { spawn as spawn2 } from "child_process";
|
|
37199
37690
|
import { execSync as execSync4 } from "child_process";
|
|
37200
|
-
import
|
|
37201
|
-
import
|
|
37691
|
+
import path25 from "path";
|
|
37692
|
+
import os20 from "os";
|
|
37202
37693
|
function checkCommand2(cmd) {
|
|
37203
37694
|
try {
|
|
37204
|
-
const isWindows2 =
|
|
37695
|
+
const isWindows2 = os20.platform() === "win32";
|
|
37205
37696
|
const whichCmd = isWindows2 ? `where ${cmd}` : `which ${cmd}`;
|
|
37206
37697
|
execSync4(whichCmd, { stdio: "ignore" });
|
|
37207
37698
|
return true;
|
|
@@ -37227,18 +37718,18 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
37227
37718
|
console.error(source_default.red("Bun is not installed. Install with: npm install -g bun"));
|
|
37228
37719
|
return 1;
|
|
37229
37720
|
}
|
|
37230
|
-
const scriptsDir =
|
|
37231
|
-
if (!await
|
|
37721
|
+
const scriptsDir = path25.join(claudeDir, "scripts");
|
|
37722
|
+
if (!await import_fs_extra21.default.pathExists(scriptsDir)) {
|
|
37232
37723
|
console.error(source_default.red(`Scripts directory not found at ${scriptsDir}`));
|
|
37233
37724
|
console.log(source_default.gray("Run: aiblueprint agents setup"));
|
|
37234
37725
|
return 1;
|
|
37235
37726
|
}
|
|
37236
|
-
const packageJsonPath =
|
|
37237
|
-
if (!await
|
|
37727
|
+
const packageJsonPath = path25.join(scriptsDir, "package.json");
|
|
37728
|
+
if (!await import_fs_extra21.default.pathExists(packageJsonPath)) {
|
|
37238
37729
|
console.error(source_default.red(`package.json not found in ${scriptsDir}`));
|
|
37239
37730
|
return 1;
|
|
37240
37731
|
}
|
|
37241
|
-
const packageJson = await
|
|
37732
|
+
const packageJson = await import_fs_extra21.default.readJson(packageJsonPath);
|
|
37242
37733
|
if (!packageJson.scripts || !packageJson.scripts[scriptName]) {
|
|
37243
37734
|
console.error(source_default.red(`Script "${scriptName}" not found in package.json`));
|
|
37244
37735
|
return 1;
|
|
@@ -37261,7 +37752,7 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
37261
37752
|
|
|
37262
37753
|
// src/commands/dynamic-scripts.ts
|
|
37263
37754
|
function getClaudeDir(parentOptions) {
|
|
37264
|
-
return parentOptions.claudeCodeFolder || parentOptions.folder ?
|
|
37755
|
+
return parentOptions.claudeCodeFolder || parentOptions.folder ? path26.resolve(parentOptions.claudeCodeFolder || parentOptions.folder) : path26.join(homedir(), ".claude");
|
|
37265
37756
|
}
|
|
37266
37757
|
async function registerDynamicScriptCommands(claudeCodeCmd, claudeDir) {
|
|
37267
37758
|
const scripts = await readScriptsPackageJson(claudeDir);
|
|
@@ -37323,6 +37814,15 @@ function registerAgentsCommands(cmd) {
|
|
|
37323
37814
|
codexFolder: parentOptions.codexFolder
|
|
37324
37815
|
});
|
|
37325
37816
|
});
|
|
37817
|
+
cmd.command("unify").description("Unify skills and agents into .agents and symlink tool folders back to it").action((options, command) => {
|
|
37818
|
+
const parentOptions = command.parent.opts();
|
|
37819
|
+
return agentsUnifyCommand({
|
|
37820
|
+
folder: parentOptions.folder,
|
|
37821
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37822
|
+
codexFolder: parentOptions.codexFolder,
|
|
37823
|
+
agentsFolder: parentOptions.agentsFolder
|
|
37824
|
+
});
|
|
37825
|
+
});
|
|
37326
37826
|
const proCmd = cmd.command("pro").description("Manage AIBlueprint CLI Premium features");
|
|
37327
37827
|
proCmd.command("activate [token]").description("Activate AIBlueprint CLI Premium with your access token").action((token) => {
|
|
37328
37828
|
proActivateCommand(token);
|
|
@@ -37370,6 +37870,16 @@ function registerAgentsCommands(cmd) {
|
|
|
37370
37870
|
function addConfigFolderOptions(cmd) {
|
|
37371
37871
|
return cmd.option("-f, --folder <path>", "Root folder that contains .claude/, .codex/, .agents/ (default: $HOME)").option("--claudeCodeFolder <path>", "Override Claude Code folder (default: {folder}/.claude)").option("--codexFolder <path>", "Override Codex folder (default: {folder}/.codex)").option("--agentsFolder <path>", "Override shared agents folder (default: {folder}/.agents)");
|
|
37372
37872
|
}
|
|
37873
|
+
function readConfigOptions(command, options = {}) {
|
|
37874
|
+
const parentOptions = command.parent?.opts() ?? {};
|
|
37875
|
+
const grandParentOptions = command.parent?.parent?.opts() ?? {};
|
|
37876
|
+
return {
|
|
37877
|
+
folder: options.folder ?? parentOptions.folder ?? grandParentOptions.folder,
|
|
37878
|
+
claudeCodeFolder: options.claudeCodeFolder ?? parentOptions.claudeCodeFolder ?? grandParentOptions.claudeCodeFolder,
|
|
37879
|
+
codexFolder: options.codexFolder ?? parentOptions.codexFolder ?? grandParentOptions.codexFolder,
|
|
37880
|
+
agentsFolder: options.agentsFolder ?? parentOptions.agentsFolder ?? grandParentOptions.agentsFolder
|
|
37881
|
+
};
|
|
37882
|
+
}
|
|
37373
37883
|
var agentsCmd = program2.command("agents").description("AI coding configuration commands");
|
|
37374
37884
|
registerAgentsCommands(agentsCmd);
|
|
37375
37885
|
var aiCodingCmd = program2.command("ai-coding").description("Legacy alias for agents configuration commands");
|
|
@@ -37377,69 +37887,48 @@ registerAgentsCommands(aiCodingCmd);
|
|
|
37377
37887
|
var claudeCodeCmd = program2.command("claude-code").description("Legacy alias for agents configuration commands");
|
|
37378
37888
|
registerAgentsCommands(claudeCodeCmd);
|
|
37379
37889
|
var configsCmd = addConfigFolderOptions(program2.command("configs").description("Save, load, undo, and inspect .claude/.codex/.agents configurations"));
|
|
37380
|
-
configsCmd.command("save <name>").description("Save the current .claude, .codex, and .agents folders as a named config").option("--force", "Overwrite an existing saved config with the same name").action((name, options, command) => {
|
|
37381
|
-
const
|
|
37890
|
+
addConfigFolderOptions(configsCmd.command("save <name>").description("Save the current .claude, .codex, and .agents folders as a named config").option("--force", "Overwrite an existing saved config with the same name")).action((name, options, command) => {
|
|
37891
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37382
37892
|
configsSaveCommand(name, {
|
|
37383
|
-
|
|
37384
|
-
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37385
|
-
codexFolder: parentOptions.codexFolder,
|
|
37386
|
-
agentsFolder: parentOptions.agentsFolder,
|
|
37893
|
+
...folderOptions,
|
|
37387
37894
|
force: options.force
|
|
37388
37895
|
});
|
|
37389
37896
|
});
|
|
37390
|
-
configsCmd.command("load <name>").description("Load a named config and backup the current folders first").action((name, options, command) => {
|
|
37391
|
-
const
|
|
37897
|
+
addConfigFolderOptions(configsCmd.command("load <name>").description("Load a named config and backup the current folders first")).action((name, options, command) => {
|
|
37898
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37392
37899
|
configsLoadCommand(name, {
|
|
37393
|
-
|
|
37394
|
-
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37395
|
-
codexFolder: parentOptions.codexFolder,
|
|
37396
|
-
agentsFolder: parentOptions.agentsFolder
|
|
37900
|
+
...folderOptions
|
|
37397
37901
|
});
|
|
37398
37902
|
});
|
|
37399
|
-
configsCmd.command("undo").description("Undo the most recent configs load by restoring its automatic backup").action((options, command) => {
|
|
37400
|
-
const
|
|
37903
|
+
addConfigFolderOptions(configsCmd.command("undo").description("Undo the most recent configs load by restoring its automatic backup")).action((options, command) => {
|
|
37904
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37401
37905
|
configsUndoCommand({
|
|
37402
|
-
|
|
37403
|
-
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37404
|
-
codexFolder: parentOptions.codexFolder,
|
|
37405
|
-
agentsFolder: parentOptions.agentsFolder
|
|
37906
|
+
...folderOptions
|
|
37406
37907
|
});
|
|
37407
37908
|
});
|
|
37408
|
-
configsCmd.command("list").description("List saved named configs").action((options, command) => {
|
|
37409
|
-
const
|
|
37909
|
+
addConfigFolderOptions(configsCmd.command("list").description("List saved named configs")).action((options, command) => {
|
|
37910
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37410
37911
|
configsListCommand({
|
|
37411
|
-
|
|
37412
|
-
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37413
|
-
codexFolder: parentOptions.codexFolder,
|
|
37414
|
-
agentsFolder: parentOptions.agentsFolder
|
|
37912
|
+
...folderOptions
|
|
37415
37913
|
});
|
|
37416
37914
|
});
|
|
37417
37915
|
var configsBackupsCmd = configsCmd.command("backups").description("Manage automatic config backups");
|
|
37418
|
-
configsBackupsCmd.command("list").description("List automatic backups with reasons").action((options, command) => {
|
|
37419
|
-
const
|
|
37916
|
+
addConfigFolderOptions(configsBackupsCmd.command("list").description("List automatic backups with reasons")).action((options, command) => {
|
|
37917
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37420
37918
|
configsBackupsListCommand({
|
|
37421
|
-
|
|
37422
|
-
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37423
|
-
codexFolder: parentOptions.codexFolder,
|
|
37424
|
-
agentsFolder: parentOptions.agentsFolder
|
|
37919
|
+
...folderOptions
|
|
37425
37920
|
});
|
|
37426
37921
|
});
|
|
37427
|
-
configsBackupsCmd.command("load <name>").description("Load a backup and backup the current folders first").action((name, options, command) => {
|
|
37428
|
-
const
|
|
37922
|
+
addConfigFolderOptions(configsBackupsCmd.command("load <name>").description("Load a backup and backup the current folders first")).action((name, options, command) => {
|
|
37923
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37429
37924
|
configsBackupsLoadCommand(name, {
|
|
37430
|
-
|
|
37431
|
-
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37432
|
-
codexFolder: parentOptions.codexFolder,
|
|
37433
|
-
agentsFolder: parentOptions.agentsFolder
|
|
37925
|
+
...folderOptions
|
|
37434
37926
|
});
|
|
37435
37927
|
});
|
|
37436
|
-
configsBackupsCmd.command("create [reason]").description("Create a manual backup of the current config folders").action((reason, options, command) => {
|
|
37437
|
-
const
|
|
37928
|
+
addConfigFolderOptions(configsBackupsCmd.command("create [reason]").description("Create a manual backup of the current config folders")).action((reason, options, command) => {
|
|
37929
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37438
37930
|
configsBackupsCreateCommand(reason, {
|
|
37439
|
-
|
|
37440
|
-
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37441
|
-
codexFolder: parentOptions.codexFolder,
|
|
37442
|
-
agentsFolder: parentOptions.agentsFolder
|
|
37931
|
+
...folderOptions
|
|
37443
37932
|
});
|
|
37444
37933
|
});
|
|
37445
37934
|
var openclawCmd = program2.command("openclaw").description("OpenClaw configuration commands").option("-f, --folder <path>", "Specify custom OpenClaw folder path (default: ~/.openclaw)");
|