aiblueprint-cli 1.4.56 → 1.4.57
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 +941 -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,397 @@ 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
|
+
function getConfigStorePaths(rootDir) {
|
|
33591
|
+
const baseDir = path11.join(rootDir, ".aiblueprint");
|
|
33592
|
+
return {
|
|
33593
|
+
baseDir,
|
|
33594
|
+
configsDir: path11.join(baseDir, "configs"),
|
|
33595
|
+
backupsDir: path11.join(baseDir, "backups"),
|
|
33596
|
+
historyPath: path11.join(baseDir, "history.jsonl")
|
|
33597
|
+
};
|
|
33598
|
+
}
|
|
33599
|
+
function resolveConfigStoreFolders(options = {}) {
|
|
33600
|
+
return resolveFolders(options);
|
|
33601
|
+
}
|
|
33602
|
+
function timestamp(date = new Date) {
|
|
33603
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
33604
|
+
return [
|
|
33605
|
+
date.getFullYear(),
|
|
33606
|
+
pad(date.getMonth() + 1),
|
|
33607
|
+
pad(date.getDate()),
|
|
33608
|
+
pad(date.getHours()),
|
|
33609
|
+
pad(date.getMinutes()),
|
|
33610
|
+
pad(date.getSeconds())
|
|
33611
|
+
].join("-");
|
|
33612
|
+
}
|
|
33613
|
+
function sanitizeSnapshotName(name) {
|
|
33614
|
+
const sanitized = name.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
33615
|
+
if (!sanitized) {
|
|
33616
|
+
throw new Error("Snapshot name cannot be empty");
|
|
33617
|
+
}
|
|
33618
|
+
if (sanitized === "." || sanitized === ".." || sanitized.includes("..")) {
|
|
33619
|
+
throw new Error("Snapshot name is not allowed");
|
|
33620
|
+
}
|
|
33621
|
+
return sanitized;
|
|
33622
|
+
}
|
|
33623
|
+
function managedFolders(folders) {
|
|
33624
|
+
return [
|
|
33625
|
+
{ name: ".claude", path: folders.claudeDir },
|
|
33626
|
+
{ name: ".codex", path: folders.codexDir },
|
|
33627
|
+
{ name: ".agents", path: folders.agentsDir }
|
|
33628
|
+
];
|
|
33629
|
+
}
|
|
33630
|
+
async function hasContent(folderPath) {
|
|
33631
|
+
if (!await import_fs_extra7.default.pathExists(folderPath))
|
|
33632
|
+
return false;
|
|
33633
|
+
const entries = await import_fs_extra7.default.readdir(folderPath);
|
|
33634
|
+
return entries.some((entry) => entry !== ".DS_Store");
|
|
33635
|
+
}
|
|
33636
|
+
async function copyManagedFolder(source, destination) {
|
|
33637
|
+
await import_fs_extra7.default.copy(source, destination, {
|
|
33638
|
+
overwrite: true,
|
|
33639
|
+
dereference: false,
|
|
33640
|
+
filter: async (src) => {
|
|
33641
|
+
try {
|
|
33642
|
+
const stat = await import_fs_extra7.default.lstat(src);
|
|
33643
|
+
return !stat.isSymbolicLink();
|
|
33644
|
+
} catch {
|
|
33645
|
+
return true;
|
|
33646
|
+
}
|
|
33647
|
+
}
|
|
33648
|
+
});
|
|
33649
|
+
}
|
|
33650
|
+
async function writeMetadata(snapshotPath, metadata) {
|
|
33651
|
+
await import_fs_extra7.default.writeJson(path11.join(snapshotPath, "metadata.json"), metadata, { spaces: 2 });
|
|
33652
|
+
}
|
|
33653
|
+
async function readMetadata(snapshotPath, fallbackType) {
|
|
33654
|
+
const metadataPath = path11.join(snapshotPath, "metadata.json");
|
|
33655
|
+
if (await import_fs_extra7.default.pathExists(metadataPath)) {
|
|
33656
|
+
return import_fs_extra7.default.readJson(metadataPath);
|
|
33657
|
+
}
|
|
33658
|
+
const name = path11.basename(snapshotPath);
|
|
33659
|
+
return {
|
|
33660
|
+
name,
|
|
33661
|
+
type: fallbackType,
|
|
33662
|
+
createdAt: new Date(0).toISOString(),
|
|
33663
|
+
reason: "Legacy snapshot without metadata",
|
|
33664
|
+
trigger: "legacy",
|
|
33665
|
+
folders: []
|
|
33666
|
+
};
|
|
33667
|
+
}
|
|
33668
|
+
async function appendHistory(paths, event) {
|
|
33669
|
+
await import_fs_extra7.default.ensureDir(paths.baseDir);
|
|
33670
|
+
await import_fs_extra7.default.appendFile(paths.historyPath, `${JSON.stringify({ at: new Date().toISOString(), ...event })}
|
|
33671
|
+
`);
|
|
33672
|
+
}
|
|
33673
|
+
async function snapshotByCopy(snapshotPath, folders, metadata) {
|
|
33674
|
+
const copied = [];
|
|
33675
|
+
await import_fs_extra7.default.ensureDir(snapshotPath);
|
|
33676
|
+
for (const folder of managedFolders(folders)) {
|
|
33677
|
+
if (!await hasContent(folder.path))
|
|
33678
|
+
continue;
|
|
33679
|
+
await copyManagedFolder(folder.path, path11.join(snapshotPath, folder.name));
|
|
33680
|
+
copied.push(folder.name);
|
|
33681
|
+
}
|
|
33682
|
+
if (copied.length === 0) {
|
|
33683
|
+
await import_fs_extra7.default.remove(snapshotPath);
|
|
33684
|
+
return null;
|
|
33685
|
+
}
|
|
33686
|
+
await writeMetadata(snapshotPath, { ...metadata, folders: copied });
|
|
33687
|
+
return snapshotPath;
|
|
33688
|
+
}
|
|
33689
|
+
async function saveNamedConfig(name, options = {}) {
|
|
33690
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33691
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33692
|
+
const safeName = sanitizeSnapshotName(name);
|
|
33693
|
+
const snapshotPath = path11.join(paths.configsDir, safeName);
|
|
33694
|
+
if (await import_fs_extra7.default.pathExists(snapshotPath) && !options.force) {
|
|
33695
|
+
throw new Error(`Config "${safeName}" already exists. Use --force to overwrite it.`);
|
|
33696
|
+
}
|
|
33697
|
+
if (await import_fs_extra7.default.pathExists(snapshotPath)) {
|
|
33698
|
+
const backupName = `${timestamp()}-replace-saved-${safeName}`;
|
|
33699
|
+
await import_fs_extra7.default.ensureDir(paths.backupsDir);
|
|
33700
|
+
await import_fs_extra7.default.move(snapshotPath, path11.join(paths.backupsDir, backupName), { overwrite: false });
|
|
33701
|
+
}
|
|
33702
|
+
const result = await snapshotByCopy(snapshotPath, folders, {
|
|
33703
|
+
name: safeName,
|
|
33704
|
+
type: "config",
|
|
33705
|
+
createdAt: new Date().toISOString(),
|
|
33706
|
+
reason: `Manual save as "${safeName}"`,
|
|
33707
|
+
trigger: "save",
|
|
33708
|
+
folders: []
|
|
33709
|
+
});
|
|
33710
|
+
if (!result) {
|
|
33711
|
+
throw new Error("No .claude, .codex, or .agents configuration found to save.");
|
|
33712
|
+
}
|
|
33713
|
+
await appendHistory(paths, { action: "save", name: safeName, path: result });
|
|
33714
|
+
return result;
|
|
33715
|
+
}
|
|
33716
|
+
async function createConfigBackup(options = {}, reason = "Backup current configuration", trigger = "manual", source) {
|
|
33717
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33718
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33719
|
+
const safeSource = source ? sanitizeSnapshotName(source) : trigger;
|
|
33720
|
+
const name = `${timestamp()}-${safeSource}`;
|
|
33721
|
+
const snapshotPath = path11.join(paths.backupsDir, name);
|
|
33722
|
+
const result = await snapshotByCopy(snapshotPath, folders, {
|
|
33723
|
+
name,
|
|
33724
|
+
type: "backup",
|
|
33725
|
+
createdAt: new Date().toISOString(),
|
|
33726
|
+
reason,
|
|
33727
|
+
trigger,
|
|
33728
|
+
source,
|
|
33729
|
+
folders: []
|
|
33730
|
+
});
|
|
33731
|
+
if (result) {
|
|
33732
|
+
await appendHistory(paths, { action: "backup", name, reason, trigger, source, path: result });
|
|
33733
|
+
}
|
|
33734
|
+
return result;
|
|
33735
|
+
}
|
|
33736
|
+
async function backupCurrentByMove(folders, reason, trigger, source) {
|
|
33737
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33738
|
+
const safeSource = source ? sanitizeSnapshotName(source) : trigger;
|
|
33739
|
+
const name = `${timestamp()}-${safeSource}`;
|
|
33740
|
+
const backupPath = path11.join(paths.backupsDir, name);
|
|
33741
|
+
const moved = [];
|
|
33742
|
+
await import_fs_extra7.default.ensureDir(backupPath);
|
|
33743
|
+
for (const folder of managedFolders(folders)) {
|
|
33744
|
+
if (!await hasContent(folder.path))
|
|
33745
|
+
continue;
|
|
33746
|
+
await import_fs_extra7.default.move(folder.path, path11.join(backupPath, folder.name), { overwrite: false });
|
|
33747
|
+
moved.push(folder.name);
|
|
33748
|
+
}
|
|
33749
|
+
if (moved.length === 0) {
|
|
33750
|
+
await import_fs_extra7.default.remove(backupPath);
|
|
33751
|
+
return null;
|
|
33752
|
+
}
|
|
33753
|
+
await writeMetadata(backupPath, {
|
|
33754
|
+
name,
|
|
33755
|
+
type: "backup",
|
|
33756
|
+
createdAt: new Date().toISOString(),
|
|
33757
|
+
reason,
|
|
33758
|
+
trigger,
|
|
33759
|
+
source,
|
|
33760
|
+
folders: moved
|
|
33761
|
+
});
|
|
33762
|
+
await appendHistory(paths, { action: "backup", name, reason, trigger, source, path: backupPath });
|
|
33763
|
+
return backupPath;
|
|
33764
|
+
}
|
|
33765
|
+
async function restoreSnapshot(snapshotPath, folders) {
|
|
33766
|
+
const restored = [];
|
|
33767
|
+
for (const folder of managedFolders(folders)) {
|
|
33768
|
+
const source = path11.join(snapshotPath, folder.name);
|
|
33769
|
+
if (!await import_fs_extra7.default.pathExists(source))
|
|
33770
|
+
continue;
|
|
33771
|
+
await import_fs_extra7.default.ensureDir(path11.dirname(folder.path));
|
|
33772
|
+
await copyManagedFolder(source, folder.path);
|
|
33773
|
+
restored.push(folder.name);
|
|
33774
|
+
}
|
|
33775
|
+
return restored;
|
|
33776
|
+
}
|
|
33777
|
+
async function loadNamedConfig(name, options = {}) {
|
|
33778
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33779
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33780
|
+
const safeName = sanitizeSnapshotName(name);
|
|
33781
|
+
const snapshotPath = path11.join(paths.configsDir, safeName);
|
|
33782
|
+
if (!await import_fs_extra7.default.pathExists(snapshotPath)) {
|
|
33783
|
+
throw new Error(`Saved config not found: ${safeName}`);
|
|
33784
|
+
}
|
|
33785
|
+
const backupPath = await backupCurrentByMove(folders, `Before loading saved config "${safeName}"`, "load", safeName);
|
|
33786
|
+
const restored = await restoreSnapshot(snapshotPath, folders);
|
|
33787
|
+
await appendHistory(paths, { action: "load", name: safeName, backupPath, restored });
|
|
33788
|
+
return { backupPath, restored };
|
|
33789
|
+
}
|
|
33790
|
+
async function loadBackupSnapshot(name, options = {}) {
|
|
33791
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33792
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33793
|
+
const safeName = sanitizeSnapshotName(name);
|
|
33794
|
+
const snapshotPath = path11.join(paths.backupsDir, safeName);
|
|
33795
|
+
if (!await import_fs_extra7.default.pathExists(snapshotPath)) {
|
|
33796
|
+
throw new Error(`Backup not found: ${safeName}`);
|
|
33797
|
+
}
|
|
33798
|
+
const backupPath = await backupCurrentByMove(folders, `Before restoring backup "${safeName}"`, "backup-load", safeName);
|
|
33799
|
+
const restored = await restoreSnapshot(snapshotPath, folders);
|
|
33800
|
+
await appendHistory(paths, { action: "backup-load", name: safeName, backupPath, restored });
|
|
33801
|
+
return { backupPath, restored };
|
|
33802
|
+
}
|
|
33803
|
+
async function undoLastLoad(options = {}) {
|
|
33804
|
+
const backups = await listConfigBackups(options);
|
|
33805
|
+
const lastLoadBackup = backups.find((backup) => backup.metadata.trigger === "load" || backup.metadata.trigger === "backup-load");
|
|
33806
|
+
if (!lastLoadBackup) {
|
|
33807
|
+
throw new Error("No load backup found to undo.");
|
|
33808
|
+
}
|
|
33809
|
+
const result = await loadBackupSnapshot(lastLoadBackup.name, options);
|
|
33810
|
+
return { backupName: lastLoadBackup.name, ...result };
|
|
33811
|
+
}
|
|
33812
|
+
async function listSnapshots(dir, type) {
|
|
33813
|
+
if (!await import_fs_extra7.default.pathExists(dir))
|
|
33814
|
+
return [];
|
|
33815
|
+
const entries = await import_fs_extra7.default.readdir(dir, { withFileTypes: true });
|
|
33816
|
+
const snapshots = [];
|
|
33817
|
+
for (const entry of entries) {
|
|
33818
|
+
if (!entry.isDirectory())
|
|
33819
|
+
continue;
|
|
33820
|
+
const snapshotPath = path11.join(dir, entry.name);
|
|
33821
|
+
const metadata = await readMetadata(snapshotPath, type);
|
|
33822
|
+
snapshots.push({ name: entry.name, path: snapshotPath, metadata });
|
|
33823
|
+
}
|
|
33824
|
+
return snapshots.sort((a, b) => b.metadata.createdAt.localeCompare(a.metadata.createdAt));
|
|
33825
|
+
}
|
|
33826
|
+
async function listSavedConfigs(options = {}) {
|
|
33827
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33828
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33829
|
+
return listSnapshots(paths.configsDir, "config");
|
|
33830
|
+
}
|
|
33831
|
+
async function listConfigBackups(options = {}) {
|
|
33832
|
+
const folders = resolveConfigStoreFolders(options);
|
|
33833
|
+
const paths = getConfigStorePaths(folders.rootDir);
|
|
33834
|
+
return listSnapshots(paths.backupsDir, "backup");
|
|
33835
|
+
}
|
|
33836
|
+
|
|
33566
33837
|
// src/commands/setup.ts
|
|
33567
33838
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
33568
33839
|
var __dirname2 = dirname2(__filename2);
|
|
33569
33840
|
async function resolveClaudeAssetPath(sourceDir, name) {
|
|
33570
33841
|
const candidates = [
|
|
33571
|
-
|
|
33572
|
-
|
|
33842
|
+
path12.join(sourceDir, "claude-config", name),
|
|
33843
|
+
path12.join(sourceDir, name)
|
|
33573
33844
|
];
|
|
33574
33845
|
for (const candidate of candidates) {
|
|
33575
|
-
if (await
|
|
33846
|
+
if (await import_fs_extra8.default.pathExists(candidate))
|
|
33576
33847
|
return candidate;
|
|
33577
33848
|
}
|
|
33578
33849
|
return null;
|
|
@@ -33660,10 +33931,10 @@ async function setupCommand(params = {}) {
|
|
|
33660
33931
|
console.log(source_default.gray(`Claude: ${claudeDir}`));
|
|
33661
33932
|
console.log(source_default.gray(`Codex: ${codexDir}`));
|
|
33662
33933
|
console.log(source_default.gray(`Agents: ${agentsDir}`));
|
|
33663
|
-
await
|
|
33664
|
-
await
|
|
33934
|
+
await import_fs_extra8.default.ensureDir(claudeDir);
|
|
33935
|
+
await import_fs_extra8.default.ensureDir(agentsDir);
|
|
33665
33936
|
s.start("Creating backup of existing configuration");
|
|
33666
|
-
const backupPath = await
|
|
33937
|
+
const backupPath = await createConfigBackup({ folder, claudeCodeFolder, codexFolder, agentsFolder }, "Before running aiblueprint setup", "setup", "aiblueprint-setup");
|
|
33667
33938
|
if (backupPath) {
|
|
33668
33939
|
s.stop(`Backup created: ${source_default.gray(backupPath)}`);
|
|
33669
33940
|
} else {
|
|
@@ -33689,11 +33960,11 @@ async function setupCommand(params = {}) {
|
|
|
33689
33960
|
s.start("Setting up scripts");
|
|
33690
33961
|
const scriptsSource = await resolveClaudeAssetPath(sourceDir, "scripts");
|
|
33691
33962
|
if (scriptsSource) {
|
|
33692
|
-
await
|
|
33963
|
+
await import_fs_extra8.default.copy(scriptsSource, path12.join(claudeDir, "scripts"), {
|
|
33693
33964
|
overwrite: true
|
|
33694
33965
|
});
|
|
33695
|
-
await replacePathPlaceholdersInDir(
|
|
33696
|
-
await
|
|
33966
|
+
await replacePathPlaceholdersInDir(path12.join(claudeDir, "scripts"), claudeDir);
|
|
33967
|
+
await import_fs_extra8.default.ensureDir(path12.join(claudeDir, "scripts/statusline/data"));
|
|
33697
33968
|
s.stop("Scripts installed");
|
|
33698
33969
|
} else {
|
|
33699
33970
|
s.stop("Scripts not available in repository");
|
|
@@ -33701,8 +33972,8 @@ async function setupCommand(params = {}) {
|
|
|
33701
33972
|
}
|
|
33702
33973
|
if (options.aiblueprintAgents) {
|
|
33703
33974
|
s.start("Setting up AIBlueprint agents");
|
|
33704
|
-
const agentsSource =
|
|
33705
|
-
if (await
|
|
33975
|
+
const agentsSource = path12.join(sourceDir, "agents");
|
|
33976
|
+
if (await import_fs_extra8.default.pathExists(agentsSource)) {
|
|
33706
33977
|
const installResult = await installCategoryToAgents(agentsSource, "agents", agentsDir, claudeDir, { migrateClaudeDirs: true, silent: true });
|
|
33707
33978
|
const summary = [
|
|
33708
33979
|
installResult.copied.length && `${installResult.copied.length} copied`,
|
|
@@ -33717,8 +33988,8 @@ async function setupCommand(params = {}) {
|
|
|
33717
33988
|
}
|
|
33718
33989
|
if (options.aiblueprintSkills) {
|
|
33719
33990
|
s.start("Setting up AIBlueprint Skills");
|
|
33720
|
-
const skillsSourcePath =
|
|
33721
|
-
if (await
|
|
33991
|
+
const skillsSourcePath = path12.join(sourceDir, "skills");
|
|
33992
|
+
if (await import_fs_extra8.default.pathExists(skillsSourcePath)) {
|
|
33722
33993
|
const installResult = await installCategoryToAgents(skillsSourcePath, "skills", agentsDir, claudeDir, { migrateClaudeDirs: true, silent: true });
|
|
33723
33994
|
const summary = [
|
|
33724
33995
|
installResult.copied.length && `${installResult.copied.length} copied`,
|
|
@@ -33738,10 +34009,21 @@ async function setupCommand(params = {}) {
|
|
|
33738
34009
|
}
|
|
33739
34010
|
if (options.installCodex) {
|
|
33740
34011
|
s.start("Setting up Codex");
|
|
33741
|
-
await
|
|
33742
|
-
const codexConfigSource =
|
|
33743
|
-
if (await
|
|
33744
|
-
|
|
34012
|
+
await import_fs_extra8.default.ensureDir(codexDir);
|
|
34013
|
+
const codexConfigSource = path12.join(sourceDir, "codex-config");
|
|
34014
|
+
if (await import_fs_extra8.default.pathExists(codexConfigSource)) {
|
|
34015
|
+
const codexConfigPath = path12.join(codexConfigSource, "config.toml");
|
|
34016
|
+
if (await import_fs_extra8.default.pathExists(codexConfigPath)) {
|
|
34017
|
+
await mergeCodexConfigFile(codexConfigPath, codexDir);
|
|
34018
|
+
}
|
|
34019
|
+
const entries = await import_fs_extra8.default.readdir(codexConfigSource);
|
|
34020
|
+
for (const entry of entries) {
|
|
34021
|
+
if (entry === "config.toml")
|
|
34022
|
+
continue;
|
|
34023
|
+
await import_fs_extra8.default.copy(path12.join(codexConfigSource, entry), path12.join(codexDir, entry), {
|
|
34024
|
+
overwrite: false
|
|
34025
|
+
});
|
|
34026
|
+
}
|
|
33745
34027
|
}
|
|
33746
34028
|
if (options.aiblueprintSkills) {
|
|
33747
34029
|
await syncCategorySymlinks("skills", agentsDir, codexDir, undefined, true);
|
|
@@ -33787,7 +34069,7 @@ async function setupCommand(params = {}) {
|
|
|
33787
34069
|
console.log(source_default.gray(`
|
|
33788
34070
|
Next steps:`));
|
|
33789
34071
|
if (options.shellShortcuts) {
|
|
33790
|
-
const platform =
|
|
34072
|
+
const platform = os10.platform();
|
|
33791
34073
|
if (platform === "win32") {
|
|
33792
34074
|
console.log(source_default.gray(" • Restart PowerShell to load the new functions"));
|
|
33793
34075
|
} else {
|
|
@@ -33813,9 +34095,9 @@ Next steps:`));
|
|
|
33813
34095
|
}
|
|
33814
34096
|
|
|
33815
34097
|
// src/commands/setup-terminal.ts
|
|
33816
|
-
var
|
|
33817
|
-
import
|
|
33818
|
-
import
|
|
34098
|
+
var import_fs_extra9 = __toESM(require_lib4(), 1);
|
|
34099
|
+
import path13 from "path";
|
|
34100
|
+
import os11 from "os";
|
|
33819
34101
|
import { execSync as execSync3, exec as exec2 } from "child_process";
|
|
33820
34102
|
var OHMYZSH_INSTALL_URL = "https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh";
|
|
33821
34103
|
var INSTALL_TIMEOUT = 120000;
|
|
@@ -33849,16 +34131,16 @@ function commandExists(cmd) {
|
|
|
33849
34131
|
}
|
|
33850
34132
|
}
|
|
33851
34133
|
function isOhMyZshInstalled(homeDir) {
|
|
33852
|
-
const ohMyZshDir =
|
|
33853
|
-
return
|
|
34134
|
+
const ohMyZshDir = path13.join(homeDir, ".oh-my-zsh");
|
|
34135
|
+
return import_fs_extra9.default.existsSync(ohMyZshDir);
|
|
33854
34136
|
}
|
|
33855
34137
|
function backupFile(filePath) {
|
|
33856
|
-
if (!
|
|
34138
|
+
if (!import_fs_extra9.default.existsSync(filePath))
|
|
33857
34139
|
return null;
|
|
33858
|
-
const
|
|
33859
|
-
const backupPath = `${filePath}.backup-${
|
|
34140
|
+
const timestamp2 = new Date().toISOString().replace(/[:.]/g, "-");
|
|
34141
|
+
const backupPath = `${filePath}.backup-${timestamp2}`;
|
|
33860
34142
|
try {
|
|
33861
|
-
|
|
34143
|
+
import_fs_extra9.default.copyFileSync(filePath, backupPath);
|
|
33862
34144
|
return backupPath;
|
|
33863
34145
|
} catch (error) {
|
|
33864
34146
|
throw new Error(`Failed to create backup: ${error.message}`);
|
|
@@ -33897,7 +34179,7 @@ function installPrerequisiteSync(packageName, installCmd) {
|
|
|
33897
34179
|
async function installOhMyZsh(homeDir) {
|
|
33898
34180
|
return new Promise((resolve, reject) => {
|
|
33899
34181
|
const installCmd = `sh -c "$(curl -fsSL ${OHMYZSH_INSTALL_URL})" "" --unattended`;
|
|
33900
|
-
const env2 = { ...process.env, HOME: homeDir, ZSH:
|
|
34182
|
+
const env2 = { ...process.env, HOME: homeDir, ZSH: path13.join(homeDir, ".oh-my-zsh") };
|
|
33901
34183
|
exec2(installCmd, { timeout: INSTALL_TIMEOUT, env: env2 }, (error, stdout, stderr) => {
|
|
33902
34184
|
if (error) {
|
|
33903
34185
|
if ("killed" in error && error.killed) {
|
|
@@ -33918,8 +34200,8 @@ async function installPlugin(pluginName, repoUrl, homeDir) {
|
|
|
33918
34200
|
if (!/^https:\/\/github\.com\/[\w-]+\/[\w-]+$/.test(repoUrl)) {
|
|
33919
34201
|
throw new Error(`Invalid repository URL: ${repoUrl}`);
|
|
33920
34202
|
}
|
|
33921
|
-
const customPluginsDir =
|
|
33922
|
-
if (
|
|
34203
|
+
const customPluginsDir = path13.join(homeDir, ".oh-my-zsh/custom/plugins", pluginName);
|
|
34204
|
+
if (import_fs_extra9.default.existsSync(customPluginsDir)) {
|
|
33923
34205
|
return;
|
|
33924
34206
|
}
|
|
33925
34207
|
return new Promise((resolve, reject) => {
|
|
@@ -33937,20 +34219,20 @@ async function installPlugin(pluginName, repoUrl, homeDir) {
|
|
|
33937
34219
|
});
|
|
33938
34220
|
}
|
|
33939
34221
|
function updateZshrcTheme(theme, homeDir) {
|
|
33940
|
-
const zshrcPath =
|
|
34222
|
+
const zshrcPath = path13.join(homeDir, ".zshrc");
|
|
33941
34223
|
const sanitizedTheme = sanitizeThemeName(theme);
|
|
33942
|
-
if (!
|
|
34224
|
+
if (!import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
33943
34225
|
throw new Error(".zshrc file not found. Please ensure Oh My ZSH is installed correctly.");
|
|
33944
34226
|
}
|
|
33945
34227
|
try {
|
|
33946
|
-
let content =
|
|
34228
|
+
let content = import_fs_extra9.default.readFileSync(zshrcPath, "utf-8");
|
|
33947
34229
|
if (content.match(/^ZSH_THEME=/m)) {
|
|
33948
34230
|
content = content.replace(/^ZSH_THEME=.*/m, `ZSH_THEME="${sanitizedTheme}"`);
|
|
33949
34231
|
} else {
|
|
33950
34232
|
content = `ZSH_THEME="${sanitizedTheme}"
|
|
33951
34233
|
${content}`;
|
|
33952
34234
|
}
|
|
33953
|
-
|
|
34235
|
+
import_fs_extra9.default.writeFileSync(zshrcPath, content);
|
|
33954
34236
|
} catch (error) {
|
|
33955
34237
|
if (error.message.includes(".zshrc file not found")) {
|
|
33956
34238
|
throw error;
|
|
@@ -33959,12 +34241,12 @@ ${content}`;
|
|
|
33959
34241
|
}
|
|
33960
34242
|
}
|
|
33961
34243
|
function updateZshrcPlugins(plugins, homeDir) {
|
|
33962
|
-
const zshrcPath =
|
|
33963
|
-
if (!
|
|
34244
|
+
const zshrcPath = path13.join(homeDir, ".zshrc");
|
|
34245
|
+
if (!import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
33964
34246
|
throw new Error(".zshrc file not found. Please ensure Oh My ZSH is installed correctly.");
|
|
33965
34247
|
}
|
|
33966
34248
|
try {
|
|
33967
|
-
let content =
|
|
34249
|
+
let content = import_fs_extra9.default.readFileSync(zshrcPath, "utf-8");
|
|
33968
34250
|
const pluginsString = plugins.join(" ");
|
|
33969
34251
|
if (content.match(/^plugins=\(/m)) {
|
|
33970
34252
|
content = content.replace(/^plugins=\([^)]*\)/m, `plugins=(${pluginsString})`);
|
|
@@ -33972,7 +34254,7 @@ function updateZshrcPlugins(plugins, homeDir) {
|
|
|
33972
34254
|
content = `${content}
|
|
33973
34255
|
plugins=(${pluginsString})`;
|
|
33974
34256
|
}
|
|
33975
|
-
|
|
34257
|
+
import_fs_extra9.default.writeFileSync(zshrcPath, content);
|
|
33976
34258
|
} catch (error) {
|
|
33977
34259
|
if (error.message.includes(".zshrc file not found")) {
|
|
33978
34260
|
throw error;
|
|
@@ -33982,7 +34264,7 @@ plugins=(${pluginsString})`;
|
|
|
33982
34264
|
}
|
|
33983
34265
|
async function setupTerminalCommand(options = {}) {
|
|
33984
34266
|
const { skipInteractive, homeDir: customHomeDir } = options;
|
|
33985
|
-
const homeDir = customHomeDir ||
|
|
34267
|
+
const homeDir = customHomeDir || os11.homedir();
|
|
33986
34268
|
try {
|
|
33987
34269
|
console.log(source_default.blue.bold(`
|
|
33988
34270
|
\uD83D\uDDA5️ AIBlueprint Terminal Setup ${source_default.gray(`v${getVersion()}`)}
|
|
@@ -34079,8 +34361,8 @@ Installing missing prerequisites: ${missingPrereqs.join(", ")}`));
|
|
|
34079
34361
|
selectedTheme = themeAnswer.theme;
|
|
34080
34362
|
}
|
|
34081
34363
|
}
|
|
34082
|
-
const zshrcPath =
|
|
34083
|
-
if (
|
|
34364
|
+
const zshrcPath = path13.join(homeDir, ".zshrc");
|
|
34365
|
+
if (import_fs_extra9.default.existsSync(zshrcPath)) {
|
|
34084
34366
|
s.start("Backing up .zshrc");
|
|
34085
34367
|
const backupPath = backupFile(zshrcPath);
|
|
34086
34368
|
if (backupPath) {
|
|
@@ -34130,37 +34412,37 @@ Next steps:`));
|
|
|
34130
34412
|
}
|
|
34131
34413
|
|
|
34132
34414
|
// src/commands/setup/symlinks.ts
|
|
34133
|
-
var
|
|
34134
|
-
import
|
|
34135
|
-
import
|
|
34415
|
+
var import_fs_extra10 = __toESM(require_lib4(), 1);
|
|
34416
|
+
import path14 from "path";
|
|
34417
|
+
import os12 from "os";
|
|
34136
34418
|
async function getToolPaths(tool, customFolder) {
|
|
34137
34419
|
let baseDir;
|
|
34138
34420
|
switch (tool) {
|
|
34139
34421
|
case "claude-code":
|
|
34140
|
-
baseDir = customFolder ?
|
|
34422
|
+
baseDir = customFolder ? path14.resolve(customFolder) : path14.join(os12.homedir(), ".claude");
|
|
34141
34423
|
return {
|
|
34142
34424
|
baseDir,
|
|
34143
|
-
commandsPath:
|
|
34144
|
-
agentsPath:
|
|
34425
|
+
commandsPath: path14.join(baseDir, "commands"),
|
|
34426
|
+
agentsPath: path14.join(baseDir, "agents")
|
|
34145
34427
|
};
|
|
34146
34428
|
case "codex":
|
|
34147
|
-
baseDir = customFolder ?
|
|
34429
|
+
baseDir = customFolder ? path14.resolve(customFolder) : path14.join(os12.homedir(), ".codex");
|
|
34148
34430
|
return {
|
|
34149
34431
|
baseDir,
|
|
34150
|
-
agentsPath:
|
|
34432
|
+
agentsPath: path14.join(baseDir, "agents")
|
|
34151
34433
|
};
|
|
34152
34434
|
case "opencode":
|
|
34153
|
-
baseDir = customFolder ?
|
|
34435
|
+
baseDir = customFolder ? path14.resolve(customFolder) : path14.join(os12.homedir(), ".config", "opencode");
|
|
34154
34436
|
return {
|
|
34155
34437
|
baseDir,
|
|
34156
|
-
commandsPath:
|
|
34438
|
+
commandsPath: path14.join(baseDir, "command")
|
|
34157
34439
|
};
|
|
34158
34440
|
case "factoryai":
|
|
34159
|
-
baseDir = customFolder ?
|
|
34441
|
+
baseDir = customFolder ? path14.resolve(customFolder) : path14.join(os12.homedir(), ".factory");
|
|
34160
34442
|
return {
|
|
34161
34443
|
baseDir,
|
|
34162
|
-
commandsPath:
|
|
34163
|
-
agentsPath:
|
|
34444
|
+
commandsPath: path14.join(baseDir, "commands"),
|
|
34445
|
+
agentsPath: path14.join(baseDir, "droids")
|
|
34164
34446
|
};
|
|
34165
34447
|
default:
|
|
34166
34448
|
throw new Error(`Unknown tool type: ${tool}`);
|
|
@@ -34168,28 +34450,28 @@ async function getToolPaths(tool, customFolder) {
|
|
|
34168
34450
|
}
|
|
34169
34451
|
async function createSymlink(sourcePath, targetPath, options = {}) {
|
|
34170
34452
|
try {
|
|
34171
|
-
const sourceExists = await
|
|
34453
|
+
const sourceExists = await import_fs_extra10.default.pathExists(sourcePath);
|
|
34172
34454
|
if (!sourceExists) {
|
|
34173
34455
|
console.log(source_default.yellow(` Source path ${sourcePath} does not exist. Skipping symlink creation...`));
|
|
34174
34456
|
return false;
|
|
34175
34457
|
}
|
|
34176
|
-
const targetDir =
|
|
34177
|
-
await
|
|
34178
|
-
const targetExists = await
|
|
34458
|
+
const targetDir = path14.dirname(targetPath);
|
|
34459
|
+
await import_fs_extra10.default.ensureDir(targetDir);
|
|
34460
|
+
const targetExists = await import_fs_extra10.default.pathExists(targetPath);
|
|
34179
34461
|
if (targetExists) {
|
|
34180
|
-
const stat = await
|
|
34462
|
+
const stat = await import_fs_extra10.default.lstat(targetPath);
|
|
34181
34463
|
if (stat.isSymbolicLink()) {
|
|
34182
|
-
await
|
|
34464
|
+
await import_fs_extra10.default.remove(targetPath);
|
|
34183
34465
|
} else {
|
|
34184
34466
|
console.log(source_default.yellow(options.skipMessage || ` ${targetPath} already exists and is not a symlink. Skipping...`));
|
|
34185
34467
|
return false;
|
|
34186
34468
|
}
|
|
34187
34469
|
}
|
|
34188
|
-
const isWindows2 =
|
|
34470
|
+
const isWindows2 = os12.platform() === "win32";
|
|
34189
34471
|
if (isWindows2) {
|
|
34190
|
-
await
|
|
34472
|
+
await import_fs_extra10.default.symlink(sourcePath, targetPath, "junction");
|
|
34191
34473
|
} else {
|
|
34192
|
-
await
|
|
34474
|
+
await import_fs_extra10.default.symlink(sourcePath, targetPath);
|
|
34193
34475
|
}
|
|
34194
34476
|
return true;
|
|
34195
34477
|
} catch (error) {
|
|
@@ -35085,12 +35367,12 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
35085
35367
|
};
|
|
35086
35368
|
|
|
35087
35369
|
// src/commands/pro.ts
|
|
35088
|
-
import
|
|
35370
|
+
import path17 from "path";
|
|
35089
35371
|
|
|
35090
35372
|
// src/lib/pro-installer.ts
|
|
35091
|
-
var
|
|
35092
|
-
import
|
|
35093
|
-
import
|
|
35373
|
+
var import_fs_extra11 = __toESM(require_lib4(), 1);
|
|
35374
|
+
import os13 from "os";
|
|
35375
|
+
import path15 from "path";
|
|
35094
35376
|
import { exec as exec3 } from "child_process";
|
|
35095
35377
|
import { promisify as promisify2 } from "util";
|
|
35096
35378
|
var execAsync2 = promisify2(exec3);
|
|
@@ -35098,9 +35380,9 @@ var PREMIUM_REPO = "Melvynx/aiblueprint-cli-premium";
|
|
|
35098
35380
|
var PREMIUM_BRANCH = "main";
|
|
35099
35381
|
var CONFIG_FOLDER_CANDIDATES2 = ["agents-config", "ai-coding", "claude-code-config", "ai-config"];
|
|
35100
35382
|
function routePath(relativePath) {
|
|
35101
|
-
const segments = relativePath.split(
|
|
35383
|
+
const segments = relativePath.split(path15.sep);
|
|
35102
35384
|
const first = segments[0];
|
|
35103
|
-
const rest = segments.slice(1).join(
|
|
35385
|
+
const rest = segments.slice(1).join(path15.sep);
|
|
35104
35386
|
if (first === "claude-config") {
|
|
35105
35387
|
return { kind: "claude", relativePath: rest };
|
|
35106
35388
|
}
|
|
@@ -35116,7 +35398,7 @@ function routePath(relativePath) {
|
|
|
35116
35398
|
return { kind: "claude", relativePath };
|
|
35117
35399
|
}
|
|
35118
35400
|
function getCacheRepoDir() {
|
|
35119
|
-
return
|
|
35401
|
+
return path15.join(os13.homedir(), ".config", "aiblueprint", "pro-repos", "aiblueprint-cli-premium");
|
|
35120
35402
|
}
|
|
35121
35403
|
async function execGitWithAuth(command, token, repoUrl, cwd) {
|
|
35122
35404
|
const authenticatedUrl = `https://x-access-token:${token}@${repoUrl.replace(/^https?:\/\//, "")}`;
|
|
@@ -35130,21 +35412,21 @@ async function execGitWithAuth(command, token, repoUrl, cwd) {
|
|
|
35130
35412
|
async function cloneOrUpdateRepo(token) {
|
|
35131
35413
|
const cacheDir = getCacheRepoDir();
|
|
35132
35414
|
const repoUrl = `https://github.com/${PREMIUM_REPO}.git`;
|
|
35133
|
-
if (await
|
|
35415
|
+
if (await import_fs_extra11.default.pathExists(path15.join(cacheDir, ".git"))) {
|
|
35134
35416
|
try {
|
|
35135
35417
|
await execGitWithAuth("pull", token, repoUrl, cacheDir);
|
|
35136
35418
|
} catch (error) {
|
|
35137
|
-
await
|
|
35138
|
-
await
|
|
35419
|
+
await import_fs_extra11.default.remove(cacheDir);
|
|
35420
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(cacheDir));
|
|
35139
35421
|
await execGitWithAuth(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
35140
35422
|
}
|
|
35141
35423
|
} else {
|
|
35142
|
-
await
|
|
35424
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(cacheDir));
|
|
35143
35425
|
await execGitWithAuth(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
35144
35426
|
}
|
|
35145
35427
|
for (const candidate of CONFIG_FOLDER_CANDIDATES2) {
|
|
35146
|
-
const candidatePath =
|
|
35147
|
-
if (await
|
|
35428
|
+
const candidatePath = path15.join(cacheDir, candidate);
|
|
35429
|
+
if (await import_fs_extra11.default.pathExists(candidatePath)) {
|
|
35148
35430
|
return candidatePath;
|
|
35149
35431
|
}
|
|
35150
35432
|
}
|
|
@@ -35152,35 +35434,38 @@ async function cloneOrUpdateRepo(token) {
|
|
|
35152
35434
|
}
|
|
35153
35435
|
async function copyConfigFromCache(cacheConfigDir, dest, onProgress) {
|
|
35154
35436
|
const walk = async (dir, baseDir = dir) => {
|
|
35155
|
-
const entries = await
|
|
35437
|
+
const entries = await import_fs_extra11.default.readdir(dir, { withFileTypes: true });
|
|
35156
35438
|
for (const entry of entries) {
|
|
35157
35439
|
if (entry.name === ".DS_Store" || entry.name === "node_modules")
|
|
35158
35440
|
continue;
|
|
35159
|
-
const sourcePath =
|
|
35160
|
-
const relativePath =
|
|
35441
|
+
const sourcePath = path15.join(dir, entry.name);
|
|
35442
|
+
const relativePath = path15.relative(baseDir, sourcePath);
|
|
35161
35443
|
const route = routePath(relativePath);
|
|
35162
35444
|
if (route.kind === "skip")
|
|
35163
35445
|
continue;
|
|
35164
35446
|
if (route.kind === "agents-category") {
|
|
35165
|
-
if (relativePath.split(
|
|
35447
|
+
if (relativePath.split(path15.sep).length === 1) {
|
|
35166
35448
|
await copyAgentCategory(sourcePath, route.category, dest.agentsDir, dest.claudeDir, onProgress);
|
|
35167
35449
|
}
|
|
35168
35450
|
continue;
|
|
35169
35451
|
}
|
|
35170
35452
|
const targetBase = route.kind === "claude" ? dest.claudeDir : dest.codexDir;
|
|
35171
|
-
const targetPath =
|
|
35453
|
+
const targetPath = path15.join(targetBase, route.relativePath);
|
|
35172
35454
|
if (entry.isDirectory()) {
|
|
35173
|
-
await
|
|
35455
|
+
await import_fs_extra11.default.ensureDir(targetPath);
|
|
35174
35456
|
onProgress?.(relativePath, "directory");
|
|
35175
35457
|
await walk(sourcePath, baseDir);
|
|
35458
|
+
} else if (route.kind === "codex" && route.relativePath === "config.toml") {
|
|
35459
|
+
await mergeCodexConfigFile(sourcePath, dest.codexDir);
|
|
35460
|
+
onProgress?.(relativePath, "file");
|
|
35176
35461
|
} else if (isTextFile(entry.name)) {
|
|
35177
|
-
const content = await
|
|
35462
|
+
const content = await import_fs_extra11.default.readFile(sourcePath, "utf-8");
|
|
35178
35463
|
const replaced = replaceClaudePathPlaceholder(content, dest.claudeDir);
|
|
35179
|
-
await
|
|
35180
|
-
await
|
|
35464
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(targetPath));
|
|
35465
|
+
await import_fs_extra11.default.writeFile(targetPath, replaced, "utf-8");
|
|
35181
35466
|
onProgress?.(relativePath, "file");
|
|
35182
35467
|
} else {
|
|
35183
|
-
await
|
|
35468
|
+
await import_fs_extra11.default.copy(sourcePath, targetPath, { overwrite: true });
|
|
35184
35469
|
onProgress?.(relativePath, "file");
|
|
35185
35470
|
}
|
|
35186
35471
|
}
|
|
@@ -35188,21 +35473,21 @@ async function copyConfigFromCache(cacheConfigDir, dest, onProgress) {
|
|
|
35188
35473
|
await walk(cacheConfigDir);
|
|
35189
35474
|
}
|
|
35190
35475
|
async function copyAgentCategory(sourceCategoryDir, category, agentsDir, claudeDir, onProgress) {
|
|
35191
|
-
const agentsCategoryDir =
|
|
35192
|
-
await
|
|
35193
|
-
const entries = await
|
|
35476
|
+
const agentsCategoryDir = path15.join(agentsDir, category);
|
|
35477
|
+
await import_fs_extra11.default.ensureDir(agentsCategoryDir);
|
|
35478
|
+
const entries = await import_fs_extra11.default.readdir(sourceCategoryDir, { withFileTypes: true });
|
|
35194
35479
|
for (const entry of entries) {
|
|
35195
35480
|
if (entry.name === ".DS_Store")
|
|
35196
35481
|
continue;
|
|
35197
|
-
const src =
|
|
35198
|
-
const dst =
|
|
35199
|
-
const claudeTop =
|
|
35200
|
-
const claudeStat = await
|
|
35482
|
+
const src = path15.join(sourceCategoryDir, entry.name);
|
|
35483
|
+
const dst = path15.join(agentsCategoryDir, entry.name);
|
|
35484
|
+
const claudeTop = path15.join(claudeDir, category, entry.name);
|
|
35485
|
+
const claudeStat = await import_fs_extra11.default.lstat(claudeTop).catch(() => null);
|
|
35201
35486
|
if (claudeStat && !claudeStat.isSymbolicLink()) {
|
|
35202
35487
|
onProgress?.(`${category}/${entry.name} (skipped - real dir in claude)`, "file");
|
|
35203
35488
|
continue;
|
|
35204
35489
|
}
|
|
35205
|
-
await
|
|
35490
|
+
await import_fs_extra11.default.copy(src, dst, { overwrite: true });
|
|
35206
35491
|
await applyPathPlaceholders(dst, claudeDir);
|
|
35207
35492
|
onProgress?.(`${category}/${entry.name}`, entry.isDirectory() ? "directory" : "file");
|
|
35208
35493
|
}
|
|
@@ -35221,8 +35506,8 @@ async function downloadFromPrivateGitHub(repo, branch, relativePath, targetPath,
|
|
|
35221
35506
|
return false;
|
|
35222
35507
|
}
|
|
35223
35508
|
const content = await response.arrayBuffer();
|
|
35224
|
-
await
|
|
35225
|
-
await
|
|
35509
|
+
await import_fs_extra11.default.ensureDir(path15.dirname(targetPath));
|
|
35510
|
+
await import_fs_extra11.default.writeFile(targetPath, Buffer.from(content));
|
|
35226
35511
|
return true;
|
|
35227
35512
|
} catch (error) {
|
|
35228
35513
|
console.error(`Error downloading ${relativePath}:`, error);
|
|
@@ -35247,10 +35532,10 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
|
|
|
35247
35532
|
console.error(`Unexpected response for directory ${dirPath}`);
|
|
35248
35533
|
return false;
|
|
35249
35534
|
}
|
|
35250
|
-
await
|
|
35535
|
+
await import_fs_extra11.default.ensureDir(targetDir);
|
|
35251
35536
|
for (const file of files) {
|
|
35252
35537
|
const relativePath = dirPath ? `${dirPath}/${file.name}` : file.name;
|
|
35253
|
-
const targetPath =
|
|
35538
|
+
const targetPath = path15.join(targetDir, file.name);
|
|
35254
35539
|
const displayPath = relativePath.replace(/^(agents-config|ai-coding|claude-code-config|ai-config)\//, "");
|
|
35255
35540
|
if (file.type === "file") {
|
|
35256
35541
|
onProgress?.(displayPath, "file");
|
|
@@ -35273,8 +35558,8 @@ async function installProConfigs(options) {
|
|
|
35273
35558
|
codexFolder,
|
|
35274
35559
|
agentsFolder
|
|
35275
35560
|
});
|
|
35276
|
-
await
|
|
35277
|
-
await
|
|
35561
|
+
await import_fs_extra11.default.ensureDir(claudeDir);
|
|
35562
|
+
await import_fs_extra11.default.ensureDir(agentsDir);
|
|
35278
35563
|
const dest = { claudeDir, codexDir, agentsDir };
|
|
35279
35564
|
try {
|
|
35280
35565
|
const cacheConfigDir = await cloneOrUpdateRepo(githubToken);
|
|
@@ -35284,7 +35569,7 @@ async function installProConfigs(options) {
|
|
|
35284
35569
|
} catch (error) {
|
|
35285
35570
|
console.warn("Git caching failed, falling back to API download");
|
|
35286
35571
|
}
|
|
35287
|
-
const tempDir =
|
|
35572
|
+
const tempDir = path15.join(os13.tmpdir(), `aiblueprint-premium-${Date.now()}`);
|
|
35288
35573
|
try {
|
|
35289
35574
|
let success = false;
|
|
35290
35575
|
for (const candidate of CONFIG_FOLDER_CANDIDATES2) {
|
|
@@ -35298,8 +35583,8 @@ async function installProConfigs(options) {
|
|
|
35298
35583
|
await copyConfigFromCache(tempDir, dest, onProgress);
|
|
35299
35584
|
await replacePathPlaceholdersInDir(claudeDir, claudeDir);
|
|
35300
35585
|
for (const category of AGENT_CATEGORIES) {
|
|
35301
|
-
const agentsCategoryDir =
|
|
35302
|
-
if (await
|
|
35586
|
+
const agentsCategoryDir = path15.join(agentsDir, category);
|
|
35587
|
+
if (await import_fs_extra11.default.pathExists(agentsCategoryDir)) {
|
|
35303
35588
|
await replacePathPlaceholdersInDir(agentsCategoryDir, claudeDir);
|
|
35304
35589
|
}
|
|
35305
35590
|
}
|
|
@@ -35308,7 +35593,7 @@ async function installProConfigs(options) {
|
|
|
35308
35593
|
throw new Error(`Failed to install premium configs: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
35309
35594
|
} finally {
|
|
35310
35595
|
try {
|
|
35311
|
-
await
|
|
35596
|
+
await import_fs_extra11.default.remove(tempDir);
|
|
35312
35597
|
} catch {}
|
|
35313
35598
|
}
|
|
35314
35599
|
}
|
|
@@ -35319,27 +35604,27 @@ async function syncAllAgentSymlinks(agentsDir, claudeDir) {
|
|
|
35319
35604
|
}
|
|
35320
35605
|
|
|
35321
35606
|
// src/lib/token-storage.ts
|
|
35322
|
-
var
|
|
35323
|
-
import
|
|
35324
|
-
import
|
|
35607
|
+
var import_fs_extra12 = __toESM(require_lib4(), 1);
|
|
35608
|
+
import os14 from "os";
|
|
35609
|
+
import path16 from "path";
|
|
35325
35610
|
function getConfigDir() {
|
|
35326
|
-
const platform =
|
|
35611
|
+
const platform = os14.platform();
|
|
35327
35612
|
if (platform === "win32") {
|
|
35328
|
-
const appData = process.env.APPDATA ||
|
|
35329
|
-
return
|
|
35613
|
+
const appData = process.env.APPDATA || path16.join(os14.homedir(), "AppData", "Roaming");
|
|
35614
|
+
return path16.join(appData, "aiblueprint");
|
|
35330
35615
|
} else {
|
|
35331
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
35332
|
-
return
|
|
35616
|
+
const configHome = process.env.XDG_CONFIG_HOME || path16.join(os14.homedir(), ".config");
|
|
35617
|
+
return path16.join(configHome, "aiblueprint");
|
|
35333
35618
|
}
|
|
35334
35619
|
}
|
|
35335
35620
|
function getTokenFilePath2() {
|
|
35336
|
-
return
|
|
35621
|
+
return path16.join(getConfigDir(), "token.txt");
|
|
35337
35622
|
}
|
|
35338
35623
|
async function saveToken(githubToken) {
|
|
35339
35624
|
const tokenFile = getTokenFilePath2();
|
|
35340
|
-
const configDir =
|
|
35625
|
+
const configDir = path16.dirname(tokenFile);
|
|
35341
35626
|
try {
|
|
35342
|
-
await
|
|
35627
|
+
await import_fs_extra12.default.ensureDir(configDir);
|
|
35343
35628
|
} catch (error) {
|
|
35344
35629
|
if (error.code === "EACCES") {
|
|
35345
35630
|
throw new Error(`Permission denied creating config directory: ${configDir}
|
|
@@ -35347,15 +35632,15 @@ async function saveToken(githubToken) {
|
|
|
35347
35632
|
}
|
|
35348
35633
|
throw error;
|
|
35349
35634
|
}
|
|
35350
|
-
await
|
|
35635
|
+
await import_fs_extra12.default.writeFile(tokenFile, githubToken, { mode: 384 });
|
|
35351
35636
|
}
|
|
35352
35637
|
async function getToken() {
|
|
35353
35638
|
const tokenFile = getTokenFilePath2();
|
|
35354
|
-
if (!await
|
|
35639
|
+
if (!await import_fs_extra12.default.pathExists(tokenFile)) {
|
|
35355
35640
|
return null;
|
|
35356
35641
|
}
|
|
35357
35642
|
try {
|
|
35358
|
-
const token = await
|
|
35643
|
+
const token = await import_fs_extra12.default.readFile(tokenFile, "utf-8");
|
|
35359
35644
|
return token.trim();
|
|
35360
35645
|
} catch (error) {
|
|
35361
35646
|
return null;
|
|
@@ -35364,12 +35649,12 @@ async function getToken() {
|
|
|
35364
35649
|
function getTokenInfo() {
|
|
35365
35650
|
return {
|
|
35366
35651
|
path: getTokenFilePath2(),
|
|
35367
|
-
platform:
|
|
35652
|
+
platform: os14.platform()
|
|
35368
35653
|
};
|
|
35369
35654
|
}
|
|
35370
35655
|
|
|
35371
35656
|
// src/commands/pro.ts
|
|
35372
|
-
var
|
|
35657
|
+
var import_fs_extra13 = __toESM(require_lib4(), 1);
|
|
35373
35658
|
var API_URL = "https://codeline.app/api/products";
|
|
35374
35659
|
var PRODUCT_IDS = ["prd_XJVgxVPbGG", "prd_NKabAkdOkw"];
|
|
35375
35660
|
async function countInstalledItems(claudeDir) {
|
|
@@ -35378,20 +35663,20 @@ async function countInstalledItems(claudeDir) {
|
|
|
35378
35663
|
skills: 0
|
|
35379
35664
|
};
|
|
35380
35665
|
try {
|
|
35381
|
-
const agentsDir =
|
|
35382
|
-
if (await
|
|
35383
|
-
const files = await
|
|
35666
|
+
const agentsDir = path17.join(claudeDir, "agents");
|
|
35667
|
+
if (await import_fs_extra13.default.pathExists(agentsDir)) {
|
|
35668
|
+
const files = await import_fs_extra13.default.readdir(agentsDir);
|
|
35384
35669
|
counts.agents = files.filter((f) => f.endsWith(".md")).length;
|
|
35385
35670
|
}
|
|
35386
35671
|
} catch (error) {
|
|
35387
35672
|
console.error("Failed to count agents:", error instanceof Error ? error.message : error);
|
|
35388
35673
|
}
|
|
35389
35674
|
try {
|
|
35390
|
-
const skillsDir =
|
|
35391
|
-
if (await
|
|
35392
|
-
const items = await
|
|
35675
|
+
const skillsDir = path17.join(claudeDir, "skills");
|
|
35676
|
+
if (await import_fs_extra13.default.pathExists(skillsDir)) {
|
|
35677
|
+
const items = await import_fs_extra13.default.readdir(skillsDir);
|
|
35393
35678
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
35394
|
-
const stat = await
|
|
35679
|
+
const stat = await import_fs_extra13.default.stat(path17.join(skillsDir, item));
|
|
35395
35680
|
return stat.isDirectory();
|
|
35396
35681
|
}));
|
|
35397
35682
|
counts.skills = dirs.filter(Boolean).length;
|
|
@@ -35599,8 +35884,8 @@ async function proUpdateCommand(options = {}) {
|
|
|
35599
35884
|
}
|
|
35600
35885
|
|
|
35601
35886
|
// src/lib/sync-utils.ts
|
|
35602
|
-
var
|
|
35603
|
-
import
|
|
35887
|
+
var import_fs_extra14 = __toESM(require_lib4(), 1);
|
|
35888
|
+
import path18 from "path";
|
|
35604
35889
|
import crypto from "crypto";
|
|
35605
35890
|
var PREMIUM_REPO2 = "Melvynx/aiblueprint-cli-premium";
|
|
35606
35891
|
var PREMIUM_BRANCH2 = "main";
|
|
@@ -35671,7 +35956,7 @@ async function listRemoteFilesRecursive(dirPath, githubToken, basePath = "") {
|
|
|
35671
35956
|
}
|
|
35672
35957
|
async function computeLocalFileSha(filePath) {
|
|
35673
35958
|
try {
|
|
35674
|
-
const content = await
|
|
35959
|
+
const content = await import_fs_extra14.default.readFile(filePath);
|
|
35675
35960
|
return computeFileSha(content);
|
|
35676
35961
|
} catch {
|
|
35677
35962
|
return null;
|
|
@@ -35679,15 +35964,15 @@ async function computeLocalFileSha(filePath) {
|
|
|
35679
35964
|
}
|
|
35680
35965
|
async function listLocalFiles(dir) {
|
|
35681
35966
|
const files = [];
|
|
35682
|
-
if (!await
|
|
35967
|
+
if (!await import_fs_extra14.default.pathExists(dir)) {
|
|
35683
35968
|
return files;
|
|
35684
35969
|
}
|
|
35685
|
-
const items = await
|
|
35970
|
+
const items = await import_fs_extra14.default.readdir(dir);
|
|
35686
35971
|
for (const item of items) {
|
|
35687
35972
|
if (item === "node_modules" || item === ".DS_Store")
|
|
35688
35973
|
continue;
|
|
35689
|
-
const fullPath =
|
|
35690
|
-
const stat = await
|
|
35974
|
+
const fullPath = path18.join(dir, item);
|
|
35975
|
+
const stat = await import_fs_extra14.default.stat(fullPath).catch(() => null);
|
|
35691
35976
|
if (!stat)
|
|
35692
35977
|
continue;
|
|
35693
35978
|
if (stat.isDirectory()) {
|
|
@@ -35702,13 +35987,13 @@ async function listLocalFiles(dir) {
|
|
|
35702
35987
|
}
|
|
35703
35988
|
async function listLocalFilesRecursive(dir, basePath) {
|
|
35704
35989
|
const files = [];
|
|
35705
|
-
const items = await
|
|
35990
|
+
const items = await import_fs_extra14.default.readdir(dir).catch(() => []);
|
|
35706
35991
|
for (const item of items) {
|
|
35707
35992
|
if (item === "node_modules" || item === ".DS_Store")
|
|
35708
35993
|
continue;
|
|
35709
|
-
const fullPath =
|
|
35994
|
+
const fullPath = path18.join(dir, item);
|
|
35710
35995
|
const relativePath = `${basePath}/${item}`;
|
|
35711
|
-
const stat = await
|
|
35996
|
+
const stat = await import_fs_extra14.default.stat(fullPath).catch(() => null);
|
|
35712
35997
|
if (!stat)
|
|
35713
35998
|
continue;
|
|
35714
35999
|
if (stat.isDirectory()) {
|
|
@@ -35722,14 +36007,14 @@ async function listLocalFilesRecursive(dir, basePath) {
|
|
|
35722
36007
|
return files;
|
|
35723
36008
|
}
|
|
35724
36009
|
async function listClaudeRealTopLevel(claudeCategoryDir) {
|
|
35725
|
-
if (!await
|
|
36010
|
+
if (!await import_fs_extra14.default.pathExists(claudeCategoryDir))
|
|
35726
36011
|
return [];
|
|
35727
|
-
const entries = await
|
|
36012
|
+
const entries = await import_fs_extra14.default.readdir(claudeCategoryDir).catch(() => []);
|
|
35728
36013
|
const real = [];
|
|
35729
36014
|
for (const name of entries) {
|
|
35730
36015
|
if (name === "node_modules" || name === ".DS_Store")
|
|
35731
36016
|
continue;
|
|
35732
|
-
const stat = await
|
|
36017
|
+
const stat = await import_fs_extra14.default.lstat(path18.join(claudeCategoryDir, name)).catch(() => null);
|
|
35733
36018
|
if (!stat)
|
|
35734
36019
|
continue;
|
|
35735
36020
|
if (stat.isDirectory())
|
|
@@ -35746,7 +36031,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
35746
36031
|
const items = [];
|
|
35747
36032
|
const useAgents = isAgentCategory(category);
|
|
35748
36033
|
const localBase = useAgents ? agentsDir : claudeDir;
|
|
35749
|
-
const localDir =
|
|
36034
|
+
const localDir = path18.join(localBase, category);
|
|
35750
36035
|
const remoteCategoryPath = getRemoteCategoryPath(category);
|
|
35751
36036
|
const remoteFiles = await listRemoteFilesRecursive(remoteCategoryPath, githubToken);
|
|
35752
36037
|
const localFiles = await listLocalFiles(localDir);
|
|
@@ -35760,7 +36045,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
35760
36045
|
}
|
|
35761
36046
|
const localSet = new Set(localFiles);
|
|
35762
36047
|
for (const [remotePath, { sha, isFolder }] of remoteSet) {
|
|
35763
|
-
const localPath =
|
|
36048
|
+
const localPath = path18.join(localDir, remotePath);
|
|
35764
36049
|
if (isFolder) {
|
|
35765
36050
|
continue;
|
|
35766
36051
|
}
|
|
@@ -35795,7 +36080,7 @@ async function analyzeCategory(category, claudeDir, agentsDir, githubToken) {
|
|
|
35795
36080
|
for (const localPath of localSet) {
|
|
35796
36081
|
agentsTopLevels.add(localPath.split("/")[0]);
|
|
35797
36082
|
}
|
|
35798
|
-
const claudeCategoryDir =
|
|
36083
|
+
const claudeCategoryDir = path18.join(claudeDir, category);
|
|
35799
36084
|
const claudeRealEntries = await listClaudeRealTopLevel(claudeCategoryDir);
|
|
35800
36085
|
for (const top of claudeRealEntries) {
|
|
35801
36086
|
if (!remoteTopLevels.has(top))
|
|
@@ -35854,13 +36139,13 @@ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken,
|
|
|
35854
36139
|
return false;
|
|
35855
36140
|
}
|
|
35856
36141
|
const content = await response.arrayBuffer();
|
|
35857
|
-
await
|
|
36142
|
+
await import_fs_extra14.default.ensureDir(path18.dirname(targetPath));
|
|
35858
36143
|
if (isTextFile(relativePath)) {
|
|
35859
36144
|
const textContent = Buffer.from(content).toString("utf-8");
|
|
35860
36145
|
const transformedContent = transformFileContent(textContent, claudeDir);
|
|
35861
|
-
await
|
|
36146
|
+
await import_fs_extra14.default.writeFile(targetPath, transformedContent, "utf-8");
|
|
35862
36147
|
} else {
|
|
35863
|
-
await
|
|
36148
|
+
await import_fs_extra14.default.writeFile(targetPath, Buffer.from(content));
|
|
35864
36149
|
}
|
|
35865
36150
|
return true;
|
|
35866
36151
|
} catch {
|
|
@@ -35876,27 +36161,27 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
35876
36161
|
for (const item of items) {
|
|
35877
36162
|
const useAgents = isAgentCategory(item.category);
|
|
35878
36163
|
const baseDir = useAgents ? agentsDir : claudeDir;
|
|
35879
|
-
const targetPath =
|
|
36164
|
+
const targetPath = path18.join(baseDir, item.relativePath);
|
|
35880
36165
|
if (item.status === "migration" && useAgents) {
|
|
35881
36166
|
const topName = item.name.split("/")[0];
|
|
35882
|
-
const agentsTop =
|
|
35883
|
-
const claudeTop =
|
|
36167
|
+
const agentsTop = path18.join(agentsDir, item.category, topName);
|
|
36168
|
+
const claudeTop = path18.join(claudeDir, item.category, topName);
|
|
35884
36169
|
try {
|
|
35885
|
-
const claudeStat = await
|
|
36170
|
+
const claudeStat = await import_fs_extra14.default.lstat(claudeTop).catch(() => null);
|
|
35886
36171
|
if (!claudeStat || claudeStat.isSymbolicLink()) {
|
|
35887
36172
|
onProgress?.(item.relativePath, "skipping (no real dir to migrate)");
|
|
35888
36173
|
failed++;
|
|
35889
36174
|
continue;
|
|
35890
36175
|
}
|
|
35891
|
-
const agentsExists = await
|
|
36176
|
+
const agentsExists = await import_fs_extra14.default.pathExists(agentsTop);
|
|
35892
36177
|
if (agentsExists) {
|
|
35893
36178
|
onProgress?.(item.relativePath, "skipping (already in .agents)");
|
|
35894
36179
|
failed++;
|
|
35895
36180
|
continue;
|
|
35896
36181
|
}
|
|
35897
36182
|
onProgress?.(item.relativePath, "moving to .agents");
|
|
35898
|
-
await
|
|
35899
|
-
await
|
|
36183
|
+
await import_fs_extra14.default.ensureDir(path18.dirname(agentsTop));
|
|
36184
|
+
await import_fs_extra14.default.move(claudeTop, agentsTop);
|
|
35900
36185
|
migrated++;
|
|
35901
36186
|
touchedAgentCategories.add(item.category);
|
|
35902
36187
|
} catch {
|
|
@@ -35906,8 +36191,8 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
35906
36191
|
}
|
|
35907
36192
|
if (useAgents) {
|
|
35908
36193
|
const topName = item.name.split("/")[0];
|
|
35909
|
-
const claudeTop =
|
|
35910
|
-
const claudeTopStat = await
|
|
36194
|
+
const claudeTop = path18.join(claudeDir, item.category, topName);
|
|
36195
|
+
const claudeTopStat = await import_fs_extra14.default.lstat(claudeTop).catch(() => null);
|
|
35911
36196
|
if (claudeTopStat && !claudeTopStat.isSymbolicLink()) {
|
|
35912
36197
|
onProgress?.(item.relativePath, "skipping (real dir in .claude)");
|
|
35913
36198
|
failed++;
|
|
@@ -35917,7 +36202,7 @@ async function syncSelectedItems(claudeDir, items, githubToken, agentsDir, onPro
|
|
|
35917
36202
|
if (item.status === "deleted") {
|
|
35918
36203
|
onProgress?.(item.relativePath, "deleting");
|
|
35919
36204
|
try {
|
|
35920
|
-
await
|
|
36205
|
+
await import_fs_extra14.default.remove(targetPath);
|
|
35921
36206
|
deleted++;
|
|
35922
36207
|
if (useAgents)
|
|
35923
36208
|
touchedAgentCategories.add(item.category);
|
|
@@ -36198,7 +36483,7 @@ async function proSyncCommand(options = {}) {
|
|
|
36198
36483
|
M2.message(source_default.yellow(` ✓ Update ${toUpdate} file${toUpdate > 1 ? "s" : ""}`));
|
|
36199
36484
|
if (toMigrate > 0)
|
|
36200
36485
|
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 ~/.
|
|
36486
|
+
M2.message(source_default.gray(` ✓ Backup current config to ~/.aiblueprint/backups/`));
|
|
36202
36487
|
M2.message("");
|
|
36203
36488
|
const confirmResult = await ye({
|
|
36204
36489
|
message: "Proceed with sync?",
|
|
@@ -36209,7 +36494,7 @@ async function proSyncCommand(options = {}) {
|
|
|
36209
36494
|
process.exit(0);
|
|
36210
36495
|
}
|
|
36211
36496
|
spinner.start("Creating backup...");
|
|
36212
|
-
const backupPath = await
|
|
36497
|
+
const backupPath = await createConfigBackup(options, "Before syncing premium aiblueprint configuration", "sync", "aiblueprint-sync");
|
|
36213
36498
|
if (backupPath) {
|
|
36214
36499
|
spinner.stop(`Backup created: ${source_default.gray(backupPath)}`);
|
|
36215
36500
|
} else {
|
|
@@ -36254,6 +36539,106 @@ async function proSyncCommand(options = {}) {
|
|
|
36254
36539
|
}
|
|
36255
36540
|
}
|
|
36256
36541
|
|
|
36542
|
+
// src/lib/backup-utils.ts
|
|
36543
|
+
var import_fs_extra15 = __toESM(require_lib4(), 1);
|
|
36544
|
+
import path19 from "path";
|
|
36545
|
+
import os15 from "os";
|
|
36546
|
+
var BACKUP_BASE_DIR = path19.join(os15.homedir(), ".config", "aiblueprint", "backup");
|
|
36547
|
+
function formatDate(date) {
|
|
36548
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
36549
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
|
|
36550
|
+
}
|
|
36551
|
+
async function listBackups() {
|
|
36552
|
+
const exists = await import_fs_extra15.default.pathExists(BACKUP_BASE_DIR);
|
|
36553
|
+
if (!exists) {
|
|
36554
|
+
return [];
|
|
36555
|
+
}
|
|
36556
|
+
const entries = await import_fs_extra15.default.readdir(BACKUP_BASE_DIR, { withFileTypes: true });
|
|
36557
|
+
const backups = [];
|
|
36558
|
+
for (const entry of entries) {
|
|
36559
|
+
if (!entry.isDirectory())
|
|
36560
|
+
continue;
|
|
36561
|
+
const match = entry.name.match(/^(\d{4})-(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})$/);
|
|
36562
|
+
if (!match)
|
|
36563
|
+
continue;
|
|
36564
|
+
const [, year, month, day, hour, minute, second] = match;
|
|
36565
|
+
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
|
|
36566
|
+
backups.push({
|
|
36567
|
+
name: entry.name,
|
|
36568
|
+
path: path19.join(BACKUP_BASE_DIR, entry.name),
|
|
36569
|
+
date
|
|
36570
|
+
});
|
|
36571
|
+
}
|
|
36572
|
+
return backups.sort((a, b3) => b3.date.getTime() - a.date.getTime());
|
|
36573
|
+
}
|
|
36574
|
+
var AGENTS_BACKUP_SUBDIR = ".agents";
|
|
36575
|
+
var CLAUDE_ITEMS = ["commands", "agents", "skills", "scripts", "settings.json"];
|
|
36576
|
+
async function copyForBackup(sourcePath, destPath) {
|
|
36577
|
+
await import_fs_extra15.default.copy(sourcePath, destPath, {
|
|
36578
|
+
overwrite: true,
|
|
36579
|
+
dereference: false,
|
|
36580
|
+
filter: async (src) => {
|
|
36581
|
+
try {
|
|
36582
|
+
const stat = await import_fs_extra15.default.lstat(src);
|
|
36583
|
+
return !stat.isSymbolicLink();
|
|
36584
|
+
} catch {
|
|
36585
|
+
return true;
|
|
36586
|
+
}
|
|
36587
|
+
}
|
|
36588
|
+
});
|
|
36589
|
+
}
|
|
36590
|
+
async function hasMeaningfulContent(dir) {
|
|
36591
|
+
if (!await import_fs_extra15.default.pathExists(dir))
|
|
36592
|
+
return false;
|
|
36593
|
+
const files = await import_fs_extra15.default.readdir(dir);
|
|
36594
|
+
return files.some((f) => f !== ".DS_Store");
|
|
36595
|
+
}
|
|
36596
|
+
async function loadBackup(backupPath, claudeDir, agentsDir) {
|
|
36597
|
+
const exists = await import_fs_extra15.default.pathExists(backupPath);
|
|
36598
|
+
if (!exists) {
|
|
36599
|
+
throw new Error(`Backup not found: ${backupPath}`);
|
|
36600
|
+
}
|
|
36601
|
+
await import_fs_extra15.default.ensureDir(claudeDir);
|
|
36602
|
+
for (const item of CLAUDE_ITEMS) {
|
|
36603
|
+
const sourcePath = path19.join(backupPath, item);
|
|
36604
|
+
const destPath = path19.join(claudeDir, item);
|
|
36605
|
+
if (await import_fs_extra15.default.pathExists(sourcePath)) {
|
|
36606
|
+
await copyForBackup(sourcePath, destPath);
|
|
36607
|
+
}
|
|
36608
|
+
}
|
|
36609
|
+
if (agentsDir) {
|
|
36610
|
+
const agentsBackupPath = path19.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
36611
|
+
if (await import_fs_extra15.default.pathExists(agentsBackupPath)) {
|
|
36612
|
+
await import_fs_extra15.default.ensureDir(agentsDir);
|
|
36613
|
+
await copyForBackup(agentsBackupPath, agentsDir);
|
|
36614
|
+
}
|
|
36615
|
+
}
|
|
36616
|
+
}
|
|
36617
|
+
async function createBackup(claudeDir, agentsDir) {
|
|
36618
|
+
const claudeHasContent = await hasMeaningfulContent(claudeDir);
|
|
36619
|
+
const agentsHasContent = agentsDir ? await hasMeaningfulContent(agentsDir) : false;
|
|
36620
|
+
if (!claudeHasContent && !agentsHasContent) {
|
|
36621
|
+
return null;
|
|
36622
|
+
}
|
|
36623
|
+
const timestamp2 = formatDate(new Date);
|
|
36624
|
+
const backupPath = path19.join(BACKUP_BASE_DIR, timestamp2);
|
|
36625
|
+
await import_fs_extra15.default.ensureDir(backupPath);
|
|
36626
|
+
if (claudeHasContent) {
|
|
36627
|
+
for (const item of CLAUDE_ITEMS) {
|
|
36628
|
+
const sourcePath = path19.join(claudeDir, item);
|
|
36629
|
+
const destPath = path19.join(backupPath, item);
|
|
36630
|
+
if (await import_fs_extra15.default.pathExists(sourcePath)) {
|
|
36631
|
+
await copyForBackup(sourcePath, destPath);
|
|
36632
|
+
}
|
|
36633
|
+
}
|
|
36634
|
+
}
|
|
36635
|
+
if (agentsHasContent && agentsDir) {
|
|
36636
|
+
const destPath = path19.join(backupPath, AGENTS_BACKUP_SUBDIR);
|
|
36637
|
+
await copyForBackup(agentsDir, destPath);
|
|
36638
|
+
}
|
|
36639
|
+
return backupPath;
|
|
36640
|
+
}
|
|
36641
|
+
|
|
36257
36642
|
// src/commands/backup.ts
|
|
36258
36643
|
function formatBackupDate(date) {
|
|
36259
36644
|
const now = new Date;
|
|
@@ -36329,20 +36714,116 @@ async function backupLoadCommand(options = {}) {
|
|
|
36329
36714
|
}
|
|
36330
36715
|
}
|
|
36331
36716
|
|
|
36717
|
+
// src/commands/configs.ts
|
|
36718
|
+
function formatDate2(iso) {
|
|
36719
|
+
const date = new Date(iso);
|
|
36720
|
+
if (Number.isNaN(date.getTime()))
|
|
36721
|
+
return "unknown date";
|
|
36722
|
+
return date.toLocaleString();
|
|
36723
|
+
}
|
|
36724
|
+
function formatFolders(folders) {
|
|
36725
|
+
return folders.length > 0 ? folders.join(", ") : "unknown folders";
|
|
36726
|
+
}
|
|
36727
|
+
function printSnapshots(title, snapshots) {
|
|
36728
|
+
console.log(source_default.blue(title));
|
|
36729
|
+
if (snapshots.length === 0) {
|
|
36730
|
+
console.log(source_default.gray("No entries found."));
|
|
36731
|
+
return;
|
|
36732
|
+
}
|
|
36733
|
+
for (const snapshot of snapshots) {
|
|
36734
|
+
console.log(`${source_default.cyan(snapshot.name)} ${source_default.gray(formatDate2(snapshot.metadata.createdAt))}`);
|
|
36735
|
+
console.log(source_default.gray(` reason: ${snapshot.metadata.reason}`));
|
|
36736
|
+
console.log(source_default.gray(` trigger: ${snapshot.metadata.trigger}`));
|
|
36737
|
+
console.log(source_default.gray(` folders: ${formatFolders(snapshot.metadata.folders)}`));
|
|
36738
|
+
console.log(source_default.gray(` path: ${snapshot.path}`));
|
|
36739
|
+
}
|
|
36740
|
+
}
|
|
36741
|
+
async function configsSaveCommand(name, options = {}) {
|
|
36742
|
+
try {
|
|
36743
|
+
const snapshotPath = await saveNamedConfig(name, options);
|
|
36744
|
+
console.log(source_default.green(`Saved config "${name}"`));
|
|
36745
|
+
console.log(source_default.gray(snapshotPath));
|
|
36746
|
+
} catch (error) {
|
|
36747
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36748
|
+
process.exit(1);
|
|
36749
|
+
}
|
|
36750
|
+
}
|
|
36751
|
+
async function configsLoadCommand(name, options = {}) {
|
|
36752
|
+
try {
|
|
36753
|
+
const result = await loadNamedConfig(name, options);
|
|
36754
|
+
console.log(source_default.green(`Loaded config "${name}"`));
|
|
36755
|
+
if (result.backupPath) {
|
|
36756
|
+
console.log(source_default.gray(`Previous config backed up to ${result.backupPath}`));
|
|
36757
|
+
}
|
|
36758
|
+
console.log(source_default.gray(`Restored: ${formatFolders(result.restored)}`));
|
|
36759
|
+
} catch (error) {
|
|
36760
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36761
|
+
process.exit(1);
|
|
36762
|
+
}
|
|
36763
|
+
}
|
|
36764
|
+
async function configsUndoCommand(options = {}) {
|
|
36765
|
+
try {
|
|
36766
|
+
const result = await undoLastLoad(options);
|
|
36767
|
+
console.log(source_default.green(`Undid last config load using backup "${result.backupName}"`));
|
|
36768
|
+
if (result.backupPath) {
|
|
36769
|
+
console.log(source_default.gray(`Current config backed up to ${result.backupPath}`));
|
|
36770
|
+
}
|
|
36771
|
+
console.log(source_default.gray(`Restored: ${formatFolders(result.restored)}`));
|
|
36772
|
+
} catch (error) {
|
|
36773
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36774
|
+
process.exit(1);
|
|
36775
|
+
}
|
|
36776
|
+
}
|
|
36777
|
+
async function configsListCommand(options = {}) {
|
|
36778
|
+
const configs = await listSavedConfigs(options);
|
|
36779
|
+
printSnapshots("Saved configs", configs);
|
|
36780
|
+
}
|
|
36781
|
+
async function configsBackupsListCommand(options = {}) {
|
|
36782
|
+
const backups = await listConfigBackups(options);
|
|
36783
|
+
printSnapshots("Config backups", backups);
|
|
36784
|
+
}
|
|
36785
|
+
async function configsBackupsLoadCommand(name, options = {}) {
|
|
36786
|
+
try {
|
|
36787
|
+
const result = await loadBackupSnapshot(name, options);
|
|
36788
|
+
console.log(source_default.green(`Loaded backup "${name}"`));
|
|
36789
|
+
if (result.backupPath) {
|
|
36790
|
+
console.log(source_default.gray(`Previous config backed up to ${result.backupPath}`));
|
|
36791
|
+
}
|
|
36792
|
+
console.log(source_default.gray(`Restored: ${formatFolders(result.restored)}`));
|
|
36793
|
+
} catch (error) {
|
|
36794
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36795
|
+
process.exit(1);
|
|
36796
|
+
}
|
|
36797
|
+
}
|
|
36798
|
+
async function configsBackupsCreateCommand(reason, options = {}) {
|
|
36799
|
+
try {
|
|
36800
|
+
const backupPath = await createConfigBackup(options, reason ?? "Manual backup from configs backups create", "manual-backup", "manual");
|
|
36801
|
+
if (!backupPath) {
|
|
36802
|
+
console.log(source_default.gray("No .claude, .codex, or .agents configuration found to backup."));
|
|
36803
|
+
return;
|
|
36804
|
+
}
|
|
36805
|
+
console.log(source_default.green("Backup created"));
|
|
36806
|
+
console.log(source_default.gray(backupPath));
|
|
36807
|
+
} catch (error) {
|
|
36808
|
+
console.error(source_default.red(error instanceof Error ? error.message : String(error)));
|
|
36809
|
+
process.exit(1);
|
|
36810
|
+
}
|
|
36811
|
+
}
|
|
36812
|
+
|
|
36332
36813
|
// src/commands/openclaw-pro.ts
|
|
36333
36814
|
import os18 from "os";
|
|
36334
|
-
import
|
|
36815
|
+
import path22 from "path";
|
|
36335
36816
|
|
|
36336
36817
|
// src/lib/openclaw-installer.ts
|
|
36337
|
-
var
|
|
36818
|
+
var import_fs_extra16 = __toESM(require_lib4(), 1);
|
|
36338
36819
|
import os16 from "os";
|
|
36339
|
-
import
|
|
36820
|
+
import path20 from "path";
|
|
36340
36821
|
import { exec as exec4 } from "child_process";
|
|
36341
36822
|
import { promisify as promisify3 } from "util";
|
|
36342
36823
|
var execAsync3 = promisify3(exec4);
|
|
36343
36824
|
var OPENCLAW_PRO_REPO = "Melvynx/openclawpro";
|
|
36344
36825
|
function getCacheRepoDir2() {
|
|
36345
|
-
return
|
|
36826
|
+
return path20.join(os16.homedir(), ".config", "openclaw", "pro-repos", "openclawpro");
|
|
36346
36827
|
}
|
|
36347
36828
|
async function execGitWithAuth2(command, token, repoUrl, cwd) {
|
|
36348
36829
|
const authenticatedUrl = `https://x-access-token:${token}@${repoUrl.replace(/^https?:\/\//, "")}`;
|
|
@@ -36356,33 +36837,33 @@ async function execGitWithAuth2(command, token, repoUrl, cwd) {
|
|
|
36356
36837
|
async function cloneOrUpdateRepo2(token) {
|
|
36357
36838
|
const cacheDir = getCacheRepoDir2();
|
|
36358
36839
|
const repoUrl = `https://github.com/${OPENCLAW_PRO_REPO}.git`;
|
|
36359
|
-
if (await
|
|
36840
|
+
if (await import_fs_extra16.default.pathExists(path20.join(cacheDir, ".git"))) {
|
|
36360
36841
|
try {
|
|
36361
36842
|
await execGitWithAuth2("pull", token, repoUrl, cacheDir);
|
|
36362
36843
|
} catch (error) {
|
|
36363
|
-
await
|
|
36364
|
-
await
|
|
36844
|
+
await import_fs_extra16.default.remove(cacheDir);
|
|
36845
|
+
await import_fs_extra16.default.ensureDir(path20.dirname(cacheDir));
|
|
36365
36846
|
await execGitWithAuth2(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
36366
36847
|
}
|
|
36367
36848
|
} else {
|
|
36368
|
-
await
|
|
36849
|
+
await import_fs_extra16.default.ensureDir(path20.dirname(cacheDir));
|
|
36369
36850
|
await execGitWithAuth2(`clone ${repoUrl} ${cacheDir}`, token, repoUrl);
|
|
36370
36851
|
}
|
|
36371
|
-
return
|
|
36852
|
+
return path20.join(cacheDir, "openclaw-config");
|
|
36372
36853
|
}
|
|
36373
36854
|
async function copyConfigFromCache2(cacheConfigDir, targetDir, onProgress) {
|
|
36374
36855
|
const walk = async (dir, baseDir = dir) => {
|
|
36375
|
-
const entries = await
|
|
36856
|
+
const entries = await import_fs_extra16.default.readdir(dir, { withFileTypes: true });
|
|
36376
36857
|
for (const entry of entries) {
|
|
36377
|
-
const sourcePath =
|
|
36378
|
-
const relativePath =
|
|
36379
|
-
const targetPath =
|
|
36858
|
+
const sourcePath = path20.join(dir, entry.name);
|
|
36859
|
+
const relativePath = path20.relative(baseDir, sourcePath);
|
|
36860
|
+
const targetPath = path20.join(targetDir, relativePath);
|
|
36380
36861
|
if (entry.isDirectory()) {
|
|
36381
|
-
await
|
|
36862
|
+
await import_fs_extra16.default.ensureDir(targetPath);
|
|
36382
36863
|
onProgress?.(relativePath, "directory");
|
|
36383
36864
|
await walk(sourcePath, baseDir);
|
|
36384
36865
|
} else {
|
|
36385
|
-
await
|
|
36866
|
+
await import_fs_extra16.default.copy(sourcePath, targetPath, { overwrite: true });
|
|
36386
36867
|
onProgress?.(relativePath, "file");
|
|
36387
36868
|
}
|
|
36388
36869
|
}
|
|
@@ -36391,7 +36872,7 @@ async function copyConfigFromCache2(cacheConfigDir, targetDir, onProgress) {
|
|
|
36391
36872
|
}
|
|
36392
36873
|
async function installOpenclawProConfigs(options) {
|
|
36393
36874
|
const { githubToken, openclawFolder, onProgress } = options;
|
|
36394
|
-
const targetFolder = openclawFolder ||
|
|
36875
|
+
const targetFolder = openclawFolder || path20.join(os16.homedir(), ".openclaw");
|
|
36395
36876
|
try {
|
|
36396
36877
|
const cacheConfigDir = await cloneOrUpdateRepo2(githubToken);
|
|
36397
36878
|
await copyConfigFromCache2(cacheConfigDir, targetFolder, onProgress);
|
|
@@ -36402,28 +36883,28 @@ async function installOpenclawProConfigs(options) {
|
|
|
36402
36883
|
}
|
|
36403
36884
|
|
|
36404
36885
|
// src/lib/openclaw-token-storage.ts
|
|
36405
|
-
var
|
|
36886
|
+
var import_fs_extra17 = __toESM(require_lib4(), 1);
|
|
36406
36887
|
import os17 from "os";
|
|
36407
|
-
import
|
|
36888
|
+
import path21 from "path";
|
|
36408
36889
|
function getConfigDir2() {
|
|
36409
36890
|
const platform = os17.platform();
|
|
36410
36891
|
if (platform === "win32") {
|
|
36411
|
-
return
|
|
36892
|
+
return path21.join(process.env.APPDATA || os17.homedir(), "openclaw");
|
|
36412
36893
|
}
|
|
36413
|
-
return
|
|
36894
|
+
return path21.join(os17.homedir(), ".config", "openclaw");
|
|
36414
36895
|
}
|
|
36415
36896
|
function getTokenPath() {
|
|
36416
|
-
return
|
|
36897
|
+
return path21.join(getConfigDir2(), "token.txt");
|
|
36417
36898
|
}
|
|
36418
36899
|
async function saveOpenclawToken(githubToken) {
|
|
36419
36900
|
const configDir = getConfigDir2();
|
|
36420
|
-
await
|
|
36421
|
-
await
|
|
36901
|
+
await import_fs_extra17.default.ensureDir(configDir);
|
|
36902
|
+
await import_fs_extra17.default.writeFile(getTokenPath(), githubToken, { mode: 384 });
|
|
36422
36903
|
}
|
|
36423
36904
|
async function getOpenclawToken() {
|
|
36424
36905
|
const tokenPath = getTokenPath();
|
|
36425
|
-
if (await
|
|
36426
|
-
const token = await
|
|
36906
|
+
if (await import_fs_extra17.default.pathExists(tokenPath)) {
|
|
36907
|
+
const token = await import_fs_extra17.default.readFile(tokenPath, "utf8");
|
|
36427
36908
|
return token.trim();
|
|
36428
36909
|
}
|
|
36429
36910
|
return null;
|
|
@@ -36436,7 +36917,7 @@ function getOpenclawTokenInfo() {
|
|
|
36436
36917
|
}
|
|
36437
36918
|
|
|
36438
36919
|
// src/commands/openclaw-pro.ts
|
|
36439
|
-
var
|
|
36920
|
+
var import_fs_extra18 = __toESM(require_lib4(), 1);
|
|
36440
36921
|
var API_URL2 = "https://codeline.app/api/products";
|
|
36441
36922
|
var OPENCLAW_PRODUCT_ID = "prd_t2GRwX3aH1";
|
|
36442
36923
|
var CLAUDE_CODE_TOOLS_INSTRUCTIONS = `
|
|
@@ -36543,7 +37024,7 @@ async function openclawProSetupCommand(options = {}) {
|
|
|
36543
37024
|
Se(source_default.red("❌ Not activated"));
|
|
36544
37025
|
process.exit(1);
|
|
36545
37026
|
}
|
|
36546
|
-
const openclawDir = options.folder ?
|
|
37027
|
+
const openclawDir = options.folder ? path22.resolve(options.folder) : path22.join(os18.homedir(), ".openclaw");
|
|
36547
37028
|
const spinner = Y2();
|
|
36548
37029
|
const onProgress = (file, type) => {
|
|
36549
37030
|
spinner.message(`Installing: ${source_default.cyan(file)} ${source_default.gray(`(${type})`)}`);
|
|
@@ -36556,23 +37037,23 @@ async function openclawProSetupCommand(options = {}) {
|
|
|
36556
37037
|
});
|
|
36557
37038
|
spinner.stop("OpenClaw Pro configurations installed");
|
|
36558
37039
|
let skillCount = 0;
|
|
36559
|
-
const skillsDir =
|
|
36560
|
-
if (await
|
|
36561
|
-
const items = await
|
|
37040
|
+
const skillsDir = path22.join(openclawDir, "skills");
|
|
37041
|
+
if (await import_fs_extra18.default.pathExists(skillsDir)) {
|
|
37042
|
+
const items = await import_fs_extra18.default.readdir(skillsDir);
|
|
36562
37043
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
36563
|
-
const stat = await
|
|
37044
|
+
const stat = await import_fs_extra18.default.stat(path22.join(skillsDir, item));
|
|
36564
37045
|
return stat.isDirectory();
|
|
36565
37046
|
}));
|
|
36566
37047
|
skillCount = dirs.filter(Boolean).length;
|
|
36567
37048
|
}
|
|
36568
37049
|
spinner.start("Setting up workspace TOOLS.md...");
|
|
36569
|
-
const workspaceDir =
|
|
36570
|
-
const toolsPath =
|
|
36571
|
-
await
|
|
36572
|
-
if (await
|
|
36573
|
-
const existingContent = await
|
|
37050
|
+
const workspaceDir = path22.join(openclawDir, "workspace");
|
|
37051
|
+
const toolsPath = path22.join(workspaceDir, "TOOLS.md");
|
|
37052
|
+
await import_fs_extra18.default.ensureDir(workspaceDir);
|
|
37053
|
+
if (await import_fs_extra18.default.pathExists(toolsPath)) {
|
|
37054
|
+
const existingContent = await import_fs_extra18.default.readFile(toolsPath, "utf-8");
|
|
36574
37055
|
if (!existingContent.includes("Claude Code CLI")) {
|
|
36575
|
-
await
|
|
37056
|
+
await import_fs_extra18.default.appendFile(toolsPath, `
|
|
36576
37057
|
|
|
36577
37058
|
` + CLAUDE_CODE_TOOLS_INSTRUCTIONS);
|
|
36578
37059
|
spinner.stop("TOOLS.md updated with Claude Code instructions");
|
|
@@ -36586,7 +37067,7 @@ Skills define _how_ tools work. This file is for _your_ specifics — the stuff
|
|
|
36586
37067
|
|
|
36587
37068
|
${CLAUDE_CODE_TOOLS_INSTRUCTIONS}
|
|
36588
37069
|
`;
|
|
36589
|
-
await
|
|
37070
|
+
await import_fs_extra18.default.writeFile(toolsPath, defaultToolsMd);
|
|
36590
37071
|
spinner.stop("TOOLS.md created with Claude Code instructions");
|
|
36591
37072
|
}
|
|
36592
37073
|
spinner.start("Creating claude-run wrapper...");
|
|
@@ -36597,9 +37078,9 @@ ${CLAUDE_CODE_TOOLS_INSTRUCTIONS}
|
|
|
36597
37078
|
script -q -c "claude $*" /dev/null
|
|
36598
37079
|
`;
|
|
36599
37080
|
const binDir = "/usr/local/bin";
|
|
36600
|
-
const wrapperPath =
|
|
37081
|
+
const wrapperPath = path22.join(binDir, "claude-run");
|
|
36601
37082
|
try {
|
|
36602
|
-
await
|
|
37083
|
+
await import_fs_extra18.default.writeFile(wrapperPath, claudeRunWrapper, { mode: 493 });
|
|
36603
37084
|
spinner.stop("claude-run wrapper created");
|
|
36604
37085
|
} catch {
|
|
36605
37086
|
spinner.stop("claude-run wrapper skipped (no write access to /usr/local/bin)");
|
|
@@ -36648,12 +37129,12 @@ async function openclawProUpdateCommand(options = {}) {
|
|
|
36648
37129
|
}
|
|
36649
37130
|
|
|
36650
37131
|
// src/commands/dynamic-scripts.ts
|
|
36651
|
-
import
|
|
37132
|
+
import path25 from "path";
|
|
36652
37133
|
import { homedir } from "os";
|
|
36653
37134
|
|
|
36654
37135
|
// src/lib/script-parser.ts
|
|
36655
|
-
var
|
|
36656
|
-
import
|
|
37136
|
+
var import_fs_extra19 = __toESM(require_lib4(), 1);
|
|
37137
|
+
import path23 from "path";
|
|
36657
37138
|
var EXCLUDED_SCRIPTS = ["test", "lint", "format", "start"];
|
|
36658
37139
|
var EXCLUDED_SUFFIXES = [":test", ":lint", ":test-fixtures", ":start"];
|
|
36659
37140
|
function shouldIncludeScript(scriptName) {
|
|
@@ -36664,12 +37145,12 @@ function shouldIncludeScript(scriptName) {
|
|
|
36664
37145
|
return true;
|
|
36665
37146
|
}
|
|
36666
37147
|
async function readScriptsPackageJson(claudeDir) {
|
|
36667
|
-
const packageJsonPath =
|
|
37148
|
+
const packageJsonPath = path23.join(claudeDir, "scripts", "package.json");
|
|
36668
37149
|
try {
|
|
36669
|
-
if (!await
|
|
37150
|
+
if (!await import_fs_extra19.default.pathExists(packageJsonPath)) {
|
|
36670
37151
|
return null;
|
|
36671
37152
|
}
|
|
36672
|
-
const content = await
|
|
37153
|
+
const content = await import_fs_extra19.default.readFile(packageJsonPath, "utf-8");
|
|
36673
37154
|
const parsed = JSON.parse(content);
|
|
36674
37155
|
return parsed.scripts || null;
|
|
36675
37156
|
} catch (error) {
|
|
@@ -36713,10 +37194,10 @@ function groupScriptsByPrefix(commands) {
|
|
|
36713
37194
|
}
|
|
36714
37195
|
|
|
36715
37196
|
// src/commands/script-runner.ts
|
|
36716
|
-
var
|
|
37197
|
+
var import_fs_extra20 = __toESM(require_lib4(), 1);
|
|
36717
37198
|
import { spawn as spawn2 } from "child_process";
|
|
36718
37199
|
import { execSync as execSync4 } from "child_process";
|
|
36719
|
-
import
|
|
37200
|
+
import path24 from "path";
|
|
36720
37201
|
import os19 from "os";
|
|
36721
37202
|
function checkCommand2(cmd) {
|
|
36722
37203
|
try {
|
|
@@ -36746,18 +37227,18 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
36746
37227
|
console.error(source_default.red("Bun is not installed. Install with: npm install -g bun"));
|
|
36747
37228
|
return 1;
|
|
36748
37229
|
}
|
|
36749
|
-
const scriptsDir =
|
|
36750
|
-
if (!await
|
|
37230
|
+
const scriptsDir = path24.join(claudeDir, "scripts");
|
|
37231
|
+
if (!await import_fs_extra20.default.pathExists(scriptsDir)) {
|
|
36751
37232
|
console.error(source_default.red(`Scripts directory not found at ${scriptsDir}`));
|
|
36752
37233
|
console.log(source_default.gray("Run: aiblueprint agents setup"));
|
|
36753
37234
|
return 1;
|
|
36754
37235
|
}
|
|
36755
|
-
const packageJsonPath =
|
|
36756
|
-
if (!await
|
|
37236
|
+
const packageJsonPath = path24.join(scriptsDir, "package.json");
|
|
37237
|
+
if (!await import_fs_extra20.default.pathExists(packageJsonPath)) {
|
|
36757
37238
|
console.error(source_default.red(`package.json not found in ${scriptsDir}`));
|
|
36758
37239
|
return 1;
|
|
36759
37240
|
}
|
|
36760
|
-
const packageJson = await
|
|
37241
|
+
const packageJson = await import_fs_extra20.default.readJson(packageJsonPath);
|
|
36761
37242
|
if (!packageJson.scripts || !packageJson.scripts[scriptName]) {
|
|
36762
37243
|
console.error(source_default.red(`Script "${scriptName}" not found in package.json`));
|
|
36763
37244
|
return 1;
|
|
@@ -36780,7 +37261,7 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
36780
37261
|
|
|
36781
37262
|
// src/commands/dynamic-scripts.ts
|
|
36782
37263
|
function getClaudeDir(parentOptions) {
|
|
36783
|
-
return parentOptions.claudeCodeFolder || parentOptions.folder ?
|
|
37264
|
+
return parentOptions.claudeCodeFolder || parentOptions.folder ? path25.resolve(parentOptions.claudeCodeFolder || parentOptions.folder) : path25.join(homedir(), ".claude");
|
|
36784
37265
|
}
|
|
36785
37266
|
async function registerDynamicScriptCommands(claudeCodeCmd, claudeDir) {
|
|
36786
37267
|
const scripts = await readScriptsPackageJson(claudeDir);
|
|
@@ -36886,12 +37367,81 @@ function registerAgentsCommands(cmd) {
|
|
|
36886
37367
|
});
|
|
36887
37368
|
});
|
|
36888
37369
|
}
|
|
37370
|
+
function addConfigFolderOptions(cmd) {
|
|
37371
|
+
return cmd.option("-f, --folder <path>", "Root folder that contains .claude/, .codex/, .agents/ (default: $HOME)").option("--claudeCodeFolder <path>", "Override Claude Code folder (default: {folder}/.claude)").option("--codexFolder <path>", "Override Codex folder (default: {folder}/.codex)").option("--agentsFolder <path>", "Override shared agents folder (default: {folder}/.agents)");
|
|
37372
|
+
}
|
|
36889
37373
|
var agentsCmd = program2.command("agents").description("AI coding configuration commands");
|
|
36890
37374
|
registerAgentsCommands(agentsCmd);
|
|
36891
37375
|
var aiCodingCmd = program2.command("ai-coding").description("Legacy alias for agents configuration commands");
|
|
36892
37376
|
registerAgentsCommands(aiCodingCmd);
|
|
36893
37377
|
var claudeCodeCmd = program2.command("claude-code").description("Legacy alias for agents configuration commands");
|
|
36894
37378
|
registerAgentsCommands(claudeCodeCmd);
|
|
37379
|
+
var configsCmd = addConfigFolderOptions(program2.command("configs").description("Save, load, undo, and inspect .claude/.codex/.agents configurations"));
|
|
37380
|
+
configsCmd.command("save <name>").description("Save the current .claude, .codex, and .agents folders as a named config").option("--force", "Overwrite an existing saved config with the same name").action((name, options, command) => {
|
|
37381
|
+
const parentOptions = command.parent.opts();
|
|
37382
|
+
configsSaveCommand(name, {
|
|
37383
|
+
folder: parentOptions.folder,
|
|
37384
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37385
|
+
codexFolder: parentOptions.codexFolder,
|
|
37386
|
+
agentsFolder: parentOptions.agentsFolder,
|
|
37387
|
+
force: options.force
|
|
37388
|
+
});
|
|
37389
|
+
});
|
|
37390
|
+
configsCmd.command("load <name>").description("Load a named config and backup the current folders first").action((name, options, command) => {
|
|
37391
|
+
const parentOptions = command.parent.opts();
|
|
37392
|
+
configsLoadCommand(name, {
|
|
37393
|
+
folder: parentOptions.folder,
|
|
37394
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37395
|
+
codexFolder: parentOptions.codexFolder,
|
|
37396
|
+
agentsFolder: parentOptions.agentsFolder
|
|
37397
|
+
});
|
|
37398
|
+
});
|
|
37399
|
+
configsCmd.command("undo").description("Undo the most recent configs load by restoring its automatic backup").action((options, command) => {
|
|
37400
|
+
const parentOptions = command.parent.opts();
|
|
37401
|
+
configsUndoCommand({
|
|
37402
|
+
folder: parentOptions.folder,
|
|
37403
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37404
|
+
codexFolder: parentOptions.codexFolder,
|
|
37405
|
+
agentsFolder: parentOptions.agentsFolder
|
|
37406
|
+
});
|
|
37407
|
+
});
|
|
37408
|
+
configsCmd.command("list").description("List saved named configs").action((options, command) => {
|
|
37409
|
+
const parentOptions = command.parent.opts();
|
|
37410
|
+
configsListCommand({
|
|
37411
|
+
folder: parentOptions.folder,
|
|
37412
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37413
|
+
codexFolder: parentOptions.codexFolder,
|
|
37414
|
+
agentsFolder: parentOptions.agentsFolder
|
|
37415
|
+
});
|
|
37416
|
+
});
|
|
37417
|
+
var configsBackupsCmd = configsCmd.command("backups").description("Manage automatic config backups");
|
|
37418
|
+
configsBackupsCmd.command("list").description("List automatic backups with reasons").action((options, command) => {
|
|
37419
|
+
const parentOptions = command.parent.parent.opts();
|
|
37420
|
+
configsBackupsListCommand({
|
|
37421
|
+
folder: parentOptions.folder,
|
|
37422
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37423
|
+
codexFolder: parentOptions.codexFolder,
|
|
37424
|
+
agentsFolder: parentOptions.agentsFolder
|
|
37425
|
+
});
|
|
37426
|
+
});
|
|
37427
|
+
configsBackupsCmd.command("load <name>").description("Load a backup and backup the current folders first").action((name, options, command) => {
|
|
37428
|
+
const parentOptions = command.parent.parent.opts();
|
|
37429
|
+
configsBackupsLoadCommand(name, {
|
|
37430
|
+
folder: parentOptions.folder,
|
|
37431
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37432
|
+
codexFolder: parentOptions.codexFolder,
|
|
37433
|
+
agentsFolder: parentOptions.agentsFolder
|
|
37434
|
+
});
|
|
37435
|
+
});
|
|
37436
|
+
configsBackupsCmd.command("create [reason]").description("Create a manual backup of the current config folders").action((reason, options, command) => {
|
|
37437
|
+
const parentOptions = command.parent.parent.opts();
|
|
37438
|
+
configsBackupsCreateCommand(reason, {
|
|
37439
|
+
folder: parentOptions.folder,
|
|
37440
|
+
claudeCodeFolder: parentOptions.claudeCodeFolder,
|
|
37441
|
+
codexFolder: parentOptions.codexFolder,
|
|
37442
|
+
agentsFolder: parentOptions.agentsFolder
|
|
37443
|
+
});
|
|
37444
|
+
});
|
|
36895
37445
|
var openclawCmd = program2.command("openclaw").description("OpenClaw configuration commands").option("-f, --folder <path>", "Specify custom OpenClaw folder path (default: ~/.openclaw)");
|
|
36896
37446
|
var openclawProCmd = openclawCmd.command("pro").description("Manage OpenClaw Pro features");
|
|
36897
37447
|
openclawProCmd.command("activate [token]").description("Activate OpenClaw Pro with your access token").action((token) => {
|