@sunasteriskrnd/takumi 1.0.0-dev.39 → 1.0.0-dev.40
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 +614 -446
- 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.40",
|
|
19819
19819
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
19820
19820
|
type: "module",
|
|
19821
19821
|
repository: {
|
|
@@ -49135,7 +49135,7 @@ __export(exports_monorepo_resolver, {
|
|
|
49135
49135
|
resolveMonorepoRoot: () => resolveMonorepoRoot
|
|
49136
49136
|
});
|
|
49137
49137
|
import { existsSync as existsSync56, readFileSync as readFileSync22 } from "node:fs";
|
|
49138
|
-
import { dirname as dirname33, join as
|
|
49138
|
+
import { dirname as dirname33, join as join117, resolve as resolve26 } from "node:path";
|
|
49139
49139
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
49140
49140
|
function parseMetadataAt(metadataPath) {
|
|
49141
49141
|
if (!existsSync56(metadataPath))
|
|
@@ -49152,7 +49152,7 @@ function parseMetadataAt(metadataPath) {
|
|
|
49152
49152
|
}
|
|
49153
49153
|
}
|
|
49154
49154
|
function readSourceDirFromPackageJson(candidateRoot) {
|
|
49155
|
-
const packageJsonPath =
|
|
49155
|
+
const packageJsonPath = join117(candidateRoot, "package.json");
|
|
49156
49156
|
if (!existsSync56(packageJsonPath))
|
|
49157
49157
|
return null;
|
|
49158
49158
|
try {
|
|
@@ -49175,7 +49175,7 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
49175
49175
|
};
|
|
49176
49176
|
}
|
|
49177
49177
|
const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
|
|
49178
|
-
const sourceRoot =
|
|
49178
|
+
const sourceRoot = join117(candidateRoot, sourceDir);
|
|
49179
49179
|
const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
|
|
49180
49180
|
if (nestedMetadata) {
|
|
49181
49181
|
return {
|
|
@@ -70229,6 +70229,9 @@ async function readStdinJson() {
|
|
|
70229
70229
|
}
|
|
70230
70230
|
}
|
|
70231
70231
|
|
|
70232
|
+
// src/domains/hooks/telemetry/lib/claude-transcript-apply.ts
|
|
70233
|
+
import { stat as stat8 } from "node:fs/promises";
|
|
70234
|
+
|
|
70232
70235
|
// src/domains/hooks/telemetry/lib/claude-transcript-reader.ts
|
|
70233
70236
|
function num2(v2) {
|
|
70234
70237
|
return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
@@ -70290,6 +70293,240 @@ function bucketTokens(records) {
|
|
|
70290
70293
|
return { mainLoopDelta, subagentDeltas, tokenUsageDeltas };
|
|
70291
70294
|
}
|
|
70292
70295
|
|
|
70296
|
+
// src/domains/hooks/telemetry/lib/session-lock.ts
|
|
70297
|
+
var import_proper_lockfile8 = __toESM(require_proper_lockfile(), 1);
|
|
70298
|
+
import { promises as fs21 } from "node:fs";
|
|
70299
|
+
import { join as join95 } from "node:path";
|
|
70300
|
+
var LOCK_RESOURCE = "summary.json";
|
|
70301
|
+
var DEFAULT_TIMEOUT_MS3 = 2000;
|
|
70302
|
+
var RETRY_INTERVAL_MS = 100;
|
|
70303
|
+
var DEFAULT_STALE_AFTER_MS = 1e4;
|
|
70304
|
+
async function withSummaryLock(sessionDir, fn, options2 = {}) {
|
|
70305
|
+
const timeoutMs = options2.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
70306
|
+
const staleAfterMs = options2.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
|
|
70307
|
+
const resource = join95(sessionDir, LOCK_RESOURCE);
|
|
70308
|
+
try {
|
|
70309
|
+
await fs21.mkdir(sessionDir, { recursive: true });
|
|
70310
|
+
} catch {
|
|
70311
|
+
return fn();
|
|
70312
|
+
}
|
|
70313
|
+
let release = null;
|
|
70314
|
+
try {
|
|
70315
|
+
release = await import_proper_lockfile8.default.lock(resource, {
|
|
70316
|
+
realpath: false,
|
|
70317
|
+
stale: staleAfterMs,
|
|
70318
|
+
retries: {
|
|
70319
|
+
retries: Math.max(0, Math.ceil(timeoutMs / RETRY_INTERVAL_MS)),
|
|
70320
|
+
factor: 1,
|
|
70321
|
+
minTimeout: RETRY_INTERVAL_MS,
|
|
70322
|
+
maxTimeout: RETRY_INTERVAL_MS
|
|
70323
|
+
},
|
|
70324
|
+
onCompromised: (err) => hookLog("summary_lock_compromised", { sessionDir, error: err?.message })
|
|
70325
|
+
});
|
|
70326
|
+
} catch (e2) {
|
|
70327
|
+
hookLog("summary_lock_timeout", { sessionDir, timeoutMs, error: e2?.message });
|
|
70328
|
+
}
|
|
70329
|
+
try {
|
|
70330
|
+
return await fn();
|
|
70331
|
+
} finally {
|
|
70332
|
+
if (release) {
|
|
70333
|
+
await release().catch(() => {});
|
|
70334
|
+
}
|
|
70335
|
+
}
|
|
70336
|
+
}
|
|
70337
|
+
|
|
70338
|
+
// src/domains/hooks/telemetry/lib/summary.ts
|
|
70339
|
+
import { promises as fs22 } from "node:fs";
|
|
70340
|
+
|
|
70341
|
+
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
70342
|
+
init_paths2();
|
|
70343
|
+
import { join as join97 } from "node:path";
|
|
70344
|
+
|
|
70345
|
+
// src/shared/project-paths.ts
|
|
70346
|
+
init_paths2();
|
|
70347
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
70348
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
70349
|
+
import { basename as basename17, join as join96 } from "node:path";
|
|
70350
|
+
function encodeCwd(cwd2) {
|
|
70351
|
+
const stripped = cwd2.replace(/^\/+/, "");
|
|
70352
|
+
const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
70353
|
+
return `-${sanitized}`;
|
|
70354
|
+
}
|
|
70355
|
+
function computeProjectHash(cwd2) {
|
|
70356
|
+
let canonical = cwd2;
|
|
70357
|
+
try {
|
|
70358
|
+
canonical = realpathSync2(cwd2);
|
|
70359
|
+
} catch {
|
|
70360
|
+
hookLog("project-hash", { fallback: "realpath_failed", cwd: cwd2 });
|
|
70361
|
+
}
|
|
70362
|
+
return createHash10("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
70363
|
+
}
|
|
70364
|
+
function getProjectLabel(cwd2) {
|
|
70365
|
+
return basename17(cwd2) || "";
|
|
70366
|
+
}
|
|
70367
|
+
function getProjectsRoot() {
|
|
70368
|
+
return join96(getConfigDir(), "projects");
|
|
70369
|
+
}
|
|
70370
|
+
function getProjectDir(args) {
|
|
70371
|
+
return join96(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
|
|
70372
|
+
}
|
|
70373
|
+
|
|
70374
|
+
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
70375
|
+
var MAX_SESSION_ID_LEN = 128;
|
|
70376
|
+
function safeSessionSegment(sessionId) {
|
|
70377
|
+
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
70378
|
+
return null;
|
|
70379
|
+
const cleaned = sessionId.replace(/[^a-zA-Z0-9._-]/g, "");
|
|
70380
|
+
return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
|
|
70381
|
+
}
|
|
70382
|
+
function getSessionsRoot() {
|
|
70383
|
+
return join97(getConfigDir(), "sessions");
|
|
70384
|
+
}
|
|
70385
|
+
function getSessionDirV2(args) {
|
|
70386
|
+
const segment = safeSessionSegment(args.sessionId);
|
|
70387
|
+
if (!segment)
|
|
70388
|
+
return null;
|
|
70389
|
+
return join97(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
|
|
70390
|
+
}
|
|
70391
|
+
function getEventsFile(sessionDir) {
|
|
70392
|
+
return join97(sessionDir, "events.jsonl");
|
|
70393
|
+
}
|
|
70394
|
+
function getSummaryFile(sessionDir) {
|
|
70395
|
+
return join97(sessionDir, "summary.json");
|
|
70396
|
+
}
|
|
70397
|
+
function getLastPushFile(sessionDir) {
|
|
70398
|
+
return join97(sessionDir, "last_push.txt");
|
|
70399
|
+
}
|
|
70400
|
+
var OBSERVATIONS_FILENAME = "observations.jsonl";
|
|
70401
|
+
function getObservationsFile(sessionDir) {
|
|
70402
|
+
return join97(sessionDir, OBSERVATIONS_FILENAME);
|
|
70403
|
+
}
|
|
70404
|
+
function getObservationsFlushingFile(sessionDir) {
|
|
70405
|
+
return join97(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
|
|
70406
|
+
}
|
|
70407
|
+
function getObservationsPushedFile(sessionDir) {
|
|
70408
|
+
return join97(sessionDir, "obs_pushed.txt");
|
|
70409
|
+
}
|
|
70410
|
+
function getMetaFile(sessionDir) {
|
|
70411
|
+
return join97(sessionDir, "meta.json");
|
|
70412
|
+
}
|
|
70413
|
+
|
|
70414
|
+
// src/domains/hooks/telemetry/lib/summary.ts
|
|
70415
|
+
function zeroTokens3() {
|
|
70416
|
+
return { input: 0, output: 0, cache_read: 0, cache_write: 0 };
|
|
70417
|
+
}
|
|
70418
|
+
function initialSummary(args) {
|
|
70419
|
+
return {
|
|
70420
|
+
schema_version: 1,
|
|
70421
|
+
session_id: args.sessionId,
|
|
70422
|
+
agent: args.agent,
|
|
70423
|
+
cli_version: args.cliVersion ?? null,
|
|
70424
|
+
kit_versions: args.kitVersions ?? {},
|
|
70425
|
+
project: args.project,
|
|
70426
|
+
timing: { started_at: args.startedAt, ended_at: null, duration_s: null },
|
|
70427
|
+
main_loop_tokens: zeroTokens3(),
|
|
70428
|
+
token_usage: {},
|
|
70429
|
+
subagents: [],
|
|
70430
|
+
skills: [],
|
|
70431
|
+
tool_stats: {
|
|
70432
|
+
schema_version: 1,
|
|
70433
|
+
total_events: 0,
|
|
70434
|
+
total_tool_calls: 0,
|
|
70435
|
+
by_type: {},
|
|
70436
|
+
by_name: {},
|
|
70437
|
+
subagents: { by_type: {} },
|
|
70438
|
+
skills: { by_name: {} }
|
|
70439
|
+
},
|
|
70440
|
+
totals: zeroTokens3(),
|
|
70441
|
+
pending_user_triggers: [],
|
|
70442
|
+
skills_in_flight: {},
|
|
70443
|
+
transcript_offset: 0,
|
|
70444
|
+
remote: { last_pushed_at: null, last_status: null }
|
|
70445
|
+
};
|
|
70446
|
+
}
|
|
70447
|
+
async function readSummary(sessionDir) {
|
|
70448
|
+
let raw;
|
|
70449
|
+
try {
|
|
70450
|
+
raw = await fs22.readFile(getSummaryFile(sessionDir), "utf8");
|
|
70451
|
+
} catch {
|
|
70452
|
+
return null;
|
|
70453
|
+
}
|
|
70454
|
+
try {
|
|
70455
|
+
return JSON.parse(raw);
|
|
70456
|
+
} catch {
|
|
70457
|
+
return null;
|
|
70458
|
+
}
|
|
70459
|
+
}
|
|
70460
|
+
async function writeSummary(sessionDir, summary) {
|
|
70461
|
+
await fs22.mkdir(sessionDir, { recursive: true });
|
|
70462
|
+
const target = getSummaryFile(sessionDir);
|
|
70463
|
+
const tmp = `${target}.tmp`;
|
|
70464
|
+
await fs22.writeFile(tmp, JSON.stringify(summary), "utf8");
|
|
70465
|
+
await fs22.rename(tmp, target);
|
|
70466
|
+
}
|
|
70467
|
+
function isPlainObject2(value) {
|
|
70468
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
70469
|
+
}
|
|
70470
|
+
function mergeDeep(existing, delta) {
|
|
70471
|
+
if (delta === undefined)
|
|
70472
|
+
return existing;
|
|
70473
|
+
if (typeof existing === "number" && typeof delta === "number")
|
|
70474
|
+
return existing + delta;
|
|
70475
|
+
if (Array.isArray(existing) && Array.isArray(delta))
|
|
70476
|
+
return [...existing, ...delta];
|
|
70477
|
+
if (isPlainObject2(existing) && isPlainObject2(delta)) {
|
|
70478
|
+
const out = { ...existing };
|
|
70479
|
+
for (const key of Object.keys(delta)) {
|
|
70480
|
+
out[key] = key in existing ? mergeDeep(existing[key], delta[key]) : delta[key];
|
|
70481
|
+
}
|
|
70482
|
+
return out;
|
|
70483
|
+
}
|
|
70484
|
+
return delta;
|
|
70485
|
+
}
|
|
70486
|
+
function mergeSummary(existing, delta) {
|
|
70487
|
+
const merged = mergeDeep(existing, delta);
|
|
70488
|
+
merged.schema_version = 1;
|
|
70489
|
+
merged.tool_stats.schema_version = 1;
|
|
70490
|
+
return merged;
|
|
70491
|
+
}
|
|
70492
|
+
|
|
70493
|
+
// src/domains/hooks/telemetry/lib/transcript-fingerprint.ts
|
|
70494
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
70495
|
+
import { open as open2 } from "node:fs/promises";
|
|
70496
|
+
var HEAD_BYTES = 4096;
|
|
70497
|
+
async function headFingerprint(transcriptPath) {
|
|
70498
|
+
let handle;
|
|
70499
|
+
try {
|
|
70500
|
+
handle = await open2(transcriptPath, "r");
|
|
70501
|
+
const buf = Buffer.alloc(HEAD_BYTES);
|
|
70502
|
+
const { bytesRead } = await handle.read(buf, 0, HEAD_BYTES, 0);
|
|
70503
|
+
if (bytesRead < HEAD_BYTES)
|
|
70504
|
+
return null;
|
|
70505
|
+
return createHash11("sha256").update(buf.subarray(0, bytesRead)).digest("hex");
|
|
70506
|
+
} catch {
|
|
70507
|
+
return null;
|
|
70508
|
+
} finally {
|
|
70509
|
+
await handle?.close().catch(() => {});
|
|
70510
|
+
}
|
|
70511
|
+
}
|
|
70512
|
+
function compactionBoundary(records) {
|
|
70513
|
+
const idx = records.findIndex((r2) => r2.isCompactSummary === true);
|
|
70514
|
+
return idx === -1 ? 0 : idx + 1;
|
|
70515
|
+
}
|
|
70516
|
+
|
|
70517
|
+
// src/domains/hooks/telemetry/lib/transcript-metrics.ts
|
|
70518
|
+
function deriveTranscriptMetrics(records) {
|
|
70519
|
+
let turnCount = 0;
|
|
70520
|
+
let apiErrorCount = 0;
|
|
70521
|
+
for (const record of records) {
|
|
70522
|
+
if (record.isApiErrorMessage === true)
|
|
70523
|
+
apiErrorCount += 1;
|
|
70524
|
+
if (record.type === "system" && record.subtype === "turn_duration")
|
|
70525
|
+
turnCount += 1;
|
|
70526
|
+
}
|
|
70527
|
+
return { turnCount, apiErrorCount };
|
|
70528
|
+
}
|
|
70529
|
+
|
|
70293
70530
|
// src/domains/hooks/telemetry/lib/claude-transcript-apply.ts
|
|
70294
70531
|
function ensureTokens(t) {
|
|
70295
70532
|
return t ?? { input: 0, output: 0, cache_read: 0, cache_write: 0 };
|
|
@@ -70309,43 +70546,85 @@ function mergeTokenUsageDeltas(existing, deltas) {
|
|
|
70309
70546
|
}
|
|
70310
70547
|
return out;
|
|
70311
70548
|
}
|
|
70312
|
-
|
|
70313
|
-
|
|
70314
|
-
|
|
70549
|
+
function foldRecordsIntoSummary(summary, records, nextOffset, newFingerprint, compactionDetected) {
|
|
70550
|
+
const { mainLoopDelta, subagentDeltas, tokenUsageDeltas } = bucketTokens(records);
|
|
70551
|
+
const metrics = deriveTranscriptMetrics(records);
|
|
70552
|
+
const merged = mergeSummary(summary, {
|
|
70553
|
+
turn_count: metrics.turnCount,
|
|
70554
|
+
api_error_count: metrics.apiErrorCount
|
|
70555
|
+
});
|
|
70556
|
+
merged.main_loop_tokens = addTokens3(summary.main_loop_tokens, mainLoopDelta);
|
|
70557
|
+
merged.subagents = summary.subagents.map((rec) => {
|
|
70558
|
+
const delta = subagentDeltas.get(rec.id);
|
|
70559
|
+
if (!delta)
|
|
70560
|
+
return rec;
|
|
70561
|
+
return { ...rec, tokens: addTokens3(ensureTokens(rec.tokens), delta) };
|
|
70562
|
+
});
|
|
70563
|
+
merged.token_usage = mergeTokenUsageDeltas(summary.token_usage, tokenUsageDeltas);
|
|
70564
|
+
merged.transcript_offset = nextOffset;
|
|
70565
|
+
if (newFingerprint) {
|
|
70566
|
+
merged.transcript_fingerprint = newFingerprint;
|
|
70567
|
+
} else if (compactionDetected) {
|
|
70568
|
+
merged.transcript_fingerprint = undefined;
|
|
70315
70569
|
}
|
|
70316
|
-
|
|
70317
|
-
|
|
70318
|
-
|
|
70319
|
-
|
|
70320
|
-
}
|
|
70321
|
-
|
|
70322
|
-
|
|
70570
|
+
return merged;
|
|
70571
|
+
}
|
|
70572
|
+
async function applyClaudeTranscriptDelta(args) {
|
|
70573
|
+
if (!args.transcriptPath)
|
|
70574
|
+
return { summary: null, read: false };
|
|
70575
|
+
const transcriptPath = args.transcriptPath;
|
|
70576
|
+
return withSummaryLock(args.sessionDir, async () => {
|
|
70577
|
+
try {
|
|
70578
|
+
const summary = await readSummary(args.sessionDir);
|
|
70579
|
+
if (!summary)
|
|
70580
|
+
return { summary: null, read: false };
|
|
70581
|
+
const newFingerprint = await headFingerprint(transcriptPath);
|
|
70582
|
+
const priorFingerprint = summary.transcript_fingerprint;
|
|
70583
|
+
const fingerprintMismatch = newFingerprint !== null && priorFingerprint !== undefined && newFingerprint !== priorFingerprint;
|
|
70584
|
+
let currentSize = null;
|
|
70585
|
+
try {
|
|
70586
|
+
currentSize = (await stat8(transcriptPath)).size;
|
|
70587
|
+
} catch {
|
|
70588
|
+
currentSize = null;
|
|
70589
|
+
}
|
|
70590
|
+
const sizeShrank = currentSize !== null && currentSize < summary.transcript_offset;
|
|
70591
|
+
const compactionDetected = fingerprintMismatch || sizeShrank;
|
|
70592
|
+
let recordsToFold;
|
|
70593
|
+
let nextOffset;
|
|
70594
|
+
if (compactionDetected) {
|
|
70595
|
+
const full = await tailRead({ transcriptPath, offset: 0 });
|
|
70596
|
+
const fullRecords = full.records;
|
|
70597
|
+
const boundary = compactionBoundary(fullRecords);
|
|
70598
|
+
if (boundary === 0) {
|
|
70599
|
+
hookLog("transcript_drift", { compaction_marker_unconfirmed: true });
|
|
70600
|
+
recordsToFold = [];
|
|
70601
|
+
} else {
|
|
70602
|
+
recordsToFold = fullRecords.slice(boundary);
|
|
70603
|
+
}
|
|
70604
|
+
nextOffset = full.nextOffset;
|
|
70605
|
+
} else {
|
|
70606
|
+
const tail = await tailRead({ transcriptPath, offset: summary.transcript_offset });
|
|
70607
|
+
recordsToFold = tail.records;
|
|
70608
|
+
nextOffset = tail.nextOffset;
|
|
70609
|
+
}
|
|
70610
|
+
if (!compactionDetected && recordsToFold.length === 0 && nextOffset === summary.transcript_offset) {
|
|
70611
|
+
return { summary, read: true };
|
|
70612
|
+
}
|
|
70613
|
+
const updated = foldRecordsIntoSummary(summary, recordsToFold, nextOffset, newFingerprint, compactionDetected);
|
|
70614
|
+
await writeSummary(args.sessionDir, updated);
|
|
70615
|
+
return { summary: updated, read: true };
|
|
70616
|
+
} catch (e2) {
|
|
70617
|
+
const error = e2?.message ?? String(e2);
|
|
70618
|
+
hookLog("transcript_apply", { error });
|
|
70619
|
+
return { summary: null, read: false, error };
|
|
70323
70620
|
}
|
|
70324
|
-
|
|
70325
|
-
const updated = {
|
|
70326
|
-
...args.summary,
|
|
70327
|
-
main_loop_tokens: addTokens3(args.summary.main_loop_tokens, mainLoopDelta),
|
|
70328
|
-
subagents: args.summary.subagents.map((rec) => {
|
|
70329
|
-
const delta = subagentDeltas.get(rec.id);
|
|
70330
|
-
if (!delta)
|
|
70331
|
-
return rec;
|
|
70332
|
-
return { ...rec, tokens: addTokens3(ensureTokens(rec.tokens), delta) };
|
|
70333
|
-
}),
|
|
70334
|
-
token_usage: mergeTokenUsageDeltas(args.summary.token_usage, tokenUsageDeltas),
|
|
70335
|
-
transcript_offset: nextOffset
|
|
70336
|
-
};
|
|
70337
|
-
return { summary: updated, read: true };
|
|
70338
|
-
} catch (e2) {
|
|
70339
|
-
const error = e2?.message ?? String(e2);
|
|
70340
|
-
hookLog("transcript_apply", { error });
|
|
70341
|
-
return { summary: args.summary, read: false, error };
|
|
70342
|
-
}
|
|
70621
|
+
});
|
|
70343
70622
|
}
|
|
70344
70623
|
|
|
70345
70624
|
// src/domains/hooks/telemetry/lib/detached-put.ts
|
|
70346
70625
|
import { spawn as spawn2 } from "node:child_process";
|
|
70347
70626
|
import { openSync as openSync5 } from "node:fs";
|
|
70348
|
-
import { dirname as dirname26, join as
|
|
70627
|
+
import { dirname as dirname26, join as join98 } from "node:path";
|
|
70349
70628
|
var ALLOWED_ENV_PREFIXES = ["TKM_", "TAKUMI_"];
|
|
70350
70629
|
var ALLOWED_ENV_KEYS = new Set(["HOME", "USERPROFILE", "PATH", "NODE_ENV"]);
|
|
70351
70630
|
var DETACH_DEBUG_LOG_NAME = "detach-debug.log";
|
|
@@ -70353,7 +70632,7 @@ function effectiveDetachMode(flags) {
|
|
|
70353
70632
|
return flags.noDetach ? "inline" : "detached";
|
|
70354
70633
|
}
|
|
70355
70634
|
function sessionDebugLogPath(sessionDir) {
|
|
70356
|
-
return
|
|
70635
|
+
return join98(sessionDir, DETACH_DEBUG_LOG_NAME);
|
|
70357
70636
|
}
|
|
70358
70637
|
var BUNFS_PREFIX = "/$bunfs/";
|
|
70359
70638
|
function resolveInvocationPrefix() {
|
|
@@ -70383,7 +70662,7 @@ function resolvePreloadScript(entryPath) {
|
|
|
70383
70662
|
try {
|
|
70384
70663
|
const srcDir = dirname26(entryPath);
|
|
70385
70664
|
const repoRoot = dirname26(srcDir);
|
|
70386
|
-
return
|
|
70665
|
+
return join98(repoRoot, "scripts", "preload-config-override.ts");
|
|
70387
70666
|
} catch {
|
|
70388
70667
|
return null;
|
|
70389
70668
|
}
|
|
@@ -70450,87 +70729,32 @@ function decodeJobArgv(argv) {
|
|
|
70450
70729
|
}
|
|
70451
70730
|
}
|
|
70452
70731
|
|
|
70453
|
-
// src/domains/hooks/telemetry/lib/session-
|
|
70454
|
-
|
|
70455
|
-
|
|
70456
|
-
|
|
70457
|
-
|
|
70458
|
-
|
|
70459
|
-
|
|
70460
|
-
// src/shared/project-paths.ts
|
|
70461
|
-
init_paths2();
|
|
70462
|
-
import { createHash as createHash10 } from "node:crypto";
|
|
70463
|
-
import { realpathSync as realpathSync2 } from "node:fs";
|
|
70464
|
-
import { basename as basename17, join as join96 } from "node:path";
|
|
70465
|
-
function encodeCwd(cwd2) {
|
|
70466
|
-
const stripped = cwd2.replace(/^\/+/, "");
|
|
70467
|
-
const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
70468
|
-
return `-${sanitized}`;
|
|
70469
|
-
}
|
|
70470
|
-
function computeProjectHash(cwd2) {
|
|
70471
|
-
let canonical = cwd2;
|
|
70472
|
-
try {
|
|
70473
|
-
canonical = realpathSync2(cwd2);
|
|
70474
|
-
} catch {
|
|
70475
|
-
hookLog("project-hash", { fallback: "realpath_failed", cwd: cwd2 });
|
|
70476
|
-
}
|
|
70477
|
-
return createHash10("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
70478
|
-
}
|
|
70479
|
-
function getProjectLabel(cwd2) {
|
|
70480
|
-
return basename17(cwd2) || "";
|
|
70481
|
-
}
|
|
70482
|
-
function getProjectsRoot() {
|
|
70483
|
-
return join96(getConfigDir(), "projects");
|
|
70484
|
-
}
|
|
70485
|
-
function getProjectDir(args) {
|
|
70486
|
-
return join96(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
|
|
70487
|
-
}
|
|
70488
|
-
|
|
70489
|
-
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
70490
|
-
var MAX_SESSION_ID_LEN = 128;
|
|
70491
|
-
function safeSessionSegment(sessionId) {
|
|
70492
|
-
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
70493
|
-
return null;
|
|
70494
|
-
const cleaned = sessionId.replace(/[^a-zA-Z0-9._-]/g, "");
|
|
70495
|
-
return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
|
|
70496
|
-
}
|
|
70497
|
-
function getSessionsRoot() {
|
|
70498
|
-
return join97(getConfigDir(), "sessions");
|
|
70499
|
-
}
|
|
70500
|
-
function getSessionDirV2(args) {
|
|
70501
|
-
const segment = safeSessionSegment(args.sessionId);
|
|
70502
|
-
if (!segment)
|
|
70503
|
-
return null;
|
|
70504
|
-
return join97(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
|
|
70505
|
-
}
|
|
70506
|
-
function getEventsFile(sessionDir) {
|
|
70507
|
-
return join97(sessionDir, "events.jsonl");
|
|
70508
|
-
}
|
|
70509
|
-
function getSummaryFile(sessionDir) {
|
|
70510
|
-
return join97(sessionDir, "summary.json");
|
|
70511
|
-
}
|
|
70512
|
-
function getLastPushFile(sessionDir) {
|
|
70513
|
-
return join97(sessionDir, "last_push.txt");
|
|
70514
|
-
}
|
|
70515
|
-
var OBSERVATIONS_FILENAME = "observations.jsonl";
|
|
70516
|
-
function getObservationsFile(sessionDir) {
|
|
70517
|
-
return join97(sessionDir, OBSERVATIONS_FILENAME);
|
|
70518
|
-
}
|
|
70519
|
-
function getObservationsFlushingFile(sessionDir) {
|
|
70520
|
-
return join97(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
|
|
70732
|
+
// src/domains/hooks/telemetry/lib/session-lifecycle.ts
|
|
70733
|
+
function elapsedSeconds(sinceIso, nowIso) {
|
|
70734
|
+
if (!sinceIso)
|
|
70735
|
+
return 0;
|
|
70736
|
+
const ms = Date.parse(nowIso) - Date.parse(sinceIso);
|
|
70737
|
+
return ms > 0 ? ms / 1000 : 0;
|
|
70521
70738
|
}
|
|
70522
|
-
function
|
|
70523
|
-
return
|
|
70739
|
+
function openBusyInterval(summary, nowIso) {
|
|
70740
|
+
return { ...summary, active_since: nowIso };
|
|
70524
70741
|
}
|
|
70525
|
-
function
|
|
70526
|
-
|
|
70742
|
+
function closeBusyInterval(summary, nowIso) {
|
|
70743
|
+
if (!summary.active_since)
|
|
70744
|
+
return summary;
|
|
70745
|
+
return {
|
|
70746
|
+
...summary,
|
|
70747
|
+
agent_busy_time_s: (summary.agent_busy_time_s ?? 0) + elapsedSeconds(summary.active_since, nowIso),
|
|
70748
|
+
active_since: undefined
|
|
70749
|
+
};
|
|
70527
70750
|
}
|
|
70528
70751
|
|
|
70529
70752
|
// src/domains/hooks/telemetry/lib/session-meta.ts
|
|
70753
|
+
import { promises as fs23 } from "node:fs";
|
|
70530
70754
|
async function readMeta(sessionDir) {
|
|
70531
70755
|
let raw;
|
|
70532
70756
|
try {
|
|
70533
|
-
raw = await
|
|
70757
|
+
raw = await fs23.readFile(getMetaFile(sessionDir), "utf8");
|
|
70534
70758
|
} catch {
|
|
70535
70759
|
return null;
|
|
70536
70760
|
}
|
|
@@ -70543,13 +70767,13 @@ async function readMeta(sessionDir) {
|
|
|
70543
70767
|
async function writeMetaIfAbsent(sessionDir, meta) {
|
|
70544
70768
|
const target = getMetaFile(sessionDir);
|
|
70545
70769
|
try {
|
|
70546
|
-
await
|
|
70770
|
+
await fs23.access(target);
|
|
70547
70771
|
return;
|
|
70548
70772
|
} catch {}
|
|
70549
|
-
await
|
|
70773
|
+
await fs23.mkdir(sessionDir, { recursive: true });
|
|
70550
70774
|
const tmp = `${target}.tmp`;
|
|
70551
|
-
await
|
|
70552
|
-
await
|
|
70775
|
+
await fs23.writeFile(tmp, JSON.stringify(meta), "utf8");
|
|
70776
|
+
await fs23.rename(tmp, target);
|
|
70553
70777
|
}
|
|
70554
70778
|
|
|
70555
70779
|
// src/domains/hooks/telemetry/lib/session-payload.ts
|
|
@@ -70577,98 +70801,22 @@ function buildSessionPayload(args) {
|
|
|
70577
70801
|
milestone_completed: args.milestone,
|
|
70578
70802
|
error_count: args.errorCount,
|
|
70579
70803
|
tool_stats: summary.tool_stats,
|
|
70580
|
-
...hasTokenUsage ? { token_usage: summary.token_usage } : {}
|
|
70804
|
+
...hasTokenUsage ? { token_usage: summary.token_usage } : {},
|
|
70805
|
+
...summary.turn_count !== undefined ? { turn_count: summary.turn_count } : {},
|
|
70806
|
+
...summary.api_error_count !== undefined ? { api_error_count: summary.api_error_count } : {},
|
|
70807
|
+
...summary.agent_busy_time_s !== undefined ? { agent_busy_time_s: Math.round(summary.agent_busy_time_s) } : {},
|
|
70808
|
+
summary_generated_at: new Date().toISOString()
|
|
70581
70809
|
}
|
|
70582
70810
|
};
|
|
70583
70811
|
}
|
|
70584
70812
|
|
|
70585
|
-
// src/domains/hooks/telemetry/lib/summary.ts
|
|
70586
|
-
import { promises as fs22 } from "node:fs";
|
|
70587
|
-
function zeroTokens3() {
|
|
70588
|
-
return { input: 0, output: 0, cache_read: 0, cache_write: 0 };
|
|
70589
|
-
}
|
|
70590
|
-
function initialSummary(args) {
|
|
70591
|
-
return {
|
|
70592
|
-
schema_version: 1,
|
|
70593
|
-
session_id: args.sessionId,
|
|
70594
|
-
agent: args.agent,
|
|
70595
|
-
cli_version: args.cliVersion ?? null,
|
|
70596
|
-
kit_versions: args.kitVersions ?? {},
|
|
70597
|
-
project: args.project,
|
|
70598
|
-
timing: { started_at: args.startedAt, ended_at: null, duration_s: null },
|
|
70599
|
-
main_loop_tokens: zeroTokens3(),
|
|
70600
|
-
token_usage: {},
|
|
70601
|
-
subagents: [],
|
|
70602
|
-
skills: [],
|
|
70603
|
-
tool_stats: {
|
|
70604
|
-
schema_version: 1,
|
|
70605
|
-
total_events: 0,
|
|
70606
|
-
total_tool_calls: 0,
|
|
70607
|
-
by_type: {},
|
|
70608
|
-
by_name: {},
|
|
70609
|
-
subagents: { by_type: {} },
|
|
70610
|
-
skills: { by_name: {} }
|
|
70611
|
-
},
|
|
70612
|
-
totals: zeroTokens3(),
|
|
70613
|
-
pending_user_triggers: [],
|
|
70614
|
-
skills_in_flight: {},
|
|
70615
|
-
transcript_offset: 0,
|
|
70616
|
-
remote: { last_pushed_at: null, last_status: null }
|
|
70617
|
-
};
|
|
70618
|
-
}
|
|
70619
|
-
async function readSummary(sessionDir) {
|
|
70620
|
-
let raw;
|
|
70621
|
-
try {
|
|
70622
|
-
raw = await fs22.readFile(getSummaryFile(sessionDir), "utf8");
|
|
70623
|
-
} catch {
|
|
70624
|
-
return null;
|
|
70625
|
-
}
|
|
70626
|
-
try {
|
|
70627
|
-
return JSON.parse(raw);
|
|
70628
|
-
} catch {
|
|
70629
|
-
return null;
|
|
70630
|
-
}
|
|
70631
|
-
}
|
|
70632
|
-
async function writeSummary(sessionDir, summary) {
|
|
70633
|
-
await fs22.mkdir(sessionDir, { recursive: true });
|
|
70634
|
-
const target = getSummaryFile(sessionDir);
|
|
70635
|
-
const tmp = `${target}.tmp`;
|
|
70636
|
-
await fs22.writeFile(tmp, JSON.stringify(summary), "utf8");
|
|
70637
|
-
await fs22.rename(tmp, target);
|
|
70638
|
-
}
|
|
70639
|
-
function isPlainObject2(value) {
|
|
70640
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
70641
|
-
}
|
|
70642
|
-
function mergeDeep(existing, delta) {
|
|
70643
|
-
if (delta === undefined)
|
|
70644
|
-
return existing;
|
|
70645
|
-
if (typeof existing === "number" && typeof delta === "number")
|
|
70646
|
-
return existing + delta;
|
|
70647
|
-
if (Array.isArray(existing) && Array.isArray(delta))
|
|
70648
|
-
return [...existing, ...delta];
|
|
70649
|
-
if (isPlainObject2(existing) && isPlainObject2(delta)) {
|
|
70650
|
-
const out = { ...existing };
|
|
70651
|
-
for (const key of Object.keys(delta)) {
|
|
70652
|
-
out[key] = key in existing ? mergeDeep(existing[key], delta[key]) : delta[key];
|
|
70653
|
-
}
|
|
70654
|
-
return out;
|
|
70655
|
-
}
|
|
70656
|
-
return delta;
|
|
70657
|
-
}
|
|
70658
|
-
function mergeSummary(existing, delta) {
|
|
70659
|
-
const merged = mergeDeep(existing, delta);
|
|
70660
|
-
merged.schema_version = 1;
|
|
70661
|
-
merged.tool_stats.schema_version = 1;
|
|
70662
|
-
return merged;
|
|
70663
|
-
}
|
|
70664
|
-
|
|
70665
70813
|
// src/domains/hooks/telemetry/lib/throttle.ts
|
|
70666
|
-
import { promises as
|
|
70814
|
+
import { promises as fs24 } from "node:fs";
|
|
70667
70815
|
var defaultNow = () => Date.now();
|
|
70668
70816
|
async function readLastPush(sessionDir) {
|
|
70669
70817
|
let raw;
|
|
70670
70818
|
try {
|
|
70671
|
-
raw = await
|
|
70819
|
+
raw = await fs24.readFile(getLastPushFile(sessionDir), "utf8");
|
|
70672
70820
|
} catch {
|
|
70673
70821
|
return null;
|
|
70674
70822
|
}
|
|
@@ -70676,11 +70824,11 @@ async function readLastPush(sessionDir) {
|
|
|
70676
70824
|
return Number.isFinite(parsed) ? parsed : null;
|
|
70677
70825
|
}
|
|
70678
70826
|
async function writeLastPush(sessionDir, ts) {
|
|
70679
|
-
await
|
|
70827
|
+
await fs24.mkdir(sessionDir, { recursive: true });
|
|
70680
70828
|
const target = getLastPushFile(sessionDir);
|
|
70681
70829
|
const tmp = `${target}.tmp`;
|
|
70682
|
-
await
|
|
70683
|
-
await
|
|
70830
|
+
await fs24.writeFile(tmp, String(ts), "utf8");
|
|
70831
|
+
await fs24.rename(tmp, target);
|
|
70684
70832
|
}
|
|
70685
70833
|
async function shouldFlush(args) {
|
|
70686
70834
|
const now = args.now ?? defaultNow;
|
|
@@ -70690,8 +70838,8 @@ async function shouldFlush(args) {
|
|
|
70690
70838
|
if (now() - last >= args.intervalMs)
|
|
70691
70839
|
return true;
|
|
70692
70840
|
try {
|
|
70693
|
-
const
|
|
70694
|
-
if (
|
|
70841
|
+
const stat9 = await fs24.stat(getEventsFile(args.sessionDir));
|
|
70842
|
+
if (stat9.size >= args.sizeBytes)
|
|
70695
70843
|
return true;
|
|
70696
70844
|
} catch {}
|
|
70697
70845
|
return false;
|
|
@@ -70737,16 +70885,21 @@ async function runSessionEndFlush(data, ctx) {
|
|
|
70737
70885
|
return;
|
|
70738
70886
|
}
|
|
70739
70887
|
const endedAtIso = new Date().toISOString();
|
|
70740
|
-
|
|
70741
|
-
|
|
70888
|
+
const closedSummary = await withSummaryLock(sessionDir, async () => {
|
|
70889
|
+
const latest = await readSummary(sessionDir) ?? summary;
|
|
70890
|
+
latest.timing.ended_at = endedAtIso;
|
|
70891
|
+
latest.timing.duration_s = Math.max(0, Math.round((Date.parse(endedAtIso) - Date.parse(latest.timing.started_at)) / 1000));
|
|
70892
|
+
const closed = closeBusyInterval(latest, endedAtIso);
|
|
70893
|
+
await writeSummary(sessionDir, closed);
|
|
70894
|
+
return closed;
|
|
70895
|
+
});
|
|
70742
70896
|
const transcriptPath = typeof data.transcript_path === "string" ? data.transcript_path : (await readMeta(sessionDir))?.transcript_path ?? null;
|
|
70743
|
-
let finalSummary =
|
|
70897
|
+
let finalSummary = closedSummary;
|
|
70744
70898
|
if (transcriptPath) {
|
|
70745
|
-
const applied = await applyClaudeTranscriptDelta({
|
|
70746
|
-
if (applied.read)
|
|
70899
|
+
const applied = await applyClaudeTranscriptDelta({ sessionDir, transcriptPath });
|
|
70900
|
+
if (applied.read && applied.summary)
|
|
70747
70901
|
finalSummary = applied.summary;
|
|
70748
70902
|
}
|
|
70749
|
-
await writeSummary(sessionDir, finalSummary);
|
|
70750
70903
|
const reason = pickReason(data);
|
|
70751
70904
|
const existingMeta = await readMeta(sessionDir);
|
|
70752
70905
|
if (existingMeta && (reason || Object.keys(data).length > 0)) {
|
|
@@ -70755,12 +70908,12 @@ async function runSessionEndFlush(data, ctx) {
|
|
|
70755
70908
|
...reason ? { session_end_reason: reason } : {},
|
|
70756
70909
|
session_end_raw: data
|
|
70757
70910
|
};
|
|
70758
|
-
const { promises:
|
|
70759
|
-
const { join:
|
|
70760
|
-
const target =
|
|
70911
|
+
const { promises: fs25 } = await import("node:fs");
|
|
70912
|
+
const { join: join99 } = await import("node:path");
|
|
70913
|
+
const target = join99(sessionDir, "meta.json");
|
|
70761
70914
|
const tmp = `${target}.tmp`;
|
|
70762
|
-
await
|
|
70763
|
-
await
|
|
70915
|
+
await fs25.writeFile(tmp, JSON.stringify(updated), "utf8");
|
|
70916
|
+
await fs25.rename(tmp, target);
|
|
70764
70917
|
} else if (!existingMeta) {
|
|
70765
70918
|
await writeMetaIfAbsent(sessionDir, {
|
|
70766
70919
|
agent,
|
|
@@ -70831,7 +70984,7 @@ async function handleSessionEnd(agent, flags = {}) {
|
|
|
70831
70984
|
init_takumi_constants();
|
|
70832
70985
|
|
|
70833
70986
|
// src/domains/hooks/telemetry/lib/codex-tokens.ts
|
|
70834
|
-
import * as
|
|
70987
|
+
import * as fs25 from "node:fs";
|
|
70835
70988
|
function n(v2) {
|
|
70836
70989
|
return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
|
|
70837
70990
|
}
|
|
@@ -70855,7 +71008,7 @@ function codexTokensOf(rec) {
|
|
|
70855
71008
|
}
|
|
70856
71009
|
function sumCodexChildTokens(jsonlPath) {
|
|
70857
71010
|
const acc = { input: 0, output: 0, cache_read: 0, cache_write: 0 };
|
|
70858
|
-
if (!jsonlPath || !
|
|
71011
|
+
if (!jsonlPath || !fs25.existsSync(jsonlPath))
|
|
70859
71012
|
return acc;
|
|
70860
71013
|
const { records } = readNew(jsonlPath, 0);
|
|
70861
71014
|
for (const rec of records) {
|
|
@@ -70941,12 +71094,12 @@ async function applyCodexTranscriptDelta(args) {
|
|
|
70941
71094
|
}
|
|
70942
71095
|
|
|
70943
71096
|
// src/domains/hooks/lib/jsonl-append.ts
|
|
70944
|
-
import { promises as
|
|
71097
|
+
import { promises as fs26, appendFileSync as appendFileSync2, mkdirSync as mkdirSync4 } from "node:fs";
|
|
70945
71098
|
import { dirname as dirname27 } from "node:path";
|
|
70946
71099
|
async function appendJsonl(filePath, record) {
|
|
70947
71100
|
try {
|
|
70948
|
-
await
|
|
70949
|
-
await
|
|
71101
|
+
await fs26.mkdir(dirname27(filePath), { recursive: true });
|
|
71102
|
+
await fs26.appendFile(filePath, `${JSON.stringify(record)}
|
|
70950
71103
|
`, "utf8");
|
|
70951
71104
|
} catch {}
|
|
70952
71105
|
}
|
|
@@ -71001,10 +71154,13 @@ async function recordEvent(args) {
|
|
|
71001
71154
|
const meta = buildMeta(args);
|
|
71002
71155
|
await writeMetaIfAbsent(sessionDir, meta);
|
|
71003
71156
|
const onDiskMeta = await readMeta(sessionDir) ?? meta;
|
|
71004
|
-
const
|
|
71005
|
-
|
|
71006
|
-
|
|
71007
|
-
|
|
71157
|
+
const next = await withSummaryLock(sessionDir, async () => {
|
|
71158
|
+
const existing = await readSummary(sessionDir);
|
|
71159
|
+
const base = existing ?? buildInitialSummary(args, onDiskMeta);
|
|
71160
|
+
const mutated = args.mutate ? args.mutate(base) : base;
|
|
71161
|
+
await writeSummary(sessionDir, mutated);
|
|
71162
|
+
return mutated;
|
|
71163
|
+
});
|
|
71008
71164
|
if (args.bufferEvent) {
|
|
71009
71165
|
await appendEvent(sessionDir, args.bufferEvent);
|
|
71010
71166
|
}
|
|
@@ -71084,7 +71240,7 @@ function recordStop(s, args) {
|
|
|
71084
71240
|
merged.timing.duration_s = Math.max(0, Math.round((Date.parse(args.endedAtIso) - Date.parse(merged.timing.started_at)) / 1000));
|
|
71085
71241
|
if (args.cliVersion)
|
|
71086
71242
|
merged.cli_version = args.cliVersion;
|
|
71087
|
-
return merged;
|
|
71243
|
+
return closeBusyInterval(merged, args.endedAtIso);
|
|
71088
71244
|
}
|
|
71089
71245
|
async function runStopFlush(data, ctx) {
|
|
71090
71246
|
const { agent, cwd: cwd2, flags } = ctx;
|
|
@@ -71133,17 +71289,32 @@ async function runStopFlush(data, ctx) {
|
|
|
71133
71289
|
setHookDebugLog(sessionDebugLogPath(result.sessionDir));
|
|
71134
71290
|
let payloadSummary = result.summary;
|
|
71135
71291
|
if (hasTranscript && transcriptPath) {
|
|
71136
|
-
|
|
71137
|
-
|
|
71138
|
-
|
|
71139
|
-
|
|
71140
|
-
|
|
71141
|
-
|
|
71142
|
-
|
|
71143
|
-
|
|
71144
|
-
|
|
71145
|
-
|
|
71146
|
-
|
|
71292
|
+
if (agent === "codex") {
|
|
71293
|
+
payloadSummary = await withSummaryLock(result.sessionDir, async () => {
|
|
71294
|
+
const latest = await readSummary(result.sessionDir) ?? result.summary;
|
|
71295
|
+
const applied = await applyCodexTranscriptDelta({
|
|
71296
|
+
summary: latest,
|
|
71297
|
+
transcriptPath,
|
|
71298
|
+
stdinModel
|
|
71299
|
+
});
|
|
71300
|
+
const recomputed = recomputeTotals(applied.read ? applied.summary : latest);
|
|
71301
|
+
await writeSummary(result.sessionDir, recomputed);
|
|
71302
|
+
return recomputed;
|
|
71303
|
+
});
|
|
71304
|
+
} else {
|
|
71305
|
+
const applied = await applyClaudeTranscriptDelta({
|
|
71306
|
+
sessionDir: result.sessionDir,
|
|
71307
|
+
transcriptPath
|
|
71308
|
+
});
|
|
71309
|
+
if (applied.read && applied.summary) {
|
|
71310
|
+
const appliedSummary = applied.summary;
|
|
71311
|
+
payloadSummary = await withSummaryLock(result.sessionDir, async () => {
|
|
71312
|
+
const latest = await readSummary(result.sessionDir) ?? appliedSummary;
|
|
71313
|
+
const recomputed = recomputeTotals(latest);
|
|
71314
|
+
await writeSummary(result.sessionDir, recomputed);
|
|
71315
|
+
return recomputed;
|
|
71316
|
+
});
|
|
71317
|
+
}
|
|
71147
71318
|
}
|
|
71148
71319
|
}
|
|
71149
71320
|
const endpoint = resolveEndpoint();
|
|
@@ -71205,11 +71376,13 @@ async function runStopFlush(data, ctx) {
|
|
|
71205
71376
|
last_pushed_at: new Date().toISOString(),
|
|
71206
71377
|
last_status: put2.status ?? null
|
|
71207
71378
|
};
|
|
71208
|
-
|
|
71209
|
-
|
|
71210
|
-
refreshed
|
|
71211
|
-
|
|
71212
|
-
|
|
71379
|
+
await withSummaryLock(result.sessionDir, async () => {
|
|
71380
|
+
const refreshed = await readSummary(result.sessionDir);
|
|
71381
|
+
if (refreshed) {
|
|
71382
|
+
refreshed.remote = remote;
|
|
71383
|
+
await writeSummary(result.sessionDir, refreshed);
|
|
71384
|
+
}
|
|
71385
|
+
});
|
|
71213
71386
|
}
|
|
71214
71387
|
} catch (e2) {
|
|
71215
71388
|
hookLog("stop", { error: e2?.message ?? String(e2) });
|
|
@@ -71222,15 +71395,15 @@ async function handleStop(agent, flags = {}) {
|
|
|
71222
71395
|
|
|
71223
71396
|
// src/domains/hooks/telemetry/otlp/observations-export.ts
|
|
71224
71397
|
init_paths2();
|
|
71225
|
-
import { promises as
|
|
71226
|
-
import { join as
|
|
71398
|
+
import { promises as fs30, openSync as openSync7 } from "node:fs";
|
|
71399
|
+
import { join as join100 } from "node:path";
|
|
71227
71400
|
|
|
71228
71401
|
// src/domains/hooks/telemetry/lib/retention.ts
|
|
71229
|
-
import { promises as
|
|
71230
|
-
import { join as
|
|
71402
|
+
import { promises as fs27 } from "node:fs";
|
|
71403
|
+
import { join as join99 } from "node:path";
|
|
71231
71404
|
async function pathExists24(path10) {
|
|
71232
71405
|
try {
|
|
71233
|
-
await
|
|
71406
|
+
await fs27.access(path10);
|
|
71234
71407
|
return true;
|
|
71235
71408
|
} catch {
|
|
71236
71409
|
return false;
|
|
@@ -71242,10 +71415,10 @@ async function hasUnexportedObservations(dir) {
|
|
|
71242
71415
|
async function decideDelete(dir, args) {
|
|
71243
71416
|
let mtimeMs = 0;
|
|
71244
71417
|
try {
|
|
71245
|
-
const
|
|
71246
|
-
if (!
|
|
71418
|
+
const stat9 = await fs27.stat(dir);
|
|
71419
|
+
if (!stat9.isDirectory())
|
|
71247
71420
|
return false;
|
|
71248
|
-
mtimeMs =
|
|
71421
|
+
mtimeMs = stat9.mtimeMs;
|
|
71249
71422
|
} catch {
|
|
71250
71423
|
return false;
|
|
71251
71424
|
}
|
|
@@ -71261,8 +71434,8 @@ async function decideDelete(dir, args) {
|
|
|
71261
71434
|
}
|
|
71262
71435
|
async function listChildren(dir) {
|
|
71263
71436
|
try {
|
|
71264
|
-
const names = await
|
|
71265
|
-
return names.map((n2) =>
|
|
71437
|
+
const names = await fs27.readdir(dir);
|
|
71438
|
+
return names.map((n2) => join99(dir, n2));
|
|
71266
71439
|
} catch {
|
|
71267
71440
|
return [];
|
|
71268
71441
|
}
|
|
@@ -71273,7 +71446,7 @@ async function collectV2Sessions() {
|
|
|
71273
71446
|
const sessions = [];
|
|
71274
71447
|
for (const projectDir of projects) {
|
|
71275
71448
|
for (const agentDir of await listChildren(projectDir)) {
|
|
71276
|
-
for (const sessionDir of await listChildren(
|
|
71449
|
+
for (const sessionDir of await listChildren(join99(agentDir, "sessions"))) {
|
|
71277
71450
|
sessions.push(sessionDir);
|
|
71278
71451
|
}
|
|
71279
71452
|
}
|
|
@@ -71297,7 +71470,7 @@ async function sweepRetention(args) {
|
|
|
71297
71470
|
continue;
|
|
71298
71471
|
}
|
|
71299
71472
|
try {
|
|
71300
|
-
await
|
|
71473
|
+
await fs27.rm(dir, { recursive: true, force: true });
|
|
71301
71474
|
deleted.push(dir);
|
|
71302
71475
|
} catch {}
|
|
71303
71476
|
}
|
|
@@ -71305,10 +71478,10 @@ async function sweepRetention(args) {
|
|
|
71305
71478
|
}
|
|
71306
71479
|
|
|
71307
71480
|
// src/domains/hooks/telemetry/otlp/observations-export-state.ts
|
|
71308
|
-
import { promises as
|
|
71481
|
+
import { promises as fs28 } from "node:fs";
|
|
71309
71482
|
async function exists(path10) {
|
|
71310
71483
|
try {
|
|
71311
|
-
await
|
|
71484
|
+
await fs28.access(path10);
|
|
71312
71485
|
return true;
|
|
71313
71486
|
} catch {
|
|
71314
71487
|
return false;
|
|
@@ -71320,7 +71493,7 @@ async function stageObservationsForFlush(sessionDir) {
|
|
|
71320
71493
|
return flushing;
|
|
71321
71494
|
const live = getObservationsFile(sessionDir);
|
|
71322
71495
|
try {
|
|
71323
|
-
await
|
|
71496
|
+
await fs28.rename(live, flushing);
|
|
71324
71497
|
return flushing;
|
|
71325
71498
|
} catch {
|
|
71326
71499
|
return null;
|
|
@@ -71328,15 +71501,15 @@ async function stageObservationsForFlush(sessionDir) {
|
|
|
71328
71501
|
}
|
|
71329
71502
|
async function completeObservationsFlush(sessionDir, flushingPath, now) {
|
|
71330
71503
|
try {
|
|
71331
|
-
await
|
|
71504
|
+
await fs28.writeFile(getObservationsPushedFile(sessionDir), String(now), "utf8");
|
|
71332
71505
|
} catch {}
|
|
71333
71506
|
try {
|
|
71334
|
-
await
|
|
71507
|
+
await fs28.rm(flushingPath, { force: true });
|
|
71335
71508
|
} catch {}
|
|
71336
71509
|
}
|
|
71337
71510
|
async function readObsPushed(sessionDir) {
|
|
71338
71511
|
try {
|
|
71339
|
-
const raw = await
|
|
71512
|
+
const raw = await fs28.readFile(getObservationsPushedFile(sessionDir), "utf8");
|
|
71340
71513
|
const parsed = Number.parseInt(raw.trim(), 10);
|
|
71341
71514
|
return Number.isFinite(parsed) ? parsed : null;
|
|
71342
71515
|
} catch {
|
|
@@ -71351,7 +71524,7 @@ async function shouldFlushObservations(sessionDir, gate) {
|
|
|
71351
71524
|
return true;
|
|
71352
71525
|
let size = 0;
|
|
71353
71526
|
try {
|
|
71354
|
-
size = (await
|
|
71527
|
+
size = (await fs28.stat(getObservationsFile(sessionDir))).size;
|
|
71355
71528
|
} catch {
|
|
71356
71529
|
return false;
|
|
71357
71530
|
}
|
|
@@ -71378,10 +71551,10 @@ async function resolveOtlpConfig() {
|
|
|
71378
71551
|
|
|
71379
71552
|
// src/domains/hooks/telemetry/otlp/otlp-post.ts
|
|
71380
71553
|
import { spawn as spawn3 } from "node:child_process";
|
|
71381
|
-
import { promises as
|
|
71554
|
+
import { promises as fs29, openSync as openSync6 } from "node:fs";
|
|
71382
71555
|
|
|
71383
71556
|
// src/domains/hooks/telemetry/otlp/otlp-payload-builder.ts
|
|
71384
|
-
import { createHash as
|
|
71557
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
71385
71558
|
var SERVICE_NAME = "tkm-hooks";
|
|
71386
71559
|
var SCOPE_NAME = "takumi-cli.hooks";
|
|
71387
71560
|
var MAX_RECORDS = 500;
|
|
@@ -71500,7 +71673,7 @@ function resourceAttributes(args) {
|
|
|
71500
71673
|
}
|
|
71501
71674
|
function batchKey(kept) {
|
|
71502
71675
|
const sessionId = str2(kept[0]?.session_id) ?? "unknown";
|
|
71503
|
-
const hash =
|
|
71676
|
+
const hash = createHash12("sha256").update(kept.map((r2) => JSON.stringify(r2)).join(`
|
|
71504
71677
|
`)).digest("hex").slice(0, 16);
|
|
71505
71678
|
return `${sessionId}:${hash}`;
|
|
71506
71679
|
}
|
|
@@ -71528,7 +71701,7 @@ function buildOtlpLogsPayload(content) {
|
|
|
71528
71701
|
}
|
|
71529
71702
|
|
|
71530
71703
|
// src/domains/hooks/telemetry/otlp/otlp-post.ts
|
|
71531
|
-
var
|
|
71704
|
+
var DEFAULT_TIMEOUT_MS4 = 5000;
|
|
71532
71705
|
var LOGS_PATH = "/v1/logs";
|
|
71533
71706
|
var ALLOWED_HOST_SUFFIXES = [".sun-asterisk.ai"];
|
|
71534
71707
|
var ALLOWED_EXACT_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
|
|
@@ -71563,7 +71736,7 @@ async function runOtlpPost(job, deps = {}) {
|
|
|
71563
71736
|
const now = deps.now ?? Date.now;
|
|
71564
71737
|
let content;
|
|
71565
71738
|
try {
|
|
71566
|
-
content = await
|
|
71739
|
+
content = await fs29.readFile(job.flushingPath, "utf8");
|
|
71567
71740
|
} catch {
|
|
71568
71741
|
return { ok: false, skipped: true, error: "no_flushing_file" };
|
|
71569
71742
|
}
|
|
@@ -71583,7 +71756,7 @@ async function runOtlpPost(job, deps = {}) {
|
|
|
71583
71756
|
headers.Authorization = `Bearer ${config.bearer}`;
|
|
71584
71757
|
}
|
|
71585
71758
|
const controller = new AbortController;
|
|
71586
|
-
const timer = setTimeout(() => controller.abort(), job.timeoutMs > 0 ? job.timeoutMs :
|
|
71759
|
+
const timer = setTimeout(() => controller.abort(), job.timeoutMs > 0 ? job.timeoutMs : DEFAULT_TIMEOUT_MS4);
|
|
71587
71760
|
try {
|
|
71588
71761
|
const res = await doFetch(url, {
|
|
71589
71762
|
method: "POST",
|
|
@@ -71702,12 +71875,12 @@ async function exportSessionObservations(sessionDir, opts = {}, deps = {}) {
|
|
|
71702
71875
|
}
|
|
71703
71876
|
}
|
|
71704
71877
|
function lockPath() {
|
|
71705
|
-
return
|
|
71878
|
+
return join100(getConfigDir(), "obs-flush.lock");
|
|
71706
71879
|
}
|
|
71707
71880
|
async function acquireSweepLock(now) {
|
|
71708
71881
|
const path10 = lockPath();
|
|
71709
71882
|
try {
|
|
71710
|
-
await
|
|
71883
|
+
await fs30.mkdir(getConfigDir(), { recursive: true });
|
|
71711
71884
|
} catch {
|
|
71712
71885
|
return false;
|
|
71713
71886
|
}
|
|
@@ -71716,9 +71889,9 @@ async function acquireSweepLock(now) {
|
|
|
71716
71889
|
return true;
|
|
71717
71890
|
} catch {
|
|
71718
71891
|
try {
|
|
71719
|
-
const
|
|
71720
|
-
if (now -
|
|
71721
|
-
await
|
|
71892
|
+
const stat9 = await fs30.stat(path10);
|
|
71893
|
+
if (now - stat9.mtimeMs > STALE_LOCK_MS) {
|
|
71894
|
+
await fs30.rm(path10, { force: true });
|
|
71722
71895
|
openSync7(path10, "wx");
|
|
71723
71896
|
return true;
|
|
71724
71897
|
}
|
|
@@ -71728,7 +71901,7 @@ async function acquireSweepLock(now) {
|
|
|
71728
71901
|
}
|
|
71729
71902
|
async function releaseSweepLock() {
|
|
71730
71903
|
try {
|
|
71731
|
-
await
|
|
71904
|
+
await fs30.rm(lockPath(), { force: true });
|
|
71732
71905
|
} catch {}
|
|
71733
71906
|
}
|
|
71734
71907
|
async function flushOrphanObservations(deps = {}) {
|
|
@@ -71857,7 +72030,7 @@ function diffTokens(post2, base) {
|
|
|
71857
72030
|
cache_write: Math.max(0, post2.cache_write - base.cache_write)
|
|
71858
72031
|
};
|
|
71859
72032
|
}
|
|
71860
|
-
function applyMutation(s, classified, tsIso, toolUseId,
|
|
72033
|
+
function applyMutation(s, classified, tsIso, toolUseId, skillTokens) {
|
|
71861
72034
|
const merged = mergeSummary(s, {
|
|
71862
72035
|
tool_stats: {
|
|
71863
72036
|
total_events: 1,
|
|
@@ -71898,8 +72071,6 @@ function applyMutation(s, classified, tsIso, toolUseId, description, skillTokens
|
|
|
71898
72071
|
started_at: tsIso,
|
|
71899
72072
|
triggered_by: triggeredBy
|
|
71900
72073
|
};
|
|
71901
|
-
if (description)
|
|
71902
|
-
record.description = description.slice(0, MAX_EVENT_NAME_LEN);
|
|
71903
72074
|
merged.subagents.push(record);
|
|
71904
72075
|
}
|
|
71905
72076
|
return merged;
|
|
@@ -71925,8 +72096,6 @@ async function runPostToolUseCapture(data, ctx) {
|
|
|
71925
72096
|
const tsIso = new Date().toISOString();
|
|
71926
72097
|
const transcriptPath = typeof data.transcript_path === "string" ? data.transcript_path : null;
|
|
71927
72098
|
const toolUseId = typeof data.tool_use_id === "string" ? data.tool_use_id : null;
|
|
71928
|
-
const input = data.tool_input && typeof data.tool_input === "object" ? data.tool_input : {};
|
|
71929
|
-
const description = typeof input.description === "string" ? input.description : null;
|
|
71930
72099
|
let skillTokens = null;
|
|
71931
72100
|
if (classified.kind === "skill" && agent === "claude" && transcriptPath) {
|
|
71932
72101
|
const sessionDir = getSessionDirV2({ agent, cwd: cwd2, sessionId });
|
|
@@ -71934,9 +72103,8 @@ async function runPostToolUseCapture(data, ctx) {
|
|
|
71934
72103
|
const before = await readSummary(sessionDir);
|
|
71935
72104
|
const baseline = before?.skills_in_flight[classified.name]?.baseline;
|
|
71936
72105
|
if (before && baseline) {
|
|
71937
|
-
const applied = await applyClaudeTranscriptDelta({
|
|
71938
|
-
if (applied.read) {
|
|
71939
|
-
await writeSummary(sessionDir, applied.summary);
|
|
72106
|
+
const applied = await applyClaudeTranscriptDelta({ sessionDir, transcriptPath });
|
|
72107
|
+
if (applied.read && applied.summary) {
|
|
71940
72108
|
skillTokens = diffTokens(applied.summary.main_loop_tokens, baseline);
|
|
71941
72109
|
}
|
|
71942
72110
|
}
|
|
@@ -71949,7 +72117,7 @@ async function runPostToolUseCapture(data, ctx) {
|
|
|
71949
72117
|
startedAt: tsIso,
|
|
71950
72118
|
transcriptPath,
|
|
71951
72119
|
bufferEvent: { event_type: classified.kind, event_name: classified.name, ts: tsIso },
|
|
71952
|
-
mutate: (s) => applyMutation(s, classified, tsIso, toolUseId,
|
|
72120
|
+
mutate: (s) => applyMutation(s, classified, tsIso, toolUseId, skillTokens)
|
|
71953
72121
|
});
|
|
71954
72122
|
if (!result) {
|
|
71955
72123
|
hookLog("post-tool-use", { agent, session_id: sessionId, skipped: "bad_session_dir" });
|
|
@@ -72289,7 +72457,7 @@ async function runUserPromptSubmitCapture(data, ctx) {
|
|
|
72289
72457
|
by_name: { [tkmCommand]: 1 }
|
|
72290
72458
|
};
|
|
72291
72459
|
}
|
|
72292
|
-
return mergeSummary(s, delta);
|
|
72460
|
+
return openBusyInterval(mergeSummary(s, delta), tsIso);
|
|
72293
72461
|
}
|
|
72294
72462
|
});
|
|
72295
72463
|
if (!result) {
|
|
@@ -72346,11 +72514,11 @@ var metricsRecord = {
|
|
|
72346
72514
|
|
|
72347
72515
|
// src/domains/hooks/handlers/session-init/handler.ts
|
|
72348
72516
|
import { mkdirSync as mkdirSync5 } from "node:fs";
|
|
72349
|
-
import { dirname as dirname28, join as
|
|
72517
|
+
import { dirname as dirname28, join as join104 } from "node:path";
|
|
72350
72518
|
|
|
72351
72519
|
// src/domains/hooks/handlers/_shared/project-detector.ts
|
|
72352
72520
|
import { existsSync as existsSync48, readFileSync as readFileSync15 } from "node:fs";
|
|
72353
|
-
import { join as
|
|
72521
|
+
import { join as join101 } from "node:path";
|
|
72354
72522
|
var LOCKFILE_PRIORITY = [
|
|
72355
72523
|
{ manager: "bun", files: ["bun.lockb", "bun.lock"] },
|
|
72356
72524
|
{ manager: "pnpm", files: ["pnpm-lock.yaml"] },
|
|
@@ -72385,14 +72553,14 @@ var APP_FRAMEWORKS = new Set([
|
|
|
72385
72553
|
var WORKSPACE_MARKER_FILES = ["pnpm-workspace.yaml", "turbo.json", "lerna.json"];
|
|
72386
72554
|
function fileExists(cwd2, name2) {
|
|
72387
72555
|
try {
|
|
72388
|
-
return existsSync48(
|
|
72556
|
+
return existsSync48(join101(cwd2, name2));
|
|
72389
72557
|
} catch {
|
|
72390
72558
|
return false;
|
|
72391
72559
|
}
|
|
72392
72560
|
}
|
|
72393
72561
|
function readPackageJson(cwd2) {
|
|
72394
72562
|
try {
|
|
72395
|
-
const raw = readFileSync15(
|
|
72563
|
+
const raw = readFileSync15(join101(cwd2, "package.json"), "utf8");
|
|
72396
72564
|
const parsed = JSON.parse(raw);
|
|
72397
72565
|
if (parsed && typeof parsed === "object")
|
|
72398
72566
|
return parsed;
|
|
@@ -72474,13 +72642,13 @@ function detectProject(cwd2) {
|
|
|
72474
72642
|
}
|
|
72475
72643
|
|
|
72476
72644
|
// src/domains/hooks/handlers/session-init/env-entries.ts
|
|
72477
|
-
import { createHash as
|
|
72645
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
72478
72646
|
import { platform as platform8, userInfo } from "node:os";
|
|
72479
|
-
import { join as
|
|
72647
|
+
import { join as join103 } from "node:path";
|
|
72480
72648
|
|
|
72481
72649
|
// src/domains/hooks/handlers/session-init/plan-resolver.ts
|
|
72482
72650
|
import { existsSync as existsSync49, readFileSync as readFileSync16, readdirSync as readdirSync7 } from "node:fs";
|
|
72483
|
-
import { join as
|
|
72651
|
+
import { join as join102 } from "node:path";
|
|
72484
72652
|
var MAX_PLAN_DIRS = 100;
|
|
72485
72653
|
var MAX_PLAN_FILE_BYTES = 64 * 1024;
|
|
72486
72654
|
function listPlanDirs(plansPath) {
|
|
@@ -72494,7 +72662,7 @@ function listPlanDirs(plansPath) {
|
|
|
72494
72662
|
}
|
|
72495
72663
|
function planFileMentionsSession(planDir, sessionId) {
|
|
72496
72664
|
try {
|
|
72497
|
-
const planFile =
|
|
72665
|
+
const planFile = join102(planDir, "plan.md");
|
|
72498
72666
|
if (!existsSync49(planFile))
|
|
72499
72667
|
return false;
|
|
72500
72668
|
const body = readFileSync16(planFile, { encoding: "utf8" });
|
|
@@ -72509,7 +72677,7 @@ function resolveActivePlan(plansPath, sessionId) {
|
|
|
72509
72677
|
if (!sessionId)
|
|
72510
72678
|
return "";
|
|
72511
72679
|
for (const name2 of listPlanDirs(plansPath)) {
|
|
72512
|
-
const dir =
|
|
72680
|
+
const dir = join102(plansPath, name2);
|
|
72513
72681
|
if (name2.includes(sessionId) || planFileMentionsSession(dir, sessionId)) {
|
|
72514
72682
|
return dir;
|
|
72515
72683
|
}
|
|
@@ -72530,7 +72698,7 @@ function resolveSuggestedPlan(plansPath, branch, branchPattern) {
|
|
|
72530
72698
|
return "";
|
|
72531
72699
|
for (const name2 of listPlanDirs(plansPath)) {
|
|
72532
72700
|
if (name2.includes(slug))
|
|
72533
|
-
return
|
|
72701
|
+
return join102(plansPath, name2);
|
|
72534
72702
|
}
|
|
72535
72703
|
return "";
|
|
72536
72704
|
}
|
|
@@ -72562,7 +72730,7 @@ function resolveTimezone() {
|
|
|
72562
72730
|
function deriveTaskListId(sessionId) {
|
|
72563
72731
|
if (!sessionId)
|
|
72564
72732
|
return "";
|
|
72565
|
-
const digest =
|
|
72733
|
+
const digest = createHash13("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
72566
72734
|
return `tkm-tasks-${digest}`;
|
|
72567
72735
|
}
|
|
72568
72736
|
function codingLevelString(level) {
|
|
@@ -72584,11 +72752,11 @@ function buildEnvEntries(params) {
|
|
|
72584
72752
|
const plan = config.plan ?? {};
|
|
72585
72753
|
const locale = config.locale ?? {};
|
|
72586
72754
|
const validation = plan.validation ?? {};
|
|
72587
|
-
const settingsDir =
|
|
72588
|
-
const docsPath =
|
|
72589
|
-
const plansPath =
|
|
72755
|
+
const settingsDir = join103(projectRoot, ".claude");
|
|
72756
|
+
const docsPath = join103(projectRoot, paths.docs ?? "docs");
|
|
72757
|
+
const plansPath = join103(projectRoot, paths.plans ?? "plans");
|
|
72590
72758
|
const reportsDir = plan.reportsDir ?? "reports";
|
|
72591
|
-
const reportsPath =
|
|
72759
|
+
const reportsPath = join103(plansPath, reportsDir);
|
|
72592
72760
|
const namingFormat = plan.namingFormat ?? "";
|
|
72593
72761
|
const activePlan = resolveActivePlan(plansPath, ctx.sessionId);
|
|
72594
72762
|
const suggestedPlan = resolveSuggestedPlan(plansPath, branch, plan.resolution?.branchPattern ?? "");
|
|
@@ -72669,7 +72837,7 @@ function resolveEnvFilePath(settingsDir) {
|
|
|
72669
72837
|
const override = process.env.CLAUDE_ENV_FILE;
|
|
72670
72838
|
if (override && override.trim().length > 0)
|
|
72671
72839
|
return override;
|
|
72672
|
-
return
|
|
72840
|
+
return join104(settingsDir, DEFAULT_ENV_FILE);
|
|
72673
72841
|
}
|
|
72674
72842
|
function persistEntries(envFilePath, entries) {
|
|
72675
72843
|
try {
|
|
@@ -72723,10 +72891,10 @@ var sessionInit = {
|
|
|
72723
72891
|
|
|
72724
72892
|
// src/domains/hooks/handlers/_shared/context-assembler.ts
|
|
72725
72893
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
72726
|
-
import { createHash as
|
|
72894
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
72727
72895
|
import { existsSync as existsSync50, mkdirSync as mkdirSync6, readFileSync as readFileSync17, rmSync as rmSync3, statSync as statSync8, writeFileSync as writeFileSync9 } from "node:fs";
|
|
72728
72896
|
import { homedir as homedir27, platform as platform9, tmpdir as tmpdir4 } from "node:os";
|
|
72729
|
-
import { basename as basename18, join as
|
|
72897
|
+
import { basename as basename18, join as join105, resolve as resolve21 } from "node:path";
|
|
72730
72898
|
var INJECTED_TTL_MS = 12 * 60 * 60 * 1000;
|
|
72731
72899
|
var RESERVATION_TTL_MS = 60 * 1000;
|
|
72732
72900
|
function gitBranch(dir) {
|
|
@@ -72798,17 +72966,17 @@ function buildPromptContext(args) {
|
|
|
72798
72966
|
}
|
|
72799
72967
|
function scopeKey(baseDir) {
|
|
72800
72968
|
const abs = resolve21(baseDir || ".");
|
|
72801
|
-
const hash =
|
|
72969
|
+
const hash = createHash14("sha256").update(abs).digest("hex").slice(0, 16);
|
|
72802
72970
|
const slug = basename18(abs).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 24) || "root";
|
|
72803
72971
|
return `${slug}-${hash}`;
|
|
72804
72972
|
}
|
|
72805
72973
|
function stateDir() {
|
|
72806
|
-
return
|
|
72974
|
+
return join105(tmpdir4(), "takumi-context-throttle");
|
|
72807
72975
|
}
|
|
72808
72976
|
function stateFile(sessionId, scope, transcriptPath) {
|
|
72809
72977
|
const key = `${sessionId}\x00${scope}\x00${transcriptPath ?? ""}`;
|
|
72810
|
-
const hash =
|
|
72811
|
-
return
|
|
72978
|
+
const hash = createHash14("sha256").update(key).digest("hex").slice(0, 32);
|
|
72979
|
+
return join105(stateDir(), `${hash}.json`);
|
|
72812
72980
|
}
|
|
72813
72981
|
function readState(file) {
|
|
72814
72982
|
try {
|
|
@@ -72877,8 +73045,8 @@ function clearPending(sessionId, scope, transcriptPath) {
|
|
|
72877
73045
|
} catch {}
|
|
72878
73046
|
}
|
|
72879
73047
|
function resolveSkillsVenv(_cwd) {
|
|
72880
|
-
const base =
|
|
72881
|
-
const interpreter = platform9() === "win32" ?
|
|
73048
|
+
const base = join105(homedir27(), ".claude", "skills", ".venv");
|
|
73049
|
+
const interpreter = platform9() === "win32" ? join105(base, "Scripts", "python.exe") : join105(base, "bin", "python3");
|
|
72882
73050
|
return existsSync50(interpreter) ? interpreter : null;
|
|
72883
73051
|
}
|
|
72884
73052
|
|
|
@@ -72917,12 +73085,12 @@ var sessionPromptContext = {
|
|
|
72917
73085
|
};
|
|
72918
73086
|
|
|
72919
73087
|
// src/domains/hooks/handlers/session-subagent-init/context-block.ts
|
|
72920
|
-
import { join as
|
|
73088
|
+
import { join as join107 } from "node:path";
|
|
72921
73089
|
|
|
72922
73090
|
// src/domains/hooks/handlers/session-subagent-init/context-sources.ts
|
|
72923
73091
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
72924
73092
|
import { readdirSync as readdirSync8, statSync as statSync9 } from "node:fs";
|
|
72925
|
-
import { isAbsolute as isAbsolute4, join as
|
|
73093
|
+
import { isAbsolute as isAbsolute4, join as join106, resolve as resolve22 } from "node:path";
|
|
72926
73094
|
var MAX_DOCS_FILES = 15;
|
|
72927
73095
|
var MAX_DOCS_SUBDIRS = 5;
|
|
72928
73096
|
function gitFacts(dir) {
|
|
@@ -72959,11 +73127,11 @@ function detectPlan(plansAbs) {
|
|
|
72959
73127
|
for (const e2 of entries) {
|
|
72960
73128
|
if (!e2.isDirectory())
|
|
72961
73129
|
continue;
|
|
72962
|
-
const dir =
|
|
73130
|
+
const dir = join106(plansAbs, e2.name);
|
|
72963
73131
|
try {
|
|
72964
73132
|
if (!readdirSync8(dir).includes("plan.md"))
|
|
72965
73133
|
continue;
|
|
72966
|
-
const mtime = statSync9(
|
|
73134
|
+
const mtime = statSync9(join106(dir, "plan.md")).mtimeMs;
|
|
72967
73135
|
if (!best || mtime > best.mtime)
|
|
72968
73136
|
best = { name: e2.name, mtime };
|
|
72969
73137
|
} catch {}
|
|
@@ -72986,7 +73154,7 @@ function docsCatalogue(docsAbs) {
|
|
|
72986
73154
|
for (const d3 of subdirs.slice(0, MAX_DOCS_SUBDIRS)) {
|
|
72987
73155
|
let count = 0;
|
|
72988
73156
|
try {
|
|
72989
|
-
count = readdirSync8(
|
|
73157
|
+
count = readdirSync8(join106(docsAbs, d3)).length;
|
|
72990
73158
|
} catch {}
|
|
72991
73159
|
lines.push(`- ${d3}/ (${count} entries)`);
|
|
72992
73160
|
}
|
|
@@ -73030,11 +73198,11 @@ function buildSubagentContext(input, ctx) {
|
|
|
73030
73198
|
const agentId = strField(input, "agent_id") || "unknown";
|
|
73031
73199
|
const plansAbs = abs(base, cfg.paths?.plans?.trim() || "plans");
|
|
73032
73200
|
const docsAbs = abs(base, cfg.paths?.docs?.trim() || "docs");
|
|
73033
|
-
const reportsAbs =
|
|
73201
|
+
const reportsAbs = join107(plansAbs, cfg.plan?.reportsDir?.trim() || "reports");
|
|
73034
73202
|
const dateStr = stamp(cfg.plan?.dateFormat?.trim() || "YYMMDD-HHmm", new Date);
|
|
73035
73203
|
const namingFormat = cfg.plan?.namingFormat?.trim() || "{date}-{slug}";
|
|
73036
|
-
const planDir =
|
|
73037
|
-
const reportFile =
|
|
73204
|
+
const planDir = join107(plansAbs, planDirTemplate(namingFormat, dateStr));
|
|
73205
|
+
const reportFile = join107(reportsAbs, `${agentKey}-${dateStr}-{slug}-report.md`);
|
|
73038
73206
|
const activePlan = detectPlan(plansAbs);
|
|
73039
73207
|
const venv = resolveSkillsVenv(effectiveCwd);
|
|
73040
73208
|
const respLang = cfg.locale?.responseLanguage?.trim() || null;
|
|
@@ -73496,7 +73664,7 @@ function buildObservation(args) {
|
|
|
73496
73664
|
}
|
|
73497
73665
|
|
|
73498
73666
|
// src/commands/hooks/lib/hook-exec-dispatch.ts
|
|
73499
|
-
var
|
|
73667
|
+
var DEFAULT_TIMEOUT_MS5 = 2000;
|
|
73500
73668
|
var RECORD_TIMEOUT_MS = 1e4;
|
|
73501
73669
|
async function defaultLoadConfig(cwd2) {
|
|
73502
73670
|
try {
|
|
@@ -73560,7 +73728,7 @@ async function runHookExec(args, deps = {}) {
|
|
|
73560
73728
|
};
|
|
73561
73729
|
const sessionDir = sessionId ? getSessionDirV2({ agent: args.agent, cwd: cwd2, sessionId }) : null;
|
|
73562
73730
|
const result = await runHooks(handlers3, input, ctx, {
|
|
73563
|
-
timeoutMs: args.timeoutMs ??
|
|
73731
|
+
timeoutMs: args.timeoutMs ?? DEFAULT_TIMEOUT_MS5,
|
|
73564
73732
|
timeoutMsByPolicy: { record: args.recordTimeoutMs ?? RECORD_TIMEOUT_MS },
|
|
73565
73733
|
onHandlerComplete: (handlerName, handlerResult) => {
|
|
73566
73734
|
if (!sessionDir)
|
|
@@ -73602,7 +73770,7 @@ async function hookExecCommand(options2) {
|
|
|
73602
73770
|
init_logger();
|
|
73603
73771
|
|
|
73604
73772
|
// src/commands/hooks/event-handlers/_do-put.ts
|
|
73605
|
-
var
|
|
73773
|
+
var DEFAULT_TIMEOUT_MS6 = 5000;
|
|
73606
73774
|
async function handleDoPut() {
|
|
73607
73775
|
let job = null;
|
|
73608
73776
|
try {
|
|
@@ -73617,7 +73785,7 @@ async function handleDoPut() {
|
|
|
73617
73785
|
const result = await authedFetch(job.url, {
|
|
73618
73786
|
method: "PUT",
|
|
73619
73787
|
body: job.payload,
|
|
73620
|
-
timeoutMs: job.timeoutMs > 0 ? job.timeoutMs :
|
|
73788
|
+
timeoutMs: job.timeoutMs > 0 ? job.timeoutMs : DEFAULT_TIMEOUT_MS6
|
|
73621
73789
|
});
|
|
73622
73790
|
hookLog("stop_detached", {
|
|
73623
73791
|
ok: result.ok,
|
|
@@ -74935,21 +75103,21 @@ import { existsSync as existsSync52 } from "node:fs";
|
|
|
74935
75103
|
// src/commands/hooks/lib/settings-path-resolver.ts
|
|
74936
75104
|
import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "node:fs";
|
|
74937
75105
|
import { homedir as homedir28 } from "node:os";
|
|
74938
|
-
import { join as
|
|
75106
|
+
import { join as join108 } from "node:path";
|
|
74939
75107
|
function rawPath(agent, global3) {
|
|
74940
75108
|
const root = global3 ? homedir28() : process.cwd();
|
|
74941
75109
|
if (agent === "claude") {
|
|
74942
|
-
return
|
|
75110
|
+
return join108(root, ".claude", "settings.json");
|
|
74943
75111
|
}
|
|
74944
|
-
return
|
|
75112
|
+
return join108(root, ".codex", "hooks.json");
|
|
74945
75113
|
}
|
|
74946
75114
|
function resolveSettingsPath(agent, options2 = {}) {
|
|
74947
75115
|
const originalPath = rawPath(agent, Boolean(options2.global));
|
|
74948
75116
|
let wasSymlink = false;
|
|
74949
75117
|
let realPath = originalPath;
|
|
74950
75118
|
try {
|
|
74951
|
-
const
|
|
74952
|
-
if (
|
|
75119
|
+
const stat9 = lstatSync3(originalPath);
|
|
75120
|
+
if (stat9.isSymbolicLink()) {
|
|
74953
75121
|
wasSymlink = true;
|
|
74954
75122
|
realPath = realpathSync3(originalPath);
|
|
74955
75123
|
}
|
|
@@ -76642,7 +76810,7 @@ init_logger();
|
|
|
76642
76810
|
init_takumi_constants();
|
|
76643
76811
|
var import_fs_extra31 = __toESM(require_lib(), 1);
|
|
76644
76812
|
var import_semver5 = __toESM(require_semver2(), 1);
|
|
76645
|
-
import { join as
|
|
76813
|
+
import { join as join109 } from "node:path";
|
|
76646
76814
|
function evaluateCliVersionGate(input) {
|
|
76647
76815
|
const min = typeof input.minCliVersion === "string" ? input.minCliVersion.trim() : undefined;
|
|
76648
76816
|
if (!min)
|
|
@@ -76663,7 +76831,7 @@ function evaluateCliVersionGate(input) {
|
|
|
76663
76831
|
}
|
|
76664
76832
|
async function readKitMinCliVersion(extractDir) {
|
|
76665
76833
|
try {
|
|
76666
|
-
const resolved = await findManifestPath(
|
|
76834
|
+
const resolved = await findManifestPath(join109(extractDir, ".claude"));
|
|
76667
76835
|
if (!resolved)
|
|
76668
76836
|
return;
|
|
76669
76837
|
const raw = await import_fs_extra31.readFile(resolved.path, "utf-8");
|
|
@@ -76773,7 +76941,7 @@ async function dispatchInstallers(ctx, targetAgents2, lifecycle) {
|
|
|
76773
76941
|
init_logger();
|
|
76774
76942
|
// src/domains/installation/download-extractor.ts
|
|
76775
76943
|
init_auth_client();
|
|
76776
|
-
import * as
|
|
76944
|
+
import * as fs32 from "node:fs";
|
|
76777
76945
|
import * as path10 from "node:path";
|
|
76778
76946
|
|
|
76779
76947
|
// src/domains/github/auth-prompt.ts
|
|
@@ -76853,9 +77021,9 @@ init_github_client();
|
|
|
76853
77021
|
init_environment();
|
|
76854
77022
|
init_logger();
|
|
76855
77023
|
init_safe_spinner();
|
|
76856
|
-
import { mkdir as mkdir25, stat as
|
|
77024
|
+
import { mkdir as mkdir25, stat as stat11 } from "node:fs/promises";
|
|
76857
77025
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
76858
|
-
import { join as
|
|
77026
|
+
import { join as join115 } from "node:path";
|
|
76859
77027
|
|
|
76860
77028
|
// src/shared/temp-cleanup.ts
|
|
76861
77029
|
init_logger();
|
|
@@ -76874,7 +77042,7 @@ init_logger();
|
|
|
76874
77042
|
init_output_manager();
|
|
76875
77043
|
import { createWriteStream as createWriteStream2, rmSync as rmSync6 } from "node:fs";
|
|
76876
77044
|
import { mkdir as mkdir21 } from "node:fs/promises";
|
|
76877
|
-
import { join as
|
|
77045
|
+
import { join as join110 } from "node:path";
|
|
76878
77046
|
|
|
76879
77047
|
// src/shared/progress-bar.ts
|
|
76880
77048
|
init_output_manager();
|
|
@@ -77044,8 +77212,8 @@ var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
|
|
|
77044
77212
|
function isPathSafe(basePath, targetPath) {
|
|
77045
77213
|
const resolvedBase = resolve23(basePath);
|
|
77046
77214
|
try {
|
|
77047
|
-
const
|
|
77048
|
-
if (
|
|
77215
|
+
const stat9 = lstatSync4(targetPath);
|
|
77216
|
+
if (stat9.isSymbolicLink()) {
|
|
77049
77217
|
const realTarget = realpathSync4(targetPath);
|
|
77050
77218
|
if (!realTarget.startsWith(resolvedBase)) {
|
|
77051
77219
|
return false;
|
|
@@ -77084,7 +77252,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
|
|
|
77084
77252
|
class FileDownloader {
|
|
77085
77253
|
async downloadAsset(asset, destDir) {
|
|
77086
77254
|
try {
|
|
77087
|
-
const destPath =
|
|
77255
|
+
const destPath = join110(destDir, asset.name);
|
|
77088
77256
|
await mkdir21(destDir, { recursive: true });
|
|
77089
77257
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
77090
77258
|
logger.verbose("Download details", {
|
|
@@ -77169,7 +77337,7 @@ class FileDownloader {
|
|
|
77169
77337
|
}
|
|
77170
77338
|
async downloadFile(params) {
|
|
77171
77339
|
const { url, name: name2, size, destDir, token } = params;
|
|
77172
|
-
const destPath =
|
|
77340
|
+
const destPath = join110(destDir, name2);
|
|
77173
77341
|
await mkdir21(destDir, { recursive: true });
|
|
77174
77342
|
output.info(`Downloading ${name2}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
77175
77343
|
const headers = {};
|
|
@@ -77272,7 +77440,7 @@ init_logger();
|
|
|
77272
77440
|
init_types2();
|
|
77273
77441
|
import { constants as constants3 } from "node:fs";
|
|
77274
77442
|
import { access as access3, readdir as readdir25 } from "node:fs/promises";
|
|
77275
|
-
import { join as
|
|
77443
|
+
import { join as join111 } from "node:path";
|
|
77276
77444
|
async function validateExtraction(extractDir) {
|
|
77277
77445
|
try {
|
|
77278
77446
|
const entries = await readdir25(extractDir, { encoding: "utf8" });
|
|
@@ -77284,7 +77452,7 @@ async function validateExtraction(extractDir) {
|
|
|
77284
77452
|
const missingPaths = [];
|
|
77285
77453
|
for (const path10 of criticalPaths) {
|
|
77286
77454
|
try {
|
|
77287
|
-
await access3(
|
|
77455
|
+
await access3(join111(extractDir, path10), constants3.F_OK);
|
|
77288
77456
|
logger.debug(`Found: ${path10}`);
|
|
77289
77457
|
} catch {
|
|
77290
77458
|
logger.warning(`Expected path not found: ${path10}`);
|
|
@@ -77305,8 +77473,8 @@ async function validateExtraction(extractDir) {
|
|
|
77305
77473
|
|
|
77306
77474
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
77307
77475
|
init_logger();
|
|
77308
|
-
import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as
|
|
77309
|
-
import { join as
|
|
77476
|
+
import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat9 } from "node:fs/promises";
|
|
77477
|
+
import { join as join113 } from "node:path";
|
|
77310
77478
|
|
|
77311
77479
|
// node_modules/tar/dist/esm/index.min.js
|
|
77312
77480
|
import Kr from "events";
|
|
@@ -79578,7 +79746,7 @@ var Vn = 512 * 1024;
|
|
|
79578
79746
|
var $n = pr | ur | dr | mr;
|
|
79579
79747
|
var lr = !fr && typeof ar == "number" ? ar | ur | dr | mr : null;
|
|
79580
79748
|
var cs = lr !== null ? () => lr : Kn ? (s3) => s3 < Vn ? $n : "w" : () => "w";
|
|
79581
|
-
var
|
|
79749
|
+
var fs31 = (s3, t, e2) => {
|
|
79582
79750
|
try {
|
|
79583
79751
|
return mi.lchownSync(s3, t, e2);
|
|
79584
79752
|
} catch (i) {
|
|
@@ -79627,7 +79795,7 @@ var ds = (s3, t, e2, i) => {
|
|
|
79627
79795
|
});
|
|
79628
79796
|
};
|
|
79629
79797
|
var qn = (s3, t, e2, i) => {
|
|
79630
|
-
t.isDirectory() && us(Ee.resolve(s3, t.name), e2, i),
|
|
79798
|
+
t.isDirectory() && us(Ee.resolve(s3, t.name), e2, i), fs31(Ee.resolve(s3, t.name), e2, i);
|
|
79631
79799
|
};
|
|
79632
79800
|
var us = (s3, t, e2) => {
|
|
79633
79801
|
let i;
|
|
@@ -79638,12 +79806,12 @@ var us = (s3, t, e2) => {
|
|
|
79638
79806
|
if (n2?.code === "ENOENT")
|
|
79639
79807
|
return;
|
|
79640
79808
|
if (n2?.code === "ENOTDIR" || n2?.code === "ENOTSUP")
|
|
79641
|
-
return
|
|
79809
|
+
return fs31(s3, t, e2);
|
|
79642
79810
|
throw n2;
|
|
79643
79811
|
}
|
|
79644
79812
|
for (let r2 of i)
|
|
79645
79813
|
qn(s3, r2, t, e2);
|
|
79646
|
-
return
|
|
79814
|
+
return fs31(s3, t, e2);
|
|
79647
79815
|
};
|
|
79648
79816
|
var we = class extends Error {
|
|
79649
79817
|
path;
|
|
@@ -80519,7 +80687,7 @@ function decodeFilePath(path10) {
|
|
|
80519
80687
|
init_logger();
|
|
80520
80688
|
init_types2();
|
|
80521
80689
|
import { copyFile as copyFile4, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
|
|
80522
|
-
import { join as
|
|
80690
|
+
import { join as join112, relative as relative16 } from "node:path";
|
|
80523
80691
|
async function withRetry2(fn2, retries = 3) {
|
|
80524
80692
|
for (let i = 0;i < retries; i++) {
|
|
80525
80693
|
try {
|
|
@@ -80541,8 +80709,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
80541
80709
|
await mkdir22(destDir, { recursive: true });
|
|
80542
80710
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
80543
80711
|
for (const entry of entries) {
|
|
80544
|
-
const sourcePath =
|
|
80545
|
-
const destPath =
|
|
80712
|
+
const sourcePath = join112(sourceDir, entry);
|
|
80713
|
+
const destPath = join112(destDir, entry);
|
|
80546
80714
|
const relativePath = relative16(sourceDir, sourcePath);
|
|
80547
80715
|
if (!isPathSafe(destDir, destPath)) {
|
|
80548
80716
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -80569,8 +80737,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
|
80569
80737
|
await mkdir22(destDir, { recursive: true });
|
|
80570
80738
|
const entries = await readdir26(sourceDir, { encoding: "utf8" });
|
|
80571
80739
|
for (const entry of entries) {
|
|
80572
|
-
const sourcePath =
|
|
80573
|
-
const destPath =
|
|
80740
|
+
const sourcePath = join112(sourceDir, entry);
|
|
80741
|
+
const destPath = join112(destDir, entry);
|
|
80574
80742
|
const relativePath = relative16(sourceDir, sourcePath);
|
|
80575
80743
|
if (!isPathSafe(destDir, destPath)) {
|
|
80576
80744
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -80625,8 +80793,8 @@ class TarExtractor {
|
|
|
80625
80793
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
80626
80794
|
if (entries.length === 1) {
|
|
80627
80795
|
const rootEntry = entries[0];
|
|
80628
|
-
const rootPath =
|
|
80629
|
-
const rootStat = await
|
|
80796
|
+
const rootPath = join113(tempExtractDir, rootEntry);
|
|
80797
|
+
const rootStat = await stat9(rootPath);
|
|
80630
80798
|
if (rootStat.isDirectory()) {
|
|
80631
80799
|
const rootContents = await readdir27(rootPath, { encoding: "utf8" });
|
|
80632
80800
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
@@ -80641,7 +80809,7 @@ class TarExtractor {
|
|
|
80641
80809
|
}
|
|
80642
80810
|
} else {
|
|
80643
80811
|
await mkdir23(destDir, { recursive: true });
|
|
80644
|
-
await copyFile5(rootPath,
|
|
80812
|
+
await copyFile5(rootPath, join113(destDir, rootEntry));
|
|
80645
80813
|
}
|
|
80646
80814
|
} else {
|
|
80647
80815
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -80661,8 +80829,8 @@ class TarExtractor {
|
|
|
80661
80829
|
// src/domains/installation/extraction/zip-extractor.ts
|
|
80662
80830
|
init_logger();
|
|
80663
80831
|
import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
80664
|
-
import { chmod as chmod3, copyFile as copyFile6, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as
|
|
80665
|
-
import { dirname as dirname31, join as
|
|
80832
|
+
import { chmod as chmod3, copyFile as copyFile6, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as stat10 } from "node:fs/promises";
|
|
80833
|
+
import { dirname as dirname31, join as join114, resolve as resolve24 } from "node:path";
|
|
80666
80834
|
import { pipeline } from "node:stream/promises";
|
|
80667
80835
|
import yauzl from "yauzl-promise";
|
|
80668
80836
|
class ZipExtractor {
|
|
@@ -80676,8 +80844,8 @@ class ZipExtractor {
|
|
|
80676
80844
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
80677
80845
|
if (entries.length === 1) {
|
|
80678
80846
|
const rootEntry = entries[0];
|
|
80679
|
-
const rootPath =
|
|
80680
|
-
const rootStat = await
|
|
80847
|
+
const rootPath = join114(tempExtractDir, rootEntry);
|
|
80848
|
+
const rootStat = await stat10(rootPath);
|
|
80681
80849
|
if (rootStat.isDirectory()) {
|
|
80682
80850
|
const rootContents = await readdir28(rootPath, { encoding: "utf8" });
|
|
80683
80851
|
logger.debug(`Root directory '${rootEntry}' contains: ${rootContents.join(", ")}`);
|
|
@@ -80692,7 +80860,7 @@ class ZipExtractor {
|
|
|
80692
80860
|
}
|
|
80693
80861
|
} else {
|
|
80694
80862
|
await mkdir24(destDir, { recursive: true });
|
|
80695
|
-
await copyFile6(rootPath,
|
|
80863
|
+
await copyFile6(rootPath, join114(destDir, rootEntry));
|
|
80696
80864
|
}
|
|
80697
80865
|
} else {
|
|
80698
80866
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -80782,7 +80950,7 @@ class DownloadManager {
|
|
|
80782
80950
|
return this.fileDownloader.downloadFile(params);
|
|
80783
80951
|
}
|
|
80784
80952
|
async extractArchive(archivePath, destDir, archiveType) {
|
|
80785
|
-
const archiveStats = await
|
|
80953
|
+
const archiveStats = await stat11(archivePath);
|
|
80786
80954
|
if (archiveStats.size > MAX_ARCHIVE_SIZE) {
|
|
80787
80955
|
throw new ExtractionError(`Archive exceeds ${formatBytes(MAX_ARCHIVE_SIZE)} limit: ${formatBytes(archiveStats.size)}`);
|
|
80788
80956
|
}
|
|
@@ -80821,7 +80989,7 @@ class DownloadManager {
|
|
|
80821
80989
|
async createTempDir() {
|
|
80822
80990
|
const timestamp = Date.now();
|
|
80823
80991
|
const counter = DownloadManager.tempDirCounter++;
|
|
80824
|
-
const primaryTempDir =
|
|
80992
|
+
const primaryTempDir = join115(tmpdir5(), `takumi-${timestamp}-${counter}`);
|
|
80825
80993
|
try {
|
|
80826
80994
|
await mkdir25(primaryTempDir, { recursive: true });
|
|
80827
80995
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -80838,7 +81006,7 @@ Solutions:
|
|
|
80838
81006
|
2. Set HOME environment variable
|
|
80839
81007
|
3. Try running from a different directory`);
|
|
80840
81008
|
}
|
|
80841
|
-
const fallbackTempDir =
|
|
81009
|
+
const fallbackTempDir = join115(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
|
|
80842
81010
|
try {
|
|
80843
81011
|
await mkdir25(fallbackTempDir, { recursive: true });
|
|
80844
81012
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -80883,8 +81051,8 @@ function buildReleaseAllowlist(layout) {
|
|
|
80883
81051
|
async function ensureLayoutSourceDir(projectRoot, layout, strict) {
|
|
80884
81052
|
const sourceDir = path10.join(projectRoot, layout.sourceDir);
|
|
80885
81053
|
try {
|
|
80886
|
-
const
|
|
80887
|
-
if (!
|
|
81054
|
+
const stat12 = await fs32.promises.stat(sourceDir);
|
|
81055
|
+
if (!stat12.isDirectory()) {
|
|
80888
81056
|
throw new Error(`Expected source directory "${layout.sourceDir}" exists but is not a directory.`);
|
|
80889
81057
|
}
|
|
80890
81058
|
return sourceDir;
|
|
@@ -80908,8 +81076,8 @@ async function materializeRuntimeLayoutInPlace(projectRoot, layout) {
|
|
|
80908
81076
|
}
|
|
80909
81077
|
const sourceDir = path10.join(projectRoot, layout.sourceDir);
|
|
80910
81078
|
const runtimeDir = path10.join(projectRoot, layout.runtimeDir);
|
|
80911
|
-
await
|
|
80912
|
-
await
|
|
81079
|
+
await fs32.promises.rm(runtimeDir, { recursive: true, force: true });
|
|
81080
|
+
await fs32.promises.rename(sourceDir, runtimeDir);
|
|
80913
81081
|
}
|
|
80914
81082
|
async function stageLocalKitPathForRuntimeLayout(kitRoot, layout) {
|
|
80915
81083
|
const sourceDir = await ensureLayoutSourceDir(kitRoot, layout, false);
|
|
@@ -80919,20 +81087,20 @@ async function stageLocalKitPathForRuntimeLayout(kitRoot, layout) {
|
|
|
80919
81087
|
const downloadManager = new DownloadManager;
|
|
80920
81088
|
const tempDir = await downloadManager.createTempDir();
|
|
80921
81089
|
const extractDir = `${tempDir}/extracted`;
|
|
80922
|
-
await
|
|
80923
|
-
const entries = await
|
|
81090
|
+
await fs32.promises.mkdir(extractDir, { recursive: true });
|
|
81091
|
+
const entries = await fs32.promises.readdir(kitRoot);
|
|
80924
81092
|
const allowlist = buildReleaseAllowlist(layout);
|
|
80925
81093
|
for (const entry of entries) {
|
|
80926
81094
|
if (!allowlist.includes(entry) || entry === layout.sourceDir) {
|
|
80927
81095
|
continue;
|
|
80928
81096
|
}
|
|
80929
|
-
await
|
|
81097
|
+
await fs32.promises.cp(path10.join(kitRoot, entry), path10.join(extractDir, entry), {
|
|
80930
81098
|
recursive: true
|
|
80931
81099
|
});
|
|
80932
81100
|
}
|
|
80933
81101
|
const runtimeDir = path10.join(extractDir, layout.runtimeDir);
|
|
80934
|
-
await
|
|
80935
|
-
await
|
|
81102
|
+
await fs32.promises.mkdir(path10.dirname(runtimeDir), { recursive: true });
|
|
81103
|
+
await fs32.promises.cp(sourceDir, runtimeDir, { recursive: true });
|
|
80936
81104
|
logger.verbose("Staged local kit path with runtime layout", {
|
|
80937
81105
|
kitRoot,
|
|
80938
81106
|
extractDir,
|
|
@@ -80961,9 +81129,9 @@ function resolveRepoRootForKit(kitRoot) {
|
|
|
80961
81129
|
try {
|
|
80962
81130
|
const parent = path10.dirname(kitRoot);
|
|
80963
81131
|
const parentPackageJson = path10.join(parent, "package.json");
|
|
80964
|
-
if (!
|
|
81132
|
+
if (!fs32.existsSync(parentPackageJson))
|
|
80965
81133
|
return kitRoot;
|
|
80966
|
-
const pkg = JSON.parse(
|
|
81134
|
+
const pkg = JSON.parse(fs32.readFileSync(parentPackageJson, "utf-8"));
|
|
80967
81135
|
const kitCfg = pkg.takumi;
|
|
80968
81136
|
const sourceDir = kitCfg?.sourceDir;
|
|
80969
81137
|
if (typeof sourceDir === "string" && path10.resolve(parent, sourceDir) === path10.resolve(kitRoot)) {
|
|
@@ -80977,9 +81145,9 @@ async function stageMonorepoForInstallation(kitRoot) {
|
|
|
80977
81145
|
const tempDir = await downloadManager.createTempDir();
|
|
80978
81146
|
const extractDir = `${tempDir}/extracted`;
|
|
80979
81147
|
const claudeDir = path10.join(extractDir, ".claude");
|
|
80980
|
-
await
|
|
81148
|
+
await fs32.promises.mkdir(claudeDir, { recursive: true });
|
|
80981
81149
|
const repoRoot = resolveRepoRootForKit(kitRoot);
|
|
80982
|
-
const kitEntries = await
|
|
81150
|
+
const kitEntries = await fs32.promises.readdir(kitRoot);
|
|
80983
81151
|
const skipLegacyManifest = kitEntries.includes(MANIFEST_FILENAME) && kitEntries.includes(LEGACY_MANIFEST_FILENAME);
|
|
80984
81152
|
for (const entry of kitEntries) {
|
|
80985
81153
|
if (!MONOREPO_KIT_CONTENT.includes(entry))
|
|
@@ -80987,14 +81155,14 @@ async function stageMonorepoForInstallation(kitRoot) {
|
|
|
80987
81155
|
if (skipLegacyManifest && entry === LEGACY_MANIFEST_FILENAME)
|
|
80988
81156
|
continue;
|
|
80989
81157
|
const srcPath = path10.join(kitRoot, entry);
|
|
80990
|
-
await
|
|
81158
|
+
await fs32.promises.cp(srcPath, path10.join(claudeDir, entry), { recursive: true });
|
|
80991
81159
|
}
|
|
80992
|
-
const repoEntries = repoRoot === kitRoot ? kitEntries : await
|
|
81160
|
+
const repoEntries = repoRoot === kitRoot ? kitEntries : await fs32.promises.readdir(repoRoot);
|
|
80993
81161
|
for (const entry of repoEntries) {
|
|
80994
81162
|
if (!RELEASE_ROOT_ALLOWLIST.includes(entry))
|
|
80995
81163
|
continue;
|
|
80996
81164
|
const srcPath = path10.join(repoRoot, entry);
|
|
80997
|
-
await
|
|
81165
|
+
await fs32.promises.cp(srcPath, path10.join(extractDir, entry), { recursive: true });
|
|
80998
81166
|
}
|
|
80999
81167
|
logger.verbose("Staged monorepo for installation", {
|
|
81000
81168
|
kitRoot,
|
|
@@ -81008,13 +81176,13 @@ async function stageMonorepoForInstallation(kitRoot) {
|
|
|
81008
81176
|
async function normalizeFullRepoExtract(dir, strict) {
|
|
81009
81177
|
const layout = resolveKitLayout(dir);
|
|
81010
81178
|
await ensureLayoutSourceDir(dir, layout, strict);
|
|
81011
|
-
const entries = await
|
|
81179
|
+
const entries = await fs32.promises.readdir(dir);
|
|
81012
81180
|
const releaseAllowlist = buildReleaseAllowlist(layout);
|
|
81013
81181
|
let removedCount = 0;
|
|
81014
81182
|
for (const entry of entries) {
|
|
81015
81183
|
if (!releaseAllowlist.includes(entry)) {
|
|
81016
81184
|
const fullPath = path10.join(dir, entry);
|
|
81017
|
-
await
|
|
81185
|
+
await fs32.promises.rm(fullPath, { recursive: true, force: true });
|
|
81018
81186
|
removedCount++;
|
|
81019
81187
|
}
|
|
81020
81188
|
}
|
|
@@ -81129,8 +81297,8 @@ async function useLocalKitPath(kitPath, isMonorepo) {
|
|
|
81129
81297
|
output.section("Using local kit");
|
|
81130
81298
|
const absolutePath = path10.resolve(kitPath);
|
|
81131
81299
|
try {
|
|
81132
|
-
const
|
|
81133
|
-
if (!
|
|
81300
|
+
const stat12 = await fs32.promises.stat(absolutePath);
|
|
81301
|
+
if (!stat12.isDirectory()) {
|
|
81134
81302
|
throw new Error(`--kit-path must point to a directory, not a file.
|
|
81135
81303
|
|
|
81136
81304
|
Provided path: ${absolutePath}
|
|
@@ -81168,8 +81336,8 @@ Please verify the path exists and is accessible.`);
|
|
|
81168
81336
|
}
|
|
81169
81337
|
const claudeDir = path10.join(absolutePath, DEFAULT_KIT_LAYOUT.runtimeDir);
|
|
81170
81338
|
try {
|
|
81171
|
-
const
|
|
81172
|
-
if (!
|
|
81339
|
+
const stat12 = await fs32.promises.stat(claudeDir);
|
|
81340
|
+
if (!stat12.isDirectory()) {
|
|
81173
81341
|
logger.warning(`Warning: ${claudeDir} exists but is not a directory.
|
|
81174
81342
|
This may not be a valid Takumi installation.`);
|
|
81175
81343
|
}
|
|
@@ -81203,15 +81371,15 @@ async function extractLocalArchive(archivePath, exclude) {
|
|
|
81203
81371
|
const absolutePath = path10.resolve(archivePath);
|
|
81204
81372
|
validateArchiveFormat(absolutePath);
|
|
81205
81373
|
try {
|
|
81206
|
-
const
|
|
81207
|
-
if (!
|
|
81374
|
+
const stat12 = await fs32.promises.stat(absolutePath);
|
|
81375
|
+
if (!stat12.isFile()) {
|
|
81208
81376
|
throw new Error(`--archive must point to a file, not a directory.
|
|
81209
81377
|
|
|
81210
81378
|
Provided path: ${absolutePath}
|
|
81211
81379
|
|
|
81212
81380
|
If you meant to use an extracted kit directory, use --kit-path instead.`);
|
|
81213
81381
|
}
|
|
81214
|
-
if (
|
|
81382
|
+
if (stat12.size === 0) {
|
|
81215
81383
|
throw new Error(`Archive file is empty: ${absolutePath}
|
|
81216
81384
|
|
|
81217
81385
|
The file exists but contains no data. Please verify the archive is not corrupted.`);
|
|
@@ -81336,7 +81504,7 @@ async function downloadViaWorker(release, kit, isNonInteractive2) {
|
|
|
81336
81504
|
const tempDir = await downloadManager.createTempDir();
|
|
81337
81505
|
const archivePath = path10.join(tempDir, assetName);
|
|
81338
81506
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
81339
|
-
await
|
|
81507
|
+
await fs32.promises.writeFile(archivePath, buf);
|
|
81340
81508
|
const extractDir = `${tempDir}/extracted`;
|
|
81341
81509
|
logger.verbose("Extraction", { archivePath, extractDir });
|
|
81342
81510
|
await downloadManager.extractArchive(archivePath, extractDir);
|
|
@@ -81545,7 +81713,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
|
|
|
81545
81713
|
}
|
|
81546
81714
|
// src/commands/init/phases/selection-handler.ts
|
|
81547
81715
|
import { mkdir as mkdir26 } from "node:fs/promises";
|
|
81548
|
-
import { join as
|
|
81716
|
+
import { join as join119, resolve as resolve28 } from "node:path";
|
|
81549
81717
|
|
|
81550
81718
|
// src/commands/shared/agent-selector.ts
|
|
81551
81719
|
init_registry();
|
|
@@ -81699,7 +81867,7 @@ init_safe_spinner();
|
|
|
81699
81867
|
init_takumi_constants();
|
|
81700
81868
|
var import_fs_extra32 = __toESM(require_lib(), 1);
|
|
81701
81869
|
import { existsSync as existsSync57, readdirSync as readdirSync9, rmSync as rmSync7, rmdirSync as rmdirSync2, unlinkSync as unlinkSync6 } from "node:fs";
|
|
81702
|
-
import { dirname as dirname34, join as
|
|
81870
|
+
import { dirname as dirname34, join as join118, resolve as resolve27 } from "node:path";
|
|
81703
81871
|
var TAKUMI_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
|
|
81704
81872
|
async function analyzeFreshInstallation(claudeDir) {
|
|
81705
81873
|
const metadata = await readManifest(claudeDir);
|
|
@@ -81769,7 +81937,7 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
|
|
|
81769
81937
|
const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
|
|
81770
81938
|
const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
|
|
81771
81939
|
for (const file of filesToRemove) {
|
|
81772
|
-
const fullPath =
|
|
81940
|
+
const fullPath = join118(claudeDir, file.path);
|
|
81773
81941
|
try {
|
|
81774
81942
|
if (existsSync57(fullPath)) {
|
|
81775
81943
|
unlinkSync6(fullPath);
|
|
@@ -81843,7 +82011,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
|
|
|
81843
82011
|
const removedFiles = [];
|
|
81844
82012
|
let removedDirCount = 0;
|
|
81845
82013
|
for (const subdir of TAKUMI_SUBDIRECTORIES) {
|
|
81846
|
-
const subdirPath =
|
|
82014
|
+
const subdirPath = join118(claudeDir, subdir);
|
|
81847
82015
|
if (await import_fs_extra32.pathExists(subdirPath)) {
|
|
81848
82016
|
rmSync7(subdirPath, { recursive: true, force: true });
|
|
81849
82017
|
removedDirCount++;
|
|
@@ -82068,7 +82236,7 @@ async function handleSelection(ctx) {
|
|
|
82068
82236
|
}
|
|
82069
82237
|
if (!ctx.options.fresh) {
|
|
82070
82238
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
82071
|
-
const claudeDir = prefix ?
|
|
82239
|
+
const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
|
|
82072
82240
|
try {
|
|
82073
82241
|
const existingMetadata = await readManifest(claudeDir);
|
|
82074
82242
|
if (existingMetadata?.kits) {
|
|
@@ -82101,7 +82269,7 @@ async function handleSelection(ctx) {
|
|
|
82101
82269
|
}
|
|
82102
82270
|
if (ctx.options.fresh) {
|
|
82103
82271
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
82104
|
-
const claudeDir = prefix ?
|
|
82272
|
+
const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
|
|
82105
82273
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
82106
82274
|
if (!canProceed) {
|
|
82107
82275
|
return { ...ctx, cancelled: true };
|
|
@@ -82121,7 +82289,7 @@ async function handleSelection(ctx) {
|
|
|
82121
82289
|
let currentVersion = null;
|
|
82122
82290
|
try {
|
|
82123
82291
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
82124
|
-
const claudeDir = prefix ?
|
|
82292
|
+
const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
|
|
82125
82293
|
const existingMetadata = await readManifest(claudeDir);
|
|
82126
82294
|
currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
|
|
82127
82295
|
if (currentVersion) {
|
|
@@ -82209,7 +82377,7 @@ async function handleSelection(ctx) {
|
|
|
82209
82377
|
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
|
|
82210
82378
|
try {
|
|
82211
82379
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
82212
|
-
const claudeDir = prefix ?
|
|
82380
|
+
const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
|
|
82213
82381
|
const existingMetadata = await readManifest(claudeDir);
|
|
82214
82382
|
const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
|
|
82215
82383
|
if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
|
|
@@ -82232,7 +82400,7 @@ async function handleSelection(ctx) {
|
|
|
82232
82400
|
let currentSecondaryVersion = null;
|
|
82233
82401
|
try {
|
|
82234
82402
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
82235
|
-
const claudeDir = prefix ?
|
|
82403
|
+
const claudeDir = prefix ? join119(resolvedDir, prefix) : resolvedDir;
|
|
82236
82404
|
const existingMetadata = await readManifest(claudeDir);
|
|
82237
82405
|
currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
|
|
82238
82406
|
} catch {}
|
|
@@ -82315,13 +82483,13 @@ function resolveGlobalTargetDir(targetAgents2) {
|
|
|
82315
82483
|
}
|
|
82316
82484
|
// src/commands/init/phases/sync-handler.ts
|
|
82317
82485
|
init_paths();
|
|
82318
|
-
import { copyFile as copyFile7, mkdir as mkdir28, open as
|
|
82319
|
-
import { dirname as dirname35, join as
|
|
82486
|
+
import { copyFile as copyFile7, mkdir as mkdir28, open as open3, readFile as readFile41, rename as rename7, stat as stat13, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
|
|
82487
|
+
import { dirname as dirname35, join as join122, resolve as resolve29 } from "node:path";
|
|
82320
82488
|
|
|
82321
82489
|
// src/domains/sync/config-version-checker.ts
|
|
82322
82490
|
init_auth_client();
|
|
82323
82491
|
import { mkdir as mkdir27, readFile as readFile39, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
|
|
82324
|
-
import { join as
|
|
82492
|
+
import { join as join120 } from "node:path";
|
|
82325
82493
|
init_version_utils();
|
|
82326
82494
|
init_logger();
|
|
82327
82495
|
init_path_resolver();
|
|
@@ -82357,7 +82525,7 @@ var CACHE_FILENAME = "config-update-cache.json";
|
|
|
82357
82525
|
class ConfigVersionChecker {
|
|
82358
82526
|
static getCacheFilePath(kitType, global3) {
|
|
82359
82527
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
82360
|
-
return
|
|
82528
|
+
return join120(cacheDir, `${kitType}-${CACHE_FILENAME}`);
|
|
82361
82529
|
}
|
|
82362
82530
|
static async loadCache(kitType, global3) {
|
|
82363
82531
|
try {
|
|
@@ -82476,8 +82644,8 @@ class ConfigVersionChecker {
|
|
|
82476
82644
|
// src/domains/sync/sync-engine.ts
|
|
82477
82645
|
init_ownership_checker();
|
|
82478
82646
|
init_logger();
|
|
82479
|
-
import { lstat as lstat7, readFile as readFile40, readlink, realpath as realpath3, stat as
|
|
82480
|
-
import { isAbsolute as isAbsolute5, join as
|
|
82647
|
+
import { lstat as lstat7, readFile as readFile40, readlink, realpath as realpath3, stat as stat12 } from "node:fs/promises";
|
|
82648
|
+
import { isAbsolute as isAbsolute5, join as join121, normalize as normalize9, relative as relative17 } from "node:path";
|
|
82481
82649
|
var MAX_SYNC_FILE_SIZE = 10 * 1024 * 1024;
|
|
82482
82650
|
var MAX_SYMLINK_DEPTH = 20;
|
|
82483
82651
|
async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
|
|
@@ -82489,7 +82657,7 @@ async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEP
|
|
|
82489
82657
|
if (!stats.isSymbolicLink())
|
|
82490
82658
|
break;
|
|
82491
82659
|
const target = await readlink(current);
|
|
82492
|
-
const resolvedTarget = isAbsolute5(target) ? target :
|
|
82660
|
+
const resolvedTarget = isAbsolute5(target) ? target : join121(current, "..", target);
|
|
82493
82661
|
const normalizedTarget = normalize9(resolvedTarget);
|
|
82494
82662
|
const rel = relative17(basePath, normalizedTarget);
|
|
82495
82663
|
if (rel.startsWith("..") || isAbsolute5(rel)) {
|
|
@@ -82525,7 +82693,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
82525
82693
|
if (normalized.startsWith("..") || normalized.includes("/../")) {
|
|
82526
82694
|
throw new Error(`Path traversal not allowed: ${filePath}`);
|
|
82527
82695
|
}
|
|
82528
|
-
const fullPath =
|
|
82696
|
+
const fullPath = join121(basePath, normalized);
|
|
82529
82697
|
const rel = relative17(basePath, fullPath);
|
|
82530
82698
|
if (rel.startsWith("..") || isAbsolute5(rel)) {
|
|
82531
82699
|
throw new Error(`Path escapes base directory: ${filePath}`);
|
|
@@ -82540,7 +82708,7 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
82540
82708
|
}
|
|
82541
82709
|
} catch (error) {
|
|
82542
82710
|
if (error.code === "ENOENT") {
|
|
82543
|
-
const parentPath =
|
|
82711
|
+
const parentPath = join121(fullPath, "..");
|
|
82544
82712
|
try {
|
|
82545
82713
|
const resolvedBase = await realpath3(basePath);
|
|
82546
82714
|
const resolvedParent = await realpath3(parentPath);
|
|
@@ -82577,7 +82745,7 @@ class SyncEngine {
|
|
|
82577
82745
|
continue;
|
|
82578
82746
|
}
|
|
82579
82747
|
try {
|
|
82580
|
-
await
|
|
82748
|
+
await stat12(upstreamPath);
|
|
82581
82749
|
} catch {
|
|
82582
82750
|
plan.skipped.push(file);
|
|
82583
82751
|
continue;
|
|
@@ -82591,7 +82759,7 @@ class SyncEngine {
|
|
|
82591
82759
|
continue;
|
|
82592
82760
|
}
|
|
82593
82761
|
try {
|
|
82594
|
-
await
|
|
82762
|
+
await stat12(localPath);
|
|
82595
82763
|
} catch {
|
|
82596
82764
|
plan.autoUpdate.push(file);
|
|
82597
82765
|
continue;
|
|
@@ -83031,13 +83199,13 @@ function getLockTimeout() {
|
|
|
83031
83199
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
83032
83200
|
async function acquireSyncLock(global3) {
|
|
83033
83201
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
83034
|
-
const lockPath2 =
|
|
83202
|
+
const lockPath2 = join122(cacheDir, ".sync-lock");
|
|
83035
83203
|
const startTime = Date.now();
|
|
83036
83204
|
const lockTimeout = getLockTimeout();
|
|
83037
83205
|
await mkdir28(dirname35(lockPath2), { recursive: true });
|
|
83038
83206
|
while (Date.now() - startTime < lockTimeout) {
|
|
83039
83207
|
try {
|
|
83040
|
-
const handle = await
|
|
83208
|
+
const handle = await open3(lockPath2, "wx");
|
|
83041
83209
|
return async () => {
|
|
83042
83210
|
await handle.close();
|
|
83043
83211
|
await unlink11(lockPath2).catch(() => {});
|
|
@@ -83045,7 +83213,7 @@ async function acquireSyncLock(global3) {
|
|
|
83045
83213
|
} catch (err) {
|
|
83046
83214
|
if (err.code === "EEXIST") {
|
|
83047
83215
|
try {
|
|
83048
|
-
const lockStat = await
|
|
83216
|
+
const lockStat = await stat13(lockPath2);
|
|
83049
83217
|
const lockAge = Math.abs(Date.now() - lockStat.mtimeMs);
|
|
83050
83218
|
if (lockAge > STALE_LOCK_THRESHOLD_MS) {
|
|
83051
83219
|
logger.warning(`Removing stale sync lock (age: ${Math.round(lockAge / 1000)}s)`);
|
|
@@ -83112,7 +83280,7 @@ async function executeSyncMerge(ctx) {
|
|
|
83112
83280
|
try {
|
|
83113
83281
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
83114
83282
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
83115
|
-
const targetDir =
|
|
83283
|
+
const targetDir = join122(targetPath, "..");
|
|
83116
83284
|
try {
|
|
83117
83285
|
await mkdir28(targetDir, { recursive: true });
|
|
83118
83286
|
} catch (mkdirError) {
|
|
@@ -83283,7 +83451,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
83283
83451
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
83284
83452
|
if (await import_fs_extra34.pathExists(sourcePath)) {
|
|
83285
83453
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
83286
|
-
const targetDir =
|
|
83454
|
+
const targetDir = join122(targetPath, "..");
|
|
83287
83455
|
await mkdir28(targetDir, { recursive: true });
|
|
83288
83456
|
await copyFile7(sourcePath, targetPath);
|
|
83289
83457
|
}
|
|
@@ -83309,38 +83477,38 @@ init_logger();
|
|
|
83309
83477
|
init_types2();
|
|
83310
83478
|
var import_fs_extra35 = __toESM(require_lib(), 1);
|
|
83311
83479
|
import { rename as rename8, rm as rm9 } from "node:fs/promises";
|
|
83312
|
-
import { join as
|
|
83480
|
+
import { join as join123, relative as relative18 } from "node:path";
|
|
83313
83481
|
async function collectDirsToRename(extractDir, folders) {
|
|
83314
83482
|
const dirsToRename = [];
|
|
83315
83483
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
83316
|
-
const docsPath =
|
|
83484
|
+
const docsPath = join123(extractDir, DEFAULT_FOLDERS.docs);
|
|
83317
83485
|
if (await import_fs_extra35.pathExists(docsPath)) {
|
|
83318
83486
|
dirsToRename.push({
|
|
83319
83487
|
from: docsPath,
|
|
83320
|
-
to:
|
|
83488
|
+
to: join123(extractDir, folders.docs)
|
|
83321
83489
|
});
|
|
83322
83490
|
}
|
|
83323
|
-
const claudeDocsPath =
|
|
83491
|
+
const claudeDocsPath = join123(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
83324
83492
|
if (await import_fs_extra35.pathExists(claudeDocsPath)) {
|
|
83325
83493
|
dirsToRename.push({
|
|
83326
83494
|
from: claudeDocsPath,
|
|
83327
|
-
to:
|
|
83495
|
+
to: join123(extractDir, ".claude", folders.docs)
|
|
83328
83496
|
});
|
|
83329
83497
|
}
|
|
83330
83498
|
}
|
|
83331
83499
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
83332
|
-
const plansPath =
|
|
83500
|
+
const plansPath = join123(extractDir, DEFAULT_FOLDERS.plans);
|
|
83333
83501
|
if (await import_fs_extra35.pathExists(plansPath)) {
|
|
83334
83502
|
dirsToRename.push({
|
|
83335
83503
|
from: plansPath,
|
|
83336
|
-
to:
|
|
83504
|
+
to: join123(extractDir, folders.plans)
|
|
83337
83505
|
});
|
|
83338
83506
|
}
|
|
83339
|
-
const claudePlansPath =
|
|
83507
|
+
const claudePlansPath = join123(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
83340
83508
|
if (await import_fs_extra35.pathExists(claudePlansPath)) {
|
|
83341
83509
|
dirsToRename.push({
|
|
83342
83510
|
from: claudePlansPath,
|
|
83343
|
-
to:
|
|
83511
|
+
to: join123(extractDir, ".claude", folders.plans)
|
|
83344
83512
|
});
|
|
83345
83513
|
}
|
|
83346
83514
|
}
|
|
@@ -83381,7 +83549,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
83381
83549
|
init_logger();
|
|
83382
83550
|
init_types2();
|
|
83383
83551
|
import { readFile as readFile42, readdir as readdir29, writeFile as writeFile29 } from "node:fs/promises";
|
|
83384
|
-
import { join as
|
|
83552
|
+
import { join as join124, relative as relative19 } from "node:path";
|
|
83385
83553
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
83386
83554
|
".md",
|
|
83387
83555
|
".txt",
|
|
@@ -83434,7 +83602,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
|
|
|
83434
83602
|
let replacementsCount = 0;
|
|
83435
83603
|
const entries = await readdir29(dir, { withFileTypes: true });
|
|
83436
83604
|
for (const entry of entries) {
|
|
83437
|
-
const fullPath =
|
|
83605
|
+
const fullPath = join124(dir, entry.name);
|
|
83438
83606
|
if (entry.isDirectory()) {
|
|
83439
83607
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
83440
83608
|
continue;
|
|
@@ -83571,7 +83739,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
83571
83739
|
init_logger();
|
|
83572
83740
|
import { readFile as readFile43, readdir as readdir30, writeFile as writeFile30 } from "node:fs/promises";
|
|
83573
83741
|
import { platform as platform11 } from "node:os";
|
|
83574
|
-
import { extname as extname7, join as
|
|
83742
|
+
import { extname as extname7, join as join125 } from "node:path";
|
|
83575
83743
|
var IS_WINDOWS3 = platform11() === "win32";
|
|
83576
83744
|
var HOME_PREFIX = "$HOME";
|
|
83577
83745
|
function getHomeDirPrefix() {
|
|
@@ -83671,7 +83839,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
83671
83839
|
async function processDirectory2(dir) {
|
|
83672
83840
|
const entries = await readdir30(dir, { withFileTypes: true });
|
|
83673
83841
|
for (const entry of entries) {
|
|
83674
|
-
const fullPath =
|
|
83842
|
+
const fullPath = join125(dir, entry.name);
|
|
83675
83843
|
if (entry.isDirectory()) {
|
|
83676
83844
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
83677
83845
|
continue;
|
|
@@ -83957,11 +84125,11 @@ async function initCommand(options2) {
|
|
|
83957
84125
|
// src/commands/plan/plan-command.ts
|
|
83958
84126
|
init_output_manager();
|
|
83959
84127
|
import { existsSync as existsSync62, statSync as statSync11 } from "node:fs";
|
|
83960
|
-
import { dirname as dirname41, join as
|
|
84128
|
+
import { dirname as dirname41, join as join129, parse as parse4, resolve as resolve33 } from "node:path";
|
|
83961
84129
|
|
|
83962
84130
|
// src/commands/plan/plan-read-handlers.ts
|
|
83963
84131
|
import { existsSync as existsSync61, statSync as statSync10 } from "node:fs";
|
|
83964
|
-
import { basename as basename21, dirname as dirname40, join as
|
|
84132
|
+
import { basename as basename21, dirname as dirname40, join as join128, relative as relative20, resolve as resolve31 } from "node:path";
|
|
83965
84133
|
|
|
83966
84134
|
// src/domains/plan-parser/index.ts
|
|
83967
84135
|
import { dirname as dirname39 } from "node:path";
|
|
@@ -84342,12 +84510,12 @@ function parsePlanFile(planFilePath, options2) {
|
|
|
84342
84510
|
}
|
|
84343
84511
|
// src/domains/plan-parser/plan-scanner.ts
|
|
84344
84512
|
import { existsSync as existsSync58, readdirSync as readdirSync10 } from "node:fs";
|
|
84345
|
-
import { join as
|
|
84513
|
+
import { join as join126 } from "node:path";
|
|
84346
84514
|
function scanPlanDir(dir) {
|
|
84347
84515
|
if (!existsSync58(dir))
|
|
84348
84516
|
return [];
|
|
84349
84517
|
try {
|
|
84350
|
-
return readdirSync10(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
84518
|
+
return readdirSync10(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join126(dir, entry.name, "plan.md")).filter(existsSync58);
|
|
84351
84519
|
} catch {
|
|
84352
84520
|
return [];
|
|
84353
84521
|
}
|
|
@@ -84416,7 +84584,7 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
84416
84584
|
var import_gray_matter7 = __toESM(require_gray_matter(), 1);
|
|
84417
84585
|
import { mkdirSync as mkdirSync9, readFileSync as readFileSync25, writeFileSync as writeFileSync12 } from "node:fs";
|
|
84418
84586
|
import { existsSync as existsSync60 } from "node:fs";
|
|
84419
|
-
import { basename as basename20, dirname as dirname38, join as
|
|
84587
|
+
import { basename as basename20, dirname as dirname38, join as join127 } from "node:path";
|
|
84420
84588
|
function phaseNameToFilename(id, name2) {
|
|
84421
84589
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
|
|
84422
84590
|
const num4 = numMatch ? numMatch[1] : id;
|
|
@@ -84524,12 +84692,12 @@ function scaffoldPlan(options2) {
|
|
|
84524
84692
|
mkdirSync9(dir, { recursive: true });
|
|
84525
84693
|
const resolvedPhases = resolvePhaseIds(options2.phases);
|
|
84526
84694
|
const optionsWithResolved = { ...options2, phases: resolvedPhases };
|
|
84527
|
-
const planFile =
|
|
84695
|
+
const planFile = join127(dir, "plan.md");
|
|
84528
84696
|
writeFileSync12(planFile, generatePlanMd(optionsWithResolved), "utf8");
|
|
84529
84697
|
const phaseFiles = [];
|
|
84530
84698
|
for (const phase of resolvedPhases) {
|
|
84531
84699
|
const filename = phaseNameToFilename(phase.id, phase.name);
|
|
84532
|
-
const phaseFile =
|
|
84700
|
+
const phaseFile = join127(dir, filename);
|
|
84533
84701
|
writeFileSync12(phaseFile, generatePhaseTemplate(phase), "utf8");
|
|
84534
84702
|
phaseFiles.push(phaseFile);
|
|
84535
84703
|
}
|
|
@@ -84609,7 +84777,7 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
|
|
|
84609
84777
|
continue;
|
|
84610
84778
|
const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
|
|
84611
84779
|
if (linkMatch)
|
|
84612
|
-
return
|
|
84780
|
+
return join127(planDir, linkMatch[2]);
|
|
84613
84781
|
}
|
|
84614
84782
|
return null;
|
|
84615
84783
|
}
|
|
@@ -84690,7 +84858,7 @@ function addPhase(planFile, name2, afterId) {
|
|
|
84690
84858
|
`);
|
|
84691
84859
|
}
|
|
84692
84860
|
writeFileSync12(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
|
|
84693
|
-
const phaseFilePath =
|
|
84861
|
+
const phaseFilePath = join127(planDir, filename);
|
|
84694
84862
|
writeFileSync12(phaseFilePath, generatePhaseTemplate({ id: phaseId, name: name2 }), "utf8");
|
|
84695
84863
|
return { phaseId, phaseFile: phaseFilePath };
|
|
84696
84864
|
}
|
|
@@ -84794,7 +84962,7 @@ async function handleValidate(target, options2) {
|
|
|
84794
84962
|
}
|
|
84795
84963
|
async function handleStatus(target, options2) {
|
|
84796
84964
|
const t = target ? resolve31(target) : null;
|
|
84797
|
-
const plansDir = t && existsSync61(t) && statSync10(t).isDirectory() && !existsSync61(
|
|
84965
|
+
const plansDir = t && existsSync61(t) && statSync10(t).isDirectory() && !existsSync61(join128(t, "plan.md")) ? t : null;
|
|
84798
84966
|
if (plansDir) {
|
|
84799
84967
|
const planFiles = scanPlanDir(plansDir);
|
|
84800
84968
|
if (planFiles.length === 0) {
|
|
@@ -85026,10 +85194,10 @@ async function handleAddPhase(target, options2) {
|
|
|
85026
85194
|
function resolvePlanFile(target) {
|
|
85027
85195
|
const t = target ? resolve33(target) : process.cwd();
|
|
85028
85196
|
if (existsSync62(t)) {
|
|
85029
|
-
const
|
|
85030
|
-
if (
|
|
85197
|
+
const stat14 = statSync11(t);
|
|
85198
|
+
if (stat14.isFile())
|
|
85031
85199
|
return t;
|
|
85032
|
-
const candidate =
|
|
85200
|
+
const candidate = join129(t, "plan.md");
|
|
85033
85201
|
if (existsSync62(candidate))
|
|
85034
85202
|
return candidate;
|
|
85035
85203
|
}
|
|
@@ -85037,7 +85205,7 @@ function resolvePlanFile(target) {
|
|
|
85037
85205
|
let dir = process.cwd();
|
|
85038
85206
|
const root = parse4(dir).root;
|
|
85039
85207
|
while (dir !== root) {
|
|
85040
|
-
const candidate =
|
|
85208
|
+
const candidate = join129(dir, "plan.md");
|
|
85041
85209
|
if (existsSync62(candidate))
|
|
85042
85210
|
return candidate;
|
|
85043
85211
|
dir = dirname41(dir);
|
|
@@ -85134,15 +85302,15 @@ init_logger();
|
|
|
85134
85302
|
// src/commands/telemetry/shared.ts
|
|
85135
85303
|
import { existsSync as existsSync63, readFileSync as readFileSync26, readdirSync as readdirSync11 } from "node:fs";
|
|
85136
85304
|
import { homedir as homedir29 } from "node:os";
|
|
85137
|
-
import { join as
|
|
85305
|
+
import { join as join130 } from "node:path";
|
|
85138
85306
|
init_token_store();
|
|
85139
85307
|
init_manifest_path_resolver();
|
|
85140
85308
|
init_takumi_constants();
|
|
85141
|
-
var USER_CACHE_PATH =
|
|
85142
|
-
var EVENT_BUFFER_DIR =
|
|
85143
|
-
var RATE_STATE_PATH =
|
|
85144
|
-
var TAKUMI_MANIFEST_PATH =
|
|
85145
|
-
var LEGACY_METADATA_PATH =
|
|
85309
|
+
var USER_CACHE_PATH = join130(homedir29(), ".claude", "sk-user.json");
|
|
85310
|
+
var EVENT_BUFFER_DIR = join130(homedir29(), ".claude", "sk-events");
|
|
85311
|
+
var RATE_STATE_PATH = join130(homedir29(), ".claude", "sk-rate-state.json");
|
|
85312
|
+
var TAKUMI_MANIFEST_PATH = join130(homedir29(), ".claude", MANIFEST_FILENAME);
|
|
85313
|
+
var LEGACY_METADATA_PATH = join130(homedir29(), ".claude", LEGACY_MANIFEST_FILENAME);
|
|
85146
85314
|
var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
|
|
85147
85315
|
var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
|
|
85148
85316
|
function readUserCache() {
|
|
@@ -85171,7 +85339,7 @@ function readTelemetryConfig() {
|
|
|
85171
85339
|
const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
|
|
85172
85340
|
let metadata = null;
|
|
85173
85341
|
try {
|
|
85174
|
-
const resolved = findManifestPathSync(
|
|
85342
|
+
const resolved = findManifestPathSync(join130(homedir29(), ".claude"));
|
|
85175
85343
|
if (resolved) {
|
|
85176
85344
|
metadata = JSON.parse(readFileSync26(resolved.path, "utf8"));
|
|
85177
85345
|
}
|
|
@@ -85349,7 +85517,7 @@ init_safe_prompts();
|
|
|
85349
85517
|
init_safe_spinner();
|
|
85350
85518
|
var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
85351
85519
|
import { readdirSync as readdirSync13, rmSync as rmSync9 } from "node:fs";
|
|
85352
|
-
import { join as
|
|
85520
|
+
import { join as join132, resolve as resolve34, sep as sep9 } from "node:path";
|
|
85353
85521
|
|
|
85354
85522
|
// src/commands/uninstall/analysis-handler.ts
|
|
85355
85523
|
init_metadata_migration();
|
|
@@ -85360,7 +85528,7 @@ init_safe_prompts();
|
|
|
85360
85528
|
init_takumi_constants();
|
|
85361
85529
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
85362
85530
|
import { existsSync as existsSync64, readdirSync as readdirSync12, rmSync as rmSync8 } from "node:fs";
|
|
85363
|
-
import { dirname as dirname42, join as
|
|
85531
|
+
import { dirname as dirname42, join as join131 } from "node:path";
|
|
85364
85532
|
function listPresentManifestNames(installPath) {
|
|
85365
85533
|
const present = [];
|
|
85366
85534
|
if (existsSync64(getManifestPath(installPath)))
|
|
@@ -85413,7 +85581,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
85413
85581
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
85414
85582
|
const kitFiles = metadata.kits[kit].files || [];
|
|
85415
85583
|
for (const trackedFile of kitFiles) {
|
|
85416
|
-
const filePath =
|
|
85584
|
+
const filePath = join131(installation.path, trackedFile.path);
|
|
85417
85585
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
85418
85586
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
85419
85587
|
continue;
|
|
@@ -85445,7 +85613,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
85445
85613
|
return result;
|
|
85446
85614
|
}
|
|
85447
85615
|
for (const trackedFile of allTrackedFiles) {
|
|
85448
|
-
const filePath =
|
|
85616
|
+
const filePath = join131(installation.path, trackedFile.path);
|
|
85449
85617
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
85450
85618
|
if (!ownershipResult.exists)
|
|
85451
85619
|
continue;
|
|
@@ -85544,7 +85712,7 @@ async function removeInstallations(installations, options2) {
|
|
|
85544
85712
|
let removedCount = 0;
|
|
85545
85713
|
let cleanedDirs = 0;
|
|
85546
85714
|
for (const item of analysis.toDelete) {
|
|
85547
|
-
const filePath =
|
|
85715
|
+
const filePath = join132(installation.path, item.path);
|
|
85548
85716
|
if (!await import_fs_extra37.pathExists(filePath))
|
|
85549
85717
|
continue;
|
|
85550
85718
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -86413,7 +86581,7 @@ init_manifest_path_resolver();
|
|
|
86413
86581
|
init_logger();
|
|
86414
86582
|
init_types2();
|
|
86415
86583
|
import { readFileSync as readFileSync27 } from "node:fs";
|
|
86416
|
-
import { join as
|
|
86584
|
+
import { join as join133 } from "node:path";
|
|
86417
86585
|
var PROVIDER_LOCAL_SUBDIRS = {
|
|
86418
86586
|
"claude-code": ".claude",
|
|
86419
86587
|
codex: ".codex"
|
|
@@ -86468,7 +86636,7 @@ async function displayVersion() {
|
|
|
86468
86636
|
const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
|
|
86469
86637
|
if (!localSubdir)
|
|
86470
86638
|
continue;
|
|
86471
|
-
const localRoot =
|
|
86639
|
+
const localRoot = join133(process.cwd(), localSubdir);
|
|
86472
86640
|
if (localRoot === inst.globalRoot())
|
|
86473
86641
|
continue;
|
|
86474
86642
|
const resolved = findManifestPathSync(localRoot);
|