@sunasteriskrnd/takumi 1.0.0-dev.30 → 1.0.0-dev.31
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 +646 -318
- 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.31",
|
|
19819
19819
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
19820
19820
|
type: "module",
|
|
19821
19821
|
repository: {
|
|
@@ -50740,7 +50740,7 @@ __export(exports_monorepo_resolver, {
|
|
|
50740
50740
|
resolveMonorepoRoot: () => resolveMonorepoRoot
|
|
50741
50741
|
});
|
|
50742
50742
|
import { existsSync as existsSync54, readFileSync as readFileSync22 } from "node:fs";
|
|
50743
|
-
import { dirname as
|
|
50743
|
+
import { dirname as dirname33, join as join116, resolve as resolve26 } from "node:path";
|
|
50744
50744
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
50745
50745
|
function parseMetadataAt(metadataPath) {
|
|
50746
50746
|
if (!existsSync54(metadataPath))
|
|
@@ -50757,7 +50757,7 @@ function parseMetadataAt(metadataPath) {
|
|
|
50757
50757
|
}
|
|
50758
50758
|
}
|
|
50759
50759
|
function readSourceDirFromPackageJson(candidateRoot) {
|
|
50760
|
-
const packageJsonPath =
|
|
50760
|
+
const packageJsonPath = join116(candidateRoot, "package.json");
|
|
50761
50761
|
if (!existsSync54(packageJsonPath))
|
|
50762
50762
|
return null;
|
|
50763
50763
|
try {
|
|
@@ -50780,7 +50780,7 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
50780
50780
|
};
|
|
50781
50781
|
}
|
|
50782
50782
|
const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
|
|
50783
|
-
const sourceRoot =
|
|
50783
|
+
const sourceRoot = join116(candidateRoot, sourceDir);
|
|
50784
50784
|
const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
|
|
50785
50785
|
if (nestedMetadata) {
|
|
50786
50786
|
return {
|
|
@@ -50798,7 +50798,7 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
|
|
|
50798
50798
|
const result = tryReadAtCandidate(current);
|
|
50799
50799
|
if (result)
|
|
50800
50800
|
return result;
|
|
50801
|
-
const parent =
|
|
50801
|
+
const parent = dirname33(current);
|
|
50802
50802
|
if (parent === current)
|
|
50803
50803
|
break;
|
|
50804
50804
|
current = parent;
|
|
@@ -50808,13 +50808,13 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
|
|
|
50808
50808
|
function resolveMonorepoRoot() {
|
|
50809
50809
|
try {
|
|
50810
50810
|
const thisFile = fileURLToPath3(import.meta.url);
|
|
50811
|
-
const thisDir =
|
|
50811
|
+
const thisDir = dirname33(thisFile);
|
|
50812
50812
|
const result2 = walkUpForMetadata(thisDir);
|
|
50813
50813
|
if (result2)
|
|
50814
50814
|
return result2;
|
|
50815
50815
|
} catch {}
|
|
50816
50816
|
if (process.argv[1]) {
|
|
50817
|
-
const binDir =
|
|
50817
|
+
const binDir = dirname33(resolve26(process.argv[1]));
|
|
50818
50818
|
const result2 = walkUpForMetadata(binDir);
|
|
50819
50819
|
if (result2)
|
|
50820
50820
|
return result2;
|
|
@@ -54914,6 +54914,143 @@ function tryOpenBrowser(target) {
|
|
|
54914
54914
|
// src/domains/sessions/server.ts
|
|
54915
54915
|
import * as http from "node:http";
|
|
54916
54916
|
|
|
54917
|
+
// src/domains/sessions/analytics-source.ts
|
|
54918
|
+
import { readdirSync as readdirSync6 } from "node:fs";
|
|
54919
|
+
import { join as join77 } from "node:path";
|
|
54920
|
+
|
|
54921
|
+
// src/domains/sessions/analytics.ts
|
|
54922
|
+
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
54923
|
+
var PER_DAY_MAX = 371;
|
|
54924
|
+
var LAST_N_DAYS = 30;
|
|
54925
|
+
var TOP_PROJECTS = 12;
|
|
54926
|
+
var num = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
54927
|
+
function dayKey(ms) {
|
|
54928
|
+
return new Date(ms).toISOString().slice(0, 10);
|
|
54929
|
+
}
|
|
54930
|
+
function startedMs(startedAt) {
|
|
54931
|
+
if (typeof startedAt !== "string")
|
|
54932
|
+
return null;
|
|
54933
|
+
const ms = Date.parse(startedAt);
|
|
54934
|
+
return Number.isNaN(ms) ? null : ms;
|
|
54935
|
+
}
|
|
54936
|
+
function normalizeTokens(t) {
|
|
54937
|
+
const o2 = t ?? {};
|
|
54938
|
+
return {
|
|
54939
|
+
input: num(o2.input),
|
|
54940
|
+
output: num(o2.output),
|
|
54941
|
+
cacheRead: num(o2.cacheRead),
|
|
54942
|
+
cacheWrite: num(o2.cacheWrite)
|
|
54943
|
+
};
|
|
54944
|
+
}
|
|
54945
|
+
function aggregateTokens(agg) {
|
|
54946
|
+
return normalizeTokens(agg?.tokens);
|
|
54947
|
+
}
|
|
54948
|
+
var sumTokens = (t) => t.input + t.output + t.cacheRead + t.cacheWrite;
|
|
54949
|
+
function accumulateTokens(a3, b3) {
|
|
54950
|
+
a3.input += b3.input;
|
|
54951
|
+
a3.output += b3.output;
|
|
54952
|
+
a3.cacheRead += b3.cacheRead;
|
|
54953
|
+
a3.cacheWrite += b3.cacheWrite;
|
|
54954
|
+
}
|
|
54955
|
+
function buildLast30(byDay, now) {
|
|
54956
|
+
const out = [];
|
|
54957
|
+
const todayMs = Date.parse(`${dayKey(now)}T00:00:00.000Z`);
|
|
54958
|
+
for (let i = LAST_N_DAYS - 1;i >= 0; i -= 1) {
|
|
54959
|
+
const date = dayKey(todayMs - i * DAY_MS);
|
|
54960
|
+
out.push({ date, count: byDay.get(date) ?? 0 });
|
|
54961
|
+
}
|
|
54962
|
+
return out;
|
|
54963
|
+
}
|
|
54964
|
+
function foldAnalytics(aggregates, now) {
|
|
54965
|
+
const totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
54966
|
+
const eventsByDay = new Map;
|
|
54967
|
+
const tokensByDow = new Map;
|
|
54968
|
+
const tokensByProject = new Map;
|
|
54969
|
+
const tokensByModel = new Map;
|
|
54970
|
+
const tokensByDay = new Map;
|
|
54971
|
+
for (let d3 = 0;d3 < 7; d3 += 1)
|
|
54972
|
+
tokensByDow.set(d3, 0);
|
|
54973
|
+
let agentCount = 0;
|
|
54974
|
+
let toolCallCount = 0;
|
|
54975
|
+
let eventTotal = 0;
|
|
54976
|
+
let earliestMs = null;
|
|
54977
|
+
let latestMs = null;
|
|
54978
|
+
const oldestAllowedMs = Date.parse(`${dayKey(now - PER_DAY_MAX * DAY_MS)}T00:00:00.000Z`);
|
|
54979
|
+
for (const agg of aggregates) {
|
|
54980
|
+
const t = aggregateTokens(agg);
|
|
54981
|
+
totals.input += t.input;
|
|
54982
|
+
totals.output += t.output;
|
|
54983
|
+
totals.cacheRead += t.cacheRead;
|
|
54984
|
+
totals.cacheWrite += t.cacheWrite;
|
|
54985
|
+
agentCount += num(agg?.agentCount);
|
|
54986
|
+
toolCallCount += num(agg?.toolCallCount);
|
|
54987
|
+
const events = num(agg?.eventCount);
|
|
54988
|
+
eventTotal += events;
|
|
54989
|
+
const sessionTokens = sumTokens(t);
|
|
54990
|
+
const label = agg?.projectLabel || "(unknown)";
|
|
54991
|
+
tokensByProject.set(label, (tokensByProject.get(label) ?? 0) + sessionTokens);
|
|
54992
|
+
const perModel = agg?.tokensByModel;
|
|
54993
|
+
if (perModel && typeof perModel === "object") {
|
|
54994
|
+
for (const [model, mtok] of Object.entries(perModel)) {
|
|
54995
|
+
let acc = tokensByModel.get(model);
|
|
54996
|
+
if (!acc) {
|
|
54997
|
+
acc = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
54998
|
+
tokensByModel.set(model, acc);
|
|
54999
|
+
}
|
|
55000
|
+
accumulateTokens(acc, normalizeTokens(mtok));
|
|
55001
|
+
}
|
|
55002
|
+
}
|
|
55003
|
+
const ms = startedMs(agg?.startedAt);
|
|
55004
|
+
if (ms === null)
|
|
55005
|
+
continue;
|
|
55006
|
+
if (earliestMs === null || ms < earliestMs)
|
|
55007
|
+
earliestMs = ms;
|
|
55008
|
+
if (latestMs === null || ms > latestMs)
|
|
55009
|
+
latestMs = ms;
|
|
55010
|
+
const key = dayKey(ms);
|
|
55011
|
+
eventsByDay.set(key, (eventsByDay.get(key) ?? 0) + events);
|
|
55012
|
+
tokensByDay.set(key, (tokensByDay.get(key) ?? 0) + sessionTokens);
|
|
55013
|
+
const dow = new Date(ms).getUTCDay();
|
|
55014
|
+
tokensByDow.set(dow, (tokensByDow.get(dow) ?? 0) + sessionTokens);
|
|
55015
|
+
}
|
|
55016
|
+
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));
|
|
55017
|
+
const byProjectAll = [...tokensByProject.entries()].map(([label, tokens]) => ({ label, tokens })).sort((a3, b3) => b3.tokens - a3.tokens || a3.label.localeCompare(b3.label));
|
|
55018
|
+
const byProject = byProjectAll.slice(0, TOP_PROJECTS);
|
|
55019
|
+
const daily = buildLast30(tokensByDay, now);
|
|
55020
|
+
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);
|
|
55021
|
+
const byModel = rankedModels.map(({ label, total }) => ({ label, tokens: total }));
|
|
55022
|
+
const byModelDetailed = rankedModels.map(({ label, tokens }) => ({ label, tokens }));
|
|
55023
|
+
const cacheDenom = totals.cacheRead + totals.input;
|
|
55024
|
+
const cacheHitRate = cacheDenom > 0 ? totals.cacheRead / cacheDenom : 0;
|
|
55025
|
+
return {
|
|
55026
|
+
schemaVersion: 1,
|
|
55027
|
+
generatedAt: new Date(now).toISOString(),
|
|
55028
|
+
sessionCount: aggregates.length,
|
|
55029
|
+
agentCount,
|
|
55030
|
+
toolCallCount,
|
|
55031
|
+
totals,
|
|
55032
|
+
cacheHitRate,
|
|
55033
|
+
events: {
|
|
55034
|
+
total: eventTotal,
|
|
55035
|
+
perDay,
|
|
55036
|
+
last30: buildLast30(eventsByDay, now)
|
|
55037
|
+
},
|
|
55038
|
+
tokens: {
|
|
55039
|
+
byType: { ...totals },
|
|
55040
|
+
byWeekday: [...tokensByDow.entries()].map(([dow, tokens]) => ({ dow, tokens })).sort((a3, b3) => a3.dow - b3.dow),
|
|
55041
|
+
byProject,
|
|
55042
|
+
daily,
|
|
55043
|
+
byModel,
|
|
55044
|
+
byModelDetailed
|
|
55045
|
+
},
|
|
55046
|
+
window: {
|
|
55047
|
+
earliest: earliestMs === null ? null : new Date(earliestMs).toISOString(),
|
|
55048
|
+
latest: latestMs === null ? null : new Date(latestMs).toISOString(),
|
|
55049
|
+
retentionLimited: earliestMs !== null && earliestMs >= now - PER_DAY_MAX * DAY_MS
|
|
55050
|
+
}
|
|
55051
|
+
};
|
|
55052
|
+
}
|
|
55053
|
+
|
|
54917
55054
|
// src/domains/sessions/adapters/claude.ts
|
|
54918
55055
|
import * as fs15 from "node:fs";
|
|
54919
55056
|
import * as os4 from "node:os";
|
|
@@ -54936,6 +55073,18 @@ function safeJSON(line) {
|
|
|
54936
55073
|
return null;
|
|
54937
55074
|
}
|
|
54938
55075
|
}
|
|
55076
|
+
function peekText(content) {
|
|
55077
|
+
if (typeof content === "string")
|
|
55078
|
+
return content;
|
|
55079
|
+
if (Array.isArray(content)) {
|
|
55080
|
+
return content.filter((it) => it && it.type === "text").map((it) => it.text || "").join(`
|
|
55081
|
+
`);
|
|
55082
|
+
}
|
|
55083
|
+
return "";
|
|
55084
|
+
}
|
|
55085
|
+
function isInterruptText(s) {
|
|
55086
|
+
return /^\s*\[Request interrupted\b/.test(String(s || ""));
|
|
55087
|
+
}
|
|
54939
55088
|
function readNew(transcriptPath, fromOffset) {
|
|
54940
55089
|
if (!transcriptPath || !fs14.existsSync(transcriptPath)) {
|
|
54941
55090
|
return { records: [], newOffset: fromOffset || 0 };
|
|
@@ -55086,18 +55235,6 @@ function decodeProjectDir(name) {
|
|
|
55086
55235
|
p = `/${p}`;
|
|
55087
55236
|
return p.replace(/\/+/g, "/");
|
|
55088
55237
|
}
|
|
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
55238
|
function stripCommandTags(s) {
|
|
55102
55239
|
let out = String(s || "");
|
|
55103
55240
|
for (const tag of HARNESS_TAGS) {
|
|
@@ -56171,6 +56308,189 @@ function invalidate() {
|
|
|
56171
56308
|
}
|
|
56172
56309
|
}
|
|
56173
56310
|
|
|
56311
|
+
// src/domains/sessions/transcript-metrics.ts
|
|
56312
|
+
import { basename as basename15, dirname as dirname20, join as join76 } from "node:path";
|
|
56313
|
+
function addModelTokens(byModel, model, t) {
|
|
56314
|
+
if (!model)
|
|
56315
|
+
return;
|
|
56316
|
+
byModel[model] = byModel[model] ? addTokens(byModel[model], t) : { ...t };
|
|
56317
|
+
}
|
|
56318
|
+
function toAggregate(session, m2) {
|
|
56319
|
+
return {
|
|
56320
|
+
startedAt: session.startedAt ?? null,
|
|
56321
|
+
tokens: {
|
|
56322
|
+
input: m2.tokens.input,
|
|
56323
|
+
output: m2.tokens.output,
|
|
56324
|
+
cacheRead: m2.tokens.cacheRead,
|
|
56325
|
+
cacheWrite: m2.tokens.cacheCreate
|
|
56326
|
+
},
|
|
56327
|
+
agentCount: m2.agentCount,
|
|
56328
|
+
toolCallCount: m2.toolCallCount,
|
|
56329
|
+
eventCount: m2.eventCount,
|
|
56330
|
+
projectLabel: session.project ?? "(unknown)",
|
|
56331
|
+
tokensByModel: Object.fromEntries(Object.entries(m2.tokensByModel).map(([model, t]) => [
|
|
56332
|
+
model,
|
|
56333
|
+
{ input: t.input, output: t.output, cacheRead: t.cacheRead, cacheWrite: t.cacheCreate }
|
|
56334
|
+
]))
|
|
56335
|
+
};
|
|
56336
|
+
}
|
|
56337
|
+
function zeroMetrics() {
|
|
56338
|
+
return {
|
|
56339
|
+
tokens: emptyTokens(),
|
|
56340
|
+
tokensByModel: {},
|
|
56341
|
+
agentCount: 0,
|
|
56342
|
+
toolCallCount: 0,
|
|
56343
|
+
eventCount: 0
|
|
56344
|
+
};
|
|
56345
|
+
}
|
|
56346
|
+
function isPromptUser2(r2) {
|
|
56347
|
+
if (!r2 || r2.type !== "user" || r2.isSidechain || r2.isMeta)
|
|
56348
|
+
return false;
|
|
56349
|
+
const c2 = r2.message?.content;
|
|
56350
|
+
if (isInterruptText(peekText(c2)))
|
|
56351
|
+
return false;
|
|
56352
|
+
if (typeof c2 === "string")
|
|
56353
|
+
return c2.length > 0;
|
|
56354
|
+
if (Array.isArray(c2)) {
|
|
56355
|
+
const arr = c2;
|
|
56356
|
+
if (arr.some((it) => it?.type === "tool_result"))
|
|
56357
|
+
return false;
|
|
56358
|
+
return arr.some((it) => it?.type === "text");
|
|
56359
|
+
}
|
|
56360
|
+
return false;
|
|
56361
|
+
}
|
|
56362
|
+
function scanClaudeMetrics(filePath, includeSidechain = false) {
|
|
56363
|
+
const m2 = zeroMetrics();
|
|
56364
|
+
try {
|
|
56365
|
+
const { records } = readNew(filePath, 0);
|
|
56366
|
+
for (const rec of records) {
|
|
56367
|
+
const r2 = rec;
|
|
56368
|
+
if (!r2)
|
|
56369
|
+
continue;
|
|
56370
|
+
const isAssistant = r2.type === "assistant" || r2.message?.role === "assistant";
|
|
56371
|
+
if (isAssistant && (includeSidechain || !r2.isSidechain)) {
|
|
56372
|
+
const tok = tokensOfClaude(rec);
|
|
56373
|
+
if (tok) {
|
|
56374
|
+
m2.tokens = addTokens(m2.tokens, tok);
|
|
56375
|
+
addModelTokens(m2.tokensByModel, r2.message?.model, tok);
|
|
56376
|
+
}
|
|
56377
|
+
const content = r2.message?.content;
|
|
56378
|
+
if (Array.isArray(content)) {
|
|
56379
|
+
for (const it of content) {
|
|
56380
|
+
const block = it;
|
|
56381
|
+
if (block?.type !== "tool_use")
|
|
56382
|
+
continue;
|
|
56383
|
+
m2.toolCallCount += 1;
|
|
56384
|
+
m2.eventCount += 1;
|
|
56385
|
+
if (block.name === "Task")
|
|
56386
|
+
m2.agentCount += 1;
|
|
56387
|
+
}
|
|
56388
|
+
}
|
|
56389
|
+
} else if (isPromptUser2(r2)) {
|
|
56390
|
+
m2.eventCount += 1;
|
|
56391
|
+
}
|
|
56392
|
+
}
|
|
56393
|
+
} catch {
|
|
56394
|
+
return zeroMetrics();
|
|
56395
|
+
}
|
|
56396
|
+
return m2;
|
|
56397
|
+
}
|
|
56398
|
+
function scanCodexMetrics(filePath) {
|
|
56399
|
+
const m2 = zeroMetrics();
|
|
56400
|
+
let currentModel;
|
|
56401
|
+
try {
|
|
56402
|
+
const { records } = readNew(filePath, 0);
|
|
56403
|
+
for (const rec of records) {
|
|
56404
|
+
const r2 = rec;
|
|
56405
|
+
if (!r2)
|
|
56406
|
+
continue;
|
|
56407
|
+
if (r2.type === "turn_context") {
|
|
56408
|
+
if (r2.payload?.model)
|
|
56409
|
+
currentModel = r2.payload.model;
|
|
56410
|
+
} else if (r2.type === "event_msg") {
|
|
56411
|
+
if (r2.payload?.type === "token_count") {
|
|
56412
|
+
const tok = tokensOfCodex(rec);
|
|
56413
|
+
if (tok) {
|
|
56414
|
+
m2.tokens = addTokens(m2.tokens, tok);
|
|
56415
|
+
addModelTokens(m2.tokensByModel, currentModel, tok);
|
|
56416
|
+
}
|
|
56417
|
+
} else if (r2.payload?.type === "user_message") {
|
|
56418
|
+
m2.eventCount += 1;
|
|
56419
|
+
}
|
|
56420
|
+
} else if (r2.type === "response_item" && r2.payload?.type === "function_call") {
|
|
56421
|
+
m2.toolCallCount += 1;
|
|
56422
|
+
m2.eventCount += 1;
|
|
56423
|
+
if (r2.payload?.name === "spawn_agent")
|
|
56424
|
+
m2.agentCount += 1;
|
|
56425
|
+
}
|
|
56426
|
+
}
|
|
56427
|
+
} catch {
|
|
56428
|
+
return zeroMetrics();
|
|
56429
|
+
}
|
|
56430
|
+
return m2;
|
|
56431
|
+
}
|
|
56432
|
+
function scanMetrics(adapterName, filePath) {
|
|
56433
|
+
return adapterName === "codex" ? scanCodexMetrics(filePath) : scanClaudeMetrics(filePath);
|
|
56434
|
+
}
|
|
56435
|
+
function mergeMetrics(a3, b3) {
|
|
56436
|
+
const tokensByModel = { ...a3.tokensByModel };
|
|
56437
|
+
for (const [model, tok] of Object.entries(b3.tokensByModel)) {
|
|
56438
|
+
tokensByModel[model] = tokensByModel[model] ? addTokens(tokensByModel[model], tok) : { ...tok };
|
|
56439
|
+
}
|
|
56440
|
+
return {
|
|
56441
|
+
tokens: addTokens(a3.tokens, b3.tokens),
|
|
56442
|
+
tokensByModel,
|
|
56443
|
+
agentCount: a3.agentCount + b3.agentCount,
|
|
56444
|
+
toolCallCount: a3.toolCallCount + b3.toolCallCount,
|
|
56445
|
+
eventCount: a3.eventCount + b3.eventCount
|
|
56446
|
+
};
|
|
56447
|
+
}
|
|
56448
|
+
function subagentDirFor(mainPath) {
|
|
56449
|
+
const stem = basename15(mainPath).replace(/\.jsonl$/i, "");
|
|
56450
|
+
return join76(dirname20(mainPath), stem, "subagents");
|
|
56451
|
+
}
|
|
56452
|
+
|
|
56453
|
+
// src/domains/sessions/analytics-source.ts
|
|
56454
|
+
var cache2 = null;
|
|
56455
|
+
function scanSessionMetrics(adapterName, mainPath) {
|
|
56456
|
+
const main2 = scanMetrics(adapterName, mainPath);
|
|
56457
|
+
if (adapterName === "codex")
|
|
56458
|
+
return main2;
|
|
56459
|
+
const dir = subagentDirFor(mainPath);
|
|
56460
|
+
let files;
|
|
56461
|
+
try {
|
|
56462
|
+
files = readdirSync6(dir).filter((f3) => f3.endsWith(".jsonl"));
|
|
56463
|
+
} catch {
|
|
56464
|
+
return main2;
|
|
56465
|
+
}
|
|
56466
|
+
let merged = main2;
|
|
56467
|
+
for (const f3 of files) {
|
|
56468
|
+
merged = mergeMetrics(merged, scanClaudeMetrics(join77(dir, f3), true));
|
|
56469
|
+
}
|
|
56470
|
+
return { ...merged, agentCount: main2.agentCount + files.length };
|
|
56471
|
+
}
|
|
56472
|
+
async function readAllAggregates(refresh2 = false) {
|
|
56473
|
+
if (refresh2)
|
|
56474
|
+
invalidate();
|
|
56475
|
+
const sessions = await list({ refresh: refresh2 });
|
|
56476
|
+
const aggregates = [];
|
|
56477
|
+
for (const s of sessions) {
|
|
56478
|
+
try {
|
|
56479
|
+
aggregates.push(toAggregate(s, scanSessionMetrics(s.adapterName, s.path)));
|
|
56480
|
+
} catch {}
|
|
56481
|
+
}
|
|
56482
|
+
return aggregates;
|
|
56483
|
+
}
|
|
56484
|
+
function invalidate2() {
|
|
56485
|
+
cache2 = null;
|
|
56486
|
+
}
|
|
56487
|
+
async function getAnalytics(opts = {}) {
|
|
56488
|
+
if (cache2 && !opts.refresh)
|
|
56489
|
+
return cache2;
|
|
56490
|
+
cache2 = foldAnalytics(await readAllAggregates(opts.refresh), Date.now());
|
|
56491
|
+
return cache2;
|
|
56492
|
+
}
|
|
56493
|
+
|
|
56174
56494
|
// src/domains/sessions/origin-allowlist.ts
|
|
56175
56495
|
init_build_config();
|
|
56176
56496
|
function originOf(url) {
|
|
@@ -56253,6 +56573,14 @@ async function route(req, res, version3) {
|
|
|
56253
56573
|
sendJSON(res, 200, list2);
|
|
56254
56574
|
return;
|
|
56255
56575
|
}
|
|
56576
|
+
if (pathname === "/api/analytics") {
|
|
56577
|
+
const refresh2 = url.searchParams.get("refresh") === "1";
|
|
56578
|
+
if (refresh2)
|
|
56579
|
+
invalidate2();
|
|
56580
|
+
const payload = await getAnalytics({ refresh: refresh2 });
|
|
56581
|
+
sendJSON(res, 200, payload);
|
|
56582
|
+
return;
|
|
56583
|
+
}
|
|
56256
56584
|
const m2 = pathname.match(/^\/api\/sessions\/([^/]+)\/state$/);
|
|
56257
56585
|
if (m2?.[1]) {
|
|
56258
56586
|
const id = decodeURIComponent(m2[1]);
|
|
@@ -57502,7 +57830,7 @@ init_takumi_constants();
|
|
|
57502
57830
|
import { existsSync as existsSync35, realpathSync } from "node:fs";
|
|
57503
57831
|
import { chmod as chmod2, mkdir as mkdir18, readFile as readFile32, writeFile as writeFile22 } from "node:fs/promises";
|
|
57504
57832
|
import { platform as platform5 } from "node:os";
|
|
57505
|
-
import { join as
|
|
57833
|
+
import { join as join78 } from "node:path";
|
|
57506
57834
|
var CACHE_FILE = "install-info.json";
|
|
57507
57835
|
var CACHE_TTL = 30 * 24 * 60 * 60 * 1000;
|
|
57508
57836
|
function detectFromBinaryPath() {
|
|
@@ -57586,7 +57914,7 @@ function detectFromEnv() {
|
|
|
57586
57914
|
}
|
|
57587
57915
|
async function readCachedPm() {
|
|
57588
57916
|
try {
|
|
57589
|
-
const cacheFile =
|
|
57917
|
+
const cacheFile = join78(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
57590
57918
|
if (!existsSync35(cacheFile)) {
|
|
57591
57919
|
return null;
|
|
57592
57920
|
}
|
|
@@ -57617,7 +57945,7 @@ async function saveCachedPm(pm, getVersion) {
|
|
|
57617
57945
|
return;
|
|
57618
57946
|
try {
|
|
57619
57947
|
const configDir = PathResolver.getConfigDir(false);
|
|
57620
|
-
const cacheFile =
|
|
57948
|
+
const cacheFile = join78(configDir, CACHE_FILE);
|
|
57621
57949
|
if (!existsSync35(configDir)) {
|
|
57622
57950
|
await mkdir18(configDir, { recursive: true });
|
|
57623
57951
|
if (platform5() !== "win32") {
|
|
@@ -57680,7 +58008,7 @@ async function findOwningPm() {
|
|
|
57680
58008
|
async function clearCache() {
|
|
57681
58009
|
try {
|
|
57682
58010
|
const { unlink: unlink7 } = await import("node:fs/promises");
|
|
57683
|
-
const cacheFile =
|
|
58011
|
+
const cacheFile = join78(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
57684
58012
|
if (existsSync35(cacheFile)) {
|
|
57685
58013
|
await unlink7(cacheFile);
|
|
57686
58014
|
logger.debug("Package manager cache cleared");
|
|
@@ -57942,17 +58270,17 @@ async function checkCliVersion() {
|
|
|
57942
58270
|
init_paths();
|
|
57943
58271
|
init_registry();
|
|
57944
58272
|
import { existsSync as existsSync36, statSync as statSync5 } from "node:fs";
|
|
57945
|
-
import { join as
|
|
58273
|
+
import { join as join79 } from "node:path";
|
|
57946
58274
|
function checkClaudeMd(setup, projectDir) {
|
|
57947
58275
|
const results = [];
|
|
57948
58276
|
const claudeCodeInstaller2 = getInstaller("claude-code");
|
|
57949
58277
|
if (claudeCodeInstaller2?.isInstalledGlobally()) {
|
|
57950
58278
|
const claudeGlobal = setup.globals.find((g2) => g2.provider === "claude-code") ?? setup.globals[0];
|
|
57951
58279
|
const globalPath = claudeGlobal?.path ?? claudeCodeInstaller2.globalRoot();
|
|
57952
|
-
const globalClaudeMd =
|
|
58280
|
+
const globalClaudeMd = join79(globalPath, "CLAUDE.md");
|
|
57953
58281
|
results.push(checkClaudeMdFile(globalClaudeMd, "Global CLAUDE.md", "sk-global-claude-md"));
|
|
57954
58282
|
}
|
|
57955
|
-
const projectClaudeMd =
|
|
58283
|
+
const projectClaudeMd = join79(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
57956
58284
|
results.push(checkClaudeMdFile(projectClaudeMd, "Project CLAUDE.md", "sk-project-claude-md"));
|
|
57957
58285
|
return results;
|
|
57958
58286
|
}
|
|
@@ -58011,9 +58339,9 @@ function checkClaudeMdFile(path9, name, id) {
|
|
|
58011
58339
|
}
|
|
58012
58340
|
// src/domains/health-checks/checkers/active-plan-checker.ts
|
|
58013
58341
|
import { existsSync as existsSync37, readFileSync as readFileSync10 } from "node:fs";
|
|
58014
|
-
import { join as
|
|
58342
|
+
import { join as join80 } from "node:path";
|
|
58015
58343
|
function checkActivePlan(projectDir) {
|
|
58016
|
-
const activePlanPath =
|
|
58344
|
+
const activePlanPath = join80(projectDir, ".claude", "active-plan");
|
|
58017
58345
|
if (!existsSync37(activePlanPath)) {
|
|
58018
58346
|
return {
|
|
58019
58347
|
id: "sk-active-plan",
|
|
@@ -58027,7 +58355,7 @@ function checkActivePlan(projectDir) {
|
|
|
58027
58355
|
}
|
|
58028
58356
|
try {
|
|
58029
58357
|
const targetPath = readFileSync10(activePlanPath, "utf-8").trim();
|
|
58030
|
-
const fullPath =
|
|
58358
|
+
const fullPath = join80(projectDir, targetPath);
|
|
58031
58359
|
if (!existsSync37(fullPath)) {
|
|
58032
58360
|
return {
|
|
58033
58361
|
id: "sk-active-plan",
|
|
@@ -58093,7 +58421,7 @@ function checkComponentCounts(setup) {
|
|
|
58093
58421
|
init_registry();
|
|
58094
58422
|
init_logger();
|
|
58095
58423
|
import { constants, access, unlink as unlink7, writeFile as writeFile23 } from "node:fs/promises";
|
|
58096
|
-
import { join as
|
|
58424
|
+
import { join as join81 } from "node:path";
|
|
58097
58425
|
|
|
58098
58426
|
// src/domains/health-checks/checkers/shared.ts
|
|
58099
58427
|
init_registry();
|
|
@@ -58168,7 +58496,7 @@ async function checkGlobalDirWritable(provider) {
|
|
|
58168
58496
|
}
|
|
58169
58497
|
const timestamp = Date.now();
|
|
58170
58498
|
const random = Math.random().toString(36).substring(2);
|
|
58171
|
-
const testFile =
|
|
58499
|
+
const testFile = join81(globalDir, `.sk-write-test-${timestamp}-${random}`);
|
|
58172
58500
|
try {
|
|
58173
58501
|
await writeFile23(testFile, "test", { encoding: "utf-8", flag: "wx" });
|
|
58174
58502
|
} catch (_error) {
|
|
@@ -58205,7 +58533,7 @@ init_paths();
|
|
|
58205
58533
|
init_registry();
|
|
58206
58534
|
import { existsSync as existsSync38 } from "node:fs";
|
|
58207
58535
|
import { readdir as readdir23 } from "node:fs/promises";
|
|
58208
|
-
import { join as
|
|
58536
|
+
import { join as join82 } from "node:path";
|
|
58209
58537
|
|
|
58210
58538
|
// src/domains/health-checks/utils/path-normalizer.ts
|
|
58211
58539
|
import { normalize as normalize6 } from "node:path";
|
|
@@ -58217,8 +58545,8 @@ function normalizePath(filePath) {
|
|
|
58217
58545
|
|
|
58218
58546
|
// src/domains/health-checks/checkers/hooks-checker.ts
|
|
58219
58547
|
async function checkHooksExist(projectDir) {
|
|
58220
|
-
const globalHooksDir =
|
|
58221
|
-
const projectHooksDir =
|
|
58548
|
+
const globalHooksDir = join82(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
|
|
58549
|
+
const projectHooksDir = join82(getLocalClaudeDir(projectDir), "hooks");
|
|
58222
58550
|
const globalExists = existsSync38(globalHooksDir);
|
|
58223
58551
|
const projectExists = existsSync38(projectHooksDir);
|
|
58224
58552
|
let hookCount = 0;
|
|
@@ -58227,7 +58555,7 @@ async function checkHooksExist(projectDir) {
|
|
|
58227
58555
|
const files = await readdir23(globalHooksDir, { withFileTypes: false });
|
|
58228
58556
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
|
|
58229
58557
|
hooks.forEach((hook) => {
|
|
58230
|
-
const fullPath =
|
|
58558
|
+
const fullPath = join82(globalHooksDir, hook);
|
|
58231
58559
|
checkedFiles.add(normalizePath(fullPath));
|
|
58232
58560
|
});
|
|
58233
58561
|
}
|
|
@@ -58237,7 +58565,7 @@ async function checkHooksExist(projectDir) {
|
|
|
58237
58565
|
const files = await readdir23(projectHooksDir, { withFileTypes: false });
|
|
58238
58566
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
|
|
58239
58567
|
hooks.forEach((hook) => {
|
|
58240
|
-
const fullPath =
|
|
58568
|
+
const fullPath = join82(projectHooksDir, hook);
|
|
58241
58569
|
checkedFiles.add(normalizePath(fullPath));
|
|
58242
58570
|
});
|
|
58243
58571
|
}
|
|
@@ -58268,14 +58596,14 @@ async function checkHooksExist(projectDir) {
|
|
|
58268
58596
|
init_registry();
|
|
58269
58597
|
import { existsSync as existsSync39 } from "node:fs";
|
|
58270
58598
|
import { readFile as readFile33 } from "node:fs/promises";
|
|
58271
|
-
import { join as
|
|
58599
|
+
import { join as join83 } from "node:path";
|
|
58272
58600
|
async function checkCodexHooksHealth() {
|
|
58273
58601
|
const codex = getInstaller("codex");
|
|
58274
58602
|
if (!codex?.isInstalledGlobally())
|
|
58275
58603
|
return [];
|
|
58276
58604
|
const codexRoot = codex.globalRoot();
|
|
58277
|
-
const configTomlPath =
|
|
58278
|
-
const hooksJsonPath =
|
|
58605
|
+
const configTomlPath = join83(codexRoot, "config.toml");
|
|
58606
|
+
const hooksJsonPath = join83(codexRoot, "hooks.json");
|
|
58279
58607
|
if (!existsSync39(hooksJsonPath))
|
|
58280
58608
|
return [];
|
|
58281
58609
|
const results = [];
|
|
@@ -58355,10 +58683,10 @@ init_registry();
|
|
|
58355
58683
|
init_logger();
|
|
58356
58684
|
import { existsSync as existsSync40 } from "node:fs";
|
|
58357
58685
|
import { readFile as readFile34 } from "node:fs/promises";
|
|
58358
|
-
import { join as
|
|
58686
|
+
import { join as join84 } from "node:path";
|
|
58359
58687
|
async function checkSettingsValid(projectDir) {
|
|
58360
|
-
const globalSettings =
|
|
58361
|
-
const projectSettings =
|
|
58688
|
+
const globalSettings = join84(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
|
|
58689
|
+
const projectSettings = join84(getLocalClaudeDir(projectDir), "settings.json");
|
|
58362
58690
|
const settingsPath = existsSync40(globalSettings) ? globalSettings : existsSync40(projectSettings) ? projectSettings : null;
|
|
58363
58691
|
if (!settingsPath) {
|
|
58364
58692
|
return {
|
|
@@ -58432,10 +58760,10 @@ init_logger();
|
|
|
58432
58760
|
import { existsSync as existsSync41 } from "node:fs";
|
|
58433
58761
|
import { readFile as readFile35 } from "node:fs/promises";
|
|
58434
58762
|
import { homedir as homedir24 } from "node:os";
|
|
58435
|
-
import { dirname as
|
|
58763
|
+
import { dirname as dirname21, join as join85, normalize as normalize7, resolve as resolve19 } from "node:path";
|
|
58436
58764
|
async function checkPathRefsValid(projectDir) {
|
|
58437
|
-
const globalClaudeMd =
|
|
58438
|
-
const projectClaudeMd =
|
|
58765
|
+
const globalClaudeMd = join85(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
|
|
58766
|
+
const projectClaudeMd = join85(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
58439
58767
|
const claudeMdPath = existsSync41(globalClaudeMd) ? globalClaudeMd : existsSync41(projectClaudeMd) ? projectClaudeMd : null;
|
|
58440
58768
|
if (!claudeMdPath) {
|
|
58441
58769
|
return {
|
|
@@ -58463,7 +58791,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
58463
58791
|
autoFixable: false
|
|
58464
58792
|
};
|
|
58465
58793
|
}
|
|
58466
|
-
const baseDir =
|
|
58794
|
+
const baseDir = dirname21(claudeMdPath);
|
|
58467
58795
|
const home6 = homedir24();
|
|
58468
58796
|
const broken = [];
|
|
58469
58797
|
for (const ref of refs) {
|
|
@@ -58531,7 +58859,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
58531
58859
|
init_paths();
|
|
58532
58860
|
import { existsSync as existsSync42 } from "node:fs";
|
|
58533
58861
|
import { readdir as readdir24 } from "node:fs/promises";
|
|
58534
|
-
import { join as
|
|
58862
|
+
import { join as join86 } from "node:path";
|
|
58535
58863
|
async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
58536
58864
|
if (setup.globals.some((g2) => g2.path === setup.project.path)) {
|
|
58537
58865
|
return {
|
|
@@ -58548,12 +58876,12 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
|
58548
58876
|
const requiredDirs = ["agents", "commands", "skills"];
|
|
58549
58877
|
const missingDirs = [];
|
|
58550
58878
|
for (const dir of requiredDirs) {
|
|
58551
|
-
const dirPath =
|
|
58879
|
+
const dirPath = join86(projectClaudeDir, dir);
|
|
58552
58880
|
if (!existsSync42(dirPath)) {
|
|
58553
58881
|
missingDirs.push(dir);
|
|
58554
58882
|
}
|
|
58555
58883
|
}
|
|
58556
|
-
const hasRulesOrWorkflows = existsSync42(
|
|
58884
|
+
const hasRulesOrWorkflows = existsSync42(join86(projectClaudeDir, "rules")) || existsSync42(join86(projectClaudeDir, "workflows"));
|
|
58557
58885
|
if (!hasRulesOrWorkflows) {
|
|
58558
58886
|
missingDirs.push("rules");
|
|
58559
58887
|
}
|
|
@@ -58994,7 +59322,7 @@ init_registry();
|
|
|
58994
59322
|
init_environment();
|
|
58995
59323
|
import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile36, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
|
|
58996
59324
|
import { arch as arch2, homedir as homedir25, platform as platform6 } from "node:os";
|
|
58997
|
-
import { join as
|
|
59325
|
+
import { join as join88, normalize as normalize8 } from "node:path";
|
|
58998
59326
|
function shouldSkipExpensiveOperations4() {
|
|
58999
59327
|
return shouldSkipExpensiveOperations();
|
|
59000
59328
|
}
|
|
@@ -59087,7 +59415,7 @@ async function checkGlobalDirAccess(provider) {
|
|
|
59087
59415
|
autoFixable: false
|
|
59088
59416
|
};
|
|
59089
59417
|
}
|
|
59090
|
-
const testFile =
|
|
59418
|
+
const testFile = join88(globalDir, ".sk-doctor-access-test");
|
|
59091
59419
|
try {
|
|
59092
59420
|
await mkdir19(globalDir, { recursive: true });
|
|
59093
59421
|
await writeFile24(testFile, "test", "utf-8");
|
|
@@ -59165,7 +59493,7 @@ async function checkWSLBoundary() {
|
|
|
59165
59493
|
// src/domains/health-checks/platform/windows-checker.ts
|
|
59166
59494
|
init_registry();
|
|
59167
59495
|
import { mkdir as mkdir20, symlink as symlink2, unlink as unlink9, writeFile as writeFile25 } from "node:fs/promises";
|
|
59168
|
-
import { join as
|
|
59496
|
+
import { join as join89 } from "node:path";
|
|
59169
59497
|
async function checkLongPathSupport() {
|
|
59170
59498
|
if (shouldSkipExpensiveOperations4()) {
|
|
59171
59499
|
return {
|
|
@@ -59217,8 +59545,8 @@ async function checkSymlinkSupport() {
|
|
|
59217
59545
|
};
|
|
59218
59546
|
}
|
|
59219
59547
|
const testDir = getInstaller("claude-code")?.globalRoot() ?? "";
|
|
59220
|
-
const target =
|
|
59221
|
-
const link =
|
|
59548
|
+
const target = join89(testDir, ".sk-symlink-test-target");
|
|
59549
|
+
const link = join89(testDir, ".sk-symlink-test-link");
|
|
59222
59550
|
try {
|
|
59223
59551
|
await mkdir20(testDir, { recursive: true });
|
|
59224
59552
|
await writeFile25(target, "test", "utf-8");
|
|
@@ -59514,15 +59842,15 @@ class AutoHealer {
|
|
|
59514
59842
|
import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
|
|
59515
59843
|
import { readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
59516
59844
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
59517
|
-
import { dirname as
|
|
59845
|
+
import { dirname as dirname22, join as join90 } from "node:path";
|
|
59518
59846
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
59519
59847
|
init_environment();
|
|
59520
59848
|
init_logger();
|
|
59521
59849
|
init_dist2();
|
|
59522
59850
|
function getCliVersion3() {
|
|
59523
59851
|
try {
|
|
59524
|
-
const __dirname3 =
|
|
59525
|
-
const pkgPath =
|
|
59852
|
+
const __dirname3 = dirname22(fileURLToPath2(import.meta.url));
|
|
59853
|
+
const pkgPath = join90(__dirname3, "../../../package.json");
|
|
59526
59854
|
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
59527
59855
|
return pkg.version || "unknown";
|
|
59528
59856
|
} catch (err) {
|
|
@@ -59661,7 +59989,7 @@ class ReportGenerator {
|
|
|
59661
59989
|
return null;
|
|
59662
59990
|
}
|
|
59663
59991
|
}
|
|
59664
|
-
const tmpFile =
|
|
59992
|
+
const tmpFile = join90(tmpdir2(), `sk-report-${Date.now()}.txt`);
|
|
59665
59993
|
writeFileSync6(tmpFile, report);
|
|
59666
59994
|
try {
|
|
59667
59995
|
const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "Takumi Diagnostic Report"], {
|
|
@@ -59986,7 +60314,7 @@ import { execSync as execSync5 } from "node:child_process";
|
|
|
59986
60314
|
// src/domains/hooks/handlers/_shared/env-file.ts
|
|
59987
60315
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
59988
60316
|
import { renameSync as renameSync2, unlinkSync as unlinkSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
59989
|
-
import { basename as
|
|
60317
|
+
import { basename as basename16, dirname as dirname23, join as join91 } from "node:path";
|
|
59990
60318
|
function hexEscape(code) {
|
|
59991
60319
|
return `\\x${code.toString(16).padStart(2, "0")}`;
|
|
59992
60320
|
}
|
|
@@ -60038,8 +60366,8 @@ function renderEnvFile(entries) {
|
|
|
60038
60366
|
}
|
|
60039
60367
|
function writeEnvFile(filePath, entries) {
|
|
60040
60368
|
const content = renderEnvFile(entries);
|
|
60041
|
-
const dir =
|
|
60042
|
-
const tmpPath =
|
|
60369
|
+
const dir = dirname23(filePath);
|
|
60370
|
+
const tmpPath = join91(dir, `.${basename16(filePath)}.${randomUUID2()}.tmp`);
|
|
60043
60371
|
try {
|
|
60044
60372
|
writeFileSync7(tmpPath, content, { encoding: "utf8", mode: 384 });
|
|
60045
60373
|
} catch (err) {
|
|
@@ -60087,10 +60415,10 @@ var defaultCommandRunner = (command, opts) => {
|
|
|
60087
60415
|
// src/domains/hooks/handlers/convention-quality-gate/debounce.ts
|
|
60088
60416
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
60089
60417
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
60090
|
-
import { join as
|
|
60418
|
+
import { join as join92 } from "node:path";
|
|
60091
60419
|
function stateFilePath(sessionId) {
|
|
60092
60420
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 128) || "default";
|
|
60093
|
-
return
|
|
60421
|
+
return join92(tmpdir3(), `takumi-guardrail-${safe}.json`);
|
|
60094
60422
|
}
|
|
60095
60423
|
function isWithinDebounce(sessionId, debounceMs, now) {
|
|
60096
60424
|
try {
|
|
@@ -60515,7 +60843,7 @@ function detectBroadGlob(pattern, pathHint) {
|
|
|
60515
60843
|
// src/domains/hooks/handlers/guard-breadth-scout/check-ignore.ts
|
|
60516
60844
|
var import_ignore3 = __toESM(require_ignore(), 1);
|
|
60517
60845
|
import { existsSync as existsSync44, readFileSync as readFileSync13 } from "node:fs";
|
|
60518
|
-
import { dirname as
|
|
60846
|
+
import { dirname as dirname24, join as join93 } from "node:path";
|
|
60519
60847
|
var BUILTIN_HEAVY_DIR_LINES = [
|
|
60520
60848
|
"node_modules",
|
|
60521
60849
|
".pnp",
|
|
@@ -60552,9 +60880,9 @@ var BUILTIN_HEAVY_DIR_LINES = [
|
|
|
60552
60880
|
function findGitRoot(startDir) {
|
|
60553
60881
|
let dir = startDir;
|
|
60554
60882
|
while (true) {
|
|
60555
|
-
if (existsSync44(
|
|
60883
|
+
if (existsSync44(join93(dir, ".git")))
|
|
60556
60884
|
return dir;
|
|
60557
|
-
const parent =
|
|
60885
|
+
const parent = dirname24(dir);
|
|
60558
60886
|
if (parent === dir)
|
|
60559
60887
|
return null;
|
|
60560
60888
|
dir = parent;
|
|
@@ -60582,11 +60910,11 @@ function loadIgnoreConfig(cwd2) {
|
|
|
60582
60910
|
const gitRoot = findGitRoot(cwd2);
|
|
60583
60911
|
const candidatePaths = [];
|
|
60584
60912
|
if (gitRoot) {
|
|
60585
|
-
candidatePaths.push(
|
|
60586
|
-
candidatePaths.push(
|
|
60913
|
+
candidatePaths.push(join93(gitRoot, ".claude", ".tkmignore"));
|
|
60914
|
+
candidatePaths.push(join93(gitRoot, ".claude", ".skignore"));
|
|
60587
60915
|
}
|
|
60588
|
-
candidatePaths.push(
|
|
60589
|
-
candidatePaths.push(
|
|
60916
|
+
candidatePaths.push(join93(cwd2, ".claude", ".tkmignore"));
|
|
60917
|
+
candidatePaths.push(join93(cwd2, ".claude", ".skignore"));
|
|
60590
60918
|
for (const candidate of candidatePaths) {
|
|
60591
60919
|
const lines = readIgnoreFile(candidate);
|
|
60592
60920
|
if (lines !== null) {
|
|
@@ -61050,10 +61378,10 @@ function getBasename(normalized) {
|
|
|
61050
61378
|
function isSensitivePath(normalized) {
|
|
61051
61379
|
if (!normalized)
|
|
61052
61380
|
return false;
|
|
61053
|
-
const
|
|
61054
|
-
if (SAFE_LIST_RE.test(
|
|
61381
|
+
const basename17 = getBasename(normalized);
|
|
61382
|
+
if (SAFE_LIST_RE.test(basename17))
|
|
61055
61383
|
return false;
|
|
61056
|
-
return SENSITIVE_CATEGORY_PATTERNS.some((re2) => re2.test(
|
|
61384
|
+
return SENSITIVE_CATEGORY_PATTERNS.some((re2) => re2.test(basename17) || re2.test(normalized));
|
|
61057
61385
|
}
|
|
61058
61386
|
function normalizeForMatch(raw) {
|
|
61059
61387
|
let value = raw;
|
|
@@ -61134,20 +61462,20 @@ function findFirstRelevantPath(candidates) {
|
|
|
61134
61462
|
}
|
|
61135
61463
|
return null;
|
|
61136
61464
|
}
|
|
61137
|
-
function buildApprovalPayload(file,
|
|
61465
|
+
function buildApprovalPayload(file, basename17) {
|
|
61138
61466
|
return {
|
|
61139
61467
|
type: "SECRET_READ_REQUEST",
|
|
61140
61468
|
file,
|
|
61141
|
-
basename:
|
|
61469
|
+
basename: basename17,
|
|
61142
61470
|
question: {
|
|
61143
61471
|
header: "Secret-bearing file",
|
|
61144
|
-
text: `"${
|
|
61472
|
+
text: `"${basename17}" looks like it stores credentials or secrets. Should the agent be allowed to read it?`,
|
|
61145
61473
|
options: [
|
|
61146
61474
|
{
|
|
61147
61475
|
label: "Approve",
|
|
61148
|
-
description: `Allow reading "${
|
|
61476
|
+
description: `Allow reading "${basename17}" once, then retry with that approval.`
|
|
61149
61477
|
},
|
|
61150
|
-
{ label: "Decline", description: `Keep "${
|
|
61478
|
+
{ label: "Decline", description: `Keep "${basename17}" blocked and do not read it.` }
|
|
61151
61479
|
]
|
|
61152
61480
|
}
|
|
61153
61481
|
};
|
|
@@ -61283,7 +61611,7 @@ function resolveEndpoint() {
|
|
|
61283
61611
|
init_manifest_path_resolver();
|
|
61284
61612
|
import { existsSync as existsSync45, readFileSync as readFileSync14 } from "node:fs";
|
|
61285
61613
|
import { homedir as homedir26 } from "node:os";
|
|
61286
|
-
import { dirname as
|
|
61614
|
+
import { dirname as dirname25, join as join94, resolve as resolve20 } from "node:path";
|
|
61287
61615
|
var PROVIDER_DIRS = [".claude", ".codex"];
|
|
61288
61616
|
var MAX_WALK = 6;
|
|
61289
61617
|
function readManifestRaw(path11) {
|
|
@@ -61302,25 +61630,25 @@ function findManifest(cwd2) {
|
|
|
61302
61630
|
let dir = resolve20(cwd2);
|
|
61303
61631
|
for (let i = 0;i < MAX_WALK; i++) {
|
|
61304
61632
|
for (const provider of PROVIDER_DIRS) {
|
|
61305
|
-
const providerRoot =
|
|
61633
|
+
const providerRoot = join94(dir, provider);
|
|
61306
61634
|
if (existsSync45(providerRoot)) {
|
|
61307
61635
|
const path11 = findManifestInProviderDir(providerRoot);
|
|
61308
61636
|
if (path11)
|
|
61309
61637
|
return path11;
|
|
61310
61638
|
}
|
|
61311
61639
|
}
|
|
61312
|
-
const parent =
|
|
61640
|
+
const parent = dirname25(dir);
|
|
61313
61641
|
if (parent === dir)
|
|
61314
61642
|
break;
|
|
61315
61643
|
dir = parent;
|
|
61316
61644
|
}
|
|
61317
61645
|
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
|
|
61318
61646
|
if (pluginRoot) {
|
|
61319
|
-
const pluginPath = findManifestInProviderDir(
|
|
61647
|
+
const pluginPath = findManifestInProviderDir(join94(pluginRoot, ".claude"));
|
|
61320
61648
|
if (pluginPath)
|
|
61321
61649
|
return pluginPath;
|
|
61322
61650
|
}
|
|
61323
|
-
const globalPath = findManifestInProviderDir(
|
|
61651
|
+
const globalPath = findManifestInProviderDir(join94(homedir26(), ".claude"));
|
|
61324
61652
|
if (globalPath)
|
|
61325
61653
|
return globalPath;
|
|
61326
61654
|
return null;
|
|
@@ -61412,7 +61740,7 @@ async function readStdinJson() {
|
|
|
61412
61740
|
// src/domains/hooks/telemetry/lib/detached-put.ts
|
|
61413
61741
|
import { spawn as spawn2 } from "node:child_process";
|
|
61414
61742
|
import { openSync as openSync4 } from "node:fs";
|
|
61415
|
-
import { dirname as
|
|
61743
|
+
import { dirname as dirname26, join as join95 } from "node:path";
|
|
61416
61744
|
var ALLOWED_ENV_PREFIXES = ["TKM_", "TAKUMI_"];
|
|
61417
61745
|
var ALLOWED_ENV_KEYS = new Set(["HOME", "USERPROFILE", "PATH", "NODE_ENV"]);
|
|
61418
61746
|
var DETACH_DEBUG_LOG_NAME = "detach-debug.log";
|
|
@@ -61420,7 +61748,7 @@ function effectiveDetachMode(flags) {
|
|
|
61420
61748
|
return flags.noDetach ? "inline" : "detached";
|
|
61421
61749
|
}
|
|
61422
61750
|
function sessionDebugLogPath(sessionDir) {
|
|
61423
|
-
return
|
|
61751
|
+
return join95(sessionDir, DETACH_DEBUG_LOG_NAME);
|
|
61424
61752
|
}
|
|
61425
61753
|
var BUNFS_PREFIX = "/$bunfs/";
|
|
61426
61754
|
function resolveInvocationPrefix() {
|
|
@@ -61448,9 +61776,9 @@ function resolveInvocationPrefix() {
|
|
|
61448
61776
|
}
|
|
61449
61777
|
function resolvePreloadScript(entryPath) {
|
|
61450
61778
|
try {
|
|
61451
|
-
const srcDir =
|
|
61452
|
-
const repoRoot =
|
|
61453
|
-
return
|
|
61779
|
+
const srcDir = dirname26(entryPath);
|
|
61780
|
+
const repoRoot = dirname26(srcDir);
|
|
61781
|
+
return join95(repoRoot, "scripts", "preload-config-override.ts");
|
|
61454
61782
|
} catch {
|
|
61455
61783
|
return null;
|
|
61456
61784
|
}
|
|
@@ -61522,13 +61850,13 @@ import { promises as fs20 } from "node:fs";
|
|
|
61522
61850
|
|
|
61523
61851
|
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
61524
61852
|
init_paths2();
|
|
61525
|
-
import { join as
|
|
61853
|
+
import { join as join97 } from "node:path";
|
|
61526
61854
|
|
|
61527
61855
|
// src/shared/project-paths.ts
|
|
61528
61856
|
init_paths2();
|
|
61529
61857
|
import { createHash as createHash9 } from "node:crypto";
|
|
61530
61858
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
61531
|
-
import { basename as
|
|
61859
|
+
import { basename as basename17, join as join96 } from "node:path";
|
|
61532
61860
|
function encodeCwd(cwd2) {
|
|
61533
61861
|
const stripped = cwd2.replace(/^\/+/, "");
|
|
61534
61862
|
const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
@@ -61544,13 +61872,13 @@ function computeProjectHash(cwd2) {
|
|
|
61544
61872
|
return createHash9("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
61545
61873
|
}
|
|
61546
61874
|
function getProjectLabel(cwd2) {
|
|
61547
|
-
return
|
|
61875
|
+
return basename17(cwd2) || "";
|
|
61548
61876
|
}
|
|
61549
61877
|
function getProjectsRoot() {
|
|
61550
|
-
return
|
|
61878
|
+
return join96(getConfigDir(), "projects");
|
|
61551
61879
|
}
|
|
61552
61880
|
function getProjectDir(args) {
|
|
61553
|
-
return
|
|
61881
|
+
return join96(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
|
|
61554
61882
|
}
|
|
61555
61883
|
|
|
61556
61884
|
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
@@ -61562,35 +61890,35 @@ function safeSessionSegment(sessionId) {
|
|
|
61562
61890
|
return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
|
|
61563
61891
|
}
|
|
61564
61892
|
function getSessionsRoot() {
|
|
61565
|
-
return
|
|
61893
|
+
return join97(getConfigDir(), "sessions");
|
|
61566
61894
|
}
|
|
61567
61895
|
function getSessionDirV2(args) {
|
|
61568
61896
|
const segment = safeSessionSegment(args.sessionId);
|
|
61569
61897
|
if (!segment)
|
|
61570
61898
|
return null;
|
|
61571
|
-
return
|
|
61899
|
+
return join97(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
|
|
61572
61900
|
}
|
|
61573
61901
|
function getEventsFile(sessionDir) {
|
|
61574
|
-
return
|
|
61902
|
+
return join97(sessionDir, "events.jsonl");
|
|
61575
61903
|
}
|
|
61576
61904
|
function getSummaryFile(sessionDir) {
|
|
61577
|
-
return
|
|
61905
|
+
return join97(sessionDir, "summary.json");
|
|
61578
61906
|
}
|
|
61579
61907
|
function getLastPushFile(sessionDir) {
|
|
61580
|
-
return
|
|
61908
|
+
return join97(sessionDir, "last_push.txt");
|
|
61581
61909
|
}
|
|
61582
61910
|
var OBSERVATIONS_FILENAME = "observations.jsonl";
|
|
61583
61911
|
function getObservationsFile(sessionDir) {
|
|
61584
|
-
return
|
|
61912
|
+
return join97(sessionDir, OBSERVATIONS_FILENAME);
|
|
61585
61913
|
}
|
|
61586
61914
|
function getObservationsFlushingFile(sessionDir) {
|
|
61587
|
-
return
|
|
61915
|
+
return join97(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
|
|
61588
61916
|
}
|
|
61589
61917
|
function getObservationsPushedFile(sessionDir) {
|
|
61590
|
-
return
|
|
61918
|
+
return join97(sessionDir, "obs_pushed.txt");
|
|
61591
61919
|
}
|
|
61592
61920
|
function getMetaFile(sessionDir) {
|
|
61593
|
-
return
|
|
61921
|
+
return join97(sessionDir, "meta.json");
|
|
61594
61922
|
}
|
|
61595
61923
|
|
|
61596
61924
|
// src/domains/hooks/telemetry/lib/session-meta.ts
|
|
@@ -61762,7 +62090,7 @@ async function shouldFlush(args) {
|
|
|
61762
62090
|
}
|
|
61763
62091
|
|
|
61764
62092
|
// src/domains/hooks/telemetry/lib/transcript-reader.ts
|
|
61765
|
-
function
|
|
62093
|
+
function num2(v2) {
|
|
61766
62094
|
return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
61767
62095
|
}
|
|
61768
62096
|
function zeroTokens2() {
|
|
@@ -61781,10 +62109,10 @@ function extractTokens(record) {
|
|
|
61781
62109
|
if (!usage)
|
|
61782
62110
|
return null;
|
|
61783
62111
|
return {
|
|
61784
|
-
input:
|
|
61785
|
-
output:
|
|
61786
|
-
cache_read:
|
|
61787
|
-
cache_write:
|
|
62112
|
+
input: num2(usage.input_tokens),
|
|
62113
|
+
output: num2(usage.output_tokens),
|
|
62114
|
+
cache_read: num2(usage.cache_read_input_tokens),
|
|
62115
|
+
cache_write: num2(usage.cache_creation_input_tokens)
|
|
61788
62116
|
};
|
|
61789
62117
|
}
|
|
61790
62118
|
async function tailRead(args) {
|
|
@@ -61919,8 +62247,8 @@ async function runSessionEndFlush(data, ctx) {
|
|
|
61919
62247
|
session_end_raw: data
|
|
61920
62248
|
};
|
|
61921
62249
|
const { promises: fs23 } = await import("node:fs");
|
|
61922
|
-
const { join:
|
|
61923
|
-
const target =
|
|
62250
|
+
const { join: join98 } = await import("node:path");
|
|
62251
|
+
const target = join98(sessionDir, "meta.json");
|
|
61924
62252
|
const tmp = `${target}.tmp`;
|
|
61925
62253
|
await fs23.writeFile(tmp, JSON.stringify(updated), "utf8");
|
|
61926
62254
|
await fs23.rename(tmp, target);
|
|
@@ -61995,17 +62323,17 @@ init_takumi_constants();
|
|
|
61995
62323
|
|
|
61996
62324
|
// src/domains/hooks/lib/jsonl-append.ts
|
|
61997
62325
|
import { promises as fs23, appendFileSync as appendFileSync2, mkdirSync as mkdirSync4 } from "node:fs";
|
|
61998
|
-
import { dirname as
|
|
62326
|
+
import { dirname as dirname27 } from "node:path";
|
|
61999
62327
|
async function appendJsonl(filePath, record) {
|
|
62000
62328
|
try {
|
|
62001
|
-
await fs23.mkdir(
|
|
62329
|
+
await fs23.mkdir(dirname27(filePath), { recursive: true });
|
|
62002
62330
|
await fs23.appendFile(filePath, `${JSON.stringify(record)}
|
|
62003
62331
|
`, "utf8");
|
|
62004
62332
|
} catch {}
|
|
62005
62333
|
}
|
|
62006
62334
|
function appendJsonlLineSync(filePath, line) {
|
|
62007
62335
|
try {
|
|
62008
|
-
mkdirSync4(
|
|
62336
|
+
mkdirSync4(dirname27(filePath), { recursive: true });
|
|
62009
62337
|
appendFileSync2(filePath, `${line}
|
|
62010
62338
|
`, "utf8");
|
|
62011
62339
|
} catch {}
|
|
@@ -62088,15 +62416,15 @@ function diagnoseStopFailure(status2, error) {
|
|
|
62088
62416
|
return "server_error_check_takumi_web_logs";
|
|
62089
62417
|
return null;
|
|
62090
62418
|
}
|
|
62091
|
-
function
|
|
62419
|
+
function num3(v2) {
|
|
62092
62420
|
return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
62093
62421
|
}
|
|
62094
62422
|
function usageToTokens(usage) {
|
|
62095
62423
|
return {
|
|
62096
|
-
input:
|
|
62097
|
-
output:
|
|
62098
|
-
cache_read:
|
|
62099
|
-
cache_write:
|
|
62424
|
+
input: num3(usage.input_tokens),
|
|
62425
|
+
output: num3(usage.output_tokens),
|
|
62426
|
+
cache_read: num3(usage.cache_read_tokens),
|
|
62427
|
+
cache_write: num3(usage.cache_write_tokens)
|
|
62100
62428
|
};
|
|
62101
62429
|
}
|
|
62102
62430
|
function readCliVersion2() {
|
|
@@ -62271,11 +62599,11 @@ async function handleStop(agent, flags = {}) {
|
|
|
62271
62599
|
// src/domains/hooks/telemetry/otlp/observations-export.ts
|
|
62272
62600
|
init_paths2();
|
|
62273
62601
|
import { promises as fs27, openSync as openSync6 } from "node:fs";
|
|
62274
|
-
import { join as
|
|
62602
|
+
import { join as join99 } from "node:path";
|
|
62275
62603
|
|
|
62276
62604
|
// src/domains/hooks/telemetry/lib/retention.ts
|
|
62277
62605
|
import { promises as fs24 } from "node:fs";
|
|
62278
|
-
import { join as
|
|
62606
|
+
import { join as join98 } from "node:path";
|
|
62279
62607
|
async function pathExists24(path11) {
|
|
62280
62608
|
try {
|
|
62281
62609
|
await fs24.access(path11);
|
|
@@ -62310,7 +62638,7 @@ async function decideDelete(dir, args) {
|
|
|
62310
62638
|
async function listChildren(dir) {
|
|
62311
62639
|
try {
|
|
62312
62640
|
const names = await fs24.readdir(dir);
|
|
62313
|
-
return names.map((n) =>
|
|
62641
|
+
return names.map((n) => join98(dir, n));
|
|
62314
62642
|
} catch {
|
|
62315
62643
|
return [];
|
|
62316
62644
|
}
|
|
@@ -62321,7 +62649,7 @@ async function collectV2Sessions() {
|
|
|
62321
62649
|
const sessions = [];
|
|
62322
62650
|
for (const projectDir of projects) {
|
|
62323
62651
|
for (const agentDir of await listChildren(projectDir)) {
|
|
62324
|
-
for (const sessionDir of await listChildren(
|
|
62652
|
+
for (const sessionDir of await listChildren(join98(agentDir, "sessions"))) {
|
|
62325
62653
|
sessions.push(sessionDir);
|
|
62326
62654
|
}
|
|
62327
62655
|
}
|
|
@@ -62750,7 +63078,7 @@ async function exportSessionObservations(sessionDir, opts = {}, deps = {}) {
|
|
|
62750
63078
|
}
|
|
62751
63079
|
}
|
|
62752
63080
|
function lockPath() {
|
|
62753
|
-
return
|
|
63081
|
+
return join99(getConfigDir(), "obs-flush.lock");
|
|
62754
63082
|
}
|
|
62755
63083
|
async function acquireSweepLock(now) {
|
|
62756
63084
|
const path11 = lockPath();
|
|
@@ -63289,11 +63617,11 @@ var metricsRecord = {
|
|
|
63289
63617
|
|
|
63290
63618
|
// src/domains/hooks/handlers/session-init/handler.ts
|
|
63291
63619
|
import { mkdirSync as mkdirSync5 } from "node:fs";
|
|
63292
|
-
import { dirname as
|
|
63620
|
+
import { dirname as dirname28, join as join103 } from "node:path";
|
|
63293
63621
|
|
|
63294
63622
|
// src/domains/hooks/handlers/_shared/project-detector.ts
|
|
63295
63623
|
import { existsSync as existsSync46, readFileSync as readFileSync15 } from "node:fs";
|
|
63296
|
-
import { join as
|
|
63624
|
+
import { join as join100 } from "node:path";
|
|
63297
63625
|
var LOCKFILE_PRIORITY = [
|
|
63298
63626
|
{ manager: "bun", files: ["bun.lockb", "bun.lock"] },
|
|
63299
63627
|
{ manager: "pnpm", files: ["pnpm-lock.yaml"] },
|
|
@@ -63328,14 +63656,14 @@ var APP_FRAMEWORKS = new Set([
|
|
|
63328
63656
|
var WORKSPACE_MARKER_FILES = ["pnpm-workspace.yaml", "turbo.json", "lerna.json"];
|
|
63329
63657
|
function fileExists(cwd2, name) {
|
|
63330
63658
|
try {
|
|
63331
|
-
return existsSync46(
|
|
63659
|
+
return existsSync46(join100(cwd2, name));
|
|
63332
63660
|
} catch {
|
|
63333
63661
|
return false;
|
|
63334
63662
|
}
|
|
63335
63663
|
}
|
|
63336
63664
|
function readPackageJson(cwd2) {
|
|
63337
63665
|
try {
|
|
63338
|
-
const raw = readFileSync15(
|
|
63666
|
+
const raw = readFileSync15(join100(cwd2, "package.json"), "utf8");
|
|
63339
63667
|
const parsed = JSON.parse(raw);
|
|
63340
63668
|
if (parsed && typeof parsed === "object")
|
|
63341
63669
|
return parsed;
|
|
@@ -63419,25 +63747,25 @@ function detectProject(cwd2) {
|
|
|
63419
63747
|
// src/domains/hooks/handlers/session-init/env-entries.ts
|
|
63420
63748
|
import { createHash as createHash11 } from "node:crypto";
|
|
63421
63749
|
import { platform as platform8, userInfo } from "node:os";
|
|
63422
|
-
import { join as
|
|
63750
|
+
import { join as join102 } from "node:path";
|
|
63423
63751
|
|
|
63424
63752
|
// src/domains/hooks/handlers/session-init/plan-resolver.ts
|
|
63425
|
-
import { existsSync as existsSync47, readFileSync as readFileSync16, readdirSync as
|
|
63426
|
-
import { join as
|
|
63753
|
+
import { existsSync as existsSync47, readFileSync as readFileSync16, readdirSync as readdirSync7 } from "node:fs";
|
|
63754
|
+
import { join as join101 } from "node:path";
|
|
63427
63755
|
var MAX_PLAN_DIRS = 100;
|
|
63428
63756
|
var MAX_PLAN_FILE_BYTES = 64 * 1024;
|
|
63429
63757
|
function listPlanDirs(plansPath) {
|
|
63430
63758
|
try {
|
|
63431
63759
|
if (!existsSync47(plansPath))
|
|
63432
63760
|
return [];
|
|
63433
|
-
return
|
|
63761
|
+
return readdirSync7(plansPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort().slice(0, MAX_PLAN_DIRS);
|
|
63434
63762
|
} catch {
|
|
63435
63763
|
return [];
|
|
63436
63764
|
}
|
|
63437
63765
|
}
|
|
63438
63766
|
function planFileMentionsSession(planDir, sessionId) {
|
|
63439
63767
|
try {
|
|
63440
|
-
const planFile =
|
|
63768
|
+
const planFile = join101(planDir, "plan.md");
|
|
63441
63769
|
if (!existsSync47(planFile))
|
|
63442
63770
|
return false;
|
|
63443
63771
|
const body = readFileSync16(planFile, { encoding: "utf8" });
|
|
@@ -63452,7 +63780,7 @@ function resolveActivePlan(plansPath, sessionId) {
|
|
|
63452
63780
|
if (!sessionId)
|
|
63453
63781
|
return "";
|
|
63454
63782
|
for (const name of listPlanDirs(plansPath)) {
|
|
63455
|
-
const dir =
|
|
63783
|
+
const dir = join101(plansPath, name);
|
|
63456
63784
|
if (name.includes(sessionId) || planFileMentionsSession(dir, sessionId)) {
|
|
63457
63785
|
return dir;
|
|
63458
63786
|
}
|
|
@@ -63473,7 +63801,7 @@ function resolveSuggestedPlan(plansPath, branch, branchPattern) {
|
|
|
63473
63801
|
return "";
|
|
63474
63802
|
for (const name of listPlanDirs(plansPath)) {
|
|
63475
63803
|
if (name.includes(slug))
|
|
63476
|
-
return
|
|
63804
|
+
return join101(plansPath, name);
|
|
63477
63805
|
}
|
|
63478
63806
|
return "";
|
|
63479
63807
|
}
|
|
@@ -63527,11 +63855,11 @@ function buildEnvEntries(params) {
|
|
|
63527
63855
|
const plan = config.plan ?? {};
|
|
63528
63856
|
const locale = config.locale ?? {};
|
|
63529
63857
|
const validation = plan.validation ?? {};
|
|
63530
|
-
const settingsDir =
|
|
63531
|
-
const docsPath =
|
|
63532
|
-
const plansPath =
|
|
63858
|
+
const settingsDir = join102(projectRoot, ".claude");
|
|
63859
|
+
const docsPath = join102(projectRoot, paths.docs ?? "docs");
|
|
63860
|
+
const plansPath = join102(projectRoot, paths.plans ?? "plans");
|
|
63533
63861
|
const reportsDir = plan.reportsDir ?? "reports";
|
|
63534
|
-
const reportsPath =
|
|
63862
|
+
const reportsPath = join102(plansPath, reportsDir);
|
|
63535
63863
|
const namingFormat = plan.namingFormat ?? "";
|
|
63536
63864
|
const activePlan = resolveActivePlan(plansPath, ctx.sessionId);
|
|
63537
63865
|
const suggestedPlan = resolveSuggestedPlan(plansPath, branch, plan.resolution?.branchPattern ?? "");
|
|
@@ -63612,11 +63940,11 @@ function resolveEnvFilePath(settingsDir) {
|
|
|
63612
63940
|
const override = process.env.CLAUDE_ENV_FILE;
|
|
63613
63941
|
if (override && override.trim().length > 0)
|
|
63614
63942
|
return override;
|
|
63615
|
-
return
|
|
63943
|
+
return join103(settingsDir, DEFAULT_ENV_FILE);
|
|
63616
63944
|
}
|
|
63617
63945
|
function persistEntries(envFilePath, entries) {
|
|
63618
63946
|
try {
|
|
63619
|
-
mkdirSync5(
|
|
63947
|
+
mkdirSync5(dirname28(envFilePath), { recursive: true });
|
|
63620
63948
|
writeEnvFile(envFilePath, entries);
|
|
63621
63949
|
return true;
|
|
63622
63950
|
} catch {
|
|
@@ -63669,7 +63997,7 @@ import { execFileSync as execFileSync3 } from "node:child_process";
|
|
|
63669
63997
|
import { createHash as createHash12 } from "node:crypto";
|
|
63670
63998
|
import { existsSync as existsSync48, mkdirSync as mkdirSync6, readFileSync as readFileSync17, rmSync as rmSync3, statSync as statSync6, writeFileSync as writeFileSync9 } from "node:fs";
|
|
63671
63999
|
import { homedir as homedir27, platform as platform9, tmpdir as tmpdir4 } from "node:os";
|
|
63672
|
-
import { basename as
|
|
64000
|
+
import { basename as basename18, join as join104, resolve as resolve21 } from "node:path";
|
|
63673
64001
|
var INJECTED_TTL_MS = 12 * 60 * 60 * 1000;
|
|
63674
64002
|
var RESERVATION_TTL_MS = 60 * 1000;
|
|
63675
64003
|
function gitBranch(dir) {
|
|
@@ -63742,16 +64070,16 @@ function buildPromptContext(args) {
|
|
|
63742
64070
|
function scopeKey(baseDir) {
|
|
63743
64071
|
const abs = resolve21(baseDir || ".");
|
|
63744
64072
|
const hash = createHash12("sha256").update(abs).digest("hex").slice(0, 16);
|
|
63745
|
-
const slug =
|
|
64073
|
+
const slug = basename18(abs).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 24) || "root";
|
|
63746
64074
|
return `${slug}-${hash}`;
|
|
63747
64075
|
}
|
|
63748
64076
|
function stateDir() {
|
|
63749
|
-
return
|
|
64077
|
+
return join104(tmpdir4(), "takumi-context-throttle");
|
|
63750
64078
|
}
|
|
63751
64079
|
function stateFile(sessionId, scope, transcriptPath) {
|
|
63752
64080
|
const key = `${sessionId}\x00${scope}\x00${transcriptPath ?? ""}`;
|
|
63753
64081
|
const hash = createHash12("sha256").update(key).digest("hex").slice(0, 32);
|
|
63754
|
-
return
|
|
64082
|
+
return join104(stateDir(), `${hash}.json`);
|
|
63755
64083
|
}
|
|
63756
64084
|
function readState(file) {
|
|
63757
64085
|
try {
|
|
@@ -63820,8 +64148,8 @@ function clearPending(sessionId, scope, transcriptPath) {
|
|
|
63820
64148
|
} catch {}
|
|
63821
64149
|
}
|
|
63822
64150
|
function resolveSkillsVenv(_cwd) {
|
|
63823
|
-
const base =
|
|
63824
|
-
const interpreter = platform9() === "win32" ?
|
|
64151
|
+
const base = join104(homedir27(), ".claude", "skills", ".venv");
|
|
64152
|
+
const interpreter = platform9() === "win32" ? join104(base, "Scripts", "python.exe") : join104(base, "bin", "python3");
|
|
63825
64153
|
return existsSync48(interpreter) ? interpreter : null;
|
|
63826
64154
|
}
|
|
63827
64155
|
|
|
@@ -63860,12 +64188,12 @@ var sessionPromptContext = {
|
|
|
63860
64188
|
};
|
|
63861
64189
|
|
|
63862
64190
|
// src/domains/hooks/handlers/session-subagent-init/context-block.ts
|
|
63863
|
-
import { join as
|
|
64191
|
+
import { join as join106 } from "node:path";
|
|
63864
64192
|
|
|
63865
64193
|
// src/domains/hooks/handlers/session-subagent-init/context-sources.ts
|
|
63866
64194
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
63867
|
-
import { readdirSync as
|
|
63868
|
-
import { isAbsolute as isAbsolute4, join as
|
|
64195
|
+
import { readdirSync as readdirSync8, statSync as statSync7 } from "node:fs";
|
|
64196
|
+
import { isAbsolute as isAbsolute4, join as join105, resolve as resolve22 } from "node:path";
|
|
63869
64197
|
var MAX_DOCS_FILES = 15;
|
|
63870
64198
|
var MAX_DOCS_SUBDIRS = 5;
|
|
63871
64199
|
function gitFacts(dir) {
|
|
@@ -63897,16 +64225,16 @@ function planDirTemplate(format, dateStr) {
|
|
|
63897
64225
|
}
|
|
63898
64226
|
function detectPlan(plansAbs) {
|
|
63899
64227
|
try {
|
|
63900
|
-
const entries =
|
|
64228
|
+
const entries = readdirSync8(plansAbs, { withFileTypes: true });
|
|
63901
64229
|
let best = null;
|
|
63902
64230
|
for (const e2 of entries) {
|
|
63903
64231
|
if (!e2.isDirectory())
|
|
63904
64232
|
continue;
|
|
63905
|
-
const dir =
|
|
64233
|
+
const dir = join105(plansAbs, e2.name);
|
|
63906
64234
|
try {
|
|
63907
|
-
if (!
|
|
64235
|
+
if (!readdirSync8(dir).includes("plan.md"))
|
|
63908
64236
|
continue;
|
|
63909
|
-
const mtime = statSync7(
|
|
64237
|
+
const mtime = statSync7(join105(dir, "plan.md")).mtimeMs;
|
|
63910
64238
|
if (!best || mtime > best.mtime)
|
|
63911
64239
|
best = { name: e2.name, mtime };
|
|
63912
64240
|
} catch {}
|
|
@@ -63918,7 +64246,7 @@ function detectPlan(plansAbs) {
|
|
|
63918
64246
|
}
|
|
63919
64247
|
function docsCatalogue(docsAbs) {
|
|
63920
64248
|
try {
|
|
63921
|
-
const entries =
|
|
64249
|
+
const entries = readdirSync8(docsAbs, { withFileTypes: true });
|
|
63922
64250
|
const files = entries.filter((e2) => e2.isFile() && e2.name.toLowerCase().endsWith(".md")).map((e2) => e2.name).sort();
|
|
63923
64251
|
const subdirs = entries.filter((e2) => e2.isDirectory()).map((e2) => e2.name).sort();
|
|
63924
64252
|
const lines = [];
|
|
@@ -63929,7 +64257,7 @@ function docsCatalogue(docsAbs) {
|
|
|
63929
64257
|
for (const d3 of subdirs.slice(0, MAX_DOCS_SUBDIRS)) {
|
|
63930
64258
|
let count = 0;
|
|
63931
64259
|
try {
|
|
63932
|
-
count =
|
|
64260
|
+
count = readdirSync8(join105(docsAbs, d3)).length;
|
|
63933
64261
|
} catch {}
|
|
63934
64262
|
lines.push(`- ${d3}/ (${count} entries)`);
|
|
63935
64263
|
}
|
|
@@ -63973,11 +64301,11 @@ function buildSubagentContext(input, ctx) {
|
|
|
63973
64301
|
const agentId = strField(input, "agent_id") || "unknown";
|
|
63974
64302
|
const plansAbs = abs(base, cfg.paths?.plans?.trim() || "plans");
|
|
63975
64303
|
const docsAbs = abs(base, cfg.paths?.docs?.trim() || "docs");
|
|
63976
|
-
const reportsAbs =
|
|
64304
|
+
const reportsAbs = join106(plansAbs, cfg.plan?.reportsDir?.trim() || "reports");
|
|
63977
64305
|
const dateStr = stamp(cfg.plan?.dateFormat?.trim() || "YYMMDD-HHmm", new Date);
|
|
63978
64306
|
const namingFormat = cfg.plan?.namingFormat?.trim() || "{date}-{slug}";
|
|
63979
|
-
const planDir =
|
|
63980
|
-
const reportFile =
|
|
64307
|
+
const planDir = join106(plansAbs, planDirTemplate(namingFormat, dateStr));
|
|
64308
|
+
const reportFile = join106(reportsAbs, `${agentKey}-${dateStr}-{slug}-report.md`);
|
|
63981
64309
|
const activePlan = detectPlan(plansAbs);
|
|
63982
64310
|
const venv = resolveSkillsVenv(effectiveCwd);
|
|
63983
64311
|
const respLang = cfg.locale?.responseLanguage?.trim() || null;
|
|
@@ -64580,7 +64908,7 @@ init_hooks_settings_merger();
|
|
|
64580
64908
|
// src/commands/portable/settings-write-with-confirm.ts
|
|
64581
64909
|
init_safe_prompts();
|
|
64582
64910
|
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
|
|
64911
|
+
import { dirname as dirname29 } from "node:path";
|
|
64584
64912
|
|
|
64585
64913
|
// node_modules/diff/libesm/diff/base.js
|
|
64586
64914
|
class Diff {
|
|
@@ -65783,7 +66111,7 @@ function diffStats(diff) {
|
|
|
65783
66111
|
return { additions, deletions };
|
|
65784
66112
|
}
|
|
65785
66113
|
function atomicWrite2(path11, contents, backupPath) {
|
|
65786
|
-
mkdirSync7(
|
|
66114
|
+
mkdirSync7(dirname29(path11), { recursive: true });
|
|
65787
66115
|
const tmp = `${path11}.tmp`;
|
|
65788
66116
|
try {
|
|
65789
66117
|
writeFileSync10(tmp, contents);
|
|
@@ -65874,13 +66202,13 @@ import { existsSync as existsSync50 } from "node:fs";
|
|
|
65874
66202
|
// src/commands/hooks/lib/settings-path-resolver.ts
|
|
65875
66203
|
import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "node:fs";
|
|
65876
66204
|
import { homedir as homedir28 } from "node:os";
|
|
65877
|
-
import { join as
|
|
66205
|
+
import { join as join107 } from "node:path";
|
|
65878
66206
|
function rawPath(agent, global3) {
|
|
65879
66207
|
const root = global3 ? homedir28() : process.cwd();
|
|
65880
66208
|
if (agent === "claude") {
|
|
65881
|
-
return
|
|
66209
|
+
return join107(root, ".claude", "settings.json");
|
|
65882
66210
|
}
|
|
65883
|
-
return
|
|
66211
|
+
return join107(root, ".codex", "hooks.json");
|
|
65884
66212
|
}
|
|
65885
66213
|
function resolveSettingsPath(agent, options2 = {}) {
|
|
65886
66214
|
const originalPath = rawPath(agent, Boolean(options2.global));
|
|
@@ -66030,7 +66358,7 @@ function buildHookSection(agent, bin, flags = {}, handlers3 = HOOK_HANDLERS) {
|
|
|
66030
66358
|
// src/commands/hooks/uninstall-handler.ts
|
|
66031
66359
|
init_logger();
|
|
66032
66360
|
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
|
|
66361
|
+
import { dirname as dirname30 } from "node:path";
|
|
66034
66362
|
var AGENT_DISPLAY2 = {
|
|
66035
66363
|
claude: "Claude Code",
|
|
66036
66364
|
codex: "Codex"
|
|
@@ -66071,7 +66399,7 @@ function pruneHooksSection(hooks, agent) {
|
|
|
66071
66399
|
return { pruned, removed };
|
|
66072
66400
|
}
|
|
66073
66401
|
function writeAtomic(path11, contents) {
|
|
66074
|
-
mkdirSync8(
|
|
66402
|
+
mkdirSync8(dirname30(path11), { recursive: true });
|
|
66075
66403
|
const tmp = `${path11}.tmp`;
|
|
66076
66404
|
try {
|
|
66077
66405
|
writeFileSync11(tmp, contents);
|
|
@@ -67573,7 +67901,7 @@ init_logger();
|
|
|
67573
67901
|
init_takumi_constants();
|
|
67574
67902
|
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
67575
67903
|
var import_semver5 = __toESM(require_semver2(), 1);
|
|
67576
|
-
import { join as
|
|
67904
|
+
import { join as join108 } from "node:path";
|
|
67577
67905
|
function evaluateCliVersionGate(input) {
|
|
67578
67906
|
const min = typeof input.minCliVersion === "string" ? input.minCliVersion.trim() : undefined;
|
|
67579
67907
|
if (!min)
|
|
@@ -67594,7 +67922,7 @@ function evaluateCliVersionGate(input) {
|
|
|
67594
67922
|
}
|
|
67595
67923
|
async function readKitMinCliVersion(extractDir) {
|
|
67596
67924
|
try {
|
|
67597
|
-
const resolved = await findManifestPath(
|
|
67925
|
+
const resolved = await findManifestPath(join108(extractDir, ".claude"));
|
|
67598
67926
|
if (!resolved)
|
|
67599
67927
|
return;
|
|
67600
67928
|
const raw = await import_fs_extra31.readFile(resolved.path, "utf-8");
|
|
@@ -67785,7 +68113,7 @@ init_logger();
|
|
|
67785
68113
|
init_safe_spinner();
|
|
67786
68114
|
import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
|
|
67787
68115
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
67788
|
-
import { join as
|
|
68116
|
+
import { join as join114 } from "node:path";
|
|
67789
68117
|
|
|
67790
68118
|
// src/shared/temp-cleanup.ts
|
|
67791
68119
|
init_logger();
|
|
@@ -67804,7 +68132,7 @@ init_logger();
|
|
|
67804
68132
|
init_output_manager();
|
|
67805
68133
|
import { createWriteStream as createWriteStream2, rmSync as rmSync6 } from "node:fs";
|
|
67806
68134
|
import { mkdir as mkdir21 } from "node:fs/promises";
|
|
67807
|
-
import { join as
|
|
68135
|
+
import { join as join109 } from "node:path";
|
|
67808
68136
|
|
|
67809
68137
|
// src/shared/progress-bar.ts
|
|
67810
68138
|
init_output_manager();
|
|
@@ -68014,7 +68342,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
|
|
|
68014
68342
|
class FileDownloader {
|
|
68015
68343
|
async downloadAsset(asset, destDir) {
|
|
68016
68344
|
try {
|
|
68017
|
-
const destPath =
|
|
68345
|
+
const destPath = join109(destDir, asset.name);
|
|
68018
68346
|
await mkdir21(destDir, { recursive: true });
|
|
68019
68347
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
68020
68348
|
logger.verbose("Download details", {
|
|
@@ -68099,7 +68427,7 @@ class FileDownloader {
|
|
|
68099
68427
|
}
|
|
68100
68428
|
async downloadFile(params) {
|
|
68101
68429
|
const { url, name, size, destDir, token } = params;
|
|
68102
|
-
const destPath =
|
|
68430
|
+
const destPath = join109(destDir, name);
|
|
68103
68431
|
await mkdir21(destDir, { recursive: true });
|
|
68104
68432
|
output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
68105
68433
|
const headers = {};
|
|
@@ -68202,7 +68530,7 @@ init_logger();
|
|
|
68202
68530
|
init_types2();
|
|
68203
68531
|
import { constants as constants3 } from "node:fs";
|
|
68204
68532
|
import { access as access3, readdir as readdir25 } from "node:fs/promises";
|
|
68205
|
-
import { join as
|
|
68533
|
+
import { join as join110 } from "node:path";
|
|
68206
68534
|
async function validateExtraction(extractDir) {
|
|
68207
68535
|
try {
|
|
68208
68536
|
const entries = await readdir25(extractDir, { encoding: "utf8" });
|
|
@@ -68214,7 +68542,7 @@ async function validateExtraction(extractDir) {
|
|
|
68214
68542
|
const missingPaths = [];
|
|
68215
68543
|
for (const path11 of criticalPaths) {
|
|
68216
68544
|
try {
|
|
68217
|
-
await access3(
|
|
68545
|
+
await access3(join110(extractDir, path11), constants3.F_OK);
|
|
68218
68546
|
logger.debug(`Found: ${path11}`);
|
|
68219
68547
|
} catch {
|
|
68220
68548
|
logger.warning(`Expected path not found: ${path11}`);
|
|
@@ -68236,7 +68564,7 @@ async function validateExtraction(extractDir) {
|
|
|
68236
68564
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
68237
68565
|
init_logger();
|
|
68238
68566
|
import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat8 } from "node:fs/promises";
|
|
68239
|
-
import { join as
|
|
68567
|
+
import { join as join112 } from "node:path";
|
|
68240
68568
|
|
|
68241
68569
|
// node_modules/tar/dist/esm/index.min.js
|
|
68242
68570
|
import Kr from "events";
|
|
@@ -71449,7 +71777,7 @@ function decodeFilePath(path11) {
|
|
|
71449
71777
|
init_logger();
|
|
71450
71778
|
init_types2();
|
|
71451
71779
|
import { copyFile as copyFile4, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
|
|
71452
|
-
import { join as
|
|
71780
|
+
import { join as join111, relative as relative16 } from "node:path";
|
|
71453
71781
|
async function withRetry2(fn2, retries = 3) {
|
|
71454
71782
|
for (let i = 0;i < retries; i++) {
|
|
71455
71783
|
try {
|
|
@@ -71471,8 +71799,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
71471
71799
|
await mkdir22(destDir, { recursive: true });
|
|
71472
71800
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
71473
71801
|
for (const entry of entries) {
|
|
71474
|
-
const sourcePath =
|
|
71475
|
-
const destPath =
|
|
71802
|
+
const sourcePath = join111(sourceDir, entry);
|
|
71803
|
+
const destPath = join111(destDir, entry);
|
|
71476
71804
|
const relativePath = relative16(sourceDir, sourcePath);
|
|
71477
71805
|
if (!isPathSafe(destDir, destPath)) {
|
|
71478
71806
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -71499,8 +71827,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
|
71499
71827
|
await mkdir22(destDir, { recursive: true });
|
|
71500
71828
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
71501
71829
|
for (const entry of entries) {
|
|
71502
|
-
const sourcePath =
|
|
71503
|
-
const destPath =
|
|
71830
|
+
const sourcePath = join111(sourceDir, entry);
|
|
71831
|
+
const destPath = join111(destDir, entry);
|
|
71504
71832
|
const relativePath = relative16(sourceDir, sourcePath);
|
|
71505
71833
|
if (!isPathSafe(destDir, destPath)) {
|
|
71506
71834
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -71555,7 +71883,7 @@ class TarExtractor {
|
|
|
71555
71883
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
71556
71884
|
if (entries.length === 1) {
|
|
71557
71885
|
const rootEntry = entries[0];
|
|
71558
|
-
const rootPath =
|
|
71886
|
+
const rootPath = join112(tempExtractDir, rootEntry);
|
|
71559
71887
|
const rootStat = await stat8(rootPath);
|
|
71560
71888
|
if (rootStat.isDirectory()) {
|
|
71561
71889
|
const rootContents = await readdir27(rootPath, { encoding: "utf8" });
|
|
@@ -71571,7 +71899,7 @@ class TarExtractor {
|
|
|
71571
71899
|
}
|
|
71572
71900
|
} else {
|
|
71573
71901
|
await mkdir23(destDir, { recursive: true });
|
|
71574
|
-
await copyFile5(rootPath,
|
|
71902
|
+
await copyFile5(rootPath, join112(destDir, rootEntry));
|
|
71575
71903
|
}
|
|
71576
71904
|
} else {
|
|
71577
71905
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -71592,7 +71920,7 @@ class TarExtractor {
|
|
|
71592
71920
|
init_logger();
|
|
71593
71921
|
import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
71594
71922
|
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
|
|
71923
|
+
import { dirname as dirname31, join as join113, resolve as resolve24 } from "node:path";
|
|
71596
71924
|
import { pipeline } from "node:stream/promises";
|
|
71597
71925
|
import yauzl from "yauzl-promise";
|
|
71598
71926
|
class ZipExtractor {
|
|
@@ -71606,7 +71934,7 @@ class ZipExtractor {
|
|
|
71606
71934
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
71607
71935
|
if (entries.length === 1) {
|
|
71608
71936
|
const rootEntry = entries[0];
|
|
71609
|
-
const rootPath =
|
|
71937
|
+
const rootPath = join113(tempExtractDir, rootEntry);
|
|
71610
71938
|
const rootStat = await stat9(rootPath);
|
|
71611
71939
|
if (rootStat.isDirectory()) {
|
|
71612
71940
|
const rootContents = await readdir28(rootPath, { encoding: "utf8" });
|
|
@@ -71622,7 +71950,7 @@ class ZipExtractor {
|
|
|
71622
71950
|
}
|
|
71623
71951
|
} else {
|
|
71624
71952
|
await mkdir24(destDir, { recursive: true });
|
|
71625
|
-
await copyFile6(rootPath,
|
|
71953
|
+
await copyFile6(rootPath, join113(destDir, rootEntry));
|
|
71626
71954
|
}
|
|
71627
71955
|
} else {
|
|
71628
71956
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -71653,7 +71981,7 @@ class ZipExtractor {
|
|
|
71653
71981
|
await mkdir24(outPath, { recursive: true });
|
|
71654
71982
|
continue;
|
|
71655
71983
|
}
|
|
71656
|
-
await mkdir24(
|
|
71984
|
+
await mkdir24(dirname31(outPath), { recursive: true });
|
|
71657
71985
|
const readStream = await entry.openReadStream();
|
|
71658
71986
|
await pipeline(readStream, createWriteStream3(outPath));
|
|
71659
71987
|
const unixMode = entry.externalFileAttributes >>> 16 & 511;
|
|
@@ -71751,7 +72079,7 @@ class DownloadManager {
|
|
|
71751
72079
|
async createTempDir() {
|
|
71752
72080
|
const timestamp = Date.now();
|
|
71753
72081
|
const counter = DownloadManager.tempDirCounter++;
|
|
71754
|
-
const primaryTempDir =
|
|
72082
|
+
const primaryTempDir = join114(tmpdir5(), `takumi-${timestamp}-${counter}`);
|
|
71755
72083
|
try {
|
|
71756
72084
|
await mkdir25(primaryTempDir, { recursive: true });
|
|
71757
72085
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -71768,7 +72096,7 @@ Solutions:
|
|
|
71768
72096
|
2. Set HOME environment variable
|
|
71769
72097
|
3. Try running from a different directory`);
|
|
71770
72098
|
}
|
|
71771
|
-
const fallbackTempDir =
|
|
72099
|
+
const fallbackTempDir = join114(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
|
|
71772
72100
|
try {
|
|
71773
72101
|
await mkdir25(fallbackTempDir, { recursive: true });
|
|
71774
72102
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -72474,7 +72802,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
|
|
|
72474
72802
|
}
|
|
72475
72803
|
// src/commands/init/phases/selection-handler.ts
|
|
72476
72804
|
import { mkdir as mkdir26 } from "node:fs/promises";
|
|
72477
|
-
import { join as
|
|
72805
|
+
import { join as join118, resolve as resolve28 } from "node:path";
|
|
72478
72806
|
|
|
72479
72807
|
// src/commands/shared/agent-selector.ts
|
|
72480
72808
|
init_registry();
|
|
@@ -72627,8 +72955,8 @@ init_logger();
|
|
|
72627
72955
|
init_safe_spinner();
|
|
72628
72956
|
init_takumi_constants();
|
|
72629
72957
|
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
72630
|
-
import { existsSync as existsSync55, readdirSync as
|
|
72631
|
-
import { dirname as
|
|
72958
|
+
import { existsSync as existsSync55, readdirSync as readdirSync9, rmSync as rmSync7, rmdirSync as rmdirSync2, unlinkSync as unlinkSync6 } from "node:fs";
|
|
72959
|
+
import { dirname as dirname34, join as join117, resolve as resolve27 } from "node:path";
|
|
72632
72960
|
var TAKUMI_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
|
|
72633
72961
|
async function analyzeFreshInstallation(claudeDir) {
|
|
72634
72962
|
const metadata = await readManifest(claudeDir);
|
|
@@ -72674,14 +73002,14 @@ async function analyzeFreshInstallation(claudeDir) {
|
|
|
72674
73002
|
}
|
|
72675
73003
|
function cleanupEmptyDirectories2(filePath, claudeDir) {
|
|
72676
73004
|
const normalizedClaudeDir = resolve27(claudeDir);
|
|
72677
|
-
let currentDir = resolve27(
|
|
73005
|
+
let currentDir = resolve27(dirname34(filePath));
|
|
72678
73006
|
while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
|
|
72679
73007
|
try {
|
|
72680
|
-
const entries =
|
|
73008
|
+
const entries = readdirSync9(currentDir);
|
|
72681
73009
|
if (entries.length === 0) {
|
|
72682
73010
|
rmdirSync2(currentDir);
|
|
72683
73011
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
72684
|
-
currentDir = resolve27(
|
|
73012
|
+
currentDir = resolve27(dirname34(currentDir));
|
|
72685
73013
|
} else {
|
|
72686
73014
|
break;
|
|
72687
73015
|
}
|
|
@@ -72698,7 +73026,7 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
72698
73026
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
72699
73027
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
72700
73028
|
for (const file of filesToRemove) {
|
|
72701
|
-
const fullPath =
|
|
73029
|
+
const fullPath = join117(claudeDir, file.path);
|
|
72702
73030
|
try {
|
|
72703
73031
|
if (existsSync55(fullPath)) {
|
|
72704
73032
|
unlinkSync6(fullPath);
|
|
@@ -72772,7 +73100,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
72772
73100
|
const removedFiles = [];
|
|
72773
73101
|
let removedDirCount = 0;
|
|
72774
73102
|
for (const subdir of TAKUMI_SUBDIRECTORIES) {
|
|
72775
|
-
const subdirPath =
|
|
73103
|
+
const subdirPath = join117(claudeDir, subdir);
|
|
72776
73104
|
if (await import_fs_extra32.pathExists(subdirPath)) {
|
|
72777
73105
|
rmSync7(subdirPath, { recursive: true, force: true });
|
|
72778
73106
|
removedDirCount++;
|
|
@@ -72997,7 +73325,7 @@ async function handleSelection(ctx) {
|
|
|
72997
73325
|
}
|
|
72998
73326
|
if (!ctx.options.fresh) {
|
|
72999
73327
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73000
|
-
const claudeDir = prefix ?
|
|
73328
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73001
73329
|
try {
|
|
73002
73330
|
const existingMetadata = await readManifest(claudeDir);
|
|
73003
73331
|
if (existingMetadata?.kits) {
|
|
@@ -73030,7 +73358,7 @@ async function handleSelection(ctx) {
|
|
|
73030
73358
|
}
|
|
73031
73359
|
if (ctx.options.fresh) {
|
|
73032
73360
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73033
|
-
const claudeDir = prefix ?
|
|
73361
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73034
73362
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
73035
73363
|
if (!canProceed) {
|
|
73036
73364
|
return { ...ctx, cancelled: true };
|
|
@@ -73050,7 +73378,7 @@ async function handleSelection(ctx) {
|
|
|
73050
73378
|
let currentVersion = null;
|
|
73051
73379
|
try {
|
|
73052
73380
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73053
|
-
const claudeDir = prefix ?
|
|
73381
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73054
73382
|
const existingMetadata = await readManifest(claudeDir);
|
|
73055
73383
|
currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
|
|
73056
73384
|
if (currentVersion) {
|
|
@@ -73138,7 +73466,7 @@ async function handleSelection(ctx) {
|
|
|
73138
73466
|
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
|
|
73139
73467
|
try {
|
|
73140
73468
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73141
|
-
const claudeDir = prefix ?
|
|
73469
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73142
73470
|
const existingMetadata = await readManifest(claudeDir);
|
|
73143
73471
|
const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
|
|
73144
73472
|
if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
|
|
@@ -73161,7 +73489,7 @@ async function handleSelection(ctx) {
|
|
|
73161
73489
|
let currentSecondaryVersion = null;
|
|
73162
73490
|
try {
|
|
73163
73491
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
73164
|
-
const claudeDir = prefix ?
|
|
73492
|
+
const claudeDir = prefix ? join118(resolvedDir, prefix) : resolvedDir;
|
|
73165
73493
|
const existingMetadata = await readManifest(claudeDir);
|
|
73166
73494
|
currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
|
|
73167
73495
|
} catch {}
|
|
@@ -73245,12 +73573,12 @@ function resolveGlobalTargetDir(targetAgents2) {
|
|
|
73245
73573
|
// src/commands/init/phases/sync-handler.ts
|
|
73246
73574
|
init_paths();
|
|
73247
73575
|
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
|
|
73576
|
+
import { dirname as dirname35, join as join121, resolve as resolve29 } from "node:path";
|
|
73249
73577
|
|
|
73250
73578
|
// src/domains/sync/config-version-checker.ts
|
|
73251
73579
|
init_auth_client();
|
|
73252
73580
|
import { mkdir as mkdir27, readFile as readFile39, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
|
|
73253
|
-
import { join as
|
|
73581
|
+
import { join as join119 } from "node:path";
|
|
73254
73582
|
init_version_utils();
|
|
73255
73583
|
init_logger();
|
|
73256
73584
|
init_path_resolver();
|
|
@@ -73286,7 +73614,7 @@ var CACHE_FILENAME = "config-update-cache.json";
|
|
|
73286
73614
|
class ConfigVersionChecker {
|
|
73287
73615
|
static getCacheFilePath(kitType, global3) {
|
|
73288
73616
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
73289
|
-
return
|
|
73617
|
+
return join119(cacheDir, `${kitType}-${CACHE_FILENAME}`);
|
|
73290
73618
|
}
|
|
73291
73619
|
static async loadCache(kitType, global3) {
|
|
73292
73620
|
try {
|
|
@@ -73302,12 +73630,12 @@ class ConfigVersionChecker {
|
|
|
73302
73630
|
return null;
|
|
73303
73631
|
}
|
|
73304
73632
|
}
|
|
73305
|
-
static async saveCache(kitType, global3,
|
|
73633
|
+
static async saveCache(kitType, global3, cache3) {
|
|
73306
73634
|
try {
|
|
73307
73635
|
const cachePath = ConfigVersionChecker.getCacheFilePath(kitType, global3);
|
|
73308
73636
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
73309
73637
|
await mkdir27(cacheDir, { recursive: true });
|
|
73310
|
-
await writeFile27(cachePath, JSON.stringify(
|
|
73638
|
+
await writeFile27(cachePath, JSON.stringify(cache3, null, 2));
|
|
73311
73639
|
} catch (error) {
|
|
73312
73640
|
logger.debug(`Cache write failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
73313
73641
|
}
|
|
@@ -73349,14 +73677,14 @@ class ConfigVersionChecker {
|
|
|
73349
73677
|
}
|
|
73350
73678
|
static async checkForUpdates(kitType, currentVersion, global3 = false) {
|
|
73351
73679
|
const normalizedCurrent = currentVersion.replace(/^v/, "");
|
|
73352
|
-
const
|
|
73680
|
+
const cache3 = await ConfigVersionChecker.loadCache(kitType, global3);
|
|
73353
73681
|
const now = Date.now();
|
|
73354
|
-
if (
|
|
73355
|
-
const hasUpdates = isNewerVersion(normalizedCurrent,
|
|
73682
|
+
if (cache3 && now - cache3.lastCheck < CACHE_TTL_MS) {
|
|
73683
|
+
const hasUpdates = isNewerVersion(normalizedCurrent, cache3.latestVersion);
|
|
73356
73684
|
return {
|
|
73357
73685
|
hasUpdates,
|
|
73358
73686
|
currentVersion: normalizedCurrent,
|
|
73359
|
-
latestVersion:
|
|
73687
|
+
latestVersion: cache3.latestVersion,
|
|
73360
73688
|
fromCache: true
|
|
73361
73689
|
};
|
|
73362
73690
|
}
|
|
@@ -73374,12 +73702,12 @@ class ConfigVersionChecker {
|
|
|
73374
73702
|
fromCache: false
|
|
73375
73703
|
};
|
|
73376
73704
|
}
|
|
73377
|
-
if (
|
|
73378
|
-
const hasUpdates = isNewerVersion(normalizedCurrent,
|
|
73705
|
+
if (cache3) {
|
|
73706
|
+
const hasUpdates = isNewerVersion(normalizedCurrent, cache3.latestVersion);
|
|
73379
73707
|
return {
|
|
73380
73708
|
hasUpdates,
|
|
73381
73709
|
currentVersion: normalizedCurrent,
|
|
73382
|
-
latestVersion:
|
|
73710
|
+
latestVersion: cache3.latestVersion,
|
|
73383
73711
|
fromCache: true
|
|
73384
73712
|
};
|
|
73385
73713
|
}
|
|
@@ -73406,7 +73734,7 @@ class ConfigVersionChecker {
|
|
|
73406
73734
|
init_ownership_checker();
|
|
73407
73735
|
init_logger();
|
|
73408
73736
|
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
|
|
73737
|
+
import { isAbsolute as isAbsolute5, join as join120, normalize as normalize9, relative as relative17 } from "node:path";
|
|
73410
73738
|
var MAX_SYNC_FILE_SIZE = 10 * 1024 * 1024;
|
|
73411
73739
|
var MAX_SYMLINK_DEPTH = 20;
|
|
73412
73740
|
async function validateSymlinkChain(path12, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
|
|
@@ -73418,7 +73746,7 @@ async function validateSymlinkChain(path12, basePath, maxDepth = MAX_SYMLINK_DEP
|
|
|
73418
73746
|
if (!stats.isSymbolicLink())
|
|
73419
73747
|
break;
|
|
73420
73748
|
const target = await readlink(current);
|
|
73421
|
-
const resolvedTarget = isAbsolute5(target) ? target :
|
|
73749
|
+
const resolvedTarget = isAbsolute5(target) ? target : join120(current, "..", target);
|
|
73422
73750
|
const normalizedTarget = normalize9(resolvedTarget);
|
|
73423
73751
|
const rel = relative17(basePath, normalizedTarget);
|
|
73424
73752
|
if (rel.startsWith("..") || isAbsolute5(rel)) {
|
|
@@ -73454,7 +73782,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
73454
73782
|
if (normalized.startsWith("..") || normalized.includes("/../")) {
|
|
73455
73783
|
throw new Error(`Path traversal not allowed: ${filePath}`);
|
|
73456
73784
|
}
|
|
73457
|
-
const fullPath =
|
|
73785
|
+
const fullPath = join120(basePath, normalized);
|
|
73458
73786
|
const rel = relative17(basePath, fullPath);
|
|
73459
73787
|
if (rel.startsWith("..") || isAbsolute5(rel)) {
|
|
73460
73788
|
throw new Error(`Path escapes base directory: ${filePath}`);
|
|
@@ -73469,7 +73797,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
73469
73797
|
}
|
|
73470
73798
|
} catch (error) {
|
|
73471
73799
|
if (error.code === "ENOENT") {
|
|
73472
|
-
const parentPath =
|
|
73800
|
+
const parentPath = join120(fullPath, "..");
|
|
73473
73801
|
try {
|
|
73474
73802
|
const resolvedBase = await realpath3(basePath);
|
|
73475
73803
|
const resolvedParent = await realpath3(parentPath);
|
|
@@ -73960,10 +74288,10 @@ function getLockTimeout() {
|
|
|
73960
74288
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
73961
74289
|
async function acquireSyncLock(global3) {
|
|
73962
74290
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
73963
|
-
const lockPath2 =
|
|
74291
|
+
const lockPath2 = join121(cacheDir, ".sync-lock");
|
|
73964
74292
|
const startTime = Date.now();
|
|
73965
74293
|
const lockTimeout = getLockTimeout();
|
|
73966
|
-
await mkdir28(
|
|
74294
|
+
await mkdir28(dirname35(lockPath2), { recursive: true });
|
|
73967
74295
|
while (Date.now() - startTime < lockTimeout) {
|
|
73968
74296
|
try {
|
|
73969
74297
|
const handle = await open2(lockPath2, "wx");
|
|
@@ -74041,7 +74369,7 @@ async function executeSyncMerge(ctx) {
|
|
|
74041
74369
|
try {
|
|
74042
74370
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
74043
74371
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
74044
|
-
const targetDir =
|
|
74372
|
+
const targetDir = join121(targetPath, "..");
|
|
74045
74373
|
try {
|
|
74046
74374
|
await mkdir28(targetDir, { recursive: true });
|
|
74047
74375
|
} catch (mkdirError) {
|
|
@@ -74212,7 +74540,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
74212
74540
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
74213
74541
|
if (await import_fs_extra34.pathExists(sourcePath)) {
|
|
74214
74542
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
74215
|
-
const targetDir =
|
|
74543
|
+
const targetDir = join121(targetPath, "..");
|
|
74216
74544
|
await mkdir28(targetDir, { recursive: true });
|
|
74217
74545
|
await copyFile7(sourcePath, targetPath);
|
|
74218
74546
|
}
|
|
@@ -74238,38 +74566,38 @@ init_logger();
|
|
|
74238
74566
|
init_types2();
|
|
74239
74567
|
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
74240
74568
|
import { rename as rename8, rm as rm9 } from "node:fs/promises";
|
|
74241
|
-
import { join as
|
|
74569
|
+
import { join as join122, relative as relative18 } from "node:path";
|
|
74242
74570
|
async function collectDirsToRename(extractDir, folders) {
|
|
74243
74571
|
const dirsToRename = [];
|
|
74244
74572
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
74245
|
-
const docsPath =
|
|
74573
|
+
const docsPath = join122(extractDir, DEFAULT_FOLDERS.docs);
|
|
74246
74574
|
if (await import_fs_extra35.pathExists(docsPath)) {
|
|
74247
74575
|
dirsToRename.push({
|
|
74248
74576
|
from: docsPath,
|
|
74249
|
-
to:
|
|
74577
|
+
to: join122(extractDir, folders.docs)
|
|
74250
74578
|
});
|
|
74251
74579
|
}
|
|
74252
|
-
const claudeDocsPath =
|
|
74580
|
+
const claudeDocsPath = join122(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
74253
74581
|
if (await import_fs_extra35.pathExists(claudeDocsPath)) {
|
|
74254
74582
|
dirsToRename.push({
|
|
74255
74583
|
from: claudeDocsPath,
|
|
74256
|
-
to:
|
|
74584
|
+
to: join122(extractDir, ".claude", folders.docs)
|
|
74257
74585
|
});
|
|
74258
74586
|
}
|
|
74259
74587
|
}
|
|
74260
74588
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
74261
|
-
const plansPath =
|
|
74589
|
+
const plansPath = join122(extractDir, DEFAULT_FOLDERS.plans);
|
|
74262
74590
|
if (await import_fs_extra35.pathExists(plansPath)) {
|
|
74263
74591
|
dirsToRename.push({
|
|
74264
74592
|
from: plansPath,
|
|
74265
|
-
to:
|
|
74593
|
+
to: join122(extractDir, folders.plans)
|
|
74266
74594
|
});
|
|
74267
74595
|
}
|
|
74268
|
-
const claudePlansPath =
|
|
74596
|
+
const claudePlansPath = join122(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
74269
74597
|
if (await import_fs_extra35.pathExists(claudePlansPath)) {
|
|
74270
74598
|
dirsToRename.push({
|
|
74271
74599
|
from: claudePlansPath,
|
|
74272
|
-
to:
|
|
74600
|
+
to: join122(extractDir, ".claude", folders.plans)
|
|
74273
74601
|
});
|
|
74274
74602
|
}
|
|
74275
74603
|
}
|
|
@@ -74310,7 +74638,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
74310
74638
|
init_logger();
|
|
74311
74639
|
init_types2();
|
|
74312
74640
|
import { readFile as readFile42, readdir as readdir29, writeFile as writeFile29 } from "node:fs/promises";
|
|
74313
|
-
import { join as
|
|
74641
|
+
import { join as join123, relative as relative19 } from "node:path";
|
|
74314
74642
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
74315
74643
|
".md",
|
|
74316
74644
|
".txt",
|
|
@@ -74363,7 +74691,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
|
|
|
74363
74691
|
let replacementsCount = 0;
|
|
74364
74692
|
const entries = await readdir29(dir, { withFileTypes: true });
|
|
74365
74693
|
for (const entry of entries) {
|
|
74366
|
-
const fullPath =
|
|
74694
|
+
const fullPath = join123(dir, entry.name);
|
|
74367
74695
|
if (entry.isDirectory()) {
|
|
74368
74696
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
74369
74697
|
continue;
|
|
@@ -74500,7 +74828,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
74500
74828
|
init_logger();
|
|
74501
74829
|
import { readFile as readFile43, readdir as readdir30, writeFile as writeFile30 } from "node:fs/promises";
|
|
74502
74830
|
import { platform as platform11 } from "node:os";
|
|
74503
|
-
import { extname as extname7, join as
|
|
74831
|
+
import { extname as extname7, join as join124 } from "node:path";
|
|
74504
74832
|
var IS_WINDOWS3 = platform11() === "win32";
|
|
74505
74833
|
var HOME_PREFIX = "$HOME";
|
|
74506
74834
|
function getHomeDirPrefix() {
|
|
@@ -74589,8 +74917,8 @@ function transformContent(content) {
|
|
|
74589
74917
|
}
|
|
74590
74918
|
function shouldTransformFile3(filename) {
|
|
74591
74919
|
const ext2 = extname7(filename).toLowerCase();
|
|
74592
|
-
const
|
|
74593
|
-
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(
|
|
74920
|
+
const basename19 = filename.split("/").pop() || filename;
|
|
74921
|
+
return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename19);
|
|
74594
74922
|
}
|
|
74595
74923
|
async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
74596
74924
|
let filesTransformed = 0;
|
|
@@ -74600,7 +74928,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
74600
74928
|
async function processDirectory2(dir) {
|
|
74601
74929
|
const entries = await readdir30(dir, { withFileTypes: true });
|
|
74602
74930
|
for (const entry of entries) {
|
|
74603
|
-
const fullPath =
|
|
74931
|
+
const fullPath = join124(dir, entry.name);
|
|
74604
74932
|
if (entry.isDirectory()) {
|
|
74605
74933
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
74606
74934
|
continue;
|
|
@@ -74883,19 +75211,19 @@ async function initCommand(options2) {
|
|
|
74883
75211
|
// src/commands/plan/plan-command.ts
|
|
74884
75212
|
init_output_manager();
|
|
74885
75213
|
import { existsSync as existsSync60, statSync as statSync9 } from "node:fs";
|
|
74886
|
-
import { dirname as
|
|
75214
|
+
import { dirname as dirname41, join as join128, parse as parse4, resolve as resolve33 } from "node:path";
|
|
74887
75215
|
|
|
74888
75216
|
// src/commands/plan/plan-read-handlers.ts
|
|
74889
75217
|
import { existsSync as existsSync59, statSync as statSync8 } from "node:fs";
|
|
74890
|
-
import { basename as
|
|
75218
|
+
import { basename as basename21, dirname as dirname40, join as join127, relative as relative20, resolve as resolve31 } from "node:path";
|
|
74891
75219
|
|
|
74892
75220
|
// src/domains/plan-parser/index.ts
|
|
74893
|
-
import { dirname as
|
|
75221
|
+
import { dirname as dirname39 } from "node:path";
|
|
74894
75222
|
|
|
74895
75223
|
// src/domains/plan-parser/plan-table-parser.ts
|
|
74896
75224
|
var import_gray_matter5 = __toESM(require_gray_matter(), 1);
|
|
74897
75225
|
import { readFileSync as readFileSync23 } from "node:fs";
|
|
74898
|
-
import { dirname as
|
|
75226
|
+
import { dirname as dirname36, resolve as resolve30 } from "node:path";
|
|
74899
75227
|
function normalizeStatus(raw) {
|
|
74900
75228
|
const s3 = raw.toLowerCase().trim();
|
|
74901
75229
|
if (s3.includes("complete") || s3.includes("done") || s3.includes("✓") || s3.includes("✅")) {
|
|
@@ -74916,9 +75244,9 @@ function filenameToTitle(name) {
|
|
|
74916
75244
|
}
|
|
74917
75245
|
function buildAnchor(phaseId, name) {
|
|
74918
75246
|
const suffix = phaseId.replace(/^\d+/, "");
|
|
74919
|
-
const
|
|
75247
|
+
const num4 = phaseId.replace(/[a-z]+$/i, "");
|
|
74920
75248
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
74921
|
-
return `phase-${String(
|
|
75249
|
+
return `phase-${String(num4).padStart(2, "0")}${suffix}-${slug}`;
|
|
74922
75250
|
}
|
|
74923
75251
|
function parseHeaderAwareTable(content, dir, options2) {
|
|
74924
75252
|
const lines = content.split(`
|
|
@@ -75011,11 +75339,11 @@ function parseFormat1(content, dir, options2) {
|
|
|
75011
75339
|
const regex2 = /\|\s*(\d+)([a-z]?)\s*\|\s*([^|]+)\s*\|\s*([^|]+)\s*\|\s*\[([^\]]+)\]\(([^)]+)\)/gi;
|
|
75012
75340
|
const phases = [];
|
|
75013
75341
|
for (const match2 of content.matchAll(regex2)) {
|
|
75014
|
-
const [,
|
|
75015
|
-
const phaseId = `${
|
|
75342
|
+
const [, num4, suffix, name, status2, linkText, linkPath] = match2;
|
|
75343
|
+
const phaseId = `${num4}${suffix}`;
|
|
75016
75344
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75017
75345
|
phases.push({
|
|
75018
|
-
phase: Number.parseInt(
|
|
75346
|
+
phase: Number.parseInt(num4, 10),
|
|
75019
75347
|
phaseId,
|
|
75020
75348
|
name: name.trim(),
|
|
75021
75349
|
status: normalizeStatus(status2),
|
|
@@ -75030,12 +75358,12 @@ function parseFormat2(content, dir, options2) {
|
|
|
75030
75358
|
const regex2 = /\|\s*\[(?:Phase\s*)?(\d+)([a-z]?)\]\(([^)]+)\)\s*\|\s*([^|]+)\s*\|\s*([^|]+)/gi;
|
|
75031
75359
|
const phases = [];
|
|
75032
75360
|
for (const match2 of content.matchAll(regex2)) {
|
|
75033
|
-
const [,
|
|
75034
|
-
const phaseId = `${
|
|
75361
|
+
const [, num4, suffix, linkPath, name, status2] = match2;
|
|
75362
|
+
const phaseId = `${num4}${suffix}`;
|
|
75035
75363
|
const linkText = `Phase ${phaseId}`;
|
|
75036
75364
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75037
75365
|
phases.push({
|
|
75038
|
-
phase: Number.parseInt(
|
|
75366
|
+
phase: Number.parseInt(num4, 10),
|
|
75039
75367
|
phaseId,
|
|
75040
75368
|
name: name.trim(),
|
|
75041
75369
|
status: normalizeStatus(status2),
|
|
@@ -75050,11 +75378,11 @@ function parseFormat2b(content, dir, options2) {
|
|
|
75050
75378
|
const regex2 = /\|\s*(\d+)([a-z]?)\s*\|\s*\[([^\]]+)\]\(([^)]+)\)\s*\|\s*([^|]+)/gi;
|
|
75051
75379
|
const phases = [];
|
|
75052
75380
|
for (const match2 of content.matchAll(regex2)) {
|
|
75053
|
-
const [,
|
|
75054
|
-
const phaseId = `${
|
|
75381
|
+
const [, num4, suffix, name, linkPath, status2] = match2;
|
|
75382
|
+
const phaseId = `${num4}${suffix}`;
|
|
75055
75383
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75056
75384
|
phases.push({
|
|
75057
|
-
phase: Number.parseInt(
|
|
75385
|
+
phase: Number.parseInt(num4, 10),
|
|
75058
75386
|
phaseId,
|
|
75059
75387
|
name: name.trim(),
|
|
75060
75388
|
status: normalizeStatus(status2),
|
|
@@ -75101,11 +75429,11 @@ function parseFormat3(content, _dir, options2) {
|
|
|
75101
75429
|
if (headingMatch) {
|
|
75102
75430
|
if (current)
|
|
75103
75431
|
phases.push(current);
|
|
75104
|
-
const [,
|
|
75105
|
-
const phaseId = `${
|
|
75432
|
+
const [, num4, suffix, name] = headingMatch;
|
|
75433
|
+
const phaseId = `${num4}${suffix}`;
|
|
75106
75434
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75107
75435
|
current = {
|
|
75108
|
-
phase: Number.parseInt(
|
|
75436
|
+
phase: Number.parseInt(num4, 10),
|
|
75109
75437
|
phaseId,
|
|
75110
75438
|
name: name.trim(),
|
|
75111
75439
|
status: "pending",
|
|
@@ -75156,7 +75484,7 @@ function parseFormat4(content, planFilePath, options2) {
|
|
|
75156
75484
|
const hasCheck = /[✅✓]/.test(line);
|
|
75157
75485
|
current = { name, status: hasCheck ? "completed" : "pending" };
|
|
75158
75486
|
} else if (fileMatch && current) {
|
|
75159
|
-
const planDir =
|
|
75487
|
+
const planDir = dirname36(planFilePath);
|
|
75160
75488
|
current.file = resolve30(planDir, fileMatch[1].trim());
|
|
75161
75489
|
} else if (statusMatch && current) {
|
|
75162
75490
|
current.status = normalizeStatus(statusMatch[2]);
|
|
@@ -75181,11 +75509,11 @@ function parseFormat5(content, _dir, options2) {
|
|
|
75181
75509
|
const phases = [];
|
|
75182
75510
|
const phaseMap = new Map;
|
|
75183
75511
|
for (const match2 of content.matchAll(/^(\d+)([a-z]?)[).]\s*\*\*([^*]+)\*\*/gim)) {
|
|
75184
|
-
const [,
|
|
75185
|
-
const phaseId = `${
|
|
75512
|
+
const [, num4, suffix, name] = match2;
|
|
75513
|
+
const phaseId = `${num4}${suffix}`;
|
|
75186
75514
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, name.trim()) : null;
|
|
75187
75515
|
phaseMap.set(name.trim().toLowerCase(), {
|
|
75188
|
-
phase: Number.parseInt(
|
|
75516
|
+
phase: Number.parseInt(num4, 10),
|
|
75189
75517
|
phaseId,
|
|
75190
75518
|
name: name.trim(),
|
|
75191
75519
|
status: "pending",
|
|
@@ -75214,12 +75542,12 @@ function parseFormat6(content, dir, options2) {
|
|
|
75214
75542
|
const regex2 = /^-\s*\[(x| )\]\s*\*\*\[(?:Phase\s*)?(\d+)([a-z]?)[:\s]*([^\]]*)\]\(([^)]+)\)\*\*/gim;
|
|
75215
75543
|
const phases = [];
|
|
75216
75544
|
for (const match2 of content.matchAll(regex2)) {
|
|
75217
|
-
const [, checked,
|
|
75218
|
-
const phaseId = `${
|
|
75545
|
+
const [, checked, num4, suffix, name, linkPath] = match2;
|
|
75546
|
+
const phaseId = `${num4}${suffix}`;
|
|
75219
75547
|
const phaseName = name.trim() || `Phase ${phaseId}`;
|
|
75220
75548
|
const anchor = options2?.generateAnchors ? buildAnchor(phaseId, phaseName) : null;
|
|
75221
75549
|
phases.push({
|
|
75222
|
-
phase: Number.parseInt(
|
|
75550
|
+
phase: Number.parseInt(num4, 10),
|
|
75223
75551
|
phaseId,
|
|
75224
75552
|
name: phaseName,
|
|
75225
75553
|
status: checked.toLowerCase() === "x" ? "completed" : "pending",
|
|
@@ -75261,19 +75589,19 @@ function parsePhasesFromBody(body, dir, options2) {
|
|
|
75261
75589
|
}
|
|
75262
75590
|
function parsePlanFile(planFilePath, options2) {
|
|
75263
75591
|
const content = readFileSync23(planFilePath, "utf8");
|
|
75264
|
-
const dir =
|
|
75592
|
+
const dir = dirname36(planFilePath);
|
|
75265
75593
|
const { data: frontmatter, content: body } = import_gray_matter5.default(content);
|
|
75266
75594
|
const phases = parsePhasesFromBody(body, dir, options2);
|
|
75267
75595
|
return { frontmatter, phases };
|
|
75268
75596
|
}
|
|
75269
75597
|
// src/domains/plan-parser/plan-scanner.ts
|
|
75270
|
-
import { existsSync as existsSync56, readdirSync as
|
|
75271
|
-
import { join as
|
|
75598
|
+
import { existsSync as existsSync56, readdirSync as readdirSync10 } from "node:fs";
|
|
75599
|
+
import { join as join125 } from "node:path";
|
|
75272
75600
|
function scanPlanDir(dir) {
|
|
75273
75601
|
if (!existsSync56(dir))
|
|
75274
75602
|
return [];
|
|
75275
75603
|
try {
|
|
75276
|
-
return
|
|
75604
|
+
return readdirSync10(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join125(dir, entry.name, "plan.md")).filter(existsSync56);
|
|
75277
75605
|
} catch {
|
|
75278
75606
|
return [];
|
|
75279
75607
|
}
|
|
@@ -75281,10 +75609,10 @@ function scanPlanDir(dir) {
|
|
|
75281
75609
|
// src/domains/plan-parser/plan-validator.ts
|
|
75282
75610
|
var import_gray_matter6 = __toESM(require_gray_matter(), 1);
|
|
75283
75611
|
import { existsSync as existsSync57, readFileSync as readFileSync24 } from "node:fs";
|
|
75284
|
-
import { basename as
|
|
75612
|
+
import { basename as basename19, dirname as dirname37 } from "node:path";
|
|
75285
75613
|
function validatePlanFile(filePath, strict = false) {
|
|
75286
75614
|
const content = readFileSync24(filePath, "utf8");
|
|
75287
|
-
const dir =
|
|
75615
|
+
const dir = dirname37(filePath);
|
|
75288
75616
|
const issues = [];
|
|
75289
75617
|
const lines = content.split(`
|
|
75290
75618
|
`);
|
|
@@ -75321,13 +75649,13 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
75321
75649
|
}
|
|
75322
75650
|
for (const phase of phases) {
|
|
75323
75651
|
if (phase.file && !existsSync57(phase.file)) {
|
|
75324
|
-
const fileBasename =
|
|
75652
|
+
const fileBasename = basename19(phase.file);
|
|
75325
75653
|
const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
|
|
75326
75654
|
issues.push({
|
|
75327
75655
|
line: refLine >= 0 ? refLine + 1 : 1,
|
|
75328
75656
|
severity: "warning",
|
|
75329
75657
|
code: "missing-phase-file",
|
|
75330
|
-
message: `Phase ${phase.phaseId} references '${
|
|
75658
|
+
message: `Phase ${phase.phaseId} references '${basename19(phase.file)}' which doesn't exist`
|
|
75331
75659
|
});
|
|
75332
75660
|
}
|
|
75333
75661
|
}
|
|
@@ -75342,12 +75670,12 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
75342
75670
|
var import_gray_matter7 = __toESM(require_gray_matter(), 1);
|
|
75343
75671
|
import { mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as writeFileSync12 } from "node:fs";
|
|
75344
75672
|
import { existsSync as existsSync58 } from "node:fs";
|
|
75345
|
-
import { basename as
|
|
75673
|
+
import { basename as basename20, dirname as dirname38, join as join126 } from "node:path";
|
|
75346
75674
|
function phaseNameToFilename(id, name) {
|
|
75347
75675
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
|
|
75348
|
-
const
|
|
75676
|
+
const num4 = numMatch ? numMatch[1] : id;
|
|
75349
75677
|
const suffix = numMatch ? numMatch[2].toLowerCase() : "";
|
|
75350
|
-
const paddedNum =
|
|
75678
|
+
const paddedNum = num4.padStart(2, "0");
|
|
75351
75679
|
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
75352
75680
|
return `phase-${paddedNum}${suffix}-${slug}.md`;
|
|
75353
75681
|
}
|
|
@@ -75450,12 +75778,12 @@ function scaffoldPlan(options2) {
|
|
|
75450
75778
|
mkdirSync9(dir, { recursive: true });
|
|
75451
75779
|
const resolvedPhases = resolvePhaseIds(options2.phases);
|
|
75452
75780
|
const optionsWithResolved = { ...options2, phases: resolvedPhases };
|
|
75453
|
-
const planFile =
|
|
75781
|
+
const planFile = join126(dir, "plan.md");
|
|
75454
75782
|
writeFileSync12(planFile, generatePlanMd(optionsWithResolved), "utf8");
|
|
75455
75783
|
const phaseFiles = [];
|
|
75456
75784
|
for (const phase of resolvedPhases) {
|
|
75457
75785
|
const filename = phaseNameToFilename(phase.id, phase.name);
|
|
75458
|
-
const phaseFile =
|
|
75786
|
+
const phaseFile = join126(dir, filename);
|
|
75459
75787
|
writeFileSync12(phaseFile, generatePhaseTemplate(phase), "utf8");
|
|
75460
75788
|
phaseFiles.push(phaseFile);
|
|
75461
75789
|
}
|
|
@@ -75465,14 +75793,14 @@ function nextSubPhaseId(afterId, existingIds) {
|
|
|
75465
75793
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(afterId);
|
|
75466
75794
|
if (!numMatch)
|
|
75467
75795
|
throw new Error(`Invalid phase ID: ${afterId}`);
|
|
75468
|
-
const
|
|
75796
|
+
const num4 = numMatch[1];
|
|
75469
75797
|
const currentSuffix = numMatch[2].toLowerCase();
|
|
75470
75798
|
const nextSuffixChar = currentSuffix === "" ? "b" : String.fromCharCode(currentSuffix.charCodeAt(0) + 1);
|
|
75471
75799
|
if (nextSuffixChar > "z")
|
|
75472
|
-
throw new Error(`Too many sub-phases for phase ${
|
|
75473
|
-
const candidate = `${
|
|
75800
|
+
throw new Error(`Too many sub-phases for phase ${num4}`);
|
|
75801
|
+
const candidate = `${num4}${nextSuffixChar}`;
|
|
75474
75802
|
if (existingIds.includes(candidate)) {
|
|
75475
|
-
return nextSubPhaseId(`${
|
|
75803
|
+
return nextSubPhaseId(`${num4}${nextSuffixChar}`, existingIds);
|
|
75476
75804
|
}
|
|
75477
75805
|
return candidate;
|
|
75478
75806
|
}
|
|
@@ -75521,7 +75849,7 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
|
75521
75849
|
const updatedFrontmatter = { ...frontmatter, status: planStatus };
|
|
75522
75850
|
const updatedContent = import_gray_matter7.default.stringify(updatedBody, updatedFrontmatter);
|
|
75523
75851
|
writeFileSync12(planFile, updatedContent, "utf8");
|
|
75524
|
-
const planDir =
|
|
75852
|
+
const planDir = dirname38(planFile);
|
|
75525
75853
|
const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
|
|
75526
75854
|
if (phaseFilename && existsSync58(phaseFilename)) {
|
|
75527
75855
|
updatePhaseFileFrontmatter(phaseFilename, newStatus);
|
|
@@ -75535,7 +75863,7 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
|
|
|
75535
75863
|
continue;
|
|
75536
75864
|
const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
|
|
75537
75865
|
if (linkMatch)
|
|
75538
|
-
return
|
|
75866
|
+
return join126(planDir, linkMatch[2]);
|
|
75539
75867
|
}
|
|
75540
75868
|
return null;
|
|
75541
75869
|
}
|
|
@@ -75553,7 +75881,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
75553
75881
|
throw new Error("Non-canonical plan.md — cannot add phase");
|
|
75554
75882
|
}
|
|
75555
75883
|
const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
|
|
75556
|
-
const planDir =
|
|
75884
|
+
const planDir = dirname38(planFile);
|
|
75557
75885
|
const existingIds = [];
|
|
75558
75886
|
for (const match2 of body.matchAll(/^\|\s*(\d+[a-z]?)\s*\|/gim)) {
|
|
75559
75887
|
existingIds.push(match2[1].toLowerCase());
|
|
@@ -75582,7 +75910,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
75582
75910
|
insertIdx = i;
|
|
75583
75911
|
}
|
|
75584
75912
|
if (insertIdx === -1) {
|
|
75585
|
-
throw new Error(`Phase ID "${afterId}" not found in ${
|
|
75913
|
+
throw new Error(`Phase ID "${afterId}" not found in ${basename20(planFile)}`);
|
|
75586
75914
|
}
|
|
75587
75915
|
lines.splice(insertIdx + 1, 0, newRow);
|
|
75588
75916
|
updatedBody = lines.join(`
|
|
@@ -75616,7 +75944,7 @@ function addPhase(planFile, name, afterId) {
|
|
|
75616
75944
|
`);
|
|
75617
75945
|
}
|
|
75618
75946
|
writeFileSync12(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
|
|
75619
|
-
const phaseFilePath =
|
|
75947
|
+
const phaseFilePath = join126(planDir, filename);
|
|
75620
75948
|
writeFileSync12(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
|
|
75621
75949
|
return { phaseId, phaseFile: phaseFilePath };
|
|
75622
75950
|
}
|
|
@@ -75628,7 +75956,7 @@ function buildPlanSummary(planFile) {
|
|
|
75628
75956
|
const inProgress = phases.filter((p2) => p2.status === "in-progress").length;
|
|
75629
75957
|
const pending = phases.filter((p2) => p2.status === "pending").length;
|
|
75630
75958
|
return {
|
|
75631
|
-
planDir:
|
|
75959
|
+
planDir: dirname39(planFile),
|
|
75632
75960
|
planFile,
|
|
75633
75961
|
title: typeof frontmatter.title === "string" ? frontmatter.title : undefined,
|
|
75634
75962
|
description: typeof frontmatter.description === "string" ? frontmatter.description : undefined,
|
|
@@ -75665,7 +75993,7 @@ async function handleParse(target, options2) {
|
|
|
75665
75993
|
console.log(JSON.stringify({ file: relative20(process.cwd(), planFile), frontmatter, phases }, null, 2));
|
|
75666
75994
|
return;
|
|
75667
75995
|
}
|
|
75668
|
-
const title = typeof frontmatter.title === "string" ? frontmatter.title :
|
|
75996
|
+
const title = typeof frontmatter.title === "string" ? frontmatter.title : basename21(dirname40(planFile));
|
|
75669
75997
|
console.log();
|
|
75670
75998
|
console.log(import_picocolors25.default.bold(` Plan: ${title}`));
|
|
75671
75999
|
console.log(` File: ${planFile}`);
|
|
@@ -75720,7 +76048,7 @@ async function handleValidate(target, options2) {
|
|
|
75720
76048
|
}
|
|
75721
76049
|
async function handleStatus(target, options2) {
|
|
75722
76050
|
const t = target ? resolve31(target) : null;
|
|
75723
|
-
const plansDir = t && existsSync59(t) && statSync8(t).isDirectory() && !existsSync59(
|
|
76051
|
+
const plansDir = t && existsSync59(t) && statSync8(t).isDirectory() && !existsSync59(join127(t, "plan.md")) ? t : null;
|
|
75724
76052
|
if (plansDir) {
|
|
75725
76053
|
const planFiles = scanPlanDir(plansDir);
|
|
75726
76054
|
if (planFiles.length === 0) {
|
|
@@ -75745,14 +76073,14 @@ async function handleStatus(target, options2) {
|
|
|
75745
76073
|
try {
|
|
75746
76074
|
const s3 = buildPlanSummary(pf);
|
|
75747
76075
|
const bar = progressBar(s3.completed, s3.totalPhases);
|
|
75748
|
-
const title2 = s3.title ??
|
|
76076
|
+
const title2 = s3.title ?? basename21(dirname40(pf));
|
|
75749
76077
|
console.log(` ${import_picocolors25.default.bold(title2)}`);
|
|
75750
76078
|
console.log(` ${bar}`);
|
|
75751
76079
|
if (s3.inProgress > 0)
|
|
75752
76080
|
console.log(` [~] ${s3.inProgress} in progress`);
|
|
75753
76081
|
console.log();
|
|
75754
76082
|
} catch {
|
|
75755
|
-
console.log(` [X] Failed to read: ${
|
|
76083
|
+
console.log(` [X] Failed to read: ${basename21(dirname40(pf))}`);
|
|
75756
76084
|
console.log();
|
|
75757
76085
|
}
|
|
75758
76086
|
}
|
|
@@ -75776,7 +76104,7 @@ async function handleStatus(target, options2) {
|
|
|
75776
76104
|
console.log(JSON.stringify(summary, null, 2));
|
|
75777
76105
|
return;
|
|
75778
76106
|
}
|
|
75779
|
-
const title = summary.title ??
|
|
76107
|
+
const title = summary.title ?? basename21(dirname40(planFile));
|
|
75780
76108
|
console.log();
|
|
75781
76109
|
console.log(import_picocolors25.default.bold(` ${title}`));
|
|
75782
76110
|
if (summary.status)
|
|
@@ -75802,7 +76130,7 @@ async function handleKanban(target, _options) {
|
|
|
75802
76130
|
}
|
|
75803
76131
|
|
|
75804
76132
|
// src/commands/plan/plan-write-handlers.ts
|
|
75805
|
-
import { basename as
|
|
76133
|
+
import { basename as basename22, relative as relative21, resolve as resolve32 } from "node:path";
|
|
75806
76134
|
init_output_manager();
|
|
75807
76135
|
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
75808
76136
|
async function handleCreate(target, options2) {
|
|
@@ -75855,7 +76183,7 @@ async function handleCreate(target, options2) {
|
|
|
75855
76183
|
console.log(` Directory: ${resolve32(dir)}`);
|
|
75856
76184
|
console.log(` Phases: ${result.phaseFiles.length}`);
|
|
75857
76185
|
for (const f4 of result.phaseFiles) {
|
|
75858
|
-
console.log(` [ ] ${
|
|
76186
|
+
console.log(` [ ] ${basename22(f4)}`);
|
|
75859
76187
|
}
|
|
75860
76188
|
console.log();
|
|
75861
76189
|
}
|
|
@@ -75955,7 +76283,7 @@ function resolvePlanFile(target) {
|
|
|
75955
76283
|
const stat13 = statSync9(t);
|
|
75956
76284
|
if (stat13.isFile())
|
|
75957
76285
|
return t;
|
|
75958
|
-
const candidate =
|
|
76286
|
+
const candidate = join128(t, "plan.md");
|
|
75959
76287
|
if (existsSync60(candidate))
|
|
75960
76288
|
return candidate;
|
|
75961
76289
|
}
|
|
@@ -75963,10 +76291,10 @@ function resolvePlanFile(target) {
|
|
|
75963
76291
|
let dir = process.cwd();
|
|
75964
76292
|
const root = parse4(dir).root;
|
|
75965
76293
|
while (dir !== root) {
|
|
75966
|
-
const candidate =
|
|
76294
|
+
const candidate = join128(dir, "plan.md");
|
|
75967
76295
|
if (existsSync60(candidate))
|
|
75968
76296
|
return candidate;
|
|
75969
|
-
dir =
|
|
76297
|
+
dir = dirname41(dir);
|
|
75970
76298
|
}
|
|
75971
76299
|
}
|
|
75972
76300
|
return null;
|
|
@@ -76058,17 +76386,17 @@ init_logger();
|
|
|
76058
76386
|
init_logger();
|
|
76059
76387
|
|
|
76060
76388
|
// src/commands/telemetry/shared.ts
|
|
76061
|
-
import { existsSync as existsSync61, readFileSync as readFileSync26, readdirSync as
|
|
76389
|
+
import { existsSync as existsSync61, readFileSync as readFileSync26, readdirSync as readdirSync11 } from "node:fs";
|
|
76062
76390
|
import { homedir as homedir29 } from "node:os";
|
|
76063
|
-
import { join as
|
|
76391
|
+
import { join as join129 } from "node:path";
|
|
76064
76392
|
init_token_store();
|
|
76065
76393
|
init_manifest_path_resolver();
|
|
76066
76394
|
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 =
|
|
76395
|
+
var USER_CACHE_PATH = join129(homedir29(), ".claude", "sk-user.json");
|
|
76396
|
+
var EVENT_BUFFER_DIR = join129(homedir29(), ".claude", "sk-events");
|
|
76397
|
+
var RATE_STATE_PATH = join129(homedir29(), ".claude", "sk-rate-state.json");
|
|
76398
|
+
var TAKUMI_MANIFEST_PATH = join129(homedir29(), ".claude", MANIFEST_FILENAME);
|
|
76399
|
+
var LEGACY_METADATA_PATH = join129(homedir29(), ".claude", LEGACY_MANIFEST_FILENAME);
|
|
76072
76400
|
var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
|
|
76073
76401
|
var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
|
|
76074
76402
|
function readUserCache() {
|
|
@@ -76087,7 +76415,7 @@ function countBufferFiles() {
|
|
|
76087
76415
|
try {
|
|
76088
76416
|
if (!existsSync61(EVENT_BUFFER_DIR))
|
|
76089
76417
|
return 0;
|
|
76090
|
-
return
|
|
76418
|
+
return readdirSync11(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
|
|
76091
76419
|
} catch {
|
|
76092
76420
|
return 0;
|
|
76093
76421
|
}
|
|
@@ -76097,7 +76425,7 @@ function readTelemetryConfig() {
|
|
|
76097
76425
|
const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
|
|
76098
76426
|
let metadata = null;
|
|
76099
76427
|
try {
|
|
76100
|
-
const resolved = findManifestPathSync(
|
|
76428
|
+
const resolved = findManifestPathSync(join129(homedir29(), ".claude"));
|
|
76101
76429
|
if (resolved) {
|
|
76102
76430
|
metadata = JSON.parse(readFileSync26(resolved.path, "utf8"));
|
|
76103
76431
|
}
|
|
@@ -76115,12 +76443,12 @@ function readTelemetryConfig() {
|
|
|
76115
76443
|
return { endpoint, token };
|
|
76116
76444
|
}
|
|
76117
76445
|
function collectRuntimeContext() {
|
|
76118
|
-
const
|
|
76446
|
+
const cache3 = readUserCache();
|
|
76119
76447
|
const { endpoint, token } = readTelemetryConfig();
|
|
76120
76448
|
return {
|
|
76121
|
-
githubLogin: typeof
|
|
76122
|
-
cacheResolvedAt: typeof
|
|
76123
|
-
cacheSource:
|
|
76449
|
+
githubLogin: typeof cache3?.githubLogin === "string" ? cache3.githubLogin : null,
|
|
76450
|
+
cacheResolvedAt: typeof cache3?.resolvedAt === "number" ? cache3.resolvedAt : null,
|
|
76451
|
+
cacheSource: cache3?.source === "gh" || cache3?.source === "manual" ? cache3.source : null,
|
|
76124
76452
|
bufferFileCount: countBufferFiles(),
|
|
76125
76453
|
bufferDir: EVENT_BUFFER_DIR,
|
|
76126
76454
|
rateStateExists: existsSync61(RATE_STATE_PATH),
|
|
@@ -76274,8 +76602,8 @@ init_logger();
|
|
|
76274
76602
|
init_safe_prompts();
|
|
76275
76603
|
init_safe_spinner();
|
|
76276
76604
|
var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
76277
|
-
import { readdirSync as
|
|
76278
|
-
import { join as
|
|
76605
|
+
import { readdirSync as readdirSync13, rmSync as rmSync9 } from "node:fs";
|
|
76606
|
+
import { join as join131, resolve as resolve34, sep as sep10 } from "node:path";
|
|
76279
76607
|
|
|
76280
76608
|
// src/commands/uninstall/analysis-handler.ts
|
|
76281
76609
|
init_metadata_migration();
|
|
@@ -76285,8 +76613,8 @@ init_logger();
|
|
|
76285
76613
|
init_safe_prompts();
|
|
76286
76614
|
init_takumi_constants();
|
|
76287
76615
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
76288
|
-
import { existsSync as existsSync62, readdirSync as
|
|
76289
|
-
import { dirname as
|
|
76616
|
+
import { existsSync as existsSync62, readdirSync as readdirSync12, rmSync as rmSync8 } from "node:fs";
|
|
76617
|
+
import { dirname as dirname42, join as join130 } from "node:path";
|
|
76290
76618
|
function listPresentManifestNames(installPath) {
|
|
76291
76619
|
const present = [];
|
|
76292
76620
|
if (existsSync62(getManifestPath(installPath)))
|
|
@@ -76309,15 +76637,15 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
|
|
|
76309
76637
|
}
|
|
76310
76638
|
async function cleanupEmptyDirectories3(filePath, installationRoot) {
|
|
76311
76639
|
let cleaned = 0;
|
|
76312
|
-
let currentDir =
|
|
76640
|
+
let currentDir = dirname42(filePath);
|
|
76313
76641
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
76314
76642
|
try {
|
|
76315
|
-
const entries =
|
|
76643
|
+
const entries = readdirSync12(currentDir);
|
|
76316
76644
|
if (entries.length === 0) {
|
|
76317
76645
|
rmSync8(currentDir, { recursive: true });
|
|
76318
76646
|
cleaned++;
|
|
76319
76647
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
76320
|
-
currentDir =
|
|
76648
|
+
currentDir = dirname42(currentDir);
|
|
76321
76649
|
} else {
|
|
76322
76650
|
break;
|
|
76323
76651
|
}
|
|
@@ -76339,7 +76667,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
76339
76667
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
76340
76668
|
const kitFiles = metadata.kits[kit].files || [];
|
|
76341
76669
|
for (const trackedFile of kitFiles) {
|
|
76342
|
-
const filePath =
|
|
76670
|
+
const filePath = join130(installation.path, trackedFile.path);
|
|
76343
76671
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
76344
76672
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
76345
76673
|
continue;
|
|
@@ -76371,7 +76699,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
76371
76699
|
return result;
|
|
76372
76700
|
}
|
|
76373
76701
|
for (const trackedFile of allTrackedFiles) {
|
|
76374
|
-
const filePath =
|
|
76702
|
+
const filePath = join130(installation.path, trackedFile.path);
|
|
76375
76703
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
76376
76704
|
if (!ownershipResult.exists)
|
|
76377
76705
|
continue;
|
|
@@ -76470,7 +76798,7 @@ async function removeInstallations(installations, options2) {
|
|
|
76470
76798
|
let removedCount = 0;
|
|
76471
76799
|
let cleanedDirs = 0;
|
|
76472
76800
|
for (const item of analysis.toDelete) {
|
|
76473
|
-
const filePath =
|
|
76801
|
+
const filePath = join131(installation.path, item.path);
|
|
76474
76802
|
if (!await import_fs_extra37.pathExists(filePath))
|
|
76475
76803
|
continue;
|
|
76476
76804
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -76489,7 +76817,7 @@ async function removeInstallations(installations, options2) {
|
|
|
76489
76817
|
await ManifestWriter.removeKitFromManifest(installation.path, options2.kit);
|
|
76490
76818
|
}
|
|
76491
76819
|
try {
|
|
76492
|
-
const remaining =
|
|
76820
|
+
const remaining = readdirSync13(installation.path);
|
|
76493
76821
|
if (remaining.length === 0) {
|
|
76494
76822
|
rmSync9(installation.path, { recursive: true });
|
|
76495
76823
|
logger.debug(`Removed empty installation directory: ${installation.path}`);
|
|
@@ -77334,7 +77662,7 @@ init_manifest_path_resolver();
|
|
|
77334
77662
|
init_logger();
|
|
77335
77663
|
init_types2();
|
|
77336
77664
|
import { readFileSync as readFileSync27 } from "node:fs";
|
|
77337
|
-
import { join as
|
|
77665
|
+
import { join as join132 } from "node:path";
|
|
77338
77666
|
var PROVIDER_LOCAL_SUBDIRS = {
|
|
77339
77667
|
"claude-code": ".claude",
|
|
77340
77668
|
codex: ".codex"
|
|
@@ -77389,7 +77717,7 @@ async function displayVersion() {
|
|
|
77389
77717
|
const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
|
|
77390
77718
|
if (!localSubdir)
|
|
77391
77719
|
continue;
|
|
77392
|
-
const localRoot =
|
|
77720
|
+
const localRoot = join132(process.cwd(), localSubdir);
|
|
77393
77721
|
if (localRoot === inst.globalRoot())
|
|
77394
77722
|
continue;
|
|
77395
77723
|
const resolved = findManifestPathSync(localRoot);
|