claudekit-cli 3.34.1-dev.4 → 3.35.0-dev.1
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/index.js +1254 -408
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -44585,10 +44585,38 @@ var init_pnpm_detector = __esm(() => {
|
|
|
44585
44585
|
});
|
|
44586
44586
|
|
|
44587
44587
|
// src/domains/installation/package-managers/detection-core.ts
|
|
44588
|
-
import { existsSync as existsSync17 } from "node:fs";
|
|
44588
|
+
import { existsSync as existsSync17, realpathSync } from "node:fs";
|
|
44589
44589
|
import { chmod as chmod2, mkdir as mkdir6, readFile as readFile13, writeFile as writeFile7 } from "node:fs/promises";
|
|
44590
44590
|
import { platform as platform4 } from "node:os";
|
|
44591
|
-
import { join as join23 } from "node:path";
|
|
44591
|
+
import { join as join23, sep } from "node:path";
|
|
44592
|
+
function detectFromBinaryPath() {
|
|
44593
|
+
try {
|
|
44594
|
+
const scriptPath = process.argv[1];
|
|
44595
|
+
if (!scriptPath)
|
|
44596
|
+
return "unknown";
|
|
44597
|
+
let resolvedPath;
|
|
44598
|
+
try {
|
|
44599
|
+
resolvedPath = realpathSync(scriptPath);
|
|
44600
|
+
} catch {
|
|
44601
|
+
resolvedPath = scriptPath;
|
|
44602
|
+
}
|
|
44603
|
+
const normalized = resolvedPath.split(sep).join("/").toLowerCase();
|
|
44604
|
+
logger.verbose(`Binary path resolved: ${normalized}`);
|
|
44605
|
+
if (normalized.includes("/.bun/install/") || normalized.includes("/bun/install/global/")) {
|
|
44606
|
+
return "bun";
|
|
44607
|
+
}
|
|
44608
|
+
if (normalized.includes("/pnpm/global/") || normalized.includes("/.local/share/pnpm/")) {
|
|
44609
|
+
return "pnpm";
|
|
44610
|
+
}
|
|
44611
|
+
if (normalized.includes("/yarn/global/") || normalized.includes("/.config/yarn/")) {
|
|
44612
|
+
return "yarn";
|
|
44613
|
+
}
|
|
44614
|
+
if (normalized.includes("/npm/node_modules/") || normalized.includes("/usr/local/lib/node_modules/") || normalized.includes("/usr/lib/node_modules/") || normalized.includes("/opt/homebrew/lib/node_modules/") || normalized.includes("/.nvm/versions/node/") || normalized.includes("/n/versions/node/") || normalized.includes("/appdata/roaming/npm/")) {
|
|
44615
|
+
return "npm";
|
|
44616
|
+
}
|
|
44617
|
+
} catch {}
|
|
44618
|
+
return "unknown";
|
|
44619
|
+
}
|
|
44592
44620
|
function detectFromEnv() {
|
|
44593
44621
|
const userAgent = process.env.npm_config_user_agent;
|
|
44594
44622
|
if (userAgent) {
|
|
@@ -44605,13 +44633,14 @@ function detectFromEnv() {
|
|
|
44605
44633
|
const execPath = process.env.npm_execpath;
|
|
44606
44634
|
if (execPath) {
|
|
44607
44635
|
logger.debug(`Detected exec path: ${execPath}`);
|
|
44608
|
-
|
|
44636
|
+
const normalizedExec = execPath.replace(/\\/g, "/").toLowerCase();
|
|
44637
|
+
if (/\/bun([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("bun"))
|
|
44609
44638
|
return "bun";
|
|
44610
|
-
if (
|
|
44639
|
+
if (/\/yarn([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("yarn"))
|
|
44611
44640
|
return "yarn";
|
|
44612
|
-
if (
|
|
44641
|
+
if (/\/pnpm([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("pnpm"))
|
|
44613
44642
|
return "pnpm";
|
|
44614
|
-
if (
|
|
44643
|
+
if (/\/npm([/.]|$)/.test(normalizedExec) || normalizedExec.startsWith("npm"))
|
|
44615
44644
|
return "npm";
|
|
44616
44645
|
}
|
|
44617
44646
|
return "unknown";
|
|
@@ -44629,8 +44658,8 @@ async function readCachedPm() {
|
|
|
44629
44658
|
return null;
|
|
44630
44659
|
}
|
|
44631
44660
|
const age = Date.now() - data.detectedAt;
|
|
44632
|
-
if (age > CACHE_TTL) {
|
|
44633
|
-
logger.debug("Cache expired, will re-detect");
|
|
44661
|
+
if (age < 0 || age > CACHE_TTL) {
|
|
44662
|
+
logger.debug(age < 0 ? "Cache timestamp in future, ignoring" : "Cache expired, will re-detect");
|
|
44634
44663
|
return null;
|
|
44635
44664
|
}
|
|
44636
44665
|
const validPms = ["npm", "bun", "yarn", "pnpm"];
|
|
@@ -44739,6 +44768,18 @@ var init_package_manager_detector = __esm(() => {
|
|
|
44739
44768
|
PackageManagerDetector = class PackageManagerDetector {
|
|
44740
44769
|
static async detect() {
|
|
44741
44770
|
logger.verbose("PackageManagerDetector: Starting detection");
|
|
44771
|
+
const binaryPm = detectFromBinaryPath();
|
|
44772
|
+
if (binaryPm !== "unknown") {
|
|
44773
|
+
logger.verbose(`PackageManagerDetector: Detected from binary path: ${binaryPm}`);
|
|
44774
|
+
const cachedPm2 = await readCachedPm();
|
|
44775
|
+
if (cachedPm2 && cachedPm2 !== binaryPm) {
|
|
44776
|
+
logger.verbose(`PackageManagerDetector: Cache says ${cachedPm2}, binary says ${binaryPm} — updating cache`);
|
|
44777
|
+
await saveCachedPm(binaryPm, PackageManagerDetector.getVersion);
|
|
44778
|
+
} else if (!cachedPm2) {
|
|
44779
|
+
await saveCachedPm(binaryPm, PackageManagerDetector.getVersion);
|
|
44780
|
+
}
|
|
44781
|
+
return binaryPm;
|
|
44782
|
+
}
|
|
44742
44783
|
const envPm = detectFromEnv();
|
|
44743
44784
|
if (envPm !== "unknown") {
|
|
44744
44785
|
logger.verbose(`PackageManagerDetector: Detected from env: ${envPm}`);
|
|
@@ -45236,7 +45277,7 @@ var package_default;
|
|
|
45236
45277
|
var init_package = __esm(() => {
|
|
45237
45278
|
package_default = {
|
|
45238
45279
|
name: "claudekit-cli",
|
|
45239
|
-
version: "3.
|
|
45280
|
+
version: "3.35.0-dev.1",
|
|
45240
45281
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
45241
45282
|
type: "module",
|
|
45242
45283
|
repository: {
|
|
@@ -45551,12 +45592,15 @@ Run 'ck update' to install`, "Update Check");
|
|
|
45551
45592
|
s.stop("Update failed");
|
|
45552
45593
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
45553
45594
|
if (errorMessage.includes("EACCES") || errorMessage.includes("EPERM") || errorMessage.includes("permission") || errorMessage.includes("Access is denied")) {
|
|
45554
|
-
|
|
45595
|
+
const permHint = pm === "npm" ? `
|
|
45555
45596
|
|
|
45556
|
-
Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally`
|
|
45597
|
+
Or fix npm permissions: https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally` : "";
|
|
45598
|
+
const isWindows3 = process.platform === "win32";
|
|
45599
|
+
const elevationHint = isWindows3 ? `Run your terminal as Administrator and retry: ${updateCmd}` : `sudo ${updateCmd}`;
|
|
45600
|
+
throw new CliUpdateError(`Permission denied. Try: ${elevationHint}${permHint}`);
|
|
45557
45601
|
}
|
|
45558
45602
|
logger.error(`Update failed: ${errorMessage}`);
|
|
45559
|
-
logger.info(
|
|
45603
|
+
logger.info(`Try running: ${updateCmd}`);
|
|
45560
45604
|
throw new CliUpdateError(`Update failed: ${errorMessage}
|
|
45561
45605
|
|
|
45562
45606
|
Manual update: ${updateCmd}`);
|
|
@@ -50573,7 +50617,7 @@ __export(exports_github_api_checker, {
|
|
|
50573
50617
|
checkRepositoryAccess: () => checkRepositoryAccess,
|
|
50574
50618
|
checkRateLimit: () => checkRateLimit
|
|
50575
50619
|
});
|
|
50576
|
-
import { spawnSync } from "node:child_process";
|
|
50620
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
50577
50621
|
async function checkRateLimit() {
|
|
50578
50622
|
if (false) {}
|
|
50579
50623
|
const apiEndpoint = "api.github.com/rate_limit";
|
|
@@ -50668,7 +50712,7 @@ async function checkTokenScopes() {
|
|
|
50668
50712
|
if (false) {}
|
|
50669
50713
|
const checkCommand = "gh auth status -h github.com";
|
|
50670
50714
|
try {
|
|
50671
|
-
const result =
|
|
50715
|
+
const result = spawnSync2("gh", ["auth", "status", "-h", "github.com"], {
|
|
50672
50716
|
encoding: "utf8",
|
|
50673
50717
|
timeout: COMMAND_TIMEOUT_MS
|
|
50674
50718
|
});
|
|
@@ -52236,7 +52280,7 @@ var require_picomatch2 = __commonJS((exports, module) => {
|
|
|
52236
52280
|
import { exec as exec7, execFile as execFile7, spawn as spawn3 } from "node:child_process";
|
|
52237
52281
|
import { promisify as promisify13 } from "node:util";
|
|
52238
52282
|
function executeInteractiveScript(command, args, options2) {
|
|
52239
|
-
return new Promise((
|
|
52283
|
+
return new Promise((resolve9, reject) => {
|
|
52240
52284
|
const child = spawn3(command, args, {
|
|
52241
52285
|
stdio: ["ignore", "inherit", "inherit"],
|
|
52242
52286
|
cwd: options2?.cwd,
|
|
@@ -52257,7 +52301,7 @@ function executeInteractiveScript(command, args, options2) {
|
|
|
52257
52301
|
} else if (code !== 0) {
|
|
52258
52302
|
reject(new Error(`Command exited with code ${code}`));
|
|
52259
52303
|
} else {
|
|
52260
|
-
|
|
52304
|
+
resolve9();
|
|
52261
52305
|
}
|
|
52262
52306
|
});
|
|
52263
52307
|
child.on("error", (error) => {
|
|
@@ -52278,7 +52322,7 @@ var init_process_executor = __esm(() => {
|
|
|
52278
52322
|
});
|
|
52279
52323
|
|
|
52280
52324
|
// src/services/package-installer/validators.ts
|
|
52281
|
-
import { resolve as
|
|
52325
|
+
import { resolve as resolve9 } from "node:path";
|
|
52282
52326
|
function validatePackageName(packageName) {
|
|
52283
52327
|
if (!packageName || typeof packageName !== "string") {
|
|
52284
52328
|
throw new Error("Package name must be a non-empty string");
|
|
@@ -52291,8 +52335,8 @@ function validatePackageName(packageName) {
|
|
|
52291
52335
|
}
|
|
52292
52336
|
}
|
|
52293
52337
|
function validateScriptPath(skillsDir2, scriptPath) {
|
|
52294
|
-
const skillsDirResolved =
|
|
52295
|
-
const scriptPathResolved =
|
|
52338
|
+
const skillsDirResolved = resolve9(skillsDir2);
|
|
52339
|
+
const scriptPathResolved = resolve9(scriptPath);
|
|
52296
52340
|
const skillsDirNormalized = isWindows() ? skillsDirResolved.toLowerCase() : skillsDirResolved;
|
|
52297
52341
|
const scriptPathNormalized = isWindows() ? scriptPathResolved.toLowerCase() : scriptPathResolved;
|
|
52298
52342
|
if (!scriptPathNormalized.startsWith(skillsDirNormalized)) {
|
|
@@ -52456,7 +52500,7 @@ var init_gemini_installer = __esm(() => {
|
|
|
52456
52500
|
});
|
|
52457
52501
|
|
|
52458
52502
|
// src/services/package-installer/opencode-installer.ts
|
|
52459
|
-
import { join as
|
|
52503
|
+
import { join as join48 } from "node:path";
|
|
52460
52504
|
async function isOpenCodeInstalled() {
|
|
52461
52505
|
try {
|
|
52462
52506
|
await execAsync7("opencode --version", { timeout: 5000 });
|
|
@@ -52478,8 +52522,8 @@ async function installOpenCode() {
|
|
|
52478
52522
|
try {
|
|
52479
52523
|
logger.info(`Installing ${displayName}...`);
|
|
52480
52524
|
const { unlink: unlink8 } = await import("node:fs/promises");
|
|
52481
|
-
const { tmpdir:
|
|
52482
|
-
const tempScriptPath =
|
|
52525
|
+
const { tmpdir: tmpdir4 } = await import("node:os");
|
|
52526
|
+
const tempScriptPath = join48(tmpdir4(), "opencode-install.sh");
|
|
52483
52527
|
try {
|
|
52484
52528
|
logger.info("Downloading OpenCode installation script...");
|
|
52485
52529
|
await execFileAsync5("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
|
|
@@ -52530,8 +52574,8 @@ var init_opencode_installer = __esm(() => {
|
|
|
52530
52574
|
var PARTIAL_INSTALL_VERSION = "partial", EXIT_CODE_CRITICAL_FAILURE = 1, EXIT_CODE_PARTIAL_SUCCESS = 2;
|
|
52531
52575
|
|
|
52532
52576
|
// src/services/package-installer/install-error-handler.ts
|
|
52533
|
-
import { existsSync as
|
|
52534
|
-
import { join as
|
|
52577
|
+
import { existsSync as existsSync32, readFileSync as readFileSync8, unlinkSync as unlinkSync2 } from "node:fs";
|
|
52578
|
+
import { join as join49 } from "node:path";
|
|
52535
52579
|
function parseNameReason(str2) {
|
|
52536
52580
|
const colonIndex = str2.indexOf(":");
|
|
52537
52581
|
if (colonIndex === -1) {
|
|
@@ -52540,14 +52584,14 @@ function parseNameReason(str2) {
|
|
|
52540
52584
|
return [str2.slice(0, colonIndex).trim(), str2.slice(colonIndex + 1).trim()];
|
|
52541
52585
|
}
|
|
52542
52586
|
function displayInstallErrors(skillsDir2) {
|
|
52543
|
-
const summaryPath =
|
|
52544
|
-
if (!
|
|
52587
|
+
const summaryPath = join49(skillsDir2, ".install-error-summary.json");
|
|
52588
|
+
if (!existsSync32(summaryPath)) {
|
|
52545
52589
|
logger.error("Skills installation failed. Run with --verbose for details.");
|
|
52546
52590
|
return;
|
|
52547
52591
|
}
|
|
52548
52592
|
let summary;
|
|
52549
52593
|
try {
|
|
52550
|
-
summary = JSON.parse(
|
|
52594
|
+
summary = JSON.parse(readFileSync8(summaryPath, "utf-8"));
|
|
52551
52595
|
} catch (parseError) {
|
|
52552
52596
|
logger.error("Failed to parse error summary. File may be corrupted.");
|
|
52553
52597
|
logger.debug(`Parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
@@ -52631,8 +52675,8 @@ async function checkNeedsSudoPackages() {
|
|
|
52631
52675
|
}
|
|
52632
52676
|
}
|
|
52633
52677
|
function hasInstallState(skillsDir2) {
|
|
52634
|
-
const stateFilePath =
|
|
52635
|
-
return
|
|
52678
|
+
const stateFilePath = join49(skillsDir2, ".install-state.json");
|
|
52679
|
+
return existsSync32(stateFilePath);
|
|
52636
52680
|
}
|
|
52637
52681
|
var WHICH_COMMAND_TIMEOUT_MS = 5000;
|
|
52638
52682
|
var init_install_error_handler = __esm(() => {
|
|
@@ -52640,7 +52684,7 @@ var init_install_error_handler = __esm(() => {
|
|
|
52640
52684
|
});
|
|
52641
52685
|
|
|
52642
52686
|
// src/services/package-installer/skills-installer.ts
|
|
52643
|
-
import { join as
|
|
52687
|
+
import { join as join50 } from "node:path";
|
|
52644
52688
|
async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
52645
52689
|
const { skipConfirm = false, withSudo = false } = options2;
|
|
52646
52690
|
const displayName = "Skills Dependencies";
|
|
@@ -52662,11 +52706,11 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
|
52662
52706
|
};
|
|
52663
52707
|
}
|
|
52664
52708
|
try {
|
|
52665
|
-
const { existsSync:
|
|
52709
|
+
const { existsSync: existsSync33 } = await import("node:fs");
|
|
52666
52710
|
const clack = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
52667
52711
|
const platform7 = process.platform;
|
|
52668
52712
|
const scriptName = platform7 === "win32" ? "install.ps1" : "install.sh";
|
|
52669
|
-
const scriptPath =
|
|
52713
|
+
const scriptPath = join50(skillsDir2, scriptName);
|
|
52670
52714
|
try {
|
|
52671
52715
|
validateScriptPath(skillsDir2, scriptPath);
|
|
52672
52716
|
} catch (error) {
|
|
@@ -52678,11 +52722,11 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
|
52678
52722
|
error: `Path validation failed: ${errorMessage}`
|
|
52679
52723
|
};
|
|
52680
52724
|
}
|
|
52681
|
-
if (!
|
|
52725
|
+
if (!existsSync33(scriptPath)) {
|
|
52682
52726
|
logger.warning(`Skills installation script not found: ${scriptPath}`);
|
|
52683
52727
|
logger.info("");
|
|
52684
52728
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
52685
|
-
logger.info(` See: ${
|
|
52729
|
+
logger.info(` See: ${join50(skillsDir2, "INSTALLATION.md")}`);
|
|
52686
52730
|
logger.info("");
|
|
52687
52731
|
logger.info("Quick start:");
|
|
52688
52732
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -52729,7 +52773,7 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
|
52729
52773
|
logger.info(` ${platform7 === "win32" ? `powershell -File "${scriptPath}"` : `bash ${scriptPath}`}`);
|
|
52730
52774
|
logger.info("");
|
|
52731
52775
|
logger.info("Or see complete guide:");
|
|
52732
|
-
logger.info(` ${
|
|
52776
|
+
logger.info(` ${join50(skillsDir2, "INSTALLATION.md")}`);
|
|
52733
52777
|
return {
|
|
52734
52778
|
success: false,
|
|
52735
52779
|
package: displayName,
|
|
@@ -52850,7 +52894,7 @@ async function installSkillsDependencies(skillsDir2, options2 = {}) {
|
|
|
52850
52894
|
logger.info("\uD83D\uDCD6 Manual Installation Instructions:");
|
|
52851
52895
|
logger.info("");
|
|
52852
52896
|
logger.info("See complete guide:");
|
|
52853
|
-
logger.info(` cat ${
|
|
52897
|
+
logger.info(` cat ${join50(skillsDir2, "INSTALLATION.md")}`);
|
|
52854
52898
|
logger.info("");
|
|
52855
52899
|
logger.info("Quick start:");
|
|
52856
52900
|
logger.info(" cd .claude/skills/ai-multimodal/scripts");
|
|
@@ -52894,9 +52938,9 @@ var init_skills_installer2 = __esm(() => {
|
|
|
52894
52938
|
});
|
|
52895
52939
|
|
|
52896
52940
|
// src/services/package-installer/gemini-mcp/config-manager.ts
|
|
52897
|
-
import { existsSync as
|
|
52941
|
+
import { existsSync as existsSync33 } from "node:fs";
|
|
52898
52942
|
import { mkdir as mkdir12, readFile as readFile26, writeFile as writeFile15 } from "node:fs/promises";
|
|
52899
|
-
import { dirname as dirname11, join as
|
|
52943
|
+
import { dirname as dirname11, join as join51 } from "node:path";
|
|
52900
52944
|
async function readJsonFile(filePath) {
|
|
52901
52945
|
try {
|
|
52902
52946
|
const content = await readFile26(filePath, "utf-8");
|
|
@@ -52908,11 +52952,11 @@ async function readJsonFile(filePath) {
|
|
|
52908
52952
|
}
|
|
52909
52953
|
}
|
|
52910
52954
|
async function addGeminiToGitignore(projectDir) {
|
|
52911
|
-
const gitignorePath =
|
|
52955
|
+
const gitignorePath = join51(projectDir, ".gitignore");
|
|
52912
52956
|
const geminiPattern = ".gemini/";
|
|
52913
52957
|
try {
|
|
52914
52958
|
let content = "";
|
|
52915
|
-
if (
|
|
52959
|
+
if (existsSync33(gitignorePath)) {
|
|
52916
52960
|
content = await readFile26(gitignorePath, "utf-8");
|
|
52917
52961
|
const lines = content.split(`
|
|
52918
52962
|
`).map((line) => line.trim()).filter((line) => !line.startsWith("#"));
|
|
@@ -52937,7 +52981,7 @@ ${geminiPattern}
|
|
|
52937
52981
|
}
|
|
52938
52982
|
async function createNewSettingsWithMerge(geminiSettingsPath, mcpConfigPath) {
|
|
52939
52983
|
const linkDir = dirname11(geminiSettingsPath);
|
|
52940
|
-
if (!
|
|
52984
|
+
if (!existsSync33(linkDir)) {
|
|
52941
52985
|
await mkdir12(linkDir, { recursive: true });
|
|
52942
52986
|
logger.debug(`Created directory: ${linkDir}`);
|
|
52943
52987
|
}
|
|
@@ -52998,23 +53042,23 @@ var init_config_manager2 = __esm(() => {
|
|
|
52998
53042
|
});
|
|
52999
53043
|
|
|
53000
53044
|
// src/services/package-installer/gemini-mcp/validation.ts
|
|
53001
|
-
import { existsSync as
|
|
53045
|
+
import { existsSync as existsSync34, lstatSync, readlinkSync } from "node:fs";
|
|
53002
53046
|
import { homedir as homedir17 } from "node:os";
|
|
53003
|
-
import { join as
|
|
53047
|
+
import { join as join52 } from "node:path";
|
|
53004
53048
|
function getGlobalMcpConfigPath() {
|
|
53005
|
-
return
|
|
53049
|
+
return join52(homedir17(), ".claude", ".mcp.json");
|
|
53006
53050
|
}
|
|
53007
53051
|
function getLocalMcpConfigPath(projectDir) {
|
|
53008
|
-
return
|
|
53052
|
+
return join52(projectDir, ".mcp.json");
|
|
53009
53053
|
}
|
|
53010
53054
|
function findMcpConfigPath(projectDir) {
|
|
53011
53055
|
const localPath = getLocalMcpConfigPath(projectDir);
|
|
53012
|
-
if (
|
|
53056
|
+
if (existsSync34(localPath)) {
|
|
53013
53057
|
logger.debug(`Found local MCP config: ${localPath}`);
|
|
53014
53058
|
return localPath;
|
|
53015
53059
|
}
|
|
53016
53060
|
const globalPath = getGlobalMcpConfigPath();
|
|
53017
|
-
if (
|
|
53061
|
+
if (existsSync34(globalPath)) {
|
|
53018
53062
|
logger.debug(`Found global MCP config: ${globalPath}`);
|
|
53019
53063
|
return globalPath;
|
|
53020
53064
|
}
|
|
@@ -53023,13 +53067,13 @@ function findMcpConfigPath(projectDir) {
|
|
|
53023
53067
|
}
|
|
53024
53068
|
function getGeminiSettingsPath(projectDir, isGlobal) {
|
|
53025
53069
|
if (isGlobal) {
|
|
53026
|
-
return
|
|
53070
|
+
return join52(homedir17(), ".gemini", "settings.json");
|
|
53027
53071
|
}
|
|
53028
|
-
return
|
|
53072
|
+
return join52(projectDir, ".gemini", "settings.json");
|
|
53029
53073
|
}
|
|
53030
53074
|
function checkExistingGeminiConfig(projectDir, isGlobal = false) {
|
|
53031
53075
|
const geminiSettingsPath = getGeminiSettingsPath(projectDir, isGlobal);
|
|
53032
|
-
if (!
|
|
53076
|
+
if (!existsSync34(geminiSettingsPath)) {
|
|
53033
53077
|
return { exists: false, isSymlink: false, settingsPath: geminiSettingsPath };
|
|
53034
53078
|
}
|
|
53035
53079
|
try {
|
|
@@ -53053,12 +53097,12 @@ var init_validation = __esm(() => {
|
|
|
53053
53097
|
});
|
|
53054
53098
|
|
|
53055
53099
|
// src/services/package-installer/gemini-mcp/linker-core.ts
|
|
53056
|
-
import { existsSync as
|
|
53100
|
+
import { existsSync as existsSync35 } from "node:fs";
|
|
53057
53101
|
import { mkdir as mkdir13, symlink as symlink2 } from "node:fs/promises";
|
|
53058
|
-
import { dirname as dirname12, join as
|
|
53102
|
+
import { dirname as dirname12, join as join53 } from "node:path";
|
|
53059
53103
|
async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
53060
53104
|
const linkDir = dirname12(linkPath);
|
|
53061
|
-
if (!
|
|
53105
|
+
if (!existsSync35(linkDir)) {
|
|
53062
53106
|
await mkdir13(linkDir, { recursive: true });
|
|
53063
53107
|
logger.debug(`Created directory: ${linkDir}`);
|
|
53064
53108
|
}
|
|
@@ -53066,7 +53110,7 @@ async function createSymlink(targetPath, linkPath, projectDir, isGlobal) {
|
|
|
53066
53110
|
if (isGlobal) {
|
|
53067
53111
|
symlinkTarget = getGlobalMcpConfigPath();
|
|
53068
53112
|
} else {
|
|
53069
|
-
const localMcpPath =
|
|
53113
|
+
const localMcpPath = join53(projectDir, ".mcp.json");
|
|
53070
53114
|
const isLocalConfig = targetPath === localMcpPath;
|
|
53071
53115
|
symlinkTarget = isLocalConfig ? "../.mcp.json" : targetPath;
|
|
53072
53116
|
}
|
|
@@ -53099,10 +53143,10 @@ __export(exports_gemini_mcp_linker, {
|
|
|
53099
53143
|
checkExistingGeminiConfig: () => checkExistingGeminiConfig,
|
|
53100
53144
|
addGeminiToGitignore: () => addGeminiToGitignore
|
|
53101
53145
|
});
|
|
53102
|
-
import { resolve as
|
|
53146
|
+
import { resolve as resolve10 } from "node:path";
|
|
53103
53147
|
async function linkGeminiMcpConfig(projectDir, options2 = {}) {
|
|
53104
53148
|
const { skipGitignore = false, isGlobal = false } = options2;
|
|
53105
|
-
const resolvedProjectDir =
|
|
53149
|
+
const resolvedProjectDir = resolve10(projectDir);
|
|
53106
53150
|
const geminiSettingsPath = getGeminiSettingsPath(resolvedProjectDir, isGlobal);
|
|
53107
53151
|
const mcpConfigPath = findMcpConfigPath(resolvedProjectDir);
|
|
53108
53152
|
if (!mcpConfigPath) {
|
|
@@ -53900,12 +53944,12 @@ var require_adapter = __commonJS((exports, module) => {
|
|
|
53900
53944
|
return newFs;
|
|
53901
53945
|
}
|
|
53902
53946
|
function toPromise(method) {
|
|
53903
|
-
return (...args) => new Promise((
|
|
53947
|
+
return (...args) => new Promise((resolve11, reject) => {
|
|
53904
53948
|
args.push((err, result) => {
|
|
53905
53949
|
if (err) {
|
|
53906
53950
|
reject(err);
|
|
53907
53951
|
} else {
|
|
53908
|
-
|
|
53952
|
+
resolve11(result);
|
|
53909
53953
|
}
|
|
53910
53954
|
});
|
|
53911
53955
|
method(...args);
|
|
@@ -54475,7 +54519,7 @@ var require_get_stream = __commonJS((exports, module) => {
|
|
|
54475
54519
|
};
|
|
54476
54520
|
const { maxBuffer } = options2;
|
|
54477
54521
|
let stream;
|
|
54478
|
-
await new Promise((
|
|
54522
|
+
await new Promise((resolve12, reject) => {
|
|
54479
54523
|
const rejectPromise = (error) => {
|
|
54480
54524
|
if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
|
|
54481
54525
|
error.bufferedData = stream.getBufferedValue();
|
|
@@ -54487,7 +54531,7 @@ var require_get_stream = __commonJS((exports, module) => {
|
|
|
54487
54531
|
rejectPromise(error);
|
|
54488
54532
|
return;
|
|
54489
54533
|
}
|
|
54490
|
-
|
|
54534
|
+
resolve12();
|
|
54491
54535
|
});
|
|
54492
54536
|
stream.on("data", () => {
|
|
54493
54537
|
if (stream.getBufferedLength() > maxBuffer) {
|
|
@@ -55848,7 +55892,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
55848
55892
|
debug("opening", this.zipPath, "with opts", this.opts);
|
|
55849
55893
|
this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
|
|
55850
55894
|
this.canceled = false;
|
|
55851
|
-
return new Promise((
|
|
55895
|
+
return new Promise((resolve12, reject) => {
|
|
55852
55896
|
this.zipfile.on("error", (err) => {
|
|
55853
55897
|
this.canceled = true;
|
|
55854
55898
|
reject(err);
|
|
@@ -55857,7 +55901,7 @@ var require_extract_zip = __commonJS((exports, module) => {
|
|
|
55857
55901
|
this.zipfile.on("close", () => {
|
|
55858
55902
|
if (!this.canceled) {
|
|
55859
55903
|
debug("zip extraction complete");
|
|
55860
|
-
|
|
55904
|
+
resolve12();
|
|
55861
55905
|
}
|
|
55862
55906
|
});
|
|
55863
55907
|
this.zipfile.on("entry", async (entry) => {
|
|
@@ -58565,7 +58609,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
58565
58609
|
return [];
|
|
58566
58610
|
}
|
|
58567
58611
|
async function trySystemPager(content) {
|
|
58568
|
-
return new Promise((
|
|
58612
|
+
return new Promise((resolve21) => {
|
|
58569
58613
|
const pagerCmd = process.env.PAGER || "less";
|
|
58570
58614
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
58571
58615
|
try {
|
|
@@ -58575,20 +58619,20 @@ async function trySystemPager(content) {
|
|
|
58575
58619
|
});
|
|
58576
58620
|
const timeout2 = setTimeout(() => {
|
|
58577
58621
|
pager.kill();
|
|
58578
|
-
|
|
58622
|
+
resolve21(false);
|
|
58579
58623
|
}, 30000);
|
|
58580
58624
|
pager.stdin.write(content);
|
|
58581
58625
|
pager.stdin.end();
|
|
58582
58626
|
pager.on("close", (code2) => {
|
|
58583
58627
|
clearTimeout(timeout2);
|
|
58584
|
-
|
|
58628
|
+
resolve21(code2 === 0);
|
|
58585
58629
|
});
|
|
58586
58630
|
pager.on("error", () => {
|
|
58587
58631
|
clearTimeout(timeout2);
|
|
58588
|
-
|
|
58632
|
+
resolve21(false);
|
|
58589
58633
|
});
|
|
58590
58634
|
} catch {
|
|
58591
|
-
|
|
58635
|
+
resolve21(false);
|
|
58592
58636
|
}
|
|
58593
58637
|
});
|
|
58594
58638
|
}
|
|
@@ -58615,16 +58659,16 @@ async function basicPager(content) {
|
|
|
58615
58659
|
break;
|
|
58616
58660
|
}
|
|
58617
58661
|
const remaining = lines.length - currentLine;
|
|
58618
|
-
await new Promise((
|
|
58662
|
+
await new Promise((resolve21) => {
|
|
58619
58663
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
58620
58664
|
if (answer.toLowerCase() === "q") {
|
|
58621
58665
|
rl.close();
|
|
58622
58666
|
process.exitCode = 0;
|
|
58623
|
-
|
|
58667
|
+
resolve21();
|
|
58624
58668
|
return;
|
|
58625
58669
|
}
|
|
58626
58670
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
58627
|
-
|
|
58671
|
+
resolve21();
|
|
58628
58672
|
});
|
|
58629
58673
|
});
|
|
58630
58674
|
}
|
|
@@ -61572,6 +61616,794 @@ async function checkEnvKeys(setup) {
|
|
|
61572
61616
|
}
|
|
61573
61617
|
return results;
|
|
61574
61618
|
}
|
|
61619
|
+
// src/domains/health-checks/checkers/hook-health-checker.ts
|
|
61620
|
+
init_logger();
|
|
61621
|
+
init_path_resolver();
|
|
61622
|
+
import { spawnSync } from "node:child_process";
|
|
61623
|
+
import { existsSync as existsSync30, readFileSync as readFileSync6, statSync as statSync5, writeFileSync } from "node:fs";
|
|
61624
|
+
import { readdir as readdir9 } from "node:fs/promises";
|
|
61625
|
+
import { tmpdir } from "node:os";
|
|
61626
|
+
import { join as join41, resolve as resolve8 } from "node:path";
|
|
61627
|
+
var HOOK_CHECK_TIMEOUT_MS = 5000;
|
|
61628
|
+
var PYTHON_CHECK_TIMEOUT_MS = 3000;
|
|
61629
|
+
var MAX_LOG_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
61630
|
+
function getHooksDir(projectDir) {
|
|
61631
|
+
const projectHooksDir = resolve8(projectDir, ".claude", "hooks");
|
|
61632
|
+
const globalHooksDir = resolve8(PathResolver.getGlobalKitDir(), "hooks");
|
|
61633
|
+
if (existsSync30(projectHooksDir))
|
|
61634
|
+
return projectHooksDir;
|
|
61635
|
+
if (existsSync30(globalHooksDir))
|
|
61636
|
+
return globalHooksDir;
|
|
61637
|
+
return null;
|
|
61638
|
+
}
|
|
61639
|
+
function isPathWithin(filePath, parentDir) {
|
|
61640
|
+
return resolve8(filePath).startsWith(resolve8(parentDir));
|
|
61641
|
+
}
|
|
61642
|
+
async function checkHookSyntax(projectDir) {
|
|
61643
|
+
const hooksDir = getHooksDir(projectDir);
|
|
61644
|
+
if (!hooksDir) {
|
|
61645
|
+
return {
|
|
61646
|
+
id: "hook-syntax",
|
|
61647
|
+
name: "Hook Syntax",
|
|
61648
|
+
group: "claudekit",
|
|
61649
|
+
priority: "critical",
|
|
61650
|
+
status: "info",
|
|
61651
|
+
message: "No hooks directory",
|
|
61652
|
+
autoFixable: false
|
|
61653
|
+
};
|
|
61654
|
+
}
|
|
61655
|
+
try {
|
|
61656
|
+
const files = await readdir9(hooksDir);
|
|
61657
|
+
const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
|
|
61658
|
+
if (cjsFiles.length === 0) {
|
|
61659
|
+
return {
|
|
61660
|
+
id: "hook-syntax",
|
|
61661
|
+
name: "Hook Syntax",
|
|
61662
|
+
group: "claudekit",
|
|
61663
|
+
priority: "critical",
|
|
61664
|
+
status: "info",
|
|
61665
|
+
message: "No .cjs hooks found",
|
|
61666
|
+
autoFixable: false
|
|
61667
|
+
};
|
|
61668
|
+
}
|
|
61669
|
+
const errors2 = [];
|
|
61670
|
+
for (const file of cjsFiles) {
|
|
61671
|
+
const filePath = join41(hooksDir, file);
|
|
61672
|
+
if (!isPathWithin(filePath, hooksDir))
|
|
61673
|
+
continue;
|
|
61674
|
+
const result = spawnSync("node", ["--check", filePath], {
|
|
61675
|
+
timeout: HOOK_CHECK_TIMEOUT_MS,
|
|
61676
|
+
encoding: "utf-8"
|
|
61677
|
+
});
|
|
61678
|
+
if (result.status !== 0) {
|
|
61679
|
+
errors2.push(`${file}: ${result.stderr?.trim() || "syntax error"}`);
|
|
61680
|
+
}
|
|
61681
|
+
}
|
|
61682
|
+
if (errors2.length > 0) {
|
|
61683
|
+
return {
|
|
61684
|
+
id: "hook-syntax",
|
|
61685
|
+
name: "Hook Syntax",
|
|
61686
|
+
group: "claudekit",
|
|
61687
|
+
priority: "critical",
|
|
61688
|
+
status: "fail",
|
|
61689
|
+
message: `${errors2.length} hook(s) with syntax errors`,
|
|
61690
|
+
details: errors2.join(`
|
|
61691
|
+
`),
|
|
61692
|
+
suggestion: "Run: ck init",
|
|
61693
|
+
autoFixable: true,
|
|
61694
|
+
fix: {
|
|
61695
|
+
id: "fix-hook-syntax",
|
|
61696
|
+
description: "Reinstall hooks via ck init",
|
|
61697
|
+
execute: async () => ({
|
|
61698
|
+
success: false,
|
|
61699
|
+
message: "Manual fix required: run 'ck init'"
|
|
61700
|
+
})
|
|
61701
|
+
}
|
|
61702
|
+
};
|
|
61703
|
+
}
|
|
61704
|
+
return {
|
|
61705
|
+
id: "hook-syntax",
|
|
61706
|
+
name: "Hook Syntax",
|
|
61707
|
+
group: "claudekit",
|
|
61708
|
+
priority: "critical",
|
|
61709
|
+
status: "pass",
|
|
61710
|
+
message: `${cjsFiles.length} hook(s) valid`,
|
|
61711
|
+
autoFixable: false
|
|
61712
|
+
};
|
|
61713
|
+
} catch (error) {
|
|
61714
|
+
logger.debug(`Hook syntax check failed: ${error}`);
|
|
61715
|
+
return {
|
|
61716
|
+
id: "hook-syntax",
|
|
61717
|
+
name: "Hook Syntax",
|
|
61718
|
+
group: "claudekit",
|
|
61719
|
+
priority: "critical",
|
|
61720
|
+
status: "fail",
|
|
61721
|
+
message: "Failed to check hook syntax",
|
|
61722
|
+
details: error instanceof Error ? error.message : String(error),
|
|
61723
|
+
autoFixable: false
|
|
61724
|
+
};
|
|
61725
|
+
}
|
|
61726
|
+
}
|
|
61727
|
+
async function checkHookDeps(projectDir) {
|
|
61728
|
+
const hooksDir = getHooksDir(projectDir);
|
|
61729
|
+
if (!hooksDir) {
|
|
61730
|
+
return {
|
|
61731
|
+
id: "hook-deps",
|
|
61732
|
+
name: "Hook Dependencies",
|
|
61733
|
+
group: "claudekit",
|
|
61734
|
+
priority: "critical",
|
|
61735
|
+
status: "info",
|
|
61736
|
+
message: "No hooks directory",
|
|
61737
|
+
autoFixable: false
|
|
61738
|
+
};
|
|
61739
|
+
}
|
|
61740
|
+
try {
|
|
61741
|
+
const files = await readdir9(hooksDir);
|
|
61742
|
+
const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
|
|
61743
|
+
if (cjsFiles.length === 0) {
|
|
61744
|
+
return {
|
|
61745
|
+
id: "hook-deps",
|
|
61746
|
+
name: "Hook Dependencies",
|
|
61747
|
+
group: "claudekit",
|
|
61748
|
+
priority: "critical",
|
|
61749
|
+
status: "info",
|
|
61750
|
+
message: "No .cjs hooks found",
|
|
61751
|
+
autoFixable: false
|
|
61752
|
+
};
|
|
61753
|
+
}
|
|
61754
|
+
const missingDeps = [];
|
|
61755
|
+
const requireRegex = /require\(['"]([^'"]+)['"]\)/g;
|
|
61756
|
+
for (const file of cjsFiles) {
|
|
61757
|
+
const filePath = join41(hooksDir, file);
|
|
61758
|
+
if (!isPathWithin(filePath, hooksDir))
|
|
61759
|
+
continue;
|
|
61760
|
+
const content = readFileSync6(filePath, "utf-8");
|
|
61761
|
+
for (let match = requireRegex.exec(content);match !== null; match = requireRegex.exec(content)) {
|
|
61762
|
+
const depPath = match[1];
|
|
61763
|
+
if (depPath.startsWith("node:") || isNodeBuiltin(depPath)) {
|
|
61764
|
+
continue;
|
|
61765
|
+
}
|
|
61766
|
+
if (depPath.startsWith(".")) {
|
|
61767
|
+
const resolvedPath = join41(hooksDir, depPath);
|
|
61768
|
+
const extensions = [".js", ".cjs", ".mjs", ".json"];
|
|
61769
|
+
const indexFiles = ["index.js", "index.cjs", "index.mjs"];
|
|
61770
|
+
const exists = existsSync30(resolvedPath) || extensions.some((ext) => existsSync30(resolvedPath + ext)) || indexFiles.some((idx) => existsSync30(join41(resolvedPath, idx)));
|
|
61771
|
+
if (!exists) {
|
|
61772
|
+
missingDeps.push(`${file}: ${depPath}`);
|
|
61773
|
+
}
|
|
61774
|
+
}
|
|
61775
|
+
}
|
|
61776
|
+
}
|
|
61777
|
+
if (missingDeps.length > 0) {
|
|
61778
|
+
return {
|
|
61779
|
+
id: "hook-deps",
|
|
61780
|
+
name: "Hook Dependencies",
|
|
61781
|
+
group: "claudekit",
|
|
61782
|
+
priority: "critical",
|
|
61783
|
+
status: "fail",
|
|
61784
|
+
message: `${missingDeps.length} missing dependency(ies)`,
|
|
61785
|
+
details: missingDeps.join(`
|
|
61786
|
+
`),
|
|
61787
|
+
suggestion: "Run: ck init",
|
|
61788
|
+
autoFixable: true,
|
|
61789
|
+
fix: {
|
|
61790
|
+
id: "fix-hook-deps",
|
|
61791
|
+
description: "Reinstall hooks via ck init",
|
|
61792
|
+
execute: async () => ({
|
|
61793
|
+
success: false,
|
|
61794
|
+
message: "Manual fix required: run 'ck init'"
|
|
61795
|
+
})
|
|
61796
|
+
}
|
|
61797
|
+
};
|
|
61798
|
+
}
|
|
61799
|
+
return {
|
|
61800
|
+
id: "hook-deps",
|
|
61801
|
+
name: "Hook Dependencies",
|
|
61802
|
+
group: "claudekit",
|
|
61803
|
+
priority: "critical",
|
|
61804
|
+
status: "pass",
|
|
61805
|
+
message: "All dependencies resolved",
|
|
61806
|
+
autoFixable: false
|
|
61807
|
+
};
|
|
61808
|
+
} catch (error) {
|
|
61809
|
+
logger.debug(`Hook deps check failed: ${error}`);
|
|
61810
|
+
return {
|
|
61811
|
+
id: "hook-deps",
|
|
61812
|
+
name: "Hook Dependencies",
|
|
61813
|
+
group: "claudekit",
|
|
61814
|
+
priority: "critical",
|
|
61815
|
+
status: "fail",
|
|
61816
|
+
message: "Failed to check dependencies",
|
|
61817
|
+
details: error instanceof Error ? error.message : String(error),
|
|
61818
|
+
autoFixable: false
|
|
61819
|
+
};
|
|
61820
|
+
}
|
|
61821
|
+
}
|
|
61822
|
+
function isNodeBuiltin(mod) {
|
|
61823
|
+
try {
|
|
61824
|
+
const { builtinModules } = __require("node:module");
|
|
61825
|
+
return builtinModules.includes(mod);
|
|
61826
|
+
} catch {
|
|
61827
|
+
const builtins = [
|
|
61828
|
+
"fs",
|
|
61829
|
+
"path",
|
|
61830
|
+
"os",
|
|
61831
|
+
"child_process",
|
|
61832
|
+
"util",
|
|
61833
|
+
"stream",
|
|
61834
|
+
"events",
|
|
61835
|
+
"crypto",
|
|
61836
|
+
"http",
|
|
61837
|
+
"https",
|
|
61838
|
+
"net",
|
|
61839
|
+
"dns",
|
|
61840
|
+
"url",
|
|
61841
|
+
"querystring",
|
|
61842
|
+
"readline",
|
|
61843
|
+
"process",
|
|
61844
|
+
"buffer",
|
|
61845
|
+
"console",
|
|
61846
|
+
"timers",
|
|
61847
|
+
"assert",
|
|
61848
|
+
"zlib",
|
|
61849
|
+
"worker_threads",
|
|
61850
|
+
"perf_hooks",
|
|
61851
|
+
"v8",
|
|
61852
|
+
"vm",
|
|
61853
|
+
"tls"
|
|
61854
|
+
];
|
|
61855
|
+
return builtins.includes(mod);
|
|
61856
|
+
}
|
|
61857
|
+
}
|
|
61858
|
+
async function checkHookRuntime(projectDir) {
|
|
61859
|
+
const hooksDir = getHooksDir(projectDir);
|
|
61860
|
+
if (!hooksDir) {
|
|
61861
|
+
return {
|
|
61862
|
+
id: "hook-runtime",
|
|
61863
|
+
name: "Hook Runtime",
|
|
61864
|
+
group: "claudekit",
|
|
61865
|
+
priority: "standard",
|
|
61866
|
+
status: "info",
|
|
61867
|
+
message: "No hooks directory",
|
|
61868
|
+
autoFixable: false
|
|
61869
|
+
};
|
|
61870
|
+
}
|
|
61871
|
+
try {
|
|
61872
|
+
const files = await readdir9(hooksDir);
|
|
61873
|
+
const cjsFiles = files.filter((f3) => f3.endsWith(".cjs"));
|
|
61874
|
+
if (cjsFiles.length === 0) {
|
|
61875
|
+
return {
|
|
61876
|
+
id: "hook-runtime",
|
|
61877
|
+
name: "Hook Runtime",
|
|
61878
|
+
group: "claudekit",
|
|
61879
|
+
priority: "standard",
|
|
61880
|
+
status: "info",
|
|
61881
|
+
message: "No .cjs hooks found",
|
|
61882
|
+
autoFixable: false
|
|
61883
|
+
};
|
|
61884
|
+
}
|
|
61885
|
+
const syntheticPayload = JSON.stringify({
|
|
61886
|
+
tool_name: "Read",
|
|
61887
|
+
tool_input: { file_path: join41(tmpdir(), "ck-doctor-test.txt") }
|
|
61888
|
+
});
|
|
61889
|
+
const failures = [];
|
|
61890
|
+
for (const file of cjsFiles) {
|
|
61891
|
+
const filePath = join41(hooksDir, file);
|
|
61892
|
+
if (!isPathWithin(filePath, hooksDir))
|
|
61893
|
+
continue;
|
|
61894
|
+
const result = spawnSync("node", [filePath], {
|
|
61895
|
+
input: syntheticPayload,
|
|
61896
|
+
timeout: HOOK_CHECK_TIMEOUT_MS,
|
|
61897
|
+
encoding: "utf-8"
|
|
61898
|
+
});
|
|
61899
|
+
if (result.status !== null && result.status !== 0 && result.status !== 2) {
|
|
61900
|
+
const error = result.error?.message || result.stderr?.trim() || `exit code ${result.status}`;
|
|
61901
|
+
failures.push(`${file}: ${error}`);
|
|
61902
|
+
} else if (result.status === null && result.error) {
|
|
61903
|
+
const error = result.error.message || "failed to execute";
|
|
61904
|
+
failures.push(`${file}: ${error}`);
|
|
61905
|
+
}
|
|
61906
|
+
}
|
|
61907
|
+
if (failures.length > 0) {
|
|
61908
|
+
return {
|
|
61909
|
+
id: "hook-runtime",
|
|
61910
|
+
name: "Hook Runtime",
|
|
61911
|
+
group: "claudekit",
|
|
61912
|
+
priority: "standard",
|
|
61913
|
+
status: "fail",
|
|
61914
|
+
message: `${failures.length} hook(s) failed dry-run`,
|
|
61915
|
+
details: failures.join(`
|
|
61916
|
+
`),
|
|
61917
|
+
suggestion: "Run: ck init",
|
|
61918
|
+
autoFixable: true,
|
|
61919
|
+
fix: {
|
|
61920
|
+
id: "fix-hook-runtime",
|
|
61921
|
+
description: "Reinstall hooks via ck init",
|
|
61922
|
+
execute: async () => ({
|
|
61923
|
+
success: false,
|
|
61924
|
+
message: "Manual fix required: run 'ck init'"
|
|
61925
|
+
})
|
|
61926
|
+
}
|
|
61927
|
+
};
|
|
61928
|
+
}
|
|
61929
|
+
return {
|
|
61930
|
+
id: "hook-runtime",
|
|
61931
|
+
name: "Hook Runtime",
|
|
61932
|
+
group: "claudekit",
|
|
61933
|
+
priority: "standard",
|
|
61934
|
+
status: "pass",
|
|
61935
|
+
message: `${cjsFiles.length} hook(s) passed dry-run`,
|
|
61936
|
+
autoFixable: false
|
|
61937
|
+
};
|
|
61938
|
+
} catch (error) {
|
|
61939
|
+
logger.debug(`Hook runtime check failed: ${error}`);
|
|
61940
|
+
return {
|
|
61941
|
+
id: "hook-runtime",
|
|
61942
|
+
name: "Hook Runtime",
|
|
61943
|
+
group: "claudekit",
|
|
61944
|
+
priority: "standard",
|
|
61945
|
+
status: "fail",
|
|
61946
|
+
message: "Failed to check hook runtime",
|
|
61947
|
+
details: error instanceof Error ? error.message : String(error),
|
|
61948
|
+
autoFixable: false
|
|
61949
|
+
};
|
|
61950
|
+
}
|
|
61951
|
+
}
|
|
61952
|
+
async function checkHookConfig(projectDir) {
|
|
61953
|
+
const projectConfigPath = join41(projectDir, ".claude", ".ck.json");
|
|
61954
|
+
const globalConfigPath = join41(PathResolver.getGlobalKitDir(), ".ck.json");
|
|
61955
|
+
const configPath = existsSync30(projectConfigPath) ? projectConfigPath : existsSync30(globalConfigPath) ? globalConfigPath : null;
|
|
61956
|
+
if (!configPath) {
|
|
61957
|
+
return {
|
|
61958
|
+
id: "hook-config",
|
|
61959
|
+
name: "Hook Config",
|
|
61960
|
+
group: "claudekit",
|
|
61961
|
+
priority: "standard",
|
|
61962
|
+
status: "info",
|
|
61963
|
+
message: "No .ck.json config",
|
|
61964
|
+
autoFixable: false
|
|
61965
|
+
};
|
|
61966
|
+
}
|
|
61967
|
+
const hooksDir = getHooksDir(projectDir);
|
|
61968
|
+
if (!hooksDir) {
|
|
61969
|
+
return {
|
|
61970
|
+
id: "hook-config",
|
|
61971
|
+
name: "Hook Config",
|
|
61972
|
+
group: "claudekit",
|
|
61973
|
+
priority: "standard",
|
|
61974
|
+
status: "info",
|
|
61975
|
+
message: "No hooks directory",
|
|
61976
|
+
autoFixable: false
|
|
61977
|
+
};
|
|
61978
|
+
}
|
|
61979
|
+
try {
|
|
61980
|
+
const configContent = readFileSync6(configPath, "utf-8");
|
|
61981
|
+
const config = JSON.parse(configContent);
|
|
61982
|
+
if (!config.hooks || typeof config.hooks !== "object") {
|
|
61983
|
+
return {
|
|
61984
|
+
id: "hook-config",
|
|
61985
|
+
name: "Hook Config",
|
|
61986
|
+
group: "claudekit",
|
|
61987
|
+
priority: "standard",
|
|
61988
|
+
status: "pass",
|
|
61989
|
+
message: "No hooks configured",
|
|
61990
|
+
autoFixable: false
|
|
61991
|
+
};
|
|
61992
|
+
}
|
|
61993
|
+
const files = await readdir9(hooksDir);
|
|
61994
|
+
const hookBaseNames = new Set(files.filter((f3) => HOOK_EXTENSIONS.some((ext) => f3.endsWith(ext))).map((f3) => {
|
|
61995
|
+
for (const ext of HOOK_EXTENSIONS) {
|
|
61996
|
+
if (f3.endsWith(ext))
|
|
61997
|
+
return f3.slice(0, -ext.length);
|
|
61998
|
+
}
|
|
61999
|
+
return f3;
|
|
62000
|
+
}));
|
|
62001
|
+
const orphanedEntries = [];
|
|
62002
|
+
for (const hookName of Object.keys(config.hooks)) {
|
|
62003
|
+
if (!hookBaseNames.has(hookName)) {
|
|
62004
|
+
orphanedEntries.push(hookName);
|
|
62005
|
+
}
|
|
62006
|
+
}
|
|
62007
|
+
if (orphanedEntries.length > 0) {
|
|
62008
|
+
return {
|
|
62009
|
+
id: "hook-config",
|
|
62010
|
+
name: "Hook Config",
|
|
62011
|
+
group: "claudekit",
|
|
62012
|
+
priority: "standard",
|
|
62013
|
+
status: "warn",
|
|
62014
|
+
message: `${orphanedEntries.length} orphaned config entry(ies)`,
|
|
62015
|
+
details: orphanedEntries.join(", "),
|
|
62016
|
+
suggestion: "Remove orphaned entries from .ck.json",
|
|
62017
|
+
autoFixable: true,
|
|
62018
|
+
fix: {
|
|
62019
|
+
id: "fix-hook-config",
|
|
62020
|
+
description: "Remove orphaned entries from .ck.json",
|
|
62021
|
+
execute: async () => {
|
|
62022
|
+
try {
|
|
62023
|
+
for (const entry of orphanedEntries) {
|
|
62024
|
+
delete config.hooks[entry];
|
|
62025
|
+
}
|
|
62026
|
+
const updatedConfig = JSON.stringify(config, null, 2);
|
|
62027
|
+
writeFileSync(configPath, updatedConfig, "utf-8");
|
|
62028
|
+
return {
|
|
62029
|
+
success: true,
|
|
62030
|
+
message: `Removed ${orphanedEntries.length} orphaned entry(ies)`
|
|
62031
|
+
};
|
|
62032
|
+
} catch (err) {
|
|
62033
|
+
return {
|
|
62034
|
+
success: false,
|
|
62035
|
+
message: `Failed to update .ck.json: ${err}`
|
|
62036
|
+
};
|
|
62037
|
+
}
|
|
62038
|
+
}
|
|
62039
|
+
}
|
|
62040
|
+
};
|
|
62041
|
+
}
|
|
62042
|
+
return {
|
|
62043
|
+
id: "hook-config",
|
|
62044
|
+
name: "Hook Config",
|
|
62045
|
+
group: "claudekit",
|
|
62046
|
+
priority: "standard",
|
|
62047
|
+
status: "pass",
|
|
62048
|
+
message: "All config entries valid",
|
|
62049
|
+
autoFixable: false
|
|
62050
|
+
};
|
|
62051
|
+
} catch (error) {
|
|
62052
|
+
logger.debug(`Hook config check failed: ${error}`);
|
|
62053
|
+
return {
|
|
62054
|
+
id: "hook-config",
|
|
62055
|
+
name: "Hook Config",
|
|
62056
|
+
group: "claudekit",
|
|
62057
|
+
priority: "standard",
|
|
62058
|
+
status: "fail",
|
|
62059
|
+
message: "Failed to validate config",
|
|
62060
|
+
details: error instanceof Error ? error.message : String(error),
|
|
62061
|
+
autoFixable: false
|
|
62062
|
+
};
|
|
62063
|
+
}
|
|
62064
|
+
}
|
|
62065
|
+
async function checkHookLogs(projectDir) {
|
|
62066
|
+
const hooksDir = getHooksDir(projectDir);
|
|
62067
|
+
if (!hooksDir) {
|
|
62068
|
+
return {
|
|
62069
|
+
id: "hook-logs",
|
|
62070
|
+
name: "Hook Crash Logs",
|
|
62071
|
+
group: "claudekit",
|
|
62072
|
+
priority: "standard",
|
|
62073
|
+
status: "info",
|
|
62074
|
+
message: "No hooks directory",
|
|
62075
|
+
autoFixable: false
|
|
62076
|
+
};
|
|
62077
|
+
}
|
|
62078
|
+
const logPath = join41(hooksDir, ".logs", "hook-log.jsonl");
|
|
62079
|
+
if (!existsSync30(logPath)) {
|
|
62080
|
+
return {
|
|
62081
|
+
id: "hook-logs",
|
|
62082
|
+
name: "Hook Crash Logs",
|
|
62083
|
+
group: "claudekit",
|
|
62084
|
+
priority: "standard",
|
|
62085
|
+
status: "pass",
|
|
62086
|
+
message: "No crash logs",
|
|
62087
|
+
autoFixable: false
|
|
62088
|
+
};
|
|
62089
|
+
}
|
|
62090
|
+
try {
|
|
62091
|
+
const logStats = statSync5(logPath);
|
|
62092
|
+
if (logStats.size > MAX_LOG_FILE_SIZE_BYTES) {
|
|
62093
|
+
return {
|
|
62094
|
+
id: "hook-logs",
|
|
62095
|
+
name: "Hook Crash Logs",
|
|
62096
|
+
group: "claudekit",
|
|
62097
|
+
priority: "standard",
|
|
62098
|
+
status: "warn",
|
|
62099
|
+
message: `Log file too large (${Math.round(logStats.size / 1024 / 1024)}MB)`,
|
|
62100
|
+
suggestion: "Delete .claude/hooks/.logs/hook-log.jsonl and run: ck init",
|
|
62101
|
+
autoFixable: true,
|
|
62102
|
+
fix: {
|
|
62103
|
+
id: "fix-hook-logs",
|
|
62104
|
+
description: "Clear oversized log file",
|
|
62105
|
+
execute: async () => {
|
|
62106
|
+
try {
|
|
62107
|
+
writeFileSync(logPath, "", "utf-8");
|
|
62108
|
+
return { success: true, message: "Cleared oversized log file" };
|
|
62109
|
+
} catch (err) {
|
|
62110
|
+
return { success: false, message: `Failed to clear log: ${err}` };
|
|
62111
|
+
}
|
|
62112
|
+
}
|
|
62113
|
+
}
|
|
62114
|
+
};
|
|
62115
|
+
}
|
|
62116
|
+
const logContent = readFileSync6(logPath, "utf-8");
|
|
62117
|
+
const lines = logContent.trim().split(`
|
|
62118
|
+
`).filter(Boolean);
|
|
62119
|
+
const now = Date.now();
|
|
62120
|
+
const oneDayAgo = now - 24 * 60 * 60 * 1000;
|
|
62121
|
+
const crashes = [];
|
|
62122
|
+
for (const line of lines) {
|
|
62123
|
+
try {
|
|
62124
|
+
const entry = JSON.parse(line);
|
|
62125
|
+
const timestamp = new Date(entry.ts || entry.timestamp).getTime();
|
|
62126
|
+
if (timestamp >= oneDayAgo && entry.status === "crash") {
|
|
62127
|
+
crashes.push({
|
|
62128
|
+
hook: entry.hook || "unknown",
|
|
62129
|
+
error: entry.error || "unknown error"
|
|
62130
|
+
});
|
|
62131
|
+
}
|
|
62132
|
+
} catch {}
|
|
62133
|
+
}
|
|
62134
|
+
if (crashes.length === 0) {
|
|
62135
|
+
return {
|
|
62136
|
+
id: "hook-logs",
|
|
62137
|
+
name: "Hook Crash Logs",
|
|
62138
|
+
group: "claudekit",
|
|
62139
|
+
priority: "standard",
|
|
62140
|
+
status: "pass",
|
|
62141
|
+
message: "No crashes in last 24h",
|
|
62142
|
+
autoFixable: false
|
|
62143
|
+
};
|
|
62144
|
+
}
|
|
62145
|
+
if (crashes.length <= 5) {
|
|
62146
|
+
const hookList = crashes.map((c2) => `${c2.hook}: ${c2.error}`).join(`
|
|
62147
|
+
`);
|
|
62148
|
+
return {
|
|
62149
|
+
id: "hook-logs",
|
|
62150
|
+
name: "Hook Crash Logs",
|
|
62151
|
+
group: "claudekit",
|
|
62152
|
+
priority: "standard",
|
|
62153
|
+
status: "warn",
|
|
62154
|
+
message: `${crashes.length} crash(es) in last 24h`,
|
|
62155
|
+
details: hookList,
|
|
62156
|
+
suggestion: "Run: ck init",
|
|
62157
|
+
autoFixable: true,
|
|
62158
|
+
fix: {
|
|
62159
|
+
id: "fix-hook-logs",
|
|
62160
|
+
description: "Clear log file",
|
|
62161
|
+
execute: async () => {
|
|
62162
|
+
try {
|
|
62163
|
+
writeFileSync(logPath, "", "utf-8");
|
|
62164
|
+
return {
|
|
62165
|
+
success: true,
|
|
62166
|
+
message: "Cleared crash log file"
|
|
62167
|
+
};
|
|
62168
|
+
} catch (err) {
|
|
62169
|
+
return {
|
|
62170
|
+
success: false,
|
|
62171
|
+
message: `Failed to clear log: ${err}`
|
|
62172
|
+
};
|
|
62173
|
+
}
|
|
62174
|
+
}
|
|
62175
|
+
}
|
|
62176
|
+
};
|
|
62177
|
+
}
|
|
62178
|
+
const hookCounts = crashes.reduce((acc, c2) => {
|
|
62179
|
+
acc[c2.hook] = (acc[c2.hook] || 0) + 1;
|
|
62180
|
+
return acc;
|
|
62181
|
+
}, {});
|
|
62182
|
+
const topCrashers = Object.entries(hookCounts).sort((a3, b3) => b3[1] - a3[1]).slice(0, 5).map(([hook, count]) => `${hook} (${count}x)`).join(", ");
|
|
62183
|
+
return {
|
|
62184
|
+
id: "hook-logs",
|
|
62185
|
+
name: "Hook Crash Logs",
|
|
62186
|
+
group: "claudekit",
|
|
62187
|
+
priority: "standard",
|
|
62188
|
+
status: "fail",
|
|
62189
|
+
message: `${crashes.length} crashes in last 24h`,
|
|
62190
|
+
details: `Most frequent: ${topCrashers}`,
|
|
62191
|
+
suggestion: "Run: ck init",
|
|
62192
|
+
autoFixable: true,
|
|
62193
|
+
fix: {
|
|
62194
|
+
id: "fix-hook-logs",
|
|
62195
|
+
description: "Clear log file and suggest reinstall",
|
|
62196
|
+
execute: async () => {
|
|
62197
|
+
try {
|
|
62198
|
+
writeFileSync(logPath, "", "utf-8");
|
|
62199
|
+
return {
|
|
62200
|
+
success: true,
|
|
62201
|
+
message: "Cleared crash log. Run 'ck init' to reinstall hooks."
|
|
62202
|
+
};
|
|
62203
|
+
} catch (err) {
|
|
62204
|
+
return {
|
|
62205
|
+
success: false,
|
|
62206
|
+
message: `Failed to clear log: ${err}`
|
|
62207
|
+
};
|
|
62208
|
+
}
|
|
62209
|
+
}
|
|
62210
|
+
}
|
|
62211
|
+
};
|
|
62212
|
+
} catch (error) {
|
|
62213
|
+
logger.debug(`Hook logs check failed: ${error}`);
|
|
62214
|
+
return {
|
|
62215
|
+
id: "hook-logs",
|
|
62216
|
+
name: "Hook Crash Logs",
|
|
62217
|
+
group: "claudekit",
|
|
62218
|
+
priority: "standard",
|
|
62219
|
+
status: "fail",
|
|
62220
|
+
message: "Failed to check crash logs",
|
|
62221
|
+
details: error instanceof Error ? error.message : String(error),
|
|
62222
|
+
autoFixable: false
|
|
62223
|
+
};
|
|
62224
|
+
}
|
|
62225
|
+
}
|
|
62226
|
+
async function checkCliVersion() {
|
|
62227
|
+
try {
|
|
62228
|
+
const versionResult = spawnSync("ck", ["-V"], {
|
|
62229
|
+
timeout: HOOK_CHECK_TIMEOUT_MS,
|
|
62230
|
+
encoding: "utf-8"
|
|
62231
|
+
});
|
|
62232
|
+
let installedVersion = "unknown";
|
|
62233
|
+
if (versionResult.status === 0 && versionResult.stdout) {
|
|
62234
|
+
installedVersion = versionResult.stdout.trim();
|
|
62235
|
+
}
|
|
62236
|
+
if (installedVersion === "unknown") {
|
|
62237
|
+
return {
|
|
62238
|
+
id: "cli-version",
|
|
62239
|
+
name: "CLI Version",
|
|
62240
|
+
group: "claudekit",
|
|
62241
|
+
priority: "critical",
|
|
62242
|
+
status: "warn",
|
|
62243
|
+
message: "Cannot determine installed version",
|
|
62244
|
+
autoFixable: false
|
|
62245
|
+
};
|
|
62246
|
+
}
|
|
62247
|
+
const npmResult = spawnSync("npm", ["view", "claudekit-cli", "version"], {
|
|
62248
|
+
timeout: HOOK_CHECK_TIMEOUT_MS,
|
|
62249
|
+
encoding: "utf-8"
|
|
62250
|
+
});
|
|
62251
|
+
if (npmResult.status !== 0) {
|
|
62252
|
+
return {
|
|
62253
|
+
id: "cli-version",
|
|
62254
|
+
name: "CLI Version",
|
|
62255
|
+
group: "claudekit",
|
|
62256
|
+
priority: "critical",
|
|
62257
|
+
status: "warn",
|
|
62258
|
+
message: `v${installedVersion} (unable to check for updates)`,
|
|
62259
|
+
autoFixable: false
|
|
62260
|
+
};
|
|
62261
|
+
}
|
|
62262
|
+
const latestVersion = npmResult.stdout?.trim() || installedVersion;
|
|
62263
|
+
const parseVersion = (v2) => v2.replace(/-.*$/, "").split(".").map(Number);
|
|
62264
|
+
const [installedMajor, installedMinor] = parseVersion(installedVersion);
|
|
62265
|
+
const [latestMajor, latestMinor] = parseVersion(latestVersion);
|
|
62266
|
+
if (installedMajor < latestMajor) {
|
|
62267
|
+
return {
|
|
62268
|
+
id: "cli-version",
|
|
62269
|
+
name: "CLI Version",
|
|
62270
|
+
group: "claudekit",
|
|
62271
|
+
priority: "critical",
|
|
62272
|
+
status: "fail",
|
|
62273
|
+
message: `v${installedVersion} (latest: v${latestVersion})`,
|
|
62274
|
+
details: "Major version behind",
|
|
62275
|
+
suggestion: "Run: ck update",
|
|
62276
|
+
autoFixable: true,
|
|
62277
|
+
fix: {
|
|
62278
|
+
id: "fix-cli-version",
|
|
62279
|
+
description: "Update CLI to latest version",
|
|
62280
|
+
execute: async () => ({
|
|
62281
|
+
success: false,
|
|
62282
|
+
message: "Manual fix required: run 'ck update'"
|
|
62283
|
+
})
|
|
62284
|
+
}
|
|
62285
|
+
};
|
|
62286
|
+
}
|
|
62287
|
+
if (installedMajor === latestMajor && installedMinor < latestMinor) {
|
|
62288
|
+
return {
|
|
62289
|
+
id: "cli-version",
|
|
62290
|
+
name: "CLI Version",
|
|
62291
|
+
group: "claudekit",
|
|
62292
|
+
priority: "critical",
|
|
62293
|
+
status: "warn",
|
|
62294
|
+
message: `v${installedVersion} (latest: v${latestVersion})`,
|
|
62295
|
+
details: "Minor version behind",
|
|
62296
|
+
suggestion: "Run: ck update",
|
|
62297
|
+
autoFixable: true,
|
|
62298
|
+
fix: {
|
|
62299
|
+
id: "fix-cli-version",
|
|
62300
|
+
description: "Update CLI to latest version",
|
|
62301
|
+
execute: async () => ({
|
|
62302
|
+
success: false,
|
|
62303
|
+
message: "Manual fix required: run 'ck update'"
|
|
62304
|
+
})
|
|
62305
|
+
}
|
|
62306
|
+
};
|
|
62307
|
+
}
|
|
62308
|
+
return {
|
|
62309
|
+
id: "cli-version",
|
|
62310
|
+
name: "CLI Version",
|
|
62311
|
+
group: "claudekit",
|
|
62312
|
+
priority: "critical",
|
|
62313
|
+
status: "pass",
|
|
62314
|
+
message: `v${installedVersion} (up to date)`,
|
|
62315
|
+
autoFixable: false
|
|
62316
|
+
};
|
|
62317
|
+
} catch (error) {
|
|
62318
|
+
logger.debug(`CLI version check failed: ${error}`);
|
|
62319
|
+
return {
|
|
62320
|
+
id: "cli-version",
|
|
62321
|
+
name: "CLI Version",
|
|
62322
|
+
group: "claudekit",
|
|
62323
|
+
priority: "critical",
|
|
62324
|
+
status: "warn",
|
|
62325
|
+
message: "Failed to check version",
|
|
62326
|
+
details: error instanceof Error ? error.message : String(error),
|
|
62327
|
+
autoFixable: false
|
|
62328
|
+
};
|
|
62329
|
+
}
|
|
62330
|
+
}
|
|
62331
|
+
async function checkPythonVenv(projectDir) {
|
|
62332
|
+
const isWindows3 = process.platform === "win32";
|
|
62333
|
+
const venvBin = isWindows3 ? join41("Scripts", "python.exe") : join41("bin", "python3");
|
|
62334
|
+
const projectVenvPath = join41(projectDir, ".claude", "skills", ".venv", venvBin);
|
|
62335
|
+
const globalVenvPath = join41(PathResolver.getGlobalKitDir(), "skills", ".venv", venvBin);
|
|
62336
|
+
const venvPath = existsSync30(projectVenvPath) ? projectVenvPath : existsSync30(globalVenvPath) ? globalVenvPath : null;
|
|
62337
|
+
if (!venvPath) {
|
|
62338
|
+
return {
|
|
62339
|
+
id: "python-venv",
|
|
62340
|
+
name: "Python Venv",
|
|
62341
|
+
group: "claudekit",
|
|
62342
|
+
priority: "standard",
|
|
62343
|
+
status: "warn",
|
|
62344
|
+
message: "Virtual environment not found",
|
|
62345
|
+
suggestion: "Delete .venv and run install.sh",
|
|
62346
|
+
autoFixable: true,
|
|
62347
|
+
fix: {
|
|
62348
|
+
id: "fix-python-venv",
|
|
62349
|
+
description: "Delete .venv and suggest reinstall",
|
|
62350
|
+
execute: async () => ({
|
|
62351
|
+
success: false,
|
|
62352
|
+
message: "Manual fix required: delete .venv and run install.sh"
|
|
62353
|
+
})
|
|
62354
|
+
}
|
|
62355
|
+
};
|
|
62356
|
+
}
|
|
62357
|
+
try {
|
|
62358
|
+
const result = spawnSync(venvPath, ["--version"], {
|
|
62359
|
+
timeout: PYTHON_CHECK_TIMEOUT_MS,
|
|
62360
|
+
encoding: "utf-8"
|
|
62361
|
+
});
|
|
62362
|
+
if (result.status !== 0) {
|
|
62363
|
+
return {
|
|
62364
|
+
id: "python-venv",
|
|
62365
|
+
name: "Python Venv",
|
|
62366
|
+
group: "claudekit",
|
|
62367
|
+
priority: "standard",
|
|
62368
|
+
status: "fail",
|
|
62369
|
+
message: "Python venv exists but broken",
|
|
62370
|
+
details: result.stderr?.trim() || "Failed to run python3 --version",
|
|
62371
|
+
suggestion: "Delete .venv and run install.sh",
|
|
62372
|
+
autoFixable: true,
|
|
62373
|
+
fix: {
|
|
62374
|
+
id: "fix-python-venv",
|
|
62375
|
+
description: "Delete .venv",
|
|
62376
|
+
execute: async () => ({
|
|
62377
|
+
success: false,
|
|
62378
|
+
message: "Manual fix required: delete .venv and run install.sh"
|
|
62379
|
+
})
|
|
62380
|
+
}
|
|
62381
|
+
};
|
|
62382
|
+
}
|
|
62383
|
+
const version = result.stdout?.trim() || "unknown";
|
|
62384
|
+
return {
|
|
62385
|
+
id: "python-venv",
|
|
62386
|
+
name: "Python Venv",
|
|
62387
|
+
group: "claudekit",
|
|
62388
|
+
priority: "standard",
|
|
62389
|
+
status: "pass",
|
|
62390
|
+
message: version,
|
|
62391
|
+
autoFixable: false
|
|
62392
|
+
};
|
|
62393
|
+
} catch (error) {
|
|
62394
|
+
logger.debug(`Python venv check failed: ${error}`);
|
|
62395
|
+
return {
|
|
62396
|
+
id: "python-venv",
|
|
62397
|
+
name: "Python Venv",
|
|
62398
|
+
group: "claudekit",
|
|
62399
|
+
priority: "standard",
|
|
62400
|
+
status: "fail",
|
|
62401
|
+
message: "Failed to check venv",
|
|
62402
|
+
details: error instanceof Error ? error.message : String(error),
|
|
62403
|
+
autoFixable: false
|
|
62404
|
+
};
|
|
62405
|
+
}
|
|
62406
|
+
}
|
|
61575
62407
|
// src/domains/health-checks/claudekit-checker.ts
|
|
61576
62408
|
class ClaudekitChecker {
|
|
61577
62409
|
group = "claudekit";
|
|
@@ -61586,6 +62418,8 @@ class ClaudekitChecker {
|
|
|
61586
62418
|
const setup = await getClaudeKitSetup(this.projectDir);
|
|
61587
62419
|
logger.verbose("ClaudekitChecker: Setup scan complete");
|
|
61588
62420
|
const results = [];
|
|
62421
|
+
logger.verbose("ClaudekitChecker: Checking CLI version");
|
|
62422
|
+
results.push(await checkCliVersion());
|
|
61589
62423
|
logger.verbose("ClaudekitChecker: Checking CLI install method");
|
|
61590
62424
|
results.push(await checkCliInstallMethod());
|
|
61591
62425
|
logger.verbose("ClaudekitChecker: Checking global install");
|
|
@@ -61608,6 +62442,18 @@ class ClaudekitChecker {
|
|
|
61608
62442
|
results.push(await checkGlobalDirWritable());
|
|
61609
62443
|
logger.verbose("ClaudekitChecker: Checking hooks directory");
|
|
61610
62444
|
results.push(await checkHooksExist(this.projectDir));
|
|
62445
|
+
logger.verbose("ClaudekitChecker: Checking hook syntax");
|
|
62446
|
+
results.push(await checkHookSyntax(this.projectDir));
|
|
62447
|
+
logger.verbose("ClaudekitChecker: Checking hook dependencies");
|
|
62448
|
+
results.push(await checkHookDeps(this.projectDir));
|
|
62449
|
+
logger.verbose("ClaudekitChecker: Checking hook runtime");
|
|
62450
|
+
results.push(await checkHookRuntime(this.projectDir));
|
|
62451
|
+
logger.verbose("ClaudekitChecker: Checking hook config");
|
|
62452
|
+
results.push(await checkHookConfig(this.projectDir));
|
|
62453
|
+
logger.verbose("ClaudekitChecker: Checking hook crash logs");
|
|
62454
|
+
results.push(await checkHookLogs(this.projectDir));
|
|
62455
|
+
logger.verbose("ClaudekitChecker: Checking Python venv");
|
|
62456
|
+
results.push(await checkPythonVenv(this.projectDir));
|
|
61611
62457
|
logger.verbose("ClaudekitChecker: Checking settings.json validity");
|
|
61612
62458
|
results.push(await checkSettingsValid(this.projectDir));
|
|
61613
62459
|
logger.verbose("ClaudekitChecker: Checking path references");
|
|
@@ -61620,7 +62466,7 @@ class ClaudekitChecker {
|
|
|
61620
62466
|
}
|
|
61621
62467
|
// src/domains/health-checks/auth-checker.ts
|
|
61622
62468
|
init_github_auth();
|
|
61623
|
-
import { spawnSync as
|
|
62469
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
61624
62470
|
|
|
61625
62471
|
// src/domains/installation/git-clone-manager.ts
|
|
61626
62472
|
init_logger();
|
|
@@ -61887,7 +62733,7 @@ class AuthChecker {
|
|
|
61887
62733
|
if (false) {}
|
|
61888
62734
|
try {
|
|
61889
62735
|
logger.verbose("AuthChecker: Running 'gh auth status -h github.com' command");
|
|
61890
|
-
const result =
|
|
62736
|
+
const result = spawnSync3("gh", ["auth", "status", "-h", "github.com"], {
|
|
61891
62737
|
encoding: "utf8",
|
|
61892
62738
|
timeout: COMMAND_TIMEOUT_MS2
|
|
61893
62739
|
});
|
|
@@ -61966,7 +62812,7 @@ import { platform as platform6 } from "node:os";
|
|
|
61966
62812
|
init_path_resolver();
|
|
61967
62813
|
import { constants as constants3, access as access3, mkdir as mkdir9, readFile as readFile23, unlink as unlink5, writeFile as writeFile12 } from "node:fs/promises";
|
|
61968
62814
|
import { arch as arch2, homedir as homedir16, platform as platform5 } from "node:os";
|
|
61969
|
-
import { join as
|
|
62815
|
+
import { join as join43, normalize as normalize6 } from "node:path";
|
|
61970
62816
|
var IS_WINDOWS = platform5() === "win32";
|
|
61971
62817
|
function shouldSkipExpensiveOperations4() {
|
|
61972
62818
|
if (process.env.CK_TEST_HOME) {
|
|
@@ -62060,7 +62906,7 @@ async function checkGlobalDirAccess() {
|
|
|
62060
62906
|
autoFixable: false
|
|
62061
62907
|
};
|
|
62062
62908
|
}
|
|
62063
|
-
const testFile =
|
|
62909
|
+
const testFile = join43(globalDir, ".ck-doctor-access-test");
|
|
62064
62910
|
try {
|
|
62065
62911
|
await mkdir9(globalDir, { recursive: true });
|
|
62066
62912
|
await writeFile12(testFile, "test", "utf-8");
|
|
@@ -62138,7 +62984,7 @@ async function checkWSLBoundary() {
|
|
|
62138
62984
|
// src/domains/health-checks/platform/windows-checker.ts
|
|
62139
62985
|
init_path_resolver();
|
|
62140
62986
|
import { mkdir as mkdir10, symlink, unlink as unlink6, writeFile as writeFile13 } from "node:fs/promises";
|
|
62141
|
-
import { join as
|
|
62987
|
+
import { join as join44 } from "node:path";
|
|
62142
62988
|
async function checkLongPathSupport() {
|
|
62143
62989
|
if (shouldSkipExpensiveOperations4()) {
|
|
62144
62990
|
return {
|
|
@@ -62190,8 +63036,8 @@ async function checkSymlinkSupport() {
|
|
|
62190
63036
|
};
|
|
62191
63037
|
}
|
|
62192
63038
|
const testDir = PathResolver.getGlobalKitDir();
|
|
62193
|
-
const target =
|
|
62194
|
-
const link =
|
|
63039
|
+
const target = join44(testDir, ".ck-symlink-test-target");
|
|
63040
|
+
const link = join44(testDir, ".ck-symlink-test-link");
|
|
62195
63041
|
try {
|
|
62196
63042
|
await mkdir10(testDir, { recursive: true });
|
|
62197
63043
|
await writeFile13(target, "test", "utf-8");
|
|
@@ -62474,10 +63320,10 @@ class AutoHealer {
|
|
|
62474
63320
|
}
|
|
62475
63321
|
}
|
|
62476
63322
|
// src/domains/health-checks/report-generator.ts
|
|
62477
|
-
import { execSync as execSync3, spawnSync as
|
|
62478
|
-
import { readFileSync as
|
|
62479
|
-
import { tmpdir as
|
|
62480
|
-
import { dirname as dirname10, join as
|
|
63323
|
+
import { execSync as execSync3, spawnSync as spawnSync4 } from "node:child_process";
|
|
63324
|
+
import { readFileSync as readFileSync7, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
63325
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
63326
|
+
import { dirname as dirname10, join as join45 } from "node:path";
|
|
62481
63327
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
62482
63328
|
init_environment();
|
|
62483
63329
|
init_logger();
|
|
@@ -62485,8 +63331,8 @@ init_dist2();
|
|
|
62485
63331
|
function getCliVersion2() {
|
|
62486
63332
|
try {
|
|
62487
63333
|
const __dirname4 = dirname10(fileURLToPath3(import.meta.url));
|
|
62488
|
-
const pkgPath =
|
|
62489
|
-
const pkg = JSON.parse(
|
|
63334
|
+
const pkgPath = join45(__dirname4, "../../../package.json");
|
|
63335
|
+
const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
62490
63336
|
return pkg.version || "unknown";
|
|
62491
63337
|
} catch (err) {
|
|
62492
63338
|
logger.debug(`Failed to read CLI version: ${err}`);
|
|
@@ -62624,10 +63470,10 @@ class ReportGenerator {
|
|
|
62624
63470
|
return null;
|
|
62625
63471
|
}
|
|
62626
63472
|
}
|
|
62627
|
-
const tmpFile =
|
|
62628
|
-
|
|
63473
|
+
const tmpFile = join45(tmpdir3(), `ck-report-${Date.now()}.txt`);
|
|
63474
|
+
writeFileSync2(tmpFile, report);
|
|
62629
63475
|
try {
|
|
62630
|
-
const result =
|
|
63476
|
+
const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "ClaudeKit Diagnostic Report"], {
|
|
62631
63477
|
encoding: "utf-8"
|
|
62632
63478
|
});
|
|
62633
63479
|
if (result.status !== 0) {
|
|
@@ -62949,7 +63795,7 @@ init_logger();
|
|
|
62949
63795
|
init_path_resolver();
|
|
62950
63796
|
var import_compare_versions5 = __toESM(require_umd(), 1);
|
|
62951
63797
|
import { mkdir as mkdir11, readFile as readFile24, unlink as unlink7, writeFile as writeFile14 } from "node:fs/promises";
|
|
62952
|
-
import { join as
|
|
63798
|
+
import { join as join46 } from "node:path";
|
|
62953
63799
|
var CACHE_TTL_HOURS = 24;
|
|
62954
63800
|
var DEFAULT_CACHE_TTL_MS = CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
62955
63801
|
var MIN_CACHE_TTL_MS = 60 * 1000;
|
|
@@ -62986,7 +63832,7 @@ var KIT_REPOS = {
|
|
|
62986
63832
|
class ConfigVersionChecker {
|
|
62987
63833
|
static getCacheFilePath(kitType, global3) {
|
|
62988
63834
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
62989
|
-
return
|
|
63835
|
+
return join46(cacheDir, `${kitType}-${CACHE_FILENAME}`);
|
|
62990
63836
|
}
|
|
62991
63837
|
static async loadCache(kitType, global3) {
|
|
62992
63838
|
try {
|
|
@@ -63073,7 +63919,7 @@ class ConfigVersionChecker {
|
|
|
63073
63919
|
return null;
|
|
63074
63920
|
}
|
|
63075
63921
|
const delay = baseBackoff * 2 ** attempt;
|
|
63076
|
-
await new Promise((
|
|
63922
|
+
await new Promise((resolve9) => setTimeout(resolve9, delay));
|
|
63077
63923
|
}
|
|
63078
63924
|
}
|
|
63079
63925
|
return null;
|
|
@@ -63149,7 +63995,7 @@ class ConfigVersionChecker {
|
|
|
63149
63995
|
}
|
|
63150
63996
|
// src/domains/sync/sync-engine.ts
|
|
63151
63997
|
import { lstat as lstat3, readFile as readFile25, readlink, realpath as realpath2, stat as stat9 } from "node:fs/promises";
|
|
63152
|
-
import { isAbsolute as isAbsolute2, join as
|
|
63998
|
+
import { isAbsolute as isAbsolute2, join as join47, normalize as normalize7, relative as relative4 } from "node:path";
|
|
63153
63999
|
|
|
63154
64000
|
// src/services/file-operations/ownership-checker.ts
|
|
63155
64001
|
init_metadata_migration();
|
|
@@ -63240,24 +64086,24 @@ function pLimit(concurrency) {
|
|
|
63240
64086
|
activeCount--;
|
|
63241
64087
|
resumeNext();
|
|
63242
64088
|
};
|
|
63243
|
-
const run = async (function_,
|
|
64089
|
+
const run = async (function_, resolve9, arguments_) => {
|
|
63244
64090
|
const result = (async () => function_(...arguments_))();
|
|
63245
|
-
|
|
64091
|
+
resolve9(result);
|
|
63246
64092
|
try {
|
|
63247
64093
|
await result;
|
|
63248
64094
|
} catch {}
|
|
63249
64095
|
next();
|
|
63250
64096
|
};
|
|
63251
|
-
const enqueue = (function_,
|
|
64097
|
+
const enqueue = (function_, resolve9, arguments_) => {
|
|
63252
64098
|
new Promise((internalResolve) => {
|
|
63253
64099
|
queue.enqueue(internalResolve);
|
|
63254
|
-
}).then(run.bind(undefined, function_,
|
|
64100
|
+
}).then(run.bind(undefined, function_, resolve9, arguments_));
|
|
63255
64101
|
if (activeCount < concurrency) {
|
|
63256
64102
|
resumeNext();
|
|
63257
64103
|
}
|
|
63258
64104
|
};
|
|
63259
|
-
const generator = (function_, ...arguments_) => new Promise((
|
|
63260
|
-
enqueue(function_,
|
|
64105
|
+
const generator = (function_, ...arguments_) => new Promise((resolve9) => {
|
|
64106
|
+
enqueue(function_, resolve9, arguments_);
|
|
63261
64107
|
});
|
|
63262
64108
|
Object.defineProperties(generator, {
|
|
63263
64109
|
activeCount: {
|
|
@@ -63308,12 +64154,12 @@ async function mapWithLimit(items, fn, concurrency = DEFAULT_CONCURRENCY) {
|
|
|
63308
64154
|
// src/services/file-operations/ownership-checker.ts
|
|
63309
64155
|
class OwnershipChecker {
|
|
63310
64156
|
static async calculateChecksum(filePath) {
|
|
63311
|
-
return new Promise((
|
|
64157
|
+
return new Promise((resolve9, reject) => {
|
|
63312
64158
|
const hash = createHash("sha256");
|
|
63313
64159
|
const stream = createReadStream2(filePath);
|
|
63314
64160
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
63315
64161
|
stream.on("end", () => {
|
|
63316
|
-
|
|
64162
|
+
resolve9(hash.digest("hex"));
|
|
63317
64163
|
});
|
|
63318
64164
|
stream.on("error", (err) => {
|
|
63319
64165
|
stream.destroy();
|
|
@@ -64437,7 +65283,7 @@ async function validateSymlinkChain(path3, basePath, maxDepth = MAX_SYMLINK_DEPT
|
|
|
64437
65283
|
if (!stats.isSymbolicLink())
|
|
64438
65284
|
break;
|
|
64439
65285
|
const target = await readlink(current);
|
|
64440
|
-
const resolvedTarget = isAbsolute2(target) ? target :
|
|
65286
|
+
const resolvedTarget = isAbsolute2(target) ? target : join47(current, "..", target);
|
|
64441
65287
|
const normalizedTarget = normalize7(resolvedTarget);
|
|
64442
65288
|
const rel = relative4(basePath, normalizedTarget);
|
|
64443
65289
|
if (rel.startsWith("..") || isAbsolute2(rel)) {
|
|
@@ -64473,7 +65319,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
64473
65319
|
if (normalized.startsWith("..") || normalized.includes("/../")) {
|
|
64474
65320
|
throw new Error(`Path traversal not allowed: ${filePath}`);
|
|
64475
65321
|
}
|
|
64476
|
-
const fullPath =
|
|
65322
|
+
const fullPath = join47(basePath, normalized);
|
|
64477
65323
|
const rel = relative4(basePath, fullPath);
|
|
64478
65324
|
if (rel.startsWith("..") || isAbsolute2(rel)) {
|
|
64479
65325
|
throw new Error(`Path escapes base directory: ${filePath}`);
|
|
@@ -64488,7 +65334,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
64488
65334
|
}
|
|
64489
65335
|
} catch (error) {
|
|
64490
65336
|
if (error.code === "ENOENT") {
|
|
64491
|
-
const parentPath =
|
|
65337
|
+
const parentPath = join47(fullPath, "..");
|
|
64492
65338
|
try {
|
|
64493
65339
|
const resolvedBase = await realpath2(basePath);
|
|
64494
65340
|
const resolvedParent = await realpath2(parentPath);
|
|
@@ -65670,7 +66516,7 @@ init_logger();
|
|
|
65670
66516
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
65671
66517
|
import { mkdir as mkdir14 } from "node:fs/promises";
|
|
65672
66518
|
import os5 from "node:os";
|
|
65673
|
-
import { join as
|
|
66519
|
+
import { join as join54 } from "node:path";
|
|
65674
66520
|
var LOCK_CONFIG = {
|
|
65675
66521
|
stale: 60000,
|
|
65676
66522
|
retries: 0
|
|
@@ -65678,12 +66524,12 @@ var LOCK_CONFIG = {
|
|
|
65678
66524
|
var activeLocks = new Set;
|
|
65679
66525
|
var cleanupRegistered = false;
|
|
65680
66526
|
function getLocksDir() {
|
|
65681
|
-
return
|
|
66527
|
+
return join54(os5.homedir(), ".claudekit", "locks");
|
|
65682
66528
|
}
|
|
65683
66529
|
function cleanupLocks() {
|
|
65684
66530
|
for (const name of activeLocks) {
|
|
65685
66531
|
try {
|
|
65686
|
-
const lockPath =
|
|
66532
|
+
const lockPath = join54(getLocksDir(), `${name}.lock`);
|
|
65687
66533
|
import_proper_lockfile.default.unlockSync(lockPath, { realpath: false });
|
|
65688
66534
|
} catch {
|
|
65689
66535
|
try {
|
|
@@ -65706,7 +66552,7 @@ async function ensureLocksDir() {
|
|
|
65706
66552
|
async function withProcessLock(lockName, fn) {
|
|
65707
66553
|
registerCleanupHandlers();
|
|
65708
66554
|
await ensureLocksDir();
|
|
65709
|
-
const lockPath =
|
|
66555
|
+
const lockPath = join54(getLocksDir(), `${lockName}.lock`);
|
|
65710
66556
|
let release;
|
|
65711
66557
|
try {
|
|
65712
66558
|
release = await import_proper_lockfile.default.lock(lockPath, { ...LOCK_CONFIG, realpath: false });
|
|
@@ -65737,7 +66583,7 @@ init_logger();
|
|
|
65737
66583
|
init_logger();
|
|
65738
66584
|
init_path_resolver();
|
|
65739
66585
|
var import_fs_extra7 = __toESM(require_lib3(), 1);
|
|
65740
|
-
import { join as
|
|
66586
|
+
import { join as join55 } from "node:path";
|
|
65741
66587
|
async function handleConflicts(ctx) {
|
|
65742
66588
|
if (ctx.cancelled)
|
|
65743
66589
|
return ctx;
|
|
@@ -65746,7 +66592,7 @@ async function handleConflicts(ctx) {
|
|
|
65746
66592
|
if (PathResolver.isLocalSameAsGlobal()) {
|
|
65747
66593
|
return ctx;
|
|
65748
66594
|
}
|
|
65749
|
-
const localSettingsPath =
|
|
66595
|
+
const localSettingsPath = join55(process.cwd(), ".claude", "settings.json");
|
|
65750
66596
|
if (!await import_fs_extra7.pathExists(localSettingsPath)) {
|
|
65751
66597
|
return ctx;
|
|
65752
66598
|
}
|
|
@@ -65761,7 +66607,7 @@ async function handleConflicts(ctx) {
|
|
|
65761
66607
|
return { ...ctx, cancelled: true };
|
|
65762
66608
|
}
|
|
65763
66609
|
if (choice === "remove") {
|
|
65764
|
-
const localClaudeDir =
|
|
66610
|
+
const localClaudeDir = join55(process.cwd(), ".claude");
|
|
65765
66611
|
try {
|
|
65766
66612
|
await import_fs_extra7.remove(localClaudeDir);
|
|
65767
66613
|
logger.success("Removed local .claude/ directory");
|
|
@@ -65857,8 +66703,8 @@ init_environment();
|
|
|
65857
66703
|
init_logger();
|
|
65858
66704
|
init_safe_spinner();
|
|
65859
66705
|
import { mkdir as mkdir20, stat as stat12 } from "node:fs/promises";
|
|
65860
|
-
import { tmpdir as
|
|
65861
|
-
import { join as
|
|
66706
|
+
import { tmpdir as tmpdir4 } from "node:os";
|
|
66707
|
+
import { join as join62 } from "node:path";
|
|
65862
66708
|
|
|
65863
66709
|
// src/shared/temp-cleanup.ts
|
|
65864
66710
|
init_logger();
|
|
@@ -65877,7 +66723,7 @@ init_logger();
|
|
|
65877
66723
|
init_output_manager();
|
|
65878
66724
|
import { createWriteStream as createWriteStream2, rmSync } from "node:fs";
|
|
65879
66725
|
import { mkdir as mkdir15 } from "node:fs/promises";
|
|
65880
|
-
import { join as
|
|
66726
|
+
import { join as join56 } from "node:path";
|
|
65881
66727
|
|
|
65882
66728
|
// src/shared/progress-bar.ts
|
|
65883
66729
|
init_output_manager();
|
|
@@ -66041,21 +66887,21 @@ init_types2();
|
|
|
66041
66887
|
|
|
66042
66888
|
// src/domains/installation/utils/path-security.ts
|
|
66043
66889
|
init_types2();
|
|
66044
|
-
import { lstatSync as lstatSync2, realpathSync } from "node:fs";
|
|
66045
|
-
import { relative as relative5, resolve as
|
|
66890
|
+
import { lstatSync as lstatSync2, realpathSync as realpathSync2 } from "node:fs";
|
|
66891
|
+
import { relative as relative5, resolve as resolve11 } from "node:path";
|
|
66046
66892
|
var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
|
|
66047
66893
|
function isPathSafe(basePath, targetPath) {
|
|
66048
|
-
const resolvedBase =
|
|
66894
|
+
const resolvedBase = resolve11(basePath);
|
|
66049
66895
|
try {
|
|
66050
66896
|
const stat10 = lstatSync2(targetPath);
|
|
66051
66897
|
if (stat10.isSymbolicLink()) {
|
|
66052
|
-
const realTarget =
|
|
66898
|
+
const realTarget = realpathSync2(targetPath);
|
|
66053
66899
|
if (!realTarget.startsWith(resolvedBase)) {
|
|
66054
66900
|
return false;
|
|
66055
66901
|
}
|
|
66056
66902
|
}
|
|
66057
66903
|
} catch {}
|
|
66058
|
-
const resolvedTarget =
|
|
66904
|
+
const resolvedTarget = resolve11(targetPath);
|
|
66059
66905
|
const relativePath = relative5(resolvedBase, resolvedTarget);
|
|
66060
66906
|
return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
|
|
66061
66907
|
}
|
|
@@ -66087,7 +66933,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
|
|
|
66087
66933
|
class FileDownloader {
|
|
66088
66934
|
async downloadAsset(asset, destDir) {
|
|
66089
66935
|
try {
|
|
66090
|
-
const destPath =
|
|
66936
|
+
const destPath = join56(destDir, asset.name);
|
|
66091
66937
|
await mkdir15(destDir, { recursive: true });
|
|
66092
66938
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
66093
66939
|
logger.verbose("Download details", {
|
|
@@ -66143,7 +66989,7 @@ class FileDownloader {
|
|
|
66143
66989
|
}
|
|
66144
66990
|
if (downloadedSize !== totalSize) {
|
|
66145
66991
|
fileStream.end();
|
|
66146
|
-
await new Promise((
|
|
66992
|
+
await new Promise((resolve12) => fileStream.once("close", resolve12));
|
|
66147
66993
|
try {
|
|
66148
66994
|
rmSync(destPath, { force: true });
|
|
66149
66995
|
} catch (cleanupError) {
|
|
@@ -66157,7 +67003,7 @@ class FileDownloader {
|
|
|
66157
67003
|
return destPath;
|
|
66158
67004
|
} catch (error) {
|
|
66159
67005
|
fileStream.end();
|
|
66160
|
-
await new Promise((
|
|
67006
|
+
await new Promise((resolve12) => fileStream.once("close", resolve12));
|
|
66161
67007
|
try {
|
|
66162
67008
|
rmSync(destPath, { force: true });
|
|
66163
67009
|
} catch (cleanupError) {
|
|
@@ -66172,7 +67018,7 @@ class FileDownloader {
|
|
|
66172
67018
|
}
|
|
66173
67019
|
async downloadFile(params) {
|
|
66174
67020
|
const { url, name, size, destDir, token } = params;
|
|
66175
|
-
const destPath =
|
|
67021
|
+
const destPath = join56(destDir, name);
|
|
66176
67022
|
await mkdir15(destDir, { recursive: true });
|
|
66177
67023
|
output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
66178
67024
|
const headers = {};
|
|
@@ -66223,7 +67069,7 @@ class FileDownloader {
|
|
|
66223
67069
|
const expectedSize = Number(response.headers.get("content-length"));
|
|
66224
67070
|
if (expectedSize > 0 && downloadedSize !== expectedSize) {
|
|
66225
67071
|
fileStream.end();
|
|
66226
|
-
await new Promise((
|
|
67072
|
+
await new Promise((resolve12) => fileStream.once("close", resolve12));
|
|
66227
67073
|
try {
|
|
66228
67074
|
rmSync(destPath, { force: true });
|
|
66229
67075
|
} catch (cleanupError) {
|
|
@@ -66241,7 +67087,7 @@ class FileDownloader {
|
|
|
66241
67087
|
return destPath;
|
|
66242
67088
|
} catch (error) {
|
|
66243
67089
|
fileStream.end();
|
|
66244
|
-
await new Promise((
|
|
67090
|
+
await new Promise((resolve12) => fileStream.once("close", resolve12));
|
|
66245
67091
|
try {
|
|
66246
67092
|
rmSync(destPath, { force: true });
|
|
66247
67093
|
} catch (cleanupError) {
|
|
@@ -66257,11 +67103,11 @@ class FileDownloader {
|
|
|
66257
67103
|
init_logger();
|
|
66258
67104
|
init_types2();
|
|
66259
67105
|
import { constants as constants4 } from "node:fs";
|
|
66260
|
-
import { access as access4, readdir as
|
|
66261
|
-
import { join as
|
|
67106
|
+
import { access as access4, readdir as readdir10 } from "node:fs/promises";
|
|
67107
|
+
import { join as join57 } from "node:path";
|
|
66262
67108
|
async function validateExtraction(extractDir) {
|
|
66263
67109
|
try {
|
|
66264
|
-
const entries = await
|
|
67110
|
+
const entries = await readdir10(extractDir, { encoding: "utf8" });
|
|
66265
67111
|
logger.debug(`Extracted files: ${entries.join(", ")}`);
|
|
66266
67112
|
if (entries.length === 0) {
|
|
66267
67113
|
throw new ExtractionError("Extraction resulted in no files");
|
|
@@ -66270,7 +67116,7 @@ async function validateExtraction(extractDir) {
|
|
|
66270
67116
|
const missingPaths = [];
|
|
66271
67117
|
for (const path3 of criticalPaths) {
|
|
66272
67118
|
try {
|
|
66273
|
-
await access4(
|
|
67119
|
+
await access4(join57(extractDir, path3), constants4.F_OK);
|
|
66274
67120
|
logger.debug(`Found: ${path3}`);
|
|
66275
67121
|
} catch {
|
|
66276
67122
|
logger.warning(`Expected path not found: ${path3}`);
|
|
@@ -66291,8 +67137,8 @@ async function validateExtraction(extractDir) {
|
|
|
66291
67137
|
|
|
66292
67138
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
66293
67139
|
init_logger();
|
|
66294
|
-
import { copyFile as copyFile3, mkdir as mkdir18, readdir as
|
|
66295
|
-
import { join as
|
|
67140
|
+
import { copyFile as copyFile3, mkdir as mkdir18, readdir as readdir12, rm as rm3, stat as stat10 } from "node:fs/promises";
|
|
67141
|
+
import { join as join60 } from "node:path";
|
|
66296
67142
|
|
|
66297
67143
|
// node_modules/@isaacs/fs-minipass/dist/esm/index.js
|
|
66298
67144
|
import EE from "events";
|
|
@@ -66840,10 +67686,10 @@ class Minipass extends EventEmitter3 {
|
|
|
66840
67686
|
return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
66841
67687
|
}
|
|
66842
67688
|
async promise() {
|
|
66843
|
-
return new Promise((
|
|
67689
|
+
return new Promise((resolve12, reject) => {
|
|
66844
67690
|
this.on(DESTROYED, () => reject(new Error("stream destroyed")));
|
|
66845
67691
|
this.on("error", (er) => reject(er));
|
|
66846
|
-
this.on("end", () =>
|
|
67692
|
+
this.on("end", () => resolve12());
|
|
66847
67693
|
});
|
|
66848
67694
|
}
|
|
66849
67695
|
[Symbol.asyncIterator]() {
|
|
@@ -66862,7 +67708,7 @@ class Minipass extends EventEmitter3 {
|
|
|
66862
67708
|
return Promise.resolve({ done: false, value: res });
|
|
66863
67709
|
if (this[EOF])
|
|
66864
67710
|
return stop();
|
|
66865
|
-
let
|
|
67711
|
+
let resolve12;
|
|
66866
67712
|
let reject;
|
|
66867
67713
|
const onerr = (er) => {
|
|
66868
67714
|
this.off("data", ondata);
|
|
@@ -66876,19 +67722,19 @@ class Minipass extends EventEmitter3 {
|
|
|
66876
67722
|
this.off("end", onend);
|
|
66877
67723
|
this.off(DESTROYED, ondestroy);
|
|
66878
67724
|
this.pause();
|
|
66879
|
-
|
|
67725
|
+
resolve12({ value, done: !!this[EOF] });
|
|
66880
67726
|
};
|
|
66881
67727
|
const onend = () => {
|
|
66882
67728
|
this.off("error", onerr);
|
|
66883
67729
|
this.off("data", ondata);
|
|
66884
67730
|
this.off(DESTROYED, ondestroy);
|
|
66885
67731
|
stop();
|
|
66886
|
-
|
|
67732
|
+
resolve12({ done: true, value: undefined });
|
|
66887
67733
|
};
|
|
66888
67734
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
66889
67735
|
return new Promise((res2, rej) => {
|
|
66890
67736
|
reject = rej;
|
|
66891
|
-
|
|
67737
|
+
resolve12 = res2;
|
|
66892
67738
|
this.once(DESTROYED, ondestroy);
|
|
66893
67739
|
this.once("error", onerr);
|
|
66894
67740
|
this.once("end", onend);
|
|
@@ -67994,10 +68840,10 @@ class Minipass2 extends EventEmitter4 {
|
|
|
67994
68840
|
return this[ENCODING2] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
67995
68841
|
}
|
|
67996
68842
|
async promise() {
|
|
67997
|
-
return new Promise((
|
|
68843
|
+
return new Promise((resolve12, reject) => {
|
|
67998
68844
|
this.on(DESTROYED2, () => reject(new Error("stream destroyed")));
|
|
67999
68845
|
this.on("error", (er) => reject(er));
|
|
68000
|
-
this.on("end", () =>
|
|
68846
|
+
this.on("end", () => resolve12());
|
|
68001
68847
|
});
|
|
68002
68848
|
}
|
|
68003
68849
|
[Symbol.asyncIterator]() {
|
|
@@ -68016,7 +68862,7 @@ class Minipass2 extends EventEmitter4 {
|
|
|
68016
68862
|
return Promise.resolve({ done: false, value: res });
|
|
68017
68863
|
if (this[EOF2])
|
|
68018
68864
|
return stop();
|
|
68019
|
-
let
|
|
68865
|
+
let resolve12;
|
|
68020
68866
|
let reject;
|
|
68021
68867
|
const onerr = (er) => {
|
|
68022
68868
|
this.off("data", ondata);
|
|
@@ -68030,19 +68876,19 @@ class Minipass2 extends EventEmitter4 {
|
|
|
68030
68876
|
this.off("end", onend);
|
|
68031
68877
|
this.off(DESTROYED2, ondestroy);
|
|
68032
68878
|
this.pause();
|
|
68033
|
-
|
|
68879
|
+
resolve12({ value, done: !!this[EOF2] });
|
|
68034
68880
|
};
|
|
68035
68881
|
const onend = () => {
|
|
68036
68882
|
this.off("error", onerr);
|
|
68037
68883
|
this.off("data", ondata);
|
|
68038
68884
|
this.off(DESTROYED2, ondestroy);
|
|
68039
68885
|
stop();
|
|
68040
|
-
|
|
68886
|
+
resolve12({ done: true, value: undefined });
|
|
68041
68887
|
};
|
|
68042
68888
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
68043
68889
|
return new Promise((res2, rej) => {
|
|
68044
68890
|
reject = rej;
|
|
68045
|
-
|
|
68891
|
+
resolve12 = res2;
|
|
68046
68892
|
this.once(DESTROYED2, ondestroy);
|
|
68047
68893
|
this.once("error", onerr);
|
|
68048
68894
|
this.once("end", onend);
|
|
@@ -69470,10 +70316,10 @@ class Minipass3 extends EventEmitter5 {
|
|
|
69470
70316
|
return this[ENCODING3] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
69471
70317
|
}
|
|
69472
70318
|
async promise() {
|
|
69473
|
-
return new Promise((
|
|
70319
|
+
return new Promise((resolve12, reject) => {
|
|
69474
70320
|
this.on(DESTROYED3, () => reject(new Error("stream destroyed")));
|
|
69475
70321
|
this.on("error", (er) => reject(er));
|
|
69476
|
-
this.on("end", () =>
|
|
70322
|
+
this.on("end", () => resolve12());
|
|
69477
70323
|
});
|
|
69478
70324
|
}
|
|
69479
70325
|
[Symbol.asyncIterator]() {
|
|
@@ -69492,7 +70338,7 @@ class Minipass3 extends EventEmitter5 {
|
|
|
69492
70338
|
return Promise.resolve({ done: false, value: res });
|
|
69493
70339
|
if (this[EOF3])
|
|
69494
70340
|
return stop();
|
|
69495
|
-
let
|
|
70341
|
+
let resolve12;
|
|
69496
70342
|
let reject;
|
|
69497
70343
|
const onerr = (er) => {
|
|
69498
70344
|
this.off("data", ondata);
|
|
@@ -69506,19 +70352,19 @@ class Minipass3 extends EventEmitter5 {
|
|
|
69506
70352
|
this.off("end", onend);
|
|
69507
70353
|
this.off(DESTROYED3, ondestroy);
|
|
69508
70354
|
this.pause();
|
|
69509
|
-
|
|
70355
|
+
resolve12({ value, done: !!this[EOF3] });
|
|
69510
70356
|
};
|
|
69511
70357
|
const onend = () => {
|
|
69512
70358
|
this.off("error", onerr);
|
|
69513
70359
|
this.off("data", ondata);
|
|
69514
70360
|
this.off(DESTROYED3, ondestroy);
|
|
69515
70361
|
stop();
|
|
69516
|
-
|
|
70362
|
+
resolve12({ done: true, value: undefined });
|
|
69517
70363
|
};
|
|
69518
70364
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
69519
70365
|
return new Promise((res2, rej) => {
|
|
69520
70366
|
reject = rej;
|
|
69521
|
-
|
|
70367
|
+
resolve12 = res2;
|
|
69522
70368
|
this.once(DESTROYED3, ondestroy);
|
|
69523
70369
|
this.once("error", onerr);
|
|
69524
70370
|
this.once("end", onend);
|
|
@@ -70289,9 +71135,9 @@ var listFile = (opt, _files) => {
|
|
|
70289
71135
|
const parse4 = new Parser(opt);
|
|
70290
71136
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
|
70291
71137
|
const file = opt.file;
|
|
70292
|
-
const p = new Promise((
|
|
71138
|
+
const p = new Promise((resolve12, reject) => {
|
|
70293
71139
|
parse4.on("error", reject);
|
|
70294
|
-
parse4.on("end",
|
|
71140
|
+
parse4.on("end", resolve12);
|
|
70295
71141
|
fs9.stat(file, (er, stat10) => {
|
|
70296
71142
|
if (er) {
|
|
70297
71143
|
reject(er);
|
|
@@ -72054,7 +72900,7 @@ var mkdirSync = (dir, opt) => {
|
|
|
72054
72900
|
};
|
|
72055
72901
|
|
|
72056
72902
|
// node_modules/tar/dist/esm/path-reservations.js
|
|
72057
|
-
import { join as
|
|
72903
|
+
import { join as join58 } from "node:path";
|
|
72058
72904
|
|
|
72059
72905
|
// node_modules/tar/dist/esm/normalize-unicode.js
|
|
72060
72906
|
var normalizeCache = Object.create(null);
|
|
@@ -72087,7 +72933,7 @@ var getDirs = (path8) => {
|
|
|
72087
72933
|
const dirs = path8.split("/").slice(0, -1).reduce((set, path9) => {
|
|
72088
72934
|
const s = set[set.length - 1];
|
|
72089
72935
|
if (s !== undefined) {
|
|
72090
|
-
path9 =
|
|
72936
|
+
path9 = join58(s, path9);
|
|
72091
72937
|
}
|
|
72092
72938
|
set.push(path9 || "/");
|
|
72093
72939
|
return set;
|
|
@@ -72101,7 +72947,7 @@ class PathReservations {
|
|
|
72101
72947
|
#running = new Set;
|
|
72102
72948
|
reserve(paths, fn) {
|
|
72103
72949
|
paths = isWindows4 ? ["win32 parallelization disabled"] : paths.map((p) => {
|
|
72104
|
-
return stripTrailingSlashes(
|
|
72950
|
+
return stripTrailingSlashes(join58(normalizeUnicode(p))).toLowerCase();
|
|
72105
72951
|
});
|
|
72106
72952
|
const dirs = new Set(paths.map((path8) => getDirs(path8)).reduce((a3, b3) => a3.concat(b3)));
|
|
72107
72953
|
this.#reservations.set(fn, { dirs, paths });
|
|
@@ -72871,9 +73717,9 @@ var extractFile = (opt, _3) => {
|
|
|
72871
73717
|
const u = new Unpack(opt);
|
|
72872
73718
|
const readSize = opt.maxReadSize || 16 * 1024 * 1024;
|
|
72873
73719
|
const file = opt.file;
|
|
72874
|
-
const p = new Promise((
|
|
73720
|
+
const p = new Promise((resolve12, reject) => {
|
|
72875
73721
|
u.on("error", reject);
|
|
72876
|
-
u.on("close",
|
|
73722
|
+
u.on("close", resolve12);
|
|
72877
73723
|
fs16.stat(file, (er, stat10) => {
|
|
72878
73724
|
if (er) {
|
|
72879
73725
|
reject(er);
|
|
@@ -73006,7 +73852,7 @@ var replaceAsync = (opt, files) => {
|
|
|
73006
73852
|
};
|
|
73007
73853
|
fs17.read(fd, headBuf, 0, 512, position, onread);
|
|
73008
73854
|
};
|
|
73009
|
-
const promise = new Promise((
|
|
73855
|
+
const promise = new Promise((resolve12, reject) => {
|
|
73010
73856
|
p.on("error", reject);
|
|
73011
73857
|
let flag = "r+";
|
|
73012
73858
|
const onopen = (er, fd) => {
|
|
@@ -73031,7 +73877,7 @@ var replaceAsync = (opt, files) => {
|
|
|
73031
73877
|
});
|
|
73032
73878
|
p.pipe(stream);
|
|
73033
73879
|
stream.on("error", reject);
|
|
73034
|
-
stream.on("close",
|
|
73880
|
+
stream.on("close", resolve12);
|
|
73035
73881
|
addFilesAsync2(p, files);
|
|
73036
73882
|
});
|
|
73037
73883
|
});
|
|
@@ -73160,8 +74006,8 @@ function decodeFilePath(path10) {
|
|
|
73160
74006
|
// src/domains/installation/utils/file-utils.ts
|
|
73161
74007
|
init_logger();
|
|
73162
74008
|
init_types2();
|
|
73163
|
-
import { copyFile as copyFile2, lstat as lstat4, mkdir as mkdir17, readdir as
|
|
73164
|
-
import { join as
|
|
74009
|
+
import { copyFile as copyFile2, lstat as lstat4, mkdir as mkdir17, readdir as readdir11 } from "node:fs/promises";
|
|
74010
|
+
import { join as join59, relative as relative6 } from "node:path";
|
|
73165
74011
|
async function withRetry(fn, retries = 3) {
|
|
73166
74012
|
for (let i = 0;i < retries; i++) {
|
|
73167
74013
|
try {
|
|
@@ -73181,10 +74027,10 @@ var isRetryable = (e2) => {
|
|
|
73181
74027
|
var delay = (ms) => new Promise((r2) => setTimeout(r2, ms));
|
|
73182
74028
|
async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
73183
74029
|
await mkdir17(destDir, { recursive: true });
|
|
73184
|
-
const entries = await
|
|
74030
|
+
const entries = await readdir11(sourceDir, { encoding: "utf8" });
|
|
73185
74031
|
for (const entry of entries) {
|
|
73186
|
-
const sourcePath =
|
|
73187
|
-
const destPath =
|
|
74032
|
+
const sourcePath = join59(sourceDir, entry);
|
|
74033
|
+
const destPath = join59(destDir, entry);
|
|
73188
74034
|
const relativePath = relative6(sourceDir, sourcePath);
|
|
73189
74035
|
if (!isPathSafe(destDir, destPath)) {
|
|
73190
74036
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -73209,10 +74055,10 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
73209
74055
|
}
|
|
73210
74056
|
async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
73211
74057
|
await mkdir17(destDir, { recursive: true });
|
|
73212
|
-
const entries = await
|
|
74058
|
+
const entries = await readdir11(sourceDir, { encoding: "utf8" });
|
|
73213
74059
|
for (const entry of entries) {
|
|
73214
|
-
const sourcePath =
|
|
73215
|
-
const destPath =
|
|
74060
|
+
const sourcePath = join59(sourceDir, entry);
|
|
74061
|
+
const destPath = join59(destDir, entry);
|
|
73216
74062
|
const relativePath = relative6(sourceDir, sourcePath);
|
|
73217
74063
|
if (!isPathSafe(destDir, destPath)) {
|
|
73218
74064
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -73256,14 +74102,14 @@ class TarExtractor {
|
|
|
73256
74102
|
}
|
|
73257
74103
|
});
|
|
73258
74104
|
logger.debug(`Extracted TAR.GZ to temp: ${tempExtractDir}`);
|
|
73259
|
-
const entries = await
|
|
74105
|
+
const entries = await readdir12(tempExtractDir, { encoding: "utf8" });
|
|
73260
74106
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
73261
74107
|
if (entries.length === 1) {
|
|
73262
74108
|
const rootEntry = entries[0];
|
|
73263
|
-
const rootPath =
|
|
74109
|
+
const rootPath = join60(tempExtractDir, rootEntry);
|
|
73264
74110
|
const rootStat = await stat10(rootPath);
|
|
73265
74111
|
if (rootStat.isDirectory()) {
|
|
73266
|
-
const rootContents = await
|
|
74112
|
+
const rootContents = await readdir12(rootPath, { encoding: "utf8" });
|
|
73267
74113
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
73268
74114
|
const isWrapper = isWrapperDirectory(rootEntry);
|
|
73269
74115
|
logger.debug(`Is wrapper directory: ${isWrapper}`);
|
|
@@ -73276,7 +74122,7 @@ class TarExtractor {
|
|
|
73276
74122
|
}
|
|
73277
74123
|
} else {
|
|
73278
74124
|
await mkdir18(destDir, { recursive: true });
|
|
73279
|
-
await copyFile3(rootPath,
|
|
74125
|
+
await copyFile3(rootPath, join60(destDir, rootEntry));
|
|
73280
74126
|
}
|
|
73281
74127
|
} else {
|
|
73282
74128
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -73298,27 +74144,27 @@ init_environment();
|
|
|
73298
74144
|
init_logger();
|
|
73299
74145
|
var import_extract_zip = __toESM(require_extract_zip(), 1);
|
|
73300
74146
|
import { execFile as execFile8 } from "node:child_process";
|
|
73301
|
-
import { copyFile as copyFile4, mkdir as mkdir19, readdir as
|
|
73302
|
-
import { join as
|
|
74147
|
+
import { copyFile as copyFile4, mkdir as mkdir19, readdir as readdir13, rm as rm4, stat as stat11 } from "node:fs/promises";
|
|
74148
|
+
import { join as join61 } from "node:path";
|
|
73303
74149
|
class ZipExtractor {
|
|
73304
74150
|
async tryNativeUnzip(archivePath, destDir) {
|
|
73305
74151
|
if (!isMacOS()) {
|
|
73306
74152
|
return false;
|
|
73307
74153
|
}
|
|
73308
|
-
return new Promise((
|
|
74154
|
+
return new Promise((resolve12) => {
|
|
73309
74155
|
mkdir19(destDir, { recursive: true }).then(() => {
|
|
73310
74156
|
execFile8("unzip", ["-o", "-q", archivePath, "-d", destDir], (error, _stdout, stderr) => {
|
|
73311
74157
|
if (error) {
|
|
73312
74158
|
logger.debug(`Native unzip failed: ${stderr || error.message}`);
|
|
73313
|
-
|
|
74159
|
+
resolve12(false);
|
|
73314
74160
|
return;
|
|
73315
74161
|
}
|
|
73316
74162
|
logger.debug("Native unzip succeeded");
|
|
73317
|
-
|
|
74163
|
+
resolve12(true);
|
|
73318
74164
|
});
|
|
73319
74165
|
}).catch((err) => {
|
|
73320
74166
|
logger.debug(`Failed to create directory for native unzip: ${err.message}`);
|
|
73321
|
-
|
|
74167
|
+
resolve12(false);
|
|
73322
74168
|
});
|
|
73323
74169
|
});
|
|
73324
74170
|
}
|
|
@@ -73343,14 +74189,14 @@ class ZipExtractor {
|
|
|
73343
74189
|
logger.verbose(`Extracted ${extractedCount} files`);
|
|
73344
74190
|
}
|
|
73345
74191
|
logger.debug(`Extracted ZIP to temp: ${tempExtractDir}`);
|
|
73346
|
-
const entries = await
|
|
74192
|
+
const entries = await readdir13(tempExtractDir, { encoding: "utf8" });
|
|
73347
74193
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
73348
74194
|
if (entries.length === 1) {
|
|
73349
74195
|
const rootEntry = entries[0];
|
|
73350
|
-
const rootPath =
|
|
74196
|
+
const rootPath = join61(tempExtractDir, rootEntry);
|
|
73351
74197
|
const rootStat = await stat11(rootPath);
|
|
73352
74198
|
if (rootStat.isDirectory()) {
|
|
73353
|
-
const rootContents = await
|
|
74199
|
+
const rootContents = await readdir13(rootPath, { encoding: "utf8" });
|
|
73354
74200
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
73355
74201
|
const isWrapper = isWrapperDirectory(rootEntry);
|
|
73356
74202
|
logger.debug(`Is wrapper directory: ${isWrapper}`);
|
|
@@ -73363,7 +74209,7 @@ class ZipExtractor {
|
|
|
73363
74209
|
}
|
|
73364
74210
|
} else {
|
|
73365
74211
|
await mkdir19(destDir, { recursive: true });
|
|
73366
|
-
await copyFile4(rootPath,
|
|
74212
|
+
await copyFile4(rootPath, join61(destDir, rootEntry));
|
|
73367
74213
|
}
|
|
73368
74214
|
} else {
|
|
73369
74215
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -73462,7 +74308,7 @@ class DownloadManager {
|
|
|
73462
74308
|
async createTempDir() {
|
|
73463
74309
|
const timestamp = Date.now();
|
|
73464
74310
|
const counter = DownloadManager.tempDirCounter++;
|
|
73465
|
-
const primaryTempDir =
|
|
74311
|
+
const primaryTempDir = join62(tmpdir4(), `claudekit-${timestamp}-${counter}`);
|
|
73466
74312
|
try {
|
|
73467
74313
|
await mkdir20(primaryTempDir, { recursive: true });
|
|
73468
74314
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -73479,7 +74325,7 @@ Solutions:
|
|
|
73479
74325
|
2. Set HOME environment variable
|
|
73480
74326
|
3. Try running from a different directory`);
|
|
73481
74327
|
}
|
|
73482
|
-
const fallbackTempDir =
|
|
74328
|
+
const fallbackTempDir = join62(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}-${counter}`);
|
|
73483
74329
|
try {
|
|
73484
74330
|
await mkdir20(fallbackTempDir, { recursive: true });
|
|
73485
74331
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -73828,20 +74674,20 @@ async function handleDownload(ctx) {
|
|
|
73828
74674
|
};
|
|
73829
74675
|
}
|
|
73830
74676
|
// src/commands/init/phases/merge-handler.ts
|
|
73831
|
-
import { join as
|
|
74677
|
+
import { join as join78 } from "node:path";
|
|
73832
74678
|
|
|
73833
74679
|
// src/domains/installation/deletion-handler.ts
|
|
73834
|
-
import { existsSync as
|
|
73835
|
-
import { dirname as dirname14, join as
|
|
74680
|
+
import { existsSync as existsSync36, lstatSync as lstatSync3, readdirSync as readdirSync2, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
74681
|
+
import { dirname as dirname14, join as join65, relative as relative7, resolve as resolve13, sep as sep2 } from "node:path";
|
|
73836
74682
|
|
|
73837
74683
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
73838
74684
|
init_metadata_migration();
|
|
73839
74685
|
init_logger();
|
|
73840
74686
|
init_types2();
|
|
73841
74687
|
var import_fs_extra8 = __toESM(require_lib3(), 1);
|
|
73842
|
-
import { join as
|
|
74688
|
+
import { join as join64 } from "node:path";
|
|
73843
74689
|
async function readManifest(claudeDir2) {
|
|
73844
|
-
const metadataPath =
|
|
74690
|
+
const metadataPath = join64(claudeDir2, "metadata.json");
|
|
73845
74691
|
if (!await import_fs_extra8.pathExists(metadataPath)) {
|
|
73846
74692
|
return null;
|
|
73847
74693
|
}
|
|
@@ -74014,12 +74860,12 @@ function shouldDeletePath(path11, metadata) {
|
|
|
74014
74860
|
}
|
|
74015
74861
|
function collectFilesRecursively(dir, baseDir) {
|
|
74016
74862
|
const results = [];
|
|
74017
|
-
if (!
|
|
74863
|
+
if (!existsSync36(dir))
|
|
74018
74864
|
return results;
|
|
74019
74865
|
try {
|
|
74020
74866
|
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
74021
74867
|
for (const entry of entries) {
|
|
74022
|
-
const fullPath =
|
|
74868
|
+
const fullPath = join65(dir, entry.name);
|
|
74023
74869
|
const relativePath = relative7(baseDir, fullPath);
|
|
74024
74870
|
if (entry.isDirectory()) {
|
|
74025
74871
|
results.push(...collectFilesRecursively(fullPath, baseDir));
|
|
@@ -74049,8 +74895,8 @@ function expandGlobPatterns(patterns, claudeDir2) {
|
|
|
74049
74895
|
}
|
|
74050
74896
|
var MAX_CLEANUP_ITERATIONS = 50;
|
|
74051
74897
|
function cleanupEmptyDirectories(filePath, claudeDir2) {
|
|
74052
|
-
const normalizedClaudeDir =
|
|
74053
|
-
let currentDir =
|
|
74898
|
+
const normalizedClaudeDir = resolve13(claudeDir2);
|
|
74899
|
+
let currentDir = resolve13(dirname14(filePath));
|
|
74054
74900
|
let iterations = 0;
|
|
74055
74901
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
|
|
74056
74902
|
iterations++;
|
|
@@ -74059,7 +74905,7 @@ function cleanupEmptyDirectories(filePath, claudeDir2) {
|
|
|
74059
74905
|
if (entries.length === 0) {
|
|
74060
74906
|
rmdirSync(currentDir);
|
|
74061
74907
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
74062
|
-
currentDir =
|
|
74908
|
+
currentDir = resolve13(dirname14(currentDir));
|
|
74063
74909
|
} else {
|
|
74064
74910
|
break;
|
|
74065
74911
|
}
|
|
@@ -74069,9 +74915,9 @@ function cleanupEmptyDirectories(filePath, claudeDir2) {
|
|
|
74069
74915
|
}
|
|
74070
74916
|
}
|
|
74071
74917
|
function deletePath(fullPath, claudeDir2) {
|
|
74072
|
-
const normalizedPath =
|
|
74073
|
-
const normalizedClaudeDir =
|
|
74074
|
-
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${
|
|
74918
|
+
const normalizedPath = resolve13(fullPath);
|
|
74919
|
+
const normalizedClaudeDir = resolve13(claudeDir2);
|
|
74920
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep2}`) && normalizedPath !== normalizedClaudeDir) {
|
|
74075
74921
|
throw new Error(`Path traversal detected: ${fullPath}`);
|
|
74076
74922
|
}
|
|
74077
74923
|
try {
|
|
@@ -74087,7 +74933,7 @@ function deletePath(fullPath, claudeDir2) {
|
|
|
74087
74933
|
}
|
|
74088
74934
|
}
|
|
74089
74935
|
async function updateMetadataAfterDeletion(claudeDir2, deletedPaths) {
|
|
74090
|
-
const metadataPath =
|
|
74936
|
+
const metadataPath = join65(claudeDir2, "metadata.json");
|
|
74091
74937
|
if (!await import_fs_extra9.pathExists(metadataPath)) {
|
|
74092
74938
|
return;
|
|
74093
74939
|
}
|
|
@@ -74142,10 +74988,10 @@ async function handleDeletions(sourceMetadata, claudeDir2) {
|
|
|
74142
74988
|
const userMetadata = await readManifest(claudeDir2);
|
|
74143
74989
|
const result = { deletedPaths: [], preservedPaths: [], errors: [] };
|
|
74144
74990
|
for (const path11 of deletions) {
|
|
74145
|
-
const fullPath =
|
|
74146
|
-
const normalizedPath =
|
|
74147
|
-
const normalizedClaudeDir =
|
|
74148
|
-
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${
|
|
74991
|
+
const fullPath = join65(claudeDir2, path11);
|
|
74992
|
+
const normalizedPath = resolve13(fullPath);
|
|
74993
|
+
const normalizedClaudeDir = resolve13(claudeDir2);
|
|
74994
|
+
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep2}`)) {
|
|
74149
74995
|
logger.warning(`Skipping invalid path: ${path11}`);
|
|
74150
74996
|
result.errors.push(path11);
|
|
74151
74997
|
continue;
|
|
@@ -74155,7 +75001,7 @@ async function handleDeletions(sourceMetadata, claudeDir2) {
|
|
|
74155
75001
|
logger.verbose(`Preserved user file: ${path11}`);
|
|
74156
75002
|
continue;
|
|
74157
75003
|
}
|
|
74158
|
-
if (
|
|
75004
|
+
if (existsSync36(fullPath)) {
|
|
74159
75005
|
try {
|
|
74160
75006
|
deletePath(fullPath, claudeDir2);
|
|
74161
75007
|
result.deletedPaths.push(path11);
|
|
@@ -74182,7 +75028,7 @@ init_logger();
|
|
|
74182
75028
|
init_types2();
|
|
74183
75029
|
var import_fs_extra12 = __toESM(require_lib3(), 1);
|
|
74184
75030
|
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
74185
|
-
import { dirname as dirname16, join as
|
|
75031
|
+
import { dirname as dirname16, join as join68, relative as relative9 } from "node:path";
|
|
74186
75032
|
|
|
74187
75033
|
// src/domains/installation/selective-merger.ts
|
|
74188
75034
|
import { stat as stat13 } from "node:fs/promises";
|
|
@@ -74361,7 +75207,7 @@ init_logger();
|
|
|
74361
75207
|
var import_fs_extra10 = __toESM(require_lib3(), 1);
|
|
74362
75208
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
74363
75209
|
import { relative as relative8 } from "node:path";
|
|
74364
|
-
import { join as
|
|
75210
|
+
import { join as join66 } from "node:path";
|
|
74365
75211
|
|
|
74366
75212
|
// node_modules/@isaacs/balanced-match/dist/esm/index.js
|
|
74367
75213
|
var balanced = (a3, b3, str2) => {
|
|
@@ -75168,8 +76014,8 @@ var path11 = {
|
|
|
75168
76014
|
win32: { sep: "\\" },
|
|
75169
76015
|
posix: { sep: "/" }
|
|
75170
76016
|
};
|
|
75171
|
-
var
|
|
75172
|
-
minimatch.sep =
|
|
76017
|
+
var sep3 = defaultPlatform === "win32" ? path11.win32.sep : path11.posix.sep;
|
|
76018
|
+
minimatch.sep = sep3;
|
|
75173
76019
|
var GLOBSTAR = Symbol("globstar **");
|
|
75174
76020
|
minimatch.GLOBSTAR = GLOBSTAR;
|
|
75175
76021
|
var qmark2 = "[^/]";
|
|
@@ -75817,7 +76663,7 @@ class FileScanner {
|
|
|
75817
76663
|
const files = [];
|
|
75818
76664
|
const entries = await import_fs_extra10.readdir(dir, { encoding: "utf8" });
|
|
75819
76665
|
for (const entry of entries) {
|
|
75820
|
-
const fullPath =
|
|
76666
|
+
const fullPath = join66(dir, entry);
|
|
75821
76667
|
const relativePath = relative8(baseDir, fullPath);
|
|
75822
76668
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
75823
76669
|
const stats = await import_fs_extra10.lstat(fullPath);
|
|
@@ -75855,9 +76701,9 @@ import { execSync as execSync4 } from "node:child_process";
|
|
|
75855
76701
|
|
|
75856
76702
|
// src/domains/config/installed-settings-tracker.ts
|
|
75857
76703
|
init_shared();
|
|
75858
|
-
import { existsSync as
|
|
76704
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
75859
76705
|
import { mkdir as mkdir21, readFile as readFile29, writeFile as writeFile17 } from "node:fs/promises";
|
|
75860
|
-
import { dirname as dirname15, join as
|
|
76706
|
+
import { dirname as dirname15, join as join67 } from "node:path";
|
|
75861
76707
|
var CK_JSON_FILE = ".ck.json";
|
|
75862
76708
|
|
|
75863
76709
|
class InstalledSettingsTracker {
|
|
@@ -75871,13 +76717,13 @@ class InstalledSettingsTracker {
|
|
|
75871
76717
|
}
|
|
75872
76718
|
getCkJsonPath() {
|
|
75873
76719
|
if (this.isGlobal) {
|
|
75874
|
-
return
|
|
76720
|
+
return join67(this.projectDir, CK_JSON_FILE);
|
|
75875
76721
|
}
|
|
75876
|
-
return
|
|
76722
|
+
return join67(this.projectDir, ".claude", CK_JSON_FILE);
|
|
75877
76723
|
}
|
|
75878
76724
|
async loadInstalledSettings() {
|
|
75879
76725
|
const ckJsonPath = this.getCkJsonPath();
|
|
75880
|
-
if (!
|
|
76726
|
+
if (!existsSync37(ckJsonPath)) {
|
|
75881
76727
|
return { hooks: [], mcpServers: [] };
|
|
75882
76728
|
}
|
|
75883
76729
|
try {
|
|
@@ -75897,7 +76743,7 @@ class InstalledSettingsTracker {
|
|
|
75897
76743
|
const ckJsonPath = this.getCkJsonPath();
|
|
75898
76744
|
try {
|
|
75899
76745
|
let data = {};
|
|
75900
|
-
if (
|
|
76746
|
+
if (existsSync37(ckJsonPath)) {
|
|
75901
76747
|
const content = await readFile29(ckJsonPath, "utf-8");
|
|
75902
76748
|
data = JSON.parse(content);
|
|
75903
76749
|
}
|
|
@@ -76304,7 +77150,7 @@ class CopyExecutor {
|
|
|
76304
77150
|
for (const file of files) {
|
|
76305
77151
|
const relativePath = relative9(sourceDir, file);
|
|
76306
77152
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
76307
|
-
const destPath =
|
|
77153
|
+
const destPath = join68(destDir, relativePath);
|
|
76308
77154
|
if (await import_fs_extra12.pathExists(destPath)) {
|
|
76309
77155
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
76310
77156
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
@@ -76326,7 +77172,7 @@ class CopyExecutor {
|
|
|
76326
77172
|
for (const file of files) {
|
|
76327
77173
|
const relativePath = relative9(sourceDir, file);
|
|
76328
77174
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
76329
|
-
const destPath =
|
|
77175
|
+
const destPath = join68(destDir, relativePath);
|
|
76330
77176
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
76331
77177
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
76332
77178
|
skippedCount++;
|
|
@@ -76495,16 +77341,16 @@ class FileMerger {
|
|
|
76495
77341
|
}
|
|
76496
77342
|
|
|
76497
77343
|
// src/domains/migration/legacy-migration.ts
|
|
76498
|
-
import { readdir as
|
|
76499
|
-
import { join as
|
|
77344
|
+
import { readdir as readdir15, stat as stat14 } from "node:fs/promises";
|
|
77345
|
+
import { join as join72, relative as relative10 } from "node:path";
|
|
76500
77346
|
// src/services/file-operations/manifest/manifest-tracker.ts
|
|
76501
|
-
import { join as
|
|
77347
|
+
import { join as join71 } from "node:path";
|
|
76502
77348
|
|
|
76503
77349
|
// src/domains/migration/release-manifest.ts
|
|
76504
77350
|
init_logger();
|
|
76505
77351
|
init_zod();
|
|
76506
77352
|
var import_fs_extra13 = __toESM(require_lib3(), 1);
|
|
76507
|
-
import { join as
|
|
77353
|
+
import { join as join69 } from "node:path";
|
|
76508
77354
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
76509
77355
|
path: exports_external.string(),
|
|
76510
77356
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -76519,7 +77365,7 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
76519
77365
|
|
|
76520
77366
|
class ReleaseManifestLoader {
|
|
76521
77367
|
static async load(extractDir) {
|
|
76522
|
-
const manifestPath =
|
|
77368
|
+
const manifestPath = join69(extractDir, "release-manifest.json");
|
|
76523
77369
|
try {
|
|
76524
77370
|
const content = await import_fs_extra13.readFile(manifestPath, "utf-8");
|
|
76525
77371
|
const parsed = JSON.parse(content);
|
|
@@ -76545,9 +77391,9 @@ init_logger();
|
|
|
76545
77391
|
init_types2();
|
|
76546
77392
|
var import_fs_extra14 = __toESM(require_lib3(), 1);
|
|
76547
77393
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
76548
|
-
import { join as
|
|
77394
|
+
import { join as join70 } from "node:path";
|
|
76549
77395
|
async function writeManifest(claudeDir2, kitName, version, scope, kitType, trackedFiles, userConfigFiles) {
|
|
76550
|
-
const metadataPath =
|
|
77396
|
+
const metadataPath = join70(claudeDir2, "metadata.json");
|
|
76551
77397
|
const kit = kitType || (/\bmarketing\b/i.test(kitName) ? "marketing" : "engineer");
|
|
76552
77398
|
await import_fs_extra14.ensureFile(metadataPath);
|
|
76553
77399
|
let release = null;
|
|
@@ -76603,7 +77449,7 @@ async function writeManifest(claudeDir2, kitName, version, scope, kitType, track
|
|
|
76603
77449
|
}
|
|
76604
77450
|
}
|
|
76605
77451
|
async function removeKitFromManifest(claudeDir2, kit) {
|
|
76606
|
-
const metadataPath =
|
|
77452
|
+
const metadataPath = join70(claudeDir2, "metadata.json");
|
|
76607
77453
|
if (!await import_fs_extra14.pathExists(metadataPath))
|
|
76608
77454
|
return false;
|
|
76609
77455
|
let release = null;
|
|
@@ -76733,7 +77579,7 @@ function buildFileTrackingList(options2) {
|
|
|
76733
77579
|
if (!isGlobal && !installedPath.startsWith(".claude/"))
|
|
76734
77580
|
continue;
|
|
76735
77581
|
const relativePath = isGlobal ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
76736
|
-
const filePath =
|
|
77582
|
+
const filePath = join71(claudeDir2, relativePath);
|
|
76737
77583
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
76738
77584
|
const ownership = manifestEntry ? "ck" : "user";
|
|
76739
77585
|
filesToTrack.push({
|
|
@@ -76823,7 +77669,7 @@ class LegacyMigration {
|
|
|
76823
77669
|
const files = [];
|
|
76824
77670
|
let entries;
|
|
76825
77671
|
try {
|
|
76826
|
-
entries = await
|
|
77672
|
+
entries = await readdir15(dir);
|
|
76827
77673
|
} catch (err) {
|
|
76828
77674
|
const error = err;
|
|
76829
77675
|
if (error.code === "ENOENT") {
|
|
@@ -76840,7 +77686,7 @@ class LegacyMigration {
|
|
|
76840
77686
|
continue;
|
|
76841
77687
|
if (SKIP_DIRS_ALL.includes(entry))
|
|
76842
77688
|
continue;
|
|
76843
|
-
const fullPath =
|
|
77689
|
+
const fullPath = join72(dir, entry);
|
|
76844
77690
|
let stats;
|
|
76845
77691
|
try {
|
|
76846
77692
|
stats = await stat14(fullPath);
|
|
@@ -76942,7 +77788,7 @@ User-created files (sample):`);
|
|
|
76942
77788
|
];
|
|
76943
77789
|
if (filesToChecksum.length > 0) {
|
|
76944
77790
|
const checksumResults = await mapWithLimit(filesToChecksum, async ({ relativePath, ownership }) => {
|
|
76945
|
-
const fullPath =
|
|
77791
|
+
const fullPath = join72(claudeDir2, relativePath);
|
|
76946
77792
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
76947
77793
|
return { relativePath, checksum, ownership };
|
|
76948
77794
|
});
|
|
@@ -76963,7 +77809,7 @@ User-created files (sample):`);
|
|
|
76963
77809
|
installedAt: new Date().toISOString(),
|
|
76964
77810
|
files: trackedFiles
|
|
76965
77811
|
};
|
|
76966
|
-
const metadataPath =
|
|
77812
|
+
const metadataPath = join72(claudeDir2, "metadata.json");
|
|
76967
77813
|
await import_fs_extra15.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
76968
77814
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
76969
77815
|
return true;
|
|
@@ -77069,7 +77915,7 @@ function buildConflictSummary(fileConflicts, hookConflicts, mcpConflicts) {
|
|
|
77069
77915
|
init_logger();
|
|
77070
77916
|
init_skip_directories();
|
|
77071
77917
|
var import_fs_extra16 = __toESM(require_lib3(), 1);
|
|
77072
|
-
import { join as
|
|
77918
|
+
import { join as join73, relative as relative11, resolve as resolve14 } from "node:path";
|
|
77073
77919
|
|
|
77074
77920
|
class FileScanner2 {
|
|
77075
77921
|
static async getFiles(dirPath, relativeTo) {
|
|
@@ -77085,7 +77931,7 @@ class FileScanner2 {
|
|
|
77085
77931
|
logger.debug(`Skipping directory: ${entry}`);
|
|
77086
77932
|
continue;
|
|
77087
77933
|
}
|
|
77088
|
-
const fullPath =
|
|
77934
|
+
const fullPath = join73(dirPath, entry);
|
|
77089
77935
|
if (!FileScanner2.isSafePath(basePath, fullPath)) {
|
|
77090
77936
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
77091
77937
|
continue;
|
|
@@ -77120,8 +77966,8 @@ class FileScanner2 {
|
|
|
77120
77966
|
return files;
|
|
77121
77967
|
}
|
|
77122
77968
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
77123
|
-
const destSubDir =
|
|
77124
|
-
const sourceSubDir =
|
|
77969
|
+
const destSubDir = join73(destDir, subPath);
|
|
77970
|
+
const sourceSubDir = join73(sourceDir, subPath);
|
|
77125
77971
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
77126
77972
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
77127
77973
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -77149,8 +77995,8 @@ class FileScanner2 {
|
|
|
77149
77995
|
return customFiles;
|
|
77150
77996
|
}
|
|
77151
77997
|
static isSafePath(basePath, targetPath) {
|
|
77152
|
-
const resolvedBase =
|
|
77153
|
-
const resolvedTarget =
|
|
77998
|
+
const resolvedBase = resolve14(basePath);
|
|
77999
|
+
const resolvedTarget = resolve14(targetPath);
|
|
77154
78000
|
return resolvedTarget.startsWith(resolvedBase);
|
|
77155
78001
|
}
|
|
77156
78002
|
static toPosixPath(path12) {
|
|
@@ -77161,13 +78007,13 @@ class FileScanner2 {
|
|
|
77161
78007
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
77162
78008
|
init_logger();
|
|
77163
78009
|
var import_fs_extra17 = __toESM(require_lib3(), 1);
|
|
77164
|
-
import { lstat as lstat7, mkdir as mkdir22, readdir as
|
|
77165
|
-
import { join as
|
|
78010
|
+
import { lstat as lstat7, mkdir as mkdir22, readdir as readdir18, stat as stat15 } from "node:fs/promises";
|
|
78011
|
+
import { join as join75 } from "node:path";
|
|
77166
78012
|
|
|
77167
78013
|
// src/services/transformers/commands-prefix/content-transformer.ts
|
|
77168
78014
|
init_logger();
|
|
77169
|
-
import { readFile as readFile33, readdir as
|
|
77170
|
-
import { join as
|
|
78015
|
+
import { readFile as readFile33, readdir as readdir17, writeFile as writeFile21 } from "node:fs/promises";
|
|
78016
|
+
import { join as join74 } from "node:path";
|
|
77171
78017
|
var TRANSFORMABLE_EXTENSIONS = new Set([
|
|
77172
78018
|
".md",
|
|
77173
78019
|
".txt",
|
|
@@ -77226,9 +78072,9 @@ async function transformCommandReferences(directory, options2 = {}) {
|
|
|
77226
78072
|
let filesTransformed = 0;
|
|
77227
78073
|
let totalReplacements = 0;
|
|
77228
78074
|
async function processDirectory(dir) {
|
|
77229
|
-
const entries = await
|
|
78075
|
+
const entries = await readdir17(dir, { withFileTypes: true });
|
|
77230
78076
|
for (const entry of entries) {
|
|
77231
|
-
const fullPath =
|
|
78077
|
+
const fullPath = join74(dir, entry.name);
|
|
77232
78078
|
if (entry.isDirectory()) {
|
|
77233
78079
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
77234
78080
|
continue;
|
|
@@ -77303,22 +78149,22 @@ function shouldApplyPrefix(options2) {
|
|
|
77303
78149
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
77304
78150
|
async function applyPrefix(extractDir) {
|
|
77305
78151
|
validatePath(extractDir, "extractDir");
|
|
77306
|
-
const commandsDir =
|
|
78152
|
+
const commandsDir = join75(extractDir, ".claude", "commands");
|
|
77307
78153
|
if (!await import_fs_extra17.pathExists(commandsDir)) {
|
|
77308
78154
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
77309
78155
|
return;
|
|
77310
78156
|
}
|
|
77311
78157
|
logger.info("Applying /ck: prefix to slash commands...");
|
|
77312
|
-
const backupDir =
|
|
77313
|
-
const tempDir =
|
|
78158
|
+
const backupDir = join75(extractDir, ".commands-backup");
|
|
78159
|
+
const tempDir = join75(extractDir, ".commands-prefix-temp");
|
|
77314
78160
|
try {
|
|
77315
|
-
const entries = await
|
|
78161
|
+
const entries = await readdir18(commandsDir);
|
|
77316
78162
|
if (entries.length === 0) {
|
|
77317
78163
|
logger.verbose("Commands directory is empty, skipping prefix application");
|
|
77318
78164
|
return;
|
|
77319
78165
|
}
|
|
77320
78166
|
if (entries.length === 1 && entries[0] === "ck") {
|
|
77321
|
-
const ckDir2 =
|
|
78167
|
+
const ckDir2 = join75(commandsDir, "ck");
|
|
77322
78168
|
const ckStat = await stat15(ckDir2);
|
|
77323
78169
|
if (ckStat.isDirectory()) {
|
|
77324
78170
|
logger.verbose("Commands already have /ck: prefix, skipping");
|
|
@@ -77328,17 +78174,17 @@ async function applyPrefix(extractDir) {
|
|
|
77328
78174
|
await import_fs_extra17.copy(commandsDir, backupDir);
|
|
77329
78175
|
logger.verbose("Created backup of commands directory");
|
|
77330
78176
|
await mkdir22(tempDir, { recursive: true });
|
|
77331
|
-
const ckDir =
|
|
78177
|
+
const ckDir = join75(tempDir, "ck");
|
|
77332
78178
|
await mkdir22(ckDir, { recursive: true });
|
|
77333
78179
|
let processedCount = 0;
|
|
77334
78180
|
for (const entry of entries) {
|
|
77335
|
-
const sourcePath =
|
|
78181
|
+
const sourcePath = join75(commandsDir, entry);
|
|
77336
78182
|
const stats = await lstat7(sourcePath);
|
|
77337
78183
|
if (stats.isSymbolicLink()) {
|
|
77338
78184
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
77339
78185
|
continue;
|
|
77340
78186
|
}
|
|
77341
|
-
const destPath =
|
|
78187
|
+
const destPath = join75(ckDir, entry);
|
|
77342
78188
|
await import_fs_extra17.copy(sourcePath, destPath, {
|
|
77343
78189
|
overwrite: false,
|
|
77344
78190
|
errorOnExist: true
|
|
@@ -77356,7 +78202,7 @@ async function applyPrefix(extractDir) {
|
|
|
77356
78202
|
await import_fs_extra17.move(tempDir, commandsDir);
|
|
77357
78203
|
await import_fs_extra17.remove(backupDir);
|
|
77358
78204
|
logger.success("Successfully reorganized commands to /ck: prefix");
|
|
77359
|
-
const claudeDir2 =
|
|
78205
|
+
const claudeDir2 = join75(extractDir, ".claude");
|
|
77360
78206
|
logger.info("Transforming command references in file contents...");
|
|
77361
78207
|
const transformResult = await transformCommandReferences(claudeDir2, {
|
|
77362
78208
|
verbose: logger.isVerbose()
|
|
@@ -77393,21 +78239,21 @@ async function applyPrefix(extractDir) {
|
|
|
77393
78239
|
|
|
77394
78240
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
77395
78241
|
init_metadata_migration();
|
|
77396
|
-
import { lstat as lstat9, readdir as
|
|
77397
|
-
import { join as
|
|
78242
|
+
import { lstat as lstat9, readdir as readdir20 } from "node:fs/promises";
|
|
78243
|
+
import { join as join77 } from "node:path";
|
|
77398
78244
|
init_logger();
|
|
77399
78245
|
var import_fs_extra19 = __toESM(require_lib3(), 1);
|
|
77400
78246
|
|
|
77401
78247
|
// src/services/transformers/commands-prefix/file-processor.ts
|
|
77402
|
-
import { lstat as lstat8, readdir as
|
|
77403
|
-
import { join as
|
|
78248
|
+
import { lstat as lstat8, readdir as readdir19 } from "node:fs/promises";
|
|
78249
|
+
import { join as join76 } from "node:path";
|
|
77404
78250
|
init_logger();
|
|
77405
78251
|
var import_fs_extra18 = __toESM(require_lib3(), 1);
|
|
77406
78252
|
async function scanDirectoryFiles(dir) {
|
|
77407
78253
|
const files = [];
|
|
77408
|
-
const entries = await
|
|
78254
|
+
const entries = await readdir19(dir);
|
|
77409
78255
|
for (const entry of entries) {
|
|
77410
|
-
const fullPath =
|
|
78256
|
+
const fullPath = join76(dir, entry);
|
|
77411
78257
|
const stats = await lstat8(fullPath);
|
|
77412
78258
|
if (stats.isSymbolicLink()) {
|
|
77413
78259
|
continue;
|
|
@@ -77535,8 +78381,8 @@ function isDifferentKitDirectory(dirName, currentKit) {
|
|
|
77535
78381
|
async function cleanupCommandsDirectory(targetDir, isGlobal, options2 = {}) {
|
|
77536
78382
|
const { dryRun = false } = options2;
|
|
77537
78383
|
validatePath(targetDir, "targetDir");
|
|
77538
|
-
const claudeDir2 = isGlobal ? targetDir :
|
|
77539
|
-
const commandsDir =
|
|
78384
|
+
const claudeDir2 = isGlobal ? targetDir : join77(targetDir, ".claude");
|
|
78385
|
+
const commandsDir = join77(claudeDir2, "commands");
|
|
77540
78386
|
const accumulator = {
|
|
77541
78387
|
results: [],
|
|
77542
78388
|
deletedCount: 0,
|
|
@@ -77571,14 +78417,14 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options2 = {}) {
|
|
|
77571
78417
|
if (options2.kitType) {
|
|
77572
78418
|
logger.verbose(`Kit-aware cleanup: only cleaning files owned by '${options2.kitType}'`);
|
|
77573
78419
|
}
|
|
77574
|
-
const entries = await
|
|
78420
|
+
const entries = await readdir20(commandsDir);
|
|
77575
78421
|
if (entries.length === 0) {
|
|
77576
78422
|
logger.verbose("Commands directory is empty");
|
|
77577
78423
|
return result;
|
|
77578
78424
|
}
|
|
77579
78425
|
const metadataForChecks = options2.kitType ? createKitSpecificMetadata(metadata, options2.kitType) : metadata;
|
|
77580
78426
|
for (const entry of entries) {
|
|
77581
|
-
const entryPath =
|
|
78427
|
+
const entryPath = join77(commandsDir, entry);
|
|
77582
78428
|
const stats = await lstat9(entryPath);
|
|
77583
78429
|
if (stats.isSymbolicLink()) {
|
|
77584
78430
|
addSymlinkSkip(entry, accumulator);
|
|
@@ -77635,7 +78481,7 @@ async function handleMerge(ctx) {
|
|
|
77635
78481
|
let customClaudeFiles = [];
|
|
77636
78482
|
if (!ctx.options.fresh) {
|
|
77637
78483
|
logger.info("Scanning for custom .claude files...");
|
|
77638
|
-
const scanSourceDir = ctx.options.global ?
|
|
78484
|
+
const scanSourceDir = ctx.options.global ? join78(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
77639
78485
|
const scanTargetSubdir = ctx.options.global ? "" : ".claude";
|
|
77640
78486
|
customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
77641
78487
|
} else {
|
|
@@ -77700,7 +78546,7 @@ async function handleMerge(ctx) {
|
|
|
77700
78546
|
return { ...ctx, cancelled: true };
|
|
77701
78547
|
}
|
|
77702
78548
|
}
|
|
77703
|
-
const sourceDir = ctx.options.global ?
|
|
78549
|
+
const sourceDir = ctx.options.global ? join78(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
77704
78550
|
await merger.merge(sourceDir, ctx.resolvedDir, ctx.isNonInteractive);
|
|
77705
78551
|
const fileConflicts = merger.getFileConflicts();
|
|
77706
78552
|
if (fileConflicts.length > 0 && !ctx.isNonInteractive) {
|
|
@@ -77708,7 +78554,7 @@ async function handleMerge(ctx) {
|
|
|
77708
78554
|
displayConflictSummary(summary);
|
|
77709
78555
|
}
|
|
77710
78556
|
try {
|
|
77711
|
-
const sourceMetadataPath = ctx.options.global ?
|
|
78557
|
+
const sourceMetadataPath = ctx.options.global ? join78(sourceDir, "metadata.json") : join78(sourceDir, ".claude", "metadata.json");
|
|
77712
78558
|
if (await import_fs_extra20.pathExists(sourceMetadataPath)) {
|
|
77713
78559
|
const metadataContent = await import_fs_extra20.readFile(sourceMetadataPath, "utf-8");
|
|
77714
78560
|
const sourceMetadata = JSON.parse(metadataContent);
|
|
@@ -77752,7 +78598,7 @@ async function handleMerge(ctx) {
|
|
|
77752
78598
|
};
|
|
77753
78599
|
}
|
|
77754
78600
|
// src/commands/init/phases/migration-handler.ts
|
|
77755
|
-
import { join as
|
|
78601
|
+
import { join as join86 } from "node:path";
|
|
77756
78602
|
|
|
77757
78603
|
// src/domains/skills/skills-detector.ts
|
|
77758
78604
|
init_logger();
|
|
@@ -77767,8 +78613,8 @@ init_skip_directories();
|
|
|
77767
78613
|
init_types2();
|
|
77768
78614
|
var import_fs_extra21 = __toESM(require_lib3(), 1);
|
|
77769
78615
|
import { createHash as createHash2 } from "node:crypto";
|
|
77770
|
-
import { readFile as readFile35, readdir as
|
|
77771
|
-
import { join as
|
|
78616
|
+
import { readFile as readFile35, readdir as readdir21, writeFile as writeFile22 } from "node:fs/promises";
|
|
78617
|
+
import { join as join79, relative as relative12 } from "node:path";
|
|
77772
78618
|
|
|
77773
78619
|
class SkillsManifestManager {
|
|
77774
78620
|
static MANIFEST_FILENAME = ".skills-manifest.json";
|
|
@@ -77790,12 +78636,12 @@ class SkillsManifestManager {
|
|
|
77790
78636
|
return manifest;
|
|
77791
78637
|
}
|
|
77792
78638
|
static async writeManifest(skillsDir2, manifest) {
|
|
77793
|
-
const manifestPath =
|
|
78639
|
+
const manifestPath = join79(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
|
|
77794
78640
|
await writeFile22(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
77795
78641
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
77796
78642
|
}
|
|
77797
78643
|
static async readManifest(skillsDir2) {
|
|
77798
|
-
const manifestPath =
|
|
78644
|
+
const manifestPath = join79(skillsDir2, SkillsManifestManager.MANIFEST_FILENAME);
|
|
77799
78645
|
if (!await import_fs_extra21.pathExists(manifestPath)) {
|
|
77800
78646
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
77801
78647
|
return null;
|
|
@@ -77812,14 +78658,14 @@ class SkillsManifestManager {
|
|
|
77812
78658
|
}
|
|
77813
78659
|
}
|
|
77814
78660
|
static async detectStructure(skillsDir2) {
|
|
77815
|
-
const entries = await
|
|
78661
|
+
const entries = await readdir21(skillsDir2, { withFileTypes: true });
|
|
77816
78662
|
const dirs = entries.filter((entry) => entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith("."));
|
|
77817
78663
|
if (dirs.length === 0) {
|
|
77818
78664
|
return "flat";
|
|
77819
78665
|
}
|
|
77820
78666
|
for (const dir of dirs.slice(0, 3)) {
|
|
77821
|
-
const dirPath =
|
|
77822
|
-
const subEntries = await
|
|
78667
|
+
const dirPath = join79(skillsDir2, dir.name);
|
|
78668
|
+
const subEntries = await readdir21(dirPath, { withFileTypes: true });
|
|
77823
78669
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
77824
78670
|
if (hasSubdirs) {
|
|
77825
78671
|
return "categorized";
|
|
@@ -77834,10 +78680,10 @@ class SkillsManifestManager {
|
|
|
77834
78680
|
static async scanSkills(skillsDir2, structure) {
|
|
77835
78681
|
const skills = [];
|
|
77836
78682
|
if (structure === "flat") {
|
|
77837
|
-
const entries = await
|
|
78683
|
+
const entries = await readdir21(skillsDir2, { withFileTypes: true });
|
|
77838
78684
|
for (const entry of entries) {
|
|
77839
78685
|
if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
|
|
77840
|
-
const skillPath =
|
|
78686
|
+
const skillPath = join79(skillsDir2, entry.name);
|
|
77841
78687
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
77842
78688
|
skills.push({
|
|
77843
78689
|
name: entry.name,
|
|
@@ -77846,14 +78692,14 @@ class SkillsManifestManager {
|
|
|
77846
78692
|
}
|
|
77847
78693
|
}
|
|
77848
78694
|
} else {
|
|
77849
|
-
const categories = await
|
|
78695
|
+
const categories = await readdir21(skillsDir2, { withFileTypes: true });
|
|
77850
78696
|
for (const category of categories) {
|
|
77851
78697
|
if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
|
|
77852
|
-
const categoryPath =
|
|
77853
|
-
const skillEntries = await
|
|
78698
|
+
const categoryPath = join79(skillsDir2, category.name);
|
|
78699
|
+
const skillEntries = await readdir21(categoryPath, { withFileTypes: true });
|
|
77854
78700
|
for (const skillEntry of skillEntries) {
|
|
77855
78701
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
77856
|
-
const skillPath =
|
|
78702
|
+
const skillPath = join79(categoryPath, skillEntry.name);
|
|
77857
78703
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
77858
78704
|
skills.push({
|
|
77859
78705
|
name: skillEntry.name,
|
|
@@ -77881,9 +78727,9 @@ class SkillsManifestManager {
|
|
|
77881
78727
|
}
|
|
77882
78728
|
static async getAllFiles(dirPath) {
|
|
77883
78729
|
const files = [];
|
|
77884
|
-
const entries = await
|
|
78730
|
+
const entries = await readdir21(dirPath, { withFileTypes: true });
|
|
77885
78731
|
for (const entry of entries) {
|
|
77886
|
-
const fullPath =
|
|
78732
|
+
const fullPath = join79(dirPath, entry.name);
|
|
77887
78733
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
|
|
77888
78734
|
continue;
|
|
77889
78735
|
}
|
|
@@ -78004,13 +78850,13 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
78004
78850
|
|
|
78005
78851
|
// src/domains/skills/detection/script-detector.ts
|
|
78006
78852
|
var import_fs_extra22 = __toESM(require_lib3(), 1);
|
|
78007
|
-
import { readdir as
|
|
78008
|
-
import { join as
|
|
78853
|
+
import { readdir as readdir22 } from "node:fs/promises";
|
|
78854
|
+
import { join as join80 } from "node:path";
|
|
78009
78855
|
async function scanDirectory(skillsDir2) {
|
|
78010
78856
|
if (!await import_fs_extra22.pathExists(skillsDir2)) {
|
|
78011
78857
|
return ["flat", []];
|
|
78012
78858
|
}
|
|
78013
|
-
const entries = await
|
|
78859
|
+
const entries = await readdir22(skillsDir2, { withFileTypes: true });
|
|
78014
78860
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
78015
78861
|
if (dirs.length === 0) {
|
|
78016
78862
|
return ["flat", []];
|
|
@@ -78018,13 +78864,13 @@ async function scanDirectory(skillsDir2) {
|
|
|
78018
78864
|
let totalSkillLikeCount = 0;
|
|
78019
78865
|
const allSkills = [];
|
|
78020
78866
|
for (const dir of dirs) {
|
|
78021
|
-
const dirPath =
|
|
78022
|
-
const subEntries = await
|
|
78867
|
+
const dirPath = join80(skillsDir2, dir.name);
|
|
78868
|
+
const subEntries = await readdir22(dirPath, { withFileTypes: true });
|
|
78023
78869
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
78024
78870
|
if (subdirs.length > 0) {
|
|
78025
78871
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
78026
|
-
const subdirPath =
|
|
78027
|
-
const subdirFiles = await
|
|
78872
|
+
const subdirPath = join80(dirPath, subdir.name);
|
|
78873
|
+
const subdirFiles = await readdir22(subdirPath, { withFileTypes: true });
|
|
78028
78874
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
78029
78875
|
if (hasSkillMarker) {
|
|
78030
78876
|
totalSkillLikeCount++;
|
|
@@ -78180,12 +79026,12 @@ class SkillsMigrationDetector {
|
|
|
78180
79026
|
// src/domains/skills/skills-migrator.ts
|
|
78181
79027
|
init_logger();
|
|
78182
79028
|
init_types2();
|
|
78183
|
-
import { join as
|
|
79029
|
+
import { join as join85 } from "node:path";
|
|
78184
79030
|
|
|
78185
79031
|
// src/domains/skills/migrator/migration-executor.ts
|
|
78186
79032
|
init_logger();
|
|
78187
|
-
import { copyFile as copyFile5, mkdir as mkdir23, readdir as
|
|
78188
|
-
import { join as
|
|
79033
|
+
import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir23, rm as rm5 } from "node:fs/promises";
|
|
79034
|
+
import { join as join81 } from "node:path";
|
|
78189
79035
|
var import_fs_extra24 = __toESM(require_lib3(), 1);
|
|
78190
79036
|
|
|
78191
79037
|
// src/domains/skills/skills-migration-prompts.ts
|
|
@@ -78348,10 +79194,10 @@ Detected changes:`;
|
|
|
78348
79194
|
// src/domains/skills/migrator/migration-executor.ts
|
|
78349
79195
|
async function copySkillDirectory(sourceDir, destDir) {
|
|
78350
79196
|
await mkdir23(destDir, { recursive: true });
|
|
78351
|
-
const entries = await
|
|
79197
|
+
const entries = await readdir23(sourceDir, { withFileTypes: true });
|
|
78352
79198
|
for (const entry of entries) {
|
|
78353
|
-
const sourcePath =
|
|
78354
|
-
const destPath =
|
|
79199
|
+
const sourcePath = join81(sourceDir, entry.name);
|
|
79200
|
+
const destPath = join81(destDir, entry.name);
|
|
78355
79201
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
78356
79202
|
continue;
|
|
78357
79203
|
}
|
|
@@ -78366,7 +79212,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
78366
79212
|
const migrated = [];
|
|
78367
79213
|
const preserved = [];
|
|
78368
79214
|
const errors2 = [];
|
|
78369
|
-
const tempDir =
|
|
79215
|
+
const tempDir = join81(currentSkillsDir, "..", ".skills-migration-temp");
|
|
78370
79216
|
await mkdir23(tempDir, { recursive: true });
|
|
78371
79217
|
try {
|
|
78372
79218
|
for (const mapping of mappings) {
|
|
@@ -78387,9 +79233,9 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
78387
79233
|
}
|
|
78388
79234
|
}
|
|
78389
79235
|
const category = mapping.category;
|
|
78390
|
-
const targetPath = category ?
|
|
79236
|
+
const targetPath = category ? join81(tempDir, category, skillName) : join81(tempDir, skillName);
|
|
78391
79237
|
if (category) {
|
|
78392
|
-
await mkdir23(
|
|
79238
|
+
await mkdir23(join81(tempDir, category), { recursive: true });
|
|
78393
79239
|
}
|
|
78394
79240
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
78395
79241
|
migrated.push(skillName);
|
|
@@ -78455,8 +79301,8 @@ function validateMigrationPath(path12, paramName) {
|
|
|
78455
79301
|
init_logger();
|
|
78456
79302
|
init_types2();
|
|
78457
79303
|
var import_fs_extra25 = __toESM(require_lib3(), 1);
|
|
78458
|
-
import { copyFile as copyFile6, mkdir as mkdir24, readdir as
|
|
78459
|
-
import { basename as basename8, join as
|
|
79304
|
+
import { copyFile as copyFile6, mkdir as mkdir24, readdir as readdir24, rm as rm6, stat as stat16 } from "node:fs/promises";
|
|
79305
|
+
import { basename as basename8, join as join82, normalize as normalize8 } from "node:path";
|
|
78460
79306
|
function validatePath2(path12, paramName) {
|
|
78461
79307
|
if (!path12 || typeof path12 !== "string") {
|
|
78462
79308
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -78482,7 +79328,7 @@ class SkillsBackupManager {
|
|
|
78482
79328
|
const timestamp = Date.now();
|
|
78483
79329
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
78484
79330
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
78485
|
-
const backupDir = parentDir ?
|
|
79331
|
+
const backupDir = parentDir ? join82(parentDir, backupDirName) : join82(skillsDir2, "..", backupDirName);
|
|
78486
79332
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
78487
79333
|
try {
|
|
78488
79334
|
await mkdir24(backupDir, { recursive: true });
|
|
@@ -78532,8 +79378,8 @@ class SkillsBackupManager {
|
|
|
78532
79378
|
return [];
|
|
78533
79379
|
}
|
|
78534
79380
|
try {
|
|
78535
|
-
const entries = await
|
|
78536
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
79381
|
+
const entries = await readdir24(parentDir, { withFileTypes: true });
|
|
79382
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join82(parentDir, entry.name));
|
|
78537
79383
|
backups.sort().reverse();
|
|
78538
79384
|
return backups;
|
|
78539
79385
|
} catch (error) {
|
|
@@ -78559,10 +79405,10 @@ class SkillsBackupManager {
|
|
|
78559
79405
|
return await SkillsBackupManager.getDirectorySize(backupDir);
|
|
78560
79406
|
}
|
|
78561
79407
|
static async copyDirectory(sourceDir, destDir) {
|
|
78562
|
-
const entries = await
|
|
79408
|
+
const entries = await readdir24(sourceDir, { withFileTypes: true });
|
|
78563
79409
|
for (const entry of entries) {
|
|
78564
|
-
const sourcePath =
|
|
78565
|
-
const destPath =
|
|
79410
|
+
const sourcePath = join82(sourceDir, entry.name);
|
|
79411
|
+
const destPath = join82(destDir, entry.name);
|
|
78566
79412
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
78567
79413
|
continue;
|
|
78568
79414
|
}
|
|
@@ -78576,9 +79422,9 @@ class SkillsBackupManager {
|
|
|
78576
79422
|
}
|
|
78577
79423
|
static async getDirectorySize(dirPath) {
|
|
78578
79424
|
let size = 0;
|
|
78579
|
-
const entries = await
|
|
79425
|
+
const entries = await readdir24(dirPath, { withFileTypes: true });
|
|
78580
79426
|
for (const entry of entries) {
|
|
78581
|
-
const fullPath =
|
|
79427
|
+
const fullPath = join82(dirPath, entry.name);
|
|
78582
79428
|
if (entry.isSymbolicLink()) {
|
|
78583
79429
|
continue;
|
|
78584
79430
|
}
|
|
@@ -78613,13 +79459,13 @@ import { relative as relative14 } from "node:path";
|
|
|
78613
79459
|
init_skip_directories();
|
|
78614
79460
|
import { createHash as createHash3 } from "node:crypto";
|
|
78615
79461
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
78616
|
-
import { readFile as readFile36, readdir as
|
|
78617
|
-
import { join as
|
|
79462
|
+
import { readFile as readFile36, readdir as readdir25 } from "node:fs/promises";
|
|
79463
|
+
import { join as join83, relative as relative13 } from "node:path";
|
|
78618
79464
|
async function getAllFiles(dirPath) {
|
|
78619
79465
|
const files = [];
|
|
78620
|
-
const entries = await
|
|
79466
|
+
const entries = await readdir25(dirPath, { withFileTypes: true });
|
|
78621
79467
|
for (const entry of entries) {
|
|
78622
|
-
const fullPath =
|
|
79468
|
+
const fullPath = join83(dirPath, entry.name);
|
|
78623
79469
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
|
|
78624
79470
|
continue;
|
|
78625
79471
|
}
|
|
@@ -78633,12 +79479,12 @@ async function getAllFiles(dirPath) {
|
|
|
78633
79479
|
return files;
|
|
78634
79480
|
}
|
|
78635
79481
|
async function hashFile(filePath) {
|
|
78636
|
-
return new Promise((
|
|
79482
|
+
return new Promise((resolve15, reject) => {
|
|
78637
79483
|
const hash = createHash3("sha256");
|
|
78638
79484
|
const stream = createReadStream3(filePath);
|
|
78639
79485
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
78640
79486
|
stream.on("end", () => {
|
|
78641
|
-
|
|
79487
|
+
resolve15(hash.digest("hex"));
|
|
78642
79488
|
});
|
|
78643
79489
|
stream.on("error", (error) => {
|
|
78644
79490
|
stream.destroy();
|
|
@@ -78745,8 +79591,8 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
|
78745
79591
|
// src/domains/skills/customization/scan-reporter.ts
|
|
78746
79592
|
init_types2();
|
|
78747
79593
|
var import_fs_extra27 = __toESM(require_lib3(), 1);
|
|
78748
|
-
import { readdir as
|
|
78749
|
-
import { join as
|
|
79594
|
+
import { readdir as readdir26 } from "node:fs/promises";
|
|
79595
|
+
import { join as join84, normalize as normalize9 } from "node:path";
|
|
78750
79596
|
function validatePath3(path12, paramName) {
|
|
78751
79597
|
if (!path12 || typeof path12 !== "string") {
|
|
78752
79598
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -78762,19 +79608,19 @@ async function scanSkillsDirectory(skillsDir2) {
|
|
|
78762
79608
|
if (!await import_fs_extra27.pathExists(skillsDir2)) {
|
|
78763
79609
|
return ["flat", []];
|
|
78764
79610
|
}
|
|
78765
|
-
const entries = await
|
|
79611
|
+
const entries = await readdir26(skillsDir2, { withFileTypes: true });
|
|
78766
79612
|
const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith("."));
|
|
78767
79613
|
if (dirs.length === 0) {
|
|
78768
79614
|
return ["flat", []];
|
|
78769
79615
|
}
|
|
78770
|
-
const firstDirPath =
|
|
78771
|
-
const subEntries = await
|
|
79616
|
+
const firstDirPath = join84(skillsDir2, dirs[0].name);
|
|
79617
|
+
const subEntries = await readdir26(firstDirPath, { withFileTypes: true });
|
|
78772
79618
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
78773
79619
|
if (subdirs.length > 0) {
|
|
78774
79620
|
let skillLikeCount = 0;
|
|
78775
79621
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
78776
|
-
const subdirPath =
|
|
78777
|
-
const subdirFiles = await
|
|
79622
|
+
const subdirPath = join84(firstDirPath, subdir.name);
|
|
79623
|
+
const subdirFiles = await readdir26(subdirPath, { withFileTypes: true });
|
|
78778
79624
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
78779
79625
|
if (hasSkillMarker) {
|
|
78780
79626
|
skillLikeCount++;
|
|
@@ -78783,8 +79629,8 @@ async function scanSkillsDirectory(skillsDir2) {
|
|
|
78783
79629
|
if (skillLikeCount > 0) {
|
|
78784
79630
|
const skills = [];
|
|
78785
79631
|
for (const dir of dirs) {
|
|
78786
|
-
const categoryPath =
|
|
78787
|
-
const skillDirs = await
|
|
79632
|
+
const categoryPath = join84(skillsDir2, dir.name);
|
|
79633
|
+
const skillDirs = await readdir26(categoryPath, { withFileTypes: true });
|
|
78788
79634
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
78789
79635
|
}
|
|
78790
79636
|
return ["categorized", skills];
|
|
@@ -78793,17 +79639,17 @@ async function scanSkillsDirectory(skillsDir2) {
|
|
|
78793
79639
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
78794
79640
|
}
|
|
78795
79641
|
async function findSkillPath(skillsDir2, skillName) {
|
|
78796
|
-
const flatPath =
|
|
79642
|
+
const flatPath = join84(skillsDir2, skillName);
|
|
78797
79643
|
if (await import_fs_extra27.pathExists(flatPath)) {
|
|
78798
79644
|
return { path: flatPath, category: undefined };
|
|
78799
79645
|
}
|
|
78800
|
-
const entries = await
|
|
79646
|
+
const entries = await readdir26(skillsDir2, { withFileTypes: true });
|
|
78801
79647
|
for (const entry of entries) {
|
|
78802
79648
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
78803
79649
|
continue;
|
|
78804
79650
|
}
|
|
78805
|
-
const categoryPath =
|
|
78806
|
-
const skillPath =
|
|
79651
|
+
const categoryPath = join84(skillsDir2, entry.name);
|
|
79652
|
+
const skillPath = join84(categoryPath, skillName);
|
|
78807
79653
|
if (await import_fs_extra27.pathExists(skillPath)) {
|
|
78808
79654
|
return { path: skillPath, category: entry.name };
|
|
78809
79655
|
}
|
|
@@ -78897,7 +79743,7 @@ class SkillsMigrator {
|
|
|
78897
79743
|
}
|
|
78898
79744
|
}
|
|
78899
79745
|
if (options2.backup && !options2.dryRun) {
|
|
78900
|
-
const claudeDir2 =
|
|
79746
|
+
const claudeDir2 = join85(currentSkillsDir, "..");
|
|
78901
79747
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir2);
|
|
78902
79748
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
78903
79749
|
}
|
|
@@ -78958,7 +79804,7 @@ async function handleMigration(ctx) {
|
|
|
78958
79804
|
logger.debug("Skipping skills migration (fresh installation)");
|
|
78959
79805
|
return ctx;
|
|
78960
79806
|
}
|
|
78961
|
-
const newSkillsDir =
|
|
79807
|
+
const newSkillsDir = join86(ctx.extractDir, ".claude", "skills");
|
|
78962
79808
|
const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
78963
79809
|
if (!await import_fs_extra28.pathExists(newSkillsDir) || !await import_fs_extra28.pathExists(currentSkillsDir)) {
|
|
78964
79810
|
return ctx;
|
|
@@ -78981,14 +79827,14 @@ async function handleMigration(ctx) {
|
|
|
78981
79827
|
return ctx;
|
|
78982
79828
|
}
|
|
78983
79829
|
// src/commands/init/phases/opencode-handler.ts
|
|
78984
|
-
import { cp as cp2, readdir as
|
|
78985
|
-
import { join as
|
|
79830
|
+
import { cp as cp2, readdir as readdir28, rm as rm7 } from "node:fs/promises";
|
|
79831
|
+
import { join as join88 } from "node:path";
|
|
78986
79832
|
|
|
78987
79833
|
// src/services/transformers/opencode-path-transformer.ts
|
|
78988
79834
|
init_logger();
|
|
78989
|
-
import { readFile as readFile37, readdir as
|
|
79835
|
+
import { readFile as readFile37, readdir as readdir27, writeFile as writeFile23 } from "node:fs/promises";
|
|
78990
79836
|
import { platform as platform12 } from "node:os";
|
|
78991
|
-
import { extname as extname3, join as
|
|
79837
|
+
import { extname as extname3, join as join87 } from "node:path";
|
|
78992
79838
|
var IS_WINDOWS3 = platform12() === "win32";
|
|
78993
79839
|
function getOpenCodeGlobalPath() {
|
|
78994
79840
|
return "$HOME/.config/opencode/";
|
|
@@ -79047,9 +79893,9 @@ async function transformPathsForGlobalOpenCode(directory, options2 = {}) {
|
|
|
79047
79893
|
let totalChanges = 0;
|
|
79048
79894
|
let filesSkipped = 0;
|
|
79049
79895
|
async function processDirectory2(dir) {
|
|
79050
|
-
const entries = await
|
|
79896
|
+
const entries = await readdir27(dir, { withFileTypes: true });
|
|
79051
79897
|
for (const entry of entries) {
|
|
79052
|
-
const fullPath =
|
|
79898
|
+
const fullPath = join87(dir, entry.name);
|
|
79053
79899
|
if (entry.isDirectory()) {
|
|
79054
79900
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) {
|
|
79055
79901
|
continue;
|
|
@@ -79088,7 +79934,7 @@ async function handleOpenCode(ctx) {
|
|
|
79088
79934
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
|
|
79089
79935
|
return ctx;
|
|
79090
79936
|
}
|
|
79091
|
-
const openCodeSource =
|
|
79937
|
+
const openCodeSource = join88(ctx.extractDir, ".opencode");
|
|
79092
79938
|
if (!await import_fs_extra29.pathExists(openCodeSource)) {
|
|
79093
79939
|
logger.debug("No .opencode directory in archive, skipping");
|
|
79094
79940
|
return ctx;
|
|
@@ -79104,10 +79950,10 @@ async function handleOpenCode(ctx) {
|
|
|
79104
79950
|
logger.success(`Transformed ${transformResult.totalChanges} OpenCode path(s) in ${transformResult.filesTransformed} file(s)`);
|
|
79105
79951
|
}
|
|
79106
79952
|
await import_fs_extra29.ensureDir(targetDir);
|
|
79107
|
-
const entries = await
|
|
79953
|
+
const entries = await readdir28(openCodeSource, { withFileTypes: true });
|
|
79108
79954
|
for (const entry of entries) {
|
|
79109
|
-
const sourcePath =
|
|
79110
|
-
const targetPath =
|
|
79955
|
+
const sourcePath = join88(openCodeSource, entry.name);
|
|
79956
|
+
const targetPath = join88(targetDir, entry.name);
|
|
79111
79957
|
if (await import_fs_extra29.pathExists(targetPath)) {
|
|
79112
79958
|
if (!ctx.options.forceOverwrite) {
|
|
79113
79959
|
logger.verbose(`Skipping existing: ${entry.name}`);
|
|
@@ -79200,7 +80046,7 @@ Please use only one download method.`);
|
|
|
79200
80046
|
}
|
|
79201
80047
|
// src/commands/init/phases/post-install-handler.ts
|
|
79202
80048
|
init_projects_registry();
|
|
79203
|
-
import { join as
|
|
80049
|
+
import { join as join89 } from "node:path";
|
|
79204
80050
|
init_logger();
|
|
79205
80051
|
init_path_resolver();
|
|
79206
80052
|
var import_fs_extra30 = __toESM(require_lib3(), 1);
|
|
@@ -79209,8 +80055,8 @@ async function handlePostInstall(ctx) {
|
|
|
79209
80055
|
return ctx;
|
|
79210
80056
|
}
|
|
79211
80057
|
if (ctx.options.global) {
|
|
79212
|
-
const claudeMdSource =
|
|
79213
|
-
const claudeMdDest =
|
|
80058
|
+
const claudeMdSource = join89(ctx.extractDir, "CLAUDE.md");
|
|
80059
|
+
const claudeMdDest = join89(ctx.resolvedDir, "CLAUDE.md");
|
|
79214
80060
|
if (await import_fs_extra30.pathExists(claudeMdSource)) {
|
|
79215
80061
|
if (!await import_fs_extra30.pathExists(claudeMdDest)) {
|
|
79216
80062
|
await import_fs_extra30.copy(claudeMdSource, claudeMdDest);
|
|
@@ -79258,7 +80104,7 @@ async function handlePostInstall(ctx) {
|
|
|
79258
80104
|
}
|
|
79259
80105
|
if (!ctx.options.skipSetup) {
|
|
79260
80106
|
await promptSetupWizardIfNeeded({
|
|
79261
|
-
envPath:
|
|
80107
|
+
envPath: join89(ctx.claudeDir, ".env"),
|
|
79262
80108
|
claudeDir: ctx.claudeDir,
|
|
79263
80109
|
isGlobal: ctx.options.global,
|
|
79264
80110
|
isNonInteractive: ctx.isNonInteractive,
|
|
@@ -79282,7 +80128,7 @@ async function handlePostInstall(ctx) {
|
|
|
79282
80128
|
init_config_manager();
|
|
79283
80129
|
init_github_client();
|
|
79284
80130
|
import { mkdir as mkdir25 } from "node:fs/promises";
|
|
79285
|
-
import { join as
|
|
80131
|
+
import { join as join91, resolve as resolve16 } from "node:path";
|
|
79286
80132
|
|
|
79287
80133
|
// src/domains/github/kit-access-checker.ts
|
|
79288
80134
|
init_logger();
|
|
@@ -79412,8 +80258,8 @@ async function runPreflightChecks() {
|
|
|
79412
80258
|
|
|
79413
80259
|
// src/domains/installation/fresh-installer.ts
|
|
79414
80260
|
init_metadata_migration();
|
|
79415
|
-
import { existsSync as
|
|
79416
|
-
import { dirname as dirname17, join as
|
|
80261
|
+
import { existsSync as existsSync38, readdirSync as readdirSync3, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
|
|
80262
|
+
import { dirname as dirname17, join as join90, resolve as resolve15 } from "node:path";
|
|
79417
80263
|
init_logger();
|
|
79418
80264
|
init_safe_spinner();
|
|
79419
80265
|
var import_fs_extra31 = __toESM(require_lib3(), 1);
|
|
@@ -79461,15 +80307,15 @@ async function analyzeFreshInstallation(claudeDir2) {
|
|
|
79461
80307
|
};
|
|
79462
80308
|
}
|
|
79463
80309
|
function cleanupEmptyDirectories2(filePath, claudeDir2) {
|
|
79464
|
-
const normalizedClaudeDir =
|
|
79465
|
-
let currentDir =
|
|
80310
|
+
const normalizedClaudeDir = resolve15(claudeDir2);
|
|
80311
|
+
let currentDir = resolve15(dirname17(filePath));
|
|
79466
80312
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
79467
80313
|
try {
|
|
79468
80314
|
const entries = readdirSync3(currentDir);
|
|
79469
80315
|
if (entries.length === 0) {
|
|
79470
80316
|
rmdirSync2(currentDir);
|
|
79471
80317
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
79472
|
-
currentDir =
|
|
80318
|
+
currentDir = resolve15(dirname17(currentDir));
|
|
79473
80319
|
} else {
|
|
79474
80320
|
break;
|
|
79475
80321
|
}
|
|
@@ -79486,9 +80332,9 @@ async function removeFilesByOwnership(claudeDir2, analysis, includeModified) {
|
|
|
79486
80332
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
79487
80333
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
79488
80334
|
for (const file of filesToRemove) {
|
|
79489
|
-
const fullPath =
|
|
80335
|
+
const fullPath = join90(claudeDir2, file.path);
|
|
79490
80336
|
try {
|
|
79491
|
-
if (
|
|
80337
|
+
if (existsSync38(fullPath)) {
|
|
79492
80338
|
unlinkSync4(fullPath);
|
|
79493
80339
|
removedFiles.push(file.path);
|
|
79494
80340
|
logger.debug(`Removed: ${file.path}`);
|
|
@@ -79511,7 +80357,7 @@ async function removeFilesByOwnership(claudeDir2, analysis, includeModified) {
|
|
|
79511
80357
|
};
|
|
79512
80358
|
}
|
|
79513
80359
|
async function updateMetadataAfterFresh(claudeDir2, removedFiles) {
|
|
79514
|
-
const metadataPath =
|
|
80360
|
+
const metadataPath = join90(claudeDir2, "metadata.json");
|
|
79515
80361
|
if (!await import_fs_extra31.pathExists(metadataPath)) {
|
|
79516
80362
|
return;
|
|
79517
80363
|
}
|
|
@@ -79554,7 +80400,7 @@ async function removeSubdirectoriesFallback(claudeDir2) {
|
|
|
79554
80400
|
const removedFiles = [];
|
|
79555
80401
|
let removedDirCount = 0;
|
|
79556
80402
|
for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
|
|
79557
|
-
const subdirPath =
|
|
80403
|
+
const subdirPath = join90(claudeDir2, subdir);
|
|
79558
80404
|
if (await import_fs_extra31.pathExists(subdirPath)) {
|
|
79559
80405
|
rmSync3(subdirPath, { recursive: true, force: true });
|
|
79560
80406
|
removedDirCount++;
|
|
@@ -79562,7 +80408,7 @@ async function removeSubdirectoriesFallback(claudeDir2) {
|
|
|
79562
80408
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
79563
80409
|
}
|
|
79564
80410
|
}
|
|
79565
|
-
const metadataPath =
|
|
80411
|
+
const metadataPath = join90(claudeDir2, "metadata.json");
|
|
79566
80412
|
if (await import_fs_extra31.pathExists(metadataPath)) {
|
|
79567
80413
|
unlinkSync4(metadataPath);
|
|
79568
80414
|
removedFiles.push("metadata.json");
|
|
@@ -79780,7 +80626,7 @@ async function handleSelection(ctx) {
|
|
|
79780
80626
|
}
|
|
79781
80627
|
}
|
|
79782
80628
|
}
|
|
79783
|
-
const resolvedDir =
|
|
80629
|
+
const resolvedDir = resolve16(targetDir);
|
|
79784
80630
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
79785
80631
|
if (!ctx.options.global && PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
79786
80632
|
logger.warning("You're at HOME directory. Installing here modifies your GLOBAL ClaudeKit.");
|
|
@@ -79814,7 +80660,7 @@ async function handleSelection(ctx) {
|
|
|
79814
80660
|
}
|
|
79815
80661
|
if (!ctx.options.fresh) {
|
|
79816
80662
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
79817
|
-
const claudeDir2 = prefix ?
|
|
80663
|
+
const claudeDir2 = prefix ? join91(resolvedDir, prefix) : resolvedDir;
|
|
79818
80664
|
try {
|
|
79819
80665
|
const existingMetadata = await readManifest(claudeDir2);
|
|
79820
80666
|
if (existingMetadata?.kits) {
|
|
@@ -79846,7 +80692,7 @@ async function handleSelection(ctx) {
|
|
|
79846
80692
|
}
|
|
79847
80693
|
if (ctx.options.fresh) {
|
|
79848
80694
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
79849
|
-
const claudeDir2 = prefix ?
|
|
80695
|
+
const claudeDir2 = prefix ? join91(resolvedDir, prefix) : resolvedDir;
|
|
79850
80696
|
const canProceed = await handleFreshInstallation(claudeDir2, ctx.prompts);
|
|
79851
80697
|
if (!canProceed) {
|
|
79852
80698
|
return { ...ctx, cancelled: true };
|
|
@@ -79865,7 +80711,7 @@ async function handleSelection(ctx) {
|
|
|
79865
80711
|
logger.info("Fetching available versions...");
|
|
79866
80712
|
let currentVersion = null;
|
|
79867
80713
|
try {
|
|
79868
|
-
const metadataPath = ctx.options.global ?
|
|
80714
|
+
const metadataPath = ctx.options.global ? join91(PathResolver.getGlobalKitDir(), "metadata.json") : join91(resolvedDir, ".claude", "metadata.json");
|
|
79869
80715
|
const metadata = await readClaudeKitMetadata(metadataPath);
|
|
79870
80716
|
currentVersion = metadata?.version || null;
|
|
79871
80717
|
if (currentVersion) {
|
|
@@ -79940,7 +80786,7 @@ async function handleSelection(ctx) {
|
|
|
79940
80786
|
}
|
|
79941
80787
|
// src/commands/init/phases/sync-handler.ts
|
|
79942
80788
|
import { copyFile as copyFile7, mkdir as mkdir26, open as open4, readFile as readFile39, rename as rename3, stat as stat17, unlink as unlink8, writeFile as writeFile25 } from "node:fs/promises";
|
|
79943
|
-
import { dirname as dirname18, join as
|
|
80789
|
+
import { dirname as dirname18, join as join92, resolve as resolve17 } from "node:path";
|
|
79944
80790
|
init_logger();
|
|
79945
80791
|
init_path_resolver();
|
|
79946
80792
|
var import_fs_extra33 = __toESM(require_lib3(), 1);
|
|
@@ -79949,14 +80795,14 @@ async function handleSync(ctx) {
|
|
|
79949
80795
|
if (!ctx.options.sync) {
|
|
79950
80796
|
return ctx;
|
|
79951
80797
|
}
|
|
79952
|
-
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() :
|
|
79953
|
-
const claudeDir2 = ctx.options.global ? resolvedDir :
|
|
80798
|
+
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve17(ctx.options.dir || ".");
|
|
80799
|
+
const claudeDir2 = ctx.options.global ? resolvedDir : join92(resolvedDir, ".claude");
|
|
79954
80800
|
if (!await import_fs_extra33.pathExists(claudeDir2)) {
|
|
79955
80801
|
logger.error("Cannot sync: no .claude directory found");
|
|
79956
80802
|
ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
|
|
79957
80803
|
return { ...ctx, cancelled: true };
|
|
79958
80804
|
}
|
|
79959
|
-
const metadataPath =
|
|
80805
|
+
const metadataPath = join92(claudeDir2, "metadata.json");
|
|
79960
80806
|
if (!await import_fs_extra33.pathExists(metadataPath)) {
|
|
79961
80807
|
logger.error("Cannot sync: no metadata.json found");
|
|
79962
80808
|
ctx.prompts.note(`Your installation may be from an older version.
|
|
@@ -80056,7 +80902,7 @@ function getLockTimeout() {
|
|
|
80056
80902
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
80057
80903
|
async function acquireSyncLock(global3) {
|
|
80058
80904
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
80059
|
-
const lockPath =
|
|
80905
|
+
const lockPath = join92(cacheDir, ".sync-lock");
|
|
80060
80906
|
const startTime = Date.now();
|
|
80061
80907
|
const lockTimeout = getLockTimeout();
|
|
80062
80908
|
await mkdir26(dirname18(lockPath), { recursive: true });
|
|
@@ -80083,7 +80929,7 @@ async function acquireSyncLock(global3) {
|
|
|
80083
80929
|
}
|
|
80084
80930
|
logger.debug(`Lock stat failed: ${statError}`);
|
|
80085
80931
|
}
|
|
80086
|
-
await new Promise((
|
|
80932
|
+
await new Promise((resolve18) => setTimeout(resolve18, 100));
|
|
80087
80933
|
continue;
|
|
80088
80934
|
}
|
|
80089
80935
|
throw err;
|
|
@@ -80102,10 +80948,10 @@ async function executeSyncMerge(ctx) {
|
|
|
80102
80948
|
const releaseLock = await acquireSyncLock(ctx.options.global);
|
|
80103
80949
|
try {
|
|
80104
80950
|
const trackedFiles = ctx.syncTrackedFiles;
|
|
80105
|
-
const upstreamDir = ctx.options.global ?
|
|
80951
|
+
const upstreamDir = ctx.options.global ? join92(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
80106
80952
|
let deletions = [];
|
|
80107
80953
|
try {
|
|
80108
|
-
const sourceMetadataPath =
|
|
80954
|
+
const sourceMetadataPath = join92(upstreamDir, "metadata.json");
|
|
80109
80955
|
if (await import_fs_extra33.pathExists(sourceMetadataPath)) {
|
|
80110
80956
|
const content = await readFile39(sourceMetadataPath, "utf-8");
|
|
80111
80957
|
const sourceMetadata = JSON.parse(content);
|
|
@@ -80137,7 +80983,7 @@ async function executeSyncMerge(ctx) {
|
|
|
80137
80983
|
try {
|
|
80138
80984
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
80139
80985
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
80140
|
-
const targetDir =
|
|
80986
|
+
const targetDir = join92(targetPath, "..");
|
|
80141
80987
|
try {
|
|
80142
80988
|
await mkdir26(targetDir, { recursive: true });
|
|
80143
80989
|
} catch (mkdirError) {
|
|
@@ -80308,7 +81154,7 @@ async function createBackup(claudeDir2, files, backupDir) {
|
|
|
80308
81154
|
const sourcePath = await validateSyncPath(claudeDir2, file.path);
|
|
80309
81155
|
if (await import_fs_extra33.pathExists(sourcePath)) {
|
|
80310
81156
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
80311
|
-
const targetDir =
|
|
81157
|
+
const targetDir = join92(targetPath, "..");
|
|
80312
81158
|
await mkdir26(targetDir, { recursive: true });
|
|
80313
81159
|
await copyFile7(sourcePath, targetPath);
|
|
80314
81160
|
}
|
|
@@ -80323,7 +81169,7 @@ async function createBackup(claudeDir2, files, backupDir) {
|
|
|
80323
81169
|
}
|
|
80324
81170
|
// src/commands/init/phases/transform-handler.ts
|
|
80325
81171
|
init_config_manager();
|
|
80326
|
-
import { join as
|
|
81172
|
+
import { join as join96 } from "node:path";
|
|
80327
81173
|
|
|
80328
81174
|
// src/services/transformers/folder-path-transformer.ts
|
|
80329
81175
|
init_logger();
|
|
@@ -80334,38 +81180,38 @@ init_logger();
|
|
|
80334
81180
|
init_types2();
|
|
80335
81181
|
var import_fs_extra34 = __toESM(require_lib3(), 1);
|
|
80336
81182
|
import { rename as rename4, rm as rm8 } from "node:fs/promises";
|
|
80337
|
-
import { join as
|
|
81183
|
+
import { join as join93, relative as relative15 } from "node:path";
|
|
80338
81184
|
async function collectDirsToRename(extractDir, folders) {
|
|
80339
81185
|
const dirsToRename = [];
|
|
80340
81186
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
80341
|
-
const docsPath =
|
|
81187
|
+
const docsPath = join93(extractDir, DEFAULT_FOLDERS.docs);
|
|
80342
81188
|
if (await import_fs_extra34.pathExists(docsPath)) {
|
|
80343
81189
|
dirsToRename.push({
|
|
80344
81190
|
from: docsPath,
|
|
80345
|
-
to:
|
|
81191
|
+
to: join93(extractDir, folders.docs)
|
|
80346
81192
|
});
|
|
80347
81193
|
}
|
|
80348
|
-
const claudeDocsPath =
|
|
81194
|
+
const claudeDocsPath = join93(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
80349
81195
|
if (await import_fs_extra34.pathExists(claudeDocsPath)) {
|
|
80350
81196
|
dirsToRename.push({
|
|
80351
81197
|
from: claudeDocsPath,
|
|
80352
|
-
to:
|
|
81198
|
+
to: join93(extractDir, ".claude", folders.docs)
|
|
80353
81199
|
});
|
|
80354
81200
|
}
|
|
80355
81201
|
}
|
|
80356
81202
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
80357
|
-
const plansPath =
|
|
81203
|
+
const plansPath = join93(extractDir, DEFAULT_FOLDERS.plans);
|
|
80358
81204
|
if (await import_fs_extra34.pathExists(plansPath)) {
|
|
80359
81205
|
dirsToRename.push({
|
|
80360
81206
|
from: plansPath,
|
|
80361
|
-
to:
|
|
81207
|
+
to: join93(extractDir, folders.plans)
|
|
80362
81208
|
});
|
|
80363
81209
|
}
|
|
80364
|
-
const claudePlansPath =
|
|
81210
|
+
const claudePlansPath = join93(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
80365
81211
|
if (await import_fs_extra34.pathExists(claudePlansPath)) {
|
|
80366
81212
|
dirsToRename.push({
|
|
80367
81213
|
from: claudePlansPath,
|
|
80368
|
-
to:
|
|
81214
|
+
to: join93(extractDir, ".claude", folders.plans)
|
|
80369
81215
|
});
|
|
80370
81216
|
}
|
|
80371
81217
|
}
|
|
@@ -80405,8 +81251,8 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
80405
81251
|
// src/services/transformers/folder-transform/path-replacer.ts
|
|
80406
81252
|
init_logger();
|
|
80407
81253
|
init_types2();
|
|
80408
|
-
import { readFile as readFile40, readdir as
|
|
80409
|
-
import { join as
|
|
81254
|
+
import { readFile as readFile40, readdir as readdir29, writeFile as writeFile26 } from "node:fs/promises";
|
|
81255
|
+
import { join as join94, relative as relative16 } from "node:path";
|
|
80410
81256
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
80411
81257
|
".md",
|
|
80412
81258
|
".txt",
|
|
@@ -80457,9 +81303,9 @@ function compileReplacements(replacements) {
|
|
|
80457
81303
|
async function transformFileContents(dir, compiledReplacements, options2) {
|
|
80458
81304
|
let filesChanged = 0;
|
|
80459
81305
|
let replacementsCount = 0;
|
|
80460
|
-
const entries = await
|
|
81306
|
+
const entries = await readdir29(dir, { withFileTypes: true });
|
|
80461
81307
|
for (const entry of entries) {
|
|
80462
|
-
const fullPath =
|
|
81308
|
+
const fullPath = join94(dir, entry.name);
|
|
80463
81309
|
if (entry.isDirectory()) {
|
|
80464
81310
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
80465
81311
|
continue;
|
|
@@ -80594,9 +81440,9 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
80594
81440
|
|
|
80595
81441
|
// src/services/transformers/global-path-transformer.ts
|
|
80596
81442
|
init_logger();
|
|
80597
|
-
import { readFile as readFile41, readdir as
|
|
81443
|
+
import { readFile as readFile41, readdir as readdir30, writeFile as writeFile27 } from "node:fs/promises";
|
|
80598
81444
|
import { platform as platform13 } from "node:os";
|
|
80599
|
-
import { extname as extname4, join as
|
|
81445
|
+
import { extname as extname4, join as join95 } from "node:path";
|
|
80600
81446
|
var IS_WINDOWS4 = platform13() === "win32";
|
|
80601
81447
|
var HOME_PREFIX = IS_WINDOWS4 ? "%USERPROFILE%" : "$HOME";
|
|
80602
81448
|
function getHomeDirPrefix() {
|
|
@@ -80704,9 +81550,9 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
80704
81550
|
let filesSkipped = 0;
|
|
80705
81551
|
const skippedFiles = [];
|
|
80706
81552
|
async function processDirectory2(dir) {
|
|
80707
|
-
const entries = await
|
|
81553
|
+
const entries = await readdir30(dir, { withFileTypes: true });
|
|
80708
81554
|
for (const entry of entries) {
|
|
80709
|
-
const fullPath =
|
|
81555
|
+
const fullPath = join95(dir, entry.name);
|
|
80710
81556
|
if (entry.isDirectory()) {
|
|
80711
81557
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
80712
81558
|
continue;
|
|
@@ -80782,7 +81628,7 @@ async function handleTransforms(ctx) {
|
|
|
80782
81628
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
|
|
80783
81629
|
}
|
|
80784
81630
|
}
|
|
80785
|
-
const claudeDir2 = ctx.options.global ? ctx.resolvedDir :
|
|
81631
|
+
const claudeDir2 = ctx.options.global ? ctx.resolvedDir : join96(ctx.resolvedDir, ".claude");
|
|
80786
81632
|
return {
|
|
80787
81633
|
...ctx,
|
|
80788
81634
|
foldersConfig,
|
|
@@ -80975,7 +81821,7 @@ var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
|
80975
81821
|
|
|
80976
81822
|
// src/commands/new/phases/directory-setup.ts
|
|
80977
81823
|
init_config_manager();
|
|
80978
|
-
import { resolve as
|
|
81824
|
+
import { resolve as resolve18 } from "node:path";
|
|
80979
81825
|
init_logger();
|
|
80980
81826
|
init_path_resolver();
|
|
80981
81827
|
init_types2();
|
|
@@ -81060,7 +81906,7 @@ async function directorySetup(validOptions, prompts) {
|
|
|
81060
81906
|
targetDir = await prompts.getDirectory(targetDir);
|
|
81061
81907
|
}
|
|
81062
81908
|
}
|
|
81063
|
-
const resolvedDir =
|
|
81909
|
+
const resolvedDir = resolve18(targetDir);
|
|
81064
81910
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
81065
81911
|
if (PathResolver.isLocalSameAsGlobal(resolvedDir)) {
|
|
81066
81912
|
logger.warning("You're creating a project at HOME directory.");
|
|
@@ -81117,7 +81963,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
81117
81963
|
// src/commands/new/phases/project-creation.ts
|
|
81118
81964
|
init_config_manager();
|
|
81119
81965
|
init_github_client();
|
|
81120
|
-
import { join as
|
|
81966
|
+
import { join as join97 } from "node:path";
|
|
81121
81967
|
init_logger();
|
|
81122
81968
|
init_output_manager();
|
|
81123
81969
|
init_types2();
|
|
@@ -81243,7 +82089,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
81243
82089
|
output.section("Installing");
|
|
81244
82090
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
81245
82091
|
const merger = new FileMerger;
|
|
81246
|
-
const claudeDir2 =
|
|
82092
|
+
const claudeDir2 = join97(resolvedDir, ".claude");
|
|
81247
82093
|
merger.setMultiKitContext(claudeDir2, kit);
|
|
81248
82094
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
81249
82095
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -81290,7 +82136,7 @@ async function handleProjectCreation(ctx) {
|
|
|
81290
82136
|
}
|
|
81291
82137
|
// src/commands/new/phases/post-setup.ts
|
|
81292
82138
|
init_projects_registry();
|
|
81293
|
-
import { join as
|
|
82139
|
+
import { join as join98 } from "node:path";
|
|
81294
82140
|
init_package_installer();
|
|
81295
82141
|
init_logger();
|
|
81296
82142
|
init_path_resolver();
|
|
@@ -81322,9 +82168,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
|
|
|
81322
82168
|
withSudo: validOptions.withSudo
|
|
81323
82169
|
});
|
|
81324
82170
|
}
|
|
81325
|
-
const claudeDir2 =
|
|
82171
|
+
const claudeDir2 = join98(resolvedDir, ".claude");
|
|
81326
82172
|
await promptSetupWizardIfNeeded({
|
|
81327
|
-
envPath:
|
|
82173
|
+
envPath: join98(claudeDir2, ".env"),
|
|
81328
82174
|
claudeDir: claudeDir2,
|
|
81329
82175
|
isGlobal: false,
|
|
81330
82176
|
isNonInteractive: isNonInteractive2,
|
|
@@ -81396,13 +82242,13 @@ init_claudekit_data2();
|
|
|
81396
82242
|
init_logger();
|
|
81397
82243
|
init_safe_prompts();
|
|
81398
82244
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
81399
|
-
import { existsSync as
|
|
81400
|
-
import { resolve as
|
|
82245
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
82246
|
+
import { resolve as resolve19 } from "node:path";
|
|
81401
82247
|
async function handleAdd(projectPath, options2) {
|
|
81402
82248
|
logger.debug(`Adding project: ${projectPath}, options: ${JSON.stringify(options2)}`);
|
|
81403
82249
|
intro("Add Project");
|
|
81404
|
-
const absolutePath =
|
|
81405
|
-
if (!
|
|
82250
|
+
const absolutePath = resolve19(projectPath);
|
|
82251
|
+
if (!existsSync39(absolutePath)) {
|
|
81406
82252
|
log.error(`Path does not exist: ${absolutePath}`);
|
|
81407
82253
|
process.exitCode = 1;
|
|
81408
82254
|
return;
|
|
@@ -82330,7 +83176,7 @@ async function detectInstallations() {
|
|
|
82330
83176
|
|
|
82331
83177
|
// src/commands/uninstall/removal-handler.ts
|
|
82332
83178
|
import { readdirSync as readdirSync5, rmSync as rmSync5 } from "node:fs";
|
|
82333
|
-
import { join as
|
|
83179
|
+
import { join as join100, resolve as resolve20, sep as sep4 } from "node:path";
|
|
82334
83180
|
init_logger();
|
|
82335
83181
|
init_safe_prompts();
|
|
82336
83182
|
init_safe_spinner();
|
|
@@ -82339,7 +83185,7 @@ var import_fs_extra37 = __toESM(require_lib3(), 1);
|
|
|
82339
83185
|
// src/commands/uninstall/analysis-handler.ts
|
|
82340
83186
|
init_metadata_migration();
|
|
82341
83187
|
import { readdirSync as readdirSync4, rmSync as rmSync4 } from "node:fs";
|
|
82342
|
-
import { dirname as dirname19, join as
|
|
83188
|
+
import { dirname as dirname19, join as join99 } from "node:path";
|
|
82343
83189
|
init_logger();
|
|
82344
83190
|
init_safe_prompts();
|
|
82345
83191
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
@@ -82387,7 +83233,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
82387
83233
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
82388
83234
|
const kitFiles = metadata.kits[kit].files || [];
|
|
82389
83235
|
for (const trackedFile of kitFiles) {
|
|
82390
|
-
const filePath =
|
|
83236
|
+
const filePath = join99(installation.path, trackedFile.path);
|
|
82391
83237
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
82392
83238
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
82393
83239
|
continue;
|
|
@@ -82417,7 +83263,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
82417
83263
|
return result;
|
|
82418
83264
|
}
|
|
82419
83265
|
for (const trackedFile of allTrackedFiles) {
|
|
82420
|
-
const filePath =
|
|
83266
|
+
const filePath = join99(installation.path, trackedFile.path);
|
|
82421
83267
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
82422
83268
|
if (!ownershipResult.exists)
|
|
82423
83269
|
continue;
|
|
@@ -82471,17 +83317,17 @@ async function isDirectory(filePath) {
|
|
|
82471
83317
|
}
|
|
82472
83318
|
async function isPathSafeToRemove(filePath, baseDir) {
|
|
82473
83319
|
try {
|
|
82474
|
-
const resolvedPath =
|
|
82475
|
-
const resolvedBase =
|
|
82476
|
-
if (!resolvedPath.startsWith(resolvedBase +
|
|
83320
|
+
const resolvedPath = resolve20(filePath);
|
|
83321
|
+
const resolvedBase = resolve20(baseDir);
|
|
83322
|
+
if (!resolvedPath.startsWith(resolvedBase + sep4) && resolvedPath !== resolvedBase) {
|
|
82477
83323
|
logger.debug(`Path outside installation directory: ${filePath}`);
|
|
82478
83324
|
return false;
|
|
82479
83325
|
}
|
|
82480
83326
|
const stats = await import_fs_extra37.lstat(filePath);
|
|
82481
83327
|
if (stats.isSymbolicLink()) {
|
|
82482
83328
|
const realPath = await import_fs_extra37.realpath(filePath);
|
|
82483
|
-
const resolvedReal =
|
|
82484
|
-
if (!resolvedReal.startsWith(resolvedBase +
|
|
83329
|
+
const resolvedReal = resolve20(realPath);
|
|
83330
|
+
if (!resolvedReal.startsWith(resolvedBase + sep4) && resolvedReal !== resolvedBase) {
|
|
82485
83331
|
logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
|
|
82486
83332
|
return false;
|
|
82487
83333
|
}
|
|
@@ -82514,7 +83360,7 @@ async function removeInstallations(installations, options2) {
|
|
|
82514
83360
|
let removedCount = 0;
|
|
82515
83361
|
let cleanedDirs = 0;
|
|
82516
83362
|
for (const item of analysis.toDelete) {
|
|
82517
|
-
const filePath =
|
|
83363
|
+
const filePath = join100(installation.path, item.path);
|
|
82518
83364
|
if (!await import_fs_extra37.pathExists(filePath))
|
|
82519
83365
|
continue;
|
|
82520
83366
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -82888,8 +83734,8 @@ init_version_checker();
|
|
|
82888
83734
|
init_logger();
|
|
82889
83735
|
init_path_resolver();
|
|
82890
83736
|
init_types2();
|
|
82891
|
-
import { existsSync as
|
|
82892
|
-
import { join as
|
|
83737
|
+
import { existsSync as existsSync40, readFileSync as readFileSync9 } from "node:fs";
|
|
83738
|
+
import { join as join101 } from "node:path";
|
|
82893
83739
|
var packageVersion = package_default.version;
|
|
82894
83740
|
function formatInstalledKits(metadata) {
|
|
82895
83741
|
if (!metadata.kits || Object.keys(metadata.kits).length === 0) {
|
|
@@ -82921,13 +83767,13 @@ async function displayVersion() {
|
|
|
82921
83767
|
let localKitVersion = null;
|
|
82922
83768
|
let isGlobalOnlyKit = false;
|
|
82923
83769
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
82924
|
-
const globalMetadataPath =
|
|
83770
|
+
const globalMetadataPath = join101(globalKitDir, "metadata.json");
|
|
82925
83771
|
const prefix = PathResolver.getPathPrefix(false);
|
|
82926
|
-
const localMetadataPath = prefix ?
|
|
83772
|
+
const localMetadataPath = prefix ? join101(process.cwd(), prefix, "metadata.json") : join101(process.cwd(), "metadata.json");
|
|
82927
83773
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
82928
|
-
if (!isLocalSameAsGlobal &&
|
|
83774
|
+
if (!isLocalSameAsGlobal && existsSync40(localMetadataPath)) {
|
|
82929
83775
|
try {
|
|
82930
|
-
const rawMetadata = JSON.parse(
|
|
83776
|
+
const rawMetadata = JSON.parse(readFileSync9(localMetadataPath, "utf-8"));
|
|
82931
83777
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
82932
83778
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
82933
83779
|
if (kitsDisplay) {
|
|
@@ -82939,9 +83785,9 @@ async function displayVersion() {
|
|
|
82939
83785
|
logger.verbose("Failed to parse local metadata.json", { error });
|
|
82940
83786
|
}
|
|
82941
83787
|
}
|
|
82942
|
-
if (
|
|
83788
|
+
if (existsSync40(globalMetadataPath)) {
|
|
82943
83789
|
try {
|
|
82944
|
-
const rawMetadata = JSON.parse(
|
|
83790
|
+
const rawMetadata = JSON.parse(readFileSync9(globalMetadataPath, "utf-8"));
|
|
82945
83791
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
82946
83792
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
82947
83793
|
if (kitsDisplay) {
|