oh-my-customcode 1.1.100 → 1.1.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +169 -162
- package/dist/index.js +30 -30
- package/package.json +1 -1
- package/templates/manifest.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -49,7 +49,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
49
49
|
// src/utils/home.ts
|
|
50
50
|
import { realpathSync } from "node:fs";
|
|
51
51
|
import { homedir, userInfo } from "node:os";
|
|
52
|
-
import { isAbsolute, parse, sep } from "node:path";
|
|
52
|
+
import { basename, dirname, isAbsolute, join, parse, sep } from "node:path";
|
|
53
53
|
function readEnvHome() {
|
|
54
54
|
return process.env.HOME;
|
|
55
55
|
}
|
|
@@ -99,11 +99,18 @@ function realpathOrSelf(p) {
|
|
|
99
99
|
if (p === "" || !isAbsolute(p)) {
|
|
100
100
|
return p;
|
|
101
101
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
const tail = [];
|
|
103
|
+
let current = p;
|
|
104
|
+
let parent = dirname(current);
|
|
105
|
+
while (parent !== current) {
|
|
106
|
+
try {
|
|
107
|
+
return join(realpathSync(current), ...tail);
|
|
108
|
+
} catch {}
|
|
109
|
+
tail.unshift(basename(current));
|
|
110
|
+
current = parent;
|
|
111
|
+
parent = dirname(current);
|
|
106
112
|
}
|
|
113
|
+
return p;
|
|
107
114
|
}
|
|
108
115
|
function isUnderHome(path, home) {
|
|
109
116
|
const base = home ?? resolveHomeDir();
|
|
@@ -149,7 +156,7 @@ var init_home = () => {};
|
|
|
149
156
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
150
157
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
151
158
|
import { tmpdir } from "node:os";
|
|
152
|
-
import { basename, join, resolve, sep as sep2 } from "node:path";
|
|
159
|
+
import { basename as basename2, join as join2, resolve, sep as sep2 } from "node:path";
|
|
153
160
|
function isTempPath(projectPath) {
|
|
154
161
|
const normalized = resolve(projectPath);
|
|
155
162
|
const candidates = new Set;
|
|
@@ -184,10 +191,10 @@ function registryDir(home) {
|
|
|
184
191
|
if (resolved === "") {
|
|
185
192
|
throw new Error("Could not determine the home directory for the project registry");
|
|
186
193
|
}
|
|
187
|
-
return
|
|
194
|
+
return join2(resolved, ".oh-my-customcode");
|
|
188
195
|
}
|
|
189
196
|
function registryPath() {
|
|
190
|
-
return
|
|
197
|
+
return join2(registryDir(), "projects.json");
|
|
191
198
|
}
|
|
192
199
|
function emptyRegistry() {
|
|
193
200
|
return { projects: {} };
|
|
@@ -288,14 +295,14 @@ async function migrateFromLockfiles(searchDirs) {
|
|
|
288
295
|
} catch {
|
|
289
296
|
return;
|
|
290
297
|
}
|
|
291
|
-
const entry = await parseLockFile(
|
|
298
|
+
const entry = await parseLockFile(join2(dir, ".omcustom.lock.json"));
|
|
292
299
|
if (entry !== null) {
|
|
293
300
|
discovered.set(resolve(dir), entry);
|
|
294
301
|
return;
|
|
295
302
|
}
|
|
296
303
|
if (depth < MAX_DEPTH) {
|
|
297
304
|
const subdirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !SCAN_SKIP_DIRS.has(e.name));
|
|
298
|
-
await Promise.all(subdirs.map((sub) => scan(
|
|
305
|
+
await Promise.all(subdirs.map((sub) => scan(join2(dir, sub.name), depth + 1)));
|
|
299
306
|
}
|
|
300
307
|
}
|
|
301
308
|
await Promise.all(searchDirs.map((dir) => scan(dir, 0).catch(() => {})));
|
|
@@ -328,7 +335,7 @@ var init_package = __esm(() => {
|
|
|
328
335
|
workspaces: [
|
|
329
336
|
"packages/*"
|
|
330
337
|
],
|
|
331
|
-
version: "1.1.
|
|
338
|
+
version: "1.1.101",
|
|
332
339
|
description: "Batteries-included agent harness for Claude Code",
|
|
333
340
|
type: "module",
|
|
334
341
|
bin: {
|
|
@@ -7324,7 +7331,7 @@ var require_public_api = __commonJS(function(exports) {
|
|
|
7324
7331
|
});
|
|
7325
7332
|
|
|
7326
7333
|
// src/utils/fs.ts
|
|
7327
|
-
import { dirname as
|
|
7334
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join4, relative, resolve as resolve2, sep as sep3 } from "node:path";
|
|
7328
7335
|
import { fileURLToPath } from "node:url";
|
|
7329
7336
|
function validatePreserveFilePath(filePath, projectRoot) {
|
|
7330
7337
|
if (!filePath || filePath.trim() === "") {
|
|
@@ -7483,17 +7490,17 @@ async function readTextFile(path) {
|
|
|
7483
7490
|
}
|
|
7484
7491
|
async function writeTextFile(path, content) {
|
|
7485
7492
|
const fs = await import("node:fs/promises");
|
|
7486
|
-
await ensureDirectory(
|
|
7493
|
+
await ensureDirectory(dirname3(path));
|
|
7487
7494
|
await fs.writeFile(path, content, "utf-8");
|
|
7488
7495
|
}
|
|
7489
7496
|
function getPackageRoot() {
|
|
7490
7497
|
const currentFile = fileURLToPath(import.meta.url);
|
|
7491
|
-
const currentDir =
|
|
7498
|
+
const currentDir = dirname3(currentFile);
|
|
7492
7499
|
return resolve2(currentDir, "..", "..");
|
|
7493
7500
|
}
|
|
7494
7501
|
function resolveTemplatePath(relativePath) {
|
|
7495
7502
|
const packageRoot = getPackageRoot();
|
|
7496
|
-
return
|
|
7503
|
+
return join4(packageRoot, "templates", relativePath);
|
|
7497
7504
|
}
|
|
7498
7505
|
async function listFiles(dir, options = {}) {
|
|
7499
7506
|
const fs = await import("node:fs/promises");
|
|
@@ -7515,7 +7522,7 @@ async function listFiles(dir, options = {}) {
|
|
|
7515
7522
|
}
|
|
7516
7523
|
async function copyFile(src, dest) {
|
|
7517
7524
|
const fs = await import("node:fs/promises");
|
|
7518
|
-
await ensureDirectory(
|
|
7525
|
+
await ensureDirectory(dirname3(dest));
|
|
7519
7526
|
await fs.copyFile(src, dest);
|
|
7520
7527
|
}
|
|
7521
7528
|
async function createTempDir(prefix = "omcustom-") {
|
|
@@ -7536,9 +7543,9 @@ var UTF8_BOM = "\uFEFF";
|
|
|
7536
7543
|
var init_fs = () => {};
|
|
7537
7544
|
|
|
7538
7545
|
// src/cli/projects.ts
|
|
7539
|
-
import { basename as
|
|
7546
|
+
import { basename as basename5, join as join12, resolve as resolve3 } from "node:path";
|
|
7540
7547
|
async function readLockFile(projectDir) {
|
|
7541
|
-
const lockFilePath =
|
|
7548
|
+
const lockFilePath = join12(projectDir, ".omcustom.lock.json");
|
|
7542
7549
|
try {
|
|
7543
7550
|
const fs = await import("node:fs/promises");
|
|
7544
7551
|
const content = await fs.readFile(lockFilePath, "utf-8");
|
|
@@ -7608,7 +7615,7 @@ async function findProjects(options = {}) {
|
|
|
7608
7615
|
if (!isUnderHome(projectPath, home))
|
|
7609
7616
|
continue;
|
|
7610
7617
|
results.push({
|
|
7611
|
-
name:
|
|
7618
|
+
name: basename5(projectPath),
|
|
7612
7619
|
path: projectPath,
|
|
7613
7620
|
version: entry.version || null,
|
|
7614
7621
|
installedAt: entry.installedAt || null,
|
|
@@ -7634,7 +7641,7 @@ async function _scanDirForLockfiles(dir, depth, seen, results, home, currentVers
|
|
|
7634
7641
|
if (isUnderHome(dir, home)) {
|
|
7635
7642
|
const version = lockFile.version || lockFile.templateVersion || null;
|
|
7636
7643
|
results.push({
|
|
7637
|
-
name:
|
|
7644
|
+
name: basename5(dir),
|
|
7638
7645
|
path: dir,
|
|
7639
7646
|
version,
|
|
7640
7647
|
installedAt: lockFile.installedAt || null,
|
|
@@ -7647,7 +7654,7 @@ async function _scanDirForLockfiles(dir, depth, seen, results, home, currentVers
|
|
|
7647
7654
|
}
|
|
7648
7655
|
if (depth < 3) {
|
|
7649
7656
|
const subdirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !SCAN_SKIP_DIRS2.has(e.name));
|
|
7650
|
-
await Promise.all(subdirs.map((sub) => _scanDirForLockfiles(
|
|
7657
|
+
await Promise.all(subdirs.map((sub) => _scanDirForLockfiles(join12(dir, sub.name), depth + 1, seen, results, home, currentVersion, fs).catch(() => {})));
|
|
7651
7658
|
}
|
|
7652
7659
|
}
|
|
7653
7660
|
async function _findProjectsFromLockfiles(options, currentVersion) {
|
|
@@ -7671,7 +7678,7 @@ async function _findProjectsFromLockfiles(options, currentVersion) {
|
|
|
7671
7678
|
}
|
|
7672
7679
|
async function writeLockFile(projectDir, version, existing) {
|
|
7673
7680
|
const fs = await import("node:fs/promises");
|
|
7674
|
-
const lockFilePath =
|
|
7681
|
+
const lockFilePath = join12(projectDir, ".omcustom.lock.json");
|
|
7675
7682
|
const now = new Date().toISOString();
|
|
7676
7683
|
const merged = {
|
|
7677
7684
|
...existing || {},
|
|
@@ -7730,7 +7737,7 @@ oh-my-customcode 적용 프로젝트 (${projects.length}개):`);
|
|
|
7730
7737
|
현재 설치 버전: v${currentVersion}`);
|
|
7731
7738
|
}
|
|
7732
7739
|
function buildMigrationSearchDirs(home, extraPaths = []) {
|
|
7733
|
-
return [...home ? DEFAULT_SEARCH_DIRS.map((d) =>
|
|
7740
|
+
return [...home ? DEFAULT_SEARCH_DIRS.map((d) => join12(home, d)) : [], ...extraPaths];
|
|
7734
7741
|
}
|
|
7735
7742
|
async function runMigration(options) {
|
|
7736
7743
|
await Promise.resolve().then(() => init_registry());
|
|
@@ -11966,7 +11973,7 @@ init_package();
|
|
|
11966
11973
|
import { execSync as execSync2, spawnSync } from "node:child_process";
|
|
11967
11974
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
11968
11975
|
import { homedir as homedir2 } from "node:os";
|
|
11969
|
-
import { dirname, join as
|
|
11976
|
+
import { dirname as dirname2, join as join3 } from "node:path";
|
|
11970
11977
|
import { createInterface } from "node:readline/promises";
|
|
11971
11978
|
|
|
11972
11979
|
// node_modules/.bun/i18next@26.0.2+ff0372d108591aba/node_modules/i18next/dist/esm/i18next.js
|
|
@@ -15264,7 +15271,7 @@ var i18n = {
|
|
|
15264
15271
|
// src/core/self-update.ts
|
|
15265
15272
|
var DEFAULT_PACKAGE_NAME = "oh-my-customcode";
|
|
15266
15273
|
var DEFAULT_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
15267
|
-
var DEFAULT_CACHE_PATH =
|
|
15274
|
+
var DEFAULT_CACHE_PATH = join3(homedir2(), ".oh-my-customcode", "self-update-cache.json");
|
|
15268
15275
|
var MS_EPOCH_THRESHOLD = 1000000000000;
|
|
15269
15276
|
function normalizeVersion(version) {
|
|
15270
15277
|
return version.trim().replace(/^v/i, "").split("-")[0] || "";
|
|
@@ -15361,7 +15368,7 @@ function readSelfUpdateCache(cachePath) {
|
|
|
15361
15368
|
return null;
|
|
15362
15369
|
}
|
|
15363
15370
|
function writeCache(cachePath, latestVersion, now) {
|
|
15364
|
-
const dir =
|
|
15371
|
+
const dir = dirname2(cachePath);
|
|
15365
15372
|
if (!existsSync(dir)) {
|
|
15366
15373
|
mkdirSync(dir, { recursive: true });
|
|
15367
15374
|
}
|
|
@@ -16118,7 +16125,7 @@ function installCodex(deps = defaultDeps) {
|
|
|
16118
16125
|
|
|
16119
16126
|
// src/core/config.ts
|
|
16120
16127
|
init_fs();
|
|
16121
|
-
import { join as
|
|
16128
|
+
import { join as join5 } from "node:path";
|
|
16122
16129
|
var CONFIG_FILE = ".omcustomrc.json";
|
|
16123
16130
|
var CURRENT_CONFIG_VERSION = 1;
|
|
16124
16131
|
function getDefaultConfig() {
|
|
@@ -16158,7 +16165,7 @@ function getDefaultPreferences() {
|
|
|
16158
16165
|
};
|
|
16159
16166
|
}
|
|
16160
16167
|
function getConfigPath(targetDir) {
|
|
16161
|
-
return
|
|
16168
|
+
return join5(targetDir, CONFIG_FILE);
|
|
16162
16169
|
}
|
|
16163
16170
|
async function loadConfig(targetDir) {
|
|
16164
16171
|
const configPath = getConfigPath(targetDir);
|
|
@@ -16256,9 +16263,9 @@ function migrateConfig(config) {
|
|
|
16256
16263
|
// src/core/doctor-framework.ts
|
|
16257
16264
|
init_fs();
|
|
16258
16265
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
16259
|
-
import { join as
|
|
16266
|
+
import { join as join6 } from "node:path";
|
|
16260
16267
|
async function getInstalledVersion(targetDir) {
|
|
16261
|
-
const rcPath =
|
|
16268
|
+
const rcPath = join6(targetDir, ".omcustomrc.json");
|
|
16262
16269
|
if (!await fileExists(rcPath))
|
|
16263
16270
|
return null;
|
|
16264
16271
|
try {
|
|
@@ -16330,7 +16337,7 @@ init_fs();
|
|
|
16330
16337
|
import { createHash } from "node:crypto";
|
|
16331
16338
|
import { createReadStream } from "node:fs";
|
|
16332
16339
|
import { readdir, stat } from "node:fs/promises";
|
|
16333
|
-
import { join as
|
|
16340
|
+
import { join as join7, relative as relative2 } from "node:path";
|
|
16334
16341
|
var LOCKFILE_NAME = ".omcustom.lock.json";
|
|
16335
16342
|
var LOCKFILE_VERSION = 1;
|
|
16336
16343
|
var LOCKFILE_COMPONENTS = [
|
|
@@ -16359,7 +16366,7 @@ function computeFileHash(filePath) {
|
|
|
16359
16366
|
});
|
|
16360
16367
|
}
|
|
16361
16368
|
async function readLockfile(targetDir) {
|
|
16362
|
-
const lockfilePath =
|
|
16369
|
+
const lockfilePath = join7(targetDir, LOCKFILE_NAME);
|
|
16363
16370
|
const exists = await fileExists(lockfilePath);
|
|
16364
16371
|
if (!exists) {
|
|
16365
16372
|
debug("lockfile.not_found", { path: lockfilePath });
|
|
@@ -16383,7 +16390,7 @@ async function readLockfile(targetDir) {
|
|
|
16383
16390
|
}
|
|
16384
16391
|
}
|
|
16385
16392
|
async function writeLockfile(targetDir, lockfile) {
|
|
16386
|
-
const lockfilePath =
|
|
16393
|
+
const lockfilePath = join7(targetDir, LOCKFILE_NAME);
|
|
16387
16394
|
await writeJsonFile(lockfilePath, lockfile);
|
|
16388
16395
|
debug("lockfile.written", { path: lockfilePath });
|
|
16389
16396
|
}
|
|
@@ -16408,7 +16415,7 @@ async function collectFiles(dir, projectRoot, isTopLevel) {
|
|
|
16408
16415
|
if (isTopLevel && entry.startsWith(".") && entry !== ".claude") {
|
|
16409
16416
|
continue;
|
|
16410
16417
|
}
|
|
16411
|
-
const fullPath =
|
|
16418
|
+
const fullPath = join7(dir, entry);
|
|
16412
16419
|
let fileStat;
|
|
16413
16420
|
try {
|
|
16414
16421
|
fileStat = await stat(fullPath);
|
|
@@ -16426,7 +16433,7 @@ async function collectFiles(dir, projectRoot, isTopLevel) {
|
|
|
16426
16433
|
}
|
|
16427
16434
|
async function generateLockfile(targetDir, generatorVersion, templateVersion) {
|
|
16428
16435
|
const files = {};
|
|
16429
|
-
const componentRoots = COMPONENT_PATHS.map(([prefix]) =>
|
|
16436
|
+
const componentRoots = COMPONENT_PATHS.map(([prefix]) => join7(targetDir, prefix));
|
|
16430
16437
|
for (const componentRoot of componentRoots) {
|
|
16431
16438
|
const exists = await fileExists(componentRoot);
|
|
16432
16439
|
if (!exists) {
|
|
@@ -16466,8 +16473,8 @@ async function generateLockfile(targetDir, generatorVersion, templateVersion) {
|
|
|
16466
16473
|
async function generateAndWriteLockfileForDir(targetDir) {
|
|
16467
16474
|
try {
|
|
16468
16475
|
const packageRoot = getPackageRoot();
|
|
16469
|
-
const manifest = await readJsonFile(
|
|
16470
|
-
const { version: generatorVersion } = await readJsonFile(
|
|
16476
|
+
const manifest = await readJsonFile(join7(packageRoot, "templates", "manifest.json"));
|
|
16477
|
+
const { version: generatorVersion } = await readJsonFile(join7(packageRoot, "package.json"));
|
|
16471
16478
|
const lockfile = await generateLockfile(targetDir, generatorVersion, manifest.version);
|
|
16472
16479
|
await writeLockfile(targetDir, lockfile);
|
|
16473
16480
|
return { fileCount: Object.keys(lockfile.files).length };
|
|
@@ -17217,7 +17224,7 @@ async function doctorCommand(options = {}) {
|
|
|
17217
17224
|
|
|
17218
17225
|
// src/cli/init.ts
|
|
17219
17226
|
init_package();
|
|
17220
|
-
import { join as
|
|
17227
|
+
import { join as join14 } from "node:path";
|
|
17221
17228
|
|
|
17222
17229
|
// src/core/installer.ts
|
|
17223
17230
|
init_fs();
|
|
@@ -17228,11 +17235,11 @@ import {
|
|
|
17228
17235
|
rename,
|
|
17229
17236
|
stat as stat2
|
|
17230
17237
|
} from "node:fs/promises";
|
|
17231
|
-
import { basename as
|
|
17238
|
+
import { basename as basename4, dirname as dirname5, join as join9 } from "node:path";
|
|
17232
17239
|
|
|
17233
17240
|
// src/core/file-preservation.ts
|
|
17234
17241
|
init_fs();
|
|
17235
|
-
import { basename as
|
|
17242
|
+
import { basename as basename3, join as join8 } from "node:path";
|
|
17236
17243
|
|
|
17237
17244
|
// src/core/hook-group-merge.ts
|
|
17238
17245
|
var LEGACY_OMCUSTOM_DESCRIPTIONS = [
|
|
@@ -17366,8 +17373,8 @@ function matchesGlobPattern(filePath, pattern) {
|
|
|
17366
17373
|
return regex.test(filePath);
|
|
17367
17374
|
}
|
|
17368
17375
|
async function extractSingleFile(fileName, rootDir, tempDir, result) {
|
|
17369
|
-
const srcPath =
|
|
17370
|
-
const destPath =
|
|
17376
|
+
const srcPath = join8(rootDir, fileName);
|
|
17377
|
+
const destPath = join8(tempDir, fileName);
|
|
17371
17378
|
try {
|
|
17372
17379
|
if (await fileExists(srcPath)) {
|
|
17373
17380
|
await copyFile(srcPath, destPath);
|
|
@@ -17381,8 +17388,8 @@ async function extractSingleFile(fileName, rootDir, tempDir, result) {
|
|
|
17381
17388
|
}
|
|
17382
17389
|
}
|
|
17383
17390
|
async function extractSingleDir(dirName, rootDir, tempDir, result) {
|
|
17384
|
-
const srcPath =
|
|
17385
|
-
const destPath =
|
|
17391
|
+
const srcPath = join8(rootDir, dirName);
|
|
17392
|
+
const destPath = join8(tempDir, dirName);
|
|
17386
17393
|
try {
|
|
17387
17394
|
if (await fileExists(srcPath)) {
|
|
17388
17395
|
await copyDirectory(srcPath, destPath, { overwrite: true, preserveTimestamps: true });
|
|
@@ -17419,8 +17426,8 @@ async function restoreCriticalFiles(rootDir, preservation) {
|
|
|
17419
17426
|
failures: []
|
|
17420
17427
|
};
|
|
17421
17428
|
for (const fileName of preservation.extractedFiles) {
|
|
17422
|
-
const preservedPath =
|
|
17423
|
-
const targetPath =
|
|
17429
|
+
const preservedPath = join8(preservation.tempDir, fileName);
|
|
17430
|
+
const targetPath = join8(rootDir, fileName);
|
|
17424
17431
|
try {
|
|
17425
17432
|
if (fileName.endsWith(".json")) {
|
|
17426
17433
|
await mergeJsonFile(preservedPath, targetPath);
|
|
@@ -17436,8 +17443,8 @@ async function restoreCriticalFiles(rootDir, preservation) {
|
|
|
17436
17443
|
}
|
|
17437
17444
|
}
|
|
17438
17445
|
for (const dirName of preservation.extractedDirs) {
|
|
17439
|
-
const preservedPath =
|
|
17440
|
-
const targetPath =
|
|
17446
|
+
const preservedPath = join8(preservation.tempDir, dirName);
|
|
17447
|
+
const targetPath = join8(rootDir, dirName);
|
|
17441
17448
|
try {
|
|
17442
17449
|
await copyDirectory(preservedPath, targetPath, {
|
|
17443
17450
|
overwrite: false,
|
|
@@ -17462,14 +17469,14 @@ async function mergeJsonFile(preservedPath, targetPath) {
|
|
|
17462
17469
|
if (await fileExists(targetPath)) {
|
|
17463
17470
|
const { data: targetData } = parseJsonText(await readTextFile(targetPath));
|
|
17464
17471
|
const merged = deepMerge(targetData, preservedData);
|
|
17465
|
-
if (HOOKS_MERGE_FILES.has(
|
|
17472
|
+
if (HOOKS_MERGE_FILES.has(basename3(targetPath)) && isGeneratedHookBlock(targetData.hooks)) {
|
|
17466
17473
|
merged.hooks = mergeHookBlocks(preservedData.hooks, targetData.hooks);
|
|
17467
17474
|
}
|
|
17468
17475
|
await writeTextFile(targetPath, stringifyJson(merged, format));
|
|
17469
|
-
debug("preserve.merged_json", { file:
|
|
17476
|
+
debug("preserve.merged_json", { file: basename3(targetPath) });
|
|
17470
17477
|
} else {
|
|
17471
17478
|
await copyFile(preservedPath, targetPath);
|
|
17472
|
-
debug("preserve.copied_json", { file:
|
|
17479
|
+
debug("preserve.copied_json", { file: basename3(targetPath) });
|
|
17473
17480
|
}
|
|
17474
17481
|
}
|
|
17475
17482
|
function deepMerge(target, source) {
|
|
@@ -17807,7 +17814,7 @@ function migrateHookCommands(settings) {
|
|
|
17807
17814
|
|
|
17808
17815
|
// src/core/hooks-settings.ts
|
|
17809
17816
|
init_fs();
|
|
17810
|
-
import { dirname as
|
|
17817
|
+
import { dirname as dirname4 } from "node:path";
|
|
17811
17818
|
var IDENT_CHAR = /[A-Za-z0-9_.]/;
|
|
17812
17819
|
var IDENT_START = /[A-Za-z_]/;
|
|
17813
17820
|
function consumeSingleCharOp(input, i) {
|
|
@@ -18311,7 +18318,7 @@ async function mergeHooksIntoSettings(settingsPath, hooksJsonPath, options = {})
|
|
|
18311
18318
|
}
|
|
18312
18319
|
const settings = existing.ok ? existing.settings : {};
|
|
18313
18320
|
settings.hooks = preserve ? mergeHookBlocks(settings.hooks, hooks) : hooks;
|
|
18314
|
-
await ensureDirectory(
|
|
18321
|
+
await ensureDirectory(dirname4(settingsPath));
|
|
18315
18322
|
await writeTextFile(settingsPath, stringifyJson(settings, { bom: existing.bom, trailingNewline: true }));
|
|
18316
18323
|
return { warnings };
|
|
18317
18324
|
}
|
|
@@ -18348,7 +18355,7 @@ function shouldInstallAgent(agentDomain, filterDomain) {
|
|
|
18348
18355
|
var DEFAULT_LANGUAGE2 = "en";
|
|
18349
18356
|
function getTemplateDir() {
|
|
18350
18357
|
const packageRoot = getPackageRoot();
|
|
18351
|
-
return
|
|
18358
|
+
return join9(packageRoot, "templates");
|
|
18352
18359
|
}
|
|
18353
18360
|
function createInstallResult(targetDir) {
|
|
18354
18361
|
return {
|
|
@@ -18370,7 +18377,7 @@ async function handleBackup(targetDir, shouldBackup, result) {
|
|
|
18370
18377
|
if (!shouldBackup)
|
|
18371
18378
|
return null;
|
|
18372
18379
|
const layout = getProviderLayout();
|
|
18373
|
-
const rootDir =
|
|
18380
|
+
const rootDir = join9(targetDir, layout.rootDir);
|
|
18374
18381
|
let preservation = null;
|
|
18375
18382
|
if (await fileExists(rootDir)) {
|
|
18376
18383
|
await Promise.resolve().then(() => init_fs());
|
|
@@ -18427,8 +18434,8 @@ async function installSingleComponent(targetDir, component, options, result) {
|
|
|
18427
18434
|
}
|
|
18428
18435
|
async function installStatusline(targetDir, options, _result) {
|
|
18429
18436
|
const layout = getProviderLayout();
|
|
18430
|
-
const srcPath = resolveTemplatePath(
|
|
18431
|
-
const destPath =
|
|
18437
|
+
const srcPath = resolveTemplatePath(join9(layout.rootDir, "statusline.sh"));
|
|
18438
|
+
const destPath = join9(targetDir, layout.rootDir, "statusline.sh");
|
|
18432
18439
|
if (!await fileExists(srcPath)) {
|
|
18433
18440
|
debug("install.statusline_not_found", { path: srcPath });
|
|
18434
18441
|
return;
|
|
@@ -18446,9 +18453,9 @@ async function installStatusline(targetDir, options, _result) {
|
|
|
18446
18453
|
}
|
|
18447
18454
|
async function installSchemas(targetDir, options, _result) {
|
|
18448
18455
|
const layout = getProviderLayout();
|
|
18449
|
-
const relPath =
|
|
18456
|
+
const relPath = join9(layout.rootDir, "schemas", "tool-inputs.json");
|
|
18450
18457
|
const srcPath = resolveTemplatePath(relPath);
|
|
18451
|
-
const destPath =
|
|
18458
|
+
const destPath = join9(targetDir, relPath);
|
|
18452
18459
|
if (!await fileExists(srcPath)) {
|
|
18453
18460
|
debug("install.schemas_not_found", { path: srcPath });
|
|
18454
18461
|
return;
|
|
@@ -18459,13 +18466,13 @@ async function installSchemas(targetDir, options, _result) {
|
|
|
18459
18466
|
return;
|
|
18460
18467
|
}
|
|
18461
18468
|
}
|
|
18462
|
-
await ensureDirectory(
|
|
18469
|
+
await ensureDirectory(dirname5(destPath));
|
|
18463
18470
|
await copyFile(srcPath, destPath);
|
|
18464
18471
|
debug("install.schemas_installed", {});
|
|
18465
18472
|
}
|
|
18466
18473
|
async function installTestsConfig(targetDir, options, _result) {
|
|
18467
|
-
const srcPath = resolveTemplatePath(
|
|
18468
|
-
const destPath =
|
|
18474
|
+
const srcPath = resolveTemplatePath(join9("tests", "tsconfig.json"));
|
|
18475
|
+
const destPath = join9(targetDir, "tests", "tsconfig.json");
|
|
18469
18476
|
if (!await fileExists(srcPath)) {
|
|
18470
18477
|
debug("install.tests_config_not_found", { path: srcPath });
|
|
18471
18478
|
return;
|
|
@@ -18515,7 +18522,7 @@ async function mergeStatusLineIntoExisting(settingsPath, existing, format, defau
|
|
|
18515
18522
|
}
|
|
18516
18523
|
async function installSettingsLocal(targetDir, result) {
|
|
18517
18524
|
const layout = getProviderLayout();
|
|
18518
|
-
const settingsPath =
|
|
18525
|
+
const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
|
|
18519
18526
|
const statusLineConfig = {
|
|
18520
18527
|
statusLine: {
|
|
18521
18528
|
type: "command",
|
|
@@ -18538,8 +18545,8 @@ async function installSettingsLocal(targetDir, result) {
|
|
|
18538
18545
|
}
|
|
18539
18546
|
async function installHooksSettings(targetDir, _options, result) {
|
|
18540
18547
|
const layout = getProviderLayout();
|
|
18541
|
-
const hooksJsonPath =
|
|
18542
|
-
const settingsPath =
|
|
18548
|
+
const hooksJsonPath = join9(targetDir, getComponentPath("hooks"), "hooks.json");
|
|
18549
|
+
const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
|
|
18543
18550
|
if (!await fileExists(hooksJsonPath)) {
|
|
18544
18551
|
debug("install.hooks_settings_skipped", { reason: "hooks.json not installed" });
|
|
18545
18552
|
return;
|
|
@@ -18561,7 +18568,7 @@ async function installHooksSettings(targetDir, _options, result) {
|
|
|
18561
18568
|
var BOM = "\uFEFF";
|
|
18562
18569
|
async function migrateRestoredHookCommands(targetDir, result) {
|
|
18563
18570
|
const layout = getProviderLayout();
|
|
18564
|
-
const settingsPath =
|
|
18571
|
+
const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
|
|
18565
18572
|
if (!await fileExists(settingsPath)) {
|
|
18566
18573
|
return;
|
|
18567
18574
|
}
|
|
@@ -18647,7 +18654,7 @@ async function install(options) {
|
|
|
18647
18654
|
await installEntryDocWithTracking(options.targetDir, options, result);
|
|
18648
18655
|
if (preservation) {
|
|
18649
18656
|
const layout = getProviderLayout();
|
|
18650
|
-
const rootDir =
|
|
18657
|
+
const rootDir = join9(options.targetDir, layout.rootDir);
|
|
18651
18658
|
const restoration = await restoreCriticalFiles(rootDir, preservation);
|
|
18652
18659
|
if (restoration.restoredFiles.length > 0 || restoration.restoredDirs.length > 0) {
|
|
18653
18660
|
info("install.restored", {
|
|
@@ -18685,7 +18692,7 @@ async function install(options) {
|
|
|
18685
18692
|
async function getTemplateManifest() {
|
|
18686
18693
|
const packageRoot = getPackageRoot();
|
|
18687
18694
|
const layout = getProviderLayout();
|
|
18688
|
-
const manifestPath =
|
|
18695
|
+
const manifestPath = join9(packageRoot, "templates", layout.manifestFile);
|
|
18689
18696
|
if (await fileExists(manifestPath)) {
|
|
18690
18697
|
return readJsonFile(manifestPath);
|
|
18691
18698
|
}
|
|
@@ -18708,10 +18715,10 @@ async function installSkillsWithScopeFilter(srcPath, destPath, options) {
|
|
|
18708
18715
|
await ensureDirectory(destPath);
|
|
18709
18716
|
const entries = await readdir2(srcPath);
|
|
18710
18717
|
for (const entry of entries) {
|
|
18711
|
-
const entrySrcPath =
|
|
18718
|
+
const entrySrcPath = join9(srcPath, entry);
|
|
18712
18719
|
if (!(await stat2(entrySrcPath)).isDirectory())
|
|
18713
18720
|
continue;
|
|
18714
|
-
const skillMdPath =
|
|
18721
|
+
const skillMdPath = join9(entrySrcPath, "SKILL.md");
|
|
18715
18722
|
if (await fileExists(skillMdPath)) {
|
|
18716
18723
|
const content = await fsReadFile(skillMdPath, "utf-8");
|
|
18717
18724
|
const scope = getSkillScope(content);
|
|
@@ -18720,7 +18727,7 @@ async function installSkillsWithScopeFilter(srcPath, destPath, options) {
|
|
|
18720
18727
|
continue;
|
|
18721
18728
|
}
|
|
18722
18729
|
}
|
|
18723
|
-
await copyDirectory(entrySrcPath,
|
|
18730
|
+
await copyDirectory(entrySrcPath, join9(destPath, entry), {
|
|
18724
18731
|
overwrite: !!(options.force || options.backup),
|
|
18725
18732
|
preserveSymlinks: true,
|
|
18726
18733
|
preserveTimestamps: true
|
|
@@ -18731,10 +18738,10 @@ async function installAgentsWithDomainFilter(srcPath, destPath, options) {
|
|
|
18731
18738
|
await ensureDirectory(destPath);
|
|
18732
18739
|
const entries = await readdir2(srcPath);
|
|
18733
18740
|
for (const entry of entries) {
|
|
18734
|
-
const entrySrcPath =
|
|
18741
|
+
const entrySrcPath = join9(srcPath, entry);
|
|
18735
18742
|
const entryStat = await stat2(entrySrcPath);
|
|
18736
18743
|
if (entryStat.isDirectory()) {
|
|
18737
|
-
await copyDirectory(entrySrcPath,
|
|
18744
|
+
await copyDirectory(entrySrcPath, join9(destPath, entry), {
|
|
18738
18745
|
overwrite: !!(options.force || options.backup),
|
|
18739
18746
|
preserveSymlinks: true,
|
|
18740
18747
|
preserveTimestamps: true
|
|
@@ -18751,7 +18758,7 @@ async function installAgentsWithDomainFilter(srcPath, destPath, options) {
|
|
|
18751
18758
|
continue;
|
|
18752
18759
|
}
|
|
18753
18760
|
}
|
|
18754
|
-
await copyFile(entrySrcPath,
|
|
18761
|
+
await copyFile(entrySrcPath, join9(destPath, entry));
|
|
18755
18762
|
}
|
|
18756
18763
|
}
|
|
18757
18764
|
async function installComponent(targetDir, component, options) {
|
|
@@ -18759,7 +18766,7 @@ async function installComponent(targetDir, component, options) {
|
|
|
18759
18766
|
return false;
|
|
18760
18767
|
}
|
|
18761
18768
|
const templatePath = getComponentPath(component);
|
|
18762
|
-
const destPath =
|
|
18769
|
+
const destPath = join9(targetDir, templatePath);
|
|
18763
18770
|
const destExists = await fileExists(destPath);
|
|
18764
18771
|
if (destExists && !options.force && !options.backup) {
|
|
18765
18772
|
debug("install.component_skipped", { component });
|
|
@@ -18793,7 +18800,7 @@ async function installEntryDoc(targetDir, language, overwrite = false) {
|
|
|
18793
18800
|
const layout = getProviderLayout();
|
|
18794
18801
|
const templateFile = getEntryTemplateName(language);
|
|
18795
18802
|
const srcPath = resolveTemplatePath(templateFile);
|
|
18796
|
-
const destPath =
|
|
18803
|
+
const destPath = join9(targetDir, layout.entryFile);
|
|
18797
18804
|
if (!await fileExists(srcPath)) {
|
|
18798
18805
|
warn("install.entry_md_not_found", { language, path: srcPath, entry: layout.entryFile });
|
|
18799
18806
|
return false;
|
|
@@ -18813,8 +18820,8 @@ async function installEntryDoc(targetDir, language, overwrite = false) {
|
|
|
18813
18820
|
return true;
|
|
18814
18821
|
}
|
|
18815
18822
|
async function backupExisting(sourcePath, backupDir) {
|
|
18816
|
-
const name =
|
|
18817
|
-
const backupPath =
|
|
18823
|
+
const name = basename4(sourcePath);
|
|
18824
|
+
const backupPath = join9(backupDir, name);
|
|
18818
18825
|
await rename(sourcePath, backupPath);
|
|
18819
18826
|
return backupPath;
|
|
18820
18827
|
}
|
|
@@ -18823,7 +18830,7 @@ async function checkExistingPaths(targetDir) {
|
|
|
18823
18830
|
const pathsToCheck = [layout.entryFile, layout.rootDir, "guides"];
|
|
18824
18831
|
const existingPaths = [];
|
|
18825
18832
|
for (const relativePath of pathsToCheck) {
|
|
18826
|
-
const fullPath =
|
|
18833
|
+
const fullPath = join9(targetDir, relativePath);
|
|
18827
18834
|
if (await fileExists(fullPath)) {
|
|
18828
18835
|
existingPaths.push(relativePath);
|
|
18829
18836
|
}
|
|
@@ -18837,11 +18844,11 @@ async function backupExistingInstallation(targetDir) {
|
|
|
18837
18844
|
return [];
|
|
18838
18845
|
}
|
|
18839
18846
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
18840
|
-
const backupDir =
|
|
18847
|
+
const backupDir = join9(targetDir, `${layout.backupDirPrefix}${timestamp}`);
|
|
18841
18848
|
await ensureDirectory(backupDir);
|
|
18842
18849
|
const backedUpPaths = [];
|
|
18843
18850
|
for (const relativePath of existingPaths) {
|
|
18844
|
-
const fullPath =
|
|
18851
|
+
const fullPath = join9(targetDir, relativePath);
|
|
18845
18852
|
try {
|
|
18846
18853
|
const backupPath = await backupExisting(fullPath, backupDir);
|
|
18847
18854
|
backedUpPaths.push(backupPath);
|
|
@@ -18857,12 +18864,12 @@ async function backupExistingInstallation(targetDir) {
|
|
|
18857
18864
|
// src/core/mcp-config.ts
|
|
18858
18865
|
init_fs();
|
|
18859
18866
|
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
18860
|
-
import { join as
|
|
18867
|
+
import { join as join10 } from "node:path";
|
|
18861
18868
|
async function generateMCPConfig(targetDir) {
|
|
18862
18869
|
const layout = getProviderLayout();
|
|
18863
|
-
const mcpConfigPath =
|
|
18864
|
-
const ontologyDir =
|
|
18865
|
-
const ontologyExists = await fileExists(
|
|
18870
|
+
const mcpConfigPath = join10(targetDir, ".mcp.json");
|
|
18871
|
+
const ontologyDir = join10(layout.rootDir, "ontology");
|
|
18872
|
+
const ontologyExists = await fileExists(join10(targetDir, ontologyDir));
|
|
18866
18873
|
if (!ontologyExists) {
|
|
18867
18874
|
return;
|
|
18868
18875
|
}
|
|
@@ -18904,7 +18911,7 @@ async function generateMCPConfig(targetDir) {
|
|
|
18904
18911
|
// src/core/ontology-rag-setup.ts
|
|
18905
18912
|
init_fs();
|
|
18906
18913
|
import { execSync as execSync5 } from "node:child_process";
|
|
18907
|
-
import { join as
|
|
18914
|
+
import { join as join11 } from "node:path";
|
|
18908
18915
|
var MIN_PYTHON_MINOR = 10;
|
|
18909
18916
|
var DETECTION_TIMEOUT_MS = 3000;
|
|
18910
18917
|
var INSTALL_TIMEOUT_MS = 90000;
|
|
@@ -18955,7 +18962,7 @@ function createVenvWithPython3(targetDir) {
|
|
|
18955
18962
|
}
|
|
18956
18963
|
function installOntologyRagEditable(targetDir, useUv) {
|
|
18957
18964
|
const packageRoot = getPackageRoot();
|
|
18958
|
-
const ontologyPkgPath =
|
|
18965
|
+
const ontologyPkgPath = join11(packageRoot, "packages", "ontology-rag");
|
|
18959
18966
|
if (useUv) {
|
|
18960
18967
|
execSync5(`uv pip install --python .venv/bin/python -e "${ontologyPkgPath}"`, {
|
|
18961
18968
|
cwd: targetDir,
|
|
@@ -19028,7 +19035,7 @@ async function setupOntologyRag(targetDir) {
|
|
|
19028
19035
|
reason
|
|
19029
19036
|
};
|
|
19030
19037
|
}
|
|
19031
|
-
const venvPython =
|
|
19038
|
+
const venvPython = join11(targetDir, ".venv", "bin", "python");
|
|
19032
19039
|
const venvReady = await fileExists(venvPython);
|
|
19033
19040
|
if (!venvReady) {
|
|
19034
19041
|
const reason = ".venv/bin/python missing after install — environment may be incomplete. " + "Run `uv pip install -e packages/ontology-rag` manually to complete setup.";
|
|
@@ -19054,12 +19061,12 @@ init_package();
|
|
|
19054
19061
|
init_projects();
|
|
19055
19062
|
import { existsSync as existsSync2 } from "node:fs";
|
|
19056
19063
|
import { copyFile as copyFile2, cp } from "node:fs/promises";
|
|
19057
|
-
import { join as
|
|
19064
|
+
import { join as join13 } from "node:path";
|
|
19058
19065
|
init_fs();
|
|
19059
19066
|
init_registry();
|
|
19060
19067
|
async function checkExistingInstallation(targetDir) {
|
|
19061
19068
|
const layout = getProviderLayout();
|
|
19062
|
-
const rootDir =
|
|
19069
|
+
const rootDir = join13(targetDir, layout.rootDir);
|
|
19063
19070
|
return fileExists(rootDir);
|
|
19064
19071
|
}
|
|
19065
19072
|
async function installFromSnapshot(targetDir, snapshotPath, options) {
|
|
@@ -19071,7 +19078,7 @@ async function installFromSnapshot(targetDir, snapshotPath, options) {
|
|
|
19071
19078
|
};
|
|
19072
19079
|
}
|
|
19073
19080
|
const layout = getProviderLayout();
|
|
19074
|
-
const snapshotClaude =
|
|
19081
|
+
const snapshotClaude = join13(snapshotPath, layout.rootDir);
|
|
19075
19082
|
if (!existsSync2(snapshotClaude)) {
|
|
19076
19083
|
return {
|
|
19077
19084
|
success: false,
|
|
@@ -19085,24 +19092,24 @@ async function installFromSnapshot(targetDir, snapshotPath, options) {
|
|
|
19085
19092
|
if (exists && !options.force) {
|
|
19086
19093
|
console.log(i18n.t("cli.init.exists", { rootDir: layout.rootDir }));
|
|
19087
19094
|
console.log(i18n.t("cli.init.backing_up"));
|
|
19088
|
-
const backupDir =
|
|
19089
|
-
await cp(
|
|
19095
|
+
const backupDir = join13(targetDir, `.claude-backup-${new Date().toISOString().replace(/[:.]/g, "-").slice(0, -1)}`);
|
|
19096
|
+
await cp(join13(targetDir, layout.rootDir), backupDir, { recursive: true });
|
|
19090
19097
|
console.log(` Backed up to: ${backupDir}`);
|
|
19091
19098
|
}
|
|
19092
|
-
await cp(snapshotClaude,
|
|
19099
|
+
await cp(snapshotClaude, join13(targetDir, layout.rootDir), {
|
|
19093
19100
|
recursive: true,
|
|
19094
19101
|
force: true
|
|
19095
19102
|
});
|
|
19096
|
-
const snapshotGuides =
|
|
19103
|
+
const snapshotGuides = join13(snapshotPath, "guides");
|
|
19097
19104
|
if (existsSync2(snapshotGuides)) {
|
|
19098
|
-
await cp(snapshotGuides,
|
|
19105
|
+
await cp(snapshotGuides, join13(targetDir, "guides"), {
|
|
19099
19106
|
recursive: true,
|
|
19100
19107
|
force: true
|
|
19101
19108
|
});
|
|
19102
19109
|
}
|
|
19103
|
-
const snapshotEntry =
|
|
19110
|
+
const snapshotEntry = join13(snapshotPath, layout.entryFile);
|
|
19104
19111
|
if (existsSync2(snapshotEntry)) {
|
|
19105
|
-
await copyFile2(snapshotEntry,
|
|
19112
|
+
await copyFile2(snapshotEntry, join13(targetDir, layout.entryFile));
|
|
19106
19113
|
}
|
|
19107
19114
|
try {
|
|
19108
19115
|
const existing = await readLockFile(targetDir);
|
|
@@ -19985,7 +19992,7 @@ async function runInitWizard(options) {
|
|
|
19985
19992
|
// src/cli/init.ts
|
|
19986
19993
|
async function checkExistingInstallation2(targetDir) {
|
|
19987
19994
|
const layout = getProviderLayout();
|
|
19988
|
-
const rootDir =
|
|
19995
|
+
const rootDir = join14(targetDir, layout.rootDir);
|
|
19989
19996
|
return fileExists(rootDir);
|
|
19990
19997
|
}
|
|
19991
19998
|
var PROVIDER_SUBDIR_COMPONENTS = new Set([
|
|
@@ -19999,13 +20006,13 @@ var PROVIDER_SUBDIR_COMPONENTS = new Set([
|
|
|
19999
20006
|
function componentToPath(targetDir, component) {
|
|
20000
20007
|
if (component === "entry-md") {
|
|
20001
20008
|
const layout = getProviderLayout();
|
|
20002
|
-
return
|
|
20009
|
+
return join14(targetDir, layout.entryFile);
|
|
20003
20010
|
}
|
|
20004
20011
|
if (PROVIDER_SUBDIR_COMPONENTS.has(component)) {
|
|
20005
20012
|
const layout = getProviderLayout();
|
|
20006
|
-
return
|
|
20013
|
+
return join14(targetDir, layout.rootDir, component);
|
|
20007
20014
|
}
|
|
20008
|
-
return
|
|
20015
|
+
return join14(targetDir, component);
|
|
20009
20016
|
}
|
|
20010
20017
|
function buildInstalledPaths(targetDir, components) {
|
|
20011
20018
|
return components.map((component) => componentToPath(targetDir, component));
|
|
@@ -20128,7 +20135,7 @@ async function initCommand(options) {
|
|
|
20128
20135
|
}
|
|
20129
20136
|
|
|
20130
20137
|
// src/cli/list.ts
|
|
20131
|
-
import { basename as
|
|
20138
|
+
import { basename as basename6, dirname as dirname6, join as join15, relative as relative3 } from "node:path";
|
|
20132
20139
|
init_fs();
|
|
20133
20140
|
var ALLOWED_TOP_LEVEL_KEYS = new Set(["name", "type", "description", "version", "category"]);
|
|
20134
20141
|
function parseKeyValue(line) {
|
|
@@ -20175,7 +20182,7 @@ function parseYamlMetadata(content) {
|
|
|
20175
20182
|
return result;
|
|
20176
20183
|
}
|
|
20177
20184
|
function extractAgentTypeFromFilename(filename) {
|
|
20178
|
-
const name =
|
|
20185
|
+
const name = basename6(filename, ".md");
|
|
20179
20186
|
const prefixMap = {
|
|
20180
20187
|
lang: "language",
|
|
20181
20188
|
be: "backend",
|
|
@@ -20193,17 +20200,17 @@ function extractAgentTypeFromFilename(filename) {
|
|
|
20193
20200
|
return prefixMap[prefix] || "unknown";
|
|
20194
20201
|
}
|
|
20195
20202
|
function extractSkillCategoryFromPath(skillPath, baseDir, rootDir) {
|
|
20196
|
-
const relativePath = relative3(
|
|
20203
|
+
const relativePath = relative3(join15(baseDir, rootDir, "skills"), skillPath);
|
|
20197
20204
|
const parts = relativePath.split("/").filter(Boolean);
|
|
20198
20205
|
return parts[0] || "unknown";
|
|
20199
20206
|
}
|
|
20200
20207
|
function extractGuideCategoryFromPath(guidePath, baseDir) {
|
|
20201
|
-
const relativePath = relative3(
|
|
20208
|
+
const relativePath = relative3(join15(baseDir, "guides"), guidePath);
|
|
20202
20209
|
const parts = relativePath.split("/").filter(Boolean);
|
|
20203
20210
|
return parts[0] || "unknown";
|
|
20204
20211
|
}
|
|
20205
20212
|
function extractRulePriorityFromFilename(filename) {
|
|
20206
|
-
const name =
|
|
20213
|
+
const name = basename6(filename, ".md");
|
|
20207
20214
|
const parts = name.split("-");
|
|
20208
20215
|
return parts[0] || "unknown";
|
|
20209
20216
|
}
|
|
@@ -20292,7 +20299,7 @@ async function tryExtractMarkdownDescription(mdPath, options = {}) {
|
|
|
20292
20299
|
}
|
|
20293
20300
|
}
|
|
20294
20301
|
async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
20295
|
-
const agentsDir =
|
|
20302
|
+
const agentsDir = join15(targetDir, rootDir, "agents");
|
|
20296
20303
|
if (!await fileExists(agentsDir))
|
|
20297
20304
|
return [];
|
|
20298
20305
|
try {
|
|
@@ -20301,8 +20308,8 @@ async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
|
20301
20308
|
const customAgentPaths = new Set(customComponents.filter((c) => c.type === "agent").map((c) => c.path));
|
|
20302
20309
|
const agentMdFiles = await listFiles(agentsDir, { recursive: false, pattern: "*.md" });
|
|
20303
20310
|
const agents = await Promise.all(agentMdFiles.map(async (agentMdPath) => {
|
|
20304
|
-
const filename =
|
|
20305
|
-
const name =
|
|
20311
|
+
const filename = basename6(agentMdPath);
|
|
20312
|
+
const name = basename6(filename, ".md");
|
|
20306
20313
|
const description = await tryExtractMarkdownDescription(agentMdPath);
|
|
20307
20314
|
const relativePath = relative3(targetDir, agentMdPath);
|
|
20308
20315
|
return {
|
|
@@ -20320,7 +20327,7 @@ async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
|
20320
20327
|
}
|
|
20321
20328
|
}
|
|
20322
20329
|
async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
20323
|
-
const skillsDir =
|
|
20330
|
+
const skillsDir = join15(targetDir, rootDir, "skills");
|
|
20324
20331
|
if (!await fileExists(skillsDir))
|
|
20325
20332
|
return [];
|
|
20326
20333
|
try {
|
|
@@ -20329,12 +20336,12 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
20329
20336
|
const customSkillPaths = new Set(customComponents.filter((c) => c.type === "skill").map((c) => c.path));
|
|
20330
20337
|
const skillMdFiles = await listFiles(skillsDir, { recursive: true, pattern: "SKILL.md" });
|
|
20331
20338
|
const skills = await Promise.all(skillMdFiles.map(async (skillMdPath) => {
|
|
20332
|
-
const skillDir =
|
|
20333
|
-
const indexYamlPath =
|
|
20339
|
+
const skillDir = dirname6(skillMdPath);
|
|
20340
|
+
const indexYamlPath = join15(skillDir, "index.yaml");
|
|
20334
20341
|
const { description, version } = await tryReadIndexYamlMetadata(indexYamlPath);
|
|
20335
20342
|
const relativePath = relative3(targetDir, skillDir);
|
|
20336
20343
|
return {
|
|
20337
|
-
name:
|
|
20344
|
+
name: basename6(skillDir),
|
|
20338
20345
|
type: "skill",
|
|
20339
20346
|
category: extractSkillCategoryFromPath(skillDir, targetDir, rootDir),
|
|
20340
20347
|
path: relativePath,
|
|
@@ -20349,7 +20356,7 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
20349
20356
|
}
|
|
20350
20357
|
}
|
|
20351
20358
|
async function getGuides(targetDir, config) {
|
|
20352
|
-
const guidesDir =
|
|
20359
|
+
const guidesDir = join15(targetDir, "guides");
|
|
20353
20360
|
if (!await fileExists(guidesDir))
|
|
20354
20361
|
return [];
|
|
20355
20362
|
try {
|
|
@@ -20361,7 +20368,7 @@ async function getGuides(targetDir, config) {
|
|
|
20361
20368
|
const description = await tryExtractMarkdownDescription(guideMdPath, { maxLength: 100 });
|
|
20362
20369
|
const relativePath = relative3(targetDir, guideMdPath);
|
|
20363
20370
|
return {
|
|
20364
|
-
name:
|
|
20371
|
+
name: basename6(guideMdPath, ".md"),
|
|
20365
20372
|
type: "guide",
|
|
20366
20373
|
category: extractGuideCategoryFromPath(guideMdPath, targetDir),
|
|
20367
20374
|
path: relativePath,
|
|
@@ -20376,7 +20383,7 @@ async function getGuides(targetDir, config) {
|
|
|
20376
20383
|
}
|
|
20377
20384
|
var RULE_PRIORITY_ORDER = { MUST: 0, SHOULD: 1, MAY: 2 };
|
|
20378
20385
|
async function getRules(targetDir, rootDir = ".claude", config) {
|
|
20379
|
-
const rulesDir =
|
|
20386
|
+
const rulesDir = join15(targetDir, rootDir, "rules");
|
|
20380
20387
|
if (!await fileExists(rulesDir))
|
|
20381
20388
|
return [];
|
|
20382
20389
|
try {
|
|
@@ -20385,13 +20392,13 @@ async function getRules(targetDir, rootDir = ".claude", config) {
|
|
|
20385
20392
|
const customRulePaths = new Set(customComponents.filter((c) => c.type === "rule").map((c) => c.path));
|
|
20386
20393
|
const ruleMdFiles = await listFiles(rulesDir, { recursive: false, pattern: "*.md" });
|
|
20387
20394
|
const rules = await Promise.all(ruleMdFiles.map(async (ruleMdPath) => {
|
|
20388
|
-
const filename =
|
|
20395
|
+
const filename = basename6(ruleMdPath);
|
|
20389
20396
|
const description = await tryExtractMarkdownDescription(ruleMdPath, {
|
|
20390
20397
|
cleanFormatting: true
|
|
20391
20398
|
});
|
|
20392
20399
|
const relativePath = relative3(targetDir, ruleMdPath);
|
|
20393
20400
|
return {
|
|
20394
|
-
name:
|
|
20401
|
+
name: basename6(ruleMdPath, ".md"),
|
|
20395
20402
|
type: extractRulePriorityFromFilename(filename),
|
|
20396
20403
|
path: relativePath,
|
|
20397
20404
|
description,
|
|
@@ -20448,7 +20455,7 @@ function formatAsJson(components) {
|
|
|
20448
20455
|
console.log(JSON.stringify(components, null, 2));
|
|
20449
20456
|
}
|
|
20450
20457
|
async function getHooks(targetDir, rootDir = ".claude") {
|
|
20451
|
-
const hooksDir =
|
|
20458
|
+
const hooksDir = join15(targetDir, rootDir, "hooks");
|
|
20452
20459
|
if (!await fileExists(hooksDir))
|
|
20453
20460
|
return [];
|
|
20454
20461
|
try {
|
|
@@ -20457,7 +20464,7 @@ async function getHooks(targetDir, rootDir = ".claude") {
|
|
|
20457
20464
|
const hookYamls = await listFiles(hooksDir, { recursive: true, pattern: "*.yaml" });
|
|
20458
20465
|
const allFiles = [...hookFiles, ...hookConfigs, ...hookYamls];
|
|
20459
20466
|
return allFiles.map((hookPath) => ({
|
|
20460
|
-
name:
|
|
20467
|
+
name: basename6(hookPath),
|
|
20461
20468
|
type: "hook",
|
|
20462
20469
|
path: relative3(targetDir, hookPath)
|
|
20463
20470
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -20466,7 +20473,7 @@ async function getHooks(targetDir, rootDir = ".claude") {
|
|
|
20466
20473
|
}
|
|
20467
20474
|
}
|
|
20468
20475
|
async function getContexts(targetDir, rootDir = ".claude") {
|
|
20469
|
-
const contextsDir =
|
|
20476
|
+
const contextsDir = join15(targetDir, rootDir, "contexts");
|
|
20470
20477
|
if (!await fileExists(contextsDir))
|
|
20471
20478
|
return [];
|
|
20472
20479
|
try {
|
|
@@ -20477,7 +20484,7 @@ async function getContexts(targetDir, rootDir = ".claude") {
|
|
|
20477
20484
|
const ext = ctxPath.endsWith(".md") ? ".md" : ".yaml";
|
|
20478
20485
|
const description = ext === ".md" ? await tryExtractMarkdownDescription(ctxPath, { maxLength: 100 }) : undefined;
|
|
20479
20486
|
return {
|
|
20480
|
-
name:
|
|
20487
|
+
name: basename6(ctxPath, ext),
|
|
20481
20488
|
type: "context",
|
|
20482
20489
|
path: relative3(targetDir, ctxPath),
|
|
20483
20490
|
description
|
|
@@ -20859,22 +20866,22 @@ async function securityCommand(_options = {}) {
|
|
|
20859
20866
|
|
|
20860
20867
|
// src/cli/serve-commands.ts
|
|
20861
20868
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
20862
|
-
import { join as
|
|
20869
|
+
import { join as join17 } from "node:path";
|
|
20863
20870
|
|
|
20864
20871
|
// src/cli/serve.ts
|
|
20865
20872
|
import { spawn } from "node:child_process";
|
|
20866
20873
|
import { existsSync as existsSync3 } from "node:fs";
|
|
20867
20874
|
import { readFile as readFile3, unlink, writeFile as writeFile3 } from "node:fs/promises";
|
|
20868
|
-
import { join as
|
|
20875
|
+
import { join as join16 } from "node:path";
|
|
20869
20876
|
var DEFAULT_PORT = 4321;
|
|
20870
|
-
var PID_FILE =
|
|
20877
|
+
var PID_FILE = join16(process.env.HOME ?? "~", ".omcustom-serve.pid");
|
|
20871
20878
|
function findServeBuildDir(projectRoot, options) {
|
|
20872
|
-
const localBuild =
|
|
20873
|
-
if (existsSync3(
|
|
20879
|
+
const localBuild = join16(projectRoot, "packages", "serve", "build");
|
|
20880
|
+
if (existsSync3(join16(localBuild, "index.js")))
|
|
20874
20881
|
return localBuild;
|
|
20875
20882
|
if (options?.skipNpmFallback !== true) {
|
|
20876
|
-
const npmBuild =
|
|
20877
|
-
if (existsSync3(
|
|
20883
|
+
const npmBuild = join16(import.meta.dirname, "..", "..", "packages", "serve", "build");
|
|
20884
|
+
if (existsSync3(join16(npmBuild, "index.js")))
|
|
20878
20885
|
return npmBuild;
|
|
20879
20886
|
}
|
|
20880
20887
|
return null;
|
|
@@ -20902,7 +20909,7 @@ async function startServeBackground(projectRoot, port = DEFAULT_PORT, buildDirOp
|
|
|
20902
20909
|
if (buildDir === null) {
|
|
20903
20910
|
return;
|
|
20904
20911
|
}
|
|
20905
|
-
const child = spawn("node", [
|
|
20912
|
+
const child = spawn("node", [join16(buildDir, "index.js")], {
|
|
20906
20913
|
env: {
|
|
20907
20914
|
...process.env,
|
|
20908
20915
|
OMCUSTOM_PORT: String(port),
|
|
@@ -20979,7 +20986,7 @@ function runForeground(projectRoot, port, buildDirOpts) {
|
|
|
20979
20986
|
process.exit(1);
|
|
20980
20987
|
}
|
|
20981
20988
|
console.log(`Web UI: http://localhost:${port}`);
|
|
20982
|
-
spawnSync2("node", [
|
|
20989
|
+
spawnSync2("node", [join17(buildDir, "index.js")], {
|
|
20983
20990
|
env: {
|
|
20984
20991
|
...process.env,
|
|
20985
20992
|
OMCUSTOM_PORT: String(port),
|
|
@@ -20998,12 +21005,12 @@ import { resolve as resolve4 } from "node:path";
|
|
|
20998
21005
|
init_fs();
|
|
20999
21006
|
import { existsSync as existsSync4 } from "node:fs";
|
|
21000
21007
|
import { cp as cp2, mkdir as mkdir2 } from "node:fs/promises";
|
|
21001
|
-
import { join as
|
|
21008
|
+
import { join as join18 } from "node:path";
|
|
21002
21009
|
async function loadVersions() {
|
|
21003
21010
|
try {
|
|
21004
21011
|
const packageRoot = getPackageRoot();
|
|
21005
|
-
const manifest = await readJsonFile(
|
|
21006
|
-
const pkg = await readJsonFile(
|
|
21012
|
+
const manifest = await readJsonFile(join18(packageRoot, "templates", "manifest.json"));
|
|
21013
|
+
const pkg = await readJsonFile(join18(packageRoot, "package.json"));
|
|
21007
21014
|
return { generatorVersion: pkg.version, templateVersion: manifest.version };
|
|
21008
21015
|
} catch {
|
|
21009
21016
|
return { generatorVersion: "0.0.0", templateVersion: "0.0.0" };
|
|
@@ -21073,7 +21080,7 @@ async function countFiles(dir) {
|
|
|
21073
21080
|
return 0;
|
|
21074
21081
|
}
|
|
21075
21082
|
for (const entry of entries) {
|
|
21076
|
-
const full =
|
|
21083
|
+
const full = join18(current, entry);
|
|
21077
21084
|
try {
|
|
21078
21085
|
const s = await stat(full);
|
|
21079
21086
|
if (s.isDirectory()) {
|
|
@@ -21088,19 +21095,19 @@ async function countFiles(dir) {
|
|
|
21088
21095
|
return walk(dir);
|
|
21089
21096
|
}
|
|
21090
21097
|
async function exportSnapshot(targetDir, outputPath) {
|
|
21091
|
-
const claudeDir =
|
|
21092
|
-
const guidesDir =
|
|
21098
|
+
const claudeDir = join18(targetDir, ".claude");
|
|
21099
|
+
const guidesDir = join18(targetDir, "guides");
|
|
21093
21100
|
if (!existsSync4(claudeDir)) {
|
|
21094
21101
|
return { success: false, exportPath: outputPath, fileCount: 0 };
|
|
21095
21102
|
}
|
|
21096
21103
|
await mkdir2(outputPath, { recursive: true });
|
|
21097
|
-
const destClaude =
|
|
21104
|
+
const destClaude = join18(outputPath, ".claude");
|
|
21098
21105
|
await cp2(claudeDir, destClaude, {
|
|
21099
21106
|
recursive: true,
|
|
21100
21107
|
filter: isExportable
|
|
21101
21108
|
});
|
|
21102
21109
|
if (existsSync4(guidesDir)) {
|
|
21103
|
-
await cp2(guidesDir,
|
|
21110
|
+
await cp2(guidesDir, join18(outputPath, "guides"), { recursive: true });
|
|
21104
21111
|
}
|
|
21105
21112
|
const lockfile = await generateCurrentLockfile(targetDir);
|
|
21106
21113
|
if (lockfile) {
|
|
@@ -21184,7 +21191,7 @@ import { constants as osConstants } from "node:os";
|
|
|
21184
21191
|
|
|
21185
21192
|
// src/core/updater.ts
|
|
21186
21193
|
init_package();
|
|
21187
|
-
import { join as
|
|
21194
|
+
import { join as join19 } from "node:path";
|
|
21188
21195
|
init_fs();
|
|
21189
21196
|
|
|
21190
21197
|
// src/core/entry-merger.ts
|
|
@@ -21439,7 +21446,7 @@ function resolveCustomizations(customizations, configPreserveFiles, targetDir) {
|
|
|
21439
21446
|
}
|
|
21440
21447
|
async function updateEntryDoc(targetDir, config, options) {
|
|
21441
21448
|
const layout = getProviderLayout();
|
|
21442
|
-
const entryPath =
|
|
21449
|
+
const entryPath = join19(targetDir, layout.entryFile);
|
|
21443
21450
|
const templateName = getEntryTemplateName2(config.language);
|
|
21444
21451
|
const templatePath = resolveTemplatePath(templateName);
|
|
21445
21452
|
if (!await fileExists(templatePath)) {
|
|
@@ -21477,7 +21484,7 @@ async function backfillStatusLineRefreshInterval(targetDir, options) {
|
|
|
21477
21484
|
return;
|
|
21478
21485
|
}
|
|
21479
21486
|
const layout = getProviderLayout();
|
|
21480
|
-
const settingsPath =
|
|
21487
|
+
const settingsPath = join19(targetDir, layout.rootDir, "settings.local.json");
|
|
21481
21488
|
if (!await fileExists(settingsPath)) {
|
|
21482
21489
|
return;
|
|
21483
21490
|
}
|
|
@@ -21503,7 +21510,7 @@ async function migrateHookCommandsInSettingsLocal(targetDir, options) {
|
|
|
21503
21510
|
return;
|
|
21504
21511
|
}
|
|
21505
21512
|
const layout = getProviderLayout();
|
|
21506
|
-
const settingsPath =
|
|
21513
|
+
const settingsPath = join19(targetDir, layout.rootDir, "settings.local.json");
|
|
21507
21514
|
if (!await fileExists(settingsPath)) {
|
|
21508
21515
|
return;
|
|
21509
21516
|
}
|
|
@@ -21598,7 +21605,7 @@ async function regenerateLockfile(targetDir, result) {
|
|
|
21598
21605
|
}
|
|
21599
21606
|
}
|
|
21600
21607
|
async function shouldSkipSelfUpdate2(targetDir, result) {
|
|
21601
|
-
const targetPkgPath =
|
|
21608
|
+
const targetPkgPath = join19(targetDir, "package.json");
|
|
21602
21609
|
if (await fileExists(targetPkgPath)) {
|
|
21603
21610
|
const targetPkg = await readJsonFile(targetPkgPath);
|
|
21604
21611
|
if (targetPkg.name === "oh-my-customcode") {
|
|
@@ -21737,11 +21744,11 @@ async function collectProtectedSkipPaths(srcPath, destPath, componentPath, force
|
|
|
21737
21744
|
const warnedPaths = [];
|
|
21738
21745
|
const updatedPaths = [];
|
|
21739
21746
|
for (const p of protectedRelative) {
|
|
21740
|
-
const targetFilePath =
|
|
21747
|
+
const targetFilePath = join19(targetDir, componentPath, p);
|
|
21741
21748
|
const lockfileKey = `${componentPath}/${p}`.replace(/\\/g, "/");
|
|
21742
21749
|
const shouldSkip = await shouldSkipProtectedFile(targetFilePath, lockfileKey, lockfile);
|
|
21743
21750
|
if (shouldSkip) {
|
|
21744
|
-
skipPaths.push(path.relative(destPath,
|
|
21751
|
+
skipPaths.push(path.relative(destPath, join19(destPath, p)));
|
|
21745
21752
|
warnedPaths.push(p);
|
|
21746
21753
|
} else {
|
|
21747
21754
|
updatedPaths.push(p);
|
|
@@ -21787,7 +21794,7 @@ async function updateComponent(targetDir, component, customizations, options, co
|
|
|
21787
21794
|
const preservedFiles = [];
|
|
21788
21795
|
const componentPath = getComponentPath2(component);
|
|
21789
21796
|
const srcPath = resolveTemplatePath(componentPath);
|
|
21790
|
-
const destPath =
|
|
21797
|
+
const destPath = join19(targetDir, componentPath);
|
|
21791
21798
|
const customComponents = config.customComponents || [];
|
|
21792
21799
|
const skipPaths = [];
|
|
21793
21800
|
if (customizations && !options.forceOverwriteAll) {
|
|
@@ -21829,7 +21836,7 @@ async function updateComponent(targetDir, component, customizations, options, co
|
|
|
21829
21836
|
}
|
|
21830
21837
|
skipPaths.push(...protectedSkipPaths);
|
|
21831
21838
|
const path = await import("node:path");
|
|
21832
|
-
const normalizedSkipPaths = skipPaths.map((p) => path.relative(destPath,
|
|
21839
|
+
const normalizedSkipPaths = skipPaths.map((p) => path.relative(destPath, join19(targetDir, p)));
|
|
21833
21840
|
const uniqueSkipPaths = [...new Set(normalizedSkipPaths)];
|
|
21834
21841
|
await copyDirectory(srcPath, destPath, {
|
|
21835
21842
|
overwrite: true,
|
|
@@ -21858,7 +21865,7 @@ async function syncRootLevelFiles(targetDir, options, customizations) {
|
|
|
21858
21865
|
const preserved = [];
|
|
21859
21866
|
const preserveSet = new Set(customizations && !options.forceOverwriteAll ? customizations.preserveFiles : []);
|
|
21860
21867
|
for (const fileName of ROOT_LEVEL_FILES) {
|
|
21861
|
-
const srcPath = resolveTemplatePath(
|
|
21868
|
+
const srcPath = resolveTemplatePath(join19(layout.rootDir, fileName));
|
|
21862
21869
|
if (!await fileExists(srcPath)) {
|
|
21863
21870
|
continue;
|
|
21864
21871
|
}
|
|
@@ -21867,8 +21874,8 @@ async function syncRootLevelFiles(targetDir, options, customizations) {
|
|
|
21867
21874
|
preserved.push(relPath);
|
|
21868
21875
|
continue;
|
|
21869
21876
|
}
|
|
21870
|
-
const destPath =
|
|
21871
|
-
await ensureDirectory(
|
|
21877
|
+
const destPath = join19(targetDir, layout.rootDir, fileName);
|
|
21878
|
+
await ensureDirectory(join19(destPath, ".."));
|
|
21872
21879
|
await fs.copyFile(srcPath, destPath);
|
|
21873
21880
|
if (fileName.endsWith(".sh")) {
|
|
21874
21881
|
await fs.chmod(destPath, 493);
|
|
@@ -21903,7 +21910,7 @@ async function removeDeprecatedFiles(targetDir, options) {
|
|
|
21903
21910
|
});
|
|
21904
21911
|
continue;
|
|
21905
21912
|
}
|
|
21906
|
-
const fullPath =
|
|
21913
|
+
const fullPath = join19(targetDir, entry.path);
|
|
21907
21914
|
if (await fileExists(fullPath)) {
|
|
21908
21915
|
await fs.unlink(fullPath);
|
|
21909
21916
|
removed.push(entry.path);
|
|
@@ -21944,7 +21951,7 @@ async function syncNamespaceInFile(targetFilePath, upstreamFilePath) {
|
|
|
21944
21951
|
async function processNamespaceSyncEntry(entry, relPath, fullSrcPath, destPath, componentPath, lockfile) {
|
|
21945
21952
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
21946
21953
|
return null;
|
|
21947
|
-
const targetFilePath =
|
|
21954
|
+
const targetFilePath = join19(destPath, relPath);
|
|
21948
21955
|
const lockfileKey = `${componentPath}/${relPath}`.replace(/\\/g, "/");
|
|
21949
21956
|
const shouldSkip = await shouldSkipProtectedFile(targetFilePath, lockfileKey, lockfile);
|
|
21950
21957
|
if (shouldSkip)
|
|
@@ -21959,7 +21966,7 @@ async function applyNamespaceSync(targetDir, component, lockfile) {
|
|
|
21959
21966
|
return [];
|
|
21960
21967
|
const componentPath = getComponentPath2(component);
|
|
21961
21968
|
const srcPath = resolveTemplatePath(componentPath);
|
|
21962
|
-
const destPath =
|
|
21969
|
+
const destPath = join19(targetDir, componentPath);
|
|
21963
21970
|
const fs = await import("node:fs/promises");
|
|
21964
21971
|
const synced = [];
|
|
21965
21972
|
const queue = [{ dir: srcPath, relDir: "" }];
|
|
@@ -21973,7 +21980,7 @@ async function applyNamespaceSync(targetDir, component, lockfile) {
|
|
|
21973
21980
|
}
|
|
21974
21981
|
for (const entry of entries) {
|
|
21975
21982
|
const relPath = relDir ? `${relDir}/${entry.name}` : entry.name;
|
|
21976
|
-
const fullSrcPath =
|
|
21983
|
+
const fullSrcPath = join19(dir, entry.name);
|
|
21977
21984
|
if (entry.isDirectory()) {
|
|
21978
21985
|
queue.push({ dir: fullSrcPath, relDir: relPath });
|
|
21979
21986
|
continue;
|
|
@@ -21996,26 +22003,26 @@ function getComponentPath2(component) {
|
|
|
21996
22003
|
}
|
|
21997
22004
|
async function backupInstallation(targetDir) {
|
|
21998
22005
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
21999
|
-
const backupDir =
|
|
22006
|
+
const backupDir = join19(targetDir, `.omcustom-backup-${timestamp}`);
|
|
22000
22007
|
const fs = await import("node:fs/promises");
|
|
22001
22008
|
await ensureDirectory(backupDir);
|
|
22002
22009
|
const layout = getProviderLayout();
|
|
22003
22010
|
const dirsToBackup = [layout.rootDir, "guides"];
|
|
22004
22011
|
for (const dir of dirsToBackup) {
|
|
22005
|
-
const srcPath =
|
|
22012
|
+
const srcPath = join19(targetDir, dir);
|
|
22006
22013
|
if (await fileExists(srcPath)) {
|
|
22007
|
-
const destPath =
|
|
22014
|
+
const destPath = join19(backupDir, dir);
|
|
22008
22015
|
await copyDirectory(srcPath, destPath, { overwrite: true });
|
|
22009
22016
|
}
|
|
22010
22017
|
}
|
|
22011
|
-
const entryPath =
|
|
22018
|
+
const entryPath = join19(targetDir, layout.entryFile);
|
|
22012
22019
|
if (await fileExists(entryPath)) {
|
|
22013
|
-
await fs.copyFile(entryPath,
|
|
22020
|
+
await fs.copyFile(entryPath, join19(backupDir, layout.entryFile));
|
|
22014
22021
|
}
|
|
22015
22022
|
return backupDir;
|
|
22016
22023
|
}
|
|
22017
22024
|
async function loadCustomizationManifest(targetDir) {
|
|
22018
|
-
const manifestPath =
|
|
22025
|
+
const manifestPath = join19(targetDir, CUSTOMIZATION_MANIFEST_FILE);
|
|
22019
22026
|
if (await fileExists(manifestPath)) {
|
|
22020
22027
|
return readJsonFile(manifestPath);
|
|
22021
22028
|
}
|