@sunasteriskrnd/takumi 1.0.0-dev.30 → 1.0.0-dev.32
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 +661 -321
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19815,7 +19815,7 @@ var package_default;
|
|
|
19815
19815
|
var init_package = __esm(() => {
|
|
19816
19816
|
package_default = {
|
|
19817
19817
|
name: "@sunasteriskrnd/takumi",
|
|
19818
|
-
version: "1.0.0-dev.
|
|
19818
|
+
version: "1.0.0-dev.32",
|
|
19819
19819
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
19820
19820
|
type: "module",
|
|
19821
19821
|
repository: {
|
|
@@ -22283,6 +22283,7 @@ var init_commands = __esm(() => {
|
|
|
22283
22283
|
fresh: exports_external.boolean().default(false),
|
|
22284
22284
|
force: exports_external.boolean().default(false),
|
|
22285
22285
|
installSkills: exports_external.boolean().default(false),
|
|
22286
|
+
installHooks: exports_external.boolean().default(false),
|
|
22286
22287
|
withSudo: exports_external.boolean().default(false),
|
|
22287
22288
|
prefix: exports_external.boolean().default(false),
|
|
22288
22289
|
beta: exports_external.boolean().default(false),
|
|
@@ -50740,7 +50741,7 @@ __export(exports_monorepo_resolver, {
|
|
|
50740
50741
|
resolveMonorepoRoot: () => resolveMonorepoRoot
|
|
50741
50742
|
});
|
|
50742
50743
|
import { existsSync as existsSync54, readFileSync as readFileSync22 } from "node:fs";
|
|
50743
|
-
import { dirname as
|
|
50744
|
+
import { dirname as dirname33, join as join116, resolve as resolve26 } from "node:path";
|
|
50744
50745
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
50745
50746
|
function parseMetadataAt(metadataPath) {
|
|
50746
50747
|
if (!existsSync54(metadataPath))
|
|
@@ -50757,7 +50758,7 @@ function parseMetadataAt(metadataPath) {
|
|
|
50757
50758
|
}
|
|
50758
50759
|
}
|
|
50759
50760
|
function readSourceDirFromPackageJson(candidateRoot) {
|
|
50760
|
-
const packageJsonPath =
|
|
50761
|
+
const packageJsonPath = join116(candidateRoot, "package.json");
|
|
50761
50762
|
if (!existsSync54(packageJsonPath))
|
|
50762
50763
|
return null;
|
|
50763
50764
|
try {
|
|
@@ -50780,7 +50781,7 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
50780
50781
|
};
|
|
50781
50782
|
}
|
|
50782
50783
|
const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
|
|
50783
|
-
const sourceRoot =
|
|
50784
|
+
const sourceRoot = join116(candidateRoot, sourceDir);
|
|
50784
50785
|
const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
|
|
50785
50786
|
if (nestedMetadata) {
|
|
50786
50787
|
return {
|
|
@@ -50798,7 +50799,7 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
|
|
|
50798
50799
|
const result = tryReadAtCandidate(current);
|
|
50799
50800
|
if (result)
|
|
50800
50801
|
return result;
|
|
50801
|
-
const parent =
|
|
50802
|
+
const parent = dirname33(current);
|
|
50802
50803
|
if (parent === current)
|
|
50803
50804
|
break;
|
|
50804
50805
|
current = parent;
|
|
@@ -50808,13 +50809,13 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
|
|
|
50808
50809
|
function resolveMonorepoRoot() {
|
|
50809
50810
|
try {
|
|
50810
50811
|
const thisFile = fileURLToPath3(import.meta.url);
|
|
50811
|
-
const thisDir =
|
|
50812
|
+
const thisDir = dirname33(thisFile);
|
|
50812
50813
|
const result2 = walkUpForMetadata(thisDir);
|
|
50813
50814
|
if (result2)
|
|
50814
50815
|
return result2;
|
|
50815
50816
|
} catch {}
|
|
50816
50817
|
if (process.argv[1]) {
|
|
50817
|
-
const binDir =
|
|
50818
|
+
const binDir = dirname33(resolve26(process.argv[1]));
|
|
50818
50819
|
const result2 = walkUpForMetadata(binDir);
|
|
50819
50820
|
if (result2)
|
|
50820
50821
|
return result2;
|
|
@@ -54914,6 +54915,143 @@ function tryOpenBrowser(target) {
|
|
|
54914
54915
|
// src/domains/sessions/server.ts
|
|
54915
54916
|
import * as http from "node:http";
|
|
54916
54917
|
|
|
54918
|
+
// src/domains/sessions/analytics-source.ts
|
|
54919
|
+
import { readdirSync as readdirSync6 } from "node:fs";
|
|
54920
|
+
import { join as join77 } from "node:path";
|
|
54921
|
+
|
|
54922
|
+
// src/domains/sessions/analytics.ts
|
|
54923
|
+
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
54924
|
+
var PER_DAY_MAX = 371;
|
|
54925
|
+
var LAST_N_DAYS = 30;
|
|
54926
|
+
var TOP_PROJECTS = 12;
|
|
54927
|
+
var num = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
54928
|
+
function dayKey(ms) {
|
|
54929
|
+
return new Date(ms).toISOString().slice(0, 10);
|
|
54930
|
+
}
|
|
54931
|
+
function startedMs(startedAt) {
|
|
54932
|
+
if (typeof startedAt !== "string")
|
|
54933
|
+
return null;
|
|
54934
|
+
const ms = Date.parse(startedAt);
|
|
54935
|
+
return Number.isNaN(ms) ? null : ms;
|
|
54936
|
+
}
|
|
54937
|
+
function normalizeTokens(t) {
|
|
54938
|
+
const o2 = t ?? {};
|
|
54939
|
+
return {
|
|
54940
|
+
input: num(o2.input),
|
|
54941
|
+
output: num(o2.output),
|
|
54942
|
+
cacheRead: num(o2.cacheRead),
|
|
54943
|
+
cacheWrite: num(o2.cacheWrite)
|
|
54944
|
+
};
|
|
54945
|
+
}
|
|
54946
|
+
function aggregateTokens(agg) {
|
|
54947
|
+
return normalizeTokens(agg?.tokens);
|
|
54948
|
+
}
|
|
54949
|
+
var sumTokens = (t) => t.input + t.output + t.cacheRead + t.cacheWrite;
|
|
54950
|
+
function accumulateTokens(a3, b3) {
|
|
54951
|
+
a3.input += b3.input;
|
|
54952
|
+
a3.output += b3.output;
|
|
54953
|
+
a3.cacheRead += b3.cacheRead;
|
|
54954
|
+
a3.cacheWrite += b3.cacheWrite;
|
|
54955
|
+
}
|
|
54956
|
+
function buildLast30(byDay, now) {
|
|
54957
|
+
const out = [];
|
|
54958
|
+
const todayMs = Date.parse(`${dayKey(now)}T00:00:00.000Z`);
|
|
54959
|
+
for (let i = LAST_N_DAYS - 1;i >= 0; i -= 1) {
|
|
54960
|
+
const date = dayKey(todayMs - i * DAY_MS);
|
|
54961
|
+
out.push({ date, count: byDay.get(date) ?? 0 });
|
|
54962
|
+
}
|
|
54963
|
+
return out;
|
|
54964
|
+
}
|
|
54965
|
+
function foldAnalytics(aggregates, now) {
|
|
54966
|
+
const totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
54967
|
+
const eventsByDay = new Map;
|
|
54968
|
+
const tokensByDow = new Map;
|
|
54969
|
+
const tokensByProject = new Map;
|
|
54970
|
+
const tokensByModel = new Map;
|
|
54971
|
+
const tokensByDay = new Map;
|
|
54972
|
+
for (let d3 = 0;d3 < 7; d3 += 1)
|
|
54973
|
+
tokensByDow.set(d3, 0);
|
|
54974
|
+
let agentCount = 0;
|
|
54975
|
+
let toolCallCount = 0;
|
|
54976
|
+
let eventTotal = 0;
|
|
54977
|
+
let earliestMs = null;
|
|
54978
|
+
let latestMs = null;
|
|
54979
|
+
const oldestAllowedMs = Date.parse(`${dayKey(now - PER_DAY_MAX * DAY_MS)}T00:00:00.000Z`);
|
|
54980
|
+
for (const agg of aggregates) {
|
|
54981
|
+
const t = aggregateTokens(agg);
|
|
54982
|
+
totals.input += t.input;
|
|
54983
|
+
totals.output += t.output;
|
|
54984
|
+
totals.cacheRead += t.cacheRead;
|
|
54985
|
+
totals.cacheWrite += t.cacheWrite;
|
|
54986
|
+
agentCount += num(agg?.agentCount);
|
|
54987
|
+
toolCallCount += num(agg?.toolCallCount);
|
|
54988
|
+
const events = num(agg?.eventCount);
|
|
54989
|
+
eventTotal += events;
|
|
54990
|
+
const sessionTokens = sumTokens(t);
|
|
54991
|
+
const label = agg?.projectLabel || "(unknown)";
|
|
54992
|
+
tokensByProject.set(label, (tokensByProject.get(label) ?? 0) + sessionTokens);
|
|
54993
|
+
const perModel = agg?.tokensByModel;
|
|
54994
|
+
if (perModel && typeof perModel === "object") {
|
|
54995
|
+
for (const [model, mtok] of Object.entries(perModel)) {
|
|
54996
|
+
let acc = tokensByModel.get(model);
|
|
54997
|
+
if (!acc) {
|
|
54998
|
+
acc = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
54999
|
+
tokensByModel.set(model, acc);
|
|
55000
|
+
}
|
|
55001
|
+
accumulateTokens(acc, normalizeTokens(mtok));
|
|
55002
|
+
}
|
|
55003
|
+
}
|
|
55004
|
+
const ms = startedMs(agg?.startedAt);
|
|
55005
|
+
if (ms === null)
|
|
55006
|
+
continue;
|
|
55007
|
+
if (earliestMs === null || ms < earliestMs)
|
|
55008
|
+
earliestMs = ms;
|
|
55009
|
+
if (latestMs === null || ms > latestMs)
|
|
55010
|
+
latestMs = ms;
|
|
55011
|
+
const key = dayKey(ms);
|
|
55012
|
+
eventsByDay.set(key, (eventsByDay.get(key) ?? 0) + events);
|
|
55013
|
+
tokensByDay.set(key, (tokensByDay.get(key) ?? 0) + sessionTokens);
|
|
55014
|
+
const dow = new Date(ms).getUTCDay();
|
|
55015
|
+
tokensByDow.set(dow, (tokensByDow.get(dow) ?? 0) + sessionTokens);
|
|
55016
|
+
}
|
|
55017
|
+
const perDay = [...eventsByDay.entries()].filter(([date]) => Date.parse(`${date}T00:00:00.000Z`) >= oldestAllowedMs).map(([date, count]) => ({ date, count })).sort((a3, b3) => a3.date.localeCompare(b3.date));
|
|
55018
|
+
const byProjectAll = [...tokensByProject.entries()].map(([label, tokens]) => ({ label, tokens })).sort((a3, b3) => b3.tokens - a3.tokens || a3.label.localeCompare(b3.label));
|
|
55019
|
+
const byProject = byProjectAll.slice(0, TOP_PROJECTS);
|
|
55020
|
+
const daily = buildLast30(tokensByDay, now);
|
|
55021
|
+
const rankedModels = [...tokensByModel.entries()].map(([label, tokens]) => ({ label, tokens, total: sumTokens(tokens) })).filter((m2) => m2.total > 0).sort((a3, b3) => b3.total - a3.total || a3.label.localeCompare(b3.label)).slice(0, TOP_PROJECTS);
|
|
55022
|
+
const byModel = rankedModels.map(({ label, total }) => ({ label, tokens: total }));
|
|
55023
|
+
const byModelDetailed = rankedModels.map(({ label, tokens }) => ({ label, tokens }));
|
|
55024
|
+
const cacheDenom = totals.cacheRead + totals.input;
|
|
55025
|
+
const cacheHitRate = cacheDenom > 0 ? totals.cacheRead / cacheDenom : 0;
|
|
55026
|
+
return {
|
|
55027
|
+
schemaVersion: 1,
|
|
55028
|
+
generatedAt: new Date(now).toISOString(),
|
|
55029
|
+
sessionCount: aggregates.length,
|
|
55030
|
+
agentCount,
|
|
55031
|
+
toolCallCount,
|
|
55032
|
+
totals,
|
|
55033
|
+
cacheHitRate,
|
|
55034
|
+
events: {
|
|
55035
|
+
total: eventTotal,
|
|
55036
|
+
perDay,
|
|
55037
|
+
last30: buildLast30(eventsByDay, now)
|
|
55038
|
+
},
|
|
55039
|
+
tokens: {
|
|
55040
|
+
byType: { ...totals },
|
|
55041
|
+
byWeekday: [...tokensByDow.entries()].map(([dow, tokens]) => ({ dow, tokens })).sort((a3, b3) => a3.dow - b3.dow),
|
|
55042
|
+
byProject,
|
|
55043
|
+
daily,
|
|
55044
|
+
byModel,
|
|
55045
|
+
byModelDetailed
|
|
55046
|
+
},
|
|
55047
|
+
window: {
|
|
55048
|
+
earliest: earliestMs === null ? null : new Date(earliestMs).toISOString(),
|
|
55049
|
+
latest: latestMs === null ? null : new Date(latestMs).toISOString(),
|
|
55050
|
+
retentionLimited: earliestMs !== null && earliestMs >= now - PER_DAY_MAX * DAY_MS
|
|
55051
|
+
}
|
|
55052
|
+
};
|
|
55053
|
+
}
|
|
55054
|
+
|
|
54917
55055
|
// src/domains/sessions/adapters/claude.ts
|
|
54918
55056
|
import * as fs15 from "node:fs";
|
|
54919
55057
|
import * as os4 from "node:os";
|
|
@@ -54936,6 +55074,18 @@ function safeJSON(line) {
|
|
|
54936
55074
|
return null;
|
|
54937
55075
|
}
|
|
54938
55076
|
}
|
|
55077
|
+
function peekText(content) {
|
|
55078
|
+
if (typeof content === "string")
|
|
55079
|
+
return content;
|
|
55080
|
+
if (Array.isArray(content)) {
|
|
55081
|
+
return content.filter((it) => it && it.type === "text").map((it) => it.text || "").join(`
|
|
55082
|
+
`);
|
|
55083
|
+
}
|
|
55084
|
+
return "";
|
|
55085
|
+
}
|
|
55086
|
+
function isInterruptText(s) {
|
|
55087
|
+
return /^\s*\[Request interrupted\b/.test(String(s || ""));
|
|
55088
|
+
}
|
|
54939
55089
|
function readNew(transcriptPath, fromOffset) {
|
|
54940
55090
|
if (!transcriptPath || !fs14.existsSync(transcriptPath)) {
|
|
54941
55091
|
return { records: [], newOffset: fromOffset || 0 };
|
|
@@ -55086,18 +55236,6 @@ function decodeProjectDir(name) {
|
|
|
55086
55236
|
p = `/${p}`;
|
|
55087
55237
|
return p.replace(/\/+/g, "/");
|
|
55088
55238
|
}
|
|
55089
|
-
function peekText(c2) {
|
|
55090
|
-
if (typeof c2 === "string")
|
|
55091
|
-
return c2;
|
|
55092
|
-
if (Array.isArray(c2)) {
|
|
55093
|
-
return c2.filter((it) => it && it.type === "text").map((it) => it.text || "").join(`
|
|
55094
|
-
`);
|
|
55095
|
-
}
|
|
55096
|
-
return "";
|
|
55097
|
-
}
|
|
55098
|
-
function isInterruptText(s) {
|
|
55099
|
-
return /^\s*\[Request interrupted\b/.test(String(s || ""));
|
|
55100
|
-
}
|
|
55101
55239
|
function stripCommandTags(s) {
|
|
55102
55240
|
let out = String(s || "");
|
|
55103
55241
|
for (const tag of HARNESS_TAGS) {
|
|
@@ -56171,6 +56309,189 @@ function invalidate() {
|
|
|
56171
56309
|
}
|
|
56172
56310
|
}
|
|
56173
56311
|
|
|
56312
|
+
// src/domains/sessions/transcript-metrics.ts
|
|
56313
|
+
import { basename as basename15, dirname as dirname20, join as join76 } from "node:path";
|
|
56314
|
+
function addModelTokens(byModel, model, t) {
|
|
56315
|
+
if (!model)
|
|
56316
|
+
return;
|
|
56317
|
+
byModel[model] = byModel[model] ? addTokens(byModel[model], t) : { ...t };
|
|
56318
|
+
}
|
|
56319
|
+
function toAggregate(session, m2) {
|
|
56320
|
+
return {
|
|
56321
|
+
startedAt: session.startedAt ?? null,
|
|
56322
|
+
tokens: {
|
|
56323
|
+
input: m2.tokens.input,
|
|
56324
|
+
output: m2.tokens.output,
|
|
56325
|
+
cacheRead: m2.tokens.cacheRead,
|
|
56326
|
+
cacheWrite: m2.tokens.cacheCreate
|
|
56327
|
+
},
|
|
56328
|
+
agentCount: m2.agentCount,
|
|
56329
|
+
toolCallCount: m2.toolCallCount,
|
|
56330
|
+
eventCount: m2.eventCount,
|
|
56331
|
+
projectLabel: session.project ?? "(unknown)",
|
|
56332
|
+
tokensByModel: Object.fromEntries(Object.entries(m2.tokensByModel).map(([model, t]) => [
|
|
56333
|
+
model,
|
|
56334
|
+
{ input: t.input, output: t.output, cacheRead: t.cacheRead, cacheWrite: t.cacheCreate }
|
|
56335
|
+
]))
|
|
56336
|
+
};
|
|
56337
|
+
}
|
|
56338
|
+
function zeroMetrics() {
|
|
56339
|
+
return {
|
|
56340
|
+
tokens: emptyTokens(),
|
|
56341
|
+
tokensByModel: {},
|
|
56342
|
+
agentCount: 0,
|
|
56343
|
+
toolCallCount: 0,
|
|
56344
|
+
eventCount: 0
|
|
56345
|
+
};
|
|
56346
|
+
}
|
|
56347
|
+
function isPromptUser2(r2) {
|
|
56348
|
+
if (!r2 || r2.type !== "user" || r2.isSidechain || r2.isMeta)
|
|
56349
|
+
return false;
|
|
56350
|
+
const c2 = r2.message?.content;
|
|
56351
|
+
if (isInterruptText(peekText(c2)))
|
|
56352
|
+
return false;
|
|
56353
|
+
if (typeof c2 === "string")
|
|
56354
|
+
return c2.length > 0;
|
|
56355
|
+
if (Array.isArray(c2)) {
|
|
56356
|
+
const arr = c2;
|
|
56357
|
+
if (arr.some((it) => it?.type === "tool_result"))
|
|
56358
|
+
return false;
|
|
56359
|
+
return arr.some((it) => it?.type === "text");
|
|
56360
|
+
}
|
|
56361
|
+
return false;
|
|
56362
|
+
}
|
|
56363
|
+
function scanClaudeMetrics(filePath, includeSidechain = false) {
|
|
56364
|
+
const m2 = zeroMetrics();
|
|
56365
|
+
try {
|
|
56366
|
+
const { records } = readNew(filePath, 0);
|
|
56367
|
+
for (const rec of records) {
|
|
56368
|
+
const r2 = rec;
|
|
56369
|
+
if (!r2)
|
|
56370
|
+
continue;
|
|
56371
|
+
const isAssistant = r2.type === "assistant" || r2.message?.role === "assistant";
|
|
56372
|
+
if (isAssistant && (includeSidechain || !r2.isSidechain)) {
|
|
56373
|
+
const tok = tokensOfClaude(rec);
|
|
56374
|
+
if (tok) {
|
|
56375
|
+
m2.tokens = addTokens(m2.tokens, tok);
|
|
56376
|
+
addModelTokens(m2.tokensByModel, r2.message?.model, tok);
|
|
56377
|
+
}
|
|
56378
|
+
const content = r2.message?.content;
|
|
56379
|
+
if (Array.isArray(content)) {
|
|
56380
|
+
for (const it of content) {
|
|
56381
|
+
const block = it;
|
|
56382
|
+
if (block?.type !== "tool_use")
|
|
56383
|
+
continue;
|
|
56384
|
+
m2.toolCallCount += 1;
|
|
56385
|
+
m2.eventCount += 1;
|
|
56386
|
+
if (block.name === "Task")
|
|
56387
|
+
m2.agentCount += 1;
|
|
56388
|
+
}
|
|
56389
|
+
}
|
|
56390
|
+
} else if (isPromptUser2(r2)) {
|
|
56391
|
+
m2.eventCount += 1;
|
|
56392
|
+
}
|
|
56393
|
+
}
|
|
56394
|
+
} catch {
|
|
56395
|
+
return zeroMetrics();
|
|
56396
|
+
}
|
|
56397
|
+
return m2;
|
|
56398
|
+
}
|
|
56399
|
+
function scanCodexMetrics(filePath) {
|
|
56400
|
+
const m2 = zeroMetrics();
|
|
56401
|
+
let currentModel;
|
|
56402
|
+
try {
|
|
56403
|
+
const { records } = readNew(filePath, 0);
|
|
56404
|
+
for (const rec of records) {
|
|
56405
|
+
const r2 = rec;
|
|
56406
|
+
if (!r2)
|
|
56407
|
+
continue;
|
|
56408
|
+
if (r2.type === "turn_context") {
|
|
56409
|
+
if (r2.payload?.model)
|
|
56410
|
+
currentModel = r2.payload.model;
|
|
56411
|
+
} else if (r2.type === "event_msg") {
|
|
56412
|
+
if (r2.payload?.type === "token_count") {
|
|
56413
|
+
const tok = tokensOfCodex(rec);
|
|
56414
|
+
if (tok) {
|
|
56415
|
+
m2.tokens = addTokens(m2.tokens, tok);
|
|
56416
|
+
addModelTokens(m2.tokensByModel, currentModel, tok);
|
|
56417
|
+
}
|
|
56418
|
+
} else if (r2.payload?.type === "user_message") {
|
|
56419
|
+
m2.eventCount += 1;
|
|
56420
|
+
}
|
|
56421
|
+
} else if (r2.type === "response_item" && r2.payload?.type === "function_call") {
|
|
56422
|
+
m2.toolCallCount += 1;
|
|
56423
|
+
m2.eventCount += 1;
|
|
56424
|
+
if (r2.payload?.name === "spawn_agent")
|
|
56425
|
+
m2.agentCount += 1;
|
|
56426
|
+
}
|
|
56427
|
+
}
|
|
56428
|
+
} catch {
|
|
56429
|
+
return zeroMetrics();
|
|
56430
|
+
}
|
|
56431
|
+
return m2;
|
|
56432
|
+
}
|
|
56433
|
+
function scanMetrics(adapterName, filePath) {
|
|
56434
|
+
return adapterName === "codex" ? scanCodexMetrics(filePath) : scanClaudeMetrics(filePath);
|
|
56435
|
+
}
|
|
56436
|
+
function mergeMetrics(a3, b3) {
|
|
56437
|
+
const tokensByModel = { ...a3.tokensByModel };
|
|
56438
|
+
for (const [model, tok] of Object.entries(b3.tokensByModel)) {
|
|
56439
|
+
tokensByModel[model] = tokensByModel[model] ? addTokens(tokensByModel[model], tok) : { ...tok };
|
|
56440
|
+
}
|
|
56441
|
+
return {
|
|
56442
|
+
tokens: addTokens(a3.tokens, b3.tokens),
|
|
56443
|
+
tokensByModel,
|
|
56444
|
+
agentCount: a3.agentCount + b3.agentCount,
|
|
56445
|
+
toolCallCount: a3.toolCallCount + b3.toolCallCount,
|
|
56446
|
+
eventCount: a3.eventCount + b3.eventCount
|
|
56447
|
+
};
|
|
56448
|
+
}
|
|
56449
|
+
function subagentDirFor(mainPath) {
|
|
56450
|
+
const stem = basename15(mainPath).replace(/\.jsonl$/i, "");
|
|
56451
|
+
return join76(dirname20(mainPath), stem, "subagents");
|
|
56452
|
+
}
|
|
56453
|
+
|
|
56454
|
+
// src/domains/sessions/analytics-source.ts
|
|
56455
|
+
var cache2 = null;
|
|
56456
|
+
function scanSessionMetrics(adapterName, mainPath) {
|
|
56457
|
+
const main2 = scanMetrics(adapterName, mainPath);
|
|
56458
|
+
if (adapterName === "codex")
|
|
56459
|
+
return main2;
|
|
56460
|
+
const dir = subagentDirFor(mainPath);
|
|
56461
|
+
let files;
|
|
56462
|
+
try {
|
|
56463
|
+
files = readdirSync6(dir).filter((f3) => f3.endsWith(".jsonl"));
|
|
56464
|
+
} catch {
|
|
56465
|
+
return main2;
|
|
56466
|
+
}
|
|
56467
|
+
let merged = main2;
|
|
56468
|
+
for (const f3 of files) {
|
|
56469
|
+
merged = mergeMetrics(merged, scanClaudeMetrics(join77(dir, f3), true));
|
|
56470
|
+
}
|
|
56471
|
+
return { ...merged, agentCount: main2.agentCount + files.length };
|
|
56472
|
+
}
|
|
56473
|
+
async function readAllAggregates(refresh2 = false) {
|
|
56474
|
+
if (refresh2)
|
|
56475
|
+
invalidate();
|
|
56476
|
+
const sessions = await list({ refresh: refresh2 });
|
|
56477
|
+
const aggregates = [];
|
|
56478
|
+
for (const s of sessions) {
|
|
56479
|
+
try {
|
|
56480
|
+
aggregates.push(toAggregate(s, scanSessionMetrics(s.adapterName, s.path)));
|
|
56481
|
+
} catch {}
|
|
56482
|
+
}
|
|
56483
|
+
return aggregates;
|
|
56484
|
+
}
|
|
56485
|
+
function invalidate2() {
|
|
56486
|
+
cache2 = null;
|
|
56487
|
+
}
|
|
56488
|
+
async function getAnalytics(opts = {}) {
|
|
56489
|
+
if (cache2 && !opts.refresh)
|
|
56490
|
+
return cache2;
|
|
56491
|
+
cache2 = foldAnalytics(await readAllAggregates(opts.refresh), Date.now());
|
|
56492
|
+
return cache2;
|
|
56493
|
+
}
|
|
56494
|
+
|
|
56174
56495
|
// src/domains/sessions/origin-allowlist.ts
|
|
56175
56496
|
init_build_config();
|
|
56176
56497
|
function originOf(url) {
|
|
@@ -56253,6 +56574,14 @@ async function route(req, res, version3) {
|
|
|
56253
56574
|
sendJSON(res, 200, list2);
|
|
56254
56575
|
return;
|
|
56255
56576
|
}
|
|
56577
|
+
if (pathname === "/api/analytics") {
|
|
56578
|
+
const refresh2 = url.searchParams.get("refresh") === "1";
|
|
56579
|
+
if (refresh2)
|
|
56580
|
+
invalidate2();
|
|
56581
|
+
const payload = await getAnalytics({ refresh: refresh2 });
|
|
56582
|
+
sendJSON(res, 200, payload);
|
|
56583
|
+
return;
|
|
56584
|
+
}
|
|
56256
56585
|
const m2 = pathname.match(/^\/api\/sessions\/([^/]+)\/state$/);
|
|
56257
56586
|
if (m2?.[1]) {
|
|
56258
56587
|
const id = decodeURIComponent(m2[1]);
|
|
@@ -57502,7 +57831,7 @@ init_takumi_constants();
|
|
|
57502
57831
|
import { existsSync as existsSync35, realpathSync } from "node:fs";
|
|
57503
57832
|
import { chmod as chmod2, mkdir as mkdir18, readFile as readFile32, writeFile as writeFile22 } from "node:fs/promises";
|
|
57504
57833
|
import { platform as platform5 } from "node:os";
|
|
57505
|
-
import { join as
|
|
57834
|
+
import { join as join78 } from "node:path";
|
|
57506
57835
|
var CACHE_FILE = "install-info.json";
|
|
57507
57836
|
var CACHE_TTL = 30 * 24 * 60 * 60 * 1000;
|
|
57508
57837
|
function detectFromBinaryPath() {
|
|
@@ -57586,7 +57915,7 @@ function detectFromEnv() {
|
|
|
57586
57915
|
}
|
|
57587
57916
|
async function readCachedPm() {
|
|
57588
57917
|
try {
|
|
57589
|
-
const cacheFile =
|
|
57918
|
+
const cacheFile = join78(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
57590
57919
|
if (!existsSync35(cacheFile)) {
|
|
57591
57920
|
return null;
|
|
57592
57921
|
}
|
|
@@ -57617,7 +57946,7 @@ async function saveCachedPm(pm, getVersion) {
|
|
|
57617
57946
|
return;
|
|
57618
57947
|
try {
|
|
57619
57948
|
const configDir = PathResolver.getConfigDir(false);
|
|
57620
|
-
const cacheFile =
|
|
57949
|
+
const cacheFile = join78(configDir, CACHE_FILE);
|
|
57621
57950
|
if (!existsSync35(configDir)) {
|
|
57622
57951
|
await mkdir18(configDir, { recursive: true });
|
|
57623
57952
|
if (platform5() !== "win32") {
|
|
@@ -57680,7 +58009,7 @@ async function findOwningPm() {
|
|
|
57680
58009
|
async function clearCache() {
|
|
57681
58010
|
try {
|
|
57682
58011
|
const { unlink: unlink7 } = await import("node:fs/promises");
|
|
57683
|
-
const cacheFile =
|
|
58012
|
+
const cacheFile = join78(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
57684
58013
|
if (existsSync35(cacheFile)) {
|
|
57685
58014
|
await unlink7(cacheFile);
|
|
57686
58015
|
logger.debug("Package manager cache cleared");
|
|
@@ -57942,17 +58271,17 @@ async function checkCliVersion() {
|
|
|
57942
58271
|
init_paths();
|
|
57943
58272
|
init_registry();
|
|
57944
58273
|
import { existsSync as existsSync36, statSync as statSync5 } from "node:fs";
|
|
57945
|
-
import { join as
|
|
58274
|
+
import { join as join79 } from "node:path";
|
|
57946
58275
|
function checkClaudeMd(setup, projectDir) {
|
|
57947
58276
|
const results = [];
|
|
57948
58277
|
const claudeCodeInstaller2 = getInstaller("claude-code");
|
|
57949
58278
|
if (claudeCodeInstaller2?.isInstalledGlobally()) {
|
|
57950
58279
|
const claudeGlobal = setup.globals.find((g2) => g2.provider === "claude-code") ?? setup.globals[0];
|
|
57951
58280
|
const globalPath = claudeGlobal?.path ?? claudeCodeInstaller2.globalRoot();
|
|
57952
|
-
const globalClaudeMd =
|
|
58281
|
+
const globalClaudeMd = join79(globalPath, "CLAUDE.md");
|
|
57953
58282
|
results.push(checkClaudeMdFile(globalClaudeMd, "Global CLAUDE.md", "sk-global-claude-md"));
|
|
57954
58283
|
}
|
|
57955
|
-
const projectClaudeMd =
|
|
58284
|
+
const projectClaudeMd = join79(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
57956
58285
|
results.push(checkClaudeMdFile(projectClaudeMd, "Project CLAUDE.md", "sk-project-claude-md"));
|
|
57957
58286
|
return results;
|
|
57958
58287
|
}
|
|
@@ -58011,9 +58340,9 @@ function checkClaudeMdFile(path9, name, id) {
|
|
|
58011
58340
|
}
|
|
58012
58341
|
// src/domains/health-checks/checkers/active-plan-checker.ts
|
|
58013
58342
|
import { existsSync as existsSync37, readFileSync as readFileSync10 } from "node:fs";
|
|
58014
|
-
import { join as
|
|
58343
|
+
import { join as join80 } from "node:path";
|
|
58015
58344
|
function checkActivePlan(projectDir) {
|
|
58016
|
-
const activePlanPath =
|
|
58345
|
+
const activePlanPath = join80(projectDir, ".claude", "active-plan");
|
|
58017
58346
|
if (!existsSync37(activePlanPath)) {
|
|
58018
58347
|
return {
|
|
58019
58348
|
id: "sk-active-plan",
|
|
@@ -58027,7 +58356,7 @@ function checkActivePlan(projectDir) {
|
|
|
58027
58356
|
}
|
|
58028
58357
|
try {
|
|
58029
58358
|
const targetPath = readFileSync10(activePlanPath, "utf-8").trim();
|
|
58030
|
-
const fullPath =
|
|
58359
|
+
const fullPath = join80(projectDir, targetPath);
|
|
58031
58360
|
if (!existsSync37(fullPath)) {
|
|
58032
58361
|
return {
|
|
58033
58362
|
id: "sk-active-plan",
|
|
@@ -58093,7 +58422,7 @@ function checkComponentCounts(setup) {
|
|
|
58093
58422
|
init_registry();
|
|
58094
58423
|
init_logger();
|
|
58095
58424
|
import { constants, access, unlink as unlink7, writeFile as writeFile23 } from "node:fs/promises";
|
|
58096
|
-
import { join as
|
|
58425
|
+
import { join as join81 } from "node:path";
|
|
58097
58426
|
|
|
58098
58427
|
// src/domains/health-checks/checkers/shared.ts
|
|
58099
58428
|
init_registry();
|
|
@@ -58168,7 +58497,7 @@ async function checkGlobalDirWritable(provider) {
|
|
|
58168
58497
|
}
|
|
58169
58498
|
const timestamp = Date.now();
|
|
58170
58499
|
const random = Math.random().toString(36).substring(2);
|
|
58171
|
-
const testFile =
|
|
58500
|
+
const testFile = join81(globalDir, `.sk-write-test-${timestamp}-${random}`);
|
|
58172
58501
|
try {
|
|
58173
58502
|
await writeFile23(testFile, "test", { encoding: "utf-8", flag: "wx" });
|
|
58174
58503
|
} catch (_error) {
|
|
@@ -58205,7 +58534,7 @@ init_paths();
|
|
|
58205
58534
|
init_registry();
|
|
58206
58535
|
import { existsSync as existsSync38 } from "node:fs";
|
|
58207
58536
|
import { readdir as readdir23 } from "node:fs/promises";
|
|
58208
|
-
import { join as
|
|
58537
|
+
import { join as join82 } from "node:path";
|
|
58209
58538
|
|
|
58210
58539
|
// src/domains/health-checks/utils/path-normalizer.ts
|
|
58211
58540
|
import { normalize as normalize6 } from "node:path";
|
|
@@ -58217,8 +58546,8 @@ function normalizePath(filePath) {
|
|
|
58217
58546
|
|
|
58218
58547
|
// src/domains/health-checks/checkers/hooks-checker.ts
|
|
58219
58548
|
async function checkHooksExist(projectDir) {
|
|
58220
|
-
const globalHooksDir =
|
|
58221
|
-
const projectHooksDir =
|
|
58549
|
+
const globalHooksDir = join82(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
|
|
58550
|
+
const projectHooksDir = join82(getLocalClaudeDir(projectDir), "hooks");
|
|
58222
58551
|
const globalExists = existsSync38(globalHooksDir);
|
|
58223
58552
|
const projectExists = existsSync38(projectHooksDir);
|
|
58224
58553
|
let hookCount = 0;
|
|
@@ -58227,7 +58556,7 @@ async function checkHooksExist(projectDir) {
|
|
|
58227
58556
|
const files = await readdir23(globalHooksDir, { withFileTypes: false });
|
|
58228
58557
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
|
|
58229
58558
|
hooks.forEach((hook) => {
|
|
58230
|
-
const fullPath =
|
|
58559
|
+
const fullPath = join82(globalHooksDir, hook);
|
|
58231
58560
|
checkedFiles.add(normalizePath(fullPath));
|
|
58232
58561
|
});
|
|
58233
58562
|
}
|
|
@@ -58237,7 +58566,7 @@ async function checkHooksExist(projectDir) {
|
|
|
58237
58566
|
const files = await readdir23(projectHooksDir, { withFileTypes: false });
|
|
58238
58567
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
|
|
58239
58568
|
hooks.forEach((hook) => {
|
|
58240
|
-
const fullPath =
|
|
58569
|
+
const fullPath = join82(projectHooksDir, hook);
|
|
58241
58570
|
checkedFiles.add(normalizePath(fullPath));
|
|
58242
58571
|
});
|
|
58243
58572
|
}
|
|
@@ -58268,14 +58597,14 @@ async function checkHooksExist(projectDir) {
|
|
|
58268
58597
|
init_registry();
|
|
58269
58598
|
import { existsSync as existsSync39 } from "node:fs";
|
|
58270
58599
|
import { readFile as readFile33 } from "node:fs/promises";
|
|
58271
|
-
import { join as
|
|
58600
|
+
import { join as join83 } from "node:path";
|
|
58272
58601
|
async function checkCodexHooksHealth() {
|
|
58273
58602
|
const codex = getInstaller("codex");
|
|
58274
58603
|
if (!codex?.isInstalledGlobally())
|
|
58275
58604
|
return [];
|
|
58276
58605
|
const codexRoot = codex.globalRoot();
|
|
58277
|
-
const configTomlPath =
|
|
58278
|
-
const hooksJsonPath =
|
|
58606
|
+
const configTomlPath = join83(codexRoot, "config.toml");
|
|
58607
|
+
const hooksJsonPath = join83(codexRoot, "hooks.json");
|
|
58279
58608
|
if (!existsSync39(hooksJsonPath))
|
|
58280
58609
|
return [];
|
|
58281
58610
|
const results = [];
|
|
@@ -58355,10 +58684,10 @@ init_registry();
|
|
|
58355
58684
|
init_logger();
|
|
58356
58685
|
import { existsSync as existsSync40 } from "node:fs";
|
|
58357
58686
|
import { readFile as readFile34 } from "node:fs/promises";
|
|
58358
|
-
import { join as
|
|
58687
|
+
import { join as join84 } from "node:path";
|
|
58359
58688
|
async function checkSettingsValid(projectDir) {
|
|
58360
|
-
const globalSettings =
|
|
58361
|
-
const projectSettings =
|
|
58689
|
+
const globalSettings = join84(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
|
|
58690
|
+
const projectSettings = join84(getLocalClaudeDir(projectDir), "settings.json");
|
|
58362
58691
|
const settingsPath = existsSync40(globalSettings) ? globalSettings : existsSync40(projectSettings) ? projectSettings : null;
|
|
58363
58692
|
if (!settingsPath) {
|
|
58364
58693
|
return {
|
|
@@ -58432,10 +58761,10 @@ init_logger();
|
|
|
58432
58761
|
import { existsSync as existsSync41 } from "node:fs";
|
|
58433
58762
|
import { readFile as readFile35 } from "node:fs/promises";
|
|
58434
58763
|
import { homedir as homedir24 } from "node:os";
|
|
58435
|
-
import { dirname as
|
|
58764
|
+
import { dirname as dirname21, join as join85, normalize as normalize7, resolve as resolve19 } from "node:path";
|
|
58436
58765
|
async function checkPathRefsValid(projectDir) {
|
|
58437
|
-
const globalClaudeMd =
|
|
58438
|
-
const projectClaudeMd =
|
|
58766
|
+
const globalClaudeMd = join85(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
|
|
58767
|
+
const projectClaudeMd = join85(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
58439
58768
|
const claudeMdPath = existsSync41(globalClaudeMd) ? globalClaudeMd : existsSync41(projectClaudeMd) ? projectClaudeMd : null;
|
|
58440
58769
|
if (!claudeMdPath) {
|
|
58441
58770
|
return {
|
|
@@ -58463,7 +58792,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
58463
58792
|
autoFixable: false
|
|
58464
58793
|
};
|
|
58465
58794
|
}
|
|
58466
|
-
const baseDir =
|
|
58795
|
+
const baseDir = dirname21(claudeMdPath);
|
|
58467
58796
|
const home6 = homedir24();
|
|
58468
58797
|
const broken = [];
|
|
58469
58798
|
for (const ref of refs) {
|
|
@@ -58531,7 +58860,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
58531
58860
|
init_paths();
|
|
58532
58861
|
import { existsSync as existsSync42 } from "node:fs";
|
|
58533
58862
|
import { readdir as readdir24 } from "node:fs/promises";
|
|
58534
|
-
import { join as
|
|
58863
|
+
import { join as join86 } from "node:path";
|
|
58535
58864
|
async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
58536
58865
|
if (setup.globals.some((g2) => g2.path === setup.project.path)) {
|
|
58537
58866
|
return {
|
|
@@ -58548,12 +58877,12 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
|
58548
58877
|
const requiredDirs = ["agents", "commands", "skills"];
|
|
58549
58878
|
const missingDirs = [];
|
|
58550
58879
|
for (const dir of requiredDirs) {
|
|
58551
|
-
const dirPath =
|
|
58880
|
+
const dirPath = join86(projectClaudeDir, dir);
|
|
58552
58881
|
if (!existsSync42(dirPath)) {
|
|
58553
58882
|
missingDirs.push(dir);
|
|
58554
58883
|
}
|
|
58555
58884
|
}
|
|
58556
|
-
const hasRulesOrWorkflows = existsSync42(
|
|
58885
|
+
const hasRulesOrWorkflows = existsSync42(join86(projectClaudeDir, "rules")) || existsSync42(join86(projectClaudeDir, "workflows"));
|
|
58557
58886
|
if (!hasRulesOrWorkflows) {
|
|
58558
58887
|
missingDirs.push("rules");
|
|
58559
58888
|
}
|
|
@@ -58994,7 +59323,7 @@ init_registry();
|
|
|
58994
59323
|
init_environment();
|
|
58995
59324
|
import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile36, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
|
|
58996
59325
|
import { arch as arch2, homedir as homedir25, platform as platform6 } from "node:os";
|
|
58997
|
-
import { join as
|
|
59326
|
+
import { join as join88, normalize as normalize8 } from "node:path";
|
|
58998
59327
|
function shouldSkipExpensiveOperations4() {
|
|
58999
59328
|
return shouldSkipExpensiveOperations();
|
|
59000
59329
|
}
|
|
@@ -59087,7 +59416,7 @@ async function checkGlobalDirAccess(provider) {
|
|
|
59087
59416
|
autoFixable: false
|
|
59088
59417
|
};
|
|
59089
59418
|
}
|
|
59090
|
-
const testFile =
|
|
59419
|
+
const testFile = join88(globalDir, ".sk-doctor-access-test");
|
|
59091
59420
|
try {
|
|
59092
59421
|
await mkdir19(globalDir, { recursive: true });
|
|
59093
59422
|
await writeFile24(testFile, "test", "utf-8");
|
|
@@ -59165,7 +59494,7 @@ async function checkWSLBoundary() {
|
|
|
59165
59494
|
// src/domains/health-checks/platform/windows-checker.ts
|
|
59166
59495
|
init_registry();
|
|
59167
59496
|
import { mkdir as mkdir20, symlink as symlink2, unlink as unlink9, writeFile as writeFile25 } from "node:fs/promises";
|
|
59168
|
-
import { join as
|
|
59497
|
+
import { join as join89 } from "node:path";
|
|
59169
59498
|
async function checkLongPathSupport() {
|
|
59170
59499
|
if (shouldSkipExpensiveOperations4()) {
|
|
59171
59500
|
return {
|
|
@@ -59217,8 +59546,8 @@ async function checkSymlinkSupport() {
|
|
|
59217
59546
|
};
|
|
59218
59547
|
}
|
|
59219
59548
|
const testDir = getInstaller("claude-code")?.globalRoot() ?? "";
|
|
59220
|
-
const target =
|
|
59221
|
-
const link =
|
|
59549
|
+
const target = join89(testDir, ".sk-symlink-test-target");
|
|
59550
|
+
const link = join89(testDir, ".sk-symlink-test-link");
|
|
59222
59551
|
try {
|
|
59223
59552
|
await mkdir20(testDir, { recursive: true });
|
|
59224
59553
|
await writeFile25(target, "test", "utf-8");
|
|
@@ -59514,15 +59843,15 @@ class AutoHealer {
|
|
|
59514
59843
|
import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
|
|
59515
59844
|
import { readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
59516
59845
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
59517
|
-
import { dirname as
|
|
59846
|
+
import { dirname as dirname22, join as join90 } from "node:path";
|
|
59518
59847
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
59519
59848
|
init_environment();
|
|
59520
59849
|
init_logger();
|
|
59521
59850
|
init_dist2();
|
|
59522
59851
|
function getCliVersion3() {
|
|
59523
59852
|
try {
|
|
59524
|
-
const __dirname3 =
|
|
59525
|
-
const pkgPath =
|
|
59853
|
+
const __dirname3 = dirname22(fileURLToPath2(import.meta.url));
|
|
59854
|
+
const pkgPath = join90(__dirname3, "../../../package.json");
|
|
59526
59855
|
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
59527
59856
|
return pkg.version || "unknown";
|
|
59528
59857
|
} catch (err) {
|
|
@@ -59661,7 +59990,7 @@ class ReportGenerator {
|
|
|
59661
59990
|
return null;
|
|
59662
59991
|
}
|
|
59663
59992
|
}
|
|
59664
|
-
const tmpFile =
|
|
59993
|
+
const tmpFile = join90(tmpdir2(), `sk-report-${Date.now()}.txt`);
|
|
59665
59994
|
writeFileSync6(tmpFile, report);
|
|
59666
59995
|
try {
|
|
59667
59996
|
const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "Takumi Diagnostic Report"], {
|
|
@@ -59986,7 +60315,7 @@ import { execSync as execSync5 } from "node:child_process";
|
|
|
59986
60315
|
// src/domains/hooks/handlers/_shared/env-file.ts
|
|
59987
60316
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
59988
60317
|
import { renameSync as renameSync2, unlinkSync as unlinkSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
59989
|
-
import { basename as
|
|
60318
|
+
import { basename as basename16, dirname as dirname23, join as join91 } from "node:path";
|
|
59990
60319
|
function hexEscape(code) {
|
|
59991
60320
|
return `\\x${code.toString(16).padStart(2, "0")}`;
|
|
59992
60321
|
}
|
|
@@ -60038,8 +60367,8 @@ function renderEnvFile(entries) {
|
|
|
60038
60367
|
}
|
|
60039
60368
|
function writeEnvFile(filePath, entries) {
|
|
60040
60369
|
const content = renderEnvFile(entries);
|
|
60041
|
-
const dir =
|
|
60042
|
-
const tmpPath =
|
|
60370
|
+
const dir = dirname23(filePath);
|
|
60371
|
+
const tmpPath = join91(dir, `.${basename16(filePath)}.${randomUUID2()}.tmp`);
|
|
60043
60372
|
try {
|
|
60044
60373
|
writeFileSync7(tmpPath, content, { encoding: "utf8", mode: 384 });
|
|
60045
60374
|
} catch (err) {
|
|
@@ -60087,10 +60416,10 @@ var defaultCommandRunner = (command, opts) => {
|
|
|
60087
60416
|
// src/domains/hooks/handlers/convention-quality-gate/debounce.ts
|
|
60088
60417
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
60089
60418
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
60090
|
-
import { join as
|
|
60419
|
+
import { join as join92 } from "node:path";
|
|
60091
60420
|
function stateFilePath(sessionId) {
|
|
60092
60421
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 128) || "default";
|
|
60093
|
-
return
|
|
60422
|
+
return join92(tmpdir3(), `takumi-guardrail-${safe}.json`);
|
|
60094
60423
|
}
|
|
60095
60424
|
function isWithinDebounce(sessionId, debounceMs, now) {
|
|
60096
60425
|
try {
|
|
@@ -60515,7 +60844,7 @@ function detectBroadGlob(pattern, pathHint) {
|
|
|
60515
60844
|
// src/domains/hooks/handlers/guard-breadth-scout/check-ignore.ts
|
|
60516
60845
|
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
60517
60846
|
import { existsSync as existsSync44, readFileSync as readFileSync13 } from "node:fs";
|
|
60518
|
-
import { dirname as
|
|
60847
|
+
import { dirname as dirname24, join as join93 } from "node:path";
|
|
60519
60848
|
var BUILTIN_HEAVY_DIR_LINES = [
|
|
60520
60849
|
"node_modules",
|
|
60521
60850
|
".pnp",
|
|
@@ -60552,9 +60881,9 @@ var BUILTIN_HEAVY_DIR_LINES = [
|
|
|
60552
60881
|
function findGitRoot(startDir) {
|
|
60553
60882
|
let dir = startDir;
|
|
60554
60883
|
while (true) {
|
|
60555
|
-
if (existsSync44(
|
|
60884
|
+
if (existsSync44(join93(dir, ".git")))
|
|
60556
60885
|
return dir;
|
|
60557
|
-
const parent =
|
|
60886
|
+
const parent = dirname24(dir);
|
|
60558
60887
|
if (parent === dir)
|
|
60559
60888
|
return null;
|
|
60560
60889
|
dir = parent;
|
|
@@ -60582,11 +60911,11 @@ function loadIgnoreConfig(cwd2) {
|
|
|
60582
60911
|
const gitRoot = findGitRoot(cwd2);
|
|
60583
60912
|
const candidatePaths = [];
|
|
60584
60913
|
if (gitRoot) {
|
|
60585
|
-
candidatePaths.push(
|
|
60586
|
-
candidatePaths.push(
|
|
60914
|
+
candidatePaths.push(join93(gitRoot, ".claude", ".tkmignore"));
|
|
60915
|
+
candidatePaths.push(join93(gitRoot, ".claude", ".skignore"));
|
|
60587
60916
|
}
|
|
60588
|
-
candidatePaths.push(
|
|
60589
|
-
candidatePaths.push(
|
|
60917
|
+
candidatePaths.push(join93(cwd2, ".claude", ".tkmignore"));
|
|
60918
|
+
candidatePaths.push(join93(cwd2, ".claude", ".skignore"));
|
|
60590
60919
|
for (const candidate of candidatePaths) {
|
|
60591
60920
|
const lines = readIgnoreFile(candidate);
|
|
60592
60921
|
if (lines !== null) {
|
|
@@ -61050,10 +61379,10 @@ function getBasename(normalized) {
|
|
|
61050
61379
|
function isSensitivePath(normalized) {
|
|
61051
61380
|
if (!normalized)
|
|
61052
61381
|
return false;
|
|
61053
|
-
const
|
|
61054
|
-
if (SAFE_LIST_RE.test(
|
|
61382
|
+
const basename17 = getBasename(normalized);
|
|
61383
|
+
if (SAFE_LIST_RE.test(basename17))
|
|
61055
61384
|
return false;
|
|
61056
|
-
return SENSITIVE_CATEGORY_PATTERNS.some((re2) => re2.test(
|
|
61385
|
+
return SENSITIVE_CATEGORY_PATTERNS.some((re2) => re2.test(basename17) || re2.test(normalized));
|
|
61057
61386
|
}
|
|
61058
61387
|
function normalizeForMatch(raw) {
|
|
61059
61388
|
let value = raw;
|
|
@@ -61134,20 +61463,20 @@ function findFirstRelevantPath(candidates) {
|
|
|
61134
61463
|
}
|
|
61135
61464
|
return null;
|
|
61136
61465
|
}
|
|
61137
|
-
function buildApprovalPayload(file,
|
|
61466
|
+
function buildApprovalPayload(file, basename17) {
|
|
61138
61467
|
return {
|
|
61139
61468
|
type: "SECRET_READ_REQUEST",
|
|
61140
61469
|
file,
|
|
61141
|
-
basename:
|
|
61470
|
+
basename: basename17,
|
|
61142
61471
|
question: {
|
|
61143
61472
|
header: "Secret-bearing file",
|
|
61144
|
-
text: `"${
|
|
61473
|
+
text: `"${basename17}" looks like it stores credentials or secrets. Should the agent be allowed to read it?`,
|
|
61145
61474
|
options: [
|
|
61146
61475
|
{
|
|
61147
61476
|
label: "Approve",
|
|
61148
|
-
description: `Allow reading "${
|
|
61477
|
+
description: `Allow reading "${basename17}" once, then retry with that approval.`
|
|
61149
61478
|
},
|
|
61150
|
-
{ label: "Decline", description: `Keep "${
|
|
61479
|
+
{ label: "Decline", description: `Keep "${basename17}" blocked and do not read it.` }
|
|
61151
61480
|
]
|
|
61152
61481
|
}
|
|
61153
61482
|
};
|
|
@@ -61283,7 +61612,7 @@ function resolveEndpoint() {
|
|
|
61283
61612
|
init_manifest_path_resolver();
|
|
61284
61613
|
import { existsSync as existsSync45, readFileSync as readFileSync14 } from "node:fs";
|
|
61285
61614
|
import { homedir as homedir26 } from "node:os";
|
|
61286
|
-
import { dirname as
|
|
61615
|
+
import { dirname as dirname25, join as join94, resolve as resolve20 } from "node:path";
|
|
61287
61616
|
var PROVIDER_DIRS = [".claude", ".codex"];
|
|
61288
61617
|
var MAX_WALK = 6;
|
|
61289
61618
|
function readManifestRaw(path11) {
|
|
@@ -61302,25 +61631,25 @@ function findManifest(cwd2) {
|
|
|
61302
61631
|
let dir = resolve20(cwd2);
|
|
61303
61632
|
for (let i = 0;i < MAX_WALK; i++) {
|
|
61304
61633
|
for (const provider of PROVIDER_DIRS) {
|
|
61305
|
-
const providerRoot =
|
|
61634
|
+
const providerRoot = join94(dir, provider);
|
|
61306
61635
|
if (existsSync45(providerRoot)) {
|
|
61307
61636
|
const path11 = findManifestInProviderDir(providerRoot);
|
|
61308
61637
|
if (path11)
|
|
61309
61638
|
return path11;
|
|
61310
61639
|
}
|
|
61311
61640
|
}
|
|
61312
|
-
const parent =
|
|
61641
|
+
const parent = dirname25(dir);
|
|
61313
61642
|
if (parent === dir)
|
|
61314
61643
|
break;
|
|
61315
61644
|
dir = parent;
|
|
61316
61645
|
}
|
|
61317
61646
|
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
|
|
61318
61647
|
if (pluginRoot) {
|
|
61319
|
-
const pluginPath = findManifestInProviderDir(
|
|
61648
|
+
const pluginPath = findManifestInProviderDir(join94(pluginRoot, ".claude"));
|
|
61320
61649
|
if (pluginPath)
|
|
61321
61650
|
return pluginPath;
|
|
61322
61651
|
}
|
|
61323
|
-
const globalPath = findManifestInProviderDir(
|
|
61652
|
+
const globalPath = findManifestInProviderDir(join94(homedir26(), ".claude"));
|
|
61324
61653
|
if (globalPath)
|
|
61325
61654
|
return globalPath;
|
|
61326
61655
|
return null;
|
|
@@ -61412,7 +61741,7 @@ async function readStdinJson() {
|
|
|
61412
61741
|
// src/domains/hooks/telemetry/lib/detached-put.ts
|
|
61413
61742
|
import { spawn as spawn2 } from "node:child_process";
|
|
61414
61743
|
import { openSync as openSync4 } from "node:fs";
|
|
61415
|
-
import { dirname as
|
|
61744
|
+
import { dirname as dirname26, join as join95 } from "node:path";
|
|
61416
61745
|
var ALLOWED_ENV_PREFIXES = ["TKM_", "TAKUMI_"];
|
|
61417
61746
|
var ALLOWED_ENV_KEYS = new Set(["HOME", "USERPROFILE", "PATH", "NODE_ENV"]);
|
|
61418
61747
|
var DETACH_DEBUG_LOG_NAME = "detach-debug.log";
|
|
@@ -61420,7 +61749,7 @@ function effectiveDetachMode(flags) {
|
|
|
61420
61749
|
return flags.noDetach ? "inline" : "detached";
|
|
61421
61750
|
}
|
|
61422
61751
|
function sessionDebugLogPath(sessionDir) {
|
|
61423
|
-
return
|
|
61752
|
+
return join95(sessionDir, DETACH_DEBUG_LOG_NAME);
|
|
61424
61753
|
}
|
|
61425
61754
|
var BUNFS_PREFIX = "/$bunfs/";
|
|
61426
61755
|
function resolveInvocationPrefix() {
|
|
@@ -61448,9 +61777,9 @@ function resolveInvocationPrefix() {
|
|
|
61448
61777
|
}
|
|
61449
61778
|
function resolvePreloadScript(entryPath) {
|
|
61450
61779
|
try {
|
|
61451
|
-
const srcDir =
|
|
61452
|
-
const repoRoot =
|
|
61453
|
-
return
|
|
61780
|
+
const srcDir = dirname26(entryPath);
|
|
61781
|
+
const repoRoot = dirname26(srcDir);
|
|
61782
|
+
return join95(repoRoot, "scripts", "preload-config-override.ts");
|
|
61454
61783
|
} catch {
|
|
61455
61784
|
return null;
|
|
61456
61785
|
}
|
|
@@ -61522,13 +61851,13 @@ import { promises as fs20 } from "node:fs";
|
|
|
61522
61851
|
|
|
61523
61852
|
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
61524
61853
|
init_paths2();
|
|
61525
|
-
import { join as
|
|
61854
|
+
import { join as join97 } from "node:path";
|
|
61526
61855
|
|
|
61527
61856
|
// src/shared/project-paths.ts
|
|
61528
61857
|
init_paths2();
|
|
61529
61858
|
import { createHash as createHash9 } from "node:crypto";
|
|
61530
61859
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
61531
|
-
import { basename as
|
|
61860
|
+
import { basename as basename17, join as join96 } from "node:path";
|
|
61532
61861
|
function encodeCwd(cwd2) {
|
|
61533
61862
|
const stripped = cwd2.replace(/^\/+/, "");
|
|
61534
61863
|
const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
@@ -61544,13 +61873,13 @@ function computeProjectHash(cwd2) {
|
|
|
61544
61873
|
return createHash9("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
61545
61874
|
}
|
|
61546
61875
|
function getProjectLabel(cwd2) {
|
|
61547
|
-
return
|
|
61876
|
+
return basename17(cwd2) || "";
|
|
61548
61877
|
}
|
|
61549
61878
|
function getProjectsRoot() {
|
|
61550
|
-
return
|
|
61879
|
+
return join96(getConfigDir(), "projects");
|
|
61551
61880
|
}
|
|
61552
61881
|
function getProjectDir(args) {
|
|
61553
|
-
return
|
|
61882
|
+
return join96(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
|
|
61554
61883
|
}
|
|
61555
61884
|
|
|
61556
61885
|
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
@@ -61562,35 +61891,35 @@ function safeSessionSegment(sessionId) {
|
|
|
61562
61891
|
return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
|
|
61563
61892
|
}
|
|
61564
61893
|
function getSessionsRoot() {
|
|
61565
|
-
return
|
|
61894
|
+
return join97(getConfigDir(), "sessions");
|
|
61566
61895
|
}
|
|
61567
61896
|
function getSessionDirV2(args) {
|
|
61568
61897
|
const segment = safeSessionSegment(args.sessionId);
|
|
61569
61898
|
if (!segment)
|
|
61570
61899
|
return null;
|
|
61571
|
-
return
|
|
61900
|
+
return join97(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
|
|
61572
61901
|
}
|
|
61573
61902
|
function getEventsFile(sessionDir) {
|
|
61574
|
-
return
|
|
61903
|
+
return join97(sessionDir, "events.jsonl");
|
|
61575
61904
|
}
|
|
61576
61905
|
function getSummaryFile(sessionDir) {
|
|
61577
|
-
return
|
|
61906
|
+
return join97(sessionDir, "summary.json");
|
|
61578
61907
|
}
|
|
61579
61908
|
function getLastPushFile(sessionDir) {
|
|
61580
|
-
return
|
|
61909
|
+
return join97(sessionDir, "last_push.txt");
|
|
61581
61910
|
}
|
|
61582
61911
|
var OBSERVATIONS_FILENAME = "observations.jsonl";
|
|
61583
61912
|
function getObservationsFile(sessionDir) {
|
|
61584
|
-
return
|
|
61913
|
+
return join97(sessionDir, OBSERVATIONS_FILENAME);
|
|
61585
61914
|
}
|
|
61586
61915
|
function getObservationsFlushingFile(sessionDir) {
|
|
61587
|
-
return
|
|
61916
|
+
return join97(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
|
|
61588
61917
|
}
|
|
61589
61918
|
function getObservationsPushedFile(sessionDir) {
|
|
61590
|
-
return
|
|
61919
|
+
return join97(sessionDir, "obs_pushed.txt");
|
|
61591
61920
|
}
|
|
61592
61921
|
function getMetaFile(sessionDir) {
|
|
61593
|
-
return
|
|
61922
|
+
return join97(sessionDir, "meta.json");
|
|
61594
61923
|
}
|
|
61595
61924
|
|
|
61596
61925
|
// src/domains/hooks/telemetry/lib/session-meta.ts
|
|
@@ -61762,7 +62091,7 @@ async function shouldFlush(args) {
|
|
|
61762
62091
|
}
|
|
61763
62092
|
|
|
61764
62093
|
// src/domains/hooks/telemetry/lib/transcript-reader.ts
|
|
61765
|
-
function
|
|
62094
|
+
function num2(v2) {
|
|
61766
62095
|
return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
61767
62096
|
}
|
|
61768
62097
|
function zeroTokens2() {
|
|
@@ -61781,10 +62110,10 @@ function extractTokens(record) {
|
|
|
61781
62110
|
if (!usage)
|
|
61782
62111
|
return null;
|
|
61783
62112
|
return {
|
|
61784
|
-
input:
|
|
61785
|
-
output:
|
|
61786
|
-
cache_read:
|
|
61787
|
-
cache_write:
|
|
62113
|
+
input: num2(usage.input_tokens),
|
|
62114
|
+
output: num2(usage.output_tokens),
|
|
62115
|
+
cache_read: num2(usage.cache_read_input_tokens),
|
|
62116
|
+
cache_write: num2(usage.cache_creation_input_tokens)
|
|
61788
62117
|
};
|
|
61789
62118
|
}
|
|
61790
62119
|
async function tailRead(args) {
|
|
@@ -61919,8 +62248,8 @@ async function runSessionEndFlush(data, ctx) {
|
|
|
61919
62248
|
session_end_raw: data
|
|
61920
62249
|
};
|
|
61921
62250
|
const { promises: fs23 } = await import("node:fs");
|
|
61922
|
-
const { join:
|
|
61923
|
-
const target =
|
|
62251
|
+
const { join: join98 } = await import("node:path");
|
|
62252
|
+
const target = join98(sessionDir, "meta.json");
|
|
61924
62253
|
const tmp = `${target}.tmp`;
|
|
61925
62254
|
await fs23.writeFile(tmp, JSON.stringify(updated), "utf8");
|
|
61926
62255
|
await fs23.rename(tmp, target);
|
|
@@ -61995,17 +62324,17 @@ init_takumi_constants();
|
|
|
61995
62324
|
|
|
61996
62325
|
// src/domains/hooks/lib/jsonl-append.ts
|
|
61997
62326
|
import { promises as fs23, appendFileSync as appendFileSync2, mkdirSync as mkdirSync4 } from "node:fs";
|
|
61998
|
-
import { dirname as
|
|
62327
|
+
import { dirname as dirname27 } from "node:path";
|
|
61999
62328
|
async function appendJsonl(filePath, record) {
|
|
62000
62329
|
try {
|
|
62001
|
-
await fs23.mkdir(
|
|
62330
|
+
await fs23.mkdir(dirname27(filePath), { recursive: true });
|
|
62002
62331
|
await fs23.appendFile(filePath, `${JSON.stringify(record)}
|
|
62003
62332
|
`, "utf8");
|
|
62004
62333
|
} catch {}
|
|
62005
62334
|
}
|
|
62006
62335
|
function appendJsonlLineSync(filePath, line) {
|
|
62007
62336
|
try {
|
|
62008
|
-
mkdirSync4(
|
|
62337
|
+
mkdirSync4(dirname27(filePath), { recursive: true });
|
|
62009
62338
|
appendFileSync2(filePath, `${line}
|
|
62010
62339
|
`, "utf8");
|
|
62011
62340
|
} catch {}
|
|
@@ -62088,15 +62417,15 @@ function diagnoseStopFailure(status2, error) {
|
|
|
62088
62417
|
return "server_error_check_takumi_web_logs";
|
|
62089
62418
|
return null;
|
|
62090
62419
|
}
|
|
62091
|
-
function
|
|
62420
|
+
function num3(v2) {
|
|
62092
62421
|
return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
62093
62422
|
}
|
|
62094
62423
|
function usageToTokens(usage) {
|
|
62095
62424
|
return {
|
|
62096
|
-
input:
|
|
62097
|
-
output:
|
|
62098
|
-
cache_read:
|
|
62099
|
-
cache_write:
|
|
62425
|
+
input: num3(usage.input_tokens),
|
|
62426
|
+
output: num3(usage.output_tokens),
|
|
62427
|
+
cache_read: num3(usage.cache_read_tokens),
|
|
62428
|
+
cache_write: num3(usage.cache_write_tokens)
|
|
62100
62429
|
};
|
|
62101
62430
|
}
|
|
62102
62431
|
function readCliVersion2() {
|
|
@@ -62271,11 +62600,11 @@ async function handleStop(agent, flags = {}) {
|
|
|
62271
62600
|
// src/domains/hooks/telemetry/otlp/observations-export.ts
|
|
62272
62601
|
init_paths2();
|
|
62273
62602
|
import { promises as fs27, openSync as openSync6 } from "node:fs";
|
|
62274
|
-
import { join as
|
|
62603
|
+
import { join as join99 } from "node:path";
|
|
62275
62604
|
|
|
62276
62605
|
// src/domains/hooks/telemetry/lib/retention.ts
|
|
62277
62606
|
import { promises as fs24 } from "node:fs";
|
|
62278
|
-
import { join as
|
|
62607
|
+
import { join as join98 } from "node:path";
|
|
62279
62608
|
async function pathExists24(path11) {
|
|
62280
62609
|
try {
|
|
62281
62610
|
await fs24.access(path11);
|
|
@@ -62310,7 +62639,7 @@ async function decideDelete(dir, args) {
|
|
|
62310
62639
|
async function listChildren(dir) {
|
|
62311
62640
|
try {
|
|
62312
62641
|
const names = await fs24.readdir(dir);
|
|
62313
|
-
return names.map((n) =>
|
|
62642
|
+
return names.map((n) => join98(dir, n));
|
|
62314
62643
|
} catch {
|
|
62315
62644
|
return [];
|
|
62316
62645
|
}
|
|
@@ -62321,7 +62650,7 @@ async function collectV2Sessions() {
|
|
|
62321
62650
|
const sessions = [];
|
|
62322
62651
|
for (const projectDir of projects) {
|
|
62323
62652
|
for (const agentDir of await listChildren(projectDir)) {
|
|
62324
|
-
for (const sessionDir of await listChildren(
|
|
62653
|
+
for (const sessionDir of await listChildren(join98(agentDir, "sessions"))) {
|
|
62325
62654
|
sessions.push(sessionDir);
|
|
62326
62655
|
}
|
|
62327
62656
|
}
|
|
@@ -62750,7 +63079,7 @@ async function exportSessionObservations(sessionDir, opts = {}, deps = {}) {
|
|
|
62750
63079
|
}
|
|
62751
63080
|
}
|
|
62752
63081
|
function lockPath() {
|
|
62753
|
-
return
|
|
63082
|
+
return join99(getConfigDir(), "obs-flush.lock");
|
|
62754
63083
|
}
|
|
62755
63084
|
async function acquireSweepLock(now) {
|
|
62756
63085
|
const path11 = lockPath();
|
|
@@ -63289,11 +63618,11 @@ var metricsRecord = {
|
|
|
63289
63618
|
|
|
63290
63619
|
// src/domains/hooks/handlers/session-init/handler.ts
|
|
63291
63620
|
import { mkdirSync as mkdirSync5 } from "node:fs";
|
|
63292
|
-
import { dirname as
|
|
63621
|
+
import { dirname as dirname28, join as join103 } from "node:path";
|
|
63293
63622
|
|
|
63294
63623
|
// src/domains/hooks/handlers/_shared/project-detector.ts
|
|
63295
63624
|
import { existsSync as existsSync46, readFileSync as readFileSync15 } from "node:fs";
|
|
63296
|
-
import { join as
|
|
63625
|
+
import { join as join100 } from "node:path";
|
|
63297
63626
|
var LOCKFILE_PRIORITY = [
|
|
63298
63627
|
{ manager: "bun", files: ["bun.lockb", "bun.lock"] },
|
|
63299
63628
|
{ manager: "pnpm", files: ["pnpm-lock.yaml"] },
|
|
@@ -63328,14 +63657,14 @@ var APP_FRAMEWORKS = new Set([
|
|
|
63328
63657
|
var WORKSPACE_MARKER_FILES = ["pnpm-workspace.yaml", "turbo.json", "lerna.json"];
|
|
63329
63658
|
function fileExists(cwd2, name) {
|
|
63330
63659
|
try {
|
|
63331
|
-
return existsSync46(
|
|
63660
|
+
return existsSync46(join100(cwd2, name));
|
|
63332
63661
|
} catch {
|
|
63333
63662
|
return false;
|
|
63334
63663
|
}
|
|
63335
63664
|
}
|
|
63336
63665
|
function readPackageJson(cwd2) {
|
|
63337
63666
|
try {
|
|
63338
|
-
const raw = readFileSync15(
|
|
63667
|
+
const raw = readFileSync15(join100(cwd2, "package.json"), "utf8");
|
|
63339
63668
|
const parsed = JSON.parse(raw);
|
|
63340
63669
|
if (parsed && typeof parsed === "object")
|
|
63341
63670
|
return parsed;
|
|
@@ -63419,25 +63748,25 @@ function detectProject(cwd2) {
|
|
|
63419
63748
|
// src/domains/hooks/handlers/session-init/env-entries.ts
|
|
63420
63749
|
import { createHash as createHash11 } from "node:crypto";
|
|
63421
63750
|
import { platform as platform8, userInfo } from "node:os";
|
|
63422
|
-
import { join as
|
|
63751
|
+
import { join as join102 } from "node:path";
|
|
63423
63752
|
|
|
63424
63753
|
// src/domains/hooks/handlers/session-init/plan-resolver.ts
|
|
63425
|
-
import { existsSync as existsSync47, readFileSync as readFileSync16, readdirSync as
|
|
63426
|
-
import { join as
|
|
63754
|
+
import { existsSync as existsSync47, readFileSync as readFileSync16, readdirSync as readdirSync7 } from "node:fs";
|
|
63755
|
+
import { join as join101 } from "node:path";
|
|
63427
63756
|
var MAX_PLAN_DIRS = 100;
|
|
63428
63757
|
var MAX_PLAN_FILE_BYTES = 64 * 1024;
|
|
63429
63758
|
function listPlanDirs(plansPath) {
|
|
63430
63759
|
try {
|
|
63431
63760
|
if (!existsSync47(plansPath))
|
|
63432
63761
|
return [];
|
|
63433
|
-
return
|
|
63762
|
+
return readdirSync7(plansPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort().slice(0, MAX_PLAN_DIRS);
|
|
63434
63763
|
} catch {
|
|
63435
63764
|
return [];
|
|
63436
63765
|
}
|
|
63437
63766
|
}
|
|
63438
63767
|
function planFileMentionsSession(planDir, sessionId) {
|
|
63439
63768
|
try {
|
|
63440
|
-
const planFile =
|
|
63769
|
+
const planFile = join101(planDir, "plan.md");
|
|
63441
63770
|
if (!existsSync47(planFile))
|
|
63442
63771
|
return false;
|
|
63443
63772
|
const body = readFileSync16(planFile, { encoding: "utf8" });
|
|
@@ -63452,7 +63781,7 @@ function resolveActivePlan(plansPath, sessionId) {
|
|
|
63452
63781
|
if (!sessionId)
|
|
63453
63782
|
return "";
|
|
63454
63783
|
for (const name of listPlanDirs(plansPath)) {
|
|
63455
|
-
const dir =
|
|
63784
|
+
const dir = join101(plansPath, name);
|
|
63456
63785
|
if (name.includes(sessionId) || planFileMentionsSession(dir, sessionId)) {
|
|
63457
63786
|
return dir;
|
|
63458
63787
|
}
|
|
@@ -63473,7 +63802,7 @@ function resolveSuggestedPlan(plansPath, branch, branchPattern) {
|
|
|
63473
63802
|
return "";
|
|
63474
63803
|
for (const name of listPlanDirs(plansPath)) {
|
|
63475
63804
|
if (name.includes(slug))
|
|
63476
|
-
return
|
|
63805
|
+
return join101(plansPath, name);
|
|
63477
63806
|
}
|
|
63478
63807
|
return "";
|
|
63479
63808
|
}
|
|
@@ -63527,11 +63856,11 @@ function buildEnvEntries(params) {
|
|
|
63527
63856
|
const plan = config.plan ?? {};
|
|
63528
63857
|
const locale = config.locale ?? {};
|
|
63529
63858
|
const validation = plan.validation ?? {};
|
|
63530
|
-
const settingsDir =
|
|
63531
|
-
const docsPath =
|
|
63532
|
-
const plansPath =
|
|
63859
|
+
const settingsDir = join102(projectRoot, ".claude");
|
|
63860
|
+
const docsPath = join102(projectRoot, paths.docs ?? "docs");
|
|
63861
|
+
const plansPath = join102(projectRoot, paths.plans ?? "plans");
|
|
63533
63862
|
const reportsDir = plan.reportsDir ?? "reports";
|
|
63534
|
-
const reportsPath =
|
|
63863
|
+
const reportsPath = join102(plansPath, reportsDir);
|
|
63535
63864
|
const namingFormat = plan.namingFormat ?? "";
|
|
63536
63865
|
const activePlan = resolveActivePlan(plansPath, ctx.sessionId);
|
|
63537
63866
|
const suggestedPlan = resolveSuggestedPlan(plansPath, branch, plan.resolution?.branchPattern ?? "");
|
|
@@ -63612,11 +63941,11 @@ function resolveEnvFilePath(settingsDir) {
|
|
|
63612
63941
|
const override = process.env.CLAUDE_ENV_FILE;
|
|
63613
63942
|
if (override && override.trim().length > 0)
|
|
63614
63943
|
return override;
|
|
63615
|
-
return
|
|
63944
|
+
return join103(settingsDir, DEFAULT_ENV_FILE);
|
|
63616
63945
|
}
|
|
63617
63946
|
function persistEntries(envFilePath, entries) {
|
|
63618
63947
|
try {
|
|
63619
|
-
mkdirSync5(
|
|
63948
|
+
mkdirSync5(dirname28(envFilePath), { recursive: true });
|
|
63620
63949
|
writeEnvFile(envFilePath, entries);
|
|
63621
63950
|
return true;
|
|
63622
63951
|
} catch {
|
|
@@ -63669,7 +63998,7 @@ import { execFileSync as execFileSync3 } from "node:child_process";
|
|
|
63669
63998
|
import { createHash as createHash12 } from "node:crypto";
|
|
63670
63999
|
import { existsSync as existsSync48, mkdirSync as mkdirSync6, readFileSync as readFileSync17, rmSync as rmSync3, statSync as statSync6, writeFileSync as writeFileSync9 } from "node:fs";
|
|
63671
64000
|
import { homedir as homedir27, platform as platform9, tmpdir as tmpdir4 } from "node:os";
|
|
63672
|
-
import { basename as
|
|
64001
|
+
import { basename as basename18, join as join104, resolve as resolve21 } from "node:path";
|
|
63673
64002
|
var INJECTED_TTL_MS = 12 * 60 * 60 * 1000;
|
|
63674
64003
|
var RESERVATION_TTL_MS = 60 * 1000;
|
|
63675
64004
|
function gitBranch(dir) {
|
|
@@ -63742,16 +64071,16 @@ function buildPromptContext(args) {
|
|
|
63742
64071
|
function scopeKey(baseDir) {
|
|
63743
64072
|
const abs = resolve21(baseDir || ".");
|
|
63744
64073
|
const hash = createHash12("sha256").update(abs).digest("hex").slice(0, 16);
|
|
63745
|
-
const slug =
|
|
64074
|
+
const slug = basename18(abs).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 24) || "root";
|
|
63746
64075
|
return `${slug}-${hash}`;
|
|
63747
64076
|
}
|
|
63748
64077
|
function stateDir() {
|
|
63749
|
-
return
|
|
64078
|
+
return join104(tmpdir4(), "takumi-context-throttle");
|
|
63750
64079
|
}
|
|
63751
64080
|
function stateFile(sessionId, scope, transcriptPath) {
|
|
63752
64081
|
const key = `${sessionId}\x00${scope}\x00${transcriptPath ?? ""}`;
|
|
63753
64082
|
const hash = createHash12("sha256").update(key).digest("hex").slice(0, 32);
|
|
63754
|
-
return
|
|
64083
|
+
return join104(stateDir(), `${hash}.json`);
|
|
63755
64084
|
}
|
|
63756
64085
|
function readState(file) {
|
|
63757
64086
|
try {
|
|
@@ -63820,8 +64149,8 @@ function clearPending(sessionId, scope, transcriptPath) {
|
|
|
63820
64149
|
} catch {}
|
|
63821
64150
|
}
|
|
63822
64151
|
function resolveSkillsVenv(_cwd) {
|
|
63823
|
-
const base =
|
|
63824
|
-
const interpreter = platform9() === "win32" ?
|
|
64152
|
+
const base = join104(homedir27(), ".claude", "skills", ".venv");
|
|
64153
|
+
const interpreter = platform9() === "win32" ? join104(base, "Scripts", "python.exe") : join104(base, "bin", "python3");
|
|
63825
64154
|
return existsSync48(interpreter) ? interpreter : null;
|
|
63826
64155
|
}
|
|
63827
64156
|
|
|
@@ -63860,12 +64189,12 @@ var sessionPromptContext = {
|
|
|
63860
64189
|
};
|
|
63861
64190
|
|
|
63862
64191
|
// src/domains/hooks/handlers/session-subagent-init/context-block.ts
|
|
63863
|
-
import { join as
|
|
64192
|
+
import { join as join106 } from "node:path";
|
|
63864
64193
|
|
|
63865
64194
|
// src/domains/hooks/handlers/session-subagent-init/context-sources.ts
|
|
63866
64195
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
63867
|
-
import { readdirSync as
|
|
63868
|
-
import { isAbsolute as isAbsolute4, join as
|
|
64196
|
+
import { readdirSync as readdirSync8, statSync as statSync7 } from "node:fs";
|
|
64197
|
+
import { isAbsolute as isAbsolute4, join as join105, resolve as resolve22 } from "node:path";
|
|
63869
64198
|
var MAX_DOCS_FILES = 15;
|
|
63870
64199
|
var MAX_DOCS_SUBDIRS = 5;
|
|
63871
64200
|
function gitFacts(dir) {
|
|
@@ -63897,16 +64226,16 @@ function planDirTemplate(format, dateStr) {
|
|
|
63897
64226
|
}
|
|
63898
64227
|
function detectPlan(plansAbs) {
|
|
63899
64228
|
try {
|
|
63900
|
-
const entries =
|
|
64229
|
+
const entries = readdirSync8(plansAbs, { withFileTypes: true });
|
|
63901
64230
|
let best = null;
|
|
63902
64231
|
for (const e2 of entries) {
|
|
63903
64232
|
if (!e2.isDirectory())
|
|
63904
64233
|
continue;
|
|
63905
|
-
const dir =
|
|
64234
|
+
const dir = join105(plansAbs, e2.name);
|
|
63906
64235
|
try {
|
|
63907
|
-
if (!
|
|
64236
|
+
if (!readdirSync8(dir).includes("plan.md"))
|
|
63908
64237
|
continue;
|
|
63909
|
-
const mtime = statSync7(
|
|
64238
|
+
const mtime = statSync7(join105(dir, "plan.md")).mtimeMs;
|
|
63910
64239
|
if (!best || mtime > best.mtime)
|
|
63911
64240
|
best = { name: e2.name, mtime };
|
|
63912
64241
|
} catch {}
|
|
@@ -63918,7 +64247,7 @@ function detectPlan(plansAbs) {
|
|
|
63918
64247
|
}
|
|
63919
64248
|
function docsCatalogue(docsAbs) {
|
|
63920
64249
|
try {
|
|
63921
|
-
const entries =
|
|
64250
|
+
const entries = readdirSync8(docsAbs, { withFileTypes: true });
|
|
63922
64251
|
const files = entries.filter((e2) => e2.isFile() && e2.name.toLowerCase().endsWith(".md")).map((e2) => e2.name).sort();
|
|
63923
64252
|
const subdirs = entries.filter((e2) => e2.isDirectory()).map((e2) => e2.name).sort();
|
|
63924
64253
|
const lines = [];
|
|
@@ -63929,7 +64258,7 @@ function docsCatalogue(docsAbs) {
|
|
|
63929
64258
|
for (const d3 of subdirs.slice(0, MAX_DOCS_SUBDIRS)) {
|
|
63930
64259
|
let count = 0;
|
|
63931
64260
|
try {
|
|
63932
|
-
count =
|
|
64261
|
+
count = readdirSync8(join105(docsAbs, d3)).length;
|
|
63933
64262
|
} catch {}
|
|
63934
64263
|
lines.push(`- ${d3}/ (${count} entries)`);
|
|
63935
64264
|
}
|
|
@@ -63973,11 +64302,11 @@ function buildSubagentContext(input, ctx) {
|
|
|
63973
64302
|
const agentId = strField(input, "agent_id") || "unknown";
|
|
63974
64303
|
const plansAbs = abs(base, cfg.paths?.plans?.trim() || "plans");
|
|
63975
64304
|
const docsAbs = abs(base, cfg.paths?.docs?.trim() || "docs");
|
|
63976
|
-
const reportsAbs =
|
|
64305
|
+
const reportsAbs = join106(plansAbs, cfg.plan?.reportsDir?.trim() || "reports");
|
|
63977
64306
|
const dateStr = stamp(cfg.plan?.dateFormat?.trim() || "YYMMDD-HHmm", new Date);
|
|
63978
64307
|
const namingFormat = cfg.plan?.namingFormat?.trim() || "{date}-{slug}";
|
|
63979
|
-
const planDir =
|
|
63980
|
-
const reportFile =
|
|
64308
|
+
const planDir = join106(plansAbs, planDirTemplate(namingFormat, dateStr));
|
|
64309
|
+
const reportFile = join106(reportsAbs, `${agentKey}-${dateStr}-{slug}-report.md`);
|
|
63981
64310
|
const activePlan = detectPlan(plansAbs);
|
|
63982
64311
|
const venv = resolveSkillsVenv(effectiveCwd);
|
|
63983
64312
|
const respLang = cfg.locale?.responseLanguage?.trim() || null;
|
|
@@ -64580,7 +64909,7 @@ init_hooks_settings_merger();
|
|
|
64580
64909
|
// src/commands/portable/settings-write-with-confirm.ts
|
|
64581
64910
|
init_safe_prompts();
|
|
64582
64911
|
import { existsSync as existsSync49, mkdirSync as mkdirSync7, readFileSync as readFileSync18, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
|
|
64583
|
-
import { dirname as
|
|
64912
|
+
import { dirname as dirname29 } from "node:path";
|
|
64584
64913
|
|
|
64585
64914
|
// node_modules/diff/libesm/diff/base.js
|
|
64586
64915
|
class Diff {
|
|
@@ -65783,7 +66112,7 @@ function diffStats(diff) {
|
|
|
65783
66112
|
return { additions, deletions };
|
|
65784
66113
|
}
|
|
65785
66114
|
function atomicWrite2(path11, contents, backupPath) {
|
|
65786
|
-
mkdirSync7(
|
|
66115
|
+
mkdirSync7(dirname29(path11), { recursive: true });
|
|
65787
66116
|
const tmp = `${path11}.tmp`;
|
|
65788
66117
|
try {
|
|
65789
66118
|
writeFileSync10(tmp, contents);
|
|
@@ -65874,13 +66203,13 @@ import { existsSync as existsSync50 } from "node:fs";
|
|
|
65874
66203
|
// src/commands/hooks/lib/settings-path-resolver.ts
|
|
65875
66204
|
import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "node:fs";
|
|
65876
66205
|
import { homedir as homedir28 } from "node:os";
|
|
65877
|
-
import { join as
|
|
66206
|
+
import { join as join107 } from "node:path";
|
|
65878
66207
|
function rawPath(agent, global3) {
|
|
65879
66208
|
const root = global3 ? homedir28() : process.cwd();
|
|
65880
66209
|
if (agent === "claude") {
|
|
65881
|
-
return
|
|
66210
|
+
return join107(root, ".claude", "settings.json");
|
|
65882
66211
|
}
|
|
65883
|
-
return
|
|
66212
|
+
return join107(root, ".codex", "hooks.json");
|
|
65884
66213
|
}
|
|
65885
66214
|
function resolveSettingsPath(agent, options2 = {}) {
|
|
65886
66215
|
const originalPath = rawPath(agent, Boolean(options2.global));
|
|
@@ -66030,7 +66359,7 @@ function buildHookSection(agent, bin, flags = {}, handlers3 = HOOK_HANDLERS) {
|
|
|
66030
66359
|
// src/commands/hooks/uninstall-handler.ts
|
|
66031
66360
|
init_logger();
|
|
66032
66361
|
import { existsSync as existsSync51, mkdirSync as mkdirSync8, readFileSync as readFileSync19, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "node:fs";
|
|
66033
|
-
import { dirname as
|
|
66362
|
+
import { dirname as dirname30 } from "node:path";
|
|
66034
66363
|
var AGENT_DISPLAY2 = {
|
|
66035
66364
|
claude: "Claude Code",
|
|
66036
66365
|
codex: "Codex"
|
|
@@ -66071,7 +66400,7 @@ function pruneHooksSection(hooks, agent) {
|
|
|
66071
66400
|
return { pruned, removed };
|
|
66072
66401
|
}
|
|
66073
66402
|
function writeAtomic(path11, contents) {
|
|
66074
|
-
mkdirSync8(
|
|
66403
|
+
mkdirSync8(dirname30(path11), { recursive: true });
|
|
66075
66404
|
const tmp = `${path11}.tmp`;
|
|
66076
66405
|
try {
|
|
66077
66406
|
writeFileSync11(tmp, contents);
|
|
@@ -66139,6 +66468,12 @@ var AGENT_DISPLAY3 = {
|
|
|
66139
66468
|
claude: "Claude Code",
|
|
66140
66469
|
codex: "Codex"
|
|
66141
66470
|
};
|
|
66471
|
+
function selectHandlersForInstall(categories) {
|
|
66472
|
+
if (!categories)
|
|
66473
|
+
return HOOK_HANDLERS;
|
|
66474
|
+
const wanted = new Set(categories);
|
|
66475
|
+
return HOOK_HANDLERS.filter((h2) => wanted.has(h2.category));
|
|
66476
|
+
}
|
|
66142
66477
|
function countEntries(section) {
|
|
66143
66478
|
let count = 0;
|
|
66144
66479
|
for (const groups of Object.values(section)) {
|
|
@@ -66155,7 +66490,7 @@ async function installForAgent(agent, options2, interactive, useStepUI) {
|
|
|
66155
66490
|
const section = buildHookSection(agent, options2.bin, {
|
|
66156
66491
|
noDetach: options2.noDetach,
|
|
66157
66492
|
debug: options2.debug
|
|
66158
|
-
});
|
|
66493
|
+
}, selectHandlersForInstall(options2.categories));
|
|
66159
66494
|
const entriesPlanned = countEntries(section);
|
|
66160
66495
|
const result = await writeSettingsWithConfirm({
|
|
66161
66496
|
path: location2.realPath,
|
|
@@ -67573,7 +67908,7 @@ init_logger();
|
|
|
67573
67908
|
init_takumi_constants();
|
|
67574
67909
|
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
67575
67910
|
var import_semver5 = __toESM(require_semver2(), 1);
|
|
67576
|
-
import { join as
|
|
67911
|
+
import { join as join108 } from "node:path";
|
|
67577
67912
|
function evaluateCliVersionGate(input) {
|
|
67578
67913
|
const min = typeof input.minCliVersion === "string" ? input.minCliVersion.trim() : undefined;
|
|
67579
67914
|
if (!min)
|
|
@@ -67594,7 +67929,7 @@ function evaluateCliVersionGate(input) {
|
|
|
67594
67929
|
}
|
|
67595
67930
|
async function readKitMinCliVersion(extractDir) {
|
|
67596
67931
|
try {
|
|
67597
|
-
const resolved = await findManifestPath(
|
|
67932
|
+
const resolved = await findManifestPath(join108(extractDir, ".claude"));
|
|
67598
67933
|
if (!resolved)
|
|
67599
67934
|
return;
|
|
67600
67935
|
const raw = await import_fs_extra31.readFile(resolved.path, "utf-8");
|
|
@@ -67624,6 +67959,7 @@ function createInitContext(rawOptions, prompts) {
|
|
|
67624
67959
|
exclude: [],
|
|
67625
67960
|
only: [],
|
|
67626
67961
|
installSkills: false,
|
|
67962
|
+
installHooks: false,
|
|
67627
67963
|
withSudo: false,
|
|
67628
67964
|
forceOverwrite: false,
|
|
67629
67965
|
forceOverwriteSettings: false,
|
|
@@ -67785,7 +68121,7 @@ init_logger();
|
|
|
67785
68121
|
init_safe_spinner();
|
|
67786
68122
|
import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
|
|
67787
68123
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
67788
|
-
import { join as
|
|
68124
|
+
import { join as join114 } from "node:path";
|
|
67789
68125
|
|
|
67790
68126
|
// src/shared/temp-cleanup.ts
|
|
67791
68127
|
init_logger();
|
|
@@ -67804,7 +68140,7 @@ init_logger();
|
|
|
67804
68140
|
init_output_manager();
|
|
67805
68141
|
import { createWriteStream as createWriteStream2, rmSync as rmSync6 } from "node:fs";
|
|
67806
68142
|
import { mkdir as mkdir21 } from "node:fs/promises";
|
|
67807
|
-
import { join as
|
|
68143
|
+
import { join as join109 } from "node:path";
|
|
67808
68144
|
|
|
67809
68145
|
// src/shared/progress-bar.ts
|
|
67810
68146
|
init_output_manager();
|
|
@@ -68014,7 +68350,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
|
|
|
68014
68350
|
class FileDownloader {
|
|
68015
68351
|
async downloadAsset(asset, destDir) {
|
|
68016
68352
|
try {
|
|
68017
|
-
const destPath =
|
|
68353
|
+
const destPath = join109(destDir, asset.name);
|
|
68018
68354
|
await mkdir21(destDir, { recursive: true });
|
|
68019
68355
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
68020
68356
|
logger.verbose("Download details", {
|
|
@@ -68099,7 +68435,7 @@ class FileDownloader {
|
|
|
68099
68435
|
}
|
|
68100
68436
|
async downloadFile(params) {
|
|
68101
68437
|
const { url, name, size, destDir, token } = params;
|
|
68102
|
-
const destPath =
|
|
68438
|
+
const destPath = join109(destDir, name);
|
|
68103
68439
|
await mkdir21(destDir, { recursive: true });
|
|
68104
68440
|
output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
68105
68441
|
const headers = {};
|
|
@@ -68202,7 +68538,7 @@ init_logger();
|
|
|
68202
68538
|
init_types2();
|
|
68203
68539
|
import { constants as constants3 } from "node:fs";
|
|
68204
68540
|
import { access as access3, readdir as readdir25 } from "node:fs/promises";
|
|
68205
|
-
import { join as
|
|
68541
|
+
import { join as join110 } from "node:path";
|
|
68206
68542
|
async function validateExtraction(extractDir) {
|
|
68207
68543
|
try {
|
|
68208
68544
|
const entries = await readdir25(extractDir, { encoding: "utf8" });
|
|
@@ -68214,7 +68550,7 @@ async function validateExtraction(extractDir) {
|
|
|
68214
68550
|
const missingPaths = [];
|
|
68215
68551
|
for (const path11 of criticalPaths) {
|
|
68216
68552
|
try {
|
|
68217
|
-
await access3(
|
|
68553
|
+
await access3(join110(extractDir, path11), constants3.F_OK);
|
|
68218
68554
|
logger.debug(`Found: ${path11}`);
|
|
68219
68555
|
} catch {
|
|
68220
68556
|
logger.warning(`Expected path not found: ${path11}`);
|
|
@@ -68236,7 +68572,7 @@ async function validateExtraction(extractDir) {
|
|
|
68236
68572
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
68237
68573
|
init_logger();
|
|
68238
68574
|
import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat8 } from "node:fs/promises";
|
|
68239
|
-
import { join as
|
|
68575
|
+
import { join as join112 } from "node:path";
|
|
68240
68576
|
|
|
68241
68577
|
// node_modules/tar/dist/esm/index.min.js
|
|
68242
68578
|
import Kr from "events";
|
|
@@ -71449,7 +71785,7 @@ function decodeFilePath(path11) {
|
|
|
71449
71785
|
init_logger();
|
|
71450
71786
|
init_types2();
|
|
71451
71787
|
import { copyFile as copyFile4, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
|
|
71452
|
-
import { join as
|
|
71788
|
+
import { join as join111, relative as relative16 } from "node:path";
|
|
71453
71789
|
async function withRetry2(fn2, retries = 3) {
|
|
71454
71790
|
for (let i = 0;i < retries; i++) {
|
|
71455
71791
|
try {
|
|
@@ -71471,8 +71807,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
71471
71807
|
await mkdir22(destDir, { recursive: true });
|
|
71472
71808
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
71473
71809
|
for (const entry of entries) {
|
|
71474
|
-
const sourcePath =
|
|
71475
|
-
const destPath =
|
|
71810
|
+
const sourcePath = join111(sourceDir, entry);
|
|
71811
|
+
const destPath = join111(destDir, entry);
|
|
71476
71812
|
const relativePath = relative16(sourceDir, sourcePath);
|
|
71477
71813
|
if (!isPathSafe(destDir, destPath)) {
|
|
71478
71814
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -71499,8 +71835,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
|
71499
71835
|
await mkdir22(destDir, { recursive: true });
|
|
71500
71836
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
71501
71837
|
for (const entry of entries) {
|
|
71502
|
-
const sourcePath =
|
|
71503
|
-
const destPath =
|
|
71838
|
+
const sourcePath = join111(sourceDir, entry);
|
|
71839
|
+
const destPath = join111(destDir, entry);
|
|
71504
71840
|
const relativePath = relative16(sourceDir, sourcePath);
|
|
71505
71841
|
if (!isPathSafe(destDir, destPath)) {
|
|
71506
71842
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -71555,7 +71891,7 @@ class TarExtractor {
|
|
|
71555
71891
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
71556
71892
|
if (entries.length === 1) {
|
|
71557
71893
|
const rootEntry = entries[0];
|
|
71558
|
-
const rootPath =
|
|
71894
|
+
const rootPath = join112(tempExtractDir, rootEntry);
|
|
71559
71895
|
const rootStat = await stat8(rootPath);
|
|
71560
71896
|
if (rootStat.isDirectory()) {
|
|
71561
71897
|
const rootContents = await readdir27(rootPath, { encoding: "utf8" });
|
|
@@ -71571,7 +71907,7 @@ class TarExtractor {
|
|
|
71571
71907
|
}
|
|
71572
71908
|
} else {
|
|
71573
71909
|
await mkdir23(destDir, { recursive: true });
|
|
71574
|
-
await copyFile5(rootPath,
|
|
71910
|
+
await copyFile5(rootPath, join112(destDir, rootEntry));
|
|
71575
71911
|
}
|
|
71576
71912
|
} else {
|
|
71577
71913
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -71592,7 +71928,7 @@ class TarExtractor {
|
|
|
71592
71928
|
init_logger();
|
|
71593
71929
|
import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
71594
71930
|
import { chmod as chmod3, copyFile as copyFile6, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as stat9 } from "node:fs/promises";
|
|
71595
|
-
import { dirname as
|
|
71931
|
+
import { dirname as dirname31, join as join113, resolve as resolve24 } from "node:path";
|
|
71596
71932
|
import { pipeline } from "node:stream/promises";
|
|
71597
71933
|
import yauzl from "yauzl-promise";
|
|
71598
71934
|
class ZipExtractor {
|
|
@@ -71606,7 +71942,7 @@ class ZipExtractor {
|
|
|
71606
71942
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
71607
71943
|
if (entries.length === 1) {
|
|
71608
71944
|
const rootEntry = entries[0];
|
|
71609
|
-
const rootPath =
|
|
71945
|
+
const rootPath = join113(tempExtractDir, rootEntry);
|
|
71610
71946
|
const rootStat = await stat9(rootPath);
|
|
71611
71947
|
if (rootStat.isDirectory()) {
|
|
71612
71948
|
const rootContents = await readdir28(rootPath, { encoding: "utf8" });
|
|
@@ -71622,7 +71958,7 @@ class ZipExtractor {
|
|
|
71622
71958
|
}
|
|
71623
71959
|
} else {
|
|
71624
71960
|
await mkdir24(destDir, { recursive: true });
|
|
71625
|
-
await copyFile6(rootPath,
|
|
71961
|
+
await copyFile6(rootPath, join113(destDir, rootEntry));
|
|
71626
71962
|
}
|
|
71627
71963
|
} else {
|
|
71628
71964
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -71653,7 +71989,7 @@ class ZipExtractor {
|
|
|
71653
71989
|
await mkdir24(outPath, { recursive: true });
|
|
71654
71990
|
continue;
|
|
71655
71991
|
}
|
|
71656
|
-
await mkdir24(
|
|
71992
|
+
await mkdir24(dirname31(outPath), { recursive: true });
|
|
71657
71993
|
const readStream = await entry.openReadStream();
|
|
71658
71994
|
await pipeline(readStream, createWriteStream3(outPath));
|
|
71659
71995
|
const unixMode = entry.externalFileAttributes >>> 16 & 511;
|
|
@@ -71751,7 +72087,7 @@ class DownloadManager {
|
|
|
71751
72087
|
async createTempDir() {
|
|
71752
72088
|
const timestamp = Date.now();
|
|
71753
72089
|
const counter = DownloadManager.tempDirCounter++;
|
|
71754
|
-
const primaryTempDir =
|
|
72090
|
+
const primaryTempDir = join114(tmpdir5(), `takumi-${timestamp}-${counter}`);
|
|
71755
72091
|
try {
|
|
71756
72092
|
await mkdir25(primaryTempDir, { recursive: true });
|
|
71757
72093
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -71768,7 +72104,7 @@ Solutions:
|
|
|
71768
72104
|
2. Set HOME environment variable
|
|
71769
72105
|
3. Try running from a different directory`);
|
|
71770
72106
|
}
|
|
71771
|
-
const fallbackTempDir =
|
|
72107
|
+
const fallbackTempDir = join114(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
|
|
71772
72108
|
try {
|
|
71773
72109
|
await mkdir25(fallbackTempDir, { recursive: true });
|
|
71774
72110
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -72341,6 +72677,7 @@ async function resolveOptions(ctx) {
|
|
|
72341
72677
|
docsDir: parsed.docsDir,
|
|
72342
72678
|
plansDir: parsed.plansDir,
|
|
72343
72679
|
installSkills: parsed.installSkills ?? false,
|
|
72680
|
+
installHooks: parsed.installHooks ?? false,
|
|
72344
72681
|
withSudo: parsed.withSudo ?? false,
|
|
72345
72682
|
forceOverwrite: parsed.forceOverwrite ?? false,
|
|
72346
72683
|
forceOverwriteSettings: parsed.forceOverwriteSettings ?? false,
|
|
@@ -72474,7 +72811,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
|
|
|
72474
72811
|
}
|
|
72475
72812
|
// src/commands/init/phases/selection-handler.ts
|
|
72476
72813
|
import { mkdir as mkdir26 } from "node:fs/promises";
|
|
72477
|
-
import { join as
|
|
72814
|
+
import { join as join118, resolve as resolve28 } from "node:path";
|
|
72478
72815
|
|
|
72479
72816
|
// src/commands/shared/agent-selector.ts
|
|
72480
72817
|
init_registry();
|
|
@@ -72627,8 +72964,8 @@ init_logger();
|
|
|
72627
72964
|
init_safe_spinner();
|
|
72628
72965
|
init_takumi_constants();
|
|
72629
72966
|
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
72630
|
-
import { existsSync as existsSync55, readdirSync as
|
|
72631
|
-
import { dirname as
|
|
72967
|
+
import { existsSync as existsSync55, readdirSync as readdirSync9, rmSync as rmSync7, rmdirSync as rmdirSync2, unlinkSync as unlinkSync6 } from "node:fs";
|
|
72968
|
+
import { dirname as dirname34, join as join117, resolve as resolve27 } from "node:path";
|
|
72632
72969
|
var TAKUMI_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
|
|
72633
72970
|
async function analyzeFreshInstallation(claudeDir) {
|
|
72634
72971
|
const metadata = await readManifest(claudeDir);
|
|
@@ -72674,14 +73011,14 @@ async function analyzeFreshInstallation(claudeDir) {
|
|
|
72674
73011
|
}
|
|
72675
73012
|
function cleanupEmptyDirectories2(filePath, claudeDir) {
|
|
72676
73013
|
const normalizedClaudeDir = resolve27(claudeDir);
|
|
72677
|
-
let currentDir = resolve27(
|
|
73014
|
+
let currentDir = resolve27(dirname34(filePath));
|
|
72678
73015
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
72679
73016
|
try {
|
|
72680
|
-
const entries =
|
|
73017
|
+
const entries = readdirSync9(currentDir);
|
|
72681
73018
|
if (entries.length === 0) {
|
|
72682
73019
|
rmdirSync2(currentDir);
|
|
72683
73020
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
72684
|
-
currentDir = resolve27(
|
|
73021
|
+
currentDir = resolve27(dirname34(currentDir));
|
|
72685
73022
|
} else {
|
|
72686
73023
|
break;
|
|
72687
73024
|
}
|
|
@@ -72698,7 +73035,7 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
72698
73035
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
72699
73036
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
72700
73037
|
for (const file of filesToRemove) {
|
|
72701
|
-
const fullPath =
|
|
73038
|
+
const fullPath = join117(claudeDir, file.path);
|
|
72702
73039
|
try {
|
|
72703
73040
|
if (existsSync55(fullPath)) {
|
|
72704
73041
|
unlinkSync6(fullPath);
|
|
@@ -72772,7 +73109,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
72772
73109
|
const removedFiles = [];
|
|
72773
73110
|
let removedDirCount = 0;
|
|
72774
73111
|
for (const subdir of TAKUMI_SUBDIRECTORIES) {
|
|
72775
|
-
const subdirPath =
|
|
73112
|
+
const subdirPath = join117(claudeDir, subdir);
|
|
72776
73113
|
if (await import_fs_extra32.pathExists(subdirPath)) {
|
|
72777
73114
|
rmSync7(subdirPath, { recursive: true, force: true });
|
|
72778
73115
|
removedDirCount++;
|
|
@@ -72997,7 +73334,7 @@ async function handleSelection(ctx) {
|
|
|
72997
73334
|
}
|
|
72998
73335
|
if (!ctx.options.fresh) {
|
|
72999
73336
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73000
|
-
const claudeDir = prefix ?
|
|
73337
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73001
73338
|
try {
|
|
73002
73339
|
const existingMetadata = await readManifest(claudeDir);
|
|
73003
73340
|
if (existingMetadata?.kits) {
|
|
@@ -73030,7 +73367,7 @@ async function handleSelection(ctx) {
|
|
|
73030
73367
|
}
|
|
73031
73368
|
if (ctx.options.fresh) {
|
|
73032
73369
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73033
|
-
const claudeDir = prefix ?
|
|
73370
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73034
73371
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
73035
73372
|
if (!canProceed) {
|
|
73036
73373
|
return { ...ctx, cancelled: true };
|
|
@@ -73050,7 +73387,7 @@ async function handleSelection(ctx) {
|
|
|
73050
73387
|
let currentVersion = null;
|
|
73051
73388
|
try {
|
|
73052
73389
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73053
|
-
const claudeDir = prefix ?
|
|
73390
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73054
73391
|
const existingMetadata = await readManifest(claudeDir);
|
|
73055
73392
|
currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
|
|
73056
73393
|
if (currentVersion) {
|
|
@@ -73138,7 +73475,7 @@ async function handleSelection(ctx) {
|
|
|
73138
73475
|
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
|
|
73139
73476
|
try {
|
|
73140
73477
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73141
|
-
const claudeDir = prefix ?
|
|
73478
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73142
73479
|
const existingMetadata = await readManifest(claudeDir);
|
|
73143
73480
|
const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
|
|
73144
73481
|
if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
|
|
@@ -73161,7 +73498,7 @@ async function handleSelection(ctx) {
|
|
|
73161
73498
|
let currentSecondaryVersion = null;
|
|
73162
73499
|
try {
|
|
73163
73500
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73164
|
-
const claudeDir = prefix ?
|
|
73501
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73165
73502
|
const existingMetadata = await readManifest(claudeDir);
|
|
73166
73503
|
currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
|
|
73167
73504
|
} catch {}
|
|
@@ -73245,12 +73582,12 @@ function resolveGlobalTargetDir(targetAgents2) {
|
|
|
73245
73582
|
// src/commands/init/phases/sync-handler.ts
|
|
73246
73583
|
init_paths();
|
|
73247
73584
|
import { copyFile as copyFile7, mkdir as mkdir28, open as open2, readFile as readFile41, rename as rename7, stat as stat12, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
|
|
73248
|
-
import { dirname as
|
|
73585
|
+
import { dirname as dirname35, join as join121, resolve as resolve29 } from "node:path";
|
|
73249
73586
|
|
|
73250
73587
|
// src/domains/sync/config-version-checker.ts
|
|
73251
73588
|
init_auth_client();
|
|
73252
73589
|
import { mkdir as mkdir27, readFile as readFile39, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
|
|
73253
|
-
import { join as
|
|
73590
|
+
import { join as join119 } from "node:path";
|
|
73254
73591
|
init_version_utils();
|
|
73255
73592
|
init_logger();
|
|
73256
73593
|
init_path_resolver();
|
|
@@ -73286,7 +73623,7 @@ var CACHE_FILENAME = "config-update-cache.json";
|
|
|
73286
73623
|
class ConfigVersionChecker {
|
|
73287
73624
|
static getCacheFilePath(kitType, global3) {
|
|
73288
73625
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
73289
|
-
return
|
|
73626
|
+
return join119(cacheDir, `${kitType}-${CACHE_FILENAME}`);
|
|
73290
73627
|
}
|
|
73291
73628
|
static async loadCache(kitType, global3) {
|
|
73292
73629
|
try {
|
|
@@ -73302,12 +73639,12 @@ class ConfigVersionChecker {
|
|
|
73302
73639
|
return null;
|
|
73303
73640
|
}
|
|
73304
73641
|
}
|
|
73305
|
-
static async saveCache(kitType, global3,
|
|
73642
|
+
static async saveCache(kitType, global3, cache3) {
|
|
73306
73643
|
try {
|
|
73307
73644
|
const cachePath = ConfigVersionChecker.getCacheFilePath(kitType, global3);
|
|
73308
73645
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
73309
73646
|
await mkdir27(cacheDir, { recursive: true });
|
|
73310
|
-
await writeFile27(cachePath, JSON.stringify(
|
|
73647
|
+
await writeFile27(cachePath, JSON.stringify(cache3, null, 2));
|
|
73311
73648
|
} catch (error) {
|
|
73312
73649
|
logger.debug(`Cache write failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
73313
73650
|
}
|
|
@@ -73349,14 +73686,14 @@ class ConfigVersionChecker {
|
|
|
73349
73686
|
}
|
|
73350
73687
|
static async checkForUpdates(kitType, currentVersion, global3 = false) {
|
|
73351
73688
|
const normalizedCurrent = currentVersion.replace(/^v/, "");
|
|
73352
|
-
const
|
|
73689
|
+
const cache3 = await ConfigVersionChecker.loadCache(kitType, global3);
|
|
73353
73690
|
const now = Date.now();
|
|
73354
|
-
if (
|
|
73355
|
-
const hasUpdates = isNewerVersion(normalizedCurrent,
|
|
73691
|
+
if (cache3 && now - cache3.lastCheck < CACHE_TTL_MS) {
|
|
73692
|
+
const hasUpdates = isNewerVersion(normalizedCurrent, cache3.latestVersion);
|
|
73356
73693
|
return {
|
|
73357
73694
|
hasUpdates,
|
|
73358
73695
|
currentVersion: normalizedCurrent,
|
|
73359
|
-
latestVersion:
|
|
73696
|
+
latestVersion: cache3.latestVersion,
|
|
73360
73697
|
fromCache: true
|
|
73361
73698
|
};
|
|
73362
73699
|
}
|
|
@@ -73374,12 +73711,12 @@ class ConfigVersionChecker {
|
|
|
73374
73711
|
fromCache: false
|
|
73375
73712
|
};
|
|
73376
73713
|
}
|
|
73377
|
-
if (
|
|
73378
|
-
const hasUpdates = isNewerVersion(normalizedCurrent,
|
|
73714
|
+
if (cache3) {
|
|
73715
|
+
const hasUpdates = isNewerVersion(normalizedCurrent, cache3.latestVersion);
|
|
73379
73716
|
return {
|
|
73380
73717
|
hasUpdates,
|
|
73381
73718
|
currentVersion: normalizedCurrent,
|
|
73382
|
-
latestVersion:
|
|
73719
|
+
latestVersion: cache3.latestVersion,
|
|
73383
73720
|
fromCache: true
|
|
73384
73721
|
};
|
|
73385
73722
|
}
|
|
@@ -73406,7 +73743,7 @@ class ConfigVersionChecker {
|
|
|
73406
73743
|
init_ownership_checker();
|
|
73407
73744
|
init_logger();
|
|
73408
73745
|
import { lstat as lstat7, readFile as readFile40, readlink, realpath as realpath3, stat as stat11 } from "node:fs/promises";
|
|
73409
|
-
import { isAbsolute as isAbsolute5, join as
|
|
73746
|
+
import { isAbsolute as isAbsolute5, join as join120, normalize as normalize9, relative as relative17 } from "node:path";
|
|
73410
73747
|
var MAX_SYNC_FILE_SIZE = 10 * 1024 * 1024;
|
|
73411
73748
|
var MAX_SYMLINK_DEPTH = 20;
|
|
73412
73749
|
async function validateSymlinkChain(path12, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
|
|
@@ -73418,7 +73755,7 @@ async function validateSymlinkChain(path12, basePath, maxDepth = MAX_SYMLINK_DEP
|
|
|
73418
73755
|
if (!stats.isSymbolicLink())
|
|
73419
73756
|
break;
|
|
73420
73757
|
const target = await readlink(current);
|
|
73421
|
-
const resolvedTarget = isAbsolute5(target) ? target :
|
|
73758
|
+
const resolvedTarget = isAbsolute5(target) ? target : join120(current, "..", target);
|
|
73422
73759
|
const normalizedTarget = normalize9(resolvedTarget);
|
|
73423
73760
|
const rel = relative17(basePath, normalizedTarget);
|
|
73424
73761
|
if (rel.startsWith("..") || isAbsolute5(rel)) {
|
|
@@ -73454,7 +73791,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
73454
73791
|
if (normalized.startsWith("..") || normalized.includes("/../")) {
|
|
73455
73792
|
throw new Error(`Path traversal not allowed: ${filePath}`);
|
|
73456
73793
|
}
|
|
73457
|
-
const fullPath =
|
|
73794
|
+
const fullPath = join120(basePath, normalized);
|
|
73458
73795
|
const rel = relative17(basePath, fullPath);
|
|
73459
73796
|
if (rel.startsWith("..") || isAbsolute5(rel)) {
|
|
73460
73797
|
throw new Error(`Path escapes base directory: ${filePath}`);
|
|
@@ -73469,7 +73806,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
73469
73806
|
}
|
|
73470
73807
|
} catch (error) {
|
|
73471
73808
|
if (error.code === "ENOENT") {
|
|
73472
|
-
const parentPath =
|
|
73809
|
+
const parentPath = join120(fullPath, "..");
|
|
73473
73810
|
try {
|
|
73474
73811
|
const resolvedBase = await realpath3(basePath);
|
|
73475
73812
|
const resolvedParent = await realpath3(parentPath);
|
|
@@ -73960,10 +74297,10 @@ function getLockTimeout() {
|
|
|
73960
74297
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
73961
74298
|
async function acquireSyncLock(global3) {
|
|
73962
74299
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
73963
|
-
const lockPath2 =
|
|
74300
|
+
const lockPath2 = join121(cacheDir, ".sync-lock");
|
|
73964
74301
|
const startTime = Date.now();
|
|
73965
74302
|
const lockTimeout = getLockTimeout();
|
|
73966
|
-
await mkdir28(
|
|
74303
|
+
await mkdir28(dirname35(lockPath2), { recursive: true });
|
|
73967
74304
|
while (Date.now() - startTime < lockTimeout) {
|
|
73968
74305
|
try {
|
|
73969
74306
|
const handle = await open2(lockPath2, "wx");
|
|
@@ -74041,7 +74378,7 @@ async function executeSyncMerge(ctx) {
|
|
|
74041
74378
|
try {
|
|
74042
74379
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
74043
74380
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
74044
|
-
const targetDir =
|
|
74381
|
+
const targetDir = join121(targetPath, "..");
|
|
74045
74382
|
try {
|
|
74046
74383
|
await mkdir28(targetDir, { recursive: true });
|
|
74047
74384
|
} catch (mkdirError) {
|
|
@@ -74212,7 +74549,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
74212
74549
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
74213
74550
|
if (await import_fs_extra34.pathExists(sourcePath)) {
|
|
74214
74551
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
74215
|
-
const targetDir =
|
|
74552
|
+
const targetDir = join121(targetPath, "..");
|
|
74216
74553
|
await mkdir28(targetDir, { recursive: true });
|
|
74217
74554
|
await copyFile7(sourcePath, targetPath);
|
|
74218
74555
|
}
|
|
@@ -74238,38 +74575,38 @@ init_logger();
|
|
|
74238
74575
|
init_types2();
|
|
74239
74576
|
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
74240
74577
|
import { rename as rename8, rm as rm9 } from "node:fs/promises";
|
|
74241
|
-
import { join as
|
|
74578
|
+
import { join as join122, relative as relative18 } from "node:path";
|
|
74242
74579
|
async function collectDirsToRename(extractDir, folders) {
|
|
74243
74580
|
const dirsToRename = [];
|
|
74244
74581
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
74245
|
-
const docsPath =
|
|
74582
|
+
const docsPath = join122(extractDir, DEFAULT_FOLDERS.docs);
|
|
74246
74583
|
if (await import_fs_extra35.pathExists(docsPath)) {
|
|
74247
74584
|
dirsToRename.push({
|
|
74248
74585
|
from: docsPath,
|
|
74249
|
-
to:
|
|
74586
|
+
to: join122(extractDir, folders.docs)
|
|
74250
74587
|
});
|
|
74251
74588
|
}
|
|
74252
|
-
const claudeDocsPath =
|
|
74589
|
+
const claudeDocsPath = join122(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
74253
74590
|
if (await import_fs_extra35.pathExists(claudeDocsPath)) {
|
|
74254
74591
|
dirsToRename.push({
|
|
74255
74592
|
from: claudeDocsPath,
|
|
74256
|
-
to:
|
|
74593
|
+
to: join122(extractDir, ".claude", folders.docs)
|
|
74257
74594
|
});
|
|
74258
74595
|
}
|
|
74259
74596
|
}
|
|
74260
74597
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
74261
|
-
const plansPath =
|
|
74598
|
+
const plansPath = join122(extractDir, DEFAULT_FOLDERS.plans);
|
|
74262
74599
|
if (await import_fs_extra35.pathExists(plansPath)) {
|
|
74263
74600
|
dirsToRename.push({
|
|
74264
74601
|
from: plansPath,
|
|
74265
|
-
to:
|
|
74602
|
+
to: join122(extractDir, folders.plans)
|
|
74266
74603
|
});
|
|
74267
74604
|
}
|
|
74268
|
-
const claudePlansPath =
|
|
74605
|
+
const claudePlansPath = join122(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
74269
74606
|
if (await import_fs_extra35.pathExists(claudePlansPath)) {
|
|
74270
74607
|
dirsToRename.push({
|
|
74271
74608
|
from: claudePlansPath,
|
|
74272
|
-
to:
|
|
74609
|
+
to: join122(extractDir, ".claude", folders.plans)
|
|
74273
74610
|
});
|
|
74274
74611
|
}
|
|
74275
74612
|
}
|
|
@@ -74310,7 +74647,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
74310
74647
|
init_logger();
|
|
74311
74648
|
init_types2();
|
|
74312
74649
|
import { readFile as readFile42, readdir as readdir29, writeFile as writeFile29 } from "node:fs/promises";
|
|
74313
|
-
import { join as
|
|
74650
|
+
import { join as join123, relative as relative19 } from "node:path";
|
|
74314
74651
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
74315
74652
|
".md",
|
|
74316
74653
|
".txt",
|
|
@@ -74363,7 +74700,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
|
|
|
74363
74700
|
let replacementsCount = 0;
|
|
74364
74701
|
const entries = await readdir29(dir, { withFileTypes: true });
|
|
74365
74702
|
for (const entry of entries) {
|
|
74366
|
-
const fullPath =
|
|
74703
|
+
const fullPath = join123(dir, entry.name);
|
|
74367
74704
|
if (entry.isDirectory()) {
|
|
74368
74705
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
74369
74706
|
continue;
|
|
@@ -74500,7 +74837,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
74500
74837
|
init_logger();
|
|
74501
74838
|
import { readFile as readFile43, readdir as readdir30, writeFile as writeFile30 } from "node:fs/promises";
|
|
74502
74839
|
import { platform as platform11 } from "node:os";
|
|
74503
|
-
import { extname as extname7, join as
|
|
74840
|
+
import { extname as extname7, join as join124 } from "node:path";
|
|
74504
74841
|
var IS_WINDOWS3 = platform11() === "win32";
|
|
74505
74842
|
var HOME_PREFIX = "$HOME";
|
|
74506
74843
|
function getHomeDirPrefix() {
|
|
@@ -74589,8 +74926,8 @@ function transformContent(content) {
|
|
|
74589
74926
|
}
|
|
74590
74927
|
function shouldTransformFile3(filename) {
|
|
74591
74928
|
const ext2 = extname7(filename).toLowerCase();
|
|
74592
|
-
const
|
|
74593
|
-
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(
|
|
74929
|
+
const basename19 = filename.split("/").pop() || filename;
|
|
74930
|
+
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename19);
|
|
74594
74931
|
}
|
|
74595
74932
|
async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
74596
74933
|
let filesTransformed = 0;
|
|
@@ -74600,7 +74937,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
74600
74937
|
async function processDirectory2(dir) {
|
|
74601
74938
|
const entries = await readdir30(dir, { withFileTypes: true });
|
|
74602
74939
|
for (const entry of entries) {
|
|
74603
|
-
const fullPath =
|
|
74940
|
+
const fullPath = join124(dir, entry.name);
|
|
74604
74941
|
if (entry.isDirectory()) {
|
|
74605
74942
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
74606
74943
|
continue;
|
|
@@ -74692,6 +75029,7 @@ function mapAgentToHookAgent(agent) {
|
|
|
74692
75029
|
return null;
|
|
74693
75030
|
}
|
|
74694
75031
|
async function installTkmHooksForAgents(targetAgents2, options2) {
|
|
75032
|
+
const categories = options2.installHooks ? undefined : ["metrics"];
|
|
74695
75033
|
for (const agent of targetAgents2) {
|
|
74696
75034
|
const hookAgent = mapAgentToHookAgent(agent);
|
|
74697
75035
|
if (!hookAgent)
|
|
@@ -74701,6 +75039,7 @@ async function installTkmHooksForAgents(targetAgents2, options2) {
|
|
|
74701
75039
|
agent: hookAgent,
|
|
74702
75040
|
global: options2.global,
|
|
74703
75041
|
dryRun: options2.dryRun,
|
|
75042
|
+
categories,
|
|
74704
75043
|
yes: true
|
|
74705
75044
|
});
|
|
74706
75045
|
} catch (err) {
|
|
@@ -74820,7 +75159,8 @@ async function executeInit(options2, prompts) {
|
|
|
74820
75159
|
if (!isSyncMode) {
|
|
74821
75160
|
await installTkmHooksForAgents(targetAgents2, {
|
|
74822
75161
|
global: Boolean(ctx.options.global),
|
|
74823
|
-
dryRun: Boolean(ctx.options.dryRun)
|
|
75162
|
+
dryRun: Boolean(ctx.options.dryRun),
|
|
75163
|
+
installHooks: Boolean(ctx.options.installHooks)
|
|
74824
75164
|
});
|
|
74825
75165
|
}
|
|
74826
75166
|
if (targetAgents2.length > 1) {
|
|
@@ -74883,19 +75223,19 @@ async function initCommand(options2) {
|
|
|
74883
75223
|
// src/commands/plan/plan-command.ts
|
|
74884
75224
|
init_output_manager();
|
|
74885
75225
|
import { existsSync as existsSync60, statSync as statSync9 } from "node:fs";
|
|
74886
|
-
import { dirname as
|
|
75226
|
+
import { dirname as dirname41, join as join128, parse as parse4, resolve as resolve33 } from "node:path";
|
|
74887
75227
|
|
|
74888
75228
|
// src/commands/plan/plan-read-handlers.ts
|
|
74889
75229
|
import { existsSync as existsSync59, statSync as statSync8 } from "node:fs";
|
|
74890
|
-
import { basename as
|
|
75230
|
+
import { basename as basename21, dirname as dirname40, join as join127, relative as relative20, resolve as resolve31 } from "node:path";
|
|
74891
75231
|
|
|
74892
75232
|
// src/domains/plan-parser/index.ts
|
|
74893
|
-
import { dirname as
|
|
75233
|
+
import { dirname as dirname39 } from "node:path";
|
|
74894
75234
|
|
|
74895
75235
|
// src/domains/plan-parser/plan-table-parser.ts
|
|
74896
75236
|
var import_gray_matter5 = __toESM(require_gray_matter(), 1);
|
|
74897
75237
|
import { readFileSync as readFileSync23 } from "node:fs";
|
|
74898
|
-
import { dirname as
|
|
75238
|
+
import { dirname as dirname36, resolve as resolve30 } from "node:path";
|
|
74899
75239
|
function normalizeStatus(raw) {
|
|
74900
75240
|
const s3 = raw.toLowerCase().trim();
|
|
74901
75241
|
if (s3.includes("complete") || s3.includes("done") || s3.includes("✓") || s3.includes("✅")) {
|
|
@@ -74916,9 +75256,9 @@ function filenameToTitle(name) {
|
|
|
74916
75256
|
}
|
|
74917
75257
|
function buildAnchor(phaseId, name) {
|
|
74918
75258
|
const suffix = phaseId.replace(/^\d+/, "");
|
|
74919
|
-
const
|
|
75259
|
+
const num4 = phaseId.replace(/[a-z]+$/i, "");
|
|
74920
75260
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
74921
|
-
return `phase-${String(
|
|
75261
|
+
return `phase-${String(num4).padStart(2, "0")}${suffix}-${slug}`;
|
|
74922
75262
|
}
|
|
74923
75263
|
function parseHeaderAwareTable(content, dir, options2) {
|
|
74924
75264
|
const lines = content.split(`
|
|
@@ -75011,11 +75351,11 @@ function parseFormat1(content, dir, options2) {
|
|
|
75011
75351
|
const regex2 = /\|\s*(\d+)([a-z]?)\s*\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|\s*\[([^\]]+)\]\(([^)]+)\)/gi;
|
|
75012
75352
|
const phases = [];
|
|
75013
75353
|
for (const match2 of content.matchAll(regex2)) {
|
|
75014
|
-
const [,
|
|
75015
|
-
const phaseId = `${
|
|
75354
|
+
const [, num4, suffix, name, status2, linkText, linkPath] = match2;
|
|
75355
|
+
const phaseId = `${num4}${suffix}`;
|
|
75016
75356
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75017
75357
|
phases.push({
|
|
75018
|
-
phase: Number.parseInt(
|
|
75358
|
+
phase: Number.parseInt(num4, 10),
|
|
75019
75359
|
phaseId,
|
|
75020
75360
|
name: name.trim(),
|
|
75021
75361
|
status: normalizeStatus(status2),
|
|
@@ -75030,12 +75370,12 @@ function parseFormat2(content, dir, options2) {
|
|
|
75030
75370
|
const regex2 = /\|\s*\[(?:Phase\s*)?(\d+)([a-z]?)\]\(([^)]+)\)\s*\|\s*([^|]+)\s*\|\s*([^|]+)/gi;
|
|
75031
75371
|
const phases = [];
|
|
75032
75372
|
for (const match2 of content.matchAll(regex2)) {
|
|
75033
|
-
const [,
|
|
75034
|
-
const phaseId = `${
|
|
75373
|
+
const [, num4, suffix, linkPath, name, status2] = match2;
|
|
75374
|
+
const phaseId = `${num4}${suffix}`;
|
|
75035
75375
|
const linkText = `Phase ${phaseId}`;
|
|
75036
75376
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75037
75377
|
phases.push({
|
|
75038
|
-
phase: Number.parseInt(
|
|
75378
|
+
phase: Number.parseInt(num4, 10),
|
|
75039
75379
|
phaseId,
|
|
75040
75380
|
name: name.trim(),
|
|
75041
75381
|
status: normalizeStatus(status2),
|
|
@@ -75050,11 +75390,11 @@ function parseFormat2b(content, dir, options2) {
|
|
|
75050
75390
|
const regex2 = /\|\s*(\d+)([a-z]?)\s*\|\s*\[([^\]]+)\]\(([^)]+)\)\s*\|\s*([^|]+)/gi;
|
|
75051
75391
|
const phases = [];
|
|
75052
75392
|
for (const match2 of content.matchAll(regex2)) {
|
|
75053
|
-
const [,
|
|
75054
|
-
const phaseId = `${
|
|
75393
|
+
const [, num4, suffix, name, linkPath, status2] = match2;
|
|
75394
|
+
const phaseId = `${num4}${suffix}`;
|
|
75055
75395
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75056
75396
|
phases.push({
|
|
75057
|
-
phase: Number.parseInt(
|
|
75397
|
+
phase: Number.parseInt(num4, 10),
|
|
75058
75398
|
phaseId,
|
|
75059
75399
|
name: name.trim(),
|
|
75060
75400
|
status: normalizeStatus(status2),
|
|
@@ -75101,11 +75441,11 @@ function parseFormat3(content, _dir, options2) {
|
|
|
75101
75441
|
if (headingMatch) {
|
|
75102
75442
|
if (current)
|
|
75103
75443
|
phases.push(current);
|
|
75104
|
-
const [,
|
|
75105
|
-
const phaseId = `${
|
|
75444
|
+
const [, num4, suffix, name] = headingMatch;
|
|
75445
|
+
const phaseId = `${num4}${suffix}`;
|
|
75106
75446
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75107
75447
|
current = {
|
|
75108
|
-
phase: Number.parseInt(
|
|
75448
|
+
phase: Number.parseInt(num4, 10),
|
|
75109
75449
|
phaseId,
|
|
75110
75450
|
name: name.trim(),
|
|
75111
75451
|
status: "pending",
|
|
@@ -75156,7 +75496,7 @@ function parseFormat4(content, planFilePath, options2) {
|
|
|
75156
75496
|
const hasCheck = /[✅✓]/.test(line);
|
|
75157
75497
|
current = { name, status: hasCheck ? "completed" : "pending" };
|
|
75158
75498
|
} else if (fileMatch && current) {
|
|
75159
|
-
const planDir =
|
|
75499
|
+
const planDir = dirname36(planFilePath);
|
|
75160
75500
|
current.file = resolve30(planDir, fileMatch[1].trim());
|
|
75161
75501
|
} else if (statusMatch && current) {
|
|
75162
75502
|
current.status = normalizeStatus(statusMatch[2]);
|
|
@@ -75181,11 +75521,11 @@ function parseFormat5(content, _dir, options2) {
|
|
|
75181
75521
|
const phases = [];
|
|
75182
75522
|
const phaseMap = new Map;
|
|
75183
75523
|
for (const match2 of content.matchAll(/^(\d+)([a-z]?)[).]\s*\*\*([^*]+)\*\*/gim)) {
|
|
75184
|
-
const [,
|
|
75185
|
-
const phaseId = `${
|
|
75524
|
+
const [, num4, suffix, name] = match2;
|
|
75525
|
+
const phaseId = `${num4}${suffix}`;
|
|
75186
75526
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75187
75527
|
phaseMap.set(name.trim().toLowerCase(), {
|
|
75188
|
-
phase: Number.parseInt(
|
|
75528
|
+
phase: Number.parseInt(num4, 10),
|
|
75189
75529
|
phaseId,
|
|
75190
75530
|
name: name.trim(),
|
|
75191
75531
|
status: "pending",
|
|
@@ -75214,12 +75554,12 @@ function parseFormat6(content, dir, options2) {
|
|
|
75214
75554
|
const regex2 = /^-\s*\[(x| )\]\s*\*\*\[(?:Phase\s*)?(\d+)([a-z]?)[:\s]*([^\]]*)\]\(([^)]+)\)\*\*/gim;
|
|
75215
75555
|
const phases = [];
|
|
75216
75556
|
for (const match2 of content.matchAll(regex2)) {
|
|
75217
|
-
const [, checked,
|
|
75218
|
-
const phaseId = `${
|
|
75557
|
+
const [, checked, num4, suffix, name, linkPath] = match2;
|
|
75558
|
+
const phaseId = `${num4}${suffix}`;
|
|
75219
75559
|
const phaseName = name.trim() || `Phase ${phaseId}`;
|
|
75220
75560
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, phaseName) : null;
|
|
75221
75561
|
phases.push({
|
|
75222
|
-
phase: Number.parseInt(
|
|
75562
|
+
phase: Number.parseInt(num4, 10),
|
|
75223
75563
|
phaseId,
|
|
75224
75564
|
name: phaseName,
|
|
75225
75565
|
status: checked.toLowerCase() === "x" ? "completed" : "pending",
|
|
@@ -75261,19 +75601,19 @@ function parsePhasesFromBody(body, dir, options2) {
|
|
|
75261
75601
|
}
|
|
75262
75602
|
function parsePlanFile(planFilePath, options2) {
|
|
75263
75603
|
const content = readFileSync23(planFilePath, "utf8");
|
|
75264
|
-
const dir =
|
|
75604
|
+
const dir = dirname36(planFilePath);
|
|
75265
75605
|
const { data: frontmatter, content: body } = import_gray_matter5.default(content);
|
|
75266
75606
|
const phases = parsePhasesFromBody(body, dir, options2);
|
|
75267
75607
|
return { frontmatter, phases };
|
|
75268
75608
|
}
|
|
75269
75609
|
// src/domains/plan-parser/plan-scanner.ts
|
|
75270
|
-
import { existsSync as existsSync56, readdirSync as
|
|
75271
|
-
import { join as
|
|
75610
|
+
import { existsSync as existsSync56, readdirSync as readdirSync10 } from "node:fs";
|
|
75611
|
+
import { join as join125 } from "node:path";
|
|
75272
75612
|
function scanPlanDir(dir) {
|
|
75273
75613
|
if (!existsSync56(dir))
|
|
75274
75614
|
return [];
|
|
75275
75615
|
try {
|
|
75276
|
-
return
|
|
75616
|
+
return readdirSync10(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join125(dir, entry.name, "plan.md")).filter(existsSync56);
|
|
75277
75617
|
} catch {
|
|
75278
75618
|
return [];
|
|
75279
75619
|
}
|
|
@@ -75281,10 +75621,10 @@ function scanPlanDir(dir) {
|
|
|
75281
75621
|
// src/domains/plan-parser/plan-validator.ts
|
|
75282
75622
|
var import_gray_matter6 = __toESM(require_gray_matter(), 1);
|
|
75283
75623
|
import { existsSync as existsSync57, readFileSync as readFileSync24 } from "node:fs";
|
|
75284
|
-
import { basename as
|
|
75624
|
+
import { basename as basename19, dirname as dirname37 } from "node:path";
|
|
75285
75625
|
function validatePlanFile(filePath, strict = false) {
|
|
75286
75626
|
const content = readFileSync24(filePath, "utf8");
|
|
75287
|
-
const dir =
|
|
75627
|
+
const dir = dirname37(filePath);
|
|
75288
75628
|
const issues = [];
|
|
75289
75629
|
const lines = content.split(`
|
|
75290
75630
|
`);
|
|
@@ -75321,13 +75661,13 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
75321
75661
|
}
|
|
75322
75662
|
for (const phase of phases) {
|
|
75323
75663
|
if (phase.file && !existsSync57(phase.file)) {
|
|
75324
|
-
const fileBasename =
|
|
75664
|
+
const fileBasename = basename19(phase.file);
|
|
75325
75665
|
const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
|
|
75326
75666
|
issues.push({
|
|
75327
75667
|
line: refLine >= 0 ? refLine + 1 : 1,
|
|
75328
75668
|
severity: "warning",
|
|
75329
75669
|
code: "missing-phase-file",
|
|
75330
|
-
message: `Phase ${phase.phaseId} references '${
|
|
75670
|
+
message: `Phase ${phase.phaseId} references '${basename19(phase.file)}' which doesn't exist`
|
|
75331
75671
|
});
|
|
75332
75672
|
}
|
|
75333
75673
|
}
|
|
@@ -75342,12 +75682,12 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
75342
75682
|
var import_gray_matter7 = __toESM(require_gray_matter(), 1);
|
|
75343
75683
|
import { mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as writeFileSync12 } from "node:fs";
|
|
75344
75684
|
import { existsSync as existsSync58 } from "node:fs";
|
|
75345
|
-
import { basename as
|
|
75685
|
+
import { basename as basename20, dirname as dirname38, join as join126 } from "node:path";
|
|
75346
75686
|
function phaseNameToFilename(id, name) {
|
|
75347
75687
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
|
|
75348
|
-
const
|
|
75688
|
+
const num4 = numMatch ? numMatch[1] : id;
|
|
75349
75689
|
const suffix = numMatch ? numMatch[2].toLowerCase() : "";
|
|
75350
|
-
const paddedNum =
|
|
75690
|
+
const paddedNum = num4.padStart(2, "0");
|
|
75351
75691
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
75352
75692
|
return `phase-${paddedNum}${suffix}-${slug}.md`;
|
|
75353
75693
|
}
|
|
@@ -75450,12 +75790,12 @@ function scaffoldPlan(options2) {
|
|
|
75450
75790
|
mkdirSync9(dir, { recursive: true });
|
|
75451
75791
|
const resolvedPhases = resolvePhaseIds(options2.phases);
|
|
75452
75792
|
const optionsWithResolved = { ...options2, phases: resolvedPhases };
|
|
75453
|
-
const planFile =
|
|
75793
|
+
const planFile = join126(dir, "plan.md");
|
|
75454
75794
|
writeFileSync12(planFile, generatePlanMd(optionsWithResolved), "utf8");
|
|
75455
75795
|
const phaseFiles = [];
|
|
75456
75796
|
for (const phase of resolvedPhases) {
|
|
75457
75797
|
const filename = phaseNameToFilename(phase.id, phase.name);
|
|
75458
|
-
const phaseFile =
|
|
75798
|
+
const phaseFile = join126(dir, filename);
|
|
75459
75799
|
writeFileSync12(phaseFile, generatePhaseTemplate(phase), "utf8");
|
|
75460
75800
|
phaseFiles.push(phaseFile);
|
|
75461
75801
|
}
|
|
@@ -75465,14 +75805,14 @@ function nextSubPhaseId(afterId, existingIds) {
|
|
|
75465
75805
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(afterId);
|
|
75466
75806
|
if (!numMatch)
|
|
75467
75807
|
throw new Error(`Invalid phase ID: ${afterId}`);
|
|
75468
|
-
const
|
|
75808
|
+
const num4 = numMatch[1];
|
|
75469
75809
|
const currentSuffix = numMatch[2].toLowerCase();
|
|
75470
75810
|
const nextSuffixChar = currentSuffix === "" ? "b" : String.fromCharCode(currentSuffix.charCodeAt(0) + 1);
|
|
75471
75811
|
if (nextSuffixChar > "z")
|
|
75472
|
-
throw new Error(`Too many sub-phases for phase ${
|
|
75473
|
-
const candidate = `${
|
|
75812
|
+
throw new Error(`Too many sub-phases for phase ${num4}`);
|
|
75813
|
+
const candidate = `${num4}${nextSuffixChar}`;
|
|
75474
75814
|
if (existingIds.includes(candidate)) {
|
|
75475
|
-
return nextSubPhaseId(`${
|
|
75815
|
+
return nextSubPhaseId(`${num4}${nextSuffixChar}`, existingIds);
|
|
75476
75816
|
}
|
|
75477
75817
|
return candidate;
|
|
75478
75818
|
}
|
|
@@ -75521,7 +75861,7 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
|
75521
75861
|
const updatedFrontmatter = { ...frontmatter, status: planStatus };
|
|
75522
75862
|
const updatedContent = import_gray_matter7.default.stringify(updatedBody, updatedFrontmatter);
|
|
75523
75863
|
writeFileSync12(planFile, updatedContent, "utf8");
|
|
75524
|
-
const planDir =
|
|
75864
|
+
const planDir = dirname38(planFile);
|
|
75525
75865
|
const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
|
|
75526
75866
|
if (phaseFilename && existsSync58(phaseFilename)) {
|
|
75527
75867
|
updatePhaseFileFrontmatter(phaseFilename, newStatus);
|
|
@@ -75535,7 +75875,7 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
|
|
|
75535
75875
|
continue;
|
|
75536
75876
|
const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
|
|
75537
75877
|
if (linkMatch)
|
|
75538
|
-
return
|
|
75878
|
+
return join126(planDir, linkMatch[2]);
|
|
75539
75879
|
}
|
|
75540
75880
|
return null;
|
|
75541
75881
|
}
|
|
@@ -75553,7 +75893,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
75553
75893
|
throw new Error("Non-canonical plan.md — cannot add phase");
|
|
75554
75894
|
}
|
|
75555
75895
|
const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
|
|
75556
|
-
const planDir =
|
|
75896
|
+
const planDir = dirname38(planFile);
|
|
75557
75897
|
const existingIds = [];
|
|
75558
75898
|
for (const match2 of body.matchAll(/^\|\s*(\d+[a-z]?)\s*\|/gim)) {
|
|
75559
75899
|
existingIds.push(match2[1].toLowerCase());
|
|
@@ -75582,7 +75922,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
75582
75922
|
insertIdx = i;
|
|
75583
75923
|
}
|
|
75584
75924
|
if (insertIdx === -1) {
|
|
75585
|
-
throw new Error(`Phase ID "${afterId}" not found in ${
|
|
75925
|
+
throw new Error(`Phase ID "${afterId}" not found in ${basename20(planFile)}`);
|
|
75586
75926
|
}
|
|
75587
75927
|
lines.splice(insertIdx + 1, 0, newRow);
|
|
75588
75928
|
updatedBody = lines.join(`
|
|
@@ -75616,7 +75956,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
75616
75956
|
`);
|
|
75617
75957
|
}
|
|
75618
75958
|
writeFileSync12(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
|
|
75619
|
-
const phaseFilePath =
|
|
75959
|
+
const phaseFilePath = join126(planDir, filename);
|
|
75620
75960
|
writeFileSync12(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
|
|
75621
75961
|
return { phaseId, phaseFile: phaseFilePath };
|
|
75622
75962
|
}
|
|
@@ -75628,7 +75968,7 @@ function buildPlanSummary(planFile) {
|
|
|
75628
75968
|
const inProgress = phases.filter((p2) => p2.status === "in-progress").length;
|
|
75629
75969
|
const pending = phases.filter((p2) => p2.status === "pending").length;
|
|
75630
75970
|
return {
|
|
75631
|
-
planDir:
|
|
75971
|
+
planDir: dirname39(planFile),
|
|
75632
75972
|
planFile,
|
|
75633
75973
|
title: typeof frontmatter.title === "string" ? frontmatter.title : undefined,
|
|
75634
75974
|
description: typeof frontmatter.description === "string" ? frontmatter.description : undefined,
|
|
@@ -75665,7 +76005,7 @@ async function handleParse(target, options2) {
|
|
|
75665
76005
|
console.log(JSON.stringify({ file: relative20(process.cwd(), planFile), frontmatter, phases }, null, 2));
|
|
75666
76006
|
return;
|
|
75667
76007
|
}
|
|
75668
|
-
const title = typeof frontmatter.title === "string" ? frontmatter.title :
|
|
76008
|
+
const title = typeof frontmatter.title === "string" ? frontmatter.title : basename21(dirname40(planFile));
|
|
75669
76009
|
console.log();
|
|
75670
76010
|
console.log(import_picocolors25.default.bold(` Plan: ${title}`));
|
|
75671
76011
|
console.log(` File: ${planFile}`);
|
|
@@ -75720,7 +76060,7 @@ async function handleValidate(target, options2) {
|
|
|
75720
76060
|
}
|
|
75721
76061
|
async function handleStatus(target, options2) {
|
|
75722
76062
|
const t = target ? resolve31(target) : null;
|
|
75723
|
-
const plansDir = t && existsSync59(t) && statSync8(t).isDirectory() && !existsSync59(
|
|
76063
|
+
const plansDir = t && existsSync59(t) && statSync8(t).isDirectory() && !existsSync59(join127(t, "plan.md")) ? t : null;
|
|
75724
76064
|
if (plansDir) {
|
|
75725
76065
|
const planFiles = scanPlanDir(plansDir);
|
|
75726
76066
|
if (planFiles.length === 0) {
|
|
@@ -75745,14 +76085,14 @@ async function handleStatus(target, options2) {
|
|
|
75745
76085
|
try {
|
|
75746
76086
|
const s3 = buildPlanSummary(pf);
|
|
75747
76087
|
const bar = progressBar(s3.completed, s3.totalPhases);
|
|
75748
|
-
const title2 = s3.title ??
|
|
76088
|
+
const title2 = s3.title ?? basename21(dirname40(pf));
|
|
75749
76089
|
console.log(` ${import_picocolors25.default.bold(title2)}`);
|
|
75750
76090
|
console.log(` ${bar}`);
|
|
75751
76091
|
if (s3.inProgress > 0)
|
|
75752
76092
|
console.log(` [~] ${s3.inProgress} in progress`);
|
|
75753
76093
|
console.log();
|
|
75754
76094
|
} catch {
|
|
75755
|
-
console.log(` [X] Failed to read: ${
|
|
76095
|
+
console.log(` [X] Failed to read: ${basename21(dirname40(pf))}`);
|
|
75756
76096
|
console.log();
|
|
75757
76097
|
}
|
|
75758
76098
|
}
|
|
@@ -75776,7 +76116,7 @@ async function handleStatus(target, options2) {
|
|
|
75776
76116
|
console.log(JSON.stringify(summary, null, 2));
|
|
75777
76117
|
return;
|
|
75778
76118
|
}
|
|
75779
|
-
const title = summary.title ??
|
|
76119
|
+
const title = summary.title ?? basename21(dirname40(planFile));
|
|
75780
76120
|
console.log();
|
|
75781
76121
|
console.log(import_picocolors25.default.bold(` ${title}`));
|
|
75782
76122
|
if (summary.status)
|
|
@@ -75802,7 +76142,7 @@ async function handleKanban(target, _options) {
|
|
|
75802
76142
|
}
|
|
75803
76143
|
|
|
75804
76144
|
// src/commands/plan/plan-write-handlers.ts
|
|
75805
|
-
import { basename as
|
|
76145
|
+
import { basename as basename22, relative as relative21, resolve as resolve32 } from "node:path";
|
|
75806
76146
|
init_output_manager();
|
|
75807
76147
|
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
75808
76148
|
async function handleCreate(target, options2) {
|
|
@@ -75855,7 +76195,7 @@ async function handleCreate(target, options2) {
|
|
|
75855
76195
|
console.log(` Directory: ${resolve32(dir)}`);
|
|
75856
76196
|
console.log(` Phases: ${result.phaseFiles.length}`);
|
|
75857
76197
|
for (const f4 of result.phaseFiles) {
|
|
75858
|
-
console.log(` [ ] ${
|
|
76198
|
+
console.log(` [ ] ${basename22(f4)}`);
|
|
75859
76199
|
}
|
|
75860
76200
|
console.log();
|
|
75861
76201
|
}
|
|
@@ -75955,7 +76295,7 @@ function resolvePlanFile(target) {
|
|
|
75955
76295
|
const stat13 = statSync9(t);
|
|
75956
76296
|
if (stat13.isFile())
|
|
75957
76297
|
return t;
|
|
75958
|
-
const candidate =
|
|
76298
|
+
const candidate = join128(t, "plan.md");
|
|
75959
76299
|
if (existsSync60(candidate))
|
|
75960
76300
|
return candidate;
|
|
75961
76301
|
}
|
|
@@ -75963,10 +76303,10 @@ function resolvePlanFile(target) {
|
|
|
75963
76303
|
let dir = process.cwd();
|
|
75964
76304
|
const root = parse4(dir).root;
|
|
75965
76305
|
while (dir !== root) {
|
|
75966
|
-
const candidate =
|
|
76306
|
+
const candidate = join128(dir, "plan.md");
|
|
75967
76307
|
if (existsSync60(candidate))
|
|
75968
76308
|
return candidate;
|
|
75969
|
-
dir =
|
|
76309
|
+
dir = dirname41(dir);
|
|
75970
76310
|
}
|
|
75971
76311
|
}
|
|
75972
76312
|
return null;
|
|
@@ -76058,17 +76398,17 @@ init_logger();
|
|
|
76058
76398
|
init_logger();
|
|
76059
76399
|
|
|
76060
76400
|
// src/commands/telemetry/shared.ts
|
|
76061
|
-
import { existsSync as existsSync61, readFileSync as readFileSync26, readdirSync as
|
|
76401
|
+
import { existsSync as existsSync61, readFileSync as readFileSync26, readdirSync as readdirSync11 } from "node:fs";
|
|
76062
76402
|
import { homedir as homedir29 } from "node:os";
|
|
76063
|
-
import { join as
|
|
76403
|
+
import { join as join129 } from "node:path";
|
|
76064
76404
|
init_token_store();
|
|
76065
76405
|
init_manifest_path_resolver();
|
|
76066
76406
|
init_takumi_constants();
|
|
76067
|
-
var USER_CACHE_PATH =
|
|
76068
|
-
var EVENT_BUFFER_DIR =
|
|
76069
|
-
var RATE_STATE_PATH =
|
|
76070
|
-
var TAKUMI_MANIFEST_PATH =
|
|
76071
|
-
var LEGACY_METADATA_PATH =
|
|
76407
|
+
var USER_CACHE_PATH = join129(homedir29(), ".claude", "sk-user.json");
|
|
76408
|
+
var EVENT_BUFFER_DIR = join129(homedir29(), ".claude", "sk-events");
|
|
76409
|
+
var RATE_STATE_PATH = join129(homedir29(), ".claude", "sk-rate-state.json");
|
|
76410
|
+
var TAKUMI_MANIFEST_PATH = join129(homedir29(), ".claude", MANIFEST_FILENAME);
|
|
76411
|
+
var LEGACY_METADATA_PATH = join129(homedir29(), ".claude", LEGACY_MANIFEST_FILENAME);
|
|
76072
76412
|
var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
|
|
76073
76413
|
var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
|
|
76074
76414
|
function readUserCache() {
|
|
@@ -76087,7 +76427,7 @@ function countBufferFiles() {
|
|
|
76087
76427
|
try {
|
|
76088
76428
|
if (!existsSync61(EVENT_BUFFER_DIR))
|
|
76089
76429
|
return 0;
|
|
76090
|
-
return
|
|
76430
|
+
return readdirSync11(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
|
|
76091
76431
|
} catch {
|
|
76092
76432
|
return 0;
|
|
76093
76433
|
}
|
|
@@ -76097,7 +76437,7 @@ function readTelemetryConfig() {
|
|
|
76097
76437
|
const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
|
|
76098
76438
|
let metadata = null;
|
|
76099
76439
|
try {
|
|
76100
|
-
const resolved = findManifestPathSync(
|
|
76440
|
+
const resolved = findManifestPathSync(join129(homedir29(), ".claude"));
|
|
76101
76441
|
if (resolved) {
|
|
76102
76442
|
metadata = JSON.parse(readFileSync26(resolved.path, "utf8"));
|
|
76103
76443
|
}
|
|
@@ -76115,12 +76455,12 @@ function readTelemetryConfig() {
|
|
|
76115
76455
|
return { endpoint, token };
|
|
76116
76456
|
}
|
|
76117
76457
|
function collectRuntimeContext() {
|
|
76118
|
-
const
|
|
76458
|
+
const cache3 = readUserCache();
|
|
76119
76459
|
const { endpoint, token } = readTelemetryConfig();
|
|
76120
76460
|
return {
|
|
76121
|
-
githubLogin: typeof
|
|
76122
|
-
cacheResolvedAt: typeof
|
|
76123
|
-
cacheSource:
|
|
76461
|
+
githubLogin: typeof cache3?.githubLogin === "string" ? cache3.githubLogin : null,
|
|
76462
|
+
cacheResolvedAt: typeof cache3?.resolvedAt === "number" ? cache3.resolvedAt : null,
|
|
76463
|
+
cacheSource: cache3?.source === "gh" || cache3?.source === "manual" ? cache3.source : null,
|
|
76124
76464
|
bufferFileCount: countBufferFiles(),
|
|
76125
76465
|
bufferDir: EVENT_BUFFER_DIR,
|
|
76126
76466
|
rateStateExists: existsSync61(RATE_STATE_PATH),
|
|
@@ -76274,8 +76614,8 @@ init_logger();
|
|
|
76274
76614
|
init_safe_prompts();
|
|
76275
76615
|
init_safe_spinner();
|
|
76276
76616
|
var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
76277
|
-
import { readdirSync as
|
|
76278
|
-
import { join as
|
|
76617
|
+
import { readdirSync as readdirSync13, rmSync as rmSync9 } from "node:fs";
|
|
76618
|
+
import { join as join131, resolve as resolve34, sep as sep10 } from "node:path";
|
|
76279
76619
|
|
|
76280
76620
|
// src/commands/uninstall/analysis-handler.ts
|
|
76281
76621
|
init_metadata_migration();
|
|
@@ -76285,8 +76625,8 @@ init_logger();
|
|
|
76285
76625
|
init_safe_prompts();
|
|
76286
76626
|
init_takumi_constants();
|
|
76287
76627
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
76288
|
-
import { existsSync as existsSync62, readdirSync as
|
|
76289
|
-
import { dirname as
|
|
76628
|
+
import { existsSync as existsSync62, readdirSync as readdirSync12, rmSync as rmSync8 } from "node:fs";
|
|
76629
|
+
import { dirname as dirname42, join as join130 } from "node:path";
|
|
76290
76630
|
function listPresentManifestNames(installPath) {
|
|
76291
76631
|
const present = [];
|
|
76292
76632
|
if (existsSync62(getManifestPath(installPath)))
|
|
@@ -76309,15 +76649,15 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
|
76309
76649
|
}
|
|
76310
76650
|
async function cleanupEmptyDirectories3(filePath, installationRoot) {
|
|
76311
76651
|
let cleaned = 0;
|
|
76312
|
-
let currentDir =
|
|
76652
|
+
let currentDir = dirname42(filePath);
|
|
76313
76653
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
76314
76654
|
try {
|
|
76315
|
-
const entries =
|
|
76655
|
+
const entries = readdirSync12(currentDir);
|
|
76316
76656
|
if (entries.length === 0) {
|
|
76317
76657
|
rmSync8(currentDir, { recursive: true });
|
|
76318
76658
|
cleaned++;
|
|
76319
76659
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
76320
|
-
currentDir =
|
|
76660
|
+
currentDir = dirname42(currentDir);
|
|
76321
76661
|
} else {
|
|
76322
76662
|
break;
|
|
76323
76663
|
}
|
|
@@ -76339,7 +76679,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
76339
76679
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
76340
76680
|
const kitFiles = metadata.kits[kit].files || [];
|
|
76341
76681
|
for (const trackedFile of kitFiles) {
|
|
76342
|
-
const filePath =
|
|
76682
|
+
const filePath = join130(installation.path, trackedFile.path);
|
|
76343
76683
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
76344
76684
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
76345
76685
|
continue;
|
|
@@ -76371,7 +76711,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
76371
76711
|
return result;
|
|
76372
76712
|
}
|
|
76373
76713
|
for (const trackedFile of allTrackedFiles) {
|
|
76374
|
-
const filePath =
|
|
76714
|
+
const filePath = join130(installation.path, trackedFile.path);
|
|
76375
76715
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
76376
76716
|
if (!ownershipResult.exists)
|
|
76377
76717
|
continue;
|
|
@@ -76470,7 +76810,7 @@ async function removeInstallations(installations, options2) {
|
|
|
76470
76810
|
let removedCount = 0;
|
|
76471
76811
|
let cleanedDirs = 0;
|
|
76472
76812
|
for (const item of analysis.toDelete) {
|
|
76473
|
-
const filePath =
|
|
76813
|
+
const filePath = join131(installation.path, item.path);
|
|
76474
76814
|
if (!await import_fs_extra37.pathExists(filePath))
|
|
76475
76815
|
continue;
|
|
76476
76816
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -76489,7 +76829,7 @@ async function removeInstallations(installations, options2) {
|
|
|
76489
76829
|
await ManifestWriter.removeKitFromManifest(installation.path, options2.kit);
|
|
76490
76830
|
}
|
|
76491
76831
|
try {
|
|
76492
|
-
const remaining =
|
|
76832
|
+
const remaining = readdirSync13(installation.path);
|
|
76493
76833
|
if (remaining.length === 0) {
|
|
76494
76834
|
rmSync9(installation.path, { recursive: true });
|
|
76495
76835
|
logger.debug(`Removed empty installation directory: ${installation.path}`);
|
|
@@ -77197,7 +77537,7 @@ ${import_picocolors29.default.bold(import_picocolors29.default.cyan(result.kitCo
|
|
|
77197
77537
|
// src/cli/command-registry.ts
|
|
77198
77538
|
init_logger();
|
|
77199
77539
|
function registerCommands(cli) {
|
|
77200
|
-
cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (core, extras). Repeat the flag to install multiple kits, e.g. --kit core --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove SK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /sk: prefix to all slash commands by moving them to commands/sk/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--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) => {
|
|
77540
|
+
cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (core, extras). Repeat the flag to install multiple kits, e.g. --kit core --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove SK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--install-hooks", "Install all agent hooks (guard, session, convention, extension). Default installs only telemetry hooks.").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("--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) => {
|
|
77201
77541
|
if (options2.exclude && !Array.isArray(options2.exclude)) {
|
|
77202
77542
|
options2.exclude = [options2.exclude];
|
|
77203
77543
|
}
|
|
@@ -77334,7 +77674,7 @@ init_manifest_path_resolver();
|
|
|
77334
77674
|
init_logger();
|
|
77335
77675
|
init_types2();
|
|
77336
77676
|
import { readFileSync as readFileSync27 } from "node:fs";
|
|
77337
|
-
import { join as
|
|
77677
|
+
import { join as join132 } from "node:path";
|
|
77338
77678
|
var PROVIDER_LOCAL_SUBDIRS = {
|
|
77339
77679
|
"claude-code": ".claude",
|
|
77340
77680
|
codex: ".codex"
|
|
@@ -77389,7 +77729,7 @@ async function displayVersion() {
|
|
|
77389
77729
|
const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
|
|
77390
77730
|
if (!localSubdir)
|
|
77391
77731
|
continue;
|
|
77392
|
-
const localRoot =
|
|
77732
|
+
const localRoot = join132(process.cwd(), localSubdir);
|
|
77393
77733
|
if (localRoot === inst.globalRoot())
|
|
77394
77734
|
continue;
|
|
77395
77735
|
const resolved = findManifestPathSync(localRoot);
|