@sunasteriskrnd/takumi 1.0.0-dev.13 → 1.0.0-dev.14
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 +596 -435
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32365,7 +32365,7 @@ var init_error_handler = __esm(() => {
|
|
|
32365
32365
|
// src/domains/versioning/release-cache.ts
|
|
32366
32366
|
import { existsSync as existsSync40 } from "node:fs";
|
|
32367
32367
|
import { mkdir as mkdir18, readFile as readFile34, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
|
|
32368
|
-
import { join as
|
|
32368
|
+
import { join as join79 } from "node:path";
|
|
32369
32369
|
var ReleaseCacheEntrySchema, ReleaseCache;
|
|
32370
32370
|
var init_release_cache = __esm(() => {
|
|
32371
32371
|
init_logger();
|
|
@@ -32380,7 +32380,7 @@ var init_release_cache = __esm(() => {
|
|
|
32380
32380
|
static CACHE_TTL_SECONDS = Number(process.env.TAKUMI_CACHE_TTL) || 3600;
|
|
32381
32381
|
cacheDir;
|
|
32382
32382
|
constructor() {
|
|
32383
|
-
this.cacheDir =
|
|
32383
|
+
this.cacheDir = join79(PathResolver.getCacheDir(false), ReleaseCache.CACHE_DIR);
|
|
32384
32384
|
}
|
|
32385
32385
|
async get(key) {
|
|
32386
32386
|
const cacheFile = this.getCachePath(key);
|
|
@@ -32438,7 +32438,7 @@ var init_release_cache = __esm(() => {
|
|
|
32438
32438
|
const files = await readdir25(this.cacheDir);
|
|
32439
32439
|
for (const file of files) {
|
|
32440
32440
|
if (file.endsWith(".json")) {
|
|
32441
|
-
await unlink8(
|
|
32441
|
+
await unlink8(join79(this.cacheDir, file));
|
|
32442
32442
|
}
|
|
32443
32443
|
}
|
|
32444
32444
|
logger.debug("All release cache cleared");
|
|
@@ -32449,7 +32449,7 @@ var init_release_cache = __esm(() => {
|
|
|
32449
32449
|
}
|
|
32450
32450
|
getCachePath(key) {
|
|
32451
32451
|
const safeKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
32452
|
-
return
|
|
32452
|
+
return join79(this.cacheDir, `${safeKey}.json`);
|
|
32453
32453
|
}
|
|
32454
32454
|
isExpired(timestamp) {
|
|
32455
32455
|
const now = Date.now();
|
|
@@ -33442,14 +33442,14 @@ var exports_monorepo_resolver = {};
|
|
|
33442
33442
|
__export(exports_monorepo_resolver, {
|
|
33443
33443
|
resolveMonorepoRoot: () => resolveMonorepoRoot
|
|
33444
33444
|
});
|
|
33445
|
-
import { existsSync as existsSync42, readFileSync as
|
|
33446
|
-
import { dirname as dirname23, join as
|
|
33445
|
+
import { existsSync as existsSync42, readFileSync as readFileSync12 } from "node:fs";
|
|
33446
|
+
import { dirname as dirname23, join as join90, resolve as resolve20 } from "node:path";
|
|
33447
33447
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
33448
33448
|
function parseMetadataAt(metadataPath) {
|
|
33449
33449
|
if (!existsSync42(metadataPath))
|
|
33450
33450
|
return null;
|
|
33451
33451
|
try {
|
|
33452
|
-
const raw =
|
|
33452
|
+
const raw = readFileSync12(metadataPath, "utf-8");
|
|
33453
33453
|
const parsed = JSON.parse(raw);
|
|
33454
33454
|
if (typeof parsed.name !== "string" || typeof parsed.version !== "string" || !ACCEPTED_METADATA_NAMES.has(parsed.name)) {
|
|
33455
33455
|
return null;
|
|
@@ -33460,11 +33460,11 @@ function parseMetadataAt(metadataPath) {
|
|
|
33460
33460
|
}
|
|
33461
33461
|
}
|
|
33462
33462
|
function readSourceDirFromPackageJson(candidateRoot) {
|
|
33463
|
-
const packageJsonPath =
|
|
33463
|
+
const packageJsonPath = join90(candidateRoot, "package.json");
|
|
33464
33464
|
if (!existsSync42(packageJsonPath))
|
|
33465
33465
|
return null;
|
|
33466
33466
|
try {
|
|
33467
|
-
const parsed = JSON.parse(
|
|
33467
|
+
const parsed = JSON.parse(readFileSync12(packageJsonPath, "utf-8"));
|
|
33468
33468
|
const kitCfg = parsed.takumi;
|
|
33469
33469
|
if (kitCfg && typeof kitCfg.sourceDir === "string" && kitCfg.sourceDir.length > 0) {
|
|
33470
33470
|
return kitCfg.sourceDir;
|
|
@@ -33483,7 +33483,7 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
33483
33483
|
};
|
|
33484
33484
|
}
|
|
33485
33485
|
const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
|
|
33486
|
-
const sourceRoot =
|
|
33486
|
+
const sourceRoot = join90(candidateRoot, sourceDir);
|
|
33487
33487
|
const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
|
|
33488
33488
|
if (nestedMetadata) {
|
|
33489
33489
|
return {
|
|
@@ -33496,7 +33496,7 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
33496
33496
|
return null;
|
|
33497
33497
|
}
|
|
33498
33498
|
function walkUpForMetadata(startDir, maxDepth = 5) {
|
|
33499
|
-
let current =
|
|
33499
|
+
let current = resolve20(startDir);
|
|
33500
33500
|
for (let i = 0;i < maxDepth; i++) {
|
|
33501
33501
|
const result = tryReadAtCandidate(current);
|
|
33502
33502
|
if (result)
|
|
@@ -33517,7 +33517,7 @@ function resolveMonorepoRoot() {
|
|
|
33517
33517
|
return result2;
|
|
33518
33518
|
} catch {}
|
|
33519
33519
|
if (process.argv[1]) {
|
|
33520
|
-
const binDir = dirname23(
|
|
33520
|
+
const binDir = dirname23(resolve20(process.argv[1]));
|
|
33521
33521
|
const result2 = walkUpForMetadata(binDir);
|
|
33522
33522
|
if (result2)
|
|
33523
33523
|
return result2;
|
|
@@ -33616,7 +33616,7 @@ async function restoreOriginalBranch(branchName, cwd2, issueNumber) {
|
|
|
33616
33616
|
}
|
|
33617
33617
|
}
|
|
33618
33618
|
function spawnAndCollect(command, args, cwd2) {
|
|
33619
|
-
return new Promise((
|
|
33619
|
+
return new Promise((resolve31, reject) => {
|
|
33620
33620
|
const child = spawn3(command, args, { ...cwd2 && { cwd: cwd2 }, stdio: ["ignore", "pipe", "pipe"] });
|
|
33621
33621
|
const chunks = [];
|
|
33622
33622
|
const stderrChunks = [];
|
|
@@ -33629,7 +33629,7 @@ function spawnAndCollect(command, args, cwd2) {
|
|
|
33629
33629
|
reject(new Error(`${command} ${args[0] ?? ""} exited with code ${code}: ${stderr}`));
|
|
33630
33630
|
return;
|
|
33631
33631
|
}
|
|
33632
|
-
|
|
33632
|
+
resolve31(Buffer.concat(chunks).toString("utf-8"));
|
|
33633
33633
|
});
|
|
33634
33634
|
});
|
|
33635
33635
|
}
|
|
@@ -33648,9 +33648,9 @@ __export(exports_worktree_manager, {
|
|
|
33648
33648
|
});
|
|
33649
33649
|
import { existsSync as existsSync53 } from "node:fs";
|
|
33650
33650
|
import { readFile as readFile44, writeFile as writeFile32 } from "node:fs/promises";
|
|
33651
|
-
import { join as
|
|
33651
|
+
import { join as join110 } from "node:path";
|
|
33652
33652
|
async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
33653
|
-
const worktreePath =
|
|
33653
|
+
const worktreePath = join110(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
33654
33654
|
const branchName = `sk-watch/issue-${issueNumber}`;
|
|
33655
33655
|
await spawnAndCollect("git", ["fetch", "origin", baseBranch], projectDir).catch(() => {
|
|
33656
33656
|
logger.warning(`[worktree] Could not fetch origin/${baseBranch}, using local`);
|
|
@@ -33668,7 +33668,7 @@ async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
|
33668
33668
|
return worktreePath;
|
|
33669
33669
|
}
|
|
33670
33670
|
async function removeWorktree(projectDir, issueNumber) {
|
|
33671
|
-
const worktreePath =
|
|
33671
|
+
const worktreePath = join110(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
33672
33672
|
const branchName = `sk-watch/issue-${issueNumber}`;
|
|
33673
33673
|
try {
|
|
33674
33674
|
await spawnAndCollect("git", ["worktree", "remove", worktreePath, "--force"], projectDir);
|
|
@@ -33682,7 +33682,7 @@ async function listActiveWorktrees(projectDir) {
|
|
|
33682
33682
|
try {
|
|
33683
33683
|
const output2 = await spawnAndCollect("git", ["worktree", "list", "--porcelain"], projectDir);
|
|
33684
33684
|
const issueNumbers = [];
|
|
33685
|
-
const worktreePrefix =
|
|
33685
|
+
const worktreePrefix = join110(projectDir, WORKTREE_DIR, "issue-").replace(/\\/g, "/");
|
|
33686
33686
|
for (const line of output2.split(`
|
|
33687
33687
|
`)) {
|
|
33688
33688
|
if (line.startsWith("worktree ")) {
|
|
@@ -33710,7 +33710,7 @@ async function cleanupAllWorktrees(projectDir) {
|
|
|
33710
33710
|
await spawnAndCollect("git", ["worktree", "prune"], projectDir).catch(() => {});
|
|
33711
33711
|
}
|
|
33712
33712
|
async function ensureGitignore(projectDir) {
|
|
33713
|
-
const gitignorePath =
|
|
33713
|
+
const gitignorePath = join110(projectDir, ".gitignore");
|
|
33714
33714
|
try {
|
|
33715
33715
|
const content = existsSync53(gitignorePath) ? await readFile44(gitignorePath, "utf-8") : "";
|
|
33716
33716
|
if (!content.includes(".worktrees")) {
|
|
@@ -33814,16 +33814,16 @@ var init_content_validator = __esm(() => {
|
|
|
33814
33814
|
|
|
33815
33815
|
// src/commands/content/phases/context-cache-manager.ts
|
|
33816
33816
|
import { createHash as createHash8 } from "node:crypto";
|
|
33817
|
-
import { existsSync as existsSync59, mkdirSync as
|
|
33817
|
+
import { existsSync as existsSync59, mkdirSync as mkdirSync5, readFileSync as readFileSync17, readdirSync as readdirSync10, statSync as statSync7 } from "node:fs";
|
|
33818
33818
|
import { rename as rename10, writeFile as writeFile34 } from "node:fs/promises";
|
|
33819
33819
|
import { homedir as homedir27 } from "node:os";
|
|
33820
|
-
import { basename as
|
|
33820
|
+
import { basename as basename14, join as join117 } from "node:path";
|
|
33821
33821
|
function getCachedContext(repoPath) {
|
|
33822
33822
|
const cachePath = getCacheFilePath(repoPath);
|
|
33823
33823
|
if (!existsSync59(cachePath))
|
|
33824
33824
|
return null;
|
|
33825
33825
|
try {
|
|
33826
|
-
const raw =
|
|
33826
|
+
const raw = readFileSync17(cachePath, "utf-8");
|
|
33827
33827
|
const cache2 = JSON.parse(raw);
|
|
33828
33828
|
const age = Date.now() - new Date(cache2.createdAt).getTime();
|
|
33829
33829
|
if (age >= CACHE_TTL_MS3)
|
|
@@ -33838,7 +33838,7 @@ function getCachedContext(repoPath) {
|
|
|
33838
33838
|
}
|
|
33839
33839
|
async function saveCachedContext(repoPath, cache2) {
|
|
33840
33840
|
if (!existsSync59(CACHE_DIR)) {
|
|
33841
|
-
|
|
33841
|
+
mkdirSync5(CACHE_DIR, { recursive: true });
|
|
33842
33842
|
}
|
|
33843
33843
|
const cachePath = getCacheFilePath(repoPath);
|
|
33844
33844
|
const tmpPath = `${cachePath}.tmp`;
|
|
@@ -33860,38 +33860,38 @@ function computeSourceHash(repoPath) {
|
|
|
33860
33860
|
}
|
|
33861
33861
|
function getDocSourcePaths(repoPath) {
|
|
33862
33862
|
const paths = [];
|
|
33863
|
-
const docsDir =
|
|
33863
|
+
const docsDir = join117(repoPath, "docs");
|
|
33864
33864
|
if (existsSync59(docsDir)) {
|
|
33865
33865
|
try {
|
|
33866
33866
|
const files = readdirSync10(docsDir);
|
|
33867
33867
|
for (const f4 of files) {
|
|
33868
33868
|
if (f4.endsWith(".md"))
|
|
33869
|
-
paths.push(
|
|
33869
|
+
paths.push(join117(docsDir, f4));
|
|
33870
33870
|
}
|
|
33871
33871
|
} catch {}
|
|
33872
33872
|
}
|
|
33873
|
-
const readme =
|
|
33873
|
+
const readme = join117(repoPath, "README.md");
|
|
33874
33874
|
if (existsSync59(readme))
|
|
33875
33875
|
paths.push(readme);
|
|
33876
|
-
const stylesDir =
|
|
33876
|
+
const stylesDir = join117(repoPath, "assets", "writing-styles");
|
|
33877
33877
|
if (existsSync59(stylesDir)) {
|
|
33878
33878
|
try {
|
|
33879
33879
|
const files = readdirSync10(stylesDir);
|
|
33880
33880
|
for (const f4 of files) {
|
|
33881
|
-
paths.push(
|
|
33881
|
+
paths.push(join117(stylesDir, f4));
|
|
33882
33882
|
}
|
|
33883
33883
|
} catch {}
|
|
33884
33884
|
}
|
|
33885
33885
|
return paths.sort();
|
|
33886
33886
|
}
|
|
33887
33887
|
function getCacheFilePath(repoPath) {
|
|
33888
|
-
const repoName =
|
|
33888
|
+
const repoName = basename14(repoPath).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
33889
33889
|
const pathHash = createHash8("sha256").update(repoPath).digest("hex").slice(0, 8);
|
|
33890
|
-
return
|
|
33890
|
+
return join117(CACHE_DIR, `${repoName}-${pathHash}-context-cache.json`);
|
|
33891
33891
|
}
|
|
33892
33892
|
var CACHE_DIR, CACHE_TTL_MS3;
|
|
33893
33893
|
var init_context_cache_manager = __esm(() => {
|
|
33894
|
-
CACHE_DIR =
|
|
33894
|
+
CACHE_DIR = join117(homedir27(), ".sunagentkit", "cache");
|
|
33895
33895
|
CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
|
|
33896
33896
|
});
|
|
33897
33897
|
|
|
@@ -34071,8 +34071,8 @@ function extractContentFromResponse(response) {
|
|
|
34071
34071
|
|
|
34072
34072
|
// src/commands/content/phases/docs-summarizer.ts
|
|
34073
34073
|
import { execSync as execSync5 } from "node:child_process";
|
|
34074
|
-
import { existsSync as existsSync60, readFileSync as
|
|
34075
|
-
import { join as
|
|
34074
|
+
import { existsSync as existsSync60, readFileSync as readFileSync18, readdirSync as readdirSync11 } from "node:fs";
|
|
34075
|
+
import { join as join118 } from "node:path";
|
|
34076
34076
|
async function summarizeProjectDocs(repoPath, contentLogger) {
|
|
34077
34077
|
const rawContent = collectRawDocs(repoPath);
|
|
34078
34078
|
if (rawContent.total.length < 200) {
|
|
@@ -34120,18 +34120,18 @@ function collectRawDocs(repoPath) {
|
|
|
34120
34120
|
return "";
|
|
34121
34121
|
if (totalChars >= MAX_RAW_CONTENT_CHARS)
|
|
34122
34122
|
return "";
|
|
34123
|
-
const content =
|
|
34123
|
+
const content = readFileSync18(filePath, "utf-8");
|
|
34124
34124
|
const capped = content.slice(0, Math.min(maxChars, MAX_RAW_CONTENT_CHARS - totalChars));
|
|
34125
34125
|
totalChars += capped.length;
|
|
34126
34126
|
return capped;
|
|
34127
34127
|
};
|
|
34128
34128
|
const docsContent = [];
|
|
34129
|
-
const docsDir =
|
|
34129
|
+
const docsDir = join118(repoPath, "docs");
|
|
34130
34130
|
if (existsSync60(docsDir)) {
|
|
34131
34131
|
try {
|
|
34132
34132
|
const files = readdirSync11(docsDir).filter((f4) => f4.endsWith(".md")).sort();
|
|
34133
34133
|
for (const f4 of files) {
|
|
34134
|
-
const content = readCapped(
|
|
34134
|
+
const content = readCapped(join118(docsDir, f4), 5000);
|
|
34135
34135
|
if (content) {
|
|
34136
34136
|
docsContent.push(`### ${f4}
|
|
34137
34137
|
${content}`);
|
|
@@ -34145,21 +34145,21 @@ ${content}`);
|
|
|
34145
34145
|
let brand = "";
|
|
34146
34146
|
const brandCandidates = ["docs/brand-guidelines.md", "docs/design-guidelines.md"];
|
|
34147
34147
|
for (const p2 of brandCandidates) {
|
|
34148
|
-
brand = readCapped(
|
|
34148
|
+
brand = readCapped(join118(repoPath, p2), 3000);
|
|
34149
34149
|
if (brand)
|
|
34150
34150
|
break;
|
|
34151
34151
|
}
|
|
34152
34152
|
let styles3 = "";
|
|
34153
|
-
const stylesDir =
|
|
34153
|
+
const stylesDir = join118(repoPath, "assets", "writing-styles");
|
|
34154
34154
|
if (existsSync60(stylesDir)) {
|
|
34155
34155
|
try {
|
|
34156
34156
|
const files = readdirSync11(stylesDir).slice(0, 3);
|
|
34157
|
-
styles3 = files.map((f4) => readCapped(
|
|
34157
|
+
styles3 = files.map((f4) => readCapped(join118(stylesDir, f4), 1000)).filter(Boolean).join(`
|
|
34158
34158
|
|
|
34159
34159
|
`);
|
|
34160
34160
|
} catch {}
|
|
34161
34161
|
}
|
|
34162
|
-
const readme = readCapped(
|
|
34162
|
+
const readme = readCapped(join118(repoPath, "README.md"), 3000);
|
|
34163
34163
|
const total = [docs, brand, styles3, readme].join(`
|
|
34164
34164
|
`);
|
|
34165
34165
|
return { docs, brand, styles: styles3, readme, total };
|
|
@@ -34344,13 +34344,13 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
|
|
|
34344
34344
|
|
|
34345
34345
|
// src/commands/content/phases/photo-generator.ts
|
|
34346
34346
|
import { execSync as execSync6 } from "node:child_process";
|
|
34347
|
-
import { existsSync as existsSync61, mkdirSync as
|
|
34347
|
+
import { existsSync as existsSync61, mkdirSync as mkdirSync6, readdirSync as readdirSync12 } from "node:fs";
|
|
34348
34348
|
import { homedir as homedir28 } from "node:os";
|
|
34349
|
-
import { join as
|
|
34349
|
+
import { join as join119 } from "node:path";
|
|
34350
34350
|
async function generatePhoto(_content, context, config, platform10, contentId, contentLogger) {
|
|
34351
|
-
const mediaDir =
|
|
34351
|
+
const mediaDir = join119(config.contentDir.replace(/^~/, homedir28()), "media", String(contentId));
|
|
34352
34352
|
if (!existsSync61(mediaDir)) {
|
|
34353
|
-
|
|
34353
|
+
mkdirSync6(mediaDir, { recursive: true });
|
|
34354
34354
|
}
|
|
34355
34355
|
const prompt = buildPhotoPrompt(context, platform10);
|
|
34356
34356
|
const dimensions = platform10 === "facebook" ? { width: 1200, height: 630 } : { width: 1200, height: 675 };
|
|
@@ -34373,7 +34373,7 @@ async function generatePhoto(_content, context, config, platform10, contentId, c
|
|
|
34373
34373
|
const imageFile = files.find((f4) => /\.(png|jpg|jpeg|webp)$/i.test(f4));
|
|
34374
34374
|
if (imageFile) {
|
|
34375
34375
|
const ext2 = imageFile.split(".").pop() ?? "png";
|
|
34376
|
-
return { path:
|
|
34376
|
+
return { path: join119(mediaDir, imageFile), ...dimensions, format: ext2 };
|
|
34377
34377
|
}
|
|
34378
34378
|
contentLogger.warn(`Photo generation produced no image for content ${contentId}`);
|
|
34379
34379
|
return null;
|
|
@@ -34461,9 +34461,9 @@ var init_content_creator = __esm(() => {
|
|
|
34461
34461
|
});
|
|
34462
34462
|
|
|
34463
34463
|
// src/commands/content/phases/content-logger.ts
|
|
34464
|
-
import { createWriteStream as createWriteStream5, existsSync as existsSync62, mkdirSync as
|
|
34464
|
+
import { createWriteStream as createWriteStream5, existsSync as existsSync62, mkdirSync as mkdirSync7, statSync as statSync8 } from "node:fs";
|
|
34465
34465
|
import { homedir as homedir29 } from "node:os";
|
|
34466
|
-
import { join as
|
|
34466
|
+
import { join as join120 } from "node:path";
|
|
34467
34467
|
|
|
34468
34468
|
class ContentLogger {
|
|
34469
34469
|
stream = null;
|
|
@@ -34471,12 +34471,12 @@ class ContentLogger {
|
|
|
34471
34471
|
logDir;
|
|
34472
34472
|
maxBytes;
|
|
34473
34473
|
constructor(maxBytes = 0) {
|
|
34474
|
-
this.logDir =
|
|
34474
|
+
this.logDir = join120(homedir29(), ".sunagentkit", "logs");
|
|
34475
34475
|
this.maxBytes = maxBytes;
|
|
34476
34476
|
}
|
|
34477
34477
|
init() {
|
|
34478
34478
|
if (!existsSync62(this.logDir)) {
|
|
34479
|
-
|
|
34479
|
+
mkdirSync7(this.logDir, { recursive: true });
|
|
34480
34480
|
}
|
|
34481
34481
|
this.rotateIfNeeded();
|
|
34482
34482
|
}
|
|
@@ -34503,7 +34503,7 @@ class ContentLogger {
|
|
|
34503
34503
|
}
|
|
34504
34504
|
}
|
|
34505
34505
|
getLogPath() {
|
|
34506
|
-
return
|
|
34506
|
+
return join120(this.logDir, `content-${this.getDateStr()}.log`);
|
|
34507
34507
|
}
|
|
34508
34508
|
write(level, message) {
|
|
34509
34509
|
this.rotateIfNeeded();
|
|
@@ -34520,18 +34520,18 @@ class ContentLogger {
|
|
|
34520
34520
|
if (dateStr !== this.currentDate) {
|
|
34521
34521
|
this.close();
|
|
34522
34522
|
this.currentDate = dateStr;
|
|
34523
|
-
const logPath =
|
|
34523
|
+
const logPath = join120(this.logDir, `content-${dateStr}.log`);
|
|
34524
34524
|
this.stream = createWriteStream5(logPath, { flags: "a", mode: 384 });
|
|
34525
34525
|
return;
|
|
34526
34526
|
}
|
|
34527
34527
|
if (this.maxBytes > 0 && this.stream) {
|
|
34528
|
-
const logPath =
|
|
34528
|
+
const logPath = join120(this.logDir, `content-${this.currentDate}.log`);
|
|
34529
34529
|
try {
|
|
34530
34530
|
const stat15 = statSync8(logPath);
|
|
34531
34531
|
if (stat15.size >= this.maxBytes) {
|
|
34532
34532
|
this.close();
|
|
34533
34533
|
const suffix = Date.now();
|
|
34534
|
-
const rotatedPath =
|
|
34534
|
+
const rotatedPath = join120(this.logDir, `content-${this.currentDate}-${suffix}.log`);
|
|
34535
34535
|
import("node:fs/promises").then(({ rename: rename11 }) => rename11(logPath, rotatedPath).catch(() => {}));
|
|
34536
34536
|
this.stream = createWriteStream5(logPath, { flags: "w", mode: 384 });
|
|
34537
34537
|
}
|
|
@@ -34568,7 +34568,7 @@ function openDatabase(dbPath) {
|
|
|
34568
34568
|
var init_sqlite_client = () => {};
|
|
34569
34569
|
|
|
34570
34570
|
// src/commands/content/phases/db-manager.ts
|
|
34571
|
-
import { existsSync as existsSync63, mkdirSync as
|
|
34571
|
+
import { existsSync as existsSync63, mkdirSync as mkdirSync8 } from "node:fs";
|
|
34572
34572
|
import { dirname as dirname34 } from "node:path";
|
|
34573
34573
|
function initDatabase(dbPath) {
|
|
34574
34574
|
ensureParentDir2(dbPath);
|
|
@@ -34592,7 +34592,7 @@ function runRetentionCleanup(db, retentionDays = 90) {
|
|
|
34592
34592
|
function ensureParentDir2(dbPath) {
|
|
34593
34593
|
const dir = dirname34(dbPath);
|
|
34594
34594
|
if (dir && !existsSync63(dir)) {
|
|
34595
|
-
|
|
34595
|
+
mkdirSync8(dir, { recursive: true });
|
|
34596
34596
|
}
|
|
34597
34597
|
}
|
|
34598
34598
|
function getCurrentSchemaVersion(db) {
|
|
@@ -34756,8 +34756,8 @@ function isNoiseCommit(title, author) {
|
|
|
34756
34756
|
|
|
34757
34757
|
// src/commands/content/phases/change-detector.ts
|
|
34758
34758
|
import { execSync as execSync8 } from "node:child_process";
|
|
34759
|
-
import { existsSync as existsSync64, readFileSync as
|
|
34760
|
-
import { join as
|
|
34759
|
+
import { existsSync as existsSync64, readFileSync as readFileSync19, readdirSync as readdirSync13, statSync as statSync9 } from "node:fs";
|
|
34760
|
+
import { join as join121 } from "node:path";
|
|
34761
34761
|
function detectCommits(repo, since) {
|
|
34762
34762
|
try {
|
|
34763
34763
|
const fetchUrl = sshToHttps(repo.remoteUrl);
|
|
@@ -34855,7 +34855,7 @@ function detectTags(repo, since) {
|
|
|
34855
34855
|
}
|
|
34856
34856
|
}
|
|
34857
34857
|
function detectCompletedPlans(repo, since) {
|
|
34858
|
-
const plansDir =
|
|
34858
|
+
const plansDir = join121(repo.path, "plans");
|
|
34859
34859
|
if (!existsSync64(plansDir))
|
|
34860
34860
|
return [];
|
|
34861
34861
|
const sinceMs = new Date(since).getTime();
|
|
@@ -34865,14 +34865,14 @@ function detectCompletedPlans(repo, since) {
|
|
|
34865
34865
|
for (const entry of entries) {
|
|
34866
34866
|
if (!entry.isDirectory())
|
|
34867
34867
|
continue;
|
|
34868
|
-
const planFile =
|
|
34868
|
+
const planFile = join121(plansDir, entry.name, "plan.md");
|
|
34869
34869
|
if (!existsSync64(planFile))
|
|
34870
34870
|
continue;
|
|
34871
34871
|
try {
|
|
34872
34872
|
const stat15 = statSync9(planFile);
|
|
34873
34873
|
if (stat15.mtimeMs < sinceMs)
|
|
34874
34874
|
continue;
|
|
34875
|
-
const content =
|
|
34875
|
+
const content = readFileSync19(planFile, "utf-8");
|
|
34876
34876
|
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
34877
34877
|
if (!frontmatterMatch)
|
|
34878
34878
|
continue;
|
|
@@ -34943,7 +34943,7 @@ function classifyCommit(event) {
|
|
|
34943
34943
|
// src/commands/content/phases/repo-discoverer.ts
|
|
34944
34944
|
import { execSync as execSync9 } from "node:child_process";
|
|
34945
34945
|
import { readdirSync as readdirSync14 } from "node:fs";
|
|
34946
|
-
import { join as
|
|
34946
|
+
import { join as join122 } from "node:path";
|
|
34947
34947
|
function discoverRepos2(cwd2) {
|
|
34948
34948
|
const repos = [];
|
|
34949
34949
|
if (isGitRepoRoot(cwd2)) {
|
|
@@ -34956,7 +34956,7 @@ function discoverRepos2(cwd2) {
|
|
|
34956
34956
|
for (const entry of entries) {
|
|
34957
34957
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
34958
34958
|
continue;
|
|
34959
|
-
const dirPath =
|
|
34959
|
+
const dirPath = join122(cwd2, entry.name);
|
|
34960
34960
|
if (isGitRepoRoot(dirPath)) {
|
|
34961
34961
|
const info = getRepoInfo(dirPath);
|
|
34962
34962
|
if (info)
|
|
@@ -35623,9 +35623,9 @@ var init_types3 = __esm(() => {
|
|
|
35623
35623
|
|
|
35624
35624
|
// src/commands/content/phases/state-manager.ts
|
|
35625
35625
|
import { readFile as readFile46, rename as rename11, writeFile as writeFile35 } from "node:fs/promises";
|
|
35626
|
-
import { join as
|
|
35626
|
+
import { join as join123 } from "node:path";
|
|
35627
35627
|
async function loadContentConfig(projectDir) {
|
|
35628
|
-
const configPath =
|
|
35628
|
+
const configPath = join123(projectDir, TAKUMI_CONFIG_FILE2);
|
|
35629
35629
|
try {
|
|
35630
35630
|
const raw = await readFile46(configPath, "utf-8");
|
|
35631
35631
|
const json = JSON.parse(raw);
|
|
@@ -35635,13 +35635,13 @@ async function loadContentConfig(projectDir) {
|
|
|
35635
35635
|
}
|
|
35636
35636
|
}
|
|
35637
35637
|
async function saveContentConfig(projectDir, config) {
|
|
35638
|
-
const configPath =
|
|
35638
|
+
const configPath = join123(projectDir, TAKUMI_CONFIG_FILE2);
|
|
35639
35639
|
const json = await readJsonSafe(configPath);
|
|
35640
35640
|
json.content = { ...json.content, ...config };
|
|
35641
35641
|
await atomicWrite2(configPath, json);
|
|
35642
35642
|
}
|
|
35643
35643
|
async function loadContentState(projectDir) {
|
|
35644
|
-
const configPath =
|
|
35644
|
+
const configPath = join123(projectDir, TAKUMI_CONFIG_FILE2);
|
|
35645
35645
|
try {
|
|
35646
35646
|
const raw = await readFile46(configPath, "utf-8");
|
|
35647
35647
|
const json = JSON.parse(raw);
|
|
@@ -35652,7 +35652,7 @@ async function loadContentState(projectDir) {
|
|
|
35652
35652
|
}
|
|
35653
35653
|
}
|
|
35654
35654
|
async function saveContentState(projectDir, state) {
|
|
35655
|
-
const configPath =
|
|
35655
|
+
const configPath = join123(projectDir, TAKUMI_CONFIG_FILE2);
|
|
35656
35656
|
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
35657
35657
|
for (const key of Object.keys(state.dailyPostCounts)) {
|
|
35658
35658
|
const dateStr = key.slice(-10);
|
|
@@ -35934,7 +35934,7 @@ var init_platform_setup_x = __esm(() => {
|
|
|
35934
35934
|
|
|
35935
35935
|
// src/commands/content/phases/setup-wizard.ts
|
|
35936
35936
|
import { existsSync as existsSync65 } from "node:fs";
|
|
35937
|
-
import { join as
|
|
35937
|
+
import { join as join124 } from "node:path";
|
|
35938
35938
|
async function runSetupWizard2(cwd2, contentLogger) {
|
|
35939
35939
|
console.log();
|
|
35940
35940
|
oe(import_picocolors34.default.bgCyan(import_picocolors34.default.white(" SK Content — Multi-Channel Content Engine ")));
|
|
@@ -36002,8 +36002,8 @@ async function showRepoSummary(cwd2) {
|
|
|
36002
36002
|
function detectBrandAssets(cwd2, contentLogger) {
|
|
36003
36003
|
const repos = discoverRepos2(cwd2);
|
|
36004
36004
|
for (const repo of repos) {
|
|
36005
|
-
const hasGuidelines = existsSync65(
|
|
36006
|
-
const hasStyles = existsSync65(
|
|
36005
|
+
const hasGuidelines = existsSync65(join124(repo.path, "docs", "brand-guidelines.md"));
|
|
36006
|
+
const hasStyles = existsSync65(join124(repo.path, "assets", "writing-styles"));
|
|
36007
36007
|
if (!hasGuidelines) {
|
|
36008
36008
|
f2.warning(`${repo.name}: No docs/brand-guidelines.md — content will use generic tone.`);
|
|
36009
36009
|
contentLogger.warn(`${repo.name}: missing docs/brand-guidelines.md`);
|
|
@@ -36143,25 +36143,25 @@ __export(exports_content_subcommands, {
|
|
|
36143
36143
|
logsContent: () => logsContent,
|
|
36144
36144
|
approveContentCmd: () => approveContentCmd
|
|
36145
36145
|
});
|
|
36146
|
-
import { existsSync as existsSync67, readFileSync as
|
|
36146
|
+
import { existsSync as existsSync67, readFileSync as readFileSync20, unlinkSync as unlinkSync7 } from "node:fs";
|
|
36147
36147
|
import { homedir as homedir31 } from "node:os";
|
|
36148
|
-
import { join as
|
|
36148
|
+
import { join as join125 } from "node:path";
|
|
36149
36149
|
function isDaemonRunning() {
|
|
36150
|
-
const lockFile =
|
|
36150
|
+
const lockFile = join125(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
36151
36151
|
if (!existsSync67(lockFile))
|
|
36152
36152
|
return { running: false, pid: null };
|
|
36153
36153
|
try {
|
|
36154
|
-
const pidStr =
|
|
36154
|
+
const pidStr = readFileSync20(lockFile, "utf-8").trim();
|
|
36155
36155
|
const pid = Number.parseInt(pidStr, 10);
|
|
36156
36156
|
if (Number.isNaN(pid)) {
|
|
36157
|
-
|
|
36157
|
+
unlinkSync7(lockFile);
|
|
36158
36158
|
return { running: false, pid: null };
|
|
36159
36159
|
}
|
|
36160
36160
|
process.kill(pid, 0);
|
|
36161
36161
|
return { running: true, pid };
|
|
36162
36162
|
} catch {
|
|
36163
36163
|
try {
|
|
36164
|
-
|
|
36164
|
+
unlinkSync7(lockFile);
|
|
36165
36165
|
} catch {}
|
|
36166
36166
|
return { running: false, pid: null };
|
|
36167
36167
|
}
|
|
@@ -36179,13 +36179,13 @@ async function startContent(options2) {
|
|
|
36179
36179
|
await contentCommand(options2);
|
|
36180
36180
|
}
|
|
36181
36181
|
async function stopContent() {
|
|
36182
|
-
const lockFile =
|
|
36182
|
+
const lockFile = join125(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
36183
36183
|
if (!existsSync67(lockFile)) {
|
|
36184
36184
|
logger.info("Content daemon is not running.");
|
|
36185
36185
|
return;
|
|
36186
36186
|
}
|
|
36187
36187
|
try {
|
|
36188
|
-
const pidStr =
|
|
36188
|
+
const pidStr = readFileSync20(lockFile, "utf-8").trim();
|
|
36189
36189
|
const pid = Number.parseInt(pidStr, 10);
|
|
36190
36190
|
if (!Number.isNaN(pid)) {
|
|
36191
36191
|
process.kill(pid, "SIGTERM");
|
|
@@ -36218,9 +36218,9 @@ async function statusContent() {
|
|
|
36218
36218
|
} catch {}
|
|
36219
36219
|
}
|
|
36220
36220
|
async function logsContent(options2) {
|
|
36221
|
-
const logDir =
|
|
36221
|
+
const logDir = join125(homedir31(), ".sunagentkit", "logs");
|
|
36222
36222
|
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
36223
|
-
const logPath =
|
|
36223
|
+
const logPath = join125(logDir, `content-${dateStr}.log`);
|
|
36224
36224
|
if (!existsSync67(logPath)) {
|
|
36225
36225
|
logger.info("No content logs found for today.");
|
|
36226
36226
|
return;
|
|
@@ -36233,7 +36233,7 @@ async function logsContent(options2) {
|
|
|
36233
36233
|
process.exit(0);
|
|
36234
36234
|
});
|
|
36235
36235
|
} else {
|
|
36236
|
-
const content =
|
|
36236
|
+
const content = readFileSync20(logPath, "utf-8");
|
|
36237
36237
|
console.log(content);
|
|
36238
36238
|
}
|
|
36239
36239
|
}
|
|
@@ -36252,13 +36252,13 @@ var init_content_subcommands = __esm(() => {
|
|
|
36252
36252
|
init_setup_wizard();
|
|
36253
36253
|
init_state_manager();
|
|
36254
36254
|
init_content_review_commands();
|
|
36255
|
-
LOCK_DIR =
|
|
36255
|
+
LOCK_DIR = join125(homedir31(), ".sunagentkit", "locks");
|
|
36256
36256
|
});
|
|
36257
36257
|
|
|
36258
36258
|
// src/commands/content/content-command.ts
|
|
36259
|
-
import { existsSync as existsSync68, mkdirSync as
|
|
36259
|
+
import { existsSync as existsSync68, mkdirSync as mkdirSync9, unlinkSync as unlinkSync8, writeFileSync as writeFileSync8 } from "node:fs";
|
|
36260
36260
|
import { homedir as homedir32 } from "node:os";
|
|
36261
|
-
import { join as
|
|
36261
|
+
import { join as join126 } from "node:path";
|
|
36262
36262
|
async function contentCommand(options2) {
|
|
36263
36263
|
const cwd2 = process.cwd();
|
|
36264
36264
|
const contentLogger = new ContentLogger;
|
|
@@ -36288,8 +36288,8 @@ async function contentCommand(options2) {
|
|
|
36288
36288
|
contentLogger.info("Setup complete. Starting daemon...");
|
|
36289
36289
|
}
|
|
36290
36290
|
if (!existsSync68(LOCK_DIR2))
|
|
36291
|
-
|
|
36292
|
-
|
|
36291
|
+
mkdirSync9(LOCK_DIR2, { recursive: true });
|
|
36292
|
+
writeFileSync8(LOCK_FILE, String(process.pid), "utf-8");
|
|
36293
36293
|
const dbPath = config.dbPath.replace(/^~/, homedir32());
|
|
36294
36294
|
const db = initDatabase(dbPath);
|
|
36295
36295
|
contentLogger.info(`Database initialised at ${dbPath}`);
|
|
@@ -36304,7 +36304,7 @@ async function contentCommand(options2) {
|
|
|
36304
36304
|
abortRequested = true;
|
|
36305
36305
|
contentLogger.info("Shutting down gracefully...");
|
|
36306
36306
|
try {
|
|
36307
|
-
|
|
36307
|
+
unlinkSync8(LOCK_FILE);
|
|
36308
36308
|
} catch {}
|
|
36309
36309
|
await saveContentState(cwd2, state);
|
|
36310
36310
|
closeDatabase(db);
|
|
@@ -36334,7 +36334,7 @@ async function contentCommand(options2) {
|
|
|
36334
36334
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36335
36335
|
contentLogger.error(`Fatal error: ${msg}`);
|
|
36336
36336
|
try {
|
|
36337
|
-
|
|
36337
|
+
unlinkSync8(LOCK_FILE);
|
|
36338
36338
|
} catch {}
|
|
36339
36339
|
contentLogger.close();
|
|
36340
36340
|
process.exit(1);
|
|
@@ -36419,8 +36419,8 @@ function shouldRunCleanup(lastAt) {
|
|
|
36419
36419
|
return Date.now() - new Date(lastAt).getTime() >= 86400000;
|
|
36420
36420
|
}
|
|
36421
36421
|
function sleep3(ms2) {
|
|
36422
|
-
return new Promise((
|
|
36423
|
-
setTimeout(
|
|
36422
|
+
return new Promise((resolve31) => {
|
|
36423
|
+
setTimeout(resolve31, ms2);
|
|
36424
36424
|
});
|
|
36425
36425
|
}
|
|
36426
36426
|
var LOCK_DIR2, LOCK_FILE, MAX_CREATION_RETRIES = 3, MAX_PUBLISH_RETRIES_PER_CYCLE = 3, PUBLISH_RETRY_WINDOW_HOURS = 24;
|
|
@@ -36436,8 +36436,8 @@ var init_content_command = __esm(() => {
|
|
|
36436
36436
|
init_publisher();
|
|
36437
36437
|
init_review_manager();
|
|
36438
36438
|
init_state_manager();
|
|
36439
|
-
LOCK_DIR2 =
|
|
36440
|
-
LOCK_FILE =
|
|
36439
|
+
LOCK_DIR2 = join126(homedir32(), ".sunagentkit", "locks");
|
|
36440
|
+
LOCK_FILE = join126(LOCK_DIR2, "sk-content.lock");
|
|
36441
36441
|
});
|
|
36442
36442
|
|
|
36443
36443
|
// src/commands/content/index.ts
|
|
@@ -37410,7 +37410,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
37410
37410
|
return [];
|
|
37411
37411
|
}
|
|
37412
37412
|
async function trySystemPager(content) {
|
|
37413
|
-
return new Promise((
|
|
37413
|
+
return new Promise((resolve31) => {
|
|
37414
37414
|
const pagerCmd = process.env.PAGER || "less";
|
|
37415
37415
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
37416
37416
|
try {
|
|
@@ -37420,20 +37420,20 @@ async function trySystemPager(content) {
|
|
|
37420
37420
|
});
|
|
37421
37421
|
const timeout = setTimeout(() => {
|
|
37422
37422
|
pager.kill();
|
|
37423
|
-
|
|
37423
|
+
resolve31(false);
|
|
37424
37424
|
}, 30000);
|
|
37425
37425
|
pager.stdin.write(content);
|
|
37426
37426
|
pager.stdin.end();
|
|
37427
37427
|
pager.on("close", (code) => {
|
|
37428
37428
|
clearTimeout(timeout);
|
|
37429
|
-
|
|
37429
|
+
resolve31(code === 0);
|
|
37430
37430
|
});
|
|
37431
37431
|
pager.on("error", () => {
|
|
37432
37432
|
clearTimeout(timeout);
|
|
37433
|
-
|
|
37433
|
+
resolve31(false);
|
|
37434
37434
|
});
|
|
37435
37435
|
} catch {
|
|
37436
|
-
|
|
37436
|
+
resolve31(false);
|
|
37437
37437
|
}
|
|
37438
37438
|
});
|
|
37439
37439
|
}
|
|
@@ -37460,16 +37460,16 @@ async function basicPager(content) {
|
|
|
37460
37460
|
break;
|
|
37461
37461
|
}
|
|
37462
37462
|
const remaining = lines.length - currentLine;
|
|
37463
|
-
await new Promise((
|
|
37463
|
+
await new Promise((resolve31) => {
|
|
37464
37464
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
37465
37465
|
if (answer.toLowerCase() === "q") {
|
|
37466
37466
|
rl.close();
|
|
37467
37467
|
process.exitCode = 0;
|
|
37468
|
-
|
|
37468
|
+
resolve31();
|
|
37469
37469
|
return;
|
|
37470
37470
|
}
|
|
37471
37471
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
37472
|
-
|
|
37472
|
+
resolve31();
|
|
37473
37473
|
});
|
|
37474
37474
|
});
|
|
37475
37475
|
}
|
|
@@ -42877,7 +42877,7 @@ class SystemChecker {
|
|
|
42877
42877
|
}
|
|
42878
42878
|
}
|
|
42879
42879
|
// src/services/file-operations/takumi-scanner.ts
|
|
42880
|
-
import { join as
|
|
42880
|
+
import { join as join69 } from "node:path";
|
|
42881
42881
|
|
|
42882
42882
|
// src/domains/installers/claude-code/paths.ts
|
|
42883
42883
|
import { homedir as homedir6 } from "node:os";
|
|
@@ -49887,7 +49887,7 @@ var claudeCodeInstaller = {
|
|
|
49887
49887
|
import { existsSync as existsSync31 } from "node:fs";
|
|
49888
49888
|
import { rm as rm6 } from "node:fs/promises";
|
|
49889
49889
|
import { homedir as homedir21 } from "node:os";
|
|
49890
|
-
import { join as
|
|
49890
|
+
import { join as join68 } from "node:path";
|
|
49891
49891
|
|
|
49892
49892
|
// src/commands/portable/provider-registry.ts
|
|
49893
49893
|
import { existsSync as existsSync16, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
@@ -50666,7 +50666,7 @@ init_takumi_constants();
|
|
|
50666
50666
|
init_dist2();
|
|
50667
50667
|
|
|
50668
50668
|
// src/domains/installers/codex/install-pipeline.ts
|
|
50669
|
-
import { basename as
|
|
50669
|
+
import { basename as basename9 } from "node:path";
|
|
50670
50670
|
|
|
50671
50671
|
// src/commands/portable/conflict-resolver.ts
|
|
50672
50672
|
init_dist2();
|
|
@@ -51796,9 +51796,32 @@ function buildPlan(actions) {
|
|
|
51796
51796
|
};
|
|
51797
51797
|
}
|
|
51798
51798
|
|
|
51799
|
+
// src/domains/installers/codex/codex-env-marker.ts
|
|
51800
|
+
import { mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
51801
|
+
import { join as join49 } from "node:path";
|
|
51802
|
+
init_logger();
|
|
51803
|
+
var CODEX_ENV_MARKER = `module.exports = { agent: 'codex' };
|
|
51804
|
+
`;
|
|
51805
|
+
function writeCodexEnvMarker(global3) {
|
|
51806
|
+
try {
|
|
51807
|
+
const pathConfig = providers.codex.hooks;
|
|
51808
|
+
if (!pathConfig)
|
|
51809
|
+
return;
|
|
51810
|
+
const scopedPath = global3 ? pathConfig.globalPath : pathConfig.projectPath;
|
|
51811
|
+
if (!scopedPath)
|
|
51812
|
+
return;
|
|
51813
|
+
const targetHooksDir = global3 ? scopedPath : join49(process.cwd(), scopedPath);
|
|
51814
|
+
const libDir = join49(targetHooksDir, "lib");
|
|
51815
|
+
mkdirSync(libDir, { recursive: true });
|
|
51816
|
+
writeFileSync2(join49(libDir, "env.cjs"), CODEX_ENV_MARKER);
|
|
51817
|
+
} catch (e2) {
|
|
51818
|
+
logger.debug(`[init/codex] writeCodexEnvMarker failed: ${String(e2)}`);
|
|
51819
|
+
}
|
|
51820
|
+
}
|
|
51821
|
+
|
|
51799
51822
|
// src/domains/installers/shared/writers/install-one-file.ts
|
|
51800
51823
|
import { writeFile as writeFile18 } from "node:fs/promises";
|
|
51801
|
-
import { dirname as dirname11, join as
|
|
51824
|
+
import { dirname as dirname11, join as join51, resolve as resolve7, sep as sep4 } from "node:path";
|
|
51802
51825
|
|
|
51803
51826
|
// src/commands/portable/converters/codex-command-skill-path.ts
|
|
51804
51827
|
var COMMAND_SKILL_PREFIX = "source-command";
|
|
@@ -52711,7 +52734,7 @@ var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
|
52711
52734
|
import { existsSync as existsSync19 } from "node:fs";
|
|
52712
52735
|
import { mkdir as mkdir13, readFile as readFile21, unlink as unlink4, writeFile as writeFile17 } from "node:fs/promises";
|
|
52713
52736
|
import { homedir as homedir11 } from "node:os";
|
|
52714
|
-
import { basename as basename3, dirname as dirname10, join as
|
|
52737
|
+
import { basename as basename3, dirname as dirname10, join as join50, resolve as resolve6, sep as sep3 } from "node:path";
|
|
52715
52738
|
function isSamePath(path1, path22) {
|
|
52716
52739
|
try {
|
|
52717
52740
|
return resolve6(path1) === resolve6(path22);
|
|
@@ -52814,7 +52837,7 @@ async function ensureDir2(filePath) {
|
|
|
52814
52837
|
}
|
|
52815
52838
|
function getMergeTargetLockPath(targetPath) {
|
|
52816
52839
|
const lockName = `.${basename3(targetPath)}.sk-merge.lock`;
|
|
52817
|
-
return
|
|
52840
|
+
return join50(dirname10(targetPath), lockName);
|
|
52818
52841
|
}
|
|
52819
52842
|
async function withMergeTargetLock(targetPath, operation) {
|
|
52820
52843
|
const resolvedTargetPath = resolve6(targetPath);
|
|
@@ -52923,7 +52946,7 @@ async function installOneFile(item, provider, kind, options2) {
|
|
|
52923
52946
|
const nameWithoutExt = extIdx >= 0 ? resolvedFilename.substring(0, extIdx) : resolvedFilename;
|
|
52924
52947
|
resolvedFilename = `${nameWithoutExt.replace(/\//g, "-")}${ext2}`;
|
|
52925
52948
|
}
|
|
52926
|
-
targetPath = pathConfig.writeStrategy === "single-file" ? basePath :
|
|
52949
|
+
targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join51(basePath, resolvedFilename);
|
|
52927
52950
|
const resolvedTarget = resolve7(targetPath);
|
|
52928
52951
|
const resolvedBase = pathConfig.writeStrategy === "single-file" ? resolve7(dirname11(basePath)) : resolve7(basePath);
|
|
52929
52952
|
if (!resolvedTarget.startsWith(resolvedBase + sep4) && resolvedTarget !== resolvedBase) {
|
|
@@ -53476,7 +53499,7 @@ ${sections.join(`
|
|
|
53476
53499
|
import { existsSync as existsSync21 } from "node:fs";
|
|
53477
53500
|
import { mkdir as mkdir14, readFile as readFile23, realpath, unlink as unlink5, writeFile as writeFile20 } from "node:fs/promises";
|
|
53478
53501
|
import { homedir as homedir12 } from "node:os";
|
|
53479
|
-
import { basename as basename4, dirname as dirname12, isAbsolute, join as
|
|
53502
|
+
import { basename as basename4, dirname as dirname12, isAbsolute, join as join52, relative as relative10, resolve as resolve8 } from "node:path";
|
|
53480
53503
|
init_logger();
|
|
53481
53504
|
var import_proper_lockfile5 = __toESM(require_proper_lockfile(), 1);
|
|
53482
53505
|
var SENTINEL_START = "# --- tkm-managed-agents-start ---";
|
|
@@ -53674,7 +53697,7 @@ function mergeConfigTomlWithDiagnostics(existing, managedBlock) {
|
|
|
53674
53697
|
};
|
|
53675
53698
|
}
|
|
53676
53699
|
function getCodexLockPath(configTomlPath) {
|
|
53677
|
-
return
|
|
53700
|
+
return join52(dirname12(configTomlPath), `.${basename4(configTomlPath)}.tkm-codex.lock`);
|
|
53678
53701
|
}
|
|
53679
53702
|
async function withCodexTargetLock(configTomlPath, operation) {
|
|
53680
53703
|
const resolvedTargetPath = resolve8(configTomlPath);
|
|
@@ -53757,7 +53780,7 @@ async function installCodexToml(items, provider, kind, options2, deps) {
|
|
|
53757
53780
|
}
|
|
53758
53781
|
const boundary = options2.global ? homedir12() : process.cwd();
|
|
53759
53782
|
const agentsDir = resolve8(basePath);
|
|
53760
|
-
const configTomlPath =
|
|
53783
|
+
const configTomlPath = join52(dirname12(agentsDir), "config.toml");
|
|
53761
53784
|
if (!isPathWithinBoundary2(agentsDir, boundary)) {
|
|
53762
53785
|
return {
|
|
53763
53786
|
provider,
|
|
@@ -53848,7 +53871,7 @@ async function installCodexToml(items, provider, kind, options2, deps) {
|
|
|
53848
53871
|
continue;
|
|
53849
53872
|
}
|
|
53850
53873
|
seenSlugOwners.set(slug, item.name);
|
|
53851
|
-
const agentTomlPath =
|
|
53874
|
+
const agentTomlPath = join52(agentsDir, `${slug}.toml`);
|
|
53852
53875
|
if (process.platform === "win32" && agentTomlPath.length > MAX_WINDOWS_PATH_LENGTH) {
|
|
53853
53876
|
allWarnings.push(`Skipped ${item.name}: target path exceeds ${MAX_WINDOWS_PATH_LENGTH} characters on Windows`);
|
|
53854
53877
|
continue;
|
|
@@ -53973,7 +53996,7 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
53973
53996
|
if (!basePath)
|
|
53974
53997
|
return [];
|
|
53975
53998
|
const agentsDir = resolve8(basePath);
|
|
53976
|
-
const configTomlPath =
|
|
53999
|
+
const configTomlPath = join52(dirname12(agentsDir), "config.toml");
|
|
53977
54000
|
if (!existsSync21(configTomlPath))
|
|
53978
54001
|
return [];
|
|
53979
54002
|
try {
|
|
@@ -53984,7 +54007,7 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
53984
54007
|
if (managedEntries.size > 0) {
|
|
53985
54008
|
const validEntries = new Map;
|
|
53986
54009
|
for (const [slug, entry] of managedEntries) {
|
|
53987
|
-
const tomlPath =
|
|
54010
|
+
const tomlPath = join52(agentsDir, `${slug}.toml`);
|
|
53988
54011
|
if (existsSync21(tomlPath)) {
|
|
53989
54012
|
validEntries.set(slug, entry);
|
|
53990
54013
|
} else {
|
|
@@ -54013,7 +54036,7 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
54013
54036
|
const unmanagedSlugs = extractUnmanagedAgentSlugs(analysis.unmanagedContent);
|
|
54014
54037
|
const legacyStaleSlugs = [];
|
|
54015
54038
|
for (const slug of unmanagedSlugs) {
|
|
54016
|
-
const tomlPath =
|
|
54039
|
+
const tomlPath = join52(agentsDir, `${slug}.toml`);
|
|
54017
54040
|
if (!isPathWithinBoundary2(tomlPath, agentsDir))
|
|
54018
54041
|
continue;
|
|
54019
54042
|
if (!existsSync21(tomlPath)) {
|
|
@@ -54090,7 +54113,7 @@ function installCodexHooksItems(items, options2) {
|
|
|
54090
54113
|
// src/domains/installers/shared/skill-directory-installer.ts
|
|
54091
54114
|
import { existsSync as existsSync22 } from "node:fs";
|
|
54092
54115
|
import { cp as cp3, mkdir as mkdir15, rename as rename5, rm as rm5 } from "node:fs/promises";
|
|
54093
|
-
import { join as
|
|
54116
|
+
import { join as join53, resolve as resolve9 } from "node:path";
|
|
54094
54117
|
async function installSkillDirectories(skills, targetProviders, options2) {
|
|
54095
54118
|
const results = [];
|
|
54096
54119
|
for (const provider of targetProviders) {
|
|
@@ -54118,7 +54141,7 @@ async function installSkillDirectories(skills, targetProviders, options2) {
|
|
|
54118
54141
|
continue;
|
|
54119
54142
|
}
|
|
54120
54143
|
for (const skill of skills) {
|
|
54121
|
-
const targetDir =
|
|
54144
|
+
const targetDir = join53(basePath, skill.name);
|
|
54122
54145
|
if (resolve9(skill.path) === resolve9(targetDir)) {
|
|
54123
54146
|
results.push({
|
|
54124
54147
|
provider,
|
|
@@ -54280,8 +54303,8 @@ function displayMultiInstallerSummary(results) {
|
|
|
54280
54303
|
}
|
|
54281
54304
|
|
|
54282
54305
|
// src/domains/installers/codex/post-pipeline.ts
|
|
54283
|
-
import { cpSync, existsSync as existsSync26, readdirSync as readdirSync3 } from "node:fs";
|
|
54284
|
-
import { basename as
|
|
54306
|
+
import { cpSync, existsSync as existsSync26, readFileSync as readFileSync7, readdirSync as readdirSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
54307
|
+
import { basename as basename8, dirname as dirname17, join as join59 } from "node:path";
|
|
54285
54308
|
|
|
54286
54309
|
// src/commands/portable/reconcile-registry-backfill.ts
|
|
54287
54310
|
function shouldBackfillRegistry(action) {
|
|
@@ -54308,7 +54331,7 @@ init_logger();
|
|
|
54308
54331
|
|
|
54309
54332
|
// src/domains/installers/codex/hooks-merger.ts
|
|
54310
54333
|
import { homedir as homedir15 } from "node:os";
|
|
54311
|
-
import { basename as basename6, extname as extname3, isAbsolute as isAbsolute2, join as
|
|
54334
|
+
import { basename as basename6, extname as extname3, isAbsolute as isAbsolute2, join as join57, resolve as resolve13 } from "node:path";
|
|
54312
54335
|
|
|
54313
54336
|
// src/commands/portable/hook-migration-compatibility.ts
|
|
54314
54337
|
import path6 from "node:path";
|
|
@@ -54427,9 +54450,9 @@ function dedupeWarnings(warnings) {
|
|
|
54427
54450
|
}
|
|
54428
54451
|
|
|
54429
54452
|
// src/commands/portable/hooks-settings-merger.ts
|
|
54430
|
-
import { existsSync as existsSync23, mkdirSync, renameSync, rmSync as rmSync2, writeFileSync as
|
|
54453
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync2, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
54431
54454
|
import { readFile as readFile24 } from "node:fs/promises";
|
|
54432
|
-
import { basename as basename5, dirname as dirname13, join as
|
|
54455
|
+
import { basename as basename5, dirname as dirname13, join as join54 } from "node:path";
|
|
54433
54456
|
async function inspectHooksSettings(settingsPath) {
|
|
54434
54457
|
try {
|
|
54435
54458
|
if (!existsSync23(settingsPath)) {
|
|
@@ -54463,7 +54486,7 @@ async function mergeHooksIntoSettings(targetSettingsPath, newHooks) {
|
|
|
54463
54486
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
54464
54487
|
backupPath = `${targetSettingsPath}.${timestamp}.bak`;
|
|
54465
54488
|
try {
|
|
54466
|
-
|
|
54489
|
+
writeFileSync3(backupPath, raw);
|
|
54467
54490
|
} catch {
|
|
54468
54491
|
backupPath = null;
|
|
54469
54492
|
}
|
|
@@ -54472,10 +54495,10 @@ async function mergeHooksIntoSettings(targetSettingsPath, newHooks) {
|
|
|
54472
54495
|
const merged = deduplicateMerge(existingHooks, newHooks);
|
|
54473
54496
|
existingSettings.hooks = merged;
|
|
54474
54497
|
const dir = dirname13(targetSettingsPath);
|
|
54475
|
-
|
|
54498
|
+
mkdirSync2(dir, { recursive: true });
|
|
54476
54499
|
const tempPath = `${targetSettingsPath}.tmp`;
|
|
54477
54500
|
try {
|
|
54478
|
-
|
|
54501
|
+
writeFileSync3(tempPath, JSON.stringify(existingSettings, null, 2));
|
|
54479
54502
|
renameSync(tempPath, targetSettingsPath);
|
|
54480
54503
|
} catch (err) {
|
|
54481
54504
|
rmSync2(tempPath, { force: true });
|
|
@@ -54769,7 +54792,7 @@ var import_proper_lockfile6 = __toESM(require_proper_lockfile(), 1);
|
|
|
54769
54792
|
import { existsSync as existsSync24 } from "node:fs";
|
|
54770
54793
|
import { mkdir as mkdir16, realpath as realpath2 } from "node:fs/promises";
|
|
54771
54794
|
import { homedir as homedir14 } from "node:os";
|
|
54772
|
-
import { dirname as dirname14, join as
|
|
54795
|
+
import { dirname as dirname14, join as join55, resolve as resolve10, sep as sep5 } from "node:path";
|
|
54773
54796
|
function isPathWithinBoundary3(targetPath, boundaryPath) {
|
|
54774
54797
|
const resolvedTarget = resolve10(targetPath);
|
|
54775
54798
|
const resolvedBoundary = resolve10(boundaryPath);
|
|
@@ -54788,7 +54811,7 @@ async function isCanonicalPathWithinBoundary2(targetPath, boundaryPath) {
|
|
|
54788
54811
|
return isPathWithinBoundary3(canonicalTarget, canonicalBoundary);
|
|
54789
54812
|
}
|
|
54790
54813
|
function getCodexLockPath2(targetFilePath) {
|
|
54791
|
-
return
|
|
54814
|
+
return join55(dirname14(resolve10(targetFilePath)), ".config.toml.tkm-codex.lock");
|
|
54792
54815
|
}
|
|
54793
54816
|
async function withCodexTargetLock2(targetFilePath, operation) {
|
|
54794
54817
|
const resolvedTargetPath = resolve10(targetFilePath);
|
|
@@ -54815,7 +54838,7 @@ async function withCodexTargetLock2(targetFilePath, operation) {
|
|
|
54815
54838
|
}
|
|
54816
54839
|
}
|
|
54817
54840
|
function getCodexGlobalBoundary() {
|
|
54818
|
-
return
|
|
54841
|
+
return join55(homedir14(), ".codex");
|
|
54819
54842
|
}
|
|
54820
54843
|
|
|
54821
54844
|
// src/domains/installers/codex/features-flag.ts
|
|
@@ -54986,8 +55009,8 @@ async function atomicWrite(filePath, content) {
|
|
|
54986
55009
|
|
|
54987
55010
|
// src/domains/installers/codex/hook-wrapper.ts
|
|
54988
55011
|
import { createHash as createHash7 } from "node:crypto";
|
|
54989
|
-
import { mkdirSync as
|
|
54990
|
-
import { dirname as dirname16, join as
|
|
55012
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
55013
|
+
import { dirname as dirname16, join as join56, resolve as resolve12 } from "node:path";
|
|
54991
55014
|
function wrapperFilename(originalPath) {
|
|
54992
55015
|
const abs = resolve12(originalPath);
|
|
54993
55016
|
const hash = createHash7("sha256").update(abs).digest("hex").slice(0, 8);
|
|
@@ -54999,7 +55022,7 @@ function generateCodexHookWrappers(originalPaths, wrapperDir, capabilities, time
|
|
|
54999
55022
|
const resolvedWrapperDir = resolve12(wrapperDir);
|
|
55000
55023
|
for (const originalPath of originalPaths) {
|
|
55001
55024
|
const filename = wrapperFilename(originalPath);
|
|
55002
|
-
const wrapperPath =
|
|
55025
|
+
const wrapperPath = join56(resolvedWrapperDir, filename);
|
|
55003
55026
|
if (!isPathWithinBoundary3(wrapperPath, resolvedWrapperDir)) {
|
|
55004
55027
|
results.push({
|
|
55005
55028
|
wrapperPath,
|
|
@@ -55010,11 +55033,11 @@ function generateCodexHookWrappers(originalPaths, wrapperDir, capabilities, time
|
|
|
55010
55033
|
continue;
|
|
55011
55034
|
}
|
|
55012
55035
|
try {
|
|
55013
|
-
|
|
55036
|
+
mkdirSync3(dirname16(wrapperPath), { recursive: true });
|
|
55014
55037
|
const resolvedPath = resolve12(originalPath);
|
|
55015
55038
|
const hookTimeoutMs = timeoutsByPath?.[resolvedPath] ?? timeoutsByPath?.[originalPath];
|
|
55016
55039
|
const content = buildWrapperScript(originalPath, capabilities, hookTimeoutMs);
|
|
55017
|
-
|
|
55040
|
+
writeFileSync4(wrapperPath, content, { mode: 493 });
|
|
55018
55041
|
results.push({ wrapperPath, originalPath, success: true });
|
|
55019
55042
|
} catch (err) {
|
|
55020
55043
|
results.push({
|
|
@@ -55253,8 +55276,8 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55253
55276
|
codexCapabilitiesVersion: capabilities.version
|
|
55254
55277
|
};
|
|
55255
55278
|
}
|
|
55256
|
-
const resolvedSourcePath = sourceSettingsPathOverride ? sourceSettingsPathOverride : isGlobal ? sourceSettingsPath :
|
|
55257
|
-
const resolvedTargetPath = isGlobal ? targetSettingsPath :
|
|
55279
|
+
const resolvedSourcePath = sourceSettingsPathOverride ? sourceSettingsPathOverride : isGlobal ? sourceSettingsPath : join57(process.cwd(), sourceSettingsPath);
|
|
55280
|
+
const resolvedTargetPath = isGlobal ? targetSettingsPath : join57(process.cwd(), targetSettingsPath);
|
|
55258
55281
|
const sourceHooksResult = await inspectHooksSettings(resolvedSourcePath);
|
|
55259
55282
|
if (sourceHooksResult.status === "missing-file") {
|
|
55260
55283
|
return {
|
|
@@ -55303,7 +55326,7 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55303
55326
|
if (targetHooksDir) {
|
|
55304
55327
|
const absSourceHooksDir = sourceHooksDir ? isAbsolute2(sourceHooksDir) ? sourceHooksDir : resolve13(sourceHooksDir) : "";
|
|
55305
55328
|
const absTargetHooksDir = isAbsolute2(targetHooksDir) ? targetHooksDir : resolve13(targetHooksDir);
|
|
55306
|
-
const targetAbsolutePaths = installedHookAbsolutePaths && installedHookAbsolutePaths.length > 0 ? installedHookAbsolutePaths.filter(isCodexWrappableHookPath) : installedHookFiles.filter(isCodexWrappableHookPath).map((basenameOrPath) => basenameOrPath.includes("/") || basenameOrPath.includes("\\") ? basenameOrPath :
|
|
55329
|
+
const targetAbsolutePaths = installedHookAbsolutePaths && installedHookAbsolutePaths.length > 0 ? installedHookAbsolutePaths.filter(isCodexWrappableHookPath) : installedHookFiles.filter(isCodexWrappableHookPath).map((basenameOrPath) => basenameOrPath.includes("/") || basenameOrPath.includes("\\") ? basenameOrPath : join57(absTargetHooksDir, basenameOrPath));
|
|
55307
55330
|
const wrapperResults = generateCodexHookWrappers(targetAbsolutePaths, absTargetHooksDir, capabilities);
|
|
55308
55331
|
for (const wr of wrapperResults) {
|
|
55309
55332
|
if (!wr.success)
|
|
@@ -55312,13 +55335,13 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55312
55335
|
const base = basename6(wr.originalPath);
|
|
55313
55336
|
const addKey = (p) => commandSubstitutions.set(p, wr.wrapperPath);
|
|
55314
55337
|
addKey(wr.originalPath);
|
|
55315
|
-
addKey(
|
|
55338
|
+
addKey(join57(absTargetHooksDir, base));
|
|
55316
55339
|
if (targetHooksDir !== absTargetHooksDir)
|
|
55317
|
-
addKey(
|
|
55340
|
+
addKey(join57(targetHooksDir, base));
|
|
55318
55341
|
if (absSourceHooksDir) {
|
|
55319
|
-
addKey(
|
|
55342
|
+
addKey(join57(absSourceHooksDir, base));
|
|
55320
55343
|
if (sourceHooksDir !== absSourceHooksDir)
|
|
55321
|
-
addKey(
|
|
55344
|
+
addKey(join57(sourceHooksDir, base));
|
|
55322
55345
|
}
|
|
55323
55346
|
}
|
|
55324
55347
|
}
|
|
@@ -55364,7 +55387,7 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55364
55387
|
}
|
|
55365
55388
|
let featureFlagWritten = false;
|
|
55366
55389
|
if (capabilities.requiresFeatureFlag) {
|
|
55367
|
-
const configTomlPath = isGlobal ?
|
|
55390
|
+
const configTomlPath = isGlobal ? join57(homedir15(), ".codex", "config.toml") : join57(process.cwd(), ".codex", "config.toml");
|
|
55368
55391
|
const flagResult = await ensureCodexHooksFeatureFlag(configTomlPath, isGlobal);
|
|
55369
55392
|
featureFlagWritten = flagResult.status === "written" || flagResult.status === "updated";
|
|
55370
55393
|
}
|
|
@@ -55382,6 +55405,101 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55382
55405
|
};
|
|
55383
55406
|
}
|
|
55384
55407
|
|
|
55408
|
+
// src/domains/installers/codex/prune-deleted-hooks.ts
|
|
55409
|
+
import { basename as basename7, join as join58, resolve as resolve14 } from "node:path";
|
|
55410
|
+
var WRAPPER_HASH_PREFIX = /^[0-9a-f]{8}-/;
|
|
55411
|
+
function deletionsToBasenames(deletions) {
|
|
55412
|
+
const out = [];
|
|
55413
|
+
for (const entry of deletions) {
|
|
55414
|
+
if (!entry || typeof entry !== "string")
|
|
55415
|
+
continue;
|
|
55416
|
+
if (!entry.startsWith("hooks/"))
|
|
55417
|
+
continue;
|
|
55418
|
+
if (entry.includes("*"))
|
|
55419
|
+
continue;
|
|
55420
|
+
const base = basename7(entry);
|
|
55421
|
+
if (base.endsWith(".cjs"))
|
|
55422
|
+
out.push(base);
|
|
55423
|
+
}
|
|
55424
|
+
return out;
|
|
55425
|
+
}
|
|
55426
|
+
function commandReferencesBasename(command, base) {
|
|
55427
|
+
const segments = command.split(/[\s"'`]+/).filter(Boolean);
|
|
55428
|
+
for (const tok of segments) {
|
|
55429
|
+
const tokBase = basename7(tok);
|
|
55430
|
+
if (tokBase === base)
|
|
55431
|
+
return true;
|
|
55432
|
+
if (tokBase.endsWith(base) && tokBase.length === base.length + 9 && WRAPPER_HASH_PREFIX.test(tokBase) && tokBase.slice(9) === base) {
|
|
55433
|
+
return true;
|
|
55434
|
+
}
|
|
55435
|
+
}
|
|
55436
|
+
return false;
|
|
55437
|
+
}
|
|
55438
|
+
function pruneDeletedHooks(userHooksJson, deletions, wrapperDir) {
|
|
55439
|
+
const basenames = deletionsToBasenames(deletions);
|
|
55440
|
+
const removedWrapperPaths = [];
|
|
55441
|
+
let prunedRegistrationCount = 0;
|
|
55442
|
+
if (!userHooksJson || typeof userHooksJson !== "object") {
|
|
55443
|
+
return {
|
|
55444
|
+
prunedJson: userHooksJson ?? {},
|
|
55445
|
+
removedWrapperPaths: [],
|
|
55446
|
+
prunedRegistrationCount: 0
|
|
55447
|
+
};
|
|
55448
|
+
}
|
|
55449
|
+
if (basenames.length === 0) {
|
|
55450
|
+
return {
|
|
55451
|
+
prunedJson: userHooksJson,
|
|
55452
|
+
removedWrapperPaths: [],
|
|
55453
|
+
prunedRegistrationCount: 0
|
|
55454
|
+
};
|
|
55455
|
+
}
|
|
55456
|
+
const resolvedWrapperDir = resolve14(wrapperDir);
|
|
55457
|
+
const cloned = JSON.parse(JSON.stringify(userHooksJson));
|
|
55458
|
+
const hooks = cloned.hooks ?? {};
|
|
55459
|
+
for (const eventName of Object.keys(hooks)) {
|
|
55460
|
+
const groups = hooks[eventName] ?? [];
|
|
55461
|
+
const survivingGroups = [];
|
|
55462
|
+
for (const group of groups) {
|
|
55463
|
+
const entries = group.hooks ?? [];
|
|
55464
|
+
const survivingEntries = [];
|
|
55465
|
+
for (const entry of entries) {
|
|
55466
|
+
const cmd = typeof entry.command === "string" ? entry.command : "";
|
|
55467
|
+
const matchedBase = basenames.find((b3) => commandReferencesBasename(cmd, b3));
|
|
55468
|
+
if (matchedBase) {
|
|
55469
|
+
prunedRegistrationCount += 1;
|
|
55470
|
+
const tokens = cmd.split(/[\s"'`]+/).filter(Boolean);
|
|
55471
|
+
for (const tok of tokens) {
|
|
55472
|
+
const tokBase = basename7(tok);
|
|
55473
|
+
if (tokBase === matchedBase || tokBase.endsWith(`-${matchedBase}`)) {
|
|
55474
|
+
const candidate = resolve14(join58(resolvedWrapperDir, tokBase));
|
|
55475
|
+
if (isPathWithinBoundary3(candidate, resolvedWrapperDir)) {
|
|
55476
|
+
removedWrapperPaths.push(candidate);
|
|
55477
|
+
}
|
|
55478
|
+
}
|
|
55479
|
+
}
|
|
55480
|
+
} else {
|
|
55481
|
+
survivingEntries.push(entry);
|
|
55482
|
+
}
|
|
55483
|
+
}
|
|
55484
|
+
if (survivingEntries.length > 0) {
|
|
55485
|
+
survivingGroups.push({ ...group, hooks: survivingEntries });
|
|
55486
|
+
}
|
|
55487
|
+
}
|
|
55488
|
+
if (survivingGroups.length > 0) {
|
|
55489
|
+
hooks[eventName] = survivingGroups;
|
|
55490
|
+
} else {
|
|
55491
|
+
delete hooks[eventName];
|
|
55492
|
+
}
|
|
55493
|
+
}
|
|
55494
|
+
cloned.hooks = hooks;
|
|
55495
|
+
const uniqueWrappers = Array.from(new Set(removedWrapperPaths));
|
|
55496
|
+
return {
|
|
55497
|
+
prunedJson: cloned,
|
|
55498
|
+
removedWrapperPaths: uniqueWrappers,
|
|
55499
|
+
prunedRegistrationCount
|
|
55500
|
+
};
|
|
55501
|
+
}
|
|
55502
|
+
|
|
55385
55503
|
// src/domains/installers/codex/post-pipeline.ts
|
|
55386
55504
|
var HOOK_SUPPORT_SKIP_DIRS = new Set(["__tests__", "tests", "docs"]);
|
|
55387
55505
|
function installCodexHookSupportDirs(hookItems, global3) {
|
|
@@ -55396,12 +55514,12 @@ function installCodexHookSupportDirs(hookItems, global3) {
|
|
|
55396
55514
|
const scopedPath = global3 ? pathConfig.globalPath : pathConfig.projectPath;
|
|
55397
55515
|
if (!scopedPath)
|
|
55398
55516
|
return;
|
|
55399
|
-
const targetHooksDir = global3 ? scopedPath :
|
|
55517
|
+
const targetHooksDir = global3 ? scopedPath : join59(process.cwd(), scopedPath);
|
|
55400
55518
|
for (const entry of readdirSync3(sourceHooksDir, { withFileTypes: true })) {
|
|
55401
55519
|
if (!entry.isDirectory() || HOOK_SUPPORT_SKIP_DIRS.has(entry.name))
|
|
55402
55520
|
continue;
|
|
55403
|
-
const src =
|
|
55404
|
-
const dest =
|
|
55521
|
+
const src = join59(sourceHooksDir, entry.name);
|
|
55522
|
+
const dest = join59(targetHooksDir, entry.name);
|
|
55405
55523
|
if (!existsSync26(dest)) {
|
|
55406
55524
|
cpSync(src, dest, { recursive: true });
|
|
55407
55525
|
} else {
|
|
@@ -55433,7 +55551,7 @@ function deriveKitHookSource(items) {
|
|
|
55433
55551
|
if (!kitConfigRoot)
|
|
55434
55552
|
return;
|
|
55435
55553
|
return {
|
|
55436
|
-
settingsPath:
|
|
55554
|
+
settingsPath: join59(kitConfigRoot, "settings.json"),
|
|
55437
55555
|
hooksDir: ".claude/hooks"
|
|
55438
55556
|
};
|
|
55439
55557
|
}
|
|
@@ -55442,7 +55560,7 @@ async function cleanupStaleCodexToml(global3) {
|
|
|
55442
55560
|
const staleSlugs = await cleanupStaleCodexConfigEntries({ global: global3, provider: "codex" });
|
|
55443
55561
|
if (staleSlugs.length > 0) {
|
|
55444
55562
|
const staleSet = new Set(staleSlugs.map((s) => `${s}.toml`));
|
|
55445
|
-
await removeInstallationsByFilter((i) => i.type === "agent" && i.provider === "codex" && i.global === global3 && staleSet.has(
|
|
55563
|
+
await removeInstallationsByFilter((i) => i.type === "agent" && i.provider === "codex" && i.global === global3 && staleSet.has(basename8(i.path)));
|
|
55446
55564
|
}
|
|
55447
55565
|
} catch (e2) {
|
|
55448
55566
|
logger.debug(`[init/codex] codex-toml cleanup failed: ${String(e2)}`);
|
|
@@ -55455,6 +55573,47 @@ async function healRegistryChecksums(actions, registry) {
|
|
|
55455
55573
|
logger.debug("[init/codex] backfill checksums failed");
|
|
55456
55574
|
}
|
|
55457
55575
|
}
|
|
55576
|
+
async function pruneCodexDeletedHooks(items, global3) {
|
|
55577
|
+
try {
|
|
55578
|
+
const kitRoot = items.agents[0]?.sourcePath?.split(/[/\\]agents[/\\]/)[0] ?? items.commands[0]?.sourcePath?.split(/[/\\]commands[/\\]/)[0] ?? items.hooks[0]?.sourcePath?.split(/[/\\]hooks[/\\]/)[0] ?? null;
|
|
55579
|
+
if (!kitRoot)
|
|
55580
|
+
return;
|
|
55581
|
+
const metadataPath = join59(kitRoot, "metadata.json");
|
|
55582
|
+
if (!existsSync26(metadataPath))
|
|
55583
|
+
return;
|
|
55584
|
+
const metadataRaw = readFileSync7(metadataPath, "utf-8");
|
|
55585
|
+
const metadata = JSON.parse(metadataRaw);
|
|
55586
|
+
const deletions = metadata.deletions ?? [];
|
|
55587
|
+
if (deletions.length === 0)
|
|
55588
|
+
return;
|
|
55589
|
+
const codex = providers.codex;
|
|
55590
|
+
const hooksJsonPath = global3 ? codex.settingsJsonPath?.globalPath : codex.settingsJsonPath?.projectPath ? join59(process.cwd(), codex.settingsJsonPath.projectPath) : null;
|
|
55591
|
+
if (!hooksJsonPath || !existsSync26(hooksJsonPath))
|
|
55592
|
+
return;
|
|
55593
|
+
const wrapperDir = global3 ? codex.hooks?.globalPath : codex.hooks?.projectPath ? join59(process.cwd(), codex.hooks.projectPath) : null;
|
|
55594
|
+
if (!wrapperDir)
|
|
55595
|
+
return;
|
|
55596
|
+
const userJson = JSON.parse(readFileSync7(hooksJsonPath, "utf-8"));
|
|
55597
|
+
const { prunedJson, removedWrapperPaths, prunedRegistrationCount } = pruneDeletedHooks(userJson, deletions, wrapperDir);
|
|
55598
|
+
if (prunedRegistrationCount === 0 && removedWrapperPaths.length === 0)
|
|
55599
|
+
return;
|
|
55600
|
+
if (prunedRegistrationCount > 0) {
|
|
55601
|
+
writeFileSync5(hooksJsonPath, `${JSON.stringify(prunedJson, null, 2)}
|
|
55602
|
+
`);
|
|
55603
|
+
}
|
|
55604
|
+
for (const wrapperPath of removedWrapperPaths) {
|
|
55605
|
+
try {
|
|
55606
|
+
if (existsSync26(wrapperPath))
|
|
55607
|
+
unlinkSync3(wrapperPath);
|
|
55608
|
+
} catch (e2) {
|
|
55609
|
+
logger.debug(`[init/codex] failed to unlink wrapper ${wrapperPath}: ${String(e2)}`);
|
|
55610
|
+
}
|
|
55611
|
+
}
|
|
55612
|
+
logger.debug(`[init/codex] pruned ${prunedRegistrationCount} stale hook registration(s) and ${removedWrapperPaths.length} wrapper file(s)`);
|
|
55613
|
+
} catch (e2) {
|
|
55614
|
+
logger.debug(`[init/codex] pruneCodexDeletedHooks failed: ${String(e2)}`);
|
|
55615
|
+
}
|
|
55616
|
+
}
|
|
55458
55617
|
async function bumpAppliedManifestVersion(items) {
|
|
55459
55618
|
try {
|
|
55460
55619
|
const kitRoot = items.agents[0]?.sourcePath?.split(/[/\\]agents[/\\]/)[0] ?? items.commands[0]?.sourcePath?.split(/[/\\]commands[/\\]/)[0] ?? null;
|
|
@@ -55651,12 +55810,12 @@ async function computeCodexTargetStates(global3) {
|
|
|
55651
55810
|
import { existsSync as existsSync29 } from "node:fs";
|
|
55652
55811
|
import { readFile as readFile27, readdir as readdir16 } from "node:fs/promises";
|
|
55653
55812
|
import { homedir as homedir16 } from "node:os";
|
|
55654
|
-
import { extname as extname4, join as
|
|
55813
|
+
import { extname as extname4, join as join61, relative as relative11, sep as sep6 } from "node:path";
|
|
55655
55814
|
|
|
55656
55815
|
// src/shared/kit-layout.ts
|
|
55657
55816
|
init_types2();
|
|
55658
|
-
import { existsSync as existsSync28, readFileSync as
|
|
55659
|
-
import { join as
|
|
55817
|
+
import { existsSync as existsSync28, readFileSync as readFileSync8 } from "node:fs";
|
|
55818
|
+
import { join as join60 } from "node:path";
|
|
55660
55819
|
function uniquePaths(paths) {
|
|
55661
55820
|
return [...new Set(paths)];
|
|
55662
55821
|
}
|
|
@@ -55669,12 +55828,12 @@ function findFirstExistingPath(paths) {
|
|
|
55669
55828
|
return null;
|
|
55670
55829
|
}
|
|
55671
55830
|
function resolveKitLayout(projectRoot) {
|
|
55672
|
-
const packageJsonPath =
|
|
55831
|
+
const packageJsonPath = join60(projectRoot, "package.json");
|
|
55673
55832
|
if (!existsSync28(packageJsonPath)) {
|
|
55674
55833
|
return DEFAULT_KIT_LAYOUT;
|
|
55675
55834
|
}
|
|
55676
55835
|
try {
|
|
55677
|
-
const parsed = TakumiPackageMetadataSchema.parse(JSON.parse(
|
|
55836
|
+
const parsed = TakumiPackageMetadataSchema.parse(JSON.parse(readFileSync8(packageJsonPath, "utf8")));
|
|
55678
55837
|
return KitLayoutSchema.parse({
|
|
55679
55838
|
...DEFAULT_KIT_LAYOUT,
|
|
55680
55839
|
...parsed.takumi ?? {}
|
|
@@ -55686,8 +55845,8 @@ function resolveKitLayout(projectRoot) {
|
|
|
55686
55845
|
function getProjectLayoutCandidates(projectRoot, subPath) {
|
|
55687
55846
|
const layout = resolveKitLayout(projectRoot);
|
|
55688
55847
|
return uniquePaths([
|
|
55689
|
-
|
|
55690
|
-
|
|
55848
|
+
join60(projectRoot, layout.sourceDir, subPath),
|
|
55849
|
+
join60(projectRoot, DEFAULT_KIT_LAYOUT.sourceDir, subPath)
|
|
55691
55850
|
]);
|
|
55692
55851
|
}
|
|
55693
55852
|
function findExistingProjectLayoutPath(projectRoot, subPath) {
|
|
@@ -55696,9 +55855,9 @@ function findExistingProjectLayoutPath(projectRoot, subPath) {
|
|
|
55696
55855
|
function getProjectConfigCandidates(projectRoot) {
|
|
55697
55856
|
const layout = resolveKitLayout(projectRoot);
|
|
55698
55857
|
return uniquePaths([
|
|
55699
|
-
|
|
55700
|
-
|
|
55701
|
-
|
|
55858
|
+
join60(projectRoot, "CLAUDE.md"),
|
|
55859
|
+
join60(projectRoot, layout.sourceDir, "CLAUDE.md"),
|
|
55860
|
+
join60(projectRoot, DEFAULT_KIT_LAYOUT.sourceDir, "CLAUDE.md")
|
|
55702
55861
|
]);
|
|
55703
55862
|
}
|
|
55704
55863
|
function findExistingProjectConfigPath(projectRoot) {
|
|
@@ -55712,13 +55871,13 @@ function getConfigSourcePath() {
|
|
|
55712
55871
|
return findExistingProjectConfigPath(process.cwd()) ?? getGlobalConfigSourcePath();
|
|
55713
55872
|
}
|
|
55714
55873
|
function getGlobalConfigSourcePath() {
|
|
55715
|
-
return
|
|
55874
|
+
return join61(homedir16(), ".claude", "CLAUDE.md");
|
|
55716
55875
|
}
|
|
55717
55876
|
function getRulesSourcePath() {
|
|
55718
|
-
return findExistingProjectLayoutPath(process.cwd(), "rules") ??
|
|
55877
|
+
return findExistingProjectLayoutPath(process.cwd(), "rules") ?? join61(homedir16(), ".claude", "rules");
|
|
55719
55878
|
}
|
|
55720
55879
|
function getHooksSourcePath() {
|
|
55721
|
-
return findExistingProjectLayoutPath(process.cwd(), "hooks") ??
|
|
55880
|
+
return findExistingProjectLayoutPath(process.cwd(), "hooks") ?? join61(homedir16(), ".claude", "hooks");
|
|
55722
55881
|
}
|
|
55723
55882
|
async function discoverConfig(sourcePath) {
|
|
55724
55883
|
const path7 = sourcePath ?? getConfigSourcePath();
|
|
@@ -55770,7 +55929,7 @@ async function discoverHooks(sourcePath) {
|
|
|
55770
55929
|
}
|
|
55771
55930
|
if (!HOOK_EXTENSIONS.has(ext2))
|
|
55772
55931
|
continue;
|
|
55773
|
-
const fullPath =
|
|
55932
|
+
const fullPath = join61(path7, entry.name);
|
|
55774
55933
|
try {
|
|
55775
55934
|
const content = await readFile27(fullPath, "utf-8");
|
|
55776
55935
|
items.push({
|
|
@@ -55796,7 +55955,7 @@ async function discoverPortableFiles(dir, baseDir, options2) {
|
|
|
55796
55955
|
for (const entry of entries) {
|
|
55797
55956
|
if (entry.name.startsWith("."))
|
|
55798
55957
|
continue;
|
|
55799
|
-
const fullPath =
|
|
55958
|
+
const fullPath = join61(dir, entry.name);
|
|
55800
55959
|
if (entry.isSymbolicLink()) {
|
|
55801
55960
|
continue;
|
|
55802
55961
|
}
|
|
@@ -55834,7 +55993,7 @@ async function discoverPortableFiles(dir, baseDir, options2) {
|
|
|
55834
55993
|
// src/domains/installers/shared/agents-discovery.ts
|
|
55835
55994
|
import { readdir as readdir17 } from "node:fs/promises";
|
|
55836
55995
|
import { homedir as homedir17 } from "node:os";
|
|
55837
|
-
import { join as
|
|
55996
|
+
import { join as join62 } from "node:path";
|
|
55838
55997
|
|
|
55839
55998
|
// src/commands/portable/frontmatter-parser.ts
|
|
55840
55999
|
init_logger();
|
|
@@ -55934,7 +56093,7 @@ var home3 = homedir17();
|
|
|
55934
56093
|
function getAgentSourcePath() {
|
|
55935
56094
|
return findFirstExistingPath([
|
|
55936
56095
|
...getProjectLayoutCandidates(process.cwd(), "agents"),
|
|
55937
|
-
|
|
56096
|
+
join62(home3, ".claude/agents")
|
|
55938
56097
|
]);
|
|
55939
56098
|
}
|
|
55940
56099
|
async function discoverAgents(sourcePath) {
|
|
@@ -55947,7 +56106,7 @@ async function discoverAgents(sourcePath) {
|
|
|
55947
56106
|
for (const entry of entries) {
|
|
55948
56107
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
55949
56108
|
continue;
|
|
55950
|
-
const filePath =
|
|
56109
|
+
const filePath = join62(searchPath, entry.name);
|
|
55951
56110
|
try {
|
|
55952
56111
|
const { frontmatter, body } = await parseFrontmatterFile(filePath);
|
|
55953
56112
|
const name = entry.name.replace(/\.md$/, "");
|
|
@@ -55971,14 +56130,14 @@ async function discoverAgents(sourcePath) {
|
|
|
55971
56130
|
// src/domains/installers/shared/commands-discovery.ts
|
|
55972
56131
|
import { readdir as readdir18 } from "node:fs/promises";
|
|
55973
56132
|
import { homedir as homedir18 } from "node:os";
|
|
55974
|
-
import { join as
|
|
56133
|
+
import { join as join63, relative as relative12 } from "node:path";
|
|
55975
56134
|
init_logger();
|
|
55976
56135
|
var home4 = homedir18();
|
|
55977
56136
|
var SKIP_DIRS = ["node_modules", ".git", "dist", "build"];
|
|
55978
56137
|
function getCommandSourcePath() {
|
|
55979
56138
|
return findFirstExistingPath([
|
|
55980
56139
|
...getProjectLayoutCandidates(process.cwd(), "commands"),
|
|
55981
|
-
|
|
56140
|
+
join63(home4, ".claude/commands")
|
|
55982
56141
|
]);
|
|
55983
56142
|
}
|
|
55984
56143
|
async function scanCommandDir(dir, rootDir) {
|
|
@@ -55986,7 +56145,7 @@ async function scanCommandDir(dir, rootDir) {
|
|
|
55986
56145
|
try {
|
|
55987
56146
|
const entries = await readdir18(dir, { withFileTypes: true });
|
|
55988
56147
|
for (const entry of entries) {
|
|
55989
|
-
const fullPath =
|
|
56148
|
+
const fullPath = join63(dir, entry.name);
|
|
55990
56149
|
if (entry.isDirectory()) {
|
|
55991
56150
|
if (SKIP_DIRS.includes(entry.name))
|
|
55992
56151
|
continue;
|
|
@@ -56028,23 +56187,23 @@ async function discoverCommands(sourcePath) {
|
|
|
56028
56187
|
// src/domains/installers/shared/skills-discovery.ts
|
|
56029
56188
|
import { readFile as readFile29, readdir as readdir19, stat as stat6 } from "node:fs/promises";
|
|
56030
56189
|
import { homedir as homedir19 } from "node:os";
|
|
56031
|
-
import { dirname as dirname18, join as
|
|
56190
|
+
import { dirname as dirname18, join as join64 } from "node:path";
|
|
56032
56191
|
init_logger();
|
|
56033
56192
|
var import_gray_matter4 = __toESM(require_gray_matter(), 1);
|
|
56034
56193
|
var home5 = homedir19();
|
|
56035
56194
|
var SKIP_DIRS2 = ["node_modules", ".git", "dist", "build", ".venv", "__pycache__", "common"];
|
|
56036
56195
|
function getSkillSourcePath() {
|
|
56037
|
-
const bundledRoot =
|
|
56196
|
+
const bundledRoot = join64(process.cwd(), "node_modules", "takumi-engineer");
|
|
56038
56197
|
return findFirstExistingPath([
|
|
56039
|
-
|
|
56198
|
+
join64(bundledRoot, "skills"),
|
|
56040
56199
|
...getProjectLayoutCandidates(bundledRoot, "skills"),
|
|
56041
56200
|
...getProjectLayoutCandidates(process.cwd(), "skills"),
|
|
56042
|
-
|
|
56201
|
+
join64(home5, ".claude/skills")
|
|
56043
56202
|
]);
|
|
56044
56203
|
}
|
|
56045
56204
|
async function hasSkillMd(dir) {
|
|
56046
56205
|
try {
|
|
56047
|
-
const skillPath =
|
|
56206
|
+
const skillPath = join64(dir, "SKILL.md");
|
|
56048
56207
|
const stats = await stat6(skillPath);
|
|
56049
56208
|
return stats.isFile();
|
|
56050
56209
|
} catch {
|
|
@@ -56092,9 +56251,9 @@ async function discoverSkills(sourcePath) {
|
|
|
56092
56251
|
if (!entry.isDirectory() || SKIP_DIRS2.includes(entry.name)) {
|
|
56093
56252
|
continue;
|
|
56094
56253
|
}
|
|
56095
|
-
const skillDir =
|
|
56254
|
+
const skillDir = join64(searchPath, entry.name);
|
|
56096
56255
|
if (await hasSkillMd(skillDir)) {
|
|
56097
|
-
const skill = await parseSkillMd(
|
|
56256
|
+
const skill = await parseSkillMd(join64(skillDir, "SKILL.md"));
|
|
56098
56257
|
if (skill && !seenNames.has(skill.name)) {
|
|
56099
56258
|
skills.push(skill);
|
|
56100
56259
|
seenNames.add(skill.name);
|
|
@@ -56236,7 +56395,7 @@ async function executeCodexPipeline(items, options2) {
|
|
|
56236
56395
|
results.push(...installed);
|
|
56237
56396
|
if (action.type === "hooks") {
|
|
56238
56397
|
for (const r2 of installed.filter((r3) => r3.success && !r3.skipped)) {
|
|
56239
|
-
successfulHookFiles.push(
|
|
56398
|
+
successfulHookFiles.push(basename9(r2.path));
|
|
56240
56399
|
}
|
|
56241
56400
|
}
|
|
56242
56401
|
}
|
|
@@ -56249,7 +56408,9 @@ async function executeCodexPipeline(items, options2) {
|
|
|
56249
56408
|
ui.phase("Finalizing post-install");
|
|
56250
56409
|
if (items.hooks.length > 0) {
|
|
56251
56410
|
installCodexHookSupportDirs(items.hooks, options2.global);
|
|
56411
|
+
writeCodexEnvMarker(options2.global);
|
|
56252
56412
|
}
|
|
56413
|
+
await pruneCodexDeletedHooks(items, options2.global);
|
|
56253
56414
|
await mergeInstalledHooks(successfulHookFiles, options2.global, deriveKitHookSource(items));
|
|
56254
56415
|
await cleanupStaleCodexToml(options2.global);
|
|
56255
56416
|
await healRegistryChecksums(plan.actions, registry);
|
|
@@ -56267,11 +56428,11 @@ async function executeCodexPipeline(items, options2) {
|
|
|
56267
56428
|
|
|
56268
56429
|
// src/domains/installers/codex/scan-codex-directory.ts
|
|
56269
56430
|
var import_fs_extra29 = __toESM(require_lib(), 1);
|
|
56270
|
-
import { join as
|
|
56431
|
+
import { join as join65 } from "node:path";
|
|
56271
56432
|
|
|
56272
56433
|
// src/domains/installers/codex/skills-paths.ts
|
|
56273
56434
|
import { homedir as homedir20 } from "node:os";
|
|
56274
|
-
import { resolve as
|
|
56435
|
+
import { resolve as resolve15 } from "node:path";
|
|
56275
56436
|
function getCodexSkillsTargetDir(global3) {
|
|
56276
56437
|
const cfg = providers.codex.skills;
|
|
56277
56438
|
if (!cfg) {
|
|
@@ -56281,7 +56442,7 @@ function getCodexSkillsTargetDir(global3) {
|
|
|
56281
56442
|
if (!path7) {
|
|
56282
56443
|
throw new Error(`[codex] no ${global3 ? "global" : "project"}-level skills path configured`);
|
|
56283
56444
|
}
|
|
56284
|
-
const resolved =
|
|
56445
|
+
const resolved = resolve15(path7);
|
|
56285
56446
|
const boundary = global3 ? homedir20() : process.cwd();
|
|
56286
56447
|
if (!isPathWithinBoundary3(resolved, boundary)) {
|
|
56287
56448
|
throw new Error(`[codex] resolved skills path "${resolved}" escapes boundary "${boundary}"`);
|
|
@@ -56297,11 +56458,11 @@ async function scanCodexDirectory(root, opts = {}) {
|
|
|
56297
56458
|
return counts;
|
|
56298
56459
|
const items = await import_fs_extra29.readdir(root);
|
|
56299
56460
|
if (items.includes("agents")) {
|
|
56300
|
-
const files = await import_fs_extra29.readdir(
|
|
56461
|
+
const files = await import_fs_extra29.readdir(join65(root, "agents")).catch(() => []);
|
|
56301
56462
|
counts.agents = files.filter((f3) => f3.endsWith(".toml")).length;
|
|
56302
56463
|
}
|
|
56303
56464
|
if (items.includes("prompts")) {
|
|
56304
|
-
const files = await import_fs_extra29.readdir(
|
|
56465
|
+
const files = await import_fs_extra29.readdir(join65(root, "prompts")).catch(() => []);
|
|
56305
56466
|
counts.commands = files.filter((f3) => f3.endsWith(".md")).length;
|
|
56306
56467
|
}
|
|
56307
56468
|
if (items.includes("AGENTS.md"))
|
|
@@ -56310,7 +56471,7 @@ async function scanCodexDirectory(root, opts = {}) {
|
|
|
56310
56471
|
if (await import_fs_extra29.pathExists(skillsRoot)) {
|
|
56311
56472
|
const dirs = await import_fs_extra29.readdir(skillsRoot).catch(() => []);
|
|
56312
56473
|
for (const d3 of dirs) {
|
|
56313
|
-
const skillDir =
|
|
56474
|
+
const skillDir = join65(skillsRoot, d3);
|
|
56314
56475
|
const entries = await import_fs_extra29.readdir(skillDir).catch(() => null);
|
|
56315
56476
|
if (entries?.includes("SKILL.md"))
|
|
56316
56477
|
counts.skills++;
|
|
@@ -56322,7 +56483,7 @@ async function scanCodexDirectory(root, opts = {}) {
|
|
|
56322
56483
|
|
|
56323
56484
|
// src/domains/installers/codex/source-resolver.ts
|
|
56324
56485
|
import { existsSync as existsSync30 } from "node:fs";
|
|
56325
|
-
import { join as
|
|
56486
|
+
import { join as join66 } from "node:path";
|
|
56326
56487
|
function resolveCodexSources(extractDir) {
|
|
56327
56488
|
return {
|
|
56328
56489
|
agents: findExistingProjectLayoutPath(extractDir, "agents"),
|
|
@@ -56334,7 +56495,7 @@ function resolveCodexSources(extractDir) {
|
|
|
56334
56495
|
};
|
|
56335
56496
|
}
|
|
56336
56497
|
function resolveConfigSource(extractDir) {
|
|
56337
|
-
const rootClaudeMd =
|
|
56498
|
+
const rootClaudeMd = join66(extractDir, "CLAUDE.md");
|
|
56338
56499
|
if (existsSync30(rootClaudeMd))
|
|
56339
56500
|
return rootClaudeMd;
|
|
56340
56501
|
return findExistingProjectConfigPath(extractDir);
|
|
@@ -56345,7 +56506,7 @@ function hasAnyCodexSource(sources) {
|
|
|
56345
56506
|
|
|
56346
56507
|
// src/domains/installers/codex/manifest-helpers.ts
|
|
56347
56508
|
var import_fs_extra30 = __toESM(require_lib(), 1);
|
|
56348
|
-
import { join as
|
|
56509
|
+
import { join as join67, relative as relative13, sep as sep7 } from "node:path";
|
|
56349
56510
|
var codexOwnershipResolver = () => ({ ownership: "takumi" });
|
|
56350
56511
|
async function collectCodexInstalledFiles(results, codexRoot) {
|
|
56351
56512
|
const out = [];
|
|
@@ -56369,7 +56530,7 @@ async function collectCodexInstalledFiles(results, codexRoot) {
|
|
|
56369
56530
|
async function walkDir(dir, root, out, toPosix) {
|
|
56370
56531
|
const entries = await import_fs_extra30.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
56371
56532
|
for (const e2 of entries) {
|
|
56372
|
-
const p =
|
|
56533
|
+
const p = join67(dir, e2.name);
|
|
56373
56534
|
if (e2.isDirectory()) {
|
|
56374
56535
|
await walkDir(p, root, out, toPosix);
|
|
56375
56536
|
} else if (e2.isFile()) {
|
|
@@ -56406,20 +56567,20 @@ var codexInstaller = {
|
|
|
56406
56567
|
globalRoot() {
|
|
56407
56568
|
const testHome = process.env.TAKUMI_TEST_HOME;
|
|
56408
56569
|
if (testHome && testHome.trim() !== "")
|
|
56409
|
-
return
|
|
56570
|
+
return join68(testHome, ".codex");
|
|
56410
56571
|
const codexHome = process.env.CODEX_HOME;
|
|
56411
56572
|
if (codexHome && codexHome.trim() !== "" && !codexHome.includes(".."))
|
|
56412
56573
|
return codexHome;
|
|
56413
56574
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
56414
56575
|
if (xdg && xdg.trim() !== "" && !xdg.includes(".."))
|
|
56415
|
-
return
|
|
56416
|
-
return
|
|
56576
|
+
return join68(xdg, "codex");
|
|
56577
|
+
return join68(homedir21(), ".codex");
|
|
56417
56578
|
},
|
|
56418
56579
|
isInstalledGlobally() {
|
|
56419
56580
|
const root = this.globalRoot();
|
|
56420
56581
|
if (!existsSync31(root))
|
|
56421
56582
|
return false;
|
|
56422
|
-
return findManifestPathSync(root) !== null || existsSync31(
|
|
56583
|
+
return findManifestPathSync(root) !== null || existsSync31(join68(root, "AGENTS.md")) || existsSync31(join68(root, "agents")) || existsSync31(join68(root, "config.toml")) || existsSync31(join68(root, "prompts"));
|
|
56423
56584
|
},
|
|
56424
56585
|
async detectGlobalSetup() {
|
|
56425
56586
|
const root = this.globalRoot();
|
|
@@ -56531,7 +56692,7 @@ var codexInstaller = {
|
|
|
56531
56692
|
error: errMsg
|
|
56532
56693
|
};
|
|
56533
56694
|
}
|
|
56534
|
-
const codexRoot = installGlobally ? this.globalRoot() :
|
|
56695
|
+
const codexRoot = installGlobally ? this.globalRoot() : join68(ctx.resolvedDir ?? process.cwd(), ".codex");
|
|
56535
56696
|
await writeCodexManifest(ctx, results, codexRoot, installGlobally);
|
|
56536
56697
|
return {
|
|
56537
56698
|
provider: "codex",
|
|
@@ -56610,33 +56771,33 @@ async function scanTakumiDirectory(directoryPath) {
|
|
|
56610
56771
|
}
|
|
56611
56772
|
const items = await import_fs_extra31.readdir(directoryPath);
|
|
56612
56773
|
if (items.includes("agents")) {
|
|
56613
|
-
const agentsPath =
|
|
56774
|
+
const agentsPath = join69(directoryPath, "agents");
|
|
56614
56775
|
const agentFiles = await import_fs_extra31.readdir(agentsPath);
|
|
56615
56776
|
counts.agents = agentFiles.filter((file) => file.endsWith(".md")).length;
|
|
56616
56777
|
}
|
|
56617
56778
|
if (items.includes("commands")) {
|
|
56618
|
-
const commandsPath =
|
|
56779
|
+
const commandsPath = join69(directoryPath, "commands");
|
|
56619
56780
|
const commandFiles = await import_fs_extra31.readdir(commandsPath);
|
|
56620
56781
|
counts.commands = commandFiles.filter((file) => file.endsWith(".md")).length;
|
|
56621
56782
|
}
|
|
56622
56783
|
if (items.includes("rules")) {
|
|
56623
|
-
const rulesPath =
|
|
56784
|
+
const rulesPath = join69(directoryPath, "rules");
|
|
56624
56785
|
const ruleFiles = await import_fs_extra31.readdir(rulesPath);
|
|
56625
56786
|
counts.rules = ruleFiles.filter((file) => file.endsWith(".md")).length;
|
|
56626
56787
|
} else if (items.includes("workflows")) {
|
|
56627
|
-
const workflowsPath =
|
|
56788
|
+
const workflowsPath = join69(directoryPath, "workflows");
|
|
56628
56789
|
const workflowFiles = await import_fs_extra31.readdir(workflowsPath);
|
|
56629
56790
|
counts.rules = workflowFiles.filter((file) => file.endsWith(".md")).length;
|
|
56630
56791
|
}
|
|
56631
56792
|
if (items.includes("skills")) {
|
|
56632
|
-
const skillsPath =
|
|
56793
|
+
const skillsPath = join69(directoryPath, "skills");
|
|
56633
56794
|
const skillItems = await import_fs_extra31.readdir(skillsPath);
|
|
56634
56795
|
let skillCount = 0;
|
|
56635
56796
|
for (const item of skillItems) {
|
|
56636
56797
|
if (SKIP_DIRS_CLAUDE_INTERNAL.includes(item)) {
|
|
56637
56798
|
continue;
|
|
56638
56799
|
}
|
|
56639
|
-
const itemPath =
|
|
56800
|
+
const itemPath = join69(skillsPath, item);
|
|
56640
56801
|
const stat8 = await import_fs_extra31.readdir(itemPath).catch(() => null);
|
|
56641
56802
|
if (stat8?.includes("SKILL.md")) {
|
|
56642
56803
|
skillCount++;
|
|
@@ -56949,7 +57110,7 @@ init_takumi_constants();
|
|
|
56949
57110
|
import { existsSync as existsSync32, realpathSync } from "node:fs";
|
|
56950
57111
|
import { chmod as chmod2, mkdir as mkdir17, readFile as readFile31, writeFile as writeFile22 } from "node:fs/promises";
|
|
56951
57112
|
import { platform as platform5 } from "node:os";
|
|
56952
|
-
import { join as
|
|
57113
|
+
import { join as join70 } from "node:path";
|
|
56953
57114
|
var CACHE_FILE = "install-info.json";
|
|
56954
57115
|
var CACHE_TTL = 30 * 24 * 60 * 60 * 1000;
|
|
56955
57116
|
function detectFromBinaryPath() {
|
|
@@ -57033,7 +57194,7 @@ function detectFromEnv() {
|
|
|
57033
57194
|
}
|
|
57034
57195
|
async function readCachedPm() {
|
|
57035
57196
|
try {
|
|
57036
|
-
const cacheFile =
|
|
57197
|
+
const cacheFile = join70(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
57037
57198
|
if (!existsSync32(cacheFile)) {
|
|
57038
57199
|
return null;
|
|
57039
57200
|
}
|
|
@@ -57064,7 +57225,7 @@ async function saveCachedPm(pm, getVersion) {
|
|
|
57064
57225
|
return;
|
|
57065
57226
|
try {
|
|
57066
57227
|
const configDir = PathResolver.getConfigDir(false);
|
|
57067
|
-
const cacheFile =
|
|
57228
|
+
const cacheFile = join70(configDir, CACHE_FILE);
|
|
57068
57229
|
if (!existsSync32(configDir)) {
|
|
57069
57230
|
await mkdir17(configDir, { recursive: true });
|
|
57070
57231
|
if (platform5() !== "win32") {
|
|
@@ -57127,7 +57288,7 @@ async function findOwningPm() {
|
|
|
57127
57288
|
async function clearCache() {
|
|
57128
57289
|
try {
|
|
57129
57290
|
const { unlink: unlink7 } = await import("node:fs/promises");
|
|
57130
|
-
const cacheFile =
|
|
57291
|
+
const cacheFile = join70(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
57131
57292
|
if (existsSync32(cacheFile)) {
|
|
57132
57293
|
await unlink7(cacheFile);
|
|
57133
57294
|
logger.debug("Package manager cache cleared");
|
|
@@ -57387,17 +57548,17 @@ async function checkCliVersion() {
|
|
|
57387
57548
|
}
|
|
57388
57549
|
// src/domains/health-checks/checkers/claude-md-checker.ts
|
|
57389
57550
|
import { existsSync as existsSync33, statSync as statSync3 } from "node:fs";
|
|
57390
|
-
import { join as
|
|
57551
|
+
import { join as join71 } from "node:path";
|
|
57391
57552
|
function checkClaudeMd(setup, projectDir) {
|
|
57392
57553
|
const results = [];
|
|
57393
57554
|
const claudeCodeInstaller2 = getInstaller("claude-code");
|
|
57394
57555
|
if (claudeCodeInstaller2?.isInstalledGlobally()) {
|
|
57395
57556
|
const claudeGlobal = setup.globals.find((g2) => g2.provider === "claude-code") ?? setup.globals[0];
|
|
57396
57557
|
const globalPath = claudeGlobal?.path ?? claudeCodeInstaller2.globalRoot();
|
|
57397
|
-
const globalClaudeMd =
|
|
57558
|
+
const globalClaudeMd = join71(globalPath, "CLAUDE.md");
|
|
57398
57559
|
results.push(checkClaudeMdFile(globalClaudeMd, "Global CLAUDE.md", "sk-global-claude-md"));
|
|
57399
57560
|
}
|
|
57400
|
-
const projectClaudeMd =
|
|
57561
|
+
const projectClaudeMd = join71(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
57401
57562
|
results.push(checkClaudeMdFile(projectClaudeMd, "Project CLAUDE.md", "sk-project-claude-md"));
|
|
57402
57563
|
return results;
|
|
57403
57564
|
}
|
|
@@ -57455,10 +57616,10 @@ function checkClaudeMdFile(path7, name, id) {
|
|
|
57455
57616
|
}
|
|
57456
57617
|
}
|
|
57457
57618
|
// src/domains/health-checks/checkers/active-plan-checker.ts
|
|
57458
|
-
import { existsSync as existsSync34, readFileSync as
|
|
57459
|
-
import { join as
|
|
57619
|
+
import { existsSync as existsSync34, readFileSync as readFileSync9 } from "node:fs";
|
|
57620
|
+
import { join as join72 } from "node:path";
|
|
57460
57621
|
function checkActivePlan(projectDir) {
|
|
57461
|
-
const activePlanPath =
|
|
57622
|
+
const activePlanPath = join72(projectDir, ".claude", "active-plan");
|
|
57462
57623
|
if (!existsSync34(activePlanPath)) {
|
|
57463
57624
|
return {
|
|
57464
57625
|
id: "sk-active-plan",
|
|
@@ -57471,8 +57632,8 @@ function checkActivePlan(projectDir) {
|
|
|
57471
57632
|
};
|
|
57472
57633
|
}
|
|
57473
57634
|
try {
|
|
57474
|
-
const targetPath =
|
|
57475
|
-
const fullPath =
|
|
57635
|
+
const targetPath = readFileSync9(activePlanPath, "utf-8").trim();
|
|
57636
|
+
const fullPath = join72(projectDir, targetPath);
|
|
57476
57637
|
if (!existsSync34(fullPath)) {
|
|
57477
57638
|
return {
|
|
57478
57639
|
id: "sk-active-plan",
|
|
@@ -57536,7 +57697,7 @@ function checkComponentCounts(setup) {
|
|
|
57536
57697
|
}
|
|
57537
57698
|
// src/domains/health-checks/checkers/permissions-checker.ts
|
|
57538
57699
|
import { constants, access, unlink as unlink7, writeFile as writeFile23 } from "node:fs/promises";
|
|
57539
|
-
import { join as
|
|
57700
|
+
import { join as join73 } from "node:path";
|
|
57540
57701
|
init_logger();
|
|
57541
57702
|
|
|
57542
57703
|
// src/domains/health-checks/checkers/shared.ts
|
|
@@ -57611,7 +57772,7 @@ async function checkGlobalDirWritable(provider) {
|
|
|
57611
57772
|
}
|
|
57612
57773
|
const timestamp = Date.now();
|
|
57613
57774
|
const random = Math.random().toString(36).substring(2);
|
|
57614
|
-
const testFile =
|
|
57775
|
+
const testFile = join73(globalDir, `.sk-write-test-${timestamp}-${random}`);
|
|
57615
57776
|
try {
|
|
57616
57777
|
await writeFile23(testFile, "test", { encoding: "utf-8", flag: "wx" });
|
|
57617
57778
|
} catch (_error) {
|
|
@@ -57646,7 +57807,7 @@ async function checkGlobalDirWritable(provider) {
|
|
|
57646
57807
|
// src/domains/health-checks/checkers/hooks-checker.ts
|
|
57647
57808
|
import { existsSync as existsSync35 } from "node:fs";
|
|
57648
57809
|
import { readdir as readdir23 } from "node:fs/promises";
|
|
57649
|
-
import { join as
|
|
57810
|
+
import { join as join74 } from "node:path";
|
|
57650
57811
|
|
|
57651
57812
|
// src/domains/health-checks/utils/path-normalizer.ts
|
|
57652
57813
|
import { normalize as normalize5 } from "node:path";
|
|
@@ -57658,8 +57819,8 @@ function normalizePath(filePath) {
|
|
|
57658
57819
|
|
|
57659
57820
|
// src/domains/health-checks/checkers/hooks-checker.ts
|
|
57660
57821
|
async function checkHooksExist(projectDir) {
|
|
57661
|
-
const globalHooksDir =
|
|
57662
|
-
const projectHooksDir =
|
|
57822
|
+
const globalHooksDir = join74(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
|
|
57823
|
+
const projectHooksDir = join74(getLocalClaudeDir(projectDir), "hooks");
|
|
57663
57824
|
const globalExists = existsSync35(globalHooksDir);
|
|
57664
57825
|
const projectExists = existsSync35(projectHooksDir);
|
|
57665
57826
|
let hookCount = 0;
|
|
@@ -57668,7 +57829,7 @@ async function checkHooksExist(projectDir) {
|
|
|
57668
57829
|
const files = await readdir23(globalHooksDir, { withFileTypes: false });
|
|
57669
57830
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
|
|
57670
57831
|
hooks.forEach((hook) => {
|
|
57671
|
-
const fullPath =
|
|
57832
|
+
const fullPath = join74(globalHooksDir, hook);
|
|
57672
57833
|
checkedFiles.add(normalizePath(fullPath));
|
|
57673
57834
|
});
|
|
57674
57835
|
}
|
|
@@ -57678,7 +57839,7 @@ async function checkHooksExist(projectDir) {
|
|
|
57678
57839
|
const files = await readdir23(projectHooksDir, { withFileTypes: false });
|
|
57679
57840
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
|
|
57680
57841
|
hooks.forEach((hook) => {
|
|
57681
|
-
const fullPath =
|
|
57842
|
+
const fullPath = join74(projectHooksDir, hook);
|
|
57682
57843
|
checkedFiles.add(normalizePath(fullPath));
|
|
57683
57844
|
});
|
|
57684
57845
|
}
|
|
@@ -57708,11 +57869,11 @@ async function checkHooksExist(projectDir) {
|
|
|
57708
57869
|
// src/domains/health-checks/checkers/settings-checker.ts
|
|
57709
57870
|
import { existsSync as existsSync36 } from "node:fs";
|
|
57710
57871
|
import { readFile as readFile32 } from "node:fs/promises";
|
|
57711
|
-
import { join as
|
|
57872
|
+
import { join as join75 } from "node:path";
|
|
57712
57873
|
init_logger();
|
|
57713
57874
|
async function checkSettingsValid(projectDir) {
|
|
57714
|
-
const globalSettings =
|
|
57715
|
-
const projectSettings =
|
|
57875
|
+
const globalSettings = join75(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
|
|
57876
|
+
const projectSettings = join75(getLocalClaudeDir(projectDir), "settings.json");
|
|
57716
57877
|
const settingsPath = existsSync36(globalSettings) ? globalSettings : existsSync36(projectSettings) ? projectSettings : null;
|
|
57717
57878
|
if (!settingsPath) {
|
|
57718
57879
|
return {
|
|
@@ -57783,11 +57944,11 @@ async function checkSettingsValid(projectDir) {
|
|
|
57783
57944
|
import { existsSync as existsSync37 } from "node:fs";
|
|
57784
57945
|
import { readFile as readFile33 } from "node:fs/promises";
|
|
57785
57946
|
import { homedir as homedir22 } from "node:os";
|
|
57786
|
-
import { dirname as dirname19, join as
|
|
57947
|
+
import { dirname as dirname19, join as join76, normalize as normalize6, resolve as resolve16 } from "node:path";
|
|
57787
57948
|
init_logger();
|
|
57788
57949
|
async function checkPathRefsValid(projectDir) {
|
|
57789
|
-
const globalClaudeMd =
|
|
57790
|
-
const projectClaudeMd =
|
|
57950
|
+
const globalClaudeMd = join76(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
|
|
57951
|
+
const projectClaudeMd = join76(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
57791
57952
|
const claudeMdPath = existsSync37(globalClaudeMd) ? globalClaudeMd : existsSync37(projectClaudeMd) ? projectClaudeMd : null;
|
|
57792
57953
|
if (!claudeMdPath) {
|
|
57793
57954
|
return {
|
|
@@ -57831,7 +57992,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
57831
57992
|
} else if (/^[A-Za-z]:/.test(ref)) {
|
|
57832
57993
|
refPath = normalize6(ref);
|
|
57833
57994
|
} else {
|
|
57834
|
-
refPath =
|
|
57995
|
+
refPath = resolve16(baseDir, ref);
|
|
57835
57996
|
}
|
|
57836
57997
|
const normalizedPath = normalize6(refPath);
|
|
57837
57998
|
const isWithinHome = normalizedPath.startsWith(home6);
|
|
@@ -57882,7 +58043,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
57882
58043
|
// src/domains/health-checks/checkers/config-completeness-checker.ts
|
|
57883
58044
|
import { existsSync as existsSync38 } from "node:fs";
|
|
57884
58045
|
import { readdir as readdir24 } from "node:fs/promises";
|
|
57885
|
-
import { join as
|
|
58046
|
+
import { join as join77 } from "node:path";
|
|
57886
58047
|
async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
57887
58048
|
if (setup.globals.some((g2) => g2.path === setup.project.path)) {
|
|
57888
58049
|
return {
|
|
@@ -57899,12 +58060,12 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
|
57899
58060
|
const requiredDirs = ["agents", "commands", "skills"];
|
|
57900
58061
|
const missingDirs = [];
|
|
57901
58062
|
for (const dir of requiredDirs) {
|
|
57902
|
-
const dirPath =
|
|
58063
|
+
const dirPath = join77(projectClaudeDir, dir);
|
|
57903
58064
|
if (!existsSync38(dirPath)) {
|
|
57904
58065
|
missingDirs.push(dir);
|
|
57905
58066
|
}
|
|
57906
58067
|
}
|
|
57907
|
-
const hasRulesOrWorkflows = existsSync38(
|
|
58068
|
+
const hasRulesOrWorkflows = existsSync38(join77(projectClaudeDir, "rules")) || existsSync38(join77(projectClaudeDir, "workflows"));
|
|
57908
58069
|
if (!hasRulesOrWorkflows) {
|
|
57909
58070
|
missingDirs.push("rules");
|
|
57910
58071
|
}
|
|
@@ -58341,7 +58502,7 @@ import { platform as platform7 } from "node:os";
|
|
|
58341
58502
|
// src/domains/health-checks/platform/environment-checker.ts
|
|
58342
58503
|
import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile35, unlink as unlink9, writeFile as writeFile25 } from "node:fs/promises";
|
|
58343
58504
|
import { arch as arch2, homedir as homedir23, platform as platform6 } from "node:os";
|
|
58344
|
-
import { join as
|
|
58505
|
+
import { join as join80, normalize as normalize7 } from "node:path";
|
|
58345
58506
|
init_environment();
|
|
58346
58507
|
function shouldSkipExpensiveOperations4() {
|
|
58347
58508
|
return shouldSkipExpensiveOperations();
|
|
@@ -58435,7 +58596,7 @@ async function checkGlobalDirAccess(provider) {
|
|
|
58435
58596
|
autoFixable: false
|
|
58436
58597
|
};
|
|
58437
58598
|
}
|
|
58438
|
-
const testFile =
|
|
58599
|
+
const testFile = join80(globalDir, ".sk-doctor-access-test");
|
|
58439
58600
|
try {
|
|
58440
58601
|
await mkdir19(globalDir, { recursive: true });
|
|
58441
58602
|
await writeFile25(testFile, "test", "utf-8");
|
|
@@ -58512,7 +58673,7 @@ async function checkWSLBoundary() {
|
|
|
58512
58673
|
|
|
58513
58674
|
// src/domains/health-checks/platform/windows-checker.ts
|
|
58514
58675
|
import { mkdir as mkdir20, symlink as symlink2, unlink as unlink10, writeFile as writeFile26 } from "node:fs/promises";
|
|
58515
|
-
import { join as
|
|
58676
|
+
import { join as join81 } from "node:path";
|
|
58516
58677
|
async function checkLongPathSupport() {
|
|
58517
58678
|
if (shouldSkipExpensiveOperations4()) {
|
|
58518
58679
|
return {
|
|
@@ -58564,8 +58725,8 @@ async function checkSymlinkSupport() {
|
|
|
58564
58725
|
};
|
|
58565
58726
|
}
|
|
58566
58727
|
const testDir = getInstaller("claude-code")?.globalRoot() ?? "";
|
|
58567
|
-
const target =
|
|
58568
|
-
const link =
|
|
58728
|
+
const target = join81(testDir, ".sk-symlink-test-target");
|
|
58729
|
+
const link = join81(testDir, ".sk-symlink-test-link");
|
|
58569
58730
|
try {
|
|
58570
58731
|
await mkdir20(testDir, { recursive: true });
|
|
58571
58732
|
await writeFile26(target, "test", "utf-8");
|
|
@@ -58859,9 +59020,9 @@ class AutoHealer {
|
|
|
58859
59020
|
}
|
|
58860
59021
|
// src/domains/health-checks/report-generator.ts
|
|
58861
59022
|
import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
|
|
58862
|
-
import { readFileSync as
|
|
59023
|
+
import { readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
58863
59024
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
58864
|
-
import { dirname as dirname20, join as
|
|
59025
|
+
import { dirname as dirname20, join as join82 } from "node:path";
|
|
58865
59026
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
58866
59027
|
init_environment();
|
|
58867
59028
|
init_logger();
|
|
@@ -58869,8 +59030,8 @@ init_dist2();
|
|
|
58869
59030
|
function getCliVersion3() {
|
|
58870
59031
|
try {
|
|
58871
59032
|
const __dirname3 = dirname20(fileURLToPath2(import.meta.url));
|
|
58872
|
-
const pkgPath =
|
|
58873
|
-
const pkg = JSON.parse(
|
|
59033
|
+
const pkgPath = join82(__dirname3, "../../../package.json");
|
|
59034
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
58874
59035
|
return pkg.version || "unknown";
|
|
58875
59036
|
} catch (err) {
|
|
58876
59037
|
logger.debug(`Failed to read CLI version: ${err}`);
|
|
@@ -59008,8 +59169,8 @@ class ReportGenerator {
|
|
|
59008
59169
|
return null;
|
|
59009
59170
|
}
|
|
59010
59171
|
}
|
|
59011
|
-
const tmpFile =
|
|
59012
|
-
|
|
59172
|
+
const tmpFile = join82(tmpdir2(), `sk-report-${Date.now()}.txt`);
|
|
59173
|
+
writeFileSync6(tmpFile, report);
|
|
59013
59174
|
try {
|
|
59014
59175
|
const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "Takumi Diagnostic Report"], {
|
|
59015
59176
|
encoding: "utf-8"
|
|
@@ -59025,7 +59186,7 @@ class ReportGenerator {
|
|
|
59025
59186
|
return null;
|
|
59026
59187
|
} finally {
|
|
59027
59188
|
try {
|
|
59028
|
-
|
|
59189
|
+
unlinkSync4(tmpFile);
|
|
59029
59190
|
} catch {}
|
|
59030
59191
|
}
|
|
59031
59192
|
}
|
|
@@ -60497,7 +60658,7 @@ init_environment();
|
|
|
60497
60658
|
init_logger();
|
|
60498
60659
|
import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
|
|
60499
60660
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
60500
|
-
import { join as
|
|
60661
|
+
import { join as join88 } from "node:path";
|
|
60501
60662
|
|
|
60502
60663
|
// src/shared/temp-cleanup.ts
|
|
60503
60664
|
init_logger();
|
|
@@ -60516,7 +60677,7 @@ init_logger();
|
|
|
60516
60677
|
init_output_manager();
|
|
60517
60678
|
import { createWriteStream as createWriteStream2, rmSync as rmSync3 } from "node:fs";
|
|
60518
60679
|
import { mkdir as mkdir21 } from "node:fs/promises";
|
|
60519
|
-
import { join as
|
|
60680
|
+
import { join as join83 } from "node:path";
|
|
60520
60681
|
|
|
60521
60682
|
// src/shared/progress-bar.ts
|
|
60522
60683
|
init_output_manager();
|
|
@@ -60681,10 +60842,10 @@ init_types2();
|
|
|
60681
60842
|
// src/domains/installation/utils/path-security.ts
|
|
60682
60843
|
init_types2();
|
|
60683
60844
|
import { lstatSync as lstatSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
60684
|
-
import { relative as relative14, resolve as
|
|
60845
|
+
import { relative as relative14, resolve as resolve17 } from "node:path";
|
|
60685
60846
|
var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
|
|
60686
60847
|
function isPathSafe(basePath, targetPath) {
|
|
60687
|
-
const resolvedBase =
|
|
60848
|
+
const resolvedBase = resolve17(basePath);
|
|
60688
60849
|
try {
|
|
60689
60850
|
const stat8 = lstatSync3(targetPath);
|
|
60690
60851
|
if (stat8.isSymbolicLink()) {
|
|
@@ -60694,7 +60855,7 @@ function isPathSafe(basePath, targetPath) {
|
|
|
60694
60855
|
}
|
|
60695
60856
|
}
|
|
60696
60857
|
} catch {}
|
|
60697
|
-
const resolvedTarget =
|
|
60858
|
+
const resolvedTarget = resolve17(targetPath);
|
|
60698
60859
|
const relativePath = relative14(resolvedBase, resolvedTarget);
|
|
60699
60860
|
return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
|
|
60700
60861
|
}
|
|
@@ -60726,7 +60887,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
|
|
|
60726
60887
|
class FileDownloader {
|
|
60727
60888
|
async downloadAsset(asset, destDir) {
|
|
60728
60889
|
try {
|
|
60729
|
-
const destPath =
|
|
60890
|
+
const destPath = join83(destDir, asset.name);
|
|
60730
60891
|
await mkdir21(destDir, { recursive: true });
|
|
60731
60892
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
60732
60893
|
logger.verbose("Download details", {
|
|
@@ -60782,7 +60943,7 @@ class FileDownloader {
|
|
|
60782
60943
|
}
|
|
60783
60944
|
if (downloadedSize !== totalSize) {
|
|
60784
60945
|
fileStream.end();
|
|
60785
|
-
await new Promise((
|
|
60946
|
+
await new Promise((resolve18) => fileStream.once("close", resolve18));
|
|
60786
60947
|
try {
|
|
60787
60948
|
rmSync3(destPath, { force: true });
|
|
60788
60949
|
} catch (cleanupError) {
|
|
@@ -60796,7 +60957,7 @@ class FileDownloader {
|
|
|
60796
60957
|
return destPath;
|
|
60797
60958
|
} catch (error) {
|
|
60798
60959
|
fileStream.end();
|
|
60799
|
-
await new Promise((
|
|
60960
|
+
await new Promise((resolve18) => fileStream.once("close", resolve18));
|
|
60800
60961
|
try {
|
|
60801
60962
|
rmSync3(destPath, { force: true });
|
|
60802
60963
|
} catch (cleanupError) {
|
|
@@ -60811,7 +60972,7 @@ class FileDownloader {
|
|
|
60811
60972
|
}
|
|
60812
60973
|
async downloadFile(params) {
|
|
60813
60974
|
const { url, name, size, destDir, token } = params;
|
|
60814
|
-
const destPath =
|
|
60975
|
+
const destPath = join83(destDir, name);
|
|
60815
60976
|
await mkdir21(destDir, { recursive: true });
|
|
60816
60977
|
output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
60817
60978
|
const headers = {};
|
|
@@ -60879,7 +61040,7 @@ class FileDownloader {
|
|
|
60879
61040
|
const expectedSize = Number(response.headers.get("content-length"));
|
|
60880
61041
|
if (expectedSize > 0 && downloadedSize !== expectedSize) {
|
|
60881
61042
|
fileStream.end();
|
|
60882
|
-
await new Promise((
|
|
61043
|
+
await new Promise((resolve18) => fileStream.once("close", resolve18));
|
|
60883
61044
|
try {
|
|
60884
61045
|
rmSync3(destPath, { force: true });
|
|
60885
61046
|
} catch (cleanupError) {
|
|
@@ -60897,7 +61058,7 @@ class FileDownloader {
|
|
|
60897
61058
|
return destPath;
|
|
60898
61059
|
} catch (error) {
|
|
60899
61060
|
fileStream.end();
|
|
60900
|
-
await new Promise((
|
|
61061
|
+
await new Promise((resolve18) => fileStream.once("close", resolve18));
|
|
60901
61062
|
try {
|
|
60902
61063
|
rmSync3(destPath, { force: true });
|
|
60903
61064
|
} catch (cleanupError) {
|
|
@@ -60914,7 +61075,7 @@ init_logger();
|
|
|
60914
61075
|
init_types2();
|
|
60915
61076
|
import { constants as constants3 } from "node:fs";
|
|
60916
61077
|
import { access as access3, readdir as readdir25 } from "node:fs/promises";
|
|
60917
|
-
import { join as
|
|
61078
|
+
import { join as join84 } from "node:path";
|
|
60918
61079
|
async function validateExtraction(extractDir) {
|
|
60919
61080
|
try {
|
|
60920
61081
|
const entries = await readdir25(extractDir, { encoding: "utf8" });
|
|
@@ -60926,7 +61087,7 @@ async function validateExtraction(extractDir) {
|
|
|
60926
61087
|
const missingPaths = [];
|
|
60927
61088
|
for (const path8 of criticalPaths) {
|
|
60928
61089
|
try {
|
|
60929
|
-
await access3(
|
|
61090
|
+
await access3(join84(extractDir, path8), constants3.F_OK);
|
|
60930
61091
|
logger.debug(`Found: ${path8}`);
|
|
60931
61092
|
} catch {
|
|
60932
61093
|
logger.warning(`Expected path not found: ${path8}`);
|
|
@@ -60948,7 +61109,7 @@ async function validateExtraction(extractDir) {
|
|
|
60948
61109
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
60949
61110
|
init_logger();
|
|
60950
61111
|
import { copyFile as copyFile6, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat8 } from "node:fs/promises";
|
|
60951
|
-
import { join as
|
|
61112
|
+
import { join as join86 } from "node:path";
|
|
60952
61113
|
|
|
60953
61114
|
// node_modules/tar/dist/esm/index.min.js
|
|
60954
61115
|
import Kr from "events";
|
|
@@ -64161,7 +64322,7 @@ function decodeFilePath(path8) {
|
|
|
64161
64322
|
init_logger();
|
|
64162
64323
|
init_types2();
|
|
64163
64324
|
import { copyFile as copyFile5, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
|
|
64164
|
-
import { join as
|
|
64325
|
+
import { join as join85, relative as relative15 } from "node:path";
|
|
64165
64326
|
async function withRetry2(fn2, retries = 3) {
|
|
64166
64327
|
for (let i = 0;i < retries; i++) {
|
|
64167
64328
|
try {
|
|
@@ -64183,8 +64344,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
64183
64344
|
await mkdir22(destDir, { recursive: true });
|
|
64184
64345
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
64185
64346
|
for (const entry of entries) {
|
|
64186
|
-
const sourcePath =
|
|
64187
|
-
const destPath =
|
|
64347
|
+
const sourcePath = join85(sourceDir, entry);
|
|
64348
|
+
const destPath = join85(destDir, entry);
|
|
64188
64349
|
const relativePath = relative15(sourceDir, sourcePath);
|
|
64189
64350
|
if (!isPathSafe(destDir, destPath)) {
|
|
64190
64351
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -64211,8 +64372,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
|
64211
64372
|
await mkdir22(destDir, { recursive: true });
|
|
64212
64373
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
64213
64374
|
for (const entry of entries) {
|
|
64214
|
-
const sourcePath =
|
|
64215
|
-
const destPath =
|
|
64375
|
+
const sourcePath = join85(sourceDir, entry);
|
|
64376
|
+
const destPath = join85(destDir, entry);
|
|
64216
64377
|
const relativePath = relative15(sourceDir, sourcePath);
|
|
64217
64378
|
if (!isPathSafe(destDir, destPath)) {
|
|
64218
64379
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -64267,7 +64428,7 @@ class TarExtractor {
|
|
|
64267
64428
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
64268
64429
|
if (entries.length === 1) {
|
|
64269
64430
|
const rootEntry = entries[0];
|
|
64270
|
-
const rootPath =
|
|
64431
|
+
const rootPath = join86(tempExtractDir, rootEntry);
|
|
64271
64432
|
const rootStat = await stat8(rootPath);
|
|
64272
64433
|
if (rootStat.isDirectory()) {
|
|
64273
64434
|
const rootContents = await readdir27(rootPath, { encoding: "utf8" });
|
|
@@ -64283,7 +64444,7 @@ class TarExtractor {
|
|
|
64283
64444
|
}
|
|
64284
64445
|
} else {
|
|
64285
64446
|
await mkdir23(destDir, { recursive: true });
|
|
64286
|
-
await copyFile6(rootPath,
|
|
64447
|
+
await copyFile6(rootPath, join86(destDir, rootEntry));
|
|
64287
64448
|
}
|
|
64288
64449
|
} else {
|
|
64289
64450
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -64304,7 +64465,7 @@ class TarExtractor {
|
|
|
64304
64465
|
init_logger();
|
|
64305
64466
|
import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
64306
64467
|
import { chmod as chmod3, copyFile as copyFile7, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as stat9 } from "node:fs/promises";
|
|
64307
|
-
import { dirname as dirname21, join as
|
|
64468
|
+
import { dirname as dirname21, join as join87, resolve as resolve18 } from "node:path";
|
|
64308
64469
|
import { pipeline } from "node:stream/promises";
|
|
64309
64470
|
import yauzl from "yauzl-promise";
|
|
64310
64471
|
class ZipExtractor {
|
|
@@ -64318,7 +64479,7 @@ class ZipExtractor {
|
|
|
64318
64479
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
64319
64480
|
if (entries.length === 1) {
|
|
64320
64481
|
const rootEntry = entries[0];
|
|
64321
|
-
const rootPath =
|
|
64482
|
+
const rootPath = join87(tempExtractDir, rootEntry);
|
|
64322
64483
|
const rootStat = await stat9(rootPath);
|
|
64323
64484
|
if (rootStat.isDirectory()) {
|
|
64324
64485
|
const rootContents = await readdir28(rootPath, { encoding: "utf8" });
|
|
@@ -64334,7 +64495,7 @@ class ZipExtractor {
|
|
|
64334
64495
|
}
|
|
64335
64496
|
} else {
|
|
64336
64497
|
await mkdir24(destDir, { recursive: true });
|
|
64337
|
-
await copyFile7(rootPath,
|
|
64498
|
+
await copyFile7(rootPath, join87(destDir, rootEntry));
|
|
64338
64499
|
}
|
|
64339
64500
|
} else {
|
|
64340
64501
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -64351,13 +64512,13 @@ class ZipExtractor {
|
|
|
64351
64512
|
}
|
|
64352
64513
|
async extractToDir(archivePath, destDir) {
|
|
64353
64514
|
const zip = await yauzl.open(archivePath, { decodeStrings: false });
|
|
64354
|
-
const destRoot =
|
|
64515
|
+
const destRoot = resolve18(destDir);
|
|
64355
64516
|
let count = 0;
|
|
64356
64517
|
try {
|
|
64357
64518
|
for await (const entry of zip) {
|
|
64358
64519
|
const rawName = entry.filename;
|
|
64359
64520
|
const name = normalizeZipEntryName(rawName);
|
|
64360
|
-
const outPath =
|
|
64521
|
+
const outPath = resolve18(destRoot, name);
|
|
64361
64522
|
if (!isPathSafe(destRoot, outPath)) {
|
|
64362
64523
|
throw new Error(`Unsafe zip entry path (zip-slip): ${name}`);
|
|
64363
64524
|
}
|
|
@@ -64463,7 +64624,7 @@ class DownloadManager {
|
|
|
64463
64624
|
async createTempDir() {
|
|
64464
64625
|
const timestamp = Date.now();
|
|
64465
64626
|
const counter = DownloadManager.tempDirCounter++;
|
|
64466
|
-
const primaryTempDir =
|
|
64627
|
+
const primaryTempDir = join88(tmpdir3(), `takumi-${timestamp}-${counter}`);
|
|
64467
64628
|
try {
|
|
64468
64629
|
await mkdir25(primaryTempDir, { recursive: true });
|
|
64469
64630
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -64480,7 +64641,7 @@ Solutions:
|
|
|
64480
64641
|
2. Set HOME environment variable
|
|
64481
64642
|
3. Try running from a different directory`);
|
|
64482
64643
|
}
|
|
64483
|
-
const fallbackTempDir =
|
|
64644
|
+
const fallbackTempDir = join88(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
|
|
64484
64645
|
try {
|
|
64485
64646
|
await mkdir25(fallbackTempDir, { recursive: true });
|
|
64486
64647
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -65177,7 +65338,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
|
|
|
65177
65338
|
}
|
|
65178
65339
|
// src/commands/init/phases/selection-handler.ts
|
|
65179
65340
|
import { mkdir as mkdir26 } from "node:fs/promises";
|
|
65180
|
-
import { join as
|
|
65341
|
+
import { join as join92, resolve as resolve22 } from "node:path";
|
|
65181
65342
|
|
|
65182
65343
|
// src/commands/shared/agent-selector.ts
|
|
65183
65344
|
function selectAgents(opts = {}) {
|
|
@@ -65321,8 +65482,8 @@ async function runPreflightChecks() {
|
|
|
65321
65482
|
}
|
|
65322
65483
|
|
|
65323
65484
|
// src/domains/installation/fresh-installer.ts
|
|
65324
|
-
import { existsSync as existsSync43, readdirSync as readdirSync4, rmSync as rmSync4, rmdirSync as rmdirSync2, unlinkSync as
|
|
65325
|
-
import { dirname as dirname24, join as
|
|
65485
|
+
import { existsSync as existsSync43, readdirSync as readdirSync4, rmSync as rmSync4, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
|
|
65486
|
+
import { dirname as dirname24, join as join91, resolve as resolve21 } from "node:path";
|
|
65326
65487
|
init_logger();
|
|
65327
65488
|
init_takumi_constants();
|
|
65328
65489
|
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
@@ -65370,15 +65531,15 @@ async function analyzeFreshInstallation(claudeDir) {
|
|
|
65370
65531
|
};
|
|
65371
65532
|
}
|
|
65372
65533
|
function cleanupEmptyDirectories2(filePath, claudeDir) {
|
|
65373
|
-
const normalizedClaudeDir =
|
|
65374
|
-
let currentDir =
|
|
65534
|
+
const normalizedClaudeDir = resolve21(claudeDir);
|
|
65535
|
+
let currentDir = resolve21(dirname24(filePath));
|
|
65375
65536
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
65376
65537
|
try {
|
|
65377
65538
|
const entries = readdirSync4(currentDir);
|
|
65378
65539
|
if (entries.length === 0) {
|
|
65379
65540
|
rmdirSync2(currentDir);
|
|
65380
65541
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
65381
|
-
currentDir =
|
|
65542
|
+
currentDir = resolve21(dirname24(currentDir));
|
|
65382
65543
|
} else {
|
|
65383
65544
|
break;
|
|
65384
65545
|
}
|
|
@@ -65395,10 +65556,10 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
65395
65556
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
65396
65557
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
65397
65558
|
for (const file of filesToRemove) {
|
|
65398
|
-
const fullPath =
|
|
65559
|
+
const fullPath = join91(claudeDir, file.path);
|
|
65399
65560
|
try {
|
|
65400
65561
|
if (existsSync43(fullPath)) {
|
|
65401
|
-
|
|
65562
|
+
unlinkSync5(fullPath);
|
|
65402
65563
|
removedFiles.push(file.path);
|
|
65403
65564
|
logger.debug(`Removed: ${file.path}`);
|
|
65404
65565
|
cleanupEmptyDirectories2(fullPath, claudeDir);
|
|
@@ -65456,7 +65617,7 @@ async function updateMetadataAfterFresh(claudeDir, removedFiles) {
|
|
|
65456
65617
|
await import_fs_extra32.writeFile(canonicalPath, JSON.stringify(metadata, null, 2));
|
|
65457
65618
|
if (resolved.isLegacy && canonicalPath !== resolved.path) {
|
|
65458
65619
|
try {
|
|
65459
|
-
|
|
65620
|
+
unlinkSync5(resolved.path);
|
|
65460
65621
|
} catch {}
|
|
65461
65622
|
}
|
|
65462
65623
|
logger.debug(`Updated manifest, removed ${removedFiles.length} file entries`);
|
|
@@ -65469,7 +65630,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
65469
65630
|
const removedFiles = [];
|
|
65470
65631
|
let removedDirCount = 0;
|
|
65471
65632
|
for (const subdir of TAKUMI_SUBDIRECTORIES) {
|
|
65472
|
-
const subdirPath =
|
|
65633
|
+
const subdirPath = join91(claudeDir, subdir);
|
|
65473
65634
|
if (await import_fs_extra32.pathExists(subdirPath)) {
|
|
65474
65635
|
rmSync4(subdirPath, { recursive: true, force: true });
|
|
65475
65636
|
removedDirCount++;
|
|
@@ -65479,12 +65640,12 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
65479
65640
|
}
|
|
65480
65641
|
const canonicalPath = getManifestPath(claudeDir);
|
|
65481
65642
|
if (await import_fs_extra32.pathExists(canonicalPath)) {
|
|
65482
|
-
|
|
65643
|
+
unlinkSync5(canonicalPath);
|
|
65483
65644
|
removedFiles.push(MANIFEST_FILENAME);
|
|
65484
65645
|
}
|
|
65485
65646
|
const legacyPath = getLegacyManifestPath(claudeDir);
|
|
65486
65647
|
if (await import_fs_extra32.pathExists(legacyPath)) {
|
|
65487
|
-
|
|
65648
|
+
unlinkSync5(legacyPath);
|
|
65488
65649
|
removedFiles.push(LEGACY_MANIFEST_FILENAME);
|
|
65489
65650
|
}
|
|
65490
65651
|
return {
|
|
@@ -65708,7 +65869,7 @@ async function handleSelection(ctx) {
|
|
|
65708
65869
|
}
|
|
65709
65870
|
}
|
|
65710
65871
|
}
|
|
65711
|
-
const resolvedDir =
|
|
65872
|
+
const resolvedDir = resolve22(targetDir);
|
|
65712
65873
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
65713
65874
|
if (!ctx.options.global && isLocalSameAsGlobal(resolvedDir)) {
|
|
65714
65875
|
logger.warning("You're at HOME directory. Installing here modifies your GLOBAL Takumi.");
|
|
@@ -65742,7 +65903,7 @@ async function handleSelection(ctx) {
|
|
|
65742
65903
|
}
|
|
65743
65904
|
if (!ctx.options.fresh) {
|
|
65744
65905
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65745
|
-
const claudeDir = prefix ?
|
|
65906
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65746
65907
|
try {
|
|
65747
65908
|
const existingMetadata = await readManifest(claudeDir);
|
|
65748
65909
|
if (existingMetadata?.kits) {
|
|
@@ -65775,7 +65936,7 @@ async function handleSelection(ctx) {
|
|
|
65775
65936
|
}
|
|
65776
65937
|
if (ctx.options.fresh) {
|
|
65777
65938
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65778
|
-
const claudeDir = prefix ?
|
|
65939
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65779
65940
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
65780
65941
|
if (!canProceed) {
|
|
65781
65942
|
return { ...ctx, cancelled: true };
|
|
@@ -65795,7 +65956,7 @@ async function handleSelection(ctx) {
|
|
|
65795
65956
|
let currentVersion = null;
|
|
65796
65957
|
try {
|
|
65797
65958
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65798
|
-
const claudeDir = prefix ?
|
|
65959
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65799
65960
|
const existingMetadata = await readManifest(claudeDir);
|
|
65800
65961
|
currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
|
|
65801
65962
|
if (currentVersion) {
|
|
@@ -65883,7 +66044,7 @@ async function handleSelection(ctx) {
|
|
|
65883
66044
|
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
|
|
65884
66045
|
try {
|
|
65885
66046
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65886
|
-
const claudeDir = prefix ?
|
|
66047
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65887
66048
|
const existingMetadata = await readManifest(claudeDir);
|
|
65888
66049
|
const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
|
|
65889
66050
|
if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
|
|
@@ -65906,7 +66067,7 @@ async function handleSelection(ctx) {
|
|
|
65906
66067
|
let currentSecondaryVersion = null;
|
|
65907
66068
|
try {
|
|
65908
66069
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65909
|
-
const claudeDir = prefix ?
|
|
66070
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65910
66071
|
const existingMetadata = await readManifest(claudeDir);
|
|
65911
66072
|
currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
|
|
65912
66073
|
} catch {}
|
|
@@ -65989,12 +66150,12 @@ function resolveGlobalTargetDir(targetAgents) {
|
|
|
65989
66150
|
}
|
|
65990
66151
|
// src/commands/init/phases/sync-handler.ts
|
|
65991
66152
|
import { copyFile as copyFile8, mkdir as mkdir28, open as open3, readFile as readFile39, rename as rename7, stat as stat12, unlink as unlink12, writeFile as writeFile29 } from "node:fs/promises";
|
|
65992
|
-
import { dirname as dirname25, join as
|
|
66153
|
+
import { dirname as dirname25, join as join95, resolve as resolve23 } from "node:path";
|
|
65993
66154
|
|
|
65994
66155
|
// src/domains/sync/config-version-checker.ts
|
|
65995
66156
|
init_auth_client();
|
|
65996
66157
|
import { mkdir as mkdir27, readFile as readFile37, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
|
|
65997
|
-
import { join as
|
|
66158
|
+
import { join as join93 } from "node:path";
|
|
65998
66159
|
init_logger();
|
|
65999
66160
|
init_path_resolver();
|
|
66000
66161
|
var CACHE_TTL_HOURS = 24;
|
|
@@ -66028,7 +66189,7 @@ var CACHE_FILENAME = "config-update-cache.json";
|
|
|
66028
66189
|
class ConfigVersionChecker {
|
|
66029
66190
|
static getCacheFilePath(kitType, global3) {
|
|
66030
66191
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
66031
|
-
return
|
|
66192
|
+
return join93(cacheDir, `${kitType}-${CACHE_FILENAME}`);
|
|
66032
66193
|
}
|
|
66033
66194
|
static async loadCache(kitType, global3) {
|
|
66034
66195
|
try {
|
|
@@ -66084,7 +66245,7 @@ class ConfigVersionChecker {
|
|
|
66084
66245
|
return null;
|
|
66085
66246
|
}
|
|
66086
66247
|
const delay3 = baseBackoff * 2 ** attempt;
|
|
66087
|
-
await new Promise((
|
|
66248
|
+
await new Promise((resolve23) => setTimeout(resolve23, delay3));
|
|
66088
66249
|
}
|
|
66089
66250
|
}
|
|
66090
66251
|
return null;
|
|
@@ -66146,7 +66307,7 @@ class ConfigVersionChecker {
|
|
|
66146
66307
|
}
|
|
66147
66308
|
// src/domains/sync/sync-engine.ts
|
|
66148
66309
|
import { lstat as lstat7, readFile as readFile38, readlink, realpath as realpath3, stat as stat11 } from "node:fs/promises";
|
|
66149
|
-
import { isAbsolute as isAbsolute3, join as
|
|
66310
|
+
import { isAbsolute as isAbsolute3, join as join94, normalize as normalize8, relative as relative16 } from "node:path";
|
|
66150
66311
|
init_logger();
|
|
66151
66312
|
|
|
66152
66313
|
// node_modules/diff/libesm/diff/base.js
|
|
@@ -67253,7 +67414,7 @@ async function validateSymlinkChain(path9, basePath, maxDepth = MAX_SYMLINK_DEPT
|
|
|
67253
67414
|
if (!stats.isSymbolicLink())
|
|
67254
67415
|
break;
|
|
67255
67416
|
const target = await readlink(current);
|
|
67256
|
-
const resolvedTarget = isAbsolute3(target) ? target :
|
|
67417
|
+
const resolvedTarget = isAbsolute3(target) ? target : join94(current, "..", target);
|
|
67257
67418
|
const normalizedTarget = normalize8(resolvedTarget);
|
|
67258
67419
|
const rel = relative16(basePath, normalizedTarget);
|
|
67259
67420
|
if (rel.startsWith("..") || isAbsolute3(rel)) {
|
|
@@ -67289,7 +67450,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
67289
67450
|
if (normalized.startsWith("..") || normalized.includes("/../")) {
|
|
67290
67451
|
throw new Error(`Path traversal not allowed: ${filePath}`);
|
|
67291
67452
|
}
|
|
67292
|
-
const fullPath =
|
|
67453
|
+
const fullPath = join94(basePath, normalized);
|
|
67293
67454
|
const rel = relative16(basePath, fullPath);
|
|
67294
67455
|
if (rel.startsWith("..") || isAbsolute3(rel)) {
|
|
67295
67456
|
throw new Error(`Path escapes base directory: ${filePath}`);
|
|
@@ -67304,7 +67465,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
67304
67465
|
}
|
|
67305
67466
|
} catch (error) {
|
|
67306
67467
|
if (error.code === "ENOENT") {
|
|
67307
|
-
const parentPath =
|
|
67468
|
+
const parentPath = join94(fullPath, "..");
|
|
67308
67469
|
try {
|
|
67309
67470
|
const resolvedBase = await realpath3(basePath);
|
|
67310
67471
|
const resolvedParent = await realpath3(parentPath);
|
|
@@ -67689,7 +67850,7 @@ async function handleSync(ctx) {
|
|
|
67689
67850
|
logger.error(`Sync not yet supported for ${targetAgent}. Only --agent claude-code supports --sync.`);
|
|
67690
67851
|
return { ...ctx, cancelled: true };
|
|
67691
67852
|
}
|
|
67692
|
-
const resolvedDir = ctx.options.global ? getClaudeDir() :
|
|
67853
|
+
const resolvedDir = ctx.options.global ? getClaudeDir() : resolve23(ctx.options.dir || ".");
|
|
67693
67854
|
const claudeDir = ctx.options.global ? resolvedDir : getLocalClaudeDir(resolvedDir);
|
|
67694
67855
|
if (!await import_fs_extra34.pathExists(claudeDir)) {
|
|
67695
67856
|
logger.error("Cannot sync: no .claude directory found");
|
|
@@ -67792,7 +67953,7 @@ function getLockTimeout() {
|
|
|
67792
67953
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
67793
67954
|
async function acquireSyncLock(global3) {
|
|
67794
67955
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
67795
|
-
const lockPath =
|
|
67956
|
+
const lockPath = join95(cacheDir, ".sync-lock");
|
|
67796
67957
|
const startTime = Date.now();
|
|
67797
67958
|
const lockTimeout = getLockTimeout();
|
|
67798
67959
|
await mkdir28(dirname25(lockPath), { recursive: true });
|
|
@@ -67819,7 +67980,7 @@ async function acquireSyncLock(global3) {
|
|
|
67819
67980
|
}
|
|
67820
67981
|
logger.debug(`Lock stat failed: ${statError}`);
|
|
67821
67982
|
}
|
|
67822
|
-
await new Promise((
|
|
67983
|
+
await new Promise((resolve24) => setTimeout(resolve24, 100));
|
|
67823
67984
|
continue;
|
|
67824
67985
|
}
|
|
67825
67986
|
throw err;
|
|
@@ -67873,7 +68034,7 @@ async function executeSyncMerge(ctx) {
|
|
|
67873
68034
|
try {
|
|
67874
68035
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
67875
68036
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
67876
|
-
const targetDir =
|
|
68037
|
+
const targetDir = join95(targetPath, "..");
|
|
67877
68038
|
try {
|
|
67878
68039
|
await mkdir28(targetDir, { recursive: true });
|
|
67879
68040
|
} catch (mkdirError) {
|
|
@@ -68044,7 +68205,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
68044
68205
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
68045
68206
|
if (await import_fs_extra34.pathExists(sourcePath)) {
|
|
68046
68207
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
68047
|
-
const targetDir =
|
|
68208
|
+
const targetDir = join95(targetPath, "..");
|
|
68048
68209
|
await mkdir28(targetDir, { recursive: true });
|
|
68049
68210
|
await copyFile8(sourcePath, targetPath);
|
|
68050
68211
|
}
|
|
@@ -68066,38 +68227,38 @@ init_logger();
|
|
|
68066
68227
|
init_types2();
|
|
68067
68228
|
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
68068
68229
|
import { rename as rename8, rm as rm9 } from "node:fs/promises";
|
|
68069
|
-
import { join as
|
|
68230
|
+
import { join as join96, relative as relative17 } from "node:path";
|
|
68070
68231
|
async function collectDirsToRename(extractDir, folders) {
|
|
68071
68232
|
const dirsToRename = [];
|
|
68072
68233
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
68073
|
-
const docsPath =
|
|
68234
|
+
const docsPath = join96(extractDir, DEFAULT_FOLDERS.docs);
|
|
68074
68235
|
if (await import_fs_extra35.pathExists(docsPath)) {
|
|
68075
68236
|
dirsToRename.push({
|
|
68076
68237
|
from: docsPath,
|
|
68077
|
-
to:
|
|
68238
|
+
to: join96(extractDir, folders.docs)
|
|
68078
68239
|
});
|
|
68079
68240
|
}
|
|
68080
|
-
const claudeDocsPath =
|
|
68241
|
+
const claudeDocsPath = join96(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
68081
68242
|
if (await import_fs_extra35.pathExists(claudeDocsPath)) {
|
|
68082
68243
|
dirsToRename.push({
|
|
68083
68244
|
from: claudeDocsPath,
|
|
68084
|
-
to:
|
|
68245
|
+
to: join96(extractDir, ".claude", folders.docs)
|
|
68085
68246
|
});
|
|
68086
68247
|
}
|
|
68087
68248
|
}
|
|
68088
68249
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
68089
|
-
const plansPath =
|
|
68250
|
+
const plansPath = join96(extractDir, DEFAULT_FOLDERS.plans);
|
|
68090
68251
|
if (await import_fs_extra35.pathExists(plansPath)) {
|
|
68091
68252
|
dirsToRename.push({
|
|
68092
68253
|
from: plansPath,
|
|
68093
|
-
to:
|
|
68254
|
+
to: join96(extractDir, folders.plans)
|
|
68094
68255
|
});
|
|
68095
68256
|
}
|
|
68096
|
-
const claudePlansPath =
|
|
68257
|
+
const claudePlansPath = join96(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
68097
68258
|
if (await import_fs_extra35.pathExists(claudePlansPath)) {
|
|
68098
68259
|
dirsToRename.push({
|
|
68099
68260
|
from: claudePlansPath,
|
|
68100
|
-
to:
|
|
68261
|
+
to: join96(extractDir, ".claude", folders.plans)
|
|
68101
68262
|
});
|
|
68102
68263
|
}
|
|
68103
68264
|
}
|
|
@@ -68138,7 +68299,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
68138
68299
|
init_logger();
|
|
68139
68300
|
init_types2();
|
|
68140
68301
|
import { readFile as readFile40, readdir as readdir29, writeFile as writeFile30 } from "node:fs/promises";
|
|
68141
|
-
import { join as
|
|
68302
|
+
import { join as join97, relative as relative18 } from "node:path";
|
|
68142
68303
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
68143
68304
|
".md",
|
|
68144
68305
|
".txt",
|
|
@@ -68191,7 +68352,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
|
|
|
68191
68352
|
let replacementsCount = 0;
|
|
68192
68353
|
const entries = await readdir29(dir, { withFileTypes: true });
|
|
68193
68354
|
for (const entry of entries) {
|
|
68194
|
-
const fullPath =
|
|
68355
|
+
const fullPath = join97(dir, entry.name);
|
|
68195
68356
|
if (entry.isDirectory()) {
|
|
68196
68357
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
68197
68358
|
continue;
|
|
@@ -68328,7 +68489,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
68328
68489
|
init_logger();
|
|
68329
68490
|
import { readFile as readFile41, readdir as readdir30, writeFile as writeFile31 } from "node:fs/promises";
|
|
68330
68491
|
import { platform as platform9 } from "node:os";
|
|
68331
|
-
import { extname as extname6, join as
|
|
68492
|
+
import { extname as extname6, join as join98 } from "node:path";
|
|
68332
68493
|
var IS_WINDOWS3 = platform9() === "win32";
|
|
68333
68494
|
var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
|
|
68334
68495
|
function getHomeDirPrefix() {
|
|
@@ -68429,8 +68590,8 @@ function transformContent(content) {
|
|
|
68429
68590
|
}
|
|
68430
68591
|
function shouldTransformFile3(filename) {
|
|
68431
68592
|
const ext2 = extname6(filename).toLowerCase();
|
|
68432
|
-
const
|
|
68433
|
-
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(
|
|
68593
|
+
const basename10 = filename.split("/").pop() || filename;
|
|
68594
|
+
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename10);
|
|
68434
68595
|
}
|
|
68435
68596
|
async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
68436
68597
|
let filesTransformed = 0;
|
|
@@ -68440,7 +68601,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
68440
68601
|
async function processDirectory2(dir) {
|
|
68441
68602
|
const entries = await readdir30(dir, { withFileTypes: true });
|
|
68442
68603
|
for (const entry of entries) {
|
|
68443
|
-
const fullPath =
|
|
68604
|
+
const fullPath = join98(dir, entry.name);
|
|
68444
68605
|
if (entry.isDirectory()) {
|
|
68445
68606
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
68446
68607
|
continue;
|
|
@@ -68680,7 +68841,7 @@ init_types2();
|
|
|
68680
68841
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
68681
68842
|
|
|
68682
68843
|
// src/commands/new/phases/directory-setup.ts
|
|
68683
|
-
import { resolve as
|
|
68844
|
+
import { resolve as resolve24 } from "node:path";
|
|
68684
68845
|
init_logger();
|
|
68685
68846
|
init_types2();
|
|
68686
68847
|
var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
@@ -68764,7 +68925,7 @@ async function directorySetup(validOptions, prompts) {
|
|
|
68764
68925
|
targetDir = await prompts.getDirectory(targetDir);
|
|
68765
68926
|
}
|
|
68766
68927
|
}
|
|
68767
|
-
const resolvedDir =
|
|
68928
|
+
const resolvedDir = resolve24(targetDir);
|
|
68768
68929
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
68769
68930
|
if (isLocalSameAsGlobal(resolvedDir)) {
|
|
68770
68931
|
logger.warning("You're creating a project at HOME directory.");
|
|
@@ -68819,7 +68980,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
68819
68980
|
};
|
|
68820
68981
|
}
|
|
68821
68982
|
// src/commands/new/phases/project-creation.ts
|
|
68822
|
-
import { join as
|
|
68983
|
+
import { join as join99 } from "node:path";
|
|
68823
68984
|
init_github_client();
|
|
68824
68985
|
init_logger();
|
|
68825
68986
|
init_output_manager();
|
|
@@ -68973,7 +69134,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
68973
69134
|
output.section("Installing");
|
|
68974
69135
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
68975
69136
|
const merger = new FileMerger;
|
|
68976
|
-
const claudeDir =
|
|
69137
|
+
const claudeDir = join99(resolvedDir, ".claude");
|
|
68977
69138
|
merger.setMultiKitContext(claudeDir, kit);
|
|
68978
69139
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
68979
69140
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -69026,10 +69187,10 @@ async function handleProjectCreation(ctx) {
|
|
|
69026
69187
|
};
|
|
69027
69188
|
}
|
|
69028
69189
|
// src/commands/new/phases/post-setup.ts
|
|
69029
|
-
import { join as
|
|
69190
|
+
import { join as join101 } from "node:path";
|
|
69030
69191
|
|
|
69031
69192
|
// src/domains/installation/setup-wizard.ts
|
|
69032
|
-
import { join as
|
|
69193
|
+
import { join as join100 } from "node:path";
|
|
69033
69194
|
init_logger();
|
|
69034
69195
|
init_dist2();
|
|
69035
69196
|
var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
@@ -69109,7 +69270,7 @@ async function parseEnvFile(path9) {
|
|
|
69109
69270
|
}
|
|
69110
69271
|
}
|
|
69111
69272
|
async function checkGlobalConfig() {
|
|
69112
|
-
const globalEnvPath =
|
|
69273
|
+
const globalEnvPath = join100(getClaudeDir(), ".env");
|
|
69113
69274
|
if (!await import_fs_extra37.pathExists(globalEnvPath))
|
|
69114
69275
|
return false;
|
|
69115
69276
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -69125,7 +69286,7 @@ async function runSetupWizard(options2) {
|
|
|
69125
69286
|
let globalEnv = {};
|
|
69126
69287
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
69127
69288
|
if (!isGlobal) {
|
|
69128
|
-
const globalEnvPath =
|
|
69289
|
+
const globalEnvPath = join100(getClaudeDir(), ".env");
|
|
69129
69290
|
if (await import_fs_extra37.pathExists(globalEnvPath)) {
|
|
69130
69291
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
69131
69292
|
}
|
|
@@ -69188,7 +69349,7 @@ async function runSetupWizard(options2) {
|
|
|
69188
69349
|
}
|
|
69189
69350
|
}
|
|
69190
69351
|
await generateEnvFile(targetDir, values);
|
|
69191
|
-
f2.success(`Configuration saved to ${
|
|
69352
|
+
f2.success(`Configuration saved to ${join100(targetDir, ".env")}`);
|
|
69192
69353
|
return true;
|
|
69193
69354
|
}
|
|
69194
69355
|
async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
@@ -69291,9 +69452,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
|
|
|
69291
69452
|
withSudo: validOptions.withSudo
|
|
69292
69453
|
});
|
|
69293
69454
|
}
|
|
69294
|
-
const claudeDir =
|
|
69455
|
+
const claudeDir = join101(resolvedDir, ".claude");
|
|
69295
69456
|
await promptSetupWizardIfNeeded({
|
|
69296
|
-
envPath:
|
|
69457
|
+
envPath: join101(claudeDir, ".env"),
|
|
69297
69458
|
claudeDir,
|
|
69298
69459
|
isGlobal: false,
|
|
69299
69460
|
isNonInteractive: isNonInteractive2,
|
|
@@ -69370,19 +69531,19 @@ Example: tkm new --use-git --release v2.1.0`);
|
|
|
69370
69531
|
// src/commands/plan/plan-command.ts
|
|
69371
69532
|
init_output_manager();
|
|
69372
69533
|
import { existsSync as existsSync48, statSync as statSync5 } from "node:fs";
|
|
69373
|
-
import { dirname as dirname31, join as
|
|
69534
|
+
import { dirname as dirname31, join as join105, parse as parse2, resolve as resolve28 } from "node:path";
|
|
69374
69535
|
|
|
69375
69536
|
// src/commands/plan/plan-read-handlers.ts
|
|
69376
69537
|
import { existsSync as existsSync47, statSync as statSync4 } from "node:fs";
|
|
69377
|
-
import { basename as
|
|
69538
|
+
import { basename as basename12, dirname as dirname30, join as join104, relative as relative19, resolve as resolve26 } from "node:path";
|
|
69378
69539
|
|
|
69379
69540
|
// src/domains/plan-parser/index.ts
|
|
69380
69541
|
import { dirname as dirname29 } from "node:path";
|
|
69381
69542
|
|
|
69382
69543
|
// src/domains/plan-parser/plan-table-parser.ts
|
|
69383
69544
|
var import_gray_matter5 = __toESM(require_gray_matter(), 1);
|
|
69384
|
-
import { readFileSync as
|
|
69385
|
-
import { dirname as dirname26, resolve as
|
|
69545
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
69546
|
+
import { dirname as dirname26, resolve as resolve25 } from "node:path";
|
|
69386
69547
|
function normalizeStatus(raw) {
|
|
69387
69548
|
const s3 = raw.toLowerCase().trim();
|
|
69388
69549
|
if (s3.includes("complete") || s3.includes("done") || s3.includes("✓") || s3.includes("✅")) {
|
|
@@ -69466,7 +69627,7 @@ function parseHeaderAwareTable(content, dir, options2) {
|
|
|
69466
69627
|
hasLinks = true;
|
|
69467
69628
|
linkText = linkMatch[1].trim();
|
|
69468
69629
|
name = filenameToTitle(linkText);
|
|
69469
|
-
file =
|
|
69630
|
+
file = resolve25(dir, linkMatch[2]);
|
|
69470
69631
|
} else {
|
|
69471
69632
|
name = nameRaw.replace(/\[.*?\]\(.*?\)/g, "").trim() || `Phase ${phaseId}`;
|
|
69472
69633
|
linkText = name;
|
|
@@ -69506,7 +69667,7 @@ function parseFormat1(content, dir, options2) {
|
|
|
69506
69667
|
phaseId,
|
|
69507
69668
|
name: name.trim(),
|
|
69508
69669
|
status: normalizeStatus(status2),
|
|
69509
|
-
file:
|
|
69670
|
+
file: resolve25(dir, linkPath),
|
|
69510
69671
|
linkText: linkText.trim(),
|
|
69511
69672
|
anchor
|
|
69512
69673
|
});
|
|
@@ -69526,7 +69687,7 @@ function parseFormat2(content, dir, options2) {
|
|
|
69526
69687
|
phaseId,
|
|
69527
69688
|
name: name.trim(),
|
|
69528
69689
|
status: normalizeStatus(status2),
|
|
69529
|
-
file:
|
|
69690
|
+
file: resolve25(dir, linkPath),
|
|
69530
69691
|
linkText,
|
|
69531
69692
|
anchor
|
|
69532
69693
|
});
|
|
@@ -69545,7 +69706,7 @@ function parseFormat2b(content, dir, options2) {
|
|
|
69545
69706
|
phaseId,
|
|
69546
69707
|
name: name.trim(),
|
|
69547
69708
|
status: normalizeStatus(status2),
|
|
69548
|
-
file:
|
|
69709
|
+
file: resolve25(dir, linkPath),
|
|
69549
69710
|
linkText: name.trim(),
|
|
69550
69711
|
anchor
|
|
69551
69712
|
});
|
|
@@ -69644,7 +69805,7 @@ function parseFormat4(content, planFilePath, options2) {
|
|
|
69644
69805
|
current = { name, status: hasCheck ? "completed" : "pending" };
|
|
69645
69806
|
} else if (fileMatch && current) {
|
|
69646
69807
|
const planDir = dirname26(planFilePath);
|
|
69647
|
-
current.file =
|
|
69808
|
+
current.file = resolve25(planDir, fileMatch[1].trim());
|
|
69648
69809
|
} else if (statusMatch && current) {
|
|
69649
69810
|
current.status = normalizeStatus(statusMatch[2]);
|
|
69650
69811
|
}
|
|
@@ -69710,7 +69871,7 @@ function parseFormat6(content, dir, options2) {
|
|
|
69710
69871
|
phaseId,
|
|
69711
69872
|
name: phaseName,
|
|
69712
69873
|
status: checked.toLowerCase() === "x" ? "completed" : "pending",
|
|
69713
|
-
file:
|
|
69874
|
+
file: resolve25(dir, linkPath),
|
|
69714
69875
|
linkText: phaseName,
|
|
69715
69876
|
anchor
|
|
69716
69877
|
});
|
|
@@ -69747,7 +69908,7 @@ function parsePhasesFromBody(body, dir, options2) {
|
|
|
69747
69908
|
return parseFormat6(normalizedBody, dir, options2);
|
|
69748
69909
|
}
|
|
69749
69910
|
function parsePlanFile(planFilePath, options2) {
|
|
69750
|
-
const content =
|
|
69911
|
+
const content = readFileSync13(planFilePath, "utf8");
|
|
69751
69912
|
const dir = dirname26(planFilePath);
|
|
69752
69913
|
const { data: frontmatter, content: body } = import_gray_matter5.default(content);
|
|
69753
69914
|
const phases = parsePhasesFromBody(body, dir, options2);
|
|
@@ -69755,22 +69916,22 @@ function parsePlanFile(planFilePath, options2) {
|
|
|
69755
69916
|
}
|
|
69756
69917
|
// src/domains/plan-parser/plan-scanner.ts
|
|
69757
69918
|
import { existsSync as existsSync44, readdirSync as readdirSync5 } from "node:fs";
|
|
69758
|
-
import { join as
|
|
69919
|
+
import { join as join102 } from "node:path";
|
|
69759
69920
|
function scanPlanDir(dir) {
|
|
69760
69921
|
if (!existsSync44(dir))
|
|
69761
69922
|
return [];
|
|
69762
69923
|
try {
|
|
69763
|
-
return readdirSync5(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
69924
|
+
return readdirSync5(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join102(dir, entry.name, "plan.md")).filter(existsSync44);
|
|
69764
69925
|
} catch {
|
|
69765
69926
|
return [];
|
|
69766
69927
|
}
|
|
69767
69928
|
}
|
|
69768
69929
|
// src/domains/plan-parser/plan-validator.ts
|
|
69769
69930
|
var import_gray_matter6 = __toESM(require_gray_matter(), 1);
|
|
69770
|
-
import { existsSync as existsSync45, readFileSync as
|
|
69771
|
-
import { basename as
|
|
69931
|
+
import { existsSync as existsSync45, readFileSync as readFileSync14 } from "node:fs";
|
|
69932
|
+
import { basename as basename10, dirname as dirname27 } from "node:path";
|
|
69772
69933
|
function validatePlanFile(filePath, strict = false) {
|
|
69773
|
-
const content =
|
|
69934
|
+
const content = readFileSync14(filePath, "utf8");
|
|
69774
69935
|
const dir = dirname27(filePath);
|
|
69775
69936
|
const issues = [];
|
|
69776
69937
|
const lines = content.split(`
|
|
@@ -69808,13 +69969,13 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
69808
69969
|
}
|
|
69809
69970
|
for (const phase of phases) {
|
|
69810
69971
|
if (phase.file && !existsSync45(phase.file)) {
|
|
69811
|
-
const fileBasename =
|
|
69972
|
+
const fileBasename = basename10(phase.file);
|
|
69812
69973
|
const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
|
|
69813
69974
|
issues.push({
|
|
69814
69975
|
line: refLine >= 0 ? refLine + 1 : 1,
|
|
69815
69976
|
severity: "warning",
|
|
69816
69977
|
code: "missing-phase-file",
|
|
69817
|
-
message: `Phase ${phase.phaseId} references '${
|
|
69978
|
+
message: `Phase ${phase.phaseId} references '${basename10(phase.file)}' which doesn't exist`
|
|
69818
69979
|
});
|
|
69819
69980
|
}
|
|
69820
69981
|
}
|
|
@@ -69827,9 +69988,9 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
69827
69988
|
}
|
|
69828
69989
|
// src/domains/plan-parser/plan-writer.ts
|
|
69829
69990
|
var import_gray_matter7 = __toESM(require_gray_matter(), 1);
|
|
69830
|
-
import { mkdirSync as
|
|
69991
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync7 } from "node:fs";
|
|
69831
69992
|
import { existsSync as existsSync46 } from "node:fs";
|
|
69832
|
-
import { basename as
|
|
69993
|
+
import { basename as basename11, dirname as dirname28, join as join103 } from "node:path";
|
|
69833
69994
|
function phaseNameToFilename(id, name) {
|
|
69834
69995
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
|
|
69835
69996
|
const num = numMatch ? numMatch[1] : id;
|
|
@@ -69934,16 +70095,16 @@ function resolvePhaseIds(phases) {
|
|
|
69934
70095
|
}
|
|
69935
70096
|
function scaffoldPlan(options2) {
|
|
69936
70097
|
const { dir } = options2;
|
|
69937
|
-
|
|
70098
|
+
mkdirSync4(dir, { recursive: true });
|
|
69938
70099
|
const resolvedPhases = resolvePhaseIds(options2.phases);
|
|
69939
70100
|
const optionsWithResolved = { ...options2, phases: resolvedPhases };
|
|
69940
|
-
const planFile =
|
|
69941
|
-
|
|
70101
|
+
const planFile = join103(dir, "plan.md");
|
|
70102
|
+
writeFileSync7(planFile, generatePlanMd(optionsWithResolved), "utf8");
|
|
69942
70103
|
const phaseFiles = [];
|
|
69943
70104
|
for (const phase of resolvedPhases) {
|
|
69944
70105
|
const filename = phaseNameToFilename(phase.id, phase.name);
|
|
69945
|
-
const phaseFile =
|
|
69946
|
-
|
|
70106
|
+
const phaseFile = join103(dir, filename);
|
|
70107
|
+
writeFileSync7(phaseFile, generatePhaseTemplate(phase), "utf8");
|
|
69947
70108
|
phaseFiles.push(phaseFile);
|
|
69948
70109
|
}
|
|
69949
70110
|
return { planFile, phaseFiles };
|
|
@@ -69967,7 +70128,7 @@ function isCanonicalFormat(content) {
|
|
|
69967
70128
|
return /^\|\s*phase\s*\|\s*name\s*\|\s*status\s*\|/im.test(content);
|
|
69968
70129
|
}
|
|
69969
70130
|
function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
69970
|
-
const raw =
|
|
70131
|
+
const raw = readFileSync15(planFile, "utf8").replace(/\r\n/g, `
|
|
69971
70132
|
`);
|
|
69972
70133
|
if (!isCanonicalFormat(raw)) {
|
|
69973
70134
|
console.error("[!] plan.md is not in canonical format — skipping status update");
|
|
@@ -70007,7 +70168,7 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
|
70007
70168
|
}
|
|
70008
70169
|
const updatedFrontmatter = { ...frontmatter, status: planStatus };
|
|
70009
70170
|
const updatedContent = import_gray_matter7.default.stringify(updatedBody, updatedFrontmatter);
|
|
70010
|
-
|
|
70171
|
+
writeFileSync7(planFile, updatedContent, "utf8");
|
|
70011
70172
|
const planDir = dirname28(planFile);
|
|
70012
70173
|
const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
|
|
70013
70174
|
if (phaseFilename && existsSync46(phaseFilename)) {
|
|
@@ -70022,18 +70183,18 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
|
|
|
70022
70183
|
continue;
|
|
70023
70184
|
const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
|
|
70024
70185
|
if (linkMatch)
|
|
70025
|
-
return
|
|
70186
|
+
return join103(planDir, linkMatch[2]);
|
|
70026
70187
|
}
|
|
70027
70188
|
return null;
|
|
70028
70189
|
}
|
|
70029
70190
|
function updatePhaseFileFrontmatter(phaseFile, newStatus) {
|
|
70030
|
-
const raw =
|
|
70191
|
+
const raw = readFileSync15(phaseFile, "utf8");
|
|
70031
70192
|
const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
|
|
70032
70193
|
const updated = { ...frontmatter, status: newStatus };
|
|
70033
|
-
|
|
70194
|
+
writeFileSync7(phaseFile, import_gray_matter7.default.stringify(body, updated), "utf8");
|
|
70034
70195
|
}
|
|
70035
70196
|
function addPhase(planFile, name, afterId) {
|
|
70036
|
-
const raw =
|
|
70197
|
+
const raw = readFileSync15(planFile, "utf8").replace(/\r\n/g, `
|
|
70037
70198
|
`);
|
|
70038
70199
|
if (!isCanonicalFormat(raw)) {
|
|
70039
70200
|
console.error("[!] plan.md is not in canonical format — cannot add phase");
|
|
@@ -70069,7 +70230,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
70069
70230
|
insertIdx = i;
|
|
70070
70231
|
}
|
|
70071
70232
|
if (insertIdx === -1) {
|
|
70072
|
-
throw new Error(`Phase ID "${afterId}" not found in ${
|
|
70233
|
+
throw new Error(`Phase ID "${afterId}" not found in ${basename11(planFile)}`);
|
|
70073
70234
|
}
|
|
70074
70235
|
lines.splice(insertIdx + 1, 0, newRow);
|
|
70075
70236
|
updatedBody = lines.join(`
|
|
@@ -70102,9 +70263,9 @@ function addPhase(planFile, name, afterId) {
|
|
|
70102
70263
|
updatedBody = lines.join(`
|
|
70103
70264
|
`);
|
|
70104
70265
|
}
|
|
70105
|
-
|
|
70106
|
-
const phaseFilePath =
|
|
70107
|
-
|
|
70266
|
+
writeFileSync7(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
|
|
70267
|
+
const phaseFilePath = join103(planDir, filename);
|
|
70268
|
+
writeFileSync7(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
|
|
70108
70269
|
return { phaseId, phaseFile: phaseFilePath };
|
|
70109
70270
|
}
|
|
70110
70271
|
|
|
@@ -70152,7 +70313,7 @@ async function handleParse(target, options2) {
|
|
|
70152
70313
|
console.log(JSON.stringify({ file: relative19(process.cwd(), planFile), frontmatter, phases }, null, 2));
|
|
70153
70314
|
return;
|
|
70154
70315
|
}
|
|
70155
|
-
const title = typeof frontmatter.title === "string" ? frontmatter.title :
|
|
70316
|
+
const title = typeof frontmatter.title === "string" ? frontmatter.title : basename12(dirname30(planFile));
|
|
70156
70317
|
console.log();
|
|
70157
70318
|
console.log(import_picocolors24.default.bold(` Plan: ${title}`));
|
|
70158
70319
|
console.log(` File: ${planFile}`);
|
|
@@ -70206,8 +70367,8 @@ async function handleValidate(target, options2) {
|
|
|
70206
70367
|
process.exitCode = 1;
|
|
70207
70368
|
}
|
|
70208
70369
|
async function handleStatus(target, options2) {
|
|
70209
|
-
const t = target ?
|
|
70210
|
-
const plansDir = t && existsSync47(t) && statSync4(t).isDirectory() && !existsSync47(
|
|
70370
|
+
const t = target ? resolve26(target) : null;
|
|
70371
|
+
const plansDir = t && existsSync47(t) && statSync4(t).isDirectory() && !existsSync47(join104(t, "plan.md")) ? t : null;
|
|
70211
70372
|
if (plansDir) {
|
|
70212
70373
|
const planFiles = scanPlanDir(plansDir);
|
|
70213
70374
|
if (planFiles.length === 0) {
|
|
@@ -70232,14 +70393,14 @@ async function handleStatus(target, options2) {
|
|
|
70232
70393
|
try {
|
|
70233
70394
|
const s3 = buildPlanSummary(pf);
|
|
70234
70395
|
const bar = progressBar(s3.completed, s3.totalPhases);
|
|
70235
|
-
const title2 = s3.title ??
|
|
70396
|
+
const title2 = s3.title ?? basename12(dirname30(pf));
|
|
70236
70397
|
console.log(` ${import_picocolors24.default.bold(title2)}`);
|
|
70237
70398
|
console.log(` ${bar}`);
|
|
70238
70399
|
if (s3.inProgress > 0)
|
|
70239
70400
|
console.log(` [~] ${s3.inProgress} in progress`);
|
|
70240
70401
|
console.log();
|
|
70241
70402
|
} catch {
|
|
70242
|
-
console.log(` [X] Failed to read: ${
|
|
70403
|
+
console.log(` [X] Failed to read: ${basename12(dirname30(pf))}`);
|
|
70243
70404
|
console.log();
|
|
70244
70405
|
}
|
|
70245
70406
|
}
|
|
@@ -70263,7 +70424,7 @@ async function handleStatus(target, options2) {
|
|
|
70263
70424
|
console.log(JSON.stringify(summary, null, 2));
|
|
70264
70425
|
return;
|
|
70265
70426
|
}
|
|
70266
|
-
const title = summary.title ??
|
|
70427
|
+
const title = summary.title ?? basename12(dirname30(planFile));
|
|
70267
70428
|
console.log();
|
|
70268
70429
|
console.log(import_picocolors24.default.bold(` ${title}`));
|
|
70269
70430
|
if (summary.status)
|
|
@@ -70289,7 +70450,7 @@ async function handleKanban(target, _options) {
|
|
|
70289
70450
|
}
|
|
70290
70451
|
|
|
70291
70452
|
// src/commands/plan/plan-write-handlers.ts
|
|
70292
|
-
import { basename as
|
|
70453
|
+
import { basename as basename13, relative as relative20, resolve as resolve27 } from "node:path";
|
|
70293
70454
|
init_output_manager();
|
|
70294
70455
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
70295
70456
|
async function handleCreate(target, options2) {
|
|
@@ -70325,7 +70486,7 @@ async function handleCreate(target, options2) {
|
|
|
70325
70486
|
const result = scaffoldPlan({
|
|
70326
70487
|
title: options2.title,
|
|
70327
70488
|
phases: phaseNames.map((name) => ({ name })),
|
|
70328
|
-
dir:
|
|
70489
|
+
dir: resolve27(dir),
|
|
70329
70490
|
priority,
|
|
70330
70491
|
issue: options2.issue ? Number(options2.issue) : undefined
|
|
70331
70492
|
});
|
|
@@ -70339,10 +70500,10 @@ async function handleCreate(target, options2) {
|
|
|
70339
70500
|
}
|
|
70340
70501
|
console.log();
|
|
70341
70502
|
console.log(import_picocolors25.default.bold(` [OK] Plan created: ${options2.title}`));
|
|
70342
|
-
console.log(` Directory: ${
|
|
70503
|
+
console.log(` Directory: ${resolve27(dir)}`);
|
|
70343
70504
|
console.log(` Phases: ${result.phaseFiles.length}`);
|
|
70344
70505
|
for (const f4 of result.phaseFiles) {
|
|
70345
|
-
console.log(` [ ] ${
|
|
70506
|
+
console.log(` [ ] ${basename13(f4)}`);
|
|
70346
70507
|
}
|
|
70347
70508
|
console.log();
|
|
70348
70509
|
}
|
|
@@ -70437,12 +70598,12 @@ async function handleAddPhase(target, options2) {
|
|
|
70437
70598
|
|
|
70438
70599
|
// src/commands/plan/plan-command.ts
|
|
70439
70600
|
function resolvePlanFile(target) {
|
|
70440
|
-
const t = target ?
|
|
70601
|
+
const t = target ? resolve28(target) : process.cwd();
|
|
70441
70602
|
if (existsSync48(t)) {
|
|
70442
70603
|
const stat13 = statSync5(t);
|
|
70443
70604
|
if (stat13.isFile())
|
|
70444
70605
|
return t;
|
|
70445
|
-
const candidate =
|
|
70606
|
+
const candidate = join105(t, "plan.md");
|
|
70446
70607
|
if (existsSync48(candidate))
|
|
70447
70608
|
return candidate;
|
|
70448
70609
|
}
|
|
@@ -70450,7 +70611,7 @@ function resolvePlanFile(target) {
|
|
|
70450
70611
|
let dir = process.cwd();
|
|
70451
70612
|
const root = parse2(dir).root;
|
|
70452
70613
|
while (dir !== root) {
|
|
70453
|
-
const candidate =
|
|
70614
|
+
const candidate = join105(dir, "plan.md");
|
|
70454
70615
|
if (existsSync48(candidate))
|
|
70455
70616
|
return candidate;
|
|
70456
70617
|
dir = dirname31(dir);
|
|
@@ -70501,7 +70662,7 @@ async function planCommand(action, target, options2) {
|
|
|
70501
70662
|
let resolvedTarget = target;
|
|
70502
70663
|
if (resolvedAction && !knownActions.has(resolvedAction)) {
|
|
70503
70664
|
const looksLikePath = resolvedAction.includes("/") || resolvedAction.includes("\\") || resolvedAction.endsWith(".md") || resolvedAction === "." || resolvedAction === "..";
|
|
70504
|
-
const existsOnDisk = !looksLikePath && existsSync48(
|
|
70665
|
+
const existsOnDisk = !looksLikePath && existsSync48(resolve28(resolvedAction));
|
|
70505
70666
|
if (looksLikePath || existsOnDisk) {
|
|
70506
70667
|
resolvedTarget = resolvedAction;
|
|
70507
70668
|
resolvedAction = undefined;
|
|
@@ -70540,7 +70701,7 @@ async function planCommand(action, target, options2) {
|
|
|
70540
70701
|
}
|
|
70541
70702
|
// src/commands/projects/add-handler.ts
|
|
70542
70703
|
import { existsSync as existsSync49 } from "node:fs";
|
|
70543
|
-
import { resolve as
|
|
70704
|
+
import { resolve as resolve29 } from "node:path";
|
|
70544
70705
|
// src/domains/takumi-data/claude-projects-scanner.ts
|
|
70545
70706
|
init_logger();
|
|
70546
70707
|
// src/commands/projects/add-handler.ts
|
|
@@ -70549,7 +70710,7 @@ var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
|
70549
70710
|
async function handleAdd(projectPath, options2) {
|
|
70550
70711
|
logger.debug(`Adding project: ${projectPath}, options: ${JSON.stringify(options2)}`);
|
|
70551
70712
|
intro("Add Project");
|
|
70552
|
-
const absolutePath =
|
|
70713
|
+
const absolutePath = resolve29(projectPath);
|
|
70553
70714
|
if (!existsSync49(absolutePath)) {
|
|
70554
70715
|
log.error(`Path does not exist: ${absolutePath}`);
|
|
70555
70716
|
process.exitCode = 1;
|
|
@@ -70721,23 +70882,23 @@ init_logger();
|
|
|
70721
70882
|
init_logger();
|
|
70722
70883
|
|
|
70723
70884
|
// src/commands/telemetry/shared.ts
|
|
70724
|
-
import { existsSync as existsSync50, readFileSync as
|
|
70885
|
+
import { existsSync as existsSync50, readFileSync as readFileSync16, readdirSync as readdirSync6 } from "node:fs";
|
|
70725
70886
|
import { homedir as homedir24 } from "node:os";
|
|
70726
|
-
import { join as
|
|
70887
|
+
import { join as join106 } from "node:path";
|
|
70727
70888
|
init_token_store();
|
|
70728
70889
|
init_takumi_constants();
|
|
70729
|
-
var USER_CACHE_PATH =
|
|
70730
|
-
var EVENT_BUFFER_DIR =
|
|
70731
|
-
var RATE_STATE_PATH =
|
|
70732
|
-
var TAKUMI_MANIFEST_PATH =
|
|
70733
|
-
var LEGACY_METADATA_PATH =
|
|
70890
|
+
var USER_CACHE_PATH = join106(homedir24(), ".claude", "sk-user.json");
|
|
70891
|
+
var EVENT_BUFFER_DIR = join106(homedir24(), ".claude", "sk-events");
|
|
70892
|
+
var RATE_STATE_PATH = join106(homedir24(), ".claude", "sk-rate-state.json");
|
|
70893
|
+
var TAKUMI_MANIFEST_PATH = join106(homedir24(), ".claude", MANIFEST_FILENAME);
|
|
70894
|
+
var LEGACY_METADATA_PATH = join106(homedir24(), ".claude", LEGACY_MANIFEST_FILENAME);
|
|
70734
70895
|
var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
|
|
70735
70896
|
var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
|
|
70736
70897
|
function readUserCache() {
|
|
70737
70898
|
try {
|
|
70738
70899
|
if (!existsSync50(USER_CACHE_PATH))
|
|
70739
70900
|
return null;
|
|
70740
|
-
const parsed = JSON.parse(
|
|
70901
|
+
const parsed = JSON.parse(readFileSync16(USER_CACHE_PATH, "utf8"));
|
|
70741
70902
|
if (!parsed || typeof parsed !== "object")
|
|
70742
70903
|
return null;
|
|
70743
70904
|
return parsed;
|
|
@@ -70771,9 +70932,9 @@ function readTelemetryConfig() {
|
|
|
70771
70932
|
const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
|
|
70772
70933
|
let metadata = null;
|
|
70773
70934
|
try {
|
|
70774
|
-
const resolved = findManifestPathSync(
|
|
70935
|
+
const resolved = findManifestPathSync(join106(homedir24(), ".claude"));
|
|
70775
70936
|
if (resolved) {
|
|
70776
|
-
metadata = JSON.parse(
|
|
70937
|
+
metadata = JSON.parse(readFileSync16(resolved.path, "utf8"));
|
|
70777
70938
|
}
|
|
70778
70939
|
} catch {
|
|
70779
70940
|
metadata = null;
|
|
@@ -70817,13 +70978,13 @@ async function handleDisable() {
|
|
|
70817
70978
|
}
|
|
70818
70979
|
// src/commands/telemetry/phases/purge-local-handler.ts
|
|
70819
70980
|
init_logger();
|
|
70820
|
-
import { existsSync as existsSync51, readdirSync as readdirSync7, unlinkSync as
|
|
70821
|
-
import { join as
|
|
70981
|
+
import { existsSync as existsSync51, readdirSync as readdirSync7, unlinkSync as unlinkSync6 } from "node:fs";
|
|
70982
|
+
import { join as join107 } from "node:path";
|
|
70822
70983
|
function removeIfExists(path9) {
|
|
70823
70984
|
try {
|
|
70824
70985
|
if (!existsSync51(path9))
|
|
70825
70986
|
return false;
|
|
70826
|
-
|
|
70987
|
+
unlinkSync6(path9);
|
|
70827
70988
|
return true;
|
|
70828
70989
|
} catch {
|
|
70829
70990
|
return false;
|
|
@@ -70838,7 +70999,7 @@ function removeBufferFiles() {
|
|
|
70838
70999
|
if (!file.endsWith(".jsonl"))
|
|
70839
71000
|
continue;
|
|
70840
71001
|
try {
|
|
70841
|
-
|
|
71002
|
+
unlinkSync6(join107(EVENT_BUFFER_DIR, file));
|
|
70842
71003
|
count += 1;
|
|
70843
71004
|
} catch {}
|
|
70844
71005
|
}
|
|
@@ -71064,13 +71225,13 @@ async function detectInstallations() {
|
|
|
71064
71225
|
|
|
71065
71226
|
// src/commands/uninstall/removal-handler.ts
|
|
71066
71227
|
import { readdirSync as readdirSync9, rmSync as rmSync6 } from "node:fs";
|
|
71067
|
-
import { join as
|
|
71228
|
+
import { join as join109, resolve as resolve30, sep as sep8 } from "node:path";
|
|
71068
71229
|
init_logger();
|
|
71069
71230
|
var import_fs_extra39 = __toESM(require_lib(), 1);
|
|
71070
71231
|
|
|
71071
71232
|
// src/commands/uninstall/analysis-handler.ts
|
|
71072
71233
|
import { existsSync as existsSync52, readdirSync as readdirSync8, rmSync as rmSync5 } from "node:fs";
|
|
71073
|
-
import { dirname as dirname32, join as
|
|
71234
|
+
import { dirname as dirname32, join as join108 } from "node:path";
|
|
71074
71235
|
init_logger();
|
|
71075
71236
|
init_takumi_constants();
|
|
71076
71237
|
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
@@ -71126,7 +71287,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
71126
71287
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
71127
71288
|
const kitFiles = metadata.kits[kit].files || [];
|
|
71128
71289
|
for (const trackedFile of kitFiles) {
|
|
71129
|
-
const filePath =
|
|
71290
|
+
const filePath = join108(installation.path, trackedFile.path);
|
|
71130
71291
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
71131
71292
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
71132
71293
|
continue;
|
|
@@ -71158,7 +71319,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
71158
71319
|
return result;
|
|
71159
71320
|
}
|
|
71160
71321
|
for (const trackedFile of allTrackedFiles) {
|
|
71161
|
-
const filePath =
|
|
71322
|
+
const filePath = join108(installation.path, trackedFile.path);
|
|
71162
71323
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
71163
71324
|
if (!ownershipResult.exists)
|
|
71164
71325
|
continue;
|
|
@@ -71214,8 +71375,8 @@ async function isDirectory(filePath) {
|
|
|
71214
71375
|
}
|
|
71215
71376
|
async function isPathSafeToRemove(filePath, baseDir) {
|
|
71216
71377
|
try {
|
|
71217
|
-
const resolvedPath =
|
|
71218
|
-
const resolvedBase =
|
|
71378
|
+
const resolvedPath = resolve30(filePath);
|
|
71379
|
+
const resolvedBase = resolve30(baseDir);
|
|
71219
71380
|
if (!resolvedPath.startsWith(resolvedBase + sep8) && resolvedPath !== resolvedBase) {
|
|
71220
71381
|
logger.debug(`Path outside installation directory: ${filePath}`);
|
|
71221
71382
|
return false;
|
|
@@ -71223,7 +71384,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
71223
71384
|
const stats = await import_fs_extra39.lstat(filePath);
|
|
71224
71385
|
if (stats.isSymbolicLink()) {
|
|
71225
71386
|
const realPath = await import_fs_extra39.realpath(filePath);
|
|
71226
|
-
const resolvedReal =
|
|
71387
|
+
const resolvedReal = resolve30(realPath);
|
|
71227
71388
|
if (!resolvedReal.startsWith(resolvedBase + sep8) && resolvedReal !== resolvedBase) {
|
|
71228
71389
|
logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
|
|
71229
71390
|
return false;
|
|
@@ -71257,7 +71418,7 @@ async function removeInstallations(installations, options2) {
|
|
|
71257
71418
|
let removedCount = 0;
|
|
71258
71419
|
let cleanedDirs = 0;
|
|
71259
71420
|
for (const item of analysis.toDelete) {
|
|
71260
|
-
const filePath =
|
|
71421
|
+
const filePath = join109(installation.path, item.path);
|
|
71261
71422
|
if (!await import_fs_extra39.pathExists(filePath))
|
|
71262
71423
|
continue;
|
|
71263
71424
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -71625,7 +71786,7 @@ var import_fs_extra40 = __toESM(require_lib(), 1);
|
|
|
71625
71786
|
// package.json
|
|
71626
71787
|
var package_default = {
|
|
71627
71788
|
name: "@sunasteriskrnd/takumi",
|
|
71628
|
-
version: "1.0.0-dev.
|
|
71789
|
+
version: "1.0.0-dev.14",
|
|
71629
71790
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
71630
71791
|
type: "module",
|
|
71631
71792
|
repository: {
|
|
@@ -71938,12 +72099,12 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
71938
72099
|
args.push("--beta");
|
|
71939
72100
|
const displayCmd = `tkm ${args.join(" ")}`;
|
|
71940
72101
|
logger.info(`Running: ${displayCmd}`);
|
|
71941
|
-
const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((
|
|
72102
|
+
const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((resolve31) => {
|
|
71942
72103
|
const child = spawn2("tkm", spawnArgs, { stdio: "inherit", shell: true });
|
|
71943
|
-
child.on("close", (code) =>
|
|
72104
|
+
child.on("close", (code) => resolve31(code ?? 1));
|
|
71944
72105
|
child.on("error", (err) => {
|
|
71945
72106
|
logger.verbose(`Failed to spawn tkm init: ${err.message}`);
|
|
71946
|
-
|
|
72107
|
+
resolve31(1);
|
|
71947
72108
|
});
|
|
71948
72109
|
}));
|
|
71949
72110
|
const exitCode = await spawnFn(args);
|
|
@@ -72232,7 +72393,7 @@ init_logger();
|
|
|
72232
72393
|
import { existsSync as existsSync58 } from "node:fs";
|
|
72233
72394
|
import { rm as rm10 } from "node:fs/promises";
|
|
72234
72395
|
import { homedir as homedir26 } from "node:os";
|
|
72235
|
-
import { join as
|
|
72396
|
+
import { join as join116 } from "node:path";
|
|
72236
72397
|
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
72237
72398
|
|
|
72238
72399
|
// src/commands/watch/phases/implementation-runner.ts
|
|
@@ -72301,7 +72462,7 @@ function getDisclaimerMarker() {
|
|
|
72301
72462
|
return AI_DISCLAIMER;
|
|
72302
72463
|
}
|
|
72303
72464
|
function spawnAndCollect2(command, args) {
|
|
72304
|
-
return new Promise((
|
|
72465
|
+
return new Promise((resolve31, reject) => {
|
|
72305
72466
|
const child = spawn4(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
72306
72467
|
const chunks = [];
|
|
72307
72468
|
const stderrChunks = [];
|
|
@@ -72314,7 +72475,7 @@ function spawnAndCollect2(command, args) {
|
|
|
72314
72475
|
reject(new Error(`${command} exited with code ${code}: ${stderr}`));
|
|
72315
72476
|
return;
|
|
72316
72477
|
}
|
|
72317
|
-
|
|
72478
|
+
resolve31(Buffer.concat(chunks).toString("utf-8"));
|
|
72318
72479
|
});
|
|
72319
72480
|
});
|
|
72320
72481
|
}
|
|
@@ -72414,7 +72575,7 @@ function formatResponse(content) {
|
|
|
72414
72575
|
return disclaimer + formatted;
|
|
72415
72576
|
}
|
|
72416
72577
|
async function postViaGh(owner, repo, issueNumber, body) {
|
|
72417
|
-
return new Promise((
|
|
72578
|
+
return new Promise((resolve31, reject) => {
|
|
72418
72579
|
const args = [
|
|
72419
72580
|
"issue",
|
|
72420
72581
|
"comment",
|
|
@@ -72436,7 +72597,7 @@ async function postViaGh(owner, repo, issueNumber, body) {
|
|
|
72436
72597
|
reject(new Error(`gh exited with code ${code}: ${stderr}`));
|
|
72437
72598
|
return;
|
|
72438
72599
|
}
|
|
72439
|
-
|
|
72600
|
+
resolve31();
|
|
72440
72601
|
});
|
|
72441
72602
|
});
|
|
72442
72603
|
}
|
|
@@ -72554,7 +72715,7 @@ After completing the implementation:
|
|
|
72554
72715
|
"--allowedTools",
|
|
72555
72716
|
tools
|
|
72556
72717
|
];
|
|
72557
|
-
await new Promise((
|
|
72718
|
+
await new Promise((resolve31, reject) => {
|
|
72558
72719
|
const child = spawn6("claude", args, { cwd: cwd2, stdio: ["pipe", "pipe", "pipe"], detached: false });
|
|
72559
72720
|
child.stdin.write(prompt);
|
|
72560
72721
|
child.stdin.end();
|
|
@@ -72579,7 +72740,7 @@ After completing the implementation:
|
|
|
72579
72740
|
reject(new Error(`Claude exited ${code}: ${stderr.slice(0, 500)}`));
|
|
72580
72741
|
return;
|
|
72581
72742
|
}
|
|
72582
|
-
|
|
72743
|
+
resolve31();
|
|
72583
72744
|
});
|
|
72584
72745
|
});
|
|
72585
72746
|
}
|
|
@@ -72722,7 +72883,7 @@ function checkRateLimit2(processedThisHour, maxPerHour) {
|
|
|
72722
72883
|
return processedThisHour < maxPerHour;
|
|
72723
72884
|
}
|
|
72724
72885
|
function spawnAndCollect3(command, args) {
|
|
72725
|
-
return new Promise((
|
|
72886
|
+
return new Promise((resolve31, reject) => {
|
|
72726
72887
|
const child = spawn7(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
72727
72888
|
const chunks = [];
|
|
72728
72889
|
const stderrChunks = [];
|
|
@@ -72735,14 +72896,14 @@ function spawnAndCollect3(command, args) {
|
|
|
72735
72896
|
reject(new Error(`${command} exited with code ${code}: ${stderr}`));
|
|
72736
72897
|
return;
|
|
72737
72898
|
}
|
|
72738
|
-
|
|
72899
|
+
resolve31(Buffer.concat(chunks).toString("utf-8"));
|
|
72739
72900
|
});
|
|
72740
72901
|
});
|
|
72741
72902
|
}
|
|
72742
72903
|
|
|
72743
72904
|
// src/commands/watch/phases/issue-processor.ts
|
|
72744
72905
|
import { mkdir as mkdir29, writeFile as writeFile33 } from "node:fs/promises";
|
|
72745
|
-
import { join as
|
|
72906
|
+
import { join as join112 } from "node:path";
|
|
72746
72907
|
|
|
72747
72908
|
// src/commands/watch/phases/approval-detector.ts
|
|
72748
72909
|
init_logger();
|
|
@@ -72784,7 +72945,7 @@ async function invokeClaude(options2) {
|
|
|
72784
72945
|
return collectClaudeOutput(child, options2.timeoutSec, verbose);
|
|
72785
72946
|
}
|
|
72786
72947
|
function collectClaudeOutput(child, timeoutSec, verbose = false) {
|
|
72787
|
-
return new Promise((
|
|
72948
|
+
return new Promise((resolve31, reject) => {
|
|
72788
72949
|
const chunks = [];
|
|
72789
72950
|
const stderrChunks = [];
|
|
72790
72951
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -72814,7 +72975,7 @@ function collectClaudeOutput(child, timeoutSec, verbose = false) {
|
|
|
72814
72975
|
reject(new Error(`Claude exited with code ${code}: ${stderr}`));
|
|
72815
72976
|
return;
|
|
72816
72977
|
}
|
|
72817
|
-
|
|
72978
|
+
resolve31(verbose ? parseStreamJsonOutput(stdout2) : parseClaudeOutput(stdout2));
|
|
72818
72979
|
});
|
|
72819
72980
|
});
|
|
72820
72981
|
}
|
|
@@ -73117,9 +73278,9 @@ async function checkAwaitingApproval(state, setup, options2, watchLog, projectDi
|
|
|
73117
73278
|
|
|
73118
73279
|
// src/commands/watch/phases/plan-dir-finder.ts
|
|
73119
73280
|
import { readdir as readdir32, stat as stat13 } from "node:fs/promises";
|
|
73120
|
-
import { join as
|
|
73281
|
+
import { join as join111 } from "node:path";
|
|
73121
73282
|
async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
73122
|
-
const plansRoot =
|
|
73283
|
+
const plansRoot = join111(cwd2, "plans");
|
|
73123
73284
|
try {
|
|
73124
73285
|
const entries = await readdir32(plansRoot);
|
|
73125
73286
|
const tenMinAgo = Date.now() - 10 * 60 * 1000;
|
|
@@ -73128,14 +73289,14 @@ async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
|
73128
73289
|
for (const entry of entries) {
|
|
73129
73290
|
if (entry === "watch" || entry === "reports" || entry === "visuals")
|
|
73130
73291
|
continue;
|
|
73131
|
-
const dirPath =
|
|
73292
|
+
const dirPath = join111(plansRoot, entry);
|
|
73132
73293
|
const dirStat = await stat13(dirPath);
|
|
73133
73294
|
if (!dirStat.isDirectory())
|
|
73134
73295
|
continue;
|
|
73135
73296
|
if (dirStat.mtimeMs < tenMinAgo)
|
|
73136
73297
|
continue;
|
|
73137
73298
|
try {
|
|
73138
|
-
await stat13(
|
|
73299
|
+
await stat13(join111(dirPath, "plan.md"));
|
|
73139
73300
|
} catch {
|
|
73140
73301
|
continue;
|
|
73141
73302
|
}
|
|
@@ -73366,13 +73527,13 @@ async function handlePlanGeneration(issue, state, config, setup, options2, watch
|
|
|
73366
73527
|
stats.plansCreated++;
|
|
73367
73528
|
const detectedPlanDir = await findRecentPlanDir(projectDir, issue.number, watchLog);
|
|
73368
73529
|
if (detectedPlanDir) {
|
|
73369
|
-
state.activeIssues[numStr].planPath =
|
|
73530
|
+
state.activeIssues[numStr].planPath = join112(detectedPlanDir, "plan.md");
|
|
73370
73531
|
watchLog.info(`Plan directory detected: ${detectedPlanDir}`);
|
|
73371
73532
|
} else {
|
|
73372
73533
|
try {
|
|
73373
|
-
const planDir =
|
|
73534
|
+
const planDir = join112(projectDir, "plans", "watch");
|
|
73374
73535
|
await mkdir29(planDir, { recursive: true });
|
|
73375
|
-
const planFilePath =
|
|
73536
|
+
const planFilePath = join112(planDir, `issue-${issue.number}-plan.md`);
|
|
73376
73537
|
await writeFile33(planFilePath, planResult.planText, "utf-8");
|
|
73377
73538
|
state.activeIssues[numStr].planPath = planFilePath;
|
|
73378
73539
|
watchLog.info(`Plan saved (fallback) to ${planFilePath}`);
|
|
@@ -73677,18 +73838,18 @@ init_logger();
|
|
|
73677
73838
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
73678
73839
|
import { existsSync as existsSync55 } from "node:fs";
|
|
73679
73840
|
import { readdir as readdir33, stat as stat14 } from "node:fs/promises";
|
|
73680
|
-
import { join as
|
|
73841
|
+
import { join as join113 } from "node:path";
|
|
73681
73842
|
async function scanForRepos(parentDir) {
|
|
73682
73843
|
const repos = [];
|
|
73683
73844
|
const entries = await readdir33(parentDir);
|
|
73684
73845
|
for (const entry of entries) {
|
|
73685
73846
|
if (entry.startsWith("."))
|
|
73686
73847
|
continue;
|
|
73687
|
-
const fullPath =
|
|
73848
|
+
const fullPath = join113(parentDir, entry);
|
|
73688
73849
|
const entryStat = await stat14(fullPath);
|
|
73689
73850
|
if (!entryStat.isDirectory())
|
|
73690
73851
|
continue;
|
|
73691
|
-
const gitDir =
|
|
73852
|
+
const gitDir = join113(fullPath, ".git");
|
|
73692
73853
|
if (!existsSync55(gitDir))
|
|
73693
73854
|
continue;
|
|
73694
73855
|
const result = spawnSync5("gh", ["repo", "view", "--json", "owner,name"], {
|
|
@@ -73715,7 +73876,7 @@ init_logger();
|
|
|
73715
73876
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
73716
73877
|
import { existsSync as existsSync56 } from "node:fs";
|
|
73717
73878
|
import { homedir as homedir25 } from "node:os";
|
|
73718
|
-
import { join as
|
|
73879
|
+
import { join as join114 } from "node:path";
|
|
73719
73880
|
async function validateSetup(cwd2) {
|
|
73720
73881
|
const workDir = cwd2 ?? process.cwd();
|
|
73721
73882
|
const ghVersion = spawnSync6("gh", ["--version"], { encoding: "utf-8", timeout: 1e4 });
|
|
@@ -73746,7 +73907,7 @@ Run this command from a directory with a GitHub remote.`);
|
|
|
73746
73907
|
} catch {
|
|
73747
73908
|
throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
|
|
73748
73909
|
}
|
|
73749
|
-
const skillsPath =
|
|
73910
|
+
const skillsPath = join114(homedir25(), ".claude", "skills");
|
|
73750
73911
|
const skillsAvailable = existsSync56(skillsPath);
|
|
73751
73912
|
if (!skillsAvailable) {
|
|
73752
73913
|
logger.warning(`Takumi Engineer skills not found at ${skillsPath}`);
|
|
@@ -73765,7 +73926,7 @@ init_path_resolver();
|
|
|
73765
73926
|
import { createWriteStream as createWriteStream4, statSync as statSync6 } from "node:fs";
|
|
73766
73927
|
import { existsSync as existsSync57 } from "node:fs";
|
|
73767
73928
|
import { mkdir as mkdir31, rename as rename9 } from "node:fs/promises";
|
|
73768
|
-
import { join as
|
|
73929
|
+
import { join as join115 } from "node:path";
|
|
73769
73930
|
|
|
73770
73931
|
class WatchLogger {
|
|
73771
73932
|
logStream = null;
|
|
@@ -73773,7 +73934,7 @@ class WatchLogger {
|
|
|
73773
73934
|
logPath = null;
|
|
73774
73935
|
maxBytes;
|
|
73775
73936
|
constructor(logDir, maxBytes = 0) {
|
|
73776
|
-
this.logDir = logDir ??
|
|
73937
|
+
this.logDir = logDir ?? join115(PathResolver.getTakumiDir(), "logs");
|
|
73777
73938
|
this.maxBytes = maxBytes;
|
|
73778
73939
|
}
|
|
73779
73940
|
async init() {
|
|
@@ -73782,7 +73943,7 @@ class WatchLogger {
|
|
|
73782
73943
|
await mkdir31(this.logDir, { recursive: true });
|
|
73783
73944
|
}
|
|
73784
73945
|
const dateStr = formatDate(new Date);
|
|
73785
|
-
this.logPath =
|
|
73946
|
+
this.logPath = join115(this.logDir, `watch-${dateStr}.log`);
|
|
73786
73947
|
this.logStream = createWriteStream4(this.logPath, { flags: "a", mode: 384 });
|
|
73787
73948
|
} catch (error) {
|
|
73788
73949
|
logger.warning(`Cannot create watch log file: ${error instanceof Error ? error.message : "Unknown"}`);
|
|
@@ -73962,7 +74123,7 @@ async function watchCommand(options2) {
|
|
|
73962
74123
|
}
|
|
73963
74124
|
async function discoverRepos(options2, watchLog) {
|
|
73964
74125
|
const cwd2 = process.cwd();
|
|
73965
|
-
const isGitRepo = existsSync58(
|
|
74126
|
+
const isGitRepo = existsSync58(join116(cwd2, ".git"));
|
|
73966
74127
|
if (options2.force) {
|
|
73967
74128
|
await forceRemoveLock(watchLog);
|
|
73968
74129
|
}
|
|
@@ -74032,7 +74193,7 @@ async function resetState(state, projectDir, watchLog) {
|
|
|
74032
74193
|
watchLog.info(`Watch state reset (--force) for ${projectDir}`);
|
|
74033
74194
|
}
|
|
74034
74195
|
async function forceRemoveLock(watchLog) {
|
|
74035
|
-
const lockPath =
|
|
74196
|
+
const lockPath = join116(homedir26(), ".sunagentkit", "locks", `${LOCK_NAME}.lock`);
|
|
74036
74197
|
try {
|
|
74037
74198
|
await rm10(lockPath, { recursive: true, force: true });
|
|
74038
74199
|
watchLog.info("Removed existing lock file (--force)");
|
|
@@ -74071,7 +74232,7 @@ function formatQueueInfo(state) {
|
|
|
74071
74232
|
return "idle";
|
|
74072
74233
|
}
|
|
74073
74234
|
function sleep2(ms2) {
|
|
74074
|
-
return new Promise((
|
|
74235
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms2));
|
|
74075
74236
|
}
|
|
74076
74237
|
// src/cli/command-registry.ts
|
|
74077
74238
|
init_logger();
|
|
@@ -74212,8 +74373,8 @@ function registerCommands(cli) {
|
|
|
74212
74373
|
}
|
|
74213
74374
|
|
|
74214
74375
|
// src/cli/version-display.ts
|
|
74215
|
-
import { readFileSync as
|
|
74216
|
-
import { join as
|
|
74376
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
74377
|
+
import { join as join128 } from "node:path";
|
|
74217
74378
|
init_help_banner();
|
|
74218
74379
|
// src/domains/versioning/checking/kit-version-checker.ts
|
|
74219
74380
|
init_github_client();
|
|
@@ -74225,14 +74386,14 @@ init_logger();
|
|
|
74225
74386
|
init_path_resolver();
|
|
74226
74387
|
import { existsSync as existsSync69 } from "node:fs";
|
|
74227
74388
|
import { mkdir as mkdir32, readFile as readFile47, writeFile as writeFile36 } from "node:fs/promises";
|
|
74228
|
-
import { join as
|
|
74389
|
+
import { join as join127 } from "node:path";
|
|
74229
74390
|
|
|
74230
74391
|
class VersionCacheManager {
|
|
74231
74392
|
static CACHE_FILENAME = "version-check.json";
|
|
74232
74393
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
74233
74394
|
static getCacheFile() {
|
|
74234
74395
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
74235
|
-
return
|
|
74396
|
+
return join127(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
74236
74397
|
}
|
|
74237
74398
|
static async load() {
|
|
74238
74399
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -74525,7 +74686,7 @@ async function displayVersion() {
|
|
|
74525
74686
|
const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
|
|
74526
74687
|
if (!localSubdir)
|
|
74527
74688
|
continue;
|
|
74528
|
-
const localRoot =
|
|
74689
|
+
const localRoot = join128(process.cwd(), localSubdir);
|
|
74529
74690
|
if (localRoot === inst.globalRoot())
|
|
74530
74691
|
continue;
|
|
74531
74692
|
const resolved = findManifestPathSync(localRoot);
|
|
@@ -74535,7 +74696,7 @@ async function displayVersion() {
|
|
|
74535
74696
|
}
|
|
74536
74697
|
for (const { provider, path: metaPath } of localChecks) {
|
|
74537
74698
|
try {
|
|
74538
|
-
const rawMetadata = JSON.parse(
|
|
74699
|
+
const rawMetadata = JSON.parse(readFileSync21(metaPath, "utf-8"));
|
|
74539
74700
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
74540
74701
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
74541
74702
|
if (kitsDisplay) {
|
|
@@ -74555,7 +74716,7 @@ async function displayVersion() {
|
|
|
74555
74716
|
const resolved = findManifestPathSync(installPath);
|
|
74556
74717
|
if (resolved) {
|
|
74557
74718
|
try {
|
|
74558
|
-
const rawMetadata = JSON.parse(
|
|
74719
|
+
const rawMetadata = JSON.parse(readFileSync21(resolved.path, "utf-8"));
|
|
74559
74720
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
74560
74721
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
74561
74722
|
if (kitsDisplay) {
|