@sunasteriskrnd/takumi 1.0.0-dev.7 → 1.0.0-dev.9
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 +493 -225
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -11225,12 +11225,12 @@ function isSafeRelativeLayoutPath(value) {
|
|
|
11225
11225
|
return segments.every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
|
|
11226
11226
|
}
|
|
11227
11227
|
function isValidKitType(value) {
|
|
11228
|
-
return value === "engineer";
|
|
11228
|
+
return value === "engineer" || value === "extras";
|
|
11229
11229
|
}
|
|
11230
|
-
var KitType, KitConfigSchema, KitLayoutSchema, TakumiPackageMetadataSchema, DEFAULT_KIT_LAYOUT, AVAILABLE_KITS, NEVER_COPY_PATTERNS, USER_CONFIG_PATTERNS, PROTECTED_PATTERNS;
|
|
11230
|
+
var KitType, KitConfigSchema, KitLayoutSchema, TakumiPackageMetadataSchema, DEFAULT_KIT_LAYOUT, AVAILABLE_KITS, BASE_KIT = "engineer", NEVER_COPY_PATTERNS, USER_CONFIG_PATTERNS, PROTECTED_PATTERNS;
|
|
11231
11231
|
var init_kit = __esm(() => {
|
|
11232
11232
|
init_zod();
|
|
11233
|
-
KitType = exports_external.enum(["engineer"]);
|
|
11233
|
+
KitType = exports_external.enum(["engineer", "extras"]);
|
|
11234
11234
|
KitConfigSchema = exports_external.object({
|
|
11235
11235
|
id: KitType,
|
|
11236
11236
|
name: exports_external.string(),
|
|
@@ -11256,6 +11256,13 @@ var init_kit = __esm(() => {
|
|
|
11256
11256
|
repo: "takumi",
|
|
11257
11257
|
owner: "sun-asterisk-internal",
|
|
11258
11258
|
description: "Engineering toolkit for building with Claude"
|
|
11259
|
+
},
|
|
11260
|
+
extras: {
|
|
11261
|
+
id: "extras",
|
|
11262
|
+
name: "Takumi Extras",
|
|
11263
|
+
repo: "takumi-extras",
|
|
11264
|
+
owner: "sun-asterisk-internal",
|
|
11265
|
+
description: "Extras agent kit"
|
|
11259
11266
|
}
|
|
11260
11267
|
};
|
|
11261
11268
|
NEVER_COPY_PATTERNS = [
|
|
@@ -11444,13 +11451,14 @@ var init_metadata = __esm(() => {
|
|
|
11444
11451
|
KitMetadataSchema = exports_external.object({
|
|
11445
11452
|
version: exports_external.string(),
|
|
11446
11453
|
installedAt: exports_external.string(),
|
|
11454
|
+
installState: exports_external.enum(["pending", "complete"]).optional(),
|
|
11447
11455
|
files: exports_external.array(TrackedFileSchema).optional(),
|
|
11448
11456
|
lastUpdateCheck: exports_external.string().optional(),
|
|
11449
11457
|
dismissedVersion: exports_external.string().optional(),
|
|
11450
11458
|
installedSettings: InstalledSettingsSchema.optional()
|
|
11451
11459
|
});
|
|
11452
11460
|
MultiKitMetadataSchema = exports_external.object({
|
|
11453
|
-
kits: exports_external.record(
|
|
11461
|
+
kits: exports_external.record(exports_external.string(), KitMetadataSchema).optional(),
|
|
11454
11462
|
scope: exports_external.enum(["local", "global"]).optional(),
|
|
11455
11463
|
name: exports_external.string().optional(),
|
|
11456
11464
|
version: exports_external.string().optional(),
|
|
@@ -12116,6 +12124,7 @@ __export(exports_types, {
|
|
|
12116
12124
|
DEFAULT_FOLDERS: () => DEFAULT_FOLDERS,
|
|
12117
12125
|
ConfigSchema: () => ConfigSchema,
|
|
12118
12126
|
CodingLevelSchema: () => CodingLevelSchema,
|
|
12127
|
+
BASE_KIT: () => BASE_KIT,
|
|
12119
12128
|
AuthenticationError: () => AuthenticationError,
|
|
12120
12129
|
ApiStatusOptionsSchema: () => ApiStatusOptionsSchema,
|
|
12121
12130
|
ApiSetupOptionsSchema: () => ApiSetupOptionsSchema,
|
|
@@ -34554,9 +34563,9 @@ __export(exports_worktree_manager, {
|
|
|
34554
34563
|
});
|
|
34555
34564
|
import { existsSync as existsSync60 } from "node:fs";
|
|
34556
34565
|
import { readFile as readFile49, writeFile as writeFile36 } from "node:fs/promises";
|
|
34557
|
-
import { join as
|
|
34566
|
+
import { join as join120 } from "node:path";
|
|
34558
34567
|
async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
34559
|
-
const worktreePath =
|
|
34568
|
+
const worktreePath = join120(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
34560
34569
|
const branchName = `sk-watch/issue-${issueNumber}`;
|
|
34561
34570
|
await spawnAndCollect("git", ["fetch", "origin", baseBranch], projectDir).catch(() => {
|
|
34562
34571
|
logger.warning(`[worktree] Could not fetch origin/${baseBranch}, using local`);
|
|
@@ -34574,7 +34583,7 @@ async function createWorktree(projectDir, issueNumber, baseBranch) {
|
|
|
34574
34583
|
return worktreePath;
|
|
34575
34584
|
}
|
|
34576
34585
|
async function removeWorktree(projectDir, issueNumber) {
|
|
34577
|
-
const worktreePath =
|
|
34586
|
+
const worktreePath = join120(projectDir, WORKTREE_DIR, `issue-${issueNumber}`);
|
|
34578
34587
|
const branchName = `sk-watch/issue-${issueNumber}`;
|
|
34579
34588
|
try {
|
|
34580
34589
|
await spawnAndCollect("git", ["worktree", "remove", worktreePath, "--force"], projectDir);
|
|
@@ -34588,7 +34597,7 @@ async function listActiveWorktrees(projectDir) {
|
|
|
34588
34597
|
try {
|
|
34589
34598
|
const output2 = await spawnAndCollect("git", ["worktree", "list", "--porcelain"], projectDir);
|
|
34590
34599
|
const issueNumbers = [];
|
|
34591
|
-
const worktreePrefix =
|
|
34600
|
+
const worktreePrefix = join120(projectDir, WORKTREE_DIR, "issue-").replace(/\\/g, "/");
|
|
34592
34601
|
for (const line of output2.split(`
|
|
34593
34602
|
`)) {
|
|
34594
34603
|
if (line.startsWith("worktree ")) {
|
|
@@ -34616,7 +34625,7 @@ async function cleanupAllWorktrees(projectDir) {
|
|
|
34616
34625
|
await spawnAndCollect("git", ["worktree", "prune"], projectDir).catch(() => {});
|
|
34617
34626
|
}
|
|
34618
34627
|
async function ensureGitignore(projectDir) {
|
|
34619
|
-
const gitignorePath =
|
|
34628
|
+
const gitignorePath = join120(projectDir, ".gitignore");
|
|
34620
34629
|
try {
|
|
34621
34630
|
const content = existsSync60(gitignorePath) ? await readFile49(gitignorePath, "utf-8") : "";
|
|
34622
34631
|
if (!content.includes(".worktrees")) {
|
|
@@ -34723,7 +34732,7 @@ import { createHash as createHash8 } from "node:crypto";
|
|
|
34723
34732
|
import { existsSync as existsSync66, mkdirSync as mkdirSync4, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync7 } from "node:fs";
|
|
34724
34733
|
import { rename as rename10, writeFile as writeFile38 } from "node:fs/promises";
|
|
34725
34734
|
import { homedir as homedir32 } from "node:os";
|
|
34726
|
-
import { basename as basename17, join as
|
|
34735
|
+
import { basename as basename17, join as join127 } from "node:path";
|
|
34727
34736
|
function getCachedContext(repoPath) {
|
|
34728
34737
|
const cachePath = getCacheFilePath(repoPath);
|
|
34729
34738
|
if (!existsSync66(cachePath))
|
|
@@ -34766,25 +34775,25 @@ function computeSourceHash(repoPath) {
|
|
|
34766
34775
|
}
|
|
34767
34776
|
function getDocSourcePaths(repoPath) {
|
|
34768
34777
|
const paths = [];
|
|
34769
|
-
const docsDir =
|
|
34778
|
+
const docsDir = join127(repoPath, "docs");
|
|
34770
34779
|
if (existsSync66(docsDir)) {
|
|
34771
34780
|
try {
|
|
34772
34781
|
const files = readdirSync10(docsDir);
|
|
34773
34782
|
for (const f4 of files) {
|
|
34774
34783
|
if (f4.endsWith(".md"))
|
|
34775
|
-
paths.push(
|
|
34784
|
+
paths.push(join127(docsDir, f4));
|
|
34776
34785
|
}
|
|
34777
34786
|
} catch {}
|
|
34778
34787
|
}
|
|
34779
|
-
const readme =
|
|
34788
|
+
const readme = join127(repoPath, "README.md");
|
|
34780
34789
|
if (existsSync66(readme))
|
|
34781
34790
|
paths.push(readme);
|
|
34782
|
-
const stylesDir =
|
|
34791
|
+
const stylesDir = join127(repoPath, "assets", "writing-styles");
|
|
34783
34792
|
if (existsSync66(stylesDir)) {
|
|
34784
34793
|
try {
|
|
34785
34794
|
const files = readdirSync10(stylesDir);
|
|
34786
34795
|
for (const f4 of files) {
|
|
34787
|
-
paths.push(
|
|
34796
|
+
paths.push(join127(stylesDir, f4));
|
|
34788
34797
|
}
|
|
34789
34798
|
} catch {}
|
|
34790
34799
|
}
|
|
@@ -34793,11 +34802,11 @@ function getDocSourcePaths(repoPath) {
|
|
|
34793
34802
|
function getCacheFilePath(repoPath) {
|
|
34794
34803
|
const repoName = basename17(repoPath).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
34795
34804
|
const pathHash = createHash8("sha256").update(repoPath).digest("hex").slice(0, 8);
|
|
34796
|
-
return
|
|
34805
|
+
return join127(CACHE_DIR, `${repoName}-${pathHash}-context-cache.json`);
|
|
34797
34806
|
}
|
|
34798
34807
|
var CACHE_DIR, CACHE_TTL_MS3;
|
|
34799
34808
|
var init_context_cache_manager = __esm(() => {
|
|
34800
|
-
CACHE_DIR =
|
|
34809
|
+
CACHE_DIR = join127(homedir32(), ".sunagentkit", "cache");
|
|
34801
34810
|
CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
|
|
34802
34811
|
});
|
|
34803
34812
|
|
|
@@ -34978,7 +34987,7 @@ function extractContentFromResponse(response) {
|
|
|
34978
34987
|
// src/commands/content/phases/docs-summarizer.ts
|
|
34979
34988
|
import { execSync as execSync5 } from "node:child_process";
|
|
34980
34989
|
import { existsSync as existsSync67, readFileSync as readFileSync17, readdirSync as readdirSync11 } from "node:fs";
|
|
34981
|
-
import { join as
|
|
34990
|
+
import { join as join128 } from "node:path";
|
|
34982
34991
|
async function summarizeProjectDocs(repoPath, contentLogger) {
|
|
34983
34992
|
const rawContent = collectRawDocs(repoPath);
|
|
34984
34993
|
if (rawContent.total.length < 200) {
|
|
@@ -35032,12 +35041,12 @@ function collectRawDocs(repoPath) {
|
|
|
35032
35041
|
return capped;
|
|
35033
35042
|
};
|
|
35034
35043
|
const docsContent = [];
|
|
35035
|
-
const docsDir =
|
|
35044
|
+
const docsDir = join128(repoPath, "docs");
|
|
35036
35045
|
if (existsSync67(docsDir)) {
|
|
35037
35046
|
try {
|
|
35038
35047
|
const files = readdirSync11(docsDir).filter((f4) => f4.endsWith(".md")).sort();
|
|
35039
35048
|
for (const f4 of files) {
|
|
35040
|
-
const content = readCapped(
|
|
35049
|
+
const content = readCapped(join128(docsDir, f4), 5000);
|
|
35041
35050
|
if (content) {
|
|
35042
35051
|
docsContent.push(`### ${f4}
|
|
35043
35052
|
${content}`);
|
|
@@ -35051,21 +35060,21 @@ ${content}`);
|
|
|
35051
35060
|
let brand = "";
|
|
35052
35061
|
const brandCandidates = ["docs/brand-guidelines.md", "docs/design-guidelines.md"];
|
|
35053
35062
|
for (const p2 of brandCandidates) {
|
|
35054
|
-
brand = readCapped(
|
|
35063
|
+
brand = readCapped(join128(repoPath, p2), 3000);
|
|
35055
35064
|
if (brand)
|
|
35056
35065
|
break;
|
|
35057
35066
|
}
|
|
35058
35067
|
let styles3 = "";
|
|
35059
|
-
const stylesDir =
|
|
35068
|
+
const stylesDir = join128(repoPath, "assets", "writing-styles");
|
|
35060
35069
|
if (existsSync67(stylesDir)) {
|
|
35061
35070
|
try {
|
|
35062
35071
|
const files = readdirSync11(stylesDir).slice(0, 3);
|
|
35063
|
-
styles3 = files.map((f4) => readCapped(
|
|
35072
|
+
styles3 = files.map((f4) => readCapped(join128(stylesDir, f4), 1000)).filter(Boolean).join(`
|
|
35064
35073
|
|
|
35065
35074
|
`);
|
|
35066
35075
|
} catch {}
|
|
35067
35076
|
}
|
|
35068
|
-
const readme = readCapped(
|
|
35077
|
+
const readme = readCapped(join128(repoPath, "README.md"), 3000);
|
|
35069
35078
|
const total = [docs, brand, styles3, readme].join(`
|
|
35070
35079
|
`);
|
|
35071
35080
|
return { docs, brand, styles: styles3, readme, total };
|
|
@@ -35252,9 +35261,9 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
|
|
|
35252
35261
|
import { execSync as execSync6 } from "node:child_process";
|
|
35253
35262
|
import { existsSync as existsSync68, mkdirSync as mkdirSync5, readdirSync as readdirSync12 } from "node:fs";
|
|
35254
35263
|
import { homedir as homedir33 } from "node:os";
|
|
35255
|
-
import { join as
|
|
35264
|
+
import { join as join129 } from "node:path";
|
|
35256
35265
|
async function generatePhoto(_content, context, config, platform10, contentId, contentLogger) {
|
|
35257
|
-
const mediaDir =
|
|
35266
|
+
const mediaDir = join129(config.contentDir.replace(/^~/, homedir33()), "media", String(contentId));
|
|
35258
35267
|
if (!existsSync68(mediaDir)) {
|
|
35259
35268
|
mkdirSync5(mediaDir, { recursive: true });
|
|
35260
35269
|
}
|
|
@@ -35279,7 +35288,7 @@ async function generatePhoto(_content, context, config, platform10, contentId, c
|
|
|
35279
35288
|
const imageFile = files.find((f4) => /\.(png|jpg|jpeg|webp)$/i.test(f4));
|
|
35280
35289
|
if (imageFile) {
|
|
35281
35290
|
const ext2 = imageFile.split(".").pop() ?? "png";
|
|
35282
|
-
return { path:
|
|
35291
|
+
return { path: join129(mediaDir, imageFile), ...dimensions, format: ext2 };
|
|
35283
35292
|
}
|
|
35284
35293
|
contentLogger.warn(`Photo generation produced no image for content ${contentId}`);
|
|
35285
35294
|
return null;
|
|
@@ -35369,7 +35378,7 @@ var init_content_creator = __esm(() => {
|
|
|
35369
35378
|
// src/commands/content/phases/content-logger.ts
|
|
35370
35379
|
import { createWriteStream as createWriteStream5, existsSync as existsSync69, mkdirSync as mkdirSync6, statSync as statSync8 } from "node:fs";
|
|
35371
35380
|
import { homedir as homedir34 } from "node:os";
|
|
35372
|
-
import { join as
|
|
35381
|
+
import { join as join130 } from "node:path";
|
|
35373
35382
|
|
|
35374
35383
|
class ContentLogger {
|
|
35375
35384
|
stream = null;
|
|
@@ -35377,7 +35386,7 @@ class ContentLogger {
|
|
|
35377
35386
|
logDir;
|
|
35378
35387
|
maxBytes;
|
|
35379
35388
|
constructor(maxBytes = 0) {
|
|
35380
|
-
this.logDir =
|
|
35389
|
+
this.logDir = join130(homedir34(), ".sunagentkit", "logs");
|
|
35381
35390
|
this.maxBytes = maxBytes;
|
|
35382
35391
|
}
|
|
35383
35392
|
init() {
|
|
@@ -35409,7 +35418,7 @@ class ContentLogger {
|
|
|
35409
35418
|
}
|
|
35410
35419
|
}
|
|
35411
35420
|
getLogPath() {
|
|
35412
|
-
return
|
|
35421
|
+
return join130(this.logDir, `content-${this.getDateStr()}.log`);
|
|
35413
35422
|
}
|
|
35414
35423
|
write(level, message) {
|
|
35415
35424
|
this.rotateIfNeeded();
|
|
@@ -35426,18 +35435,18 @@ class ContentLogger {
|
|
|
35426
35435
|
if (dateStr !== this.currentDate) {
|
|
35427
35436
|
this.close();
|
|
35428
35437
|
this.currentDate = dateStr;
|
|
35429
|
-
const logPath =
|
|
35438
|
+
const logPath = join130(this.logDir, `content-${dateStr}.log`);
|
|
35430
35439
|
this.stream = createWriteStream5(logPath, { flags: "a", mode: 384 });
|
|
35431
35440
|
return;
|
|
35432
35441
|
}
|
|
35433
35442
|
if (this.maxBytes > 0 && this.stream) {
|
|
35434
|
-
const logPath =
|
|
35443
|
+
const logPath = join130(this.logDir, `content-${this.currentDate}.log`);
|
|
35435
35444
|
try {
|
|
35436
35445
|
const stat16 = statSync8(logPath);
|
|
35437
35446
|
if (stat16.size >= this.maxBytes) {
|
|
35438
35447
|
this.close();
|
|
35439
35448
|
const suffix = Date.now();
|
|
35440
|
-
const rotatedPath =
|
|
35449
|
+
const rotatedPath = join130(this.logDir, `content-${this.currentDate}-${suffix}.log`);
|
|
35441
35450
|
import("node:fs/promises").then(({ rename: rename11 }) => rename11(logPath, rotatedPath).catch(() => {}));
|
|
35442
35451
|
this.stream = createWriteStream5(logPath, { flags: "w", mode: 384 });
|
|
35443
35452
|
}
|
|
@@ -35663,7 +35672,7 @@ function isNoiseCommit(title, author) {
|
|
|
35663
35672
|
// src/commands/content/phases/change-detector.ts
|
|
35664
35673
|
import { execSync as execSync8 } from "node:child_process";
|
|
35665
35674
|
import { existsSync as existsSync71, readFileSync as readFileSync18, readdirSync as readdirSync13, statSync as statSync9 } from "node:fs";
|
|
35666
|
-
import { join as
|
|
35675
|
+
import { join as join131 } from "node:path";
|
|
35667
35676
|
function detectCommits(repo, since) {
|
|
35668
35677
|
try {
|
|
35669
35678
|
const fetchUrl = sshToHttps(repo.remoteUrl);
|
|
@@ -35761,7 +35770,7 @@ function detectTags(repo, since) {
|
|
|
35761
35770
|
}
|
|
35762
35771
|
}
|
|
35763
35772
|
function detectCompletedPlans(repo, since) {
|
|
35764
|
-
const plansDir =
|
|
35773
|
+
const plansDir = join131(repo.path, "plans");
|
|
35765
35774
|
if (!existsSync71(plansDir))
|
|
35766
35775
|
return [];
|
|
35767
35776
|
const sinceMs = new Date(since).getTime();
|
|
@@ -35771,7 +35780,7 @@ function detectCompletedPlans(repo, since) {
|
|
|
35771
35780
|
for (const entry of entries) {
|
|
35772
35781
|
if (!entry.isDirectory())
|
|
35773
35782
|
continue;
|
|
35774
|
-
const planFile =
|
|
35783
|
+
const planFile = join131(plansDir, entry.name, "plan.md");
|
|
35775
35784
|
if (!existsSync71(planFile))
|
|
35776
35785
|
continue;
|
|
35777
35786
|
try {
|
|
@@ -35849,7 +35858,7 @@ function classifyCommit(event) {
|
|
|
35849
35858
|
// src/commands/content/phases/repo-discoverer.ts
|
|
35850
35859
|
import { execSync as execSync9 } from "node:child_process";
|
|
35851
35860
|
import { readdirSync as readdirSync14 } from "node:fs";
|
|
35852
|
-
import { join as
|
|
35861
|
+
import { join as join132 } from "node:path";
|
|
35853
35862
|
function discoverRepos2(cwd2) {
|
|
35854
35863
|
const repos = [];
|
|
35855
35864
|
if (isGitRepoRoot(cwd2)) {
|
|
@@ -35862,7 +35871,7 @@ function discoverRepos2(cwd2) {
|
|
|
35862
35871
|
for (const entry of entries) {
|
|
35863
35872
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
35864
35873
|
continue;
|
|
35865
|
-
const dirPath =
|
|
35874
|
+
const dirPath = join132(cwd2, entry.name);
|
|
35866
35875
|
if (isGitRepoRoot(dirPath)) {
|
|
35867
35876
|
const info = getRepoInfo(dirPath);
|
|
35868
35877
|
if (info)
|
|
@@ -36529,9 +36538,9 @@ var init_types3 = __esm(() => {
|
|
|
36529
36538
|
|
|
36530
36539
|
// src/commands/content/phases/state-manager.ts
|
|
36531
36540
|
import { readFile as readFile51, rename as rename11, writeFile as writeFile39 } from "node:fs/promises";
|
|
36532
|
-
import { join as
|
|
36541
|
+
import { join as join133 } from "node:path";
|
|
36533
36542
|
async function loadContentConfig(projectDir) {
|
|
36534
|
-
const configPath =
|
|
36543
|
+
const configPath = join133(projectDir, TAKUMI_CONFIG_FILE2);
|
|
36535
36544
|
try {
|
|
36536
36545
|
const raw = await readFile51(configPath, "utf-8");
|
|
36537
36546
|
const json = JSON.parse(raw);
|
|
@@ -36541,13 +36550,13 @@ async function loadContentConfig(projectDir) {
|
|
|
36541
36550
|
}
|
|
36542
36551
|
}
|
|
36543
36552
|
async function saveContentConfig(projectDir, config) {
|
|
36544
|
-
const configPath =
|
|
36553
|
+
const configPath = join133(projectDir, TAKUMI_CONFIG_FILE2);
|
|
36545
36554
|
const json = await readJsonSafe(configPath);
|
|
36546
36555
|
json.content = { ...json.content, ...config };
|
|
36547
36556
|
await atomicWrite3(configPath, json);
|
|
36548
36557
|
}
|
|
36549
36558
|
async function loadContentState(projectDir) {
|
|
36550
|
-
const configPath =
|
|
36559
|
+
const configPath = join133(projectDir, TAKUMI_CONFIG_FILE2);
|
|
36551
36560
|
try {
|
|
36552
36561
|
const raw = await readFile51(configPath, "utf-8");
|
|
36553
36562
|
const json = JSON.parse(raw);
|
|
@@ -36558,7 +36567,7 @@ async function loadContentState(projectDir) {
|
|
|
36558
36567
|
}
|
|
36559
36568
|
}
|
|
36560
36569
|
async function saveContentState(projectDir, state) {
|
|
36561
|
-
const configPath =
|
|
36570
|
+
const configPath = join133(projectDir, TAKUMI_CONFIG_FILE2);
|
|
36562
36571
|
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
36563
36572
|
for (const key of Object.keys(state.dailyPostCounts)) {
|
|
36564
36573
|
const dateStr = key.slice(-10);
|
|
@@ -36840,7 +36849,7 @@ var init_platform_setup_x = __esm(() => {
|
|
|
36840
36849
|
|
|
36841
36850
|
// src/commands/content/phases/setup-wizard.ts
|
|
36842
36851
|
import { existsSync as existsSync72 } from "node:fs";
|
|
36843
|
-
import { join as
|
|
36852
|
+
import { join as join134 } from "node:path";
|
|
36844
36853
|
async function runSetupWizard2(cwd2, contentLogger) {
|
|
36845
36854
|
console.log();
|
|
36846
36855
|
oe(import_picocolors40.default.bgCyan(import_picocolors40.default.white(" SK Content — Multi-Channel Content Engine ")));
|
|
@@ -36908,8 +36917,8 @@ async function showRepoSummary(cwd2) {
|
|
|
36908
36917
|
function detectBrandAssets(cwd2, contentLogger) {
|
|
36909
36918
|
const repos = discoverRepos2(cwd2);
|
|
36910
36919
|
for (const repo of repos) {
|
|
36911
|
-
const hasGuidelines = existsSync72(
|
|
36912
|
-
const hasStyles = existsSync72(
|
|
36920
|
+
const hasGuidelines = existsSync72(join134(repo.path, "docs", "brand-guidelines.md"));
|
|
36921
|
+
const hasStyles = existsSync72(join134(repo.path, "assets", "writing-styles"));
|
|
36913
36922
|
if (!hasGuidelines) {
|
|
36914
36923
|
f2.warning(`${repo.name}: No docs/brand-guidelines.md — content will use generic tone.`);
|
|
36915
36924
|
contentLogger.warn(`${repo.name}: missing docs/brand-guidelines.md`);
|
|
@@ -37051,9 +37060,9 @@ __export(exports_content_subcommands, {
|
|
|
37051
37060
|
});
|
|
37052
37061
|
import { existsSync as existsSync74, readFileSync as readFileSync19, unlinkSync as unlinkSync6 } from "node:fs";
|
|
37053
37062
|
import { homedir as homedir36 } from "node:os";
|
|
37054
|
-
import { join as
|
|
37063
|
+
import { join as join135 } from "node:path";
|
|
37055
37064
|
function isDaemonRunning() {
|
|
37056
|
-
const lockFile =
|
|
37065
|
+
const lockFile = join135(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
37057
37066
|
if (!existsSync74(lockFile))
|
|
37058
37067
|
return { running: false, pid: null };
|
|
37059
37068
|
try {
|
|
@@ -37085,7 +37094,7 @@ async function startContent(options2) {
|
|
|
37085
37094
|
await contentCommand(options2);
|
|
37086
37095
|
}
|
|
37087
37096
|
async function stopContent() {
|
|
37088
|
-
const lockFile =
|
|
37097
|
+
const lockFile = join135(LOCK_DIR, `${LOCK_NAME2}.lock`);
|
|
37089
37098
|
if (!existsSync74(lockFile)) {
|
|
37090
37099
|
logger.info("Content daemon is not running.");
|
|
37091
37100
|
return;
|
|
@@ -37124,9 +37133,9 @@ async function statusContent() {
|
|
|
37124
37133
|
} catch {}
|
|
37125
37134
|
}
|
|
37126
37135
|
async function logsContent(options2) {
|
|
37127
|
-
const logDir =
|
|
37136
|
+
const logDir = join135(homedir36(), ".sunagentkit", "logs");
|
|
37128
37137
|
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
37129
|
-
const logPath =
|
|
37138
|
+
const logPath = join135(logDir, `content-${dateStr}.log`);
|
|
37130
37139
|
if (!existsSync74(logPath)) {
|
|
37131
37140
|
logger.info("No content logs found for today.");
|
|
37132
37141
|
return;
|
|
@@ -37158,13 +37167,13 @@ var init_content_subcommands = __esm(() => {
|
|
|
37158
37167
|
init_setup_wizard();
|
|
37159
37168
|
init_state_manager();
|
|
37160
37169
|
init_content_review_commands();
|
|
37161
|
-
LOCK_DIR =
|
|
37170
|
+
LOCK_DIR = join135(homedir36(), ".sunagentkit", "locks");
|
|
37162
37171
|
});
|
|
37163
37172
|
|
|
37164
37173
|
// src/commands/content/content-command.ts
|
|
37165
37174
|
import { existsSync as existsSync75, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7, writeFileSync as writeFileSync6 } from "node:fs";
|
|
37166
37175
|
import { homedir as homedir37 } from "node:os";
|
|
37167
|
-
import { join as
|
|
37176
|
+
import { join as join136 } from "node:path";
|
|
37168
37177
|
async function contentCommand(options2) {
|
|
37169
37178
|
const cwd2 = process.cwd();
|
|
37170
37179
|
const contentLogger = new ContentLogger;
|
|
@@ -37342,8 +37351,8 @@ var init_content_command = __esm(() => {
|
|
|
37342
37351
|
init_publisher();
|
|
37343
37352
|
init_review_manager();
|
|
37344
37353
|
init_state_manager();
|
|
37345
|
-
LOCK_DIR2 =
|
|
37346
|
-
LOCK_FILE =
|
|
37354
|
+
LOCK_DIR2 = join136(homedir37(), ".sunagentkit", "locks");
|
|
37355
|
+
LOCK_FILE = join136(LOCK_DIR2, "sk-content.lock");
|
|
37347
37356
|
});
|
|
37348
37357
|
|
|
37349
37358
|
// src/commands/content/index.ts
|
|
@@ -49278,28 +49287,32 @@ var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
|
49278
49287
|
var import_picomatch = __toESM(require_picomatch2(), 1);
|
|
49279
49288
|
function findFileInMetadata(metadata, path3) {
|
|
49280
49289
|
if (!metadata)
|
|
49281
|
-
return null;
|
|
49290
|
+
return { tracked: null, ownerKit: null };
|
|
49282
49291
|
if (metadata.kits) {
|
|
49283
|
-
for (const kitMeta of Object.
|
|
49284
|
-
if (kitMeta?.files)
|
|
49285
|
-
|
|
49286
|
-
|
|
49287
|
-
|
|
49288
|
-
|
|
49292
|
+
for (const [kitName, kitMeta] of Object.entries(metadata.kits)) {
|
|
49293
|
+
if (!kitMeta?.files)
|
|
49294
|
+
continue;
|
|
49295
|
+
const found = kitMeta.files.find((f3) => f3.path === path3);
|
|
49296
|
+
if (found)
|
|
49297
|
+
return { tracked: found, ownerKit: kitName };
|
|
49289
49298
|
}
|
|
49290
49299
|
}
|
|
49291
49300
|
if (metadata.files) {
|
|
49292
49301
|
const found = metadata.files.find((f3) => f3.path === path3);
|
|
49293
49302
|
if (found)
|
|
49294
|
-
return found;
|
|
49303
|
+
return { tracked: found, ownerKit: null };
|
|
49295
49304
|
}
|
|
49296
|
-
return null;
|
|
49305
|
+
return { tracked: null, ownerKit: null };
|
|
49297
49306
|
}
|
|
49298
|
-
function shouldDeletePath(path3, metadata) {
|
|
49299
|
-
const tracked = findFileInMetadata(metadata, path3);
|
|
49307
|
+
function shouldDeletePath(path3, metadata, installingKit) {
|
|
49308
|
+
const { tracked, ownerKit } = findFileInMetadata(metadata, path3);
|
|
49300
49309
|
if (!tracked)
|
|
49301
49310
|
return true;
|
|
49302
|
-
|
|
49311
|
+
if (tracked.ownership === "user")
|
|
49312
|
+
return false;
|
|
49313
|
+
if (installingKit && ownerKit && ownerKit !== installingKit)
|
|
49314
|
+
return false;
|
|
49315
|
+
return true;
|
|
49303
49316
|
}
|
|
49304
49317
|
function collectFilesRecursively(dir, baseDir) {
|
|
49305
49318
|
const results = [];
|
|
@@ -49422,7 +49435,7 @@ async function updateMetadataAfterDeletion(claudeDir, deletedPaths) {
|
|
|
49422
49435
|
logger.debug("Failed to write updated metadata.json");
|
|
49423
49436
|
}
|
|
49424
49437
|
}
|
|
49425
|
-
async function handleDeletions(sourceMetadata, claudeDir) {
|
|
49438
|
+
async function handleDeletions(sourceMetadata, claudeDir, installingKit) {
|
|
49426
49439
|
const deletionPatterns = sourceMetadata.deletions || [];
|
|
49427
49440
|
if (deletionPatterns.length === 0) {
|
|
49428
49441
|
return { deletedPaths: [], preservedPaths: [], errors: [] };
|
|
@@ -49439,9 +49452,9 @@ async function handleDeletions(sourceMetadata, claudeDir) {
|
|
|
49439
49452
|
result.errors.push(path3);
|
|
49440
49453
|
continue;
|
|
49441
49454
|
}
|
|
49442
|
-
if (!shouldDeletePath(path3, userMetadata)) {
|
|
49455
|
+
if (!shouldDeletePath(path3, userMetadata, installingKit)) {
|
|
49443
49456
|
result.preservedPaths.push(path3);
|
|
49444
|
-
logger.verbose(`Preserved user
|
|
49457
|
+
logger.verbose(`Preserved file (cross-kit or user-owned): ${path3}`);
|
|
49445
49458
|
continue;
|
|
49446
49459
|
}
|
|
49447
49460
|
if (existsSync13(fullPath)) {
|
|
@@ -52510,14 +52523,17 @@ async function writeManifest(providerRoot, kitName, version3, scope, kitType, tr
|
|
|
52510
52523
|
logger.debug(`Could not read existing metadata: ${error}`);
|
|
52511
52524
|
}
|
|
52512
52525
|
}
|
|
52526
|
+
const existingKits = existingMetadata.kits || {};
|
|
52527
|
+
const otherKitsExist = Object.keys(existingKits).some((k2) => k2 !== kit);
|
|
52513
52528
|
const installedAt = new Date().toISOString();
|
|
52529
|
+
const existingKitMeta = existingKits[kit];
|
|
52514
52530
|
const kitMetadata = {
|
|
52531
|
+
...existingKitMeta ?? {},
|
|
52515
52532
|
version: version3,
|
|
52516
52533
|
installedAt,
|
|
52534
|
+
installState: "complete",
|
|
52517
52535
|
files: trackedFiles.length > 0 ? trackedFiles : undefined
|
|
52518
52536
|
};
|
|
52519
|
-
const existingKits = existingMetadata.kits || {};
|
|
52520
|
-
const otherKitsExist = Object.keys(existingKits).some((k2) => k2 !== kit);
|
|
52521
52537
|
const metadata = {
|
|
52522
52538
|
kits: {
|
|
52523
52539
|
...existingKits,
|
|
@@ -52548,6 +52564,69 @@ async function writeManifest(providerRoot, kitName, version3, scope, kitType, tr
|
|
|
52548
52564
|
}
|
|
52549
52565
|
}
|
|
52550
52566
|
}
|
|
52567
|
+
async function writeKitPending(providerRoot, kit, version3, scope) {
|
|
52568
|
+
const metadataPath = join28(providerRoot, "metadata.json");
|
|
52569
|
+
await import_fs_extra10.ensureFile(metadataPath);
|
|
52570
|
+
let release = null;
|
|
52571
|
+
try {
|
|
52572
|
+
release = await import_proper_lockfile4.lock(metadataPath, {
|
|
52573
|
+
retries: { retries: 5, minTimeout: 100, maxTimeout: 1000 },
|
|
52574
|
+
stale: 60000
|
|
52575
|
+
});
|
|
52576
|
+
logger.debug(`Acquired lock on ${metadataPath} for pending-state write`);
|
|
52577
|
+
const migrationResult = await migrateToMultiKit(providerRoot);
|
|
52578
|
+
if (!migrationResult.success) {
|
|
52579
|
+
logger.warning(`Metadata migration warning: ${migrationResult.error}`);
|
|
52580
|
+
}
|
|
52581
|
+
let existingMetadata = { kits: {} };
|
|
52582
|
+
if (await import_fs_extra10.pathExists(metadataPath)) {
|
|
52583
|
+
try {
|
|
52584
|
+
const content = await import_fs_extra10.readFile(metadataPath, "utf-8");
|
|
52585
|
+
const parsed = JSON.parse(content);
|
|
52586
|
+
if (parsed && typeof parsed === "object" && Object.keys(parsed).length > 0) {
|
|
52587
|
+
existingMetadata = parsed;
|
|
52588
|
+
}
|
|
52589
|
+
} catch (error) {
|
|
52590
|
+
logger.debug(`Could not read existing metadata: ${error}`);
|
|
52591
|
+
}
|
|
52592
|
+
}
|
|
52593
|
+
const existingKits = existingMetadata.kits || {};
|
|
52594
|
+
const pendingMetadata = {
|
|
52595
|
+
version: version3,
|
|
52596
|
+
installedAt: new Date().toISOString(),
|
|
52597
|
+
installState: "pending",
|
|
52598
|
+
files: []
|
|
52599
|
+
};
|
|
52600
|
+
const metadata = {
|
|
52601
|
+
...existingMetadata,
|
|
52602
|
+
kits: {
|
|
52603
|
+
...existingKits,
|
|
52604
|
+
[kit]: pendingMetadata
|
|
52605
|
+
},
|
|
52606
|
+
scope
|
|
52607
|
+
};
|
|
52608
|
+
const validated = MetadataSchema.parse(metadata);
|
|
52609
|
+
await import_fs_extra10.writeFile(metadataPath, JSON.stringify(validated, null, 2), "utf-8");
|
|
52610
|
+
logger.debug(`Wrote pending-state entry for kit "${kit}"`);
|
|
52611
|
+
} finally {
|
|
52612
|
+
if (release) {
|
|
52613
|
+
await release();
|
|
52614
|
+
logger.debug(`Released lock on ${metadataPath}`);
|
|
52615
|
+
}
|
|
52616
|
+
}
|
|
52617
|
+
}
|
|
52618
|
+
async function findPendingKits(providerRoot) {
|
|
52619
|
+
const metadata = await readManifest(providerRoot);
|
|
52620
|
+
if (!metadata?.kits)
|
|
52621
|
+
return [];
|
|
52622
|
+
const pending = [];
|
|
52623
|
+
for (const [kitName, kitMeta] of Object.entries(metadata.kits)) {
|
|
52624
|
+
if (kitMeta?.installState === "pending") {
|
|
52625
|
+
pending.push(kitName);
|
|
52626
|
+
}
|
|
52627
|
+
}
|
|
52628
|
+
return pending;
|
|
52629
|
+
}
|
|
52551
52630
|
async function removeKitFromManifest(providerRoot, kit) {
|
|
52552
52631
|
const metadataPath = join28(providerRoot, "metadata.json");
|
|
52553
52632
|
if (!await import_fs_extra10.pathExists(metadataPath))
|
|
@@ -52749,6 +52828,12 @@ class ManifestWriter {
|
|
|
52749
52828
|
async writeManifest(providerRoot, kitName, version3, scope, kitType) {
|
|
52750
52829
|
return writeManifest(providerRoot, kitName, version3, scope, kitType, this.getTrackedFiles(), this.getUserConfigFiles());
|
|
52751
52830
|
}
|
|
52831
|
+
static async writeKitPending(providerRoot, kit, version3, scope) {
|
|
52832
|
+
return writeKitPending(providerRoot, kit, version3, scope);
|
|
52833
|
+
}
|
|
52834
|
+
static async findPendingKits(providerRoot) {
|
|
52835
|
+
return findPendingKits(providerRoot);
|
|
52836
|
+
}
|
|
52752
52837
|
static async readManifest(providerRoot) {
|
|
52753
52838
|
return readManifest(providerRoot);
|
|
52754
52839
|
}
|
|
@@ -53716,7 +53801,7 @@ async function handleMerge(ctx) {
|
|
|
53716
53801
|
}
|
|
53717
53802
|
try {
|
|
53718
53803
|
if (sourceMetadata?.deletions && sourceMetadata.deletions.length > 0) {
|
|
53719
|
-
const deletionResult = await handleDeletions(sourceMetadata, ctx.claudeDir);
|
|
53804
|
+
const deletionResult = await handleDeletions(sourceMetadata, ctx.claudeDir, ctx.kitType);
|
|
53720
53805
|
if (deletionResult.deletedPaths.length > 0) {
|
|
53721
53806
|
logger.info(`Removed ${deletionResult.deletedPaths.length} deprecated file(s)`);
|
|
53722
53807
|
for (const path4 of deletionResult.deletedPaths) {
|
|
@@ -63269,6 +63354,9 @@ async function doctorCommand(options2 = {}) {
|
|
|
63269
63354
|
}
|
|
63270
63355
|
}
|
|
63271
63356
|
|
|
63357
|
+
// src/commands/init/init-command.ts
|
|
63358
|
+
import { join as join102 } from "node:path";
|
|
63359
|
+
|
|
63272
63360
|
// src/domains/sync/config-version-checker.ts
|
|
63273
63361
|
init_auth_client();
|
|
63274
63362
|
import { mkdir as mkdir22, readFile as readFile38, unlink as unlink12, writeFile as writeFile29 } from "node:fs/promises";
|
|
@@ -64138,6 +64226,7 @@ async function promptAgentSelection(supported) {
|
|
|
64138
64226
|
return selected;
|
|
64139
64227
|
}
|
|
64140
64228
|
// src/domains/ui/prompts/kit-prompts.ts
|
|
64229
|
+
init_logger();
|
|
64141
64230
|
init_types2();
|
|
64142
64231
|
async function selectKit(defaultKit, accessibleKits) {
|
|
64143
64232
|
const kits = accessibleKits ?? Object.keys(AVAILABLE_KITS);
|
|
@@ -64155,6 +64244,39 @@ async function selectKit(defaultKit, accessibleKits) {
|
|
|
64155
64244
|
}
|
|
64156
64245
|
return kit;
|
|
64157
64246
|
}
|
|
64247
|
+
async function selectKits(accessibleKits, defaults2) {
|
|
64248
|
+
const kits = accessibleKits ?? Object.keys(AVAILABLE_KITS);
|
|
64249
|
+
const options2 = kits.map((key) => {
|
|
64250
|
+
const isBase = key === BASE_KIT;
|
|
64251
|
+
const cfg = AVAILABLE_KITS[key];
|
|
64252
|
+
return {
|
|
64253
|
+
value: key,
|
|
64254
|
+
label: isBase ? `${cfg.name} (base, required)` : cfg.name,
|
|
64255
|
+
hint: cfg.description
|
|
64256
|
+
};
|
|
64257
|
+
});
|
|
64258
|
+
const initialValues = defaults2 && defaults2.length > 0 ? Array.from(new Set([BASE_KIT, ...defaults2])).filter((k2) => kits.includes(k2)) : kits;
|
|
64259
|
+
const selected = await ae({
|
|
64260
|
+
message: "Select kit(s) to install:",
|
|
64261
|
+
options: options2,
|
|
64262
|
+
initialValues,
|
|
64263
|
+
required: true
|
|
64264
|
+
});
|
|
64265
|
+
if (lD(selected)) {
|
|
64266
|
+
throw new Error("Kit selection cancelled");
|
|
64267
|
+
}
|
|
64268
|
+
const result = selected;
|
|
64269
|
+
if (!result.includes(BASE_KIT) && kits.includes(BASE_KIT)) {
|
|
64270
|
+
logger.info(`"${AVAILABLE_KITS[BASE_KIT].name}" is the base kit and was added back automatically.`);
|
|
64271
|
+
result.unshift(BASE_KIT);
|
|
64272
|
+
}
|
|
64273
|
+
const idx = result.indexOf(BASE_KIT);
|
|
64274
|
+
if (idx > 0) {
|
|
64275
|
+
result.splice(idx, 1);
|
|
64276
|
+
result.unshift(BASE_KIT);
|
|
64277
|
+
}
|
|
64278
|
+
return result;
|
|
64279
|
+
}
|
|
64158
64280
|
async function getDirectory(defaultDir = ".") {
|
|
64159
64281
|
const dir = await te({
|
|
64160
64282
|
message: "Enter target directory:",
|
|
@@ -64818,6 +64940,9 @@ class PromptsManager {
|
|
|
64818
64940
|
async selectKit(defaultKit, accessibleKits) {
|
|
64819
64941
|
return selectKit(defaultKit, accessibleKits);
|
|
64820
64942
|
}
|
|
64943
|
+
async selectKits(accessibleKits, defaults2) {
|
|
64944
|
+
return selectKits(accessibleKits, defaults2);
|
|
64945
|
+
}
|
|
64821
64946
|
async selectVersion(versions, defaultVersion) {
|
|
64822
64947
|
return selectVersion(versions, defaultVersion);
|
|
64823
64948
|
}
|
|
@@ -64959,6 +65084,8 @@ class PromptsManager {
|
|
|
64959
65084
|
|
|
64960
65085
|
// src/commands/init/init-command.ts
|
|
64961
65086
|
init_logger();
|
|
65087
|
+
init_path_resolver();
|
|
65088
|
+
init_types2();
|
|
64962
65089
|
|
|
64963
65090
|
// src/commands/init/context-factory.ts
|
|
64964
65091
|
function createInitContext(rawOptions, prompts) {
|
|
@@ -69636,6 +69763,25 @@ async function handleDownload(ctx) {
|
|
|
69636
69763
|
// src/commands/init/phases/options-resolver.ts
|
|
69637
69764
|
init_logger();
|
|
69638
69765
|
init_types2();
|
|
69766
|
+
function parseKitFlag(raw) {
|
|
69767
|
+
const tokens = raw.split(",").map((s3) => s3.trim()).filter((s3) => s3.length > 0);
|
|
69768
|
+
if (tokens.length === 0)
|
|
69769
|
+
return null;
|
|
69770
|
+
if (tokens.length === 1 && tokens[0] === "all") {
|
|
69771
|
+
return Object.keys(AVAILABLE_KITS);
|
|
69772
|
+
}
|
|
69773
|
+
const seen = new Set;
|
|
69774
|
+
const out = [];
|
|
69775
|
+
for (const tok of tokens) {
|
|
69776
|
+
if (!isValidKitType(tok))
|
|
69777
|
+
return null;
|
|
69778
|
+
if (!seen.has(tok)) {
|
|
69779
|
+
seen.add(tok);
|
|
69780
|
+
out.push(tok);
|
|
69781
|
+
}
|
|
69782
|
+
}
|
|
69783
|
+
return out;
|
|
69784
|
+
}
|
|
69639
69785
|
async function resolveOptions(ctx) {
|
|
69640
69786
|
const explicitDir = ctx.rawOptions.dir !== undefined;
|
|
69641
69787
|
const explicitAgents = Array.isArray(ctx.rawOptions.agents) && ctx.rawOptions.agents.length > 0;
|
|
@@ -69725,6 +69871,28 @@ Example: takumi init --use-git --release v2.1.0`);
|
|
|
69725
69871
|
Choose one approach.`);
|
|
69726
69872
|
}
|
|
69727
69873
|
const isNonInteractive2 = validOptions.yes || !process.stdin.isTTY || process.env.CI === "true" || process.env.NON_INTERACTIVE === "true";
|
|
69874
|
+
if (validOptions.kit) {
|
|
69875
|
+
const parsed2 = parseKitFlag(validOptions.kit);
|
|
69876
|
+
if (!parsed2 || parsed2.length === 0) {
|
|
69877
|
+
throw new Error(`Invalid --kit value: "${validOptions.kit}".
|
|
69878
|
+
Valid kits: ${Object.keys(AVAILABLE_KITS).join(", ")}`);
|
|
69879
|
+
}
|
|
69880
|
+
if (!parsed2.includes(BASE_KIT)) {
|
|
69881
|
+
if (isNonInteractive2) {
|
|
69882
|
+
throw new Error(`The "${BASE_KIT}" kit is required when installing additional kits.
|
|
69883
|
+
Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --kit ")}`);
|
|
69884
|
+
}
|
|
69885
|
+
logger.info(`"${BASE_KIT}" is the required base kit — adding it automatically.`);
|
|
69886
|
+
parsed2.unshift(BASE_KIT);
|
|
69887
|
+
} else {
|
|
69888
|
+
const idx = parsed2.indexOf(BASE_KIT);
|
|
69889
|
+
if (idx > 0) {
|
|
69890
|
+
parsed2.splice(idx, 1);
|
|
69891
|
+
parsed2.unshift(BASE_KIT);
|
|
69892
|
+
}
|
|
69893
|
+
}
|
|
69894
|
+
validOptions.selectedKits = parsed2;
|
|
69895
|
+
}
|
|
69728
69896
|
if (validOptions.yes) {
|
|
69729
69897
|
logger.info("Running in non-interactive mode (--yes flag)");
|
|
69730
69898
|
}
|
|
@@ -70162,48 +70330,58 @@ async function handleSelection(ctx) {
|
|
|
70162
70330
|
return { ...ctx, cancelled: true };
|
|
70163
70331
|
}
|
|
70164
70332
|
}
|
|
70165
|
-
let
|
|
70166
|
-
|
|
70167
|
-
if (kitOption) {
|
|
70333
|
+
let selectedKits = ctx.options.selectedKits;
|
|
70334
|
+
if (!selectedKits || selectedKits.length === 0) {
|
|
70168
70335
|
const allKitTypes = Object.keys(AVAILABLE_KITS);
|
|
70169
|
-
|
|
70170
|
-
|
|
70171
|
-
if (
|
|
70172
|
-
|
|
70173
|
-
|
|
70174
|
-
}
|
|
70175
|
-
kitType = kitsToInstall[0];
|
|
70176
|
-
logger.info(`Using kit: ${AVAILABLE_KITS[kitType].name}`);
|
|
70177
|
-
} else {
|
|
70178
|
-
if (!isValidKitType(kitOption)) {
|
|
70336
|
+
const kitOption = ctx.options.kit || config.defaults?.kit;
|
|
70337
|
+
if (kitOption) {
|
|
70338
|
+
if (kitOption === "all") {
|
|
70339
|
+
selectedKits = accessibleKits ?? allKitTypes;
|
|
70340
|
+
} else if (!isValidKitType(kitOption)) {
|
|
70179
70341
|
logger.error(`Invalid kit: ${kitOption}`);
|
|
70180
70342
|
logger.info(`Valid kits: ${allKitTypes.join(", ")}`);
|
|
70181
70343
|
return { ...ctx, cancelled: true };
|
|
70344
|
+
} else {
|
|
70345
|
+
selectedKits = [kitOption];
|
|
70182
70346
|
}
|
|
70183
|
-
|
|
70184
|
-
|
|
70185
|
-
|
|
70186
|
-
|
|
70187
|
-
|
|
70347
|
+
}
|
|
70348
|
+
if (!selectedKits || selectedKits.length === 0) {
|
|
70349
|
+
if (ctx.isNonInteractive) {
|
|
70350
|
+
if (!accessibleKits || accessibleKits.length === 0) {
|
|
70351
|
+
throw new Error("Kit must be specified via --kit flag in non-interactive mode (no accessible kits detected)");
|
|
70352
|
+
}
|
|
70353
|
+
selectedKits = [accessibleKits[0]];
|
|
70354
|
+
logger.info(`Auto-selected: ${AVAILABLE_KITS[selectedKits[0]].name}`);
|
|
70355
|
+
} else if (accessibleKits?.length === 1) {
|
|
70356
|
+
selectedKits = [accessibleKits[0]];
|
|
70357
|
+
logger.info(`Using ${AVAILABLE_KITS[selectedKits[0]].name} (only accessible kit)`);
|
|
70358
|
+
} else {
|
|
70359
|
+
selectedKits = await ctx.prompts.selectKits(accessibleKits);
|
|
70188
70360
|
}
|
|
70189
70361
|
}
|
|
70190
70362
|
}
|
|
70191
|
-
if (
|
|
70192
|
-
|
|
70193
|
-
|
|
70194
|
-
|
|
70195
|
-
|
|
70196
|
-
|
|
70197
|
-
logger.info(`Auto-selected: ${AVAILABLE_KITS[kitType].name}`);
|
|
70198
|
-
} else if (accessibleKits?.length === 1) {
|
|
70199
|
-
kitType = accessibleKits[0];
|
|
70200
|
-
logger.info(`Using ${AVAILABLE_KITS[kitType].name} (only accessible kit)`);
|
|
70201
|
-
} else {
|
|
70202
|
-
kitType = await ctx.prompts.selectKit(undefined, accessibleKits);
|
|
70363
|
+
if (accessibleKits) {
|
|
70364
|
+
const inaccessible = selectedKits.filter((k3) => !accessibleKits.includes(k3));
|
|
70365
|
+
if (inaccessible.length > 0) {
|
|
70366
|
+
logger.error(`No access to: ${inaccessible.map((k3) => AVAILABLE_KITS[k3].name).join(", ")}`);
|
|
70367
|
+
logger.info("Request access from your team lead or check your GitHub invitation");
|
|
70368
|
+
return { ...ctx, cancelled: true };
|
|
70203
70369
|
}
|
|
70204
70370
|
}
|
|
70371
|
+
if (selectedKits.includes(BASE_KIT)) {
|
|
70372
|
+
const idx = selectedKits.indexOf(BASE_KIT);
|
|
70373
|
+
if (idx > 0) {
|
|
70374
|
+
selectedKits.splice(idx, 1);
|
|
70375
|
+
selectedKits.unshift(BASE_KIT);
|
|
70376
|
+
}
|
|
70377
|
+
}
|
|
70378
|
+
const kitType = selectedKits[0];
|
|
70205
70379
|
const kit = AVAILABLE_KITS[kitType];
|
|
70206
|
-
|
|
70380
|
+
if (selectedKits.length > 1) {
|
|
70381
|
+
logger.info(`Selected kits: ${selectedKits.map((k3) => AVAILABLE_KITS[k3].name).join(", ")} (installed in order)`);
|
|
70382
|
+
} else {
|
|
70383
|
+
logger.info(`Selected kit: ${kit.name}`);
|
|
70384
|
+
}
|
|
70207
70385
|
let targetDir;
|
|
70208
70386
|
if (ctx.explicitDir) {
|
|
70209
70387
|
targetDir = ctx.options.dir;
|
|
@@ -70412,12 +70590,30 @@ async function handleSelection(ctx) {
|
|
|
70412
70590
|
...ctx,
|
|
70413
70591
|
kit,
|
|
70414
70592
|
kitType,
|
|
70593
|
+
selectedKits,
|
|
70415
70594
|
resolvedDir,
|
|
70416
70595
|
release,
|
|
70417
70596
|
selectedVersion,
|
|
70418
70597
|
accessibleKits
|
|
70419
70598
|
};
|
|
70420
70599
|
}
|
|
70600
|
+
async function resolveReleaseForKit(ctx, kitType) {
|
|
70601
|
+
const isOfflineMode = !!(ctx.options.kitPath || ctx.options.archive);
|
|
70602
|
+
if (isOfflineMode)
|
|
70603
|
+
return;
|
|
70604
|
+
const kit = AVAILABLE_KITS[kitType];
|
|
70605
|
+
if (ctx.options.useGit) {
|
|
70606
|
+
throw new Error(`--use-git is not supported for multi-kit installs (secondary kit: ${kitType}). Run kits individually.`);
|
|
70607
|
+
}
|
|
70608
|
+
if (ctx.options.useGh) {
|
|
70609
|
+
const github = new GitHubClient;
|
|
70610
|
+
const release = await github.getLatestRelease(kit, ctx.options.beta);
|
|
70611
|
+
return release;
|
|
70612
|
+
}
|
|
70613
|
+
const worker = new WorkerSource(getServerUrl(), kitType);
|
|
70614
|
+
const entry = await worker.fetchLatest(ctx.options.beta);
|
|
70615
|
+
return releaseEntryToGitHubRelease(entry, kit);
|
|
70616
|
+
}
|
|
70421
70617
|
function resolveGlobalTargetDir(targetAgents) {
|
|
70422
70618
|
const primary = targetAgents[0];
|
|
70423
70619
|
if (primary) {
|
|
@@ -70458,7 +70654,7 @@ async function handleSync(ctx) {
|
|
|
70458
70654
|
Run 'takumi init' to update.`, "Legacy Installation");
|
|
70459
70655
|
return { ...ctx, cancelled: true };
|
|
70460
70656
|
}
|
|
70461
|
-
let kitType = ctx.options.
|
|
70657
|
+
let kitType = ctx.options.selectedKits?.[0];
|
|
70462
70658
|
if (!kitType) {
|
|
70463
70659
|
const engineerMeta = await readKitManifest(claudeDir, "engineer");
|
|
70464
70660
|
if (engineerMeta) {
|
|
@@ -71291,23 +71487,91 @@ async function executeInit(options2, prompts) {
|
|
|
71291
71487
|
ctx = await handleSelection(ctx);
|
|
71292
71488
|
if (ctx.cancelled)
|
|
71293
71489
|
return;
|
|
71294
|
-
ctx
|
|
71295
|
-
|
|
71490
|
+
if (ctx.resolvedDir && !isSyncMode) {
|
|
71491
|
+
try {
|
|
71492
|
+
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
71493
|
+
const claudeDir = prefix ? join102(ctx.resolvedDir, prefix) : ctx.resolvedDir;
|
|
71494
|
+
const pending = await ManifestWriter.findPendingKits(claudeDir);
|
|
71495
|
+
if (pending.length > 0) {
|
|
71496
|
+
logger.warning(`Previous install was interrupted for kit(s): ${pending.join(", ")}. Re-running install will overwrite the pending entry.`);
|
|
71497
|
+
}
|
|
71498
|
+
} catch (error) {
|
|
71499
|
+
logger.debug(`Pending-kit check skipped: ${error}`);
|
|
71500
|
+
}
|
|
71501
|
+
}
|
|
71502
|
+
const selectedKits = ctx.selectedKits && ctx.selectedKits.length > 0 ? ctx.selectedKits : ctx.kitType ? [ctx.kitType] : [];
|
|
71503
|
+
if (selectedKits.length === 0) {
|
|
71504
|
+
logger.error("No kits resolved for installation");
|
|
71296
71505
|
return;
|
|
71297
|
-
if (!isSyncMode) {
|
|
71298
|
-
ctx = await handleTransforms(ctx);
|
|
71299
|
-
if (ctx.cancelled)
|
|
71300
|
-
return;
|
|
71301
71506
|
}
|
|
71302
|
-
|
|
71303
|
-
|
|
71304
|
-
|
|
71507
|
+
const aggregatedResults = [];
|
|
71508
|
+
let lastCtx = ctx;
|
|
71509
|
+
for (let i = 0;i < selectedKits.length; i++) {
|
|
71510
|
+
const currentKit = selectedKits[i];
|
|
71511
|
+
if (i > 0) {
|
|
71512
|
+
logger.info(`Installing kit ${i + 1}/${selectedKits.length}: ${AVAILABLE_KITS[currentKit].name}`);
|
|
71513
|
+
if (lastCtx.options.release) {
|
|
71514
|
+
logger.info(`Secondary kit "${currentKit}" uses latest channel — --release applies only to the primary kit.`);
|
|
71515
|
+
}
|
|
71516
|
+
let nextRelease;
|
|
71517
|
+
try {
|
|
71518
|
+
nextRelease = await resolveReleaseForKit(lastCtx, currentKit);
|
|
71519
|
+
} catch (error) {
|
|
71520
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
71521
|
+
logger.error(`Failed to resolve release for ${currentKit}: ${message}`);
|
|
71522
|
+
aggregatedResults.push({
|
|
71523
|
+
provider: targetAgents[0] ?? "claude-code",
|
|
71524
|
+
success: false,
|
|
71525
|
+
cancelled: false,
|
|
71526
|
+
installedFiles: [],
|
|
71527
|
+
error: `Release fetch failed for kit "${currentKit}": ${message}`
|
|
71528
|
+
});
|
|
71529
|
+
continue;
|
|
71530
|
+
}
|
|
71531
|
+
lastCtx = {
|
|
71532
|
+
...lastCtx,
|
|
71533
|
+
kit: AVAILABLE_KITS[currentKit],
|
|
71534
|
+
kitType: currentKit,
|
|
71535
|
+
release: nextRelease,
|
|
71536
|
+
selectedVersion: nextRelease?.tag_name,
|
|
71537
|
+
tempDir: undefined,
|
|
71538
|
+
extractDir: undefined,
|
|
71539
|
+
archivePath: undefined
|
|
71540
|
+
};
|
|
71541
|
+
} else if (selectedKits.length > 1) {
|
|
71542
|
+
logger.info(`Installing kit ${i + 1}/${selectedKits.length}: ${AVAILABLE_KITS[currentKit].name}`);
|
|
71543
|
+
}
|
|
71544
|
+
if (lastCtx.resolvedDir && lastCtx.release && !isSyncMode) {
|
|
71545
|
+
try {
|
|
71546
|
+
const prefix = PathResolver.getPathPrefix(lastCtx.options.global);
|
|
71547
|
+
const claudeDir = prefix ? join102(lastCtx.resolvedDir, prefix) : lastCtx.resolvedDir;
|
|
71548
|
+
const scope = lastCtx.options.global ? "global" : "local";
|
|
71549
|
+
await ManifestWriter.writeKitPending(claudeDir, currentKit, lastCtx.release.tag_name, scope);
|
|
71550
|
+
} catch (error) {
|
|
71551
|
+
logger.debug(`writeKitPending skipped: ${error}`);
|
|
71552
|
+
}
|
|
71553
|
+
}
|
|
71554
|
+
lastCtx = await handleDownload(lastCtx);
|
|
71555
|
+
if (lastCtx.cancelled)
|
|
71556
|
+
return;
|
|
71557
|
+
if (!isSyncMode) {
|
|
71558
|
+
lastCtx = await handleTransforms(lastCtx);
|
|
71559
|
+
if (lastCtx.cancelled)
|
|
71560
|
+
return;
|
|
71561
|
+
}
|
|
71562
|
+
if (isSyncMode) {
|
|
71563
|
+
lastCtx = await executeSyncMerge(lastCtx);
|
|
71564
|
+
if (lastCtx.cancelled)
|
|
71565
|
+
return;
|
|
71566
|
+
}
|
|
71567
|
+
const kitResults = await dispatchInstallers(lastCtx, targetAgents);
|
|
71568
|
+
aggregatedResults.push(...kitResults);
|
|
71569
|
+
if (kitResults.some((r2) => r2.cancelled))
|
|
71305
71570
|
return;
|
|
71306
71571
|
}
|
|
71307
|
-
|
|
71572
|
+
ctx = lastCtx;
|
|
71573
|
+
const results = aggregatedResults;
|
|
71308
71574
|
ctx.installerResults = results;
|
|
71309
|
-
if (results.some((r2) => r2.cancelled))
|
|
71310
|
-
return;
|
|
71311
71575
|
if (targetAgents.length > 1) {
|
|
71312
71576
|
displayMultiInstallerSummary(results);
|
|
71313
71577
|
}
|
|
@@ -71368,7 +71632,7 @@ async function initCommand(options2) {
|
|
|
71368
71632
|
import { existsSync as existsSync47 } from "node:fs";
|
|
71369
71633
|
import { readFile as readFile45, rm as rm13, unlink as unlink15 } from "node:fs/promises";
|
|
71370
71634
|
import { homedir as homedir25 } from "node:os";
|
|
71371
|
-
import { basename as basename12, join as
|
|
71635
|
+
import { basename as basename12, join as join103, resolve as resolve26 } from "node:path";
|
|
71372
71636
|
init_dist2();
|
|
71373
71637
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
71374
71638
|
init_logger();
|
|
@@ -71850,7 +72114,7 @@ async function executeDeleteAction(action, options2) {
|
|
|
71850
72114
|
async function processMetadataDeletions(skillSourcePath, installGlobally) {
|
|
71851
72115
|
if (!skillSourcePath)
|
|
71852
72116
|
return;
|
|
71853
|
-
const sourceMetadataPath =
|
|
72117
|
+
const sourceMetadataPath = join103(resolve26(skillSourcePath, ".."), "metadata.json");
|
|
71854
72118
|
if (!existsSync47(sourceMetadataPath))
|
|
71855
72119
|
return;
|
|
71856
72120
|
let sourceMetadata;
|
|
@@ -71863,11 +72127,11 @@ async function processMetadataDeletions(skillSourcePath, installGlobally) {
|
|
|
71863
72127
|
}
|
|
71864
72128
|
if (!sourceMetadata.deletions || sourceMetadata.deletions.length === 0)
|
|
71865
72129
|
return;
|
|
71866
|
-
const claudeDir = installGlobally ?
|
|
72130
|
+
const claudeDir = installGlobally ? join103(homedir25(), ".claude") : join103(process.cwd(), ".claude");
|
|
71867
72131
|
if (!existsSync47(claudeDir))
|
|
71868
72132
|
return;
|
|
71869
72133
|
try {
|
|
71870
|
-
const result = await handleDeletions(sourceMetadata, claudeDir);
|
|
72134
|
+
const result = await handleDeletions(sourceMetadata, claudeDir, undefined);
|
|
71871
72135
|
if (result.deletedPaths.length > 0) {
|
|
71872
72136
|
logger.verbose(`[migrate] Cleaned up ${result.deletedPaths.length} deprecated path(s): ${result.deletedPaths.join(", ")}`);
|
|
71873
72137
|
}
|
|
@@ -72011,8 +72275,8 @@ async function migrateCommand(options2) {
|
|
|
72011
72275
|
selectedProviders = Array.from(new Set(selectedProviders));
|
|
72012
72276
|
let installGlobally = options2.global ?? false;
|
|
72013
72277
|
if (options2.global === undefined && !options2.yes) {
|
|
72014
|
-
const projectTarget =
|
|
72015
|
-
const globalTarget =
|
|
72278
|
+
const projectTarget = join103(process.cwd(), ".claude");
|
|
72279
|
+
const globalTarget = join103(homedir25(), ".claude");
|
|
72016
72280
|
const scopeChoice = await ie({
|
|
72017
72281
|
message: "Installation scope",
|
|
72018
72282
|
options: [
|
|
@@ -72064,7 +72328,7 @@ async function migrateCommand(options2) {
|
|
|
72064
72328
|
}
|
|
72065
72329
|
const providerNames = selectedProviders.map((prov) => import_picocolors27.default.cyan(providers[prov].displayName)).join(", ");
|
|
72066
72330
|
f2.message(` Providers: ${providerNames}`);
|
|
72067
|
-
const targetDir = installGlobally ?
|
|
72331
|
+
const targetDir = installGlobally ? join103(homedir25(), ".claude") : join103(process.cwd(), ".claude");
|
|
72068
72332
|
f2.message(` Scope: ${installGlobally ? "Global" : "Project"} ${import_picocolors27.default.dim(`-> ${targetDir}`)}`);
|
|
72069
72333
|
const cmdProviders = getProvidersSupporting("commands");
|
|
72070
72334
|
const unsupportedCmd = selectedProviders.filter((pv) => !cmdProviders.includes(pv));
|
|
@@ -72574,7 +72838,7 @@ async function handleDirectorySetup(ctx) {
|
|
|
72574
72838
|
};
|
|
72575
72839
|
}
|
|
72576
72840
|
// src/commands/new/phases/project-creation.ts
|
|
72577
|
-
import { join as
|
|
72841
|
+
import { join as join104 } from "node:path";
|
|
72578
72842
|
init_github_client();
|
|
72579
72843
|
init_logger();
|
|
72580
72844
|
init_output_manager();
|
|
@@ -72728,7 +72992,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
|
|
|
72728
72992
|
output.section("Installing");
|
|
72729
72993
|
logger.verbose("Installation target", { directory: resolvedDir });
|
|
72730
72994
|
const merger = new FileMerger;
|
|
72731
|
-
const claudeDir =
|
|
72995
|
+
const claudeDir = join104(resolvedDir, ".claude");
|
|
72732
72996
|
merger.setMultiKitContext(claudeDir, kit);
|
|
72733
72997
|
if (validOptions.exclude && validOptions.exclude.length > 0) {
|
|
72734
72998
|
merger.addIgnorePatterns(validOptions.exclude);
|
|
@@ -72781,10 +73045,10 @@ async function handleProjectCreation(ctx) {
|
|
|
72781
73045
|
};
|
|
72782
73046
|
}
|
|
72783
73047
|
// src/commands/new/phases/post-setup.ts
|
|
72784
|
-
import { join as
|
|
73048
|
+
import { join as join106 } from "node:path";
|
|
72785
73049
|
|
|
72786
73050
|
// src/domains/installation/setup-wizard.ts
|
|
72787
|
-
import { join as
|
|
73051
|
+
import { join as join105 } from "node:path";
|
|
72788
73052
|
init_logger();
|
|
72789
73053
|
init_dist2();
|
|
72790
73054
|
var import_fs_extra36 = __toESM(require_lib(), 1);
|
|
@@ -72864,7 +73128,7 @@ async function parseEnvFile(path9) {
|
|
|
72864
73128
|
}
|
|
72865
73129
|
}
|
|
72866
73130
|
async function checkGlobalConfig() {
|
|
72867
|
-
const globalEnvPath =
|
|
73131
|
+
const globalEnvPath = join105(getClaudeDir(), ".env");
|
|
72868
73132
|
if (!await import_fs_extra36.pathExists(globalEnvPath))
|
|
72869
73133
|
return false;
|
|
72870
73134
|
const env2 = await parseEnvFile(globalEnvPath);
|
|
@@ -72880,7 +73144,7 @@ async function runSetupWizard(options2) {
|
|
|
72880
73144
|
let globalEnv = {};
|
|
72881
73145
|
const hasGlobalConfig = !isGlobal && await checkGlobalConfig();
|
|
72882
73146
|
if (!isGlobal) {
|
|
72883
|
-
const globalEnvPath =
|
|
73147
|
+
const globalEnvPath = join105(getClaudeDir(), ".env");
|
|
72884
73148
|
if (await import_fs_extra36.pathExists(globalEnvPath)) {
|
|
72885
73149
|
globalEnv = await parseEnvFile(globalEnvPath);
|
|
72886
73150
|
}
|
|
@@ -72943,7 +73207,7 @@ async function runSetupWizard(options2) {
|
|
|
72943
73207
|
}
|
|
72944
73208
|
}
|
|
72945
73209
|
await generateEnvFile(targetDir, values);
|
|
72946
|
-
f2.success(`Configuration saved to ${
|
|
73210
|
+
f2.success(`Configuration saved to ${join105(targetDir, ".env")}`);
|
|
72947
73211
|
return true;
|
|
72948
73212
|
}
|
|
72949
73213
|
async function promptForAdditionalGeminiKeys(primaryKey) {
|
|
@@ -73046,9 +73310,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
|
|
|
73046
73310
|
withSudo: validOptions.withSudo
|
|
73047
73311
|
});
|
|
73048
73312
|
}
|
|
73049
|
-
const claudeDir =
|
|
73313
|
+
const claudeDir = join106(resolvedDir, ".claude");
|
|
73050
73314
|
await promptSetupWizardIfNeeded({
|
|
73051
|
-
envPath:
|
|
73315
|
+
envPath: join106(claudeDir, ".env"),
|
|
73052
73316
|
claudeDir,
|
|
73053
73317
|
isGlobal: false,
|
|
73054
73318
|
isNonInteractive: isNonInteractive2,
|
|
@@ -73125,11 +73389,11 @@ Example: tkm new --use-git --release v2.1.0`);
|
|
|
73125
73389
|
// src/commands/plan/plan-command.ts
|
|
73126
73390
|
init_output_manager();
|
|
73127
73391
|
import { existsSync as existsSync52, statSync as statSync5 } from "node:fs";
|
|
73128
|
-
import { dirname as dirname33, join as
|
|
73392
|
+
import { dirname as dirname33, join as join110, parse as parse2, resolve as resolve31 } from "node:path";
|
|
73129
73393
|
|
|
73130
73394
|
// src/commands/plan/plan-read-handlers.ts
|
|
73131
73395
|
import { existsSync as existsSync51, statSync as statSync4 } from "node:fs";
|
|
73132
|
-
import { basename as basename15, dirname as dirname32, join as
|
|
73396
|
+
import { basename as basename15, dirname as dirname32, join as join109, relative as relative20, resolve as resolve29 } from "node:path";
|
|
73133
73397
|
|
|
73134
73398
|
// src/domains/plan-parser/index.ts
|
|
73135
73399
|
import { dirname as dirname31 } from "node:path";
|
|
@@ -73510,12 +73774,12 @@ function parsePlanFile(planFilePath, options2) {
|
|
|
73510
73774
|
}
|
|
73511
73775
|
// src/domains/plan-parser/plan-scanner.ts
|
|
73512
73776
|
import { existsSync as existsSync48, readdirSync as readdirSync5 } from "node:fs";
|
|
73513
|
-
import { join as
|
|
73777
|
+
import { join as join107 } from "node:path";
|
|
73514
73778
|
function scanPlanDir(dir) {
|
|
73515
73779
|
if (!existsSync48(dir))
|
|
73516
73780
|
return [];
|
|
73517
73781
|
try {
|
|
73518
|
-
return readdirSync5(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
73782
|
+
return readdirSync5(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join107(dir, entry.name, "plan.md")).filter(existsSync48);
|
|
73519
73783
|
} catch {
|
|
73520
73784
|
return [];
|
|
73521
73785
|
}
|
|
@@ -73584,7 +73848,7 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
73584
73848
|
var import_gray_matter7 = __toESM(require_gray_matter(), 1);
|
|
73585
73849
|
import { mkdirSync as mkdirSync3, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "node:fs";
|
|
73586
73850
|
import { existsSync as existsSync50 } from "node:fs";
|
|
73587
|
-
import { basename as basename14, dirname as dirname30, join as
|
|
73851
|
+
import { basename as basename14, dirname as dirname30, join as join108 } from "node:path";
|
|
73588
73852
|
function phaseNameToFilename(id, name) {
|
|
73589
73853
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
|
|
73590
73854
|
const num = numMatch ? numMatch[1] : id;
|
|
@@ -73692,12 +73956,12 @@ function scaffoldPlan(options2) {
|
|
|
73692
73956
|
mkdirSync3(dir, { recursive: true });
|
|
73693
73957
|
const resolvedPhases = resolvePhaseIds(options2.phases);
|
|
73694
73958
|
const optionsWithResolved = { ...options2, phases: resolvedPhases };
|
|
73695
|
-
const planFile =
|
|
73959
|
+
const planFile = join108(dir, "plan.md");
|
|
73696
73960
|
writeFileSync5(planFile, generatePlanMd(optionsWithResolved), "utf8");
|
|
73697
73961
|
const phaseFiles = [];
|
|
73698
73962
|
for (const phase of resolvedPhases) {
|
|
73699
73963
|
const filename = phaseNameToFilename(phase.id, phase.name);
|
|
73700
|
-
const phaseFile =
|
|
73964
|
+
const phaseFile = join108(dir, filename);
|
|
73701
73965
|
writeFileSync5(phaseFile, generatePhaseTemplate(phase), "utf8");
|
|
73702
73966
|
phaseFiles.push(phaseFile);
|
|
73703
73967
|
}
|
|
@@ -73777,7 +74041,7 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
|
|
|
73777
74041
|
continue;
|
|
73778
74042
|
const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
|
|
73779
74043
|
if (linkMatch)
|
|
73780
|
-
return
|
|
74044
|
+
return join108(planDir, linkMatch[2]);
|
|
73781
74045
|
}
|
|
73782
74046
|
return null;
|
|
73783
74047
|
}
|
|
@@ -73858,7 +74122,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
73858
74122
|
`);
|
|
73859
74123
|
}
|
|
73860
74124
|
writeFileSync5(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
|
|
73861
|
-
const phaseFilePath =
|
|
74125
|
+
const phaseFilePath = join108(planDir, filename);
|
|
73862
74126
|
writeFileSync5(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
|
|
73863
74127
|
return { phaseId, phaseFile: phaseFilePath };
|
|
73864
74128
|
}
|
|
@@ -73962,7 +74226,7 @@ async function handleValidate(target, options2) {
|
|
|
73962
74226
|
}
|
|
73963
74227
|
async function handleStatus(target, options2) {
|
|
73964
74228
|
const t = target ? resolve29(target) : null;
|
|
73965
|
-
const plansDir = t && existsSync51(t) && statSync4(t).isDirectory() && !existsSync51(
|
|
74229
|
+
const plansDir = t && existsSync51(t) && statSync4(t).isDirectory() && !existsSync51(join109(t, "plan.md")) ? t : null;
|
|
73966
74230
|
if (plansDir) {
|
|
73967
74231
|
const planFiles = scanPlanDir(plansDir);
|
|
73968
74232
|
if (planFiles.length === 0) {
|
|
@@ -74197,7 +74461,7 @@ function resolvePlanFile(target) {
|
|
|
74197
74461
|
const stat13 = statSync5(t);
|
|
74198
74462
|
if (stat13.isFile())
|
|
74199
74463
|
return t;
|
|
74200
|
-
const candidate =
|
|
74464
|
+
const candidate = join110(t, "plan.md");
|
|
74201
74465
|
if (existsSync52(candidate))
|
|
74202
74466
|
return candidate;
|
|
74203
74467
|
}
|
|
@@ -74205,7 +74469,7 @@ function resolvePlanFile(target) {
|
|
|
74205
74469
|
let dir = process.cwd();
|
|
74206
74470
|
const root = parse2(dir).root;
|
|
74207
74471
|
while (dir !== root) {
|
|
74208
|
-
const candidate =
|
|
74472
|
+
const candidate = join110(dir, "plan.md");
|
|
74209
74473
|
if (existsSync52(candidate))
|
|
74210
74474
|
return candidate;
|
|
74211
74475
|
dir = dirname33(dir);
|
|
@@ -74477,112 +74741,112 @@ var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
|
74477
74741
|
// src/commands/skills/agents.ts
|
|
74478
74742
|
import { existsSync as existsSync54 } from "node:fs";
|
|
74479
74743
|
import { homedir as homedir26 } from "node:os";
|
|
74480
|
-
import { join as
|
|
74744
|
+
import { join as join111 } from "node:path";
|
|
74481
74745
|
var home6 = homedir26();
|
|
74482
74746
|
var agents = {
|
|
74483
74747
|
"claude-code": {
|
|
74484
74748
|
name: "claude-code",
|
|
74485
74749
|
displayName: "Claude Code",
|
|
74486
74750
|
projectPath: ".claude/skills",
|
|
74487
|
-
globalPath:
|
|
74488
|
-
detect: async () => existsSync54(
|
|
74751
|
+
globalPath: join111(home6, ".claude/skills"),
|
|
74752
|
+
detect: async () => existsSync54(join111(home6, ".claude"))
|
|
74489
74753
|
},
|
|
74490
74754
|
cursor: {
|
|
74491
74755
|
name: "cursor",
|
|
74492
74756
|
displayName: "Cursor",
|
|
74493
74757
|
projectPath: ".cursor/skills",
|
|
74494
|
-
globalPath:
|
|
74495
|
-
detect: async () => existsSync54(
|
|
74758
|
+
globalPath: join111(home6, ".cursor/skills"),
|
|
74759
|
+
detect: async () => existsSync54(join111(home6, ".cursor"))
|
|
74496
74760
|
},
|
|
74497
74761
|
codex: {
|
|
74498
74762
|
name: "codex",
|
|
74499
74763
|
displayName: "Codex",
|
|
74500
74764
|
projectPath: ".codex/skills",
|
|
74501
|
-
globalPath:
|
|
74502
|
-
detect: async () => existsSync54(
|
|
74765
|
+
globalPath: join111(home6, ".codex/skills"),
|
|
74766
|
+
detect: async () => existsSync54(join111(home6, ".codex"))
|
|
74503
74767
|
},
|
|
74504
74768
|
opencode: {
|
|
74505
74769
|
name: "opencode",
|
|
74506
74770
|
displayName: "OpenCode",
|
|
74507
74771
|
projectPath: ".opencode/skills",
|
|
74508
|
-
globalPath:
|
|
74509
|
-
detect: async () => existsSync54(
|
|
74772
|
+
globalPath: join111(home6, ".config/opencode/skills"),
|
|
74773
|
+
detect: async () => existsSync54(join111(home6, ".config/opencode"))
|
|
74510
74774
|
},
|
|
74511
74775
|
goose: {
|
|
74512
74776
|
name: "goose",
|
|
74513
74777
|
displayName: "Goose",
|
|
74514
74778
|
projectPath: ".goose/skills",
|
|
74515
|
-
globalPath:
|
|
74516
|
-
detect: async () => existsSync54(
|
|
74779
|
+
globalPath: join111(home6, ".config/goose/skills"),
|
|
74780
|
+
detect: async () => existsSync54(join111(home6, ".config/goose"))
|
|
74517
74781
|
},
|
|
74518
74782
|
"gemini-cli": {
|
|
74519
74783
|
name: "gemini-cli",
|
|
74520
74784
|
displayName: "Gemini CLI",
|
|
74521
74785
|
projectPath: ".agents/skills",
|
|
74522
|
-
globalPath:
|
|
74523
|
-
detect: async () => existsSync54(
|
|
74786
|
+
globalPath: join111(home6, ".agents/skills"),
|
|
74787
|
+
detect: async () => existsSync54(join111(home6, ".gemini"))
|
|
74524
74788
|
},
|
|
74525
74789
|
antigravity: {
|
|
74526
74790
|
name: "antigravity",
|
|
74527
74791
|
displayName: "Antigravity",
|
|
74528
74792
|
projectPath: ".agent/skills",
|
|
74529
|
-
globalPath:
|
|
74530
|
-
detect: async () => existsSync54(
|
|
74793
|
+
globalPath: join111(home6, ".gemini/antigravity/skills"),
|
|
74794
|
+
detect: async () => existsSync54(join111(process.cwd(), ".agent")) || existsSync54(join111(home6, ".gemini/antigravity"))
|
|
74531
74795
|
},
|
|
74532
74796
|
"github-copilot": {
|
|
74533
74797
|
name: "github-copilot",
|
|
74534
74798
|
displayName: "GitHub Copilot",
|
|
74535
74799
|
projectPath: ".github/skills",
|
|
74536
|
-
globalPath:
|
|
74537
|
-
detect: async () => existsSync54(
|
|
74800
|
+
globalPath: join111(home6, ".copilot/skills"),
|
|
74801
|
+
detect: async () => existsSync54(join111(home6, ".copilot"))
|
|
74538
74802
|
},
|
|
74539
74803
|
amp: {
|
|
74540
74804
|
name: "amp",
|
|
74541
74805
|
displayName: "Amp",
|
|
74542
74806
|
projectPath: ".agents/skills",
|
|
74543
|
-
globalPath:
|
|
74544
|
-
detect: async () => existsSync54(
|
|
74807
|
+
globalPath: join111(home6, ".config/agents/skills"),
|
|
74808
|
+
detect: async () => existsSync54(join111(home6, ".config/amp"))
|
|
74545
74809
|
},
|
|
74546
74810
|
kilo: {
|
|
74547
74811
|
name: "kilo",
|
|
74548
74812
|
displayName: "Kilo Code",
|
|
74549
74813
|
projectPath: ".kilocode/skills",
|
|
74550
|
-
globalPath:
|
|
74551
|
-
detect: async () => existsSync54(
|
|
74814
|
+
globalPath: join111(home6, ".kilocode/skills"),
|
|
74815
|
+
detect: async () => existsSync54(join111(home6, ".kilocode"))
|
|
74552
74816
|
},
|
|
74553
74817
|
roo: {
|
|
74554
74818
|
name: "roo",
|
|
74555
74819
|
displayName: "Roo Code",
|
|
74556
74820
|
projectPath: ".roo/skills",
|
|
74557
|
-
globalPath:
|
|
74558
|
-
detect: async () => existsSync54(
|
|
74821
|
+
globalPath: join111(home6, ".roo/skills"),
|
|
74822
|
+
detect: async () => existsSync54(join111(home6, ".roo"))
|
|
74559
74823
|
},
|
|
74560
74824
|
windsurf: {
|
|
74561
74825
|
name: "windsurf",
|
|
74562
74826
|
displayName: "Windsurf",
|
|
74563
74827
|
projectPath: ".windsurf/skills",
|
|
74564
|
-
globalPath:
|
|
74565
|
-
detect: async () => existsSync54(
|
|
74828
|
+
globalPath: join111(home6, ".codeium/windsurf/skills"),
|
|
74829
|
+
detect: async () => existsSync54(join111(home6, ".codeium/windsurf"))
|
|
74566
74830
|
},
|
|
74567
74831
|
cline: {
|
|
74568
74832
|
name: "cline",
|
|
74569
74833
|
displayName: "Cline",
|
|
74570
74834
|
projectPath: ".cline/skills",
|
|
74571
|
-
globalPath:
|
|
74572
|
-
detect: async () => existsSync54(
|
|
74835
|
+
globalPath: join111(home6, ".cline/skills"),
|
|
74836
|
+
detect: async () => existsSync54(join111(home6, ".cline"))
|
|
74573
74837
|
},
|
|
74574
74838
|
openhands: {
|
|
74575
74839
|
name: "openhands",
|
|
74576
74840
|
displayName: "OpenHands",
|
|
74577
74841
|
projectPath: ".openhands/skills",
|
|
74578
|
-
globalPath:
|
|
74579
|
-
detect: async () => existsSync54(
|
|
74842
|
+
globalPath: join111(home6, ".openhands/skills"),
|
|
74843
|
+
detect: async () => existsSync54(join111(home6, ".openhands"))
|
|
74580
74844
|
}
|
|
74581
74845
|
};
|
|
74582
74846
|
function getInstallPath(skillName, agent, options2) {
|
|
74583
74847
|
const config = agents[agent];
|
|
74584
74848
|
const basePath = options2.global ? config.globalPath : config.projectPath;
|
|
74585
|
-
return
|
|
74849
|
+
return join111(basePath, skillName);
|
|
74586
74850
|
}
|
|
74587
74851
|
function isSkillInstalled(skillName, agent, options2) {
|
|
74588
74852
|
const installPath = getInstallPath(skillName, agent, options2);
|
|
@@ -74593,16 +74857,16 @@ function isSkillInstalled(skillName, agent, options2) {
|
|
|
74593
74857
|
import { existsSync as existsSync56 } from "node:fs";
|
|
74594
74858
|
import { cp as cp4, mkdir as mkdir31, rm as rm14, stat as stat13 } from "node:fs/promises";
|
|
74595
74859
|
import { homedir as homedir28 } from "node:os";
|
|
74596
|
-
import { dirname as dirname35, join as
|
|
74860
|
+
import { dirname as dirname35, join as join113, resolve as resolve33 } from "node:path";
|
|
74597
74861
|
|
|
74598
74862
|
// src/commands/skills/skills-registry.ts
|
|
74599
74863
|
init_zod();
|
|
74600
74864
|
import { existsSync as existsSync55 } from "node:fs";
|
|
74601
74865
|
import { mkdir as mkdir30, readFile as readFile47, writeFile as writeFile35 } from "node:fs/promises";
|
|
74602
74866
|
import { homedir as homedir27 } from "node:os";
|
|
74603
|
-
import { dirname as dirname34, join as
|
|
74867
|
+
import { dirname as dirname34, join as join112, sep as sep9 } from "node:path";
|
|
74604
74868
|
var home7 = homedir27();
|
|
74605
|
-
var REGISTRY_PATH2 =
|
|
74869
|
+
var REGISTRY_PATH2 = join112(home7, ".sunagentkit", "skill-registry.json");
|
|
74606
74870
|
var SkillInstallationSchema = exports_external.object({
|
|
74607
74871
|
skill: exports_external.string(),
|
|
74608
74872
|
agent: exports_external.string(),
|
|
@@ -74740,7 +75004,7 @@ async function syncRegistry() {
|
|
|
74740
75004
|
var LEGACY_SKILL_PATHS = {
|
|
74741
75005
|
"gemini-cli": {
|
|
74742
75006
|
project: ".gemini/skills",
|
|
74743
|
-
global:
|
|
75007
|
+
global: join113(homedir28(), ".gemini/skills")
|
|
74744
75008
|
}
|
|
74745
75009
|
};
|
|
74746
75010
|
function isSamePath3(path1, path22) {
|
|
@@ -74774,7 +75038,7 @@ async function cleanupLegacySkillPath(skillName, agent, global3) {
|
|
|
74774
75038
|
if (!legacy)
|
|
74775
75039
|
return;
|
|
74776
75040
|
const legacyBase = global3 ? legacy.global : legacy.project;
|
|
74777
|
-
const legacyPath =
|
|
75041
|
+
const legacyPath = join113(legacyBase, skillName);
|
|
74778
75042
|
if (!existsSync56(legacyPath))
|
|
74779
75043
|
return;
|
|
74780
75044
|
await rm14(legacyPath, { recursive: true, force: true });
|
|
@@ -74784,7 +75048,7 @@ async function cleanupLegacySkillPath(skillName, agent, global3) {
|
|
|
74784
75048
|
if (entry.skill === skillName && entry.agent === agent && entry.global === global3) {
|
|
74785
75049
|
if (entry.path === legacyPath) {
|
|
74786
75050
|
const newBase = global3 ? agents[agent].globalPath : agents[agent].projectPath;
|
|
74787
|
-
entry.path =
|
|
75051
|
+
entry.path = join113(newBase, skillName);
|
|
74788
75052
|
changed = true;
|
|
74789
75053
|
}
|
|
74790
75054
|
}
|
|
@@ -74869,7 +75133,7 @@ function getInstallPreview(skill, targetAgents, options2) {
|
|
|
74869
75133
|
// src/commands/skills/skills-uninstaller.ts
|
|
74870
75134
|
import { existsSync as existsSync57 } from "node:fs";
|
|
74871
75135
|
import { rm as rm15 } from "node:fs/promises";
|
|
74872
|
-
import { join as
|
|
75136
|
+
import { join as join114 } from "node:path";
|
|
74873
75137
|
async function uninstallSkillFromAgent(skill, agent, global3) {
|
|
74874
75138
|
const agentConfig = agents[agent];
|
|
74875
75139
|
const registry = await readRegistry();
|
|
@@ -74917,7 +75181,7 @@ async function uninstallSkillFromAgent(skill, agent, global3) {
|
|
|
74917
75181
|
async function forceUninstallSkill(skill, agent, global3) {
|
|
74918
75182
|
const agentConfig = agents[agent];
|
|
74919
75183
|
const basePath = global3 ? agentConfig.globalPath : agentConfig.projectPath;
|
|
74920
|
-
const path9 =
|
|
75184
|
+
const path9 = join114(basePath, skill);
|
|
74921
75185
|
if (!existsSync57(path9)) {
|
|
74922
75186
|
return {
|
|
74923
75187
|
skill,
|
|
@@ -75422,12 +75686,12 @@ init_logger();
|
|
|
75422
75686
|
// src/commands/telemetry/shared.ts
|
|
75423
75687
|
import { existsSync as existsSync58, readFileSync as readFileSync15, readdirSync as readdirSync6 } from "node:fs";
|
|
75424
75688
|
import { homedir as homedir29 } from "node:os";
|
|
75425
|
-
import { join as
|
|
75689
|
+
import { join as join115 } from "node:path";
|
|
75426
75690
|
init_token_store();
|
|
75427
|
-
var USER_CACHE_PATH =
|
|
75428
|
-
var EVENT_BUFFER_DIR =
|
|
75429
|
-
var RATE_STATE_PATH =
|
|
75430
|
-
var METADATA_PATH =
|
|
75691
|
+
var USER_CACHE_PATH = join115(homedir29(), ".claude", "sk-user.json");
|
|
75692
|
+
var EVENT_BUFFER_DIR = join115(homedir29(), ".claude", "sk-events");
|
|
75693
|
+
var RATE_STATE_PATH = join115(homedir29(), ".claude", "sk-rate-state.json");
|
|
75694
|
+
var METADATA_PATH = join115(homedir29(), ".claude", "metadata.json");
|
|
75431
75695
|
var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
|
|
75432
75696
|
var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
|
|
75433
75697
|
function readUserCache() {
|
|
@@ -75514,7 +75778,7 @@ async function handleDisable() {
|
|
|
75514
75778
|
// src/commands/telemetry/phases/purge-local-handler.ts
|
|
75515
75779
|
init_logger();
|
|
75516
75780
|
import { existsSync as existsSync59, readdirSync as readdirSync7, unlinkSync as unlinkSync5 } from "node:fs";
|
|
75517
|
-
import { join as
|
|
75781
|
+
import { join as join116 } from "node:path";
|
|
75518
75782
|
function removeIfExists(path9) {
|
|
75519
75783
|
try {
|
|
75520
75784
|
if (!existsSync59(path9))
|
|
@@ -75534,7 +75798,7 @@ function removeBufferFiles() {
|
|
|
75534
75798
|
if (!file.endsWith(".jsonl"))
|
|
75535
75799
|
continue;
|
|
75536
75800
|
try {
|
|
75537
|
-
unlinkSync5(
|
|
75801
|
+
unlinkSync5(join116(EVENT_BUFFER_DIR, file));
|
|
75538
75802
|
count += 1;
|
|
75539
75803
|
} catch {}
|
|
75540
75804
|
}
|
|
@@ -75760,13 +76024,13 @@ async function detectInstallations() {
|
|
|
75760
76024
|
|
|
75761
76025
|
// src/commands/uninstall/removal-handler.ts
|
|
75762
76026
|
import { readdirSync as readdirSync9, rmSync as rmSync6 } from "node:fs";
|
|
75763
|
-
import { join as
|
|
76027
|
+
import { join as join118, resolve as resolve34, sep as sep10 } from "node:path";
|
|
75764
76028
|
init_logger();
|
|
75765
76029
|
var import_fs_extra38 = __toESM(require_lib(), 1);
|
|
75766
76030
|
|
|
75767
76031
|
// src/commands/uninstall/analysis-handler.ts
|
|
75768
76032
|
import { readdirSync as readdirSync8, rmSync as rmSync5 } from "node:fs";
|
|
75769
|
-
import { dirname as dirname36, join as
|
|
76033
|
+
import { dirname as dirname36, join as join117 } from "node:path";
|
|
75770
76034
|
init_logger();
|
|
75771
76035
|
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
75772
76036
|
function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
@@ -75813,7 +76077,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
75813
76077
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
75814
76078
|
const kitFiles = metadata.kits[kit].files || [];
|
|
75815
76079
|
for (const trackedFile of kitFiles) {
|
|
75816
|
-
const filePath =
|
|
76080
|
+
const filePath = join117(installation.path, trackedFile.path);
|
|
75817
76081
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
75818
76082
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
75819
76083
|
continue;
|
|
@@ -75843,7 +76107,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
75843
76107
|
return result;
|
|
75844
76108
|
}
|
|
75845
76109
|
for (const trackedFile of allTrackedFiles) {
|
|
75846
|
-
const filePath =
|
|
76110
|
+
const filePath = join117(installation.path, trackedFile.path);
|
|
75847
76111
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
75848
76112
|
if (!ownershipResult.exists)
|
|
75849
76113
|
continue;
|
|
@@ -75940,7 +76204,7 @@ async function removeInstallations(installations, options2) {
|
|
|
75940
76204
|
let removedCount = 0;
|
|
75941
76205
|
let cleanedDirs = 0;
|
|
75942
76206
|
for (const item of analysis.toDelete) {
|
|
75943
|
-
const filePath =
|
|
76207
|
+
const filePath = join118(installation.path, item.path);
|
|
75944
76208
|
if (!await import_fs_extra38.pathExists(filePath))
|
|
75945
76209
|
continue;
|
|
75946
76210
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -76142,7 +76406,7 @@ ${import_picocolors36.default.yellow("User modifications will be permanently del
|
|
|
76142
76406
|
// src/commands/update-cli.ts
|
|
76143
76407
|
init_takumi_config_manager();
|
|
76144
76408
|
import { exec as exec8, spawn as spawn2 } from "node:child_process";
|
|
76145
|
-
import { join as
|
|
76409
|
+
import { join as join119 } from "node:path";
|
|
76146
76410
|
import { promisify as promisify14 } from "node:util";
|
|
76147
76411
|
|
|
76148
76412
|
// src/domains/github/npm-registry.ts
|
|
@@ -76309,7 +76573,7 @@ var import_fs_extra39 = __toESM(require_lib(), 1);
|
|
|
76309
76573
|
// package.json
|
|
76310
76574
|
var package_default = {
|
|
76311
76575
|
name: "@sunasteriskrnd/takumi",
|
|
76312
|
-
version: "1.0.0-dev.
|
|
76576
|
+
version: "1.0.0-dev.9",
|
|
76313
76577
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
76314
76578
|
type: "module",
|
|
76315
76579
|
repository: {
|
|
@@ -76332,6 +76596,7 @@ var package_default = {
|
|
|
76332
76596
|
build: `bun build src/index.ts --outdir dist --target node --external @octokit/rest --external better-sqlite3 --external yauzl-promise --external @node-rs/crc32 && node -e "const fs=require('fs'),f='dist/index.js',c=fs.readFileSync(f,'utf-8');fs.writeFileSync(f,c.replace(/^#!.*\\n\\/\\/ @bun\\n/,''))"`,
|
|
76333
76597
|
"verify:package": "node scripts/prepublish-check.js",
|
|
76334
76598
|
test: "bun test",
|
|
76599
|
+
"test:ci": "NON_INTERACTIVE=true CI_SAFE_MODE=true bun test",
|
|
76335
76600
|
"test:integration": "CK_RUN_CLI_INTEGRATION=1 bun test tests/integration/cli.test.ts",
|
|
76336
76601
|
"test:watch": "bun test --watch",
|
|
76337
76602
|
"test:quick": "./scripts/dev-quick-start.sh test",
|
|
@@ -76493,7 +76758,7 @@ function selectKitForUpdate(params) {
|
|
|
76493
76758
|
};
|
|
76494
76759
|
}
|
|
76495
76760
|
async function readMetadataFile(claudeDir) {
|
|
76496
|
-
const metadataPath =
|
|
76761
|
+
const metadataPath = join119(claudeDir, "metadata.json");
|
|
76497
76762
|
try {
|
|
76498
76763
|
if (!await import_fs_extra39.pathExists(metadataPath)) {
|
|
76499
76764
|
return null;
|
|
@@ -76994,7 +77259,7 @@ init_logger();
|
|
|
76994
77259
|
import { existsSync as existsSync65 } from "node:fs";
|
|
76995
77260
|
import { rm as rm16 } from "node:fs/promises";
|
|
76996
77261
|
import { homedir as homedir31 } from "node:os";
|
|
76997
|
-
import { join as
|
|
77262
|
+
import { join as join126 } from "node:path";
|
|
76998
77263
|
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
76999
77264
|
|
|
77000
77265
|
// src/commands/watch/phases/implementation-runner.ts
|
|
@@ -77504,7 +77769,7 @@ function spawnAndCollect3(command, args) {
|
|
|
77504
77769
|
|
|
77505
77770
|
// src/commands/watch/phases/issue-processor.ts
|
|
77506
77771
|
import { mkdir as mkdir32, writeFile as writeFile37 } from "node:fs/promises";
|
|
77507
|
-
import { join as
|
|
77772
|
+
import { join as join122 } from "node:path";
|
|
77508
77773
|
|
|
77509
77774
|
// src/commands/watch/phases/approval-detector.ts
|
|
77510
77775
|
init_logger();
|
|
@@ -77879,9 +78144,9 @@ async function checkAwaitingApproval(state, setup, options2, watchLog, projectDi
|
|
|
77879
78144
|
|
|
77880
78145
|
// src/commands/watch/phases/plan-dir-finder.ts
|
|
77881
78146
|
import { readdir as readdir32, stat as stat14 } from "node:fs/promises";
|
|
77882
|
-
import { join as
|
|
78147
|
+
import { join as join121 } from "node:path";
|
|
77883
78148
|
async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
77884
|
-
const plansRoot =
|
|
78149
|
+
const plansRoot = join121(cwd2, "plans");
|
|
77885
78150
|
try {
|
|
77886
78151
|
const entries = await readdir32(plansRoot);
|
|
77887
78152
|
const tenMinAgo = Date.now() - 10 * 60 * 1000;
|
|
@@ -77890,14 +78155,14 @@ async function findRecentPlanDir(cwd2, issueNumber, watchLog) {
|
|
|
77890
78155
|
for (const entry of entries) {
|
|
77891
78156
|
if (entry === "watch" || entry === "reports" || entry === "visuals")
|
|
77892
78157
|
continue;
|
|
77893
|
-
const dirPath =
|
|
78158
|
+
const dirPath = join121(plansRoot, entry);
|
|
77894
78159
|
const dirStat = await stat14(dirPath);
|
|
77895
78160
|
if (!dirStat.isDirectory())
|
|
77896
78161
|
continue;
|
|
77897
78162
|
if (dirStat.mtimeMs < tenMinAgo)
|
|
77898
78163
|
continue;
|
|
77899
78164
|
try {
|
|
77900
|
-
await stat14(
|
|
78165
|
+
await stat14(join121(dirPath, "plan.md"));
|
|
77901
78166
|
} catch {
|
|
77902
78167
|
continue;
|
|
77903
78168
|
}
|
|
@@ -78128,13 +78393,13 @@ async function handlePlanGeneration(issue, state, config, setup, options2, watch
|
|
|
78128
78393
|
stats.plansCreated++;
|
|
78129
78394
|
const detectedPlanDir = await findRecentPlanDir(projectDir, issue.number, watchLog);
|
|
78130
78395
|
if (detectedPlanDir) {
|
|
78131
|
-
state.activeIssues[numStr].planPath =
|
|
78396
|
+
state.activeIssues[numStr].planPath = join122(detectedPlanDir, "plan.md");
|
|
78132
78397
|
watchLog.info(`Plan directory detected: ${detectedPlanDir}`);
|
|
78133
78398
|
} else {
|
|
78134
78399
|
try {
|
|
78135
|
-
const planDir =
|
|
78400
|
+
const planDir = join122(projectDir, "plans", "watch");
|
|
78136
78401
|
await mkdir32(planDir, { recursive: true });
|
|
78137
|
-
const planFilePath =
|
|
78402
|
+
const planFilePath = join122(planDir, `issue-${issue.number}-plan.md`);
|
|
78138
78403
|
await writeFile37(planFilePath, planResult.planText, "utf-8");
|
|
78139
78404
|
state.activeIssues[numStr].planPath = planFilePath;
|
|
78140
78405
|
watchLog.info(`Plan saved (fallback) to ${planFilePath}`);
|
|
@@ -78439,18 +78704,18 @@ init_logger();
|
|
|
78439
78704
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
78440
78705
|
import { existsSync as existsSync62 } from "node:fs";
|
|
78441
78706
|
import { readdir as readdir33, stat as stat15 } from "node:fs/promises";
|
|
78442
|
-
import { join as
|
|
78707
|
+
import { join as join123 } from "node:path";
|
|
78443
78708
|
async function scanForRepos(parentDir) {
|
|
78444
78709
|
const repos = [];
|
|
78445
78710
|
const entries = await readdir33(parentDir);
|
|
78446
78711
|
for (const entry of entries) {
|
|
78447
78712
|
if (entry.startsWith("."))
|
|
78448
78713
|
continue;
|
|
78449
|
-
const fullPath =
|
|
78714
|
+
const fullPath = join123(parentDir, entry);
|
|
78450
78715
|
const entryStat = await stat15(fullPath);
|
|
78451
78716
|
if (!entryStat.isDirectory())
|
|
78452
78717
|
continue;
|
|
78453
|
-
const gitDir =
|
|
78718
|
+
const gitDir = join123(fullPath, ".git");
|
|
78454
78719
|
if (!existsSync62(gitDir))
|
|
78455
78720
|
continue;
|
|
78456
78721
|
const result = spawnSync5("gh", ["repo", "view", "--json", "owner,name"], {
|
|
@@ -78477,7 +78742,7 @@ init_logger();
|
|
|
78477
78742
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
78478
78743
|
import { existsSync as existsSync63 } from "node:fs";
|
|
78479
78744
|
import { homedir as homedir30 } from "node:os";
|
|
78480
|
-
import { join as
|
|
78745
|
+
import { join as join124 } from "node:path";
|
|
78481
78746
|
async function validateSetup(cwd2) {
|
|
78482
78747
|
const workDir = cwd2 ?? process.cwd();
|
|
78483
78748
|
const ghVersion = spawnSync6("gh", ["--version"], { encoding: "utf-8", timeout: 1e4 });
|
|
@@ -78508,7 +78773,7 @@ Run this command from a directory with a GitHub remote.`);
|
|
|
78508
78773
|
} catch {
|
|
78509
78774
|
throw new Error(`Failed to parse repository info: ${ghRepo.stdout}`);
|
|
78510
78775
|
}
|
|
78511
|
-
const skillsPath =
|
|
78776
|
+
const skillsPath = join124(homedir30(), ".claude", "skills");
|
|
78512
78777
|
const skillsAvailable = existsSync63(skillsPath);
|
|
78513
78778
|
if (!skillsAvailable) {
|
|
78514
78779
|
logger.warning(`Takumi Engineer skills not found at ${skillsPath}`);
|
|
@@ -78527,7 +78792,7 @@ init_path_resolver();
|
|
|
78527
78792
|
import { createWriteStream as createWriteStream4, statSync as statSync6 } from "node:fs";
|
|
78528
78793
|
import { existsSync as existsSync64 } from "node:fs";
|
|
78529
78794
|
import { mkdir as mkdir34, rename as rename9 } from "node:fs/promises";
|
|
78530
|
-
import { join as
|
|
78795
|
+
import { join as join125 } from "node:path";
|
|
78531
78796
|
|
|
78532
78797
|
class WatchLogger {
|
|
78533
78798
|
logStream = null;
|
|
@@ -78535,7 +78800,7 @@ class WatchLogger {
|
|
|
78535
78800
|
logPath = null;
|
|
78536
78801
|
maxBytes;
|
|
78537
78802
|
constructor(logDir, maxBytes = 0) {
|
|
78538
|
-
this.logDir = logDir ??
|
|
78803
|
+
this.logDir = logDir ?? join125(PathResolver.getTakumiDir(), "logs");
|
|
78539
78804
|
this.maxBytes = maxBytes;
|
|
78540
78805
|
}
|
|
78541
78806
|
async init() {
|
|
@@ -78544,7 +78809,7 @@ class WatchLogger {
|
|
|
78544
78809
|
await mkdir34(this.logDir, { recursive: true });
|
|
78545
78810
|
}
|
|
78546
78811
|
const dateStr = formatDate(new Date);
|
|
78547
|
-
this.logPath =
|
|
78812
|
+
this.logPath = join125(this.logDir, `watch-${dateStr}.log`);
|
|
78548
78813
|
this.logStream = createWriteStream4(this.logPath, { flags: "a", mode: 384 });
|
|
78549
78814
|
} catch (error) {
|
|
78550
78815
|
logger.warning(`Cannot create watch log file: ${error instanceof Error ? error.message : "Unknown"}`);
|
|
@@ -78724,7 +78989,7 @@ async function watchCommand(options2) {
|
|
|
78724
78989
|
}
|
|
78725
78990
|
async function discoverRepos(options2, watchLog) {
|
|
78726
78991
|
const cwd2 = process.cwd();
|
|
78727
|
-
const isGitRepo = existsSync65(
|
|
78992
|
+
const isGitRepo = existsSync65(join126(cwd2, ".git"));
|
|
78728
78993
|
if (options2.force) {
|
|
78729
78994
|
await forceRemoveLock(watchLog);
|
|
78730
78995
|
}
|
|
@@ -78794,7 +79059,7 @@ async function resetState(state, projectDir, watchLog) {
|
|
|
78794
79059
|
watchLog.info(`Watch state reset (--force) for ${projectDir}`);
|
|
78795
79060
|
}
|
|
78796
79061
|
async function forceRemoveLock(watchLog) {
|
|
78797
|
-
const lockPath =
|
|
79062
|
+
const lockPath = join126(homedir31(), ".sunagentkit", "locks", `${LOCK_NAME}.lock`);
|
|
78798
79063
|
try {
|
|
78799
79064
|
await rm16(lockPath, { recursive: true, force: true });
|
|
78800
79065
|
watchLog.info("Removed existing lock file (--force)");
|
|
@@ -78838,13 +79103,13 @@ function sleep2(ms2) {
|
|
|
78838
79103
|
// src/cli/command-registry.ts
|
|
78839
79104
|
init_logger();
|
|
78840
79105
|
function registerCommands(cli) {
|
|
78841
|
-
cli.command("new", "Bootstrap a new Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to
|
|
79106
|
+
cli.command("new", "Bootstrap a new Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (engineer, extras). Repeat the flag to install multiple kits, e.g. --kit engineer --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--force", "Overwrite existing files without confirmation").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--opencode", "Install OpenCode CLI package (non-interactive mode)").option("--gemini", "Install Google Gemini CLI package (non-interactive mode)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /sk: prefix to all slash commands by moving them to commands/sk/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").option("--local", "Use local monorepo as kit source (auto-detects from CLI location)").option("--use-gh", "Force GitHub release source (bypass Worker R2 proxy; default uses Worker)").action(async (options2) => {
|
|
78842
79107
|
if (options2.exclude && !Array.isArray(options2.exclude)) {
|
|
78843
79108
|
options2.exclude = [options2.exclude];
|
|
78844
79109
|
}
|
|
78845
79110
|
await newCommand(options2);
|
|
78846
79111
|
});
|
|
78847
|
-
cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to
|
|
79112
|
+
cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (engineer, extras). Repeat the flag to install multiple kits, e.g. --kit engineer --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove SK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /sk: prefix to all slash commands by moving them to commands/sk/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").option("--local", "Use local monorepo as kit source (auto-detects from CLI location)").option("--use-gh", "Force GitHub release source (bypass Worker R2 proxy; default uses Worker)").option("-a, --agent <agents...>", "Target agents (claude-code, codex). Default: claude-code").action(async (options2) => {
|
|
78848
79113
|
if (options2.exclude && !Array.isArray(options2.exclude)) {
|
|
78849
79114
|
options2.exclude = [options2.exclude];
|
|
78850
79115
|
}
|
|
@@ -78857,6 +79122,9 @@ function registerCommands(cli) {
|
|
|
78857
79122
|
if (options2.agent) {
|
|
78858
79123
|
options2.agents = options2.agent;
|
|
78859
79124
|
}
|
|
79125
|
+
if (options2.kit && Array.isArray(options2.kit)) {
|
|
79126
|
+
options2.kit = options2.kit.join(",");
|
|
79127
|
+
}
|
|
78860
79128
|
await initCommand(options2);
|
|
78861
79129
|
});
|
|
78862
79130
|
cli.command("update", "Update Takumi CLI to the latest version").option("-r, --release <version>", "Update to a specific version").option("--check", "Check for updates without installing").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("-d, --dev", "Update to the latest dev version").option("--beta", "Alias for --dev (deprecated)").option("--registry <url>", "Custom npm registry URL").option("--kit <kit>", "[DEPRECATED] Use 'takumi init --kit <kit>' instead").option("-g, --global", "[DEPRECATED] Use 'takumi init --global' instead").action(async (options2) => {
|
|
@@ -78996,7 +79264,7 @@ function registerCommands(cli) {
|
|
|
78996
79264
|
|
|
78997
79265
|
// src/cli/version-display.ts
|
|
78998
79266
|
import { existsSync as existsSync77, readFileSync as readFileSync20 } from "node:fs";
|
|
78999
|
-
import { join as
|
|
79267
|
+
import { join as join138 } from "node:path";
|
|
79000
79268
|
init_help_banner();
|
|
79001
79269
|
// src/domains/versioning/checking/kit-version-checker.ts
|
|
79002
79270
|
init_github_client();
|
|
@@ -79008,14 +79276,14 @@ init_logger();
|
|
|
79008
79276
|
init_path_resolver();
|
|
79009
79277
|
import { existsSync as existsSync76 } from "node:fs";
|
|
79010
79278
|
import { mkdir as mkdir35, readFile as readFile52, writeFile as writeFile40 } from "node:fs/promises";
|
|
79011
|
-
import { join as
|
|
79279
|
+
import { join as join137 } from "node:path";
|
|
79012
79280
|
|
|
79013
79281
|
class VersionCacheManager {
|
|
79014
79282
|
static CACHE_FILENAME = "version-check.json";
|
|
79015
79283
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
79016
79284
|
static getCacheFile() {
|
|
79017
79285
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
79018
|
-
return
|
|
79286
|
+
return join137(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
79019
79287
|
}
|
|
79020
79288
|
static async load() {
|
|
79021
79289
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -79308,8 +79576,8 @@ async function displayVersion() {
|
|
|
79308
79576
|
const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
|
|
79309
79577
|
if (!localSubdir)
|
|
79310
79578
|
continue;
|
|
79311
|
-
const localMeta =
|
|
79312
|
-
if (localMeta ===
|
|
79579
|
+
const localMeta = join138(process.cwd(), localSubdir, "metadata.json");
|
|
79580
|
+
if (localMeta === join138(inst.globalRoot(), "metadata.json"))
|
|
79313
79581
|
continue;
|
|
79314
79582
|
if (!existsSync77(localMeta))
|
|
79315
79583
|
continue;
|
|
@@ -79334,7 +79602,7 @@ async function displayVersion() {
|
|
|
79334
79602
|
}
|
|
79335
79603
|
const singleInstall = detectedGlobals.length === 1 && detectedGlobals[0]?.provider === "claude-code";
|
|
79336
79604
|
for (const { provider, path: installPath } of detectedGlobals) {
|
|
79337
|
-
const metadataPath =
|
|
79605
|
+
const metadataPath = join138(installPath, "metadata.json");
|
|
79338
79606
|
if (existsSync77(metadataPath)) {
|
|
79339
79607
|
try {
|
|
79340
79608
|
const rawMetadata = JSON.parse(readFileSync20(metadataPath, "utf-8"));
|