@sunasteriskrnd/takumi 1.0.0-dev.3 → 1.0.0-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +612 -695
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -36905,14 +36905,14 @@ var exports_monorepo_resolver = {};
|
|
|
36905
36905
|
__export(exports_monorepo_resolver, {
|
|
36906
36906
|
resolveMonorepoRoot: () => resolveMonorepoRoot
|
|
36907
36907
|
});
|
|
36908
|
-
import { existsSync as
|
|
36909
|
-
import { dirname as
|
|
36908
|
+
import { existsSync as existsSync29, readFileSync as readFileSync11 } from "node:fs";
|
|
36909
|
+
import { dirname as dirname14, join as join77, resolve as resolve10 } from "node:path";
|
|
36910
36910
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
36911
36911
|
function parseMetadataAt(metadataPath) {
|
|
36912
|
-
if (!
|
|
36912
|
+
if (!existsSync29(metadataPath))
|
|
36913
36913
|
return null;
|
|
36914
36914
|
try {
|
|
36915
|
-
const raw =
|
|
36915
|
+
const raw = readFileSync11(metadataPath, "utf-8");
|
|
36916
36916
|
const parsed = JSON.parse(raw);
|
|
36917
36917
|
if (typeof parsed.name !== "string" || typeof parsed.version !== "string" || !ACCEPTED_METADATA_NAMES.has(parsed.name)) {
|
|
36918
36918
|
return null;
|
|
@@ -36923,11 +36923,11 @@ function parseMetadataAt(metadataPath) {
|
|
|
36923
36923
|
}
|
|
36924
36924
|
}
|
|
36925
36925
|
function readSourceDirFromPackageJson(candidateRoot) {
|
|
36926
|
-
const packageJsonPath =
|
|
36927
|
-
if (!
|
|
36926
|
+
const packageJsonPath = join77(candidateRoot, "package.json");
|
|
36927
|
+
if (!existsSync29(packageJsonPath))
|
|
36928
36928
|
return null;
|
|
36929
36929
|
try {
|
|
36930
|
-
const parsed = JSON.parse(
|
|
36930
|
+
const parsed = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));
|
|
36931
36931
|
const kitCfg = parsed.takumi;
|
|
36932
36932
|
if (kitCfg && typeof kitCfg.sourceDir === "string" && kitCfg.sourceDir.length > 0) {
|
|
36933
36933
|
return kitCfg.sourceDir;
|
|
@@ -36936,7 +36936,7 @@ function readSourceDirFromPackageJson(candidateRoot) {
|
|
|
36936
36936
|
return null;
|
|
36937
36937
|
}
|
|
36938
36938
|
function tryReadAtCandidate(candidateRoot) {
|
|
36939
|
-
const flatMetadata = parseMetadataAt(
|
|
36939
|
+
const flatMetadata = parseMetadataAt(join77(candidateRoot, "metadata.json"));
|
|
36940
36940
|
if (flatMetadata) {
|
|
36941
36941
|
return {
|
|
36942
36942
|
root: candidateRoot,
|
|
@@ -36946,10 +36946,10 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
36946
36946
|
};
|
|
36947
36947
|
}
|
|
36948
36948
|
const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
|
|
36949
|
-
const nestedMetadata = parseMetadataAt(
|
|
36949
|
+
const nestedMetadata = parseMetadataAt(join77(candidateRoot, sourceDir, "metadata.json"));
|
|
36950
36950
|
if (nestedMetadata) {
|
|
36951
36951
|
return {
|
|
36952
|
-
root:
|
|
36952
|
+
root: join77(candidateRoot, sourceDir),
|
|
36953
36953
|
repoRoot: candidateRoot,
|
|
36954
36954
|
version: nestedMetadata.version,
|
|
36955
36955
|
name: nestedMetadata.name
|
|
@@ -36963,7 +36963,7 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
|
|
|
36963
36963
|
const result = tryReadAtCandidate(current);
|
|
36964
36964
|
if (result)
|
|
36965
36965
|
return result;
|
|
36966
|
-
const parent =
|
|
36966
|
+
const parent = dirname14(current);
|
|
36967
36967
|
if (parent === current)
|
|
36968
36968
|
break;
|
|
36969
36969
|
current = parent;
|
|
@@ -36973,13 +36973,13 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
|
|
|
36973
36973
|
function resolveMonorepoRoot() {
|
|
36974
36974
|
try {
|
|
36975
36975
|
const thisFile = fileURLToPath3(import.meta.url);
|
|
36976
|
-
const thisDir =
|
|
36976
|
+
const thisDir = dirname14(thisFile);
|
|
36977
36977
|
const result2 = walkUpForMetadata(thisDir);
|
|
36978
36978
|
if (result2)
|
|
36979
36979
|
return result2;
|
|
36980
36980
|
} catch {}
|
|
36981
36981
|
if (process.argv[1]) {
|
|
36982
|
-
const binDir =
|
|
36982
|
+
const binDir = dirname14(resolve10(process.argv[1]));
|
|
36983
36983
|
const result2 = walkUpForMetadata(binDir);
|
|
36984
36984
|
if (result2)
|
|
36985
36985
|
return result2;
|
|
@@ -37107,11 +37107,11 @@ __export(exports_worktree_manager, {
|
|
|
37107
37107
|
createWorktree: () => createWorktree,
|
|
37108
37108
|
cleanupAllWorktrees: () => cleanupAllWorktrees
|
|
37109
37109
|
});
|
|
37110
|
-
import { existsSync as
|
|
37110
|
+
import { existsSync as existsSync50 } from "node:fs";
|
|
37111
37111
|
import { readFile as readFile45, writeFile as writeFile31 } from "node:fs/promises";
|
|
37112
|
-
import { join as
|
|
37112
|
+
import { join as join107 } from "node:path";
|
|
37113
37113
|
async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
37114
|
-
const worktreePath =
|
|
37114
|
+
const worktreePath = join107(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
37115
37115
|
const branchName = `sk-watch/issue-${issueNumber}`;
|
|
37116
37116
|
await spawnAndCollect("git", ["fetch", "origin", baseBranch], projectDir).catch(() => {
|
|
37117
37117
|
logger.warning(`[worktree] Could not fetch origin/${baseBranch}, using local`);
|
|
@@ -37129,7 +37129,7 @@ async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
|
37129
37129
|
return worktreePath;
|
|
37130
37130
|
}
|
|
37131
37131
|
async function removeWorktree(projectDir, issueNumber) {
|
|
37132
|
-
const worktreePath =
|
|
37132
|
+
const worktreePath = join107(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
37133
37133
|
const branchName = `sk-watch/issue-${issueNumber}`;
|
|
37134
37134
|
try {
|
|
37135
37135
|
await spawnAndCollect("git", ["worktree", "remove", worktreePath, "--force"], projectDir);
|
|
@@ -37143,7 +37143,7 @@ async function listActiveWorktrees(projectDir) {
|
|
|
37143
37143
|
try {
|
|
37144
37144
|
const output2 = await spawnAndCollect("git", ["worktree", "list", "--porcelain"], projectDir);
|
|
37145
37145
|
const issueNumbers = [];
|
|
37146
|
-
const worktreePrefix =
|
|
37146
|
+
const worktreePrefix = join107(projectDir, WORKTREE_DIR, "issue-").replace(/\\/g, "/");
|
|
37147
37147
|
for (const line of output2.split(`
|
|
37148
37148
|
`)) {
|
|
37149
37149
|
if (line.startsWith("worktree ")) {
|
|
@@ -37171,9 +37171,9 @@ async function cleanupAllWorktrees(projectDir) {
|
|
|
37171
37171
|
await spawnAndCollect("git", ["worktree", "prune"], projectDir).catch(() => {});
|
|
37172
37172
|
}
|
|
37173
37173
|
async function ensureGitignore(projectDir) {
|
|
37174
|
-
const gitignorePath =
|
|
37174
|
+
const gitignorePath = join107(projectDir, ".gitignore");
|
|
37175
37175
|
try {
|
|
37176
|
-
const content =
|
|
37176
|
+
const content = existsSync50(gitignorePath) ? await readFile45(gitignorePath, "utf-8") : "";
|
|
37177
37177
|
if (!content.includes(".worktrees")) {
|
|
37178
37178
|
const newContent = content.endsWith(`
|
|
37179
37179
|
`) ? `${content}.worktrees/
|
|
@@ -37275,19 +37275,19 @@ var init_content_validator = __esm(() => {
|
|
|
37275
37275
|
|
|
37276
37276
|
// src/commands/content/phases/context-cache-manager.ts
|
|
37277
37277
|
import { createHash as createHash7 } from "node:crypto";
|
|
37278
|
-
import { existsSync as
|
|
37278
|
+
import { existsSync as existsSync56, mkdirSync as mkdirSync3, readFileSync as readFileSync16, readdirSync as readdirSync9, statSync as statSync7 } from "node:fs";
|
|
37279
37279
|
import { rename as rename8, writeFile as writeFile33 } from "node:fs/promises";
|
|
37280
|
-
import { homedir as
|
|
37281
|
-
import { basename as basename11, join as
|
|
37280
|
+
import { homedir as homedir25 } from "node:os";
|
|
37281
|
+
import { basename as basename11, join as join114 } from "node:path";
|
|
37282
37282
|
function getCachedContext(repoPath) {
|
|
37283
37283
|
const cachePath = getCacheFilePath(repoPath);
|
|
37284
|
-
if (!
|
|
37284
|
+
if (!existsSync56(cachePath))
|
|
37285
37285
|
return null;
|
|
37286
37286
|
try {
|
|
37287
|
-
const raw =
|
|
37287
|
+
const raw = readFileSync16(cachePath, "utf-8");
|
|
37288
37288
|
const cache2 = JSON.parse(raw);
|
|
37289
37289
|
const age = Date.now() - new Date(cache2.createdAt).getTime();
|
|
37290
|
-
if (age >=
|
|
37290
|
+
if (age >= CACHE_TTL_MS3)
|
|
37291
37291
|
return null;
|
|
37292
37292
|
const currentHash = computeSourceHash(repoPath);
|
|
37293
37293
|
if (currentHash !== cache2.sourceHash)
|
|
@@ -37298,8 +37298,8 @@ function getCachedContext(repoPath) {
|
|
|
37298
37298
|
}
|
|
37299
37299
|
}
|
|
37300
37300
|
async function saveCachedContext(repoPath, cache2) {
|
|
37301
|
-
if (!
|
|
37302
|
-
|
|
37301
|
+
if (!existsSync56(CACHE_DIR)) {
|
|
37302
|
+
mkdirSync3(CACHE_DIR, { recursive: true });
|
|
37303
37303
|
}
|
|
37304
37304
|
const cachePath = getCacheFilePath(repoPath);
|
|
37305
37305
|
const tmpPath = `${cachePath}.tmp`;
|
|
@@ -37321,25 +37321,25 @@ function computeSourceHash(repoPath) {
|
|
|
37321
37321
|
}
|
|
37322
37322
|
function getDocSourcePaths(repoPath) {
|
|
37323
37323
|
const paths = [];
|
|
37324
|
-
const docsDir =
|
|
37325
|
-
if (
|
|
37324
|
+
const docsDir = join114(repoPath, "docs");
|
|
37325
|
+
if (existsSync56(docsDir)) {
|
|
37326
37326
|
try {
|
|
37327
37327
|
const files = readdirSync9(docsDir);
|
|
37328
37328
|
for (const f4 of files) {
|
|
37329
37329
|
if (f4.endsWith(".md"))
|
|
37330
|
-
paths.push(
|
|
37330
|
+
paths.push(join114(docsDir, f4));
|
|
37331
37331
|
}
|
|
37332
37332
|
} catch {}
|
|
37333
37333
|
}
|
|
37334
|
-
const readme =
|
|
37335
|
-
if (
|
|
37334
|
+
const readme = join114(repoPath, "README.md");
|
|
37335
|
+
if (existsSync56(readme))
|
|
37336
37336
|
paths.push(readme);
|
|
37337
|
-
const stylesDir =
|
|
37338
|
-
if (
|
|
37337
|
+
const stylesDir = join114(repoPath, "assets", "writing-styles");
|
|
37338
|
+
if (existsSync56(stylesDir)) {
|
|
37339
37339
|
try {
|
|
37340
37340
|
const files = readdirSync9(stylesDir);
|
|
37341
37341
|
for (const f4 of files) {
|
|
37342
|
-
paths.push(
|
|
37342
|
+
paths.push(join114(stylesDir, f4));
|
|
37343
37343
|
}
|
|
37344
37344
|
} catch {}
|
|
37345
37345
|
}
|
|
@@ -37348,12 +37348,12 @@ function getDocSourcePaths(repoPath) {
|
|
|
37348
37348
|
function getCacheFilePath(repoPath) {
|
|
37349
37349
|
const repoName = basename11(repoPath).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
37350
37350
|
const pathHash = createHash7("sha256").update(repoPath).digest("hex").slice(0, 8);
|
|
37351
|
-
return
|
|
37351
|
+
return join114(CACHE_DIR, `${repoName}-${pathHash}-context-cache.json`);
|
|
37352
37352
|
}
|
|
37353
|
-
var CACHE_DIR,
|
|
37353
|
+
var CACHE_DIR, CACHE_TTL_MS3;
|
|
37354
37354
|
var init_context_cache_manager = __esm(() => {
|
|
37355
|
-
CACHE_DIR =
|
|
37356
|
-
|
|
37355
|
+
CACHE_DIR = join114(homedir25(), ".sunagentkit", "cache");
|
|
37356
|
+
CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
|
|
37357
37357
|
});
|
|
37358
37358
|
|
|
37359
37359
|
// src/commands/content/phases/db-queries-git-events.ts
|
|
@@ -37532,8 +37532,8 @@ function extractContentFromResponse(response) {
|
|
|
37532
37532
|
|
|
37533
37533
|
// src/commands/content/phases/docs-summarizer.ts
|
|
37534
37534
|
import { execSync as execSync6 } from "node:child_process";
|
|
37535
|
-
import { existsSync as
|
|
37536
|
-
import { join as
|
|
37535
|
+
import { existsSync as existsSync57, readFileSync as readFileSync17, readdirSync as readdirSync10 } from "node:fs";
|
|
37536
|
+
import { join as join115 } from "node:path";
|
|
37537
37537
|
async function summarizeProjectDocs(repoPath, contentLogger) {
|
|
37538
37538
|
const rawContent = collectRawDocs(repoPath);
|
|
37539
37539
|
if (rawContent.total.length < 200) {
|
|
@@ -37577,22 +37577,22 @@ async function summarizeProjectDocs(repoPath, contentLogger) {
|
|
|
37577
37577
|
function collectRawDocs(repoPath) {
|
|
37578
37578
|
let totalChars = 0;
|
|
37579
37579
|
const readCapped = (filePath, maxChars) => {
|
|
37580
|
-
if (!
|
|
37580
|
+
if (!existsSync57(filePath))
|
|
37581
37581
|
return "";
|
|
37582
37582
|
if (totalChars >= MAX_RAW_CONTENT_CHARS)
|
|
37583
37583
|
return "";
|
|
37584
|
-
const content =
|
|
37584
|
+
const content = readFileSync17(filePath, "utf-8");
|
|
37585
37585
|
const capped = content.slice(0, Math.min(maxChars, MAX_RAW_CONTENT_CHARS - totalChars));
|
|
37586
37586
|
totalChars += capped.length;
|
|
37587
37587
|
return capped;
|
|
37588
37588
|
};
|
|
37589
37589
|
const docsContent = [];
|
|
37590
|
-
const docsDir =
|
|
37591
|
-
if (
|
|
37590
|
+
const docsDir = join115(repoPath, "docs");
|
|
37591
|
+
if (existsSync57(docsDir)) {
|
|
37592
37592
|
try {
|
|
37593
37593
|
const files = readdirSync10(docsDir).filter((f4) => f4.endsWith(".md")).sort();
|
|
37594
37594
|
for (const f4 of files) {
|
|
37595
|
-
const content = readCapped(
|
|
37595
|
+
const content = readCapped(join115(docsDir, f4), 5000);
|
|
37596
37596
|
if (content) {
|
|
37597
37597
|
docsContent.push(`### ${f4}
|
|
37598
37598
|
${content}`);
|
|
@@ -37606,21 +37606,21 @@ ${content}`);
|
|
|
37606
37606
|
let brand = "";
|
|
37607
37607
|
const brandCandidates = ["docs/brand-guidelines.md", "docs/design-guidelines.md"];
|
|
37608
37608
|
for (const p2 of brandCandidates) {
|
|
37609
|
-
brand = readCapped(
|
|
37609
|
+
brand = readCapped(join115(repoPath, p2), 3000);
|
|
37610
37610
|
if (brand)
|
|
37611
37611
|
break;
|
|
37612
37612
|
}
|
|
37613
37613
|
let styles3 = "";
|
|
37614
|
-
const stylesDir =
|
|
37615
|
-
if (
|
|
37614
|
+
const stylesDir = join115(repoPath, "assets", "writing-styles");
|
|
37615
|
+
if (existsSync57(stylesDir)) {
|
|
37616
37616
|
try {
|
|
37617
37617
|
const files = readdirSync10(stylesDir).slice(0, 3);
|
|
37618
|
-
styles3 = files.map((f4) => readCapped(
|
|
37618
|
+
styles3 = files.map((f4) => readCapped(join115(stylesDir, f4), 1000)).filter(Boolean).join(`
|
|
37619
37619
|
|
|
37620
37620
|
`);
|
|
37621
37621
|
} catch {}
|
|
37622
37622
|
}
|
|
37623
|
-
const readme = readCapped(
|
|
37623
|
+
const readme = readCapped(join115(repoPath, "README.md"), 3000);
|
|
37624
37624
|
const total = [docs, brand, styles3, readme].join(`
|
|
37625
37625
|
`);
|
|
37626
37626
|
return { docs, brand, styles: styles3, readme, total };
|
|
@@ -37805,13 +37805,13 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
|
|
|
37805
37805
|
|
|
37806
37806
|
// src/commands/content/phases/photo-generator.ts
|
|
37807
37807
|
import { execSync as execSync7 } from "node:child_process";
|
|
37808
|
-
import { existsSync as
|
|
37809
|
-
import { homedir as
|
|
37810
|
-
import { join as
|
|
37808
|
+
import { existsSync as existsSync58, mkdirSync as mkdirSync4, readdirSync as readdirSync11 } from "node:fs";
|
|
37809
|
+
import { homedir as homedir26 } from "node:os";
|
|
37810
|
+
import { join as join116 } from "node:path";
|
|
37811
37811
|
async function generatePhoto(_content, context, config, platform10, contentId, contentLogger) {
|
|
37812
|
-
const mediaDir =
|
|
37813
|
-
if (!
|
|
37814
|
-
|
|
37812
|
+
const mediaDir = join116(config.contentDir.replace(/^~/, homedir26()), "media", String(contentId));
|
|
37813
|
+
if (!existsSync58(mediaDir)) {
|
|
37814
|
+
mkdirSync4(mediaDir, { recursive: true });
|
|
37815
37815
|
}
|
|
37816
37816
|
const prompt = buildPhotoPrompt(context, platform10);
|
|
37817
37817
|
const dimensions = platform10 === "facebook" ? { width: 1200, height: 630 } : { width: 1200, height: 675 };
|
|
@@ -37826,7 +37826,7 @@ async function generatePhoto(_content, context, config, platform10, contentId, c
|
|
|
37826
37826
|
const parsed = parseClaudeJsonOutput(result);
|
|
37827
37827
|
if (parsed && typeof parsed === "object" && "imagePath" in parsed) {
|
|
37828
37828
|
const imagePath = String(parsed.imagePath);
|
|
37829
|
-
if (
|
|
37829
|
+
if (existsSync58(imagePath)) {
|
|
37830
37830
|
return { path: imagePath, ...dimensions, format: "png" };
|
|
37831
37831
|
}
|
|
37832
37832
|
}
|
|
@@ -37834,7 +37834,7 @@ async function generatePhoto(_content, context, config, platform10, contentId, c
|
|
|
37834
37834
|
const imageFile = files.find((f4) => /\.(png|jpg|jpeg|webp)$/i.test(f4));
|
|
37835
37835
|
if (imageFile) {
|
|
37836
37836
|
const ext2 = imageFile.split(".").pop() ?? "png";
|
|
37837
|
-
return { path:
|
|
37837
|
+
return { path: join116(mediaDir, imageFile), ...dimensions, format: ext2 };
|
|
37838
37838
|
}
|
|
37839
37839
|
contentLogger.warn(`Photo generation produced no image for content ${contentId}`);
|
|
37840
37840
|
return null;
|
|
@@ -37922,9 +37922,9 @@ var init_content_creator = __esm(() => {
|
|
|
37922
37922
|
});
|
|
37923
37923
|
|
|
37924
37924
|
// src/commands/content/phases/content-logger.ts
|
|
37925
|
-
import { createWriteStream as createWriteStream4, existsSync as
|
|
37926
|
-
import { homedir as
|
|
37927
|
-
import { join as
|
|
37925
|
+
import { createWriteStream as createWriteStream4, existsSync as existsSync59, mkdirSync as mkdirSync5, statSync as statSync8 } from "node:fs";
|
|
37926
|
+
import { homedir as homedir27 } from "node:os";
|
|
37927
|
+
import { join as join117 } from "node:path";
|
|
37928
37928
|
|
|
37929
37929
|
class ContentLogger {
|
|
37930
37930
|
stream = null;
|
|
@@ -37932,12 +37932,12 @@ class ContentLogger {
|
|
|
37932
37932
|
logDir;
|
|
37933
37933
|
maxBytes;
|
|
37934
37934
|
constructor(maxBytes = 0) {
|
|
37935
|
-
this.logDir =
|
|
37935
|
+
this.logDir = join117(homedir27(), ".sunagentkit", "logs");
|
|
37936
37936
|
this.maxBytes = maxBytes;
|
|
37937
37937
|
}
|
|
37938
37938
|
init() {
|
|
37939
|
-
if (!
|
|
37940
|
-
|
|
37939
|
+
if (!existsSync59(this.logDir)) {
|
|
37940
|
+
mkdirSync5(this.logDir, { recursive: true });
|
|
37941
37941
|
}
|
|
37942
37942
|
this.rotateIfNeeded();
|
|
37943
37943
|
}
|
|
@@ -37964,7 +37964,7 @@ class ContentLogger {
|
|
|
37964
37964
|
}
|
|
37965
37965
|
}
|
|
37966
37966
|
getLogPath() {
|
|
37967
|
-
return
|
|
37967
|
+
return join117(this.logDir, `content-${this.getDateStr()}.log`);
|
|
37968
37968
|
}
|
|
37969
37969
|
write(level, message) {
|
|
37970
37970
|
this.rotateIfNeeded();
|
|
@@ -37981,18 +37981,18 @@ class ContentLogger {
|
|
|
37981
37981
|
if (dateStr !== this.currentDate) {
|
|
37982
37982
|
this.close();
|
|
37983
37983
|
this.currentDate = dateStr;
|
|
37984
|
-
const logPath =
|
|
37984
|
+
const logPath = join117(this.logDir, `content-${dateStr}.log`);
|
|
37985
37985
|
this.stream = createWriteStream4(logPath, { flags: "a", mode: 384 });
|
|
37986
37986
|
return;
|
|
37987
37987
|
}
|
|
37988
37988
|
if (this.maxBytes > 0 && this.stream) {
|
|
37989
|
-
const logPath =
|
|
37989
|
+
const logPath = join117(this.logDir, `content-${this.currentDate}.log`);
|
|
37990
37990
|
try {
|
|
37991
37991
|
const stat15 = statSync8(logPath);
|
|
37992
37992
|
if (stat15.size >= this.maxBytes) {
|
|
37993
37993
|
this.close();
|
|
37994
37994
|
const suffix = Date.now();
|
|
37995
|
-
const rotatedPath =
|
|
37995
|
+
const rotatedPath = join117(this.logDir, `content-${this.currentDate}-${suffix}.log`);
|
|
37996
37996
|
import("node:fs/promises").then(({ rename: rename9 }) => rename9(logPath, rotatedPath).catch(() => {}));
|
|
37997
37997
|
this.stream = createWriteStream4(logPath, { flags: "w", mode: 384 });
|
|
37998
37998
|
}
|
|
@@ -38029,8 +38029,8 @@ function openDatabase(dbPath) {
|
|
|
38029
38029
|
var init_sqlite_client = () => {};
|
|
38030
38030
|
|
|
38031
38031
|
// src/commands/content/phases/db-manager.ts
|
|
38032
|
-
import { existsSync as
|
|
38033
|
-
import { dirname as
|
|
38032
|
+
import { existsSync as existsSync60, mkdirSync as mkdirSync6 } from "node:fs";
|
|
38033
|
+
import { dirname as dirname30 } from "node:path";
|
|
38034
38034
|
function initDatabase(dbPath) {
|
|
38035
38035
|
ensureParentDir2(dbPath);
|
|
38036
38036
|
const db = openDatabase(dbPath);
|
|
@@ -38051,9 +38051,9 @@ function runRetentionCleanup(db, retentionDays = 90) {
|
|
|
38051
38051
|
db.prepare("DELETE FROM git_events WHERE processed = 1 AND created_at < ?").run(cutoff);
|
|
38052
38052
|
}
|
|
38053
38053
|
function ensureParentDir2(dbPath) {
|
|
38054
|
-
const dir =
|
|
38055
|
-
if (dir && !
|
|
38056
|
-
|
|
38054
|
+
const dir = dirname30(dbPath);
|
|
38055
|
+
if (dir && !existsSync60(dir)) {
|
|
38056
|
+
mkdirSync6(dir, { recursive: true });
|
|
38057
38057
|
}
|
|
38058
38058
|
}
|
|
38059
38059
|
function getCurrentSchemaVersion(db) {
|
|
@@ -38217,8 +38217,8 @@ function isNoiseCommit(title, author) {
|
|
|
38217
38217
|
|
|
38218
38218
|
// src/commands/content/phases/change-detector.ts
|
|
38219
38219
|
import { execSync as execSync9 } from "node:child_process";
|
|
38220
|
-
import { existsSync as
|
|
38221
|
-
import { join as
|
|
38220
|
+
import { existsSync as existsSync61, readFileSync as readFileSync18, readdirSync as readdirSync12, statSync as statSync9 } from "node:fs";
|
|
38221
|
+
import { join as join118 } from "node:path";
|
|
38222
38222
|
function detectCommits(repo, since) {
|
|
38223
38223
|
try {
|
|
38224
38224
|
const fetchUrl = sshToHttps(repo.remoteUrl);
|
|
@@ -38316,8 +38316,8 @@ function detectTags(repo, since) {
|
|
|
38316
38316
|
}
|
|
38317
38317
|
}
|
|
38318
38318
|
function detectCompletedPlans(repo, since) {
|
|
38319
|
-
const plansDir =
|
|
38320
|
-
if (!
|
|
38319
|
+
const plansDir = join118(repo.path, "plans");
|
|
38320
|
+
if (!existsSync61(plansDir))
|
|
38321
38321
|
return [];
|
|
38322
38322
|
const sinceMs = new Date(since).getTime();
|
|
38323
38323
|
const events = [];
|
|
@@ -38326,14 +38326,14 @@ function detectCompletedPlans(repo, since) {
|
|
|
38326
38326
|
for (const entry of entries) {
|
|
38327
38327
|
if (!entry.isDirectory())
|
|
38328
38328
|
continue;
|
|
38329
|
-
const planFile =
|
|
38330
|
-
if (!
|
|
38329
|
+
const planFile = join118(plansDir, entry.name, "plan.md");
|
|
38330
|
+
if (!existsSync61(planFile))
|
|
38331
38331
|
continue;
|
|
38332
38332
|
try {
|
|
38333
38333
|
const stat15 = statSync9(planFile);
|
|
38334
38334
|
if (stat15.mtimeMs < sinceMs)
|
|
38335
38335
|
continue;
|
|
38336
|
-
const content =
|
|
38336
|
+
const content = readFileSync18(planFile, "utf-8");
|
|
38337
38337
|
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
38338
38338
|
if (!frontmatterMatch)
|
|
38339
38339
|
continue;
|
|
@@ -38404,7 +38404,7 @@ function classifyCommit(event) {
|
|
|
38404
38404
|
// src/commands/content/phases/repo-discoverer.ts
|
|
38405
38405
|
import { execSync as execSync10 } from "node:child_process";
|
|
38406
38406
|
import { readdirSync as readdirSync13 } from "node:fs";
|
|
38407
|
-
import { join as
|
|
38407
|
+
import { join as join119 } from "node:path";
|
|
38408
38408
|
function discoverRepos2(cwd2) {
|
|
38409
38409
|
const repos = [];
|
|
38410
38410
|
if (isGitRepoRoot(cwd2)) {
|
|
@@ -38417,7 +38417,7 @@ function discoverRepos2(cwd2) {
|
|
|
38417
38417
|
for (const entry of entries) {
|
|
38418
38418
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
38419
38419
|
continue;
|
|
38420
|
-
const dirPath =
|
|
38420
|
+
const dirPath = join119(cwd2, entry.name);
|
|
38421
38421
|
if (isGitRepoRoot(dirPath)) {
|
|
38422
38422
|
const info = getRepoInfo(dirPath);
|
|
38423
38423
|
if (info)
|
|
@@ -38537,9 +38537,9 @@ var init_git_scanner = __esm(() => {
|
|
|
38537
38537
|
});
|
|
38538
38538
|
|
|
38539
38539
|
// src/commands/content/phases/platform-adapters/facebook-adapter.ts
|
|
38540
|
-
import { execFileSync as
|
|
38540
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
38541
38541
|
function runFbcli(args, timeoutMs = 30000) {
|
|
38542
|
-
return
|
|
38542
|
+
return execFileSync2("fbcli", [...args, "--json"], {
|
|
38543
38543
|
stdio: "pipe",
|
|
38544
38544
|
timeout: timeoutMs
|
|
38545
38545
|
}).toString();
|
|
@@ -38579,7 +38579,7 @@ class FacebookAdapter {
|
|
|
38579
38579
|
if (options2?.dryRun)
|
|
38580
38580
|
return dryRunResult();
|
|
38581
38581
|
try {
|
|
38582
|
-
const raw =
|
|
38582
|
+
const raw = execFileSync2("fbcli", ["post", "--json"], {
|
|
38583
38583
|
input: text,
|
|
38584
38584
|
stdio: ["pipe", "pipe", "pipe"],
|
|
38585
38585
|
timeout: 30000
|
|
@@ -38604,7 +38604,7 @@ class FacebookAdapter {
|
|
|
38604
38604
|
if (options2?.dryRun)
|
|
38605
38605
|
return dryRunResult();
|
|
38606
38606
|
try {
|
|
38607
|
-
const raw =
|
|
38607
|
+
const raw = execFileSync2("fbcli", ["post", "-i", mediaPath, "--json"], {
|
|
38608
38608
|
input: text,
|
|
38609
38609
|
stdio: ["pipe", "pipe", "pipe"],
|
|
38610
38610
|
timeout: 60000
|
|
@@ -39084,9 +39084,9 @@ var init_types3 = __esm(() => {
|
|
|
39084
39084
|
|
|
39085
39085
|
// src/commands/content/phases/state-manager.ts
|
|
39086
39086
|
import { readFile as readFile47, rename as rename9, writeFile as writeFile34 } from "node:fs/promises";
|
|
39087
|
-
import { join as
|
|
39087
|
+
import { join as join120 } from "node:path";
|
|
39088
39088
|
async function loadContentConfig(projectDir) {
|
|
39089
|
-
const configPath =
|
|
39089
|
+
const configPath = join120(projectDir, TAKUMI_CONFIG_FILE2);
|
|
39090
39090
|
try {
|
|
39091
39091
|
const raw = await readFile47(configPath, "utf-8");
|
|
39092
39092
|
const json = JSON.parse(raw);
|
|
@@ -39096,13 +39096,13 @@ async function loadContentConfig(projectDir) {
|
|
|
39096
39096
|
}
|
|
39097
39097
|
}
|
|
39098
39098
|
async function saveContentConfig(projectDir, config) {
|
|
39099
|
-
const configPath =
|
|
39099
|
+
const configPath = join120(projectDir, TAKUMI_CONFIG_FILE2);
|
|
39100
39100
|
const json = await readJsonSafe(configPath);
|
|
39101
39101
|
json.content = { ...json.content, ...config };
|
|
39102
39102
|
await atomicWrite(configPath, json);
|
|
39103
39103
|
}
|
|
39104
39104
|
async function loadContentState(projectDir) {
|
|
39105
|
-
const configPath =
|
|
39105
|
+
const configPath = join120(projectDir, TAKUMI_CONFIG_FILE2);
|
|
39106
39106
|
try {
|
|
39107
39107
|
const raw = await readFile47(configPath, "utf-8");
|
|
39108
39108
|
const json = JSON.parse(raw);
|
|
@@ -39113,7 +39113,7 @@ async function loadContentState(projectDir) {
|
|
|
39113
39113
|
}
|
|
39114
39114
|
}
|
|
39115
39115
|
async function saveContentState(projectDir, state) {
|
|
39116
|
-
const configPath =
|
|
39116
|
+
const configPath = join120(projectDir, TAKUMI_CONFIG_FILE2);
|
|
39117
39117
|
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
39118
39118
|
for (const key of Object.keys(state.dailyPostCounts)) {
|
|
39119
39119
|
const dateStr = key.slice(-10);
|
|
@@ -39394,8 +39394,8 @@ var init_platform_setup_x = __esm(() => {
|
|
|
39394
39394
|
});
|
|
39395
39395
|
|
|
39396
39396
|
// src/commands/content/phases/setup-wizard.ts
|
|
39397
|
-
import { existsSync as
|
|
39398
|
-
import { join as
|
|
39397
|
+
import { existsSync as existsSync62 } from "node:fs";
|
|
39398
|
+
import { join as join121 } from "node:path";
|
|
39399
39399
|
async function runSetupWizard2(cwd2, contentLogger) {
|
|
39400
39400
|
console.log();
|
|
39401
39401
|
oe(import_picocolors38.default.bgCyan(import_picocolors38.default.white(" SK Content — Multi-Channel Content Engine ")));
|
|
@@ -39463,8 +39463,8 @@ async function showRepoSummary(cwd2) {
|
|
|
39463
39463
|
function detectBrandAssets(cwd2, contentLogger) {
|
|
39464
39464
|
const repos = discoverRepos2(cwd2);
|
|
39465
39465
|
for (const repo of repos) {
|
|
39466
|
-
const hasGuidelines =
|
|
39467
|
-
const hasStyles =
|
|
39466
|
+
const hasGuidelines = existsSync62(join121(repo.path, "docs", "brand-guidelines.md"));
|
|
39467
|
+
const hasStyles = existsSync62(join121(repo.path, "assets", "writing-styles"));
|
|
39468
39468
|
if (!hasGuidelines) {
|
|
39469
39469
|
f2.warning(`${repo.name}: No docs/brand-guidelines.md — content will use generic tone.`);
|
|
39470
39470
|
contentLogger.warn(`${repo.name}: missing docs/brand-guidelines.md`);
|
|
@@ -39530,13 +39530,13 @@ var init_setup_wizard = __esm(() => {
|
|
|
39530
39530
|
});
|
|
39531
39531
|
|
|
39532
39532
|
// src/commands/content/content-review-commands.ts
|
|
39533
|
-
import { existsSync as
|
|
39534
|
-
import { homedir as
|
|
39533
|
+
import { existsSync as existsSync63 } from "node:fs";
|
|
39534
|
+
import { homedir as homedir28 } from "node:os";
|
|
39535
39535
|
async function queueContent() {
|
|
39536
39536
|
const cwd2 = process.cwd();
|
|
39537
39537
|
const config = await loadContentConfig(cwd2);
|
|
39538
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
39539
|
-
if (!
|
|
39538
|
+
const dbPath = config.dbPath.replace(/^~/, homedir28());
|
|
39539
|
+
if (!existsSync63(dbPath)) {
|
|
39540
39540
|
logger.info("No content database found. Run 'takumi content setup' first.");
|
|
39541
39541
|
return;
|
|
39542
39542
|
}
|
|
@@ -39562,7 +39562,7 @@ async function queueContent() {
|
|
|
39562
39562
|
async function approveContentCmd(id) {
|
|
39563
39563
|
const cwd2 = process.cwd();
|
|
39564
39564
|
const config = await loadContentConfig(cwd2);
|
|
39565
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
39565
|
+
const dbPath = config.dbPath.replace(/^~/, homedir28());
|
|
39566
39566
|
const db = initDatabase(dbPath);
|
|
39567
39567
|
try {
|
|
39568
39568
|
approveContent(db, Number.parseInt(id, 10));
|
|
@@ -39574,7 +39574,7 @@ async function approveContentCmd(id) {
|
|
|
39574
39574
|
async function rejectContentCmd(id, reason) {
|
|
39575
39575
|
const cwd2 = process.cwd();
|
|
39576
39576
|
const config = await loadContentConfig(cwd2);
|
|
39577
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
39577
|
+
const dbPath = config.dbPath.replace(/^~/, homedir28());
|
|
39578
39578
|
const db = initDatabase(dbPath);
|
|
39579
39579
|
try {
|
|
39580
39580
|
rejectContent(db, Number.parseInt(id, 10), reason);
|
|
@@ -39604,25 +39604,25 @@ __export(exports_content_subcommands, {
|
|
|
39604
39604
|
logsContent: () => logsContent,
|
|
39605
39605
|
approveContentCmd: () => approveContentCmd
|
|
39606
39606
|
});
|
|
39607
|
-
import { existsSync as
|
|
39608
|
-
import { homedir as
|
|
39609
|
-
import { join as
|
|
39607
|
+
import { existsSync as existsSync64, readFileSync as readFileSync19, unlinkSync as unlinkSync6 } from "node:fs";
|
|
39608
|
+
import { homedir as homedir29 } from "node:os";
|
|
39609
|
+
import { join as join122 } from "node:path";
|
|
39610
39610
|
function isDaemonRunning() {
|
|
39611
|
-
const lockFile =
|
|
39612
|
-
if (!
|
|
39611
|
+
const lockFile = join122(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
39612
|
+
if (!existsSync64(lockFile))
|
|
39613
39613
|
return { running: false, pid: null };
|
|
39614
39614
|
try {
|
|
39615
|
-
const pidStr =
|
|
39615
|
+
const pidStr = readFileSync19(lockFile, "utf-8").trim();
|
|
39616
39616
|
const pid = Number.parseInt(pidStr, 10);
|
|
39617
39617
|
if (Number.isNaN(pid)) {
|
|
39618
|
-
|
|
39618
|
+
unlinkSync6(lockFile);
|
|
39619
39619
|
return { running: false, pid: null };
|
|
39620
39620
|
}
|
|
39621
39621
|
process.kill(pid, 0);
|
|
39622
39622
|
return { running: true, pid };
|
|
39623
39623
|
} catch {
|
|
39624
39624
|
try {
|
|
39625
|
-
|
|
39625
|
+
unlinkSync6(lockFile);
|
|
39626
39626
|
} catch {}
|
|
39627
39627
|
return { running: false, pid: null };
|
|
39628
39628
|
}
|
|
@@ -39640,13 +39640,13 @@ async function startContent(options2) {
|
|
|
39640
39640
|
await contentCommand(options2);
|
|
39641
39641
|
}
|
|
39642
39642
|
async function stopContent() {
|
|
39643
|
-
const lockFile =
|
|
39644
|
-
if (!
|
|
39643
|
+
const lockFile = join122(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
39644
|
+
if (!existsSync64(lockFile)) {
|
|
39645
39645
|
logger.info("Content daemon is not running.");
|
|
39646
39646
|
return;
|
|
39647
39647
|
}
|
|
39648
39648
|
try {
|
|
39649
|
-
const pidStr =
|
|
39649
|
+
const pidStr = readFileSync19(lockFile, "utf-8").trim();
|
|
39650
39650
|
const pid = Number.parseInt(pidStr, 10);
|
|
39651
39651
|
if (!Number.isNaN(pid)) {
|
|
39652
39652
|
process.kill(pid, "SIGTERM");
|
|
@@ -39679,10 +39679,10 @@ async function statusContent() {
|
|
|
39679
39679
|
} catch {}
|
|
39680
39680
|
}
|
|
39681
39681
|
async function logsContent(options2) {
|
|
39682
|
-
const logDir =
|
|
39682
|
+
const logDir = join122(homedir29(), ".sunagentkit", "logs");
|
|
39683
39683
|
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
39684
|
-
const logPath =
|
|
39685
|
-
if (!
|
|
39684
|
+
const logPath = join122(logDir, `content-${dateStr}.log`);
|
|
39685
|
+
if (!existsSync64(logPath)) {
|
|
39686
39686
|
logger.info("No content logs found for today.");
|
|
39687
39687
|
return;
|
|
39688
39688
|
}
|
|
@@ -39694,7 +39694,7 @@ async function logsContent(options2) {
|
|
|
39694
39694
|
process.exit(0);
|
|
39695
39695
|
});
|
|
39696
39696
|
} else {
|
|
39697
|
-
const content =
|
|
39697
|
+
const content = readFileSync19(logPath, "utf-8");
|
|
39698
39698
|
console.log(content);
|
|
39699
39699
|
}
|
|
39700
39700
|
}
|
|
@@ -39713,13 +39713,13 @@ var init_content_subcommands = __esm(() => {
|
|
|
39713
39713
|
init_setup_wizard();
|
|
39714
39714
|
init_state_manager();
|
|
39715
39715
|
init_content_review_commands();
|
|
39716
|
-
LOCK_DIR =
|
|
39716
|
+
LOCK_DIR = join122(homedir29(), ".sunagentkit", "locks");
|
|
39717
39717
|
});
|
|
39718
39718
|
|
|
39719
39719
|
// src/commands/content/content-command.ts
|
|
39720
|
-
import { existsSync as
|
|
39721
|
-
import { homedir as
|
|
39722
|
-
import { join as
|
|
39720
|
+
import { existsSync as existsSync65, mkdirSync as mkdirSync7, unlinkSync as unlinkSync7, writeFileSync as writeFileSync5 } from "node:fs";
|
|
39721
|
+
import { homedir as homedir30 } from "node:os";
|
|
39722
|
+
import { join as join123 } from "node:path";
|
|
39723
39723
|
async function contentCommand(options2) {
|
|
39724
39724
|
const cwd2 = process.cwd();
|
|
39725
39725
|
const contentLogger = new ContentLogger;
|
|
@@ -39748,10 +39748,10 @@ async function contentCommand(options2) {
|
|
|
39748
39748
|
}
|
|
39749
39749
|
contentLogger.info("Setup complete. Starting daemon...");
|
|
39750
39750
|
}
|
|
39751
|
-
if (!
|
|
39752
|
-
|
|
39753
|
-
|
|
39754
|
-
const dbPath = config.dbPath.replace(/^~/,
|
|
39751
|
+
if (!existsSync65(LOCK_DIR2))
|
|
39752
|
+
mkdirSync7(LOCK_DIR2, { recursive: true });
|
|
39753
|
+
writeFileSync5(LOCK_FILE, String(process.pid), "utf-8");
|
|
39754
|
+
const dbPath = config.dbPath.replace(/^~/, homedir30());
|
|
39755
39755
|
const db = initDatabase(dbPath);
|
|
39756
39756
|
contentLogger.info(`Database initialised at ${dbPath}`);
|
|
39757
39757
|
const adapters = initializeAdapters(config);
|
|
@@ -39765,7 +39765,7 @@ async function contentCommand(options2) {
|
|
|
39765
39765
|
abortRequested = true;
|
|
39766
39766
|
contentLogger.info("Shutting down gracefully...");
|
|
39767
39767
|
try {
|
|
39768
|
-
|
|
39768
|
+
unlinkSync7(LOCK_FILE);
|
|
39769
39769
|
} catch {}
|
|
39770
39770
|
await saveContentState(cwd2, state);
|
|
39771
39771
|
closeDatabase(db);
|
|
@@ -39795,7 +39795,7 @@ async function contentCommand(options2) {
|
|
|
39795
39795
|
const msg = err instanceof Error ? err.message : String(err);
|
|
39796
39796
|
contentLogger.error(`Fatal error: ${msg}`);
|
|
39797
39797
|
try {
|
|
39798
|
-
|
|
39798
|
+
unlinkSync7(LOCK_FILE);
|
|
39799
39799
|
} catch {}
|
|
39800
39800
|
contentLogger.close();
|
|
39801
39801
|
process.exit(1);
|
|
@@ -39897,8 +39897,8 @@ var init_content_command = __esm(() => {
|
|
|
39897
39897
|
init_publisher();
|
|
39898
39898
|
init_review_manager();
|
|
39899
39899
|
init_state_manager();
|
|
39900
|
-
LOCK_DIR2 =
|
|
39901
|
-
LOCK_FILE =
|
|
39900
|
+
LOCK_DIR2 = join123(homedir30(), ".sunagentkit", "locks");
|
|
39901
|
+
LOCK_FILE = join123(LOCK_DIR2, "sk-content.lock");
|
|
39902
39902
|
});
|
|
39903
39903
|
|
|
39904
39904
|
// src/commands/content/index.ts
|
|
@@ -48793,6 +48793,28 @@ async function logout() {
|
|
|
48793
48793
|
// src/commands/auth/status-command.ts
|
|
48794
48794
|
init_dist2();
|
|
48795
48795
|
init_auth_client();
|
|
48796
|
+
|
|
48797
|
+
// src/domains/auth/identity.ts
|
|
48798
|
+
var GITHUB_LOGIN_REGEX = /^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$/;
|
|
48799
|
+
function pickGithubLogin(user) {
|
|
48800
|
+
if (!user)
|
|
48801
|
+
return null;
|
|
48802
|
+
const meta = user.user_metadata;
|
|
48803
|
+
if (!meta || typeof meta !== "object")
|
|
48804
|
+
return null;
|
|
48805
|
+
const candidates = [
|
|
48806
|
+
meta.user_name,
|
|
48807
|
+
meta.preferred_username
|
|
48808
|
+
];
|
|
48809
|
+
for (const candidate of candidates) {
|
|
48810
|
+
if (typeof candidate === "string" && GITHUB_LOGIN_REGEX.test(candidate)) {
|
|
48811
|
+
return candidate;
|
|
48812
|
+
}
|
|
48813
|
+
}
|
|
48814
|
+
return null;
|
|
48815
|
+
}
|
|
48816
|
+
|
|
48817
|
+
// src/commands/auth/status-command.ts
|
|
48796
48818
|
init_token_store();
|
|
48797
48819
|
init_logger();
|
|
48798
48820
|
function formatExpiry(expiresAt) {
|
|
@@ -48803,8 +48825,25 @@ function formatExpiry(expiresAt) {
|
|
|
48803
48825
|
return "unknown";
|
|
48804
48826
|
return new Date(ms).toISOString();
|
|
48805
48827
|
}
|
|
48806
|
-
|
|
48828
|
+
function emitJson(payload) {
|
|
48829
|
+
process.stdout.write(`${JSON.stringify(payload)}
|
|
48830
|
+
`);
|
|
48831
|
+
}
|
|
48832
|
+
async function status(options2 = {}) {
|
|
48807
48833
|
const stored = await readToken();
|
|
48834
|
+
if (options2.json) {
|
|
48835
|
+
if (!stored) {
|
|
48836
|
+
emitJson({ loggedIn: false, email: null, githubLogin: null, expiresAt: null });
|
|
48837
|
+
return;
|
|
48838
|
+
}
|
|
48839
|
+
emitJson({
|
|
48840
|
+
loggedIn: true,
|
|
48841
|
+
email: stored.user?.email ?? null,
|
|
48842
|
+
githubLogin: pickGithubLogin(stored.user),
|
|
48843
|
+
expiresAt: stored.expires_at ?? null
|
|
48844
|
+
});
|
|
48845
|
+
return;
|
|
48846
|
+
}
|
|
48808
48847
|
if (!stored) {
|
|
48809
48848
|
f2.info("Not logged in. Run `tkm auth login`.");
|
|
48810
48849
|
return;
|
|
@@ -48822,6 +48861,9 @@ async function status() {
|
|
|
48822
48861
|
logger.verbose(`auth status: getUser failed, using cached identity: ${err instanceof Error ? err.message : String(err)}`);
|
|
48823
48862
|
}
|
|
48824
48863
|
f2.success(`Signed in as ${email ?? "(unknown email)"}`);
|
|
48864
|
+
const githubLogin = pickGithubLogin(stored.user);
|
|
48865
|
+
if (githubLogin)
|
|
48866
|
+
f2.info(`GitHub login: ${githubLogin}`);
|
|
48825
48867
|
f2.info(`Token expires: ${formatExpiry(stored.expires_at)}`);
|
|
48826
48868
|
}
|
|
48827
48869
|
// src/commands/commands/commands-command.ts
|
|
@@ -61817,155 +61859,20 @@ async function handleDownload(ctx) {
|
|
|
61817
61859
|
extractDir: result.extractDir
|
|
61818
61860
|
};
|
|
61819
61861
|
}
|
|
61820
|
-
// src/commands/init/phases/identity-handler.ts
|
|
61821
|
-
init_takumi_config_manager();
|
|
61822
|
-
init_logger();
|
|
61823
|
-
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
61824
|
-
import { mkdirSync, readFileSync as readFileSync11, renameSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
61825
|
-
import { existsSync as existsSync27 } from "node:fs";
|
|
61826
|
-
import { homedir as homedir16 } from "node:os";
|
|
61827
|
-
import { dirname as dirname11, join as join52 } from "node:path";
|
|
61828
|
-
var TELEMETRY_BANNER_FIELD = "telemetry.bannerShownAt";
|
|
61829
|
-
var CACHE_FILE2 = join52(homedir16(), ".claude", "sk-user.json");
|
|
61830
|
-
var CACHE_TTL_MS2 = 30 * 24 * 60 * 60 * 1000;
|
|
61831
|
-
var GH_TIMEOUT_MS = 2000;
|
|
61832
|
-
var GITHUB_LOGIN_REGEX = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,38})$/;
|
|
61833
|
-
var MAX_ATTEMPTS2 = 3;
|
|
61834
|
-
function isValidLogin(login2) {
|
|
61835
|
-
return GITHUB_LOGIN_REGEX.test(login2);
|
|
61836
|
-
}
|
|
61837
|
-
function readCache() {
|
|
61838
|
-
try {
|
|
61839
|
-
if (!existsSync27(CACHE_FILE2))
|
|
61840
|
-
return null;
|
|
61841
|
-
const parsed = JSON.parse(readFileSync11(CACHE_FILE2, "utf8"));
|
|
61842
|
-
if (!parsed || typeof parsed !== "object")
|
|
61843
|
-
return null;
|
|
61844
|
-
if (!isValidLogin(parsed.githubLogin))
|
|
61845
|
-
return null;
|
|
61846
|
-
if (typeof parsed.resolvedAt !== "number")
|
|
61847
|
-
return null;
|
|
61848
|
-
if (parsed.source !== "gh" && parsed.source !== "manual")
|
|
61849
|
-
return null;
|
|
61850
|
-
if (Date.now() - parsed.resolvedAt > CACHE_TTL_MS2)
|
|
61851
|
-
return null;
|
|
61852
|
-
return parsed;
|
|
61853
|
-
} catch {
|
|
61854
|
-
return null;
|
|
61855
|
-
}
|
|
61856
|
-
}
|
|
61857
|
-
function writeCache(login2, source) {
|
|
61858
|
-
if (!isValidLogin(login2))
|
|
61859
|
-
return false;
|
|
61860
|
-
const payload = { githubLogin: login2, resolvedAt: Date.now(), source };
|
|
61861
|
-
try {
|
|
61862
|
-
mkdirSync(dirname11(CACHE_FILE2), { recursive: true });
|
|
61863
|
-
} catch {
|
|
61864
|
-
return false;
|
|
61865
|
-
}
|
|
61866
|
-
const tmp = `${CACHE_FILE2}.${process.pid}.${Math.random().toString(36).slice(2)}`;
|
|
61867
|
-
try {
|
|
61868
|
-
writeFileSync3(tmp, JSON.stringify(payload, null, 2));
|
|
61869
|
-
renameSync(tmp, CACHE_FILE2);
|
|
61870
|
-
return true;
|
|
61871
|
-
} catch {
|
|
61872
|
-
try {
|
|
61873
|
-
unlinkSync3(tmp);
|
|
61874
|
-
} catch {}
|
|
61875
|
-
return false;
|
|
61876
|
-
}
|
|
61877
|
-
}
|
|
61878
|
-
function resolveViaGhCli() {
|
|
61879
|
-
try {
|
|
61880
|
-
const out = execFileSync2("gh", ["api", "user", "--jq", ".login"], {
|
|
61881
|
-
encoding: "utf8",
|
|
61882
|
-
timeout: GH_TIMEOUT_MS,
|
|
61883
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
61884
|
-
windowsHide: true
|
|
61885
|
-
});
|
|
61886
|
-
const login2 = (out || "").trim();
|
|
61887
|
-
return isValidLogin(login2) ? login2 : null;
|
|
61888
|
-
} catch {
|
|
61889
|
-
return null;
|
|
61890
|
-
}
|
|
61891
|
-
}
|
|
61892
|
-
async function showTelemetryBannerOnce(ctx) {
|
|
61893
|
-
try {
|
|
61894
|
-
const { value } = await TakumiConfigManager.getFieldWithSource(TELEMETRY_BANNER_FIELD, null);
|
|
61895
|
-
if (typeof value === "number" && value > 0)
|
|
61896
|
-
return;
|
|
61897
|
-
ctx.prompts.note([
|
|
61898
|
-
"Takumi sends anonymous usage events (command names, tool/agent/skill",
|
|
61899
|
-
"names, token totals) to help us improve the tooling.",
|
|
61900
|
-
"",
|
|
61901
|
-
"Never collected: prompt text, file contents, paths, branch names, env vars.",
|
|
61902
|
-
"",
|
|
61903
|
-
"Inspect or opt out anytime:",
|
|
61904
|
-
" takumi telemetry status # current state + buffered events",
|
|
61905
|
-
" takumi telemetry disable # stop sending on future sessions",
|
|
61906
|
-
" takumi telemetry purge-remote # delete your rows on the server"
|
|
61907
|
-
].join(`
|
|
61908
|
-
`), "Telemetry & Privacy");
|
|
61909
|
-
await TakumiConfigManager.updateField(TELEMETRY_BANNER_FIELD, Date.now(), "global", null);
|
|
61910
|
-
} catch {}
|
|
61911
|
-
}
|
|
61912
|
-
async function handleIdentityResolution(ctx) {
|
|
61913
|
-
if (ctx.cancelled)
|
|
61914
|
-
return ctx;
|
|
61915
|
-
if (readCache()) {
|
|
61916
|
-
await showTelemetryBannerOnce(ctx);
|
|
61917
|
-
return ctx;
|
|
61918
|
-
}
|
|
61919
|
-
const ghLogin = resolveViaGhCli();
|
|
61920
|
-
if (ghLogin) {
|
|
61921
|
-
writeCache(ghLogin, "gh");
|
|
61922
|
-
logger.success(`Identified as GitHub user: ${ghLogin}`);
|
|
61923
|
-
await showTelemetryBannerOnce(ctx);
|
|
61924
|
-
return ctx;
|
|
61925
|
-
}
|
|
61926
|
-
if (ctx.isNonInteractive) {
|
|
61927
|
-
logger.warning("GitHub CLI (`gh`) not found or unauthenticated. Skipping identity setup (non-interactive mode).");
|
|
61928
|
-
logger.info("Telemetry / feedback features will be disabled until `gh auth login` is run and `tkm init` is re-run.");
|
|
61929
|
-
return ctx;
|
|
61930
|
-
}
|
|
61931
|
-
ctx.prompts.note(`Takumi uses your GitHub login to attribute feedback, ratings, and telemetry.
|
|
61932
|
-
No tokens are stored — just the public username.`, "GitHub Identity");
|
|
61933
|
-
for (let attempt = 1;attempt <= MAX_ATTEMPTS2; attempt++) {
|
|
61934
|
-
const input = await ctx.prompts.text("Enter your GitHub username:", "e.g. octocat");
|
|
61935
|
-
if (input === undefined) {
|
|
61936
|
-
logger.error("GitHub username is required. Install `gh` CLI (`gh auth login`) or re-run `tkm init`.");
|
|
61937
|
-
return { ...ctx, cancelled: true };
|
|
61938
|
-
}
|
|
61939
|
-
const login2 = input.trim();
|
|
61940
|
-
if (!isValidLogin(login2)) {
|
|
61941
|
-
logger.warning("Invalid GitHub username. Must be 1–39 chars, alphanumeric or hyphen, no leading hyphen.");
|
|
61942
|
-
continue;
|
|
61943
|
-
}
|
|
61944
|
-
if (writeCache(login2, "manual")) {
|
|
61945
|
-
logger.success(`Saved GitHub identity: ${login2}`);
|
|
61946
|
-
await showTelemetryBannerOnce(ctx);
|
|
61947
|
-
return ctx;
|
|
61948
|
-
}
|
|
61949
|
-
logger.warning("Could not write identity cache — continuing without it.");
|
|
61950
|
-
return ctx;
|
|
61951
|
-
}
|
|
61952
|
-
logger.error(`Failed to capture a valid GitHub username after ${MAX_ATTEMPTS2} attempts. Aborting init.`);
|
|
61953
|
-
return { ...ctx, cancelled: true };
|
|
61954
|
-
}
|
|
61955
61862
|
// src/commands/init/phases/merge-handler.ts
|
|
61956
|
-
import { join as
|
|
61863
|
+
import { join as join66 } from "node:path";
|
|
61957
61864
|
|
|
61958
61865
|
// src/domains/installation/deletion-handler.ts
|
|
61959
|
-
import { existsSync as
|
|
61960
|
-
import { dirname as
|
|
61866
|
+
import { existsSync as existsSync27, lstatSync as lstatSync3, readdirSync as readdirSync2, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
61867
|
+
import { dirname as dirname11, join as join53, relative as relative7, resolve as resolve8, sep as sep2 } from "node:path";
|
|
61961
61868
|
|
|
61962
61869
|
// src/services/file-operations/manifest/manifest-reader.ts
|
|
61963
|
-
import { join as
|
|
61870
|
+
import { join as join52 } from "node:path";
|
|
61964
61871
|
init_logger();
|
|
61965
61872
|
init_types2();
|
|
61966
61873
|
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
61967
61874
|
async function readManifest(claudeDir) {
|
|
61968
|
-
const metadataPath =
|
|
61875
|
+
const metadataPath = join52(claudeDir, "metadata.json");
|
|
61969
61876
|
if (!await import_fs_extra6.pathExists(metadataPath)) {
|
|
61970
61877
|
return null;
|
|
61971
61878
|
}
|
|
@@ -62139,12 +62046,12 @@ function shouldDeletePath(path5, metadata) {
|
|
|
62139
62046
|
}
|
|
62140
62047
|
function collectFilesRecursively(dir, baseDir) {
|
|
62141
62048
|
const results = [];
|
|
62142
|
-
if (!
|
|
62049
|
+
if (!existsSync27(dir))
|
|
62143
62050
|
return results;
|
|
62144
62051
|
try {
|
|
62145
62052
|
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
62146
62053
|
for (const entry of entries) {
|
|
62147
|
-
const fullPath =
|
|
62054
|
+
const fullPath = join53(dir, entry.name);
|
|
62148
62055
|
const relativePath = relative7(baseDir, fullPath);
|
|
62149
62056
|
if (entry.isDirectory()) {
|
|
62150
62057
|
results.push(...collectFilesRecursively(fullPath, baseDir));
|
|
@@ -62175,7 +62082,7 @@ function expandGlobPatterns(patterns, claudeDir) {
|
|
|
62175
62082
|
var MAX_CLEANUP_ITERATIONS = 50;
|
|
62176
62083
|
function cleanupEmptyDirectories(filePath, claudeDir) {
|
|
62177
62084
|
const normalizedClaudeDir = resolve8(claudeDir);
|
|
62178
|
-
let currentDir = resolve8(
|
|
62085
|
+
let currentDir = resolve8(dirname11(filePath));
|
|
62179
62086
|
let iterations = 0;
|
|
62180
62087
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
|
|
62181
62088
|
iterations++;
|
|
@@ -62184,7 +62091,7 @@ function cleanupEmptyDirectories(filePath, claudeDir) {
|
|
|
62184
62091
|
if (entries.length === 0) {
|
|
62185
62092
|
rmdirSync(currentDir);
|
|
62186
62093
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
62187
|
-
currentDir = resolve8(
|
|
62094
|
+
currentDir = resolve8(dirname11(currentDir));
|
|
62188
62095
|
} else {
|
|
62189
62096
|
break;
|
|
62190
62097
|
}
|
|
@@ -62204,7 +62111,7 @@ function deletePath(fullPath, claudeDir) {
|
|
|
62204
62111
|
if (stat6.isDirectory()) {
|
|
62205
62112
|
rmSync2(fullPath, { recursive: true, force: true });
|
|
62206
62113
|
} else {
|
|
62207
|
-
|
|
62114
|
+
unlinkSync3(fullPath);
|
|
62208
62115
|
cleanupEmptyDirectories(fullPath, claudeDir);
|
|
62209
62116
|
}
|
|
62210
62117
|
} catch (error) {
|
|
@@ -62212,7 +62119,7 @@ function deletePath(fullPath, claudeDir) {
|
|
|
62212
62119
|
}
|
|
62213
62120
|
}
|
|
62214
62121
|
async function updateMetadataAfterDeletion(claudeDir, deletedPaths) {
|
|
62215
|
-
const metadataPath =
|
|
62122
|
+
const metadataPath = join53(claudeDir, "metadata.json");
|
|
62216
62123
|
if (!await import_fs_extra7.pathExists(metadataPath)) {
|
|
62217
62124
|
return;
|
|
62218
62125
|
}
|
|
@@ -62267,7 +62174,7 @@ async function handleDeletions(sourceMetadata, claudeDir) {
|
|
|
62267
62174
|
const userMetadata = await readManifest(claudeDir);
|
|
62268
62175
|
const result = { deletedPaths: [], preservedPaths: [], errors: [] };
|
|
62269
62176
|
for (const path5 of deletions) {
|
|
62270
|
-
const fullPath =
|
|
62177
|
+
const fullPath = join53(claudeDir, path5);
|
|
62271
62178
|
const normalizedPath = resolve8(fullPath);
|
|
62272
62179
|
const normalizedClaudeDir = resolve8(claudeDir);
|
|
62273
62180
|
if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep2}`)) {
|
|
@@ -62280,7 +62187,7 @@ async function handleDeletions(sourceMetadata, claudeDir) {
|
|
|
62280
62187
|
logger.verbose(`Preserved user file: ${path5}`);
|
|
62281
62188
|
continue;
|
|
62282
62189
|
}
|
|
62283
|
-
if (
|
|
62190
|
+
if (existsSync27(fullPath)) {
|
|
62284
62191
|
try {
|
|
62285
62192
|
deletePath(fullPath, claudeDir);
|
|
62286
62193
|
result.deletedPaths.push(path5);
|
|
@@ -62307,7 +62214,7 @@ init_logger();
|
|
|
62307
62214
|
init_types2();
|
|
62308
62215
|
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
62309
62216
|
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
62310
|
-
import { dirname as
|
|
62217
|
+
import { dirname as dirname13, join as join56, relative as relative9 } from "node:path";
|
|
62311
62218
|
|
|
62312
62219
|
// src/domains/installation/selective-merger.ts
|
|
62313
62220
|
import { stat as stat6 } from "node:fs/promises";
|
|
@@ -62486,7 +62393,7 @@ init_logger();
|
|
|
62486
62393
|
var import_fs_extra8 = __toESM(require_lib(), 1);
|
|
62487
62394
|
var import_ignore2 = __toESM(require_ignore(), 1);
|
|
62488
62395
|
import { relative as relative8 } from "node:path";
|
|
62489
|
-
import { join as
|
|
62396
|
+
import { join as join54 } from "node:path";
|
|
62490
62397
|
|
|
62491
62398
|
// node_modules/balanced-match/dist/esm/index.js
|
|
62492
62399
|
var balanced = (a3, b4, str2) => {
|
|
@@ -64187,7 +64094,7 @@ class FileScanner {
|
|
|
64187
64094
|
const files = [];
|
|
64188
64095
|
const entries = await import_fs_extra8.readdir(dir, { encoding: "utf8" });
|
|
64189
64096
|
for (const entry of entries) {
|
|
64190
|
-
const fullPath =
|
|
64097
|
+
const fullPath = join54(dir, entry);
|
|
64191
64098
|
const relativePath = relative8(baseDir, fullPath);
|
|
64192
64099
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
64193
64100
|
const stats = await import_fs_extra8.lstat(fullPath);
|
|
@@ -64224,9 +64131,9 @@ class FileScanner {
|
|
|
64224
64131
|
import { execSync as execSync4 } from "node:child_process";
|
|
64225
64132
|
|
|
64226
64133
|
// src/domains/config/installed-settings-tracker.ts
|
|
64227
|
-
import { existsSync as
|
|
64134
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
64228
64135
|
import { mkdir as mkdir19, readFile as readFile22, writeFile as writeFile18 } from "node:fs/promises";
|
|
64229
|
-
import { dirname as
|
|
64136
|
+
import { dirname as dirname12, join as join55 } from "node:path";
|
|
64230
64137
|
var TAKUMI_JSON_FILE = ".takumi.json";
|
|
64231
64138
|
|
|
64232
64139
|
class InstalledSettingsTracker {
|
|
@@ -64240,13 +64147,13 @@ class InstalledSettingsTracker {
|
|
|
64240
64147
|
}
|
|
64241
64148
|
getCkJsonPath() {
|
|
64242
64149
|
if (this.isGlobal) {
|
|
64243
|
-
return
|
|
64150
|
+
return join55(this.projectDir, TAKUMI_JSON_FILE);
|
|
64244
64151
|
}
|
|
64245
|
-
return
|
|
64152
|
+
return join55(this.projectDir, ".claude", TAKUMI_JSON_FILE);
|
|
64246
64153
|
}
|
|
64247
64154
|
async loadInstalledSettings() {
|
|
64248
64155
|
const ckJsonPath = this.getCkJsonPath();
|
|
64249
|
-
if (!
|
|
64156
|
+
if (!existsSync28(ckJsonPath)) {
|
|
64250
64157
|
return { hooks: [], mcpServers: [] };
|
|
64251
64158
|
}
|
|
64252
64159
|
try {
|
|
@@ -64266,7 +64173,7 @@ class InstalledSettingsTracker {
|
|
|
64266
64173
|
const ckJsonPath = this.getCkJsonPath();
|
|
64267
64174
|
try {
|
|
64268
64175
|
let data = {};
|
|
64269
|
-
if (
|
|
64176
|
+
if (existsSync28(ckJsonPath)) {
|
|
64270
64177
|
const content = await readFile22(ckJsonPath, "utf-8");
|
|
64271
64178
|
data = JSON.parse(content);
|
|
64272
64179
|
}
|
|
@@ -64277,7 +64184,7 @@ class InstalledSettingsTracker {
|
|
|
64277
64184
|
data.kits[this.kitName] = {};
|
|
64278
64185
|
}
|
|
64279
64186
|
data.kits[this.kitName].installedSettings = settings;
|
|
64280
|
-
await mkdir19(
|
|
64187
|
+
await mkdir19(dirname12(ckJsonPath), { recursive: true });
|
|
64281
64188
|
await writeFile18(ckJsonPath, JSON.stringify(data, null, 2), "utf-8");
|
|
64282
64189
|
logger.debug(`Saved installed settings to ${ckJsonPath}`);
|
|
64283
64190
|
} catch (error) {
|
|
@@ -64886,7 +64793,7 @@ class CopyExecutor {
|
|
|
64886
64793
|
for (const file of files) {
|
|
64887
64794
|
const relativePath = relative9(sourceDir, file);
|
|
64888
64795
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
64889
|
-
const destPath =
|
|
64796
|
+
const destPath = join56(destDir, relativePath);
|
|
64890
64797
|
if (await import_fs_extra10.pathExists(destPath)) {
|
|
64891
64798
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
64892
64799
|
logger.debug(`Security-sensitive file exists but won't be overwritten: ${normalizedRelativePath}`);
|
|
@@ -64908,7 +64815,7 @@ class CopyExecutor {
|
|
|
64908
64815
|
for (const file of files) {
|
|
64909
64816
|
const relativePath = relative9(sourceDir, file);
|
|
64910
64817
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
64911
|
-
const destPath =
|
|
64818
|
+
const destPath = join56(destDir, relativePath);
|
|
64912
64819
|
if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
|
|
64913
64820
|
logger.debug(`Skipping security-sensitive file: ${normalizedRelativePath}`);
|
|
64914
64821
|
skippedCount++;
|
|
@@ -64985,10 +64892,10 @@ class CopyExecutor {
|
|
|
64985
64892
|
}
|
|
64986
64893
|
trackInstalledFile(relativePath) {
|
|
64987
64894
|
this.installedFiles.add(relativePath);
|
|
64988
|
-
let dir =
|
|
64895
|
+
let dir = dirname13(relativePath);
|
|
64989
64896
|
while (dir && dir !== "." && dir !== "/") {
|
|
64990
64897
|
this.installedDirectories.add(`${dir}/`);
|
|
64991
|
-
dir =
|
|
64898
|
+
dir = dirname13(dir);
|
|
64992
64899
|
}
|
|
64993
64900
|
}
|
|
64994
64901
|
}
|
|
@@ -65081,15 +64988,15 @@ class FileMerger {
|
|
|
65081
64988
|
|
|
65082
64989
|
// src/domains/migration/legacy-migration.ts
|
|
65083
64990
|
import { readdir as readdir11, stat as stat7 } from "node:fs/promises";
|
|
65084
|
-
import { join as
|
|
64991
|
+
import { join as join60, relative as relative10 } from "node:path";
|
|
65085
64992
|
// src/services/file-operations/manifest/manifest-tracker.ts
|
|
65086
|
-
import { join as
|
|
64993
|
+
import { join as join59 } from "node:path";
|
|
65087
64994
|
|
|
65088
64995
|
// src/domains/migration/release-manifest.ts
|
|
65089
64996
|
init_logger();
|
|
65090
64997
|
init_zod();
|
|
65091
64998
|
var import_fs_extra11 = __toESM(require_lib(), 1);
|
|
65092
|
-
import { join as
|
|
64999
|
+
import { join as join57 } from "node:path";
|
|
65093
65000
|
var ReleaseManifestFileSchema = exports_external.object({
|
|
65094
65001
|
path: exports_external.string(),
|
|
65095
65002
|
checksum: exports_external.string().regex(/^[a-f0-9]{64}$/),
|
|
@@ -65104,7 +65011,7 @@ var ReleaseManifestSchema = exports_external.object({
|
|
|
65104
65011
|
|
|
65105
65012
|
class ReleaseManifestLoader {
|
|
65106
65013
|
static async load(extractDir) {
|
|
65107
|
-
const manifestPath =
|
|
65014
|
+
const manifestPath = join57(extractDir, "release-manifest.json");
|
|
65108
65015
|
try {
|
|
65109
65016
|
const content = await import_fs_extra11.readFile(manifestPath, "utf-8");
|
|
65110
65017
|
const parsed = JSON.parse(content);
|
|
@@ -65124,13 +65031,13 @@ init_environment();
|
|
|
65124
65031
|
init_logger();
|
|
65125
65032
|
|
|
65126
65033
|
// src/services/file-operations/manifest/manifest-updater.ts
|
|
65127
|
-
import { join as
|
|
65034
|
+
import { join as join58 } from "node:path";
|
|
65128
65035
|
init_logger();
|
|
65129
65036
|
init_types2();
|
|
65130
65037
|
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
65131
65038
|
var import_proper_lockfile5 = __toESM(require_proper_lockfile(), 1);
|
|
65132
65039
|
async function writeManifest(claudeDir, kitName, version3, scope, kitType, trackedFiles, userConfigFiles) {
|
|
65133
|
-
const metadataPath =
|
|
65040
|
+
const metadataPath = join58(claudeDir, "metadata.json");
|
|
65134
65041
|
const kit = kitType || "engineer";
|
|
65135
65042
|
await import_fs_extra12.ensureFile(metadataPath);
|
|
65136
65043
|
let release = null;
|
|
@@ -65195,7 +65102,7 @@ async function writeManifest(claudeDir, kitName, version3, scope, kitType, track
|
|
|
65195
65102
|
}
|
|
65196
65103
|
}
|
|
65197
65104
|
async function removeKitFromManifest(claudeDir, kit) {
|
|
65198
|
-
const metadataPath =
|
|
65105
|
+
const metadataPath = join58(claudeDir, "metadata.json");
|
|
65199
65106
|
if (!await import_fs_extra12.pathExists(metadataPath))
|
|
65200
65107
|
return false;
|
|
65201
65108
|
let release = null;
|
|
@@ -65325,7 +65232,7 @@ function buildFileTrackingList(options2) {
|
|
|
65325
65232
|
if (!isGlobal && !installedPath.startsWith(".claude/"))
|
|
65326
65233
|
continue;
|
|
65327
65234
|
const relativePath = isGlobal ? installedPath : installedPath.replace(/^\.claude\//, "");
|
|
65328
|
-
const filePath =
|
|
65235
|
+
const filePath = join59(claudeDir, relativePath);
|
|
65329
65236
|
const manifestEntry = releaseManifest ? ReleaseManifestLoader.findFile(releaseManifest, installedPath) : null;
|
|
65330
65237
|
const ownership = manifestEntry ? "takumi" : "user";
|
|
65331
65238
|
filesToTrack.push({
|
|
@@ -65431,7 +65338,7 @@ class LegacyMigration {
|
|
|
65431
65338
|
continue;
|
|
65432
65339
|
if (SKIP_DIRS_ALL.includes(entry))
|
|
65433
65340
|
continue;
|
|
65434
|
-
const fullPath =
|
|
65341
|
+
const fullPath = join60(dir, entry);
|
|
65435
65342
|
let stats;
|
|
65436
65343
|
try {
|
|
65437
65344
|
stats = await stat7(fullPath);
|
|
@@ -65536,7 +65443,7 @@ User-created files (sample):`);
|
|
|
65536
65443
|
];
|
|
65537
65444
|
if (filesToChecksum.length > 0) {
|
|
65538
65445
|
const checksumResults = await mapWithLimit(filesToChecksum, async ({ relativePath, ownership }) => {
|
|
65539
|
-
const fullPath =
|
|
65446
|
+
const fullPath = join60(claudeDir, relativePath);
|
|
65540
65447
|
const checksum = await OwnershipChecker.calculateChecksum(fullPath);
|
|
65541
65448
|
return { relativePath, checksum, ownership };
|
|
65542
65449
|
});
|
|
@@ -65557,7 +65464,7 @@ User-created files (sample):`);
|
|
|
65557
65464
|
installedAt: new Date().toISOString(),
|
|
65558
65465
|
files: trackedFiles
|
|
65559
65466
|
};
|
|
65560
|
-
const metadataPath =
|
|
65467
|
+
const metadataPath = join60(claudeDir, "metadata.json");
|
|
65561
65468
|
await import_fs_extra13.writeFile(metadataPath, JSON.stringify(updatedMetadata, null, 2));
|
|
65562
65469
|
logger.success(`Migration complete: tracked ${trackedFiles.length} files`);
|
|
65563
65470
|
return true;
|
|
@@ -65660,7 +65567,7 @@ function buildConflictSummary(fileConflicts, hookConflicts, mcpConflicts) {
|
|
|
65660
65567
|
}
|
|
65661
65568
|
|
|
65662
65569
|
// src/services/file-operations/file-scanner.ts
|
|
65663
|
-
import { join as
|
|
65570
|
+
import { join as join61, relative as relative11, resolve as resolve9 } from "node:path";
|
|
65664
65571
|
init_logger();
|
|
65665
65572
|
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
65666
65573
|
|
|
@@ -65678,7 +65585,7 @@ class FileScanner2 {
|
|
|
65678
65585
|
logger.debug(`Skipping directory: ${entry}`);
|
|
65679
65586
|
continue;
|
|
65680
65587
|
}
|
|
65681
|
-
const fullPath =
|
|
65588
|
+
const fullPath = join61(dirPath, entry);
|
|
65682
65589
|
if (!FileScanner2.isSafePath(basePath, fullPath)) {
|
|
65683
65590
|
logger.warning(`Skipping potentially unsafe path: ${entry}`);
|
|
65684
65591
|
continue;
|
|
@@ -65713,8 +65620,8 @@ class FileScanner2 {
|
|
|
65713
65620
|
return files;
|
|
65714
65621
|
}
|
|
65715
65622
|
static async findCustomFiles(destDir, sourceDir, subPath) {
|
|
65716
|
-
const destSubDir =
|
|
65717
|
-
const sourceSubDir =
|
|
65623
|
+
const destSubDir = join61(destDir, subPath);
|
|
65624
|
+
const sourceSubDir = join61(sourceDir, subPath);
|
|
65718
65625
|
logger.debug(`findCustomFiles - destDir: ${destDir}`);
|
|
65719
65626
|
logger.debug(`findCustomFiles - sourceDir: ${sourceDir}`);
|
|
65720
65627
|
logger.debug(`findCustomFiles - subPath: "${subPath}"`);
|
|
@@ -65755,12 +65662,12 @@ class FileScanner2 {
|
|
|
65755
65662
|
init_logger();
|
|
65756
65663
|
var import_fs_extra15 = __toESM(require_lib(), 1);
|
|
65757
65664
|
import { lstat as lstat5, mkdir as mkdir20, readdir as readdir14, stat as stat8 } from "node:fs/promises";
|
|
65758
|
-
import { join as
|
|
65665
|
+
import { join as join63 } from "node:path";
|
|
65759
65666
|
|
|
65760
65667
|
// src/services/transformers/commands-prefix/content-transformer.ts
|
|
65761
65668
|
init_logger();
|
|
65762
65669
|
import { readFile as readFile26, readdir as readdir13, writeFile as writeFile22 } from "node:fs/promises";
|
|
65763
|
-
import { join as
|
|
65670
|
+
import { join as join62 } from "node:path";
|
|
65764
65671
|
var TRANSFORMABLE_EXTENSIONS = new Set([
|
|
65765
65672
|
".md",
|
|
65766
65673
|
".txt",
|
|
@@ -65821,7 +65728,7 @@ async function transformCommandReferences(directory, options2 = {}) {
|
|
|
65821
65728
|
async function processDirectory(dir) {
|
|
65822
65729
|
const entries = await readdir13(dir, { withFileTypes: true });
|
|
65823
65730
|
for (const entry of entries) {
|
|
65824
|
-
const fullPath =
|
|
65731
|
+
const fullPath = join62(dir, entry.name);
|
|
65825
65732
|
if (entry.isDirectory()) {
|
|
65826
65733
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
65827
65734
|
continue;
|
|
@@ -65896,14 +65803,14 @@ function shouldApplyPrefix(options2) {
|
|
|
65896
65803
|
// src/services/transformers/commands-prefix/prefix-applier.ts
|
|
65897
65804
|
async function applyPrefix(extractDir) {
|
|
65898
65805
|
validatePath(extractDir, "extractDir");
|
|
65899
|
-
const commandsDir =
|
|
65806
|
+
const commandsDir = join63(extractDir, ".claude", "commands");
|
|
65900
65807
|
if (!await import_fs_extra15.pathExists(commandsDir)) {
|
|
65901
65808
|
logger.verbose("No commands directory found, skipping prefix application");
|
|
65902
65809
|
return;
|
|
65903
65810
|
}
|
|
65904
65811
|
logger.info("Applying /tkm: prefix to slash commands...");
|
|
65905
|
-
const backupDir =
|
|
65906
|
-
const tempDir =
|
|
65812
|
+
const backupDir = join63(extractDir, ".commands-backup");
|
|
65813
|
+
const tempDir = join63(extractDir, ".commands-prefix-temp");
|
|
65907
65814
|
try {
|
|
65908
65815
|
const entries = await readdir14(commandsDir);
|
|
65909
65816
|
if (entries.length === 0) {
|
|
@@ -65911,7 +65818,7 @@ async function applyPrefix(extractDir) {
|
|
|
65911
65818
|
return;
|
|
65912
65819
|
}
|
|
65913
65820
|
if (entries.length === 1 && entries[0] === "tkm") {
|
|
65914
|
-
const ckDir2 =
|
|
65821
|
+
const ckDir2 = join63(commandsDir, "tkm");
|
|
65915
65822
|
const ckStat = await stat8(ckDir2);
|
|
65916
65823
|
if (ckStat.isDirectory()) {
|
|
65917
65824
|
logger.verbose("Commands already have /tkm: prefix, skipping");
|
|
@@ -65921,17 +65828,17 @@ async function applyPrefix(extractDir) {
|
|
|
65921
65828
|
await import_fs_extra15.copy(commandsDir, backupDir);
|
|
65922
65829
|
logger.verbose("Created backup of commands directory");
|
|
65923
65830
|
await mkdir20(tempDir, { recursive: true });
|
|
65924
|
-
const ckDir =
|
|
65831
|
+
const ckDir = join63(tempDir, "tkm");
|
|
65925
65832
|
await mkdir20(ckDir, { recursive: true });
|
|
65926
65833
|
let processedCount = 0;
|
|
65927
65834
|
for (const entry of entries) {
|
|
65928
|
-
const sourcePath =
|
|
65835
|
+
const sourcePath = join63(commandsDir, entry);
|
|
65929
65836
|
const stats = await lstat5(sourcePath);
|
|
65930
65837
|
if (stats.isSymbolicLink()) {
|
|
65931
65838
|
logger.warning(`Skipping symlink for security: ${entry}`);
|
|
65932
65839
|
continue;
|
|
65933
65840
|
}
|
|
65934
|
-
const destPath =
|
|
65841
|
+
const destPath = join63(ckDir, entry);
|
|
65935
65842
|
await import_fs_extra15.copy(sourcePath, destPath, {
|
|
65936
65843
|
overwrite: false,
|
|
65937
65844
|
errorOnExist: true
|
|
@@ -65949,7 +65856,7 @@ async function applyPrefix(extractDir) {
|
|
|
65949
65856
|
await import_fs_extra15.move(tempDir, commandsDir);
|
|
65950
65857
|
await import_fs_extra15.remove(backupDir);
|
|
65951
65858
|
logger.success("Successfully reorganized commands to /tkm: prefix");
|
|
65952
|
-
const claudeDir =
|
|
65859
|
+
const claudeDir = join63(extractDir, ".claude");
|
|
65953
65860
|
logger.info("Transforming command references in file contents...");
|
|
65954
65861
|
const transformResult = await transformCommandReferences(claudeDir, {
|
|
65955
65862
|
verbose: logger.isVerbose()
|
|
@@ -65986,20 +65893,20 @@ async function applyPrefix(extractDir) {
|
|
|
65986
65893
|
|
|
65987
65894
|
// src/services/transformers/commands-prefix/prefix-cleaner.ts
|
|
65988
65895
|
import { lstat as lstat7, readdir as readdir16 } from "node:fs/promises";
|
|
65989
|
-
import { join as
|
|
65896
|
+
import { join as join65 } from "node:path";
|
|
65990
65897
|
init_logger();
|
|
65991
65898
|
var import_fs_extra17 = __toESM(require_lib(), 1);
|
|
65992
65899
|
|
|
65993
65900
|
// src/services/transformers/commands-prefix/file-processor.ts
|
|
65994
65901
|
import { lstat as lstat6, readdir as readdir15 } from "node:fs/promises";
|
|
65995
|
-
import { join as
|
|
65902
|
+
import { join as join64 } from "node:path";
|
|
65996
65903
|
init_logger();
|
|
65997
65904
|
var import_fs_extra16 = __toESM(require_lib(), 1);
|
|
65998
65905
|
async function scanDirectoryFiles(dir) {
|
|
65999
65906
|
const files = [];
|
|
66000
65907
|
const entries = await readdir15(dir);
|
|
66001
65908
|
for (const entry of entries) {
|
|
66002
|
-
const fullPath =
|
|
65909
|
+
const fullPath = join64(dir, entry);
|
|
66003
65910
|
const stats = await lstat6(fullPath);
|
|
66004
65911
|
if (stats.isSymbolicLink()) {
|
|
66005
65912
|
continue;
|
|
@@ -66126,8 +66033,8 @@ function isDifferentKitDirectory(dirName, currentKit) {
|
|
|
66126
66033
|
async function cleanupCommandsDirectory(targetDir, isGlobal, options2 = {}) {
|
|
66127
66034
|
const { dryRun = false } = options2;
|
|
66128
66035
|
validatePath(targetDir, "targetDir");
|
|
66129
|
-
const claudeDir = isGlobal ? targetDir :
|
|
66130
|
-
const commandsDir =
|
|
66036
|
+
const claudeDir = isGlobal ? targetDir : join65(targetDir, ".claude");
|
|
66037
|
+
const commandsDir = join65(claudeDir, "commands");
|
|
66131
66038
|
const accumulator = {
|
|
66132
66039
|
results: [],
|
|
66133
66040
|
deletedCount: 0,
|
|
@@ -66169,7 +66076,7 @@ async function cleanupCommandsDirectory(targetDir, isGlobal, options2 = {}) {
|
|
|
66169
66076
|
}
|
|
66170
66077
|
const metadataForChecks = options2.kitType ? createKitSpecificMetadata(metadata, options2.kitType) : metadata;
|
|
66171
66078
|
for (const entry of entries) {
|
|
66172
|
-
const entryPath =
|
|
66079
|
+
const entryPath = join65(commandsDir, entry);
|
|
66173
66080
|
const stats = await lstat7(entryPath);
|
|
66174
66081
|
if (stats.isSymbolicLink()) {
|
|
66175
66082
|
addSymlinkSkip(entry, accumulator);
|
|
@@ -66226,7 +66133,7 @@ async function handleMerge(ctx) {
|
|
|
66226
66133
|
let customClaudeFiles = [];
|
|
66227
66134
|
if (!ctx.options.fresh) {
|
|
66228
66135
|
logger.info("Scanning for custom .claude files...");
|
|
66229
|
-
const scanSourceDir = ctx.options.global ?
|
|
66136
|
+
const scanSourceDir = ctx.options.global ? join66(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
66230
66137
|
const scanTargetSubdir = ctx.options.global ? "" : ".claude";
|
|
66231
66138
|
customClaudeFiles = await FileScanner2.findCustomFiles(ctx.resolvedDir, scanSourceDir, scanTargetSubdir);
|
|
66232
66139
|
} else {
|
|
@@ -66291,8 +66198,8 @@ async function handleMerge(ctx) {
|
|
|
66291
66198
|
return { ...ctx, cancelled: true };
|
|
66292
66199
|
}
|
|
66293
66200
|
}
|
|
66294
|
-
const sourceDir = ctx.options.global ?
|
|
66295
|
-
const sourceMetadataPath = ctx.options.global ?
|
|
66201
|
+
const sourceDir = ctx.options.global ? join66(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
66202
|
+
const sourceMetadataPath = ctx.options.global ? join66(sourceDir, "metadata.json") : join66(sourceDir, ".claude", "metadata.json");
|
|
66296
66203
|
let sourceMetadata = null;
|
|
66297
66204
|
try {
|
|
66298
66205
|
if (await import_fs_extra18.pathExists(sourceMetadataPath)) {
|
|
@@ -66349,7 +66256,7 @@ async function handleMerge(ctx) {
|
|
|
66349
66256
|
};
|
|
66350
66257
|
}
|
|
66351
66258
|
// src/commands/init/phases/migration-handler.ts
|
|
66352
|
-
import { join as
|
|
66259
|
+
import { join as join74 } from "node:path";
|
|
66353
66260
|
|
|
66354
66261
|
// src/domains/skills/skills-detector.ts
|
|
66355
66262
|
init_logger();
|
|
@@ -66362,7 +66269,7 @@ init_logger();
|
|
|
66362
66269
|
init_logger();
|
|
66363
66270
|
import { createHash as createHash5 } from "node:crypto";
|
|
66364
66271
|
import { readFile as readFile28, readdir as readdir17, writeFile as writeFile23 } from "node:fs/promises";
|
|
66365
|
-
import { join as
|
|
66272
|
+
import { join as join67, relative as relative12 } from "node:path";
|
|
66366
66273
|
init_types2();
|
|
66367
66274
|
var import_fs_extra19 = __toESM(require_lib(), 1);
|
|
66368
66275
|
|
|
@@ -66386,12 +66293,12 @@ class SkillsManifestManager {
|
|
|
66386
66293
|
return manifest;
|
|
66387
66294
|
}
|
|
66388
66295
|
static async writeManifest(skillsDir, manifest) {
|
|
66389
|
-
const manifestPath =
|
|
66296
|
+
const manifestPath = join67(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
66390
66297
|
await writeFile23(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
66391
66298
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
66392
66299
|
}
|
|
66393
66300
|
static async readManifest(skillsDir) {
|
|
66394
|
-
const manifestPath =
|
|
66301
|
+
const manifestPath = join67(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
66395
66302
|
if (!await import_fs_extra19.pathExists(manifestPath)) {
|
|
66396
66303
|
logger.debug(`No manifest found at: ${manifestPath}`);
|
|
66397
66304
|
return null;
|
|
@@ -66414,7 +66321,7 @@ class SkillsManifestManager {
|
|
|
66414
66321
|
return "flat";
|
|
66415
66322
|
}
|
|
66416
66323
|
for (const dir of dirs.slice(0, 3)) {
|
|
66417
|
-
const dirPath =
|
|
66324
|
+
const dirPath = join67(skillsDir, dir.name);
|
|
66418
66325
|
const subEntries = await readdir17(dirPath, { withFileTypes: true });
|
|
66419
66326
|
const hasSubdirs = subEntries.some((entry) => entry.isDirectory());
|
|
66420
66327
|
if (hasSubdirs) {
|
|
@@ -66433,7 +66340,7 @@ class SkillsManifestManager {
|
|
|
66433
66340
|
const entries = await readdir17(skillsDir, { withFileTypes: true });
|
|
66434
66341
|
for (const entry of entries) {
|
|
66435
66342
|
if (entry.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
|
|
66436
|
-
const skillPath =
|
|
66343
|
+
const skillPath = join67(skillsDir, entry.name);
|
|
66437
66344
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
66438
66345
|
skills.push({
|
|
66439
66346
|
name: entry.name,
|
|
@@ -66445,11 +66352,11 @@ class SkillsManifestManager {
|
|
|
66445
66352
|
const categories = await readdir17(skillsDir, { withFileTypes: true });
|
|
66446
66353
|
for (const category of categories) {
|
|
66447
66354
|
if (category.isDirectory() && !BUILD_ARTIFACT_DIRS.includes(category.name) && !category.name.startsWith(".")) {
|
|
66448
|
-
const categoryPath =
|
|
66355
|
+
const categoryPath = join67(skillsDir, category.name);
|
|
66449
66356
|
const skillEntries = await readdir17(categoryPath, { withFileTypes: true });
|
|
66450
66357
|
for (const skillEntry of skillEntries) {
|
|
66451
66358
|
if (skillEntry.isDirectory() && !skillEntry.name.startsWith(".")) {
|
|
66452
|
-
const skillPath =
|
|
66359
|
+
const skillPath = join67(categoryPath, skillEntry.name);
|
|
66453
66360
|
const hash = await SkillsManifestManager.hashDirectory(skillPath);
|
|
66454
66361
|
skills.push({
|
|
66455
66362
|
name: skillEntry.name,
|
|
@@ -66479,7 +66386,7 @@ class SkillsManifestManager {
|
|
|
66479
66386
|
const files = [];
|
|
66480
66387
|
const entries = await readdir17(dirPath, { withFileTypes: true });
|
|
66481
66388
|
for (const entry of entries) {
|
|
66482
|
-
const fullPath =
|
|
66389
|
+
const fullPath = join67(dirPath, entry.name);
|
|
66483
66390
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name)) {
|
|
66484
66391
|
continue;
|
|
66485
66392
|
}
|
|
@@ -66599,7 +66506,7 @@ function getPathMapping(skillName, oldBasePath, newBasePath) {
|
|
|
66599
66506
|
// src/domains/skills/detection/script-detector.ts
|
|
66600
66507
|
var import_fs_extra20 = __toESM(require_lib(), 1);
|
|
66601
66508
|
import { readdir as readdir18 } from "node:fs/promises";
|
|
66602
|
-
import { join as
|
|
66509
|
+
import { join as join68 } from "node:path";
|
|
66603
66510
|
async function scanDirectory(skillsDir) {
|
|
66604
66511
|
if (!await import_fs_extra20.pathExists(skillsDir)) {
|
|
66605
66512
|
return ["flat", []];
|
|
@@ -66612,12 +66519,12 @@ async function scanDirectory(skillsDir) {
|
|
|
66612
66519
|
let totalSkillLikeCount = 0;
|
|
66613
66520
|
const allSkills = [];
|
|
66614
66521
|
for (const dir of dirs) {
|
|
66615
|
-
const dirPath =
|
|
66522
|
+
const dirPath = join68(skillsDir, dir.name);
|
|
66616
66523
|
const subEntries = await readdir18(dirPath, { withFileTypes: true });
|
|
66617
66524
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
66618
66525
|
if (subdirs.length > 0) {
|
|
66619
66526
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
66620
|
-
const subdirPath =
|
|
66527
|
+
const subdirPath = join68(dirPath, subdir.name);
|
|
66621
66528
|
const subdirFiles = await readdir18(subdirPath, { withFileTypes: true });
|
|
66622
66529
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
66623
66530
|
if (hasSkillMarker) {
|
|
@@ -66774,12 +66681,12 @@ class SkillsMigrationDetector {
|
|
|
66774
66681
|
// src/domains/skills/skills-migrator.ts
|
|
66775
66682
|
init_logger();
|
|
66776
66683
|
init_types2();
|
|
66777
|
-
import { join as
|
|
66684
|
+
import { join as join73 } from "node:path";
|
|
66778
66685
|
|
|
66779
66686
|
// src/domains/skills/migrator/migration-executor.ts
|
|
66780
66687
|
init_logger();
|
|
66781
66688
|
import { copyFile as copyFile4, mkdir as mkdir21, readdir as readdir19, rm as rm6 } from "node:fs/promises";
|
|
66782
|
-
import { join as
|
|
66689
|
+
import { join as join69 } from "node:path";
|
|
66783
66690
|
var import_fs_extra22 = __toESM(require_lib(), 1);
|
|
66784
66691
|
|
|
66785
66692
|
// src/domains/skills/skills-migration-prompts.ts
|
|
@@ -66944,8 +66851,8 @@ async function copySkillDirectory(sourceDir, destDir) {
|
|
|
66944
66851
|
await mkdir21(destDir, { recursive: true });
|
|
66945
66852
|
const entries = await readdir19(sourceDir, { withFileTypes: true });
|
|
66946
66853
|
for (const entry of entries) {
|
|
66947
|
-
const sourcePath =
|
|
66948
|
-
const destPath =
|
|
66854
|
+
const sourcePath = join69(sourceDir, entry.name);
|
|
66855
|
+
const destPath = join69(destDir, entry.name);
|
|
66949
66856
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
66950
66857
|
continue;
|
|
66951
66858
|
}
|
|
@@ -66960,7 +66867,7 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
66960
66867
|
const migrated = [];
|
|
66961
66868
|
const preserved = [];
|
|
66962
66869
|
const errors2 = [];
|
|
66963
|
-
const tempDir =
|
|
66870
|
+
const tempDir = join69(currentSkillsDir, "..", ".skills-migration-temp");
|
|
66964
66871
|
await mkdir21(tempDir, { recursive: true });
|
|
66965
66872
|
try {
|
|
66966
66873
|
for (const mapping of mappings) {
|
|
@@ -66981,9 +66888,9 @@ async function executeInternal(mappings, customizations, currentSkillsDir, inter
|
|
|
66981
66888
|
}
|
|
66982
66889
|
}
|
|
66983
66890
|
const category = mapping.category;
|
|
66984
|
-
const targetPath = category ?
|
|
66891
|
+
const targetPath = category ? join69(tempDir, category, skillName) : join69(tempDir, skillName);
|
|
66985
66892
|
if (category) {
|
|
66986
|
-
await mkdir21(
|
|
66893
|
+
await mkdir21(join69(tempDir, category), { recursive: true });
|
|
66987
66894
|
}
|
|
66988
66895
|
await copySkillDirectory(currentSkillPath, targetPath);
|
|
66989
66896
|
migrated.push(skillName);
|
|
@@ -67050,7 +66957,7 @@ init_logger();
|
|
|
67050
66957
|
init_types2();
|
|
67051
66958
|
var import_fs_extra23 = __toESM(require_lib(), 1);
|
|
67052
66959
|
import { copyFile as copyFile5, mkdir as mkdir22, readdir as readdir20, rm as rm7, stat as stat9 } from "node:fs/promises";
|
|
67053
|
-
import { basename as basename3, join as
|
|
66960
|
+
import { basename as basename3, join as join70, normalize as normalize6 } from "node:path";
|
|
67054
66961
|
function validatePath2(path6, paramName) {
|
|
67055
66962
|
if (!path6 || typeof path6 !== "string") {
|
|
67056
66963
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -67076,7 +66983,7 @@ class SkillsBackupManager {
|
|
|
67076
66983
|
const timestamp = Date.now();
|
|
67077
66984
|
const randomSuffix = Math.random().toString(36).substring(2, 8);
|
|
67078
66985
|
const backupDirName = `${SkillsBackupManager.BACKUP_PREFIX}${timestamp}-${randomSuffix}`;
|
|
67079
|
-
const backupDir = parentDir ?
|
|
66986
|
+
const backupDir = parentDir ? join70(parentDir, backupDirName) : join70(skillsDir, "..", backupDirName);
|
|
67080
66987
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
67081
66988
|
try {
|
|
67082
66989
|
await mkdir22(backupDir, { recursive: true });
|
|
@@ -67127,7 +67034,7 @@ class SkillsBackupManager {
|
|
|
67127
67034
|
}
|
|
67128
67035
|
try {
|
|
67129
67036
|
const entries = await readdir20(parentDir, { withFileTypes: true });
|
|
67130
|
-
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) =>
|
|
67037
|
+
const backups = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith(SkillsBackupManager.BACKUP_PREFIX)).map((entry) => join70(parentDir, entry.name));
|
|
67131
67038
|
backups.sort().reverse();
|
|
67132
67039
|
return backups;
|
|
67133
67040
|
} catch (error) {
|
|
@@ -67155,8 +67062,8 @@ class SkillsBackupManager {
|
|
|
67155
67062
|
static async copyDirectory(sourceDir, destDir) {
|
|
67156
67063
|
const entries = await readdir20(sourceDir, { withFileTypes: true });
|
|
67157
67064
|
for (const entry of entries) {
|
|
67158
|
-
const sourcePath =
|
|
67159
|
-
const destPath =
|
|
67065
|
+
const sourcePath = join70(sourceDir, entry.name);
|
|
67066
|
+
const destPath = join70(destDir, entry.name);
|
|
67160
67067
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.isSymbolicLink()) {
|
|
67161
67068
|
continue;
|
|
67162
67069
|
}
|
|
@@ -67172,7 +67079,7 @@ class SkillsBackupManager {
|
|
|
67172
67079
|
let size = 0;
|
|
67173
67080
|
const entries = await readdir20(dirPath, { withFileTypes: true });
|
|
67174
67081
|
for (const entry of entries) {
|
|
67175
|
-
const fullPath =
|
|
67082
|
+
const fullPath = join70(dirPath, entry.name);
|
|
67176
67083
|
if (entry.isSymbolicLink()) {
|
|
67177
67084
|
continue;
|
|
67178
67085
|
}
|
|
@@ -67207,12 +67114,12 @@ import { relative as relative14 } from "node:path";
|
|
|
67207
67114
|
import { createHash as createHash6 } from "node:crypto";
|
|
67208
67115
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
67209
67116
|
import { readFile as readFile29, readdir as readdir21 } from "node:fs/promises";
|
|
67210
|
-
import { join as
|
|
67117
|
+
import { join as join71, relative as relative13 } from "node:path";
|
|
67211
67118
|
async function getAllFiles(dirPath) {
|
|
67212
67119
|
const files = [];
|
|
67213
67120
|
const entries = await readdir21(dirPath, { withFileTypes: true });
|
|
67214
67121
|
for (const entry of entries) {
|
|
67215
|
-
const fullPath =
|
|
67122
|
+
const fullPath = join71(dirPath, entry.name);
|
|
67216
67123
|
if (entry.name.startsWith(".") || BUILD_ARTIFACT_DIRS.includes(entry.name) || entry.isSymbolicLink()) {
|
|
67217
67124
|
continue;
|
|
67218
67125
|
}
|
|
@@ -67339,7 +67246,7 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
|
|
|
67339
67246
|
init_types2();
|
|
67340
67247
|
var import_fs_extra25 = __toESM(require_lib(), 1);
|
|
67341
67248
|
import { readdir as readdir22 } from "node:fs/promises";
|
|
67342
|
-
import { join as
|
|
67249
|
+
import { join as join72, normalize as normalize7 } from "node:path";
|
|
67343
67250
|
function validatePath3(path6, paramName) {
|
|
67344
67251
|
if (!path6 || typeof path6 !== "string") {
|
|
67345
67252
|
throw new SkillsMigrationError(`${paramName} must be a non-empty string`);
|
|
@@ -67360,13 +67267,13 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
67360
67267
|
if (dirs.length === 0) {
|
|
67361
67268
|
return ["flat", []];
|
|
67362
67269
|
}
|
|
67363
|
-
const firstDirPath =
|
|
67270
|
+
const firstDirPath = join72(skillsDir, dirs[0].name);
|
|
67364
67271
|
const subEntries = await readdir22(firstDirPath, { withFileTypes: true });
|
|
67365
67272
|
const subdirs = subEntries.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."));
|
|
67366
67273
|
if (subdirs.length > 0) {
|
|
67367
67274
|
let skillLikeCount = 0;
|
|
67368
67275
|
for (const subdir of subdirs.slice(0, 3)) {
|
|
67369
|
-
const subdirPath =
|
|
67276
|
+
const subdirPath = join72(firstDirPath, subdir.name);
|
|
67370
67277
|
const subdirFiles = await readdir22(subdirPath, { withFileTypes: true });
|
|
67371
67278
|
const hasSkillMarker = subdirFiles.some((file) => file.isFile() && (file.name === "skill.md" || file.name === "README.md" || file.name === "readme.md" || file.name === "config.json" || file.name === "package.json"));
|
|
67372
67279
|
if (hasSkillMarker) {
|
|
@@ -67376,7 +67283,7 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
67376
67283
|
if (skillLikeCount > 0) {
|
|
67377
67284
|
const skills = [];
|
|
67378
67285
|
for (const dir of dirs) {
|
|
67379
|
-
const categoryPath =
|
|
67286
|
+
const categoryPath = join72(skillsDir, dir.name);
|
|
67380
67287
|
const skillDirs = await readdir22(categoryPath, { withFileTypes: true });
|
|
67381
67288
|
skills.push(...skillDirs.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name));
|
|
67382
67289
|
}
|
|
@@ -67386,7 +67293,7 @@ async function scanSkillsDirectory(skillsDir) {
|
|
|
67386
67293
|
return ["flat", dirs.map((dir) => dir.name)];
|
|
67387
67294
|
}
|
|
67388
67295
|
async function findSkillPath(skillsDir, skillName) {
|
|
67389
|
-
const flatPath =
|
|
67296
|
+
const flatPath = join72(skillsDir, skillName);
|
|
67390
67297
|
if (await import_fs_extra25.pathExists(flatPath)) {
|
|
67391
67298
|
return { path: flatPath, category: undefined };
|
|
67392
67299
|
}
|
|
@@ -67395,8 +67302,8 @@ async function findSkillPath(skillsDir, skillName) {
|
|
|
67395
67302
|
if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
67396
67303
|
continue;
|
|
67397
67304
|
}
|
|
67398
|
-
const categoryPath =
|
|
67399
|
-
const skillPath =
|
|
67305
|
+
const categoryPath = join72(skillsDir, entry.name);
|
|
67306
|
+
const skillPath = join72(categoryPath, skillName);
|
|
67400
67307
|
if (await import_fs_extra25.pathExists(skillPath)) {
|
|
67401
67308
|
return { path: skillPath, category: entry.name };
|
|
67402
67309
|
}
|
|
@@ -67490,7 +67397,7 @@ class SkillsMigrator {
|
|
|
67490
67397
|
}
|
|
67491
67398
|
}
|
|
67492
67399
|
if (options2.backup && !options2.dryRun) {
|
|
67493
|
-
const claudeDir =
|
|
67400
|
+
const claudeDir = join73(currentSkillsDir, "..");
|
|
67494
67401
|
result.backupPath = await SkillsBackupManager.createBackup(currentSkillsDir, claudeDir);
|
|
67495
67402
|
logger.success(`Backup created at: ${result.backupPath}`);
|
|
67496
67403
|
}
|
|
@@ -67551,7 +67458,7 @@ async function handleMigration(ctx) {
|
|
|
67551
67458
|
logger.debug("Skipping skills migration (fresh installation)");
|
|
67552
67459
|
return ctx;
|
|
67553
67460
|
}
|
|
67554
|
-
const newSkillsDir =
|
|
67461
|
+
const newSkillsDir = join74(ctx.extractDir, ".claude", "skills");
|
|
67555
67462
|
const currentSkillsDir = PathResolver.buildSkillsPath(ctx.resolvedDir, ctx.options.global);
|
|
67556
67463
|
if (!await import_fs_extra26.pathExists(newSkillsDir) || !await import_fs_extra26.pathExists(currentSkillsDir)) {
|
|
67557
67464
|
return ctx;
|
|
@@ -67575,13 +67482,13 @@ async function handleMigration(ctx) {
|
|
|
67575
67482
|
}
|
|
67576
67483
|
// src/commands/init/phases/opencode-handler.ts
|
|
67577
67484
|
import { cp, readdir as readdir24, rm as rm8 } from "node:fs/promises";
|
|
67578
|
-
import { join as
|
|
67485
|
+
import { join as join76 } from "node:path";
|
|
67579
67486
|
|
|
67580
67487
|
// src/services/transformers/opencode-path-transformer.ts
|
|
67581
67488
|
init_logger();
|
|
67582
67489
|
import { readFile as readFile30, readdir as readdir23, writeFile as writeFile24 } from "node:fs/promises";
|
|
67583
67490
|
import { platform as platform8 } from "node:os";
|
|
67584
|
-
import { extname as extname3, join as
|
|
67491
|
+
import { extname as extname3, join as join75 } from "node:path";
|
|
67585
67492
|
var IS_WINDOWS2 = platform8() === "win32";
|
|
67586
67493
|
function getOpenCodeGlobalPath() {
|
|
67587
67494
|
return "$HOME/.config/opencode/";
|
|
@@ -67642,7 +67549,7 @@ async function transformPathsForGlobalOpenCode(directory, options2 = {}) {
|
|
|
67642
67549
|
async function processDirectory2(dir) {
|
|
67643
67550
|
const entries = await readdir23(dir, { withFileTypes: true });
|
|
67644
67551
|
for (const entry of entries) {
|
|
67645
|
-
const fullPath =
|
|
67552
|
+
const fullPath = join75(dir, entry.name);
|
|
67646
67553
|
if (entry.isDirectory()) {
|
|
67647
67554
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) {
|
|
67648
67555
|
continue;
|
|
@@ -67681,7 +67588,7 @@ async function handleOpenCode(ctx) {
|
|
|
67681
67588
|
if (ctx.cancelled || !ctx.extractDir || !ctx.resolvedDir) {
|
|
67682
67589
|
return ctx;
|
|
67683
67590
|
}
|
|
67684
|
-
const openCodeSource =
|
|
67591
|
+
const openCodeSource = join76(ctx.extractDir, ".opencode");
|
|
67685
67592
|
if (!await import_fs_extra27.pathExists(openCodeSource)) {
|
|
67686
67593
|
logger.debug("No .opencode directory in archive, skipping");
|
|
67687
67594
|
return ctx;
|
|
@@ -67699,8 +67606,8 @@ async function handleOpenCode(ctx) {
|
|
|
67699
67606
|
await import_fs_extra27.ensureDir(targetDir);
|
|
67700
67607
|
const entries = await readdir24(openCodeSource, { withFileTypes: true });
|
|
67701
67608
|
for (const entry of entries) {
|
|
67702
|
-
const sourcePath =
|
|
67703
|
-
const targetPath =
|
|
67609
|
+
const sourcePath = join76(openCodeSource, entry.name);
|
|
67610
|
+
const targetPath = join76(targetDir, entry.name);
|
|
67704
67611
|
if (await import_fs_extra27.pathExists(targetPath)) {
|
|
67705
67612
|
if (!ctx.options.forceOverwrite) {
|
|
67706
67613
|
logger.verbose(`Skipping existing: ${entry.name}`);
|
|
@@ -67805,16 +67712,16 @@ Choose one approach.`);
|
|
|
67805
67712
|
};
|
|
67806
67713
|
}
|
|
67807
67714
|
// src/commands/init/phases/post-install-handler.ts
|
|
67808
|
-
import { join as
|
|
67715
|
+
import { join as join78 } from "node:path";
|
|
67809
67716
|
|
|
67810
67717
|
// src/domains/takumi-data/projects-registry.ts
|
|
67811
67718
|
init_logger();
|
|
67812
67719
|
init_path_resolver();
|
|
67813
67720
|
init_types2();
|
|
67814
67721
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
67815
|
-
import { existsSync as
|
|
67722
|
+
import { existsSync as existsSync30, statSync as statSync3 } from "node:fs";
|
|
67816
67723
|
import { copyFile as copyFile6, mkdir as mkdir23, open as open2, readFile as readFile31, unlink as unlink10, writeFile as writeFile25 } from "node:fs/promises";
|
|
67817
|
-
import { basename as basename4, dirname as
|
|
67724
|
+
import { basename as basename4, dirname as dirname15, resolve as resolve11 } from "node:path";
|
|
67818
67725
|
|
|
67819
67726
|
class ProjectsRegistryManager {
|
|
67820
67727
|
static registry = null;
|
|
@@ -67825,8 +67732,8 @@ class ProjectsRegistryManager {
|
|
|
67825
67732
|
static LOCK_MAX_RETRIES = 50;
|
|
67826
67733
|
static async acquireLock(retries = 0) {
|
|
67827
67734
|
const lockPath = `${PathResolver.getProjectsRegistryPath()}.lock`;
|
|
67828
|
-
const lockDir =
|
|
67829
|
-
if (!
|
|
67735
|
+
const lockDir = dirname15(lockPath);
|
|
67736
|
+
if (!existsSync30(lockDir)) {
|
|
67830
67737
|
await mkdir23(lockDir, { recursive: true });
|
|
67831
67738
|
}
|
|
67832
67739
|
try {
|
|
@@ -67834,7 +67741,7 @@ class ProjectsRegistryManager {
|
|
|
67834
67741
|
} catch (err) {
|
|
67835
67742
|
const error = err;
|
|
67836
67743
|
if (error.code === "EEXIST") {
|
|
67837
|
-
if (
|
|
67744
|
+
if (existsSync30(lockPath)) {
|
|
67838
67745
|
const lockStat = statSync3(lockPath);
|
|
67839
67746
|
const lockAge = Date.now() - lockStat.mtimeMs;
|
|
67840
67747
|
const STALE_LOCK_MS = 30000;
|
|
@@ -67871,7 +67778,7 @@ class ProjectsRegistryManager {
|
|
|
67871
67778
|
await ProjectsRegistryManager.acquireLock();
|
|
67872
67779
|
try {
|
|
67873
67780
|
const registryPath = PathResolver.getProjectsRegistryPath();
|
|
67874
|
-
if (
|
|
67781
|
+
if (existsSync30(registryPath)) {
|
|
67875
67782
|
const content = await readFile31(registryPath, "utf-8");
|
|
67876
67783
|
const data = JSON.parse(content);
|
|
67877
67784
|
if (data.projects && !Array.isArray(data.projects)) {
|
|
@@ -67914,8 +67821,8 @@ class ProjectsRegistryManager {
|
|
|
67914
67821
|
try {
|
|
67915
67822
|
const validRegistry = ProjectsRegistrySchema.parse(registry);
|
|
67916
67823
|
const registryPath = PathResolver.getProjectsRegistryPath();
|
|
67917
|
-
const dir =
|
|
67918
|
-
if (!
|
|
67824
|
+
const dir = dirname15(registryPath);
|
|
67825
|
+
if (!existsSync30(dir)) {
|
|
67919
67826
|
await mkdir23(dir, { recursive: true });
|
|
67920
67827
|
}
|
|
67921
67828
|
await writeFile25(registryPath, JSON.stringify(validRegistry, null, 2), "utf-8");
|
|
@@ -67933,7 +67840,7 @@ class ProjectsRegistryManager {
|
|
|
67933
67840
|
throw new Error("Invalid path: path traversal patterns not allowed");
|
|
67934
67841
|
}
|
|
67935
67842
|
const absolutePath = resolve11(projectPath);
|
|
67936
|
-
if (!
|
|
67843
|
+
if (!existsSync30(absolutePath)) {
|
|
67937
67844
|
throw new Error(`Path does not exist: ${absolutePath}`);
|
|
67938
67845
|
}
|
|
67939
67846
|
const stat10 = statSync3(absolutePath);
|
|
@@ -68082,8 +67989,8 @@ async function handlePostInstall(ctx) {
|
|
|
68082
67989
|
return ctx;
|
|
68083
67990
|
}
|
|
68084
67991
|
if (ctx.options.global) {
|
|
68085
|
-
const claudeMdSource =
|
|
68086
|
-
const claudeMdDest =
|
|
67992
|
+
const claudeMdSource = join78(ctx.extractDir, "CLAUDE.md");
|
|
67993
|
+
const claudeMdDest = join78(ctx.resolvedDir, "CLAUDE.md");
|
|
68087
67994
|
if (await import_fs_extra28.pathExists(claudeMdSource)) {
|
|
68088
67995
|
if (ctx.options.fresh || !await import_fs_extra28.pathExists(claudeMdDest)) {
|
|
68089
67996
|
await import_fs_extra28.copy(claudeMdSource, claudeMdDest);
|
|
@@ -68145,7 +68052,7 @@ async function handlePostInstall(ctx) {
|
|
|
68145
68052
|
// src/commands/init/phases/selection-handler.ts
|
|
68146
68053
|
init_auth_client();
|
|
68147
68054
|
import { mkdir as mkdir24 } from "node:fs/promises";
|
|
68148
|
-
import { join as
|
|
68055
|
+
import { join as join80, resolve as resolve13 } from "node:path";
|
|
68149
68056
|
init_github_client();
|
|
68150
68057
|
|
|
68151
68058
|
// src/domains/github/kit-access-checker.ts
|
|
@@ -68274,8 +68181,8 @@ async function runPreflightChecks() {
|
|
|
68274
68181
|
}
|
|
68275
68182
|
|
|
68276
68183
|
// src/domains/installation/fresh-installer.ts
|
|
68277
|
-
import { existsSync as
|
|
68278
|
-
import { dirname as
|
|
68184
|
+
import { existsSync as existsSync31, readdirSync as readdirSync3, rmSync as rmSync3, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
|
|
68185
|
+
import { dirname as dirname16, join as join79, resolve as resolve12 } from "node:path";
|
|
68279
68186
|
init_logger();
|
|
68280
68187
|
var import_fs_extra29 = __toESM(require_lib(), 1);
|
|
68281
68188
|
var TAKUMI_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
|
|
@@ -68323,14 +68230,14 @@ async function analyzeFreshInstallation(claudeDir) {
|
|
|
68323
68230
|
}
|
|
68324
68231
|
function cleanupEmptyDirectories2(filePath, claudeDir) {
|
|
68325
68232
|
const normalizedClaudeDir = resolve12(claudeDir);
|
|
68326
|
-
let currentDir = resolve12(
|
|
68233
|
+
let currentDir = resolve12(dirname16(filePath));
|
|
68327
68234
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
68328
68235
|
try {
|
|
68329
68236
|
const entries = readdirSync3(currentDir);
|
|
68330
68237
|
if (entries.length === 0) {
|
|
68331
68238
|
rmdirSync2(currentDir);
|
|
68332
68239
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
68333
|
-
currentDir = resolve12(
|
|
68240
|
+
currentDir = resolve12(dirname16(currentDir));
|
|
68334
68241
|
} else {
|
|
68335
68242
|
break;
|
|
68336
68243
|
}
|
|
@@ -68347,10 +68254,10 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
68347
68254
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
68348
68255
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
68349
68256
|
for (const file of filesToRemove) {
|
|
68350
|
-
const fullPath =
|
|
68257
|
+
const fullPath = join79(claudeDir, file.path);
|
|
68351
68258
|
try {
|
|
68352
|
-
if (
|
|
68353
|
-
|
|
68259
|
+
if (existsSync31(fullPath)) {
|
|
68260
|
+
unlinkSync4(fullPath);
|
|
68354
68261
|
removedFiles.push(file.path);
|
|
68355
68262
|
logger.debug(`Removed: ${file.path}`);
|
|
68356
68263
|
cleanupEmptyDirectories2(fullPath, claudeDir);
|
|
@@ -68372,7 +68279,7 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
68372
68279
|
};
|
|
68373
68280
|
}
|
|
68374
68281
|
async function updateMetadataAfterFresh(claudeDir, removedFiles) {
|
|
68375
|
-
const metadataPath =
|
|
68282
|
+
const metadataPath = join79(claudeDir, "metadata.json");
|
|
68376
68283
|
if (!await import_fs_extra29.pathExists(metadataPath)) {
|
|
68377
68284
|
return;
|
|
68378
68285
|
}
|
|
@@ -68415,7 +68322,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
68415
68322
|
const removedFiles = [];
|
|
68416
68323
|
let removedDirCount = 0;
|
|
68417
68324
|
for (const subdir of TAKUMI_SUBDIRECTORIES) {
|
|
68418
|
-
const subdirPath =
|
|
68325
|
+
const subdirPath = join79(claudeDir, subdir);
|
|
68419
68326
|
if (await import_fs_extra29.pathExists(subdirPath)) {
|
|
68420
68327
|
rmSync3(subdirPath, { recursive: true, force: true });
|
|
68421
68328
|
removedDirCount++;
|
|
@@ -68423,9 +68330,9 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
68423
68330
|
logger.debug(`Removed subdirectory: ${subdir}/`);
|
|
68424
68331
|
}
|
|
68425
68332
|
}
|
|
68426
|
-
const metadataPath =
|
|
68333
|
+
const metadataPath = join79(claudeDir, "metadata.json");
|
|
68427
68334
|
if (await import_fs_extra29.pathExists(metadataPath)) {
|
|
68428
|
-
|
|
68335
|
+
unlinkSync4(metadataPath);
|
|
68429
68336
|
removedFiles.push("metadata.json");
|
|
68430
68337
|
}
|
|
68431
68338
|
return {
|
|
@@ -68633,7 +68540,7 @@ async function handleSelection(ctx) {
|
|
|
68633
68540
|
}
|
|
68634
68541
|
if (!ctx.options.fresh) {
|
|
68635
68542
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
68636
|
-
const claudeDir = prefix ?
|
|
68543
|
+
const claudeDir = prefix ? join80(resolvedDir, prefix) : resolvedDir;
|
|
68637
68544
|
try {
|
|
68638
68545
|
const existingMetadata = await readManifest(claudeDir);
|
|
68639
68546
|
if (existingMetadata?.kits) {
|
|
@@ -68666,7 +68573,7 @@ async function handleSelection(ctx) {
|
|
|
68666
68573
|
}
|
|
68667
68574
|
if (ctx.options.fresh) {
|
|
68668
68575
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
68669
|
-
const claudeDir = prefix ?
|
|
68576
|
+
const claudeDir = prefix ? join80(resolvedDir, prefix) : resolvedDir;
|
|
68670
68577
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
68671
68578
|
if (!canProceed) {
|
|
68672
68579
|
return { ...ctx, cancelled: true };
|
|
@@ -68686,7 +68593,7 @@ async function handleSelection(ctx) {
|
|
|
68686
68593
|
let currentVersion = null;
|
|
68687
68594
|
try {
|
|
68688
68595
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
68689
|
-
const claudeDir = prefix ?
|
|
68596
|
+
const claudeDir = prefix ? join80(resolvedDir, prefix) : resolvedDir;
|
|
68690
68597
|
const existingMetadata = await readManifest(claudeDir);
|
|
68691
68598
|
currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
|
|
68692
68599
|
if (currentVersion) {
|
|
@@ -68774,7 +68681,7 @@ async function handleSelection(ctx) {
|
|
|
68774
68681
|
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
|
|
68775
68682
|
try {
|
|
68776
68683
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
68777
|
-
const claudeDir = prefix ?
|
|
68684
|
+
const claudeDir = prefix ? join80(resolvedDir, prefix) : resolvedDir;
|
|
68778
68685
|
const existingMetadata = await readManifest(claudeDir);
|
|
68779
68686
|
const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
|
|
68780
68687
|
if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
|
|
@@ -68797,7 +68704,7 @@ async function handleSelection(ctx) {
|
|
|
68797
68704
|
}
|
|
68798
68705
|
// src/commands/init/phases/sync-handler.ts
|
|
68799
68706
|
import { copyFile as copyFile7, mkdir as mkdir25, open as open3, readFile as readFile33, rename as rename4, stat as stat10, unlink as unlink11, writeFile as writeFile27 } from "node:fs/promises";
|
|
68800
|
-
import { dirname as
|
|
68707
|
+
import { dirname as dirname17, join as join81, resolve as resolve14 } from "node:path";
|
|
68801
68708
|
init_logger();
|
|
68802
68709
|
init_path_resolver();
|
|
68803
68710
|
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
@@ -68807,13 +68714,13 @@ async function handleSync(ctx) {
|
|
|
68807
68714
|
return ctx;
|
|
68808
68715
|
}
|
|
68809
68716
|
const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve14(ctx.options.dir || ".");
|
|
68810
|
-
const claudeDir = ctx.options.global ? resolvedDir :
|
|
68717
|
+
const claudeDir = ctx.options.global ? resolvedDir : join81(resolvedDir, ".claude");
|
|
68811
68718
|
if (!await import_fs_extra31.pathExists(claudeDir)) {
|
|
68812
68719
|
logger.error("Cannot sync: no .claude directory found");
|
|
68813
68720
|
ctx.prompts.note("Run 'takumi init' without --sync to install first.", "No Installation Found");
|
|
68814
68721
|
return { ...ctx, cancelled: true };
|
|
68815
68722
|
}
|
|
68816
|
-
const metadataPath =
|
|
68723
|
+
const metadataPath = join81(claudeDir, "metadata.json");
|
|
68817
68724
|
if (!await import_fs_extra31.pathExists(metadataPath)) {
|
|
68818
68725
|
logger.error("Cannot sync: no metadata.json found");
|
|
68819
68726
|
ctx.prompts.note(`Your installation may be from an older version.
|
|
@@ -68903,10 +68810,10 @@ function getLockTimeout() {
|
|
|
68903
68810
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
68904
68811
|
async function acquireSyncLock(global3) {
|
|
68905
68812
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
68906
|
-
const lockPath =
|
|
68813
|
+
const lockPath = join81(cacheDir, ".sync-lock");
|
|
68907
68814
|
const startTime = Date.now();
|
|
68908
68815
|
const lockTimeout = getLockTimeout();
|
|
68909
|
-
await mkdir25(
|
|
68816
|
+
await mkdir25(dirname17(lockPath), { recursive: true });
|
|
68910
68817
|
while (Date.now() - startTime < lockTimeout) {
|
|
68911
68818
|
try {
|
|
68912
68819
|
const handle = await open3(lockPath, "wx");
|
|
@@ -68949,10 +68856,10 @@ async function executeSyncMerge(ctx) {
|
|
|
68949
68856
|
const releaseLock = await acquireSyncLock(ctx.options.global);
|
|
68950
68857
|
try {
|
|
68951
68858
|
const trackedFiles = ctx.syncTrackedFiles;
|
|
68952
|
-
const upstreamDir = ctx.options.global ?
|
|
68859
|
+
const upstreamDir = ctx.options.global ? join81(ctx.extractDir, ".claude") : ctx.extractDir;
|
|
68953
68860
|
let deletions = [];
|
|
68954
68861
|
try {
|
|
68955
|
-
const sourceMetadataPath =
|
|
68862
|
+
const sourceMetadataPath = join81(upstreamDir, "metadata.json");
|
|
68956
68863
|
if (await import_fs_extra31.pathExists(sourceMetadataPath)) {
|
|
68957
68864
|
const content = await readFile33(sourceMetadataPath, "utf-8");
|
|
68958
68865
|
const sourceMetadata = JSON.parse(content);
|
|
@@ -68984,7 +68891,7 @@ async function executeSyncMerge(ctx) {
|
|
|
68984
68891
|
try {
|
|
68985
68892
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
68986
68893
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
68987
|
-
const targetDir =
|
|
68894
|
+
const targetDir = join81(targetPath, "..");
|
|
68988
68895
|
try {
|
|
68989
68896
|
await mkdir25(targetDir, { recursive: true });
|
|
68990
68897
|
} catch (mkdirError) {
|
|
@@ -69155,7 +69062,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
69155
69062
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
69156
69063
|
if (await import_fs_extra31.pathExists(sourcePath)) {
|
|
69157
69064
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
69158
|
-
const targetDir =
|
|
69065
|
+
const targetDir = join81(targetPath, "..");
|
|
69159
69066
|
await mkdir25(targetDir, { recursive: true });
|
|
69160
69067
|
await copyFile7(sourcePath, targetPath);
|
|
69161
69068
|
}
|
|
@@ -69169,7 +69076,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
69169
69076
|
}
|
|
69170
69077
|
}
|
|
69171
69078
|
// src/commands/init/phases/transform-handler.ts
|
|
69172
|
-
import { join as
|
|
69079
|
+
import { join as join85 } from "node:path";
|
|
69173
69080
|
|
|
69174
69081
|
// src/services/transformers/folder-path-transformer.ts
|
|
69175
69082
|
init_logger();
|
|
@@ -69180,38 +69087,38 @@ init_logger();
|
|
|
69180
69087
|
init_types2();
|
|
69181
69088
|
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
69182
69089
|
import { rename as rename5, rm as rm9 } from "node:fs/promises";
|
|
69183
|
-
import { join as
|
|
69090
|
+
import { join as join82, relative as relative15 } from "node:path";
|
|
69184
69091
|
async function collectDirsToRename(extractDir, folders) {
|
|
69185
69092
|
const dirsToRename = [];
|
|
69186
69093
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
69187
|
-
const docsPath =
|
|
69094
|
+
const docsPath = join82(extractDir, DEFAULT_FOLDERS.docs);
|
|
69188
69095
|
if (await import_fs_extra32.pathExists(docsPath)) {
|
|
69189
69096
|
dirsToRename.push({
|
|
69190
69097
|
from: docsPath,
|
|
69191
|
-
to:
|
|
69098
|
+
to: join82(extractDir, folders.docs)
|
|
69192
69099
|
});
|
|
69193
69100
|
}
|
|
69194
|
-
const claudeDocsPath =
|
|
69101
|
+
const claudeDocsPath = join82(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
69195
69102
|
if (await import_fs_extra32.pathExists(claudeDocsPath)) {
|
|
69196
69103
|
dirsToRename.push({
|
|
69197
69104
|
from: claudeDocsPath,
|
|
69198
|
-
to:
|
|
69105
|
+
to: join82(extractDir, ".claude", folders.docs)
|
|
69199
69106
|
});
|
|
69200
69107
|
}
|
|
69201
69108
|
}
|
|
69202
69109
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
69203
|
-
const plansPath =
|
|
69110
|
+
const plansPath = join82(extractDir, DEFAULT_FOLDERS.plans);
|
|
69204
69111
|
if (await import_fs_extra32.pathExists(plansPath)) {
|
|
69205
69112
|
dirsToRename.push({
|
|
69206
69113
|
from: plansPath,
|
|
69207
|
-
to:
|
|
69114
|
+
to: join82(extractDir, folders.plans)
|
|
69208
69115
|
});
|
|
69209
69116
|
}
|
|
69210
|
-
const claudePlansPath =
|
|
69117
|
+
const claudePlansPath = join82(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
69211
69118
|
if (await import_fs_extra32.pathExists(claudePlansPath)) {
|
|
69212
69119
|
dirsToRename.push({
|
|
69213
69120
|
from: claudePlansPath,
|
|
69214
|
-
to:
|
|
69121
|
+
to: join82(extractDir, ".claude", folders.plans)
|
|
69215
69122
|
});
|
|
69216
69123
|
}
|
|
69217
69124
|
}
|
|
@@ -69252,7 +69159,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
69252
69159
|
init_logger();
|
|
69253
69160
|
init_types2();
|
|
69254
69161
|
import { readFile as readFile34, readdir as readdir25, writeFile as writeFile28 } from "node:fs/promises";
|
|
69255
|
-
import { join as
|
|
69162
|
+
import { join as join83, relative as relative16 } from "node:path";
|
|
69256
69163
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
69257
69164
|
".md",
|
|
69258
69165
|
".txt",
|
|
@@ -69305,7 +69212,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
|
|
|
69305
69212
|
let replacementsCount = 0;
|
|
69306
69213
|
const entries = await readdir25(dir, { withFileTypes: true });
|
|
69307
69214
|
for (const entry of entries) {
|
|
69308
|
-
const fullPath =
|
|
69215
|
+
const fullPath = join83(dir, entry.name);
|
|
69309
69216
|
if (entry.isDirectory()) {
|
|
69310
69217
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
69311
69218
|
continue;
|
|
@@ -69442,7 +69349,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
69442
69349
|
init_logger();
|
|
69443
69350
|
import { readFile as readFile35, readdir as readdir26, writeFile as writeFile29 } from "node:fs/promises";
|
|
69444
69351
|
import { platform as platform9 } from "node:os";
|
|
69445
|
-
import { extname as extname4, join as
|
|
69352
|
+
import { extname as extname4, join as join84 } from "node:path";
|
|
69446
69353
|
var IS_WINDOWS3 = platform9() === "win32";
|
|
69447
69354
|
var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
|
|
69448
69355
|
function getHomeDirPrefix() {
|
|
@@ -69554,7 +69461,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
69554
69461
|
async function processDirectory2(dir) {
|
|
69555
69462
|
const entries = await readdir26(dir, { withFileTypes: true });
|
|
69556
69463
|
for (const entry of entries) {
|
|
69557
|
-
const fullPath =
|
|
69464
|
+
const fullPath = join84(dir, entry.name);
|
|
69558
69465
|
if (entry.isDirectory()) {
|
|
69559
69466
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
69560
69467
|
continue;
|
|
@@ -69630,7 +69537,7 @@ async function handleTransforms(ctx) {
|
|
|
69630
69537
|
logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.takumi.json" : "Saved folder configuration to .claude/.takumi.json");
|
|
69631
69538
|
}
|
|
69632
69539
|
}
|
|
69633
|
-
const claudeDir = ctx.options.global ? ctx.resolvedDir :
|
|
69540
|
+
const claudeDir = ctx.options.global ? ctx.resolvedDir : join85(ctx.resolvedDir, ".claude");
|
|
69634
69541
|
return {
|
|
69635
69542
|
...ctx,
|
|
69636
69543
|
foldersConfig,
|
|
@@ -69676,9 +69583,6 @@ function createInitContext(rawOptions, prompts) {
|
|
|
69676
69583
|
async function executeInit(options2, prompts) {
|
|
69677
69584
|
let ctx = createInitContext(options2, prompts);
|
|
69678
69585
|
ctx = await resolveOptions(ctx);
|
|
69679
|
-
if (ctx.cancelled)
|
|
69680
|
-
return;
|
|
69681
|
-
ctx = await handleIdentityResolution(ctx);
|
|
69682
69586
|
if (ctx.cancelled)
|
|
69683
69587
|
return;
|
|
69684
69588
|
ctx = await handleSync(ctx);
|
|
@@ -69755,23 +69659,23 @@ async function initCommand(options2) {
|
|
|
69755
69659
|
// src/commands/migrate/migrate-command.ts
|
|
69756
69660
|
init_dist2();
|
|
69757
69661
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
69758
|
-
import { existsSync as
|
|
69662
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
69759
69663
|
import { readFile as readFile41, rm as rm11, unlink as unlink12 } from "node:fs/promises";
|
|
69760
|
-
import { homedir as
|
|
69761
|
-
import { basename as basename6, join as
|
|
69664
|
+
import { homedir as homedir18 } from "node:os";
|
|
69665
|
+
import { basename as basename6, join as join90, resolve as resolve16 } from "node:path";
|
|
69762
69666
|
init_logger();
|
|
69763
69667
|
|
|
69764
69668
|
// src/commands/portable/config-discovery.ts
|
|
69765
|
-
import { existsSync as
|
|
69669
|
+
import { existsSync as existsSync32 } from "node:fs";
|
|
69766
69670
|
import { readFile as readFile36, readdir as readdir27 } from "node:fs/promises";
|
|
69767
|
-
import { homedir as
|
|
69768
|
-
import { extname as extname5, join as
|
|
69671
|
+
import { homedir as homedir16 } from "node:os";
|
|
69672
|
+
import { extname as extname5, join as join86, relative as relative17, sep as sep4 } from "node:path";
|
|
69769
69673
|
var HOOK_EXTENSIONS2 = new Set([".js", ".cjs", ".mjs", ".ts"]);
|
|
69770
69674
|
var SHELL_HOOK_EXTENSIONS = new Set([".sh", ".ps1", ".bat", ".cmd"]);
|
|
69771
69675
|
function resolveSourceOrigin(sourcePath) {
|
|
69772
69676
|
if (!sourcePath)
|
|
69773
69677
|
return "global";
|
|
69774
|
-
const home5 =
|
|
69678
|
+
const home5 = homedir16();
|
|
69775
69679
|
const cwd2 = process.cwd();
|
|
69776
69680
|
if (cwd2 === home5)
|
|
69777
69681
|
return "global";
|
|
@@ -69784,17 +69688,17 @@ function getConfigSourcePath() {
|
|
|
69784
69688
|
return findExistingProjectConfigPath(process.cwd()) ?? getGlobalConfigSourcePath();
|
|
69785
69689
|
}
|
|
69786
69690
|
function getGlobalConfigSourcePath() {
|
|
69787
|
-
return
|
|
69691
|
+
return join86(homedir16(), ".claude", "CLAUDE.md");
|
|
69788
69692
|
}
|
|
69789
69693
|
function getRulesSourcePath() {
|
|
69790
|
-
return findExistingProjectLayoutPath(process.cwd(), "rules") ??
|
|
69694
|
+
return findExistingProjectLayoutPath(process.cwd(), "rules") ?? join86(homedir16(), ".claude", "rules");
|
|
69791
69695
|
}
|
|
69792
69696
|
function getHooksSourcePath() {
|
|
69793
|
-
return findExistingProjectLayoutPath(process.cwd(), "hooks") ??
|
|
69697
|
+
return findExistingProjectLayoutPath(process.cwd(), "hooks") ?? join86(homedir16(), ".claude", "hooks");
|
|
69794
69698
|
}
|
|
69795
69699
|
async function discoverConfig(sourcePath) {
|
|
69796
69700
|
const path6 = sourcePath ?? getConfigSourcePath();
|
|
69797
|
-
if (!
|
|
69701
|
+
if (!existsSync32(path6)) {
|
|
69798
69702
|
return null;
|
|
69799
69703
|
}
|
|
69800
69704
|
const content = await readFile36(path6, "utf-8");
|
|
@@ -69809,7 +69713,7 @@ async function discoverConfig(sourcePath) {
|
|
|
69809
69713
|
}
|
|
69810
69714
|
async function discoverRules(sourcePath) {
|
|
69811
69715
|
const path6 = sourcePath ?? getRulesSourcePath();
|
|
69812
|
-
if (!
|
|
69716
|
+
if (!existsSync32(path6)) {
|
|
69813
69717
|
return [];
|
|
69814
69718
|
}
|
|
69815
69719
|
return discoverPortableFiles(path6, path6, {
|
|
@@ -69821,7 +69725,7 @@ async function discoverRules(sourcePath) {
|
|
|
69821
69725
|
}
|
|
69822
69726
|
async function discoverHooks(sourcePath) {
|
|
69823
69727
|
const path6 = sourcePath ?? getHooksSourcePath();
|
|
69824
|
-
if (!
|
|
69728
|
+
if (!existsSync32(path6)) {
|
|
69825
69729
|
return { items: [], skippedShellHooks: [] };
|
|
69826
69730
|
}
|
|
69827
69731
|
let entries;
|
|
@@ -69842,7 +69746,7 @@ async function discoverHooks(sourcePath) {
|
|
|
69842
69746
|
}
|
|
69843
69747
|
if (!HOOK_EXTENSIONS2.has(ext2))
|
|
69844
69748
|
continue;
|
|
69845
|
-
const fullPath =
|
|
69749
|
+
const fullPath = join86(path6, entry.name);
|
|
69846
69750
|
try {
|
|
69847
69751
|
const content = await readFile36(fullPath, "utf-8");
|
|
69848
69752
|
items.push({
|
|
@@ -69868,7 +69772,7 @@ async function discoverPortableFiles(dir, baseDir, options2) {
|
|
|
69868
69772
|
for (const entry of entries) {
|
|
69869
69773
|
if (entry.name.startsWith("."))
|
|
69870
69774
|
continue;
|
|
69871
|
-
const fullPath =
|
|
69775
|
+
const fullPath = join86(dir, entry.name);
|
|
69872
69776
|
if (entry.isSymbolicLink()) {
|
|
69873
69777
|
continue;
|
|
69874
69778
|
}
|
|
@@ -70047,12 +69951,12 @@ async function resolveConflict(action, options2) {
|
|
|
70047
69951
|
|
|
70048
69952
|
// src/commands/portable/hooks-settings-merger.ts
|
|
70049
69953
|
init_provider_registry();
|
|
70050
|
-
import { existsSync as
|
|
69954
|
+
import { existsSync as existsSync33, mkdirSync, renameSync, rmSync as rmSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
70051
69955
|
import { readFile as readFile37 } from "node:fs/promises";
|
|
70052
|
-
import { basename as basename5, dirname as
|
|
69956
|
+
import { basename as basename5, dirname as dirname18, join as join87 } from "node:path";
|
|
70053
69957
|
async function inspectHooksSettings(settingsPath) {
|
|
70054
69958
|
try {
|
|
70055
|
-
if (!
|
|
69959
|
+
if (!existsSync33(settingsPath)) {
|
|
70056
69960
|
return { status: "missing-file" };
|
|
70057
69961
|
}
|
|
70058
69962
|
const raw = await readFile37(settingsPath, "utf8");
|
|
@@ -70124,7 +70028,7 @@ function extractFilenameFromCommand(command) {
|
|
|
70124
70028
|
async function mergeHooksIntoSettings(targetSettingsPath, newHooks) {
|
|
70125
70029
|
let existingSettings = {};
|
|
70126
70030
|
let backupPath = null;
|
|
70127
|
-
if (
|
|
70031
|
+
if (existsSync33(targetSettingsPath)) {
|
|
70128
70032
|
let raw;
|
|
70129
70033
|
try {
|
|
70130
70034
|
raw = await readFile37(targetSettingsPath, "utf8");
|
|
@@ -70136,7 +70040,7 @@ async function mergeHooksIntoSettings(targetSettingsPath, newHooks) {
|
|
|
70136
70040
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
70137
70041
|
backupPath = `${targetSettingsPath}.${timestamp}.bak`;
|
|
70138
70042
|
try {
|
|
70139
|
-
|
|
70043
|
+
writeFileSync3(backupPath, raw);
|
|
70140
70044
|
} catch {
|
|
70141
70045
|
backupPath = null;
|
|
70142
70046
|
}
|
|
@@ -70144,12 +70048,12 @@ async function mergeHooksIntoSettings(targetSettingsPath, newHooks) {
|
|
|
70144
70048
|
const existingHooks = existingSettings.hooks ?? {};
|
|
70145
70049
|
const merged = deduplicateMerge(existingHooks, newHooks);
|
|
70146
70050
|
existingSettings.hooks = merged;
|
|
70147
|
-
const dir =
|
|
70148
|
-
|
|
70051
|
+
const dir = dirname18(targetSettingsPath);
|
|
70052
|
+
mkdirSync(dir, { recursive: true });
|
|
70149
70053
|
const tempPath = `${targetSettingsPath}.tmp`;
|
|
70150
70054
|
try {
|
|
70151
|
-
|
|
70152
|
-
|
|
70055
|
+
writeFileSync3(tempPath, JSON.stringify(existingSettings, null, 2));
|
|
70056
|
+
renameSync(tempPath, targetSettingsPath);
|
|
70153
70057
|
} catch (err) {
|
|
70154
70058
|
rmSync4(tempPath, { force: true });
|
|
70155
70059
|
throw new Error(`Failed to write settings: ${err}. Backup preserved at: ${backupPath}`);
|
|
@@ -70230,8 +70134,8 @@ async function migrateHooksSettings(options2) {
|
|
|
70230
70134
|
targetSettingsPath: null
|
|
70231
70135
|
};
|
|
70232
70136
|
}
|
|
70233
|
-
const resolvedSourcePath = isGlobal ? sourceSettingsPath :
|
|
70234
|
-
const resolvedTargetPath = isGlobal ? targetSettingsPath :
|
|
70137
|
+
const resolvedSourcePath = isGlobal ? sourceSettingsPath : join87(process.cwd(), sourceSettingsPath);
|
|
70138
|
+
const resolvedTargetPath = isGlobal ? targetSettingsPath : join87(process.cwd(), targetSettingsPath);
|
|
70235
70139
|
const sourceHooksResult = await inspectHooksSettings(resolvedSourcePath);
|
|
70236
70140
|
if (sourceHooksResult.status === "missing-file") {
|
|
70237
70141
|
return {
|
|
@@ -70497,7 +70401,7 @@ function displayMigrationSummary(plan, results, options2) {
|
|
|
70497
70401
|
init_zod();
|
|
70498
70402
|
init_logger();
|
|
70499
70403
|
var import_semver3 = __toESM(require_semver2(), 1);
|
|
70500
|
-
import { existsSync as
|
|
70404
|
+
import { existsSync as existsSync34 } from "node:fs";
|
|
70501
70405
|
import { readFile as readFile38 } from "node:fs/promises";
|
|
70502
70406
|
import path6 from "node:path";
|
|
70503
70407
|
var safeRelativePath = exports_external.string().min(1).refine((p2) => !p2.includes("..") && !path6.isAbsolute(p2), {
|
|
@@ -70531,7 +70435,7 @@ var PortableManifestSchema = exports_external.object({
|
|
|
70531
70435
|
async function loadPortableManifest(kitPath) {
|
|
70532
70436
|
const manifestPath = path6.join(kitPath, "portable-manifest.json");
|
|
70533
70437
|
try {
|
|
70534
|
-
if (!
|
|
70438
|
+
if (!existsSync34(manifestPath)) {
|
|
70535
70439
|
logger.verbose("No portable-manifest.json found — no evolution tracking");
|
|
70536
70440
|
return null;
|
|
70537
70441
|
}
|
|
@@ -70611,7 +70515,7 @@ async function backfillRegistryChecksums(actions, registry) {
|
|
|
70611
70515
|
}
|
|
70612
70516
|
|
|
70613
70517
|
// src/commands/portable/reconcile-state-builders.ts
|
|
70614
|
-
import { existsSync as
|
|
70518
|
+
import { existsSync as existsSync35 } from "node:fs";
|
|
70615
70519
|
import { readFile as readFile39 } from "node:fs/promises";
|
|
70616
70520
|
init_provider_registry();
|
|
70617
70521
|
function getProviderPathKeyForPortableType2(type) {
|
|
@@ -70719,7 +70623,7 @@ async function buildTargetStates(entries, options2) {
|
|
|
70719
70623
|
entriesByPath.set(entry.path, group);
|
|
70720
70624
|
}
|
|
70721
70625
|
for (const [entryPath, groupedEntries] of entriesByPath) {
|
|
70722
|
-
const exists =
|
|
70626
|
+
const exists = existsSync35(entryPath);
|
|
70723
70627
|
const state = { path: entryPath, exists };
|
|
70724
70628
|
if (exists) {
|
|
70725
70629
|
try {
|
|
@@ -71201,24 +71105,24 @@ function buildPlan(actions) {
|
|
|
71201
71105
|
|
|
71202
71106
|
// src/commands/skills/skills-discovery.ts
|
|
71203
71107
|
import { readFile as readFile40, readdir as readdir28, stat as stat11 } from "node:fs/promises";
|
|
71204
|
-
import { homedir as
|
|
71205
|
-
import { dirname as
|
|
71108
|
+
import { homedir as homedir17 } from "node:os";
|
|
71109
|
+
import { dirname as dirname19, join as join88 } from "node:path";
|
|
71206
71110
|
init_logger();
|
|
71207
71111
|
var import_gray_matter4 = __toESM(require_gray_matter(), 1);
|
|
71208
|
-
var home5 =
|
|
71112
|
+
var home5 = homedir17();
|
|
71209
71113
|
var SKIP_DIRS2 = ["node_modules", ".git", "dist", "build", ".venv", "__pycache__", "common"];
|
|
71210
71114
|
function getSkillSourcePath() {
|
|
71211
|
-
const bundledRoot =
|
|
71115
|
+
const bundledRoot = join88(process.cwd(), "node_modules", "takumi-engineer");
|
|
71212
71116
|
return findFirstExistingPath([
|
|
71213
|
-
|
|
71117
|
+
join88(bundledRoot, "skills"),
|
|
71214
71118
|
...getProjectLayoutCandidates(bundledRoot, "skills"),
|
|
71215
71119
|
...getProjectLayoutCandidates(process.cwd(), "skills"),
|
|
71216
|
-
|
|
71120
|
+
join88(home5, ".claude/skills")
|
|
71217
71121
|
]);
|
|
71218
71122
|
}
|
|
71219
71123
|
async function hasSkillMd(dir) {
|
|
71220
71124
|
try {
|
|
71221
|
-
const skillPath =
|
|
71125
|
+
const skillPath = join88(dir, "SKILL.md");
|
|
71222
71126
|
const stats = await stat11(skillPath);
|
|
71223
71127
|
return stats.isFile();
|
|
71224
71128
|
} catch {
|
|
@@ -71229,7 +71133,7 @@ async function parseSkillMd(skillMdPath) {
|
|
|
71229
71133
|
try {
|
|
71230
71134
|
const content = await readFile40(skillMdPath, "utf-8");
|
|
71231
71135
|
const { data } = import_gray_matter4.default(content);
|
|
71232
|
-
const skillDir =
|
|
71136
|
+
const skillDir = dirname19(skillMdPath);
|
|
71233
71137
|
const dirName = skillDir.split(/[/\\]/).pop() || "";
|
|
71234
71138
|
if (!dirName) {
|
|
71235
71139
|
logger.verbose(`Skipping ${skillMdPath}: cannot determine skill directory`);
|
|
@@ -71266,9 +71170,9 @@ async function discoverSkills(sourcePath) {
|
|
|
71266
71170
|
if (!entry.isDirectory() || SKIP_DIRS2.includes(entry.name)) {
|
|
71267
71171
|
continue;
|
|
71268
71172
|
}
|
|
71269
|
-
const skillDir =
|
|
71173
|
+
const skillDir = join88(searchPath, entry.name);
|
|
71270
71174
|
if (await hasSkillMd(skillDir)) {
|
|
71271
|
-
const skill = await parseSkillMd(
|
|
71175
|
+
const skill = await parseSkillMd(join88(skillDir, "SKILL.md"));
|
|
71272
71176
|
if (skill && !seenNames.has(skill.name)) {
|
|
71273
71177
|
skills.push(skill);
|
|
71274
71178
|
seenNames.add(skill.name);
|
|
@@ -71315,9 +71219,9 @@ function resolveMigrationScope(argv, options2) {
|
|
|
71315
71219
|
}
|
|
71316
71220
|
|
|
71317
71221
|
// src/commands/migrate/skill-directory-installer.ts
|
|
71318
|
-
import { existsSync as
|
|
71222
|
+
import { existsSync as existsSync36 } from "node:fs";
|
|
71319
71223
|
import { cp as cp2, mkdir as mkdir26, rename as rename6, rm as rm10 } from "node:fs/promises";
|
|
71320
|
-
import { join as
|
|
71224
|
+
import { join as join89, resolve as resolve15 } from "node:path";
|
|
71321
71225
|
init_provider_registry();
|
|
71322
71226
|
async function installSkillDirectories(skills, targetProviders, options2) {
|
|
71323
71227
|
const results = [];
|
|
@@ -71346,7 +71250,7 @@ async function installSkillDirectories(skills, targetProviders, options2) {
|
|
|
71346
71250
|
continue;
|
|
71347
71251
|
}
|
|
71348
71252
|
for (const skill of skills) {
|
|
71349
|
-
const targetDir =
|
|
71253
|
+
const targetDir = join89(basePath, skill.name);
|
|
71350
71254
|
if (resolve15(skill.path) === resolve15(targetDir)) {
|
|
71351
71255
|
results.push({
|
|
71352
71256
|
provider,
|
|
@@ -71359,10 +71263,10 @@ async function installSkillDirectories(skills, targetProviders, options2) {
|
|
|
71359
71263
|
continue;
|
|
71360
71264
|
}
|
|
71361
71265
|
try {
|
|
71362
|
-
if (!
|
|
71266
|
+
if (!existsSync36(basePath)) {
|
|
71363
71267
|
await mkdir26(basePath, { recursive: true });
|
|
71364
71268
|
}
|
|
71365
|
-
const alreadyExists =
|
|
71269
|
+
const alreadyExists = existsSync36(targetDir);
|
|
71366
71270
|
const backupDir = alreadyExists ? `${targetDir}.sk-backup-${process.pid}-${Date.now()}` : null;
|
|
71367
71271
|
let copied = false;
|
|
71368
71272
|
if (backupDir) {
|
|
@@ -71374,10 +71278,10 @@ async function installSkillDirectories(skills, targetProviders, options2) {
|
|
|
71374
71278
|
await addPortableInstallation(skill.name, "skill", provider, options2.global, targetDir, skill.path);
|
|
71375
71279
|
} catch (error) {
|
|
71376
71280
|
try {
|
|
71377
|
-
if (copied &&
|
|
71281
|
+
if (copied && existsSync36(targetDir)) {
|
|
71378
71282
|
await rm10(targetDir, { recursive: true, force: true });
|
|
71379
71283
|
}
|
|
71380
|
-
if (backupDir &&
|
|
71284
|
+
if (backupDir && existsSync36(backupDir)) {
|
|
71381
71285
|
await rename6(backupDir, targetDir);
|
|
71382
71286
|
}
|
|
71383
71287
|
} catch (rollbackError) {
|
|
@@ -71386,7 +71290,7 @@ async function installSkillDirectories(skills, targetProviders, options2) {
|
|
|
71386
71290
|
}
|
|
71387
71291
|
throw error;
|
|
71388
71292
|
}
|
|
71389
|
-
if (backupDir &&
|
|
71293
|
+
if (backupDir && existsSync36(backupDir)) {
|
|
71390
71294
|
await rm10(backupDir, { recursive: true, force: true });
|
|
71391
71295
|
}
|
|
71392
71296
|
const warnings = [];
|
|
@@ -71448,7 +71352,7 @@ async function executeDeleteAction(action, options2) {
|
|
|
71448
71352
|
const preservePaths = options2?.preservePaths ?? new Set;
|
|
71449
71353
|
const shouldPreserveTarget = action.targetPath.length > 0 && preservePaths.has(resolve16(action.targetPath));
|
|
71450
71354
|
try {
|
|
71451
|
-
if (!shouldPreserveTarget && action.targetPath &&
|
|
71355
|
+
if (!shouldPreserveTarget && action.targetPath && existsSync37(action.targetPath)) {
|
|
71452
71356
|
await rm11(action.targetPath, { recursive: true, force: true });
|
|
71453
71357
|
}
|
|
71454
71358
|
await removePortableInstallation(action.item, action.type, action.provider, action.global);
|
|
@@ -71473,8 +71377,8 @@ async function executeDeleteAction(action, options2) {
|
|
|
71473
71377
|
async function processMetadataDeletions(skillSourcePath, installGlobally) {
|
|
71474
71378
|
if (!skillSourcePath)
|
|
71475
71379
|
return;
|
|
71476
|
-
const sourceMetadataPath =
|
|
71477
|
-
if (!
|
|
71380
|
+
const sourceMetadataPath = join90(resolve16(skillSourcePath, ".."), "metadata.json");
|
|
71381
|
+
if (!existsSync37(sourceMetadataPath))
|
|
71478
71382
|
return;
|
|
71479
71383
|
let sourceMetadata;
|
|
71480
71384
|
try {
|
|
@@ -71486,8 +71390,8 @@ async function processMetadataDeletions(skillSourcePath, installGlobally) {
|
|
|
71486
71390
|
}
|
|
71487
71391
|
if (!sourceMetadata.deletions || sourceMetadata.deletions.length === 0)
|
|
71488
71392
|
return;
|
|
71489
|
-
const claudeDir = installGlobally ?
|
|
71490
|
-
if (!
|
|
71393
|
+
const claudeDir = installGlobally ? join90(homedir18(), ".claude") : join90(process.cwd(), ".claude");
|
|
71394
|
+
if (!existsSync37(claudeDir))
|
|
71491
71395
|
return;
|
|
71492
71396
|
try {
|
|
71493
71397
|
const result = await handleDeletions(sourceMetadata, claudeDir);
|
|
@@ -71634,8 +71538,8 @@ async function migrateCommand(options2) {
|
|
|
71634
71538
|
selectedProviders = Array.from(new Set(selectedProviders));
|
|
71635
71539
|
let installGlobally = options2.global ?? false;
|
|
71636
71540
|
if (options2.global === undefined && !options2.yes) {
|
|
71637
|
-
const projectTarget =
|
|
71638
|
-
const globalTarget =
|
|
71541
|
+
const projectTarget = join90(process.cwd(), ".claude");
|
|
71542
|
+
const globalTarget = join90(homedir18(), ".claude");
|
|
71639
71543
|
const scopeChoice = await ie({
|
|
71640
71544
|
message: "Installation scope",
|
|
71641
71545
|
options: [
|
|
@@ -71687,7 +71591,7 @@ async function migrateCommand(options2) {
|
|
|
71687
71591
|
}
|
|
71688
71592
|
const providerNames = selectedProviders.map((prov) => import_picocolors25.default.cyan(providers[prov].displayName)).join(", ");
|
|
71689
71593
|
f2.message(` Providers: ${providerNames}`);
|
|
71690
|
-
const targetDir = installGlobally ?
|
|
71594
|
+
const targetDir = installGlobally ? join90(homedir18(), ".claude") : join90(process.cwd(), ".claude");
|
|
71691
71595
|
f2.message(` Scope: ${installGlobally ? "Global" : "Project"} ${import_picocolors25.default.dim(`-> ${targetDir}`)}`);
|
|
71692
71596
|
const cmdProviders = getProvidersSupporting("commands");
|
|
71693
71597
|
const unsupportedCmd = selectedProviders.filter((pv) => !cmdProviders.includes(pv));
|
|
@@ -71736,7 +71640,7 @@ async function migrateCommand(options2) {
|
|
|
71736
71640
|
const interactive = process.stdout.isTTY && !options2.yes;
|
|
71737
71641
|
const conflictActions = plan.actions.filter((a3) => a3.action === "conflict");
|
|
71738
71642
|
for (const action of conflictActions) {
|
|
71739
|
-
if (!action.diff && action.targetPath &&
|
|
71643
|
+
if (!action.diff && action.targetPath && existsSync37(action.targetPath)) {
|
|
71740
71644
|
try {
|
|
71741
71645
|
const targetContent = await readFile41(action.targetPath, "utf-8");
|
|
71742
71646
|
const sourceItem = agents.find((a3) => a3.name === action.item) || commands.find((c2) => c2.name === action.item) || (configItem?.name === action.item ? configItem : null) || ruleItems.find((r2) => r2.name === action.item) || hookItems.find((h2) => h2.name === action.item);
|
|
@@ -71941,7 +71845,7 @@ async function migrateCommand(options2) {
|
|
|
71941
71845
|
}
|
|
71942
71846
|
async function rollbackResults(results) {
|
|
71943
71847
|
for (const result of results) {
|
|
71944
|
-
if (!result.path || !
|
|
71848
|
+
if (!result.path || !existsSync37(result.path))
|
|
71945
71849
|
continue;
|
|
71946
71850
|
try {
|
|
71947
71851
|
if (result.overwritten)
|
|
@@ -72179,7 +72083,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
72179
72083
|
};
|
|
72180
72084
|
}
|
|
72181
72085
|
// src/commands/new/phases/project-creation.ts
|
|
72182
|
-
import { join as
|
|
72086
|
+
import { join as join91 } from "node:path";
|
|
72183
72087
|
init_github_client();
|
|
72184
72088
|
init_logger();
|
|
72185
72089
|
init_output_manager();
|
|
@@ -72333,7 +72237,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
72333
72237
|
output.section("Installing");
|
|
72334
72238
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
72335
72239
|
const merger = new FileMerger;
|
|
72336
|
-
const claudeDir =
|
|
72240
|
+
const claudeDir = join91(resolvedDir, ".claude");
|
|
72337
72241
|
merger.setMultiKitContext(claudeDir, kit);
|
|
72338
72242
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
72339
72243
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -72379,10 +72283,10 @@ async function handleProjectCreation(ctx) {
|
|
|
72379
72283
|
};
|
|
72380
72284
|
}
|
|
72381
72285
|
// src/commands/new/phases/post-setup.ts
|
|
72382
|
-
import { join as
|
|
72286
|
+
import { join as join93 } from "node:path";
|
|
72383
72287
|
|
|
72384
72288
|
// src/domains/installation/setup-wizard.ts
|
|
72385
|
-
import { join as
|
|
72289
|
+
import { join as join92 } from "node:path";
|
|
72386
72290
|
init_logger();
|
|
72387
72291
|
init_path_resolver();
|
|
72388
72292
|
init_dist2();
|
|
@@ -72463,7 +72367,7 @@ async function parseEnvFile(path8) {
|
|
|
72463
72367
|
}
|
|
72464
72368
|
}
|
|
72465
72369
|
async function checkGlobalConfig() {
|
|
72466
|
-
const globalEnvPath =
|
|
72370
|
+
const globalEnvPath = join92(PathResolver.getGlobalKitDir(), ".env");
|
|
72467
72371
|
if (!await import_fs_extra34.pathExists(globalEnvPath))
|
|
72468
72372
|
return false;
|
|
72469
72373
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -72479,7 +72383,7 @@ async function runSetupWizard(options2) {
|
|
|
72479
72383
|
let globalEnv = {};
|
|
72480
72384
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
72481
72385
|
if (!isGlobal) {
|
|
72482
|
-
const globalEnvPath =
|
|
72386
|
+
const globalEnvPath = join92(PathResolver.getGlobalKitDir(), ".env");
|
|
72483
72387
|
if (await import_fs_extra34.pathExists(globalEnvPath)) {
|
|
72484
72388
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
72485
72389
|
}
|
|
@@ -72542,7 +72446,7 @@ async function runSetupWizard(options2) {
|
|
|
72542
72446
|
}
|
|
72543
72447
|
}
|
|
72544
72448
|
await generateEnvFile(targetDir, values);
|
|
72545
|
-
f2.success(`Configuration saved to ${
|
|
72449
|
+
f2.success(`Configuration saved to ${join92(targetDir, ".env")}`);
|
|
72546
72450
|
return true;
|
|
72547
72451
|
}
|
|
72548
72452
|
async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
@@ -72645,9 +72549,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
|
|
|
72645
72549
|
withSudo: validOptions.withSudo
|
|
72646
72550
|
});
|
|
72647
72551
|
}
|
|
72648
|
-
const claudeDir =
|
|
72552
|
+
const claudeDir = join93(resolvedDir, ".claude");
|
|
72649
72553
|
await promptSetupWizardIfNeeded({
|
|
72650
|
-
envPath:
|
|
72554
|
+
envPath: join93(claudeDir, ".env"),
|
|
72651
72555
|
claudeDir,
|
|
72652
72556
|
isGlobal: false,
|
|
72653
72557
|
isNonInteractive: isNonInteractive2,
|
|
@@ -72723,20 +72627,20 @@ Example: tkm new --use-git --release v2.1.0`);
|
|
|
72723
72627
|
}
|
|
72724
72628
|
// src/commands/plan/plan-command.ts
|
|
72725
72629
|
init_output_manager();
|
|
72726
|
-
import { existsSync as
|
|
72727
|
-
import { dirname as
|
|
72630
|
+
import { existsSync as existsSync42, statSync as statSync5 } from "node:fs";
|
|
72631
|
+
import { dirname as dirname25, join as join97, parse as parse2, resolve as resolve21 } from "node:path";
|
|
72728
72632
|
|
|
72729
72633
|
// src/commands/plan/plan-read-handlers.ts
|
|
72730
|
-
import { existsSync as
|
|
72731
|
-
import { basename as basename9, dirname as
|
|
72634
|
+
import { existsSync as existsSync41, statSync as statSync4 } from "node:fs";
|
|
72635
|
+
import { basename as basename9, dirname as dirname24, join as join96, relative as relative18, resolve as resolve19 } from "node:path";
|
|
72732
72636
|
|
|
72733
72637
|
// src/domains/plan-parser/index.ts
|
|
72734
|
-
import { dirname as
|
|
72638
|
+
import { dirname as dirname23 } from "node:path";
|
|
72735
72639
|
|
|
72736
72640
|
// src/domains/plan-parser/plan-table-parser.ts
|
|
72737
72641
|
var import_gray_matter5 = __toESM(require_gray_matter(), 1);
|
|
72738
|
-
import { readFileSync as
|
|
72739
|
-
import { dirname as
|
|
72642
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
72643
|
+
import { dirname as dirname20, resolve as resolve18 } from "node:path";
|
|
72740
72644
|
function normalizeStatus(raw) {
|
|
72741
72645
|
const s3 = raw.toLowerCase().trim();
|
|
72742
72646
|
if (s3.includes("complete") || s3.includes("done") || s3.includes("✓") || s3.includes("✅")) {
|
|
@@ -72997,7 +72901,7 @@ function parseFormat4(content, planFilePath, options2) {
|
|
|
72997
72901
|
const hasCheck = /[✅✓]/.test(line);
|
|
72998
72902
|
current = { name, status: hasCheck ? "completed" : "pending" };
|
|
72999
72903
|
} else if (fileMatch && current) {
|
|
73000
|
-
const planDir =
|
|
72904
|
+
const planDir = dirname20(planFilePath);
|
|
73001
72905
|
current.file = resolve18(planDir, fileMatch[1].trim());
|
|
73002
72906
|
} else if (statusMatch && current) {
|
|
73003
72907
|
current.status = normalizeStatus(statusMatch[2]);
|
|
@@ -73101,31 +73005,31 @@ function parsePhasesFromBody(body, dir, options2) {
|
|
|
73101
73005
|
return parseFormat6(normalizedBody, dir, options2);
|
|
73102
73006
|
}
|
|
73103
73007
|
function parsePlanFile(planFilePath, options2) {
|
|
73104
|
-
const content =
|
|
73105
|
-
const dir =
|
|
73008
|
+
const content = readFileSync12(planFilePath, "utf8");
|
|
73009
|
+
const dir = dirname20(planFilePath);
|
|
73106
73010
|
const { data: frontmatter, content: body } = import_gray_matter5.default(content);
|
|
73107
73011
|
const phases = parsePhasesFromBody(body, dir, options2);
|
|
73108
73012
|
return { frontmatter, phases };
|
|
73109
73013
|
}
|
|
73110
73014
|
// src/domains/plan-parser/plan-scanner.ts
|
|
73111
|
-
import { existsSync as
|
|
73112
|
-
import { join as
|
|
73015
|
+
import { existsSync as existsSync38, readdirSync as readdirSync4 } from "node:fs";
|
|
73016
|
+
import { join as join94 } from "node:path";
|
|
73113
73017
|
function scanPlanDir(dir) {
|
|
73114
|
-
if (!
|
|
73018
|
+
if (!existsSync38(dir))
|
|
73115
73019
|
return [];
|
|
73116
73020
|
try {
|
|
73117
|
-
return readdirSync4(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
73021
|
+
return readdirSync4(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join94(dir, entry.name, "plan.md")).filter(existsSync38);
|
|
73118
73022
|
} catch {
|
|
73119
73023
|
return [];
|
|
73120
73024
|
}
|
|
73121
73025
|
}
|
|
73122
73026
|
// src/domains/plan-parser/plan-validator.ts
|
|
73123
73027
|
var import_gray_matter6 = __toESM(require_gray_matter(), 1);
|
|
73124
|
-
import { existsSync as
|
|
73125
|
-
import { basename as basename7, dirname as
|
|
73028
|
+
import { existsSync as existsSync39, readFileSync as readFileSync13 } from "node:fs";
|
|
73029
|
+
import { basename as basename7, dirname as dirname21 } from "node:path";
|
|
73126
73030
|
function validatePlanFile(filePath, strict = false) {
|
|
73127
|
-
const content =
|
|
73128
|
-
const dir =
|
|
73031
|
+
const content = readFileSync13(filePath, "utf8");
|
|
73032
|
+
const dir = dirname21(filePath);
|
|
73129
73033
|
const issues = [];
|
|
73130
73034
|
const lines = content.split(`
|
|
73131
73035
|
`);
|
|
@@ -73161,7 +73065,7 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
73161
73065
|
});
|
|
73162
73066
|
}
|
|
73163
73067
|
for (const phase of phases) {
|
|
73164
|
-
if (phase.file && !
|
|
73068
|
+
if (phase.file && !existsSync39(phase.file)) {
|
|
73165
73069
|
const fileBasename = basename7(phase.file);
|
|
73166
73070
|
const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
|
|
73167
73071
|
issues.push({
|
|
@@ -73181,9 +73085,9 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
73181
73085
|
}
|
|
73182
73086
|
// src/domains/plan-parser/plan-writer.ts
|
|
73183
73087
|
var import_gray_matter7 = __toESM(require_gray_matter(), 1);
|
|
73184
|
-
import { mkdirSync as
|
|
73185
|
-
import { existsSync as
|
|
73186
|
-
import { basename as basename8, dirname as
|
|
73088
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync14, writeFileSync as writeFileSync4 } from "node:fs";
|
|
73089
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
73090
|
+
import { basename as basename8, dirname as dirname22, join as join95 } from "node:path";
|
|
73187
73091
|
function phaseNameToFilename(id, name) {
|
|
73188
73092
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
|
|
73189
73093
|
const num = numMatch ? numMatch[1] : id;
|
|
@@ -73288,16 +73192,16 @@ function resolvePhaseIds(phases) {
|
|
|
73288
73192
|
}
|
|
73289
73193
|
function scaffoldPlan(options2) {
|
|
73290
73194
|
const { dir } = options2;
|
|
73291
|
-
|
|
73195
|
+
mkdirSync2(dir, { recursive: true });
|
|
73292
73196
|
const resolvedPhases = resolvePhaseIds(options2.phases);
|
|
73293
73197
|
const optionsWithResolved = { ...options2, phases: resolvedPhases };
|
|
73294
|
-
const planFile =
|
|
73295
|
-
|
|
73198
|
+
const planFile = join95(dir, "plan.md");
|
|
73199
|
+
writeFileSync4(planFile, generatePlanMd(optionsWithResolved), "utf8");
|
|
73296
73200
|
const phaseFiles = [];
|
|
73297
73201
|
for (const phase of resolvedPhases) {
|
|
73298
73202
|
const filename = phaseNameToFilename(phase.id, phase.name);
|
|
73299
|
-
const phaseFile =
|
|
73300
|
-
|
|
73203
|
+
const phaseFile = join95(dir, filename);
|
|
73204
|
+
writeFileSync4(phaseFile, generatePhaseTemplate(phase), "utf8");
|
|
73301
73205
|
phaseFiles.push(phaseFile);
|
|
73302
73206
|
}
|
|
73303
73207
|
return { planFile, phaseFiles };
|
|
@@ -73321,7 +73225,7 @@ function isCanonicalFormat(content) {
|
|
|
73321
73225
|
return /^\|\s*phase\s*\|\s*name\s*\|\s*status\s*\|/im.test(content);
|
|
73322
73226
|
}
|
|
73323
73227
|
function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
73324
|
-
const raw =
|
|
73228
|
+
const raw = readFileSync14(planFile, "utf8").replace(/\r\n/g, `
|
|
73325
73229
|
`);
|
|
73326
73230
|
if (!isCanonicalFormat(raw)) {
|
|
73327
73231
|
console.error("[!] plan.md is not in canonical format — skipping status update");
|
|
@@ -73361,10 +73265,10 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
|
73361
73265
|
}
|
|
73362
73266
|
const updatedFrontmatter = { ...frontmatter, status: planStatus };
|
|
73363
73267
|
const updatedContent = import_gray_matter7.default.stringify(updatedBody, updatedFrontmatter);
|
|
73364
|
-
|
|
73365
|
-
const planDir =
|
|
73268
|
+
writeFileSync4(planFile, updatedContent, "utf8");
|
|
73269
|
+
const planDir = dirname22(planFile);
|
|
73366
73270
|
const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
|
|
73367
|
-
if (phaseFilename &&
|
|
73271
|
+
if (phaseFilename && existsSync40(phaseFilename)) {
|
|
73368
73272
|
updatePhaseFileFrontmatter(phaseFilename, newStatus);
|
|
73369
73273
|
}
|
|
73370
73274
|
}
|
|
@@ -73376,25 +73280,25 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
|
|
|
73376
73280
|
continue;
|
|
73377
73281
|
const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
|
|
73378
73282
|
if (linkMatch)
|
|
73379
|
-
return
|
|
73283
|
+
return join95(planDir, linkMatch[2]);
|
|
73380
73284
|
}
|
|
73381
73285
|
return null;
|
|
73382
73286
|
}
|
|
73383
73287
|
function updatePhaseFileFrontmatter(phaseFile, newStatus) {
|
|
73384
|
-
const raw =
|
|
73288
|
+
const raw = readFileSync14(phaseFile, "utf8");
|
|
73385
73289
|
const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
|
|
73386
73290
|
const updated = { ...frontmatter, status: newStatus };
|
|
73387
|
-
|
|
73291
|
+
writeFileSync4(phaseFile, import_gray_matter7.default.stringify(body, updated), "utf8");
|
|
73388
73292
|
}
|
|
73389
73293
|
function addPhase(planFile, name, afterId) {
|
|
73390
|
-
const raw =
|
|
73294
|
+
const raw = readFileSync14(planFile, "utf8").replace(/\r\n/g, `
|
|
73391
73295
|
`);
|
|
73392
73296
|
if (!isCanonicalFormat(raw)) {
|
|
73393
73297
|
console.error("[!] plan.md is not in canonical format — cannot add phase");
|
|
73394
73298
|
throw new Error("Non-canonical plan.md — cannot add phase");
|
|
73395
73299
|
}
|
|
73396
73300
|
const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
|
|
73397
|
-
const planDir =
|
|
73301
|
+
const planDir = dirname22(planFile);
|
|
73398
73302
|
const existingIds = [];
|
|
73399
73303
|
for (const match2 of body.matchAll(/^\|\s*(\d+[a-z]?)\s*\|/gim)) {
|
|
73400
73304
|
existingIds.push(match2[1].toLowerCase());
|
|
@@ -73456,9 +73360,9 @@ function addPhase(planFile, name, afterId) {
|
|
|
73456
73360
|
updatedBody = lines.join(`
|
|
73457
73361
|
`);
|
|
73458
73362
|
}
|
|
73459
|
-
|
|
73460
|
-
const phaseFilePath =
|
|
73461
|
-
|
|
73363
|
+
writeFileSync4(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
|
|
73364
|
+
const phaseFilePath = join95(planDir, filename);
|
|
73365
|
+
writeFileSync4(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
|
|
73462
73366
|
return { phaseId, phaseFile: phaseFilePath };
|
|
73463
73367
|
}
|
|
73464
73368
|
|
|
@@ -73469,7 +73373,7 @@ function buildPlanSummary(planFile) {
|
|
|
73469
73373
|
const inProgress = phases.filter((p2) => p2.status === "in-progress").length;
|
|
73470
73374
|
const pending = phases.filter((p2) => p2.status === "pending").length;
|
|
73471
73375
|
return {
|
|
73472
|
-
planDir:
|
|
73376
|
+
planDir: dirname23(planFile),
|
|
73473
73377
|
planFile,
|
|
73474
73378
|
title: typeof frontmatter.title === "string" ? frontmatter.title : undefined,
|
|
73475
73379
|
description: typeof frontmatter.description === "string" ? frontmatter.description : undefined,
|
|
@@ -73506,7 +73410,7 @@ async function handleParse(target, options2) {
|
|
|
73506
73410
|
console.log(JSON.stringify({ file: relative18(process.cwd(), planFile), frontmatter, phases }, null, 2));
|
|
73507
73411
|
return;
|
|
73508
73412
|
}
|
|
73509
|
-
const title = typeof frontmatter.title === "string" ? frontmatter.title : basename9(
|
|
73413
|
+
const title = typeof frontmatter.title === "string" ? frontmatter.title : basename9(dirname24(planFile));
|
|
73510
73414
|
console.log();
|
|
73511
73415
|
console.log(import_picocolors27.default.bold(` Plan: ${title}`));
|
|
73512
73416
|
console.log(` File: ${planFile}`);
|
|
@@ -73561,7 +73465,7 @@ async function handleValidate(target, options2) {
|
|
|
73561
73465
|
}
|
|
73562
73466
|
async function handleStatus(target, options2) {
|
|
73563
73467
|
const t = target ? resolve19(target) : null;
|
|
73564
|
-
const plansDir = t &&
|
|
73468
|
+
const plansDir = t && existsSync41(t) && statSync4(t).isDirectory() && !existsSync41(join96(t, "plan.md")) ? t : null;
|
|
73565
73469
|
if (plansDir) {
|
|
73566
73470
|
const planFiles = scanPlanDir(plansDir);
|
|
73567
73471
|
if (planFiles.length === 0) {
|
|
@@ -73586,14 +73490,14 @@ async function handleStatus(target, options2) {
|
|
|
73586
73490
|
try {
|
|
73587
73491
|
const s3 = buildPlanSummary(pf);
|
|
73588
73492
|
const bar = progressBar(s3.completed, s3.totalPhases);
|
|
73589
|
-
const title2 = s3.title ?? basename9(
|
|
73493
|
+
const title2 = s3.title ?? basename9(dirname24(pf));
|
|
73590
73494
|
console.log(` ${import_picocolors27.default.bold(title2)}`);
|
|
73591
73495
|
console.log(` ${bar}`);
|
|
73592
73496
|
if (s3.inProgress > 0)
|
|
73593
73497
|
console.log(` [~] ${s3.inProgress} in progress`);
|
|
73594
73498
|
console.log();
|
|
73595
73499
|
} catch {
|
|
73596
|
-
console.log(` [X] Failed to read: ${basename9(
|
|
73500
|
+
console.log(` [X] Failed to read: ${basename9(dirname24(pf))}`);
|
|
73597
73501
|
console.log();
|
|
73598
73502
|
}
|
|
73599
73503
|
}
|
|
@@ -73617,7 +73521,7 @@ async function handleStatus(target, options2) {
|
|
|
73617
73521
|
console.log(JSON.stringify(summary, null, 2));
|
|
73618
73522
|
return;
|
|
73619
73523
|
}
|
|
73620
|
-
const title = summary.title ?? basename9(
|
|
73524
|
+
const title = summary.title ?? basename9(dirname24(planFile));
|
|
73621
73525
|
console.log();
|
|
73622
73526
|
console.log(import_picocolors27.default.bold(` ${title}`));
|
|
73623
73527
|
if (summary.status)
|
|
@@ -73792,22 +73696,22 @@ async function handleAddPhase(target, options2) {
|
|
|
73792
73696
|
// src/commands/plan/plan-command.ts
|
|
73793
73697
|
function resolvePlanFile(target) {
|
|
73794
73698
|
const t = target ? resolve21(target) : process.cwd();
|
|
73795
|
-
if (
|
|
73699
|
+
if (existsSync42(t)) {
|
|
73796
73700
|
const stat12 = statSync5(t);
|
|
73797
73701
|
if (stat12.isFile())
|
|
73798
73702
|
return t;
|
|
73799
|
-
const candidate =
|
|
73800
|
-
if (
|
|
73703
|
+
const candidate = join97(t, "plan.md");
|
|
73704
|
+
if (existsSync42(candidate))
|
|
73801
73705
|
return candidate;
|
|
73802
73706
|
}
|
|
73803
73707
|
if (!target) {
|
|
73804
73708
|
let dir = process.cwd();
|
|
73805
73709
|
const root = parse2(dir).root;
|
|
73806
73710
|
while (dir !== root) {
|
|
73807
|
-
const candidate =
|
|
73808
|
-
if (
|
|
73711
|
+
const candidate = join97(dir, "plan.md");
|
|
73712
|
+
if (existsSync42(candidate))
|
|
73809
73713
|
return candidate;
|
|
73810
|
-
dir =
|
|
73714
|
+
dir = dirname25(dir);
|
|
73811
73715
|
}
|
|
73812
73716
|
}
|
|
73813
73717
|
return null;
|
|
@@ -73855,7 +73759,7 @@ async function planCommand(action, target, options2) {
|
|
|
73855
73759
|
let resolvedTarget = target;
|
|
73856
73760
|
if (resolvedAction && !knownActions.has(resolvedAction)) {
|
|
73857
73761
|
const looksLikePath = resolvedAction.includes("/") || resolvedAction.includes("\\") || resolvedAction.endsWith(".md") || resolvedAction === "." || resolvedAction === "..";
|
|
73858
|
-
const existsOnDisk = !looksLikePath &&
|
|
73762
|
+
const existsOnDisk = !looksLikePath && existsSync42(resolve21(resolvedAction));
|
|
73859
73763
|
if (looksLikePath || existsOnDisk) {
|
|
73860
73764
|
resolvedTarget = resolvedAction;
|
|
73861
73765
|
resolvedAction = undefined;
|
|
@@ -73893,7 +73797,7 @@ async function planCommand(action, target, options2) {
|
|
|
73893
73797
|
}
|
|
73894
73798
|
}
|
|
73895
73799
|
// src/commands/projects/add-handler.ts
|
|
73896
|
-
import { existsSync as
|
|
73800
|
+
import { existsSync as existsSync43 } from "node:fs";
|
|
73897
73801
|
import { resolve as resolve22 } from "node:path";
|
|
73898
73802
|
// src/domains/takumi-data/claude-projects-scanner.ts
|
|
73899
73803
|
init_logger();
|
|
@@ -73905,7 +73809,7 @@ async function handleAdd(projectPath, options2) {
|
|
|
73905
73809
|
logger.debug(`Adding project: ${projectPath}, options: ${JSON.stringify(options2)}`);
|
|
73906
73810
|
intro("Add Project");
|
|
73907
73811
|
const absolutePath = resolve22(projectPath);
|
|
73908
|
-
if (!
|
|
73812
|
+
if (!existsSync43(absolutePath)) {
|
|
73909
73813
|
log.error(`Path does not exist: ${absolutePath}`);
|
|
73910
73814
|
process.exitCode = 1;
|
|
73911
73815
|
return;
|
|
@@ -74304,134 +74208,134 @@ init_logger();
|
|
|
74304
74208
|
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
74305
74209
|
|
|
74306
74210
|
// src/commands/skills/agents.ts
|
|
74307
|
-
import { existsSync as
|
|
74308
|
-
import { homedir as
|
|
74309
|
-
import { join as
|
|
74310
|
-
var home6 =
|
|
74211
|
+
import { existsSync as existsSync44 } from "node:fs";
|
|
74212
|
+
import { homedir as homedir19 } from "node:os";
|
|
74213
|
+
import { join as join98 } from "node:path";
|
|
74214
|
+
var home6 = homedir19();
|
|
74311
74215
|
var agents = {
|
|
74312
74216
|
"claude-code": {
|
|
74313
74217
|
name: "claude-code",
|
|
74314
74218
|
displayName: "Claude Code",
|
|
74315
74219
|
projectPath: ".claude/skills",
|
|
74316
|
-
globalPath:
|
|
74317
|
-
detect: async () =>
|
|
74220
|
+
globalPath: join98(home6, ".claude/skills"),
|
|
74221
|
+
detect: async () => existsSync44(join98(home6, ".claude"))
|
|
74318
74222
|
},
|
|
74319
74223
|
cursor: {
|
|
74320
74224
|
name: "cursor",
|
|
74321
74225
|
displayName: "Cursor",
|
|
74322
74226
|
projectPath: ".cursor/skills",
|
|
74323
|
-
globalPath:
|
|
74324
|
-
detect: async () =>
|
|
74227
|
+
globalPath: join98(home6, ".cursor/skills"),
|
|
74228
|
+
detect: async () => existsSync44(join98(home6, ".cursor"))
|
|
74325
74229
|
},
|
|
74326
74230
|
codex: {
|
|
74327
74231
|
name: "codex",
|
|
74328
74232
|
displayName: "Codex",
|
|
74329
74233
|
projectPath: ".codex/skills",
|
|
74330
|
-
globalPath:
|
|
74331
|
-
detect: async () =>
|
|
74234
|
+
globalPath: join98(home6, ".codex/skills"),
|
|
74235
|
+
detect: async () => existsSync44(join98(home6, ".codex"))
|
|
74332
74236
|
},
|
|
74333
74237
|
opencode: {
|
|
74334
74238
|
name: "opencode",
|
|
74335
74239
|
displayName: "OpenCode",
|
|
74336
74240
|
projectPath: ".opencode/skills",
|
|
74337
|
-
globalPath:
|
|
74338
|
-
detect: async () =>
|
|
74241
|
+
globalPath: join98(home6, ".config/opencode/skills"),
|
|
74242
|
+
detect: async () => existsSync44(join98(home6, ".config/opencode"))
|
|
74339
74243
|
},
|
|
74340
74244
|
goose: {
|
|
74341
74245
|
name: "goose",
|
|
74342
74246
|
displayName: "Goose",
|
|
74343
74247
|
projectPath: ".goose/skills",
|
|
74344
|
-
globalPath:
|
|
74345
|
-
detect: async () =>
|
|
74248
|
+
globalPath: join98(home6, ".config/goose/skills"),
|
|
74249
|
+
detect: async () => existsSync44(join98(home6, ".config/goose"))
|
|
74346
74250
|
},
|
|
74347
74251
|
"gemini-cli": {
|
|
74348
74252
|
name: "gemini-cli",
|
|
74349
74253
|
displayName: "Gemini CLI",
|
|
74350
74254
|
projectPath: ".agents/skills",
|
|
74351
|
-
globalPath:
|
|
74352
|
-
detect: async () =>
|
|
74255
|
+
globalPath: join98(home6, ".agents/skills"),
|
|
74256
|
+
detect: async () => existsSync44(join98(home6, ".gemini"))
|
|
74353
74257
|
},
|
|
74354
74258
|
antigravity: {
|
|
74355
74259
|
name: "antigravity",
|
|
74356
74260
|
displayName: "Antigravity",
|
|
74357
74261
|
projectPath: ".agent/skills",
|
|
74358
|
-
globalPath:
|
|
74359
|
-
detect: async () =>
|
|
74262
|
+
globalPath: join98(home6, ".gemini/antigravity/skills"),
|
|
74263
|
+
detect: async () => existsSync44(join98(process.cwd(), ".agent")) || existsSync44(join98(home6, ".gemini/antigravity"))
|
|
74360
74264
|
},
|
|
74361
74265
|
"github-copilot": {
|
|
74362
74266
|
name: "github-copilot",
|
|
74363
74267
|
displayName: "GitHub Copilot",
|
|
74364
74268
|
projectPath: ".github/skills",
|
|
74365
|
-
globalPath:
|
|
74366
|
-
detect: async () =>
|
|
74269
|
+
globalPath: join98(home6, ".copilot/skills"),
|
|
74270
|
+
detect: async () => existsSync44(join98(home6, ".copilot"))
|
|
74367
74271
|
},
|
|
74368
74272
|
amp: {
|
|
74369
74273
|
name: "amp",
|
|
74370
74274
|
displayName: "Amp",
|
|
74371
74275
|
projectPath: ".agents/skills",
|
|
74372
|
-
globalPath:
|
|
74373
|
-
detect: async () =>
|
|
74276
|
+
globalPath: join98(home6, ".config/agents/skills"),
|
|
74277
|
+
detect: async () => existsSync44(join98(home6, ".config/amp"))
|
|
74374
74278
|
},
|
|
74375
74279
|
kilo: {
|
|
74376
74280
|
name: "kilo",
|
|
74377
74281
|
displayName: "Kilo Code",
|
|
74378
74282
|
projectPath: ".kilocode/skills",
|
|
74379
|
-
globalPath:
|
|
74380
|
-
detect: async () =>
|
|
74283
|
+
globalPath: join98(home6, ".kilocode/skills"),
|
|
74284
|
+
detect: async () => existsSync44(join98(home6, ".kilocode"))
|
|
74381
74285
|
},
|
|
74382
74286
|
roo: {
|
|
74383
74287
|
name: "roo",
|
|
74384
74288
|
displayName: "Roo Code",
|
|
74385
74289
|
projectPath: ".roo/skills",
|
|
74386
|
-
globalPath:
|
|
74387
|
-
detect: async () =>
|
|
74290
|
+
globalPath: join98(home6, ".roo/skills"),
|
|
74291
|
+
detect: async () => existsSync44(join98(home6, ".roo"))
|
|
74388
74292
|
},
|
|
74389
74293
|
windsurf: {
|
|
74390
74294
|
name: "windsurf",
|
|
74391
74295
|
displayName: "Windsurf",
|
|
74392
74296
|
projectPath: ".windsurf/skills",
|
|
74393
|
-
globalPath:
|
|
74394
|
-
detect: async () =>
|
|
74297
|
+
globalPath: join98(home6, ".codeium/windsurf/skills"),
|
|
74298
|
+
detect: async () => existsSync44(join98(home6, ".codeium/windsurf"))
|
|
74395
74299
|
},
|
|
74396
74300
|
cline: {
|
|
74397
74301
|
name: "cline",
|
|
74398
74302
|
displayName: "Cline",
|
|
74399
74303
|
projectPath: ".cline/skills",
|
|
74400
|
-
globalPath:
|
|
74401
|
-
detect: async () =>
|
|
74304
|
+
globalPath: join98(home6, ".cline/skills"),
|
|
74305
|
+
detect: async () => existsSync44(join98(home6, ".cline"))
|
|
74402
74306
|
},
|
|
74403
74307
|
openhands: {
|
|
74404
74308
|
name: "openhands",
|
|
74405
74309
|
displayName: "OpenHands",
|
|
74406
74310
|
projectPath: ".openhands/skills",
|
|
74407
|
-
globalPath:
|
|
74408
|
-
detect: async () =>
|
|
74311
|
+
globalPath: join98(home6, ".openhands/skills"),
|
|
74312
|
+
detect: async () => existsSync44(join98(home6, ".openhands"))
|
|
74409
74313
|
}
|
|
74410
74314
|
};
|
|
74411
74315
|
function getInstallPath(skillName, agent, options2) {
|
|
74412
74316
|
const config = agents[agent];
|
|
74413
74317
|
const basePath = options2.global ? config.globalPath : config.projectPath;
|
|
74414
|
-
return
|
|
74318
|
+
return join98(basePath, skillName);
|
|
74415
74319
|
}
|
|
74416
74320
|
function isSkillInstalled(skillName, agent, options2) {
|
|
74417
74321
|
const installPath = getInstallPath(skillName, agent, options2);
|
|
74418
|
-
return
|
|
74322
|
+
return existsSync44(installPath);
|
|
74419
74323
|
}
|
|
74420
74324
|
|
|
74421
74325
|
// src/commands/skills/skills-installer.ts
|
|
74422
|
-
import { existsSync as
|
|
74326
|
+
import { existsSync as existsSync46 } from "node:fs";
|
|
74423
74327
|
import { cp as cp3, mkdir as mkdir28, rm as rm12, stat as stat12 } from "node:fs/promises";
|
|
74424
|
-
import { homedir as
|
|
74425
|
-
import { dirname as
|
|
74328
|
+
import { homedir as homedir21 } from "node:os";
|
|
74329
|
+
import { dirname as dirname27, join as join100, resolve as resolve23 } from "node:path";
|
|
74426
74330
|
|
|
74427
74331
|
// src/commands/skills/skills-registry.ts
|
|
74428
74332
|
init_zod();
|
|
74429
|
-
import { existsSync as
|
|
74333
|
+
import { existsSync as existsSync45 } from "node:fs";
|
|
74430
74334
|
import { mkdir as mkdir27, readFile as readFile43, writeFile as writeFile30 } from "node:fs/promises";
|
|
74431
|
-
import { homedir as
|
|
74432
|
-
import { dirname as
|
|
74433
|
-
var home7 =
|
|
74434
|
-
var REGISTRY_PATH2 =
|
|
74335
|
+
import { homedir as homedir20 } from "node:os";
|
|
74336
|
+
import { dirname as dirname26, join as join99, sep as sep5 } from "node:path";
|
|
74337
|
+
var home7 = homedir20();
|
|
74338
|
+
var REGISTRY_PATH2 = join99(home7, ".sunagentkit", "skill-registry.json");
|
|
74435
74339
|
var SkillInstallationSchema = exports_external.object({
|
|
74436
74340
|
skill: exports_external.string(),
|
|
74437
74341
|
agent: exports_external.string(),
|
|
@@ -74450,12 +74354,12 @@ function getCliVersion4() {
|
|
|
74450
74354
|
if (process.env.npm_package_version) {
|
|
74451
74355
|
return process.env.npm_package_version;
|
|
74452
74356
|
}
|
|
74453
|
-
const { readFileSync:
|
|
74454
|
-
const { dirname:
|
|
74357
|
+
const { readFileSync: readFileSync15 } = __require("node:fs");
|
|
74358
|
+
const { dirname: dirname27, join: joinPath } = __require("node:path");
|
|
74455
74359
|
const { fileURLToPath: fileURLToPath4 } = __require("node:url");
|
|
74456
|
-
const __dirname3 =
|
|
74360
|
+
const __dirname3 = dirname27(fileURLToPath4(import.meta.url));
|
|
74457
74361
|
const pkgPath = joinPath(__dirname3, "../../../package.json");
|
|
74458
|
-
const pkg = JSON.parse(
|
|
74362
|
+
const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
74459
74363
|
return pkg.version || "unknown";
|
|
74460
74364
|
} catch {
|
|
74461
74365
|
return "unknown";
|
|
@@ -74488,7 +74392,7 @@ function migrateRegistryPaths(registry) {
|
|
|
74488
74392
|
}
|
|
74489
74393
|
async function readRegistry() {
|
|
74490
74394
|
try {
|
|
74491
|
-
if (!
|
|
74395
|
+
if (!existsSync45(REGISTRY_PATH2)) {
|
|
74492
74396
|
return { version: "1.0", installations: [] };
|
|
74493
74397
|
}
|
|
74494
74398
|
const content = await readFile43(REGISTRY_PATH2, "utf-8");
|
|
@@ -74508,8 +74412,8 @@ async function readRegistry() {
|
|
|
74508
74412
|
}
|
|
74509
74413
|
}
|
|
74510
74414
|
async function writeRegistry(registry) {
|
|
74511
|
-
const dir =
|
|
74512
|
-
if (!
|
|
74415
|
+
const dir = dirname26(REGISTRY_PATH2);
|
|
74416
|
+
if (!existsSync45(dir)) {
|
|
74513
74417
|
await mkdir27(dir, { recursive: true });
|
|
74514
74418
|
}
|
|
74515
74419
|
await writeFile30(REGISTRY_PATH2, JSON.stringify(registry, null, 2), "utf-8");
|
|
@@ -74553,7 +74457,7 @@ async function syncRegistry() {
|
|
|
74553
74457
|
const registry = await readRegistry();
|
|
74554
74458
|
const removed = [];
|
|
74555
74459
|
registry.installations = registry.installations.filter((i) => {
|
|
74556
|
-
if (!
|
|
74460
|
+
if (!existsSync45(i.path)) {
|
|
74557
74461
|
removed.push(i);
|
|
74558
74462
|
return false;
|
|
74559
74463
|
}
|
|
@@ -74569,7 +74473,7 @@ async function syncRegistry() {
|
|
|
74569
74473
|
var LEGACY_SKILL_PATHS = {
|
|
74570
74474
|
"gemini-cli": {
|
|
74571
74475
|
project: ".gemini/skills",
|
|
74572
|
-
global:
|
|
74476
|
+
global: join100(homedir21(), ".gemini/skills")
|
|
74573
74477
|
}
|
|
74574
74478
|
};
|
|
74575
74479
|
function isSamePath2(path1, path22) {
|
|
@@ -74603,8 +74507,8 @@ async function cleanupLegacySkillPath(skillName, agent, global3) {
|
|
|
74603
74507
|
if (!legacy)
|
|
74604
74508
|
return;
|
|
74605
74509
|
const legacyBase = global3 ? legacy.global : legacy.project;
|
|
74606
|
-
const legacyPath =
|
|
74607
|
-
if (!
|
|
74510
|
+
const legacyPath = join100(legacyBase, skillName);
|
|
74511
|
+
if (!existsSync46(legacyPath))
|
|
74608
74512
|
return;
|
|
74609
74513
|
await rm12(legacyPath, { recursive: true, force: true });
|
|
74610
74514
|
const registry = await readRegistry();
|
|
@@ -74613,7 +74517,7 @@ async function cleanupLegacySkillPath(skillName, agent, global3) {
|
|
|
74613
74517
|
if (entry.skill === skillName && entry.agent === agent && entry.global === global3) {
|
|
74614
74518
|
if (entry.path === legacyPath) {
|
|
74615
74519
|
const newBase = global3 ? agents[agent].globalPath : agents[agent].projectPath;
|
|
74616
|
-
entry.path =
|
|
74520
|
+
entry.path = join100(newBase, skillName);
|
|
74617
74521
|
changed = true;
|
|
74618
74522
|
}
|
|
74619
74523
|
}
|
|
@@ -74640,11 +74544,11 @@ async function installSkillForAgent(skill, agent, options2) {
|
|
|
74640
74544
|
try {
|
|
74641
74545
|
await cleanupLegacySkillPath(skill.name, agent, options2.global);
|
|
74642
74546
|
} catch {}
|
|
74643
|
-
const parentDir =
|
|
74644
|
-
if (!
|
|
74547
|
+
const parentDir = dirname27(targetPath);
|
|
74548
|
+
if (!existsSync46(parentDir)) {
|
|
74645
74549
|
await mkdir28(parentDir, { recursive: true });
|
|
74646
74550
|
}
|
|
74647
|
-
if (
|
|
74551
|
+
if (existsSync46(targetPath)) {
|
|
74648
74552
|
const stats = await stat12(targetPath);
|
|
74649
74553
|
if (stats.isFile()) {
|
|
74650
74554
|
return {
|
|
@@ -74696,9 +74600,9 @@ function getInstallPreview(skill, targetAgents, options2) {
|
|
|
74696
74600
|
}
|
|
74697
74601
|
|
|
74698
74602
|
// src/commands/skills/skills-uninstaller.ts
|
|
74699
|
-
import { existsSync as
|
|
74603
|
+
import { existsSync as existsSync47 } from "node:fs";
|
|
74700
74604
|
import { rm as rm13 } from "node:fs/promises";
|
|
74701
|
-
import { join as
|
|
74605
|
+
import { join as join101 } from "node:path";
|
|
74702
74606
|
async function uninstallSkillFromAgent(skill, agent, global3) {
|
|
74703
74607
|
const agentConfig = agents[agent];
|
|
74704
74608
|
const registry = await readRegistry();
|
|
@@ -74716,7 +74620,7 @@ async function uninstallSkillFromAgent(skill, agent, global3) {
|
|
|
74716
74620
|
}
|
|
74717
74621
|
const installation = installations[0];
|
|
74718
74622
|
const path8 = installation.path;
|
|
74719
|
-
const fileExists =
|
|
74623
|
+
const fileExists = existsSync47(path8);
|
|
74720
74624
|
try {
|
|
74721
74625
|
if (fileExists) {
|
|
74722
74626
|
await rm13(path8, { recursive: true, force: true });
|
|
@@ -74746,8 +74650,8 @@ async function uninstallSkillFromAgent(skill, agent, global3) {
|
|
|
74746
74650
|
async function forceUninstallSkill(skill, agent, global3) {
|
|
74747
74651
|
const agentConfig = agents[agent];
|
|
74748
74652
|
const basePath = global3 ? agentConfig.globalPath : agentConfig.projectPath;
|
|
74749
|
-
const path8 =
|
|
74750
|
-
if (!
|
|
74653
|
+
const path8 = join101(basePath, skill);
|
|
74654
|
+
if (!existsSync47(path8)) {
|
|
74751
74655
|
return {
|
|
74752
74656
|
skill,
|
|
74753
74657
|
agent,
|
|
@@ -75249,20 +75153,21 @@ init_logger();
|
|
|
75249
75153
|
init_logger();
|
|
75250
75154
|
|
|
75251
75155
|
// src/commands/telemetry/shared.ts
|
|
75252
|
-
import { existsSync as
|
|
75253
|
-
import { homedir as
|
|
75254
|
-
import { join as
|
|
75255
|
-
|
|
75256
|
-
var
|
|
75257
|
-
var
|
|
75258
|
-
var
|
|
75156
|
+
import { existsSync as existsSync48, readFileSync as readFileSync15, readdirSync as readdirSync5 } from "node:fs";
|
|
75157
|
+
import { homedir as homedir22 } from "node:os";
|
|
75158
|
+
import { join as join102 } from "node:path";
|
|
75159
|
+
init_token_store();
|
|
75160
|
+
var USER_CACHE_PATH = join102(homedir22(), ".claude", "sk-user.json");
|
|
75161
|
+
var EVENT_BUFFER_DIR = join102(homedir22(), ".claude", "sk-events");
|
|
75162
|
+
var RATE_STATE_PATH = join102(homedir22(), ".claude", "sk-rate-state.json");
|
|
75163
|
+
var METADATA_PATH = join102(homedir22(), ".claude", "metadata.json");
|
|
75259
75164
|
var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
|
|
75260
75165
|
var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
|
|
75261
75166
|
function readUserCache() {
|
|
75262
75167
|
try {
|
|
75263
|
-
if (!
|
|
75168
|
+
if (!existsSync48(USER_CACHE_PATH))
|
|
75264
75169
|
return null;
|
|
75265
|
-
const parsed = JSON.parse(
|
|
75170
|
+
const parsed = JSON.parse(readFileSync15(USER_CACHE_PATH, "utf8"));
|
|
75266
75171
|
if (!parsed || typeof parsed !== "object")
|
|
75267
75172
|
return null;
|
|
75268
75173
|
return parsed;
|
|
@@ -75270,9 +75175,21 @@ function readUserCache() {
|
|
|
75270
75175
|
return null;
|
|
75271
75176
|
}
|
|
75272
75177
|
}
|
|
75178
|
+
async function resolveGithubLogin() {
|
|
75179
|
+
const cache = readUserCache();
|
|
75180
|
+
if (cache?.githubLogin && GITHUB_LOGIN_REGEX.test(cache.githubLogin)) {
|
|
75181
|
+
return cache.githubLogin;
|
|
75182
|
+
}
|
|
75183
|
+
try {
|
|
75184
|
+
const session = await readToken();
|
|
75185
|
+
return pickGithubLogin(session?.user);
|
|
75186
|
+
} catch {
|
|
75187
|
+
return null;
|
|
75188
|
+
}
|
|
75189
|
+
}
|
|
75273
75190
|
function countBufferFiles() {
|
|
75274
75191
|
try {
|
|
75275
|
-
if (!
|
|
75192
|
+
if (!existsSync48(EVENT_BUFFER_DIR))
|
|
75276
75193
|
return 0;
|
|
75277
75194
|
return readdirSync5(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
|
|
75278
75195
|
} catch {
|
|
@@ -75284,8 +75201,8 @@ function readTelemetryConfig() {
|
|
|
75284
75201
|
const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
|
|
75285
75202
|
let metadata = null;
|
|
75286
75203
|
try {
|
|
75287
|
-
if (
|
|
75288
|
-
metadata = JSON.parse(
|
|
75204
|
+
if (existsSync48(METADATA_PATH)) {
|
|
75205
|
+
metadata = JSON.parse(readFileSync15(METADATA_PATH, "utf8"));
|
|
75289
75206
|
}
|
|
75290
75207
|
} catch {
|
|
75291
75208
|
metadata = null;
|
|
@@ -75309,8 +75226,8 @@ function collectRuntimeContext() {
|
|
|
75309
75226
|
cacheSource: cache?.source === "gh" || cache?.source === "manual" ? cache.source : null,
|
|
75310
75227
|
bufferFileCount: countBufferFiles(),
|
|
75311
75228
|
bufferDir: EVENT_BUFFER_DIR,
|
|
75312
|
-
rateStateExists:
|
|
75313
|
-
userCacheExists:
|
|
75229
|
+
rateStateExists: existsSync48(RATE_STATE_PATH),
|
|
75230
|
+
userCacheExists: existsSync48(USER_CACHE_PATH),
|
|
75314
75231
|
endpoint,
|
|
75315
75232
|
tokenConfigured: Boolean(token)
|
|
75316
75233
|
};
|
|
@@ -75329,13 +75246,13 @@ async function handleDisable() {
|
|
|
75329
75246
|
}
|
|
75330
75247
|
// src/commands/telemetry/phases/purge-local-handler.ts
|
|
75331
75248
|
init_logger();
|
|
75332
|
-
import { existsSync as
|
|
75333
|
-
import { join as
|
|
75249
|
+
import { existsSync as existsSync49, readdirSync as readdirSync6, unlinkSync as unlinkSync5 } from "node:fs";
|
|
75250
|
+
import { join as join103 } from "node:path";
|
|
75334
75251
|
function removeIfExists(path8) {
|
|
75335
75252
|
try {
|
|
75336
|
-
if (!
|
|
75253
|
+
if (!existsSync49(path8))
|
|
75337
75254
|
return false;
|
|
75338
|
-
|
|
75255
|
+
unlinkSync5(path8);
|
|
75339
75256
|
return true;
|
|
75340
75257
|
} catch {
|
|
75341
75258
|
return false;
|
|
@@ -75343,14 +75260,14 @@ function removeIfExists(path8) {
|
|
|
75343
75260
|
}
|
|
75344
75261
|
function removeBufferFiles() {
|
|
75345
75262
|
try {
|
|
75346
|
-
if (!
|
|
75263
|
+
if (!existsSync49(EVENT_BUFFER_DIR))
|
|
75347
75264
|
return 0;
|
|
75348
75265
|
let count = 0;
|
|
75349
75266
|
for (const file of readdirSync6(EVENT_BUFFER_DIR)) {
|
|
75350
75267
|
if (!file.endsWith(".jsonl"))
|
|
75351
75268
|
continue;
|
|
75352
75269
|
try {
|
|
75353
|
-
|
|
75270
|
+
unlinkSync5(join103(EVENT_BUFFER_DIR, file));
|
|
75354
75271
|
count += 1;
|
|
75355
75272
|
} catch {}
|
|
75356
75273
|
}
|
|
@@ -75376,9 +75293,9 @@ init_logger();
|
|
|
75376
75293
|
init_dist2();
|
|
75377
75294
|
var PURGE_TIMEOUT_MS = 1e4;
|
|
75378
75295
|
async function handlePurgeRemote(options2) {
|
|
75379
|
-
const
|
|
75380
|
-
if (!
|
|
75381
|
-
logger.error("No GitHub identity
|
|
75296
|
+
const githubLogin = await resolveGithubLogin();
|
|
75297
|
+
if (!githubLogin) {
|
|
75298
|
+
logger.error("No GitHub identity available. Sign in with `tkm auth login` (GitHub provider) so we know which account to purge.");
|
|
75382
75299
|
process.exitCode = 1;
|
|
75383
75300
|
return;
|
|
75384
75301
|
}
|
|
@@ -75395,7 +75312,7 @@ async function handlePurgeRemote(options2) {
|
|
|
75395
75312
|
}
|
|
75396
75313
|
if (!options2.yes) {
|
|
75397
75314
|
const answer = await se({
|
|
75398
|
-
message: `This will permanently delete ALL telemetry, feedback, and ratings for "${
|
|
75315
|
+
message: `This will permanently delete ALL telemetry, feedback, and ratings for "${githubLogin}" on the server. Continue?`,
|
|
75399
75316
|
initialValue: false
|
|
75400
75317
|
});
|
|
75401
75318
|
if (lD(answer) || answer !== true) {
|
|
@@ -75409,7 +75326,7 @@ async function handlePurgeRemote(options2) {
|
|
|
75409
75326
|
try {
|
|
75410
75327
|
resp = await fetch(`${endpoint}/user-purge`, {
|
|
75411
75328
|
method: "DELETE",
|
|
75412
|
-
body: JSON.stringify({ github_login:
|
|
75329
|
+
body: JSON.stringify({ github_login: githubLogin }),
|
|
75413
75330
|
headers: {
|
|
75414
75331
|
"content-type": "application/json",
|
|
75415
75332
|
"X-SK-Token": token
|
|
@@ -75425,7 +75342,7 @@ async function handlePurgeRemote(options2) {
|
|
|
75425
75342
|
}
|
|
75426
75343
|
clearTimeout(timer);
|
|
75427
75344
|
if (resp.status === 204) {
|
|
75428
|
-
logger.success(`Server-side data for "${
|
|
75345
|
+
logger.success(`Server-side data for "${githubLogin}" deleted.`);
|
|
75429
75346
|
logger.info("Run `tkm telemetry purge` to clear the local cache and buffer too, if you haven't already.");
|
|
75430
75347
|
return;
|
|
75431
75348
|
}
|
|
@@ -75577,13 +75494,13 @@ async function detectInstallations() {
|
|
|
75577
75494
|
|
|
75578
75495
|
// src/commands/uninstall/removal-handler.ts
|
|
75579
75496
|
import { readdirSync as readdirSync8, rmSync as rmSync6 } from "node:fs";
|
|
75580
|
-
import { join as
|
|
75497
|
+
import { join as join105, resolve as resolve24, sep as sep6 } from "node:path";
|
|
75581
75498
|
init_logger();
|
|
75582
75499
|
var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
75583
75500
|
|
|
75584
75501
|
// src/commands/uninstall/analysis-handler.ts
|
|
75585
75502
|
import { readdirSync as readdirSync7, rmSync as rmSync5 } from "node:fs";
|
|
75586
|
-
import { dirname as
|
|
75503
|
+
import { dirname as dirname28, join as join104 } from "node:path";
|
|
75587
75504
|
init_logger();
|
|
75588
75505
|
var import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
75589
75506
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -75600,7 +75517,7 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
|
75600
75517
|
}
|
|
75601
75518
|
async function cleanupEmptyDirectories3(filePath, installationRoot) {
|
|
75602
75519
|
let cleaned = 0;
|
|
75603
|
-
let currentDir =
|
|
75520
|
+
let currentDir = dirname28(filePath);
|
|
75604
75521
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
75605
75522
|
try {
|
|
75606
75523
|
const entries = readdirSync7(currentDir);
|
|
@@ -75608,7 +75525,7 @@ async function cleanupEmptyDirectories3(filePath, installationRoot) {
|
|
|
75608
75525
|
rmSync5(currentDir, { recursive: true });
|
|
75609
75526
|
cleaned++;
|
|
75610
75527
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
75611
|
-
currentDir =
|
|
75528
|
+
currentDir = dirname28(currentDir);
|
|
75612
75529
|
} else {
|
|
75613
75530
|
break;
|
|
75614
75531
|
}
|
|
@@ -75630,7 +75547,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
75630
75547
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
75631
75548
|
const kitFiles = metadata.kits[kit].files || [];
|
|
75632
75549
|
for (const trackedFile of kitFiles) {
|
|
75633
|
-
const filePath =
|
|
75550
|
+
const filePath = join104(installation.path, trackedFile.path);
|
|
75634
75551
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
75635
75552
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
75636
75553
|
continue;
|
|
@@ -75660,7 +75577,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
75660
75577
|
return result;
|
|
75661
75578
|
}
|
|
75662
75579
|
for (const trackedFile of allTrackedFiles) {
|
|
75663
|
-
const filePath =
|
|
75580
|
+
const filePath = join104(installation.path, trackedFile.path);
|
|
75664
75581
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
75665
75582
|
if (!ownershipResult.exists)
|
|
75666
75583
|
continue;
|
|
@@ -75757,7 +75674,7 @@ async function removeInstallations(installations, options2) {
|
|
|
75757
75674
|
let removedCount = 0;
|
|
75758
75675
|
let cleanedDirs = 0;
|
|
75759
75676
|
for (const item of analysis.toDelete) {
|
|
75760
|
-
const filePath =
|
|
75677
|
+
const filePath = join105(installation.path, item.path);
|
|
75761
75678
|
if (!await import_fs_extra36.pathExists(filePath))
|
|
75762
75679
|
continue;
|
|
75763
75680
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -75959,7 +75876,7 @@ ${import_picocolors34.default.yellow("User modifications will be permanently del
|
|
|
75959
75876
|
// src/commands/update-cli.ts
|
|
75960
75877
|
init_takumi_config_manager();
|
|
75961
75878
|
import { exec as exec8, spawn as spawn2 } from "node:child_process";
|
|
75962
|
-
import { join as
|
|
75879
|
+
import { join as join106 } from "node:path";
|
|
75963
75880
|
import { promisify as promisify13 } from "node:util";
|
|
75964
75881
|
|
|
75965
75882
|
// src/domains/github/npm-registry.ts
|
|
@@ -76126,7 +76043,7 @@ var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
|
76126
76043
|
// package.json
|
|
76127
76044
|
var package_default = {
|
|
76128
76045
|
name: "@sunasteriskrnd/takumi",
|
|
76129
|
-
version: "1.0.0-dev.
|
|
76046
|
+
version: "1.0.0-dev.4",
|
|
76130
76047
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
76131
76048
|
type: "module",
|
|
76132
76049
|
repository: {
|
|
@@ -76309,7 +76226,7 @@ function selectKitForUpdate(params) {
|
|
|
76309
76226
|
};
|
|
76310
76227
|
}
|
|
76311
76228
|
async function readMetadataFile(claudeDir) {
|
|
76312
|
-
const metadataPath =
|
|
76229
|
+
const metadataPath = join106(claudeDir, "metadata.json");
|
|
76313
76230
|
try {
|
|
76314
76231
|
if (!await import_fs_extra37.pathExists(metadataPath)) {
|
|
76315
76232
|
return null;
|
|
@@ -76805,10 +76722,10 @@ ${import_picocolors35.default.bold(import_picocolors35.default.cyan(result.kitCo
|
|
|
76805
76722
|
|
|
76806
76723
|
// src/commands/watch/watch-command.ts
|
|
76807
76724
|
init_logger();
|
|
76808
|
-
import { existsSync as
|
|
76725
|
+
import { existsSync as existsSync55 } from "node:fs";
|
|
76809
76726
|
import { rm as rm14 } from "node:fs/promises";
|
|
76810
|
-
import { homedir as
|
|
76811
|
-
import { join as
|
|
76727
|
+
import { homedir as homedir24 } from "node:os";
|
|
76728
|
+
import { join as join113 } from "node:path";
|
|
76812
76729
|
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
76813
76730
|
|
|
76814
76731
|
// src/commands/watch/phases/implementation-runner.ts
|
|
@@ -77318,7 +77235,7 @@ function spawnAndCollect3(command, args) {
|
|
|
77318
77235
|
|
|
77319
77236
|
// src/commands/watch/phases/issue-processor.ts
|
|
77320
77237
|
import { mkdir as mkdir29, writeFile as writeFile32 } from "node:fs/promises";
|
|
77321
|
-
import { join as
|
|
77238
|
+
import { join as join109 } from "node:path";
|
|
77322
77239
|
|
|
77323
77240
|
// src/commands/watch/phases/approval-detector.ts
|
|
77324
77241
|
init_logger();
|
|
@@ -77693,9 +77610,9 @@ async function checkAwaitingApproval(state, setup, options2, watchLog, projectDi
|
|
|
77693
77610
|
|
|
77694
77611
|
// src/commands/watch/phases/plan-dir-finder.ts
|
|
77695
77612
|
import { readdir as readdir30, stat as stat13 } from "node:fs/promises";
|
|
77696
|
-
import { join as
|
|
77613
|
+
import { join as join108 } from "node:path";
|
|
77697
77614
|
async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
77698
|
-
const plansRoot =
|
|
77615
|
+
const plansRoot = join108(cwd2, "plans");
|
|
77699
77616
|
try {
|
|
77700
77617
|
const entries = await readdir30(plansRoot);
|
|
77701
77618
|
const tenMinAgo = Date.now() - 10 * 60 * 1000;
|
|
@@ -77704,14 +77621,14 @@ async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
|
77704
77621
|
for (const entry of entries) {
|
|
77705
77622
|
if (entry === "watch" || entry === "reports" || entry === "visuals")
|
|
77706
77623
|
continue;
|
|
77707
|
-
const dirPath =
|
|
77624
|
+
const dirPath = join108(plansRoot, entry);
|
|
77708
77625
|
const dirStat = await stat13(dirPath);
|
|
77709
77626
|
if (!dirStat.isDirectory())
|
|
77710
77627
|
continue;
|
|
77711
77628
|
if (dirStat.mtimeMs < tenMinAgo)
|
|
77712
77629
|
continue;
|
|
77713
77630
|
try {
|
|
77714
|
-
await stat13(
|
|
77631
|
+
await stat13(join108(dirPath, "plan.md"));
|
|
77715
77632
|
} catch {
|
|
77716
77633
|
continue;
|
|
77717
77634
|
}
|
|
@@ -77942,13 +77859,13 @@ async function handlePlanGeneration(issue, state, config, setup, options2, watch
|
|
|
77942
77859
|
stats.plansCreated++;
|
|
77943
77860
|
const detectedPlanDir = await findRecentPlanDir(projectDir, issue.number, watchLog);
|
|
77944
77861
|
if (detectedPlanDir) {
|
|
77945
|
-
state.activeIssues[numStr].planPath =
|
|
77862
|
+
state.activeIssues[numStr].planPath = join109(detectedPlanDir, "plan.md");
|
|
77946
77863
|
watchLog.info(`Plan directory detected: ${detectedPlanDir}`);
|
|
77947
77864
|
} else {
|
|
77948
77865
|
try {
|
|
77949
|
-
const planDir =
|
|
77866
|
+
const planDir = join109(projectDir, "plans", "watch");
|
|
77950
77867
|
await mkdir29(planDir, { recursive: true });
|
|
77951
|
-
const planFilePath =
|
|
77868
|
+
const planFilePath = join109(planDir, `issue-${issue.number}-plan.md`);
|
|
77952
77869
|
await writeFile32(planFilePath, planResult.planText, "utf-8");
|
|
77953
77870
|
state.activeIssues[numStr].planPath = planFilePath;
|
|
77954
77871
|
watchLog.info(`Plan saved (fallback) to ${planFilePath}`);
|
|
@@ -78026,7 +77943,7 @@ async function checkActiveIssues(state, config, setup, options2, watchLog, stats
|
|
|
78026
77943
|
// src/commands/watch/phases/maintainer-resolver.ts
|
|
78027
77944
|
init_logger();
|
|
78028
77945
|
init_implementation_git_helpers();
|
|
78029
|
-
var
|
|
77946
|
+
var CACHE_TTL_MS2 = 3600000;
|
|
78030
77947
|
var cache = new Map;
|
|
78031
77948
|
async function resolveMaintainers(owner, repo, excludeAuthors, autoDetect) {
|
|
78032
77949
|
const normalizedExclude = excludeAuthors.map((s3) => s3.toLowerCase());
|
|
@@ -78035,7 +77952,7 @@ async function resolveMaintainers(owner, repo, excludeAuthors, autoDetect) {
|
|
|
78035
77952
|
}
|
|
78036
77953
|
const cacheKey = `${owner}/${repo}`;
|
|
78037
77954
|
const cached = cache.get(cacheKey);
|
|
78038
|
-
if (cached && Date.now() - cached.fetchedAt >=
|
|
77955
|
+
if (cached && Date.now() - cached.fetchedAt >= CACHE_TTL_MS2) {
|
|
78039
77956
|
cache.delete(cacheKey);
|
|
78040
77957
|
} else if (cached) {
|
|
78041
77958
|
const merged = Array.from(new Set([...cached.users, ...normalizedExclude]));
|
|
@@ -78090,16 +78007,16 @@ function cleanExpiredIssues(state, ttlDays) {
|
|
|
78090
78007
|
}
|
|
78091
78008
|
|
|
78092
78009
|
// src/commands/watch/phases/state-manager.ts
|
|
78093
|
-
import { existsSync as
|
|
78010
|
+
import { existsSync as existsSync51 } from "node:fs";
|
|
78094
78011
|
import { mkdir as mkdir30, readFile as readFile46 } from "node:fs/promises";
|
|
78095
|
-
import { dirname as
|
|
78012
|
+
import { dirname as dirname29 } from "node:path";
|
|
78096
78013
|
init_takumi_config_manager();
|
|
78097
78014
|
init_logger();
|
|
78098
78015
|
var PROCESSED_ISSUES_CAP = 500;
|
|
78099
78016
|
async function readCkJson(projectDir) {
|
|
78100
78017
|
const configPath = TakumiConfigManager.getProjectConfigPath(projectDir);
|
|
78101
78018
|
try {
|
|
78102
|
-
if (!
|
|
78019
|
+
if (!existsSync51(configPath))
|
|
78103
78020
|
return {};
|
|
78104
78021
|
const content = await readFile46(configPath, "utf-8");
|
|
78105
78022
|
return JSON.parse(content);
|
|
@@ -78124,8 +78041,8 @@ async function loadWatchState(projectDir) {
|
|
|
78124
78041
|
}
|
|
78125
78042
|
async function saveWatchState(projectDir, state) {
|
|
78126
78043
|
const configPath = TakumiConfigManager.getProjectConfigPath(projectDir);
|
|
78127
|
-
const configDir =
|
|
78128
|
-
if (!
|
|
78044
|
+
const configDir = dirname29(configPath);
|
|
78045
|
+
if (!existsSync51(configDir)) {
|
|
78129
78046
|
await mkdir30(configDir, { recursive: true });
|
|
78130
78047
|
}
|
|
78131
78048
|
const raw = await readCkJson(projectDir);
|
|
@@ -78251,21 +78168,21 @@ async function processImplementationQueue(state, config, setup, options2, watchL
|
|
|
78251
78168
|
// src/commands/watch/phases/repo-scanner.ts
|
|
78252
78169
|
init_logger();
|
|
78253
78170
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
78254
|
-
import { existsSync as
|
|
78171
|
+
import { existsSync as existsSync52 } from "node:fs";
|
|
78255
78172
|
import { readdir as readdir31, stat as stat14 } from "node:fs/promises";
|
|
78256
|
-
import { join as
|
|
78173
|
+
import { join as join110 } from "node:path";
|
|
78257
78174
|
async function scanForRepos(parentDir) {
|
|
78258
78175
|
const repos = [];
|
|
78259
78176
|
const entries = await readdir31(parentDir);
|
|
78260
78177
|
for (const entry of entries) {
|
|
78261
78178
|
if (entry.startsWith("."))
|
|
78262
78179
|
continue;
|
|
78263
|
-
const fullPath =
|
|
78180
|
+
const fullPath = join110(parentDir, entry);
|
|
78264
78181
|
const entryStat = await stat14(fullPath);
|
|
78265
78182
|
if (!entryStat.isDirectory())
|
|
78266
78183
|
continue;
|
|
78267
|
-
const gitDir =
|
|
78268
|
-
if (!
|
|
78184
|
+
const gitDir = join110(fullPath, ".git");
|
|
78185
|
+
if (!existsSync52(gitDir))
|
|
78269
78186
|
continue;
|
|
78270
78187
|
const result = spawnSync5("gh", ["repo", "view", "--json", "owner,name"], {
|
|
78271
78188
|
encoding: "utf-8",
|
|
@@ -78289,9 +78206,9 @@ async function scanForRepos(parentDir) {
|
|
|
78289
78206
|
// src/commands/watch/phases/setup-validator.ts
|
|
78290
78207
|
init_logger();
|
|
78291
78208
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
78292
|
-
import { existsSync as
|
|
78293
|
-
import { homedir as
|
|
78294
|
-
import { join as
|
|
78209
|
+
import { existsSync as existsSync53 } from "node:fs";
|
|
78210
|
+
import { homedir as homedir23 } from "node:os";
|
|
78211
|
+
import { join as join111 } from "node:path";
|
|
78295
78212
|
async function validateSetup(cwd2) {
|
|
78296
78213
|
const workDir = cwd2 ?? process.cwd();
|
|
78297
78214
|
const ghVersion = spawnSync6("gh", ["--version"], { encoding: "utf-8", timeout: 1e4 });
|
|
@@ -78322,8 +78239,8 @@ Run this command from a directory with a GitHub remote.`);
|
|
|
78322
78239
|
} catch {
|
|
78323
78240
|
throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
|
|
78324
78241
|
}
|
|
78325
|
-
const skillsPath =
|
|
78326
|
-
const skillsAvailable =
|
|
78242
|
+
const skillsPath = join111(homedir23(), ".claude", "skills");
|
|
78243
|
+
const skillsAvailable = existsSync53(skillsPath);
|
|
78327
78244
|
if (!skillsAvailable) {
|
|
78328
78245
|
logger.warning(`Takumi Engineer skills not found at ${skillsPath}`);
|
|
78329
78246
|
}
|
|
@@ -78339,9 +78256,9 @@ Run this command from a directory with a GitHub remote.`);
|
|
|
78339
78256
|
init_logger();
|
|
78340
78257
|
init_path_resolver();
|
|
78341
78258
|
import { createWriteStream as createWriteStream3, statSync as statSync6 } from "node:fs";
|
|
78342
|
-
import { existsSync as
|
|
78259
|
+
import { existsSync as existsSync54 } from "node:fs";
|
|
78343
78260
|
import { mkdir as mkdir31, rename as rename7 } from "node:fs/promises";
|
|
78344
|
-
import { join as
|
|
78261
|
+
import { join as join112 } from "node:path";
|
|
78345
78262
|
|
|
78346
78263
|
class WatchLogger {
|
|
78347
78264
|
logStream = null;
|
|
@@ -78349,16 +78266,16 @@ class WatchLogger {
|
|
|
78349
78266
|
logPath = null;
|
|
78350
78267
|
maxBytes;
|
|
78351
78268
|
constructor(logDir, maxBytes = 0) {
|
|
78352
|
-
this.logDir = logDir ??
|
|
78269
|
+
this.logDir = logDir ?? join112(PathResolver.getTakumiDir(), "logs");
|
|
78353
78270
|
this.maxBytes = maxBytes;
|
|
78354
78271
|
}
|
|
78355
78272
|
async init() {
|
|
78356
78273
|
try {
|
|
78357
|
-
if (!
|
|
78274
|
+
if (!existsSync54(this.logDir)) {
|
|
78358
78275
|
await mkdir31(this.logDir, { recursive: true });
|
|
78359
78276
|
}
|
|
78360
78277
|
const dateStr = formatDate(new Date);
|
|
78361
|
-
this.logPath =
|
|
78278
|
+
this.logPath = join112(this.logDir, `watch-${dateStr}.log`);
|
|
78362
78279
|
this.logStream = createWriteStream3(this.logPath, { flags: "a", mode: 384 });
|
|
78363
78280
|
} catch (error) {
|
|
78364
78281
|
logger.warning(`Cannot create watch log file: ${error instanceof Error ? error.message : "Unknown"}`);
|
|
@@ -78538,7 +78455,7 @@ async function watchCommand(options2) {
|
|
|
78538
78455
|
}
|
|
78539
78456
|
async function discoverRepos(options2, watchLog) {
|
|
78540
78457
|
const cwd2 = process.cwd();
|
|
78541
|
-
const isGitRepo =
|
|
78458
|
+
const isGitRepo = existsSync55(join113(cwd2, ".git"));
|
|
78542
78459
|
if (options2.force) {
|
|
78543
78460
|
await forceRemoveLock(watchLog);
|
|
78544
78461
|
}
|
|
@@ -78608,7 +78525,7 @@ async function resetState(state, projectDir, watchLog) {
|
|
|
78608
78525
|
watchLog.info(`Watch state reset (--force) for ${projectDir}`);
|
|
78609
78526
|
}
|
|
78610
78527
|
async function forceRemoveLock(watchLog) {
|
|
78611
|
-
const lockPath =
|
|
78528
|
+
const lockPath = join113(homedir24(), ".sunagentkit", "locks", `${LOCK_NAME}.lock`);
|
|
78612
78529
|
try {
|
|
78613
78530
|
await rm14(lockPath, { recursive: true, force: true });
|
|
78614
78531
|
watchLog.info("Removed existing lock file (--force)");
|
|
@@ -78780,7 +78697,7 @@ function registerCommands(cli) {
|
|
|
78780
78697
|
}
|
|
78781
78698
|
await migrateCommand(options2);
|
|
78782
78699
|
});
|
|
78783
|
-
cli.command("auth [action]", "Sign in/out and check Takumi session (login|logout|status)").action(async (action) => {
|
|
78700
|
+
cli.command("auth [action]", "Sign in/out and check Takumi session (login|logout|status)").option("--json", "Machine-readable JSON output (status only)").action(async (action, options2 = {}) => {
|
|
78784
78701
|
switch (action) {
|
|
78785
78702
|
case "login":
|
|
78786
78703
|
await login();
|
|
@@ -78789,7 +78706,7 @@ function registerCommands(cli) {
|
|
|
78789
78706
|
await logout();
|
|
78790
78707
|
break;
|
|
78791
78708
|
case "status":
|
|
78792
|
-
await status();
|
|
78709
|
+
await status({ json: options2.json });
|
|
78793
78710
|
break;
|
|
78794
78711
|
case undefined:
|
|
78795
78712
|
console.error("Usage: tkm auth <login|logout|status>");
|
|
@@ -78806,8 +78723,8 @@ function registerCommands(cli) {
|
|
|
78806
78723
|
}
|
|
78807
78724
|
|
|
78808
78725
|
// src/cli/version-display.ts
|
|
78809
|
-
import { existsSync as
|
|
78810
|
-
import { join as
|
|
78726
|
+
import { existsSync as existsSync67, readFileSync as readFileSync20 } from "node:fs";
|
|
78727
|
+
import { join as join125 } from "node:path";
|
|
78811
78728
|
init_help_banner();
|
|
78812
78729
|
// src/domains/versioning/checking/kit-version-checker.ts
|
|
78813
78730
|
init_github_client();
|
|
@@ -78817,21 +78734,21 @@ init_types2();
|
|
|
78817
78734
|
// src/domains/versioning/version-cache.ts
|
|
78818
78735
|
init_logger();
|
|
78819
78736
|
init_path_resolver();
|
|
78820
|
-
import { existsSync as
|
|
78737
|
+
import { existsSync as existsSync66 } from "node:fs";
|
|
78821
78738
|
import { mkdir as mkdir32, readFile as readFile48, writeFile as writeFile35 } from "node:fs/promises";
|
|
78822
|
-
import { join as
|
|
78739
|
+
import { join as join124 } from "node:path";
|
|
78823
78740
|
|
|
78824
78741
|
class VersionCacheManager {
|
|
78825
78742
|
static CACHE_FILENAME = "version-check.json";
|
|
78826
78743
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
78827
78744
|
static getCacheFile() {
|
|
78828
78745
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
78829
|
-
return
|
|
78746
|
+
return join124(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
78830
78747
|
}
|
|
78831
78748
|
static async load() {
|
|
78832
78749
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
78833
78750
|
try {
|
|
78834
|
-
if (!
|
|
78751
|
+
if (!existsSync66(cacheFile)) {
|
|
78835
78752
|
logger.debug("Version check cache not found");
|
|
78836
78753
|
return null;
|
|
78837
78754
|
}
|
|
@@ -78852,7 +78769,7 @@ class VersionCacheManager {
|
|
|
78852
78769
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
78853
78770
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
78854
78771
|
try {
|
|
78855
|
-
if (!
|
|
78772
|
+
if (!existsSync66(cacheDir)) {
|
|
78856
78773
|
await mkdir32(cacheDir, { recursive: true, mode: 448 });
|
|
78857
78774
|
}
|
|
78858
78775
|
await writeFile35(cacheFile, JSON.stringify(cache2, null, 2), "utf-8");
|
|
@@ -78874,7 +78791,7 @@ class VersionCacheManager {
|
|
|
78874
78791
|
static async clear() {
|
|
78875
78792
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
78876
78793
|
try {
|
|
78877
|
-
if (
|
|
78794
|
+
if (existsSync66(cacheFile)) {
|
|
78878
78795
|
const fs12 = await import("node:fs/promises");
|
|
78879
78796
|
await fs12.unlink(cacheFile);
|
|
78880
78797
|
logger.debug("Version check cache cleared");
|
|
@@ -79102,13 +79019,13 @@ async function displayVersion() {
|
|
|
79102
79019
|
let localKitVersion = null;
|
|
79103
79020
|
let isGlobalOnlyKit = false;
|
|
79104
79021
|
const globalKitDir = PathResolver.getGlobalKitDir();
|
|
79105
|
-
const globalMetadataPath =
|
|
79022
|
+
const globalMetadataPath = join125(globalKitDir, "metadata.json");
|
|
79106
79023
|
const prefix = PathResolver.getPathPrefix(false);
|
|
79107
|
-
const localMetadataPath = prefix ?
|
|
79024
|
+
const localMetadataPath = prefix ? join125(process.cwd(), prefix, "metadata.json") : join125(process.cwd(), "metadata.json");
|
|
79108
79025
|
const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
|
|
79109
|
-
if (!isLocalSameAsGlobal &&
|
|
79026
|
+
if (!isLocalSameAsGlobal && existsSync67(localMetadataPath)) {
|
|
79110
79027
|
try {
|
|
79111
|
-
const rawMetadata = JSON.parse(
|
|
79028
|
+
const rawMetadata = JSON.parse(readFileSync20(localMetadataPath, "utf-8"));
|
|
79112
79029
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
79113
79030
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
79114
79031
|
if (kitsDisplay) {
|
|
@@ -79120,9 +79037,9 @@ async function displayVersion() {
|
|
|
79120
79037
|
logger.verbose("Failed to parse local metadata.json", { error });
|
|
79121
79038
|
}
|
|
79122
79039
|
}
|
|
79123
|
-
if (
|
|
79040
|
+
if (existsSync67(globalMetadataPath)) {
|
|
79124
79041
|
try {
|
|
79125
|
-
const rawMetadata = JSON.parse(
|
|
79042
|
+
const rawMetadata = JSON.parse(readFileSync20(globalMetadataPath, "utf-8"));
|
|
79126
79043
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
79127
79044
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
79128
79045
|
if (kitsDisplay) {
|