aiblueprint-cli 1.4.56 → 1.4.58
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/agents-config/codex-config/config.toml +17 -2
- package/dist/cli.js +994 -391
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -32263,9 +32263,9 @@ var inquirer = {
|
|
|
32263
32263
|
var lib_default = inquirer;
|
|
32264
32264
|
|
|
32265
32265
|
// src/commands/setup.ts
|
|
32266
|
-
var
|
|
32267
|
-
import
|
|
32268
|
-
import
|
|
32266
|
+
var import_fs_extra8 = __toESM(require_lib4(), 1);
|
|
32267
|
+
import path12 from "path";
|
|
32268
|
+
import os10 from "os";
|
|
32269
32269
|
|
|
32270
32270
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
32271
32271
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -33051,110 +33051,10 @@ function getVersion() {
|
|
|
33051
33051
|
}
|
|
33052
33052
|
}
|
|
33053
33053
|
|
|
33054
|
-
// src/lib/
|
|
33054
|
+
// src/lib/platform.ts
|
|
33055
33055
|
var import_fs_extra4 = __toESM(require_lib4(), 1);
|
|
33056
|
-
import path6 from "path";
|
|
33057
33056
|
import os6 from "os";
|
|
33058
|
-
|
|
33059
|
-
function formatDate(date) {
|
|
33060
|
-
const pad = (n) => n.toString().padStart(2, "0");
|
|
33061
|
-
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
|
|
33062
|
-
}
|
|
33063
|
-
async function listBackups() {
|
|
33064
|
-
const exists = await import_fs_extra4.default.pathExists(BACKUP_BASE_DIR);
|
|
33065
|
-
if (!exists) {
|
|
33066
|
-
return [];
|
|
33067
|
-
}
|
|
33068
|
-
const entries = await import_fs_extra4.default.readdir(BACKUP_BASE_DIR, { withFileTypes: true });
|
|
33069
|
-
const backups = [];
|
|
33070
|
-
for (const entry of entries) {
|
|
33071
|
-
if (!entry.isDirectory())
|
|
33072
|
-
continue;
|
|
33073
|
-
const match = entry.name.match(/^(\d{4})-(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})$/);
|
|
33074
|
-
if (!match)
|
|
33075
|
-
continue;
|
|
33076
|
-
const [, year, month, day, hour, minute, second] = match;
|
|
33077
|
-
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
|
|
33078
|
-
backups.push({
|
|
33079
|
-
name: entry.name,
|
|
33080
|
-
path: path6.join(BACKUP_BASE_DIR, entry.name),
|
|
33081
|
-
date
|
|
33082
|
-
});
|
|
33083
|
-
}
|
|
33084
|
-
return backups.sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
33085
|
-
}
|
|
33086
|
-
var AGENTS_BACKUP_SUBDIR = ".agents";
|
|
33087
|
-
var CLAUDE_ITEMS = ["commands", "agents", "skills", "scripts", "settings.json"];
|
|
33088
|
-
async function copyForBackup(sourcePath, destPath) {
|
|
33089
|
-
await import_fs_extra4.default.copy(sourcePath, destPath, {
|
|
33090
|
-
overwrite: true,
|
|
33091
|
-
dereference: false,
|
|
33092
|
-
filter: async (src) => {
|
|
33093
|
-
try {
|
|
33094
|
-
const stat = await import_fs_extra4.default.lstat(src);
|
|
33095
|
-
return !stat.isSymbolicLink();
|
|
33096
|
-
} catch {
|
|
33097
|
-
return true;
|
|
33098
|
-
}
|
|
33099
|
-
}
|
|
33100
|
-
});
|
|
33101
|
-
}
|
|
33102
|
-
async function hasMeaningfulContent(dir) {
|
|
33103
|
-
if (!await import_fs_extra4.default.pathExists(dir))
|
|
33104
|
-
return false;
|
|
33105
|
-
const files = await import_fs_extra4.default.readdir(dir);
|
|
33106
|
-
return files.some((f) => f !== ".DS_Store");
|
|
33107
|
-
}
|
|
33108
|
-
async function loadBackup(backupPath, claudeDir, agentsDir) {
|
|
33109
|
-
const exists = await import_fs_extra4.default.pathExists(backupPath);
|
|
33110
|
-
if (!exists) {
|
|
33111
|
-
throw new Error(`Backup not found: ${backupPath}`);
|
|
33112
|
-
}
|
|
33113
|
-
await import_fs_extra4.default.ensureDir(claudeDir);
|
|
33114
|
-
for (const item of CLAUDE_ITEMS) {
|
|
33115
|
-
const sourcePath = path6.join(backupPath, item);
|
|
33116
|
-
const destPath = path6.join(claudeDir, item);
|
|
33117
|
-
if (await import_fs_extra4.default.pathExists(sourcePath)) {
|
|
33118
|
-
await copyForBackup(sourcePath, destPath);
|
|
33119
|
-
}
|
|
33120
|
-
}
|
|
33121
|
-
if (agentsDir) {
|
|
33122
|
-
const agentsBackupPath = path6.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
33123
|
-
if (await import_fs_extra4.default.pathExists(agentsBackupPath)) {
|
|
33124
|
-
await import_fs_extra4.default.ensureDir(agentsDir);
|
|
33125
|
-
await copyForBackup(agentsBackupPath, agentsDir);
|
|
33126
|
-
}
|
|
33127
|
-
}
|
|
33128
|
-
}
|
|
33129
|
-
async function createBackup(claudeDir, agentsDir) {
|
|
33130
|
-
const claudeHasContent = await hasMeaningfulContent(claudeDir);
|
|
33131
|
-
const agentsHasContent = agentsDir ? await hasMeaningfulContent(agentsDir) : false;
|
|
33132
|
-
if (!claudeHasContent && !agentsHasContent) {
|
|
33133
|
-
return null;
|
|
33134
|
-
}
|
|
33135
|
-
const timestamp = formatDate(new Date);
|
|
33136
|
-
const backupPath = path6.join(BACKUP_BASE_DIR, timestamp);
|
|
33137
|
-
await import_fs_extra4.default.ensureDir(backupPath);
|
|
33138
|
-
if (claudeHasContent) {
|
|
33139
|
-
for (const item of CLAUDE_ITEMS) {
|
|
33140
|
-
const sourcePath = path6.join(claudeDir, item);
|
|
33141
|
-
const destPath = path6.join(backupPath, item);
|
|
33142
|
-
if (await import_fs_extra4.default.pathExists(sourcePath)) {
|
|
33143
|
-
await copyForBackup(sourcePath, destPath);
|
|
33144
|
-
}
|
|
33145
|
-
}
|
|
33146
|
-
}
|
|
33147
|
-
if (agentsHasContent && agentsDir) {
|
|
33148
|
-
const destPath = path6.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
33149
|
-
await copyForBackup(agentsDir, destPath);
|
|
33150
|
-
}
|
|
33151
|
-
return backupPath;
|
|
33152
|
-
}
|
|
33153
|
-
|
|
33154
|
-
// src/lib/platform.ts
|
|
33155
|
-
var import_fs_extra5 = __toESM(require_lib4(), 1);
|
|
33156
|
-
import os7 from "os";
|
|
33157
|
-
import path7 from "path";
|
|
33057
|
+
import path6 from "path";
|
|
33158
33058
|
import { execSync as execSync2 } from "child_process";
|
|
33159
33059
|
function escapeShellArg(arg) {
|
|
33160
33060
|
return "'" + arg.replace(/'/g, "'\\''") + "'";
|
|
@@ -33162,15 +33062,15 @@ function escapeShellArg(arg) {
|
|
|
33162
33062
|
var cachedPlatformInfo = null;
|
|
33163
33063
|
var cachedAudioPlayer = undefined;
|
|
33164
33064
|
function isWSL() {
|
|
33165
|
-
if (
|
|
33065
|
+
if (os6.platform() !== "linux")
|
|
33166
33066
|
return false;
|
|
33167
|
-
const release =
|
|
33067
|
+
const release = os6.release().toLowerCase();
|
|
33168
33068
|
return release.includes("microsoft") || release.includes("wsl");
|
|
33169
33069
|
}
|
|
33170
33070
|
function getPlatformInfo() {
|
|
33171
33071
|
if (cachedPlatformInfo)
|
|
33172
33072
|
return cachedPlatformInfo;
|
|
33173
|
-
const platform =
|
|
33073
|
+
const platform = os6.platform();
|
|
33174
33074
|
const wsl = isWSL();
|
|
33175
33075
|
cachedPlatformInfo = {
|
|
33176
33076
|
platform,
|
|
@@ -33178,14 +33078,14 @@ function getPlatformInfo() {
|
|
|
33178
33078
|
isMacOS: platform === "darwin",
|
|
33179
33079
|
isLinux: platform === "linux" && !wsl,
|
|
33180
33080
|
isWSL: wsl,
|
|
33181
|
-
homeDir:
|
|
33081
|
+
homeDir: os6.homedir()
|
|
33182
33082
|
};
|
|
33183
33083
|
return cachedPlatformInfo;
|
|
33184
33084
|
}
|
|
33185
33085
|
function detectAudioPlayer() {
|
|
33186
33086
|
if (cachedAudioPlayer !== undefined)
|
|
33187
33087
|
return cachedAudioPlayer;
|
|
33188
|
-
const platform =
|
|
33088
|
+
const platform = os6.platform();
|
|
33189
33089
|
if (platform === "darwin") {
|
|
33190
33090
|
cachedAudioPlayer = "afplay";
|
|
33191
33091
|
return cachedAudioPlayer;
|
|
@@ -33224,7 +33124,7 @@ function getPlaySoundCommand(soundPath) {
|
|
|
33224
33124
|
const player = detectAudioPlayer();
|
|
33225
33125
|
if (!player)
|
|
33226
33126
|
return null;
|
|
33227
|
-
const platform =
|
|
33127
|
+
const platform = os6.platform();
|
|
33228
33128
|
const safePath = escapeShellArg(soundPath);
|
|
33229
33129
|
if (platform === "darwin") {
|
|
33230
33130
|
return `afplay -v 0.1 ${safePath}`;
|
|
@@ -33307,31 +33207,31 @@ function replaceClaudePathPlaceholder(content, claudeDir) {
|
|
|
33307
33207
|
return content.replaceAll("{CLAUDE_PATH}", claudeDir);
|
|
33308
33208
|
}
|
|
33309
33209
|
async function replacePathPlaceholdersInDir(dir, claudeDir) {
|
|
33310
|
-
const entries = await
|
|
33210
|
+
const entries = await import_fs_extra4.default.readdir(dir, { withFileTypes: true });
|
|
33311
33211
|
for (const entry of entries) {
|
|
33312
|
-
const fullPath =
|
|
33212
|
+
const fullPath = path6.join(dir, entry.name);
|
|
33313
33213
|
if (entry.isDirectory()) {
|
|
33314
33214
|
await replacePathPlaceholdersInDir(fullPath, claudeDir);
|
|
33315
33215
|
} else if (isTextFile(entry.name)) {
|
|
33316
|
-
const content = await
|
|
33216
|
+
const content = await import_fs_extra4.default.readFile(fullPath, "utf-8");
|
|
33317
33217
|
const replaced = replaceClaudePathPlaceholder(content, claudeDir);
|
|
33318
33218
|
if (replaced !== content) {
|
|
33319
|
-
await
|
|
33219
|
+
await import_fs_extra4.default.writeFile(fullPath, replaced, "utf-8");
|
|
33320
33220
|
}
|
|
33321
33221
|
}
|
|
33322
33222
|
}
|
|
33323
33223
|
}
|
|
33324
33224
|
async function applyPathPlaceholders(target, claudeDir) {
|
|
33325
|
-
const stat = await
|
|
33225
|
+
const stat = await import_fs_extra4.default.stat(target).catch(() => null);
|
|
33326
33226
|
if (!stat)
|
|
33327
33227
|
return;
|
|
33328
33228
|
if (stat.isDirectory()) {
|
|
33329
33229
|
await replacePathPlaceholdersInDir(target, claudeDir);
|
|
33330
33230
|
} else if (isTextFile(target)) {
|
|
33331
|
-
const content = await
|
|
33231
|
+
const content = await import_fs_extra4.default.readFile(target, "utf-8");
|
|
33332
33232
|
const replaced = replaceClaudePathPlaceholder(content, claudeDir);
|
|
33333
33233
|
if (replaced !== content) {
|
|
33334
|
-
await
|
|
33234
|
+
await import_fs_extra4.default.writeFile(target, replaced, "utf-8");
|
|
33335
33235
|
}
|
|
33336
33236
|
}
|
|
33337
33237
|
}
|
|
@@ -33360,40 +33260,40 @@ function transformFileContent(content, claudeDir) {
|
|
|
33360
33260
|
}
|
|
33361
33261
|
|
|
33362
33262
|
// src/lib/telemetry.ts
|
|
33363
|
-
import
|
|
33364
|
-
import
|
|
33365
|
-
import
|
|
33263
|
+
import os7 from "os";
|
|
33264
|
+
import fs5 from "fs";
|
|
33265
|
+
import path7 from "path";
|
|
33366
33266
|
var TELEMETRY_URL = "https://codelynx.dev/api/cli/events";
|
|
33367
33267
|
var isDisabled = () => {
|
|
33368
33268
|
return process.env.AIBLUEPRINT_TELEMETRY_DISABLED === "1";
|
|
33369
33269
|
};
|
|
33370
33270
|
var getBasePayload = () => ({
|
|
33371
33271
|
cliVersion: getVersion(),
|
|
33372
|
-
platform:
|
|
33373
|
-
arch:
|
|
33272
|
+
platform: os7.platform(),
|
|
33273
|
+
arch: os7.arch(),
|
|
33374
33274
|
nodeVersion: process.version
|
|
33375
33275
|
});
|
|
33376
33276
|
function getTokenFilePath() {
|
|
33377
|
-
const homeDir =
|
|
33378
|
-
if (
|
|
33379
|
-
const appData = process.env.APPDATA ||
|
|
33380
|
-
return
|
|
33277
|
+
const homeDir = os7.homedir();
|
|
33278
|
+
if (os7.platform() === "win32") {
|
|
33279
|
+
const appData = process.env.APPDATA || path7.join(homeDir, "AppData", "Roaming");
|
|
33280
|
+
return path7.join(appData, "aiblueprint", "token.txt");
|
|
33381
33281
|
}
|
|
33382
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
33383
|
-
return
|
|
33282
|
+
const configHome = process.env.XDG_CONFIG_HOME || path7.join(homeDir, ".config");
|
|
33283
|
+
return path7.join(configHome, "aiblueprint", "token.txt");
|
|
33384
33284
|
}
|
|
33385
33285
|
function getSystemInfo() {
|
|
33386
33286
|
let hasProToken = false;
|
|
33387
33287
|
try {
|
|
33388
|
-
hasProToken =
|
|
33288
|
+
hasProToken = fs5.existsSync(getTokenFilePath());
|
|
33389
33289
|
} catch {}
|
|
33390
33290
|
return {
|
|
33391
|
-
osVersion:
|
|
33392
|
-
osType:
|
|
33393
|
-
totalMemory: `${Math.round(
|
|
33394
|
-
cpus:
|
|
33291
|
+
osVersion: os7.release(),
|
|
33292
|
+
osType: os7.type(),
|
|
33293
|
+
totalMemory: `${Math.round(os7.totalmem() / (1024 * 1024 * 1024))}GB`,
|
|
33294
|
+
cpus: os7.cpus().length,
|
|
33395
33295
|
shell: process.env.SHELL || process.env.COMSPEC || "unknown",
|
|
33396
|
-
homeDir:
|
|
33296
|
+
homeDir: os7.homedir(),
|
|
33397
33297
|
locale: process.env.LANG || process.env.LC_ALL || "unknown",
|
|
33398
33298
|
hasProToken
|
|
33399
33299
|
};
|
|
@@ -33435,28 +33335,28 @@ async function flushTelemetry() {
|
|
|
33435
33335
|
}
|
|
33436
33336
|
|
|
33437
33337
|
// src/lib/agents-installer.ts
|
|
33438
|
-
var
|
|
33439
|
-
import
|
|
33440
|
-
import
|
|
33338
|
+
var import_fs_extra5 = __toESM(require_lib4(), 1);
|
|
33339
|
+
import os8 from "os";
|
|
33340
|
+
import path8 from "path";
|
|
33441
33341
|
var AGENT_CATEGORIES = ["skills", "agents"];
|
|
33442
33342
|
async function platformSymlink(source, target) {
|
|
33443
|
-
await
|
|
33444
|
-
const isWindows2 =
|
|
33445
|
-
const sourceStat = await
|
|
33343
|
+
await import_fs_extra5.default.ensureDir(path8.dirname(target));
|
|
33344
|
+
const isWindows2 = os8.platform() === "win32";
|
|
33345
|
+
const sourceStat = await import_fs_extra5.default.stat(source).catch(() => null);
|
|
33446
33346
|
const isDir = sourceStat?.isDirectory() ?? false;
|
|
33447
33347
|
if (isWindows2 && isDir) {
|
|
33448
|
-
await
|
|
33348
|
+
await import_fs_extra5.default.symlink(source, target, "junction");
|
|
33449
33349
|
return;
|
|
33450
33350
|
}
|
|
33451
33351
|
try {
|
|
33452
|
-
await
|
|
33352
|
+
await import_fs_extra5.default.symlink(source, target);
|
|
33453
33353
|
} catch (error) {
|
|
33454
33354
|
if (!isWindows2 || isDir)
|
|
33455
33355
|
throw error;
|
|
33456
33356
|
try {
|
|
33457
|
-
await
|
|
33357
|
+
await import_fs_extra5.default.link(source, target);
|
|
33458
33358
|
} catch {
|
|
33459
|
-
await
|
|
33359
|
+
await import_fs_extra5.default.copy(source, target, { overwrite: true });
|
|
33460
33360
|
}
|
|
33461
33361
|
}
|
|
33462
33362
|
}
|
|
@@ -33467,37 +33367,37 @@ async function installCategoryToAgents(sourceCategoryDir, category, agentsDir, c
|
|
|
33467
33367
|
symlinked: [],
|
|
33468
33368
|
skipped: []
|
|
33469
33369
|
};
|
|
33470
|
-
if (!await
|
|
33370
|
+
if (!await import_fs_extra5.default.pathExists(sourceCategoryDir)) {
|
|
33471
33371
|
return result;
|
|
33472
33372
|
}
|
|
33473
|
-
const agentsCategoryDir =
|
|
33474
|
-
await
|
|
33475
|
-
const entries = await
|
|
33373
|
+
const agentsCategoryDir = path8.join(agentsDir, category);
|
|
33374
|
+
await import_fs_extra5.default.ensureDir(agentsCategoryDir);
|
|
33375
|
+
const entries = await import_fs_extra5.default.readdir(sourceCategoryDir, { withFileTypes: true });
|
|
33476
33376
|
for (const entry of entries) {
|
|
33477
33377
|
if (entry.name === ".DS_Store" || entry.name === "node_modules")
|
|
33478
33378
|
continue;
|
|
33479
|
-
const sourcePath =
|
|
33480
|
-
const agentsTarget =
|
|
33481
|
-
const claudeTarget =
|
|
33482
|
-
const agentsExists = await
|
|
33379
|
+
const sourcePath = path8.join(sourceCategoryDir, entry.name);
|
|
33380
|
+
const agentsTarget = path8.join(agentsCategoryDir, entry.name);
|
|
33381
|
+
const claudeTarget = path8.join(claudeDir, category, entry.name);
|
|
33382
|
+
const agentsExists = await import_fs_extra5.default.pathExists(agentsTarget);
|
|
33483
33383
|
if (!agentsExists) {
|
|
33484
33384
|
let migrated = false;
|
|
33485
33385
|
if (options.migrateClaudeDirs) {
|
|
33486
|
-
const claudeStat = await
|
|
33386
|
+
const claudeStat = await import_fs_extra5.default.lstat(claudeTarget).catch(() => null);
|
|
33487
33387
|
if (claudeStat && !claudeStat.isSymbolicLink()) {
|
|
33488
|
-
await
|
|
33388
|
+
await import_fs_extra5.default.move(claudeTarget, agentsTarget);
|
|
33489
33389
|
result.migrated.push(entry.name);
|
|
33490
33390
|
migrated = true;
|
|
33491
33391
|
}
|
|
33492
33392
|
}
|
|
33493
33393
|
if (!migrated) {
|
|
33494
|
-
await
|
|
33394
|
+
await import_fs_extra5.default.copy(sourcePath, agentsTarget, { overwrite: false });
|
|
33495
33395
|
await applyPathPlaceholders(agentsTarget, claudeDir);
|
|
33496
33396
|
result.copied.push(entry.name);
|
|
33497
33397
|
}
|
|
33498
33398
|
} else if (options.overwrite) {
|
|
33499
|
-
await
|
|
33500
|
-
await
|
|
33399
|
+
await import_fs_extra5.default.remove(agentsTarget);
|
|
33400
|
+
await import_fs_extra5.default.copy(sourcePath, agentsTarget, { overwrite: false });
|
|
33501
33401
|
await applyPathPlaceholders(agentsTarget, claudeDir);
|
|
33502
33402
|
result.copied.push(entry.name);
|
|
33503
33403
|
}
|
|
@@ -33506,24 +33406,24 @@ async function installCategoryToAgents(sourceCategoryDir, category, agentsDir, c
|
|
|
33506
33406
|
return result;
|
|
33507
33407
|
}
|
|
33508
33408
|
async function syncCategorySymlinks(category, agentsDir, claudeDir, result, silent = false) {
|
|
33509
|
-
const agentsCategoryDir =
|
|
33510
|
-
const claudeCategoryDir =
|
|
33511
|
-
if (!await
|
|
33409
|
+
const agentsCategoryDir = path8.join(agentsDir, category);
|
|
33410
|
+
const claudeCategoryDir = path8.join(claudeDir, category);
|
|
33411
|
+
if (!await import_fs_extra5.default.pathExists(agentsCategoryDir)) {
|
|
33512
33412
|
return;
|
|
33513
33413
|
}
|
|
33514
|
-
await
|
|
33515
|
-
const entries = await
|
|
33414
|
+
await import_fs_extra5.default.ensureDir(claudeCategoryDir);
|
|
33415
|
+
const entries = await import_fs_extra5.default.readdir(agentsCategoryDir, { withFileTypes: true });
|
|
33516
33416
|
for (const entry of entries) {
|
|
33517
33417
|
if (entry.name === ".DS_Store")
|
|
33518
33418
|
continue;
|
|
33519
|
-
const agentsTarget =
|
|
33520
|
-
const claudeTarget =
|
|
33521
|
-
const claudeStat = await
|
|
33419
|
+
const agentsTarget = path8.join(agentsCategoryDir, entry.name);
|
|
33420
|
+
const claudeTarget = path8.join(claudeCategoryDir, entry.name);
|
|
33421
|
+
const claudeStat = await import_fs_extra5.default.lstat(claudeTarget).catch(() => null);
|
|
33522
33422
|
if (!claudeStat) {
|
|
33523
33423
|
await platformSymlink(agentsTarget, claudeTarget);
|
|
33524
33424
|
result?.symlinked.push(entry.name);
|
|
33525
33425
|
} else if (claudeStat.isSymbolicLink()) {
|
|
33526
|
-
await
|
|
33426
|
+
await import_fs_extra5.default.remove(claudeTarget);
|
|
33527
33427
|
await platformSymlink(agentsTarget, claudeTarget);
|
|
33528
33428
|
result?.symlinked.push(entry.name);
|
|
33529
33429
|
} else {
|
|
@@ -33534,15 +33434,15 @@ async function syncCategorySymlinks(category, agentsDir, claudeDir, result, sile
|
|
|
33534
33434
|
}
|
|
33535
33435
|
}
|
|
33536
33436
|
}
|
|
33537
|
-
if (await
|
|
33538
|
-
const claudeEntries = await
|
|
33437
|
+
if (await import_fs_extra5.default.pathExists(claudeCategoryDir)) {
|
|
33438
|
+
const claudeEntries = await import_fs_extra5.default.readdir(claudeCategoryDir, { withFileTypes: true });
|
|
33539
33439
|
for (const entry of claudeEntries) {
|
|
33540
|
-
const claudeTarget =
|
|
33541
|
-
const stat = await
|
|
33440
|
+
const claudeTarget = path8.join(claudeCategoryDir, entry.name);
|
|
33441
|
+
const stat = await import_fs_extra5.default.lstat(claudeTarget).catch(() => null);
|
|
33542
33442
|
if (stat?.isSymbolicLink()) {
|
|
33543
|
-
const exists = await
|
|
33443
|
+
const exists = await import_fs_extra5.default.pathExists(claudeTarget);
|
|
33544
33444
|
if (!exists) {
|
|
33545
|
-
await
|
|
33445
|
+
await import_fs_extra5.default.remove(claudeTarget);
|
|
33546
33446
|
}
|
|
33547
33447
|
}
|
|
33548
33448
|
}
|
|
@@ -33553,26 +33453,456 @@ function isAgentCategory(category) {
|
|
|
33553
33453
|
}
|
|
33554
33454
|
|
|
33555
33455
|
// src/lib/folder-paths.ts
|
|
33556
|
-
import
|
|
33557
|
-
import
|
|
33456
|
+
import os9 from "os";
|
|
33457
|
+
import path9 from "path";
|
|
33558
33458
|
function resolveFolders(options = {}) {
|
|
33559
|
-
const rootDir = options.folder ?
|
|
33560
|
-
const claudeDir = options.claudeCodeFolder ?
|
|
33561
|
-
const codexDir = options.codexFolder ?
|
|
33562
|
-
const agentsDir = options.agentsFolder ?
|
|
33459
|
+
const rootDir = options.folder ? path9.resolve(options.folder) : os9.homedir();
|
|
33460
|
+
const claudeDir = options.claudeCodeFolder ? path9.resolve(options.claudeCodeFolder) : path9.join(rootDir, ".claude");
|
|
33461
|
+
const codexDir = options.codexFolder ? path9.resolve(options.codexFolder) : path9.join(rootDir, ".codex");
|
|
33462
|
+
const agentsDir = options.agentsFolder ? path9.resolve(options.agentsFolder) : path9.join(rootDir, ".agents");
|
|
33563
33463
|
return { rootDir, claudeDir, codexDir, agentsDir };
|
|
33564
33464
|
}
|
|
33565
33465
|
|
|
33466
|
+
// src/lib/codex-config.ts
|
|
33467
|
+
var import_fs_extra6 = __toESM(require_lib4(), 1);
|
|
33468
|
+
import path10 from "path";
|
|
33469
|
+
var TUI_STATUS_LINE_BLOCK = `status_line = [
|
|
33470
|
+
"model-with-reasoning",
|
|
33471
|
+
"run-state",
|
|
33472
|
+
"project-name",
|
|
33473
|
+
"git-branch",
|
|
33474
|
+
"branch-changes",
|
|
33475
|
+
"context-remaining",
|
|
33476
|
+
"used-tokens",
|
|
33477
|
+
"five-hour-limit",
|
|
33478
|
+
"weekly-limit",
|
|
33479
|
+
"task-progress",
|
|
33480
|
+
]
|
|
33481
|
+
status_line_use_colors = true`;
|
|
33482
|
+
var TUI_SECTION = `[tui]
|
|
33483
|
+
${TUI_STATUS_LINE_BLOCK}`;
|
|
33484
|
+
function hasTopLevelKey(content, key) {
|
|
33485
|
+
let inSection = false;
|
|
33486
|
+
for (const line of content.split(/\r?\n/)) {
|
|
33487
|
+
const trimmed = line.trim();
|
|
33488
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
33489
|
+
continue;
|
|
33490
|
+
if (/^\[[^\]]+\]$/.test(trimmed)) {
|
|
33491
|
+
inSection = true;
|
|
33492
|
+
continue;
|
|
33493
|
+
}
|
|
33494
|
+
if (!inSection && (trimmed.startsWith(`${key} `) || trimmed.startsWith(`${key}=`))) {
|
|
33495
|
+
return true;
|
|
33496
|
+
}
|
|
33497
|
+
}
|
|
33498
|
+
return false;
|
|
33499
|
+
}
|
|
33500
|
+
function getTopLevelAssignments(defaultConfig) {
|
|
33501
|
+
const assignments = [];
|
|
33502
|
+
for (const line of defaultConfig.split(/\r?\n/)) {
|
|
33503
|
+
const trimmed = line.trim();
|
|
33504
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
33505
|
+
continue;
|
|
33506
|
+
if (/^\[[^\]]+\]$/.test(trimmed))
|
|
33507
|
+
break;
|
|
33508
|
+
if (/^[A-Za-z0-9_-]+\s*=/.test(trimmed)) {
|
|
33509
|
+
assignments.push(line);
|
|
33510
|
+
}
|
|
33511
|
+
}
|
|
33512
|
+
return assignments;
|
|
33513
|
+
}
|
|
33514
|
+
function findSectionRange(content, sectionName) {
|
|
33515
|
+
const lines = content.split(/\r?\n/);
|
|
33516
|
+
const sectionHeader = `[${sectionName}]`;
|
|
33517
|
+
let start = -1;
|
|
33518
|
+
for (let index = 0;index < lines.length; index += 1) {
|
|
33519
|
+
if (lines[index].trim() === sectionHeader) {
|
|
33520
|
+
start = index;
|
|
33521
|
+
break;
|
|
33522
|
+
}
|
|
33523
|
+
}
|
|
33524
|
+
if (start === -1)
|
|
33525
|
+
return null;
|
|
33526
|
+
let end = lines.length;
|
|
33527
|
+
for (let index = start + 1;index < lines.length; index += 1) {
|
|
33528
|
+
const trimmed = lines[index].trim();
|
|
33529
|
+
if (/^\[[^\]]+\]$/.test(trimmed)) {
|
|
33530
|
+
end = index;
|
|
33531
|
+
break;
|
|
33532
|
+
}
|
|
33533
|
+
}
|
|
33534
|
+
return { start, end };
|
|
33535
|
+
}
|
|
33536
|
+
function sectionHasKey(content, sectionName, key) {
|
|
33537
|
+
const range = findSectionRange(content, sectionName);
|
|
33538
|
+
if (!range)
|
|
33539
|
+
return false;
|
|
33540
|
+
const lines = content.split(/\r?\n/).slice(range.start + 1, range.end);
|
|
33541
|
+
return lines.some((line) => {
|
|
33542
|
+
const trimmed = line.trim();
|
|
33543
|
+
return trimmed.startsWith(`${key} `) || trimmed.startsWith(`${key}=`);
|
|
33544
|
+
});
|
|
33545
|
+
}
|
|
33546
|
+
function appendBlock(content, block) {
|
|
33547
|
+
const normalized = content.trimEnd();
|
|
33548
|
+
if (!normalized)
|
|
33549
|
+
return `${block}
|
|
33550
|
+
`;
|
|
33551
|
+
return `${normalized}
|
|
33552
|
+
|
|
33553
|
+
${block}
|
|
33554
|
+
`;
|
|
33555
|
+
}
|
|
33556
|
+
function mergeCodexConfig(existingConfig, defaultConfig) {
|
|
33557
|
+
let merged = existingConfig.trimEnd();
|
|
33558
|
+
for (const assignment of getTopLevelAssignments(defaultConfig)) {
|
|
33559
|
+
const key = assignment.split("=")[0].trim();
|
|
33560
|
+
if (!hasTopLevelKey(merged, key)) {
|
|
33561
|
+
merged = appendBlock(merged, assignment);
|
|
33562
|
+
}
|
|
33563
|
+
}
|
|
33564
|
+
if (sectionHasKey(merged, "tui", "status_line")) {
|
|
33565
|
+
return `${merged}
|
|
33566
|
+
`;
|
|
33567
|
+
}
|
|
33568
|
+
const tuiRange = findSectionRange(merged, "tui");
|
|
33569
|
+
if (!tuiRange) {
|
|
33570
|
+
return appendBlock(merged, TUI_SECTION);
|
|
33571
|
+
}
|
|
33572
|
+
const lines = merged.split(/\r?\n/);
|
|
33573
|
+
lines.splice(tuiRange.start + 1, 0, TUI_STATUS_LINE_BLOCK);
|
|
33574
|
+
return `${lines.join(`
|
|
33575
|
+
`).trimEnd()}
|
|
33576
|
+
`;
|
|
33577
|
+
}
|
|
33578
|
+
async function mergeCodexConfigFile(sourceConfigPath, codexDir) {
|
|
33579
|
+
const targetConfigPath = path10.join(codexDir, "config.toml");
|
|
33580
|
+
const defaultConfig = await import_fs_extra6.default.readFile(sourceConfigPath, "utf-8");
|
|
33581
|
+
const existingConfig = await import_fs_extra6.default.readFile(targetConfigPath, "utf-8").catch(() => "");
|
|
33582
|
+
const merged = mergeCodexConfig(existingConfig, defaultConfig);
|
|
33583
|
+
await import_fs_extra6.default.ensureDir(codexDir);
|
|
33584
|
+
await import_fs_extra6.default.writeFile(targetConfigPath, merged, "utf-8");
|
|
33585
|
+
}
|
|
33586
|
+
|
|
33587
|
+
// src/lib/configs-store.ts
|
|
33588
|
+
var import_fs_extra7 = __toESM(require_lib4(), 1);
|
|
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
|
+
};
|
|
33630
|
+
function getConfigStorePaths(rootDir) {
|
|
33631
|
+
const baseDir = path11.join(rootDir, ".aiblueprint");
|
|
33632
|
+
return {
|
|
33633
|
+
baseDir,
|
|
33634
|
+
configsDir: path11.join(baseDir, "configs"),
|
|
33635
|
+
backupsDir: path11.join(baseDir, "backups"),
|
|
33636
|
+
historyPath: path11.join(baseDir, "history.jsonl")
|
|
33637
|
+
};
|
|
33638
|
+
}
|
|
33639
|
+
function resolveConfigStoreFolders(options = {}) {
|
|
33640
|
+
return resolveFolders(options);
|
|
33641
|
+
}
|
|
33642
|
+
function timestamp(date = new Date) {
|
|
33643
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
33644
|
+
return [
|
|
33645
|
+
date.getFullYear(),
|
|
33646
|
+
pad(date.getMonth() + 1),
|
|
33647
|
+
pad(date.getDate()),
|
|
33648
|
+
pad(date.getHours()),
|
|
33649
|
+
pad(date.getMinutes()),
|
|
33650
|
+
pad(date.getSeconds())
|
|
33651
|
+
].join("-");
|
|
33652
|
+
}
|
|
33653
|
+
function sanitizeSnapshotName(name) {
|
|
33654
|
+
const sanitized = name.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
33655
|
+
if (!sanitized) {
|
|
33656
|
+
throw new Error("Snapshot name cannot be empty");
|
|
33657
|
+
}
|
|
33658
|
+
if (sanitized === "." || sanitized === ".." || sanitized.includes("..")) {
|
|
33659
|
+
throw new Error("Snapshot name is not allowed");
|
|
33660
|
+
}
|
|
33661
|
+
return sanitized;
|
|
33662
|
+
}
|
|
33663
|
+
function managedFolders(folders) {
|
|
33664
|
+
return [
|
|
33665
|
+
{ name: ".claude", path: folders.claudeDir },
|
|
33666
|
+
{ name: ".codex", path: folders.codexDir },
|
|
33667
|
+
{ name: ".agents", path: folders.agentsDir }
|
|
33668
|
+
];
|
|
33669
|
+
}
|
|
33670
|
+
async function hasContent(folderPath) {
|
|
33671
|
+
if (!await import_fs_extra7.default.pathExists(folderPath))
|
|
33672
|
+
return false;
|
|
33673
|
+
const entries = await import_fs_extra7.default.readdir(folderPath);
|
|
33674
|
+
return entries.some((entry) => entry !== ".DS_Store");
|
|
33675
|
+
}
|
|
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) {
|
|
33696
|
+
await import_fs_extra7.default.copy(source, destination, {
|
|
33697
|
+
overwrite: true,
|
|
33698
|
+
dereference: false,
|
|
33699
|
+
filter: async (src) => {
|
|
33700
|
+
try {
|
|
33701
|
+
const stat = await import_fs_extra7.default.lstat(src);
|
|
33702
|
+
return !stat.isSymbolicLink() && shouldCopyManagedPath(name, source, src);
|
|
33703
|
+
} catch {
|
|
33704
|
+
return true;
|
|
33705
|
+
}
|
|
33706
|
+
}
|
|
33707
|
+
});
|
|
33708
|
+
}
|
|
33709
|
+
async function writeMetadata(snapshotPath, metadata) {
|
|
33710
|
+
await import_fs_extra7.default.writeJson(path11.join(snapshotPath, "metadata.json"), metadata, { spaces: 2 });
|
|
33711
|
+
}
|
|
33712
|
+
async function readMetadata(snapshotPath, fallbackType) {
|
|
33713
|
+
const metadataPath = path11.join(snapshotPath, "metadata.json");
|
|
33714
|
+
if (await import_fs_extra7.default.pathExists(metadataPath)) {
|
|
33715
|
+
return import_fs_extra7.default.readJson(metadataPath);
|
|
33716
|
+
}
|
|
33717
|
+
const name = path11.basename(snapshotPath);
|
|
33718
|
+
return {
|
|
33719
|
+
name,
|
|
33720
|
+
type: fallbackType,
|
|
33721
|
+
createdAt: new Date(0).toISOString(),
|
|
33722
|
+
reason: "Legacy snapshot without metadata",
|
|
33723
|
+
trigger: "legacy",
|
|
33724
|
+
folders: []
|
|
33725
|
+
};
|
|
33726
|
+
}
|
|
33727
|
+
async function appendHistory(paths, event) {
|
|
33728
|
+
await import_fs_extra7.default.ensureDir(paths.baseDir);
|
|
33729
|
+
await import_fs_extra7.default.appendFile(paths.historyPath, `${JSON.stringify({ at: new Date().toISOString(), ...event })}
|
|
33730
|
+
`);
|
|
33731
|
+
}
|
|
33732
|
+
async function snapshotByCopy(snapshotPath, folders, metadata) {
|
|
33733
|
+
const copied = [];
|
|
33734
|
+
await import_fs_extra7.default.ensureDir(snapshotPath);
|
|
33735
|
+
for (const folder of managedFolders(folders)) {
|
|
33736
|
+
if (!await hasContent(folder.path))
|
|
33737
|
+
continue;
|
|
33738
|
+
await copyManagedFolder(folder.name, folder.path, path11.join(snapshotPath, folder.name));
|
|
33739
|
+
copied.push(folder.name);
|
|
33740
|
+
}
|
|
33741
|
+
if (copied.length === 0) {
|
|
33742
|
+
await import_fs_extra7.default.remove(snapshotPath);
|
|
33743
|
+
return null;
|
|
33744
|
+
}
|
|
33745
|
+
await writeMetadata(snapshotPath, { ...metadata, folders: copied });
|
|
33746
|
+
return snapshotPath;
|
|
33747
|
+
}
|
|
33748
|
+
async function saveNamedConfig(name, options = {}) {
|
|
33749
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33750
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33751
|
+
const safeName = sanitizeSnapshotName(name);
|
|
33752
|
+
const snapshotPath = path11.join(paths.configsDir, safeName);
|
|
33753
|
+
if (await import_fs_extra7.default.pathExists(snapshotPath) && !options.force) {
|
|
33754
|
+
throw new Error(`Config "${safeName}" already exists. Use --force to overwrite it.`);
|
|
33755
|
+
}
|
|
33756
|
+
if (await import_fs_extra7.default.pathExists(snapshotPath)) {
|
|
33757
|
+
const backupName = `${timestamp()}-replace-saved-${safeName}`;
|
|
33758
|
+
await import_fs_extra7.default.ensureDir(paths.backupsDir);
|
|
33759
|
+
await import_fs_extra7.default.move(snapshotPath, path11.join(paths.backupsDir, backupName), { overwrite: false });
|
|
33760
|
+
}
|
|
33761
|
+
const result = await snapshotByCopy(snapshotPath, folders, {
|
|
33762
|
+
name: safeName,
|
|
33763
|
+
type: "config",
|
|
33764
|
+
createdAt: new Date().toISOString(),
|
|
33765
|
+
reason: `Manual save as "${safeName}"`,
|
|
33766
|
+
trigger: "save",
|
|
33767
|
+
folders: []
|
|
33768
|
+
});
|
|
33769
|
+
if (!result) {
|
|
33770
|
+
throw new Error("No .claude, .codex, or .agents configuration found to save.");
|
|
33771
|
+
}
|
|
33772
|
+
await appendHistory(paths, { action: "save", name: safeName, path: result });
|
|
33773
|
+
return result;
|
|
33774
|
+
}
|
|
33775
|
+
async function createConfigBackup(options = {}, reason = "Backup current configuration", trigger = "manual", source) {
|
|
33776
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33777
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33778
|
+
const safeSource = source ? sanitizeSnapshotName(source) : trigger;
|
|
33779
|
+
const name = `${timestamp()}-${safeSource}`;
|
|
33780
|
+
const snapshotPath = path11.join(paths.backupsDir, name);
|
|
33781
|
+
const result = await snapshotByCopy(snapshotPath, folders, {
|
|
33782
|
+
name,
|
|
33783
|
+
type: "backup",
|
|
33784
|
+
createdAt: new Date().toISOString(),
|
|
33785
|
+
reason,
|
|
33786
|
+
trigger,
|
|
33787
|
+
source,
|
|
33788
|
+
folders: []
|
|
33789
|
+
});
|
|
33790
|
+
if (result) {
|
|
33791
|
+
await appendHistory(paths, { action: "backup", name, reason, trigger, source, path: result });
|
|
33792
|
+
}
|
|
33793
|
+
return result;
|
|
33794
|
+
}
|
|
33795
|
+
async function backupCurrentByMove(folders, reason, trigger, source) {
|
|
33796
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33797
|
+
const safeSource = source ? sanitizeSnapshotName(source) : trigger;
|
|
33798
|
+
const name = `${timestamp()}-${safeSource}`;
|
|
33799
|
+
const backupPath = path11.join(paths.backupsDir, name);
|
|
33800
|
+
const moved = [];
|
|
33801
|
+
await import_fs_extra7.default.ensureDir(backupPath);
|
|
33802
|
+
for (const folder of managedFolders(folders)) {
|
|
33803
|
+
if (!await hasContent(folder.path))
|
|
33804
|
+
continue;
|
|
33805
|
+
await import_fs_extra7.default.move(folder.path, path11.join(backupPath, folder.name), { overwrite: false });
|
|
33806
|
+
moved.push(folder.name);
|
|
33807
|
+
}
|
|
33808
|
+
if (moved.length === 0) {
|
|
33809
|
+
await import_fs_extra7.default.remove(backupPath);
|
|
33810
|
+
return null;
|
|
33811
|
+
}
|
|
33812
|
+
await writeMetadata(backupPath, {
|
|
33813
|
+
name,
|
|
33814
|
+
type: "backup",
|
|
33815
|
+
createdAt: new Date().toISOString(),
|
|
33816
|
+
reason,
|
|
33817
|
+
trigger,
|
|
33818
|
+
source,
|
|
33819
|
+
folders: moved
|
|
33820
|
+
});
|
|
33821
|
+
await appendHistory(paths, { action: "backup", name, reason, trigger, source, path: backupPath });
|
|
33822
|
+
return backupPath;
|
|
33823
|
+
}
|
|
33824
|
+
async function restoreSnapshot(snapshotPath, folders) {
|
|
33825
|
+
const restored = [];
|
|
33826
|
+
for (const folder of managedFolders(folders)) {
|
|
33827
|
+
const source = path11.join(snapshotPath, folder.name);
|
|
33828
|
+
if (!await import_fs_extra7.default.pathExists(source))
|
|
33829
|
+
continue;
|
|
33830
|
+
await import_fs_extra7.default.ensureDir(path11.dirname(folder.path));
|
|
33831
|
+
await copyManagedFolder(folder.name, source, folder.path);
|
|
33832
|
+
restored.push(folder.name);
|
|
33833
|
+
}
|
|
33834
|
+
return restored;
|
|
33835
|
+
}
|
|
33836
|
+
async function loadNamedConfig(name, options = {}) {
|
|
33837
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33838
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33839
|
+
const safeName = sanitizeSnapshotName(name);
|
|
33840
|
+
const snapshotPath = path11.join(paths.configsDir, safeName);
|
|
33841
|
+
if (!await import_fs_extra7.default.pathExists(snapshotPath)) {
|
|
33842
|
+
throw new Error(`Saved config not found: ${safeName}`);
|
|
33843
|
+
}
|
|
33844
|
+
const backupPath = await backupCurrentByMove(folders, `Before loading saved config "${safeName}"`, "load", safeName);
|
|
33845
|
+
const restored = await restoreSnapshot(snapshotPath, folders);
|
|
33846
|
+
await appendHistory(paths, { action: "load", name: safeName, backupPath, restored });
|
|
33847
|
+
return { backupPath, restored };
|
|
33848
|
+
}
|
|
33849
|
+
async function loadBackupSnapshot(name, options = {}) {
|
|
33850
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33851
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33852
|
+
const safeName = sanitizeSnapshotName(name);
|
|
33853
|
+
const snapshotPath = path11.join(paths.backupsDir, safeName);
|
|
33854
|
+
if (!await import_fs_extra7.default.pathExists(snapshotPath)) {
|
|
33855
|
+
throw new Error(`Backup not found: ${safeName}`);
|
|
33856
|
+
}
|
|
33857
|
+
const backupPath = await backupCurrentByMove(folders, `Before restoring backup "${safeName}"`, "backup-load", safeName);
|
|
33858
|
+
const restored = await restoreSnapshot(snapshotPath, folders);
|
|
33859
|
+
await appendHistory(paths, { action: "backup-load", name: safeName, backupPath, restored });
|
|
33860
|
+
return { backupPath, restored };
|
|
33861
|
+
}
|
|
33862
|
+
async function undoLastLoad(options = {}) {
|
|
33863
|
+
const backups = await listConfigBackups(options);
|
|
33864
|
+
const lastLoadBackup = backups.find((backup) => backup.metadata.trigger === "load" || backup.metadata.trigger === "backup-load");
|
|
33865
|
+
if (!lastLoadBackup) {
|
|
33866
|
+
throw new Error("No load backup found to undo.");
|
|
33867
|
+
}
|
|
33868
|
+
const result = await loadBackupSnapshot(lastLoadBackup.name, options);
|
|
33869
|
+
return { backupName: lastLoadBackup.name, ...result };
|
|
33870
|
+
}
|
|
33871
|
+
async function listSnapshots(dir, type) {
|
|
33872
|
+
if (!await import_fs_extra7.default.pathExists(dir))
|
|
33873
|
+
return [];
|
|
33874
|
+
const entries = await import_fs_extra7.default.readdir(dir, { withFileTypes: true });
|
|
33875
|
+
const snapshots = [];
|
|
33876
|
+
for (const entry of entries) {
|
|
33877
|
+
if (!entry.isDirectory())
|
|
33878
|
+
continue;
|
|
33879
|
+
const snapshotPath = path11.join(dir, entry.name);
|
|
33880
|
+
const metadata = await readMetadata(snapshotPath, type);
|
|
33881
|
+
snapshots.push({ name: entry.name, path: snapshotPath, metadata });
|
|
33882
|
+
}
|
|
33883
|
+
return snapshots.sort((a, b) => b.metadata.createdAt.localeCompare(a.metadata.createdAt));
|
|
33884
|
+
}
|
|
33885
|
+
async function listSavedConfigs(options = {}) {
|
|
33886
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33887
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33888
|
+
return listSnapshots(paths.configsDir, "config");
|
|
33889
|
+
}
|
|
33890
|
+
async function listConfigBackups(options = {}) {
|
|
33891
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33892
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33893
|
+
return listSnapshots(paths.backupsDir, "backup");
|
|
33894
|
+
}
|
|
33895
|
+
|
|
33566
33896
|
// src/commands/setup.ts
|
|
33567
33897
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
33568
33898
|
var __dirname2 = dirname2(__filename2);
|
|
33569
33899
|
async function resolveClaudeAssetPath(sourceDir, name) {
|
|
33570
33900
|
const candidates = [
|
|
33571
|
-
|
|
33572
|
-
|
|
33901
|
+
path12.join(sourceDir, "claude-config", name),
|
|
33902
|
+
path12.join(sourceDir, name)
|
|
33573
33903
|
];
|
|
33574
33904
|
for (const candidate of candidates) {
|
|
33575
|
-
if (await
|
|
33905
|
+
if (await import_fs_extra8.default.pathExists(candidate))
|
|
33576
33906
|
return candidate;
|
|
33577
33907
|
}
|
|
33578
33908
|
return null;
|
|
@@ -33660,10 +33990,10 @@ async function setupCommand(params = {}) {
|
|
|
33660
33990
|
console.log(source_default.gray(`Claude: ${claudeDir}`));
|
|
33661
33991
|
console.log(source_default.gray(`Codex: ${codexDir}`));
|
|
33662
33992
|
console.log(source_default.gray(`Agents: ${agentsDir}`));
|
|
33663
|
-
await
|
|
33664
|
-
await
|
|
33993
|
+
await import_fs_extra8.default.ensureDir(claudeDir);
|
|
33994
|
+
await import_fs_extra8.default.ensureDir(agentsDir);
|
|
33665
33995
|
s.start("Creating backup of existing configuration");
|
|
33666
|
-
const backupPath = await
|
|
33996
|
+
const backupPath = await createConfigBackup({ folder, claudeCodeFolder, codexFolder, agentsFolder }, "Before running aiblueprint setup", "setup", "aiblueprint-setup");
|
|
33667
33997
|
if (backupPath) {
|
|
33668
33998
|
s.stop(`Backup created: ${source_default.gray(backupPath)}`);
|
|
33669
33999
|
} else {
|
|
@@ -33689,11 +34019,11 @@ async function setupCommand(params = {}) {
|
|
|
33689
34019
|
s.start("Setting up scripts");
|
|
33690
34020
|
const scriptsSource = await resolveClaudeAssetPath(sourceDir, "scripts");
|
|
33691
34021
|
if (scriptsSource) {
|
|
33692
|
-
await
|
|
34022
|
+
await import_fs_extra8.default.copy(scriptsSource, path12.join(claudeDir, "scripts"), {
|
|
33693
34023
|
overwrite: true
|
|
33694
34024
|
});
|
|
33695
|
-
await replacePathPlaceholdersInDir(
|
|
33696
|
-
await
|
|
34025
|
+
await replacePathPlaceholdersInDir(path12.join(claudeDir, "scripts"), claudeDir);
|
|
34026
|
+
await import_fs_extra8.default.ensureDir(path12.join(claudeDir, "scripts/statusline/data"));
|
|
33697
34027
|
s.stop("Scripts installed");
|
|
33698
34028
|
} else {
|
|
33699
34029
|
s.stop("Scripts not available in repository");
|
|
@@ -33701,8 +34031,8 @@ async function setupCommand(params = {}) {
|
|
|
33701
34031
|
}
|
|
33702
34032
|
if (options.aiblueprintAgents) {
|
|
33703
34033
|
s.start("Setting up AIBlueprint agents");
|
|
33704
|
-
const agentsSource =
|
|
33705
|
-
if (await
|
|
34034
|
+
const agentsSource = path12.join(sourceDir, "agents");
|
|
34035
|
+
if (await import_fs_extra8.default.pathExists(agentsSource)) {
|
|
33706
34036
|
const installResult = await installCategoryToAgents(agentsSource, "agents", agentsDir, claudeDir, { migrateClaudeDirs: true, silent: true });
|
|
33707
34037
|
const summary = [
|
|
33708
34038
|
installResult.copied.length && `${installResult.copied.length} copied`,
|
|
@@ -33717,8 +34047,8 @@ async function setupCommand(params = {}) {
|
|
|
33717
34047
|
}
|
|
33718
34048
|
if (options.aiblueprintSkills) {
|
|
33719
34049
|
s.start("Setting up AIBlueprint Skills");
|
|
33720
|
-
const skillsSourcePath =
|
|
33721
|
-
if (await
|
|
34050
|
+
const skillsSourcePath = path12.join(sourceDir, "skills");
|
|
34051
|
+
if (await import_fs_extra8.default.pathExists(skillsSourcePath)) {
|
|
33722
34052
|
const installResult = await installCategoryToAgents(skillsSourcePath, "skills", agentsDir, claudeDir, { migrateClaudeDirs: true, silent: true });
|
|
33723
34053
|
const summary = [
|
|
33724
34054
|
installResult.copied.length && `${installResult.copied.length} copied`,
|
|
@@ -33738,10 +34068,21 @@ async function setupCommand(params = {}) {
|
|
|
33738
34068
|
}
|
|
33739
34069
|
if (options.installCodex) {
|
|
33740
34070
|
s.start("Setting up Codex");
|
|
33741
|
-
await
|
|
33742
|
-
const codexConfigSource =
|
|
33743
|
-
if (await
|
|
33744
|
-
|
|
34071
|
+
await import_fs_extra8.default.ensureDir(codexDir);
|
|
34072
|
+
const codexConfigSource = path12.join(sourceDir, "codex-config");
|
|
34073
|
+
if (await import_fs_extra8.default.pathExists(codexConfigSource)) {
|
|
34074
|
+
const codexConfigPath = path12.join(codexConfigSource, "config.toml");
|
|
34075
|
+
if (await import_fs_extra8.default.pathExists(codexConfigPath)) {
|
|
34076
|
+
await mergeCodexConfigFile(codexConfigPath, codexDir);
|
|
34077
|
+
}
|
|
34078
|
+
const entries = await import_fs_extra8.default.readdir(codexConfigSource);
|
|
34079
|
+
for (const entry of entries) {
|
|
34080
|
+
if (entry === "config.toml")
|
|
34081
|
+
continue;
|
|
34082
|
+
await import_fs_extra8.default.copy(path12.join(codexConfigSource, entry), path12.join(codexDir, entry), {
|
|
34083
|
+
overwrite: false
|
|
34084
|
+
});
|
|
34085
|
+
}
|
|
33745
34086
|
}
|
|
33746
34087
|
if (options.aiblueprintSkills) {
|
|
33747
34088
|
await syncCategorySymlinks("skills", agentsDir, codexDir, undefined, true);
|
|
@@ -33787,7 +34128,7 @@ async function setupCommand(params = {}) {
|
|
|
33787
34128
|
console.log(source_default.gray(`
|
|
33788
34129
|
Next steps:`));
|
|
33789
34130
|
if (options.shellShortcuts) {
|
|
33790
|
-
const platform =
|
|
34131
|
+
const platform = os10.platform();
|
|
33791
34132
|
if (platform === "win32") {
|
|
33792
34133
|
console.log(source_default.gray(" • Restart PowerShell to load the new functions"));
|
|
33793
34134
|
} else {
|
|
@@ -33813,9 +34154,9 @@ Next steps:`));
|
|
|
33813
34154
|
}
|
|
33814
34155
|
|
|
33815
34156
|
// src/commands/setup-terminal.ts
|
|
33816
|
-
var
|
|
33817
|
-
import
|
|
33818
|
-
import
|
|
34157
|
+
var import_fs_extra9 = __toESM(require_lib4(), 1);
|
|
34158
|
+
import path13 from "path";
|
|
34159
|
+
import os11 from "os";
|
|
33819
34160
|
import { execSync as execSync3, exec as exec2 } from "child_process";
|
|
33820
34161
|
var OHMYZSH_INSTALL_URL = "https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh";
|
|
33821
34162
|
var INSTALL_TIMEOUT = 120000;
|
|
@@ -33849,16 +34190,16 @@ function commandExists(cmd) {
|
|
|
33849
34190
|
}
|
|
33850
34191
|
}
|
|
33851
34192
|
function isOhMyZshInstalled(homeDir) {
|
|
33852
|
-
const ohMyZshDir =
|
|
33853
|
-
return
|
|
34193
|
+
const ohMyZshDir = path13.join(homeDir, ".oh-my-zsh");
|
|
34194
|
+
return import_fs_extra9.default.existsSync(ohMyZshDir);
|
|
33854
34195
|
}
|
|
33855
34196
|
function backupFile(filePath) {
|
|
33856
|
-
if (!
|
|
34197
|
+
if (!import_fs_extra9.default.existsSync(filePath))
|
|
33857
34198
|
return null;
|
|
33858
|
-
const
|
|
33859
|
-
const backupPath = `${filePath}.backup-${
|
|
34199
|
+
const timestamp2 = new Date().toISOString().replace(/[:.]/g, "-");
|
|
34200
|
+
const backupPath = `${filePath}.backup-${timestamp2}`;
|
|
33860
34201
|
try {
|
|
33861
|
-
|
|
34202
|
+
import_fs_extra9.default.copyFileSync(filePath, backupPath);
|
|
33862
34203
|
return backupPath;
|
|
33863
34204
|
} catch (error) {
|
|
33864
34205
|
throw new Error(`Failed to create backup: ${error.message}`);
|
|
@@ -33897,7 +34238,7 @@ function installPrerequisiteSync(packageName, installCmd) {
|
|
|
33897
34238
|
async function installOhMyZsh(homeDir) {
|
|
33898
34239
|
return new Promise((resolve, reject) => {
|
|
33899
34240
|
const installCmd = `sh -c "$(curl -fsSL ${OHMYZSH_INSTALL_URL})" "" --unattended`;
|
|
33900
|
-
const env2 = { ...process.env, HOME: homeDir, ZSH:
|
|
34241
|
+
const env2 = { ...process.env, HOME: homeDir, ZSH: path13.join(homeDir, ".oh-my-zsh") };
|
|
33901
34242
|
exec2(installCmd, { timeout: INSTALL_TIMEOUT, env: env2 }, (error, stdout, stderr) => {
|
|
33902
34243
|
if (error) {
|
|
33903
34244
|
if ("killed" in error && error.killed) {
|
|
@@ -33918,8 +34259,8 @@ async function installPlugin(pluginName, repoUrl, homeDir) {
|
|
|
33918
34259
|
if (!/^https:\/\/github\.com\/[\w-]+\/[\w-]+$/.test(repoUrl)) {
|
|
33919
34260
|
throw new Error(`Invalid repository URL: ${repoUrl}`);
|
|
33920
34261
|
}
|
|
33921
|
-
const customPluginsDir =
|
|
33922
|
-
if (
|
|
34262
|
+
const customPluginsDir = path13.join(homeDir, ".oh-my-zsh/custom/plugins", pluginName);
|
|
34263
|
+
if (import_fs_extra9.default.existsSync(customPluginsDir)) {
|
|
33923
34264
|
return;
|
|
33924
34265
|
}
|
|
33925
34266
|
return new Promise((resolve, reject) => {
|
|
@@ -33937,20 +34278,20 @@ async function installPlugin(pluginName, repoUrl, homeDir) {
|
|
|
33937
34278
|
});
|
|
33938
34279
|
}
|
|
33939
34280
|
function updateZshrcTheme(theme, homeDir) {
|
|
33940
|
-
const zshrcPath =
|
|
34281
|
+
const zshrcPath = path13.join(homeDir, ".zshrc");
|
|
33941
34282
|
const sanitizedTheme = sanitizeThemeName(theme);
|
|
33942
|
-
if (!
|
|
34283
|
+
if (!import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
33943
34284
|
throw new Error(".zshrc file not found. Please ensure Oh My ZSH is installed correctly.");
|
|
33944
34285
|
}
|
|
33945
34286
|
try {
|
|
33946
|
-
let content =
|
|
34287
|
+
let content = import_fs_extra9.default.readFileSync(zshrcPath, "utf-8");
|
|
33947
34288
|
if (content.match(/^ZSH_THEME=/m)) {
|
|
33948
34289
|
content = content.replace(/^ZSH_THEME=.*/m, `ZSH_THEME="${sanitizedTheme}"`);
|
|
33949
34290
|
} else {
|
|
33950
34291
|
content = `ZSH_THEME="${sanitizedTheme}"
|
|
33951
34292
|
${content}`;
|
|
33952
34293
|
}
|
|
33953
|
-
|
|
34294
|
+
import_fs_extra9.default.writeFileSync(zshrcPath, content);
|
|
33954
34295
|
} catch (error) {
|
|
33955
34296
|
if (error.message.includes(".zshrc file not found")) {
|
|
33956
34297
|
throw error;
|
|
@@ -33959,12 +34300,12 @@ ${content}`;
|
|
|
33959
34300
|
}
|
|
33960
34301
|
}
|
|
33961
34302
|
function updateZshrcPlugins(plugins, homeDir) {
|
|
33962
|
-
const zshrcPath =
|
|
33963
|
-
if (!
|
|
34303
|
+
const zshrcPath = path13.join(homeDir, ".zshrc");
|
|
34304
|
+
if (!import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
33964
34305
|
throw new Error(".zshrc file not found. Please ensure Oh My ZSH is installed correctly.");
|
|
33965
34306
|
}
|
|
33966
34307
|
try {
|
|
33967
|
-
let content =
|
|
34308
|
+
let content = import_fs_extra9.default.readFileSync(zshrcPath, "utf-8");
|
|
33968
34309
|
const pluginsString = plugins.join(" ");
|
|
33969
34310
|
if (content.match(/^plugins=\(/m)) {
|
|
33970
34311
|
content = content.replace(/^plugins=\([^)]*\)/m, `plugins=(${pluginsString})`);
|
|
@@ -33972,7 +34313,7 @@ function updateZshrcPlugins(plugins, homeDir) {
|
|
|
33972
34313
|
content = `${content}
|
|
33973
34314
|
plugins=(${pluginsString})`;
|
|
33974
34315
|
}
|
|
33975
|
-
|
|
34316
|
+
import_fs_extra9.default.writeFileSync(zshrcPath, content);
|
|
33976
34317
|
} catch (error) {
|
|
33977
34318
|
if (error.message.includes(".zshrc file not found")) {
|
|
33978
34319
|
throw error;
|
|
@@ -33982,7 +34323,7 @@ plugins=(${pluginsString})`;
|
|
|
33982
34323
|
}
|
|
33983
34324
|
async function setupTerminalCommand(options = {}) {
|
|
33984
34325
|
const { skipInteractive, homeDir: customHomeDir } = options;
|
|
33985
|
-
const homeDir = customHomeDir ||
|
|
34326
|
+
const homeDir = customHomeDir || os11.homedir();
|
|
33986
34327
|
try {
|
|
33987
34328
|
console.log(source_default.blue.bold(`
|
|
33988
34329
|
\uD83D\uDDA5️ AIBlueprint Terminal Setup ${source_default.gray(`v${getVersion()}`)}
|
|
@@ -34079,8 +34420,8 @@ Installing missing prerequisites: ${missingPrereqs.join(", ")}`));
|
|
|
34079
34420
|
selectedTheme = themeAnswer.theme;
|
|
34080
34421
|
}
|
|
34081
34422
|
}
|
|
34082
|
-
const zshrcPath =
|
|
34083
|
-
if (
|
|
34423
|
+
const zshrcPath = path13.join(homeDir, ".zshrc");
|
|
34424
|
+
if (import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
34084
34425
|
s.start("Backing up .zshrc");
|
|
34085
34426
|
const backupPath = backupFile(zshrcPath);
|
|
34086
34427
|
if (backupPath) {
|
|
@@ -34130,37 +34471,37 @@ Next steps:`));
|
|
|
34130
34471
|
}
|
|
34131
34472
|
|
|
34132
34473
|
// src/commands/setup/symlinks.ts
|
|
34133
|
-
var
|
|
34134
|
-
import
|
|
34135
|
-
import
|
|
34474
|
+
var import_fs_extra10 = __toESM(require_lib4(), 1);
|
|
34475
|
+
import path14 from "path";
|
|
34476
|
+
import os12 from "os";
|
|
34136
34477
|
async function getToolPaths(tool, customFolder) {
|
|
34137
34478
|
let baseDir;
|
|
34138
34479
|
switch (tool) {
|
|
34139
34480
|
case "claude-code":
|
|
34140
|
-
baseDir = customFolder ?
|
|
34481
|
+
baseDir = customFolder ? path14.resolve(customFolder) : path14.join(os12.homedir(), ".claude");
|
|
34141
34482
|
return {
|
|
34142
34483
|
baseDir,
|
|
34143
|
-
commandsPath:
|
|
34144
|
-
agentsPath:
|
|
34484
|
+
commandsPath: path14.join(baseDir, "commands"),
|
|
34485
|
+
agentsPath: path14.join(baseDir, "agents")
|
|
34145
34486
|
};
|
|
34146
34487
|
case "codex":
|
|
34147
|
-
baseDir = customFolder ?
|
|
34488
|
+
baseDir = customFolder ? path14.resolve(customFolder) : path14.join(os12.homedir(), ".codex");
|
|
34148
34489
|
return {
|
|
34149
34490
|
baseDir,
|
|
34150
|
-
agentsPath:
|
|
34491
|
+
agentsPath: path14.join(baseDir, "agents")
|
|
34151
34492
|
};
|
|
34152
34493
|
case "opencode":
|
|
34153
|
-
baseDir = customFolder ?
|
|
34494
|
+
baseDir = customFolder ? path14.resolve(customFolder) : path14.join(os12.homedir(), ".config", "opencode");
|
|
34154
34495
|
return {
|
|
34155
34496
|
baseDir,
|
|
34156
|
-
commandsPath:
|
|
34497
|
+
commandsPath: path14.join(baseDir, "command")
|
|
34157
34498
|
};
|
|
34158
34499
|
case "factoryai":
|
|
34159
|
-
baseDir = customFolder ?
|
|
34500
|
+
baseDir = customFolder ? path14.resolve(customFolder) : path14.join(os12.homedir(), ".factory");
|
|
34160
34501
|
return {
|
|
34161
34502
|
baseDir,
|
|
34162
|
-
commandsPath:
|
|
34163
|
-
agentsPath:
|
|
34503
|
+
commandsPath: path14.join(baseDir, "commands"),
|
|
34504
|
+
agentsPath: path14.join(baseDir, "droids")
|
|
34164
34505
|
};
|
|
34165
34506
|
default:
|
|
34166
34507
|
throw new Error(`Unknown tool type: ${tool}`);
|
|
@@ -34168,28 +34509,28 @@ async function getToolPaths(tool, customFolder) {
|
|
|
34168
34509
|
}
|
|
34169
34510
|
async function createSymlink(sourcePath, targetPath, options = {}) {
|
|
34170
34511
|
try {
|
|
34171
|
-
const sourceExists = await
|
|
34512
|
+
const sourceExists = await import_fs_extra10.default.pathExists(sourcePath);
|
|
34172
34513
|
if (!sourceExists) {
|
|
34173
34514
|
console.log(source_default.yellow(` Source path ${sourcePath} does not exist. Skipping symlink creation...`));
|
|
34174
34515
|
return false;
|
|
34175
34516
|
}
|
|
34176
|
-
const targetDir =
|
|
34177
|
-
await
|
|
34178
|
-
const targetExists = await
|
|
34517
|
+
const targetDir = path14.dirname(targetPath);
|
|
34518
|
+
await import_fs_extra10.default.ensureDir(targetDir);
|
|
34519
|
+
const targetExists = await import_fs_extra10.default.pathExists(targetPath);
|
|
34179
34520
|
if (targetExists) {
|
|
34180
|
-
const stat = await
|
|
34521
|
+
const stat = await import_fs_extra10.default.lstat(targetPath);
|
|
34181
34522
|
if (stat.isSymbolicLink()) {
|
|
34182
|
-
await
|
|
34523
|
+
await import_fs_extra10.default.remove(targetPath);
|
|
34183
34524
|
} else {
|
|
34184
34525
|
console.log(source_default.yellow(options.skipMessage || ` ${targetPath} already exists and is not a symlink. Skipping...`));
|
|
34185
34526
|
return false;
|
|
34186
34527
|
}
|
|
34187
34528
|
}
|
|
34188
|
-
const isWindows2 =
|
|
34529
|
+
const isWindows2 = os12.platform() === "win32";
|
|
34189
34530
|
if (isWindows2) {
|
|
34190
|
-
await
|
|
34531
|
+
await import_fs_extra10.default.symlink(sourcePath, targetPath, "junction");
|
|
34191
34532
|
} else {
|
|
34192
|
-
await
|
|
34533
|
+
await import_fs_extra10.default.symlink(sourcePath, targetPath);
|
|
34193
34534
|
}
|
|
34194
34535
|
return true;
|
|
34195
34536
|
} catch (error) {
|
|
@@ -35085,12 +35426,12 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
35085
35426
|
};
|
|
35086
35427
|
|
|
35087
35428
|
// src/commands/pro.ts
|
|
35088
|
-
import
|
|
35429
|
+
import path17 from "path";
|
|
35089
35430
|
|
|
35090
35431
|
// src/lib/pro-installer.ts
|
|
35091
|
-
var
|
|
35092
|
-
import
|
|
35093
|
-
import
|
|
35432
|
+
var import_fs_extra11 = __toESM(require_lib4(), 1);
|
|
35433
|
+
import os13 from "os";
|
|
35434
|
+
import path15 from "path";
|
|
35094
35435
|
import { exec as exec3 } from "child_process";
|
|
35095
35436
|
import { promisify as promisify2 } from "util";
|
|
35096
35437
|
var execAsync2 = promisify2(exec3);
|
|
@@ -35098,9 +35439,9 @@ var PREMIUM_REPO = "Melvynx/aiblueprint-cli-premium";
|
|
|
35098
35439
|
var PREMIUM_BRANCH = "main";
|
|
35099
35440
|
var CONFIG_FOLDER_CANDIDATES2 = ["agents-config", "ai-coding", "claude-code-config", "ai-config"];
|
|
35100
35441
|
function routePath(relativePath) {
|
|
35101
|
-
const segments = relativePath.split(
|
|
35442
|
+
const segments = relativePath.split(path15.sep);
|
|
35102
35443
|
const first = segments[0];
|
|
35103
|
-
const rest = segments.slice(1).join(
|
|
35444
|
+
const rest = segments.slice(1).join(path15.sep);
|
|
35104
35445
|
if (first === "claude-config") {
|
|
35105
35446
|
return { kind: "claude", relativePath: rest };
|
|
35106
35447
|
}
|
|
@@ -35116,7 +35457,7 @@ function routePath(relativePath) {
|
|
|
35116
35457
|
return { kind: "claude", relativePath };
|
|
35117
35458
|
}
|
|
35118
35459
|
function getCacheRepoDir() {
|
|
35119
|
-
return
|
|
35460
|
+
return path15.join(os13.homedir(), ".config", "aiblueprint", "pro-repos", "aiblueprint-cli-premium");
|
|
35120
35461
|
}
|
|
35121
35462
|
async function execGitWithAuth(command, token, repoUrl, cwd) {
|
|
35122
35463
|
const authenticatedUrl = `https://x-access-token:${token}@${repoUrl.replace(/^https?:\/\//, "")}`;
|
|
@@ -35130,21 +35471,21 @@ async function execGitWithAuth(command, token, repoUrl, cwd) {
|
|
|
35130
35471
|
async function cloneOrUpdateRepo(token) {
|
|
35131
35472
|
const cacheDir = getCacheRepoDir();
|
|
35132
35473
|
const repoUrl = `https://github.com/${PREMIUM_REPO}.git`;
|
|
35133
|
-
if (await
|
|
35474
|
+
if (await import_fs_extra11.default.pathExists(path15.join(cacheDir, ".git"))) {
|
|
35134
35475
|
try {
|
|
35135
35476
|
await execGitWithAuth("pull", token, repoUrl, cacheDir);
|
|
35136
35477
|
} catch (error) {
|
|
35137
|
-
await
|
|
35138
|
-
await
|
|
35478
|
+
await import_fs_extra11.default.remove(cacheDir);
|
|
35479
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(cacheDir));
|
|
35139
35480
|
await execGitWithAuth(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
35140
35481
|
}
|
|
35141
35482
|
} else {
|
|
35142
|
-
await
|
|
35483
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(cacheDir));
|
|
35143
35484
|
await execGitWithAuth(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
35144
35485
|
}
|
|
35145
35486
|
for (const candidate of CONFIG_FOLDER_CANDIDATES2) {
|
|
35146
|
-
const candidatePath =
|
|
35147
|
-
if (await
|
|
35487
|
+
const candidatePath = path15.join(cacheDir, candidate);
|
|
35488
|
+
if (await import_fs_extra11.default.pathExists(candidatePath)) {
|
|
35148
35489
|
return candidatePath;
|
|
35149
35490
|
}
|
|
35150
35491
|
}
|
|
@@ -35152,35 +35493,38 @@ async function cloneOrUpdateRepo(token) {
|
|
|
35152
35493
|
}
|
|
35153
35494
|
async function copyConfigFromCache(cacheConfigDir, dest, onProgress) {
|
|
35154
35495
|
const walk = async (dir, baseDir = dir) => {
|
|
35155
|
-
const entries = await
|
|
35496
|
+
const entries = await import_fs_extra11.default.readdir(dir, { withFileTypes: true });
|
|
35156
35497
|
for (const entry of entries) {
|
|
35157
35498
|
if (entry.name === ".DS_Store" || entry.name === "node_modules")
|
|
35158
35499
|
continue;
|
|
35159
|
-
const sourcePath =
|
|
35160
|
-
const relativePath =
|
|
35500
|
+
const sourcePath = path15.join(dir, entry.name);
|
|
35501
|
+
const relativePath = path15.relative(baseDir, sourcePath);
|
|
35161
35502
|
const route = routePath(relativePath);
|
|
35162
35503
|
if (route.kind === "skip")
|
|
35163
35504
|
continue;
|
|
35164
35505
|
if (route.kind === "agents-category") {
|
|
35165
|
-
if (relativePath.split(
|
|
35506
|
+
if (relativePath.split(path15.sep).length === 1) {
|
|
35166
35507
|
await copyAgentCategory(sourcePath, route.category, dest.agentsDir, dest.claudeDir, onProgress);
|
|
35167
35508
|
}
|
|
35168
35509
|
continue;
|
|
35169
35510
|
}
|
|
35170
35511
|
const targetBase = route.kind === "claude" ? dest.claudeDir : dest.codexDir;
|
|
35171
|
-
const targetPath =
|
|
35512
|
+
const targetPath = path15.join(targetBase, route.relativePath);
|
|
35172
35513
|
if (entry.isDirectory()) {
|
|
35173
|
-
await
|
|
35514
|
+
await import_fs_extra11.default.ensureDir(targetPath);
|
|
35174
35515
|
onProgress?.(relativePath, "directory");
|
|
35175
35516
|
await walk(sourcePath, baseDir);
|
|
35517
|
+
} else if (route.kind === "codex" && route.relativePath === "config.toml") {
|
|
35518
|
+
await mergeCodexConfigFile(sourcePath, dest.codexDir);
|
|
35519
|
+
onProgress?.(relativePath, "file");
|
|
35176
35520
|
} else if (isTextFile(entry.name)) {
|
|
35177
|
-
const content = await
|
|
35521
|
+
const content = await import_fs_extra11.default.readFile(sourcePath, "utf-8");
|
|
35178
35522
|
const replaced = replaceClaudePathPlaceholder(content, dest.claudeDir);
|
|
35179
|
-
await
|
|
35180
|
-
await
|
|
35523
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(targetPath));
|
|
35524
|
+
await import_fs_extra11.default.writeFile(targetPath, replaced, "utf-8");
|
|
35181
35525
|
onProgress?.(relativePath, "file");
|
|
35182
35526
|
} else {
|
|
35183
|
-
await
|
|
35527
|
+
await import_fs_extra11.default.copy(sourcePath, targetPath, { overwrite: true });
|
|
35184
35528
|
onProgress?.(relativePath, "file");
|
|
35185
35529
|
}
|
|
35186
35530
|
}
|
|
@@ -35188,21 +35532,21 @@ async function copyConfigFromCache(cacheConfigDir, dest, onProgress) {
|
|
|
35188
35532
|
await walk(cacheConfigDir);
|
|
35189
35533
|
}
|
|
35190
35534
|
async function copyAgentCategory(sourceCategoryDir, category, agentsDir, claudeDir, onProgress) {
|
|
35191
|
-
const agentsCategoryDir =
|
|
35192
|
-
await
|
|
35193
|
-
const entries = await
|
|
35535
|
+
const agentsCategoryDir = path15.join(agentsDir, category);
|
|
35536
|
+
await import_fs_extra11.default.ensureDir(agentsCategoryDir);
|
|
35537
|
+
const entries = await import_fs_extra11.default.readdir(sourceCategoryDir, { withFileTypes: true });
|
|
35194
35538
|
for (const entry of entries) {
|
|
35195
35539
|
if (entry.name === ".DS_Store")
|
|
35196
35540
|
continue;
|
|
35197
|
-
const src =
|
|
35198
|
-
const dst =
|
|
35199
|
-
const claudeTop =
|
|
35200
|
-
const claudeStat = await
|
|
35541
|
+
const src = path15.join(sourceCategoryDir, entry.name);
|
|
35542
|
+
const dst = path15.join(agentsCategoryDir, entry.name);
|
|
35543
|
+
const claudeTop = path15.join(claudeDir, category, entry.name);
|
|
35544
|
+
const claudeStat = await import_fs_extra11.default.lstat(claudeTop).catch(() => null);
|
|
35201
35545
|
if (claudeStat && !claudeStat.isSymbolicLink()) {
|
|
35202
35546
|
onProgress?.(`${category}/${entry.name} (skipped - real dir in claude)`, "file");
|
|
35203
35547
|
continue;
|
|
35204
35548
|
}
|
|
35205
|
-
await
|
|
35549
|
+
await import_fs_extra11.default.copy(src, dst, { overwrite: true });
|
|
35206
35550
|
await applyPathPlaceholders(dst, claudeDir);
|
|
35207
35551
|
onProgress?.(`${category}/${entry.name}`, entry.isDirectory() ? "directory" : "file");
|
|
35208
35552
|
}
|
|
@@ -35221,8 +35565,8 @@ async function downloadFromPrivateGitHub(repo, branch, relativePath, targetPath,
|
|
|
35221
35565
|
return false;
|
|
35222
35566
|
}
|
|
35223
35567
|
const content = await response.arrayBuffer();
|
|
35224
|
-
await
|
|
35225
|
-
await
|
|
35568
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(targetPath));
|
|
35569
|
+
await import_fs_extra11.default.writeFile(targetPath, Buffer.from(content));
|
|
35226
35570
|
return true;
|
|
35227
35571
|
} catch (error) {
|
|
35228
35572
|
console.error(`Error downloading ${relativePath}:`, error);
|
|
@@ -35247,10 +35591,10 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
|
|
|
35247
35591
|
console.error(`Unexpected response for directory ${dirPath}`);
|
|
35248
35592
|
return false;
|
|
35249
35593
|
}
|
|
35250
|
-
await
|
|
35594
|
+
await import_fs_extra11.default.ensureDir(targetDir);
|
|
35251
35595
|
for (const file of files) {
|
|
35252
35596
|
const relativePath = dirPath ? `${dirPath}/${file.name}` : file.name;
|
|
35253
|
-
const targetPath =
|
|
35597
|
+
const targetPath = path15.join(targetDir, file.name);
|
|
35254
35598
|
const displayPath = relativePath.replace(/^(agents-config|ai-coding|claude-code-config|ai-config)\//, "");
|
|
35255
35599
|
if (file.type === "file") {
|
|
35256
35600
|
onProgress?.(displayPath, "file");
|
|
@@ -35273,8 +35617,8 @@ async function installProConfigs(options) {
|
|
|
35273
35617
|
codexFolder,
|
|
35274
35618
|
agentsFolder
|
|
35275
35619
|
});
|
|
35276
|
-
await
|
|
35277
|
-
await
|
|
35620
|
+
await import_fs_extra11.default.ensureDir(claudeDir);
|
|
35621
|
+
await import_fs_extra11.default.ensureDir(agentsDir);
|
|
35278
35622
|
const dest = { claudeDir, codexDir, agentsDir };
|
|
35279
35623
|
try {
|
|
35280
35624
|
const cacheConfigDir = await cloneOrUpdateRepo(githubToken);
|
|
@@ -35284,7 +35628,7 @@ async function installProConfigs(options) {
|
|
|
35284
35628
|
} catch (error) {
|
|
35285
35629
|
console.warn("Git caching failed, falling back to API download");
|
|
35286
35630
|
}
|
|
35287
|
-
const tempDir =
|
|
35631
|
+
const tempDir = path15.join(os13.tmpdir(), `aiblueprint-premium-${Date.now()}`);
|
|
35288
35632
|
try {
|
|
35289
35633
|
let success = false;
|
|
35290
35634
|
for (const candidate of CONFIG_FOLDER_CANDIDATES2) {
|
|
@@ -35298,8 +35642,8 @@ async function installProConfigs(options) {
|
|
|
35298
35642
|
await copyConfigFromCache(tempDir, dest, onProgress);
|
|
35299
35643
|
await replacePathPlaceholdersInDir(claudeDir, claudeDir);
|
|
35300
35644
|
for (const category of AGENT_CATEGORIES) {
|
|
35301
|
-
const agentsCategoryDir =
|
|
35302
|
-
if (await
|
|
35645
|
+
const agentsCategoryDir = path15.join(agentsDir, category);
|
|
35646
|
+
if (await import_fs_extra11.default.pathExists(agentsCategoryDir)) {
|
|
35303
35647
|
await replacePathPlaceholdersInDir(agentsCategoryDir, claudeDir);
|
|
35304
35648
|
}
|
|
35305
35649
|
}
|
|
@@ -35308,7 +35652,7 @@ async function installProConfigs(options) {
|
|
|
35308
35652
|
throw new Error(`Failed to install premium configs: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
35309
35653
|
} finally {
|
|
35310
35654
|
try {
|
|
35311
|
-
await
|
|
35655
|
+
await import_fs_extra11.default.remove(tempDir);
|
|
35312
35656
|
} catch {}
|
|
35313
35657
|
}
|
|
35314
35658
|
}
|
|
@@ -35319,27 +35663,27 @@ async function syncAllAgentSymlinks(agentsDir, claudeDir) {
|
|
|
35319
35663
|
}
|
|
35320
35664
|
|
|
35321
35665
|
// src/lib/token-storage.ts
|
|
35322
|
-
var
|
|
35323
|
-
import
|
|
35324
|
-
import
|
|
35666
|
+
var import_fs_extra12 = __toESM(require_lib4(), 1);
|
|
35667
|
+
import os14 from "os";
|
|
35668
|
+
import path16 from "path";
|
|
35325
35669
|
function getConfigDir() {
|
|
35326
|
-
const platform =
|
|
35670
|
+
const platform = os14.platform();
|
|
35327
35671
|
if (platform === "win32") {
|
|
35328
|
-
const appData = process.env.APPDATA ||
|
|
35329
|
-
return
|
|
35672
|
+
const appData = process.env.APPDATA || path16.join(os14.homedir(), "AppData", "Roaming");
|
|
35673
|
+
return path16.join(appData, "aiblueprint");
|
|
35330
35674
|
} else {
|
|
35331
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
35332
|
-
return
|
|
35675
|
+
const configHome = process.env.XDG_CONFIG_HOME || path16.join(os14.homedir(), ".config");
|
|
35676
|
+
return path16.join(configHome, "aiblueprint");
|
|
35333
35677
|
}
|
|
35334
35678
|
}
|
|
35335
35679
|
function getTokenFilePath2() {
|
|
35336
|
-
return
|
|
35680
|
+
return path16.join(getConfigDir(), "token.txt");
|
|
35337
35681
|
}
|
|
35338
35682
|
async function saveToken(githubToken) {
|
|
35339
35683
|
const tokenFile = getTokenFilePath2();
|
|
35340
|
-
const configDir =
|
|
35684
|
+
const configDir = path16.dirname(tokenFile);
|
|
35341
35685
|
try {
|
|
35342
|
-
await
|
|
35686
|
+
await import_fs_extra12.default.ensureDir(configDir);
|
|
35343
35687
|
} catch (error) {
|
|
35344
35688
|
if (error.code === "EACCES") {
|
|
35345
35689
|
throw new Error(`Permission denied creating config directory: ${configDir}
|
|
@@ -35347,15 +35691,15 @@ async function saveToken(githubToken) {
|
|
|
35347
35691
|
}
|
|
35348
35692
|
throw error;
|
|
35349
35693
|
}
|
|
35350
|
-
await
|
|
35694
|
+
await import_fs_extra12.default.writeFile(tokenFile, githubToken, { mode: 384 });
|
|
35351
35695
|
}
|
|
35352
35696
|
async function getToken() {
|
|
35353
35697
|
const tokenFile = getTokenFilePath2();
|
|
35354
|
-
if (!await
|
|
35698
|
+
if (!await import_fs_extra12.default.pathExists(tokenFile)) {
|
|
35355
35699
|
return null;
|
|
35356
35700
|
}
|
|
35357
35701
|
try {
|
|
35358
|
-
const token = await
|
|
35702
|
+
const token = await import_fs_extra12.default.readFile(tokenFile, "utf-8");
|
|
35359
35703
|
return token.trim();
|
|
35360
35704
|
} catch (error) {
|
|
35361
35705
|
return null;
|
|
@@ -35364,12 +35708,12 @@ async function getToken() {
|
|
|
35364
35708
|
function getTokenInfo() {
|
|
35365
35709
|
return {
|
|
35366
35710
|
path: getTokenFilePath2(),
|
|
35367
|
-
platform:
|
|
35711
|
+
platform: os14.platform()
|
|
35368
35712
|
};
|
|
35369
35713
|
}
|
|
35370
35714
|
|
|
35371
35715
|
// src/commands/pro.ts
|
|
35372
|
-
var
|
|
35716
|
+
var import_fs_extra13 = __toESM(require_lib4(), 1);
|
|
35373
35717
|
var API_URL = "https://codeline.app/api/products";
|
|
35374
35718
|
var PRODUCT_IDS = ["prd_XJVgxVPbGG", "prd_NKabAkdOkw"];
|
|
35375
35719
|
async function countInstalledItems(claudeDir) {
|
|
@@ -35378,20 +35722,20 @@ async function countInstalledItems(claudeDir) {
|
|
|
35378
35722
|
skills: 0
|
|
35379
35723
|
};
|
|
35380
35724
|
try {
|
|
35381
|
-
const agentsDir =
|
|
35382
|
-
if (await
|
|
35383
|
-
const files = await
|
|
35725
|
+
const agentsDir = path17.join(claudeDir, "agents");
|
|
35726
|
+
if (await import_fs_extra13.default.pathExists(agentsDir)) {
|
|
35727
|
+
const files = await import_fs_extra13.default.readdir(agentsDir);
|
|
35384
35728
|
counts.agents = files.filter((f) => f.endsWith(".md")).length;
|
|
35385
35729
|
}
|
|
35386
35730
|
} catch (error) {
|
|
35387
35731
|
console.error("Failed to count agents:", error instanceof Error ? error.message : error);
|
|
35388
35732
|
}
|
|
35389
35733
|
try {
|
|
35390
|
-
const skillsDir =
|
|
35391
|
-
if (await
|
|
35392
|
-
const items = await
|
|
35734
|
+
const skillsDir = path17.join(claudeDir, "skills");
|
|
35735
|
+
if (await import_fs_extra13.default.pathExists(skillsDir)) {
|
|
35736
|
+
const items = await import_fs_extra13.default.readdir(skillsDir);
|
|
35393
35737
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
35394
|
-
const stat = await
|
|
35738
|
+
const stat = await import_fs_extra13.default.stat(path17.join(skillsDir, item));
|
|
35395
35739
|
return stat.isDirectory();
|
|
35396
35740
|
}));
|
|
35397
35741
|
counts.skills = dirs.filter(Boolean).length;
|
|
@@ -35599,8 +35943,8 @@ async function proUpdateCommand(options = {}) {
|
|
|
35599
35943
|
}
|
|
35600
35944
|
|
|
35601
35945
|
// src/lib/sync-utils.ts
|
|
35602
|
-
var
|
|
35603
|
-
import
|
|
35946
|
+
var import_fs_extra14 = __toESM(require_lib4(), 1);
|
|
35947
|
+
import path18 from "path";
|
|
35604
35948
|
import crypto from "crypto";
|
|
35605
35949
|
var PREMIUM_REPO2 = "Melvynx/aiblueprint-cli-premium";
|
|
35606
35950
|
var PREMIUM_BRANCH2 = "main";
|
|
@@ -35671,7 +36015,7 @@ async function listRemoteFilesRecursive(dirPath, githubToken, basePath = "") {
|
|
|
35671
36015
|
}
|
|
35672
36016
|
async function computeLocalFileSha(filePath) {
|
|
35673
36017
|
try {
|
|
35674
|
-
const content = await
|
|
36018
|
+
const content = await import_fs_extra14.default.readFile(filePath);
|
|
35675
36019
|
return computeFileSha(content);
|
|
35676
36020
|
} catch {
|
|
35677
36021
|
return null;
|
|
@@ -35679,15 +36023,15 @@ async function computeLocalFileSha(filePath) {
|
|
|
35679
36023
|
}
|
|
35680
36024
|
async function listLocalFiles(dir) {
|
|
35681
36025
|
const files = [];
|
|
35682
|
-
if (!await
|
|
36026
|
+
if (!await import_fs_extra14.default.pathExists(dir)) {
|
|
35683
36027
|
return files;
|
|
35684
36028
|
}
|
|
35685
|
-
const items = await
|
|
36029
|
+
const items = await import_fs_extra14.default.readdir(dir);
|
|
35686
36030
|
for (const item of items) {
|
|
35687
36031
|
if (item === "node_modules" || item === ".DS_Store")
|
|
35688
36032
|
continue;
|
|
35689
|
-
const fullPath =
|
|
35690
|
-
const stat = await
|
|
36033
|
+
const fullPath = path18.join(dir, item);
|
|
36034
|
+
const stat = await import_fs_extra14.default.stat(fullPath).catch(() => null);
|
|
35691
36035
|
if (!stat)
|
|
35692
36036
|
continue;
|
|
35693
36037
|
if (stat.isDirectory()) {
|
|
@@ -35702,13 +36046,13 @@ async function listLocalFiles(dir) {
|
|
|
35702
36046
|
}
|
|
35703
36047
|
async function listLocalFilesRecursive(dir, basePath) {
|
|
35704
36048
|
const files = [];
|
|
35705
|
-
const items = await
|
|
36049
|
+
const items = await import_fs_extra14.default.readdir(dir).catch(() => []);
|
|
35706
36050
|
for (const item of items) {
|
|
35707
36051
|
if (item === "node_modules" || item === ".DS_Store")
|
|
35708
36052
|
continue;
|
|
35709
|
-
const fullPath =
|
|
36053
|
+
const fullPath = path18.join(dir, item);
|
|
35710
36054
|
const relativePath = `${basePath}/${item}`;
|
|
35711
|
-
const stat = await
|
|
36055
|
+
const stat = await import_fs_extra14.default.stat(fullPath).catch(() => null);
|
|
35712
36056
|
if (!stat)
|
|
35713
36057
|
continue;
|
|
35714
36058
|
if (stat.isDirectory()) {
|
|
@@ -35722,14 +36066,14 @@ async function listLocalFilesRecursive(dir, basePath) {
|
|
|
35722
36066
|
return files;
|
|
35723
36067
|
}
|
|
35724
36068
|
async function listClaudeRealTopLevel(claudeCategoryDir) {
|
|
35725
|
-
if (!await
|
|
36069
|
+
if (!await import_fs_extra14.default.pathExists(claudeCategoryDir))
|
|
35726
36070
|
return [];
|
|
35727
|
-
const entries = await
|
|
36071
|
+
const entries = await import_fs_extra14.default.readdir(claudeCategoryDir).catch(() => []);
|
|
35728
36072
|
const real = [];
|
|
35729
36073
|
for (const name of entries) {
|
|
35730
36074
|
if (name === "node_modules" || name === ".DS_Store")
|
|
35731
36075
|
continue;
|
|
35732
|
-
const stat = await
|
|
36076
|
+
const stat = await import_fs_extra14.default.lstat(path18.join(claudeCategoryDir, name)).catch(() => null);
|
|
35733
36077
|
if (!stat)
|
|
35734
36078
|
continue;
|
|
35735
36079
|
if (stat.isDirectory())
|
|
@@ -35746,7 +36090,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
35746
36090
|
const items = [];
|
|
35747
36091
|
const useAgents = isAgentCategory(category);
|
|
35748
36092
|
const localBase = useAgents ? agentsDir : claudeDir;
|
|
35749
|
-
const localDir =
|
|
36093
|
+
const localDir = path18.join(localBase, category);
|
|
35750
36094
|
const remoteCategoryPath = getRemoteCategoryPath(category);
|
|
35751
36095
|
const remoteFiles = await listRemoteFilesRecursive(remoteCategoryPath, githubToken);
|
|
35752
36096
|
const localFiles = await listLocalFiles(localDir);
|
|
@@ -35760,7 +36104,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
35760
36104
|
}
|
|
35761
36105
|
const localSet = new Set(localFiles);
|
|
35762
36106
|
for (const [remotePath, { sha, isFolder }] of remoteSet) {
|
|
35763
|
-
const localPath =
|
|
36107
|
+
const localPath = path18.join(localDir, remotePath);
|
|
35764
36108
|
if (isFolder) {
|
|
35765
36109
|
continue;
|
|
35766
36110
|
}
|
|
@@ -35795,7 +36139,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
35795
36139
|
for (const localPath of localSet) {
|
|
35796
36140
|
agentsTopLevels.add(localPath.split("/")[0]);
|
|
35797
36141
|
}
|
|
35798
|
-
const claudeCategoryDir =
|
|
36142
|
+
const claudeCategoryDir = path18.join(claudeDir, category);
|
|
35799
36143
|
const claudeRealEntries = await listClaudeRealTopLevel(claudeCategoryDir);
|
|
35800
36144
|
for (const top of claudeRealEntries) {
|
|
35801
36145
|
if (!remoteTopLevels.has(top))
|
|
@@ -35854,13 +36198,13 @@ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken,
|
|
|
35854
36198
|
return false;
|
|
35855
36199
|
}
|
|
35856
36200
|
const content = await response.arrayBuffer();
|
|
35857
|
-
await
|
|
36201
|
+
await import_fs_extra14.default.ensureDir(path18.dirname(targetPath));
|
|
35858
36202
|
if (isTextFile(relativePath)) {
|
|
35859
36203
|
const textContent = Buffer.from(content).toString("utf-8");
|
|
35860
36204
|
const transformedContent = transformFileContent(textContent, claudeDir);
|
|
35861
|
-
await
|
|
36205
|
+
await import_fs_extra14.default.writeFile(targetPath, transformedContent, "utf-8");
|
|
35862
36206
|
} else {
|
|
35863
|
-
await
|
|
36207
|
+
await import_fs_extra14.default.writeFile(targetPath, Buffer.from(content));
|
|
35864
36208
|
}
|
|
35865
36209
|
return true;
|
|
35866
36210
|
} catch {
|
|
@@ -35876,27 +36220,27 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
35876
36220
|
for (const item of items) {
|
|
35877
36221
|
const useAgents = isAgentCategory(item.category);
|
|
35878
36222
|
const baseDir = useAgents ? agentsDir : claudeDir;
|
|
35879
|
-
const targetPath =
|
|
36223
|
+
const targetPath = path18.join(baseDir, item.relativePath);
|
|
35880
36224
|
if (item.status === "migration" && useAgents) {
|
|
35881
36225
|
const topName = item.name.split("/")[0];
|
|
35882
|
-
const agentsTop =
|
|
35883
|
-
const claudeTop =
|
|
36226
|
+
const agentsTop = path18.join(agentsDir, item.category, topName);
|
|
36227
|
+
const claudeTop = path18.join(claudeDir, item.category, topName);
|
|
35884
36228
|
try {
|
|
35885
|
-
const claudeStat = await
|
|
36229
|
+
const claudeStat = await import_fs_extra14.default.lstat(claudeTop).catch(() => null);
|
|
35886
36230
|
if (!claudeStat || claudeStat.isSymbolicLink()) {
|
|
35887
36231
|
onProgress?.(item.relativePath, "skipping (no real dir to migrate)");
|
|
35888
36232
|
failed++;
|
|
35889
36233
|
continue;
|
|
35890
36234
|
}
|
|
35891
|
-
const agentsExists = await
|
|
36235
|
+
const agentsExists = await import_fs_extra14.default.pathExists(agentsTop);
|
|
35892
36236
|
if (agentsExists) {
|
|
35893
36237
|
onProgress?.(item.relativePath, "skipping (already in .agents)");
|
|
35894
36238
|
failed++;
|
|
35895
36239
|
continue;
|
|
35896
36240
|
}
|
|
35897
36241
|
onProgress?.(item.relativePath, "moving to .agents");
|
|
35898
|
-
await
|
|
35899
|
-
await
|
|
36242
|
+
await import_fs_extra14.default.ensureDir(path18.dirname(agentsTop));
|
|
36243
|
+
await import_fs_extra14.default.move(claudeTop, agentsTop);
|
|
35900
36244
|
migrated++;
|
|
35901
36245
|
touchedAgentCategories.add(item.category);
|
|
35902
36246
|
} catch {
|
|
@@ -35906,8 +36250,8 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
35906
36250
|
}
|
|
35907
36251
|
if (useAgents) {
|
|
35908
36252
|
const topName = item.name.split("/")[0];
|
|
35909
|
-
const claudeTop =
|
|
35910
|
-
const claudeTopStat = await
|
|
36253
|
+
const claudeTop = path18.join(claudeDir, item.category, topName);
|
|
36254
|
+
const claudeTopStat = await import_fs_extra14.default.lstat(claudeTop).catch(() => null);
|
|
35911
36255
|
if (claudeTopStat && !claudeTopStat.isSymbolicLink()) {
|
|
35912
36256
|
onProgress?.(item.relativePath, "skipping (real dir in .claude)");
|
|
35913
36257
|
failed++;
|
|
@@ -35917,7 +36261,7 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
35917
36261
|
if (item.status === "deleted") {
|
|
35918
36262
|
onProgress?.(item.relativePath, "deleting");
|
|
35919
36263
|
try {
|
|
35920
|
-
await
|
|
36264
|
+
await import_fs_extra14.default.remove(targetPath);
|
|
35921
36265
|
deleted++;
|
|
35922
36266
|
if (useAgents)
|
|
35923
36267
|
touchedAgentCategories.add(item.category);
|
|
@@ -36198,7 +36542,7 @@ async function proSyncCommand(options = {}) {
|
|
|
36198
36542
|
M2.message(source_default.yellow(` ✓ Update ${toUpdate} file${toUpdate > 1 ? "s" : ""}`));
|
|
36199
36543
|
if (toMigrate > 0)
|
|
36200
36544
|
M2.message(source_default.blue(` ✓ Move ${toMigrate} skill${toMigrate > 1 ? "s" : ""} from .claude to .agents`));
|
|
36201
|
-
M2.message(source_default.gray(` ✓ Backup current config to ~/.
|
|
36545
|
+
M2.message(source_default.gray(` ✓ Backup current config to ~/.aiblueprint/backups/`));
|
|
36202
36546
|
M2.message("");
|
|
36203
36547
|
const confirmResult = await ye({
|
|
36204
36548
|
message: "Proceed with sync?",
|
|
@@ -36209,7 +36553,7 @@ async function proSyncCommand(options = {}) {
|
|
|
36209
36553
|
process.exit(0);
|
|
36210
36554
|
}
|
|
36211
36555
|
spinner.start("Creating backup...");
|
|
36212
|
-
const backupPath = await
|
|
36556
|
+
const backupPath = await createConfigBackup(options, "Before syncing premium aiblueprint configuration", "sync", "aiblueprint-sync");
|
|
36213
36557
|
if (backupPath) {
|
|
36214
36558
|
spinner.stop(`Backup created: ${source_default.gray(backupPath)}`);
|
|
36215
36559
|
} else {
|
|
@@ -36254,6 +36598,106 @@ async function proSyncCommand(options = {}) {
|
|
|
36254
36598
|
}
|
|
36255
36599
|
}
|
|
36256
36600
|
|
|
36601
|
+
// src/lib/backup-utils.ts
|
|
36602
|
+
var import_fs_extra15 = __toESM(require_lib4(), 1);
|
|
36603
|
+
import path19 from "path";
|
|
36604
|
+
import os15 from "os";
|
|
36605
|
+
var BACKUP_BASE_DIR = path19.join(os15.homedir(), ".config", "aiblueprint", "backup");
|
|
36606
|
+
function formatDate(date) {
|
|
36607
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
36608
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
|
|
36609
|
+
}
|
|
36610
|
+
async function listBackups() {
|
|
36611
|
+
const exists = await import_fs_extra15.default.pathExists(BACKUP_BASE_DIR);
|
|
36612
|
+
if (!exists) {
|
|
36613
|
+
return [];
|
|
36614
|
+
}
|
|
36615
|
+
const entries = await import_fs_extra15.default.readdir(BACKUP_BASE_DIR, { withFileTypes: true });
|
|
36616
|
+
const backups = [];
|
|
36617
|
+
for (const entry of entries) {
|
|
36618
|
+
if (!entry.isDirectory())
|
|
36619
|
+
continue;
|
|
36620
|
+
const match = entry.name.match(/^(\d{4})-(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})$/);
|
|
36621
|
+
if (!match)
|
|
36622
|
+
continue;
|
|
36623
|
+
const [, year, month, day, hour, minute, second] = match;
|
|
36624
|
+
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
|
|
36625
|
+
backups.push({
|
|
36626
|
+
name: entry.name,
|
|
36627
|
+
path: path19.join(BACKUP_BASE_DIR, entry.name),
|
|
36628
|
+
date
|
|
36629
|
+
});
|
|
36630
|
+
}
|
|
36631
|
+
return backups.sort((a, b3) => b3.date.getTime() - a.date.getTime());
|
|
36632
|
+
}
|
|
36633
|
+
var AGENTS_BACKUP_SUBDIR = ".agents";
|
|
36634
|
+
var CLAUDE_ITEMS = ["commands", "agents", "skills", "scripts", "settings.json"];
|
|
36635
|
+
async function copyForBackup(sourcePath, destPath) {
|
|
36636
|
+
await import_fs_extra15.default.copy(sourcePath, destPath, {
|
|
36637
|
+
overwrite: true,
|
|
36638
|
+
dereference: false,
|
|
36639
|
+
filter: async (src) => {
|
|
36640
|
+
try {
|
|
36641
|
+
const stat = await import_fs_extra15.default.lstat(src);
|
|
36642
|
+
return !stat.isSymbolicLink();
|
|
36643
|
+
} catch {
|
|
36644
|
+
return true;
|
|
36645
|
+
}
|
|
36646
|
+
}
|
|
36647
|
+
});
|
|
36648
|
+
}
|
|
36649
|
+
async function hasMeaningfulContent(dir) {
|
|
36650
|
+
if (!await import_fs_extra15.default.pathExists(dir))
|
|
36651
|
+
return false;
|
|
36652
|
+
const files = await import_fs_extra15.default.readdir(dir);
|
|
36653
|
+
return files.some((f) => f !== ".DS_Store");
|
|
36654
|
+
}
|
|
36655
|
+
async function loadBackup(backupPath, claudeDir, agentsDir) {
|
|
36656
|
+
const exists = await import_fs_extra15.default.pathExists(backupPath);
|
|
36657
|
+
if (!exists) {
|
|
36658
|
+
throw new Error(`Backup not found: ${backupPath}`);
|
|
36659
|
+
}
|
|
36660
|
+
await import_fs_extra15.default.ensureDir(claudeDir);
|
|
36661
|
+
for (const item of CLAUDE_ITEMS) {
|
|
36662
|
+
const sourcePath = path19.join(backupPath, item);
|
|
36663
|
+
const destPath = path19.join(claudeDir, item);
|
|
36664
|
+
if (await import_fs_extra15.default.pathExists(sourcePath)) {
|
|
36665
|
+
await copyForBackup(sourcePath, destPath);
|
|
36666
|
+
}
|
|
36667
|
+
}
|
|
36668
|
+
if (agentsDir) {
|
|
36669
|
+
const agentsBackupPath = path19.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
36670
|
+
if (await import_fs_extra15.default.pathExists(agentsBackupPath)) {
|
|
36671
|
+
await import_fs_extra15.default.ensureDir(agentsDir);
|
|
36672
|
+
await copyForBackup(agentsBackupPath, agentsDir);
|
|
36673
|
+
}
|
|
36674
|
+
}
|
|
36675
|
+
}
|
|
36676
|
+
async function createBackup(claudeDir, agentsDir) {
|
|
36677
|
+
const claudeHasContent = await hasMeaningfulContent(claudeDir);
|
|
36678
|
+
const agentsHasContent = agentsDir ? await hasMeaningfulContent(agentsDir) : false;
|
|
36679
|
+
if (!claudeHasContent && !agentsHasContent) {
|
|
36680
|
+
return null;
|
|
36681
|
+
}
|
|
36682
|
+
const timestamp2 = formatDate(new Date);
|
|
36683
|
+
const backupPath = path19.join(BACKUP_BASE_DIR, timestamp2);
|
|
36684
|
+
await import_fs_extra15.default.ensureDir(backupPath);
|
|
36685
|
+
if (claudeHasContent) {
|
|
36686
|
+
for (const item of CLAUDE_ITEMS) {
|
|
36687
|
+
const sourcePath = path19.join(claudeDir, item);
|
|
36688
|
+
const destPath = path19.join(backupPath, item);
|
|
36689
|
+
if (await import_fs_extra15.default.pathExists(sourcePath)) {
|
|
36690
|
+
await copyForBackup(sourcePath, destPath);
|
|
36691
|
+
}
|
|
36692
|
+
}
|
|
36693
|
+
}
|
|
36694
|
+
if (agentsHasContent && agentsDir) {
|
|
36695
|
+
const destPath = path19.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
36696
|
+
await copyForBackup(agentsDir, destPath);
|
|
36697
|
+
}
|
|
36698
|
+
return backupPath;
|
|
36699
|
+
}
|
|
36700
|
+
|
|
36257
36701
|
// src/commands/backup.ts
|
|
36258
36702
|
function formatBackupDate(date) {
|
|
36259
36703
|
const now = new Date;
|
|
@@ -36329,20 +36773,121 @@ async function backupLoadCommand(options = {}) {
|
|
|
36329
36773
|
}
|
|
36330
36774
|
}
|
|
36331
36775
|
|
|
36776
|
+
// src/commands/configs.ts
|
|
36777
|
+
function formatDate2(iso) {
|
|
36778
|
+
const date = new Date(iso);
|
|
36779
|
+
if (Number.isNaN(date.getTime()))
|
|
36780
|
+
return "unknown date";
|
|
36781
|
+
return date.toLocaleString();
|
|
36782
|
+
}
|
|
36783
|
+
function formatFolders(folders) {
|
|
36784
|
+
return folders.length > 0 ? folders.join(", ") : "unknown folders";
|
|
36785
|
+
}
|
|
36786
|
+
function printSnapshots(title, snapshots) {
|
|
36787
|
+
console.log(source_default.blue(title));
|
|
36788
|
+
if (snapshots.length === 0) {
|
|
36789
|
+
console.log(source_default.gray("No entries found."));
|
|
36790
|
+
return;
|
|
36791
|
+
}
|
|
36792
|
+
for (const snapshot of snapshots) {
|
|
36793
|
+
console.log(`${source_default.cyan(snapshot.name)} ${source_default.gray(formatDate2(snapshot.metadata.createdAt))}`);
|
|
36794
|
+
console.log(source_default.gray(` reason: ${snapshot.metadata.reason}`));
|
|
36795
|
+
console.log(source_default.gray(` trigger: ${snapshot.metadata.trigger}`));
|
|
36796
|
+
console.log(source_default.gray(` folders: ${formatFolders(snapshot.metadata.folders)}`));
|
|
36797
|
+
console.log(source_default.gray(` path: ${snapshot.path}`));
|
|
36798
|
+
}
|
|
36799
|
+
}
|
|
36800
|
+
async function configsSaveCommand(name, options = {}) {
|
|
36801
|
+
try {
|
|
36802
|
+
console.log(source_default.gray("Saving .claude, .codex, and .agents config files..."));
|
|
36803
|
+
const snapshotPath = await saveNamedConfig(name, options);
|
|
36804
|
+
console.log(source_default.green(`Saved config "${name}"`));
|
|
36805
|
+
console.log(source_default.gray(snapshotPath));
|
|
36806
|
+
} catch (error) {
|
|
36807
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36808
|
+
process.exit(1);
|
|
36809
|
+
}
|
|
36810
|
+
}
|
|
36811
|
+
async function configsLoadCommand(name, options = {}) {
|
|
36812
|
+
try {
|
|
36813
|
+
console.log(source_default.gray(`Loading config "${name}"...`));
|
|
36814
|
+
const result = await loadNamedConfig(name, options);
|
|
36815
|
+
console.log(source_default.green(`Loaded config "${name}"`));
|
|
36816
|
+
if (result.backupPath) {
|
|
36817
|
+
console.log(source_default.gray(`Previous config backed up to ${result.backupPath}`));
|
|
36818
|
+
}
|
|
36819
|
+
console.log(source_default.gray(`Restored: ${formatFolders(result.restored)}`));
|
|
36820
|
+
} catch (error) {
|
|
36821
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36822
|
+
process.exit(1);
|
|
36823
|
+
}
|
|
36824
|
+
}
|
|
36825
|
+
async function configsUndoCommand(options = {}) {
|
|
36826
|
+
try {
|
|
36827
|
+
console.log(source_default.gray("Restoring the previous config backup..."));
|
|
36828
|
+
const result = await undoLastLoad(options);
|
|
36829
|
+
console.log(source_default.green(`Undid last config load using backup "${result.backupName}"`));
|
|
36830
|
+
if (result.backupPath) {
|
|
36831
|
+
console.log(source_default.gray(`Current config backed up to ${result.backupPath}`));
|
|
36832
|
+
}
|
|
36833
|
+
console.log(source_default.gray(`Restored: ${formatFolders(result.restored)}`));
|
|
36834
|
+
} catch (error) {
|
|
36835
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36836
|
+
process.exit(1);
|
|
36837
|
+
}
|
|
36838
|
+
}
|
|
36839
|
+
async function configsListCommand(options = {}) {
|
|
36840
|
+
const configs = await listSavedConfigs(options);
|
|
36841
|
+
printSnapshots("Saved configs", configs);
|
|
36842
|
+
}
|
|
36843
|
+
async function configsBackupsListCommand(options = {}) {
|
|
36844
|
+
const backups = await listConfigBackups(options);
|
|
36845
|
+
printSnapshots("Config backups", backups);
|
|
36846
|
+
}
|
|
36847
|
+
async function configsBackupsLoadCommand(name, options = {}) {
|
|
36848
|
+
try {
|
|
36849
|
+
console.log(source_default.gray(`Loading backup "${name}"...`));
|
|
36850
|
+
const result = await loadBackupSnapshot(name, options);
|
|
36851
|
+
console.log(source_default.green(`Loaded backup "${name}"`));
|
|
36852
|
+
if (result.backupPath) {
|
|
36853
|
+
console.log(source_default.gray(`Previous config backed up to ${result.backupPath}`));
|
|
36854
|
+
}
|
|
36855
|
+
console.log(source_default.gray(`Restored: ${formatFolders(result.restored)}`));
|
|
36856
|
+
} catch (error) {
|
|
36857
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36858
|
+
process.exit(1);
|
|
36859
|
+
}
|
|
36860
|
+
}
|
|
36861
|
+
async function configsBackupsCreateCommand(reason, options = {}) {
|
|
36862
|
+
try {
|
|
36863
|
+
console.log(source_default.gray("Creating config backup..."));
|
|
36864
|
+
const backupPath = await createConfigBackup(options, reason ?? "Manual backup from configs backups create", "manual-backup", "manual");
|
|
36865
|
+
if (!backupPath) {
|
|
36866
|
+
console.log(source_default.gray("No .claude, .codex, or .agents configuration found to backup."));
|
|
36867
|
+
return;
|
|
36868
|
+
}
|
|
36869
|
+
console.log(source_default.green("Backup created"));
|
|
36870
|
+
console.log(source_default.gray(backupPath));
|
|
36871
|
+
} catch (error) {
|
|
36872
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36873
|
+
process.exit(1);
|
|
36874
|
+
}
|
|
36875
|
+
}
|
|
36876
|
+
|
|
36332
36877
|
// src/commands/openclaw-pro.ts
|
|
36333
36878
|
import os18 from "os";
|
|
36334
|
-
import
|
|
36879
|
+
import path22 from "path";
|
|
36335
36880
|
|
|
36336
36881
|
// src/lib/openclaw-installer.ts
|
|
36337
|
-
var
|
|
36882
|
+
var import_fs_extra16 = __toESM(require_lib4(), 1);
|
|
36338
36883
|
import os16 from "os";
|
|
36339
|
-
import
|
|
36884
|
+
import path20 from "path";
|
|
36340
36885
|
import { exec as exec4 } from "child_process";
|
|
36341
36886
|
import { promisify as promisify3 } from "util";
|
|
36342
36887
|
var execAsync3 = promisify3(exec4);
|
|
36343
36888
|
var OPENCLAW_PRO_REPO = "Melvynx/openclawpro";
|
|
36344
36889
|
function getCacheRepoDir2() {
|
|
36345
|
-
return
|
|
36890
|
+
return path20.join(os16.homedir(), ".config", "openclaw", "pro-repos", "openclawpro");
|
|
36346
36891
|
}
|
|
36347
36892
|
async function execGitWithAuth2(command, token, repoUrl, cwd) {
|
|
36348
36893
|
const authenticatedUrl = `https://x-access-token:${token}@${repoUrl.replace(/^https?:\/\//, "")}`;
|
|
@@ -36356,33 +36901,33 @@ async function execGitWithAuth2(command, token, repoUrl, cwd) {
|
|
|
36356
36901
|
async function cloneOrUpdateRepo2(token) {
|
|
36357
36902
|
const cacheDir = getCacheRepoDir2();
|
|
36358
36903
|
const repoUrl = `https://github.com/${OPENCLAW_PRO_REPO}.git`;
|
|
36359
|
-
if (await
|
|
36904
|
+
if (await import_fs_extra16.default.pathExists(path20.join(cacheDir, ".git"))) {
|
|
36360
36905
|
try {
|
|
36361
36906
|
await execGitWithAuth2("pull", token, repoUrl, cacheDir);
|
|
36362
36907
|
} catch (error) {
|
|
36363
|
-
await
|
|
36364
|
-
await
|
|
36908
|
+
await import_fs_extra16.default.remove(cacheDir);
|
|
36909
|
+
await import_fs_extra16.default.ensureDir(path20.dirname(cacheDir));
|
|
36365
36910
|
await execGitWithAuth2(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
36366
36911
|
}
|
|
36367
36912
|
} else {
|
|
36368
|
-
await
|
|
36913
|
+
await import_fs_extra16.default.ensureDir(path20.dirname(cacheDir));
|
|
36369
36914
|
await execGitWithAuth2(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
36370
36915
|
}
|
|
36371
|
-
return
|
|
36916
|
+
return path20.join(cacheDir, "openclaw-config");
|
|
36372
36917
|
}
|
|
36373
36918
|
async function copyConfigFromCache2(cacheConfigDir, targetDir, onProgress) {
|
|
36374
36919
|
const walk = async (dir, baseDir = dir) => {
|
|
36375
|
-
const entries = await
|
|
36920
|
+
const entries = await import_fs_extra16.default.readdir(dir, { withFileTypes: true });
|
|
36376
36921
|
for (const entry of entries) {
|
|
36377
|
-
const sourcePath =
|
|
36378
|
-
const relativePath =
|
|
36379
|
-
const targetPath =
|
|
36922
|
+
const sourcePath = path20.join(dir, entry.name);
|
|
36923
|
+
const relativePath = path20.relative(baseDir, sourcePath);
|
|
36924
|
+
const targetPath = path20.join(targetDir, relativePath);
|
|
36380
36925
|
if (entry.isDirectory()) {
|
|
36381
|
-
await
|
|
36926
|
+
await import_fs_extra16.default.ensureDir(targetPath);
|
|
36382
36927
|
onProgress?.(relativePath, "directory");
|
|
36383
36928
|
await walk(sourcePath, baseDir);
|
|
36384
36929
|
} else {
|
|
36385
|
-
await
|
|
36930
|
+
await import_fs_extra16.default.copy(sourcePath, targetPath, { overwrite: true });
|
|
36386
36931
|
onProgress?.(relativePath, "file");
|
|
36387
36932
|
}
|
|
36388
36933
|
}
|
|
@@ -36391,7 +36936,7 @@ async function copyConfigFromCache2(cacheConfigDir, targetDir, onProgress) {
|
|
|
36391
36936
|
}
|
|
36392
36937
|
async function installOpenclawProConfigs(options) {
|
|
36393
36938
|
const { githubToken, openclawFolder, onProgress } = options;
|
|
36394
|
-
const targetFolder = openclawFolder ||
|
|
36939
|
+
const targetFolder = openclawFolder || path20.join(os16.homedir(), ".openclaw");
|
|
36395
36940
|
try {
|
|
36396
36941
|
const cacheConfigDir = await cloneOrUpdateRepo2(githubToken);
|
|
36397
36942
|
await copyConfigFromCache2(cacheConfigDir, targetFolder, onProgress);
|
|
@@ -36402,28 +36947,28 @@ async function installOpenclawProConfigs(options) {
|
|
|
36402
36947
|
}
|
|
36403
36948
|
|
|
36404
36949
|
// src/lib/openclaw-token-storage.ts
|
|
36405
|
-
var
|
|
36950
|
+
var import_fs_extra17 = __toESM(require_lib4(), 1);
|
|
36406
36951
|
import os17 from "os";
|
|
36407
|
-
import
|
|
36952
|
+
import path21 from "path";
|
|
36408
36953
|
function getConfigDir2() {
|
|
36409
36954
|
const platform = os17.platform();
|
|
36410
36955
|
if (platform === "win32") {
|
|
36411
|
-
return
|
|
36956
|
+
return path21.join(process.env.APPDATA || os17.homedir(), "openclaw");
|
|
36412
36957
|
}
|
|
36413
|
-
return
|
|
36958
|
+
return path21.join(os17.homedir(), ".config", "openclaw");
|
|
36414
36959
|
}
|
|
36415
36960
|
function getTokenPath() {
|
|
36416
|
-
return
|
|
36961
|
+
return path21.join(getConfigDir2(), "token.txt");
|
|
36417
36962
|
}
|
|
36418
36963
|
async function saveOpenclawToken(githubToken) {
|
|
36419
36964
|
const configDir = getConfigDir2();
|
|
36420
|
-
await
|
|
36421
|
-
await
|
|
36965
|
+
await import_fs_extra17.default.ensureDir(configDir);
|
|
36966
|
+
await import_fs_extra17.default.writeFile(getTokenPath(), githubToken, { mode: 384 });
|
|
36422
36967
|
}
|
|
36423
36968
|
async function getOpenclawToken() {
|
|
36424
36969
|
const tokenPath = getTokenPath();
|
|
36425
|
-
if (await
|
|
36426
|
-
const token = await
|
|
36970
|
+
if (await import_fs_extra17.default.pathExists(tokenPath)) {
|
|
36971
|
+
const token = await import_fs_extra17.default.readFile(tokenPath, "utf8");
|
|
36427
36972
|
return token.trim();
|
|
36428
36973
|
}
|
|
36429
36974
|
return null;
|
|
@@ -36436,7 +36981,7 @@ function getOpenclawTokenInfo() {
|
|
|
36436
36981
|
}
|
|
36437
36982
|
|
|
36438
36983
|
// src/commands/openclaw-pro.ts
|
|
36439
|
-
var
|
|
36984
|
+
var import_fs_extra18 = __toESM(require_lib4(), 1);
|
|
36440
36985
|
var API_URL2 = "https://codeline.app/api/products";
|
|
36441
36986
|
var OPENCLAW_PRODUCT_ID = "prd_t2GRwX3aH1";
|
|
36442
36987
|
var CLAUDE_CODE_TOOLS_INSTRUCTIONS = `
|
|
@@ -36543,7 +37088,7 @@ async function openclawProSetupCommand(options = {}) {
|
|
|
36543
37088
|
Se(source_default.red("❌ Not activated"));
|
|
36544
37089
|
process.exit(1);
|
|
36545
37090
|
}
|
|
36546
|
-
const openclawDir = options.folder ?
|
|
37091
|
+
const openclawDir = options.folder ? path22.resolve(options.folder) : path22.join(os18.homedir(), ".openclaw");
|
|
36547
37092
|
const spinner = Y2();
|
|
36548
37093
|
const onProgress = (file, type) => {
|
|
36549
37094
|
spinner.message(`Installing: ${source_default.cyan(file)} ${source_default.gray(`(${type})`)}`);
|
|
@@ -36556,23 +37101,23 @@ async function openclawProSetupCommand(options = {}) {
|
|
|
36556
37101
|
});
|
|
36557
37102
|
spinner.stop("OpenClaw Pro configurations installed");
|
|
36558
37103
|
let skillCount = 0;
|
|
36559
|
-
const skillsDir =
|
|
36560
|
-
if (await
|
|
36561
|
-
const items = await
|
|
37104
|
+
const skillsDir = path22.join(openclawDir, "skills");
|
|
37105
|
+
if (await import_fs_extra18.default.pathExists(skillsDir)) {
|
|
37106
|
+
const items = await import_fs_extra18.default.readdir(skillsDir);
|
|
36562
37107
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
36563
|
-
const stat = await
|
|
37108
|
+
const stat = await import_fs_extra18.default.stat(path22.join(skillsDir, item));
|
|
36564
37109
|
return stat.isDirectory();
|
|
36565
37110
|
}));
|
|
36566
37111
|
skillCount = dirs.filter(Boolean).length;
|
|
36567
37112
|
}
|
|
36568
37113
|
spinner.start("Setting up workspace TOOLS.md...");
|
|
36569
|
-
const workspaceDir =
|
|
36570
|
-
const toolsPath =
|
|
36571
|
-
await
|
|
36572
|
-
if (await
|
|
36573
|
-
const existingContent = await
|
|
37114
|
+
const workspaceDir = path22.join(openclawDir, "workspace");
|
|
37115
|
+
const toolsPath = path22.join(workspaceDir, "TOOLS.md");
|
|
37116
|
+
await import_fs_extra18.default.ensureDir(workspaceDir);
|
|
37117
|
+
if (await import_fs_extra18.default.pathExists(toolsPath)) {
|
|
37118
|
+
const existingContent = await import_fs_extra18.default.readFile(toolsPath, "utf-8");
|
|
36574
37119
|
if (!existingContent.includes("Claude Code CLI")) {
|
|
36575
|
-
await
|
|
37120
|
+
await import_fs_extra18.default.appendFile(toolsPath, `
|
|
36576
37121
|
|
|
36577
37122
|
` + CLAUDE_CODE_TOOLS_INSTRUCTIONS);
|
|
36578
37123
|
spinner.stop("TOOLS.md updated with Claude Code instructions");
|
|
@@ -36586,7 +37131,7 @@ Skills define _how_ tools work. This file is for _your_ specifics — the stuff
|
|
|
36586
37131
|
|
|
36587
37132
|
${CLAUDE_CODE_TOOLS_INSTRUCTIONS}
|
|
36588
37133
|
`;
|
|
36589
|
-
await
|
|
37134
|
+
await import_fs_extra18.default.writeFile(toolsPath, defaultToolsMd);
|
|
36590
37135
|
spinner.stop("TOOLS.md created with Claude Code instructions");
|
|
36591
37136
|
}
|
|
36592
37137
|
spinner.start("Creating claude-run wrapper...");
|
|
@@ -36597,9 +37142,9 @@ ${CLAUDE_CODE_TOOLS_INSTRUCTIONS}
|
|
|
36597
37142
|
script -q -c "claude $*" /dev/null
|
|
36598
37143
|
`;
|
|
36599
37144
|
const binDir = "/usr/local/bin";
|
|
36600
|
-
const wrapperPath =
|
|
37145
|
+
const wrapperPath = path22.join(binDir, "claude-run");
|
|
36601
37146
|
try {
|
|
36602
|
-
await
|
|
37147
|
+
await import_fs_extra18.default.writeFile(wrapperPath, claudeRunWrapper, { mode: 493 });
|
|
36603
37148
|
spinner.stop("claude-run wrapper created");
|
|
36604
37149
|
} catch {
|
|
36605
37150
|
spinner.stop("claude-run wrapper skipped (no write access to /usr/local/bin)");
|
|
@@ -36648,12 +37193,12 @@ async function openclawProUpdateCommand(options = {}) {
|
|
|
36648
37193
|
}
|
|
36649
37194
|
|
|
36650
37195
|
// src/commands/dynamic-scripts.ts
|
|
36651
|
-
import
|
|
37196
|
+
import path25 from "path";
|
|
36652
37197
|
import { homedir } from "os";
|
|
36653
37198
|
|
|
36654
37199
|
// src/lib/script-parser.ts
|
|
36655
|
-
var
|
|
36656
|
-
import
|
|
37200
|
+
var import_fs_extra19 = __toESM(require_lib4(), 1);
|
|
37201
|
+
import path23 from "path";
|
|
36657
37202
|
var EXCLUDED_SCRIPTS = ["test", "lint", "format", "start"];
|
|
36658
37203
|
var EXCLUDED_SUFFIXES = [":test", ":lint", ":test-fixtures", ":start"];
|
|
36659
37204
|
function shouldIncludeScript(scriptName) {
|
|
@@ -36664,12 +37209,12 @@ function shouldIncludeScript(scriptName) {
|
|
|
36664
37209
|
return true;
|
|
36665
37210
|
}
|
|
36666
37211
|
async function readScriptsPackageJson(claudeDir) {
|
|
36667
|
-
const packageJsonPath =
|
|
37212
|
+
const packageJsonPath = path23.join(claudeDir, "scripts", "package.json");
|
|
36668
37213
|
try {
|
|
36669
|
-
if (!await
|
|
37214
|
+
if (!await import_fs_extra19.default.pathExists(packageJsonPath)) {
|
|
36670
37215
|
return null;
|
|
36671
37216
|
}
|
|
36672
|
-
const content = await
|
|
37217
|
+
const content = await import_fs_extra19.default.readFile(packageJsonPath, "utf-8");
|
|
36673
37218
|
const parsed = JSON.parse(content);
|
|
36674
37219
|
return parsed.scripts || null;
|
|
36675
37220
|
} catch (error) {
|
|
@@ -36713,10 +37258,10 @@ function groupScriptsByPrefix(commands) {
|
|
|
36713
37258
|
}
|
|
36714
37259
|
|
|
36715
37260
|
// src/commands/script-runner.ts
|
|
36716
|
-
var
|
|
37261
|
+
var import_fs_extra20 = __toESM(require_lib4(), 1);
|
|
36717
37262
|
import { spawn as spawn2 } from "child_process";
|
|
36718
37263
|
import { execSync as execSync4 } from "child_process";
|
|
36719
|
-
import
|
|
37264
|
+
import path24 from "path";
|
|
36720
37265
|
import os19 from "os";
|
|
36721
37266
|
function checkCommand2(cmd) {
|
|
36722
37267
|
try {
|
|
@@ -36746,18 +37291,18 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
36746
37291
|
console.error(source_default.red("Bun is not installed. Install with: npm install -g bun"));
|
|
36747
37292
|
return 1;
|
|
36748
37293
|
}
|
|
36749
|
-
const scriptsDir =
|
|
36750
|
-
if (!await
|
|
37294
|
+
const scriptsDir = path24.join(claudeDir, "scripts");
|
|
37295
|
+
if (!await import_fs_extra20.default.pathExists(scriptsDir)) {
|
|
36751
37296
|
console.error(source_default.red(`Scripts directory not found at ${scriptsDir}`));
|
|
36752
37297
|
console.log(source_default.gray("Run: aiblueprint agents setup"));
|
|
36753
37298
|
return 1;
|
|
36754
37299
|
}
|
|
36755
|
-
const packageJsonPath =
|
|
36756
|
-
if (!await
|
|
37300
|
+
const packageJsonPath = path24.join(scriptsDir, "package.json");
|
|
37301
|
+
if (!await import_fs_extra20.default.pathExists(packageJsonPath)) {
|
|
36757
37302
|
console.error(source_default.red(`package.json not found in ${scriptsDir}`));
|
|
36758
37303
|
return 1;
|
|
36759
37304
|
}
|
|
36760
|
-
const packageJson = await
|
|
37305
|
+
const packageJson = await import_fs_extra20.default.readJson(packageJsonPath);
|
|
36761
37306
|
if (!packageJson.scripts || !packageJson.scripts[scriptName]) {
|
|
36762
37307
|
console.error(source_default.red(`Script "${scriptName}" not found in package.json`));
|
|
36763
37308
|
return 1;
|
|
@@ -36780,7 +37325,7 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
36780
37325
|
|
|
36781
37326
|
// src/commands/dynamic-scripts.ts
|
|
36782
37327
|
function getClaudeDir(parentOptions) {
|
|
36783
|
-
return parentOptions.claudeCodeFolder || parentOptions.folder ?
|
|
37328
|
+
return parentOptions.claudeCodeFolder || parentOptions.folder ? path25.resolve(parentOptions.claudeCodeFolder || parentOptions.folder) : path25.join(homedir(), ".claude");
|
|
36784
37329
|
}
|
|
36785
37330
|
async function registerDynamicScriptCommands(claudeCodeCmd, claudeDir) {
|
|
36786
37331
|
const scripts = await readScriptsPackageJson(claudeDir);
|
|
@@ -36886,12 +37431,70 @@ function registerAgentsCommands(cmd) {
|
|
|
36886
37431
|
});
|
|
36887
37432
|
});
|
|
36888
37433
|
}
|
|
37434
|
+
function addConfigFolderOptions(cmd) {
|
|
37435
|
+
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)");
|
|
37436
|
+
}
|
|
37437
|
+
function readConfigOptions(command, options = {}) {
|
|
37438
|
+
const parentOptions = command.parent?.opts() ?? {};
|
|
37439
|
+
const grandParentOptions = command.parent?.parent?.opts() ?? {};
|
|
37440
|
+
return {
|
|
37441
|
+
folder: options.folder ?? parentOptions.folder ?? grandParentOptions.folder,
|
|
37442
|
+
claudeCodeFolder: options.claudeCodeFolder ?? parentOptions.claudeCodeFolder ?? grandParentOptions.claudeCodeFolder,
|
|
37443
|
+
codexFolder: options.codexFolder ?? parentOptions.codexFolder ?? grandParentOptions.codexFolder,
|
|
37444
|
+
agentsFolder: options.agentsFolder ?? parentOptions.agentsFolder ?? grandParentOptions.agentsFolder
|
|
37445
|
+
};
|
|
37446
|
+
}
|
|
36889
37447
|
var agentsCmd = program2.command("agents").description("AI coding configuration commands");
|
|
36890
37448
|
registerAgentsCommands(agentsCmd);
|
|
36891
37449
|
var aiCodingCmd = program2.command("ai-coding").description("Legacy alias for agents configuration commands");
|
|
36892
37450
|
registerAgentsCommands(aiCodingCmd);
|
|
36893
37451
|
var claudeCodeCmd = program2.command("claude-code").description("Legacy alias for agents configuration commands");
|
|
36894
37452
|
registerAgentsCommands(claudeCodeCmd);
|
|
37453
|
+
var configsCmd = addConfigFolderOptions(program2.command("configs").description("Save, load, undo, and inspect .claude/.codex/.agents configurations"));
|
|
37454
|
+
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) => {
|
|
37455
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37456
|
+
configsSaveCommand(name, {
|
|
37457
|
+
...folderOptions,
|
|
37458
|
+
force: options.force
|
|
37459
|
+
});
|
|
37460
|
+
});
|
|
37461
|
+
addConfigFolderOptions(configsCmd.command("load <name>").description("Load a named config and backup the current folders first")).action((name, options, command) => {
|
|
37462
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37463
|
+
configsLoadCommand(name, {
|
|
37464
|
+
...folderOptions
|
|
37465
|
+
});
|
|
37466
|
+
});
|
|
37467
|
+
addConfigFolderOptions(configsCmd.command("undo").description("Undo the most recent configs load by restoring its automatic backup")).action((options, command) => {
|
|
37468
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37469
|
+
configsUndoCommand({
|
|
37470
|
+
...folderOptions
|
|
37471
|
+
});
|
|
37472
|
+
});
|
|
37473
|
+
addConfigFolderOptions(configsCmd.command("list").description("List saved named configs")).action((options, command) => {
|
|
37474
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37475
|
+
configsListCommand({
|
|
37476
|
+
...folderOptions
|
|
37477
|
+
});
|
|
37478
|
+
});
|
|
37479
|
+
var configsBackupsCmd = configsCmd.command("backups").description("Manage automatic config backups");
|
|
37480
|
+
addConfigFolderOptions(configsBackupsCmd.command("list").description("List automatic backups with reasons")).action((options, command) => {
|
|
37481
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37482
|
+
configsBackupsListCommand({
|
|
37483
|
+
...folderOptions
|
|
37484
|
+
});
|
|
37485
|
+
});
|
|
37486
|
+
addConfigFolderOptions(configsBackupsCmd.command("load <name>").description("Load a backup and backup the current folders first")).action((name, options, command) => {
|
|
37487
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37488
|
+
configsBackupsLoadCommand(name, {
|
|
37489
|
+
...folderOptions
|
|
37490
|
+
});
|
|
37491
|
+
});
|
|
37492
|
+
addConfigFolderOptions(configsBackupsCmd.command("create [reason]").description("Create a manual backup of the current config folders")).action((reason, options, command) => {
|
|
37493
|
+
const folderOptions = readConfigOptions(command, options);
|
|
37494
|
+
configsBackupsCreateCommand(reason, {
|
|
37495
|
+
...folderOptions
|
|
37496
|
+
});
|
|
37497
|
+
});
|
|
36895
37498
|
var openclawCmd = program2.command("openclaw").description("OpenClaw configuration commands").option("-f, --folder <path>", "Specify custom OpenClaw folder path (default: ~/.openclaw)");
|
|
36896
37499
|
var openclawProCmd = openclawCmd.command("pro").description("Manage OpenClaw Pro features");
|
|
36897
37500
|
openclawProCmd.command("activate [token]").description("Activate OpenClaw Pro with your access token").action((token) => {
|