@sunasteriskrnd/takumi 1.0.0-dev.13 → 1.0.0-dev.15
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/README.md +7 -7
- package/dist/index.js +670 -488
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19579,14 +19579,17 @@ function isSafeRelativeLayoutPath(value) {
|
|
|
19579
19579
|
return segments.every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
|
|
19580
19580
|
}
|
|
19581
19581
|
function isValidKitType(value) {
|
|
19582
|
-
return value === "
|
|
19582
|
+
return value === "core" || value === "extras";
|
|
19583
19583
|
}
|
|
19584
|
-
|
|
19584
|
+
function backendIdOf(kitType) {
|
|
19585
|
+
return AVAILABLE_KITS[kitType].id;
|
|
19586
|
+
}
|
|
19587
|
+
var KitType, KitConfigSchema, KitLayoutSchema, TakumiPackageMetadataSchema, DEFAULT_KIT_LAYOUT, AVAILABLE_KITS, BASE_KIT = "core", NEVER_COPY_PATTERNS, USER_CONFIG_PATTERNS, PROTECTED_PATTERNS;
|
|
19585
19588
|
var init_kit = __esm(() => {
|
|
19586
19589
|
init_zod();
|
|
19587
|
-
KitType = exports_external.enum(["
|
|
19590
|
+
KitType = exports_external.enum(["core", "extras"]);
|
|
19588
19591
|
KitConfigSchema = exports_external.object({
|
|
19589
|
-
id:
|
|
19592
|
+
id: exports_external.string(),
|
|
19590
19593
|
name: exports_external.string(),
|
|
19591
19594
|
repo: exports_external.string(),
|
|
19592
19595
|
owner: exports_external.string(),
|
|
@@ -19604,12 +19607,12 @@ var init_kit = __esm(() => {
|
|
|
19604
19607
|
runtimeDir: ".claude"
|
|
19605
19608
|
};
|
|
19606
19609
|
AVAILABLE_KITS = {
|
|
19607
|
-
|
|
19610
|
+
core: {
|
|
19608
19611
|
id: "engineer",
|
|
19609
|
-
name: "
|
|
19612
|
+
name: "Core",
|
|
19610
19613
|
repo: "takumi",
|
|
19611
19614
|
owner: "sun-asterisk-internal",
|
|
19612
|
-
description: "
|
|
19615
|
+
description: "Core toolkit for building with Claude"
|
|
19613
19616
|
},
|
|
19614
19617
|
extras: {
|
|
19615
19618
|
id: "extras",
|
|
@@ -20270,6 +20273,7 @@ var exports_types = {};
|
|
|
20270
20273
|
__export(exports_types, {
|
|
20271
20274
|
normalizeTakumiConfigInput: () => normalizeTakumiConfigInput,
|
|
20272
20275
|
isValidKitType: () => isValidKitType,
|
|
20276
|
+
backendIdOf: () => backendIdOf,
|
|
20273
20277
|
VidcapOptionsSchema: () => VidcapOptionsSchema,
|
|
20274
20278
|
VersionCommandOptionsSchema: () => VersionCommandOptionsSchema,
|
|
20275
20279
|
ValidationResultSchema: () => ValidationResultSchema,
|
|
@@ -32365,7 +32369,7 @@ var init_error_handler = __esm(() => {
|
|
|
32365
32369
|
// src/domains/versioning/release-cache.ts
|
|
32366
32370
|
import { existsSync as existsSync40 } from "node:fs";
|
|
32367
32371
|
import { mkdir as mkdir18, readFile as readFile34, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
|
|
32368
|
-
import { join as
|
|
32372
|
+
import { join as join79 } from "node:path";
|
|
32369
32373
|
var ReleaseCacheEntrySchema, ReleaseCache;
|
|
32370
32374
|
var init_release_cache = __esm(() => {
|
|
32371
32375
|
init_logger();
|
|
@@ -32380,7 +32384,7 @@ var init_release_cache = __esm(() => {
|
|
|
32380
32384
|
static CACHE_TTL_SECONDS = Number(process.env.TAKUMI_CACHE_TTL) || 3600;
|
|
32381
32385
|
cacheDir;
|
|
32382
32386
|
constructor() {
|
|
32383
|
-
this.cacheDir =
|
|
32387
|
+
this.cacheDir = join79(PathResolver.getCacheDir(false), ReleaseCache.CACHE_DIR);
|
|
32384
32388
|
}
|
|
32385
32389
|
async get(key) {
|
|
32386
32390
|
const cacheFile = this.getCachePath(key);
|
|
@@ -32438,7 +32442,7 @@ var init_release_cache = __esm(() => {
|
|
|
32438
32442
|
const files = await readdir25(this.cacheDir);
|
|
32439
32443
|
for (const file of files) {
|
|
32440
32444
|
if (file.endsWith(".json")) {
|
|
32441
|
-
await unlink8(
|
|
32445
|
+
await unlink8(join79(this.cacheDir, file));
|
|
32442
32446
|
}
|
|
32443
32447
|
}
|
|
32444
32448
|
logger.debug("All release cache cleared");
|
|
@@ -32449,7 +32453,7 @@ var init_release_cache = __esm(() => {
|
|
|
32449
32453
|
}
|
|
32450
32454
|
getCachePath(key) {
|
|
32451
32455
|
const safeKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
32452
|
-
return
|
|
32456
|
+
return join79(this.cacheDir, `${safeKey}.json`);
|
|
32453
32457
|
}
|
|
32454
32458
|
isExpired(timestamp) {
|
|
32455
32459
|
const now = Date.now();
|
|
@@ -33370,7 +33374,7 @@ async function checkTokenScopes() {
|
|
|
33370
33374
|
};
|
|
33371
33375
|
}
|
|
33372
33376
|
}
|
|
33373
|
-
async function checkRepositoryAccess(kitType = "
|
|
33377
|
+
async function checkRepositoryAccess(kitType = "core") {
|
|
33374
33378
|
if (process.env.CI === "true") {
|
|
33375
33379
|
return {
|
|
33376
33380
|
id: `github-repo-access-${kitType}`,
|
|
@@ -33442,14 +33446,14 @@ var exports_monorepo_resolver = {};
|
|
|
33442
33446
|
__export(exports_monorepo_resolver, {
|
|
33443
33447
|
resolveMonorepoRoot: () => resolveMonorepoRoot
|
|
33444
33448
|
});
|
|
33445
|
-
import { existsSync as existsSync42, readFileSync as
|
|
33446
|
-
import { dirname as dirname23, join as
|
|
33449
|
+
import { existsSync as existsSync42, readFileSync as readFileSync12 } from "node:fs";
|
|
33450
|
+
import { dirname as dirname23, join as join90, resolve as resolve20 } from "node:path";
|
|
33447
33451
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
33448
33452
|
function parseMetadataAt(metadataPath) {
|
|
33449
33453
|
if (!existsSync42(metadataPath))
|
|
33450
33454
|
return null;
|
|
33451
33455
|
try {
|
|
33452
|
-
const raw =
|
|
33456
|
+
const raw = readFileSync12(metadataPath, "utf-8");
|
|
33453
33457
|
const parsed = JSON.parse(raw);
|
|
33454
33458
|
if (typeof parsed.name !== "string" || typeof parsed.version !== "string" || !ACCEPTED_METADATA_NAMES.has(parsed.name)) {
|
|
33455
33459
|
return null;
|
|
@@ -33460,11 +33464,11 @@ function parseMetadataAt(metadataPath) {
|
|
|
33460
33464
|
}
|
|
33461
33465
|
}
|
|
33462
33466
|
function readSourceDirFromPackageJson(candidateRoot) {
|
|
33463
|
-
const packageJsonPath =
|
|
33467
|
+
const packageJsonPath = join90(candidateRoot, "package.json");
|
|
33464
33468
|
if (!existsSync42(packageJsonPath))
|
|
33465
33469
|
return null;
|
|
33466
33470
|
try {
|
|
33467
|
-
const parsed = JSON.parse(
|
|
33471
|
+
const parsed = JSON.parse(readFileSync12(packageJsonPath, "utf-8"));
|
|
33468
33472
|
const kitCfg = parsed.takumi;
|
|
33469
33473
|
if (kitCfg && typeof kitCfg.sourceDir === "string" && kitCfg.sourceDir.length > 0) {
|
|
33470
33474
|
return kitCfg.sourceDir;
|
|
@@ -33483,7 +33487,7 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
33483
33487
|
};
|
|
33484
33488
|
}
|
|
33485
33489
|
const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
|
|
33486
|
-
const sourceRoot =
|
|
33490
|
+
const sourceRoot = join90(candidateRoot, sourceDir);
|
|
33487
33491
|
const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
|
|
33488
33492
|
if (nestedMetadata) {
|
|
33489
33493
|
return {
|
|
@@ -33496,7 +33500,7 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
33496
33500
|
return null;
|
|
33497
33501
|
}
|
|
33498
33502
|
function walkUpForMetadata(startDir, maxDepth = 5) {
|
|
33499
|
-
let current =
|
|
33503
|
+
let current = resolve20(startDir);
|
|
33500
33504
|
for (let i = 0;i < maxDepth; i++) {
|
|
33501
33505
|
const result = tryReadAtCandidate(current);
|
|
33502
33506
|
if (result)
|
|
@@ -33517,7 +33521,7 @@ function resolveMonorepoRoot() {
|
|
|
33517
33521
|
return result2;
|
|
33518
33522
|
} catch {}
|
|
33519
33523
|
if (process.argv[1]) {
|
|
33520
|
-
const binDir = dirname23(
|
|
33524
|
+
const binDir = dirname23(resolve20(process.argv[1]));
|
|
33521
33525
|
const result2 = walkUpForMetadata(binDir);
|
|
33522
33526
|
if (result2)
|
|
33523
33527
|
return result2;
|
|
@@ -33616,7 +33620,7 @@ async function restoreOriginalBranch(branchName, cwd2, issueNumber) {
|
|
|
33616
33620
|
}
|
|
33617
33621
|
}
|
|
33618
33622
|
function spawnAndCollect(command, args, cwd2) {
|
|
33619
|
-
return new Promise((
|
|
33623
|
+
return new Promise((resolve31, reject) => {
|
|
33620
33624
|
const child = spawn3(command, args, { ...cwd2 && { cwd: cwd2 }, stdio: ["ignore", "pipe", "pipe"] });
|
|
33621
33625
|
const chunks = [];
|
|
33622
33626
|
const stderrChunks = [];
|
|
@@ -33629,7 +33633,7 @@ function spawnAndCollect(command, args, cwd2) {
|
|
|
33629
33633
|
reject(new Error(`${command} ${args[0] ?? ""} exited with code ${code}: ${stderr}`));
|
|
33630
33634
|
return;
|
|
33631
33635
|
}
|
|
33632
|
-
|
|
33636
|
+
resolve31(Buffer.concat(chunks).toString("utf-8"));
|
|
33633
33637
|
});
|
|
33634
33638
|
});
|
|
33635
33639
|
}
|
|
@@ -33648,9 +33652,9 @@ __export(exports_worktree_manager, {
|
|
|
33648
33652
|
});
|
|
33649
33653
|
import { existsSync as existsSync53 } from "node:fs";
|
|
33650
33654
|
import { readFile as readFile44, writeFile as writeFile32 } from "node:fs/promises";
|
|
33651
|
-
import { join as
|
|
33655
|
+
import { join as join110 } from "node:path";
|
|
33652
33656
|
async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
33653
|
-
const worktreePath =
|
|
33657
|
+
const worktreePath = join110(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
33654
33658
|
const branchName = `sk-watch/issue-${issueNumber}`;
|
|
33655
33659
|
await spawnAndCollect("git", ["fetch", "origin", baseBranch], projectDir).catch(() => {
|
|
33656
33660
|
logger.warning(`[worktree] Could not fetch origin/${baseBranch}, using local`);
|
|
@@ -33668,7 +33672,7 @@ async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
|
33668
33672
|
return worktreePath;
|
|
33669
33673
|
}
|
|
33670
33674
|
async function removeWorktree(projectDir, issueNumber) {
|
|
33671
|
-
const worktreePath =
|
|
33675
|
+
const worktreePath = join110(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
33672
33676
|
const branchName = `sk-watch/issue-${issueNumber}`;
|
|
33673
33677
|
try {
|
|
33674
33678
|
await spawnAndCollect("git", ["worktree", "remove", worktreePath, "--force"], projectDir);
|
|
@@ -33682,7 +33686,7 @@ async function listActiveWorktrees(projectDir) {
|
|
|
33682
33686
|
try {
|
|
33683
33687
|
const output2 = await spawnAndCollect("git", ["worktree", "list", "--porcelain"], projectDir);
|
|
33684
33688
|
const issueNumbers = [];
|
|
33685
|
-
const worktreePrefix =
|
|
33689
|
+
const worktreePrefix = join110(projectDir, WORKTREE_DIR, "issue-").replace(/\\/g, "/");
|
|
33686
33690
|
for (const line of output2.split(`
|
|
33687
33691
|
`)) {
|
|
33688
33692
|
if (line.startsWith("worktree ")) {
|
|
@@ -33710,7 +33714,7 @@ async function cleanupAllWorktrees(projectDir) {
|
|
|
33710
33714
|
await spawnAndCollect("git", ["worktree", "prune"], projectDir).catch(() => {});
|
|
33711
33715
|
}
|
|
33712
33716
|
async function ensureGitignore(projectDir) {
|
|
33713
|
-
const gitignorePath =
|
|
33717
|
+
const gitignorePath = join110(projectDir, ".gitignore");
|
|
33714
33718
|
try {
|
|
33715
33719
|
const content = existsSync53(gitignorePath) ? await readFile44(gitignorePath, "utf-8") : "";
|
|
33716
33720
|
if (!content.includes(".worktrees")) {
|
|
@@ -33814,16 +33818,16 @@ var init_content_validator = __esm(() => {
|
|
|
33814
33818
|
|
|
33815
33819
|
// src/commands/content/phases/context-cache-manager.ts
|
|
33816
33820
|
import { createHash as createHash8 } from "node:crypto";
|
|
33817
|
-
import { existsSync as existsSync59, mkdirSync as
|
|
33821
|
+
import { existsSync as existsSync59, mkdirSync as mkdirSync5, readFileSync as readFileSync17, readdirSync as readdirSync10, statSync as statSync7 } from "node:fs";
|
|
33818
33822
|
import { rename as rename10, writeFile as writeFile34 } from "node:fs/promises";
|
|
33819
33823
|
import { homedir as homedir27 } from "node:os";
|
|
33820
|
-
import { basename as
|
|
33824
|
+
import { basename as basename14, join as join117 } from "node:path";
|
|
33821
33825
|
function getCachedContext(repoPath) {
|
|
33822
33826
|
const cachePath = getCacheFilePath(repoPath);
|
|
33823
33827
|
if (!existsSync59(cachePath))
|
|
33824
33828
|
return null;
|
|
33825
33829
|
try {
|
|
33826
|
-
const raw =
|
|
33830
|
+
const raw = readFileSync17(cachePath, "utf-8");
|
|
33827
33831
|
const cache2 = JSON.parse(raw);
|
|
33828
33832
|
const age = Date.now() - new Date(cache2.createdAt).getTime();
|
|
33829
33833
|
if (age >= CACHE_TTL_MS3)
|
|
@@ -33838,7 +33842,7 @@ function getCachedContext(repoPath) {
|
|
|
33838
33842
|
}
|
|
33839
33843
|
async function saveCachedContext(repoPath, cache2) {
|
|
33840
33844
|
if (!existsSync59(CACHE_DIR)) {
|
|
33841
|
-
|
|
33845
|
+
mkdirSync5(CACHE_DIR, { recursive: true });
|
|
33842
33846
|
}
|
|
33843
33847
|
const cachePath = getCacheFilePath(repoPath);
|
|
33844
33848
|
const tmpPath = `${cachePath}.tmp`;
|
|
@@ -33860,38 +33864,38 @@ function computeSourceHash(repoPath) {
|
|
|
33860
33864
|
}
|
|
33861
33865
|
function getDocSourcePaths(repoPath) {
|
|
33862
33866
|
const paths = [];
|
|
33863
|
-
const docsDir =
|
|
33867
|
+
const docsDir = join117(repoPath, "docs");
|
|
33864
33868
|
if (existsSync59(docsDir)) {
|
|
33865
33869
|
try {
|
|
33866
33870
|
const files = readdirSync10(docsDir);
|
|
33867
33871
|
for (const f4 of files) {
|
|
33868
33872
|
if (f4.endsWith(".md"))
|
|
33869
|
-
paths.push(
|
|
33873
|
+
paths.push(join117(docsDir, f4));
|
|
33870
33874
|
}
|
|
33871
33875
|
} catch {}
|
|
33872
33876
|
}
|
|
33873
|
-
const readme =
|
|
33877
|
+
const readme = join117(repoPath, "README.md");
|
|
33874
33878
|
if (existsSync59(readme))
|
|
33875
33879
|
paths.push(readme);
|
|
33876
|
-
const stylesDir =
|
|
33880
|
+
const stylesDir = join117(repoPath, "assets", "writing-styles");
|
|
33877
33881
|
if (existsSync59(stylesDir)) {
|
|
33878
33882
|
try {
|
|
33879
33883
|
const files = readdirSync10(stylesDir);
|
|
33880
33884
|
for (const f4 of files) {
|
|
33881
|
-
paths.push(
|
|
33885
|
+
paths.push(join117(stylesDir, f4));
|
|
33882
33886
|
}
|
|
33883
33887
|
} catch {}
|
|
33884
33888
|
}
|
|
33885
33889
|
return paths.sort();
|
|
33886
33890
|
}
|
|
33887
33891
|
function getCacheFilePath(repoPath) {
|
|
33888
|
-
const repoName =
|
|
33892
|
+
const repoName = basename14(repoPath).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
33889
33893
|
const pathHash = createHash8("sha256").update(repoPath).digest("hex").slice(0, 8);
|
|
33890
|
-
return
|
|
33894
|
+
return join117(CACHE_DIR, `${repoName}-${pathHash}-context-cache.json`);
|
|
33891
33895
|
}
|
|
33892
33896
|
var CACHE_DIR, CACHE_TTL_MS3;
|
|
33893
33897
|
var init_context_cache_manager = __esm(() => {
|
|
33894
|
-
CACHE_DIR =
|
|
33898
|
+
CACHE_DIR = join117(homedir27(), ".sunagentkit", "cache");
|
|
33895
33899
|
CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
|
|
33896
33900
|
});
|
|
33897
33901
|
|
|
@@ -34071,8 +34075,8 @@ function extractContentFromResponse(response) {
|
|
|
34071
34075
|
|
|
34072
34076
|
// src/commands/content/phases/docs-summarizer.ts
|
|
34073
34077
|
import { execSync as execSync5 } from "node:child_process";
|
|
34074
|
-
import { existsSync as existsSync60, readFileSync as
|
|
34075
|
-
import { join as
|
|
34078
|
+
import { existsSync as existsSync60, readFileSync as readFileSync18, readdirSync as readdirSync11 } from "node:fs";
|
|
34079
|
+
import { join as join118 } from "node:path";
|
|
34076
34080
|
async function summarizeProjectDocs(repoPath, contentLogger) {
|
|
34077
34081
|
const rawContent = collectRawDocs(repoPath);
|
|
34078
34082
|
if (rawContent.total.length < 200) {
|
|
@@ -34120,18 +34124,18 @@ function collectRawDocs(repoPath) {
|
|
|
34120
34124
|
return "";
|
|
34121
34125
|
if (totalChars >= MAX_RAW_CONTENT_CHARS)
|
|
34122
34126
|
return "";
|
|
34123
|
-
const content =
|
|
34127
|
+
const content = readFileSync18(filePath, "utf-8");
|
|
34124
34128
|
const capped = content.slice(0, Math.min(maxChars, MAX_RAW_CONTENT_CHARS - totalChars));
|
|
34125
34129
|
totalChars += capped.length;
|
|
34126
34130
|
return capped;
|
|
34127
34131
|
};
|
|
34128
34132
|
const docsContent = [];
|
|
34129
|
-
const docsDir =
|
|
34133
|
+
const docsDir = join118(repoPath, "docs");
|
|
34130
34134
|
if (existsSync60(docsDir)) {
|
|
34131
34135
|
try {
|
|
34132
34136
|
const files = readdirSync11(docsDir).filter((f4) => f4.endsWith(".md")).sort();
|
|
34133
34137
|
for (const f4 of files) {
|
|
34134
|
-
const content = readCapped(
|
|
34138
|
+
const content = readCapped(join118(docsDir, f4), 5000);
|
|
34135
34139
|
if (content) {
|
|
34136
34140
|
docsContent.push(`### ${f4}
|
|
34137
34141
|
${content}`);
|
|
@@ -34145,21 +34149,21 @@ ${content}`);
|
|
|
34145
34149
|
let brand = "";
|
|
34146
34150
|
const brandCandidates = ["docs/brand-guidelines.md", "docs/design-guidelines.md"];
|
|
34147
34151
|
for (const p2 of brandCandidates) {
|
|
34148
|
-
brand = readCapped(
|
|
34152
|
+
brand = readCapped(join118(repoPath, p2), 3000);
|
|
34149
34153
|
if (brand)
|
|
34150
34154
|
break;
|
|
34151
34155
|
}
|
|
34152
34156
|
let styles3 = "";
|
|
34153
|
-
const stylesDir =
|
|
34157
|
+
const stylesDir = join118(repoPath, "assets", "writing-styles");
|
|
34154
34158
|
if (existsSync60(stylesDir)) {
|
|
34155
34159
|
try {
|
|
34156
34160
|
const files = readdirSync11(stylesDir).slice(0, 3);
|
|
34157
|
-
styles3 = files.map((f4) => readCapped(
|
|
34161
|
+
styles3 = files.map((f4) => readCapped(join118(stylesDir, f4), 1000)).filter(Boolean).join(`
|
|
34158
34162
|
|
|
34159
34163
|
`);
|
|
34160
34164
|
} catch {}
|
|
34161
34165
|
}
|
|
34162
|
-
const readme = readCapped(
|
|
34166
|
+
const readme = readCapped(join118(repoPath, "README.md"), 3000);
|
|
34163
34167
|
const total = [docs, brand, styles3, readme].join(`
|
|
34164
34168
|
`);
|
|
34165
34169
|
return { docs, brand, styles: styles3, readme, total };
|
|
@@ -34344,13 +34348,13 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
|
|
|
34344
34348
|
|
|
34345
34349
|
// src/commands/content/phases/photo-generator.ts
|
|
34346
34350
|
import { execSync as execSync6 } from "node:child_process";
|
|
34347
|
-
import { existsSync as existsSync61, mkdirSync as
|
|
34351
|
+
import { existsSync as existsSync61, mkdirSync as mkdirSync6, readdirSync as readdirSync12 } from "node:fs";
|
|
34348
34352
|
import { homedir as homedir28 } from "node:os";
|
|
34349
|
-
import { join as
|
|
34353
|
+
import { join as join119 } from "node:path";
|
|
34350
34354
|
async function generatePhoto(_content, context, config, platform10, contentId, contentLogger) {
|
|
34351
|
-
const mediaDir =
|
|
34355
|
+
const mediaDir = join119(config.contentDir.replace(/^~/, homedir28()), "media", String(contentId));
|
|
34352
34356
|
if (!existsSync61(mediaDir)) {
|
|
34353
|
-
|
|
34357
|
+
mkdirSync6(mediaDir, { recursive: true });
|
|
34354
34358
|
}
|
|
34355
34359
|
const prompt = buildPhotoPrompt(context, platform10);
|
|
34356
34360
|
const dimensions = platform10 === "facebook" ? { width: 1200, height: 630 } : { width: 1200, height: 675 };
|
|
@@ -34373,7 +34377,7 @@ async function generatePhoto(_content, context, config, platform10, contentId, c
|
|
|
34373
34377
|
const imageFile = files.find((f4) => /\.(png|jpg|jpeg|webp)$/i.test(f4));
|
|
34374
34378
|
if (imageFile) {
|
|
34375
34379
|
const ext2 = imageFile.split(".").pop() ?? "png";
|
|
34376
|
-
return { path:
|
|
34380
|
+
return { path: join119(mediaDir, imageFile), ...dimensions, format: ext2 };
|
|
34377
34381
|
}
|
|
34378
34382
|
contentLogger.warn(`Photo generation produced no image for content ${contentId}`);
|
|
34379
34383
|
return null;
|
|
@@ -34461,9 +34465,9 @@ var init_content_creator = __esm(() => {
|
|
|
34461
34465
|
});
|
|
34462
34466
|
|
|
34463
34467
|
// src/commands/content/phases/content-logger.ts
|
|
34464
|
-
import { createWriteStream as createWriteStream5, existsSync as existsSync62, mkdirSync as
|
|
34468
|
+
import { createWriteStream as createWriteStream5, existsSync as existsSync62, mkdirSync as mkdirSync7, statSync as statSync8 } from "node:fs";
|
|
34465
34469
|
import { homedir as homedir29 } from "node:os";
|
|
34466
|
-
import { join as
|
|
34470
|
+
import { join as join120 } from "node:path";
|
|
34467
34471
|
|
|
34468
34472
|
class ContentLogger {
|
|
34469
34473
|
stream = null;
|
|
@@ -34471,12 +34475,12 @@ class ContentLogger {
|
|
|
34471
34475
|
logDir;
|
|
34472
34476
|
maxBytes;
|
|
34473
34477
|
constructor(maxBytes = 0) {
|
|
34474
|
-
this.logDir =
|
|
34478
|
+
this.logDir = join120(homedir29(), ".sunagentkit", "logs");
|
|
34475
34479
|
this.maxBytes = maxBytes;
|
|
34476
34480
|
}
|
|
34477
34481
|
init() {
|
|
34478
34482
|
if (!existsSync62(this.logDir)) {
|
|
34479
|
-
|
|
34483
|
+
mkdirSync7(this.logDir, { recursive: true });
|
|
34480
34484
|
}
|
|
34481
34485
|
this.rotateIfNeeded();
|
|
34482
34486
|
}
|
|
@@ -34503,7 +34507,7 @@ class ContentLogger {
|
|
|
34503
34507
|
}
|
|
34504
34508
|
}
|
|
34505
34509
|
getLogPath() {
|
|
34506
|
-
return
|
|
34510
|
+
return join120(this.logDir, `content-${this.getDateStr()}.log`);
|
|
34507
34511
|
}
|
|
34508
34512
|
write(level, message) {
|
|
34509
34513
|
this.rotateIfNeeded();
|
|
@@ -34520,18 +34524,18 @@ class ContentLogger {
|
|
|
34520
34524
|
if (dateStr !== this.currentDate) {
|
|
34521
34525
|
this.close();
|
|
34522
34526
|
this.currentDate = dateStr;
|
|
34523
|
-
const logPath =
|
|
34527
|
+
const logPath = join120(this.logDir, `content-${dateStr}.log`);
|
|
34524
34528
|
this.stream = createWriteStream5(logPath, { flags: "a", mode: 384 });
|
|
34525
34529
|
return;
|
|
34526
34530
|
}
|
|
34527
34531
|
if (this.maxBytes > 0 && this.stream) {
|
|
34528
|
-
const logPath =
|
|
34532
|
+
const logPath = join120(this.logDir, `content-${this.currentDate}.log`);
|
|
34529
34533
|
try {
|
|
34530
34534
|
const stat15 = statSync8(logPath);
|
|
34531
34535
|
if (stat15.size >= this.maxBytes) {
|
|
34532
34536
|
this.close();
|
|
34533
34537
|
const suffix = Date.now();
|
|
34534
|
-
const rotatedPath =
|
|
34538
|
+
const rotatedPath = join120(this.logDir, `content-${this.currentDate}-${suffix}.log`);
|
|
34535
34539
|
import("node:fs/promises").then(({ rename: rename11 }) => rename11(logPath, rotatedPath).catch(() => {}));
|
|
34536
34540
|
this.stream = createWriteStream5(logPath, { flags: "w", mode: 384 });
|
|
34537
34541
|
}
|
|
@@ -34568,7 +34572,7 @@ function openDatabase(dbPath) {
|
|
|
34568
34572
|
var init_sqlite_client = () => {};
|
|
34569
34573
|
|
|
34570
34574
|
// src/commands/content/phases/db-manager.ts
|
|
34571
|
-
import { existsSync as existsSync63, mkdirSync as
|
|
34575
|
+
import { existsSync as existsSync63, mkdirSync as mkdirSync8 } from "node:fs";
|
|
34572
34576
|
import { dirname as dirname34 } from "node:path";
|
|
34573
34577
|
function initDatabase(dbPath) {
|
|
34574
34578
|
ensureParentDir2(dbPath);
|
|
@@ -34592,7 +34596,7 @@ function runRetentionCleanup(db, retentionDays = 90) {
|
|
|
34592
34596
|
function ensureParentDir2(dbPath) {
|
|
34593
34597
|
const dir = dirname34(dbPath);
|
|
34594
34598
|
if (dir && !existsSync63(dir)) {
|
|
34595
|
-
|
|
34599
|
+
mkdirSync8(dir, { recursive: true });
|
|
34596
34600
|
}
|
|
34597
34601
|
}
|
|
34598
34602
|
function getCurrentSchemaVersion(db) {
|
|
@@ -34756,8 +34760,8 @@ function isNoiseCommit(title, author) {
|
|
|
34756
34760
|
|
|
34757
34761
|
// src/commands/content/phases/change-detector.ts
|
|
34758
34762
|
import { execSync as execSync8 } from "node:child_process";
|
|
34759
|
-
import { existsSync as existsSync64, readFileSync as
|
|
34760
|
-
import { join as
|
|
34763
|
+
import { existsSync as existsSync64, readFileSync as readFileSync19, readdirSync as readdirSync13, statSync as statSync9 } from "node:fs";
|
|
34764
|
+
import { join as join121 } from "node:path";
|
|
34761
34765
|
function detectCommits(repo, since) {
|
|
34762
34766
|
try {
|
|
34763
34767
|
const fetchUrl = sshToHttps(repo.remoteUrl);
|
|
@@ -34855,7 +34859,7 @@ function detectTags(repo, since) {
|
|
|
34855
34859
|
}
|
|
34856
34860
|
}
|
|
34857
34861
|
function detectCompletedPlans(repo, since) {
|
|
34858
|
-
const plansDir =
|
|
34862
|
+
const plansDir = join121(repo.path, "plans");
|
|
34859
34863
|
if (!existsSync64(plansDir))
|
|
34860
34864
|
return [];
|
|
34861
34865
|
const sinceMs = new Date(since).getTime();
|
|
@@ -34865,14 +34869,14 @@ function detectCompletedPlans(repo, since) {
|
|
|
34865
34869
|
for (const entry of entries) {
|
|
34866
34870
|
if (!entry.isDirectory())
|
|
34867
34871
|
continue;
|
|
34868
|
-
const planFile =
|
|
34872
|
+
const planFile = join121(plansDir, entry.name, "plan.md");
|
|
34869
34873
|
if (!existsSync64(planFile))
|
|
34870
34874
|
continue;
|
|
34871
34875
|
try {
|
|
34872
34876
|
const stat15 = statSync9(planFile);
|
|
34873
34877
|
if (stat15.mtimeMs < sinceMs)
|
|
34874
34878
|
continue;
|
|
34875
|
-
const content =
|
|
34879
|
+
const content = readFileSync19(planFile, "utf-8");
|
|
34876
34880
|
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
34877
34881
|
if (!frontmatterMatch)
|
|
34878
34882
|
continue;
|
|
@@ -34943,7 +34947,7 @@ function classifyCommit(event) {
|
|
|
34943
34947
|
// src/commands/content/phases/repo-discoverer.ts
|
|
34944
34948
|
import { execSync as execSync9 } from "node:child_process";
|
|
34945
34949
|
import { readdirSync as readdirSync14 } from "node:fs";
|
|
34946
|
-
import { join as
|
|
34950
|
+
import { join as join122 } from "node:path";
|
|
34947
34951
|
function discoverRepos2(cwd2) {
|
|
34948
34952
|
const repos = [];
|
|
34949
34953
|
if (isGitRepoRoot(cwd2)) {
|
|
@@ -34956,7 +34960,7 @@ function discoverRepos2(cwd2) {
|
|
|
34956
34960
|
for (const entry of entries) {
|
|
34957
34961
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
34958
34962
|
continue;
|
|
34959
|
-
const dirPath =
|
|
34963
|
+
const dirPath = join122(cwd2, entry.name);
|
|
34960
34964
|
if (isGitRepoRoot(dirPath)) {
|
|
34961
34965
|
const info = getRepoInfo(dirPath);
|
|
34962
34966
|
if (info)
|
|
@@ -35623,9 +35627,9 @@ var init_types3 = __esm(() => {
|
|
|
35623
35627
|
|
|
35624
35628
|
// src/commands/content/phases/state-manager.ts
|
|
35625
35629
|
import { readFile as readFile46, rename as rename11, writeFile as writeFile35 } from "node:fs/promises";
|
|
35626
|
-
import { join as
|
|
35630
|
+
import { join as join123 } from "node:path";
|
|
35627
35631
|
async function loadContentConfig(projectDir) {
|
|
35628
|
-
const configPath =
|
|
35632
|
+
const configPath = join123(projectDir, TAKUMI_CONFIG_FILE2);
|
|
35629
35633
|
try {
|
|
35630
35634
|
const raw = await readFile46(configPath, "utf-8");
|
|
35631
35635
|
const json = JSON.parse(raw);
|
|
@@ -35635,13 +35639,13 @@ async function loadContentConfig(projectDir) {
|
|
|
35635
35639
|
}
|
|
35636
35640
|
}
|
|
35637
35641
|
async function saveContentConfig(projectDir, config) {
|
|
35638
|
-
const configPath =
|
|
35642
|
+
const configPath = join123(projectDir, TAKUMI_CONFIG_FILE2);
|
|
35639
35643
|
const json = await readJsonSafe(configPath);
|
|
35640
35644
|
json.content = { ...json.content, ...config };
|
|
35641
35645
|
await atomicWrite2(configPath, json);
|
|
35642
35646
|
}
|
|
35643
35647
|
async function loadContentState(projectDir) {
|
|
35644
|
-
const configPath =
|
|
35648
|
+
const configPath = join123(projectDir, TAKUMI_CONFIG_FILE2);
|
|
35645
35649
|
try {
|
|
35646
35650
|
const raw = await readFile46(configPath, "utf-8");
|
|
35647
35651
|
const json = JSON.parse(raw);
|
|
@@ -35652,7 +35656,7 @@ async function loadContentState(projectDir) {
|
|
|
35652
35656
|
}
|
|
35653
35657
|
}
|
|
35654
35658
|
async function saveContentState(projectDir, state) {
|
|
35655
|
-
const configPath =
|
|
35659
|
+
const configPath = join123(projectDir, TAKUMI_CONFIG_FILE2);
|
|
35656
35660
|
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
35657
35661
|
for (const key of Object.keys(state.dailyPostCounts)) {
|
|
35658
35662
|
const dateStr = key.slice(-10);
|
|
@@ -35934,7 +35938,7 @@ var init_platform_setup_x = __esm(() => {
|
|
|
35934
35938
|
|
|
35935
35939
|
// src/commands/content/phases/setup-wizard.ts
|
|
35936
35940
|
import { existsSync as existsSync65 } from "node:fs";
|
|
35937
|
-
import { join as
|
|
35941
|
+
import { join as join124 } from "node:path";
|
|
35938
35942
|
async function runSetupWizard2(cwd2, contentLogger) {
|
|
35939
35943
|
console.log();
|
|
35940
35944
|
oe(import_picocolors34.default.bgCyan(import_picocolors34.default.white(" SK Content — Multi-Channel Content Engine ")));
|
|
@@ -36002,8 +36006,8 @@ async function showRepoSummary(cwd2) {
|
|
|
36002
36006
|
function detectBrandAssets(cwd2, contentLogger) {
|
|
36003
36007
|
const repos = discoverRepos2(cwd2);
|
|
36004
36008
|
for (const repo of repos) {
|
|
36005
|
-
const hasGuidelines = existsSync65(
|
|
36006
|
-
const hasStyles = existsSync65(
|
|
36009
|
+
const hasGuidelines = existsSync65(join124(repo.path, "docs", "brand-guidelines.md"));
|
|
36010
|
+
const hasStyles = existsSync65(join124(repo.path, "assets", "writing-styles"));
|
|
36007
36011
|
if (!hasGuidelines) {
|
|
36008
36012
|
f2.warning(`${repo.name}: No docs/brand-guidelines.md — content will use generic tone.`);
|
|
36009
36013
|
contentLogger.warn(`${repo.name}: missing docs/brand-guidelines.md`);
|
|
@@ -36143,25 +36147,25 @@ __export(exports_content_subcommands, {
|
|
|
36143
36147
|
logsContent: () => logsContent,
|
|
36144
36148
|
approveContentCmd: () => approveContentCmd
|
|
36145
36149
|
});
|
|
36146
|
-
import { existsSync as existsSync67, readFileSync as
|
|
36150
|
+
import { existsSync as existsSync67, readFileSync as readFileSync20, unlinkSync as unlinkSync7 } from "node:fs";
|
|
36147
36151
|
import { homedir as homedir31 } from "node:os";
|
|
36148
|
-
import { join as
|
|
36152
|
+
import { join as join125 } from "node:path";
|
|
36149
36153
|
function isDaemonRunning() {
|
|
36150
|
-
const lockFile =
|
|
36154
|
+
const lockFile = join125(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
36151
36155
|
if (!existsSync67(lockFile))
|
|
36152
36156
|
return { running: false, pid: null };
|
|
36153
36157
|
try {
|
|
36154
|
-
const pidStr =
|
|
36158
|
+
const pidStr = readFileSync20(lockFile, "utf-8").trim();
|
|
36155
36159
|
const pid = Number.parseInt(pidStr, 10);
|
|
36156
36160
|
if (Number.isNaN(pid)) {
|
|
36157
|
-
|
|
36161
|
+
unlinkSync7(lockFile);
|
|
36158
36162
|
return { running: false, pid: null };
|
|
36159
36163
|
}
|
|
36160
36164
|
process.kill(pid, 0);
|
|
36161
36165
|
return { running: true, pid };
|
|
36162
36166
|
} catch {
|
|
36163
36167
|
try {
|
|
36164
|
-
|
|
36168
|
+
unlinkSync7(lockFile);
|
|
36165
36169
|
} catch {}
|
|
36166
36170
|
return { running: false, pid: null };
|
|
36167
36171
|
}
|
|
@@ -36179,13 +36183,13 @@ async function startContent(options2) {
|
|
|
36179
36183
|
await contentCommand(options2);
|
|
36180
36184
|
}
|
|
36181
36185
|
async function stopContent() {
|
|
36182
|
-
const lockFile =
|
|
36186
|
+
const lockFile = join125(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
36183
36187
|
if (!existsSync67(lockFile)) {
|
|
36184
36188
|
logger.info("Content daemon is not running.");
|
|
36185
36189
|
return;
|
|
36186
36190
|
}
|
|
36187
36191
|
try {
|
|
36188
|
-
const pidStr =
|
|
36192
|
+
const pidStr = readFileSync20(lockFile, "utf-8").trim();
|
|
36189
36193
|
const pid = Number.parseInt(pidStr, 10);
|
|
36190
36194
|
if (!Number.isNaN(pid)) {
|
|
36191
36195
|
process.kill(pid, "SIGTERM");
|
|
@@ -36218,9 +36222,9 @@ async function statusContent() {
|
|
|
36218
36222
|
} catch {}
|
|
36219
36223
|
}
|
|
36220
36224
|
async function logsContent(options2) {
|
|
36221
|
-
const logDir =
|
|
36225
|
+
const logDir = join125(homedir31(), ".sunagentkit", "logs");
|
|
36222
36226
|
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
36223
|
-
const logPath =
|
|
36227
|
+
const logPath = join125(logDir, `content-${dateStr}.log`);
|
|
36224
36228
|
if (!existsSync67(logPath)) {
|
|
36225
36229
|
logger.info("No content logs found for today.");
|
|
36226
36230
|
return;
|
|
@@ -36233,7 +36237,7 @@ async function logsContent(options2) {
|
|
|
36233
36237
|
process.exit(0);
|
|
36234
36238
|
});
|
|
36235
36239
|
} else {
|
|
36236
|
-
const content =
|
|
36240
|
+
const content = readFileSync20(logPath, "utf-8");
|
|
36237
36241
|
console.log(content);
|
|
36238
36242
|
}
|
|
36239
36243
|
}
|
|
@@ -36252,13 +36256,13 @@ var init_content_subcommands = __esm(() => {
|
|
|
36252
36256
|
init_setup_wizard();
|
|
36253
36257
|
init_state_manager();
|
|
36254
36258
|
init_content_review_commands();
|
|
36255
|
-
LOCK_DIR =
|
|
36259
|
+
LOCK_DIR = join125(homedir31(), ".sunagentkit", "locks");
|
|
36256
36260
|
});
|
|
36257
36261
|
|
|
36258
36262
|
// src/commands/content/content-command.ts
|
|
36259
|
-
import { existsSync as existsSync68, mkdirSync as
|
|
36263
|
+
import { existsSync as existsSync68, mkdirSync as mkdirSync9, unlinkSync as unlinkSync8, writeFileSync as writeFileSync8 } from "node:fs";
|
|
36260
36264
|
import { homedir as homedir32 } from "node:os";
|
|
36261
|
-
import { join as
|
|
36265
|
+
import { join as join126 } from "node:path";
|
|
36262
36266
|
async function contentCommand(options2) {
|
|
36263
36267
|
const cwd2 = process.cwd();
|
|
36264
36268
|
const contentLogger = new ContentLogger;
|
|
@@ -36288,8 +36292,8 @@ async function contentCommand(options2) {
|
|
|
36288
36292
|
contentLogger.info("Setup complete. Starting daemon...");
|
|
36289
36293
|
}
|
|
36290
36294
|
if (!existsSync68(LOCK_DIR2))
|
|
36291
|
-
|
|
36292
|
-
|
|
36295
|
+
mkdirSync9(LOCK_DIR2, { recursive: true });
|
|
36296
|
+
writeFileSync8(LOCK_FILE, String(process.pid), "utf-8");
|
|
36293
36297
|
const dbPath = config.dbPath.replace(/^~/, homedir32());
|
|
36294
36298
|
const db = initDatabase(dbPath);
|
|
36295
36299
|
contentLogger.info(`Database initialised at ${dbPath}`);
|
|
@@ -36304,7 +36308,7 @@ async function contentCommand(options2) {
|
|
|
36304
36308
|
abortRequested = true;
|
|
36305
36309
|
contentLogger.info("Shutting down gracefully...");
|
|
36306
36310
|
try {
|
|
36307
|
-
|
|
36311
|
+
unlinkSync8(LOCK_FILE);
|
|
36308
36312
|
} catch {}
|
|
36309
36313
|
await saveContentState(cwd2, state);
|
|
36310
36314
|
closeDatabase(db);
|
|
@@ -36334,7 +36338,7 @@ async function contentCommand(options2) {
|
|
|
36334
36338
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36335
36339
|
contentLogger.error(`Fatal error: ${msg}`);
|
|
36336
36340
|
try {
|
|
36337
|
-
|
|
36341
|
+
unlinkSync8(LOCK_FILE);
|
|
36338
36342
|
} catch {}
|
|
36339
36343
|
contentLogger.close();
|
|
36340
36344
|
process.exit(1);
|
|
@@ -36419,8 +36423,8 @@ function shouldRunCleanup(lastAt) {
|
|
|
36419
36423
|
return Date.now() - new Date(lastAt).getTime() >= 86400000;
|
|
36420
36424
|
}
|
|
36421
36425
|
function sleep3(ms2) {
|
|
36422
|
-
return new Promise((
|
|
36423
|
-
setTimeout(
|
|
36426
|
+
return new Promise((resolve31) => {
|
|
36427
|
+
setTimeout(resolve31, ms2);
|
|
36424
36428
|
});
|
|
36425
36429
|
}
|
|
36426
36430
|
var LOCK_DIR2, LOCK_FILE, MAX_CREATION_RETRIES = 3, MAX_PUBLISH_RETRIES_PER_CYCLE = 3, PUBLISH_RETRY_WINDOW_HOURS = 24;
|
|
@@ -36436,8 +36440,8 @@ var init_content_command = __esm(() => {
|
|
|
36436
36440
|
init_publisher();
|
|
36437
36441
|
init_review_manager();
|
|
36438
36442
|
init_state_manager();
|
|
36439
|
-
LOCK_DIR2 =
|
|
36440
|
-
LOCK_FILE =
|
|
36443
|
+
LOCK_DIR2 = join126(homedir32(), ".sunagentkit", "locks");
|
|
36444
|
+
LOCK_FILE = join126(LOCK_DIR2, "sk-content.lock");
|
|
36441
36445
|
});
|
|
36442
36446
|
|
|
36443
36447
|
// src/commands/content/index.ts
|
|
@@ -36583,8 +36587,8 @@ var init_new_command_help = __esm(() => {
|
|
|
36583
36587
|
usage: "tkm new [options]",
|
|
36584
36588
|
examples: [
|
|
36585
36589
|
{
|
|
36586
|
-
command: "tkm new --kit
|
|
36587
|
-
description: "Create
|
|
36590
|
+
command: "tkm new --kit core --dir ./my-project",
|
|
36591
|
+
description: "Create core kit project in specific directory"
|
|
36588
36592
|
},
|
|
36589
36593
|
{
|
|
36590
36594
|
command: "tkm new -y --use-git --release v2.1.0",
|
|
@@ -36619,7 +36623,7 @@ var init_new_command_help = __esm(() => {
|
|
|
36619
36623
|
},
|
|
36620
36624
|
{
|
|
36621
36625
|
flags: "--kit <kit>",
|
|
36622
|
-
description: "Kit to use (
|
|
36626
|
+
description: "Kit to use (core, extras)"
|
|
36623
36627
|
},
|
|
36624
36628
|
{
|
|
36625
36629
|
flags: "-r, --release <version>",
|
|
@@ -36672,8 +36676,8 @@ var init_init_command_help = __esm(() => {
|
|
|
36672
36676
|
usage: "tkm init [options]",
|
|
36673
36677
|
examples: [
|
|
36674
36678
|
{
|
|
36675
|
-
command: "tkm init --kit
|
|
36676
|
-
description: "Update local project with latest
|
|
36679
|
+
command: "tkm init --kit core",
|
|
36680
|
+
description: "Update local project with latest core kit"
|
|
36677
36681
|
},
|
|
36678
36682
|
{
|
|
36679
36683
|
command: "tkm init --use-git --release v2.1.0 -y",
|
|
@@ -36686,7 +36690,7 @@ var init_init_command_help = __esm(() => {
|
|
|
36686
36690
|
options: [
|
|
36687
36691
|
{
|
|
36688
36692
|
flags: "-y, --yes",
|
|
36689
|
-
description: "Non-interactive mode with sensible defaults (kit:
|
|
36693
|
+
description: "Non-interactive mode with sensible defaults (kit: core, dir: ., version: latest)"
|
|
36690
36694
|
},
|
|
36691
36695
|
{
|
|
36692
36696
|
flags: "--use-git",
|
|
@@ -36712,7 +36716,7 @@ var init_init_command_help = __esm(() => {
|
|
|
36712
36716
|
},
|
|
36713
36717
|
{
|
|
36714
36718
|
flags: "--kit <kit>",
|
|
36715
|
-
description: "Kit to use (
|
|
36719
|
+
description: "Kit to use (core, extras)"
|
|
36716
36720
|
},
|
|
36717
36721
|
{
|
|
36718
36722
|
flags: "-r, --release <version>",
|
|
@@ -36877,7 +36881,7 @@ var init_uninstall_command_help = __esm(() => {
|
|
|
36877
36881
|
},
|
|
36878
36882
|
{
|
|
36879
36883
|
flags: "-k, --kit <type>",
|
|
36880
|
-
description: "Uninstall specific kit only (
|
|
36884
|
+
description: "Uninstall specific kit only (core, extras)"
|
|
36881
36885
|
}
|
|
36882
36886
|
]
|
|
36883
36887
|
},
|
|
@@ -36991,8 +36995,8 @@ var init_versions_command_help = __esm(() => {
|
|
|
36991
36995
|
usage: "tkm versions [options]",
|
|
36992
36996
|
examples: [
|
|
36993
36997
|
{
|
|
36994
|
-
command: "tkm versions --kit
|
|
36995
|
-
description: "Show latest 10 versions of
|
|
36998
|
+
command: "tkm versions --kit core --limit 10",
|
|
36999
|
+
description: "Show latest 10 versions of core kit"
|
|
36996
37000
|
},
|
|
36997
37001
|
{
|
|
36998
37002
|
command: "tkm versions --all",
|
|
@@ -37005,7 +37009,7 @@ var init_versions_command_help = __esm(() => {
|
|
|
37005
37009
|
options: [
|
|
37006
37010
|
{
|
|
37007
37011
|
flags: "--kit <kit>",
|
|
37008
|
-
description: "Filter by specific kit (
|
|
37012
|
+
description: "Filter by specific kit (core, extras)"
|
|
37009
37013
|
},
|
|
37010
37014
|
{
|
|
37011
37015
|
flags: "--limit <number>",
|
|
@@ -37035,7 +37039,7 @@ var init_config_command_help = __esm(() => {
|
|
|
37035
37039
|
description: "Read a config value"
|
|
37036
37040
|
},
|
|
37037
37041
|
{
|
|
37038
|
-
command: "tkm config set defaults.kit
|
|
37042
|
+
command: "tkm config set defaults.kit core",
|
|
37039
37043
|
description: "Set a config value from the CLI"
|
|
37040
37044
|
},
|
|
37041
37045
|
{
|
|
@@ -37410,7 +37414,7 @@ function getPagerArgs(pagerCmd) {
|
|
|
37410
37414
|
return [];
|
|
37411
37415
|
}
|
|
37412
37416
|
async function trySystemPager(content) {
|
|
37413
|
-
return new Promise((
|
|
37417
|
+
return new Promise((resolve31) => {
|
|
37414
37418
|
const pagerCmd = process.env.PAGER || "less";
|
|
37415
37419
|
const pagerArgs = getPagerArgs(pagerCmd);
|
|
37416
37420
|
try {
|
|
@@ -37420,20 +37424,20 @@ async function trySystemPager(content) {
|
|
|
37420
37424
|
});
|
|
37421
37425
|
const timeout = setTimeout(() => {
|
|
37422
37426
|
pager.kill();
|
|
37423
|
-
|
|
37427
|
+
resolve31(false);
|
|
37424
37428
|
}, 30000);
|
|
37425
37429
|
pager.stdin.write(content);
|
|
37426
37430
|
pager.stdin.end();
|
|
37427
37431
|
pager.on("close", (code) => {
|
|
37428
37432
|
clearTimeout(timeout);
|
|
37429
|
-
|
|
37433
|
+
resolve31(code === 0);
|
|
37430
37434
|
});
|
|
37431
37435
|
pager.on("error", () => {
|
|
37432
37436
|
clearTimeout(timeout);
|
|
37433
|
-
|
|
37437
|
+
resolve31(false);
|
|
37434
37438
|
});
|
|
37435
37439
|
} catch {
|
|
37436
|
-
|
|
37440
|
+
resolve31(false);
|
|
37437
37441
|
}
|
|
37438
37442
|
});
|
|
37439
37443
|
}
|
|
@@ -37460,16 +37464,16 @@ async function basicPager(content) {
|
|
|
37460
37464
|
break;
|
|
37461
37465
|
}
|
|
37462
37466
|
const remaining = lines.length - currentLine;
|
|
37463
|
-
await new Promise((
|
|
37467
|
+
await new Promise((resolve31) => {
|
|
37464
37468
|
rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
|
|
37465
37469
|
if (answer.toLowerCase() === "q") {
|
|
37466
37470
|
rl.close();
|
|
37467
37471
|
process.exitCode = 0;
|
|
37468
|
-
|
|
37472
|
+
resolve31();
|
|
37469
37473
|
return;
|
|
37470
37474
|
}
|
|
37471
37475
|
process.stdout.write("\x1B[1A\x1B[2K");
|
|
37472
|
-
|
|
37476
|
+
resolve31();
|
|
37473
37477
|
});
|
|
37474
37478
|
});
|
|
37475
37479
|
}
|
|
@@ -42877,7 +42881,7 @@ class SystemChecker {
|
|
|
42877
42881
|
}
|
|
42878
42882
|
}
|
|
42879
42883
|
// src/services/file-operations/takumi-scanner.ts
|
|
42880
|
-
import { join as
|
|
42884
|
+
import { join as join69 } from "node:path";
|
|
42881
42885
|
|
|
42882
42886
|
// src/domains/installers/claude-code/paths.ts
|
|
42883
42887
|
import { homedir as homedir6 } from "node:os";
|
|
@@ -42942,7 +42946,21 @@ function findManifestPathSync(providerRoot) {
|
|
|
42942
42946
|
// src/domains/migration/metadata-migration.ts
|
|
42943
42947
|
init_logger();
|
|
42944
42948
|
init_takumi_constants();
|
|
42949
|
+
init_types2();
|
|
42945
42950
|
var import_fs_extra4 = __toESM(require_lib(), 1);
|
|
42951
|
+
function renameLegacyKitsKey(metadata) {
|
|
42952
|
+
if (!metadata.kits)
|
|
42953
|
+
return metadata;
|
|
42954
|
+
const raw = metadata.kits;
|
|
42955
|
+
const { engineer: legacy, ...rest } = raw;
|
|
42956
|
+
if (legacy == null)
|
|
42957
|
+
return metadata;
|
|
42958
|
+
const nextKits = rest;
|
|
42959
|
+
if (nextKits.core == null) {
|
|
42960
|
+
nextKits.core = legacy;
|
|
42961
|
+
}
|
|
42962
|
+
return { ...metadata, kits: nextKits };
|
|
42963
|
+
}
|
|
42946
42964
|
async function detectMetadataFormat(claudeDir) {
|
|
42947
42965
|
const resolved = await findManifestPath(claudeDir);
|
|
42948
42966
|
if (!resolved) {
|
|
@@ -42955,9 +42973,9 @@ async function detectMetadataFormat(claudeDir) {
|
|
|
42955
42973
|
if (!trimmed) {
|
|
42956
42974
|
return { format: "none", metadata: null, detectedKit: null, filenameUsed: null };
|
|
42957
42975
|
}
|
|
42958
|
-
const parsed = JSON.parse(trimmed);
|
|
42976
|
+
const parsed = renameLegacyKitsKey(JSON.parse(trimmed));
|
|
42959
42977
|
if (parsed.kits && Object.keys(parsed.kits).length > 0) {
|
|
42960
|
-
const installedKits = Object.keys(parsed.kits);
|
|
42978
|
+
const installedKits = Object.keys(parsed.kits).filter(isValidKitType);
|
|
42961
42979
|
return {
|
|
42962
42980
|
format: "multi-kit",
|
|
42963
42981
|
metadata: parsed,
|
|
@@ -42966,12 +42984,12 @@ async function detectMetadataFormat(claudeDir) {
|
|
|
42966
42984
|
};
|
|
42967
42985
|
}
|
|
42968
42986
|
if (parsed.name || parsed.version || parsed.files) {
|
|
42969
|
-
let detectedKit = "
|
|
42987
|
+
let detectedKit = "core";
|
|
42970
42988
|
const nameToCheck = parsed.name || "";
|
|
42971
42989
|
if (/\bextras\b/i.test(nameToCheck)) {
|
|
42972
42990
|
detectedKit = "extras";
|
|
42973
42991
|
} else if (/\bengineer\b/i.test(nameToCheck)) {
|
|
42974
|
-
detectedKit = "
|
|
42992
|
+
detectedKit = "core";
|
|
42975
42993
|
}
|
|
42976
42994
|
return { format: "legacy", metadata: parsed, detectedKit, filenameUsed };
|
|
42977
42995
|
}
|
|
@@ -43011,7 +43029,7 @@ async function migrateToMultiKit(claudeDir) {
|
|
|
43011
43029
|
error: "Metadata exists but could not be read"
|
|
43012
43030
|
};
|
|
43013
43031
|
}
|
|
43014
|
-
const legacyKit = detection.detectedKit || "
|
|
43032
|
+
const legacyKit = detection.detectedKit || "core";
|
|
43015
43033
|
try {
|
|
43016
43034
|
const kitMetadata = {
|
|
43017
43035
|
version: legacy.version || "unknown",
|
|
@@ -43101,18 +43119,19 @@ function getTrackedFilesForKit(metadata, kitType) {
|
|
|
43101
43119
|
}
|
|
43102
43120
|
function getInstalledKits(metadata) {
|
|
43103
43121
|
if (metadata.kits) {
|
|
43104
|
-
|
|
43122
|
+
const migrated = renameLegacyKitsKey(metadata);
|
|
43123
|
+
return Object.keys(migrated.kits ?? {}).filter(isValidKitType);
|
|
43105
43124
|
}
|
|
43106
43125
|
const nameToCheck = metadata.name || "";
|
|
43107
43126
|
const kits = [];
|
|
43108
43127
|
if (/\bengineer\b/i.test(nameToCheck)) {
|
|
43109
|
-
kits.push("
|
|
43128
|
+
kits.push("core");
|
|
43110
43129
|
}
|
|
43111
43130
|
if (kits.length > 0) {
|
|
43112
43131
|
return kits;
|
|
43113
43132
|
}
|
|
43114
43133
|
if (metadata.version) {
|
|
43115
|
-
return ["
|
|
43134
|
+
return ["core"];
|
|
43116
43135
|
}
|
|
43117
43136
|
return [];
|
|
43118
43137
|
}
|
|
@@ -43130,7 +43149,7 @@ async function readManifest(providerRoot) {
|
|
|
43130
43149
|
try {
|
|
43131
43150
|
const content = await import_fs_extra5.readFile(resolved.path, "utf-8");
|
|
43132
43151
|
const parsed = JSON.parse(content);
|
|
43133
|
-
return MetadataSchema.parse(parsed);
|
|
43152
|
+
return renameLegacyKitsKey(MetadataSchema.parse(parsed));
|
|
43134
43153
|
} catch (error) {
|
|
43135
43154
|
logger.debug(`Failed to read manifest: ${error}`);
|
|
43136
43155
|
return null;
|
|
@@ -43557,7 +43576,7 @@ async function reconcileCoexistingLegacy(legacyPath, canonicalPath) {
|
|
|
43557
43576
|
async function writeManifest(providerRoot, kitName, version3, scope, kitType, trackedFiles, userConfigFiles) {
|
|
43558
43577
|
await migrateLegacyManifestFilename(providerRoot);
|
|
43559
43578
|
const metadataPath = getManifestPath(providerRoot);
|
|
43560
|
-
const kit = kitType || "
|
|
43579
|
+
const kit = kitType || "core";
|
|
43561
43580
|
await import_fs_extra6.ensureFile(metadataPath);
|
|
43562
43581
|
let release = null;
|
|
43563
43582
|
try {
|
|
@@ -43576,7 +43595,7 @@ async function writeManifest(providerRoot, kitName, version3, scope, kitType, tr
|
|
|
43576
43595
|
const content = await import_fs_extra6.readFile(metadataPath, "utf-8");
|
|
43577
43596
|
const parsed = JSON.parse(content);
|
|
43578
43597
|
if (parsed && typeof parsed === "object" && Object.keys(parsed).length > 0) {
|
|
43579
|
-
existingMetadata = parsed;
|
|
43598
|
+
existingMetadata = renameLegacyKitsKey(parsed);
|
|
43580
43599
|
}
|
|
43581
43600
|
} catch (error) {
|
|
43582
43601
|
logger.debug(`Could not read existing metadata: ${error}`);
|
|
@@ -47692,7 +47711,7 @@ function logCleanupSummary(deletedCount, preservedCount, dryRun, results) {
|
|
|
47692
47711
|
|
|
47693
47712
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
47694
47713
|
var KIT_PREFIX_MAP = {
|
|
47695
|
-
tkm: "
|
|
47714
|
+
tkm: "core"
|
|
47696
47715
|
};
|
|
47697
47716
|
function createKitSpecificMetadata(metadata, kitType) {
|
|
47698
47717
|
if (metadata.kits?.[kitType]) {
|
|
@@ -49887,7 +49906,7 @@ var claudeCodeInstaller = {
|
|
|
49887
49906
|
import { existsSync as existsSync31 } from "node:fs";
|
|
49888
49907
|
import { rm as rm6 } from "node:fs/promises";
|
|
49889
49908
|
import { homedir as homedir21 } from "node:os";
|
|
49890
|
-
import { join as
|
|
49909
|
+
import { join as join68 } from "node:path";
|
|
49891
49910
|
|
|
49892
49911
|
// src/commands/portable/provider-registry.ts
|
|
49893
49912
|
import { existsSync as existsSync16, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
@@ -50666,7 +50685,7 @@ init_takumi_constants();
|
|
|
50666
50685
|
init_dist2();
|
|
50667
50686
|
|
|
50668
50687
|
// src/domains/installers/codex/install-pipeline.ts
|
|
50669
|
-
import { basename as
|
|
50688
|
+
import { basename as basename9 } from "node:path";
|
|
50670
50689
|
|
|
50671
50690
|
// src/commands/portable/conflict-resolver.ts
|
|
50672
50691
|
init_dist2();
|
|
@@ -51796,9 +51815,32 @@ function buildPlan(actions) {
|
|
|
51796
51815
|
};
|
|
51797
51816
|
}
|
|
51798
51817
|
|
|
51818
|
+
// src/domains/installers/codex/codex-env-marker.ts
|
|
51819
|
+
import { mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
51820
|
+
import { join as join49 } from "node:path";
|
|
51821
|
+
init_logger();
|
|
51822
|
+
var CODEX_ENV_MARKER = `module.exports = { agent: 'codex' };
|
|
51823
|
+
`;
|
|
51824
|
+
function writeCodexEnvMarker(global3) {
|
|
51825
|
+
try {
|
|
51826
|
+
const pathConfig = providers.codex.hooks;
|
|
51827
|
+
if (!pathConfig)
|
|
51828
|
+
return;
|
|
51829
|
+
const scopedPath = global3 ? pathConfig.globalPath : pathConfig.projectPath;
|
|
51830
|
+
if (!scopedPath)
|
|
51831
|
+
return;
|
|
51832
|
+
const targetHooksDir = global3 ? scopedPath : join49(process.cwd(), scopedPath);
|
|
51833
|
+
const libDir = join49(targetHooksDir, "lib");
|
|
51834
|
+
mkdirSync(libDir, { recursive: true });
|
|
51835
|
+
writeFileSync2(join49(libDir, "env.cjs"), CODEX_ENV_MARKER);
|
|
51836
|
+
} catch (e2) {
|
|
51837
|
+
logger.debug(`[init/codex] writeCodexEnvMarker failed: ${String(e2)}`);
|
|
51838
|
+
}
|
|
51839
|
+
}
|
|
51840
|
+
|
|
51799
51841
|
// src/domains/installers/shared/writers/install-one-file.ts
|
|
51800
51842
|
import { writeFile as writeFile18 } from "node:fs/promises";
|
|
51801
|
-
import { dirname as dirname11, join as
|
|
51843
|
+
import { dirname as dirname11, join as join51, resolve as resolve7, sep as sep4 } from "node:path";
|
|
51802
51844
|
|
|
51803
51845
|
// src/commands/portable/converters/codex-command-skill-path.ts
|
|
51804
51846
|
var COMMAND_SKILL_PREFIX = "source-command";
|
|
@@ -52711,7 +52753,7 @@ var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
|
52711
52753
|
import { existsSync as existsSync19 } from "node:fs";
|
|
52712
52754
|
import { mkdir as mkdir13, readFile as readFile21, unlink as unlink4, writeFile as writeFile17 } from "node:fs/promises";
|
|
52713
52755
|
import { homedir as homedir11 } from "node:os";
|
|
52714
|
-
import { basename as basename3, dirname as dirname10, join as
|
|
52756
|
+
import { basename as basename3, dirname as dirname10, join as join50, resolve as resolve6, sep as sep3 } from "node:path";
|
|
52715
52757
|
function isSamePath(path1, path22) {
|
|
52716
52758
|
try {
|
|
52717
52759
|
return resolve6(path1) === resolve6(path22);
|
|
@@ -52814,7 +52856,7 @@ async function ensureDir2(filePath) {
|
|
|
52814
52856
|
}
|
|
52815
52857
|
function getMergeTargetLockPath(targetPath) {
|
|
52816
52858
|
const lockName = `.${basename3(targetPath)}.sk-merge.lock`;
|
|
52817
|
-
return
|
|
52859
|
+
return join50(dirname10(targetPath), lockName);
|
|
52818
52860
|
}
|
|
52819
52861
|
async function withMergeTargetLock(targetPath, operation) {
|
|
52820
52862
|
const resolvedTargetPath = resolve6(targetPath);
|
|
@@ -52923,7 +52965,7 @@ async function installOneFile(item, provider, kind, options2) {
|
|
|
52923
52965
|
const nameWithoutExt = extIdx >= 0 ? resolvedFilename.substring(0, extIdx) : resolvedFilename;
|
|
52924
52966
|
resolvedFilename = `${nameWithoutExt.replace(/\//g, "-")}${ext2}`;
|
|
52925
52967
|
}
|
|
52926
|
-
targetPath = pathConfig.writeStrategy === "single-file" ? basePath :
|
|
52968
|
+
targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join51(basePath, resolvedFilename);
|
|
52927
52969
|
const resolvedTarget = resolve7(targetPath);
|
|
52928
52970
|
const resolvedBase = pathConfig.writeStrategy === "single-file" ? resolve7(dirname11(basePath)) : resolve7(basePath);
|
|
52929
52971
|
if (!resolvedTarget.startsWith(resolvedBase + sep4) && resolvedTarget !== resolvedBase) {
|
|
@@ -53476,7 +53518,7 @@ ${sections.join(`
|
|
|
53476
53518
|
import { existsSync as existsSync21 } from "node:fs";
|
|
53477
53519
|
import { mkdir as mkdir14, readFile as readFile23, realpath, unlink as unlink5, writeFile as writeFile20 } from "node:fs/promises";
|
|
53478
53520
|
import { homedir as homedir12 } from "node:os";
|
|
53479
|
-
import { basename as basename4, dirname as dirname12, isAbsolute, join as
|
|
53521
|
+
import { basename as basename4, dirname as dirname12, isAbsolute, join as join52, relative as relative10, resolve as resolve8 } from "node:path";
|
|
53480
53522
|
init_logger();
|
|
53481
53523
|
var import_proper_lockfile5 = __toESM(require_proper_lockfile(), 1);
|
|
53482
53524
|
var SENTINEL_START = "# --- tkm-managed-agents-start ---";
|
|
@@ -53674,7 +53716,7 @@ function mergeConfigTomlWithDiagnostics(existing, managedBlock) {
|
|
|
53674
53716
|
};
|
|
53675
53717
|
}
|
|
53676
53718
|
function getCodexLockPath(configTomlPath) {
|
|
53677
|
-
return
|
|
53719
|
+
return join52(dirname12(configTomlPath), `.${basename4(configTomlPath)}.tkm-codex.lock`);
|
|
53678
53720
|
}
|
|
53679
53721
|
async function withCodexTargetLock(configTomlPath, operation) {
|
|
53680
53722
|
const resolvedTargetPath = resolve8(configTomlPath);
|
|
@@ -53757,7 +53799,7 @@ async function installCodexToml(items, provider, kind, options2, deps) {
|
|
|
53757
53799
|
}
|
|
53758
53800
|
const boundary = options2.global ? homedir12() : process.cwd();
|
|
53759
53801
|
const agentsDir = resolve8(basePath);
|
|
53760
|
-
const configTomlPath =
|
|
53802
|
+
const configTomlPath = join52(dirname12(agentsDir), "config.toml");
|
|
53761
53803
|
if (!isPathWithinBoundary2(agentsDir, boundary)) {
|
|
53762
53804
|
return {
|
|
53763
53805
|
provider,
|
|
@@ -53848,7 +53890,7 @@ async function installCodexToml(items, provider, kind, options2, deps) {
|
|
|
53848
53890
|
continue;
|
|
53849
53891
|
}
|
|
53850
53892
|
seenSlugOwners.set(slug, item.name);
|
|
53851
|
-
const agentTomlPath =
|
|
53893
|
+
const agentTomlPath = join52(agentsDir, `${slug}.toml`);
|
|
53852
53894
|
if (process.platform === "win32" && agentTomlPath.length > MAX_WINDOWS_PATH_LENGTH) {
|
|
53853
53895
|
allWarnings.push(`Skipped ${item.name}: target path exceeds ${MAX_WINDOWS_PATH_LENGTH} characters on Windows`);
|
|
53854
53896
|
continue;
|
|
@@ -53973,7 +54015,7 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
53973
54015
|
if (!basePath)
|
|
53974
54016
|
return [];
|
|
53975
54017
|
const agentsDir = resolve8(basePath);
|
|
53976
|
-
const configTomlPath =
|
|
54018
|
+
const configTomlPath = join52(dirname12(agentsDir), "config.toml");
|
|
53977
54019
|
if (!existsSync21(configTomlPath))
|
|
53978
54020
|
return [];
|
|
53979
54021
|
try {
|
|
@@ -53984,7 +54026,7 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
53984
54026
|
if (managedEntries.size > 0) {
|
|
53985
54027
|
const validEntries = new Map;
|
|
53986
54028
|
for (const [slug, entry] of managedEntries) {
|
|
53987
|
-
const tomlPath =
|
|
54029
|
+
const tomlPath = join52(agentsDir, `${slug}.toml`);
|
|
53988
54030
|
if (existsSync21(tomlPath)) {
|
|
53989
54031
|
validEntries.set(slug, entry);
|
|
53990
54032
|
} else {
|
|
@@ -54013,7 +54055,7 @@ async function cleanupStaleCodexConfigEntries(options2) {
|
|
|
54013
54055
|
const unmanagedSlugs = extractUnmanagedAgentSlugs(analysis.unmanagedContent);
|
|
54014
54056
|
const legacyStaleSlugs = [];
|
|
54015
54057
|
for (const slug of unmanagedSlugs) {
|
|
54016
|
-
const tomlPath =
|
|
54058
|
+
const tomlPath = join52(agentsDir, `${slug}.toml`);
|
|
54017
54059
|
if (!isPathWithinBoundary2(tomlPath, agentsDir))
|
|
54018
54060
|
continue;
|
|
54019
54061
|
if (!existsSync21(tomlPath)) {
|
|
@@ -54090,7 +54132,7 @@ function installCodexHooksItems(items, options2) {
|
|
|
54090
54132
|
// src/domains/installers/shared/skill-directory-installer.ts
|
|
54091
54133
|
import { existsSync as existsSync22 } from "node:fs";
|
|
54092
54134
|
import { cp as cp3, mkdir as mkdir15, rename as rename5, rm as rm5 } from "node:fs/promises";
|
|
54093
|
-
import { join as
|
|
54135
|
+
import { join as join53, resolve as resolve9 } from "node:path";
|
|
54094
54136
|
async function installSkillDirectories(skills, targetProviders, options2) {
|
|
54095
54137
|
const results = [];
|
|
54096
54138
|
for (const provider of targetProviders) {
|
|
@@ -54118,7 +54160,7 @@ async function installSkillDirectories(skills, targetProviders, options2) {
|
|
|
54118
54160
|
continue;
|
|
54119
54161
|
}
|
|
54120
54162
|
for (const skill of skills) {
|
|
54121
|
-
const targetDir =
|
|
54163
|
+
const targetDir = join53(basePath, skill.name);
|
|
54122
54164
|
if (resolve9(skill.path) === resolve9(targetDir)) {
|
|
54123
54165
|
results.push({
|
|
54124
54166
|
provider,
|
|
@@ -54280,8 +54322,8 @@ function displayMultiInstallerSummary(results) {
|
|
|
54280
54322
|
}
|
|
54281
54323
|
|
|
54282
54324
|
// src/domains/installers/codex/post-pipeline.ts
|
|
54283
|
-
import { cpSync, existsSync as existsSync26, readdirSync as readdirSync3 } from "node:fs";
|
|
54284
|
-
import { basename as
|
|
54325
|
+
import { cpSync, existsSync as existsSync26, readFileSync as readFileSync7, readdirSync as readdirSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
54326
|
+
import { basename as basename8, dirname as dirname17, join as join59 } from "node:path";
|
|
54285
54327
|
|
|
54286
54328
|
// src/commands/portable/reconcile-registry-backfill.ts
|
|
54287
54329
|
function shouldBackfillRegistry(action) {
|
|
@@ -54308,7 +54350,7 @@ init_logger();
|
|
|
54308
54350
|
|
|
54309
54351
|
// src/domains/installers/codex/hooks-merger.ts
|
|
54310
54352
|
import { homedir as homedir15 } from "node:os";
|
|
54311
|
-
import { basename as basename6, extname as extname3, isAbsolute as isAbsolute2, join as
|
|
54353
|
+
import { basename as basename6, extname as extname3, isAbsolute as isAbsolute2, join as join57, resolve as resolve13 } from "node:path";
|
|
54312
54354
|
|
|
54313
54355
|
// src/commands/portable/hook-migration-compatibility.ts
|
|
54314
54356
|
import path6 from "node:path";
|
|
@@ -54427,9 +54469,9 @@ function dedupeWarnings(warnings) {
|
|
|
54427
54469
|
}
|
|
54428
54470
|
|
|
54429
54471
|
// src/commands/portable/hooks-settings-merger.ts
|
|
54430
|
-
import { existsSync as existsSync23, mkdirSync, renameSync, rmSync as rmSync2, writeFileSync as
|
|
54472
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync2, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
54431
54473
|
import { readFile as readFile24 } from "node:fs/promises";
|
|
54432
|
-
import { basename as basename5, dirname as dirname13, join as
|
|
54474
|
+
import { basename as basename5, dirname as dirname13, join as join54 } from "node:path";
|
|
54433
54475
|
async function inspectHooksSettings(settingsPath) {
|
|
54434
54476
|
try {
|
|
54435
54477
|
if (!existsSync23(settingsPath)) {
|
|
@@ -54463,7 +54505,7 @@ async function mergeHooksIntoSettings(targetSettingsPath, newHooks) {
|
|
|
54463
54505
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
54464
54506
|
backupPath = `${targetSettingsPath}.${timestamp}.bak`;
|
|
54465
54507
|
try {
|
|
54466
|
-
|
|
54508
|
+
writeFileSync3(backupPath, raw);
|
|
54467
54509
|
} catch {
|
|
54468
54510
|
backupPath = null;
|
|
54469
54511
|
}
|
|
@@ -54472,10 +54514,10 @@ async function mergeHooksIntoSettings(targetSettingsPath, newHooks) {
|
|
|
54472
54514
|
const merged = deduplicateMerge(existingHooks, newHooks);
|
|
54473
54515
|
existingSettings.hooks = merged;
|
|
54474
54516
|
const dir = dirname13(targetSettingsPath);
|
|
54475
|
-
|
|
54517
|
+
mkdirSync2(dir, { recursive: true });
|
|
54476
54518
|
const tempPath = `${targetSettingsPath}.tmp`;
|
|
54477
54519
|
try {
|
|
54478
|
-
|
|
54520
|
+
writeFileSync3(tempPath, JSON.stringify(existingSettings, null, 2));
|
|
54479
54521
|
renameSync(tempPath, targetSettingsPath);
|
|
54480
54522
|
} catch (err) {
|
|
54481
54523
|
rmSync2(tempPath, { force: true });
|
|
@@ -54769,7 +54811,7 @@ var import_proper_lockfile6 = __toESM(require_proper_lockfile(), 1);
|
|
|
54769
54811
|
import { existsSync as existsSync24 } from "node:fs";
|
|
54770
54812
|
import { mkdir as mkdir16, realpath as realpath2 } from "node:fs/promises";
|
|
54771
54813
|
import { homedir as homedir14 } from "node:os";
|
|
54772
|
-
import { dirname as dirname14, join as
|
|
54814
|
+
import { dirname as dirname14, join as join55, resolve as resolve10, sep as sep5 } from "node:path";
|
|
54773
54815
|
function isPathWithinBoundary3(targetPath, boundaryPath) {
|
|
54774
54816
|
const resolvedTarget = resolve10(targetPath);
|
|
54775
54817
|
const resolvedBoundary = resolve10(boundaryPath);
|
|
@@ -54788,7 +54830,7 @@ async function isCanonicalPathWithinBoundary2(targetPath, boundaryPath) {
|
|
|
54788
54830
|
return isPathWithinBoundary3(canonicalTarget, canonicalBoundary);
|
|
54789
54831
|
}
|
|
54790
54832
|
function getCodexLockPath2(targetFilePath) {
|
|
54791
|
-
return
|
|
54833
|
+
return join55(dirname14(resolve10(targetFilePath)), ".config.toml.tkm-codex.lock");
|
|
54792
54834
|
}
|
|
54793
54835
|
async function withCodexTargetLock2(targetFilePath, operation) {
|
|
54794
54836
|
const resolvedTargetPath = resolve10(targetFilePath);
|
|
@@ -54815,7 +54857,7 @@ async function withCodexTargetLock2(targetFilePath, operation) {
|
|
|
54815
54857
|
}
|
|
54816
54858
|
}
|
|
54817
54859
|
function getCodexGlobalBoundary() {
|
|
54818
|
-
return
|
|
54860
|
+
return join55(homedir14(), ".codex");
|
|
54819
54861
|
}
|
|
54820
54862
|
|
|
54821
54863
|
// src/domains/installers/codex/features-flag.ts
|
|
@@ -54986,8 +55028,8 @@ async function atomicWrite(filePath, content) {
|
|
|
54986
55028
|
|
|
54987
55029
|
// src/domains/installers/codex/hook-wrapper.ts
|
|
54988
55030
|
import { createHash as createHash7 } from "node:crypto";
|
|
54989
|
-
import { mkdirSync as
|
|
54990
|
-
import { dirname as dirname16, join as
|
|
55031
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
55032
|
+
import { dirname as dirname16, join as join56, resolve as resolve12 } from "node:path";
|
|
54991
55033
|
function wrapperFilename(originalPath) {
|
|
54992
55034
|
const abs = resolve12(originalPath);
|
|
54993
55035
|
const hash = createHash7("sha256").update(abs).digest("hex").slice(0, 8);
|
|
@@ -54999,7 +55041,7 @@ function generateCodexHookWrappers(originalPaths, wrapperDir, capabilities, time
|
|
|
54999
55041
|
const resolvedWrapperDir = resolve12(wrapperDir);
|
|
55000
55042
|
for (const originalPath of originalPaths) {
|
|
55001
55043
|
const filename = wrapperFilename(originalPath);
|
|
55002
|
-
const wrapperPath =
|
|
55044
|
+
const wrapperPath = join56(resolvedWrapperDir, filename);
|
|
55003
55045
|
if (!isPathWithinBoundary3(wrapperPath, resolvedWrapperDir)) {
|
|
55004
55046
|
results.push({
|
|
55005
55047
|
wrapperPath,
|
|
@@ -55010,11 +55052,11 @@ function generateCodexHookWrappers(originalPaths, wrapperDir, capabilities, time
|
|
|
55010
55052
|
continue;
|
|
55011
55053
|
}
|
|
55012
55054
|
try {
|
|
55013
|
-
|
|
55055
|
+
mkdirSync3(dirname16(wrapperPath), { recursive: true });
|
|
55014
55056
|
const resolvedPath = resolve12(originalPath);
|
|
55015
55057
|
const hookTimeoutMs = timeoutsByPath?.[resolvedPath] ?? timeoutsByPath?.[originalPath];
|
|
55016
55058
|
const content = buildWrapperScript(originalPath, capabilities, hookTimeoutMs);
|
|
55017
|
-
|
|
55059
|
+
writeFileSync4(wrapperPath, content, { mode: 493 });
|
|
55018
55060
|
results.push({ wrapperPath, originalPath, success: true });
|
|
55019
55061
|
} catch (err) {
|
|
55020
55062
|
results.push({
|
|
@@ -55253,8 +55295,8 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55253
55295
|
codexCapabilitiesVersion: capabilities.version
|
|
55254
55296
|
};
|
|
55255
55297
|
}
|
|
55256
|
-
const resolvedSourcePath = sourceSettingsPathOverride ? sourceSettingsPathOverride : isGlobal ? sourceSettingsPath :
|
|
55257
|
-
const resolvedTargetPath = isGlobal ? targetSettingsPath :
|
|
55298
|
+
const resolvedSourcePath = sourceSettingsPathOverride ? sourceSettingsPathOverride : isGlobal ? sourceSettingsPath : join57(process.cwd(), sourceSettingsPath);
|
|
55299
|
+
const resolvedTargetPath = isGlobal ? targetSettingsPath : join57(process.cwd(), targetSettingsPath);
|
|
55258
55300
|
const sourceHooksResult = await inspectHooksSettings(resolvedSourcePath);
|
|
55259
55301
|
if (sourceHooksResult.status === "missing-file") {
|
|
55260
55302
|
return {
|
|
@@ -55303,7 +55345,7 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55303
55345
|
if (targetHooksDir) {
|
|
55304
55346
|
const absSourceHooksDir = sourceHooksDir ? isAbsolute2(sourceHooksDir) ? sourceHooksDir : resolve13(sourceHooksDir) : "";
|
|
55305
55347
|
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 :
|
|
55348
|
+
const targetAbsolutePaths = installedHookAbsolutePaths && installedHookAbsolutePaths.length > 0 ? installedHookAbsolutePaths.filter(isCodexWrappableHookPath) : installedHookFiles.filter(isCodexWrappableHookPath).map((basenameOrPath) => basenameOrPath.includes("/") || basenameOrPath.includes("\\") ? basenameOrPath : join57(absTargetHooksDir, basenameOrPath));
|
|
55307
55349
|
const wrapperResults = generateCodexHookWrappers(targetAbsolutePaths, absTargetHooksDir, capabilities);
|
|
55308
55350
|
for (const wr of wrapperResults) {
|
|
55309
55351
|
if (!wr.success)
|
|
@@ -55312,13 +55354,13 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55312
55354
|
const base = basename6(wr.originalPath);
|
|
55313
55355
|
const addKey = (p) => commandSubstitutions.set(p, wr.wrapperPath);
|
|
55314
55356
|
addKey(wr.originalPath);
|
|
55315
|
-
addKey(
|
|
55357
|
+
addKey(join57(absTargetHooksDir, base));
|
|
55316
55358
|
if (targetHooksDir !== absTargetHooksDir)
|
|
55317
|
-
addKey(
|
|
55359
|
+
addKey(join57(targetHooksDir, base));
|
|
55318
55360
|
if (absSourceHooksDir) {
|
|
55319
|
-
addKey(
|
|
55361
|
+
addKey(join57(absSourceHooksDir, base));
|
|
55320
55362
|
if (sourceHooksDir !== absSourceHooksDir)
|
|
55321
|
-
addKey(
|
|
55363
|
+
addKey(join57(sourceHooksDir, base));
|
|
55322
55364
|
}
|
|
55323
55365
|
}
|
|
55324
55366
|
}
|
|
@@ -55364,7 +55406,7 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55364
55406
|
}
|
|
55365
55407
|
let featureFlagWritten = false;
|
|
55366
55408
|
if (capabilities.requiresFeatureFlag) {
|
|
55367
|
-
const configTomlPath = isGlobal ?
|
|
55409
|
+
const configTomlPath = isGlobal ? join57(homedir15(), ".codex", "config.toml") : join57(process.cwd(), ".codex", "config.toml");
|
|
55368
55410
|
const flagResult = await ensureCodexHooksFeatureFlag(configTomlPath, isGlobal);
|
|
55369
55411
|
featureFlagWritten = flagResult.status === "written" || flagResult.status === "updated";
|
|
55370
55412
|
}
|
|
@@ -55382,6 +55424,101 @@ async function migrateCodexHooksSettings(options2) {
|
|
|
55382
55424
|
};
|
|
55383
55425
|
}
|
|
55384
55426
|
|
|
55427
|
+
// src/domains/installers/codex/prune-deleted-hooks.ts
|
|
55428
|
+
import { basename as basename7, join as join58, resolve as resolve14 } from "node:path";
|
|
55429
|
+
var WRAPPER_HASH_PREFIX = /^[0-9a-f]{8}-/;
|
|
55430
|
+
function deletionsToBasenames(deletions) {
|
|
55431
|
+
const out = [];
|
|
55432
|
+
for (const entry of deletions) {
|
|
55433
|
+
if (!entry || typeof entry !== "string")
|
|
55434
|
+
continue;
|
|
55435
|
+
if (!entry.startsWith("hooks/"))
|
|
55436
|
+
continue;
|
|
55437
|
+
if (entry.includes("*"))
|
|
55438
|
+
continue;
|
|
55439
|
+
const base = basename7(entry);
|
|
55440
|
+
if (base.endsWith(".cjs"))
|
|
55441
|
+
out.push(base);
|
|
55442
|
+
}
|
|
55443
|
+
return out;
|
|
55444
|
+
}
|
|
55445
|
+
function commandReferencesBasename(command, base) {
|
|
55446
|
+
const segments = command.split(/[\s"'`]+/).filter(Boolean);
|
|
55447
|
+
for (const tok of segments) {
|
|
55448
|
+
const tokBase = basename7(tok);
|
|
55449
|
+
if (tokBase === base)
|
|
55450
|
+
return true;
|
|
55451
|
+
if (tokBase.endsWith(base) && tokBase.length === base.length + 9 && WRAPPER_HASH_PREFIX.test(tokBase) && tokBase.slice(9) === base) {
|
|
55452
|
+
return true;
|
|
55453
|
+
}
|
|
55454
|
+
}
|
|
55455
|
+
return false;
|
|
55456
|
+
}
|
|
55457
|
+
function pruneDeletedHooks(userHooksJson, deletions, wrapperDir) {
|
|
55458
|
+
const basenames = deletionsToBasenames(deletions);
|
|
55459
|
+
const removedWrapperPaths = [];
|
|
55460
|
+
let prunedRegistrationCount = 0;
|
|
55461
|
+
if (!userHooksJson || typeof userHooksJson !== "object") {
|
|
55462
|
+
return {
|
|
55463
|
+
prunedJson: userHooksJson ?? {},
|
|
55464
|
+
removedWrapperPaths: [],
|
|
55465
|
+
prunedRegistrationCount: 0
|
|
55466
|
+
};
|
|
55467
|
+
}
|
|
55468
|
+
if (basenames.length === 0) {
|
|
55469
|
+
return {
|
|
55470
|
+
prunedJson: userHooksJson,
|
|
55471
|
+
removedWrapperPaths: [],
|
|
55472
|
+
prunedRegistrationCount: 0
|
|
55473
|
+
};
|
|
55474
|
+
}
|
|
55475
|
+
const resolvedWrapperDir = resolve14(wrapperDir);
|
|
55476
|
+
const cloned = JSON.parse(JSON.stringify(userHooksJson));
|
|
55477
|
+
const hooks = cloned.hooks ?? {};
|
|
55478
|
+
for (const eventName of Object.keys(hooks)) {
|
|
55479
|
+
const groups = hooks[eventName] ?? [];
|
|
55480
|
+
const survivingGroups = [];
|
|
55481
|
+
for (const group of groups) {
|
|
55482
|
+
const entries = group.hooks ?? [];
|
|
55483
|
+
const survivingEntries = [];
|
|
55484
|
+
for (const entry of entries) {
|
|
55485
|
+
const cmd = typeof entry.command === "string" ? entry.command : "";
|
|
55486
|
+
const matchedBase = basenames.find((b3) => commandReferencesBasename(cmd, b3));
|
|
55487
|
+
if (matchedBase) {
|
|
55488
|
+
prunedRegistrationCount += 1;
|
|
55489
|
+
const tokens = cmd.split(/[\s"'`]+/).filter(Boolean);
|
|
55490
|
+
for (const tok of tokens) {
|
|
55491
|
+
const tokBase = basename7(tok);
|
|
55492
|
+
if (tokBase === matchedBase || tokBase.endsWith(`-${matchedBase}`)) {
|
|
55493
|
+
const candidate = resolve14(join58(resolvedWrapperDir, tokBase));
|
|
55494
|
+
if (isPathWithinBoundary3(candidate, resolvedWrapperDir)) {
|
|
55495
|
+
removedWrapperPaths.push(candidate);
|
|
55496
|
+
}
|
|
55497
|
+
}
|
|
55498
|
+
}
|
|
55499
|
+
} else {
|
|
55500
|
+
survivingEntries.push(entry);
|
|
55501
|
+
}
|
|
55502
|
+
}
|
|
55503
|
+
if (survivingEntries.length > 0) {
|
|
55504
|
+
survivingGroups.push({ ...group, hooks: survivingEntries });
|
|
55505
|
+
}
|
|
55506
|
+
}
|
|
55507
|
+
if (survivingGroups.length > 0) {
|
|
55508
|
+
hooks[eventName] = survivingGroups;
|
|
55509
|
+
} else {
|
|
55510
|
+
delete hooks[eventName];
|
|
55511
|
+
}
|
|
55512
|
+
}
|
|
55513
|
+
cloned.hooks = hooks;
|
|
55514
|
+
const uniqueWrappers = Array.from(new Set(removedWrapperPaths));
|
|
55515
|
+
return {
|
|
55516
|
+
prunedJson: cloned,
|
|
55517
|
+
removedWrapperPaths: uniqueWrappers,
|
|
55518
|
+
prunedRegistrationCount
|
|
55519
|
+
};
|
|
55520
|
+
}
|
|
55521
|
+
|
|
55385
55522
|
// src/domains/installers/codex/post-pipeline.ts
|
|
55386
55523
|
var HOOK_SUPPORT_SKIP_DIRS = new Set(["__tests__", "tests", "docs"]);
|
|
55387
55524
|
function installCodexHookSupportDirs(hookItems, global3) {
|
|
@@ -55396,12 +55533,12 @@ function installCodexHookSupportDirs(hookItems, global3) {
|
|
|
55396
55533
|
const scopedPath = global3 ? pathConfig.globalPath : pathConfig.projectPath;
|
|
55397
55534
|
if (!scopedPath)
|
|
55398
55535
|
return;
|
|
55399
|
-
const targetHooksDir = global3 ? scopedPath :
|
|
55536
|
+
const targetHooksDir = global3 ? scopedPath : join59(process.cwd(), scopedPath);
|
|
55400
55537
|
for (const entry of readdirSync3(sourceHooksDir, { withFileTypes: true })) {
|
|
55401
55538
|
if (!entry.isDirectory() || HOOK_SUPPORT_SKIP_DIRS.has(entry.name))
|
|
55402
55539
|
continue;
|
|
55403
|
-
const src =
|
|
55404
|
-
const dest =
|
|
55540
|
+
const src = join59(sourceHooksDir, entry.name);
|
|
55541
|
+
const dest = join59(targetHooksDir, entry.name);
|
|
55405
55542
|
if (!existsSync26(dest)) {
|
|
55406
55543
|
cpSync(src, dest, { recursive: true });
|
|
55407
55544
|
} else {
|
|
@@ -55433,7 +55570,7 @@ function deriveKitHookSource(items) {
|
|
|
55433
55570
|
if (!kitConfigRoot)
|
|
55434
55571
|
return;
|
|
55435
55572
|
return {
|
|
55436
|
-
settingsPath:
|
|
55573
|
+
settingsPath: join59(kitConfigRoot, "settings.json"),
|
|
55437
55574
|
hooksDir: ".claude/hooks"
|
|
55438
55575
|
};
|
|
55439
55576
|
}
|
|
@@ -55442,7 +55579,7 @@ async function cleanupStaleCodexToml(global3) {
|
|
|
55442
55579
|
const staleSlugs = await cleanupStaleCodexConfigEntries({ global: global3, provider: "codex" });
|
|
55443
55580
|
if (staleSlugs.length > 0) {
|
|
55444
55581
|
const staleSet = new Set(staleSlugs.map((s) => `${s}.toml`));
|
|
55445
|
-
await removeInstallationsByFilter((i) => i.type === "agent" && i.provider === "codex" && i.global === global3 && staleSet.has(
|
|
55582
|
+
await removeInstallationsByFilter((i) => i.type === "agent" && i.provider === "codex" && i.global === global3 && staleSet.has(basename8(i.path)));
|
|
55446
55583
|
}
|
|
55447
55584
|
} catch (e2) {
|
|
55448
55585
|
logger.debug(`[init/codex] codex-toml cleanup failed: ${String(e2)}`);
|
|
@@ -55455,6 +55592,47 @@ async function healRegistryChecksums(actions, registry) {
|
|
|
55455
55592
|
logger.debug("[init/codex] backfill checksums failed");
|
|
55456
55593
|
}
|
|
55457
55594
|
}
|
|
55595
|
+
async function pruneCodexDeletedHooks(items, global3) {
|
|
55596
|
+
try {
|
|
55597
|
+
const kitRoot = items.agents[0]?.sourcePath?.split(/[/\\]agents[/\\]/)[0] ?? items.commands[0]?.sourcePath?.split(/[/\\]commands[/\\]/)[0] ?? items.hooks[0]?.sourcePath?.split(/[/\\]hooks[/\\]/)[0] ?? null;
|
|
55598
|
+
if (!kitRoot)
|
|
55599
|
+
return;
|
|
55600
|
+
const metadataPath = join59(kitRoot, "metadata.json");
|
|
55601
|
+
if (!existsSync26(metadataPath))
|
|
55602
|
+
return;
|
|
55603
|
+
const metadataRaw = readFileSync7(metadataPath, "utf-8");
|
|
55604
|
+
const metadata = JSON.parse(metadataRaw);
|
|
55605
|
+
const deletions = metadata.deletions ?? [];
|
|
55606
|
+
if (deletions.length === 0)
|
|
55607
|
+
return;
|
|
55608
|
+
const codex = providers.codex;
|
|
55609
|
+
const hooksJsonPath = global3 ? codex.settingsJsonPath?.globalPath : codex.settingsJsonPath?.projectPath ? join59(process.cwd(), codex.settingsJsonPath.projectPath) : null;
|
|
55610
|
+
if (!hooksJsonPath || !existsSync26(hooksJsonPath))
|
|
55611
|
+
return;
|
|
55612
|
+
const wrapperDir = global3 ? codex.hooks?.globalPath : codex.hooks?.projectPath ? join59(process.cwd(), codex.hooks.projectPath) : null;
|
|
55613
|
+
if (!wrapperDir)
|
|
55614
|
+
return;
|
|
55615
|
+
const userJson = JSON.parse(readFileSync7(hooksJsonPath, "utf-8"));
|
|
55616
|
+
const { prunedJson, removedWrapperPaths, prunedRegistrationCount } = pruneDeletedHooks(userJson, deletions, wrapperDir);
|
|
55617
|
+
if (prunedRegistrationCount === 0 && removedWrapperPaths.length === 0)
|
|
55618
|
+
return;
|
|
55619
|
+
if (prunedRegistrationCount > 0) {
|
|
55620
|
+
writeFileSync5(hooksJsonPath, `${JSON.stringify(prunedJson, null, 2)}
|
|
55621
|
+
`);
|
|
55622
|
+
}
|
|
55623
|
+
for (const wrapperPath of removedWrapperPaths) {
|
|
55624
|
+
try {
|
|
55625
|
+
if (existsSync26(wrapperPath))
|
|
55626
|
+
unlinkSync3(wrapperPath);
|
|
55627
|
+
} catch (e2) {
|
|
55628
|
+
logger.debug(`[init/codex] failed to unlink wrapper ${wrapperPath}: ${String(e2)}`);
|
|
55629
|
+
}
|
|
55630
|
+
}
|
|
55631
|
+
logger.debug(`[init/codex] pruned ${prunedRegistrationCount} stale hook registration(s) and ${removedWrapperPaths.length} wrapper file(s)`);
|
|
55632
|
+
} catch (e2) {
|
|
55633
|
+
logger.debug(`[init/codex] pruneCodexDeletedHooks failed: ${String(e2)}`);
|
|
55634
|
+
}
|
|
55635
|
+
}
|
|
55458
55636
|
async function bumpAppliedManifestVersion(items) {
|
|
55459
55637
|
try {
|
|
55460
55638
|
const kitRoot = items.agents[0]?.sourcePath?.split(/[/\\]agents[/\\]/)[0] ?? items.commands[0]?.sourcePath?.split(/[/\\]commands[/\\]/)[0] ?? null;
|
|
@@ -55651,12 +55829,12 @@ async function computeCodexTargetStates(global3) {
|
|
|
55651
55829
|
import { existsSync as existsSync29 } from "node:fs";
|
|
55652
55830
|
import { readFile as readFile27, readdir as readdir16 } from "node:fs/promises";
|
|
55653
55831
|
import { homedir as homedir16 } from "node:os";
|
|
55654
|
-
import { extname as extname4, join as
|
|
55832
|
+
import { extname as extname4, join as join61, relative as relative11, sep as sep6 } from "node:path";
|
|
55655
55833
|
|
|
55656
55834
|
// src/shared/kit-layout.ts
|
|
55657
55835
|
init_types2();
|
|
55658
|
-
import { existsSync as existsSync28, readFileSync as
|
|
55659
|
-
import { join as
|
|
55836
|
+
import { existsSync as existsSync28, readFileSync as readFileSync8 } from "node:fs";
|
|
55837
|
+
import { join as join60 } from "node:path";
|
|
55660
55838
|
function uniquePaths(paths) {
|
|
55661
55839
|
return [...new Set(paths)];
|
|
55662
55840
|
}
|
|
@@ -55669,12 +55847,12 @@ function findFirstExistingPath(paths) {
|
|
|
55669
55847
|
return null;
|
|
55670
55848
|
}
|
|
55671
55849
|
function resolveKitLayout(projectRoot) {
|
|
55672
|
-
const packageJsonPath =
|
|
55850
|
+
const packageJsonPath = join60(projectRoot, "package.json");
|
|
55673
55851
|
if (!existsSync28(packageJsonPath)) {
|
|
55674
55852
|
return DEFAULT_KIT_LAYOUT;
|
|
55675
55853
|
}
|
|
55676
55854
|
try {
|
|
55677
|
-
const parsed = TakumiPackageMetadataSchema.parse(JSON.parse(
|
|
55855
|
+
const parsed = TakumiPackageMetadataSchema.parse(JSON.parse(readFileSync8(packageJsonPath, "utf8")));
|
|
55678
55856
|
return KitLayoutSchema.parse({
|
|
55679
55857
|
...DEFAULT_KIT_LAYOUT,
|
|
55680
55858
|
...parsed.takumi ?? {}
|
|
@@ -55686,8 +55864,8 @@ function resolveKitLayout(projectRoot) {
|
|
|
55686
55864
|
function getProjectLayoutCandidates(projectRoot, subPath) {
|
|
55687
55865
|
const layout = resolveKitLayout(projectRoot);
|
|
55688
55866
|
return uniquePaths([
|
|
55689
|
-
|
|
55690
|
-
|
|
55867
|
+
join60(projectRoot, layout.sourceDir, subPath),
|
|
55868
|
+
join60(projectRoot, DEFAULT_KIT_LAYOUT.sourceDir, subPath)
|
|
55691
55869
|
]);
|
|
55692
55870
|
}
|
|
55693
55871
|
function findExistingProjectLayoutPath(projectRoot, subPath) {
|
|
@@ -55696,9 +55874,9 @@ function findExistingProjectLayoutPath(projectRoot, subPath) {
|
|
|
55696
55874
|
function getProjectConfigCandidates(projectRoot) {
|
|
55697
55875
|
const layout = resolveKitLayout(projectRoot);
|
|
55698
55876
|
return uniquePaths([
|
|
55699
|
-
|
|
55700
|
-
|
|
55701
|
-
|
|
55877
|
+
join60(projectRoot, "CLAUDE.md"),
|
|
55878
|
+
join60(projectRoot, layout.sourceDir, "CLAUDE.md"),
|
|
55879
|
+
join60(projectRoot, DEFAULT_KIT_LAYOUT.sourceDir, "CLAUDE.md")
|
|
55702
55880
|
]);
|
|
55703
55881
|
}
|
|
55704
55882
|
function findExistingProjectConfigPath(projectRoot) {
|
|
@@ -55712,13 +55890,13 @@ function getConfigSourcePath() {
|
|
|
55712
55890
|
return findExistingProjectConfigPath(process.cwd()) ?? getGlobalConfigSourcePath();
|
|
55713
55891
|
}
|
|
55714
55892
|
function getGlobalConfigSourcePath() {
|
|
55715
|
-
return
|
|
55893
|
+
return join61(homedir16(), ".claude", "CLAUDE.md");
|
|
55716
55894
|
}
|
|
55717
55895
|
function getRulesSourcePath() {
|
|
55718
|
-
return findExistingProjectLayoutPath(process.cwd(), "rules") ??
|
|
55896
|
+
return findExistingProjectLayoutPath(process.cwd(), "rules") ?? join61(homedir16(), ".claude", "rules");
|
|
55719
55897
|
}
|
|
55720
55898
|
function getHooksSourcePath() {
|
|
55721
|
-
return findExistingProjectLayoutPath(process.cwd(), "hooks") ??
|
|
55899
|
+
return findExistingProjectLayoutPath(process.cwd(), "hooks") ?? join61(homedir16(), ".claude", "hooks");
|
|
55722
55900
|
}
|
|
55723
55901
|
async function discoverConfig(sourcePath) {
|
|
55724
55902
|
const path7 = sourcePath ?? getConfigSourcePath();
|
|
@@ -55770,7 +55948,7 @@ async function discoverHooks(sourcePath) {
|
|
|
55770
55948
|
}
|
|
55771
55949
|
if (!HOOK_EXTENSIONS.has(ext2))
|
|
55772
55950
|
continue;
|
|
55773
|
-
const fullPath =
|
|
55951
|
+
const fullPath = join61(path7, entry.name);
|
|
55774
55952
|
try {
|
|
55775
55953
|
const content = await readFile27(fullPath, "utf-8");
|
|
55776
55954
|
items.push({
|
|
@@ -55796,7 +55974,7 @@ async function discoverPortableFiles(dir, baseDir, options2) {
|
|
|
55796
55974
|
for (const entry of entries) {
|
|
55797
55975
|
if (entry.name.startsWith("."))
|
|
55798
55976
|
continue;
|
|
55799
|
-
const fullPath =
|
|
55977
|
+
const fullPath = join61(dir, entry.name);
|
|
55800
55978
|
if (entry.isSymbolicLink()) {
|
|
55801
55979
|
continue;
|
|
55802
55980
|
}
|
|
@@ -55834,7 +56012,7 @@ async function discoverPortableFiles(dir, baseDir, options2) {
|
|
|
55834
56012
|
// src/domains/installers/shared/agents-discovery.ts
|
|
55835
56013
|
import { readdir as readdir17 } from "node:fs/promises";
|
|
55836
56014
|
import { homedir as homedir17 } from "node:os";
|
|
55837
|
-
import { join as
|
|
56015
|
+
import { join as join62 } from "node:path";
|
|
55838
56016
|
|
|
55839
56017
|
// src/commands/portable/frontmatter-parser.ts
|
|
55840
56018
|
init_logger();
|
|
@@ -55934,7 +56112,7 @@ var home3 = homedir17();
|
|
|
55934
56112
|
function getAgentSourcePath() {
|
|
55935
56113
|
return findFirstExistingPath([
|
|
55936
56114
|
...getProjectLayoutCandidates(process.cwd(), "agents"),
|
|
55937
|
-
|
|
56115
|
+
join62(home3, ".claude/agents")
|
|
55938
56116
|
]);
|
|
55939
56117
|
}
|
|
55940
56118
|
async function discoverAgents(sourcePath) {
|
|
@@ -55947,7 +56125,7 @@ async function discoverAgents(sourcePath) {
|
|
|
55947
56125
|
for (const entry of entries) {
|
|
55948
56126
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
55949
56127
|
continue;
|
|
55950
|
-
const filePath =
|
|
56128
|
+
const filePath = join62(searchPath, entry.name);
|
|
55951
56129
|
try {
|
|
55952
56130
|
const { frontmatter, body } = await parseFrontmatterFile(filePath);
|
|
55953
56131
|
const name = entry.name.replace(/\.md$/, "");
|
|
@@ -55971,14 +56149,14 @@ async function discoverAgents(sourcePath) {
|
|
|
55971
56149
|
// src/domains/installers/shared/commands-discovery.ts
|
|
55972
56150
|
import { readdir as readdir18 } from "node:fs/promises";
|
|
55973
56151
|
import { homedir as homedir18 } from "node:os";
|
|
55974
|
-
import { join as
|
|
56152
|
+
import { join as join63, relative as relative12 } from "node:path";
|
|
55975
56153
|
init_logger();
|
|
55976
56154
|
var home4 = homedir18();
|
|
55977
56155
|
var SKIP_DIRS = ["node_modules", ".git", "dist", "build"];
|
|
55978
56156
|
function getCommandSourcePath() {
|
|
55979
56157
|
return findFirstExistingPath([
|
|
55980
56158
|
...getProjectLayoutCandidates(process.cwd(), "commands"),
|
|
55981
|
-
|
|
56159
|
+
join63(home4, ".claude/commands")
|
|
55982
56160
|
]);
|
|
55983
56161
|
}
|
|
55984
56162
|
async function scanCommandDir(dir, rootDir) {
|
|
@@ -55986,7 +56164,7 @@ async function scanCommandDir(dir, rootDir) {
|
|
|
55986
56164
|
try {
|
|
55987
56165
|
const entries = await readdir18(dir, { withFileTypes: true });
|
|
55988
56166
|
for (const entry of entries) {
|
|
55989
|
-
const fullPath =
|
|
56167
|
+
const fullPath = join63(dir, entry.name);
|
|
55990
56168
|
if (entry.isDirectory()) {
|
|
55991
56169
|
if (SKIP_DIRS.includes(entry.name))
|
|
55992
56170
|
continue;
|
|
@@ -56028,23 +56206,23 @@ async function discoverCommands(sourcePath) {
|
|
|
56028
56206
|
// src/domains/installers/shared/skills-discovery.ts
|
|
56029
56207
|
import { readFile as readFile29, readdir as readdir19, stat as stat6 } from "node:fs/promises";
|
|
56030
56208
|
import { homedir as homedir19 } from "node:os";
|
|
56031
|
-
import { dirname as dirname18, join as
|
|
56209
|
+
import { dirname as dirname18, join as join64 } from "node:path";
|
|
56032
56210
|
init_logger();
|
|
56033
56211
|
var import_gray_matter4 = __toESM(require_gray_matter(), 1);
|
|
56034
56212
|
var home5 = homedir19();
|
|
56035
56213
|
var SKIP_DIRS2 = ["node_modules", ".git", "dist", "build", ".venv", "__pycache__", "common"];
|
|
56036
56214
|
function getSkillSourcePath() {
|
|
56037
|
-
const bundledRoot =
|
|
56215
|
+
const bundledRoot = join64(process.cwd(), "node_modules", "takumi-engineer");
|
|
56038
56216
|
return findFirstExistingPath([
|
|
56039
|
-
|
|
56217
|
+
join64(bundledRoot, "skills"),
|
|
56040
56218
|
...getProjectLayoutCandidates(bundledRoot, "skills"),
|
|
56041
56219
|
...getProjectLayoutCandidates(process.cwd(), "skills"),
|
|
56042
|
-
|
|
56220
|
+
join64(home5, ".claude/skills")
|
|
56043
56221
|
]);
|
|
56044
56222
|
}
|
|
56045
56223
|
async function hasSkillMd(dir) {
|
|
56046
56224
|
try {
|
|
56047
|
-
const skillPath =
|
|
56225
|
+
const skillPath = join64(dir, "SKILL.md");
|
|
56048
56226
|
const stats = await stat6(skillPath);
|
|
56049
56227
|
return stats.isFile();
|
|
56050
56228
|
} catch {
|
|
@@ -56092,9 +56270,9 @@ async function discoverSkills(sourcePath) {
|
|
|
56092
56270
|
if (!entry.isDirectory() || SKIP_DIRS2.includes(entry.name)) {
|
|
56093
56271
|
continue;
|
|
56094
56272
|
}
|
|
56095
|
-
const skillDir =
|
|
56273
|
+
const skillDir = join64(searchPath, entry.name);
|
|
56096
56274
|
if (await hasSkillMd(skillDir)) {
|
|
56097
|
-
const skill = await parseSkillMd(
|
|
56275
|
+
const skill = await parseSkillMd(join64(skillDir, "SKILL.md"));
|
|
56098
56276
|
if (skill && !seenNames.has(skill.name)) {
|
|
56099
56277
|
skills.push(skill);
|
|
56100
56278
|
seenNames.add(skill.name);
|
|
@@ -56236,7 +56414,7 @@ async function executeCodexPipeline(items, options2) {
|
|
|
56236
56414
|
results.push(...installed);
|
|
56237
56415
|
if (action.type === "hooks") {
|
|
56238
56416
|
for (const r2 of installed.filter((r3) => r3.success && !r3.skipped)) {
|
|
56239
|
-
successfulHookFiles.push(
|
|
56417
|
+
successfulHookFiles.push(basename9(r2.path));
|
|
56240
56418
|
}
|
|
56241
56419
|
}
|
|
56242
56420
|
}
|
|
@@ -56249,7 +56427,9 @@ async function executeCodexPipeline(items, options2) {
|
|
|
56249
56427
|
ui.phase("Finalizing post-install");
|
|
56250
56428
|
if (items.hooks.length > 0) {
|
|
56251
56429
|
installCodexHookSupportDirs(items.hooks, options2.global);
|
|
56430
|
+
writeCodexEnvMarker(options2.global);
|
|
56252
56431
|
}
|
|
56432
|
+
await pruneCodexDeletedHooks(items, options2.global);
|
|
56253
56433
|
await mergeInstalledHooks(successfulHookFiles, options2.global, deriveKitHookSource(items));
|
|
56254
56434
|
await cleanupStaleCodexToml(options2.global);
|
|
56255
56435
|
await healRegistryChecksums(plan.actions, registry);
|
|
@@ -56267,11 +56447,11 @@ async function executeCodexPipeline(items, options2) {
|
|
|
56267
56447
|
|
|
56268
56448
|
// src/domains/installers/codex/scan-codex-directory.ts
|
|
56269
56449
|
var import_fs_extra29 = __toESM(require_lib(), 1);
|
|
56270
|
-
import { join as
|
|
56450
|
+
import { join as join65 } from "node:path";
|
|
56271
56451
|
|
|
56272
56452
|
// src/domains/installers/codex/skills-paths.ts
|
|
56273
56453
|
import { homedir as homedir20 } from "node:os";
|
|
56274
|
-
import { resolve as
|
|
56454
|
+
import { resolve as resolve15 } from "node:path";
|
|
56275
56455
|
function getCodexSkillsTargetDir(global3) {
|
|
56276
56456
|
const cfg = providers.codex.skills;
|
|
56277
56457
|
if (!cfg) {
|
|
@@ -56281,7 +56461,7 @@ function getCodexSkillsTargetDir(global3) {
|
|
|
56281
56461
|
if (!path7) {
|
|
56282
56462
|
throw new Error(`[codex] no ${global3 ? "global" : "project"}-level skills path configured`);
|
|
56283
56463
|
}
|
|
56284
|
-
const resolved =
|
|
56464
|
+
const resolved = resolve15(path7);
|
|
56285
56465
|
const boundary = global3 ? homedir20() : process.cwd();
|
|
56286
56466
|
if (!isPathWithinBoundary3(resolved, boundary)) {
|
|
56287
56467
|
throw new Error(`[codex] resolved skills path "${resolved}" escapes boundary "${boundary}"`);
|
|
@@ -56297,11 +56477,11 @@ async function scanCodexDirectory(root, opts = {}) {
|
|
|
56297
56477
|
return counts;
|
|
56298
56478
|
const items = await import_fs_extra29.readdir(root);
|
|
56299
56479
|
if (items.includes("agents")) {
|
|
56300
|
-
const files = await import_fs_extra29.readdir(
|
|
56480
|
+
const files = await import_fs_extra29.readdir(join65(root, "agents")).catch(() => []);
|
|
56301
56481
|
counts.agents = files.filter((f3) => f3.endsWith(".toml")).length;
|
|
56302
56482
|
}
|
|
56303
56483
|
if (items.includes("prompts")) {
|
|
56304
|
-
const files = await import_fs_extra29.readdir(
|
|
56484
|
+
const files = await import_fs_extra29.readdir(join65(root, "prompts")).catch(() => []);
|
|
56305
56485
|
counts.commands = files.filter((f3) => f3.endsWith(".md")).length;
|
|
56306
56486
|
}
|
|
56307
56487
|
if (items.includes("AGENTS.md"))
|
|
@@ -56310,7 +56490,7 @@ async function scanCodexDirectory(root, opts = {}) {
|
|
|
56310
56490
|
if (await import_fs_extra29.pathExists(skillsRoot)) {
|
|
56311
56491
|
const dirs = await import_fs_extra29.readdir(skillsRoot).catch(() => []);
|
|
56312
56492
|
for (const d3 of dirs) {
|
|
56313
|
-
const skillDir =
|
|
56493
|
+
const skillDir = join65(skillsRoot, d3);
|
|
56314
56494
|
const entries = await import_fs_extra29.readdir(skillDir).catch(() => null);
|
|
56315
56495
|
if (entries?.includes("SKILL.md"))
|
|
56316
56496
|
counts.skills++;
|
|
@@ -56322,7 +56502,7 @@ async function scanCodexDirectory(root, opts = {}) {
|
|
|
56322
56502
|
|
|
56323
56503
|
// src/domains/installers/codex/source-resolver.ts
|
|
56324
56504
|
import { existsSync as existsSync30 } from "node:fs";
|
|
56325
|
-
import { join as
|
|
56505
|
+
import { join as join66 } from "node:path";
|
|
56326
56506
|
function resolveCodexSources(extractDir) {
|
|
56327
56507
|
return {
|
|
56328
56508
|
agents: findExistingProjectLayoutPath(extractDir, "agents"),
|
|
@@ -56334,7 +56514,7 @@ function resolveCodexSources(extractDir) {
|
|
|
56334
56514
|
};
|
|
56335
56515
|
}
|
|
56336
56516
|
function resolveConfigSource(extractDir) {
|
|
56337
|
-
const rootClaudeMd =
|
|
56517
|
+
const rootClaudeMd = join66(extractDir, "CLAUDE.md");
|
|
56338
56518
|
if (existsSync30(rootClaudeMd))
|
|
56339
56519
|
return rootClaudeMd;
|
|
56340
56520
|
return findExistingProjectConfigPath(extractDir);
|
|
@@ -56345,7 +56525,7 @@ function hasAnyCodexSource(sources) {
|
|
|
56345
56525
|
|
|
56346
56526
|
// src/domains/installers/codex/manifest-helpers.ts
|
|
56347
56527
|
var import_fs_extra30 = __toESM(require_lib(), 1);
|
|
56348
|
-
import { join as
|
|
56528
|
+
import { join as join67, relative as relative13, sep as sep7 } from "node:path";
|
|
56349
56529
|
var codexOwnershipResolver = () => ({ ownership: "takumi" });
|
|
56350
56530
|
async function collectCodexInstalledFiles(results, codexRoot) {
|
|
56351
56531
|
const out = [];
|
|
@@ -56369,7 +56549,7 @@ async function collectCodexInstalledFiles(results, codexRoot) {
|
|
|
56369
56549
|
async function walkDir(dir, root, out, toPosix) {
|
|
56370
56550
|
const entries = await import_fs_extra30.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
56371
56551
|
for (const e2 of entries) {
|
|
56372
|
-
const p =
|
|
56552
|
+
const p = join67(dir, e2.name);
|
|
56373
56553
|
if (e2.isDirectory()) {
|
|
56374
56554
|
await walkDir(p, root, out, toPosix);
|
|
56375
56555
|
} else if (e2.isFile()) {
|
|
@@ -56393,7 +56573,7 @@ async function writeCodexManifest(ctx, results, codexRoot, installGlobally) {
|
|
|
56393
56573
|
});
|
|
56394
56574
|
await trackFilesWithProgress(filesToTrack, {
|
|
56395
56575
|
providerRoot: codexRoot,
|
|
56396
|
-
kitName: ctx.kit?.name ?? "
|
|
56576
|
+
kitName: ctx.kit?.name ?? "Core",
|
|
56397
56577
|
releaseTag: installedVersion,
|
|
56398
56578
|
mode: installGlobally ? "global" : "local",
|
|
56399
56579
|
kitType: ctx.kitType
|
|
@@ -56406,20 +56586,20 @@ var codexInstaller = {
|
|
|
56406
56586
|
globalRoot() {
|
|
56407
56587
|
const testHome = process.env.TAKUMI_TEST_HOME;
|
|
56408
56588
|
if (testHome && testHome.trim() !== "")
|
|
56409
|
-
return
|
|
56589
|
+
return join68(testHome, ".codex");
|
|
56410
56590
|
const codexHome = process.env.CODEX_HOME;
|
|
56411
56591
|
if (codexHome && codexHome.trim() !== "" && !codexHome.includes(".."))
|
|
56412
56592
|
return codexHome;
|
|
56413
56593
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
56414
56594
|
if (xdg && xdg.trim() !== "" && !xdg.includes(".."))
|
|
56415
|
-
return
|
|
56416
|
-
return
|
|
56595
|
+
return join68(xdg, "codex");
|
|
56596
|
+
return join68(homedir21(), ".codex");
|
|
56417
56597
|
},
|
|
56418
56598
|
isInstalledGlobally() {
|
|
56419
56599
|
const root = this.globalRoot();
|
|
56420
56600
|
if (!existsSync31(root))
|
|
56421
56601
|
return false;
|
|
56422
|
-
return findManifestPathSync(root) !== null || existsSync31(
|
|
56602
|
+
return findManifestPathSync(root) !== null || existsSync31(join68(root, "AGENTS.md")) || existsSync31(join68(root, "agents")) || existsSync31(join68(root, "config.toml")) || existsSync31(join68(root, "prompts"));
|
|
56423
56603
|
},
|
|
56424
56604
|
async detectGlobalSetup() {
|
|
56425
56605
|
const root = this.globalRoot();
|
|
@@ -56531,7 +56711,7 @@ var codexInstaller = {
|
|
|
56531
56711
|
error: errMsg
|
|
56532
56712
|
};
|
|
56533
56713
|
}
|
|
56534
|
-
const codexRoot = installGlobally ? this.globalRoot() :
|
|
56714
|
+
const codexRoot = installGlobally ? this.globalRoot() : join68(ctx.resolvedDir ?? process.cwd(), ".codex");
|
|
56535
56715
|
await writeCodexManifest(ctx, results, codexRoot, installGlobally);
|
|
56536
56716
|
return {
|
|
56537
56717
|
provider: "codex",
|
|
@@ -56610,33 +56790,33 @@ async function scanTakumiDirectory(directoryPath) {
|
|
|
56610
56790
|
}
|
|
56611
56791
|
const items = await import_fs_extra31.readdir(directoryPath);
|
|
56612
56792
|
if (items.includes("agents")) {
|
|
56613
|
-
const agentsPath =
|
|
56793
|
+
const agentsPath = join69(directoryPath, "agents");
|
|
56614
56794
|
const agentFiles = await import_fs_extra31.readdir(agentsPath);
|
|
56615
56795
|
counts.agents = agentFiles.filter((file) => file.endsWith(".md")).length;
|
|
56616
56796
|
}
|
|
56617
56797
|
if (items.includes("commands")) {
|
|
56618
|
-
const commandsPath =
|
|
56798
|
+
const commandsPath = join69(directoryPath, "commands");
|
|
56619
56799
|
const commandFiles = await import_fs_extra31.readdir(commandsPath);
|
|
56620
56800
|
counts.commands = commandFiles.filter((file) => file.endsWith(".md")).length;
|
|
56621
56801
|
}
|
|
56622
56802
|
if (items.includes("rules")) {
|
|
56623
|
-
const rulesPath =
|
|
56803
|
+
const rulesPath = join69(directoryPath, "rules");
|
|
56624
56804
|
const ruleFiles = await import_fs_extra31.readdir(rulesPath);
|
|
56625
56805
|
counts.rules = ruleFiles.filter((file) => file.endsWith(".md")).length;
|
|
56626
56806
|
} else if (items.includes("workflows")) {
|
|
56627
|
-
const workflowsPath =
|
|
56807
|
+
const workflowsPath = join69(directoryPath, "workflows");
|
|
56628
56808
|
const workflowFiles = await import_fs_extra31.readdir(workflowsPath);
|
|
56629
56809
|
counts.rules = workflowFiles.filter((file) => file.endsWith(".md")).length;
|
|
56630
56810
|
}
|
|
56631
56811
|
if (items.includes("skills")) {
|
|
56632
|
-
const skillsPath =
|
|
56812
|
+
const skillsPath = join69(directoryPath, "skills");
|
|
56633
56813
|
const skillItems = await import_fs_extra31.readdir(skillsPath);
|
|
56634
56814
|
let skillCount = 0;
|
|
56635
56815
|
for (const item of skillItems) {
|
|
56636
56816
|
if (SKIP_DIRS_CLAUDE_INTERNAL.includes(item)) {
|
|
56637
56817
|
continue;
|
|
56638
56818
|
}
|
|
56639
|
-
const itemPath =
|
|
56819
|
+
const itemPath = join69(skillsPath, item);
|
|
56640
56820
|
const stat8 = await import_fs_extra31.readdir(itemPath).catch(() => null);
|
|
56641
56821
|
if (stat8?.includes("SKILL.md")) {
|
|
56642
56822
|
skillCount++;
|
|
@@ -56949,7 +57129,7 @@ init_takumi_constants();
|
|
|
56949
57129
|
import { existsSync as existsSync32, realpathSync } from "node:fs";
|
|
56950
57130
|
import { chmod as chmod2, mkdir as mkdir17, readFile as readFile31, writeFile as writeFile22 } from "node:fs/promises";
|
|
56951
57131
|
import { platform as platform5 } from "node:os";
|
|
56952
|
-
import { join as
|
|
57132
|
+
import { join as join70 } from "node:path";
|
|
56953
57133
|
var CACHE_FILE = "install-info.json";
|
|
56954
57134
|
var CACHE_TTL = 30 * 24 * 60 * 60 * 1000;
|
|
56955
57135
|
function detectFromBinaryPath() {
|
|
@@ -57033,7 +57213,7 @@ function detectFromEnv() {
|
|
|
57033
57213
|
}
|
|
57034
57214
|
async function readCachedPm() {
|
|
57035
57215
|
try {
|
|
57036
|
-
const cacheFile =
|
|
57216
|
+
const cacheFile = join70(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
57037
57217
|
if (!existsSync32(cacheFile)) {
|
|
57038
57218
|
return null;
|
|
57039
57219
|
}
|
|
@@ -57064,7 +57244,7 @@ async function saveCachedPm(pm, getVersion) {
|
|
|
57064
57244
|
return;
|
|
57065
57245
|
try {
|
|
57066
57246
|
const configDir = PathResolver.getConfigDir(false);
|
|
57067
|
-
const cacheFile =
|
|
57247
|
+
const cacheFile = join70(configDir, CACHE_FILE);
|
|
57068
57248
|
if (!existsSync32(configDir)) {
|
|
57069
57249
|
await mkdir17(configDir, { recursive: true });
|
|
57070
57250
|
if (platform5() !== "win32") {
|
|
@@ -57127,7 +57307,7 @@ async function findOwningPm() {
|
|
|
57127
57307
|
async function clearCache() {
|
|
57128
57308
|
try {
|
|
57129
57309
|
const { unlink: unlink7 } = await import("node:fs/promises");
|
|
57130
|
-
const cacheFile =
|
|
57310
|
+
const cacheFile = join70(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
57131
57311
|
if (existsSync32(cacheFile)) {
|
|
57132
57312
|
await unlink7(cacheFile);
|
|
57133
57313
|
logger.debug("Package manager cache cleared");
|
|
@@ -57387,17 +57567,17 @@ async function checkCliVersion() {
|
|
|
57387
57567
|
}
|
|
57388
57568
|
// src/domains/health-checks/checkers/claude-md-checker.ts
|
|
57389
57569
|
import { existsSync as existsSync33, statSync as statSync3 } from "node:fs";
|
|
57390
|
-
import { join as
|
|
57570
|
+
import { join as join71 } from "node:path";
|
|
57391
57571
|
function checkClaudeMd(setup, projectDir) {
|
|
57392
57572
|
const results = [];
|
|
57393
57573
|
const claudeCodeInstaller2 = getInstaller("claude-code");
|
|
57394
57574
|
if (claudeCodeInstaller2?.isInstalledGlobally()) {
|
|
57395
57575
|
const claudeGlobal = setup.globals.find((g2) => g2.provider === "claude-code") ?? setup.globals[0];
|
|
57396
57576
|
const globalPath = claudeGlobal?.path ?? claudeCodeInstaller2.globalRoot();
|
|
57397
|
-
const globalClaudeMd =
|
|
57577
|
+
const globalClaudeMd = join71(globalPath, "CLAUDE.md");
|
|
57398
57578
|
results.push(checkClaudeMdFile(globalClaudeMd, "Global CLAUDE.md", "sk-global-claude-md"));
|
|
57399
57579
|
}
|
|
57400
|
-
const projectClaudeMd =
|
|
57580
|
+
const projectClaudeMd = join71(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
57401
57581
|
results.push(checkClaudeMdFile(projectClaudeMd, "Project CLAUDE.md", "sk-project-claude-md"));
|
|
57402
57582
|
return results;
|
|
57403
57583
|
}
|
|
@@ -57455,10 +57635,10 @@ function checkClaudeMdFile(path7, name, id) {
|
|
|
57455
57635
|
}
|
|
57456
57636
|
}
|
|
57457
57637
|
// src/domains/health-checks/checkers/active-plan-checker.ts
|
|
57458
|
-
import { existsSync as existsSync34, readFileSync as
|
|
57459
|
-
import { join as
|
|
57638
|
+
import { existsSync as existsSync34, readFileSync as readFileSync9 } from "node:fs";
|
|
57639
|
+
import { join as join72 } from "node:path";
|
|
57460
57640
|
function checkActivePlan(projectDir) {
|
|
57461
|
-
const activePlanPath =
|
|
57641
|
+
const activePlanPath = join72(projectDir, ".claude", "active-plan");
|
|
57462
57642
|
if (!existsSync34(activePlanPath)) {
|
|
57463
57643
|
return {
|
|
57464
57644
|
id: "sk-active-plan",
|
|
@@ -57471,8 +57651,8 @@ function checkActivePlan(projectDir) {
|
|
|
57471
57651
|
};
|
|
57472
57652
|
}
|
|
57473
57653
|
try {
|
|
57474
|
-
const targetPath =
|
|
57475
|
-
const fullPath =
|
|
57654
|
+
const targetPath = readFileSync9(activePlanPath, "utf-8").trim();
|
|
57655
|
+
const fullPath = join72(projectDir, targetPath);
|
|
57476
57656
|
if (!existsSync34(fullPath)) {
|
|
57477
57657
|
return {
|
|
57478
57658
|
id: "sk-active-plan",
|
|
@@ -57530,13 +57710,13 @@ function checkComponentCounts(setup) {
|
|
|
57530
57710
|
priority: "standard",
|
|
57531
57711
|
status: totalComponents > 0 ? "info" : "warn",
|
|
57532
57712
|
message: totalComponents > 0 ? `${totalAgents} agents, ${totalCommands} commands, ${totalRules} rules, ${totalSkills} skills` : "No components found",
|
|
57533
|
-
suggestion: totalComponents === 0 ? "Install Takumi: takumi new --kit
|
|
57713
|
+
suggestion: totalComponents === 0 ? "Install Takumi: takumi new --kit core" : undefined,
|
|
57534
57714
|
autoFixable: false
|
|
57535
57715
|
};
|
|
57536
57716
|
}
|
|
57537
57717
|
// src/domains/health-checks/checkers/permissions-checker.ts
|
|
57538
57718
|
import { constants, access, unlink as unlink7, writeFile as writeFile23 } from "node:fs/promises";
|
|
57539
|
-
import { join as
|
|
57719
|
+
import { join as join73 } from "node:path";
|
|
57540
57720
|
init_logger();
|
|
57541
57721
|
|
|
57542
57722
|
// src/domains/health-checks/checkers/shared.ts
|
|
@@ -57611,7 +57791,7 @@ async function checkGlobalDirWritable(provider) {
|
|
|
57611
57791
|
}
|
|
57612
57792
|
const timestamp = Date.now();
|
|
57613
57793
|
const random = Math.random().toString(36).substring(2);
|
|
57614
|
-
const testFile =
|
|
57794
|
+
const testFile = join73(globalDir, `.sk-write-test-${timestamp}-${random}`);
|
|
57615
57795
|
try {
|
|
57616
57796
|
await writeFile23(testFile, "test", { encoding: "utf-8", flag: "wx" });
|
|
57617
57797
|
} catch (_error) {
|
|
@@ -57646,7 +57826,7 @@ async function checkGlobalDirWritable(provider) {
|
|
|
57646
57826
|
// src/domains/health-checks/checkers/hooks-checker.ts
|
|
57647
57827
|
import { existsSync as existsSync35 } from "node:fs";
|
|
57648
57828
|
import { readdir as readdir23 } from "node:fs/promises";
|
|
57649
|
-
import { join as
|
|
57829
|
+
import { join as join74 } from "node:path";
|
|
57650
57830
|
|
|
57651
57831
|
// src/domains/health-checks/utils/path-normalizer.ts
|
|
57652
57832
|
import { normalize as normalize5 } from "node:path";
|
|
@@ -57658,8 +57838,8 @@ function normalizePath(filePath) {
|
|
|
57658
57838
|
|
|
57659
57839
|
// src/domains/health-checks/checkers/hooks-checker.ts
|
|
57660
57840
|
async function checkHooksExist(projectDir) {
|
|
57661
|
-
const globalHooksDir =
|
|
57662
|
-
const projectHooksDir =
|
|
57841
|
+
const globalHooksDir = join74(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
|
|
57842
|
+
const projectHooksDir = join74(getLocalClaudeDir(projectDir), "hooks");
|
|
57663
57843
|
const globalExists = existsSync35(globalHooksDir);
|
|
57664
57844
|
const projectExists = existsSync35(projectHooksDir);
|
|
57665
57845
|
let hookCount = 0;
|
|
@@ -57668,7 +57848,7 @@ async function checkHooksExist(projectDir) {
|
|
|
57668
57848
|
const files = await readdir23(globalHooksDir, { withFileTypes: false });
|
|
57669
57849
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
|
|
57670
57850
|
hooks.forEach((hook) => {
|
|
57671
|
-
const fullPath =
|
|
57851
|
+
const fullPath = join74(globalHooksDir, hook);
|
|
57672
57852
|
checkedFiles.add(normalizePath(fullPath));
|
|
57673
57853
|
});
|
|
57674
57854
|
}
|
|
@@ -57678,7 +57858,7 @@ async function checkHooksExist(projectDir) {
|
|
|
57678
57858
|
const files = await readdir23(projectHooksDir, { withFileTypes: false });
|
|
57679
57859
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
|
|
57680
57860
|
hooks.forEach((hook) => {
|
|
57681
|
-
const fullPath =
|
|
57861
|
+
const fullPath = join74(projectHooksDir, hook);
|
|
57682
57862
|
checkedFiles.add(normalizePath(fullPath));
|
|
57683
57863
|
});
|
|
57684
57864
|
}
|
|
@@ -57708,11 +57888,11 @@ async function checkHooksExist(projectDir) {
|
|
|
57708
57888
|
// src/domains/health-checks/checkers/settings-checker.ts
|
|
57709
57889
|
import { existsSync as existsSync36 } from "node:fs";
|
|
57710
57890
|
import { readFile as readFile32 } from "node:fs/promises";
|
|
57711
|
-
import { join as
|
|
57891
|
+
import { join as join75 } from "node:path";
|
|
57712
57892
|
init_logger();
|
|
57713
57893
|
async function checkSettingsValid(projectDir) {
|
|
57714
|
-
const globalSettings =
|
|
57715
|
-
const projectSettings =
|
|
57894
|
+
const globalSettings = join75(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
|
|
57895
|
+
const projectSettings = join75(getLocalClaudeDir(projectDir), "settings.json");
|
|
57716
57896
|
const settingsPath = existsSync36(globalSettings) ? globalSettings : existsSync36(projectSettings) ? projectSettings : null;
|
|
57717
57897
|
if (!settingsPath) {
|
|
57718
57898
|
return {
|
|
@@ -57783,11 +57963,11 @@ async function checkSettingsValid(projectDir) {
|
|
|
57783
57963
|
import { existsSync as existsSync37 } from "node:fs";
|
|
57784
57964
|
import { readFile as readFile33 } from "node:fs/promises";
|
|
57785
57965
|
import { homedir as homedir22 } from "node:os";
|
|
57786
|
-
import { dirname as dirname19, join as
|
|
57966
|
+
import { dirname as dirname19, join as join76, normalize as normalize6, resolve as resolve16 } from "node:path";
|
|
57787
57967
|
init_logger();
|
|
57788
57968
|
async function checkPathRefsValid(projectDir) {
|
|
57789
|
-
const globalClaudeMd =
|
|
57790
|
-
const projectClaudeMd =
|
|
57969
|
+
const globalClaudeMd = join76(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
|
|
57970
|
+
const projectClaudeMd = join76(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
57791
57971
|
const claudeMdPath = existsSync37(globalClaudeMd) ? globalClaudeMd : existsSync37(projectClaudeMd) ? projectClaudeMd : null;
|
|
57792
57972
|
if (!claudeMdPath) {
|
|
57793
57973
|
return {
|
|
@@ -57831,7 +58011,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
57831
58011
|
} else if (/^[A-Za-z]:/.test(ref)) {
|
|
57832
58012
|
refPath = normalize6(ref);
|
|
57833
58013
|
} else {
|
|
57834
|
-
refPath =
|
|
58014
|
+
refPath = resolve16(baseDir, ref);
|
|
57835
58015
|
}
|
|
57836
58016
|
const normalizedPath = normalize6(refPath);
|
|
57837
58017
|
const isWithinHome = normalizedPath.startsWith(home6);
|
|
@@ -57882,7 +58062,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
57882
58062
|
// src/domains/health-checks/checkers/config-completeness-checker.ts
|
|
57883
58063
|
import { existsSync as existsSync38 } from "node:fs";
|
|
57884
58064
|
import { readdir as readdir24 } from "node:fs/promises";
|
|
57885
|
-
import { join as
|
|
58065
|
+
import { join as join77 } from "node:path";
|
|
57886
58066
|
async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
57887
58067
|
if (setup.globals.some((g2) => g2.path === setup.project.path)) {
|
|
57888
58068
|
return {
|
|
@@ -57899,12 +58079,12 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
|
57899
58079
|
const requiredDirs = ["agents", "commands", "skills"];
|
|
57900
58080
|
const missingDirs = [];
|
|
57901
58081
|
for (const dir of requiredDirs) {
|
|
57902
|
-
const dirPath =
|
|
58082
|
+
const dirPath = join77(projectClaudeDir, dir);
|
|
57903
58083
|
if (!existsSync38(dirPath)) {
|
|
57904
58084
|
missingDirs.push(dir);
|
|
57905
58085
|
}
|
|
57906
58086
|
}
|
|
57907
|
-
const hasRulesOrWorkflows = existsSync38(
|
|
58087
|
+
const hasRulesOrWorkflows = existsSync38(join77(projectClaudeDir, "rules")) || existsSync38(join77(projectClaudeDir, "workflows"));
|
|
57908
58088
|
if (!hasRulesOrWorkflows) {
|
|
57909
58089
|
missingDirs.push("rules");
|
|
57910
58090
|
}
|
|
@@ -58153,7 +58333,7 @@ function maskToken(token) {
|
|
|
58153
58333
|
class AuthChecker {
|
|
58154
58334
|
group = "auth";
|
|
58155
58335
|
kits;
|
|
58156
|
-
constructor(kits = ["
|
|
58336
|
+
constructor(kits = ["core"]) {
|
|
58157
58337
|
this.kits = kits;
|
|
58158
58338
|
}
|
|
58159
58339
|
async run() {
|
|
@@ -58341,7 +58521,7 @@ import { platform as platform7 } from "node:os";
|
|
|
58341
58521
|
// src/domains/health-checks/platform/environment-checker.ts
|
|
58342
58522
|
import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile35, unlink as unlink9, writeFile as writeFile25 } from "node:fs/promises";
|
|
58343
58523
|
import { arch as arch2, homedir as homedir23, platform as platform6 } from "node:os";
|
|
58344
|
-
import { join as
|
|
58524
|
+
import { join as join80, normalize as normalize7 } from "node:path";
|
|
58345
58525
|
init_environment();
|
|
58346
58526
|
function shouldSkipExpensiveOperations4() {
|
|
58347
58527
|
return shouldSkipExpensiveOperations();
|
|
@@ -58435,7 +58615,7 @@ async function checkGlobalDirAccess(provider) {
|
|
|
58435
58615
|
autoFixable: false
|
|
58436
58616
|
};
|
|
58437
58617
|
}
|
|
58438
|
-
const testFile =
|
|
58618
|
+
const testFile = join80(globalDir, ".sk-doctor-access-test");
|
|
58439
58619
|
try {
|
|
58440
58620
|
await mkdir19(globalDir, { recursive: true });
|
|
58441
58621
|
await writeFile25(testFile, "test", "utf-8");
|
|
@@ -58512,7 +58692,7 @@ async function checkWSLBoundary() {
|
|
|
58512
58692
|
|
|
58513
58693
|
// src/domains/health-checks/platform/windows-checker.ts
|
|
58514
58694
|
import { mkdir as mkdir20, symlink as symlink2, unlink as unlink10, writeFile as writeFile26 } from "node:fs/promises";
|
|
58515
|
-
import { join as
|
|
58695
|
+
import { join as join81 } from "node:path";
|
|
58516
58696
|
async function checkLongPathSupport() {
|
|
58517
58697
|
if (shouldSkipExpensiveOperations4()) {
|
|
58518
58698
|
return {
|
|
@@ -58564,8 +58744,8 @@ async function checkSymlinkSupport() {
|
|
|
58564
58744
|
};
|
|
58565
58745
|
}
|
|
58566
58746
|
const testDir = getInstaller("claude-code")?.globalRoot() ?? "";
|
|
58567
|
-
const target =
|
|
58568
|
-
const link =
|
|
58747
|
+
const target = join81(testDir, ".sk-symlink-test-target");
|
|
58748
|
+
const link = join81(testDir, ".sk-symlink-test-link");
|
|
58569
58749
|
try {
|
|
58570
58750
|
await mkdir20(testDir, { recursive: true });
|
|
58571
58751
|
await writeFile26(target, "test", "utf-8");
|
|
@@ -58859,9 +59039,9 @@ class AutoHealer {
|
|
|
58859
59039
|
}
|
|
58860
59040
|
// src/domains/health-checks/report-generator.ts
|
|
58861
59041
|
import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
|
|
58862
|
-
import { readFileSync as
|
|
59042
|
+
import { readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
58863
59043
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
58864
|
-
import { dirname as dirname20, join as
|
|
59044
|
+
import { dirname as dirname20, join as join82 } from "node:path";
|
|
58865
59045
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
58866
59046
|
init_environment();
|
|
58867
59047
|
init_logger();
|
|
@@ -58869,8 +59049,8 @@ init_dist2();
|
|
|
58869
59049
|
function getCliVersion3() {
|
|
58870
59050
|
try {
|
|
58871
59051
|
const __dirname3 = dirname20(fileURLToPath2(import.meta.url));
|
|
58872
|
-
const pkgPath =
|
|
58873
|
-
const pkg = JSON.parse(
|
|
59052
|
+
const pkgPath = join82(__dirname3, "../../../package.json");
|
|
59053
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
58874
59054
|
return pkg.version || "unknown";
|
|
58875
59055
|
} catch (err) {
|
|
58876
59056
|
logger.debug(`Failed to read CLI version: ${err}`);
|
|
@@ -59008,8 +59188,8 @@ class ReportGenerator {
|
|
|
59008
59188
|
return null;
|
|
59009
59189
|
}
|
|
59010
59190
|
}
|
|
59011
|
-
const tmpFile =
|
|
59012
|
-
|
|
59191
|
+
const tmpFile = join82(tmpdir2(), `sk-report-${Date.now()}.txt`);
|
|
59192
|
+
writeFileSync6(tmpFile, report);
|
|
59013
59193
|
try {
|
|
59014
59194
|
const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "Takumi Diagnostic Report"], {
|
|
59015
59195
|
encoding: "utf-8"
|
|
@@ -59025,7 +59205,7 @@ class ReportGenerator {
|
|
|
59025
59205
|
return null;
|
|
59026
59206
|
} finally {
|
|
59027
59207
|
try {
|
|
59028
|
-
|
|
59208
|
+
unlinkSync4(tmpFile);
|
|
59029
59209
|
} catch {}
|
|
59030
59210
|
}
|
|
59031
59211
|
}
|
|
@@ -59534,8 +59714,9 @@ class WorkerSource {
|
|
|
59534
59714
|
}
|
|
59535
59715
|
|
|
59536
59716
|
// src/domains/installation/release-entry-adapter.ts
|
|
59537
|
-
|
|
59538
|
-
|
|
59717
|
+
init_types2();
|
|
59718
|
+
function githubReleaseToEntry(release, kit = "core") {
|
|
59719
|
+
const expected = assetNameFor(backendIdOf(kit));
|
|
59539
59720
|
const expectedAsset = release.assets.find((a3) => a3.name === expected);
|
|
59540
59721
|
const fallback2 = release.assets[0];
|
|
59541
59722
|
const archive = expectedAsset?.name ?? fallback2?.name ?? expected;
|
|
@@ -60497,7 +60678,7 @@ init_environment();
|
|
|
60497
60678
|
init_logger();
|
|
60498
60679
|
import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
|
|
60499
60680
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
60500
|
-
import { join as
|
|
60681
|
+
import { join as join88 } from "node:path";
|
|
60501
60682
|
|
|
60502
60683
|
// src/shared/temp-cleanup.ts
|
|
60503
60684
|
init_logger();
|
|
@@ -60516,7 +60697,7 @@ init_logger();
|
|
|
60516
60697
|
init_output_manager();
|
|
60517
60698
|
import { createWriteStream as createWriteStream2, rmSync as rmSync3 } from "node:fs";
|
|
60518
60699
|
import { mkdir as mkdir21 } from "node:fs/promises";
|
|
60519
|
-
import { join as
|
|
60700
|
+
import { join as join83 } from "node:path";
|
|
60520
60701
|
|
|
60521
60702
|
// src/shared/progress-bar.ts
|
|
60522
60703
|
init_output_manager();
|
|
@@ -60681,10 +60862,10 @@ init_types2();
|
|
|
60681
60862
|
// src/domains/installation/utils/path-security.ts
|
|
60682
60863
|
init_types2();
|
|
60683
60864
|
import { lstatSync as lstatSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
60684
|
-
import { relative as relative14, resolve as
|
|
60865
|
+
import { relative as relative14, resolve as resolve17 } from "node:path";
|
|
60685
60866
|
var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
|
|
60686
60867
|
function isPathSafe(basePath, targetPath) {
|
|
60687
|
-
const resolvedBase =
|
|
60868
|
+
const resolvedBase = resolve17(basePath);
|
|
60688
60869
|
try {
|
|
60689
60870
|
const stat8 = lstatSync3(targetPath);
|
|
60690
60871
|
if (stat8.isSymbolicLink()) {
|
|
@@ -60694,7 +60875,7 @@ function isPathSafe(basePath, targetPath) {
|
|
|
60694
60875
|
}
|
|
60695
60876
|
}
|
|
60696
60877
|
} catch {}
|
|
60697
|
-
const resolvedTarget =
|
|
60878
|
+
const resolvedTarget = resolve17(targetPath);
|
|
60698
60879
|
const relativePath = relative14(resolvedBase, resolvedTarget);
|
|
60699
60880
|
return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
|
|
60700
60881
|
}
|
|
@@ -60726,7 +60907,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
|
|
|
60726
60907
|
class FileDownloader {
|
|
60727
60908
|
async downloadAsset(asset, destDir) {
|
|
60728
60909
|
try {
|
|
60729
|
-
const destPath =
|
|
60910
|
+
const destPath = join83(destDir, asset.name);
|
|
60730
60911
|
await mkdir21(destDir, { recursive: true });
|
|
60731
60912
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
60732
60913
|
logger.verbose("Download details", {
|
|
@@ -60782,7 +60963,7 @@ class FileDownloader {
|
|
|
60782
60963
|
}
|
|
60783
60964
|
if (downloadedSize !== totalSize) {
|
|
60784
60965
|
fileStream.end();
|
|
60785
|
-
await new Promise((
|
|
60966
|
+
await new Promise((resolve18) => fileStream.once("close", resolve18));
|
|
60786
60967
|
try {
|
|
60787
60968
|
rmSync3(destPath, { force: true });
|
|
60788
60969
|
} catch (cleanupError) {
|
|
@@ -60796,7 +60977,7 @@ class FileDownloader {
|
|
|
60796
60977
|
return destPath;
|
|
60797
60978
|
} catch (error) {
|
|
60798
60979
|
fileStream.end();
|
|
60799
|
-
await new Promise((
|
|
60980
|
+
await new Promise((resolve18) => fileStream.once("close", resolve18));
|
|
60800
60981
|
try {
|
|
60801
60982
|
rmSync3(destPath, { force: true });
|
|
60802
60983
|
} catch (cleanupError) {
|
|
@@ -60811,7 +60992,7 @@ class FileDownloader {
|
|
|
60811
60992
|
}
|
|
60812
60993
|
async downloadFile(params) {
|
|
60813
60994
|
const { url, name, size, destDir, token } = params;
|
|
60814
|
-
const destPath =
|
|
60995
|
+
const destPath = join83(destDir, name);
|
|
60815
60996
|
await mkdir21(destDir, { recursive: true });
|
|
60816
60997
|
output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
60817
60998
|
const headers = {};
|
|
@@ -60879,7 +61060,7 @@ class FileDownloader {
|
|
|
60879
61060
|
const expectedSize = Number(response.headers.get("content-length"));
|
|
60880
61061
|
if (expectedSize > 0 && downloadedSize !== expectedSize) {
|
|
60881
61062
|
fileStream.end();
|
|
60882
|
-
await new Promise((
|
|
61063
|
+
await new Promise((resolve18) => fileStream.once("close", resolve18));
|
|
60883
61064
|
try {
|
|
60884
61065
|
rmSync3(destPath, { force: true });
|
|
60885
61066
|
} catch (cleanupError) {
|
|
@@ -60897,7 +61078,7 @@ class FileDownloader {
|
|
|
60897
61078
|
return destPath;
|
|
60898
61079
|
} catch (error) {
|
|
60899
61080
|
fileStream.end();
|
|
60900
|
-
await new Promise((
|
|
61081
|
+
await new Promise((resolve18) => fileStream.once("close", resolve18));
|
|
60901
61082
|
try {
|
|
60902
61083
|
rmSync3(destPath, { force: true });
|
|
60903
61084
|
} catch (cleanupError) {
|
|
@@ -60914,7 +61095,7 @@ init_logger();
|
|
|
60914
61095
|
init_types2();
|
|
60915
61096
|
import { constants as constants3 } from "node:fs";
|
|
60916
61097
|
import { access as access3, readdir as readdir25 } from "node:fs/promises";
|
|
60917
|
-
import { join as
|
|
61098
|
+
import { join as join84 } from "node:path";
|
|
60918
61099
|
async function validateExtraction(extractDir) {
|
|
60919
61100
|
try {
|
|
60920
61101
|
const entries = await readdir25(extractDir, { encoding: "utf8" });
|
|
@@ -60926,7 +61107,7 @@ async function validateExtraction(extractDir) {
|
|
|
60926
61107
|
const missingPaths = [];
|
|
60927
61108
|
for (const path8 of criticalPaths) {
|
|
60928
61109
|
try {
|
|
60929
|
-
await access3(
|
|
61110
|
+
await access3(join84(extractDir, path8), constants3.F_OK);
|
|
60930
61111
|
logger.debug(`Found: ${path8}`);
|
|
60931
61112
|
} catch {
|
|
60932
61113
|
logger.warning(`Expected path not found: ${path8}`);
|
|
@@ -60948,7 +61129,7 @@ async function validateExtraction(extractDir) {
|
|
|
60948
61129
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
60949
61130
|
init_logger();
|
|
60950
61131
|
import { copyFile as copyFile6, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat8 } from "node:fs/promises";
|
|
60951
|
-
import { join as
|
|
61132
|
+
import { join as join86 } from "node:path";
|
|
60952
61133
|
|
|
60953
61134
|
// node_modules/tar/dist/esm/index.min.js
|
|
60954
61135
|
import Kr from "events";
|
|
@@ -64161,7 +64342,7 @@ function decodeFilePath(path8) {
|
|
|
64161
64342
|
init_logger();
|
|
64162
64343
|
init_types2();
|
|
64163
64344
|
import { copyFile as copyFile5, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
|
|
64164
|
-
import { join as
|
|
64345
|
+
import { join as join85, relative as relative15 } from "node:path";
|
|
64165
64346
|
async function withRetry2(fn2, retries = 3) {
|
|
64166
64347
|
for (let i = 0;i < retries; i++) {
|
|
64167
64348
|
try {
|
|
@@ -64183,8 +64364,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
64183
64364
|
await mkdir22(destDir, { recursive: true });
|
|
64184
64365
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
64185
64366
|
for (const entry of entries) {
|
|
64186
|
-
const sourcePath =
|
|
64187
|
-
const destPath =
|
|
64367
|
+
const sourcePath = join85(sourceDir, entry);
|
|
64368
|
+
const destPath = join85(destDir, entry);
|
|
64188
64369
|
const relativePath = relative15(sourceDir, sourcePath);
|
|
64189
64370
|
if (!isPathSafe(destDir, destPath)) {
|
|
64190
64371
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -64211,8 +64392,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
|
64211
64392
|
await mkdir22(destDir, { recursive: true });
|
|
64212
64393
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
64213
64394
|
for (const entry of entries) {
|
|
64214
|
-
const sourcePath =
|
|
64215
|
-
const destPath =
|
|
64395
|
+
const sourcePath = join85(sourceDir, entry);
|
|
64396
|
+
const destPath = join85(destDir, entry);
|
|
64216
64397
|
const relativePath = relative15(sourceDir, sourcePath);
|
|
64217
64398
|
if (!isPathSafe(destDir, destPath)) {
|
|
64218
64399
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -64267,7 +64448,7 @@ class TarExtractor {
|
|
|
64267
64448
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
64268
64449
|
if (entries.length === 1) {
|
|
64269
64450
|
const rootEntry = entries[0];
|
|
64270
|
-
const rootPath =
|
|
64451
|
+
const rootPath = join86(tempExtractDir, rootEntry);
|
|
64271
64452
|
const rootStat = await stat8(rootPath);
|
|
64272
64453
|
if (rootStat.isDirectory()) {
|
|
64273
64454
|
const rootContents = await readdir27(rootPath, { encoding: "utf8" });
|
|
@@ -64283,7 +64464,7 @@ class TarExtractor {
|
|
|
64283
64464
|
}
|
|
64284
64465
|
} else {
|
|
64285
64466
|
await mkdir23(destDir, { recursive: true });
|
|
64286
|
-
await copyFile6(rootPath,
|
|
64467
|
+
await copyFile6(rootPath, join86(destDir, rootEntry));
|
|
64287
64468
|
}
|
|
64288
64469
|
} else {
|
|
64289
64470
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -64304,7 +64485,7 @@ class TarExtractor {
|
|
|
64304
64485
|
init_logger();
|
|
64305
64486
|
import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
64306
64487
|
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
|
|
64488
|
+
import { dirname as dirname21, join as join87, resolve as resolve18 } from "node:path";
|
|
64308
64489
|
import { pipeline } from "node:stream/promises";
|
|
64309
64490
|
import yauzl from "yauzl-promise";
|
|
64310
64491
|
class ZipExtractor {
|
|
@@ -64318,7 +64499,7 @@ class ZipExtractor {
|
|
|
64318
64499
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
64319
64500
|
if (entries.length === 1) {
|
|
64320
64501
|
const rootEntry = entries[0];
|
|
64321
|
-
const rootPath =
|
|
64502
|
+
const rootPath = join87(tempExtractDir, rootEntry);
|
|
64322
64503
|
const rootStat = await stat9(rootPath);
|
|
64323
64504
|
if (rootStat.isDirectory()) {
|
|
64324
64505
|
const rootContents = await readdir28(rootPath, { encoding: "utf8" });
|
|
@@ -64334,7 +64515,7 @@ class ZipExtractor {
|
|
|
64334
64515
|
}
|
|
64335
64516
|
} else {
|
|
64336
64517
|
await mkdir24(destDir, { recursive: true });
|
|
64337
|
-
await copyFile7(rootPath,
|
|
64518
|
+
await copyFile7(rootPath, join87(destDir, rootEntry));
|
|
64338
64519
|
}
|
|
64339
64520
|
} else {
|
|
64340
64521
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -64351,13 +64532,13 @@ class ZipExtractor {
|
|
|
64351
64532
|
}
|
|
64352
64533
|
async extractToDir(archivePath, destDir) {
|
|
64353
64534
|
const zip = await yauzl.open(archivePath, { decodeStrings: false });
|
|
64354
|
-
const destRoot =
|
|
64535
|
+
const destRoot = resolve18(destDir);
|
|
64355
64536
|
let count = 0;
|
|
64356
64537
|
try {
|
|
64357
64538
|
for await (const entry of zip) {
|
|
64358
64539
|
const rawName = entry.filename;
|
|
64359
64540
|
const name = normalizeZipEntryName(rawName);
|
|
64360
|
-
const outPath =
|
|
64541
|
+
const outPath = resolve18(destRoot, name);
|
|
64361
64542
|
if (!isPathSafe(destRoot, outPath)) {
|
|
64362
64543
|
throw new Error(`Unsafe zip entry path (zip-slip): ${name}`);
|
|
64363
64544
|
}
|
|
@@ -64463,7 +64644,7 @@ class DownloadManager {
|
|
|
64463
64644
|
async createTempDir() {
|
|
64464
64645
|
const timestamp = Date.now();
|
|
64465
64646
|
const counter = DownloadManager.tempDirCounter++;
|
|
64466
|
-
const primaryTempDir =
|
|
64647
|
+
const primaryTempDir = join88(tmpdir3(), `takumi-${timestamp}-${counter}`);
|
|
64467
64648
|
try {
|
|
64468
64649
|
await mkdir25(primaryTempDir, { recursive: true });
|
|
64469
64650
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -64480,7 +64661,7 @@ Solutions:
|
|
|
64480
64661
|
2. Set HOME environment variable
|
|
64481
64662
|
3. Try running from a different directory`);
|
|
64482
64663
|
}
|
|
64483
|
-
const fallbackTempDir =
|
|
64664
|
+
const fallbackTempDir = join88(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
|
|
64484
64665
|
try {
|
|
64485
64666
|
await mkdir25(fallbackTempDir, { recursive: true });
|
|
64486
64667
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -65177,7 +65358,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
|
|
|
65177
65358
|
}
|
|
65178
65359
|
// src/commands/init/phases/selection-handler.ts
|
|
65179
65360
|
import { mkdir as mkdir26 } from "node:fs/promises";
|
|
65180
|
-
import { join as
|
|
65361
|
+
import { join as join92, resolve as resolve22 } from "node:path";
|
|
65181
65362
|
|
|
65182
65363
|
// src/commands/shared/agent-selector.ts
|
|
65183
65364
|
function selectAgents(opts = {}) {
|
|
@@ -65321,8 +65502,8 @@ async function runPreflightChecks() {
|
|
|
65321
65502
|
}
|
|
65322
65503
|
|
|
65323
65504
|
// 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
|
|
65505
|
+
import { existsSync as existsSync43, readdirSync as readdirSync4, rmSync as rmSync4, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
|
|
65506
|
+
import { dirname as dirname24, join as join91, resolve as resolve21 } from "node:path";
|
|
65326
65507
|
init_logger();
|
|
65327
65508
|
init_takumi_constants();
|
|
65328
65509
|
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
@@ -65370,15 +65551,15 @@ async function analyzeFreshInstallation(claudeDir) {
|
|
|
65370
65551
|
};
|
|
65371
65552
|
}
|
|
65372
65553
|
function cleanupEmptyDirectories2(filePath, claudeDir) {
|
|
65373
|
-
const normalizedClaudeDir =
|
|
65374
|
-
let currentDir =
|
|
65554
|
+
const normalizedClaudeDir = resolve21(claudeDir);
|
|
65555
|
+
let currentDir = resolve21(dirname24(filePath));
|
|
65375
65556
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
65376
65557
|
try {
|
|
65377
65558
|
const entries = readdirSync4(currentDir);
|
|
65378
65559
|
if (entries.length === 0) {
|
|
65379
65560
|
rmdirSync2(currentDir);
|
|
65380
65561
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
65381
|
-
currentDir =
|
|
65562
|
+
currentDir = resolve21(dirname24(currentDir));
|
|
65382
65563
|
} else {
|
|
65383
65564
|
break;
|
|
65384
65565
|
}
|
|
@@ -65395,10 +65576,10 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
65395
65576
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
65396
65577
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
65397
65578
|
for (const file of filesToRemove) {
|
|
65398
|
-
const fullPath =
|
|
65579
|
+
const fullPath = join91(claudeDir, file.path);
|
|
65399
65580
|
try {
|
|
65400
65581
|
if (existsSync43(fullPath)) {
|
|
65401
|
-
|
|
65582
|
+
unlinkSync5(fullPath);
|
|
65402
65583
|
removedFiles.push(file.path);
|
|
65403
65584
|
logger.debug(`Removed: ${file.path}`);
|
|
65404
65585
|
cleanupEmptyDirectories2(fullPath, claudeDir);
|
|
@@ -65456,7 +65637,7 @@ async function updateMetadataAfterFresh(claudeDir, removedFiles) {
|
|
|
65456
65637
|
await import_fs_extra32.writeFile(canonicalPath, JSON.stringify(metadata, null, 2));
|
|
65457
65638
|
if (resolved.isLegacy && canonicalPath !== resolved.path) {
|
|
65458
65639
|
try {
|
|
65459
|
-
|
|
65640
|
+
unlinkSync5(resolved.path);
|
|
65460
65641
|
} catch {}
|
|
65461
65642
|
}
|
|
65462
65643
|
logger.debug(`Updated manifest, removed ${removedFiles.length} file entries`);
|
|
@@ -65469,7 +65650,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
65469
65650
|
const removedFiles = [];
|
|
65470
65651
|
let removedDirCount = 0;
|
|
65471
65652
|
for (const subdir of TAKUMI_SUBDIRECTORIES) {
|
|
65472
|
-
const subdirPath =
|
|
65653
|
+
const subdirPath = join91(claudeDir, subdir);
|
|
65473
65654
|
if (await import_fs_extra32.pathExists(subdirPath)) {
|
|
65474
65655
|
rmSync4(subdirPath, { recursive: true, force: true });
|
|
65475
65656
|
removedDirCount++;
|
|
@@ -65479,12 +65660,12 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
65479
65660
|
}
|
|
65480
65661
|
const canonicalPath = getManifestPath(claudeDir);
|
|
65481
65662
|
if (await import_fs_extra32.pathExists(canonicalPath)) {
|
|
65482
|
-
|
|
65663
|
+
unlinkSync5(canonicalPath);
|
|
65483
65664
|
removedFiles.push(MANIFEST_FILENAME);
|
|
65484
65665
|
}
|
|
65485
65666
|
const legacyPath = getLegacyManifestPath(claudeDir);
|
|
65486
65667
|
if (await import_fs_extra32.pathExists(legacyPath)) {
|
|
65487
|
-
|
|
65668
|
+
unlinkSync5(legacyPath);
|
|
65488
65669
|
removedFiles.push(LEGACY_MANIFEST_FILENAME);
|
|
65489
65670
|
}
|
|
65490
65671
|
return {
|
|
@@ -65588,7 +65769,7 @@ async function handleSelection(ctx) {
|
|
|
65588
65769
|
const github2 = new GitHubClient;
|
|
65589
65770
|
release2 = await github2.getReleaseByTag(kit2, ctx.selectedVersion);
|
|
65590
65771
|
} else {
|
|
65591
|
-
const worker = new WorkerSource(getServerUrl(), ctx.kitType);
|
|
65772
|
+
const worker = new WorkerSource(getServerUrl(), backendIdOf(ctx.kitType));
|
|
65592
65773
|
const entry = await worker.fetchByTag(ctx.selectedVersion);
|
|
65593
65774
|
release2 = releaseEntryToGitHubRelease(entry, kit2);
|
|
65594
65775
|
}
|
|
@@ -65708,7 +65889,7 @@ async function handleSelection(ctx) {
|
|
|
65708
65889
|
}
|
|
65709
65890
|
}
|
|
65710
65891
|
}
|
|
65711
|
-
const resolvedDir =
|
|
65892
|
+
const resolvedDir = resolve22(targetDir);
|
|
65712
65893
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
65713
65894
|
if (!ctx.options.global && isLocalSameAsGlobal(resolvedDir)) {
|
|
65714
65895
|
logger.warning("You're at HOME directory. Installing here modifies your GLOBAL Takumi.");
|
|
@@ -65742,7 +65923,7 @@ async function handleSelection(ctx) {
|
|
|
65742
65923
|
}
|
|
65743
65924
|
if (!ctx.options.fresh) {
|
|
65744
65925
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65745
|
-
const claudeDir = prefix ?
|
|
65926
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65746
65927
|
try {
|
|
65747
65928
|
const existingMetadata = await readManifest(claudeDir);
|
|
65748
65929
|
if (existingMetadata?.kits) {
|
|
@@ -65775,7 +65956,7 @@ async function handleSelection(ctx) {
|
|
|
65775
65956
|
}
|
|
65776
65957
|
if (ctx.options.fresh) {
|
|
65777
65958
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65778
|
-
const claudeDir = prefix ?
|
|
65959
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65779
65960
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
65780
65961
|
if (!canProceed) {
|
|
65781
65962
|
return { ...ctx, cancelled: true };
|
|
@@ -65795,7 +65976,7 @@ async function handleSelection(ctx) {
|
|
|
65795
65976
|
let currentVersion = null;
|
|
65796
65977
|
try {
|
|
65797
65978
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65798
|
-
const claudeDir = prefix ?
|
|
65979
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65799
65980
|
const existingMetadata = await readManifest(claudeDir);
|
|
65800
65981
|
currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
|
|
65801
65982
|
if (currentVersion) {
|
|
@@ -65858,7 +66039,7 @@ async function handleSelection(ctx) {
|
|
|
65858
66039
|
logger.success(`Found: ${release.tag_name}`);
|
|
65859
66040
|
}
|
|
65860
66041
|
} else if (selectedVersion) {
|
|
65861
|
-
const worker = new WorkerSource(getServerUrl(), kitType);
|
|
66042
|
+
const worker = new WorkerSource(getServerUrl(), backendIdOf(kitType));
|
|
65862
66043
|
const entry = await worker.fetchByTag(selectedVersion);
|
|
65863
66044
|
release = releaseEntryToGitHubRelease(entry, kit);
|
|
65864
66045
|
} else {
|
|
@@ -65867,7 +66048,7 @@ async function handleSelection(ctx) {
|
|
|
65867
66048
|
} else {
|
|
65868
66049
|
logger.info("Fetching latest release...");
|
|
65869
66050
|
}
|
|
65870
|
-
const worker = new WorkerSource(getServerUrl(), kitType);
|
|
66051
|
+
const worker = new WorkerSource(getServerUrl(), backendIdOf(kitType));
|
|
65871
66052
|
const entry = await worker.fetchLatest(ctx.options.beta);
|
|
65872
66053
|
release = releaseEntryToGitHubRelease(entry, kit);
|
|
65873
66054
|
if (release.prerelease) {
|
|
@@ -65883,7 +66064,7 @@ async function handleSelection(ctx) {
|
|
|
65883
66064
|
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
|
|
65884
66065
|
try {
|
|
65885
66066
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65886
|
-
const claudeDir = prefix ?
|
|
66067
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65887
66068
|
const existingMetadata = await readManifest(claudeDir);
|
|
65888
66069
|
const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
|
|
65889
66070
|
if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
|
|
@@ -65906,7 +66087,7 @@ async function handleSelection(ctx) {
|
|
|
65906
66087
|
let currentSecondaryVersion = null;
|
|
65907
66088
|
try {
|
|
65908
66089
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
65909
|
-
const claudeDir = prefix ?
|
|
66090
|
+
const claudeDir = prefix ? join92(resolvedDir, prefix) : resolvedDir;
|
|
65910
66091
|
const existingMetadata = await readManifest(claudeDir);
|
|
65911
66092
|
currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
|
|
65912
66093
|
} catch {}
|
|
@@ -65938,7 +66119,7 @@ async function handleSelection(ctx) {
|
|
|
65938
66119
|
const ghClient = github ?? new GitHubClient;
|
|
65939
66120
|
secondaryRelease = secondaryVersion ? await ghClient.getReleaseByTag(kitConfig, secondaryVersion) : await ghClient.getLatestRelease(kitConfig, ctx.options.beta);
|
|
65940
66121
|
} else {
|
|
65941
|
-
const worker = new WorkerSource(getServerUrl(), secondaryKit);
|
|
66122
|
+
const worker = new WorkerSource(getServerUrl(), backendIdOf(secondaryKit));
|
|
65942
66123
|
const entry = secondaryVersion ? await worker.fetchByTag(secondaryVersion) : await worker.fetchLatest(ctx.options.beta);
|
|
65943
66124
|
secondaryRelease = releaseEntryToGitHubRelease(entry, kitConfig);
|
|
65944
66125
|
}
|
|
@@ -65973,7 +66154,7 @@ async function resolveReleaseForKit(ctx, kitType) {
|
|
|
65973
66154
|
const release = await github.getLatestRelease(kit, ctx.options.beta);
|
|
65974
66155
|
return release;
|
|
65975
66156
|
}
|
|
65976
|
-
const worker = new WorkerSource(getServerUrl(), kitType);
|
|
66157
|
+
const worker = new WorkerSource(getServerUrl(), backendIdOf(kitType));
|
|
65977
66158
|
const entry = await worker.fetchLatest(ctx.options.beta);
|
|
65978
66159
|
return releaseEntryToGitHubRelease(entry, kit);
|
|
65979
66160
|
}
|
|
@@ -65989,14 +66170,15 @@ function resolveGlobalTargetDir(targetAgents) {
|
|
|
65989
66170
|
}
|
|
65990
66171
|
// src/commands/init/phases/sync-handler.ts
|
|
65991
66172
|
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
|
|
66173
|
+
import { dirname as dirname25, join as join95, resolve as resolve23 } from "node:path";
|
|
65993
66174
|
|
|
65994
66175
|
// src/domains/sync/config-version-checker.ts
|
|
65995
66176
|
init_auth_client();
|
|
65996
66177
|
import { mkdir as mkdir27, readFile as readFile37, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
|
|
65997
|
-
import { join as
|
|
66178
|
+
import { join as join93 } from "node:path";
|
|
65998
66179
|
init_logger();
|
|
65999
66180
|
init_path_resolver();
|
|
66181
|
+
init_types2();
|
|
66000
66182
|
var CACHE_TTL_HOURS = 24;
|
|
66001
66183
|
var DEFAULT_CACHE_TTL_MS = CACHE_TTL_HOURS * 60 * 60 * 1000;
|
|
66002
66184
|
var MIN_CACHE_TTL_MS = 60 * 1000;
|
|
@@ -66028,7 +66210,7 @@ var CACHE_FILENAME = "config-update-cache.json";
|
|
|
66028
66210
|
class ConfigVersionChecker {
|
|
66029
66211
|
static getCacheFilePath(kitType, global3) {
|
|
66030
66212
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
66031
|
-
return
|
|
66213
|
+
return join93(cacheDir, `${kitType}-${CACHE_FILENAME}`);
|
|
66032
66214
|
}
|
|
66033
66215
|
static async loadCache(kitType, global3) {
|
|
66034
66216
|
try {
|
|
@@ -66059,7 +66241,7 @@ class ConfigVersionChecker {
|
|
|
66059
66241
|
const baseBackoff = 1000;
|
|
66060
66242
|
for (let attempt = 0;attempt < maxRetries; attempt++) {
|
|
66061
66243
|
try {
|
|
66062
|
-
const worker = new WorkerSource(getServerUrl(), kitType);
|
|
66244
|
+
const worker = new WorkerSource(getServerUrl(), backendIdOf(kitType));
|
|
66063
66245
|
const entry = await worker.fetchLatest();
|
|
66064
66246
|
const version3 = entry.version.replace(/^v/, "");
|
|
66065
66247
|
if (!version3 || version3.length > 256) {
|
|
@@ -66084,7 +66266,7 @@ class ConfigVersionChecker {
|
|
|
66084
66266
|
return null;
|
|
66085
66267
|
}
|
|
66086
66268
|
const delay3 = baseBackoff * 2 ** attempt;
|
|
66087
|
-
await new Promise((
|
|
66269
|
+
await new Promise((resolve23) => setTimeout(resolve23, delay3));
|
|
66088
66270
|
}
|
|
66089
66271
|
}
|
|
66090
66272
|
return null;
|
|
@@ -66146,7 +66328,7 @@ class ConfigVersionChecker {
|
|
|
66146
66328
|
}
|
|
66147
66329
|
// src/domains/sync/sync-engine.ts
|
|
66148
66330
|
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
|
|
66331
|
+
import { isAbsolute as isAbsolute3, join as join94, normalize as normalize8, relative as relative16 } from "node:path";
|
|
66150
66332
|
init_logger();
|
|
66151
66333
|
|
|
66152
66334
|
// node_modules/diff/libesm/diff/base.js
|
|
@@ -67253,7 +67435,7 @@ async function validateSymlinkChain(path9, basePath, maxDepth = MAX_SYMLINK_DEPT
|
|
|
67253
67435
|
if (!stats.isSymbolicLink())
|
|
67254
67436
|
break;
|
|
67255
67437
|
const target = await readlink(current);
|
|
67256
|
-
const resolvedTarget = isAbsolute3(target) ? target :
|
|
67438
|
+
const resolvedTarget = isAbsolute3(target) ? target : join94(current, "..", target);
|
|
67257
67439
|
const normalizedTarget = normalize8(resolvedTarget);
|
|
67258
67440
|
const rel = relative16(basePath, normalizedTarget);
|
|
67259
67441
|
if (rel.startsWith("..") || isAbsolute3(rel)) {
|
|
@@ -67289,7 +67471,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
67289
67471
|
if (normalized.startsWith("..") || normalized.includes("/../")) {
|
|
67290
67472
|
throw new Error(`Path traversal not allowed: ${filePath}`);
|
|
67291
67473
|
}
|
|
67292
|
-
const fullPath =
|
|
67474
|
+
const fullPath = join94(basePath, normalized);
|
|
67293
67475
|
const rel = relative16(basePath, fullPath);
|
|
67294
67476
|
if (rel.startsWith("..") || isAbsolute3(rel)) {
|
|
67295
67477
|
throw new Error(`Path escapes base directory: ${filePath}`);
|
|
@@ -67304,7 +67486,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
67304
67486
|
}
|
|
67305
67487
|
} catch (error) {
|
|
67306
67488
|
if (error.code === "ENOENT") {
|
|
67307
|
-
const parentPath =
|
|
67489
|
+
const parentPath = join94(fullPath, "..");
|
|
67308
67490
|
try {
|
|
67309
67491
|
const resolvedBase = await realpath3(basePath);
|
|
67310
67492
|
const resolvedParent = await realpath3(parentPath);
|
|
@@ -67689,7 +67871,7 @@ async function handleSync(ctx) {
|
|
|
67689
67871
|
logger.error(`Sync not yet supported for ${targetAgent}. Only --agent claude-code supports --sync.`);
|
|
67690
67872
|
return { ...ctx, cancelled: true };
|
|
67691
67873
|
}
|
|
67692
|
-
const resolvedDir = ctx.options.global ? getClaudeDir() :
|
|
67874
|
+
const resolvedDir = ctx.options.global ? getClaudeDir() : resolve23(ctx.options.dir || ".");
|
|
67693
67875
|
const claudeDir = ctx.options.global ? resolvedDir : getLocalClaudeDir(resolvedDir);
|
|
67694
67876
|
if (!await import_fs_extra34.pathExists(claudeDir)) {
|
|
67695
67877
|
logger.error("Cannot sync: no .claude directory found");
|
|
@@ -67705,9 +67887,9 @@ Run 'takumi init' to update.`, "Legacy Installation");
|
|
|
67705
67887
|
}
|
|
67706
67888
|
let kitType = ctx.options.selectedKits?.[0];
|
|
67707
67889
|
if (!kitType) {
|
|
67708
|
-
const
|
|
67709
|
-
if (
|
|
67710
|
-
kitType = "
|
|
67890
|
+
const coreMeta = await readKitManifest(claudeDir, "core");
|
|
67891
|
+
if (coreMeta) {
|
|
67892
|
+
kitType = "core";
|
|
67711
67893
|
} else {
|
|
67712
67894
|
logger.error("Cannot sync: no kit installation found in metadata");
|
|
67713
67895
|
return { ...ctx, cancelled: true };
|
|
@@ -67792,7 +67974,7 @@ function getLockTimeout() {
|
|
|
67792
67974
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
67793
67975
|
async function acquireSyncLock(global3) {
|
|
67794
67976
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
67795
|
-
const lockPath =
|
|
67977
|
+
const lockPath = join95(cacheDir, ".sync-lock");
|
|
67796
67978
|
const startTime = Date.now();
|
|
67797
67979
|
const lockTimeout = getLockTimeout();
|
|
67798
67980
|
await mkdir28(dirname25(lockPath), { recursive: true });
|
|
@@ -67819,7 +68001,7 @@ async function acquireSyncLock(global3) {
|
|
|
67819
68001
|
}
|
|
67820
68002
|
logger.debug(`Lock stat failed: ${statError}`);
|
|
67821
68003
|
}
|
|
67822
|
-
await new Promise((
|
|
68004
|
+
await new Promise((resolve24) => setTimeout(resolve24, 100));
|
|
67823
68005
|
continue;
|
|
67824
68006
|
}
|
|
67825
68007
|
throw err;
|
|
@@ -67873,7 +68055,7 @@ async function executeSyncMerge(ctx) {
|
|
|
67873
68055
|
try {
|
|
67874
68056
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
67875
68057
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
67876
|
-
const targetDir =
|
|
68058
|
+
const targetDir = join95(targetPath, "..");
|
|
67877
68059
|
try {
|
|
67878
68060
|
await mkdir28(targetDir, { recursive: true });
|
|
67879
68061
|
} catch (mkdirError) {
|
|
@@ -68044,7 +68226,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
68044
68226
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
68045
68227
|
if (await import_fs_extra34.pathExists(sourcePath)) {
|
|
68046
68228
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
68047
|
-
const targetDir =
|
|
68229
|
+
const targetDir = join95(targetPath, "..");
|
|
68048
68230
|
await mkdir28(targetDir, { recursive: true });
|
|
68049
68231
|
await copyFile8(sourcePath, targetPath);
|
|
68050
68232
|
}
|
|
@@ -68066,38 +68248,38 @@ init_logger();
|
|
|
68066
68248
|
init_types2();
|
|
68067
68249
|
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
68068
68250
|
import { rename as rename8, rm as rm9 } from "node:fs/promises";
|
|
68069
|
-
import { join as
|
|
68251
|
+
import { join as join96, relative as relative17 } from "node:path";
|
|
68070
68252
|
async function collectDirsToRename(extractDir, folders) {
|
|
68071
68253
|
const dirsToRename = [];
|
|
68072
68254
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
68073
|
-
const docsPath =
|
|
68255
|
+
const docsPath = join96(extractDir, DEFAULT_FOLDERS.docs);
|
|
68074
68256
|
if (await import_fs_extra35.pathExists(docsPath)) {
|
|
68075
68257
|
dirsToRename.push({
|
|
68076
68258
|
from: docsPath,
|
|
68077
|
-
to:
|
|
68259
|
+
to: join96(extractDir, folders.docs)
|
|
68078
68260
|
});
|
|
68079
68261
|
}
|
|
68080
|
-
const claudeDocsPath =
|
|
68262
|
+
const claudeDocsPath = join96(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
68081
68263
|
if (await import_fs_extra35.pathExists(claudeDocsPath)) {
|
|
68082
68264
|
dirsToRename.push({
|
|
68083
68265
|
from: claudeDocsPath,
|
|
68084
|
-
to:
|
|
68266
|
+
to: join96(extractDir, ".claude", folders.docs)
|
|
68085
68267
|
});
|
|
68086
68268
|
}
|
|
68087
68269
|
}
|
|
68088
68270
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
68089
|
-
const plansPath =
|
|
68271
|
+
const plansPath = join96(extractDir, DEFAULT_FOLDERS.plans);
|
|
68090
68272
|
if (await import_fs_extra35.pathExists(plansPath)) {
|
|
68091
68273
|
dirsToRename.push({
|
|
68092
68274
|
from: plansPath,
|
|
68093
|
-
to:
|
|
68275
|
+
to: join96(extractDir, folders.plans)
|
|
68094
68276
|
});
|
|
68095
68277
|
}
|
|
68096
|
-
const claudePlansPath =
|
|
68278
|
+
const claudePlansPath = join96(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
68097
68279
|
if (await import_fs_extra35.pathExists(claudePlansPath)) {
|
|
68098
68280
|
dirsToRename.push({
|
|
68099
68281
|
from: claudePlansPath,
|
|
68100
|
-
to:
|
|
68282
|
+
to: join96(extractDir, ".claude", folders.plans)
|
|
68101
68283
|
});
|
|
68102
68284
|
}
|
|
68103
68285
|
}
|
|
@@ -68138,7 +68320,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
68138
68320
|
init_logger();
|
|
68139
68321
|
init_types2();
|
|
68140
68322
|
import { readFile as readFile40, readdir as readdir29, writeFile as writeFile30 } from "node:fs/promises";
|
|
68141
|
-
import { join as
|
|
68323
|
+
import { join as join97, relative as relative18 } from "node:path";
|
|
68142
68324
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
68143
68325
|
".md",
|
|
68144
68326
|
".txt",
|
|
@@ -68191,7 +68373,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
|
|
|
68191
68373
|
let replacementsCount = 0;
|
|
68192
68374
|
const entries = await readdir29(dir, { withFileTypes: true });
|
|
68193
68375
|
for (const entry of entries) {
|
|
68194
|
-
const fullPath =
|
|
68376
|
+
const fullPath = join97(dir, entry.name);
|
|
68195
68377
|
if (entry.isDirectory()) {
|
|
68196
68378
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
68197
68379
|
continue;
|
|
@@ -68328,7 +68510,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
68328
68510
|
init_logger();
|
|
68329
68511
|
import { readFile as readFile41, readdir as readdir30, writeFile as writeFile31 } from "node:fs/promises";
|
|
68330
68512
|
import { platform as platform9 } from "node:os";
|
|
68331
|
-
import { extname as extname6, join as
|
|
68513
|
+
import { extname as extname6, join as join98 } from "node:path";
|
|
68332
68514
|
var IS_WINDOWS3 = platform9() === "win32";
|
|
68333
68515
|
var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
|
|
68334
68516
|
function getHomeDirPrefix() {
|
|
@@ -68429,8 +68611,8 @@ function transformContent(content) {
|
|
|
68429
68611
|
}
|
|
68430
68612
|
function shouldTransformFile3(filename) {
|
|
68431
68613
|
const ext2 = extname6(filename).toLowerCase();
|
|
68432
|
-
const
|
|
68433
|
-
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(
|
|
68614
|
+
const basename10 = filename.split("/").pop() || filename;
|
|
68615
|
+
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename10);
|
|
68434
68616
|
}
|
|
68435
68617
|
async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
68436
68618
|
let filesTransformed = 0;
|
|
@@ -68440,7 +68622,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
68440
68622
|
async function processDirectory2(dir) {
|
|
68441
68623
|
const entries = await readdir30(dir, { withFileTypes: true });
|
|
68442
68624
|
for (const entry of entries) {
|
|
68443
|
-
const fullPath =
|
|
68625
|
+
const fullPath = join98(dir, entry.name);
|
|
68444
68626
|
if (entry.isDirectory()) {
|
|
68445
68627
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
68446
68628
|
continue;
|
|
@@ -68680,7 +68862,7 @@ init_types2();
|
|
|
68680
68862
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
68681
68863
|
|
|
68682
68864
|
// src/commands/new/phases/directory-setup.ts
|
|
68683
|
-
import { resolve as
|
|
68865
|
+
import { resolve as resolve24 } from "node:path";
|
|
68684
68866
|
init_logger();
|
|
68685
68867
|
init_types2();
|
|
68686
68868
|
var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
@@ -68764,7 +68946,7 @@ async function directorySetup(validOptions, prompts) {
|
|
|
68764
68946
|
targetDir = await prompts.getDirectory(targetDir);
|
|
68765
68947
|
}
|
|
68766
68948
|
}
|
|
68767
|
-
const resolvedDir =
|
|
68949
|
+
const resolvedDir = resolve24(targetDir);
|
|
68768
68950
|
logger.info(`Target directory: ${resolvedDir}`);
|
|
68769
68951
|
if (isLocalSameAsGlobal(resolvedDir)) {
|
|
68770
68952
|
logger.warning("You're creating a project at HOME directory.");
|
|
@@ -68819,7 +69001,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
68819
69001
|
};
|
|
68820
69002
|
}
|
|
68821
69003
|
// src/commands/new/phases/project-creation.ts
|
|
68822
|
-
import { join as
|
|
69004
|
+
import { join as join99 } from "node:path";
|
|
68823
69005
|
init_github_client();
|
|
68824
69006
|
init_logger();
|
|
68825
69007
|
init_output_manager();
|
|
@@ -68973,7 +69155,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
68973
69155
|
output.section("Installing");
|
|
68974
69156
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
68975
69157
|
const merger = new FileMerger;
|
|
68976
|
-
const claudeDir =
|
|
69158
|
+
const claudeDir = join99(resolvedDir, ".claude");
|
|
68977
69159
|
merger.setMultiKitContext(claudeDir, kit);
|
|
68978
69160
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
68979
69161
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -69026,10 +69208,10 @@ async function handleProjectCreation(ctx) {
|
|
|
69026
69208
|
};
|
|
69027
69209
|
}
|
|
69028
69210
|
// src/commands/new/phases/post-setup.ts
|
|
69029
|
-
import { join as
|
|
69211
|
+
import { join as join101 } from "node:path";
|
|
69030
69212
|
|
|
69031
69213
|
// src/domains/installation/setup-wizard.ts
|
|
69032
|
-
import { join as
|
|
69214
|
+
import { join as join100 } from "node:path";
|
|
69033
69215
|
init_logger();
|
|
69034
69216
|
init_dist2();
|
|
69035
69217
|
var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
@@ -69109,7 +69291,7 @@ async function parseEnvFile(path9) {
|
|
|
69109
69291
|
}
|
|
69110
69292
|
}
|
|
69111
69293
|
async function checkGlobalConfig() {
|
|
69112
|
-
const globalEnvPath =
|
|
69294
|
+
const globalEnvPath = join100(getClaudeDir(), ".env");
|
|
69113
69295
|
if (!await import_fs_extra37.pathExists(globalEnvPath))
|
|
69114
69296
|
return false;
|
|
69115
69297
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -69125,7 +69307,7 @@ async function runSetupWizard(options2) {
|
|
|
69125
69307
|
let globalEnv = {};
|
|
69126
69308
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
69127
69309
|
if (!isGlobal) {
|
|
69128
|
-
const globalEnvPath =
|
|
69310
|
+
const globalEnvPath = join100(getClaudeDir(), ".env");
|
|
69129
69311
|
if (await import_fs_extra37.pathExists(globalEnvPath)) {
|
|
69130
69312
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
69131
69313
|
}
|
|
@@ -69188,7 +69370,7 @@ async function runSetupWizard(options2) {
|
|
|
69188
69370
|
}
|
|
69189
69371
|
}
|
|
69190
69372
|
await generateEnvFile(targetDir, values);
|
|
69191
|
-
f2.success(`Configuration saved to ${
|
|
69373
|
+
f2.success(`Configuration saved to ${join100(targetDir, ".env")}`);
|
|
69192
69374
|
return true;
|
|
69193
69375
|
}
|
|
69194
69376
|
async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
@@ -69291,9 +69473,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
|
|
|
69291
69473
|
withSudo: validOptions.withSudo
|
|
69292
69474
|
});
|
|
69293
69475
|
}
|
|
69294
|
-
const claudeDir =
|
|
69476
|
+
const claudeDir = join101(resolvedDir, ".claude");
|
|
69295
69477
|
await promptSetupWizardIfNeeded({
|
|
69296
|
-
envPath:
|
|
69478
|
+
envPath: join101(claudeDir, ".env"),
|
|
69297
69479
|
claudeDir,
|
|
69298
69480
|
isGlobal: false,
|
|
69299
69481
|
isNonInteractive: isNonInteractive2,
|
|
@@ -69370,19 +69552,19 @@ Example: tkm new --use-git --release v2.1.0`);
|
|
|
69370
69552
|
// src/commands/plan/plan-command.ts
|
|
69371
69553
|
init_output_manager();
|
|
69372
69554
|
import { existsSync as existsSync48, statSync as statSync5 } from "node:fs";
|
|
69373
|
-
import { dirname as dirname31, join as
|
|
69555
|
+
import { dirname as dirname31, join as join105, parse as parse2, resolve as resolve28 } from "node:path";
|
|
69374
69556
|
|
|
69375
69557
|
// src/commands/plan/plan-read-handlers.ts
|
|
69376
69558
|
import { existsSync as existsSync47, statSync as statSync4 } from "node:fs";
|
|
69377
|
-
import { basename as
|
|
69559
|
+
import { basename as basename12, dirname as dirname30, join as join104, relative as relative19, resolve as resolve26 } from "node:path";
|
|
69378
69560
|
|
|
69379
69561
|
// src/domains/plan-parser/index.ts
|
|
69380
69562
|
import { dirname as dirname29 } from "node:path";
|
|
69381
69563
|
|
|
69382
69564
|
// src/domains/plan-parser/plan-table-parser.ts
|
|
69383
69565
|
var import_gray_matter5 = __toESM(require_gray_matter(), 1);
|
|
69384
|
-
import { readFileSync as
|
|
69385
|
-
import { dirname as dirname26, resolve as
|
|
69566
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
69567
|
+
import { dirname as dirname26, resolve as resolve25 } from "node:path";
|
|
69386
69568
|
function normalizeStatus(raw) {
|
|
69387
69569
|
const s3 = raw.toLowerCase().trim();
|
|
69388
69570
|
if (s3.includes("complete") || s3.includes("done") || s3.includes("✓") || s3.includes("✅")) {
|
|
@@ -69466,7 +69648,7 @@ function parseHeaderAwareTable(content, dir, options2) {
|
|
|
69466
69648
|
hasLinks = true;
|
|
69467
69649
|
linkText = linkMatch[1].trim();
|
|
69468
69650
|
name = filenameToTitle(linkText);
|
|
69469
|
-
file =
|
|
69651
|
+
file = resolve25(dir, linkMatch[2]);
|
|
69470
69652
|
} else {
|
|
69471
69653
|
name = nameRaw.replace(/\[.*?\]\(.*?\)/g, "").trim() || `Phase ${phaseId}`;
|
|
69472
69654
|
linkText = name;
|
|
@@ -69506,7 +69688,7 @@ function parseFormat1(content, dir, options2) {
|
|
|
69506
69688
|
phaseId,
|
|
69507
69689
|
name: name.trim(),
|
|
69508
69690
|
status: normalizeStatus(status2),
|
|
69509
|
-
file:
|
|
69691
|
+
file: resolve25(dir, linkPath),
|
|
69510
69692
|
linkText: linkText.trim(),
|
|
69511
69693
|
anchor
|
|
69512
69694
|
});
|
|
@@ -69526,7 +69708,7 @@ function parseFormat2(content, dir, options2) {
|
|
|
69526
69708
|
phaseId,
|
|
69527
69709
|
name: name.trim(),
|
|
69528
69710
|
status: normalizeStatus(status2),
|
|
69529
|
-
file:
|
|
69711
|
+
file: resolve25(dir, linkPath),
|
|
69530
69712
|
linkText,
|
|
69531
69713
|
anchor
|
|
69532
69714
|
});
|
|
@@ -69545,7 +69727,7 @@ function parseFormat2b(content, dir, options2) {
|
|
|
69545
69727
|
phaseId,
|
|
69546
69728
|
name: name.trim(),
|
|
69547
69729
|
status: normalizeStatus(status2),
|
|
69548
|
-
file:
|
|
69730
|
+
file: resolve25(dir, linkPath),
|
|
69549
69731
|
linkText: name.trim(),
|
|
69550
69732
|
anchor
|
|
69551
69733
|
});
|
|
@@ -69644,7 +69826,7 @@ function parseFormat4(content, planFilePath, options2) {
|
|
|
69644
69826
|
current = { name, status: hasCheck ? "completed" : "pending" };
|
|
69645
69827
|
} else if (fileMatch && current) {
|
|
69646
69828
|
const planDir = dirname26(planFilePath);
|
|
69647
|
-
current.file =
|
|
69829
|
+
current.file = resolve25(planDir, fileMatch[1].trim());
|
|
69648
69830
|
} else if (statusMatch && current) {
|
|
69649
69831
|
current.status = normalizeStatus(statusMatch[2]);
|
|
69650
69832
|
}
|
|
@@ -69710,7 +69892,7 @@ function parseFormat6(content, dir, options2) {
|
|
|
69710
69892
|
phaseId,
|
|
69711
69893
|
name: phaseName,
|
|
69712
69894
|
status: checked.toLowerCase() === "x" ? "completed" : "pending",
|
|
69713
|
-
file:
|
|
69895
|
+
file: resolve25(dir, linkPath),
|
|
69714
69896
|
linkText: phaseName,
|
|
69715
69897
|
anchor
|
|
69716
69898
|
});
|
|
@@ -69747,7 +69929,7 @@ function parsePhasesFromBody(body, dir, options2) {
|
|
|
69747
69929
|
return parseFormat6(normalizedBody, dir, options2);
|
|
69748
69930
|
}
|
|
69749
69931
|
function parsePlanFile(planFilePath, options2) {
|
|
69750
|
-
const content =
|
|
69932
|
+
const content = readFileSync13(planFilePath, "utf8");
|
|
69751
69933
|
const dir = dirname26(planFilePath);
|
|
69752
69934
|
const { data: frontmatter, content: body } = import_gray_matter5.default(content);
|
|
69753
69935
|
const phases = parsePhasesFromBody(body, dir, options2);
|
|
@@ -69755,22 +69937,22 @@ function parsePlanFile(planFilePath, options2) {
|
|
|
69755
69937
|
}
|
|
69756
69938
|
// src/domains/plan-parser/plan-scanner.ts
|
|
69757
69939
|
import { existsSync as existsSync44, readdirSync as readdirSync5 } from "node:fs";
|
|
69758
|
-
import { join as
|
|
69940
|
+
import { join as join102 } from "node:path";
|
|
69759
69941
|
function scanPlanDir(dir) {
|
|
69760
69942
|
if (!existsSync44(dir))
|
|
69761
69943
|
return [];
|
|
69762
69944
|
try {
|
|
69763
|
-
return readdirSync5(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
69945
|
+
return readdirSync5(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join102(dir, entry.name, "plan.md")).filter(existsSync44);
|
|
69764
69946
|
} catch {
|
|
69765
69947
|
return [];
|
|
69766
69948
|
}
|
|
69767
69949
|
}
|
|
69768
69950
|
// src/domains/plan-parser/plan-validator.ts
|
|
69769
69951
|
var import_gray_matter6 = __toESM(require_gray_matter(), 1);
|
|
69770
|
-
import { existsSync as existsSync45, readFileSync as
|
|
69771
|
-
import { basename as
|
|
69952
|
+
import { existsSync as existsSync45, readFileSync as readFileSync14 } from "node:fs";
|
|
69953
|
+
import { basename as basename10, dirname as dirname27 } from "node:path";
|
|
69772
69954
|
function validatePlanFile(filePath, strict = false) {
|
|
69773
|
-
const content =
|
|
69955
|
+
const content = readFileSync14(filePath, "utf8");
|
|
69774
69956
|
const dir = dirname27(filePath);
|
|
69775
69957
|
const issues = [];
|
|
69776
69958
|
const lines = content.split(`
|
|
@@ -69808,13 +69990,13 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
69808
69990
|
}
|
|
69809
69991
|
for (const phase of phases) {
|
|
69810
69992
|
if (phase.file && !existsSync45(phase.file)) {
|
|
69811
|
-
const fileBasename =
|
|
69993
|
+
const fileBasename = basename10(phase.file);
|
|
69812
69994
|
const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
|
|
69813
69995
|
issues.push({
|
|
69814
69996
|
line: refLine >= 0 ? refLine + 1 : 1,
|
|
69815
69997
|
severity: "warning",
|
|
69816
69998
|
code: "missing-phase-file",
|
|
69817
|
-
message: `Phase ${phase.phaseId} references '${
|
|
69999
|
+
message: `Phase ${phase.phaseId} references '${basename10(phase.file)}' which doesn't exist`
|
|
69818
70000
|
});
|
|
69819
70001
|
}
|
|
69820
70002
|
}
|
|
@@ -69827,9 +70009,9 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
69827
70009
|
}
|
|
69828
70010
|
// src/domains/plan-parser/plan-writer.ts
|
|
69829
70011
|
var import_gray_matter7 = __toESM(require_gray_matter(), 1);
|
|
69830
|
-
import { mkdirSync as
|
|
70012
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync7 } from "node:fs";
|
|
69831
70013
|
import { existsSync as existsSync46 } from "node:fs";
|
|
69832
|
-
import { basename as
|
|
70014
|
+
import { basename as basename11, dirname as dirname28, join as join103 } from "node:path";
|
|
69833
70015
|
function phaseNameToFilename(id, name) {
|
|
69834
70016
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
|
|
69835
70017
|
const num = numMatch ? numMatch[1] : id;
|
|
@@ -69934,16 +70116,16 @@ function resolvePhaseIds(phases) {
|
|
|
69934
70116
|
}
|
|
69935
70117
|
function scaffoldPlan(options2) {
|
|
69936
70118
|
const { dir } = options2;
|
|
69937
|
-
|
|
70119
|
+
mkdirSync4(dir, { recursive: true });
|
|
69938
70120
|
const resolvedPhases = resolvePhaseIds(options2.phases);
|
|
69939
70121
|
const optionsWithResolved = { ...options2, phases: resolvedPhases };
|
|
69940
|
-
const planFile =
|
|
69941
|
-
|
|
70122
|
+
const planFile = join103(dir, "plan.md");
|
|
70123
|
+
writeFileSync7(planFile, generatePlanMd(optionsWithResolved), "utf8");
|
|
69942
70124
|
const phaseFiles = [];
|
|
69943
70125
|
for (const phase of resolvedPhases) {
|
|
69944
70126
|
const filename = phaseNameToFilename(phase.id, phase.name);
|
|
69945
|
-
const phaseFile =
|
|
69946
|
-
|
|
70127
|
+
const phaseFile = join103(dir, filename);
|
|
70128
|
+
writeFileSync7(phaseFile, generatePhaseTemplate(phase), "utf8");
|
|
69947
70129
|
phaseFiles.push(phaseFile);
|
|
69948
70130
|
}
|
|
69949
70131
|
return { planFile, phaseFiles };
|
|
@@ -69967,7 +70149,7 @@ function isCanonicalFormat(content) {
|
|
|
69967
70149
|
return /^\|\s*phase\s*\|\s*name\s*\|\s*status\s*\|/im.test(content);
|
|
69968
70150
|
}
|
|
69969
70151
|
function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
69970
|
-
const raw =
|
|
70152
|
+
const raw = readFileSync15(planFile, "utf8").replace(/\r\n/g, `
|
|
69971
70153
|
`);
|
|
69972
70154
|
if (!isCanonicalFormat(raw)) {
|
|
69973
70155
|
console.error("[!] plan.md is not in canonical format — skipping status update");
|
|
@@ -70007,7 +70189,7 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
|
70007
70189
|
}
|
|
70008
70190
|
const updatedFrontmatter = { ...frontmatter, status: planStatus };
|
|
70009
70191
|
const updatedContent = import_gray_matter7.default.stringify(updatedBody, updatedFrontmatter);
|
|
70010
|
-
|
|
70192
|
+
writeFileSync7(planFile, updatedContent, "utf8");
|
|
70011
70193
|
const planDir = dirname28(planFile);
|
|
70012
70194
|
const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
|
|
70013
70195
|
if (phaseFilename && existsSync46(phaseFilename)) {
|
|
@@ -70022,18 +70204,18 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
|
|
|
70022
70204
|
continue;
|
|
70023
70205
|
const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
|
|
70024
70206
|
if (linkMatch)
|
|
70025
|
-
return
|
|
70207
|
+
return join103(planDir, linkMatch[2]);
|
|
70026
70208
|
}
|
|
70027
70209
|
return null;
|
|
70028
70210
|
}
|
|
70029
70211
|
function updatePhaseFileFrontmatter(phaseFile, newStatus) {
|
|
70030
|
-
const raw =
|
|
70212
|
+
const raw = readFileSync15(phaseFile, "utf8");
|
|
70031
70213
|
const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
|
|
70032
70214
|
const updated = { ...frontmatter, status: newStatus };
|
|
70033
|
-
|
|
70215
|
+
writeFileSync7(phaseFile, import_gray_matter7.default.stringify(body, updated), "utf8");
|
|
70034
70216
|
}
|
|
70035
70217
|
function addPhase(planFile, name, afterId) {
|
|
70036
|
-
const raw =
|
|
70218
|
+
const raw = readFileSync15(planFile, "utf8").replace(/\r\n/g, `
|
|
70037
70219
|
`);
|
|
70038
70220
|
if (!isCanonicalFormat(raw)) {
|
|
70039
70221
|
console.error("[!] plan.md is not in canonical format — cannot add phase");
|
|
@@ -70069,7 +70251,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
70069
70251
|
insertIdx = i;
|
|
70070
70252
|
}
|
|
70071
70253
|
if (insertIdx === -1) {
|
|
70072
|
-
throw new Error(`Phase ID "${afterId}" not found in ${
|
|
70254
|
+
throw new Error(`Phase ID "${afterId}" not found in ${basename11(planFile)}`);
|
|
70073
70255
|
}
|
|
70074
70256
|
lines.splice(insertIdx + 1, 0, newRow);
|
|
70075
70257
|
updatedBody = lines.join(`
|
|
@@ -70102,9 +70284,9 @@ function addPhase(planFile, name, afterId) {
|
|
|
70102
70284
|
updatedBody = lines.join(`
|
|
70103
70285
|
`);
|
|
70104
70286
|
}
|
|
70105
|
-
|
|
70106
|
-
const phaseFilePath =
|
|
70107
|
-
|
|
70287
|
+
writeFileSync7(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
|
|
70288
|
+
const phaseFilePath = join103(planDir, filename);
|
|
70289
|
+
writeFileSync7(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
|
|
70108
70290
|
return { phaseId, phaseFile: phaseFilePath };
|
|
70109
70291
|
}
|
|
70110
70292
|
|
|
@@ -70152,7 +70334,7 @@ async function handleParse(target, options2) {
|
|
|
70152
70334
|
console.log(JSON.stringify({ file: relative19(process.cwd(), planFile), frontmatter, phases }, null, 2));
|
|
70153
70335
|
return;
|
|
70154
70336
|
}
|
|
70155
|
-
const title = typeof frontmatter.title === "string" ? frontmatter.title :
|
|
70337
|
+
const title = typeof frontmatter.title === "string" ? frontmatter.title : basename12(dirname30(planFile));
|
|
70156
70338
|
console.log();
|
|
70157
70339
|
console.log(import_picocolors24.default.bold(` Plan: ${title}`));
|
|
70158
70340
|
console.log(` File: ${planFile}`);
|
|
@@ -70206,8 +70388,8 @@ async function handleValidate(target, options2) {
|
|
|
70206
70388
|
process.exitCode = 1;
|
|
70207
70389
|
}
|
|
70208
70390
|
async function handleStatus(target, options2) {
|
|
70209
|
-
const t = target ?
|
|
70210
|
-
const plansDir = t && existsSync47(t) && statSync4(t).isDirectory() && !existsSync47(
|
|
70391
|
+
const t = target ? resolve26(target) : null;
|
|
70392
|
+
const plansDir = t && existsSync47(t) && statSync4(t).isDirectory() && !existsSync47(join104(t, "plan.md")) ? t : null;
|
|
70211
70393
|
if (plansDir) {
|
|
70212
70394
|
const planFiles = scanPlanDir(plansDir);
|
|
70213
70395
|
if (planFiles.length === 0) {
|
|
@@ -70232,14 +70414,14 @@ async function handleStatus(target, options2) {
|
|
|
70232
70414
|
try {
|
|
70233
70415
|
const s3 = buildPlanSummary(pf);
|
|
70234
70416
|
const bar = progressBar(s3.completed, s3.totalPhases);
|
|
70235
|
-
const title2 = s3.title ??
|
|
70417
|
+
const title2 = s3.title ?? basename12(dirname30(pf));
|
|
70236
70418
|
console.log(` ${import_picocolors24.default.bold(title2)}`);
|
|
70237
70419
|
console.log(` ${bar}`);
|
|
70238
70420
|
if (s3.inProgress > 0)
|
|
70239
70421
|
console.log(` [~] ${s3.inProgress} in progress`);
|
|
70240
70422
|
console.log();
|
|
70241
70423
|
} catch {
|
|
70242
|
-
console.log(` [X] Failed to read: ${
|
|
70424
|
+
console.log(` [X] Failed to read: ${basename12(dirname30(pf))}`);
|
|
70243
70425
|
console.log();
|
|
70244
70426
|
}
|
|
70245
70427
|
}
|
|
@@ -70263,7 +70445,7 @@ async function handleStatus(target, options2) {
|
|
|
70263
70445
|
console.log(JSON.stringify(summary, null, 2));
|
|
70264
70446
|
return;
|
|
70265
70447
|
}
|
|
70266
|
-
const title = summary.title ??
|
|
70448
|
+
const title = summary.title ?? basename12(dirname30(planFile));
|
|
70267
70449
|
console.log();
|
|
70268
70450
|
console.log(import_picocolors24.default.bold(` ${title}`));
|
|
70269
70451
|
if (summary.status)
|
|
@@ -70289,7 +70471,7 @@ async function handleKanban(target, _options) {
|
|
|
70289
70471
|
}
|
|
70290
70472
|
|
|
70291
70473
|
// src/commands/plan/plan-write-handlers.ts
|
|
70292
|
-
import { basename as
|
|
70474
|
+
import { basename as basename13, relative as relative20, resolve as resolve27 } from "node:path";
|
|
70293
70475
|
init_output_manager();
|
|
70294
70476
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
70295
70477
|
async function handleCreate(target, options2) {
|
|
@@ -70325,7 +70507,7 @@ async function handleCreate(target, options2) {
|
|
|
70325
70507
|
const result = scaffoldPlan({
|
|
70326
70508
|
title: options2.title,
|
|
70327
70509
|
phases: phaseNames.map((name) => ({ name })),
|
|
70328
|
-
dir:
|
|
70510
|
+
dir: resolve27(dir),
|
|
70329
70511
|
priority,
|
|
70330
70512
|
issue: options2.issue ? Number(options2.issue) : undefined
|
|
70331
70513
|
});
|
|
@@ -70339,10 +70521,10 @@ async function handleCreate(target, options2) {
|
|
|
70339
70521
|
}
|
|
70340
70522
|
console.log();
|
|
70341
70523
|
console.log(import_picocolors25.default.bold(` [OK] Plan created: ${options2.title}`));
|
|
70342
|
-
console.log(` Directory: ${
|
|
70524
|
+
console.log(` Directory: ${resolve27(dir)}`);
|
|
70343
70525
|
console.log(` Phases: ${result.phaseFiles.length}`);
|
|
70344
70526
|
for (const f4 of result.phaseFiles) {
|
|
70345
|
-
console.log(` [ ] ${
|
|
70527
|
+
console.log(` [ ] ${basename13(f4)}`);
|
|
70346
70528
|
}
|
|
70347
70529
|
console.log();
|
|
70348
70530
|
}
|
|
@@ -70437,12 +70619,12 @@ async function handleAddPhase(target, options2) {
|
|
|
70437
70619
|
|
|
70438
70620
|
// src/commands/plan/plan-command.ts
|
|
70439
70621
|
function resolvePlanFile(target) {
|
|
70440
|
-
const t = target ?
|
|
70622
|
+
const t = target ? resolve28(target) : process.cwd();
|
|
70441
70623
|
if (existsSync48(t)) {
|
|
70442
70624
|
const stat13 = statSync5(t);
|
|
70443
70625
|
if (stat13.isFile())
|
|
70444
70626
|
return t;
|
|
70445
|
-
const candidate =
|
|
70627
|
+
const candidate = join105(t, "plan.md");
|
|
70446
70628
|
if (existsSync48(candidate))
|
|
70447
70629
|
return candidate;
|
|
70448
70630
|
}
|
|
@@ -70450,7 +70632,7 @@ function resolvePlanFile(target) {
|
|
|
70450
70632
|
let dir = process.cwd();
|
|
70451
70633
|
const root = parse2(dir).root;
|
|
70452
70634
|
while (dir !== root) {
|
|
70453
|
-
const candidate =
|
|
70635
|
+
const candidate = join105(dir, "plan.md");
|
|
70454
70636
|
if (existsSync48(candidate))
|
|
70455
70637
|
return candidate;
|
|
70456
70638
|
dir = dirname31(dir);
|
|
@@ -70501,7 +70683,7 @@ async function planCommand(action, target, options2) {
|
|
|
70501
70683
|
let resolvedTarget = target;
|
|
70502
70684
|
if (resolvedAction && !knownActions.has(resolvedAction)) {
|
|
70503
70685
|
const looksLikePath = resolvedAction.includes("/") || resolvedAction.includes("\\") || resolvedAction.endsWith(".md") || resolvedAction === "." || resolvedAction === "..";
|
|
70504
|
-
const existsOnDisk = !looksLikePath && existsSync48(
|
|
70686
|
+
const existsOnDisk = !looksLikePath && existsSync48(resolve28(resolvedAction));
|
|
70505
70687
|
if (looksLikePath || existsOnDisk) {
|
|
70506
70688
|
resolvedTarget = resolvedAction;
|
|
70507
70689
|
resolvedAction = undefined;
|
|
@@ -70540,7 +70722,7 @@ async function planCommand(action, target, options2) {
|
|
|
70540
70722
|
}
|
|
70541
70723
|
// src/commands/projects/add-handler.ts
|
|
70542
70724
|
import { existsSync as existsSync49 } from "node:fs";
|
|
70543
|
-
import { resolve as
|
|
70725
|
+
import { resolve as resolve29 } from "node:path";
|
|
70544
70726
|
// src/domains/takumi-data/claude-projects-scanner.ts
|
|
70545
70727
|
init_logger();
|
|
70546
70728
|
// src/commands/projects/add-handler.ts
|
|
@@ -70549,7 +70731,7 @@ var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
|
70549
70731
|
async function handleAdd(projectPath, options2) {
|
|
70550
70732
|
logger.debug(`Adding project: ${projectPath}, options: ${JSON.stringify(options2)}`);
|
|
70551
70733
|
intro("Add Project");
|
|
70552
|
-
const absolutePath =
|
|
70734
|
+
const absolutePath = resolve29(projectPath);
|
|
70553
70735
|
if (!existsSync49(absolutePath)) {
|
|
70554
70736
|
log.error(`Path does not exist: ${absolutePath}`);
|
|
70555
70737
|
process.exitCode = 1;
|
|
@@ -70721,23 +70903,23 @@ init_logger();
|
|
|
70721
70903
|
init_logger();
|
|
70722
70904
|
|
|
70723
70905
|
// src/commands/telemetry/shared.ts
|
|
70724
|
-
import { existsSync as existsSync50, readFileSync as
|
|
70906
|
+
import { existsSync as existsSync50, readFileSync as readFileSync16, readdirSync as readdirSync6 } from "node:fs";
|
|
70725
70907
|
import { homedir as homedir24 } from "node:os";
|
|
70726
|
-
import { join as
|
|
70908
|
+
import { join as join106 } from "node:path";
|
|
70727
70909
|
init_token_store();
|
|
70728
70910
|
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 =
|
|
70911
|
+
var USER_CACHE_PATH = join106(homedir24(), ".claude", "sk-user.json");
|
|
70912
|
+
var EVENT_BUFFER_DIR = join106(homedir24(), ".claude", "sk-events");
|
|
70913
|
+
var RATE_STATE_PATH = join106(homedir24(), ".claude", "sk-rate-state.json");
|
|
70914
|
+
var TAKUMI_MANIFEST_PATH = join106(homedir24(), ".claude", MANIFEST_FILENAME);
|
|
70915
|
+
var LEGACY_METADATA_PATH = join106(homedir24(), ".claude", LEGACY_MANIFEST_FILENAME);
|
|
70734
70916
|
var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
|
|
70735
70917
|
var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
|
|
70736
70918
|
function readUserCache() {
|
|
70737
70919
|
try {
|
|
70738
70920
|
if (!existsSync50(USER_CACHE_PATH))
|
|
70739
70921
|
return null;
|
|
70740
|
-
const parsed = JSON.parse(
|
|
70922
|
+
const parsed = JSON.parse(readFileSync16(USER_CACHE_PATH, "utf8"));
|
|
70741
70923
|
if (!parsed || typeof parsed !== "object")
|
|
70742
70924
|
return null;
|
|
70743
70925
|
return parsed;
|
|
@@ -70771,9 +70953,9 @@ function readTelemetryConfig() {
|
|
|
70771
70953
|
const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
|
|
70772
70954
|
let metadata = null;
|
|
70773
70955
|
try {
|
|
70774
|
-
const resolved = findManifestPathSync(
|
|
70956
|
+
const resolved = findManifestPathSync(join106(homedir24(), ".claude"));
|
|
70775
70957
|
if (resolved) {
|
|
70776
|
-
metadata = JSON.parse(
|
|
70958
|
+
metadata = JSON.parse(readFileSync16(resolved.path, "utf8"));
|
|
70777
70959
|
}
|
|
70778
70960
|
} catch {
|
|
70779
70961
|
metadata = null;
|
|
@@ -70817,13 +70999,13 @@ async function handleDisable() {
|
|
|
70817
70999
|
}
|
|
70818
71000
|
// src/commands/telemetry/phases/purge-local-handler.ts
|
|
70819
71001
|
init_logger();
|
|
70820
|
-
import { existsSync as existsSync51, readdirSync as readdirSync7, unlinkSync as
|
|
70821
|
-
import { join as
|
|
71002
|
+
import { existsSync as existsSync51, readdirSync as readdirSync7, unlinkSync as unlinkSync6 } from "node:fs";
|
|
71003
|
+
import { join as join107 } from "node:path";
|
|
70822
71004
|
function removeIfExists(path9) {
|
|
70823
71005
|
try {
|
|
70824
71006
|
if (!existsSync51(path9))
|
|
70825
71007
|
return false;
|
|
70826
|
-
|
|
71008
|
+
unlinkSync6(path9);
|
|
70827
71009
|
return true;
|
|
70828
71010
|
} catch {
|
|
70829
71011
|
return false;
|
|
@@ -70838,7 +71020,7 @@ function removeBufferFiles() {
|
|
|
70838
71020
|
if (!file.endsWith(".jsonl"))
|
|
70839
71021
|
continue;
|
|
70840
71022
|
try {
|
|
70841
|
-
|
|
71023
|
+
unlinkSync6(join107(EVENT_BUFFER_DIR, file));
|
|
70842
71024
|
count += 1;
|
|
70843
71025
|
} catch {}
|
|
70844
71026
|
}
|
|
@@ -71064,13 +71246,13 @@ async function detectInstallations() {
|
|
|
71064
71246
|
|
|
71065
71247
|
// src/commands/uninstall/removal-handler.ts
|
|
71066
71248
|
import { readdirSync as readdirSync9, rmSync as rmSync6 } from "node:fs";
|
|
71067
|
-
import { join as
|
|
71249
|
+
import { join as join109, resolve as resolve30, sep as sep8 } from "node:path";
|
|
71068
71250
|
init_logger();
|
|
71069
71251
|
var import_fs_extra39 = __toESM(require_lib(), 1);
|
|
71070
71252
|
|
|
71071
71253
|
// src/commands/uninstall/analysis-handler.ts
|
|
71072
71254
|
import { existsSync as existsSync52, readdirSync as readdirSync8, rmSync as rmSync5 } from "node:fs";
|
|
71073
|
-
import { dirname as dirname32, join as
|
|
71255
|
+
import { dirname as dirname32, join as join108 } from "node:path";
|
|
71074
71256
|
init_logger();
|
|
71075
71257
|
init_takumi_constants();
|
|
71076
71258
|
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
@@ -71126,7 +71308,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
71126
71308
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
71127
71309
|
const kitFiles = metadata.kits[kit].files || [];
|
|
71128
71310
|
for (const trackedFile of kitFiles) {
|
|
71129
|
-
const filePath =
|
|
71311
|
+
const filePath = join108(installation.path, trackedFile.path);
|
|
71130
71312
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
71131
71313
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
71132
71314
|
continue;
|
|
@@ -71158,7 +71340,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
71158
71340
|
return result;
|
|
71159
71341
|
}
|
|
71160
71342
|
for (const trackedFile of allTrackedFiles) {
|
|
71161
|
-
const filePath =
|
|
71343
|
+
const filePath = join108(installation.path, trackedFile.path);
|
|
71162
71344
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
71163
71345
|
if (!ownershipResult.exists)
|
|
71164
71346
|
continue;
|
|
@@ -71214,8 +71396,8 @@ async function isDirectory(filePath) {
|
|
|
71214
71396
|
}
|
|
71215
71397
|
async function isPathSafeToRemove(filePath, baseDir) {
|
|
71216
71398
|
try {
|
|
71217
|
-
const resolvedPath =
|
|
71218
|
-
const resolvedBase =
|
|
71399
|
+
const resolvedPath = resolve30(filePath);
|
|
71400
|
+
const resolvedBase = resolve30(baseDir);
|
|
71219
71401
|
if (!resolvedPath.startsWith(resolvedBase + sep8) && resolvedPath !== resolvedBase) {
|
|
71220
71402
|
logger.debug(`Path outside installation directory: ${filePath}`);
|
|
71221
71403
|
return false;
|
|
@@ -71223,7 +71405,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
71223
71405
|
const stats = await import_fs_extra39.lstat(filePath);
|
|
71224
71406
|
if (stats.isSymbolicLink()) {
|
|
71225
71407
|
const realPath = await import_fs_extra39.realpath(filePath);
|
|
71226
|
-
const resolvedReal =
|
|
71408
|
+
const resolvedReal = resolve30(realPath);
|
|
71227
71409
|
if (!resolvedReal.startsWith(resolvedBase + sep8) && resolvedReal !== resolvedBase) {
|
|
71228
71410
|
logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
|
|
71229
71411
|
return false;
|
|
@@ -71257,7 +71439,7 @@ async function removeInstallations(installations, options2) {
|
|
|
71257
71439
|
let removedCount = 0;
|
|
71258
71440
|
let cleanedDirs = 0;
|
|
71259
71441
|
for (const item of analysis.toDelete) {
|
|
71260
|
-
const filePath =
|
|
71442
|
+
const filePath = join109(installation.path, item.path);
|
|
71261
71443
|
if (!await import_fs_extra39.pathExists(filePath))
|
|
71262
71444
|
continue;
|
|
71263
71445
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -71625,7 +71807,7 @@ var import_fs_extra40 = __toESM(require_lib(), 1);
|
|
|
71625
71807
|
// package.json
|
|
71626
71808
|
var package_default = {
|
|
71627
71809
|
name: "@sunasteriskrnd/takumi",
|
|
71628
|
-
version: "1.0.0-dev.
|
|
71810
|
+
version: "1.0.0-dev.15",
|
|
71629
71811
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
71630
71812
|
type: "module",
|
|
71631
71813
|
repository: {
|
|
@@ -71938,12 +72120,12 @@ async function promptKitUpdate(beta, yes, deps) {
|
|
|
71938
72120
|
args.push("--beta");
|
|
71939
72121
|
const displayCmd = `tkm ${args.join(" ")}`;
|
|
71940
72122
|
logger.info(`Running: ${displayCmd}`);
|
|
71941
|
-
const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((
|
|
72123
|
+
const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((resolve31) => {
|
|
71942
72124
|
const child = spawn2("tkm", spawnArgs, { stdio: "inherit", shell: true });
|
|
71943
|
-
child.on("close", (code) =>
|
|
72125
|
+
child.on("close", (code) => resolve31(code ?? 1));
|
|
71944
72126
|
child.on("error", (err) => {
|
|
71945
72127
|
logger.verbose(`Failed to spawn tkm init: ${err.message}`);
|
|
71946
|
-
|
|
72128
|
+
resolve31(1);
|
|
71947
72129
|
});
|
|
71948
72130
|
}));
|
|
71949
72131
|
const exitCode = await spawnFn(args);
|
|
@@ -72180,7 +72362,7 @@ async function fetchReleasesForKit(kitType, options2) {
|
|
|
72180
72362
|
const filtered = options2.includePrereleases ? releases : releases.filter((r2) => !r2.draft && !r2.prerelease);
|
|
72181
72363
|
return filtered.map((r2) => githubReleaseToEntry(r2, kitType));
|
|
72182
72364
|
}
|
|
72183
|
-
const worker = new WorkerSource(getServerUrl(), kitType);
|
|
72365
|
+
const worker = new WorkerSource(getServerUrl(), backendIdOf(kitType));
|
|
72184
72366
|
const entries = await worker.fetchReleaseList(options2.includePrereleases);
|
|
72185
72367
|
return entries.slice(0, options2.limit);
|
|
72186
72368
|
}
|
|
@@ -72232,7 +72414,7 @@ init_logger();
|
|
|
72232
72414
|
import { existsSync as existsSync58 } from "node:fs";
|
|
72233
72415
|
import { rm as rm10 } from "node:fs/promises";
|
|
72234
72416
|
import { homedir as homedir26 } from "node:os";
|
|
72235
|
-
import { join as
|
|
72417
|
+
import { join as join116 } from "node:path";
|
|
72236
72418
|
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
72237
72419
|
|
|
72238
72420
|
// src/commands/watch/phases/implementation-runner.ts
|
|
@@ -72301,7 +72483,7 @@ function getDisclaimerMarker() {
|
|
|
72301
72483
|
return AI_DISCLAIMER;
|
|
72302
72484
|
}
|
|
72303
72485
|
function spawnAndCollect2(command, args) {
|
|
72304
|
-
return new Promise((
|
|
72486
|
+
return new Promise((resolve31, reject) => {
|
|
72305
72487
|
const child = spawn4(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
72306
72488
|
const chunks = [];
|
|
72307
72489
|
const stderrChunks = [];
|
|
@@ -72314,7 +72496,7 @@ function spawnAndCollect2(command, args) {
|
|
|
72314
72496
|
reject(new Error(`${command} exited with code ${code}: ${stderr}`));
|
|
72315
72497
|
return;
|
|
72316
72498
|
}
|
|
72317
|
-
|
|
72499
|
+
resolve31(Buffer.concat(chunks).toString("utf-8"));
|
|
72318
72500
|
});
|
|
72319
72501
|
});
|
|
72320
72502
|
}
|
|
@@ -72414,7 +72596,7 @@ function formatResponse(content) {
|
|
|
72414
72596
|
return disclaimer + formatted;
|
|
72415
72597
|
}
|
|
72416
72598
|
async function postViaGh(owner, repo, issueNumber, body) {
|
|
72417
|
-
return new Promise((
|
|
72599
|
+
return new Promise((resolve31, reject) => {
|
|
72418
72600
|
const args = [
|
|
72419
72601
|
"issue",
|
|
72420
72602
|
"comment",
|
|
@@ -72436,7 +72618,7 @@ async function postViaGh(owner, repo, issueNumber, body) {
|
|
|
72436
72618
|
reject(new Error(`gh exited with code ${code}: ${stderr}`));
|
|
72437
72619
|
return;
|
|
72438
72620
|
}
|
|
72439
|
-
|
|
72621
|
+
resolve31();
|
|
72440
72622
|
});
|
|
72441
72623
|
});
|
|
72442
72624
|
}
|
|
@@ -72554,7 +72736,7 @@ After completing the implementation:
|
|
|
72554
72736
|
"--allowedTools",
|
|
72555
72737
|
tools
|
|
72556
72738
|
];
|
|
72557
|
-
await new Promise((
|
|
72739
|
+
await new Promise((resolve31, reject) => {
|
|
72558
72740
|
const child = spawn6("claude", args, { cwd: cwd2, stdio: ["pipe", "pipe", "pipe"], detached: false });
|
|
72559
72741
|
child.stdin.write(prompt);
|
|
72560
72742
|
child.stdin.end();
|
|
@@ -72579,7 +72761,7 @@ After completing the implementation:
|
|
|
72579
72761
|
reject(new Error(`Claude exited ${code}: ${stderr.slice(0, 500)}`));
|
|
72580
72762
|
return;
|
|
72581
72763
|
}
|
|
72582
|
-
|
|
72764
|
+
resolve31();
|
|
72583
72765
|
});
|
|
72584
72766
|
});
|
|
72585
72767
|
}
|
|
@@ -72722,7 +72904,7 @@ function checkRateLimit2(processedThisHour, maxPerHour) {
|
|
|
72722
72904
|
return processedThisHour < maxPerHour;
|
|
72723
72905
|
}
|
|
72724
72906
|
function spawnAndCollect3(command, args) {
|
|
72725
|
-
return new Promise((
|
|
72907
|
+
return new Promise((resolve31, reject) => {
|
|
72726
72908
|
const child = spawn7(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
72727
72909
|
const chunks = [];
|
|
72728
72910
|
const stderrChunks = [];
|
|
@@ -72735,14 +72917,14 @@ function spawnAndCollect3(command, args) {
|
|
|
72735
72917
|
reject(new Error(`${command} exited with code ${code}: ${stderr}`));
|
|
72736
72918
|
return;
|
|
72737
72919
|
}
|
|
72738
|
-
|
|
72920
|
+
resolve31(Buffer.concat(chunks).toString("utf-8"));
|
|
72739
72921
|
});
|
|
72740
72922
|
});
|
|
72741
72923
|
}
|
|
72742
72924
|
|
|
72743
72925
|
// src/commands/watch/phases/issue-processor.ts
|
|
72744
72926
|
import { mkdir as mkdir29, writeFile as writeFile33 } from "node:fs/promises";
|
|
72745
|
-
import { join as
|
|
72927
|
+
import { join as join112 } from "node:path";
|
|
72746
72928
|
|
|
72747
72929
|
// src/commands/watch/phases/approval-detector.ts
|
|
72748
72930
|
init_logger();
|
|
@@ -72784,7 +72966,7 @@ async function invokeClaude(options2) {
|
|
|
72784
72966
|
return collectClaudeOutput(child, options2.timeoutSec, verbose);
|
|
72785
72967
|
}
|
|
72786
72968
|
function collectClaudeOutput(child, timeoutSec, verbose = false) {
|
|
72787
|
-
return new Promise((
|
|
72969
|
+
return new Promise((resolve31, reject) => {
|
|
72788
72970
|
const chunks = [];
|
|
72789
72971
|
const stderrChunks = [];
|
|
72790
72972
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -72814,7 +72996,7 @@ function collectClaudeOutput(child, timeoutSec, verbose = false) {
|
|
|
72814
72996
|
reject(new Error(`Claude exited with code ${code}: ${stderr}`));
|
|
72815
72997
|
return;
|
|
72816
72998
|
}
|
|
72817
|
-
|
|
72999
|
+
resolve31(verbose ? parseStreamJsonOutput(stdout2) : parseClaudeOutput(stdout2));
|
|
72818
73000
|
});
|
|
72819
73001
|
});
|
|
72820
73002
|
}
|
|
@@ -73117,9 +73299,9 @@ async function checkAwaitingApproval(state, setup, options2, watchLog, projectDi
|
|
|
73117
73299
|
|
|
73118
73300
|
// src/commands/watch/phases/plan-dir-finder.ts
|
|
73119
73301
|
import { readdir as readdir32, stat as stat13 } from "node:fs/promises";
|
|
73120
|
-
import { join as
|
|
73302
|
+
import { join as join111 } from "node:path";
|
|
73121
73303
|
async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
73122
|
-
const plansRoot =
|
|
73304
|
+
const plansRoot = join111(cwd2, "plans");
|
|
73123
73305
|
try {
|
|
73124
73306
|
const entries = await readdir32(plansRoot);
|
|
73125
73307
|
const tenMinAgo = Date.now() - 10 * 60 * 1000;
|
|
@@ -73128,14 +73310,14 @@ async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
|
73128
73310
|
for (const entry of entries) {
|
|
73129
73311
|
if (entry === "watch" || entry === "reports" || entry === "visuals")
|
|
73130
73312
|
continue;
|
|
73131
|
-
const dirPath =
|
|
73313
|
+
const dirPath = join111(plansRoot, entry);
|
|
73132
73314
|
const dirStat = await stat13(dirPath);
|
|
73133
73315
|
if (!dirStat.isDirectory())
|
|
73134
73316
|
continue;
|
|
73135
73317
|
if (dirStat.mtimeMs < tenMinAgo)
|
|
73136
73318
|
continue;
|
|
73137
73319
|
try {
|
|
73138
|
-
await stat13(
|
|
73320
|
+
await stat13(join111(dirPath, "plan.md"));
|
|
73139
73321
|
} catch {
|
|
73140
73322
|
continue;
|
|
73141
73323
|
}
|
|
@@ -73366,13 +73548,13 @@ async function handlePlanGeneration(issue, state, config, setup, options2, watch
|
|
|
73366
73548
|
stats.plansCreated++;
|
|
73367
73549
|
const detectedPlanDir = await findRecentPlanDir(projectDir, issue.number, watchLog);
|
|
73368
73550
|
if (detectedPlanDir) {
|
|
73369
|
-
state.activeIssues[numStr].planPath =
|
|
73551
|
+
state.activeIssues[numStr].planPath = join112(detectedPlanDir, "plan.md");
|
|
73370
73552
|
watchLog.info(`Plan directory detected: ${detectedPlanDir}`);
|
|
73371
73553
|
} else {
|
|
73372
73554
|
try {
|
|
73373
|
-
const planDir =
|
|
73555
|
+
const planDir = join112(projectDir, "plans", "watch");
|
|
73374
73556
|
await mkdir29(planDir, { recursive: true });
|
|
73375
|
-
const planFilePath =
|
|
73557
|
+
const planFilePath = join112(planDir, `issue-${issue.number}-plan.md`);
|
|
73376
73558
|
await writeFile33(planFilePath, planResult.planText, "utf-8");
|
|
73377
73559
|
state.activeIssues[numStr].planPath = planFilePath;
|
|
73378
73560
|
watchLog.info(`Plan saved (fallback) to ${planFilePath}`);
|
|
@@ -73677,18 +73859,18 @@ init_logger();
|
|
|
73677
73859
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
73678
73860
|
import { existsSync as existsSync55 } from "node:fs";
|
|
73679
73861
|
import { readdir as readdir33, stat as stat14 } from "node:fs/promises";
|
|
73680
|
-
import { join as
|
|
73862
|
+
import { join as join113 } from "node:path";
|
|
73681
73863
|
async function scanForRepos(parentDir) {
|
|
73682
73864
|
const repos = [];
|
|
73683
73865
|
const entries = await readdir33(parentDir);
|
|
73684
73866
|
for (const entry of entries) {
|
|
73685
73867
|
if (entry.startsWith("."))
|
|
73686
73868
|
continue;
|
|
73687
|
-
const fullPath =
|
|
73869
|
+
const fullPath = join113(parentDir, entry);
|
|
73688
73870
|
const entryStat = await stat14(fullPath);
|
|
73689
73871
|
if (!entryStat.isDirectory())
|
|
73690
73872
|
continue;
|
|
73691
|
-
const gitDir =
|
|
73873
|
+
const gitDir = join113(fullPath, ".git");
|
|
73692
73874
|
if (!existsSync55(gitDir))
|
|
73693
73875
|
continue;
|
|
73694
73876
|
const result = spawnSync5("gh", ["repo", "view", "--json", "owner,name"], {
|
|
@@ -73715,7 +73897,7 @@ init_logger();
|
|
|
73715
73897
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
73716
73898
|
import { existsSync as existsSync56 } from "node:fs";
|
|
73717
73899
|
import { homedir as homedir25 } from "node:os";
|
|
73718
|
-
import { join as
|
|
73900
|
+
import { join as join114 } from "node:path";
|
|
73719
73901
|
async function validateSetup(cwd2) {
|
|
73720
73902
|
const workDir = cwd2 ?? process.cwd();
|
|
73721
73903
|
const ghVersion = spawnSync6("gh", ["--version"], { encoding: "utf-8", timeout: 1e4 });
|
|
@@ -73746,10 +73928,10 @@ Run this command from a directory with a GitHub remote.`);
|
|
|
73746
73928
|
} catch {
|
|
73747
73929
|
throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
|
|
73748
73930
|
}
|
|
73749
|
-
const skillsPath =
|
|
73931
|
+
const skillsPath = join114(homedir25(), ".claude", "skills");
|
|
73750
73932
|
const skillsAvailable = existsSync56(skillsPath);
|
|
73751
73933
|
if (!skillsAvailable) {
|
|
73752
|
-
logger.warning(`
|
|
73934
|
+
logger.warning(`Core skills not found at ${skillsPath}`);
|
|
73753
73935
|
}
|
|
73754
73936
|
return {
|
|
73755
73937
|
repoOwner,
|
|
@@ -73765,7 +73947,7 @@ init_path_resolver();
|
|
|
73765
73947
|
import { createWriteStream as createWriteStream4, statSync as statSync6 } from "node:fs";
|
|
73766
73948
|
import { existsSync as existsSync57 } from "node:fs";
|
|
73767
73949
|
import { mkdir as mkdir31, rename as rename9 } from "node:fs/promises";
|
|
73768
|
-
import { join as
|
|
73950
|
+
import { join as join115 } from "node:path";
|
|
73769
73951
|
|
|
73770
73952
|
class WatchLogger {
|
|
73771
73953
|
logStream = null;
|
|
@@ -73773,7 +73955,7 @@ class WatchLogger {
|
|
|
73773
73955
|
logPath = null;
|
|
73774
73956
|
maxBytes;
|
|
73775
73957
|
constructor(logDir, maxBytes = 0) {
|
|
73776
|
-
this.logDir = logDir ??
|
|
73958
|
+
this.logDir = logDir ?? join115(PathResolver.getTakumiDir(), "logs");
|
|
73777
73959
|
this.maxBytes = maxBytes;
|
|
73778
73960
|
}
|
|
73779
73961
|
async init() {
|
|
@@ -73782,7 +73964,7 @@ class WatchLogger {
|
|
|
73782
73964
|
await mkdir31(this.logDir, { recursive: true });
|
|
73783
73965
|
}
|
|
73784
73966
|
const dateStr = formatDate(new Date);
|
|
73785
|
-
this.logPath =
|
|
73967
|
+
this.logPath = join115(this.logDir, `watch-${dateStr}.log`);
|
|
73786
73968
|
this.logStream = createWriteStream4(this.logPath, { flags: "a", mode: 384 });
|
|
73787
73969
|
} catch (error) {
|
|
73788
73970
|
logger.warning(`Cannot create watch log file: ${error instanceof Error ? error.message : "Unknown"}`);
|
|
@@ -73962,7 +74144,7 @@ async function watchCommand(options2) {
|
|
|
73962
74144
|
}
|
|
73963
74145
|
async function discoverRepos(options2, watchLog) {
|
|
73964
74146
|
const cwd2 = process.cwd();
|
|
73965
|
-
const isGitRepo = existsSync58(
|
|
74147
|
+
const isGitRepo = existsSync58(join116(cwd2, ".git"));
|
|
73966
74148
|
if (options2.force) {
|
|
73967
74149
|
await forceRemoveLock(watchLog);
|
|
73968
74150
|
}
|
|
@@ -74032,7 +74214,7 @@ async function resetState(state, projectDir, watchLog) {
|
|
|
74032
74214
|
watchLog.info(`Watch state reset (--force) for ${projectDir}`);
|
|
74033
74215
|
}
|
|
74034
74216
|
async function forceRemoveLock(watchLog) {
|
|
74035
|
-
const lockPath =
|
|
74217
|
+
const lockPath = join116(homedir26(), ".sunagentkit", "locks", `${LOCK_NAME}.lock`);
|
|
74036
74218
|
try {
|
|
74037
74219
|
await rm10(lockPath, { recursive: true, force: true });
|
|
74038
74220
|
watchLog.info("Removed existing lock file (--force)");
|
|
@@ -74071,18 +74253,18 @@ function formatQueueInfo(state) {
|
|
|
74071
74253
|
return "idle";
|
|
74072
74254
|
}
|
|
74073
74255
|
function sleep2(ms2) {
|
|
74074
|
-
return new Promise((
|
|
74256
|
+
return new Promise((resolve31) => setTimeout(resolve31, ms2));
|
|
74075
74257
|
}
|
|
74076
74258
|
// src/cli/command-registry.ts
|
|
74077
74259
|
init_logger();
|
|
74078
74260
|
function registerCommands(cli) {
|
|
74079
|
-
cli.command("new", "Bootstrap a new Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (
|
|
74261
|
+
cli.command("new", "Bootstrap a new Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (core, extras). Repeat the flag to install multiple kits, e.g. --kit core --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /sk: prefix to all slash commands by moving them to commands/sk/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").option("--local", "Use local monorepo as kit source (auto-detects from CLI location)").option("--use-gh", "Force GitHub release source (bypass Worker R2 proxy; default uses Worker)").action(async (options2) => {
|
|
74080
74262
|
if (options2.exclude && !Array.isArray(options2.exclude)) {
|
|
74081
74263
|
options2.exclude = [options2.exclude];
|
|
74082
74264
|
}
|
|
74083
74265
|
await newCommand(options2);
|
|
74084
74266
|
});
|
|
74085
|
-
cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (
|
|
74267
|
+
cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (core, extras). Repeat the flag to install multiple kits, e.g. --kit core --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove SK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /sk: prefix to all slash commands by moving them to commands/sk/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").option("--local", "Use local monorepo as kit source (auto-detects from CLI location)").option("--use-gh", "Force GitHub release source (bypass Worker R2 proxy; default uses Worker)").option("-a, --agent <agents...>", "Target agents (claude-code, codex). Default: claude-code").action(async (options2) => {
|
|
74086
74268
|
if (options2.exclude && !Array.isArray(options2.exclude)) {
|
|
74087
74269
|
options2.exclude = [options2.exclude];
|
|
74088
74270
|
}
|
|
@@ -74124,13 +74306,13 @@ function registerCommands(cli) {
|
|
|
74124
74306
|
process.exit(1);
|
|
74125
74307
|
}
|
|
74126
74308
|
});
|
|
74127
|
-
cli.command("versions", "List available versions of Takumi repositories").option("--kit <kit>", "Filter by specific kit (
|
|
74309
|
+
cli.command("versions", "List available versions of Takumi repositories").option("--kit <kit>", "Filter by specific kit (core)").option("--limit <limit>", "Number of releases to show (default: 30)").option("--all", "Show the beta channel (prereleases only) instead of the stable channel. " + "On --use-gh, returns all release types interleaved.").option("--use-gh", "Use legacy GitHub release source (requires gh CLI)").action(async (options2) => {
|
|
74128
74310
|
await versionCommand(options2);
|
|
74129
74311
|
});
|
|
74130
74312
|
cli.command("doctor", "Comprehensive health check for Takumi").option("--report", "Generate shareable diagnostic report").option("--fix", "Auto-fix all fixable issues").option("--check-only", "CI mode: no prompts, exit 1 on failures").option("--json", "Output JSON format").option("--full", "Include extended priority checks (slower)").action(async (options2) => {
|
|
74131
74313
|
await doctorCommand(options2);
|
|
74132
74314
|
});
|
|
74133
|
-
cli.command("uninstall", "Remove Takumi installations").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("-l, --local", "Uninstall only local installation (current project)").option("-g, --global", "Uninstall only global installation (~/.claude/)").option("-A, --all", "Uninstall from both local and global locations").option("-k, --kit <type>", "Uninstall specific kit only (
|
|
74315
|
+
cli.command("uninstall", "Remove Takumi installations").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("-l, --local", "Uninstall only local installation (current project)").option("-g, --global", "Uninstall only global installation (~/.claude/)").option("-A, --all", "Uninstall from both local and global locations").option("-k, --kit <type>", "Uninstall specific kit only (core)").option("--dry-run", "Preview what would be removed without deleting").option("--force-overwrite", "Delete even user-modified files (requires confirmation)").action(async (options2) => {
|
|
74134
74316
|
await uninstallCommand(options2);
|
|
74135
74317
|
});
|
|
74136
74318
|
cli.command("content [action] [id]", "Multi-channel content automation (start|stop|status|logs|setup|queue|approve|reject)").option("--dry-run", "Generate content without publishing").option("--verbose", "Enable verbose logging").option("--force", "Kill existing process and start fresh").option("--tail", "Follow log output (for logs action)").option("--reason <reason>", "Rejection reason (for reject action)").action(async (action, id, options2) => {
|
|
@@ -74212,8 +74394,8 @@ function registerCommands(cli) {
|
|
|
74212
74394
|
}
|
|
74213
74395
|
|
|
74214
74396
|
// src/cli/version-display.ts
|
|
74215
|
-
import { readFileSync as
|
|
74216
|
-
import { join as
|
|
74397
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
74398
|
+
import { join as join128 } from "node:path";
|
|
74217
74399
|
init_help_banner();
|
|
74218
74400
|
// src/domains/versioning/checking/kit-version-checker.ts
|
|
74219
74401
|
init_github_client();
|
|
@@ -74225,14 +74407,14 @@ init_logger();
|
|
|
74225
74407
|
init_path_resolver();
|
|
74226
74408
|
import { existsSync as existsSync69 } from "node:fs";
|
|
74227
74409
|
import { mkdir as mkdir32, readFile as readFile47, writeFile as writeFile36 } from "node:fs/promises";
|
|
74228
|
-
import { join as
|
|
74410
|
+
import { join as join127 } from "node:path";
|
|
74229
74411
|
|
|
74230
74412
|
class VersionCacheManager {
|
|
74231
74413
|
static CACHE_FILENAME = "version-check.json";
|
|
74232
74414
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
74233
74415
|
static getCacheFile() {
|
|
74234
74416
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
74235
|
-
return
|
|
74417
|
+
return join127(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
74236
74418
|
}
|
|
74237
74419
|
static async load() {
|
|
74238
74420
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -74295,7 +74477,7 @@ class VersionCacheManager {
|
|
|
74295
74477
|
async function fetchLatestRelease(currentVersion) {
|
|
74296
74478
|
try {
|
|
74297
74479
|
const githubClient = new GitHubClient;
|
|
74298
|
-
const kit = AVAILABLE_KITS.
|
|
74480
|
+
const kit = AVAILABLE_KITS.core;
|
|
74299
74481
|
const timeoutPromise = new Promise((_4, reject) => setTimeout(() => reject(new Error("Timeout")), 5000));
|
|
74300
74482
|
const releasePromise = githubClient.getLatestRelease(kit);
|
|
74301
74483
|
const release = await Promise.race([releasePromise, timeoutPromise]);
|
|
@@ -74525,7 +74707,7 @@ async function displayVersion() {
|
|
|
74525
74707
|
const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
|
|
74526
74708
|
if (!localSubdir)
|
|
74527
74709
|
continue;
|
|
74528
|
-
const localRoot =
|
|
74710
|
+
const localRoot = join128(process.cwd(), localSubdir);
|
|
74529
74711
|
if (localRoot === inst.globalRoot())
|
|
74530
74712
|
continue;
|
|
74531
74713
|
const resolved = findManifestPathSync(localRoot);
|
|
@@ -74535,7 +74717,7 @@ async function displayVersion() {
|
|
|
74535
74717
|
}
|
|
74536
74718
|
for (const { provider, path: metaPath } of localChecks) {
|
|
74537
74719
|
try {
|
|
74538
|
-
const rawMetadata = JSON.parse(
|
|
74720
|
+
const rawMetadata = JSON.parse(readFileSync21(metaPath, "utf-8"));
|
|
74539
74721
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
74540
74722
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
74541
74723
|
if (kitsDisplay) {
|
|
@@ -74555,7 +74737,7 @@ async function displayVersion() {
|
|
|
74555
74737
|
const resolved = findManifestPathSync(installPath);
|
|
74556
74738
|
if (resolved) {
|
|
74557
74739
|
try {
|
|
74558
|
-
const rawMetadata = JSON.parse(
|
|
74740
|
+
const rawMetadata = JSON.parse(readFileSync21(resolved.path, "utf-8"));
|
|
74559
74741
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
74560
74742
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
74561
74743
|
if (kitsDisplay) {
|