oh-my-customcode 1.1.99 → 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 +206 -168
- package/dist/index.js +30 -30
- package/package.json +1 -1
- package/templates/manifest.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -47,8 +47,9 @@ var __esm = (fn, res, err) => () => {
|
|
|
47
47
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
48
48
|
|
|
49
49
|
// src/utils/home.ts
|
|
50
|
+
import { realpathSync } from "node:fs";
|
|
50
51
|
import { homedir, userInfo } from "node:os";
|
|
51
|
-
import { parse, sep } from "node:path";
|
|
52
|
+
import { basename, dirname, isAbsolute, join, parse, sep } from "node:path";
|
|
52
53
|
function readEnvHome() {
|
|
53
54
|
return process.env.HOME;
|
|
54
55
|
}
|
|
@@ -94,16 +95,35 @@ function isPathWithin(path, base) {
|
|
|
94
95
|
const prefix = strippedBase.endsWith(sep) || strippedBase.endsWith("/") ? strippedBase : strippedBase + sep;
|
|
95
96
|
return path.startsWith(prefix);
|
|
96
97
|
}
|
|
98
|
+
function realpathOrSelf(p) {
|
|
99
|
+
if (p === "" || !isAbsolute(p)) {
|
|
100
|
+
return p;
|
|
101
|
+
}
|
|
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);
|
|
112
|
+
}
|
|
113
|
+
return p;
|
|
114
|
+
}
|
|
97
115
|
function isUnderHome(path, home) {
|
|
98
|
-
|
|
116
|
+
const base = home ?? resolveHomeDir();
|
|
117
|
+
const paths = [path, realpathOrSelf(path)];
|
|
118
|
+
const bases = [base, realpathOrSelf(base)];
|
|
119
|
+
return paths.some((p) => bases.some((b) => isPathWithin(p, b)));
|
|
99
120
|
}
|
|
100
|
-
function
|
|
101
|
-
const base = stripTrailingSeparators(
|
|
121
|
+
function tildeRelative(path, rawBase) {
|
|
122
|
+
const base = stripTrailingSeparators(rawBase);
|
|
102
123
|
if (!isPathWithin(path, base)) {
|
|
103
|
-
return
|
|
124
|
+
return;
|
|
104
125
|
}
|
|
105
|
-
|
|
106
|
-
if (strippedPath === base) {
|
|
126
|
+
if (stripTrailingSeparators(path) === base) {
|
|
107
127
|
return "~";
|
|
108
128
|
}
|
|
109
129
|
let rest = path.slice(base.length);
|
|
@@ -112,13 +132,31 @@ function shortenHome(path, home) {
|
|
|
112
132
|
}
|
|
113
133
|
return `~${sep}${rest}`;
|
|
114
134
|
}
|
|
135
|
+
function shortenHome(path, home) {
|
|
136
|
+
const base = home ?? resolveHomeDir();
|
|
137
|
+
const realPath = realpathOrSelf(path);
|
|
138
|
+
const realBase = realpathOrSelf(base);
|
|
139
|
+
const candidates = [
|
|
140
|
+
[path, base],
|
|
141
|
+
[path, realBase],
|
|
142
|
+
[realPath, base],
|
|
143
|
+
[realPath, realBase]
|
|
144
|
+
];
|
|
145
|
+
for (const [p, b] of candidates) {
|
|
146
|
+
const shortened = tildeRelative(p, b);
|
|
147
|
+
if (shortened !== undefined) {
|
|
148
|
+
return shortened;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return path;
|
|
152
|
+
}
|
|
115
153
|
var init_home = () => {};
|
|
116
154
|
|
|
117
155
|
// src/core/registry.ts
|
|
118
|
-
import { realpathSync } from "node:fs";
|
|
156
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
119
157
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
120
158
|
import { tmpdir } from "node:os";
|
|
121
|
-
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";
|
|
122
160
|
function isTempPath(projectPath) {
|
|
123
161
|
const normalized = resolve(projectPath);
|
|
124
162
|
const candidates = new Set;
|
|
@@ -133,7 +171,7 @@ function isTempPath(projectPath) {
|
|
|
133
171
|
candidates.add("/var/folders");
|
|
134
172
|
for (const candidate of [...candidates]) {
|
|
135
173
|
try {
|
|
136
|
-
candidates.add(
|
|
174
|
+
candidates.add(realpathSync2(candidate));
|
|
137
175
|
} catch {}
|
|
138
176
|
}
|
|
139
177
|
for (const candidate of candidates) {
|
|
@@ -153,10 +191,10 @@ function registryDir(home) {
|
|
|
153
191
|
if (resolved === "") {
|
|
154
192
|
throw new Error("Could not determine the home directory for the project registry");
|
|
155
193
|
}
|
|
156
|
-
return
|
|
194
|
+
return join2(resolved, ".oh-my-customcode");
|
|
157
195
|
}
|
|
158
196
|
function registryPath() {
|
|
159
|
-
return
|
|
197
|
+
return join2(registryDir(), "projects.json");
|
|
160
198
|
}
|
|
161
199
|
function emptyRegistry() {
|
|
162
200
|
return { projects: {} };
|
|
@@ -257,14 +295,14 @@ async function migrateFromLockfiles(searchDirs) {
|
|
|
257
295
|
} catch {
|
|
258
296
|
return;
|
|
259
297
|
}
|
|
260
|
-
const entry = await parseLockFile(
|
|
298
|
+
const entry = await parseLockFile(join2(dir, ".omcustom.lock.json"));
|
|
261
299
|
if (entry !== null) {
|
|
262
300
|
discovered.set(resolve(dir), entry);
|
|
263
301
|
return;
|
|
264
302
|
}
|
|
265
303
|
if (depth < MAX_DEPTH) {
|
|
266
304
|
const subdirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !SCAN_SKIP_DIRS.has(e.name));
|
|
267
|
-
await Promise.all(subdirs.map((sub) => scan(
|
|
305
|
+
await Promise.all(subdirs.map((sub) => scan(join2(dir, sub.name), depth + 1)));
|
|
268
306
|
}
|
|
269
307
|
}
|
|
270
308
|
await Promise.all(searchDirs.map((dir) => scan(dir, 0).catch(() => {})));
|
|
@@ -297,7 +335,7 @@ var init_package = __esm(() => {
|
|
|
297
335
|
workspaces: [
|
|
298
336
|
"packages/*"
|
|
299
337
|
],
|
|
300
|
-
version: "1.1.
|
|
338
|
+
version: "1.1.101",
|
|
301
339
|
description: "Batteries-included agent harness for Claude Code",
|
|
302
340
|
type: "module",
|
|
303
341
|
bin: {
|
|
@@ -7293,7 +7331,7 @@ var require_public_api = __commonJS(function(exports) {
|
|
|
7293
7331
|
});
|
|
7294
7332
|
|
|
7295
7333
|
// src/utils/fs.ts
|
|
7296
|
-
import { dirname as
|
|
7334
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join4, relative, resolve as resolve2, sep as sep3 } from "node:path";
|
|
7297
7335
|
import { fileURLToPath } from "node:url";
|
|
7298
7336
|
function validatePreserveFilePath(filePath, projectRoot) {
|
|
7299
7337
|
if (!filePath || filePath.trim() === "") {
|
|
@@ -7302,7 +7340,7 @@ function validatePreserveFilePath(filePath, projectRoot) {
|
|
|
7302
7340
|
reason: "Path cannot be empty"
|
|
7303
7341
|
};
|
|
7304
7342
|
}
|
|
7305
|
-
if (
|
|
7343
|
+
if (isAbsolute2(filePath)) {
|
|
7306
7344
|
return {
|
|
7307
7345
|
valid: false,
|
|
7308
7346
|
reason: "Absolute paths are not allowed"
|
|
@@ -7310,7 +7348,7 @@ function validatePreserveFilePath(filePath, projectRoot) {
|
|
|
7310
7348
|
}
|
|
7311
7349
|
const resolvedPath = resolve2(projectRoot, filePath);
|
|
7312
7350
|
const relativePath = relative(projectRoot, resolvedPath);
|
|
7313
|
-
if (relativePath.startsWith("..") ||
|
|
7351
|
+
if (relativePath.startsWith("..") || isAbsolute2(relativePath)) {
|
|
7314
7352
|
return {
|
|
7315
7353
|
valid: false,
|
|
7316
7354
|
reason: "Path cannot traverse outside project root"
|
|
@@ -7452,17 +7490,17 @@ async function readTextFile(path) {
|
|
|
7452
7490
|
}
|
|
7453
7491
|
async function writeTextFile(path, content) {
|
|
7454
7492
|
const fs = await import("node:fs/promises");
|
|
7455
|
-
await ensureDirectory(
|
|
7493
|
+
await ensureDirectory(dirname3(path));
|
|
7456
7494
|
await fs.writeFile(path, content, "utf-8");
|
|
7457
7495
|
}
|
|
7458
7496
|
function getPackageRoot() {
|
|
7459
7497
|
const currentFile = fileURLToPath(import.meta.url);
|
|
7460
|
-
const currentDir =
|
|
7498
|
+
const currentDir = dirname3(currentFile);
|
|
7461
7499
|
return resolve2(currentDir, "..", "..");
|
|
7462
7500
|
}
|
|
7463
7501
|
function resolveTemplatePath(relativePath) {
|
|
7464
7502
|
const packageRoot = getPackageRoot();
|
|
7465
|
-
return
|
|
7503
|
+
return join4(packageRoot, "templates", relativePath);
|
|
7466
7504
|
}
|
|
7467
7505
|
async function listFiles(dir, options = {}) {
|
|
7468
7506
|
const fs = await import("node:fs/promises");
|
|
@@ -7484,7 +7522,7 @@ async function listFiles(dir, options = {}) {
|
|
|
7484
7522
|
}
|
|
7485
7523
|
async function copyFile(src, dest) {
|
|
7486
7524
|
const fs = await import("node:fs/promises");
|
|
7487
|
-
await ensureDirectory(
|
|
7525
|
+
await ensureDirectory(dirname3(dest));
|
|
7488
7526
|
await fs.copyFile(src, dest);
|
|
7489
7527
|
}
|
|
7490
7528
|
async function createTempDir(prefix = "omcustom-") {
|
|
@@ -7505,9 +7543,9 @@ var UTF8_BOM = "\uFEFF";
|
|
|
7505
7543
|
var init_fs = () => {};
|
|
7506
7544
|
|
|
7507
7545
|
// src/cli/projects.ts
|
|
7508
|
-
import { basename as
|
|
7546
|
+
import { basename as basename5, join as join12, resolve as resolve3 } from "node:path";
|
|
7509
7547
|
async function readLockFile(projectDir) {
|
|
7510
|
-
const lockFilePath =
|
|
7548
|
+
const lockFilePath = join12(projectDir, ".omcustom.lock.json");
|
|
7511
7549
|
try {
|
|
7512
7550
|
const fs = await import("node:fs/promises");
|
|
7513
7551
|
const content = await fs.readFile(lockFilePath, "utf-8");
|
|
@@ -7577,7 +7615,7 @@ async function findProjects(options = {}) {
|
|
|
7577
7615
|
if (!isUnderHome(projectPath, home))
|
|
7578
7616
|
continue;
|
|
7579
7617
|
results.push({
|
|
7580
|
-
name:
|
|
7618
|
+
name: basename5(projectPath),
|
|
7581
7619
|
path: projectPath,
|
|
7582
7620
|
version: entry.version || null,
|
|
7583
7621
|
installedAt: entry.installedAt || null,
|
|
@@ -7603,7 +7641,7 @@ async function _scanDirForLockfiles(dir, depth, seen, results, home, currentVers
|
|
|
7603
7641
|
if (isUnderHome(dir, home)) {
|
|
7604
7642
|
const version = lockFile.version || lockFile.templateVersion || null;
|
|
7605
7643
|
results.push({
|
|
7606
|
-
name:
|
|
7644
|
+
name: basename5(dir),
|
|
7607
7645
|
path: dir,
|
|
7608
7646
|
version,
|
|
7609
7647
|
installedAt: lockFile.installedAt || null,
|
|
@@ -7616,7 +7654,7 @@ async function _scanDirForLockfiles(dir, depth, seen, results, home, currentVers
|
|
|
7616
7654
|
}
|
|
7617
7655
|
if (depth < 3) {
|
|
7618
7656
|
const subdirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !SCAN_SKIP_DIRS2.has(e.name));
|
|
7619
|
-
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(() => {})));
|
|
7620
7658
|
}
|
|
7621
7659
|
}
|
|
7622
7660
|
async function _findProjectsFromLockfiles(options, currentVersion) {
|
|
@@ -7640,7 +7678,7 @@ async function _findProjectsFromLockfiles(options, currentVersion) {
|
|
|
7640
7678
|
}
|
|
7641
7679
|
async function writeLockFile(projectDir, version, existing) {
|
|
7642
7680
|
const fs = await import("node:fs/promises");
|
|
7643
|
-
const lockFilePath =
|
|
7681
|
+
const lockFilePath = join12(projectDir, ".omcustom.lock.json");
|
|
7644
7682
|
const now = new Date().toISOString();
|
|
7645
7683
|
const merged = {
|
|
7646
7684
|
...existing || {},
|
|
@@ -7699,7 +7737,7 @@ oh-my-customcode 적용 프로젝트 (${projects.length}개):`);
|
|
|
7699
7737
|
현재 설치 버전: v${currentVersion}`);
|
|
7700
7738
|
}
|
|
7701
7739
|
function buildMigrationSearchDirs(home, extraPaths = []) {
|
|
7702
|
-
return [...home ? DEFAULT_SEARCH_DIRS.map((d) =>
|
|
7740
|
+
return [...home ? DEFAULT_SEARCH_DIRS.map((d) => join12(home, d)) : [], ...extraPaths];
|
|
7703
7741
|
}
|
|
7704
7742
|
async function runMigration(options) {
|
|
7705
7743
|
await Promise.resolve().then(() => init_registry());
|
|
@@ -11935,7 +11973,7 @@ init_package();
|
|
|
11935
11973
|
import { execSync as execSync2, spawnSync } from "node:child_process";
|
|
11936
11974
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
11937
11975
|
import { homedir as homedir2 } from "node:os";
|
|
11938
|
-
import { dirname, join as
|
|
11976
|
+
import { dirname as dirname2, join as join3 } from "node:path";
|
|
11939
11977
|
import { createInterface } from "node:readline/promises";
|
|
11940
11978
|
|
|
11941
11979
|
// node_modules/.bun/i18next@26.0.2+ff0372d108591aba/node_modules/i18next/dist/esm/i18next.js
|
|
@@ -15233,7 +15271,7 @@ var i18n = {
|
|
|
15233
15271
|
// src/core/self-update.ts
|
|
15234
15272
|
var DEFAULT_PACKAGE_NAME = "oh-my-customcode";
|
|
15235
15273
|
var DEFAULT_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
15236
|
-
var DEFAULT_CACHE_PATH =
|
|
15274
|
+
var DEFAULT_CACHE_PATH = join3(homedir2(), ".oh-my-customcode", "self-update-cache.json");
|
|
15237
15275
|
var MS_EPOCH_THRESHOLD = 1000000000000;
|
|
15238
15276
|
function normalizeVersion(version) {
|
|
15239
15277
|
return version.trim().replace(/^v/i, "").split("-")[0] || "";
|
|
@@ -15330,7 +15368,7 @@ function readSelfUpdateCache(cachePath) {
|
|
|
15330
15368
|
return null;
|
|
15331
15369
|
}
|
|
15332
15370
|
function writeCache(cachePath, latestVersion, now) {
|
|
15333
|
-
const dir =
|
|
15371
|
+
const dir = dirname2(cachePath);
|
|
15334
15372
|
if (!existsSync(dir)) {
|
|
15335
15373
|
mkdirSync(dir, { recursive: true });
|
|
15336
15374
|
}
|
|
@@ -16087,7 +16125,7 @@ function installCodex(deps = defaultDeps) {
|
|
|
16087
16125
|
|
|
16088
16126
|
// src/core/config.ts
|
|
16089
16127
|
init_fs();
|
|
16090
|
-
import { join as
|
|
16128
|
+
import { join as join5 } from "node:path";
|
|
16091
16129
|
var CONFIG_FILE = ".omcustomrc.json";
|
|
16092
16130
|
var CURRENT_CONFIG_VERSION = 1;
|
|
16093
16131
|
function getDefaultConfig() {
|
|
@@ -16127,7 +16165,7 @@ function getDefaultPreferences() {
|
|
|
16127
16165
|
};
|
|
16128
16166
|
}
|
|
16129
16167
|
function getConfigPath(targetDir) {
|
|
16130
|
-
return
|
|
16168
|
+
return join5(targetDir, CONFIG_FILE);
|
|
16131
16169
|
}
|
|
16132
16170
|
async function loadConfig(targetDir) {
|
|
16133
16171
|
const configPath = getConfigPath(targetDir);
|
|
@@ -16225,9 +16263,9 @@ function migrateConfig(config) {
|
|
|
16225
16263
|
// src/core/doctor-framework.ts
|
|
16226
16264
|
init_fs();
|
|
16227
16265
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
16228
|
-
import { join as
|
|
16266
|
+
import { join as join6 } from "node:path";
|
|
16229
16267
|
async function getInstalledVersion(targetDir) {
|
|
16230
|
-
const rcPath =
|
|
16268
|
+
const rcPath = join6(targetDir, ".omcustomrc.json");
|
|
16231
16269
|
if (!await fileExists(rcPath))
|
|
16232
16270
|
return null;
|
|
16233
16271
|
try {
|
|
@@ -16299,7 +16337,7 @@ init_fs();
|
|
|
16299
16337
|
import { createHash } from "node:crypto";
|
|
16300
16338
|
import { createReadStream } from "node:fs";
|
|
16301
16339
|
import { readdir, stat } from "node:fs/promises";
|
|
16302
|
-
import { join as
|
|
16340
|
+
import { join as join7, relative as relative2 } from "node:path";
|
|
16303
16341
|
var LOCKFILE_NAME = ".omcustom.lock.json";
|
|
16304
16342
|
var LOCKFILE_VERSION = 1;
|
|
16305
16343
|
var LOCKFILE_COMPONENTS = [
|
|
@@ -16328,7 +16366,7 @@ function computeFileHash(filePath) {
|
|
|
16328
16366
|
});
|
|
16329
16367
|
}
|
|
16330
16368
|
async function readLockfile(targetDir) {
|
|
16331
|
-
const lockfilePath =
|
|
16369
|
+
const lockfilePath = join7(targetDir, LOCKFILE_NAME);
|
|
16332
16370
|
const exists = await fileExists(lockfilePath);
|
|
16333
16371
|
if (!exists) {
|
|
16334
16372
|
debug("lockfile.not_found", { path: lockfilePath });
|
|
@@ -16352,7 +16390,7 @@ async function readLockfile(targetDir) {
|
|
|
16352
16390
|
}
|
|
16353
16391
|
}
|
|
16354
16392
|
async function writeLockfile(targetDir, lockfile) {
|
|
16355
|
-
const lockfilePath =
|
|
16393
|
+
const lockfilePath = join7(targetDir, LOCKFILE_NAME);
|
|
16356
16394
|
await writeJsonFile(lockfilePath, lockfile);
|
|
16357
16395
|
debug("lockfile.written", { path: lockfilePath });
|
|
16358
16396
|
}
|
|
@@ -16377,7 +16415,7 @@ async function collectFiles(dir, projectRoot, isTopLevel) {
|
|
|
16377
16415
|
if (isTopLevel && entry.startsWith(".") && entry !== ".claude") {
|
|
16378
16416
|
continue;
|
|
16379
16417
|
}
|
|
16380
|
-
const fullPath =
|
|
16418
|
+
const fullPath = join7(dir, entry);
|
|
16381
16419
|
let fileStat;
|
|
16382
16420
|
try {
|
|
16383
16421
|
fileStat = await stat(fullPath);
|
|
@@ -16395,7 +16433,7 @@ async function collectFiles(dir, projectRoot, isTopLevel) {
|
|
|
16395
16433
|
}
|
|
16396
16434
|
async function generateLockfile(targetDir, generatorVersion, templateVersion) {
|
|
16397
16435
|
const files = {};
|
|
16398
|
-
const componentRoots = COMPONENT_PATHS.map(([prefix]) =>
|
|
16436
|
+
const componentRoots = COMPONENT_PATHS.map(([prefix]) => join7(targetDir, prefix));
|
|
16399
16437
|
for (const componentRoot of componentRoots) {
|
|
16400
16438
|
const exists = await fileExists(componentRoot);
|
|
16401
16439
|
if (!exists) {
|
|
@@ -16435,8 +16473,8 @@ async function generateLockfile(targetDir, generatorVersion, templateVersion) {
|
|
|
16435
16473
|
async function generateAndWriteLockfileForDir(targetDir) {
|
|
16436
16474
|
try {
|
|
16437
16475
|
const packageRoot = getPackageRoot();
|
|
16438
|
-
const manifest = await readJsonFile(
|
|
16439
|
-
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"));
|
|
16440
16478
|
const lockfile = await generateLockfile(targetDir, generatorVersion, manifest.version);
|
|
16441
16479
|
await writeLockfile(targetDir, lockfile);
|
|
16442
16480
|
return { fileCount: Object.keys(lockfile.files).length };
|
|
@@ -17186,7 +17224,7 @@ async function doctorCommand(options = {}) {
|
|
|
17186
17224
|
|
|
17187
17225
|
// src/cli/init.ts
|
|
17188
17226
|
init_package();
|
|
17189
|
-
import { join as
|
|
17227
|
+
import { join as join14 } from "node:path";
|
|
17190
17228
|
|
|
17191
17229
|
// src/core/installer.ts
|
|
17192
17230
|
init_fs();
|
|
@@ -17197,11 +17235,11 @@ import {
|
|
|
17197
17235
|
rename,
|
|
17198
17236
|
stat as stat2
|
|
17199
17237
|
} from "node:fs/promises";
|
|
17200
|
-
import { basename as
|
|
17238
|
+
import { basename as basename4, dirname as dirname5, join as join9 } from "node:path";
|
|
17201
17239
|
|
|
17202
17240
|
// src/core/file-preservation.ts
|
|
17203
17241
|
init_fs();
|
|
17204
|
-
import { basename as
|
|
17242
|
+
import { basename as basename3, join as join8 } from "node:path";
|
|
17205
17243
|
|
|
17206
17244
|
// src/core/hook-group-merge.ts
|
|
17207
17245
|
var LEGACY_OMCUSTOM_DESCRIPTIONS = [
|
|
@@ -17335,8 +17373,8 @@ function matchesGlobPattern(filePath, pattern) {
|
|
|
17335
17373
|
return regex.test(filePath);
|
|
17336
17374
|
}
|
|
17337
17375
|
async function extractSingleFile(fileName, rootDir, tempDir, result) {
|
|
17338
|
-
const srcPath =
|
|
17339
|
-
const destPath =
|
|
17376
|
+
const srcPath = join8(rootDir, fileName);
|
|
17377
|
+
const destPath = join8(tempDir, fileName);
|
|
17340
17378
|
try {
|
|
17341
17379
|
if (await fileExists(srcPath)) {
|
|
17342
17380
|
await copyFile(srcPath, destPath);
|
|
@@ -17350,8 +17388,8 @@ async function extractSingleFile(fileName, rootDir, tempDir, result) {
|
|
|
17350
17388
|
}
|
|
17351
17389
|
}
|
|
17352
17390
|
async function extractSingleDir(dirName, rootDir, tempDir, result) {
|
|
17353
|
-
const srcPath =
|
|
17354
|
-
const destPath =
|
|
17391
|
+
const srcPath = join8(rootDir, dirName);
|
|
17392
|
+
const destPath = join8(tempDir, dirName);
|
|
17355
17393
|
try {
|
|
17356
17394
|
if (await fileExists(srcPath)) {
|
|
17357
17395
|
await copyDirectory(srcPath, destPath, { overwrite: true, preserveTimestamps: true });
|
|
@@ -17388,8 +17426,8 @@ async function restoreCriticalFiles(rootDir, preservation) {
|
|
|
17388
17426
|
failures: []
|
|
17389
17427
|
};
|
|
17390
17428
|
for (const fileName of preservation.extractedFiles) {
|
|
17391
|
-
const preservedPath =
|
|
17392
|
-
const targetPath =
|
|
17429
|
+
const preservedPath = join8(preservation.tempDir, fileName);
|
|
17430
|
+
const targetPath = join8(rootDir, fileName);
|
|
17393
17431
|
try {
|
|
17394
17432
|
if (fileName.endsWith(".json")) {
|
|
17395
17433
|
await mergeJsonFile(preservedPath, targetPath);
|
|
@@ -17405,8 +17443,8 @@ async function restoreCriticalFiles(rootDir, preservation) {
|
|
|
17405
17443
|
}
|
|
17406
17444
|
}
|
|
17407
17445
|
for (const dirName of preservation.extractedDirs) {
|
|
17408
|
-
const preservedPath =
|
|
17409
|
-
const targetPath =
|
|
17446
|
+
const preservedPath = join8(preservation.tempDir, dirName);
|
|
17447
|
+
const targetPath = join8(rootDir, dirName);
|
|
17410
17448
|
try {
|
|
17411
17449
|
await copyDirectory(preservedPath, targetPath, {
|
|
17412
17450
|
overwrite: false,
|
|
@@ -17431,14 +17469,14 @@ async function mergeJsonFile(preservedPath, targetPath) {
|
|
|
17431
17469
|
if (await fileExists(targetPath)) {
|
|
17432
17470
|
const { data: targetData } = parseJsonText(await readTextFile(targetPath));
|
|
17433
17471
|
const merged = deepMerge(targetData, preservedData);
|
|
17434
|
-
if (HOOKS_MERGE_FILES.has(
|
|
17472
|
+
if (HOOKS_MERGE_FILES.has(basename3(targetPath)) && isGeneratedHookBlock(targetData.hooks)) {
|
|
17435
17473
|
merged.hooks = mergeHookBlocks(preservedData.hooks, targetData.hooks);
|
|
17436
17474
|
}
|
|
17437
17475
|
await writeTextFile(targetPath, stringifyJson(merged, format));
|
|
17438
|
-
debug("preserve.merged_json", { file:
|
|
17476
|
+
debug("preserve.merged_json", { file: basename3(targetPath) });
|
|
17439
17477
|
} else {
|
|
17440
17478
|
await copyFile(preservedPath, targetPath);
|
|
17441
|
-
debug("preserve.copied_json", { file:
|
|
17479
|
+
debug("preserve.copied_json", { file: basename3(targetPath) });
|
|
17442
17480
|
}
|
|
17443
17481
|
}
|
|
17444
17482
|
function deepMerge(target, source) {
|
|
@@ -17776,7 +17814,7 @@ function migrateHookCommands(settings) {
|
|
|
17776
17814
|
|
|
17777
17815
|
// src/core/hooks-settings.ts
|
|
17778
17816
|
init_fs();
|
|
17779
|
-
import { dirname as
|
|
17817
|
+
import { dirname as dirname4 } from "node:path";
|
|
17780
17818
|
var IDENT_CHAR = /[A-Za-z0-9_.]/;
|
|
17781
17819
|
var IDENT_START = /[A-Za-z_]/;
|
|
17782
17820
|
function consumeSingleCharOp(input, i) {
|
|
@@ -18280,7 +18318,7 @@ async function mergeHooksIntoSettings(settingsPath, hooksJsonPath, options = {})
|
|
|
18280
18318
|
}
|
|
18281
18319
|
const settings = existing.ok ? existing.settings : {};
|
|
18282
18320
|
settings.hooks = preserve ? mergeHookBlocks(settings.hooks, hooks) : hooks;
|
|
18283
|
-
await ensureDirectory(
|
|
18321
|
+
await ensureDirectory(dirname4(settingsPath));
|
|
18284
18322
|
await writeTextFile(settingsPath, stringifyJson(settings, { bom: existing.bom, trailingNewline: true }));
|
|
18285
18323
|
return { warnings };
|
|
18286
18324
|
}
|
|
@@ -18317,7 +18355,7 @@ function shouldInstallAgent(agentDomain, filterDomain) {
|
|
|
18317
18355
|
var DEFAULT_LANGUAGE2 = "en";
|
|
18318
18356
|
function getTemplateDir() {
|
|
18319
18357
|
const packageRoot = getPackageRoot();
|
|
18320
|
-
return
|
|
18358
|
+
return join9(packageRoot, "templates");
|
|
18321
18359
|
}
|
|
18322
18360
|
function createInstallResult(targetDir) {
|
|
18323
18361
|
return {
|
|
@@ -18339,7 +18377,7 @@ async function handleBackup(targetDir, shouldBackup, result) {
|
|
|
18339
18377
|
if (!shouldBackup)
|
|
18340
18378
|
return null;
|
|
18341
18379
|
const layout = getProviderLayout();
|
|
18342
|
-
const rootDir =
|
|
18380
|
+
const rootDir = join9(targetDir, layout.rootDir);
|
|
18343
18381
|
let preservation = null;
|
|
18344
18382
|
if (await fileExists(rootDir)) {
|
|
18345
18383
|
await Promise.resolve().then(() => init_fs());
|
|
@@ -18396,8 +18434,8 @@ async function installSingleComponent(targetDir, component, options, result) {
|
|
|
18396
18434
|
}
|
|
18397
18435
|
async function installStatusline(targetDir, options, _result) {
|
|
18398
18436
|
const layout = getProviderLayout();
|
|
18399
|
-
const srcPath = resolveTemplatePath(
|
|
18400
|
-
const destPath =
|
|
18437
|
+
const srcPath = resolveTemplatePath(join9(layout.rootDir, "statusline.sh"));
|
|
18438
|
+
const destPath = join9(targetDir, layout.rootDir, "statusline.sh");
|
|
18401
18439
|
if (!await fileExists(srcPath)) {
|
|
18402
18440
|
debug("install.statusline_not_found", { path: srcPath });
|
|
18403
18441
|
return;
|
|
@@ -18415,9 +18453,9 @@ async function installStatusline(targetDir, options, _result) {
|
|
|
18415
18453
|
}
|
|
18416
18454
|
async function installSchemas(targetDir, options, _result) {
|
|
18417
18455
|
const layout = getProviderLayout();
|
|
18418
|
-
const relPath =
|
|
18456
|
+
const relPath = join9(layout.rootDir, "schemas", "tool-inputs.json");
|
|
18419
18457
|
const srcPath = resolveTemplatePath(relPath);
|
|
18420
|
-
const destPath =
|
|
18458
|
+
const destPath = join9(targetDir, relPath);
|
|
18421
18459
|
if (!await fileExists(srcPath)) {
|
|
18422
18460
|
debug("install.schemas_not_found", { path: srcPath });
|
|
18423
18461
|
return;
|
|
@@ -18428,13 +18466,13 @@ async function installSchemas(targetDir, options, _result) {
|
|
|
18428
18466
|
return;
|
|
18429
18467
|
}
|
|
18430
18468
|
}
|
|
18431
|
-
await ensureDirectory(
|
|
18469
|
+
await ensureDirectory(dirname5(destPath));
|
|
18432
18470
|
await copyFile(srcPath, destPath);
|
|
18433
18471
|
debug("install.schemas_installed", {});
|
|
18434
18472
|
}
|
|
18435
18473
|
async function installTestsConfig(targetDir, options, _result) {
|
|
18436
|
-
const srcPath = resolveTemplatePath(
|
|
18437
|
-
const destPath =
|
|
18474
|
+
const srcPath = resolveTemplatePath(join9("tests", "tsconfig.json"));
|
|
18475
|
+
const destPath = join9(targetDir, "tests", "tsconfig.json");
|
|
18438
18476
|
if (!await fileExists(srcPath)) {
|
|
18439
18477
|
debug("install.tests_config_not_found", { path: srcPath });
|
|
18440
18478
|
return;
|
|
@@ -18484,7 +18522,7 @@ async function mergeStatusLineIntoExisting(settingsPath, existing, format, defau
|
|
|
18484
18522
|
}
|
|
18485
18523
|
async function installSettingsLocal(targetDir, result) {
|
|
18486
18524
|
const layout = getProviderLayout();
|
|
18487
|
-
const settingsPath =
|
|
18525
|
+
const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
|
|
18488
18526
|
const statusLineConfig = {
|
|
18489
18527
|
statusLine: {
|
|
18490
18528
|
type: "command",
|
|
@@ -18507,8 +18545,8 @@ async function installSettingsLocal(targetDir, result) {
|
|
|
18507
18545
|
}
|
|
18508
18546
|
async function installHooksSettings(targetDir, _options, result) {
|
|
18509
18547
|
const layout = getProviderLayout();
|
|
18510
|
-
const hooksJsonPath =
|
|
18511
|
-
const settingsPath =
|
|
18548
|
+
const hooksJsonPath = join9(targetDir, getComponentPath("hooks"), "hooks.json");
|
|
18549
|
+
const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
|
|
18512
18550
|
if (!await fileExists(hooksJsonPath)) {
|
|
18513
18551
|
debug("install.hooks_settings_skipped", { reason: "hooks.json not installed" });
|
|
18514
18552
|
return;
|
|
@@ -18530,7 +18568,7 @@ async function installHooksSettings(targetDir, _options, result) {
|
|
|
18530
18568
|
var BOM = "\uFEFF";
|
|
18531
18569
|
async function migrateRestoredHookCommands(targetDir, result) {
|
|
18532
18570
|
const layout = getProviderLayout();
|
|
18533
|
-
const settingsPath =
|
|
18571
|
+
const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
|
|
18534
18572
|
if (!await fileExists(settingsPath)) {
|
|
18535
18573
|
return;
|
|
18536
18574
|
}
|
|
@@ -18616,7 +18654,7 @@ async function install(options) {
|
|
|
18616
18654
|
await installEntryDocWithTracking(options.targetDir, options, result);
|
|
18617
18655
|
if (preservation) {
|
|
18618
18656
|
const layout = getProviderLayout();
|
|
18619
|
-
const rootDir =
|
|
18657
|
+
const rootDir = join9(options.targetDir, layout.rootDir);
|
|
18620
18658
|
const restoration = await restoreCriticalFiles(rootDir, preservation);
|
|
18621
18659
|
if (restoration.restoredFiles.length > 0 || restoration.restoredDirs.length > 0) {
|
|
18622
18660
|
info("install.restored", {
|
|
@@ -18654,7 +18692,7 @@ async function install(options) {
|
|
|
18654
18692
|
async function getTemplateManifest() {
|
|
18655
18693
|
const packageRoot = getPackageRoot();
|
|
18656
18694
|
const layout = getProviderLayout();
|
|
18657
|
-
const manifestPath =
|
|
18695
|
+
const manifestPath = join9(packageRoot, "templates", layout.manifestFile);
|
|
18658
18696
|
if (await fileExists(manifestPath)) {
|
|
18659
18697
|
return readJsonFile(manifestPath);
|
|
18660
18698
|
}
|
|
@@ -18677,10 +18715,10 @@ async function installSkillsWithScopeFilter(srcPath, destPath, options) {
|
|
|
18677
18715
|
await ensureDirectory(destPath);
|
|
18678
18716
|
const entries = await readdir2(srcPath);
|
|
18679
18717
|
for (const entry of entries) {
|
|
18680
|
-
const entrySrcPath =
|
|
18718
|
+
const entrySrcPath = join9(srcPath, entry);
|
|
18681
18719
|
if (!(await stat2(entrySrcPath)).isDirectory())
|
|
18682
18720
|
continue;
|
|
18683
|
-
const skillMdPath =
|
|
18721
|
+
const skillMdPath = join9(entrySrcPath, "SKILL.md");
|
|
18684
18722
|
if (await fileExists(skillMdPath)) {
|
|
18685
18723
|
const content = await fsReadFile(skillMdPath, "utf-8");
|
|
18686
18724
|
const scope = getSkillScope(content);
|
|
@@ -18689,7 +18727,7 @@ async function installSkillsWithScopeFilter(srcPath, destPath, options) {
|
|
|
18689
18727
|
continue;
|
|
18690
18728
|
}
|
|
18691
18729
|
}
|
|
18692
|
-
await copyDirectory(entrySrcPath,
|
|
18730
|
+
await copyDirectory(entrySrcPath, join9(destPath, entry), {
|
|
18693
18731
|
overwrite: !!(options.force || options.backup),
|
|
18694
18732
|
preserveSymlinks: true,
|
|
18695
18733
|
preserveTimestamps: true
|
|
@@ -18700,10 +18738,10 @@ async function installAgentsWithDomainFilter(srcPath, destPath, options) {
|
|
|
18700
18738
|
await ensureDirectory(destPath);
|
|
18701
18739
|
const entries = await readdir2(srcPath);
|
|
18702
18740
|
for (const entry of entries) {
|
|
18703
|
-
const entrySrcPath =
|
|
18741
|
+
const entrySrcPath = join9(srcPath, entry);
|
|
18704
18742
|
const entryStat = await stat2(entrySrcPath);
|
|
18705
18743
|
if (entryStat.isDirectory()) {
|
|
18706
|
-
await copyDirectory(entrySrcPath,
|
|
18744
|
+
await copyDirectory(entrySrcPath, join9(destPath, entry), {
|
|
18707
18745
|
overwrite: !!(options.force || options.backup),
|
|
18708
18746
|
preserveSymlinks: true,
|
|
18709
18747
|
preserveTimestamps: true
|
|
@@ -18720,7 +18758,7 @@ async function installAgentsWithDomainFilter(srcPath, destPath, options) {
|
|
|
18720
18758
|
continue;
|
|
18721
18759
|
}
|
|
18722
18760
|
}
|
|
18723
|
-
await copyFile(entrySrcPath,
|
|
18761
|
+
await copyFile(entrySrcPath, join9(destPath, entry));
|
|
18724
18762
|
}
|
|
18725
18763
|
}
|
|
18726
18764
|
async function installComponent(targetDir, component, options) {
|
|
@@ -18728,7 +18766,7 @@ async function installComponent(targetDir, component, options) {
|
|
|
18728
18766
|
return false;
|
|
18729
18767
|
}
|
|
18730
18768
|
const templatePath = getComponentPath(component);
|
|
18731
|
-
const destPath =
|
|
18769
|
+
const destPath = join9(targetDir, templatePath);
|
|
18732
18770
|
const destExists = await fileExists(destPath);
|
|
18733
18771
|
if (destExists && !options.force && !options.backup) {
|
|
18734
18772
|
debug("install.component_skipped", { component });
|
|
@@ -18762,7 +18800,7 @@ async function installEntryDoc(targetDir, language, overwrite = false) {
|
|
|
18762
18800
|
const layout = getProviderLayout();
|
|
18763
18801
|
const templateFile = getEntryTemplateName(language);
|
|
18764
18802
|
const srcPath = resolveTemplatePath(templateFile);
|
|
18765
|
-
const destPath =
|
|
18803
|
+
const destPath = join9(targetDir, layout.entryFile);
|
|
18766
18804
|
if (!await fileExists(srcPath)) {
|
|
18767
18805
|
warn("install.entry_md_not_found", { language, path: srcPath, entry: layout.entryFile });
|
|
18768
18806
|
return false;
|
|
@@ -18782,8 +18820,8 @@ async function installEntryDoc(targetDir, language, overwrite = false) {
|
|
|
18782
18820
|
return true;
|
|
18783
18821
|
}
|
|
18784
18822
|
async function backupExisting(sourcePath, backupDir) {
|
|
18785
|
-
const name =
|
|
18786
|
-
const backupPath =
|
|
18823
|
+
const name = basename4(sourcePath);
|
|
18824
|
+
const backupPath = join9(backupDir, name);
|
|
18787
18825
|
await rename(sourcePath, backupPath);
|
|
18788
18826
|
return backupPath;
|
|
18789
18827
|
}
|
|
@@ -18792,7 +18830,7 @@ async function checkExistingPaths(targetDir) {
|
|
|
18792
18830
|
const pathsToCheck = [layout.entryFile, layout.rootDir, "guides"];
|
|
18793
18831
|
const existingPaths = [];
|
|
18794
18832
|
for (const relativePath of pathsToCheck) {
|
|
18795
|
-
const fullPath =
|
|
18833
|
+
const fullPath = join9(targetDir, relativePath);
|
|
18796
18834
|
if (await fileExists(fullPath)) {
|
|
18797
18835
|
existingPaths.push(relativePath);
|
|
18798
18836
|
}
|
|
@@ -18806,11 +18844,11 @@ async function backupExistingInstallation(targetDir) {
|
|
|
18806
18844
|
return [];
|
|
18807
18845
|
}
|
|
18808
18846
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
18809
|
-
const backupDir =
|
|
18847
|
+
const backupDir = join9(targetDir, `${layout.backupDirPrefix}${timestamp}`);
|
|
18810
18848
|
await ensureDirectory(backupDir);
|
|
18811
18849
|
const backedUpPaths = [];
|
|
18812
18850
|
for (const relativePath of existingPaths) {
|
|
18813
|
-
const fullPath =
|
|
18851
|
+
const fullPath = join9(targetDir, relativePath);
|
|
18814
18852
|
try {
|
|
18815
18853
|
const backupPath = await backupExisting(fullPath, backupDir);
|
|
18816
18854
|
backedUpPaths.push(backupPath);
|
|
@@ -18826,12 +18864,12 @@ async function backupExistingInstallation(targetDir) {
|
|
|
18826
18864
|
// src/core/mcp-config.ts
|
|
18827
18865
|
init_fs();
|
|
18828
18866
|
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
18829
|
-
import { join as
|
|
18867
|
+
import { join as join10 } from "node:path";
|
|
18830
18868
|
async function generateMCPConfig(targetDir) {
|
|
18831
18869
|
const layout = getProviderLayout();
|
|
18832
|
-
const mcpConfigPath =
|
|
18833
|
-
const ontologyDir =
|
|
18834
|
-
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));
|
|
18835
18873
|
if (!ontologyExists) {
|
|
18836
18874
|
return;
|
|
18837
18875
|
}
|
|
@@ -18873,7 +18911,7 @@ async function generateMCPConfig(targetDir) {
|
|
|
18873
18911
|
// src/core/ontology-rag-setup.ts
|
|
18874
18912
|
init_fs();
|
|
18875
18913
|
import { execSync as execSync5 } from "node:child_process";
|
|
18876
|
-
import { join as
|
|
18914
|
+
import { join as join11 } from "node:path";
|
|
18877
18915
|
var MIN_PYTHON_MINOR = 10;
|
|
18878
18916
|
var DETECTION_TIMEOUT_MS = 3000;
|
|
18879
18917
|
var INSTALL_TIMEOUT_MS = 90000;
|
|
@@ -18924,7 +18962,7 @@ function createVenvWithPython3(targetDir) {
|
|
|
18924
18962
|
}
|
|
18925
18963
|
function installOntologyRagEditable(targetDir, useUv) {
|
|
18926
18964
|
const packageRoot = getPackageRoot();
|
|
18927
|
-
const ontologyPkgPath =
|
|
18965
|
+
const ontologyPkgPath = join11(packageRoot, "packages", "ontology-rag");
|
|
18928
18966
|
if (useUv) {
|
|
18929
18967
|
execSync5(`uv pip install --python .venv/bin/python -e "${ontologyPkgPath}"`, {
|
|
18930
18968
|
cwd: targetDir,
|
|
@@ -18997,7 +19035,7 @@ async function setupOntologyRag(targetDir) {
|
|
|
18997
19035
|
reason
|
|
18998
19036
|
};
|
|
18999
19037
|
}
|
|
19000
|
-
const venvPython =
|
|
19038
|
+
const venvPython = join11(targetDir, ".venv", "bin", "python");
|
|
19001
19039
|
const venvReady = await fileExists(venvPython);
|
|
19002
19040
|
if (!venvReady) {
|
|
19003
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.";
|
|
@@ -19023,12 +19061,12 @@ init_package();
|
|
|
19023
19061
|
init_projects();
|
|
19024
19062
|
import { existsSync as existsSync2 } from "node:fs";
|
|
19025
19063
|
import { copyFile as copyFile2, cp } from "node:fs/promises";
|
|
19026
|
-
import { join as
|
|
19064
|
+
import { join as join13 } from "node:path";
|
|
19027
19065
|
init_fs();
|
|
19028
19066
|
init_registry();
|
|
19029
19067
|
async function checkExistingInstallation(targetDir) {
|
|
19030
19068
|
const layout = getProviderLayout();
|
|
19031
|
-
const rootDir =
|
|
19069
|
+
const rootDir = join13(targetDir, layout.rootDir);
|
|
19032
19070
|
return fileExists(rootDir);
|
|
19033
19071
|
}
|
|
19034
19072
|
async function installFromSnapshot(targetDir, snapshotPath, options) {
|
|
@@ -19040,7 +19078,7 @@ async function installFromSnapshot(targetDir, snapshotPath, options) {
|
|
|
19040
19078
|
};
|
|
19041
19079
|
}
|
|
19042
19080
|
const layout = getProviderLayout();
|
|
19043
|
-
const snapshotClaude =
|
|
19081
|
+
const snapshotClaude = join13(snapshotPath, layout.rootDir);
|
|
19044
19082
|
if (!existsSync2(snapshotClaude)) {
|
|
19045
19083
|
return {
|
|
19046
19084
|
success: false,
|
|
@@ -19054,24 +19092,24 @@ async function installFromSnapshot(targetDir, snapshotPath, options) {
|
|
|
19054
19092
|
if (exists && !options.force) {
|
|
19055
19093
|
console.log(i18n.t("cli.init.exists", { rootDir: layout.rootDir }));
|
|
19056
19094
|
console.log(i18n.t("cli.init.backing_up"));
|
|
19057
|
-
const backupDir =
|
|
19058
|
-
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 });
|
|
19059
19097
|
console.log(` Backed up to: ${backupDir}`);
|
|
19060
19098
|
}
|
|
19061
|
-
await cp(snapshotClaude,
|
|
19099
|
+
await cp(snapshotClaude, join13(targetDir, layout.rootDir), {
|
|
19062
19100
|
recursive: true,
|
|
19063
19101
|
force: true
|
|
19064
19102
|
});
|
|
19065
|
-
const snapshotGuides =
|
|
19103
|
+
const snapshotGuides = join13(snapshotPath, "guides");
|
|
19066
19104
|
if (existsSync2(snapshotGuides)) {
|
|
19067
|
-
await cp(snapshotGuides,
|
|
19105
|
+
await cp(snapshotGuides, join13(targetDir, "guides"), {
|
|
19068
19106
|
recursive: true,
|
|
19069
19107
|
force: true
|
|
19070
19108
|
});
|
|
19071
19109
|
}
|
|
19072
|
-
const snapshotEntry =
|
|
19110
|
+
const snapshotEntry = join13(snapshotPath, layout.entryFile);
|
|
19073
19111
|
if (existsSync2(snapshotEntry)) {
|
|
19074
|
-
await copyFile2(snapshotEntry,
|
|
19112
|
+
await copyFile2(snapshotEntry, join13(targetDir, layout.entryFile));
|
|
19075
19113
|
}
|
|
19076
19114
|
try {
|
|
19077
19115
|
const existing = await readLockFile(targetDir);
|
|
@@ -19954,7 +19992,7 @@ async function runInitWizard(options) {
|
|
|
19954
19992
|
// src/cli/init.ts
|
|
19955
19993
|
async function checkExistingInstallation2(targetDir) {
|
|
19956
19994
|
const layout = getProviderLayout();
|
|
19957
|
-
const rootDir =
|
|
19995
|
+
const rootDir = join14(targetDir, layout.rootDir);
|
|
19958
19996
|
return fileExists(rootDir);
|
|
19959
19997
|
}
|
|
19960
19998
|
var PROVIDER_SUBDIR_COMPONENTS = new Set([
|
|
@@ -19968,13 +20006,13 @@ var PROVIDER_SUBDIR_COMPONENTS = new Set([
|
|
|
19968
20006
|
function componentToPath(targetDir, component) {
|
|
19969
20007
|
if (component === "entry-md") {
|
|
19970
20008
|
const layout = getProviderLayout();
|
|
19971
|
-
return
|
|
20009
|
+
return join14(targetDir, layout.entryFile);
|
|
19972
20010
|
}
|
|
19973
20011
|
if (PROVIDER_SUBDIR_COMPONENTS.has(component)) {
|
|
19974
20012
|
const layout = getProviderLayout();
|
|
19975
|
-
return
|
|
20013
|
+
return join14(targetDir, layout.rootDir, component);
|
|
19976
20014
|
}
|
|
19977
|
-
return
|
|
20015
|
+
return join14(targetDir, component);
|
|
19978
20016
|
}
|
|
19979
20017
|
function buildInstalledPaths(targetDir, components) {
|
|
19980
20018
|
return components.map((component) => componentToPath(targetDir, component));
|
|
@@ -20097,7 +20135,7 @@ async function initCommand(options) {
|
|
|
20097
20135
|
}
|
|
20098
20136
|
|
|
20099
20137
|
// src/cli/list.ts
|
|
20100
|
-
import { basename as
|
|
20138
|
+
import { basename as basename6, dirname as dirname6, join as join15, relative as relative3 } from "node:path";
|
|
20101
20139
|
init_fs();
|
|
20102
20140
|
var ALLOWED_TOP_LEVEL_KEYS = new Set(["name", "type", "description", "version", "category"]);
|
|
20103
20141
|
function parseKeyValue(line) {
|
|
@@ -20144,7 +20182,7 @@ function parseYamlMetadata(content) {
|
|
|
20144
20182
|
return result;
|
|
20145
20183
|
}
|
|
20146
20184
|
function extractAgentTypeFromFilename(filename) {
|
|
20147
|
-
const name =
|
|
20185
|
+
const name = basename6(filename, ".md");
|
|
20148
20186
|
const prefixMap = {
|
|
20149
20187
|
lang: "language",
|
|
20150
20188
|
be: "backend",
|
|
@@ -20162,17 +20200,17 @@ function extractAgentTypeFromFilename(filename) {
|
|
|
20162
20200
|
return prefixMap[prefix] || "unknown";
|
|
20163
20201
|
}
|
|
20164
20202
|
function extractSkillCategoryFromPath(skillPath, baseDir, rootDir) {
|
|
20165
|
-
const relativePath = relative3(
|
|
20203
|
+
const relativePath = relative3(join15(baseDir, rootDir, "skills"), skillPath);
|
|
20166
20204
|
const parts = relativePath.split("/").filter(Boolean);
|
|
20167
20205
|
return parts[0] || "unknown";
|
|
20168
20206
|
}
|
|
20169
20207
|
function extractGuideCategoryFromPath(guidePath, baseDir) {
|
|
20170
|
-
const relativePath = relative3(
|
|
20208
|
+
const relativePath = relative3(join15(baseDir, "guides"), guidePath);
|
|
20171
20209
|
const parts = relativePath.split("/").filter(Boolean);
|
|
20172
20210
|
return parts[0] || "unknown";
|
|
20173
20211
|
}
|
|
20174
20212
|
function extractRulePriorityFromFilename(filename) {
|
|
20175
|
-
const name =
|
|
20213
|
+
const name = basename6(filename, ".md");
|
|
20176
20214
|
const parts = name.split("-");
|
|
20177
20215
|
return parts[0] || "unknown";
|
|
20178
20216
|
}
|
|
@@ -20261,7 +20299,7 @@ async function tryExtractMarkdownDescription(mdPath, options = {}) {
|
|
|
20261
20299
|
}
|
|
20262
20300
|
}
|
|
20263
20301
|
async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
20264
|
-
const agentsDir =
|
|
20302
|
+
const agentsDir = join15(targetDir, rootDir, "agents");
|
|
20265
20303
|
if (!await fileExists(agentsDir))
|
|
20266
20304
|
return [];
|
|
20267
20305
|
try {
|
|
@@ -20270,8 +20308,8 @@ async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
|
20270
20308
|
const customAgentPaths = new Set(customComponents.filter((c) => c.type === "agent").map((c) => c.path));
|
|
20271
20309
|
const agentMdFiles = await listFiles(agentsDir, { recursive: false, pattern: "*.md" });
|
|
20272
20310
|
const agents = await Promise.all(agentMdFiles.map(async (agentMdPath) => {
|
|
20273
|
-
const filename =
|
|
20274
|
-
const name =
|
|
20311
|
+
const filename = basename6(agentMdPath);
|
|
20312
|
+
const name = basename6(filename, ".md");
|
|
20275
20313
|
const description = await tryExtractMarkdownDescription(agentMdPath);
|
|
20276
20314
|
const relativePath = relative3(targetDir, agentMdPath);
|
|
20277
20315
|
return {
|
|
@@ -20289,7 +20327,7 @@ async function getAgents(targetDir, rootDir = ".claude", config) {
|
|
|
20289
20327
|
}
|
|
20290
20328
|
}
|
|
20291
20329
|
async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
20292
|
-
const skillsDir =
|
|
20330
|
+
const skillsDir = join15(targetDir, rootDir, "skills");
|
|
20293
20331
|
if (!await fileExists(skillsDir))
|
|
20294
20332
|
return [];
|
|
20295
20333
|
try {
|
|
@@ -20298,12 +20336,12 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
20298
20336
|
const customSkillPaths = new Set(customComponents.filter((c) => c.type === "skill").map((c) => c.path));
|
|
20299
20337
|
const skillMdFiles = await listFiles(skillsDir, { recursive: true, pattern: "SKILL.md" });
|
|
20300
20338
|
const skills = await Promise.all(skillMdFiles.map(async (skillMdPath) => {
|
|
20301
|
-
const skillDir =
|
|
20302
|
-
const indexYamlPath =
|
|
20339
|
+
const skillDir = dirname6(skillMdPath);
|
|
20340
|
+
const indexYamlPath = join15(skillDir, "index.yaml");
|
|
20303
20341
|
const { description, version } = await tryReadIndexYamlMetadata(indexYamlPath);
|
|
20304
20342
|
const relativePath = relative3(targetDir, skillDir);
|
|
20305
20343
|
return {
|
|
20306
|
-
name:
|
|
20344
|
+
name: basename6(skillDir),
|
|
20307
20345
|
type: "skill",
|
|
20308
20346
|
category: extractSkillCategoryFromPath(skillDir, targetDir, rootDir),
|
|
20309
20347
|
path: relativePath,
|
|
@@ -20318,7 +20356,7 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
|
|
|
20318
20356
|
}
|
|
20319
20357
|
}
|
|
20320
20358
|
async function getGuides(targetDir, config) {
|
|
20321
|
-
const guidesDir =
|
|
20359
|
+
const guidesDir = join15(targetDir, "guides");
|
|
20322
20360
|
if (!await fileExists(guidesDir))
|
|
20323
20361
|
return [];
|
|
20324
20362
|
try {
|
|
@@ -20330,7 +20368,7 @@ async function getGuides(targetDir, config) {
|
|
|
20330
20368
|
const description = await tryExtractMarkdownDescription(guideMdPath, { maxLength: 100 });
|
|
20331
20369
|
const relativePath = relative3(targetDir, guideMdPath);
|
|
20332
20370
|
return {
|
|
20333
|
-
name:
|
|
20371
|
+
name: basename6(guideMdPath, ".md"),
|
|
20334
20372
|
type: "guide",
|
|
20335
20373
|
category: extractGuideCategoryFromPath(guideMdPath, targetDir),
|
|
20336
20374
|
path: relativePath,
|
|
@@ -20345,7 +20383,7 @@ async function getGuides(targetDir, config) {
|
|
|
20345
20383
|
}
|
|
20346
20384
|
var RULE_PRIORITY_ORDER = { MUST: 0, SHOULD: 1, MAY: 2 };
|
|
20347
20385
|
async function getRules(targetDir, rootDir = ".claude", config) {
|
|
20348
|
-
const rulesDir =
|
|
20386
|
+
const rulesDir = join15(targetDir, rootDir, "rules");
|
|
20349
20387
|
if (!await fileExists(rulesDir))
|
|
20350
20388
|
return [];
|
|
20351
20389
|
try {
|
|
@@ -20354,13 +20392,13 @@ async function getRules(targetDir, rootDir = ".claude", config) {
|
|
|
20354
20392
|
const customRulePaths = new Set(customComponents.filter((c) => c.type === "rule").map((c) => c.path));
|
|
20355
20393
|
const ruleMdFiles = await listFiles(rulesDir, { recursive: false, pattern: "*.md" });
|
|
20356
20394
|
const rules = await Promise.all(ruleMdFiles.map(async (ruleMdPath) => {
|
|
20357
|
-
const filename =
|
|
20395
|
+
const filename = basename6(ruleMdPath);
|
|
20358
20396
|
const description = await tryExtractMarkdownDescription(ruleMdPath, {
|
|
20359
20397
|
cleanFormatting: true
|
|
20360
20398
|
});
|
|
20361
20399
|
const relativePath = relative3(targetDir, ruleMdPath);
|
|
20362
20400
|
return {
|
|
20363
|
-
name:
|
|
20401
|
+
name: basename6(ruleMdPath, ".md"),
|
|
20364
20402
|
type: extractRulePriorityFromFilename(filename),
|
|
20365
20403
|
path: relativePath,
|
|
20366
20404
|
description,
|
|
@@ -20417,7 +20455,7 @@ function formatAsJson(components) {
|
|
|
20417
20455
|
console.log(JSON.stringify(components, null, 2));
|
|
20418
20456
|
}
|
|
20419
20457
|
async function getHooks(targetDir, rootDir = ".claude") {
|
|
20420
|
-
const hooksDir =
|
|
20458
|
+
const hooksDir = join15(targetDir, rootDir, "hooks");
|
|
20421
20459
|
if (!await fileExists(hooksDir))
|
|
20422
20460
|
return [];
|
|
20423
20461
|
try {
|
|
@@ -20426,7 +20464,7 @@ async function getHooks(targetDir, rootDir = ".claude") {
|
|
|
20426
20464
|
const hookYamls = await listFiles(hooksDir, { recursive: true, pattern: "*.yaml" });
|
|
20427
20465
|
const allFiles = [...hookFiles, ...hookConfigs, ...hookYamls];
|
|
20428
20466
|
return allFiles.map((hookPath) => ({
|
|
20429
|
-
name:
|
|
20467
|
+
name: basename6(hookPath),
|
|
20430
20468
|
type: "hook",
|
|
20431
20469
|
path: relative3(targetDir, hookPath)
|
|
20432
20470
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -20435,7 +20473,7 @@ async function getHooks(targetDir, rootDir = ".claude") {
|
|
|
20435
20473
|
}
|
|
20436
20474
|
}
|
|
20437
20475
|
async function getContexts(targetDir, rootDir = ".claude") {
|
|
20438
|
-
const contextsDir =
|
|
20476
|
+
const contextsDir = join15(targetDir, rootDir, "contexts");
|
|
20439
20477
|
if (!await fileExists(contextsDir))
|
|
20440
20478
|
return [];
|
|
20441
20479
|
try {
|
|
@@ -20446,7 +20484,7 @@ async function getContexts(targetDir, rootDir = ".claude") {
|
|
|
20446
20484
|
const ext = ctxPath.endsWith(".md") ? ".md" : ".yaml";
|
|
20447
20485
|
const description = ext === ".md" ? await tryExtractMarkdownDescription(ctxPath, { maxLength: 100 }) : undefined;
|
|
20448
20486
|
return {
|
|
20449
|
-
name:
|
|
20487
|
+
name: basename6(ctxPath, ext),
|
|
20450
20488
|
type: "context",
|
|
20451
20489
|
path: relative3(targetDir, ctxPath),
|
|
20452
20490
|
description
|
|
@@ -20828,22 +20866,22 @@ async function securityCommand(_options = {}) {
|
|
|
20828
20866
|
|
|
20829
20867
|
// src/cli/serve-commands.ts
|
|
20830
20868
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
20831
|
-
import { join as
|
|
20869
|
+
import { join as join17 } from "node:path";
|
|
20832
20870
|
|
|
20833
20871
|
// src/cli/serve.ts
|
|
20834
20872
|
import { spawn } from "node:child_process";
|
|
20835
20873
|
import { existsSync as existsSync3 } from "node:fs";
|
|
20836
20874
|
import { readFile as readFile3, unlink, writeFile as writeFile3 } from "node:fs/promises";
|
|
20837
|
-
import { join as
|
|
20875
|
+
import { join as join16 } from "node:path";
|
|
20838
20876
|
var DEFAULT_PORT = 4321;
|
|
20839
|
-
var PID_FILE =
|
|
20877
|
+
var PID_FILE = join16(process.env.HOME ?? "~", ".omcustom-serve.pid");
|
|
20840
20878
|
function findServeBuildDir(projectRoot, options) {
|
|
20841
|
-
const localBuild =
|
|
20842
|
-
if (existsSync3(
|
|
20879
|
+
const localBuild = join16(projectRoot, "packages", "serve", "build");
|
|
20880
|
+
if (existsSync3(join16(localBuild, "index.js")))
|
|
20843
20881
|
return localBuild;
|
|
20844
20882
|
if (options?.skipNpmFallback !== true) {
|
|
20845
|
-
const npmBuild =
|
|
20846
|
-
if (existsSync3(
|
|
20883
|
+
const npmBuild = join16(import.meta.dirname, "..", "..", "packages", "serve", "build");
|
|
20884
|
+
if (existsSync3(join16(npmBuild, "index.js")))
|
|
20847
20885
|
return npmBuild;
|
|
20848
20886
|
}
|
|
20849
20887
|
return null;
|
|
@@ -20871,7 +20909,7 @@ async function startServeBackground(projectRoot, port = DEFAULT_PORT, buildDirOp
|
|
|
20871
20909
|
if (buildDir === null) {
|
|
20872
20910
|
return;
|
|
20873
20911
|
}
|
|
20874
|
-
const child = spawn("node", [
|
|
20912
|
+
const child = spawn("node", [join16(buildDir, "index.js")], {
|
|
20875
20913
|
env: {
|
|
20876
20914
|
...process.env,
|
|
20877
20915
|
OMCUSTOM_PORT: String(port),
|
|
@@ -20948,7 +20986,7 @@ function runForeground(projectRoot, port, buildDirOpts) {
|
|
|
20948
20986
|
process.exit(1);
|
|
20949
20987
|
}
|
|
20950
20988
|
console.log(`Web UI: http://localhost:${port}`);
|
|
20951
|
-
spawnSync2("node", [
|
|
20989
|
+
spawnSync2("node", [join17(buildDir, "index.js")], {
|
|
20952
20990
|
env: {
|
|
20953
20991
|
...process.env,
|
|
20954
20992
|
OMCUSTOM_PORT: String(port),
|
|
@@ -20967,12 +21005,12 @@ import { resolve as resolve4 } from "node:path";
|
|
|
20967
21005
|
init_fs();
|
|
20968
21006
|
import { existsSync as existsSync4 } from "node:fs";
|
|
20969
21007
|
import { cp as cp2, mkdir as mkdir2 } from "node:fs/promises";
|
|
20970
|
-
import { join as
|
|
21008
|
+
import { join as join18 } from "node:path";
|
|
20971
21009
|
async function loadVersions() {
|
|
20972
21010
|
try {
|
|
20973
21011
|
const packageRoot = getPackageRoot();
|
|
20974
|
-
const manifest = await readJsonFile(
|
|
20975
|
-
const pkg = await readJsonFile(
|
|
21012
|
+
const manifest = await readJsonFile(join18(packageRoot, "templates", "manifest.json"));
|
|
21013
|
+
const pkg = await readJsonFile(join18(packageRoot, "package.json"));
|
|
20976
21014
|
return { generatorVersion: pkg.version, templateVersion: manifest.version };
|
|
20977
21015
|
} catch {
|
|
20978
21016
|
return { generatorVersion: "0.0.0", templateVersion: "0.0.0" };
|
|
@@ -21042,7 +21080,7 @@ async function countFiles(dir) {
|
|
|
21042
21080
|
return 0;
|
|
21043
21081
|
}
|
|
21044
21082
|
for (const entry of entries) {
|
|
21045
|
-
const full =
|
|
21083
|
+
const full = join18(current, entry);
|
|
21046
21084
|
try {
|
|
21047
21085
|
const s = await stat(full);
|
|
21048
21086
|
if (s.isDirectory()) {
|
|
@@ -21057,19 +21095,19 @@ async function countFiles(dir) {
|
|
|
21057
21095
|
return walk(dir);
|
|
21058
21096
|
}
|
|
21059
21097
|
async function exportSnapshot(targetDir, outputPath) {
|
|
21060
|
-
const claudeDir =
|
|
21061
|
-
const guidesDir =
|
|
21098
|
+
const claudeDir = join18(targetDir, ".claude");
|
|
21099
|
+
const guidesDir = join18(targetDir, "guides");
|
|
21062
21100
|
if (!existsSync4(claudeDir)) {
|
|
21063
21101
|
return { success: false, exportPath: outputPath, fileCount: 0 };
|
|
21064
21102
|
}
|
|
21065
21103
|
await mkdir2(outputPath, { recursive: true });
|
|
21066
|
-
const destClaude =
|
|
21104
|
+
const destClaude = join18(outputPath, ".claude");
|
|
21067
21105
|
await cp2(claudeDir, destClaude, {
|
|
21068
21106
|
recursive: true,
|
|
21069
21107
|
filter: isExportable
|
|
21070
21108
|
});
|
|
21071
21109
|
if (existsSync4(guidesDir)) {
|
|
21072
|
-
await cp2(guidesDir,
|
|
21110
|
+
await cp2(guidesDir, join18(outputPath, "guides"), { recursive: true });
|
|
21073
21111
|
}
|
|
21074
21112
|
const lockfile = await generateCurrentLockfile(targetDir);
|
|
21075
21113
|
if (lockfile) {
|
|
@@ -21153,7 +21191,7 @@ import { constants as osConstants } from "node:os";
|
|
|
21153
21191
|
|
|
21154
21192
|
// src/core/updater.ts
|
|
21155
21193
|
init_package();
|
|
21156
|
-
import { join as
|
|
21194
|
+
import { join as join19 } from "node:path";
|
|
21157
21195
|
init_fs();
|
|
21158
21196
|
|
|
21159
21197
|
// src/core/entry-merger.ts
|
|
@@ -21408,7 +21446,7 @@ function resolveCustomizations(customizations, configPreserveFiles, targetDir) {
|
|
|
21408
21446
|
}
|
|
21409
21447
|
async function updateEntryDoc(targetDir, config, options) {
|
|
21410
21448
|
const layout = getProviderLayout();
|
|
21411
|
-
const entryPath =
|
|
21449
|
+
const entryPath = join19(targetDir, layout.entryFile);
|
|
21412
21450
|
const templateName = getEntryTemplateName2(config.language);
|
|
21413
21451
|
const templatePath = resolveTemplatePath(templateName);
|
|
21414
21452
|
if (!await fileExists(templatePath)) {
|
|
@@ -21446,7 +21484,7 @@ async function backfillStatusLineRefreshInterval(targetDir, options) {
|
|
|
21446
21484
|
return;
|
|
21447
21485
|
}
|
|
21448
21486
|
const layout = getProviderLayout();
|
|
21449
|
-
const settingsPath =
|
|
21487
|
+
const settingsPath = join19(targetDir, layout.rootDir, "settings.local.json");
|
|
21450
21488
|
if (!await fileExists(settingsPath)) {
|
|
21451
21489
|
return;
|
|
21452
21490
|
}
|
|
@@ -21472,7 +21510,7 @@ async function migrateHookCommandsInSettingsLocal(targetDir, options) {
|
|
|
21472
21510
|
return;
|
|
21473
21511
|
}
|
|
21474
21512
|
const layout = getProviderLayout();
|
|
21475
|
-
const settingsPath =
|
|
21513
|
+
const settingsPath = join19(targetDir, layout.rootDir, "settings.local.json");
|
|
21476
21514
|
if (!await fileExists(settingsPath)) {
|
|
21477
21515
|
return;
|
|
21478
21516
|
}
|
|
@@ -21567,7 +21605,7 @@ async function regenerateLockfile(targetDir, result) {
|
|
|
21567
21605
|
}
|
|
21568
21606
|
}
|
|
21569
21607
|
async function shouldSkipSelfUpdate2(targetDir, result) {
|
|
21570
|
-
const targetPkgPath =
|
|
21608
|
+
const targetPkgPath = join19(targetDir, "package.json");
|
|
21571
21609
|
if (await fileExists(targetPkgPath)) {
|
|
21572
21610
|
const targetPkg = await readJsonFile(targetPkgPath);
|
|
21573
21611
|
if (targetPkg.name === "oh-my-customcode") {
|
|
@@ -21706,11 +21744,11 @@ async function collectProtectedSkipPaths(srcPath, destPath, componentPath, force
|
|
|
21706
21744
|
const warnedPaths = [];
|
|
21707
21745
|
const updatedPaths = [];
|
|
21708
21746
|
for (const p of protectedRelative) {
|
|
21709
|
-
const targetFilePath =
|
|
21747
|
+
const targetFilePath = join19(targetDir, componentPath, p);
|
|
21710
21748
|
const lockfileKey = `${componentPath}/${p}`.replace(/\\/g, "/");
|
|
21711
21749
|
const shouldSkip = await shouldSkipProtectedFile(targetFilePath, lockfileKey, lockfile);
|
|
21712
21750
|
if (shouldSkip) {
|
|
21713
|
-
skipPaths.push(path.relative(destPath,
|
|
21751
|
+
skipPaths.push(path.relative(destPath, join19(destPath, p)));
|
|
21714
21752
|
warnedPaths.push(p);
|
|
21715
21753
|
} else {
|
|
21716
21754
|
updatedPaths.push(p);
|
|
@@ -21756,7 +21794,7 @@ async function updateComponent(targetDir, component, customizations, options, co
|
|
|
21756
21794
|
const preservedFiles = [];
|
|
21757
21795
|
const componentPath = getComponentPath2(component);
|
|
21758
21796
|
const srcPath = resolveTemplatePath(componentPath);
|
|
21759
|
-
const destPath =
|
|
21797
|
+
const destPath = join19(targetDir, componentPath);
|
|
21760
21798
|
const customComponents = config.customComponents || [];
|
|
21761
21799
|
const skipPaths = [];
|
|
21762
21800
|
if (customizations && !options.forceOverwriteAll) {
|
|
@@ -21798,7 +21836,7 @@ async function updateComponent(targetDir, component, customizations, options, co
|
|
|
21798
21836
|
}
|
|
21799
21837
|
skipPaths.push(...protectedSkipPaths);
|
|
21800
21838
|
const path = await import("node:path");
|
|
21801
|
-
const normalizedSkipPaths = skipPaths.map((p) => path.relative(destPath,
|
|
21839
|
+
const normalizedSkipPaths = skipPaths.map((p) => path.relative(destPath, join19(targetDir, p)));
|
|
21802
21840
|
const uniqueSkipPaths = [...new Set(normalizedSkipPaths)];
|
|
21803
21841
|
await copyDirectory(srcPath, destPath, {
|
|
21804
21842
|
overwrite: true,
|
|
@@ -21827,7 +21865,7 @@ async function syncRootLevelFiles(targetDir, options, customizations) {
|
|
|
21827
21865
|
const preserved = [];
|
|
21828
21866
|
const preserveSet = new Set(customizations && !options.forceOverwriteAll ? customizations.preserveFiles : []);
|
|
21829
21867
|
for (const fileName of ROOT_LEVEL_FILES) {
|
|
21830
|
-
const srcPath = resolveTemplatePath(
|
|
21868
|
+
const srcPath = resolveTemplatePath(join19(layout.rootDir, fileName));
|
|
21831
21869
|
if (!await fileExists(srcPath)) {
|
|
21832
21870
|
continue;
|
|
21833
21871
|
}
|
|
@@ -21836,8 +21874,8 @@ async function syncRootLevelFiles(targetDir, options, customizations) {
|
|
|
21836
21874
|
preserved.push(relPath);
|
|
21837
21875
|
continue;
|
|
21838
21876
|
}
|
|
21839
|
-
const destPath =
|
|
21840
|
-
await ensureDirectory(
|
|
21877
|
+
const destPath = join19(targetDir, layout.rootDir, fileName);
|
|
21878
|
+
await ensureDirectory(join19(destPath, ".."));
|
|
21841
21879
|
await fs.copyFile(srcPath, destPath);
|
|
21842
21880
|
if (fileName.endsWith(".sh")) {
|
|
21843
21881
|
await fs.chmod(destPath, 493);
|
|
@@ -21872,7 +21910,7 @@ async function removeDeprecatedFiles(targetDir, options) {
|
|
|
21872
21910
|
});
|
|
21873
21911
|
continue;
|
|
21874
21912
|
}
|
|
21875
|
-
const fullPath =
|
|
21913
|
+
const fullPath = join19(targetDir, entry.path);
|
|
21876
21914
|
if (await fileExists(fullPath)) {
|
|
21877
21915
|
await fs.unlink(fullPath);
|
|
21878
21916
|
removed.push(entry.path);
|
|
@@ -21913,7 +21951,7 @@ async function syncNamespaceInFile(targetFilePath, upstreamFilePath) {
|
|
|
21913
21951
|
async function processNamespaceSyncEntry(entry, relPath, fullSrcPath, destPath, componentPath, lockfile) {
|
|
21914
21952
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
21915
21953
|
return null;
|
|
21916
|
-
const targetFilePath =
|
|
21954
|
+
const targetFilePath = join19(destPath, relPath);
|
|
21917
21955
|
const lockfileKey = `${componentPath}/${relPath}`.replace(/\\/g, "/");
|
|
21918
21956
|
const shouldSkip = await shouldSkipProtectedFile(targetFilePath, lockfileKey, lockfile);
|
|
21919
21957
|
if (shouldSkip)
|
|
@@ -21928,7 +21966,7 @@ async function applyNamespaceSync(targetDir, component, lockfile) {
|
|
|
21928
21966
|
return [];
|
|
21929
21967
|
const componentPath = getComponentPath2(component);
|
|
21930
21968
|
const srcPath = resolveTemplatePath(componentPath);
|
|
21931
|
-
const destPath =
|
|
21969
|
+
const destPath = join19(targetDir, componentPath);
|
|
21932
21970
|
const fs = await import("node:fs/promises");
|
|
21933
21971
|
const synced = [];
|
|
21934
21972
|
const queue = [{ dir: srcPath, relDir: "" }];
|
|
@@ -21942,7 +21980,7 @@ async function applyNamespaceSync(targetDir, component, lockfile) {
|
|
|
21942
21980
|
}
|
|
21943
21981
|
for (const entry of entries) {
|
|
21944
21982
|
const relPath = relDir ? `${relDir}/${entry.name}` : entry.name;
|
|
21945
|
-
const fullSrcPath =
|
|
21983
|
+
const fullSrcPath = join19(dir, entry.name);
|
|
21946
21984
|
if (entry.isDirectory()) {
|
|
21947
21985
|
queue.push({ dir: fullSrcPath, relDir: relPath });
|
|
21948
21986
|
continue;
|
|
@@ -21965,26 +22003,26 @@ function getComponentPath2(component) {
|
|
|
21965
22003
|
}
|
|
21966
22004
|
async function backupInstallation(targetDir) {
|
|
21967
22005
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
21968
|
-
const backupDir =
|
|
22006
|
+
const backupDir = join19(targetDir, `.omcustom-backup-${timestamp}`);
|
|
21969
22007
|
const fs = await import("node:fs/promises");
|
|
21970
22008
|
await ensureDirectory(backupDir);
|
|
21971
22009
|
const layout = getProviderLayout();
|
|
21972
22010
|
const dirsToBackup = [layout.rootDir, "guides"];
|
|
21973
22011
|
for (const dir of dirsToBackup) {
|
|
21974
|
-
const srcPath =
|
|
22012
|
+
const srcPath = join19(targetDir, dir);
|
|
21975
22013
|
if (await fileExists(srcPath)) {
|
|
21976
|
-
const destPath =
|
|
22014
|
+
const destPath = join19(backupDir, dir);
|
|
21977
22015
|
await copyDirectory(srcPath, destPath, { overwrite: true });
|
|
21978
22016
|
}
|
|
21979
22017
|
}
|
|
21980
|
-
const entryPath =
|
|
22018
|
+
const entryPath = join19(targetDir, layout.entryFile);
|
|
21981
22019
|
if (await fileExists(entryPath)) {
|
|
21982
|
-
await fs.copyFile(entryPath,
|
|
22020
|
+
await fs.copyFile(entryPath, join19(backupDir, layout.entryFile));
|
|
21983
22021
|
}
|
|
21984
22022
|
return backupDir;
|
|
21985
22023
|
}
|
|
21986
22024
|
async function loadCustomizationManifest(targetDir) {
|
|
21987
|
-
const manifestPath =
|
|
22025
|
+
const manifestPath = join19(targetDir, CUSTOMIZATION_MANIFEST_FILE);
|
|
21988
22026
|
if (await fileExists(manifestPath)) {
|
|
21989
22027
|
return readJsonFile(manifestPath);
|
|
21990
22028
|
}
|