@sunasteriskrnd/takumi 1.0.0-dev.60 → 1.0.0-dev.62
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 +1067 -590
- 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.62",
|
|
19819
19819
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
19820
19820
|
type: "module",
|
|
19821
19821
|
repository: {
|
|
@@ -20012,7 +20012,7 @@ function getLegacyManifestPath(providerRoot) {
|
|
|
20012
20012
|
return join4(providerRoot, LEGACY_MANIFEST_FILENAME);
|
|
20013
20013
|
}
|
|
20014
20014
|
function getCliVersion() {
|
|
20015
|
-
return "1.0.0-dev.
|
|
20015
|
+
return "1.0.0-dev.62"?.trim() || process.env.npm_package_version?.trim() || "unknown";
|
|
20016
20016
|
}
|
|
20017
20017
|
function getCliUserAgent() {
|
|
20018
20018
|
return `${TAKUMI_CLI_NPM_PACKAGE_NAME}/${getCliVersion()}`;
|
|
@@ -22554,7 +22554,7 @@ function normalizeTakumiConfigInput(value) {
|
|
|
22554
22554
|
}
|
|
22555
22555
|
return normalized;
|
|
22556
22556
|
}
|
|
22557
|
-
var PlanValidationModeSchema, PlanFocusAreaSchema, PlanResolutionOrderSchema, ProjectTypeSchema, PackageManagerSchema, FrameworkSchema, GEMINI_MODEL_VALUES, LEGACY_GEMINI_MODEL_ALIASES, GeminiModelSchema, StatuslineModeSchema, StatuslineSectionIdSchema, StatuslineSectionConfigSchema, StatuslineThemeSchema, StatuslineLayoutSchema, StatuslineBarStyleSchema, StatuslineConfigSchema, CodingLevelSchema, PlanResolutionSchema, PlanValidationSchema, SkPlanConfigSchema, SkDocsConfigSchema, SkPathsConfigSchema, SkLocaleConfigSchema, SkTrustConfigSchema, SkGraphifyConfigSchema, SkProjectConfigSchema, SkGeminiConfigSchema, SkSkillsConfigSchema, SkSkillExtensionsConfigSchema, UpdatePipelineSchema, ResolvedModelConfigSchema, ModelTierMapSchema, SkModelTaxonomySchema, SkAssertionSchema, SkHooksConfigSchema, TakumiConfigSchema, DEFAULT_TAKUMI_CONFIG, TAKUMI_HOOK_NAMES;
|
|
22557
|
+
var PlanValidationModeSchema, PlanFocusAreaSchema, PlanResolutionOrderSchema, ProjectTypeSchema, PackageManagerSchema, FrameworkSchema, GEMINI_MODEL_VALUES, LEGACY_GEMINI_MODEL_ALIASES, GeminiModelSchema, StatuslineModeSchema, StatuslineSectionIdSchema, StatuslineSectionConfigSchema, StatuslineThemeSchema, StatuslineLayoutSchema, StatuslineBarStyleSchema, StatuslineConfigSchema, CodingLevelSchema, PlanResolutionSchema, PlanValidationSchema, SkPlanConfigSchema, SkDocsConfigSchema, SkPathsConfigSchema, SkLocaleConfigSchema, SkTrustConfigSchema, SkGraphifyConfigSchema, SkProjectConfigSchema, SkGeminiConfigSchema, SkSkillsConfigSchema, SkSkillExtensionsConfigSchema, SkTakumiConfigSchema, SkSubagentAgentConfigSchema, SkSubagentConfigSchema, UpdatePipelineSchema, ResolvedModelConfigSchema, ModelTierMapSchema, SkModelTaxonomySchema, SkAssertionSchema, SkHooksConfigSchema, TakumiConfigSchema, DEFAULT_TAKUMI_CONFIG, TAKUMI_HOOK_NAMES;
|
|
22558
22558
|
var init_takumi_config = __esm(() => {
|
|
22559
22559
|
init_zod();
|
|
22560
22560
|
PlanValidationModeSchema = exports_external.enum(["prompt", "auto", "strict", "none"]);
|
|
@@ -22739,6 +22739,15 @@ var init_takumi_config = __esm(() => {
|
|
|
22739
22739
|
SkSkillExtensionsConfigSchema = exports_external.object({
|
|
22740
22740
|
sharedDir: exports_external.string().optional()
|
|
22741
22741
|
}).passthrough();
|
|
22742
|
+
SkTakumiConfigSchema = exports_external.object({
|
|
22743
|
+
sddMode: exports_external.enum(["ask", "on", "off"]).optional()
|
|
22744
|
+
}).passthrough();
|
|
22745
|
+
SkSubagentAgentConfigSchema = exports_external.object({
|
|
22746
|
+
contextPrefix: exports_external.string().optional()
|
|
22747
|
+
}).passthrough();
|
|
22748
|
+
SkSubagentConfigSchema = exports_external.object({
|
|
22749
|
+
agents: exports_external.record(exports_external.string(), SkSubagentAgentConfigSchema).optional()
|
|
22750
|
+
}).passthrough();
|
|
22742
22751
|
UpdatePipelineSchema = exports_external.object({
|
|
22743
22752
|
autoInitAfterUpdate: exports_external.boolean().default(false)
|
|
22744
22753
|
});
|
|
@@ -22787,6 +22796,8 @@ var init_takumi_config = __esm(() => {
|
|
|
22787
22796
|
gemini: SkGeminiConfigSchema.optional(),
|
|
22788
22797
|
skills: SkSkillsConfigSchema.optional(),
|
|
22789
22798
|
skillExtensions: SkSkillExtensionsConfigSchema.optional(),
|
|
22799
|
+
takumi: SkTakumiConfigSchema.optional(),
|
|
22800
|
+
subagent: SkSubagentConfigSchema.optional(),
|
|
22790
22801
|
assertions: exports_external.array(SkAssertionSchema).optional(),
|
|
22791
22802
|
hooks: SkHooksConfigSchema.optional(),
|
|
22792
22803
|
updatePipeline: UpdatePipelineSchema.optional(),
|
|
@@ -33976,17 +33987,13 @@ var init_settings_merger = __esm(() => {
|
|
|
33976
33987
|
});
|
|
33977
33988
|
|
|
33978
33989
|
// src/domains/installation/merger/settings-processor.ts
|
|
33979
|
-
import { execSync } from "node:child_process";
|
|
33980
|
-
|
|
33981
33990
|
class SettingsProcessor {
|
|
33982
|
-
static MIN_TEAM_HOOKS_VERSION = "2.1.33";
|
|
33983
33991
|
isGlobal = false;
|
|
33984
33992
|
forceOverwriteSettings = false;
|
|
33985
33993
|
projectDir = "";
|
|
33986
33994
|
kitName = "engineer";
|
|
33987
33995
|
tracker = null;
|
|
33988
33996
|
installingKit;
|
|
33989
|
-
cachedVersion = undefined;
|
|
33990
33997
|
deletionPatterns = [];
|
|
33991
33998
|
setGlobalFlag(isGlobal) {
|
|
33992
33999
|
this.isGlobal = isGlobal;
|
|
@@ -34052,7 +34059,6 @@ class SettingsProcessor {
|
|
|
34052
34059
|
const formattedContent = this.formatJsonContent(transformedSource);
|
|
34053
34060
|
await import_fs_extra11.writeFile(destFile, formattedContent, "utf-8");
|
|
34054
34061
|
}
|
|
34055
|
-
await this.injectTeamHooksIfSupported(destFile);
|
|
34056
34062
|
}
|
|
34057
34063
|
} catch (error) {
|
|
34058
34064
|
logger.error(`Failed to process settings.json: ${error}`);
|
|
@@ -34122,7 +34128,6 @@ class SettingsProcessor {
|
|
|
34122
34128
|
}
|
|
34123
34129
|
await SettingsMerger.writeSettingsFile(destFile, mergeResult.merged);
|
|
34124
34130
|
logger.success("Merged settings.json (user customizations preserved)");
|
|
34125
|
-
await this.injectTeamHooksIfSupported(destFile, mergeResult.merged);
|
|
34126
34131
|
}
|
|
34127
34132
|
migrateDeprecatedMatchers(destSettings, sourceSettings) {
|
|
34128
34133
|
if (!destSettings.hooks || !sourceSettings.hooks)
|
|
@@ -34389,87 +34394,13 @@ class SettingsProcessor {
|
|
|
34389
34394
|
return capturedVar;
|
|
34390
34395
|
}
|
|
34391
34396
|
}
|
|
34392
|
-
detectClaudeCodeVersion() {
|
|
34393
|
-
if (this.cachedVersion !== undefined)
|
|
34394
|
-
return this.cachedVersion;
|
|
34395
|
-
try {
|
|
34396
|
-
const output2 = execSync("claude --version", {
|
|
34397
|
-
encoding: "utf-8",
|
|
34398
|
-
timeout: 5000,
|
|
34399
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
34400
|
-
});
|
|
34401
|
-
const match = output2.match(/(\d+\.\d+\.\d+)/);
|
|
34402
|
-
this.cachedVersion = match ? match[1] : null;
|
|
34403
|
-
} catch {
|
|
34404
|
-
this.cachedVersion = null;
|
|
34405
|
-
}
|
|
34406
|
-
return this.cachedVersion;
|
|
34407
|
-
}
|
|
34408
|
-
isVersionAtLeast(version3, minimum) {
|
|
34409
|
-
const coerced = import_semver2.default.coerce(version3);
|
|
34410
|
-
if (!coerced)
|
|
34411
|
-
return false;
|
|
34412
|
-
return import_semver2.default.gte(coerced, minimum);
|
|
34413
|
-
}
|
|
34414
|
-
async injectTeamHooksIfSupported(destFile, existingSettings) {
|
|
34415
|
-
const version3 = this.detectClaudeCodeVersion();
|
|
34416
|
-
if (!version3) {
|
|
34417
|
-
logger.debug("Claude Code version not detected, skipping team hooks injection");
|
|
34418
|
-
return;
|
|
34419
|
-
}
|
|
34420
|
-
if (!this.isVersionAtLeast(version3, SettingsProcessor.MIN_TEAM_HOOKS_VERSION)) {
|
|
34421
|
-
logger.debug(`Claude Code ${version3} does not support team hooks (requires >= 2.1.33), skipping injection`);
|
|
34422
|
-
return;
|
|
34423
|
-
}
|
|
34424
|
-
logger.debug(`Claude Code ${version3} detected, checking team hooks`);
|
|
34425
|
-
const settings = existingSettings ?? await SettingsMerger.readSettingsFile(destFile);
|
|
34426
|
-
if (!settings) {
|
|
34427
|
-
logger.warning("Failed to read settings file for team hooks injection");
|
|
34428
|
-
return;
|
|
34429
|
-
}
|
|
34430
|
-
if (!settings.hooks) {
|
|
34431
|
-
settings.hooks = {};
|
|
34432
|
-
}
|
|
34433
|
-
let injected = false;
|
|
34434
|
-
const installedSettings = this.tracker ? await this.tracker.loadInstalledSettings() : { hooks: [], mcpServers: [] };
|
|
34435
|
-
const teamHooks = [
|
|
34436
|
-
{ event: "TaskCompleted", handler: "task-completed-handler.cjs" },
|
|
34437
|
-
{ event: "TeammateIdle", handler: "teammate-idle-handler.cjs" }
|
|
34438
|
-
];
|
|
34439
|
-
for (const { event, handler } of teamHooks) {
|
|
34440
|
-
const hookCommand = this.formatCommandPath("node ", this.isGlobal ? "$HOME" : "$CLAUDE_PROJECT_DIR", `.claude/hooks/${handler}`);
|
|
34441
|
-
const eventHooks = settings.hooks[event];
|
|
34442
|
-
if (eventHooks && eventHooks.length > 0)
|
|
34443
|
-
continue;
|
|
34444
|
-
if (this.tracker?.wasHookInstalled(hookCommand, installedSettings)) {
|
|
34445
|
-
logger.debug(`Skipping ${event} hook injection (previously removed by user)`);
|
|
34446
|
-
continue;
|
|
34447
|
-
}
|
|
34448
|
-
settings.hooks[event] = [{ hooks: [{ type: "command", command: hookCommand }] }];
|
|
34449
|
-
logger.info(`Injected ${event} hook`);
|
|
34450
|
-
injected = true;
|
|
34451
|
-
if (this.tracker) {
|
|
34452
|
-
this.tracker.trackHook(hookCommand, installedSettings);
|
|
34453
|
-
}
|
|
34454
|
-
}
|
|
34455
|
-
if (injected) {
|
|
34456
|
-
await SettingsMerger.writeSettingsFile(destFile, settings);
|
|
34457
|
-
if (this.tracker) {
|
|
34458
|
-
await this.tracker.saveInstalledSettings(installedSettings);
|
|
34459
|
-
}
|
|
34460
|
-
logger.success("Team hooks injected successfully");
|
|
34461
|
-
} else {
|
|
34462
|
-
logger.debug("Team hooks already present, no injection needed");
|
|
34463
|
-
}
|
|
34464
|
-
}
|
|
34465
34397
|
}
|
|
34466
|
-
var import_fs_extra11
|
|
34398
|
+
var import_fs_extra11;
|
|
34467
34399
|
var init_settings_processor = __esm(() => {
|
|
34468
34400
|
init_installed_settings_tracker();
|
|
34469
34401
|
init_settings_merger();
|
|
34470
34402
|
init_logger();
|
|
34471
34403
|
import_fs_extra11 = __toESM(require_lib(), 1);
|
|
34472
|
-
import_semver2 = __toESM(require_semver2(), 1);
|
|
34473
34404
|
});
|
|
34474
34405
|
|
|
34475
34406
|
// src/domains/installation/merger/copy-executor.ts
|
|
@@ -40953,7 +40884,7 @@ async function loadPortableManifest(kitPath) {
|
|
|
40953
40884
|
}
|
|
40954
40885
|
}
|
|
40955
40886
|
function getApplicableEntries(entries, appliedVersion, currentVersion) {
|
|
40956
|
-
const normalizedCurrentVersionRaw =
|
|
40887
|
+
const normalizedCurrentVersionRaw = import_semver2.default.valid(currentVersion);
|
|
40957
40888
|
if (!normalizedCurrentVersionRaw) {
|
|
40958
40889
|
logger.verbose(`Invalid manifest current version "${currentVersion}" — skipping manifest entries safely`);
|
|
40959
40890
|
return [];
|
|
@@ -40961,34 +40892,34 @@ function getApplicableEntries(entries, appliedVersion, currentVersion) {
|
|
|
40961
40892
|
const normalizedCurrentVersion = normalizedCurrentVersionRaw;
|
|
40962
40893
|
let normalizedAppliedVersion;
|
|
40963
40894
|
if (appliedVersion) {
|
|
40964
|
-
const normalizedAppliedVersionRaw =
|
|
40895
|
+
const normalizedAppliedVersionRaw = import_semver2.default.valid(appliedVersion);
|
|
40965
40896
|
if (!normalizedAppliedVersionRaw) {
|
|
40966
40897
|
logger.verbose(`Invalid applied manifest version "${appliedVersion}" — skipping manifest entries safely`);
|
|
40967
40898
|
return [];
|
|
40968
40899
|
}
|
|
40969
40900
|
normalizedAppliedVersion = normalizedAppliedVersionRaw;
|
|
40970
|
-
if (
|
|
40901
|
+
if (import_semver2.default.gt(normalizedAppliedVersion, normalizedCurrentVersion)) {
|
|
40971
40902
|
logger.verbose(`Applied manifest version ${normalizedAppliedVersion} is newer than current ${normalizedCurrentVersion} — skipping manifest entries safely`);
|
|
40972
40903
|
return [];
|
|
40973
40904
|
}
|
|
40974
40905
|
}
|
|
40975
40906
|
return entries.filter((entry) => {
|
|
40976
|
-
const normalizedSince =
|
|
40907
|
+
const normalizedSince = import_semver2.default.valid(entry.since);
|
|
40977
40908
|
if (!normalizedSince) {
|
|
40978
40909
|
logger.verbose(`Skipping manifest entry with invalid "since" version: ${entry.since}`);
|
|
40979
40910
|
return false;
|
|
40980
40911
|
}
|
|
40981
40912
|
if (!normalizedAppliedVersion) {
|
|
40982
|
-
return
|
|
40913
|
+
return import_semver2.default.lte(normalizedSince, normalizedCurrentVersion);
|
|
40983
40914
|
}
|
|
40984
|
-
return
|
|
40915
|
+
return import_semver2.default.gt(normalizedSince, normalizedAppliedVersion) && import_semver2.default.lte(normalizedSince, normalizedCurrentVersion);
|
|
40985
40916
|
});
|
|
40986
40917
|
}
|
|
40987
|
-
var
|
|
40918
|
+
var import_semver2, safeRelativePath, RenameEntrySchema, ProviderPathMigrationSchema, SectionRenameSchema, PortableManifestSchema;
|
|
40988
40919
|
var init_portable_manifest = __esm(() => {
|
|
40989
40920
|
init_zod();
|
|
40990
40921
|
init_logger();
|
|
40991
|
-
|
|
40922
|
+
import_semver2 = __toESM(require_semver2(), 1);
|
|
40992
40923
|
safeRelativePath = exports_external.string().min(1).refine((p) => !p.includes("..") && !path2.isAbsolute(p), {
|
|
40993
40924
|
message: "Path must be relative without traversal"
|
|
40994
40925
|
});
|
|
@@ -41300,26 +41231,26 @@ function findCapabilitiesForVersion(version3) {
|
|
|
41300
41231
|
const exact = CODEX_CAPABILITY_TABLE.find((entry) => entry.version === version3);
|
|
41301
41232
|
if (exact)
|
|
41302
41233
|
return exact;
|
|
41303
|
-
const coercedDetected =
|
|
41234
|
+
const coercedDetected = import_semver3.default.coerce(version3);
|
|
41304
41235
|
if (!coercedDetected)
|
|
41305
41236
|
return null;
|
|
41306
41237
|
for (const entry of CODEX_CAPABILITY_TABLE) {
|
|
41307
|
-
const coercedEntry =
|
|
41238
|
+
const coercedEntry = import_semver3.default.coerce(entry.version);
|
|
41308
41239
|
if (!coercedEntry)
|
|
41309
41240
|
continue;
|
|
41310
41241
|
if (coercedDetected.major === coercedEntry.major && coercedDetected.minor === coercedEntry.minor) {
|
|
41311
41242
|
return entry;
|
|
41312
41243
|
}
|
|
41313
|
-
if (
|
|
41244
|
+
if (import_semver3.default.gte(coercedDetected, coercedEntry)) {
|
|
41314
41245
|
return entry;
|
|
41315
41246
|
}
|
|
41316
41247
|
}
|
|
41317
41248
|
return null;
|
|
41318
41249
|
}
|
|
41319
|
-
var
|
|
41250
|
+
var import_semver3, execFileAsync2, CODEX_CAPABILITY_TABLE, FALLBACK_CAPABILITIES, CODEX_SUPPORTED_EVENTS;
|
|
41320
41251
|
var init_capabilities = __esm(() => {
|
|
41321
41252
|
init_logger();
|
|
41322
|
-
|
|
41253
|
+
import_semver3 = __toESM(require_semver2(), 1);
|
|
41323
41254
|
execFileAsync2 = promisify2(execFile2);
|
|
41324
41255
|
CODEX_CAPABILITY_TABLE = [
|
|
41325
41256
|
{
|
|
@@ -41432,9 +41363,9 @@ var init_capabilities = __esm(() => {
|
|
|
41432
41363
|
];
|
|
41433
41364
|
if (CODEX_CAPABILITY_TABLE.length > 1) {
|
|
41434
41365
|
for (let i = 0;i < CODEX_CAPABILITY_TABLE.length - 1; i++) {
|
|
41435
|
-
const newer =
|
|
41436
|
-
const older =
|
|
41437
|
-
if (newer && older && !
|
|
41366
|
+
const newer = import_semver3.default.coerce(CODEX_CAPABILITY_TABLE[i].version);
|
|
41367
|
+
const older = import_semver3.default.coerce(CODEX_CAPABILITY_TABLE[i + 1].version);
|
|
41368
|
+
if (newer && older && !import_semver3.default.gte(newer, older)) {
|
|
41438
41369
|
throw new Error(`[ck] CODEX_CAPABILITY_TABLE ordering violation: entry[${i}] (${CODEX_CAPABILITY_TABLE[i].version}) must be >= entry[${i + 1}] (${CODEX_CAPABILITY_TABLE[i + 1].version}). Table must be sorted newest-first.`);
|
|
41439
41370
|
}
|
|
41440
41371
|
}
|
|
@@ -44296,6 +44227,23 @@ var init_agent_prune = __esm(() => {
|
|
|
44296
44227
|
init_post_pipeline();
|
|
44297
44228
|
});
|
|
44298
44229
|
|
|
44230
|
+
// src/domains/installers/codex/codex-paths.ts
|
|
44231
|
+
import { homedir as homedir16 } from "node:os";
|
|
44232
|
+
import { join as join60 } from "node:path";
|
|
44233
|
+
function codexGlobalRoot() {
|
|
44234
|
+
const testHome = process.env.TAKUMI_TEST_HOME;
|
|
44235
|
+
if (testHome && testHome.trim() !== "")
|
|
44236
|
+
return join60(testHome, ".codex");
|
|
44237
|
+
const codexHome = process.env.CODEX_HOME;
|
|
44238
|
+
if (codexHome && codexHome.trim() !== "" && !codexHome.includes(".."))
|
|
44239
|
+
return codexHome;
|
|
44240
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
44241
|
+
if (xdg && xdg.trim() !== "" && !xdg.includes(".."))
|
|
44242
|
+
return join60(xdg, "codex");
|
|
44243
|
+
return join60(homedir16(), ".codex");
|
|
44244
|
+
}
|
|
44245
|
+
var init_codex_paths = () => {};
|
|
44246
|
+
|
|
44299
44247
|
// src/commands/portable/output-sanitizer.ts
|
|
44300
44248
|
function isDisallowedControlCode(codePoint) {
|
|
44301
44249
|
return codePoint >= 0 && codePoint <= 8 || codePoint >= 11 && codePoint <= 26 || codePoint >= 28 && codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
|
|
@@ -44916,7 +44864,7 @@ var init_reconciler = __esm(() => {
|
|
|
44916
44864
|
|
|
44917
44865
|
// src/domains/installers/codex/codex-env-marker.ts
|
|
44918
44866
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
44919
|
-
import { join as
|
|
44867
|
+
import { join as join61 } from "node:path";
|
|
44920
44868
|
function writeCodexEnvMarker(global3, projectRoot) {
|
|
44921
44869
|
try {
|
|
44922
44870
|
const pathConfig = providers.codex.hooks;
|
|
@@ -44925,10 +44873,10 @@ function writeCodexEnvMarker(global3, projectRoot) {
|
|
|
44925
44873
|
const scopedPath = global3 ? pathConfig.globalPath : pathConfig.projectPath;
|
|
44926
44874
|
if (!scopedPath)
|
|
44927
44875
|
return;
|
|
44928
|
-
const targetHooksDir = global3 ? scopedPath :
|
|
44929
|
-
const libDir =
|
|
44876
|
+
const targetHooksDir = global3 ? scopedPath : join61(projectRoot ?? process.cwd(), scopedPath);
|
|
44877
|
+
const libDir = join61(targetHooksDir, "lib");
|
|
44930
44878
|
mkdirSync3(libDir, { recursive: true });
|
|
44931
|
-
writeFileSync5(
|
|
44879
|
+
writeFileSync5(join61(libDir, "env.cjs"), CODEX_ENV_MARKER);
|
|
44932
44880
|
} catch (e2) {
|
|
44933
44881
|
logger.debug(`[init/codex] writeCodexEnvMarker failed: ${String(e2)}`);
|
|
44934
44882
|
}
|
|
@@ -44942,7 +44890,7 @@ var init_codex_env_marker = __esm(() => {
|
|
|
44942
44890
|
|
|
44943
44891
|
// src/domains/installers/shared/writers/install-one-file.ts
|
|
44944
44892
|
import { writeFile as writeFile18 } from "node:fs/promises";
|
|
44945
|
-
import { dirname as dirname18, join as
|
|
44893
|
+
import { dirname as dirname18, join as join62, resolve as resolve15, sep as sep5 } from "node:path";
|
|
44946
44894
|
async function installOneFile(item, provider, kind, options2) {
|
|
44947
44895
|
const config = providers[provider];
|
|
44948
44896
|
const typeKey = getProviderPathKey(kind);
|
|
@@ -44998,7 +44946,7 @@ async function installOneFile(item, provider, kind, options2) {
|
|
|
44998
44946
|
const nameWithoutExt = extIdx >= 0 ? resolvedFilename.substring(0, extIdx) : resolvedFilename;
|
|
44999
44947
|
resolvedFilename = `${nameWithoutExt.replace(/\//g, "-")}${ext}`;
|
|
45000
44948
|
}
|
|
45001
|
-
targetPath = pathConfig.writeStrategy === "single-file" ? basePath :
|
|
44949
|
+
targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join62(basePath, resolvedFilename);
|
|
45002
44950
|
const resolvedTarget = resolve15(targetPath);
|
|
45003
44951
|
const resolvedBase = pathConfig.writeStrategy === "single-file" ? resolve15(dirname18(basePath)) : resolve15(basePath);
|
|
45004
44952
|
if (!resolvedTarget.startsWith(resolvedBase + sep5) && resolvedTarget !== resolvedBase) {
|
|
@@ -45638,7 +45586,7 @@ var init_install_items = __esm(() => {
|
|
|
45638
45586
|
// src/domains/installers/shared/skill-directory-installer.ts
|
|
45639
45587
|
import { existsSync as existsSync25 } from "node:fs";
|
|
45640
45588
|
import { cp as cp3, mkdir as mkdir13, rename as rename6, rm as rm5 } from "node:fs/promises";
|
|
45641
|
-
import { join as
|
|
45589
|
+
import { join as join63, resolve as resolve16 } from "node:path";
|
|
45642
45590
|
async function installSkillDirectories(skills, targetProviders, options2) {
|
|
45643
45591
|
const results = [];
|
|
45644
45592
|
for (const provider of targetProviders) {
|
|
@@ -45667,7 +45615,7 @@ async function installSkillDirectories(skills, targetProviders, options2) {
|
|
|
45667
45615
|
}
|
|
45668
45616
|
const basePath = resolveInstallBasePath(rawBasePath, options2);
|
|
45669
45617
|
for (const skill of skills) {
|
|
45670
|
-
const targetDir =
|
|
45618
|
+
const targetDir = join63(basePath, skill.name);
|
|
45671
45619
|
if (resolve16(skill.path) === resolve16(targetDir)) {
|
|
45672
45620
|
results.push({
|
|
45673
45621
|
provider,
|
|
@@ -46030,19 +45978,19 @@ var init_reconcile_helpers = __esm(() => {
|
|
|
46030
45978
|
// src/commands/portable/config-discovery.ts
|
|
46031
45979
|
import { existsSync as existsSync27 } from "node:fs";
|
|
46032
45980
|
import { readFile as readFile31, readdir as readdir20 } from "node:fs/promises";
|
|
46033
|
-
import { homedir as
|
|
46034
|
-
import { extname as extname4, join as
|
|
45981
|
+
import { homedir as homedir17 } from "node:os";
|
|
45982
|
+
import { extname as extname4, join as join64, relative as relative12, sep as sep6 } from "node:path";
|
|
46035
45983
|
function getConfigSourcePath() {
|
|
46036
45984
|
return findExistingProjectConfigPath(process.cwd()) ?? getGlobalConfigSourcePath();
|
|
46037
45985
|
}
|
|
46038
45986
|
function getGlobalConfigSourcePath() {
|
|
46039
|
-
return
|
|
45987
|
+
return join64(homedir17(), ".claude", "CLAUDE.md");
|
|
46040
45988
|
}
|
|
46041
45989
|
function getRulesSourcePath() {
|
|
46042
|
-
return findExistingProjectLayoutPath(process.cwd(), "rules") ??
|
|
45990
|
+
return findExistingProjectLayoutPath(process.cwd(), "rules") ?? join64(homedir17(), ".claude", "rules");
|
|
46043
45991
|
}
|
|
46044
45992
|
function getHooksSourcePath() {
|
|
46045
|
-
return findExistingProjectLayoutPath(process.cwd(), "hooks") ??
|
|
45993
|
+
return findExistingProjectLayoutPath(process.cwd(), "hooks") ?? join64(homedir17(), ".claude", "hooks");
|
|
46046
45994
|
}
|
|
46047
45995
|
async function discoverConfig(sourcePath) {
|
|
46048
45996
|
const path5 = sourcePath ?? getConfigSourcePath();
|
|
@@ -46094,7 +46042,7 @@ async function discoverHooks(sourcePath) {
|
|
|
46094
46042
|
}
|
|
46095
46043
|
if (!HOOK_EXTENSIONS.has(ext))
|
|
46096
46044
|
continue;
|
|
46097
|
-
const fullPath =
|
|
46045
|
+
const fullPath = join64(path5, entry.name);
|
|
46098
46046
|
try {
|
|
46099
46047
|
const content = await readFile31(fullPath, "utf-8");
|
|
46100
46048
|
items.push({
|
|
@@ -46120,7 +46068,7 @@ async function discoverPortableFiles(dir, baseDir, options2) {
|
|
|
46120
46068
|
for (const entry of entries) {
|
|
46121
46069
|
if (entry.name.startsWith("."))
|
|
46122
46070
|
continue;
|
|
46123
|
-
const fullPath =
|
|
46071
|
+
const fullPath = join64(dir, entry.name);
|
|
46124
46072
|
if (entry.isSymbolicLink()) {
|
|
46125
46073
|
continue;
|
|
46126
46074
|
}
|
|
@@ -46163,12 +46111,12 @@ var init_config_discovery = __esm(() => {
|
|
|
46163
46111
|
|
|
46164
46112
|
// src/domains/installers/shared/commands-discovery.ts
|
|
46165
46113
|
import { readdir as readdir21 } from "node:fs/promises";
|
|
46166
|
-
import { homedir as
|
|
46167
|
-
import { join as
|
|
46114
|
+
import { homedir as homedir18 } from "node:os";
|
|
46115
|
+
import { join as join65, relative as relative13 } from "node:path";
|
|
46168
46116
|
function getCommandSourcePath() {
|
|
46169
46117
|
return findFirstExistingPath([
|
|
46170
46118
|
...getProjectLayoutCandidates(process.cwd(), "commands"),
|
|
46171
|
-
|
|
46119
|
+
join65(home5, ".claude/commands")
|
|
46172
46120
|
]);
|
|
46173
46121
|
}
|
|
46174
46122
|
async function scanCommandDir(dir, rootDir) {
|
|
@@ -46176,7 +46124,7 @@ async function scanCommandDir(dir, rootDir) {
|
|
|
46176
46124
|
try {
|
|
46177
46125
|
const entries = await readdir21(dir, { withFileTypes: true });
|
|
46178
46126
|
for (const entry of entries) {
|
|
46179
|
-
const fullPath =
|
|
46127
|
+
const fullPath = join65(dir, entry.name);
|
|
46180
46128
|
if (entry.isDirectory()) {
|
|
46181
46129
|
if (SKIP_DIRS2.includes(entry.name))
|
|
46182
46130
|
continue;
|
|
@@ -46219,7 +46167,7 @@ var init_commands_discovery = __esm(() => {
|
|
|
46219
46167
|
init_frontmatter_parser();
|
|
46220
46168
|
init_kit_layout();
|
|
46221
46169
|
init_logger();
|
|
46222
|
-
home5 =
|
|
46170
|
+
home5 = homedir18();
|
|
46223
46171
|
SKIP_DIRS2 = ["node_modules", ".git", "dist", "build"];
|
|
46224
46172
|
});
|
|
46225
46173
|
|
|
@@ -46328,8 +46276,8 @@ __export(exports_takumi_config_manager, {
|
|
|
46328
46276
|
});
|
|
46329
46277
|
import { existsSync as existsSync28 } from "node:fs";
|
|
46330
46278
|
import { mkdir as mkdir14, readFile as readFile33, writeFile as writeFile20 } from "node:fs/promises";
|
|
46331
|
-
import { homedir as
|
|
46332
|
-
import { join as
|
|
46279
|
+
import { homedir as homedir19 } from "node:os";
|
|
46280
|
+
import { join as join66 } from "node:path";
|
|
46333
46281
|
function getNestedValue(obj, path5) {
|
|
46334
46282
|
if (!obj || typeof obj !== "object")
|
|
46335
46283
|
return;
|
|
@@ -46403,25 +46351,25 @@ function valuesEqual(a3, b3) {
|
|
|
46403
46351
|
|
|
46404
46352
|
class TakumiConfigManager {
|
|
46405
46353
|
static getGlobalConfigDir() {
|
|
46406
|
-
return
|
|
46354
|
+
return join66(homedir19(), ".claude");
|
|
46407
46355
|
}
|
|
46408
46356
|
static resolveConfigPath(dir) {
|
|
46409
|
-
const preferred =
|
|
46357
|
+
const preferred = join66(dir, TAKUMI_CONFIG_FILE);
|
|
46410
46358
|
if (existsSync28(preferred))
|
|
46411
46359
|
return preferred;
|
|
46412
|
-
const legacy =
|
|
46360
|
+
const legacy = join66(dir, LEGACY_TAKUMI_CONFIG_FILE);
|
|
46413
46361
|
if (existsSync28(legacy))
|
|
46414
46362
|
return legacy;
|
|
46415
46363
|
return preferred;
|
|
46416
46364
|
}
|
|
46417
46365
|
static configFileExistsIn(dir) {
|
|
46418
|
-
return existsSync28(
|
|
46366
|
+
return existsSync28(join66(dir, TAKUMI_CONFIG_FILE)) || existsSync28(join66(dir, LEGACY_TAKUMI_CONFIG_FILE));
|
|
46419
46367
|
}
|
|
46420
46368
|
static getGlobalConfigPath() {
|
|
46421
46369
|
return TakumiConfigManager.resolveConfigPath(TakumiConfigManager.getGlobalConfigDir());
|
|
46422
46370
|
}
|
|
46423
46371
|
static getProjectConfigDir(projectDir) {
|
|
46424
|
-
return
|
|
46372
|
+
return join66(projectDir, ".claude");
|
|
46425
46373
|
}
|
|
46426
46374
|
static getProjectConfigPath(projectDir) {
|
|
46427
46375
|
return TakumiConfigManager.resolveConfigPath(TakumiConfigManager.getProjectConfigDir(projectDir));
|
|
@@ -46703,7 +46651,7 @@ var init_install_pipeline = __esm(() => {
|
|
|
46703
46651
|
});
|
|
46704
46652
|
|
|
46705
46653
|
// src/domains/installers/codex/skills-paths.ts
|
|
46706
|
-
import { homedir as
|
|
46654
|
+
import { homedir as homedir20 } from "node:os";
|
|
46707
46655
|
import { resolve as resolve17 } from "node:path";
|
|
46708
46656
|
function getCodexSkillsTargetDir(global3, projectRoot) {
|
|
46709
46657
|
const cfg = providers.codex.skills;
|
|
@@ -46716,7 +46664,7 @@ function getCodexSkillsTargetDir(global3, projectRoot) {
|
|
|
46716
46664
|
}
|
|
46717
46665
|
const projectBase = projectRoot ?? process.cwd();
|
|
46718
46666
|
const resolved = global3 ? resolve17(path5) : resolve17(projectBase, path5);
|
|
46719
|
-
const boundary = global3 ?
|
|
46667
|
+
const boundary = global3 ? homedir20() : projectBase;
|
|
46720
46668
|
if (!isPathWithinBoundary(resolved, boundary)) {
|
|
46721
46669
|
throw new Error(`[codex] resolved skills path "${resolved}" escapes boundary "${boundary}"`);
|
|
46722
46670
|
}
|
|
@@ -46728,7 +46676,7 @@ var init_skills_paths = __esm(() => {
|
|
|
46728
46676
|
});
|
|
46729
46677
|
|
|
46730
46678
|
// src/domains/installers/codex/scan-codex-directory.ts
|
|
46731
|
-
import { join as
|
|
46679
|
+
import { join as join67 } from "node:path";
|
|
46732
46680
|
async function scanCodexDirectory(root, opts = {}) {
|
|
46733
46681
|
const counts = { agents: 0, commands: 0, rules: 0, skills: 0 };
|
|
46734
46682
|
try {
|
|
@@ -46736,11 +46684,11 @@ async function scanCodexDirectory(root, opts = {}) {
|
|
|
46736
46684
|
return counts;
|
|
46737
46685
|
const items = await import_fs_extra32.readdir(root);
|
|
46738
46686
|
if (items.includes("agents")) {
|
|
46739
|
-
const files = await import_fs_extra32.readdir(
|
|
46687
|
+
const files = await import_fs_extra32.readdir(join67(root, "agents")).catch(() => []);
|
|
46740
46688
|
counts.agents = files.filter((f3) => f3.endsWith(".toml")).length;
|
|
46741
46689
|
}
|
|
46742
46690
|
if (items.includes("prompts")) {
|
|
46743
|
-
const files = await import_fs_extra32.readdir(
|
|
46691
|
+
const files = await import_fs_extra32.readdir(join67(root, "prompts")).catch(() => []);
|
|
46744
46692
|
counts.commands = files.filter((f3) => f3.endsWith(".md")).length;
|
|
46745
46693
|
}
|
|
46746
46694
|
if (items.includes("AGENTS.md"))
|
|
@@ -46749,7 +46697,7 @@ async function scanCodexDirectory(root, opts = {}) {
|
|
|
46749
46697
|
if (await import_fs_extra32.pathExists(skillsRoot)) {
|
|
46750
46698
|
const dirs = await import_fs_extra32.readdir(skillsRoot).catch(() => []);
|
|
46751
46699
|
for (const d3 of dirs) {
|
|
46752
|
-
const skillDir =
|
|
46700
|
+
const skillDir = join67(skillsRoot, d3);
|
|
46753
46701
|
const entries = await import_fs_extra32.readdir(skillDir).catch(() => null);
|
|
46754
46702
|
if (entries?.includes("SKILL.md"))
|
|
46755
46703
|
counts.skills++;
|
|
@@ -46766,7 +46714,7 @@ var init_scan_codex_directory = __esm(() => {
|
|
|
46766
46714
|
|
|
46767
46715
|
// src/domains/installers/codex/source-resolver.ts
|
|
46768
46716
|
import { existsSync as existsSync29 } from "node:fs";
|
|
46769
|
-
import { join as
|
|
46717
|
+
import { join as join68 } from "node:path";
|
|
46770
46718
|
function resolveCodexSources(extractDir) {
|
|
46771
46719
|
return {
|
|
46772
46720
|
agents: findExistingProjectLayoutPath(extractDir, "agents"),
|
|
@@ -46778,7 +46726,7 @@ function resolveCodexSources(extractDir) {
|
|
|
46778
46726
|
};
|
|
46779
46727
|
}
|
|
46780
46728
|
function resolveConfigSource(extractDir) {
|
|
46781
|
-
const rootClaudeMd =
|
|
46729
|
+
const rootClaudeMd = join68(extractDir, "CLAUDE.md");
|
|
46782
46730
|
if (existsSync29(rootClaudeMd))
|
|
46783
46731
|
return rootClaudeMd;
|
|
46784
46732
|
return findExistingProjectConfigPath(extractDir);
|
|
@@ -46791,7 +46739,7 @@ var init_source_resolver = __esm(() => {
|
|
|
46791
46739
|
});
|
|
46792
46740
|
|
|
46793
46741
|
// src/domains/installers/codex/manifest-helpers.ts
|
|
46794
|
-
import { join as
|
|
46742
|
+
import { join as join69, relative as relative14, sep as sep7 } from "node:path";
|
|
46795
46743
|
async function collectCodexInstalledFiles(results, codexRoot) {
|
|
46796
46744
|
const out = [];
|
|
46797
46745
|
const toPosix = (p) => p.split(sep7).join("/");
|
|
@@ -46814,7 +46762,7 @@ async function collectCodexInstalledFiles(results, codexRoot) {
|
|
|
46814
46762
|
async function walkDir(dir, root, out, toPosix) {
|
|
46815
46763
|
const entries = await import_fs_extra33.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
46816
46764
|
for (const e2 of entries) {
|
|
46817
|
-
const p =
|
|
46765
|
+
const p = join69(dir, e2.name);
|
|
46818
46766
|
if (e2.isDirectory()) {
|
|
46819
46767
|
await walkDir(p, root, out, toPosix);
|
|
46820
46768
|
} else if (e2.isFile()) {
|
|
@@ -46857,22 +46805,9 @@ var init_write_codex_manifest = __esm(() => {
|
|
|
46857
46805
|
// src/domains/installers/codex/installer.ts
|
|
46858
46806
|
import { existsSync as existsSync30 } from "node:fs";
|
|
46859
46807
|
import { rm as rm6 } from "node:fs/promises";
|
|
46860
|
-
import {
|
|
46861
|
-
import { join as join69 } from "node:path";
|
|
46862
|
-
function codexGlobalRoot() {
|
|
46863
|
-
const testHome = process.env.TAKUMI_TEST_HOME;
|
|
46864
|
-
if (testHome && testHome.trim() !== "")
|
|
46865
|
-
return join69(testHome, ".codex");
|
|
46866
|
-
const codexHome = process.env.CODEX_HOME;
|
|
46867
|
-
if (codexHome && codexHome.trim() !== "" && !codexHome.includes(".."))
|
|
46868
|
-
return codexHome;
|
|
46869
|
-
const xdg = process.env.XDG_CONFIG_HOME;
|
|
46870
|
-
if (xdg && xdg.trim() !== "" && !xdg.includes(".."))
|
|
46871
|
-
return join69(xdg, "codex");
|
|
46872
|
-
return join69(homedir20(), ".codex");
|
|
46873
|
-
}
|
|
46808
|
+
import { join as join70 } from "node:path";
|
|
46874
46809
|
function resolveCodexRoot(ctx) {
|
|
46875
|
-
return ctx.options.global ? codexGlobalRoot() :
|
|
46810
|
+
return ctx.options.global ? codexGlobalRoot() : join70(ctx.resolvedDir ?? process.cwd(), ".codex");
|
|
46876
46811
|
}
|
|
46877
46812
|
async function resolveCodexEffectiveSelection(ctx, codexRoot) {
|
|
46878
46813
|
if (ctx.kitType === BASE_KIT) {
|
|
@@ -46900,7 +46835,7 @@ async function syncCodexSkillsLedger(args) {
|
|
|
46900
46835
|
}
|
|
46901
46836
|
const claims = [];
|
|
46902
46837
|
for (const name of args.keptSkills) {
|
|
46903
|
-
const dir =
|
|
46838
|
+
const dir = join70(skillsRoot, name);
|
|
46904
46839
|
try {
|
|
46905
46840
|
if (!existsSync30(dir))
|
|
46906
46841
|
continue;
|
|
@@ -46955,7 +46890,7 @@ async function wipeCodexTargets(global3, projectRoot) {
|
|
|
46955
46890
|
global3 ? codexConfig.config?.globalPath : codexConfig.config?.projectPath
|
|
46956
46891
|
].filter((p) => Boolean(p));
|
|
46957
46892
|
const projectBase = projectRoot ?? process.cwd();
|
|
46958
|
-
const targetPaths = rawPaths.map((p) => global3 ? p :
|
|
46893
|
+
const targetPaths = rawPaths.map((p) => global3 ? p : join70(projectBase, p));
|
|
46959
46894
|
for (const path5 of targetPaths) {
|
|
46960
46895
|
if (existsSync30(path5)) {
|
|
46961
46896
|
try {
|
|
@@ -46982,6 +46917,7 @@ var init_installer2 = __esm(() => {
|
|
|
46982
46917
|
init_types2();
|
|
46983
46918
|
init_dist2();
|
|
46984
46919
|
init_agent_prune();
|
|
46920
|
+
init_codex_paths();
|
|
46985
46921
|
init_install_pipeline();
|
|
46986
46922
|
init_scan_codex_directory();
|
|
46987
46923
|
init_skills_paths();
|
|
@@ -46996,7 +46932,7 @@ var init_installer2 = __esm(() => {
|
|
|
46996
46932
|
const root = this.globalRoot();
|
|
46997
46933
|
if (!existsSync30(root))
|
|
46998
46934
|
return false;
|
|
46999
|
-
return findManifestPathSync(root) !== null || existsSync30(
|
|
46935
|
+
return findManifestPathSync(root) !== null || existsSync30(join70(root, "AGENTS.md")) || existsSync30(join70(root, "agents")) || existsSync30(join70(root, "config.toml")) || existsSync30(join70(root, "prompts"));
|
|
47000
46936
|
},
|
|
47001
46937
|
async detectGlobalSetup() {
|
|
47002
46938
|
const root = this.globalRoot();
|
|
@@ -47195,12 +47131,12 @@ var require_umd = __commonJS((exports, module) => {
|
|
|
47195
47131
|
(function(global3, factory) {
|
|
47196
47132
|
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global3 = typeof globalThis !== "undefined" ? globalThis : global3 || self, factory(global3.compareVersions = {}));
|
|
47197
47133
|
})(exports, function(exports2) {
|
|
47198
|
-
const
|
|
47134
|
+
const semver4 = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
|
|
47199
47135
|
const validateAndParse = (version3) => {
|
|
47200
47136
|
if (typeof version3 !== "string") {
|
|
47201
47137
|
throw new TypeError("Invalid argument expected string");
|
|
47202
47138
|
}
|
|
47203
|
-
const match = version3.match(
|
|
47139
|
+
const match = version3.match(semver4);
|
|
47204
47140
|
if (!match) {
|
|
47205
47141
|
throw new Error(`Invalid argument not valid semver ('${version3}' received)`);
|
|
47206
47142
|
}
|
|
@@ -47302,7 +47238,7 @@ var require_umd = __commonJS((exports, module) => {
|
|
|
47302
47238
|
return false;
|
|
47303
47239
|
return true;
|
|
47304
47240
|
};
|
|
47305
|
-
const validate2 = (version3) => typeof version3 === "string" && /^[v\d]/.test(version3) &&
|
|
47241
|
+
const validate2 = (version3) => typeof version3 === "string" && /^[v\d]/.test(version3) && semver4.test(version3);
|
|
47306
47242
|
const validateStrict = (version3) => typeof version3 === "string" && /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(version3);
|
|
47307
47243
|
exports2.compare = compare;
|
|
47308
47244
|
exports2.compareVersions = compareVersions;
|
|
@@ -47362,7 +47298,7 @@ var init_version_utils = __esm(() => {
|
|
|
47362
47298
|
});
|
|
47363
47299
|
|
|
47364
47300
|
// src/domains/github/github-auth.ts
|
|
47365
|
-
import { execSync
|
|
47301
|
+
import { execSync } from "node:child_process";
|
|
47366
47302
|
|
|
47367
47303
|
class AuthManager {
|
|
47368
47304
|
static token = null;
|
|
@@ -47446,7 +47382,7 @@ Note: Do NOT use 'Paste an authentication token' - use web browser login.`);
|
|
|
47446
47382
|
static runDiagnostic() {
|
|
47447
47383
|
const info = [];
|
|
47448
47384
|
try {
|
|
47449
|
-
const version3 =
|
|
47385
|
+
const version3 = execSync("gh --version", {
|
|
47450
47386
|
encoding: "utf-8",
|
|
47451
47387
|
stdio: ["pipe", "pipe", "pipe"],
|
|
47452
47388
|
timeout: 3000
|
|
@@ -47457,7 +47393,7 @@ Note: Do NOT use 'Paste an authentication token' - use web browser login.`);
|
|
|
47457
47393
|
info.push(" gh version: failed to retrieve");
|
|
47458
47394
|
}
|
|
47459
47395
|
try {
|
|
47460
|
-
const status =
|
|
47396
|
+
const status = execSync("gh auth status -h github.com", {
|
|
47461
47397
|
encoding: "utf-8",
|
|
47462
47398
|
stdio: ["pipe", "pipe", "pipe"],
|
|
47463
47399
|
timeout: 5000
|
|
@@ -47483,7 +47419,7 @@ Note: Do NOT use 'Paste an authentication token' - use web browser login.`);
|
|
|
47483
47419
|
return AuthManager.ghCliInstalled;
|
|
47484
47420
|
}
|
|
47485
47421
|
try {
|
|
47486
|
-
|
|
47422
|
+
execSync("gh --version", {
|
|
47487
47423
|
stdio: "ignore",
|
|
47488
47424
|
timeout: 5000
|
|
47489
47425
|
});
|
|
@@ -47496,7 +47432,7 @@ Note: Do NOT use 'Paste an authentication token' - use web browser login.`);
|
|
|
47496
47432
|
}
|
|
47497
47433
|
static getFromGhCli() {
|
|
47498
47434
|
try {
|
|
47499
|
-
const token =
|
|
47435
|
+
const token = execSync("gh auth token -h github.com", {
|
|
47500
47436
|
encoding: "utf-8",
|
|
47501
47437
|
stdio: ["pipe", "pipe", "pipe"],
|
|
47502
47438
|
timeout: 5000
|
|
@@ -47511,7 +47447,7 @@ Note: Do NOT use 'Paste an authentication token' - use web browser login.`);
|
|
|
47511
47447
|
logger.debug(`gh auth token stderr: ${error.stderr.toString().trim()}`);
|
|
47512
47448
|
}
|
|
47513
47449
|
try {
|
|
47514
|
-
const token =
|
|
47450
|
+
const token = execSync("gh auth token", {
|
|
47515
47451
|
encoding: "utf-8",
|
|
47516
47452
|
stdio: ["pipe", "pipe", "pipe"],
|
|
47517
47453
|
timeout: 5000
|
|
@@ -47807,7 +47743,7 @@ var init_error_handler = __esm(() => {
|
|
|
47807
47743
|
// src/domains/versioning/release-cache.ts
|
|
47808
47744
|
import { existsSync as existsSync31 } from "node:fs";
|
|
47809
47745
|
import { mkdir as mkdir15, readFile as readFile34, unlink as unlink7, writeFile as writeFile21 } from "node:fs/promises";
|
|
47810
|
-
import { join as
|
|
47746
|
+
import { join as join71 } from "node:path";
|
|
47811
47747
|
var ReleaseCacheEntrySchema, ReleaseCache;
|
|
47812
47748
|
var init_release_cache = __esm(() => {
|
|
47813
47749
|
init_logger();
|
|
@@ -47822,7 +47758,7 @@ var init_release_cache = __esm(() => {
|
|
|
47822
47758
|
static CACHE_TTL_SECONDS = Number(process.env.TAKUMI_CACHE_TTL) || 3600;
|
|
47823
47759
|
cacheDir;
|
|
47824
47760
|
constructor() {
|
|
47825
|
-
this.cacheDir =
|
|
47761
|
+
this.cacheDir = join71(PathResolver.getCacheDir(false), ReleaseCache.CACHE_DIR);
|
|
47826
47762
|
}
|
|
47827
47763
|
async get(key) {
|
|
47828
47764
|
const cacheFile = this.getCachePath(key);
|
|
@@ -47880,7 +47816,7 @@ var init_release_cache = __esm(() => {
|
|
|
47880
47816
|
const files = await readdir24(this.cacheDir);
|
|
47881
47817
|
for (const file of files) {
|
|
47882
47818
|
if (file.endsWith(".json")) {
|
|
47883
|
-
await unlink7(
|
|
47819
|
+
await unlink7(join71(this.cacheDir, file));
|
|
47884
47820
|
}
|
|
47885
47821
|
}
|
|
47886
47822
|
logger.debug("All release cache cleared");
|
|
@@ -47891,7 +47827,7 @@ var init_release_cache = __esm(() => {
|
|
|
47891
47827
|
}
|
|
47892
47828
|
getCachePath(key) {
|
|
47893
47829
|
const safeKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
47894
|
-
return
|
|
47830
|
+
return join71(this.cacheDir, `${safeKey}.json`);
|
|
47895
47831
|
}
|
|
47896
47832
|
isExpired(timestamp) {
|
|
47897
47833
|
const now = Date.now();
|
|
@@ -48541,7 +48477,7 @@ var init_github_client = __esm(() => {
|
|
|
48541
48477
|
// src/domains/versioning/version-cache.ts
|
|
48542
48478
|
import { existsSync as existsSync32 } from "node:fs";
|
|
48543
48479
|
import { mkdir as mkdir16, readFile as readFile35, writeFile as writeFile22 } from "node:fs/promises";
|
|
48544
|
-
import { join as
|
|
48480
|
+
import { join as join72 } from "node:path";
|
|
48545
48481
|
var VersionCacheManager;
|
|
48546
48482
|
var init_version_cache = __esm(() => {
|
|
48547
48483
|
init_logger();
|
|
@@ -48551,7 +48487,7 @@ var init_version_cache = __esm(() => {
|
|
|
48551
48487
|
static CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
48552
48488
|
static getCacheFile() {
|
|
48553
48489
|
const cacheDir = PathResolver.getCacheDir(false);
|
|
48554
|
-
return
|
|
48490
|
+
return join72(cacheDir, VersionCacheManager.CACHE_FILENAME);
|
|
48555
48491
|
}
|
|
48556
48492
|
static async load() {
|
|
48557
48493
|
const cacheFile = VersionCacheManager.getCacheFile();
|
|
@@ -49007,18 +48943,18 @@ var init_version_display = __esm(() => {
|
|
|
49007
48943
|
|
|
49008
48944
|
// src/domains/auth/paths.ts
|
|
49009
48945
|
import { homedir as homedir21 } from "node:os";
|
|
49010
|
-
import { join as
|
|
48946
|
+
import { join as join73 } from "node:path";
|
|
49011
48947
|
function getConfigDir() {
|
|
49012
48948
|
const override = process.env.TAKUMI_HOME;
|
|
49013
48949
|
if (override && override.trim().length > 0)
|
|
49014
48950
|
return override;
|
|
49015
|
-
return
|
|
48951
|
+
return join73(homedir21(), STATE_DIRNAME);
|
|
49016
48952
|
}
|
|
49017
48953
|
function getAuthDir() {
|
|
49018
|
-
return
|
|
48954
|
+
return join73(getConfigDir(), "auth");
|
|
49019
48955
|
}
|
|
49020
48956
|
function getTokenPath() {
|
|
49021
|
-
return
|
|
48957
|
+
return join73(getAuthDir(), "token.json");
|
|
49022
48958
|
}
|
|
49023
48959
|
var init_paths2 = __esm(() => {
|
|
49024
48960
|
init_build_config();
|
|
@@ -49026,9 +48962,9 @@ var init_paths2 = __esm(() => {
|
|
|
49026
48962
|
|
|
49027
48963
|
// src/domains/auth/config-cache.ts
|
|
49028
48964
|
import { promises as fs } from "node:fs";
|
|
49029
|
-
import { join as
|
|
48965
|
+
import { join as join74 } from "node:path";
|
|
49030
48966
|
function getCachePath() {
|
|
49031
|
-
return
|
|
48967
|
+
return join74(getConfigDir(), "auth", "config.json");
|
|
49032
48968
|
}
|
|
49033
48969
|
async function readCachedConfig() {
|
|
49034
48970
|
try {
|
|
@@ -49052,7 +48988,7 @@ async function readCachedConfig() {
|
|
|
49052
48988
|
}
|
|
49053
48989
|
async function writeCachedConfig(config) {
|
|
49054
48990
|
const path5 = getCachePath();
|
|
49055
|
-
const dir =
|
|
48991
|
+
const dir = join74(getConfigDir(), "auth");
|
|
49056
48992
|
await fs.mkdir(dir, { recursive: true, mode: 448 });
|
|
49057
48993
|
const body = { ...config, cachedAt: Date.now() };
|
|
49058
48994
|
const fh = await fs.open(path5, "w", 384);
|
|
@@ -50611,12 +50547,12 @@ import {
|
|
|
50611
50547
|
rmSync as rmSync4,
|
|
50612
50548
|
writeFileSync as writeFileSync9
|
|
50613
50549
|
} from "node:fs";
|
|
50614
|
-
import { join as
|
|
50550
|
+
import { join as join104 } from "node:path";
|
|
50615
50551
|
function getStatuslineCacheDir() {
|
|
50616
|
-
return
|
|
50552
|
+
return join104(getConfigDir(), "cache", "statusline");
|
|
50617
50553
|
}
|
|
50618
50554
|
function getStatuslineCachePath(fileName) {
|
|
50619
|
-
return
|
|
50555
|
+
return join104(getStatuslineCacheDir(), fileName);
|
|
50620
50556
|
}
|
|
50621
50557
|
function ensureStatuslineCacheDir() {
|
|
50622
50558
|
try {
|
|
@@ -50682,7 +50618,7 @@ var init_cache_dir = __esm(() => {
|
|
|
50682
50618
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
50683
50619
|
import { closeSync as closeSync6, constants as fsConstants4, fstatSync as fstatSync2, openSync as openSync7, readFileSync as readFileSync15 } from "node:fs";
|
|
50684
50620
|
import { homedir as homedir28, platform as platform8 } from "node:os";
|
|
50685
|
-
import { join as
|
|
50621
|
+
import { join as join105 } from "node:path";
|
|
50686
50622
|
function hasAnthropicRuntimeOverride(env2 = process.env) {
|
|
50687
50623
|
return OVERRIDE_ENV_KEYS.some((key) => {
|
|
50688
50624
|
const value = env2[key];
|
|
@@ -50732,7 +50668,7 @@ function readTrustedFile(path10) {
|
|
|
50732
50668
|
}
|
|
50733
50669
|
}
|
|
50734
50670
|
function fromCredentialsFile() {
|
|
50735
|
-
const raw = readTrustedFile(
|
|
50671
|
+
const raw = readTrustedFile(join105(homedir28(), ".claude", ".credentials.json"));
|
|
50736
50672
|
if (!raw)
|
|
50737
50673
|
return null;
|
|
50738
50674
|
try {
|
|
@@ -50890,14 +50826,14 @@ var exports_monorepo_resolver = {};
|
|
|
50890
50826
|
__export(exports_monorepo_resolver, {
|
|
50891
50827
|
resolveMonorepoRoot: () => resolveMonorepoRoot
|
|
50892
50828
|
});
|
|
50893
|
-
import { existsSync as existsSync60, readFileSync as
|
|
50894
|
-
import { dirname as dirname34, join as
|
|
50829
|
+
import { existsSync as existsSync60, readFileSync as readFileSync26 } from "node:fs";
|
|
50830
|
+
import { dirname as dirname34, join as join130, resolve as resolve29 } from "node:path";
|
|
50895
50831
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
50896
50832
|
function parseMetadataAt(metadataPath) {
|
|
50897
50833
|
if (!existsSync60(metadataPath))
|
|
50898
50834
|
return null;
|
|
50899
50835
|
try {
|
|
50900
|
-
const raw =
|
|
50836
|
+
const raw = readFileSync26(metadataPath, "utf-8");
|
|
50901
50837
|
const parsed = JSON.parse(raw);
|
|
50902
50838
|
if (typeof parsed.name !== "string" || typeof parsed.version !== "string" || !ACCEPTED_METADATA_NAMES.has(parsed.name)) {
|
|
50903
50839
|
return null;
|
|
@@ -50908,11 +50844,11 @@ function parseMetadataAt(metadataPath) {
|
|
|
50908
50844
|
}
|
|
50909
50845
|
}
|
|
50910
50846
|
function readSourceDirFromPackageJson(candidateRoot) {
|
|
50911
|
-
const packageJsonPath =
|
|
50847
|
+
const packageJsonPath = join130(candidateRoot, "package.json");
|
|
50912
50848
|
if (!existsSync60(packageJsonPath))
|
|
50913
50849
|
return null;
|
|
50914
50850
|
try {
|
|
50915
|
-
const parsed = JSON.parse(
|
|
50851
|
+
const parsed = JSON.parse(readFileSync26(packageJsonPath, "utf-8"));
|
|
50916
50852
|
const kitCfg = parsed.takumi;
|
|
50917
50853
|
if (kitCfg && typeof kitCfg.sourceDir === "string" && kitCfg.sourceDir.length > 0) {
|
|
50918
50854
|
return kitCfg.sourceDir;
|
|
@@ -50931,7 +50867,7 @@ function tryReadAtCandidate(candidateRoot) {
|
|
|
50931
50867
|
};
|
|
50932
50868
|
}
|
|
50933
50869
|
const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
|
|
50934
|
-
const sourceRoot =
|
|
50870
|
+
const sourceRoot = join130(candidateRoot, sourceDir);
|
|
50935
50871
|
const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
|
|
50936
50872
|
if (nestedMetadata) {
|
|
50937
50873
|
return {
|
|
@@ -52025,8 +51961,8 @@ function renderHelp(help, context = { globalHelp: false, options: DEFAULT_HELP_O
|
|
|
52025
51961
|
const sections = [
|
|
52026
51962
|
renderBanner2(options2),
|
|
52027
51963
|
renderDeprecationWarning(help, theme),
|
|
52028
|
-
renderCommandHeader(help, theme)
|
|
52029
|
-
|
|
51964
|
+
`${renderCommandHeader(help, theme)}
|
|
51965
|
+
`,
|
|
52030
51966
|
renderUsage(help, theme),
|
|
52031
51967
|
renderExamples(help, options2),
|
|
52032
51968
|
renderOptionGroups(help, theme),
|
|
@@ -52132,7 +52068,7 @@ async function handleHelp(_args) {
|
|
|
52132
52068
|
output3 = renderHelp(help, {
|
|
52133
52069
|
command: help.name,
|
|
52134
52070
|
globalHelp: false,
|
|
52135
|
-
options: options2
|
|
52071
|
+
options: { ...options2, showBanner: false }
|
|
52136
52072
|
});
|
|
52137
52073
|
}
|
|
52138
52074
|
await displayHelp(output3, options2);
|
|
@@ -54082,9 +54018,9 @@ import { promises as fs9 } from "node:fs";
|
|
|
54082
54018
|
|
|
54083
54019
|
// src/domains/artifact/paths.ts
|
|
54084
54020
|
init_paths2();
|
|
54085
|
-
import { join as
|
|
54021
|
+
import { join as join75 } from "node:path";
|
|
54086
54022
|
function getManifestPath2() {
|
|
54087
|
-
return
|
|
54023
|
+
return join75(getConfigDir(), "artifacts.json");
|
|
54088
54024
|
}
|
|
54089
54025
|
|
|
54090
54026
|
// src/domains/artifact/manifest-store.ts
|
|
@@ -54277,13 +54213,13 @@ import { basename as basename11, resolve as resolve18 } from "node:path";
|
|
|
54277
54213
|
|
|
54278
54214
|
// src/domains/artifact/folder-download.ts
|
|
54279
54215
|
import { promises as fs10 } from "node:fs";
|
|
54280
|
-
import { dirname as dirname19, isAbsolute as isAbsolute4, join as
|
|
54216
|
+
import { dirname as dirname19, isAbsolute as isAbsolute4, join as join76, normalize as normalize5 } from "node:path";
|
|
54281
54217
|
var CONCURRENCY = 6;
|
|
54282
54218
|
function sanitizeFilePath(filePath, destDir) {
|
|
54283
54219
|
if (isAbsolute4(filePath)) {
|
|
54284
54220
|
throw new Error(`Path traversal rejected: absolute path "${filePath}"`);
|
|
54285
54221
|
}
|
|
54286
|
-
const resolved = normalize5(
|
|
54222
|
+
const resolved = normalize5(join76(destDir, filePath));
|
|
54287
54223
|
const safeBase = normalize5(destDir);
|
|
54288
54224
|
if (resolved !== safeBase && !resolved.startsWith(`${safeBase}/`)) {
|
|
54289
54225
|
throw new Error(`Path traversal rejected: "${filePath}" escapes destination directory`);
|
|
@@ -54697,7 +54633,7 @@ import { basename as basename12, extname as extname6, resolve as resolve19 } fro
|
|
|
54697
54633
|
// src/domains/artifact/folder-walk.ts
|
|
54698
54634
|
var import_ignore4 = __toESM(require_ignore(), 1);
|
|
54699
54635
|
import { promises as fs12 } from "node:fs";
|
|
54700
|
-
import { join as
|
|
54636
|
+
import { join as join77, relative as relative15 } from "node:path";
|
|
54701
54637
|
var MAX_FILE_BYTES = 20 * 1024 * 1024;
|
|
54702
54638
|
var IGNORE_FILES = [".gitignore", ".tkmignore"];
|
|
54703
54639
|
var HARD_IGNORES = [".git", ".gitignore", ".tkmignore"];
|
|
@@ -54713,7 +54649,7 @@ async function buildIgnoreMatcher(rootDir) {
|
|
|
54713
54649
|
const ig = import_ignore4.default();
|
|
54714
54650
|
for (const file of IGNORE_FILES) {
|
|
54715
54651
|
try {
|
|
54716
|
-
ig.add(await fs12.readFile(
|
|
54652
|
+
ig.add(await fs12.readFile(join77(rootDir, file), "utf8"));
|
|
54717
54653
|
} catch {}
|
|
54718
54654
|
}
|
|
54719
54655
|
ig.add(HARD_IGNORES);
|
|
@@ -54745,7 +54681,7 @@ async function walk2(rootDir, dir, ig, out, skipped) {
|
|
|
54745
54681
|
if (dirent.isSymbolicLink())
|
|
54746
54682
|
continue;
|
|
54747
54683
|
const name = String(dirent.name);
|
|
54748
|
-
const absPath =
|
|
54684
|
+
const absPath = join77(dir, name);
|
|
54749
54685
|
const relPath = relative15(rootDir, absPath).split("\\").join("/");
|
|
54750
54686
|
if (dirent.isDirectory()) {
|
|
54751
54687
|
if (ig.ignores(`${relPath}/`)) {
|
|
@@ -55295,14 +55231,14 @@ import { existsSync as existsSync33 } from "node:fs";
|
|
|
55295
55231
|
import { copyFile as copyFile4, mkdir as mkdir17, readFile as readFile36, rename as rename7, rm as rm7, writeFile as writeFile23 } from "node:fs/promises";
|
|
55296
55232
|
import { chmod as chmod2 } from "node:fs/promises";
|
|
55297
55233
|
import { homedir as homedir22, platform as platform4 } from "node:os";
|
|
55298
|
-
import { join as
|
|
55234
|
+
import { join as join78 } from "node:path";
|
|
55299
55235
|
var PROJECT_CONFIG_FILE = ".takumi.json";
|
|
55300
55236
|
|
|
55301
55237
|
class ConfigManager {
|
|
55302
55238
|
static config = null;
|
|
55303
55239
|
static globalFlag = false;
|
|
55304
55240
|
static getProjectConfigDir(projectDir, global3) {
|
|
55305
|
-
return global3 ? projectDir :
|
|
55241
|
+
return global3 ? projectDir : join78(projectDir, ".claude");
|
|
55306
55242
|
}
|
|
55307
55243
|
static setGlobalFlag(global3) {
|
|
55308
55244
|
ConfigManager.globalFlag = global3;
|
|
@@ -55316,7 +55252,7 @@ class ConfigManager {
|
|
|
55316
55252
|
return;
|
|
55317
55253
|
const testHome = process.env.TAKUMI_TEST_HOME;
|
|
55318
55254
|
const base = testHome && testHome.trim() !== "" ? testHome : homedir22();
|
|
55319
|
-
const legacyFile =
|
|
55255
|
+
const legacyFile = join78(base, ".sunagentkit", "config.json");
|
|
55320
55256
|
if (!existsSync33(legacyFile))
|
|
55321
55257
|
return;
|
|
55322
55258
|
const targetFile = PathResolver.getConfigFile(false);
|
|
@@ -55401,7 +55337,7 @@ class ConfigManager {
|
|
|
55401
55337
|
}
|
|
55402
55338
|
static async loadProjectConfig(projectDir, global3 = false) {
|
|
55403
55339
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
55404
|
-
const configPath =
|
|
55340
|
+
const configPath = join78(configDir, PROJECT_CONFIG_FILE);
|
|
55405
55341
|
try {
|
|
55406
55342
|
if (existsSync33(configPath)) {
|
|
55407
55343
|
const content = await readFile36(configPath, "utf-8");
|
|
@@ -55417,7 +55353,7 @@ class ConfigManager {
|
|
|
55417
55353
|
}
|
|
55418
55354
|
static async saveProjectConfig(projectDir, folders, global3 = false) {
|
|
55419
55355
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
55420
|
-
const configPath =
|
|
55356
|
+
const configPath = join78(configDir, PROJECT_CONFIG_FILE);
|
|
55421
55357
|
try {
|
|
55422
55358
|
if (!existsSync33(configDir)) {
|
|
55423
55359
|
await mkdir17(configDir, { recursive: true });
|
|
@@ -55466,11 +55402,11 @@ class ConfigManager {
|
|
|
55466
55402
|
}
|
|
55467
55403
|
static projectConfigExists(projectDir, global3 = false) {
|
|
55468
55404
|
const configDir = ConfigManager.getProjectConfigDir(projectDir, global3);
|
|
55469
|
-
return existsSync33(
|
|
55405
|
+
return existsSync33(join78(configDir, PROJECT_CONFIG_FILE));
|
|
55470
55406
|
}
|
|
55471
55407
|
static async migrateNestedConfig(globalDir) {
|
|
55472
|
-
const correctPath =
|
|
55473
|
-
const incorrectPath =
|
|
55408
|
+
const correctPath = join78(globalDir, PROJECT_CONFIG_FILE);
|
|
55409
|
+
const incorrectPath = join78(globalDir, ".claude", PROJECT_CONFIG_FILE);
|
|
55474
55410
|
if (existsSync33(correctPath)) {
|
|
55475
55411
|
logger.debug("Config already exists at correct location, skipping migration");
|
|
55476
55412
|
return false;
|
|
@@ -55480,7 +55416,7 @@ class ConfigManager {
|
|
|
55480
55416
|
logger.info("Migrating .takumi.json from nested location to correct location...");
|
|
55481
55417
|
await rename7(incorrectPath, correctPath);
|
|
55482
55418
|
logger.success(`Migrated ${PROJECT_CONFIG_FILE} to ${correctPath}`);
|
|
55483
|
-
const nestedClaudeDir =
|
|
55419
|
+
const nestedClaudeDir = join78(globalDir, ".claude");
|
|
55484
55420
|
try {
|
|
55485
55421
|
await rm7(nestedClaudeDir, { recursive: false });
|
|
55486
55422
|
logger.debug("Removed empty nested .claude directory");
|
|
@@ -57180,7 +57116,7 @@ function filterSessionMetas(metas, filter) {
|
|
|
57180
57116
|
// src/domains/sessions/store/ingest.ts
|
|
57181
57117
|
import { createHash as createHash10 } from "node:crypto";
|
|
57182
57118
|
import { closeSync as closeSync4, openSync as openSync4, readSync as readSync4, readdirSync as readdirSync7, statSync as statSync5 } from "node:fs";
|
|
57183
|
-
import { basename as basename15, dirname as dirname21, join as
|
|
57119
|
+
import { basename as basename15, dirname as dirname21, join as join82 } from "node:path";
|
|
57184
57120
|
|
|
57185
57121
|
// node_modules/kysely/dist/util/object-utils.js
|
|
57186
57122
|
function isUndefined(obj) {
|
|
@@ -58612,10 +58548,10 @@ var QueryNode = freeze({
|
|
|
58612
58548
|
where: node.where ? WhereNode.cloneWithOperation(node.where, "And", operation) : WhereNode.create(operation)
|
|
58613
58549
|
});
|
|
58614
58550
|
},
|
|
58615
|
-
cloneWithJoin(node,
|
|
58551
|
+
cloneWithJoin(node, join81) {
|
|
58616
58552
|
return freeze({
|
|
58617
58553
|
...node,
|
|
58618
|
-
joins: node.joins ? freeze([...node.joins,
|
|
58554
|
+
joins: node.joins ? freeze([...node.joins, join81]) : freeze([join81])
|
|
58619
58555
|
});
|
|
58620
58556
|
},
|
|
58621
58557
|
cloneWithReturning(node, selections) {
|
|
@@ -61166,8 +61102,8 @@ class WithSchemaTransformer extends OperationNodeTransformer {
|
|
|
61166
61102
|
this.#collectSchemableIdsFromTableExpr(node.table, schemableIds);
|
|
61167
61103
|
}
|
|
61168
61104
|
if ("joins" in node && node.joins) {
|
|
61169
|
-
for (const
|
|
61170
|
-
this.#collectSchemableIdsFromTableExpr(
|
|
61105
|
+
for (const join81 of node.joins) {
|
|
61106
|
+
this.#collectSchemableIdsFromTableExpr(join81.table, schemableIds);
|
|
61171
61107
|
}
|
|
61172
61108
|
}
|
|
61173
61109
|
if ("using" in node && node.using) {
|
|
@@ -66439,7 +66375,7 @@ var import_proper_lockfile8 = __toESM(require_proper_lockfile(), 1);
|
|
|
66439
66375
|
|
|
66440
66376
|
// src/domains/sessions/store/db.ts
|
|
66441
66377
|
import { promises as fs17 } from "node:fs";
|
|
66442
|
-
import { join as
|
|
66378
|
+
import { join as join81 } from "node:path";
|
|
66443
66379
|
init_logger();
|
|
66444
66380
|
init_paths2();
|
|
66445
66381
|
|
|
@@ -66534,10 +66470,10 @@ class StoreUnavailableError extends Error {
|
|
|
66534
66470
|
|
|
66535
66471
|
// src/domains/sessions/store/db.ts
|
|
66536
66472
|
function getConsoleStoreDir() {
|
|
66537
|
-
return
|
|
66473
|
+
return join81(getConfigDir(), "console");
|
|
66538
66474
|
}
|
|
66539
66475
|
function getConsoleStorePath() {
|
|
66540
|
-
return
|
|
66476
|
+
return join81(getConsoleStoreDir(), "store.sqlite");
|
|
66541
66477
|
}
|
|
66542
66478
|
async function chmodSafe2(path8, mode) {
|
|
66543
66479
|
try {
|
|
@@ -66806,7 +66742,7 @@ async function ingestFile(handle, target) {
|
|
|
66806
66742
|
}
|
|
66807
66743
|
function subagentDirFor(mainPath) {
|
|
66808
66744
|
const stem = basename15(mainPath).replace(/\.jsonl$/i, "");
|
|
66809
|
-
return
|
|
66745
|
+
return join82(dirname21(mainPath), stem, "subagents");
|
|
66810
66746
|
}
|
|
66811
66747
|
async function enumerateTargets(refresh2 = false) {
|
|
66812
66748
|
const sessions = await list({ refresh: refresh2 });
|
|
@@ -66828,7 +66764,7 @@ async function enumerateTargets(refresh2 = false) {
|
|
|
66828
66764
|
} catch {}
|
|
66829
66765
|
for (const f3 of files) {
|
|
66830
66766
|
targets.push({
|
|
66831
|
-
path:
|
|
66767
|
+
path: join82(dir, f3),
|
|
66832
66768
|
adapter: "claude",
|
|
66833
66769
|
sessionId: s.id,
|
|
66834
66770
|
project: s.project,
|
|
@@ -66839,7 +66775,7 @@ async function enumerateTargets(refresh2 = false) {
|
|
|
66839
66775
|
return targets;
|
|
66840
66776
|
}
|
|
66841
66777
|
async function withIngestLock(fn) {
|
|
66842
|
-
const lockPath =
|
|
66778
|
+
const lockPath = join82(getConsoleStoreDir(), "ingest");
|
|
66843
66779
|
let release;
|
|
66844
66780
|
try {
|
|
66845
66781
|
release = await import_proper_lockfile8.default.lock(lockPath, { stale: 60000, retries: 0, realpath: false });
|
|
@@ -68647,7 +68583,7 @@ init_takumi_constants();
|
|
|
68647
68583
|
import { existsSync as existsSync38, realpathSync } from "node:fs";
|
|
68648
68584
|
import { chmod as chmod3, mkdir as mkdir18, readFile as readFile37, writeFile as writeFile24 } from "node:fs/promises";
|
|
68649
68585
|
import { platform as platform5 } from "node:os";
|
|
68650
|
-
import { join as
|
|
68586
|
+
import { join as join83 } from "node:path";
|
|
68651
68587
|
var CACHE_FILE = "install-info.json";
|
|
68652
68588
|
var CACHE_TTL = 30 * 24 * 60 * 60 * 1000;
|
|
68653
68589
|
function detectFromBinaryPath() {
|
|
@@ -68731,7 +68667,7 @@ function detectFromEnv() {
|
|
|
68731
68667
|
}
|
|
68732
68668
|
async function readCachedPm() {
|
|
68733
68669
|
try {
|
|
68734
|
-
const cacheFile =
|
|
68670
|
+
const cacheFile = join83(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
68735
68671
|
if (!existsSync38(cacheFile)) {
|
|
68736
68672
|
return null;
|
|
68737
68673
|
}
|
|
@@ -68762,7 +68698,7 @@ async function saveCachedPm(pm, getVersion) {
|
|
|
68762
68698
|
return;
|
|
68763
68699
|
try {
|
|
68764
68700
|
const configDir = PathResolver.getConfigDir(false);
|
|
68765
|
-
const cacheFile =
|
|
68701
|
+
const cacheFile = join83(configDir, CACHE_FILE);
|
|
68766
68702
|
if (!existsSync38(configDir)) {
|
|
68767
68703
|
await mkdir18(configDir, { recursive: true });
|
|
68768
68704
|
if (platform5() !== "win32") {
|
|
@@ -68825,7 +68761,7 @@ async function findOwningPm() {
|
|
|
68825
68761
|
async function clearCache() {
|
|
68826
68762
|
try {
|
|
68827
68763
|
const { unlink: unlink8 } = await import("node:fs/promises");
|
|
68828
|
-
const cacheFile =
|
|
68764
|
+
const cacheFile = join83(PathResolver.getConfigDir(false), CACHE_FILE);
|
|
68829
68765
|
if (existsSync38(cacheFile)) {
|
|
68830
68766
|
await unlink8(cacheFile);
|
|
68831
68767
|
logger.debug("Package manager cache cleared");
|
|
@@ -69087,17 +69023,17 @@ async function checkCliVersion() {
|
|
|
69087
69023
|
init_paths();
|
|
69088
69024
|
init_registry();
|
|
69089
69025
|
import { existsSync as existsSync39, statSync as statSync7 } from "node:fs";
|
|
69090
|
-
import { join as
|
|
69026
|
+
import { join as join84 } from "node:path";
|
|
69091
69027
|
function checkClaudeMd(setup, projectDir) {
|
|
69092
69028
|
const results = [];
|
|
69093
69029
|
const claudeCodeInstaller2 = getInstaller("claude-code");
|
|
69094
69030
|
if (claudeCodeInstaller2?.isInstalledGlobally()) {
|
|
69095
69031
|
const claudeGlobal = setup.globals.find((g2) => g2.provider === "claude-code") ?? setup.globals[0];
|
|
69096
69032
|
const globalPath = claudeGlobal?.path ?? claudeCodeInstaller2.globalRoot();
|
|
69097
|
-
const globalClaudeMd =
|
|
69033
|
+
const globalClaudeMd = join84(globalPath, "CLAUDE.md");
|
|
69098
69034
|
results.push(checkClaudeMdFile(globalClaudeMd, "Global CLAUDE.md", "tkm-global-claude-md"));
|
|
69099
69035
|
}
|
|
69100
|
-
const projectClaudeMd =
|
|
69036
|
+
const projectClaudeMd = join84(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
69101
69037
|
results.push(checkClaudeMdFile(projectClaudeMd, "Project CLAUDE.md", "tkm-project-claude-md"));
|
|
69102
69038
|
return results;
|
|
69103
69039
|
}
|
|
@@ -69156,9 +69092,9 @@ function checkClaudeMdFile(path8, name2, id) {
|
|
|
69156
69092
|
}
|
|
69157
69093
|
// src/domains/health-checks/checkers/active-plan-checker.ts
|
|
69158
69094
|
import { existsSync as existsSync40, readFileSync as readFileSync10 } from "node:fs";
|
|
69159
|
-
import { join as
|
|
69095
|
+
import { join as join85 } from "node:path";
|
|
69160
69096
|
function checkActivePlan(projectDir) {
|
|
69161
|
-
const activePlanPath =
|
|
69097
|
+
const activePlanPath = join85(projectDir, ".claude", "active-plan");
|
|
69162
69098
|
if (!existsSync40(activePlanPath)) {
|
|
69163
69099
|
return {
|
|
69164
69100
|
id: "tkm-active-plan",
|
|
@@ -69172,7 +69108,7 @@ function checkActivePlan(projectDir) {
|
|
|
69172
69108
|
}
|
|
69173
69109
|
try {
|
|
69174
69110
|
const targetPath = readFileSync10(activePlanPath, "utf-8").trim();
|
|
69175
|
-
const fullPath =
|
|
69111
|
+
const fullPath = join85(projectDir, targetPath);
|
|
69176
69112
|
if (!existsSync40(fullPath)) {
|
|
69177
69113
|
return {
|
|
69178
69114
|
id: "tkm-active-plan",
|
|
@@ -69238,7 +69174,7 @@ function checkComponentCounts(setup) {
|
|
|
69238
69174
|
init_registry();
|
|
69239
69175
|
init_logger();
|
|
69240
69176
|
import { constants, access, unlink as unlink8, writeFile as writeFile25 } from "node:fs/promises";
|
|
69241
|
-
import { join as
|
|
69177
|
+
import { join as join86 } from "node:path";
|
|
69242
69178
|
|
|
69243
69179
|
// src/domains/health-checks/checkers/shared.ts
|
|
69244
69180
|
init_registry();
|
|
@@ -69313,7 +69249,7 @@ async function checkGlobalDirWritable(provider) {
|
|
|
69313
69249
|
}
|
|
69314
69250
|
const timestamp = Date.now();
|
|
69315
69251
|
const random = Math.random().toString(36).substring(2);
|
|
69316
|
-
const testFile =
|
|
69252
|
+
const testFile = join86(globalDir, `.tkm-write-test-${timestamp}-${random}`);
|
|
69317
69253
|
try {
|
|
69318
69254
|
await writeFile25(testFile, "test", { encoding: "utf-8", flag: "wx" });
|
|
69319
69255
|
} catch (_error) {
|
|
@@ -69350,7 +69286,7 @@ init_paths();
|
|
|
69350
69286
|
init_registry();
|
|
69351
69287
|
import { existsSync as existsSync41 } from "node:fs";
|
|
69352
69288
|
import { readdir as readdir24 } from "node:fs/promises";
|
|
69353
|
-
import { join as
|
|
69289
|
+
import { join as join87 } from "node:path";
|
|
69354
69290
|
|
|
69355
69291
|
// src/domains/health-checks/utils/path-normalizer.ts
|
|
69356
69292
|
import { normalize as normalize6 } from "node:path";
|
|
@@ -69362,8 +69298,8 @@ function normalizePath(filePath) {
|
|
|
69362
69298
|
|
|
69363
69299
|
// src/domains/health-checks/checkers/hooks-checker.ts
|
|
69364
69300
|
async function checkHooksExist(projectDir) {
|
|
69365
|
-
const globalHooksDir =
|
|
69366
|
-
const projectHooksDir =
|
|
69301
|
+
const globalHooksDir = join87(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
|
|
69302
|
+
const projectHooksDir = join87(getLocalClaudeDir(projectDir), "hooks");
|
|
69367
69303
|
const globalExists = existsSync41(globalHooksDir);
|
|
69368
69304
|
const projectExists = existsSync41(projectHooksDir);
|
|
69369
69305
|
let hookCount = 0;
|
|
@@ -69372,7 +69308,7 @@ async function checkHooksExist(projectDir) {
|
|
|
69372
69308
|
const files = await readdir24(globalHooksDir, { withFileTypes: false });
|
|
69373
69309
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext) => f3.endsWith(ext)));
|
|
69374
69310
|
hooks.forEach((hook) => {
|
|
69375
|
-
const fullPath =
|
|
69311
|
+
const fullPath = join87(globalHooksDir, hook);
|
|
69376
69312
|
checkedFiles.add(normalizePath(fullPath));
|
|
69377
69313
|
});
|
|
69378
69314
|
}
|
|
@@ -69382,7 +69318,7 @@ async function checkHooksExist(projectDir) {
|
|
|
69382
69318
|
const files = await readdir24(projectHooksDir, { withFileTypes: false });
|
|
69383
69319
|
const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext) => f3.endsWith(ext)));
|
|
69384
69320
|
hooks.forEach((hook) => {
|
|
69385
|
-
const fullPath =
|
|
69321
|
+
const fullPath = join87(projectHooksDir, hook);
|
|
69386
69322
|
checkedFiles.add(normalizePath(fullPath));
|
|
69387
69323
|
});
|
|
69388
69324
|
}
|
|
@@ -69413,14 +69349,14 @@ async function checkHooksExist(projectDir) {
|
|
|
69413
69349
|
init_registry();
|
|
69414
69350
|
import { existsSync as existsSync42 } from "node:fs";
|
|
69415
69351
|
import { readFile as readFile38 } from "node:fs/promises";
|
|
69416
|
-
import { join as
|
|
69352
|
+
import { join as join88 } from "node:path";
|
|
69417
69353
|
async function checkCodexHooksHealth() {
|
|
69418
69354
|
const codex = getInstaller("codex");
|
|
69419
69355
|
if (!codex?.isInstalledGlobally())
|
|
69420
69356
|
return [];
|
|
69421
69357
|
const codexRoot = codex.globalRoot();
|
|
69422
|
-
const configTomlPath =
|
|
69423
|
-
const hooksJsonPath =
|
|
69358
|
+
const configTomlPath = join88(codexRoot, "config.toml");
|
|
69359
|
+
const hooksJsonPath = join88(codexRoot, "hooks.json");
|
|
69424
69360
|
if (!existsSync42(hooksJsonPath))
|
|
69425
69361
|
return [];
|
|
69426
69362
|
const results = [];
|
|
@@ -69532,10 +69468,10 @@ init_registry();
|
|
|
69532
69468
|
init_logger();
|
|
69533
69469
|
import { existsSync as existsSync43 } from "node:fs";
|
|
69534
69470
|
import { readFile as readFile39 } from "node:fs/promises";
|
|
69535
|
-
import { join as
|
|
69471
|
+
import { join as join89 } from "node:path";
|
|
69536
69472
|
async function checkSettingsValid(projectDir) {
|
|
69537
|
-
const globalSettings =
|
|
69538
|
-
const projectSettings =
|
|
69473
|
+
const globalSettings = join89(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
|
|
69474
|
+
const projectSettings = join89(getLocalClaudeDir(projectDir), "settings.json");
|
|
69539
69475
|
const settingsPath = existsSync43(globalSettings) ? globalSettings : existsSync43(projectSettings) ? projectSettings : null;
|
|
69540
69476
|
if (!settingsPath) {
|
|
69541
69477
|
return {
|
|
@@ -69609,10 +69545,10 @@ init_logger();
|
|
|
69609
69545
|
import { existsSync as existsSync44 } from "node:fs";
|
|
69610
69546
|
import { readFile as readFile40 } from "node:fs/promises";
|
|
69611
69547
|
import { homedir as homedir25 } from "node:os";
|
|
69612
|
-
import { dirname as dirname22, join as
|
|
69548
|
+
import { dirname as dirname22, join as join90, normalize as normalize7, resolve as resolve22 } from "node:path";
|
|
69613
69549
|
async function checkPathRefsValid(projectDir) {
|
|
69614
|
-
const globalClaudeMd =
|
|
69615
|
-
const projectClaudeMd =
|
|
69550
|
+
const globalClaudeMd = join90(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
|
|
69551
|
+
const projectClaudeMd = join90(getLocalClaudeDir(projectDir), "CLAUDE.md");
|
|
69616
69552
|
const claudeMdPath = existsSync44(globalClaudeMd) ? globalClaudeMd : existsSync44(projectClaudeMd) ? projectClaudeMd : null;
|
|
69617
69553
|
if (!claudeMdPath) {
|
|
69618
69554
|
return {
|
|
@@ -69708,7 +69644,7 @@ async function checkPathRefsValid(projectDir) {
|
|
|
69708
69644
|
init_paths();
|
|
69709
69645
|
import { existsSync as existsSync45 } from "node:fs";
|
|
69710
69646
|
import { readdir as readdir25 } from "node:fs/promises";
|
|
69711
|
-
import { join as
|
|
69647
|
+
import { join as join91 } from "node:path";
|
|
69712
69648
|
async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
69713
69649
|
if (setup.globals.some((g2) => g2.path === setup.project.path)) {
|
|
69714
69650
|
return {
|
|
@@ -69725,12 +69661,12 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
|
|
|
69725
69661
|
const requiredDirs = ["agents", "commands", "skills"];
|
|
69726
69662
|
const missingDirs = [];
|
|
69727
69663
|
for (const dir of requiredDirs) {
|
|
69728
|
-
const dirPath =
|
|
69664
|
+
const dirPath = join91(projectClaudeDir, dir);
|
|
69729
69665
|
if (!existsSync45(dirPath)) {
|
|
69730
69666
|
missingDirs.push(dir);
|
|
69731
69667
|
}
|
|
69732
69668
|
}
|
|
69733
|
-
const hasRulesOrWorkflows = existsSync45(
|
|
69669
|
+
const hasRulesOrWorkflows = existsSync45(join91(projectClaudeDir, "rules")) || existsSync45(join91(projectClaudeDir, "workflows"));
|
|
69734
69670
|
if (!hasRulesOrWorkflows) {
|
|
69735
69671
|
missingDirs.push("rules");
|
|
69736
69672
|
}
|
|
@@ -69829,7 +69765,7 @@ import { spawnSync as spawnSync3 } from "node:child_process";
|
|
|
69829
69765
|
// src/domains/installation/git-clone-manager.ts
|
|
69830
69766
|
init_build_config();
|
|
69831
69767
|
init_logger();
|
|
69832
|
-
import { execSync as
|
|
69768
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
69833
69769
|
import * as fs19 from "node:fs";
|
|
69834
69770
|
import * as os6 from "node:os";
|
|
69835
69771
|
import * as path8 from "node:path";
|
|
@@ -69868,7 +69804,7 @@ Check disk space and directory permissions.`);
|
|
|
69868
69804
|
const quotedUrl = `"${url}"`;
|
|
69869
69805
|
const quotedDir = `"${tempDir}"`;
|
|
69870
69806
|
try {
|
|
69871
|
-
|
|
69807
|
+
execSync2(`git clone --depth 1 --branch "${tag}" ${quotedUrl} ${quotedDir}`, {
|
|
69872
69808
|
stdio: ["pipe", "pipe", "pipe"],
|
|
69873
69809
|
timeout,
|
|
69874
69810
|
encoding: "utf-8"
|
|
@@ -69879,12 +69815,12 @@ Check disk space and directory permissions.`);
|
|
|
69879
69815
|
logger.debug(`Shallow clone failed for tag ${tag}, trying full clone...`);
|
|
69880
69816
|
await fs19.promises.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
69881
69817
|
await fs19.promises.mkdir(tempDir, { recursive: true });
|
|
69882
|
-
|
|
69818
|
+
execSync2(`git clone --no-checkout ${quotedUrl} ${quotedDir}`, {
|
|
69883
69819
|
stdio: ["pipe", "pipe", "pipe"],
|
|
69884
69820
|
timeout,
|
|
69885
69821
|
encoding: "utf-8"
|
|
69886
69822
|
});
|
|
69887
|
-
|
|
69823
|
+
execSync2(`git -C ${quotedDir} checkout "tags/${tag}"`, {
|
|
69888
69824
|
stdio: ["pipe", "pipe", "pipe"],
|
|
69889
69825
|
timeout: 30000,
|
|
69890
69826
|
encoding: "utf-8"
|
|
@@ -69932,7 +69868,7 @@ Ensure you have access to the repository and your git credentials are configured
|
|
|
69932
69868
|
}
|
|
69933
69869
|
static isGitInstalled() {
|
|
69934
69870
|
try {
|
|
69935
|
-
|
|
69871
|
+
execSync2("git --version", { stdio: "ignore", timeout: 5000 });
|
|
69936
69872
|
return true;
|
|
69937
69873
|
} catch {
|
|
69938
69874
|
return false;
|
|
@@ -69957,7 +69893,7 @@ Ensure you have access to the repository and your git credentials are configured
|
|
|
69957
69893
|
}
|
|
69958
69894
|
static async testSshConnection() {
|
|
69959
69895
|
try {
|
|
69960
|
-
|
|
69896
|
+
execSync2("ssh -T git@github.com 2>&1 || true", {
|
|
69961
69897
|
encoding: "utf-8",
|
|
69962
69898
|
timeout: 1e4
|
|
69963
69899
|
});
|
|
@@ -70172,7 +70108,7 @@ init_registry();
|
|
|
70172
70108
|
init_environment();
|
|
70173
70109
|
import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile41, unlink as unlink9, writeFile as writeFile26 } from "node:fs/promises";
|
|
70174
70110
|
import { arch as arch2, homedir as homedir26, platform as platform6 } from "node:os";
|
|
70175
|
-
import { join as
|
|
70111
|
+
import { join as join93, normalize as normalize8 } from "node:path";
|
|
70176
70112
|
function shouldSkipExpensiveOperations4() {
|
|
70177
70113
|
return shouldSkipExpensiveOperations();
|
|
70178
70114
|
}
|
|
@@ -70265,7 +70201,7 @@ async function checkGlobalDirAccess(provider) {
|
|
|
70265
70201
|
autoFixable: false
|
|
70266
70202
|
};
|
|
70267
70203
|
}
|
|
70268
|
-
const testFile =
|
|
70204
|
+
const testFile = join93(globalDir, ".tkm-doctor-access-test");
|
|
70269
70205
|
try {
|
|
70270
70206
|
await mkdir19(globalDir, { recursive: true });
|
|
70271
70207
|
await writeFile26(testFile, "test", "utf-8");
|
|
@@ -70343,7 +70279,7 @@ async function checkWSLBoundary() {
|
|
|
70343
70279
|
// src/domains/health-checks/platform/windows-checker.ts
|
|
70344
70280
|
init_registry();
|
|
70345
70281
|
import { mkdir as mkdir20, symlink as symlink2, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
|
|
70346
|
-
import { join as
|
|
70282
|
+
import { join as join94 } from "node:path";
|
|
70347
70283
|
async function checkLongPathSupport() {
|
|
70348
70284
|
if (shouldSkipExpensiveOperations4()) {
|
|
70349
70285
|
return {
|
|
@@ -70357,8 +70293,8 @@ async function checkLongPathSupport() {
|
|
|
70357
70293
|
};
|
|
70358
70294
|
}
|
|
70359
70295
|
try {
|
|
70360
|
-
const { execSync:
|
|
70361
|
-
const result =
|
|
70296
|
+
const { execSync: execSync3 } = await import("node:child_process");
|
|
70297
|
+
const result = execSync3('reg query "HKLM\\SYSTEM\\CurrentControlSet\\Control\\FileSystem" /v LongPathsEnabled', { encoding: "utf-8", timeout: 2000 });
|
|
70362
70298
|
const enabled = result.includes("0x1");
|
|
70363
70299
|
return {
|
|
70364
70300
|
id: "long-path-support",
|
|
@@ -70395,8 +70331,8 @@ async function checkSymlinkSupport() {
|
|
|
70395
70331
|
};
|
|
70396
70332
|
}
|
|
70397
70333
|
const testDir = getInstaller("claude-code")?.globalRoot() ?? "";
|
|
70398
|
-
const target =
|
|
70399
|
-
const link =
|
|
70334
|
+
const target = join94(testDir, ".tkm-symlink-test-target");
|
|
70335
|
+
const link = join94(testDir, ".tkm-symlink-test-link");
|
|
70400
70336
|
try {
|
|
70401
70337
|
await mkdir20(testDir, { recursive: true });
|
|
70402
70338
|
await writeFile27(target, "test", "utf-8");
|
|
@@ -70689,10 +70625,10 @@ class AutoHealer {
|
|
|
70689
70625
|
}
|
|
70690
70626
|
}
|
|
70691
70627
|
// src/domains/health-checks/report-generator.ts
|
|
70692
|
-
import { execSync as
|
|
70628
|
+
import { execSync as execSync3, spawnSync as spawnSync4 } from "node:child_process";
|
|
70693
70629
|
import { readFileSync as readFileSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
70694
70630
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
70695
|
-
import { dirname as dirname23, join as
|
|
70631
|
+
import { dirname as dirname23, join as join95 } from "node:path";
|
|
70696
70632
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
70697
70633
|
init_environment();
|
|
70698
70634
|
init_logger();
|
|
@@ -70700,7 +70636,7 @@ init_dist2();
|
|
|
70700
70636
|
function getCliVersion3() {
|
|
70701
70637
|
try {
|
|
70702
70638
|
const __dirname3 = dirname23(fileURLToPath2(import.meta.url));
|
|
70703
|
-
const pkgPath =
|
|
70639
|
+
const pkgPath = join95(__dirname3, "../../../package.json");
|
|
70704
70640
|
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
70705
70641
|
return pkg.version || "unknown";
|
|
70706
70642
|
} catch (err) {
|
|
@@ -70825,7 +70761,7 @@ class ReportGenerator {
|
|
|
70825
70761
|
}
|
|
70826
70762
|
async uploadToGist(report) {
|
|
70827
70763
|
try {
|
|
70828
|
-
|
|
70764
|
+
execSync3("gh --version", { stdio: "ignore" });
|
|
70829
70765
|
} catch {
|
|
70830
70766
|
logger.warning("GitHub CLI not installed, skipping gist upload");
|
|
70831
70767
|
return null;
|
|
@@ -70839,7 +70775,7 @@ class ReportGenerator {
|
|
|
70839
70775
|
return null;
|
|
70840
70776
|
}
|
|
70841
70777
|
}
|
|
70842
|
-
const tmpFile =
|
|
70778
|
+
const tmpFile = join95(tmpdir2(), `tkm-report-${Date.now()}.txt`);
|
|
70843
70779
|
writeFileSync6(tmpFile, report);
|
|
70844
70780
|
try {
|
|
70845
70781
|
const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "Takumi Diagnostic Report"], {
|
|
@@ -71159,12 +71095,12 @@ var conventionDescriptiveName = {
|
|
|
71159
71095
|
};
|
|
71160
71096
|
|
|
71161
71097
|
// src/domains/hooks/handlers/convention-quality-gate/command-runner.ts
|
|
71162
|
-
import { execSync as
|
|
71098
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
71163
71099
|
|
|
71164
71100
|
// src/domains/hooks/handlers/_shared/env-file.ts
|
|
71165
71101
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
71166
71102
|
import { renameSync as renameSync2, unlinkSync as unlinkSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
71167
|
-
import { basename as basename16, dirname as dirname24, join as
|
|
71103
|
+
import { basename as basename16, dirname as dirname24, join as join96 } from "node:path";
|
|
71168
71104
|
function hexEscape(code) {
|
|
71169
71105
|
return `\\x${code.toString(16).padStart(2, "0")}`;
|
|
71170
71106
|
}
|
|
@@ -71217,7 +71153,7 @@ function renderEnvFile(entries) {
|
|
|
71217
71153
|
function writeEnvFile(filePath, entries) {
|
|
71218
71154
|
const content = renderEnvFile(entries);
|
|
71219
71155
|
const dir = dirname24(filePath);
|
|
71220
|
-
const tmpPath =
|
|
71156
|
+
const tmpPath = join96(dir, `.${basename16(filePath)}.${randomUUID2()}.tmp`);
|
|
71221
71157
|
try {
|
|
71222
71158
|
writeFileSync7(tmpPath, content, { encoding: "utf8", mode: 384 });
|
|
71223
71159
|
} catch (err) {
|
|
@@ -71244,7 +71180,7 @@ function substituteFileToken(command, filePath) {
|
|
|
71244
71180
|
}
|
|
71245
71181
|
var defaultCommandRunner = (command, opts) => {
|
|
71246
71182
|
try {
|
|
71247
|
-
|
|
71183
|
+
execSync4(command, {
|
|
71248
71184
|
cwd: opts.cwd,
|
|
71249
71185
|
timeout: opts.timeoutMs,
|
|
71250
71186
|
encoding: "utf8",
|
|
@@ -71265,10 +71201,10 @@ var defaultCommandRunner = (command, opts) => {
|
|
|
71265
71201
|
// src/domains/hooks/handlers/convention-quality-gate/debounce.ts
|
|
71266
71202
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
71267
71203
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
71268
|
-
import { join as
|
|
71204
|
+
import { join as join97 } from "node:path";
|
|
71269
71205
|
function stateFilePath(sessionId) {
|
|
71270
71206
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 128) || "default";
|
|
71271
|
-
return
|
|
71207
|
+
return join97(tmpdir3(), `takumi-guardrail-${safe}.json`);
|
|
71272
71208
|
}
|
|
71273
71209
|
function isWithinDebounce(sessionId, debounceMs, now) {
|
|
71274
71210
|
try {
|
|
@@ -71416,6 +71352,7 @@ var conventionQualityGate = {
|
|
|
71416
71352
|
|
|
71417
71353
|
// src/domains/hooks/handlers/extension-skill/handler.ts
|
|
71418
71354
|
import fs20 from "node:fs";
|
|
71355
|
+
import os7 from "node:os";
|
|
71419
71356
|
import path9 from "node:path";
|
|
71420
71357
|
var CONFIG_KEY2 = "skill-extension-loader";
|
|
71421
71358
|
var SKILLS_ROOT_SEGMENTS = [".claude", "skills"];
|
|
@@ -71470,9 +71407,9 @@ function readFrontmatter(raw) {
|
|
|
71470
71407
|
`).trim()
|
|
71471
71408
|
};
|
|
71472
71409
|
}
|
|
71473
|
-
function renderBlock(skill,
|
|
71410
|
+
function renderBlock(skill, kept, skipped) {
|
|
71474
71411
|
const parts = [
|
|
71475
|
-
`Skill extensions for "${skill}" (user-owned,
|
|
71412
|
+
`Skill extensions for "${skill}" (user-owned, local + team-shared)`,
|
|
71476
71413
|
"Apply order: pre → override → post. The entries below are already in that order; layer them on top of the shipped skill instructions."
|
|
71477
71414
|
];
|
|
71478
71415
|
const totalChars = kept.reduce((n, e2) => n + e2.body.length, 0);
|
|
@@ -71495,36 +71432,54 @@ ${refs}`);
|
|
|
71495
71432
|
|
|
71496
71433
|
`);
|
|
71497
71434
|
}
|
|
71498
|
-
function
|
|
71499
|
-
|
|
71500
|
-
|
|
71501
|
-
|
|
71502
|
-
|
|
71503
|
-
|
|
71504
|
-
|
|
71505
|
-
|
|
71506
|
-
|
|
71507
|
-
|
|
71508
|
-
|
|
71509
|
-
|
|
71510
|
-
|
|
71511
|
-
|
|
71512
|
-
|
|
71435
|
+
function displayRel(cwd2, filePath) {
|
|
71436
|
+
const rel = path9.relative(cwd2, filePath);
|
|
71437
|
+
return rel.startsWith("..") ? filePath : rel;
|
|
71438
|
+
}
|
|
71439
|
+
function resolveLocalExtDir(skillDir, roots) {
|
|
71440
|
+
const seen = new Set;
|
|
71441
|
+
for (const root of roots) {
|
|
71442
|
+
if (!root || seen.has(root))
|
|
71443
|
+
continue;
|
|
71444
|
+
seen.add(root);
|
|
71445
|
+
const skillsRoot = path9.resolve(root, ...SKILLS_ROOT_SEGMENTS);
|
|
71446
|
+
const extDir = path9.resolve(skillsRoot, skillDir, "extensions");
|
|
71447
|
+
if (extDir !== skillsRoot && !extDir.startsWith(skillsRoot + path9.sep))
|
|
71448
|
+
continue;
|
|
71449
|
+
if (fs20.existsSync(extDir))
|
|
71450
|
+
return extDir;
|
|
71451
|
+
}
|
|
71452
|
+
return null;
|
|
71453
|
+
}
|
|
71454
|
+
function resolveSharedExtDir(skillDir, sharedDirRaw, projectRoot) {
|
|
71455
|
+
const raw = typeof sharedDirRaw === "string" ? sharedDirRaw.trim() : "";
|
|
71456
|
+
if (!raw)
|
|
71457
|
+
return null;
|
|
71458
|
+
const sharedRoot = path9.isAbsolute(raw) ? raw : path9.resolve(projectRoot, raw);
|
|
71459
|
+
if (!path9.isAbsolute(raw) && sharedRoot !== projectRoot && !sharedRoot.startsWith(projectRoot + path9.sep)) {
|
|
71460
|
+
return null;
|
|
71461
|
+
}
|
|
71462
|
+
const cand = path9.resolve(sharedRoot, skillDir);
|
|
71463
|
+
if (cand !== sharedRoot && !cand.startsWith(sharedRoot + path9.sep))
|
|
71464
|
+
return null;
|
|
71465
|
+
return fs20.existsSync(cand) ? cand : null;
|
|
71466
|
+
}
|
|
71467
|
+
function readExtensionsFromDir(extDir, skillDir, cwd2) {
|
|
71468
|
+
const kept = [];
|
|
71469
|
+
const skipped = [];
|
|
71513
71470
|
let entries;
|
|
71514
71471
|
try {
|
|
71515
71472
|
entries = fs20.readdirSync(extDir, { withFileTypes: true });
|
|
71516
71473
|
} catch {
|
|
71517
|
-
return
|
|
71474
|
+
return { kept, skipped };
|
|
71518
71475
|
}
|
|
71519
|
-
const relBase = `.claude/skills/${skillDir}/extensions`;
|
|
71520
|
-
const kept = [];
|
|
71521
|
-
const skipped = [];
|
|
71522
71476
|
for (const entry of entries) {
|
|
71523
71477
|
if (!entry.isFile() || !entry.name.toLowerCase().endsWith(".md"))
|
|
71524
71478
|
continue;
|
|
71479
|
+
const absPath = path9.join(extDir, entry.name);
|
|
71525
71480
|
let raw;
|
|
71526
71481
|
try {
|
|
71527
|
-
raw = fs20.readFileSync(
|
|
71482
|
+
raw = fs20.readFileSync(absPath, "utf8");
|
|
71528
71483
|
} catch {
|
|
71529
71484
|
skipped.push(entry.name);
|
|
71530
71485
|
continue;
|
|
@@ -71536,12 +71491,37 @@ function loadExtensions(input, ctx) {
|
|
|
71536
71491
|
skipped.push(entry.name);
|
|
71537
71492
|
continue;
|
|
71538
71493
|
}
|
|
71539
|
-
kept.push({ file: entry.name, relPath:
|
|
71494
|
+
kept.push({ file: entry.name, relPath: displayRel(cwd2, absPath), type, body: parsed.body });
|
|
71540
71495
|
}
|
|
71496
|
+
return { kept, skipped };
|
|
71497
|
+
}
|
|
71498
|
+
function loadExtensions(input, ctx) {
|
|
71499
|
+
if (input.tool_name !== "Skill")
|
|
71500
|
+
return NO_OP2;
|
|
71501
|
+
const toolInput = input.tool_input;
|
|
71502
|
+
const skill = toolInput && typeof toolInput.skill === "string" ? toolInput.skill.trim() : "";
|
|
71503
|
+
if (!skill)
|
|
71504
|
+
return NO_OP2;
|
|
71505
|
+
const cwd2 = typeof input.cwd === "string" && input.cwd ? input.cwd : ctx.cwd;
|
|
71506
|
+
const skillDir = baseSkillName(skill);
|
|
71507
|
+
if (!skillDir)
|
|
71508
|
+
return NO_OP2;
|
|
71509
|
+
const projectDir = process.env.CLAUDE_PROJECT_DIR ?? "";
|
|
71510
|
+
const home6 = os7.homedir();
|
|
71511
|
+
const primaryRoot = projectDir || cwd2;
|
|
71512
|
+
const localExtDir = resolveLocalExtDir(skillDir, [projectDir, cwd2, home6]);
|
|
71513
|
+
const sharedExtDir = resolveSharedExtDir(skillDir, ctx.config?.skillExtensions?.sharedDir, primaryRoot);
|
|
71514
|
+
if (!localExtDir && !sharedExtDir)
|
|
71515
|
+
return NO_OP2;
|
|
71516
|
+
const local = localExtDir ? readExtensionsFromDir(localExtDir, skillDir, cwd2) : { kept: [], skipped: [] };
|
|
71517
|
+
const shared = sharedExtDir ? readExtensionsFromDir(sharedExtDir, skillDir, cwd2) : { kept: [], skipped: [] };
|
|
71518
|
+
const localNames = new Set(local.kept.map((e2) => e2.file));
|
|
71519
|
+
const kept = [...local.kept, ...shared.kept.filter((e2) => !localNames.has(e2.file))];
|
|
71520
|
+
const skipped = [...local.skipped, ...shared.skipped];
|
|
71541
71521
|
if (kept.length === 0)
|
|
71542
71522
|
return NO_OP2;
|
|
71543
71523
|
kept.sort((a3, b3) => a3.type.order - b3.type.order || a3.file.localeCompare(b3.file));
|
|
71544
|
-
return { status: "context", output: renderBlock(skill,
|
|
71524
|
+
return { status: "context", output: renderBlock(skill, kept, skipped), timingMs: 0 };
|
|
71545
71525
|
}
|
|
71546
71526
|
var extensionSkill = {
|
|
71547
71527
|
name: "extension-skill",
|
|
@@ -71693,7 +71673,7 @@ function detectBroadGlob(pattern, pathHint) {
|
|
|
71693
71673
|
// src/domains/hooks/handlers/guard-breadth-scout/check-ignore.ts
|
|
71694
71674
|
var import_ignore5 = __toESM(require_ignore(), 1);
|
|
71695
71675
|
import { existsSync as existsSync47, readFileSync as readFileSync13 } from "node:fs";
|
|
71696
|
-
import { dirname as dirname25, join as
|
|
71676
|
+
import { dirname as dirname25, join as join98 } from "node:path";
|
|
71697
71677
|
var BUILTIN_HEAVY_DIR_LINES = [
|
|
71698
71678
|
"node_modules",
|
|
71699
71679
|
".pnp",
|
|
@@ -71730,7 +71710,7 @@ var BUILTIN_HEAVY_DIR_LINES = [
|
|
|
71730
71710
|
function findGitRoot(startDir) {
|
|
71731
71711
|
let dir = startDir;
|
|
71732
71712
|
while (true) {
|
|
71733
|
-
if (existsSync47(
|
|
71713
|
+
if (existsSync47(join98(dir, ".git")))
|
|
71734
71714
|
return dir;
|
|
71735
71715
|
const parent = dirname25(dir);
|
|
71736
71716
|
if (parent === dir)
|
|
@@ -71760,9 +71740,9 @@ function loadIgnoreConfig(cwd2) {
|
|
|
71760
71740
|
const gitRoot = findGitRoot(cwd2);
|
|
71761
71741
|
const candidatePaths = [];
|
|
71762
71742
|
if (gitRoot) {
|
|
71763
|
-
candidatePaths.push(
|
|
71743
|
+
candidatePaths.push(join98(gitRoot, ".claude", ".tkmignore"));
|
|
71764
71744
|
}
|
|
71765
|
-
candidatePaths.push(
|
|
71745
|
+
candidatePaths.push(join98(cwd2, ".claude", ".tkmignore"));
|
|
71766
71746
|
for (const candidate of candidatePaths) {
|
|
71767
71747
|
const lines = readIgnoreFile(candidate);
|
|
71768
71748
|
if (lines !== null) {
|
|
@@ -72167,7 +72147,10 @@ var guardJailbreak = {
|
|
|
72167
72147
|
events: ["PreToolUse"],
|
|
72168
72148
|
matchers: { PreToolUse: "Bash|Glob|Grep|Read|Edit|Write" },
|
|
72169
72149
|
denyOnTimeout: true,
|
|
72170
|
-
run(input) {
|
|
72150
|
+
run(input, ctx) {
|
|
72151
|
+
if (!isHandlerEnabled(ctx, "guard-jailbreak")) {
|
|
72152
|
+
return NO_OP3;
|
|
72153
|
+
}
|
|
72171
72154
|
if (typeof input?.tool_name !== "string" || input.tool_name.length === 0) {
|
|
72172
72155
|
return ALLOW;
|
|
72173
72156
|
}
|
|
@@ -72458,7 +72441,7 @@ function resolveEndpoint() {
|
|
|
72458
72441
|
init_manifest_path_resolver();
|
|
72459
72442
|
import { existsSync as existsSync48, readFileSync as readFileSync14 } from "node:fs";
|
|
72460
72443
|
import { homedir as homedir27 } from "node:os";
|
|
72461
|
-
import { dirname as dirname26, join as
|
|
72444
|
+
import { dirname as dirname26, join as join99, resolve as resolve23 } from "node:path";
|
|
72462
72445
|
var PROVIDER_DIRS = [".claude", ".codex"];
|
|
72463
72446
|
var MAX_WALK = 6;
|
|
72464
72447
|
function readManifestRaw(path10) {
|
|
@@ -72477,7 +72460,7 @@ function findManifest(cwd2) {
|
|
|
72477
72460
|
let dir = resolve23(cwd2);
|
|
72478
72461
|
for (let i = 0;i < MAX_WALK; i++) {
|
|
72479
72462
|
for (const provider of PROVIDER_DIRS) {
|
|
72480
|
-
const providerRoot =
|
|
72463
|
+
const providerRoot = join99(dir, provider);
|
|
72481
72464
|
if (existsSync48(providerRoot)) {
|
|
72482
72465
|
const path10 = findManifestInProviderDir(providerRoot);
|
|
72483
72466
|
if (path10)
|
|
@@ -72491,11 +72474,11 @@ function findManifest(cwd2) {
|
|
|
72491
72474
|
}
|
|
72492
72475
|
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
|
|
72493
72476
|
if (pluginRoot) {
|
|
72494
|
-
const pluginPath = findManifestInProviderDir(
|
|
72477
|
+
const pluginPath = findManifestInProviderDir(join99(pluginRoot, ".claude"));
|
|
72495
72478
|
if (pluginPath)
|
|
72496
72479
|
return pluginPath;
|
|
72497
72480
|
}
|
|
72498
|
-
const globalPath = findManifestInProviderDir(
|
|
72481
|
+
const globalPath = findManifestInProviderDir(join99(homedir27(), ".claude"));
|
|
72499
72482
|
if (globalPath)
|
|
72500
72483
|
return globalPath;
|
|
72501
72484
|
return null;
|
|
@@ -72651,7 +72634,7 @@ function bucketTokens(records) {
|
|
|
72651
72634
|
// src/domains/hooks/telemetry/lib/session-lock.ts
|
|
72652
72635
|
var import_proper_lockfile9 = __toESM(require_proper_lockfile(), 1);
|
|
72653
72636
|
import { promises as fs21 } from "node:fs";
|
|
72654
|
-
import { join as
|
|
72637
|
+
import { join as join100 } from "node:path";
|
|
72655
72638
|
var LOCK_RESOURCE = "summary.json";
|
|
72656
72639
|
var DEFAULT_TIMEOUT_MS3 = 2000;
|
|
72657
72640
|
var RETRY_INTERVAL_MS = 100;
|
|
@@ -72659,7 +72642,7 @@ var DEFAULT_STALE_AFTER_MS = 1e4;
|
|
|
72659
72642
|
async function withSummaryLock(sessionDir, fn, options2 = {}) {
|
|
72660
72643
|
const timeoutMs = options2.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
72661
72644
|
const staleAfterMs = options2.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
|
|
72662
|
-
const resource =
|
|
72645
|
+
const resource = join100(sessionDir, LOCK_RESOURCE);
|
|
72663
72646
|
try {
|
|
72664
72647
|
await fs21.mkdir(sessionDir, { recursive: true });
|
|
72665
72648
|
} catch {
|
|
@@ -72695,13 +72678,13 @@ import { promises as fs22 } from "node:fs";
|
|
|
72695
72678
|
|
|
72696
72679
|
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
72697
72680
|
init_paths2();
|
|
72698
|
-
import { join as
|
|
72681
|
+
import { join as join102 } from "node:path";
|
|
72699
72682
|
|
|
72700
72683
|
// src/shared/project-paths.ts
|
|
72701
72684
|
init_paths2();
|
|
72702
72685
|
import { createHash as createHash11 } from "node:crypto";
|
|
72703
72686
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
72704
|
-
import { basename as basename17, join as
|
|
72687
|
+
import { basename as basename17, join as join101 } from "node:path";
|
|
72705
72688
|
function encodeCwd(cwd2) {
|
|
72706
72689
|
const stripped = cwd2.replace(/^\/+/, "");
|
|
72707
72690
|
const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
@@ -72720,10 +72703,10 @@ function getProjectLabel(cwd2) {
|
|
|
72720
72703
|
return basename17(cwd2) || "";
|
|
72721
72704
|
}
|
|
72722
72705
|
function getProjectsRoot() {
|
|
72723
|
-
return
|
|
72706
|
+
return join101(getConfigDir(), "projects");
|
|
72724
72707
|
}
|
|
72725
72708
|
function getProjectDir(args) {
|
|
72726
|
-
return
|
|
72709
|
+
return join101(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
|
|
72727
72710
|
}
|
|
72728
72711
|
|
|
72729
72712
|
// src/domains/hooks/telemetry/lib/session-paths.ts
|
|
@@ -72735,35 +72718,35 @@ function safeSessionSegment(sessionId) {
|
|
|
72735
72718
|
return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
|
|
72736
72719
|
}
|
|
72737
72720
|
function getSessionsRoot() {
|
|
72738
|
-
return
|
|
72721
|
+
return join102(getConfigDir(), "sessions");
|
|
72739
72722
|
}
|
|
72740
72723
|
function getSessionDirV2(args) {
|
|
72741
72724
|
const segment = safeSessionSegment(args.sessionId);
|
|
72742
72725
|
if (!segment)
|
|
72743
72726
|
return null;
|
|
72744
|
-
return
|
|
72727
|
+
return join102(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
|
|
72745
72728
|
}
|
|
72746
72729
|
function getEventsFile(sessionDir) {
|
|
72747
|
-
return
|
|
72730
|
+
return join102(sessionDir, "events.jsonl");
|
|
72748
72731
|
}
|
|
72749
72732
|
function getSummaryFile(sessionDir) {
|
|
72750
|
-
return
|
|
72733
|
+
return join102(sessionDir, "summary.json");
|
|
72751
72734
|
}
|
|
72752
72735
|
function getLastPushFile(sessionDir) {
|
|
72753
|
-
return
|
|
72736
|
+
return join102(sessionDir, "last_push.txt");
|
|
72754
72737
|
}
|
|
72755
72738
|
var OBSERVATIONS_FILENAME = "observations.jsonl";
|
|
72756
72739
|
function getObservationsFile(sessionDir) {
|
|
72757
|
-
return
|
|
72740
|
+
return join102(sessionDir, OBSERVATIONS_FILENAME);
|
|
72758
72741
|
}
|
|
72759
72742
|
function getObservationsFlushingFile(sessionDir) {
|
|
72760
|
-
return
|
|
72743
|
+
return join102(sessionDir, `${OBSERVATIONS_FILENAME}.flushing`);
|
|
72761
72744
|
}
|
|
72762
72745
|
function getObservationsPushedFile(sessionDir) {
|
|
72763
|
-
return
|
|
72746
|
+
return join102(sessionDir, "obs_pushed.txt");
|
|
72764
72747
|
}
|
|
72765
72748
|
function getMetaFile(sessionDir) {
|
|
72766
|
-
return
|
|
72749
|
+
return join102(sessionDir, "meta.json");
|
|
72767
72750
|
}
|
|
72768
72751
|
|
|
72769
72752
|
// src/domains/hooks/telemetry/lib/summary.ts
|
|
@@ -72985,7 +72968,7 @@ async function applyClaudeTranscriptDelta(args) {
|
|
|
72985
72968
|
// src/domains/hooks/telemetry/lib/detached-put.ts
|
|
72986
72969
|
import { spawn as spawn2 } from "node:child_process";
|
|
72987
72970
|
import { openSync as openSync5 } from "node:fs";
|
|
72988
|
-
import { dirname as dirname27, join as
|
|
72971
|
+
import { dirname as dirname27, join as join103 } from "node:path";
|
|
72989
72972
|
var ALLOWED_ENV_PREFIXES = ["TKM_", "TAKUMI_"];
|
|
72990
72973
|
var ALLOWED_ENV_KEYS = new Set(["HOME", "USERPROFILE", "PATH", "NODE_ENV"]);
|
|
72991
72974
|
var DETACH_DEBUG_LOG_NAME = "detach-debug.log";
|
|
@@ -72993,7 +72976,7 @@ function effectiveDetachMode(flags) {
|
|
|
72993
72976
|
return flags.noDetach ? "inline" : "detached";
|
|
72994
72977
|
}
|
|
72995
72978
|
function sessionDebugLogPath(sessionDir) {
|
|
72996
|
-
return
|
|
72979
|
+
return join103(sessionDir, DETACH_DEBUG_LOG_NAME);
|
|
72997
72980
|
}
|
|
72998
72981
|
var BUNFS_PREFIX = "/$bunfs/";
|
|
72999
72982
|
var REENTRY_VERBS = ["hooks", "hook-exec"];
|
|
@@ -73013,8 +72996,7 @@ function resolveInvocationPrefix() {
|
|
|
73013
72996
|
if (verbIdx === -1) {
|
|
73014
72997
|
if (isCompiledBunBinary)
|
|
73015
72998
|
return { command, prefixArgs: [] };
|
|
73016
|
-
|
|
73017
|
-
return { command, prefixArgs: isScriptEntry ? [entry] : [] };
|
|
72999
|
+
return { command, prefixArgs: typeof entry === "string" && entry.length > 0 ? [entry] : [] };
|
|
73018
73000
|
}
|
|
73019
73001
|
if (isCompiledBunBinary) {
|
|
73020
73002
|
return { command, prefixArgs: [] };
|
|
@@ -73034,7 +73016,7 @@ function resolvePreloadScript(entryPath) {
|
|
|
73034
73016
|
try {
|
|
73035
73017
|
const srcDir = dirname27(entryPath);
|
|
73036
73018
|
const repoRoot = dirname27(srcDir);
|
|
73037
|
-
return
|
|
73019
|
+
return join103(repoRoot, "scripts", "preload-config-override.ts");
|
|
73038
73020
|
} catch {
|
|
73039
73021
|
return null;
|
|
73040
73022
|
}
|
|
@@ -73318,8 +73300,8 @@ async function runSessionEndFlush(data, ctx) {
|
|
|
73318
73300
|
session_end_raw: data
|
|
73319
73301
|
};
|
|
73320
73302
|
const { promises: fs25 } = await import("node:fs");
|
|
73321
|
-
const { join:
|
|
73322
|
-
const target =
|
|
73303
|
+
const { join: join106 } = await import("node:path");
|
|
73304
|
+
const target = join106(sessionDir, "meta.json");
|
|
73323
73305
|
const tmp = `${target}.tmp`;
|
|
73324
73306
|
await fs25.writeFile(tmp, JSON.stringify(updated), "utf8");
|
|
73325
73307
|
await fs25.rename(tmp, target);
|
|
@@ -73807,11 +73789,11 @@ async function handleStop(agent, flags = {}) {
|
|
|
73807
73789
|
// src/domains/hooks/telemetry/otlp/observations-export.ts
|
|
73808
73790
|
init_paths2();
|
|
73809
73791
|
import { promises as fs30, openSync as openSync9 } from "node:fs";
|
|
73810
|
-
import { join as
|
|
73792
|
+
import { join as join107 } from "node:path";
|
|
73811
73793
|
|
|
73812
73794
|
// src/domains/hooks/telemetry/lib/retention.ts
|
|
73813
73795
|
import { promises as fs27 } from "node:fs";
|
|
73814
|
-
import { join as
|
|
73796
|
+
import { join as join106 } from "node:path";
|
|
73815
73797
|
async function pathExists25(path10) {
|
|
73816
73798
|
try {
|
|
73817
73799
|
await fs27.access(path10);
|
|
@@ -73846,7 +73828,7 @@ async function decideDelete(dir, args) {
|
|
|
73846
73828
|
async function listChildren(dir) {
|
|
73847
73829
|
try {
|
|
73848
73830
|
const names = await fs27.readdir(dir);
|
|
73849
|
-
return names.map((n2) =>
|
|
73831
|
+
return names.map((n2) => join106(dir, n2));
|
|
73850
73832
|
} catch {
|
|
73851
73833
|
return [];
|
|
73852
73834
|
}
|
|
@@ -73857,7 +73839,7 @@ async function collectV2Sessions() {
|
|
|
73857
73839
|
const sessions = [];
|
|
73858
73840
|
for (const projectDir of projects) {
|
|
73859
73841
|
for (const agentDir of await listChildren(projectDir)) {
|
|
73860
|
-
for (const sessionDir of await listChildren(
|
|
73842
|
+
for (const sessionDir of await listChildren(join106(agentDir, "sessions"))) {
|
|
73861
73843
|
sessions.push(sessionDir);
|
|
73862
73844
|
}
|
|
73863
73845
|
}
|
|
@@ -74286,7 +74268,7 @@ async function exportSessionObservations(sessionDir, opts = {}, deps = {}) {
|
|
|
74286
74268
|
}
|
|
74287
74269
|
}
|
|
74288
74270
|
function lockPath() {
|
|
74289
|
-
return
|
|
74271
|
+
return join107(getConfigDir(), "obs-flush.lock");
|
|
74290
74272
|
}
|
|
74291
74273
|
async function acquireSweepLock(now) {
|
|
74292
74274
|
const path10 = lockPath();
|
|
@@ -74925,7 +74907,7 @@ var metricsRecord = {
|
|
|
74925
74907
|
|
|
74926
74908
|
// src/domains/statusline/activity-cache.ts
|
|
74927
74909
|
import { readdirSync as readdirSync8, rmSync as rmSync5, statSync as statSync8 } from "node:fs";
|
|
74928
|
-
import { join as
|
|
74910
|
+
import { join as join108 } from "node:path";
|
|
74929
74911
|
|
|
74930
74912
|
// src/domains/statusline/activity-snapshot.ts
|
|
74931
74913
|
import { existsSync as existsSync51 } from "node:fs";
|
|
@@ -75385,7 +75367,7 @@ function cleanupStaleActivity(now = Date.now()) {
|
|
|
75385
75367
|
for (const entry of entries) {
|
|
75386
75368
|
if (!entry.startsWith(FILE_PREFIX) || !entry.endsWith(FILE_SUFFIX))
|
|
75387
75369
|
continue;
|
|
75388
|
-
const full =
|
|
75370
|
+
const full = join108(getStatuslineCacheDir(), entry);
|
|
75389
75371
|
try {
|
|
75390
75372
|
if (now - statSync8(full).mtimeMs > ACTIVITY_TTL_MS)
|
|
75391
75373
|
rmSync5(full, { force: true });
|
|
@@ -75450,11 +75432,11 @@ var sessionActivity = {
|
|
|
75450
75432
|
|
|
75451
75433
|
// src/domains/hooks/handlers/session-init/handler.ts
|
|
75452
75434
|
import { mkdirSync as mkdirSync6 } from "node:fs";
|
|
75453
|
-
import { dirname as dirname29, join as
|
|
75435
|
+
import { dirname as dirname29, join as join113 } from "node:path";
|
|
75454
75436
|
|
|
75455
75437
|
// src/domains/hooks/handlers/_shared/project-detector.ts
|
|
75456
75438
|
import { existsSync as existsSync52, readFileSync as readFileSync16 } from "node:fs";
|
|
75457
|
-
import { join as
|
|
75439
|
+
import { join as join109 } from "node:path";
|
|
75458
75440
|
var LOCKFILE_PRIORITY = [
|
|
75459
75441
|
{ manager: "bun", files: ["bun.lockb", "bun.lock"] },
|
|
75460
75442
|
{ manager: "pnpm", files: ["pnpm-lock.yaml"] },
|
|
@@ -75489,14 +75471,14 @@ var APP_FRAMEWORKS = new Set([
|
|
|
75489
75471
|
var WORKSPACE_MARKER_FILES = ["pnpm-workspace.yaml", "turbo.json", "lerna.json"];
|
|
75490
75472
|
function fileExists(cwd2, name2) {
|
|
75491
75473
|
try {
|
|
75492
|
-
return existsSync52(
|
|
75474
|
+
return existsSync52(join109(cwd2, name2));
|
|
75493
75475
|
} catch {
|
|
75494
75476
|
return false;
|
|
75495
75477
|
}
|
|
75496
75478
|
}
|
|
75497
75479
|
function readPackageJson(cwd2) {
|
|
75498
75480
|
try {
|
|
75499
|
-
const raw = readFileSync16(
|
|
75481
|
+
const raw = readFileSync16(join109(cwd2, "package.json"), "utf8");
|
|
75500
75482
|
const parsed = JSON.parse(raw);
|
|
75501
75483
|
if (parsed && typeof parsed === "object")
|
|
75502
75484
|
return parsed;
|
|
@@ -75577,14 +75559,86 @@ function detectProject(cwd2) {
|
|
|
75577
75559
|
};
|
|
75578
75560
|
}
|
|
75579
75561
|
|
|
75562
|
+
// src/domains/hooks/handlers/session-init/context-blocks.ts
|
|
75563
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
75564
|
+
import { join as join110 } from "node:path";
|
|
75565
|
+
var CODING_LEVEL_STYLE_FILES = {
|
|
75566
|
+
0: "coding-level-0-eli5",
|
|
75567
|
+
1: "coding-level-1-junior",
|
|
75568
|
+
2: "coding-level-2-middle",
|
|
75569
|
+
3: "coding-level-3-senior",
|
|
75570
|
+
4: "coding-level-4-expert",
|
|
75571
|
+
5: "coding-level-5-principal"
|
|
75572
|
+
};
|
|
75573
|
+
function compactionApprovalWarning(source) {
|
|
75574
|
+
if (source !== "compact")
|
|
75575
|
+
return null;
|
|
75576
|
+
return [
|
|
75577
|
+
"⚠️ CONTEXT COMPACTED - APPROVAL STATE CHECK:",
|
|
75578
|
+
"If you were waiting for user approval via AskUserQuestion (e.g., a review gate),",
|
|
75579
|
+
"you MUST re-confirm with the user before proceeding. Do NOT assume approval was given.",
|
|
75580
|
+
'Use AskUserQuestion to verify: "Context was compacted. Please confirm approval to continue."'
|
|
75581
|
+
].join(`
|
|
75582
|
+
`);
|
|
75583
|
+
}
|
|
75584
|
+
function codingLevelGuidelines(codingLevel, settingsDir) {
|
|
75585
|
+
if (typeof codingLevel !== "number")
|
|
75586
|
+
return null;
|
|
75587
|
+
const styleFile = CODING_LEVEL_STYLE_FILES[codingLevel];
|
|
75588
|
+
if (!styleFile)
|
|
75589
|
+
return null;
|
|
75590
|
+
try {
|
|
75591
|
+
const stylePath = join110(settingsDir, "output-styles", `${styleFile}.md`);
|
|
75592
|
+
const content = readFileSync17(stylePath, "utf8");
|
|
75593
|
+
const withoutFrontmatter = content.replace(/^---[\s\S]*?---\n*/, "").trim();
|
|
75594
|
+
return withoutFrontmatter.length > 0 ? withoutFrontmatter : null;
|
|
75595
|
+
} catch {
|
|
75596
|
+
return null;
|
|
75597
|
+
}
|
|
75598
|
+
}
|
|
75599
|
+
function renderAssertion(assertion) {
|
|
75600
|
+
if (typeof assertion === "string")
|
|
75601
|
+
return assertion;
|
|
75602
|
+
if (assertion && typeof assertion === "object") {
|
|
75603
|
+
const a3 = assertion;
|
|
75604
|
+
const text = typeof a3.message === "string" ? a3.message : typeof a3.rule === "string" ? a3.rule : "";
|
|
75605
|
+
const pattern = typeof a3.pattern === "string" && a3.pattern.length > 0 ? ` (${a3.pattern})` : "";
|
|
75606
|
+
if (text)
|
|
75607
|
+
return `${text}${pattern}`;
|
|
75608
|
+
}
|
|
75609
|
+
return String(assertion);
|
|
75610
|
+
}
|
|
75611
|
+
function userAssertions(assertions) {
|
|
75612
|
+
if (!Array.isArray(assertions) || assertions.length === 0)
|
|
75613
|
+
return null;
|
|
75614
|
+
const lines = ["User Assertions:"];
|
|
75615
|
+
assertions.forEach((assertion, i) => {
|
|
75616
|
+
lines.push(` ${i + 1}. ${renderAssertion(assertion)}`);
|
|
75617
|
+
});
|
|
75618
|
+
return lines.join(`
|
|
75619
|
+
`);
|
|
75620
|
+
}
|
|
75621
|
+
function renderContextBlocks(source, ctx, settingsDir) {
|
|
75622
|
+
const config = ctx.config ?? {};
|
|
75623
|
+
const blocks = [
|
|
75624
|
+
compactionApprovalWarning(source),
|
|
75625
|
+
codingLevelGuidelines(config.codingLevel, settingsDir),
|
|
75626
|
+
userAssertions(config.assertions)
|
|
75627
|
+
].filter((b3) => b3 !== null);
|
|
75628
|
+
return blocks.length > 0 ? `
|
|
75629
|
+
${blocks.join(`
|
|
75630
|
+
|
|
75631
|
+
`)}` : "";
|
|
75632
|
+
}
|
|
75633
|
+
|
|
75580
75634
|
// src/domains/hooks/handlers/session-init/env-entries.ts
|
|
75581
75635
|
import { createHash as createHash14 } from "node:crypto";
|
|
75582
75636
|
import { platform as platform9, userInfo } from "node:os";
|
|
75583
|
-
import { join as
|
|
75637
|
+
import { join as join112 } from "node:path";
|
|
75584
75638
|
|
|
75585
75639
|
// src/domains/hooks/handlers/session-init/plan-resolver.ts
|
|
75586
|
-
import { existsSync as existsSync53, readFileSync as
|
|
75587
|
-
import { join as
|
|
75640
|
+
import { existsSync as existsSync53, readFileSync as readFileSync18, readdirSync as readdirSync9 } from "node:fs";
|
|
75641
|
+
import { join as join111 } from "node:path";
|
|
75588
75642
|
var MAX_PLAN_DIRS = 100;
|
|
75589
75643
|
var MAX_PLAN_FILE_BYTES = 64 * 1024;
|
|
75590
75644
|
function listPlanDirs(plansPath) {
|
|
@@ -75598,10 +75652,10 @@ function listPlanDirs(plansPath) {
|
|
|
75598
75652
|
}
|
|
75599
75653
|
function planFileMentionsSession(planDir, sessionId) {
|
|
75600
75654
|
try {
|
|
75601
|
-
const planFile =
|
|
75655
|
+
const planFile = join111(planDir, "plan.md");
|
|
75602
75656
|
if (!existsSync53(planFile))
|
|
75603
75657
|
return false;
|
|
75604
|
-
const body =
|
|
75658
|
+
const body = readFileSync18(planFile, { encoding: "utf8" });
|
|
75605
75659
|
if (body.length > MAX_PLAN_FILE_BYTES)
|
|
75606
75660
|
return false;
|
|
75607
75661
|
return body.includes(sessionId);
|
|
@@ -75613,7 +75667,7 @@ function resolveActivePlan(plansPath, sessionId) {
|
|
|
75613
75667
|
if (!sessionId)
|
|
75614
75668
|
return "";
|
|
75615
75669
|
for (const name2 of listPlanDirs(plansPath)) {
|
|
75616
|
-
const dir =
|
|
75670
|
+
const dir = join111(plansPath, name2);
|
|
75617
75671
|
if (name2.includes(sessionId) || planFileMentionsSession(dir, sessionId)) {
|
|
75618
75672
|
return dir;
|
|
75619
75673
|
}
|
|
@@ -75634,7 +75688,7 @@ function resolveSuggestedPlan(plansPath, branch, branchPattern) {
|
|
|
75634
75688
|
return "";
|
|
75635
75689
|
for (const name2 of listPlanDirs(plansPath)) {
|
|
75636
75690
|
if (name2.includes(slug))
|
|
75637
|
-
return
|
|
75691
|
+
return join111(plansPath, name2);
|
|
75638
75692
|
}
|
|
75639
75693
|
return "";
|
|
75640
75694
|
}
|
|
@@ -75688,11 +75742,11 @@ function buildEnvEntries(params) {
|
|
|
75688
75742
|
const plan = config.plan ?? {};
|
|
75689
75743
|
const locale = config.locale ?? {};
|
|
75690
75744
|
const validation = plan.validation ?? {};
|
|
75691
|
-
const settingsDir =
|
|
75692
|
-
const docsPath =
|
|
75693
|
-
const plansPath =
|
|
75745
|
+
const settingsDir = join112(projectRoot, ".claude");
|
|
75746
|
+
const docsPath = join112(projectRoot, paths.docs ?? "docs");
|
|
75747
|
+
const plansPath = join112(projectRoot, paths.plans ?? "plans");
|
|
75694
75748
|
const reportsDir = plan.reportsDir ?? "reports";
|
|
75695
|
-
const reportsPath =
|
|
75749
|
+
const reportsPath = join112(plansPath, reportsDir);
|
|
75696
75750
|
const namingFormat = plan.namingFormat ?? "";
|
|
75697
75751
|
const activePlan = resolveActivePlan(plansPath, ctx.sessionId);
|
|
75698
75752
|
const suggestedPlan = resolveSuggestedPlan(plansPath, branch, plan.resolution?.branchPattern ?? "");
|
|
@@ -75724,7 +75778,7 @@ function buildEnvEntries(params) {
|
|
|
75724
75778
|
TKM_CODING_LEVEL_STYLE: codingLevelStyle(config.codingLevel),
|
|
75725
75779
|
TKM_THINKING_LANGUAGE: locale.thinkingLanguage ?? "",
|
|
75726
75780
|
TKM_RESPONSE_LANGUAGE: locale.responseLanguage ?? "",
|
|
75727
|
-
TKM_SDD_MODE: "",
|
|
75781
|
+
TKM_SDD_MODE: config.takumi?.sddMode ?? "ask",
|
|
75728
75782
|
TKM_VALIDATION_MODE: validation.mode ?? "",
|
|
75729
75783
|
TKM_VALIDATION_MIN_QUESTIONS: numberString(validation.minQuestions),
|
|
75730
75784
|
TKM_VALIDATION_MAX_QUESTIONS: numberString(validation.maxQuestions),
|
|
@@ -75781,7 +75835,7 @@ function resolveEnvFilePath(settingsDir) {
|
|
|
75781
75835
|
const override = process.env.CLAUDE_ENV_FILE;
|
|
75782
75836
|
if (override && override.trim().length > 0)
|
|
75783
75837
|
return override;
|
|
75784
|
-
return
|
|
75838
|
+
return join113(settingsDir, DEFAULT_ENV_FILE);
|
|
75785
75839
|
}
|
|
75786
75840
|
function persistEntries(envFilePath, entries) {
|
|
75787
75841
|
try {
|
|
@@ -75826,7 +75880,8 @@ var sessionInit = {
|
|
|
75826
75880
|
if (!persistEntries(envFilePath, entries)) {
|
|
75827
75881
|
return { status: "no-op", timingMs: 0 };
|
|
75828
75882
|
}
|
|
75829
|
-
|
|
75883
|
+
const output2 = renderBanner(source, entries) + renderContextBlocks(source, ctx, entries.TKM_CLAUDE_SETTINGS_DIR ?? "");
|
|
75884
|
+
return { status: "context", output: output2, timingMs: 0 };
|
|
75830
75885
|
} catch {
|
|
75831
75886
|
return { status: "no-op", timingMs: 0 };
|
|
75832
75887
|
}
|
|
@@ -75836,9 +75891,9 @@ var sessionInit = {
|
|
|
75836
75891
|
// src/domains/hooks/handlers/_shared/context-assembler.ts
|
|
75837
75892
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
75838
75893
|
import { createHash as createHash15 } from "node:crypto";
|
|
75839
|
-
import { existsSync as existsSync54, mkdirSync as mkdirSync7, readFileSync as
|
|
75894
|
+
import { existsSync as existsSync54, mkdirSync as mkdirSync7, readFileSync as readFileSync19, rmSync as rmSync6, statSync as statSync9, writeFileSync as writeFileSync10 } from "node:fs";
|
|
75840
75895
|
import { homedir as homedir29, platform as platform10, tmpdir as tmpdir4 } from "node:os";
|
|
75841
|
-
import { basename as basename18, join as
|
|
75896
|
+
import { basename as basename18, join as join114, resolve as resolve24 } from "node:path";
|
|
75842
75897
|
var INJECTED_TTL_MS = 12 * 60 * 60 * 1000;
|
|
75843
75898
|
var RESERVATION_TTL_MS = 60 * 1000;
|
|
75844
75899
|
function gitBranch(dir) {
|
|
@@ -75915,18 +75970,18 @@ function scopeKey(baseDir) {
|
|
|
75915
75970
|
return `${slug}-${hash}`;
|
|
75916
75971
|
}
|
|
75917
75972
|
function stateDir() {
|
|
75918
|
-
return
|
|
75973
|
+
return join114(tmpdir4(), "takumi-context-throttle");
|
|
75919
75974
|
}
|
|
75920
75975
|
function stateFile(sessionId, scope, transcriptPath) {
|
|
75921
75976
|
const key = `${sessionId}\x00${scope}\x00${transcriptPath ?? ""}`;
|
|
75922
75977
|
const hash = createHash15("sha256").update(key).digest("hex").slice(0, 32);
|
|
75923
|
-
return
|
|
75978
|
+
return join114(stateDir(), `${hash}.json`);
|
|
75924
75979
|
}
|
|
75925
75980
|
function readState(file) {
|
|
75926
75981
|
try {
|
|
75927
75982
|
if (!existsSync54(file))
|
|
75928
75983
|
return null;
|
|
75929
|
-
return JSON.parse(
|
|
75984
|
+
return JSON.parse(readFileSync19(file, "utf8"));
|
|
75930
75985
|
} catch {
|
|
75931
75986
|
return null;
|
|
75932
75987
|
}
|
|
@@ -75989,8 +76044,8 @@ function clearPending(sessionId, scope, transcriptPath) {
|
|
|
75989
76044
|
} catch {}
|
|
75990
76045
|
}
|
|
75991
76046
|
function resolveSkillsVenv(_cwd) {
|
|
75992
|
-
const base =
|
|
75993
|
-
const interpreter = platform10() === "win32" ?
|
|
76047
|
+
const base = join114(homedir29(), ".claude", "skills", ".venv");
|
|
76048
|
+
const interpreter = platform10() === "win32" ? join114(base, "Scripts", "python.exe") : join114(base, "bin", "python3");
|
|
75994
76049
|
return existsSync54(interpreter) ? interpreter : null;
|
|
75995
76050
|
}
|
|
75996
76051
|
|
|
@@ -76029,12 +76084,12 @@ var sessionPromptContext = {
|
|
|
76029
76084
|
};
|
|
76030
76085
|
|
|
76031
76086
|
// src/domains/hooks/handlers/session-subagent-init/context-block.ts
|
|
76032
|
-
import { join as
|
|
76087
|
+
import { join as join116 } from "node:path";
|
|
76033
76088
|
|
|
76034
76089
|
// src/domains/hooks/handlers/session-subagent-init/context-sources.ts
|
|
76035
76090
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
76036
76091
|
import { readdirSync as readdirSync10, statSync as statSync10 } from "node:fs";
|
|
76037
|
-
import { isAbsolute as isAbsolute5, join as
|
|
76092
|
+
import { isAbsolute as isAbsolute5, join as join115, resolve as resolve25 } from "node:path";
|
|
76038
76093
|
var MAX_DOCS_FILES = 15;
|
|
76039
76094
|
var MAX_DOCS_SUBDIRS = 5;
|
|
76040
76095
|
function gitFacts(dir) {
|
|
@@ -76071,11 +76126,11 @@ function detectPlan(plansAbs) {
|
|
|
76071
76126
|
for (const e2 of entries) {
|
|
76072
76127
|
if (!e2.isDirectory())
|
|
76073
76128
|
continue;
|
|
76074
|
-
const dir =
|
|
76129
|
+
const dir = join115(plansAbs, e2.name);
|
|
76075
76130
|
try {
|
|
76076
76131
|
if (!readdirSync10(dir).includes("plan.md"))
|
|
76077
76132
|
continue;
|
|
76078
|
-
const mtime = statSync10(
|
|
76133
|
+
const mtime = statSync10(join115(dir, "plan.md")).mtimeMs;
|
|
76079
76134
|
if (!best || mtime > best.mtime)
|
|
76080
76135
|
best = { name: e2.name, mtime };
|
|
76081
76136
|
} catch {}
|
|
@@ -76098,7 +76153,7 @@ function docsCatalogue(docsAbs) {
|
|
|
76098
76153
|
for (const d3 of subdirs.slice(0, MAX_DOCS_SUBDIRS)) {
|
|
76099
76154
|
let count = 0;
|
|
76100
76155
|
try {
|
|
76101
|
-
count = readdirSync10(
|
|
76156
|
+
count = readdirSync10(join115(docsAbs, d3)).length;
|
|
76102
76157
|
} catch {}
|
|
76103
76158
|
lines.push(`- ${d3}/ (${count} entries)`);
|
|
76104
76159
|
}
|
|
@@ -76142,11 +76197,11 @@ function buildSubagentContext(input, ctx) {
|
|
|
76142
76197
|
const agentId = strField(input, "agent_id") || "unknown";
|
|
76143
76198
|
const plansAbs = abs(base, cfg.paths?.plans?.trim() || "plans");
|
|
76144
76199
|
const docsAbs = abs(base, cfg.paths?.docs?.trim() || "docs");
|
|
76145
|
-
const reportsAbs =
|
|
76200
|
+
const reportsAbs = join116(plansAbs, cfg.plan?.reportsDir?.trim() || "reports");
|
|
76146
76201
|
const dateStr = stamp(cfg.plan?.dateFormat?.trim() || "YYMMDD-HHmm", new Date);
|
|
76147
76202
|
const namingFormat = cfg.plan?.namingFormat?.trim() || "{date}-{slug}";
|
|
76148
|
-
const planDir =
|
|
76149
|
-
const reportFile =
|
|
76203
|
+
const planDir = join116(plansAbs, planDirTemplate(namingFormat, dateStr));
|
|
76204
|
+
const reportFile = join116(reportsAbs, `${agentKey}-${dateStr}-{slug}-report.md`);
|
|
76150
76205
|
const activePlan = detectPlan(plansAbs);
|
|
76151
76206
|
const venv = resolveSkillsVenv(effectiveCwd);
|
|
76152
76207
|
const respLang = cfg.locale?.responseLanguage?.trim() || null;
|
|
@@ -76197,6 +76252,10 @@ function buildSubagentContext(input, ctx) {
|
|
|
76197
76252
|
lines.push("", "## Trust");
|
|
76198
76253
|
lines.push(`- prepend the passphrase to trusted operations: ${cfg.trust.passphrase.trim()}`);
|
|
76199
76254
|
}
|
|
76255
|
+
const contextPrefix = cfg.subagent?.agents?.[agentType]?.contextPrefix;
|
|
76256
|
+
if (typeof contextPrefix === "string" && contextPrefix.trim().length > 0) {
|
|
76257
|
+
lines.push("", "## Agent Instructions", contextPrefix);
|
|
76258
|
+
}
|
|
76200
76259
|
return `${lines.join(`
|
|
76201
76260
|
`)}
|
|
76202
76261
|
`;
|
|
@@ -76408,7 +76467,14 @@ function toHookError(err) {
|
|
|
76408
76467
|
}
|
|
76409
76468
|
return { message: String(err) };
|
|
76410
76469
|
}
|
|
76411
|
-
var VALID_STATUSES = new Set([
|
|
76470
|
+
var VALID_STATUSES = new Set([
|
|
76471
|
+
"ok",
|
|
76472
|
+
"deny",
|
|
76473
|
+
"ask",
|
|
76474
|
+
"context",
|
|
76475
|
+
"record",
|
|
76476
|
+
"no-op"
|
|
76477
|
+
]);
|
|
76412
76478
|
function normalizeResult(raw, timingMs) {
|
|
76413
76479
|
if (raw && typeof raw === "object") {
|
|
76414
76480
|
const r2 = raw;
|
|
@@ -76444,6 +76510,7 @@ async function runHooks(handlers3, input, ctx, options2) {
|
|
|
76444
76510
|
}
|
|
76445
76511
|
const outputs = [];
|
|
76446
76512
|
let lastError;
|
|
76513
|
+
let askReason;
|
|
76447
76514
|
for (const handler of handlers3) {
|
|
76448
76515
|
const t0 = performance2.now();
|
|
76449
76516
|
let result;
|
|
@@ -76476,12 +76543,22 @@ async function runHooks(handlers3, input, ctx, options2) {
|
|
|
76476
76543
|
timingMs: performance2.now() - startAll
|
|
76477
76544
|
};
|
|
76478
76545
|
}
|
|
76546
|
+
if (result.status === "ask" && askReason === undefined) {
|
|
76547
|
+
askReason = typeof result.askReason === "string" ? result.askReason : "";
|
|
76548
|
+
}
|
|
76479
76549
|
if (result.status === "context" && typeof result.output === "string" && result.output.length > 0) {
|
|
76480
76550
|
outputs.push(result.output);
|
|
76481
76551
|
}
|
|
76482
76552
|
if (result.error)
|
|
76483
76553
|
lastError = result.error;
|
|
76484
76554
|
}
|
|
76555
|
+
if (askReason !== undefined) {
|
|
76556
|
+
return {
|
|
76557
|
+
status: "ask",
|
|
76558
|
+
askReason,
|
|
76559
|
+
timingMs: performance2.now() - startAll
|
|
76560
|
+
};
|
|
76561
|
+
}
|
|
76485
76562
|
if (outputs.length > 0) {
|
|
76486
76563
|
return {
|
|
76487
76564
|
status: "context",
|
|
@@ -76504,6 +76581,152 @@ async function runHooks(handlers3, input, ctx, options2) {
|
|
|
76504
76581
|
init_takumi_constants();
|
|
76505
76582
|
init_types2();
|
|
76506
76583
|
|
|
76584
|
+
// src/commands/hooks/lib/codex-runtime-scrub.ts
|
|
76585
|
+
init_capabilities();
|
|
76586
|
+
function resolveCodexCapabilitiesSync() {
|
|
76587
|
+
if (process.env.CK_CODEX_COMPAT === "optimistic") {
|
|
76588
|
+
return CODEX_CAPABILITY_TABLE[0];
|
|
76589
|
+
}
|
|
76590
|
+
return CODEX_CAPABILITY_TABLE[CODEX_CAPABILITY_TABLE.length - 1];
|
|
76591
|
+
}
|
|
76592
|
+
function codexAllowsAdditionalContext(caps, event) {
|
|
76593
|
+
return caps.events[event]?.supportsAdditionalContext === true;
|
|
76594
|
+
}
|
|
76595
|
+
function codexAllowsPermission(caps, event, value) {
|
|
76596
|
+
const allowed = caps.events[event]?.permissionDecisionValues;
|
|
76597
|
+
return Array.isArray(allowed) && allowed.includes(value);
|
|
76598
|
+
}
|
|
76599
|
+
|
|
76600
|
+
// src/commands/hooks/lib/eval-hook-loader.ts
|
|
76601
|
+
import { pathToFileURL } from "node:url";
|
|
76602
|
+
|
|
76603
|
+
// src/commands/hooks/lib/process-exit-guard.ts
|
|
76604
|
+
var HOOK_EXIT = Symbol.for("takumi.eval.hookExit");
|
|
76605
|
+
function isHookExit(value) {
|
|
76606
|
+
return typeof value === "object" && value !== null && value[HOOK_EXIT] === true;
|
|
76607
|
+
}
|
|
76608
|
+
function installExitSentinel() {
|
|
76609
|
+
const realExit = process.exit;
|
|
76610
|
+
process.exit = (code) => {
|
|
76611
|
+
throw { [HOOK_EXIT]: true, code };
|
|
76612
|
+
};
|
|
76613
|
+
return () => {
|
|
76614
|
+
process.exit = realExit;
|
|
76615
|
+
};
|
|
76616
|
+
}
|
|
76617
|
+
var CONSOLE_METHODS = ["log", "info", "debug", "warn", "error", "trace", "dir", "table"];
|
|
76618
|
+
function installOutputSuppression() {
|
|
76619
|
+
const realOut = process.stdout.write.bind(process.stdout);
|
|
76620
|
+
const realErr = process.stderr.write.bind(process.stderr);
|
|
76621
|
+
const noopWrite = () => true;
|
|
76622
|
+
process.stdout.write = noopWrite;
|
|
76623
|
+
process.stderr.write = noopWrite;
|
|
76624
|
+
const con = console;
|
|
76625
|
+
const savedConsole = {};
|
|
76626
|
+
const noop2 = () => {};
|
|
76627
|
+
for (const m2 of CONSOLE_METHODS) {
|
|
76628
|
+
savedConsole[m2] = con[m2];
|
|
76629
|
+
con[m2] = noop2;
|
|
76630
|
+
}
|
|
76631
|
+
return () => {
|
|
76632
|
+
process.stdout.write = realOut;
|
|
76633
|
+
process.stderr.write = realErr;
|
|
76634
|
+
for (const m2 of CONSOLE_METHODS)
|
|
76635
|
+
con[m2] = savedConsole[m2];
|
|
76636
|
+
};
|
|
76637
|
+
}
|
|
76638
|
+
|
|
76639
|
+
// src/commands/hooks/lib/eval-hook-loader.ts
|
|
76640
|
+
async function loadEvalHook(absPath, meta) {
|
|
76641
|
+
const restore = installExitSentinel();
|
|
76642
|
+
let mod;
|
|
76643
|
+
try {
|
|
76644
|
+
mod = await import(pathToFileURL(absPath).href);
|
|
76645
|
+
} catch {
|
|
76646
|
+
return null;
|
|
76647
|
+
} finally {
|
|
76648
|
+
restore();
|
|
76649
|
+
}
|
|
76650
|
+
const runExport = resolveRunExport(mod);
|
|
76651
|
+
if (!runExport)
|
|
76652
|
+
return null;
|
|
76653
|
+
return {
|
|
76654
|
+
...meta,
|
|
76655
|
+
async run(input, ctx) {
|
|
76656
|
+
const restoreRun = installExitSentinel();
|
|
76657
|
+
try {
|
|
76658
|
+
return await runExport(input, ctx);
|
|
76659
|
+
} catch (err) {
|
|
76660
|
+
if (isHookExit(err)) {
|
|
76661
|
+
return { status: "no-op", timingMs: 0 };
|
|
76662
|
+
}
|
|
76663
|
+
throw err;
|
|
76664
|
+
} finally {
|
|
76665
|
+
restoreRun();
|
|
76666
|
+
}
|
|
76667
|
+
}
|
|
76668
|
+
};
|
|
76669
|
+
}
|
|
76670
|
+
function resolveRunExport(mod) {
|
|
76671
|
+
if (typeof mod.run === "function")
|
|
76672
|
+
return mod.run;
|
|
76673
|
+
const def = mod.default;
|
|
76674
|
+
if (def && typeof def.run === "function")
|
|
76675
|
+
return def.run;
|
|
76676
|
+
return null;
|
|
76677
|
+
}
|
|
76678
|
+
|
|
76679
|
+
// src/commands/hooks/lib/eval-hook-resolver.ts
|
|
76680
|
+
init_paths();
|
|
76681
|
+
init_codex_paths();
|
|
76682
|
+
import { isAbsolute as isAbsolute6, join as join117, normalize as normalize9, sep as sep10 } from "node:path";
|
|
76683
|
+
var HOOK_EXTENSIONS3 = [".cjs", ".mjs"];
|
|
76684
|
+
function hasHookExtension(p) {
|
|
76685
|
+
return HOOK_EXTENSIONS3.some((ext) => p.endsWith(ext));
|
|
76686
|
+
}
|
|
76687
|
+
function claudeHooksParent(scope, env2) {
|
|
76688
|
+
if (scope === "global")
|
|
76689
|
+
return getClaudeDir();
|
|
76690
|
+
if (scope === "project") {
|
|
76691
|
+
const projectDir = env2.CLAUDE_PROJECT_DIR;
|
|
76692
|
+
if (!projectDir || projectDir.trim() === "")
|
|
76693
|
+
return null;
|
|
76694
|
+
return join117(projectDir, ".claude");
|
|
76695
|
+
}
|
|
76696
|
+
const pluginRoot = env2.CLAUDE_PLUGIN_ROOT;
|
|
76697
|
+
if (!pluginRoot || pluginRoot.trim() === "")
|
|
76698
|
+
return null;
|
|
76699
|
+
return pluginRoot;
|
|
76700
|
+
}
|
|
76701
|
+
function resolveEvalHook(input) {
|
|
76702
|
+
const env2 = input.env ?? process.env;
|
|
76703
|
+
const { evalPath, scope, agent } = input;
|
|
76704
|
+
if (!evalPath || evalPath.trim() === "")
|
|
76705
|
+
return { ok: false, reason: "empty --eval path" };
|
|
76706
|
+
if (!hasHookExtension(evalPath)) {
|
|
76707
|
+
return { ok: false, reason: `--eval path is not a .cjs/.mjs file: ${evalPath}` };
|
|
76708
|
+
}
|
|
76709
|
+
if (agent === "codex" && scope === "project") {
|
|
76710
|
+
if (!isAbsolute6(evalPath)) {
|
|
76711
|
+
return { ok: false, reason: `codex --project --eval path must be absolute: ${evalPath}` };
|
|
76712
|
+
}
|
|
76713
|
+
return { ok: true, absPath: normalize9(evalPath) };
|
|
76714
|
+
}
|
|
76715
|
+
if (isAbsolute6(evalPath)) {
|
|
76716
|
+
return { ok: false, reason: `--eval path must be relative for ${agent}/${scope}: ${evalPath}` };
|
|
76717
|
+
}
|
|
76718
|
+
const hooksParent = agent === "codex" ? codexGlobalRoot() : claudeHooksParent(scope, env2);
|
|
76719
|
+
if (!hooksParent) {
|
|
76720
|
+
return { ok: false, reason: `no trusted anchor for ${agent}/${scope} (env var unset)` };
|
|
76721
|
+
}
|
|
76722
|
+
const hooksDir = normalize9(join117(hooksParent, "hooks"));
|
|
76723
|
+
const abs2 = normalize9(join117(hooksParent, evalPath));
|
|
76724
|
+
if (abs2 !== hooksDir && !abs2.startsWith(hooksDir + sep10)) {
|
|
76725
|
+
return { ok: false, reason: `--eval path escapes the hooks dir: ${evalPath}` };
|
|
76726
|
+
}
|
|
76727
|
+
return { ok: true, absPath: abs2 };
|
|
76728
|
+
}
|
|
76729
|
+
|
|
76507
76730
|
// src/commands/hooks/lib/hook-events.ts
|
|
76508
76731
|
var KEBAB_TO_CANONICAL = {
|
|
76509
76732
|
"session-start": "SessionStart",
|
|
@@ -76683,7 +76906,11 @@ async function defaultLoadConfig(cwd2) {
|
|
|
76683
76906
|
return DEFAULT_TAKUMI_CONFIG;
|
|
76684
76907
|
}
|
|
76685
76908
|
}
|
|
76686
|
-
function emitDeny(write, event, reason) {
|
|
76909
|
+
function emitDeny(write, event, reason, caps) {
|
|
76910
|
+
if (caps && !codexAllowsPermission(caps, event, "deny")) {
|
|
76911
|
+
write("{}");
|
|
76912
|
+
return;
|
|
76913
|
+
}
|
|
76687
76914
|
write(JSON.stringify({
|
|
76688
76915
|
hookSpecificOutput: {
|
|
76689
76916
|
hookEventName: event,
|
|
@@ -76692,7 +76919,24 @@ function emitDeny(write, event, reason) {
|
|
|
76692
76919
|
}
|
|
76693
76920
|
}));
|
|
76694
76921
|
}
|
|
76695
|
-
function
|
|
76922
|
+
function emitAsk(write, event, reason, caps) {
|
|
76923
|
+
if (caps && !codexAllowsPermission(caps, event, "ask")) {
|
|
76924
|
+
write("{}");
|
|
76925
|
+
return;
|
|
76926
|
+
}
|
|
76927
|
+
write(JSON.stringify({
|
|
76928
|
+
hookSpecificOutput: {
|
|
76929
|
+
hookEventName: event,
|
|
76930
|
+
permissionDecision: "ask",
|
|
76931
|
+
permissionDecisionReason: reason ?? ""
|
|
76932
|
+
}
|
|
76933
|
+
}));
|
|
76934
|
+
}
|
|
76935
|
+
function emitContext(write, event, output2, caps) {
|
|
76936
|
+
if (caps && !codexAllowsAdditionalContext(caps, event)) {
|
|
76937
|
+
write("{}");
|
|
76938
|
+
return;
|
|
76939
|
+
}
|
|
76696
76940
|
write(JSON.stringify({
|
|
76697
76941
|
hookSpecificOutput: { hookEventName: event, additionalContext: output2 }
|
|
76698
76942
|
}));
|
|
@@ -76702,10 +76946,12 @@ async function runHookExec(args, deps = {}) {
|
|
|
76702
76946
|
try {
|
|
76703
76947
|
const readInput = deps.readInput ?? (() => readStdinJson());
|
|
76704
76948
|
const now = deps.now ?? (() => new Date().toISOString());
|
|
76705
|
-
|
|
76706
|
-
|
|
76707
|
-
|
|
76708
|
-
|
|
76949
|
+
if (!args.eval) {
|
|
76950
|
+
const selector = parseHookSelector(args.hook ?? "");
|
|
76951
|
+
if (!selector) {
|
|
76952
|
+
write("{}");
|
|
76953
|
+
return;
|
|
76954
|
+
}
|
|
76709
76955
|
}
|
|
76710
76956
|
const input = await readInput();
|
|
76711
76957
|
const event = normalizeHookEvent(typeof input.hook_event_name === "string" ? input.hook_event_name : args.event);
|
|
@@ -76713,7 +76959,7 @@ async function runHookExec(args, deps = {}) {
|
|
|
76713
76959
|
write("{}");
|
|
76714
76960
|
return;
|
|
76715
76961
|
}
|
|
76716
|
-
const handlers3 =
|
|
76962
|
+
const handlers3 = await resolveHandlers(args, event, deps);
|
|
76717
76963
|
if (handlers3.length === 0) {
|
|
76718
76964
|
write("{}");
|
|
76719
76965
|
return;
|
|
@@ -76736,21 +76982,29 @@ async function runHookExec(args, deps = {}) {
|
|
|
76736
76982
|
runtimeFlags: { noDetach: args.noDetach, debug: args.debug }
|
|
76737
76983
|
};
|
|
76738
76984
|
const sessionDir = sessionId ? getSessionDirV2({ agent: args.agent, cwd: cwd2, sessionId }) : null;
|
|
76739
|
-
const
|
|
76985
|
+
const budget = args.eval && args.timeoutMs === undefined ? {} : {
|
|
76740
76986
|
timeoutMs: args.timeoutMs ?? DEFAULT_TIMEOUT_MS5,
|
|
76741
|
-
timeoutMsByPolicy: { record: args.recordTimeoutMs ?? RECORD_TIMEOUT_MS }
|
|
76987
|
+
timeoutMsByPolicy: { record: args.recordTimeoutMs ?? RECORD_TIMEOUT_MS }
|
|
76988
|
+
};
|
|
76989
|
+
const result = await runHooks(handlers3, input, ctx, {
|
|
76990
|
+
...budget,
|
|
76742
76991
|
onHandlerComplete: (handlerName, handlerResult) => {
|
|
76743
76992
|
if (!sessionDir)
|
|
76744
76993
|
return;
|
|
76745
76994
|
appendObservation(sessionDir, buildObservation({ handlerName, ctx, result: handlerResult, endedAt: now() }));
|
|
76746
76995
|
}
|
|
76747
76996
|
});
|
|
76997
|
+
const caps = args.agent === "codex" ? resolveCodexCapabilitiesSync() : null;
|
|
76748
76998
|
if (result.status === "deny") {
|
|
76749
|
-
emitDeny(write, event, result.denyReason);
|
|
76999
|
+
emitDeny(write, event, result.denyReason, caps);
|
|
77000
|
+
return;
|
|
77001
|
+
}
|
|
77002
|
+
if (result.status === "ask") {
|
|
77003
|
+
emitAsk(write, event, result.askReason, caps);
|
|
76750
77004
|
return;
|
|
76751
77005
|
}
|
|
76752
77006
|
if (result.status === "context" && result.output) {
|
|
76753
|
-
emitContext(write, event, result.output);
|
|
77007
|
+
emitContext(write, event, result.output, caps);
|
|
76754
77008
|
return;
|
|
76755
77009
|
}
|
|
76756
77010
|
write("{}");
|
|
@@ -76758,8 +77012,36 @@ async function runHookExec(args, deps = {}) {
|
|
|
76758
77012
|
write("{}");
|
|
76759
77013
|
}
|
|
76760
77014
|
}
|
|
77015
|
+
async function resolveHandlers(args, event, deps) {
|
|
77016
|
+
if (args.eval) {
|
|
77017
|
+
const resolved = resolveEvalHook({
|
|
77018
|
+
evalPath: args.eval.path,
|
|
77019
|
+
scope: args.eval.scope,
|
|
77020
|
+
agent: args.agent
|
|
77021
|
+
});
|
|
77022
|
+
if (!resolved.ok)
|
|
77023
|
+
return [];
|
|
77024
|
+
const meta = args.eval.meta ?? defaultEvalMeta(resolved.absPath, event);
|
|
77025
|
+
const handler = await loadEvalHook(resolved.absPath, meta);
|
|
77026
|
+
return handler ? [handler] : [];
|
|
77027
|
+
}
|
|
77028
|
+
const selector = parseHookSelector(args.hook ?? "");
|
|
77029
|
+
if (!selector)
|
|
77030
|
+
return [];
|
|
77031
|
+
return selectHandlers(selector, event, deps.handlers);
|
|
77032
|
+
}
|
|
77033
|
+
function defaultEvalMeta(absPath, event) {
|
|
77034
|
+
const base = absPath.split(/[\\/]/).pop() ?? "eval-hook";
|
|
77035
|
+
return {
|
|
77036
|
+
name: base.replace(/\.(cjs|mjs)$/, ""),
|
|
77037
|
+
category: "extension",
|
|
77038
|
+
policy: "context",
|
|
77039
|
+
events: [event]
|
|
77040
|
+
};
|
|
77041
|
+
}
|
|
76761
77042
|
|
|
76762
77043
|
// src/commands/hooks/hook-exec-command.ts
|
|
77044
|
+
var realProcessExit = process.exit;
|
|
76763
77045
|
async function hookExecCommand(options2) {
|
|
76764
77046
|
const agent = options2.agent === "codex" ? "codex" : "claude";
|
|
76765
77047
|
try {
|
|
@@ -76768,12 +77050,15 @@ async function hookExecCommand(options2) {
|
|
|
76768
77050
|
event: options2.event,
|
|
76769
77051
|
agent,
|
|
76770
77052
|
noDetach: options2.noDetach,
|
|
76771
|
-
debug: options2.debug
|
|
77053
|
+
debug: options2.debug,
|
|
77054
|
+
eval: options2.eval ? { path: options2.eval, scope: options2.scope ?? "project" } : undefined
|
|
76772
77055
|
});
|
|
76773
77056
|
} catch {
|
|
76774
77057
|
process.stdout.write("{}");
|
|
76775
77058
|
}
|
|
76776
77059
|
process.exitCode = 0;
|
|
77060
|
+
if (options2.eval)
|
|
77061
|
+
realProcessExit(0);
|
|
76777
77062
|
}
|
|
76778
77063
|
// src/commands/hooks/hooks-command.ts
|
|
76779
77064
|
init_logger();
|
|
@@ -76812,12 +77097,85 @@ async function handleDoPut() {
|
|
|
76812
77097
|
}
|
|
76813
77098
|
}
|
|
76814
77099
|
|
|
77100
|
+
// src/commands/hooks/event-handlers/scan-meta.ts
|
|
77101
|
+
import { writeFileSync as writeFileSync11 } from "node:fs";
|
|
77102
|
+
|
|
77103
|
+
// src/commands/hooks/lib/kit-hook-resolver.ts
|
|
77104
|
+
init_zod();
|
|
77105
|
+
import { readFileSync as readFileSync20, readdirSync as readdirSync11 } from "node:fs";
|
|
77106
|
+
import { join as join118 } from "node:path";
|
|
77107
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
77108
|
+
var KitHookMetaSchema = exports_external.object({
|
|
77109
|
+
events: exports_external.array(exports_external.string().min(1)).min(1),
|
|
77110
|
+
matchers: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
77111
|
+
timeout: exports_external.number().positive().optional()
|
|
77112
|
+
});
|
|
77113
|
+
var NOT_A_HOOK = /(\.test\.|\.spec\.|^_|^\.)/;
|
|
77114
|
+
var HOOK_EXT = /\.(?:cjs|mjs)$/;
|
|
77115
|
+
var DUAL_MODE_GUARD = /require\.main|import\.meta\.main/;
|
|
77116
|
+
async function readKitHookMeta(absPath) {
|
|
77117
|
+
const restoreExit = installExitSentinel();
|
|
77118
|
+
const restoreOut = installOutputSuppression();
|
|
77119
|
+
let mod;
|
|
77120
|
+
try {
|
|
77121
|
+
mod = await import(pathToFileURL2(absPath).href);
|
|
77122
|
+
} catch {
|
|
77123
|
+
return null;
|
|
77124
|
+
} finally {
|
|
77125
|
+
restoreOut();
|
|
77126
|
+
restoreExit();
|
|
77127
|
+
}
|
|
77128
|
+
const raw = mod.meta ?? mod.default?.meta;
|
|
77129
|
+
const parsed = KitHookMetaSchema.safeParse(raw);
|
|
77130
|
+
return parsed.success ? parsed.data : null;
|
|
77131
|
+
}
|
|
77132
|
+
async function scanHooksDirForMeta(hooksDir) {
|
|
77133
|
+
let names;
|
|
77134
|
+
try {
|
|
77135
|
+
names = readdirSync11(hooksDir, { withFileTypes: true }).filter((d3) => d3.isFile()).map((d3) => d3.name);
|
|
77136
|
+
} catch {
|
|
77137
|
+
return [];
|
|
77138
|
+
}
|
|
77139
|
+
const out = [];
|
|
77140
|
+
for (const file of names) {
|
|
77141
|
+
if (!HOOK_EXT.test(file) || NOT_A_HOOK.test(file))
|
|
77142
|
+
continue;
|
|
77143
|
+
const abs2 = join118(hooksDir, file);
|
|
77144
|
+
let src;
|
|
77145
|
+
try {
|
|
77146
|
+
src = readFileSync20(abs2, "utf8");
|
|
77147
|
+
} catch {
|
|
77148
|
+
continue;
|
|
77149
|
+
}
|
|
77150
|
+
if (!DUAL_MODE_GUARD.test(src))
|
|
77151
|
+
continue;
|
|
77152
|
+
const meta = await readKitHookMeta(abs2);
|
|
77153
|
+
if (meta)
|
|
77154
|
+
out.push({ file, ...meta });
|
|
77155
|
+
}
|
|
77156
|
+
return out;
|
|
77157
|
+
}
|
|
77158
|
+
|
|
77159
|
+
// src/commands/hooks/event-handlers/scan-meta.ts
|
|
77160
|
+
async function handleScanMeta(dir, out) {
|
|
77161
|
+
const entries = dir ? await scanHooksDirForMeta(dir) : [];
|
|
77162
|
+
const json = JSON.stringify(entries);
|
|
77163
|
+
if (out) {
|
|
77164
|
+
try {
|
|
77165
|
+
writeFileSync11(out, json);
|
|
77166
|
+
return;
|
|
77167
|
+
} catch {}
|
|
77168
|
+
}
|
|
77169
|
+
process.stdout.write(json);
|
|
77170
|
+
}
|
|
77171
|
+
|
|
76815
77172
|
// src/commands/hooks/install-handler.ts
|
|
76816
77173
|
init_hooks_settings_merger();
|
|
77174
|
+
import { basename as basename19 } from "node:path";
|
|
76817
77175
|
|
|
76818
77176
|
// src/commands/portable/settings-write-with-confirm.ts
|
|
76819
77177
|
init_safe_prompts();
|
|
76820
|
-
import { existsSync as existsSync55, mkdirSync as mkdirSync8, readFileSync as
|
|
77178
|
+
import { existsSync as existsSync55, mkdirSync as mkdirSync8, readFileSync as readFileSync21, renameSync as renameSync4, rmSync as rmSync7, writeFileSync as writeFileSync12 } from "node:fs";
|
|
76821
77179
|
import { dirname as dirname30 } from "node:path";
|
|
76822
77180
|
|
|
76823
77181
|
// node_modules/diff/libesm/diff/base.js
|
|
@@ -77994,7 +78352,7 @@ function readCurrent(path10) {
|
|
|
77994
78352
|
return { kind: "missing" };
|
|
77995
78353
|
let raw = "";
|
|
77996
78354
|
try {
|
|
77997
|
-
raw =
|
|
78355
|
+
raw = readFileSync21(path10, "utf8");
|
|
77998
78356
|
const parsed = JSON.parse(raw);
|
|
77999
78357
|
return { kind: "ok", raw, parsed };
|
|
78000
78358
|
} catch {
|
|
@@ -78024,7 +78382,7 @@ function atomicWrite2(path10, contents, backupPath) {
|
|
|
78024
78382
|
mkdirSync8(dirname30(path10), { recursive: true });
|
|
78025
78383
|
const tmp = `${path10}.tmp`;
|
|
78026
78384
|
try {
|
|
78027
|
-
|
|
78385
|
+
writeFileSync12(tmp, contents);
|
|
78028
78386
|
renameSync4(tmp, path10);
|
|
78029
78387
|
} catch (err) {
|
|
78030
78388
|
rmSync7(tmp, { force: true });
|
|
@@ -78036,7 +78394,7 @@ function writeBackup(path10, raw) {
|
|
|
78036
78394
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
78037
78395
|
const backupPath = `${path10}.${timestamp}.bak`;
|
|
78038
78396
|
try {
|
|
78039
|
-
|
|
78397
|
+
writeFileSync12(backupPath, raw);
|
|
78040
78398
|
return backupPath;
|
|
78041
78399
|
} catch {
|
|
78042
78400
|
return null;
|
|
@@ -78110,15 +78468,21 @@ init_dist2();
|
|
|
78110
78468
|
import { existsSync as existsSync56 } from "node:fs";
|
|
78111
78469
|
|
|
78112
78470
|
// src/commands/hooks/lib/settings-path-resolver.ts
|
|
78471
|
+
init_paths();
|
|
78472
|
+
init_codex_paths();
|
|
78113
78473
|
import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "node:fs";
|
|
78114
|
-
import {
|
|
78115
|
-
|
|
78474
|
+
import { join as join119 } from "node:path";
|
|
78475
|
+
function agentConfigDir(agent, global3) {
|
|
78476
|
+
if (global3)
|
|
78477
|
+
return agent === "claude" ? getClaudeDir() : codexGlobalRoot();
|
|
78478
|
+
return join119(process.cwd(), agent === "claude" ? ".claude" : ".codex");
|
|
78479
|
+
}
|
|
78116
78480
|
function rawPath(agent, global3) {
|
|
78117
|
-
const
|
|
78118
|
-
|
|
78119
|
-
|
|
78120
|
-
|
|
78121
|
-
return
|
|
78481
|
+
const configDir = agentConfigDir(agent, global3);
|
|
78482
|
+
return join119(configDir, agent === "claude" ? "settings.json" : "hooks.json");
|
|
78483
|
+
}
|
|
78484
|
+
function resolveHooksDir(agent, options2 = {}) {
|
|
78485
|
+
return join119(agentConfigDir(agent, Boolean(options2.global)), "hooks");
|
|
78122
78486
|
}
|
|
78123
78487
|
function resolveSettingsPath(agent, options2 = {}) {
|
|
78124
78488
|
const originalPath = rawPath(agent, Boolean(options2.global));
|
|
@@ -78190,7 +78554,9 @@ async function promptHookAgentTargets(options2) {
|
|
|
78190
78554
|
}
|
|
78191
78555
|
|
|
78192
78556
|
// src/commands/hooks/lib/entry-builder.ts
|
|
78557
|
+
import { join as join120 } from "node:path";
|
|
78193
78558
|
init_capabilities();
|
|
78559
|
+
init_logger();
|
|
78194
78560
|
var DEFAULT_HOOK_BIN = "tkm";
|
|
78195
78561
|
var SETTINGS_TIMEOUT_BY_POLICY = {
|
|
78196
78562
|
deny: 10,
|
|
@@ -78210,11 +78576,11 @@ function codexMatcher(event, declared) {
|
|
|
78210
78576
|
const kept = declared.split("|").filter((m2) => allowed.includes(m2));
|
|
78211
78577
|
return kept.length > 0 ? kept.join("|") : undefined;
|
|
78212
78578
|
}
|
|
78213
|
-
function buildHookExecCommand(handler, event, agent, bin = DEFAULT_HOOK_BIN, flags = {}) {
|
|
78579
|
+
function buildHookExecCommand(handler, event, agent, bin = DEFAULT_HOOK_BIN, flags = {}, scope = "project") {
|
|
78214
78580
|
const kebab = canonicalToKebab(event);
|
|
78215
78581
|
if (!kebab)
|
|
78216
78582
|
return null;
|
|
78217
|
-
const parts = [
|
|
78583
|
+
const parts = handler.evalPath ? buildEvalParts(handler.evalPath, agent, scope, bin, kebab) : [
|
|
78218
78584
|
bin,
|
|
78219
78585
|
"hook-exec",
|
|
78220
78586
|
"--hook",
|
|
@@ -78230,12 +78596,21 @@ function buildHookExecCommand(handler, event, agent, bin = DEFAULT_HOOK_BIN, fla
|
|
|
78230
78596
|
parts.push("--debug");
|
|
78231
78597
|
return parts.join(" ");
|
|
78232
78598
|
}
|
|
78233
|
-
function
|
|
78234
|
-
|
|
78599
|
+
function buildEvalParts(evalPath, agent, scope, bin, kebab) {
|
|
78600
|
+
const scopeFlag = scope === "global" ? "-g" : scope === "plugin" ? "--plugin" : "--project";
|
|
78601
|
+
const pathArg = agent === "codex" && scope === "project" ? `"${join120(process.cwd(), ".codex", evalPath)}"` : evalPath;
|
|
78602
|
+
return [bin, "hook-exec", "--eval", pathArg, scopeFlag, "--event", kebab, "-a", agent];
|
|
78603
|
+
}
|
|
78604
|
+
function planEntry(handler, event, agent, bin, flags, scope) {
|
|
78605
|
+
if (agent === "codex" && !codexSupportsEvent(event)) {
|
|
78606
|
+
if (handler.evalPath) {
|
|
78607
|
+
logger.warning(`[hooks] kit eval hook "${handler.name}" declares event "${event}" not supported by Codex — skipping this entry for Codex.`);
|
|
78608
|
+
}
|
|
78235
78609
|
return null;
|
|
78610
|
+
}
|
|
78236
78611
|
if (agent !== "codex" && handler.codexOnlyEvents?.includes(event))
|
|
78237
78612
|
return null;
|
|
78238
|
-
const command = buildHookExecCommand(handler, event, agent, bin, flags);
|
|
78613
|
+
const command = buildHookExecCommand(handler, event, agent, bin, flags, scope);
|
|
78239
78614
|
if (!command)
|
|
78240
78615
|
return null;
|
|
78241
78616
|
const declared = handler.matchers?.[event];
|
|
@@ -78243,16 +78618,20 @@ function planEntry(handler, event, agent, bin, flags) {
|
|
|
78243
78618
|
return {
|
|
78244
78619
|
event,
|
|
78245
78620
|
matcher,
|
|
78246
|
-
entry: {
|
|
78621
|
+
entry: {
|
|
78622
|
+
type: "command",
|
|
78623
|
+
command,
|
|
78624
|
+
timeout: handler.timeoutSeconds ?? SETTINGS_TIMEOUT_BY_POLICY[handler.policy]
|
|
78625
|
+
}
|
|
78247
78626
|
};
|
|
78248
78627
|
}
|
|
78249
|
-
function buildHookSection(agent, bin, flags = {}, handlers3 = HOOK_HANDLERS) {
|
|
78628
|
+
function buildHookSection(agent, bin, flags = {}, handlers3 = HOOK_HANDLERS, scope = "project") {
|
|
78250
78629
|
const section = {};
|
|
78251
78630
|
for (const handler of handlers3) {
|
|
78252
78631
|
if (handler.installAgents && !handler.installAgents.includes(agent))
|
|
78253
78632
|
continue;
|
|
78254
78633
|
for (const event of handler.events) {
|
|
78255
|
-
const planned = planEntry(handler, event, agent, bin, flags);
|
|
78634
|
+
const planned = planEntry(handler, event, agent, bin, flags, scope);
|
|
78256
78635
|
if (!planned)
|
|
78257
78636
|
continue;
|
|
78258
78637
|
if (!section[planned.event])
|
|
@@ -78344,23 +78723,96 @@ function installStatusline(settings, opts) {
|
|
|
78344
78723
|
|
|
78345
78724
|
// src/commands/hooks/uninstall-handler.ts
|
|
78346
78725
|
init_logger();
|
|
78347
|
-
import { existsSync as existsSync57, mkdirSync as mkdirSync9, readFileSync as
|
|
78726
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync9, readFileSync as readFileSync23, renameSync as renameSync5, rmSync as rmSync9, writeFileSync as writeFileSync13 } from "node:fs";
|
|
78348
78727
|
import { dirname as dirname31 } from "node:path";
|
|
78728
|
+
|
|
78729
|
+
// src/commands/hooks/lib/kit-hook-scan.ts
|
|
78730
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
78731
|
+
import { mkdtempSync, readFileSync as readFileSync22, rmSync as rmSync8 } from "node:fs";
|
|
78732
|
+
import { tmpdir as tmpdir5 } from "node:os";
|
|
78733
|
+
import { join as join121 } from "node:path";
|
|
78734
|
+
var SCAN_TIMEOUT_MS = 8000;
|
|
78735
|
+
function scanKitHookMetas(hooksDir) {
|
|
78736
|
+
const { command, prefixArgs } = resolveInvocationPrefix();
|
|
78737
|
+
const tmp = mkdtempSync(join121(tmpdir5(), "tkm-hook-scan-"));
|
|
78738
|
+
const outFile = join121(tmp, "meta.json");
|
|
78739
|
+
try {
|
|
78740
|
+
spawnSync5(command, [...prefixArgs, "hooks", "scan-meta", "--dir", hooksDir, "--out", outFile], {
|
|
78741
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
78742
|
+
timeout: SCAN_TIMEOUT_MS,
|
|
78743
|
+
killSignal: "SIGKILL",
|
|
78744
|
+
env: buildChildEnv()
|
|
78745
|
+
});
|
|
78746
|
+
const parsed = JSON.parse(readFileSync22(outFile, "utf8"));
|
|
78747
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
78748
|
+
} catch {
|
|
78749
|
+
return [];
|
|
78750
|
+
} finally {
|
|
78751
|
+
rmSync8(tmp, { recursive: true, force: true });
|
|
78752
|
+
}
|
|
78753
|
+
}
|
|
78754
|
+
function kitHookToInstallMeta(entry) {
|
|
78755
|
+
return {
|
|
78756
|
+
name: entry.file.replace(/\.(?:cjs|mjs)$/, ""),
|
|
78757
|
+
category: "extension",
|
|
78758
|
+
policy: "context",
|
|
78759
|
+
events: entry.events,
|
|
78760
|
+
matchers: entry.matchers,
|
|
78761
|
+
evalPath: `hooks/${entry.file}`,
|
|
78762
|
+
timeoutSeconds: entry.timeout
|
|
78763
|
+
};
|
|
78764
|
+
}
|
|
78765
|
+
|
|
78766
|
+
// src/commands/hooks/uninstall-handler.ts
|
|
78349
78767
|
var AGENT_DISPLAY2 = {
|
|
78350
78768
|
claude: "Claude Code",
|
|
78351
78769
|
codex: "Codex"
|
|
78352
78770
|
};
|
|
78353
78771
|
var HOOK_CATEGORIES = "(guard|session|convention|extension|metrics|perf)";
|
|
78354
78772
|
var LEGACY_EVENTS = "(session-start|user-prompt-submit|pre-tool-use|post-tool-use|stop|session-end)";
|
|
78355
|
-
|
|
78773
|
+
var LEGACY_NODE_HOOK = /\bnode(?:\.exe)?\s+["']?.*?[/\\]hooks[/\\]([\w.-]+\.(?:cjs|mjs))["']?/;
|
|
78774
|
+
var EVAL_HOOK_FILE = /--eval\s+["']?[^\s"']*?([\w.-]+\.(?:cjs|mjs))["']?/;
|
|
78775
|
+
function isOurCommand(command, agent, evalHookNames, unconditionalEval = false) {
|
|
78356
78776
|
const agentTail = `-a\\s+${agent}(?![\\w-])`;
|
|
78357
78777
|
const newShape = new RegExp(`\\bhook-exec\\b.*--hook\\s+${HOOK_CATEGORIES}\\.\\S+.*${agentTail}`);
|
|
78358
78778
|
if (newShape.test(command))
|
|
78359
78779
|
return true;
|
|
78780
|
+
if (isKitEvalHook(command, agentTail, evalHookNames, unconditionalEval))
|
|
78781
|
+
return true;
|
|
78360
78782
|
const legacy = new RegExp(`\\bhooks\\s+${LEGACY_EVENTS}\\s+${agentTail}`);
|
|
78361
|
-
|
|
78783
|
+
if (legacy.test(command))
|
|
78784
|
+
return true;
|
|
78785
|
+
return isLegacyKitNodeHook(command, evalHookNames);
|
|
78786
|
+
}
|
|
78787
|
+
function isKitEvalHook(command, agentTail, evalHookNames, unconditional) {
|
|
78788
|
+
if (!new RegExp(`\\bhook-exec\\b.*--eval\\b.*${agentTail}`).test(command))
|
|
78789
|
+
return false;
|
|
78790
|
+
if (unconditional)
|
|
78791
|
+
return true;
|
|
78792
|
+
if (!evalHookNames || evalHookNames.size === 0)
|
|
78793
|
+
return false;
|
|
78794
|
+
const m2 = command.match(EVAL_HOOK_FILE);
|
|
78795
|
+
return m2 !== null && evalHookNames.has(m2[1]);
|
|
78796
|
+
}
|
|
78797
|
+
function isLegacyKitNodeHook(command, evalHookNames) {
|
|
78798
|
+
if (!evalHookNames || evalHookNames.size === 0)
|
|
78799
|
+
return false;
|
|
78800
|
+
const m2 = command.match(LEGACY_NODE_HOOK);
|
|
78801
|
+
if (!m2)
|
|
78802
|
+
return false;
|
|
78803
|
+
const file = m2[1];
|
|
78804
|
+
if (evalHookNames.has(file))
|
|
78805
|
+
return true;
|
|
78806
|
+
for (const name2 of evalHookNames) {
|
|
78807
|
+
if (!file.endsWith(`-${name2}`))
|
|
78808
|
+
continue;
|
|
78809
|
+
const prefix = file.slice(0, file.length - name2.length - 1);
|
|
78810
|
+
if (/^[0-9a-f]+$/.test(prefix))
|
|
78811
|
+
return true;
|
|
78812
|
+
}
|
|
78813
|
+
return false;
|
|
78362
78814
|
}
|
|
78363
|
-
function pruneHooksSection(hooks, agent) {
|
|
78815
|
+
function pruneHooksSection(hooks, agent, evalHookNames, unconditionalEval = false) {
|
|
78364
78816
|
const pruned = {};
|
|
78365
78817
|
let removed = 0;
|
|
78366
78818
|
for (const [event, groups] of Object.entries(hooks)) {
|
|
@@ -78369,7 +78821,7 @@ function pruneHooksSection(hooks, agent) {
|
|
|
78369
78821
|
const kept = [];
|
|
78370
78822
|
for (const entry of group.hooks) {
|
|
78371
78823
|
const command = typeof entry.command === "string" ? entry.command : "";
|
|
78372
|
-
if (isOurCommand(command, agent)) {
|
|
78824
|
+
if (isOurCommand(command, agent, evalHookNames, unconditionalEval)) {
|
|
78373
78825
|
removed++;
|
|
78374
78826
|
} else {
|
|
78375
78827
|
kept.push(entry);
|
|
@@ -78389,10 +78841,10 @@ function writeAtomic(path10, contents) {
|
|
|
78389
78841
|
mkdirSync9(dirname31(path10), { recursive: true });
|
|
78390
78842
|
const tmp = `${path10}.tmp`;
|
|
78391
78843
|
try {
|
|
78392
|
-
|
|
78844
|
+
writeFileSync13(tmp, contents);
|
|
78393
78845
|
renameSync5(tmp, path10);
|
|
78394
78846
|
} catch (err) {
|
|
78395
|
-
|
|
78847
|
+
rmSync9(tmp, { force: true });
|
|
78396
78848
|
throw err;
|
|
78397
78849
|
}
|
|
78398
78850
|
}
|
|
@@ -78409,13 +78861,15 @@ async function uninstallForAgent(agent, options2) {
|
|
|
78409
78861
|
}
|
|
78410
78862
|
let parsed;
|
|
78411
78863
|
try {
|
|
78412
|
-
parsed = JSON.parse(
|
|
78864
|
+
parsed = JSON.parse(readFileSync23(location2.realPath, "utf8"));
|
|
78413
78865
|
} catch {
|
|
78414
78866
|
logger.warning(`[hooks] could not parse ${location2.realPath}; uninstall skipped to avoid clobbering`);
|
|
78415
78867
|
return result;
|
|
78416
78868
|
}
|
|
78417
78869
|
const hooks = parsed.hooks ?? {};
|
|
78418
|
-
const
|
|
78870
|
+
const hooksDir = resolveHooksDir(agent, { global: options2.global });
|
|
78871
|
+
const evalHookNames = new Set(scanKitHookMetas(hooksDir).map((e2) => e2.file));
|
|
78872
|
+
const { pruned, removed } = pruneHooksSection(hooks, agent, evalHookNames, true);
|
|
78419
78873
|
result.removed = removed;
|
|
78420
78874
|
if (removed === 0)
|
|
78421
78875
|
return result;
|
|
@@ -78473,11 +78927,14 @@ function eventsSummary(section) {
|
|
|
78473
78927
|
}
|
|
78474
78928
|
async function installForAgent(agent, options2, interactive, useStepUI) {
|
|
78475
78929
|
const location2 = resolveSettingsPath(agent, { global: options2.global });
|
|
78930
|
+
const scope = options2.global ? "global" : "project";
|
|
78476
78931
|
const handlers3 = selectHandlersForInstall(options2.categories);
|
|
78932
|
+
const evalMetas = options2.evalHooks ?? [];
|
|
78933
|
+
const evalHookNames = new Set(evalMetas.map((m2) => m2.evalPath ? basename19(m2.evalPath) : "").filter(Boolean));
|
|
78477
78934
|
const section = buildHookSection(agent, options2.bin, {
|
|
78478
78935
|
noDetach: options2.noDetach,
|
|
78479
78936
|
debug: options2.debug
|
|
78480
|
-
}, handlers3);
|
|
78937
|
+
}, [...handlers3, ...evalMetas], scope);
|
|
78481
78938
|
const entriesPlanned = countEntries(section);
|
|
78482
78939
|
const handlerNames = new Set(handlers3.map((h2) => h2.name));
|
|
78483
78940
|
const result = await writeSettingsWithConfirm({
|
|
@@ -78486,7 +78943,7 @@ async function installForAgent(agent, options2, interactive, useStepUI) {
|
|
|
78486
78943
|
transform: (current) => {
|
|
78487
78944
|
const safeCurrent = current ?? {};
|
|
78488
78945
|
const existingHooks = safeCurrent.hooks ?? {};
|
|
78489
|
-
const { pruned } = pruneHooksSection(existingHooks, agent);
|
|
78946
|
+
const { pruned } = pruneHooksSection(existingHooks, agent, evalHookNames);
|
|
78490
78947
|
const purged = { ...safeCurrent, hooks: pruned };
|
|
78491
78948
|
const merged = mergeHooksObject(purged, section);
|
|
78492
78949
|
return installStatusline(merged, {
|
|
@@ -78631,7 +79088,7 @@ async function installHook(options2) {
|
|
|
78631
79088
|
// src/commands/hooks/status.ts
|
|
78632
79089
|
init_takumi_config_manager();
|
|
78633
79090
|
init_logger();
|
|
78634
|
-
import { existsSync as existsSync58, readFileSync as
|
|
79091
|
+
import { existsSync as existsSync58, readFileSync as readFileSync24 } from "node:fs";
|
|
78635
79092
|
var AGENT_DISPLAY4 = { claude: "Claude Code", codex: "Codex" };
|
|
78636
79093
|
var NEW_SHAPE = /\bhook-exec\b.*--hook\s+(guard|session|convention|extension|metrics|perf)\.(\S+).*-a\s+(claude|codex)(?![\w-])/;
|
|
78637
79094
|
var LEGACY_SHAPE = /\bhooks\s+(?:session-start|user-prompt-submit|pre-tool-use|post-tool-use|stop|session-end)\s+-a\s+(claude|codex)(?![\w-])/;
|
|
@@ -78672,7 +79129,7 @@ async function statusForAgent(agent, options2, cwd2 = process.cwd()) {
|
|
|
78672
79129
|
return result;
|
|
78673
79130
|
let hooks;
|
|
78674
79131
|
try {
|
|
78675
|
-
const parsed = JSON.parse(
|
|
79132
|
+
const parsed = JSON.parse(readFileSync24(location2.realPath, "utf8"));
|
|
78676
79133
|
hooks = parsed.hooks ?? {};
|
|
78677
79134
|
} catch {
|
|
78678
79135
|
return result;
|
|
@@ -78734,7 +79191,7 @@ var VALID_EVENTS = [
|
|
|
78734
79191
|
"stop",
|
|
78735
79192
|
"session-end"
|
|
78736
79193
|
];
|
|
78737
|
-
var VALID_INTERNAL_EVENTS = ["_do-put", "_otlp-post"];
|
|
79194
|
+
var VALID_INTERNAL_EVENTS = ["_do-put", "_otlp-post", "scan-meta"];
|
|
78738
79195
|
function isAction(token) {
|
|
78739
79196
|
return VALID_ACTIONS.includes(token);
|
|
78740
79197
|
}
|
|
@@ -78817,6 +79274,9 @@ async function hooksCommand(subcommand, options2 = {}) {
|
|
|
78817
79274
|
case "_otlp-post":
|
|
78818
79275
|
await handleOtlpPost();
|
|
78819
79276
|
return;
|
|
79277
|
+
case "scan-meta":
|
|
79278
|
+
await handleScanMeta(options2.dir, options2.out);
|
|
79279
|
+
return;
|
|
78820
79280
|
}
|
|
78821
79281
|
}
|
|
78822
79282
|
logger.error(`Unknown hooks subcommand: ${subcommand}`);
|
|
@@ -80002,20 +80462,20 @@ init_manifest_path_resolver();
|
|
|
80002
80462
|
init_logger();
|
|
80003
80463
|
init_takumi_constants();
|
|
80004
80464
|
var import_fs_extra34 = __toESM(require_lib(), 1);
|
|
80005
|
-
var
|
|
80006
|
-
import { join as
|
|
80465
|
+
var import_semver4 = __toESM(require_semver2(), 1);
|
|
80466
|
+
import { join as join122 } from "node:path";
|
|
80007
80467
|
function evaluateCliVersionGate(input) {
|
|
80008
80468
|
const min = typeof input.minCliVersion === "string" ? input.minCliVersion.trim() : undefined;
|
|
80009
80469
|
if (!min)
|
|
80010
80470
|
return { allowed: true };
|
|
80011
|
-
const coercedMin =
|
|
80471
|
+
const coercedMin = import_semver4.default.coerce(min);
|
|
80012
80472
|
if (!coercedMin)
|
|
80013
80473
|
return { allowed: true };
|
|
80014
80474
|
const rawCli = (input.cliVersion ?? getCliVersion()).trim();
|
|
80015
|
-
const coercedCli =
|
|
80475
|
+
const coercedCli = import_semver4.default.coerce(rawCli);
|
|
80016
80476
|
if (!coercedCli)
|
|
80017
80477
|
return { allowed: true };
|
|
80018
|
-
if (
|
|
80478
|
+
if (import_semver4.default.gte(coercedCli, coercedMin))
|
|
80019
80479
|
return { allowed: true };
|
|
80020
80480
|
const reason = `This kit requires takumi CLI >= ${coercedMin.version}, but the installed CLI is ${rawCli}. Upgrade with \`${TAKUMI_CLI_GLOBAL_INSTALL_COMMAND}\`, or re-run with --force to install anyway.`;
|
|
80021
80481
|
if (input.force)
|
|
@@ -80024,7 +80484,7 @@ function evaluateCliVersionGate(input) {
|
|
|
80024
80484
|
}
|
|
80025
80485
|
async function readKitMinCliVersion(extractDir) {
|
|
80026
80486
|
try {
|
|
80027
|
-
const resolved = await findManifestPath(
|
|
80487
|
+
const resolved = await findManifestPath(join122(extractDir, ".claude"));
|
|
80028
80488
|
if (!resolved)
|
|
80029
80489
|
return;
|
|
80030
80490
|
const raw = await import_fs_extra34.readFile(resolved.path, "utf-8");
|
|
@@ -80039,6 +80499,7 @@ async function readKitMinCliVersion(extractDir) {
|
|
|
80039
80499
|
// src/commands/init/init-command.ts
|
|
80040
80500
|
init_manifest();
|
|
80041
80501
|
init_environment();
|
|
80502
|
+
init_kit_layout();
|
|
80042
80503
|
init_logger();
|
|
80043
80504
|
init_process_lock();
|
|
80044
80505
|
init_types2();
|
|
@@ -80220,8 +80681,8 @@ init_environment();
|
|
|
80220
80681
|
init_logger();
|
|
80221
80682
|
init_safe_spinner();
|
|
80222
80683
|
import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
|
|
80223
|
-
import { tmpdir as
|
|
80224
|
-
import { join as
|
|
80684
|
+
import { tmpdir as tmpdir6 } from "node:os";
|
|
80685
|
+
import { join as join128 } from "node:path";
|
|
80225
80686
|
|
|
80226
80687
|
// src/shared/temp-cleanup.ts
|
|
80227
80688
|
init_logger();
|
|
@@ -80238,9 +80699,9 @@ var import_ignore6 = __toESM(require_ignore(), 1);
|
|
|
80238
80699
|
// src/domains/installation/download/file-downloader.ts
|
|
80239
80700
|
init_logger();
|
|
80240
80701
|
init_output_manager();
|
|
80241
|
-
import { createWriteStream as createWriteStream2, rmSync as
|
|
80702
|
+
import { createWriteStream as createWriteStream2, rmSync as rmSync10 } from "node:fs";
|
|
80242
80703
|
import { mkdir as mkdir21 } from "node:fs/promises";
|
|
80243
|
-
import { join as
|
|
80704
|
+
import { join as join123 } from "node:path";
|
|
80244
80705
|
|
|
80245
80706
|
// src/shared/progress-bar.ts
|
|
80246
80707
|
init_output_manager();
|
|
@@ -80450,7 +80911,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
|
|
|
80450
80911
|
class FileDownloader {
|
|
80451
80912
|
async downloadAsset(asset, destDir) {
|
|
80452
80913
|
try {
|
|
80453
|
-
const destPath =
|
|
80914
|
+
const destPath = join123(destDir, asset.name);
|
|
80454
80915
|
await mkdir21(destDir, { recursive: true });
|
|
80455
80916
|
output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
|
|
80456
80917
|
logger.verbose("Download details", {
|
|
@@ -80508,7 +80969,7 @@ class FileDownloader {
|
|
|
80508
80969
|
fileStream.end();
|
|
80509
80970
|
await new Promise((resolve27) => fileStream.once("close", resolve27));
|
|
80510
80971
|
try {
|
|
80511
|
-
|
|
80972
|
+
rmSync10(destPath, { force: true });
|
|
80512
80973
|
} catch (cleanupError) {
|
|
80513
80974
|
const errorMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
80514
80975
|
logger.debug(`Failed to clean up partial download ${destPath}: ${errorMsg}`);
|
|
@@ -80522,7 +80983,7 @@ class FileDownloader {
|
|
|
80522
80983
|
fileStream.end();
|
|
80523
80984
|
await new Promise((resolve27) => fileStream.once("close", resolve27));
|
|
80524
80985
|
try {
|
|
80525
|
-
|
|
80986
|
+
rmSync10(destPath, { force: true });
|
|
80526
80987
|
} catch (cleanupError) {
|
|
80527
80988
|
const errorMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
80528
80989
|
logger.debug(`Failed to clean up partial download ${destPath}: ${errorMsg}`);
|
|
@@ -80535,7 +80996,7 @@ class FileDownloader {
|
|
|
80535
80996
|
}
|
|
80536
80997
|
async downloadFile(params) {
|
|
80537
80998
|
const { url, name: name2, size, destDir, token } = params;
|
|
80538
|
-
const destPath =
|
|
80999
|
+
const destPath = join123(destDir, name2);
|
|
80539
81000
|
await mkdir21(destDir, { recursive: true });
|
|
80540
81001
|
output.info(`Downloading ${name2}${size ? ` (${formatBytes(size)})` : ""}...`);
|
|
80541
81002
|
const headers = {};
|
|
@@ -80605,7 +81066,7 @@ class FileDownloader {
|
|
|
80605
81066
|
fileStream.end();
|
|
80606
81067
|
await new Promise((resolve27) => fileStream.once("close", resolve27));
|
|
80607
81068
|
try {
|
|
80608
|
-
|
|
81069
|
+
rmSync10(destPath, { force: true });
|
|
80609
81070
|
} catch (cleanupError) {
|
|
80610
81071
|
const errorMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
80611
81072
|
logger.debug(`Failed to clean up partial download ${destPath}: ${errorMsg}`);
|
|
@@ -80623,7 +81084,7 @@ class FileDownloader {
|
|
|
80623
81084
|
fileStream.end();
|
|
80624
81085
|
await new Promise((resolve27) => fileStream.once("close", resolve27));
|
|
80625
81086
|
try {
|
|
80626
|
-
|
|
81087
|
+
rmSync10(destPath, { force: true });
|
|
80627
81088
|
} catch (cleanupError) {
|
|
80628
81089
|
const errorMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
|
|
80629
81090
|
logger.debug(`Failed to clean up partial download ${destPath}: ${errorMsg}`);
|
|
@@ -80638,7 +81099,7 @@ init_logger();
|
|
|
80638
81099
|
init_types2();
|
|
80639
81100
|
import { constants as constants3 } from "node:fs";
|
|
80640
81101
|
import { access as access3, readdir as readdir26 } from "node:fs/promises";
|
|
80641
|
-
import { join as
|
|
81102
|
+
import { join as join124 } from "node:path";
|
|
80642
81103
|
async function validateExtraction(extractDir) {
|
|
80643
81104
|
try {
|
|
80644
81105
|
const entries = await readdir26(extractDir, { encoding: "utf8" });
|
|
@@ -80650,7 +81111,7 @@ async function validateExtraction(extractDir) {
|
|
|
80650
81111
|
const missingPaths = [];
|
|
80651
81112
|
for (const path10 of criticalPaths) {
|
|
80652
81113
|
try {
|
|
80653
|
-
await access3(
|
|
81114
|
+
await access3(join124(extractDir, path10), constants3.F_OK);
|
|
80654
81115
|
logger.debug(`Found: ${path10}`);
|
|
80655
81116
|
} catch {
|
|
80656
81117
|
logger.warning(`Expected path not found: ${path10}`);
|
|
@@ -80672,7 +81133,7 @@ async function validateExtraction(extractDir) {
|
|
|
80672
81133
|
// src/domains/installation/extraction/tar-extractor.ts
|
|
80673
81134
|
init_logger();
|
|
80674
81135
|
import { copyFile as copyFile6, mkdir as mkdir23, readdir as readdir28, rm as rm8, stat as stat8 } from "node:fs/promises";
|
|
80675
|
-
import { join as
|
|
81136
|
+
import { join as join126 } from "node:path";
|
|
80676
81137
|
|
|
80677
81138
|
// node_modules/tar/dist/esm/index.min.js
|
|
80678
81139
|
import Kr from "events";
|
|
@@ -82704,7 +83165,7 @@ var ls = Symbol("readdir");
|
|
|
82704
83165
|
var ai = Symbol("onreaddir");
|
|
82705
83166
|
var li = Symbol("pipe");
|
|
82706
83167
|
var ir = Symbol("entry");
|
|
82707
|
-
var
|
|
83168
|
+
var os8 = Symbol("entryOpt");
|
|
82708
83169
|
var ci = Symbol("writeEntryClass");
|
|
82709
83170
|
var rr = Symbol("write");
|
|
82710
83171
|
var hs = Symbol("ondrain");
|
|
@@ -82767,7 +83228,7 @@ var Et = class extends D {
|
|
|
82767
83228
|
t.resume();
|
|
82768
83229
|
else {
|
|
82769
83230
|
let i = new di(t.path, e2);
|
|
82770
|
-
i.entry = new ri(t, this[
|
|
83231
|
+
i.entry = new ri(t, this[os8](i)), i.entry.on("end", () => this[ns](i)), this[G2] += 1, this[W2].push(i);
|
|
82771
83232
|
}
|
|
82772
83233
|
this[Ft]();
|
|
82773
83234
|
}
|
|
@@ -82836,13 +83297,13 @@ var Et = class extends D {
|
|
|
82836
83297
|
}
|
|
82837
83298
|
}
|
|
82838
83299
|
}
|
|
82839
|
-
[
|
|
83300
|
+
[os8](t) {
|
|
82840
83301
|
return { onwarn: (e2, i, r2) => this.warn(e2, i, r2), noPax: this.noPax, cwd: this.cwd, absolute: t.absolute, preservePaths: this.preservePaths, maxReadSize: this.maxReadSize, strict: this.strict, portable: this.portable, linkCache: this.linkCache, statCache: this.statCache, noMtime: this.noMtime, mtime: this.mtime, prefix: this.prefix, onWriteEntry: this.onWriteEntry };
|
|
82841
83302
|
}
|
|
82842
83303
|
[ir](t) {
|
|
82843
83304
|
this[G2] += 1;
|
|
82844
83305
|
try {
|
|
82845
|
-
return new this[ci](t.path, this[
|
|
83306
|
+
return new this[ci](t.path, this[os8](t)).on("end", () => this[ns](t)).on("error", (i) => this.emit("error", i));
|
|
82846
83307
|
} catch (e2) {
|
|
82847
83308
|
this.emit("error", e2);
|
|
82848
83309
|
}
|
|
@@ -83885,7 +84346,7 @@ function decodeFilePath(path10) {
|
|
|
83885
84346
|
init_logger();
|
|
83886
84347
|
init_types2();
|
|
83887
84348
|
import { copyFile as copyFile5, lstat as lstat8, mkdir as mkdir22, readdir as readdir27 } from "node:fs/promises";
|
|
83888
|
-
import { join as
|
|
84349
|
+
import { join as join125, relative as relative17 } from "node:path";
|
|
83889
84350
|
async function withRetry2(fn2, retries = 3) {
|
|
83890
84351
|
for (let i = 0;i < retries; i++) {
|
|
83891
84352
|
try {
|
|
@@ -83907,8 +84368,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
|
|
|
83907
84368
|
await mkdir22(destDir, { recursive: true });
|
|
83908
84369
|
const entries = await readdir27(sourceDir, { encoding: "utf8" });
|
|
83909
84370
|
for (const entry of entries) {
|
|
83910
|
-
const sourcePath =
|
|
83911
|
-
const destPath =
|
|
84371
|
+
const sourcePath = join125(sourceDir, entry);
|
|
84372
|
+
const destPath = join125(destDir, entry);
|
|
83912
84373
|
const relativePath = relative17(sourceDir, sourcePath);
|
|
83913
84374
|
if (!isPathSafe(destDir, destPath)) {
|
|
83914
84375
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -83935,8 +84396,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
|
|
|
83935
84396
|
await mkdir22(destDir, { recursive: true });
|
|
83936
84397
|
const entries = await readdir27(sourceDir, { encoding: "utf8" });
|
|
83937
84398
|
for (const entry of entries) {
|
|
83938
|
-
const sourcePath =
|
|
83939
|
-
const destPath =
|
|
84399
|
+
const sourcePath = join125(sourceDir, entry);
|
|
84400
|
+
const destPath = join125(destDir, entry);
|
|
83940
84401
|
const relativePath = relative17(sourceDir, sourcePath);
|
|
83941
84402
|
if (!isPathSafe(destDir, destPath)) {
|
|
83942
84403
|
logger.warning(`Skipping unsafe path: ${relativePath}`);
|
|
@@ -83991,7 +84452,7 @@ class TarExtractor {
|
|
|
83991
84452
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
83992
84453
|
if (entries.length === 1) {
|
|
83993
84454
|
const rootEntry = entries[0];
|
|
83994
|
-
const rootPath =
|
|
84455
|
+
const rootPath = join126(tempExtractDir, rootEntry);
|
|
83995
84456
|
const rootStat = await stat8(rootPath);
|
|
83996
84457
|
if (rootStat.isDirectory()) {
|
|
83997
84458
|
const rootContents = await readdir28(rootPath, { encoding: "utf8" });
|
|
@@ -84007,7 +84468,7 @@ class TarExtractor {
|
|
|
84007
84468
|
}
|
|
84008
84469
|
} else {
|
|
84009
84470
|
await mkdir23(destDir, { recursive: true });
|
|
84010
|
-
await copyFile6(rootPath,
|
|
84471
|
+
await copyFile6(rootPath, join126(destDir, rootEntry));
|
|
84011
84472
|
}
|
|
84012
84473
|
} else {
|
|
84013
84474
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -84028,7 +84489,7 @@ class TarExtractor {
|
|
|
84028
84489
|
init_logger();
|
|
84029
84490
|
import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
84030
84491
|
import { chmod as chmod4, copyFile as copyFile7, mkdir as mkdir24, readdir as readdir29, rm as rm9, stat as stat9 } from "node:fs/promises";
|
|
84031
|
-
import { dirname as dirname32, join as
|
|
84492
|
+
import { dirname as dirname32, join as join127, resolve as resolve27 } from "node:path";
|
|
84032
84493
|
import { pipeline } from "node:stream/promises";
|
|
84033
84494
|
import yauzl from "yauzl-promise";
|
|
84034
84495
|
class ZipExtractor {
|
|
@@ -84042,7 +84503,7 @@ class ZipExtractor {
|
|
|
84042
84503
|
logger.debug(`Root entries: ${entries.join(", ")}`);
|
|
84043
84504
|
if (entries.length === 1) {
|
|
84044
84505
|
const rootEntry = entries[0];
|
|
84045
|
-
const rootPath =
|
|
84506
|
+
const rootPath = join127(tempExtractDir, rootEntry);
|
|
84046
84507
|
const rootStat = await stat9(rootPath);
|
|
84047
84508
|
if (rootStat.isDirectory()) {
|
|
84048
84509
|
const rootContents = await readdir29(rootPath, { encoding: "utf8" });
|
|
@@ -84058,7 +84519,7 @@ class ZipExtractor {
|
|
|
84058
84519
|
}
|
|
84059
84520
|
} else {
|
|
84060
84521
|
await mkdir24(destDir, { recursive: true });
|
|
84061
|
-
await copyFile7(rootPath,
|
|
84522
|
+
await copyFile7(rootPath, join127(destDir, rootEntry));
|
|
84062
84523
|
}
|
|
84063
84524
|
} else {
|
|
84064
84525
|
logger.debug("Multiple root entries - moving all");
|
|
@@ -84187,7 +84648,7 @@ class DownloadManager {
|
|
|
84187
84648
|
async createTempDir() {
|
|
84188
84649
|
const timestamp = Date.now();
|
|
84189
84650
|
const counter = DownloadManager.tempDirCounter++;
|
|
84190
|
-
const primaryTempDir =
|
|
84651
|
+
const primaryTempDir = join128(tmpdir6(), `takumi-${timestamp}-${counter}`);
|
|
84191
84652
|
try {
|
|
84192
84653
|
await mkdir25(primaryTempDir, { recursive: true });
|
|
84193
84654
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
@@ -84204,7 +84665,7 @@ Solutions:
|
|
|
84204
84665
|
2. Set HOME environment variable
|
|
84205
84666
|
3. Try running from a different directory`);
|
|
84206
84667
|
}
|
|
84207
|
-
const fallbackTempDir =
|
|
84668
|
+
const fallbackTempDir = join128(homeDir, STATE_DIRNAME, "tmp", `takumi-${timestamp}-${counter}`);
|
|
84208
84669
|
try {
|
|
84209
84670
|
await mkdir25(fallbackTempDir, { recursive: true });
|
|
84210
84671
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
@@ -84932,7 +85393,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
|
|
|
84932
85393
|
}
|
|
84933
85394
|
// src/commands/init/phases/selection-handler.ts
|
|
84934
85395
|
import { mkdir as mkdir26 } from "node:fs/promises";
|
|
84935
|
-
import { join as
|
|
85396
|
+
import { join as join131, resolve as resolve30 } from "node:path";
|
|
84936
85397
|
|
|
84937
85398
|
// src/commands/shared/agent-selector.ts
|
|
84938
85399
|
init_registry();
|
|
@@ -85246,7 +85707,7 @@ async function handleSelection(ctx) {
|
|
|
85246
85707
|
}
|
|
85247
85708
|
if (!ctx.options.fresh) {
|
|
85248
85709
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
85249
|
-
const claudeDir = prefix ?
|
|
85710
|
+
const claudeDir = prefix ? join131(resolvedDir, prefix) : resolvedDir;
|
|
85250
85711
|
try {
|
|
85251
85712
|
const existingMetadata = await readManifest(claudeDir);
|
|
85252
85713
|
if (existingMetadata?.kits) {
|
|
@@ -85279,7 +85740,7 @@ async function handleSelection(ctx) {
|
|
|
85279
85740
|
}
|
|
85280
85741
|
if (ctx.options.fresh) {
|
|
85281
85742
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
85282
|
-
const claudeDir = prefix ?
|
|
85743
|
+
const claudeDir = prefix ? join131(resolvedDir, prefix) : resolvedDir;
|
|
85283
85744
|
const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
|
|
85284
85745
|
if (!canProceed) {
|
|
85285
85746
|
return { ...ctx, cancelled: true };
|
|
@@ -85299,7 +85760,7 @@ async function handleSelection(ctx) {
|
|
|
85299
85760
|
let currentVersion = null;
|
|
85300
85761
|
try {
|
|
85301
85762
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
85302
|
-
const claudeDir = prefix ?
|
|
85763
|
+
const claudeDir = prefix ? join131(resolvedDir, prefix) : resolvedDir;
|
|
85303
85764
|
const existingMetadata = await readManifest(claudeDir);
|
|
85304
85765
|
currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
|
|
85305
85766
|
if (currentVersion) {
|
|
@@ -85387,7 +85848,7 @@ async function handleSelection(ctx) {
|
|
|
85387
85848
|
if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
|
|
85388
85849
|
try {
|
|
85389
85850
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
85390
|
-
const claudeDir = prefix ?
|
|
85851
|
+
const claudeDir = prefix ? join131(resolvedDir, prefix) : resolvedDir;
|
|
85391
85852
|
const existingMetadata = await readManifest(claudeDir);
|
|
85392
85853
|
const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
|
|
85393
85854
|
if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
|
|
@@ -85410,7 +85871,7 @@ async function handleSelection(ctx) {
|
|
|
85410
85871
|
let currentSecondaryVersion = null;
|
|
85411
85872
|
try {
|
|
85412
85873
|
const prefix = PathResolver.getPathPrefix(ctx.options.global);
|
|
85413
|
-
const claudeDir = prefix ?
|
|
85874
|
+
const claudeDir = prefix ? join131(resolvedDir, prefix) : resolvedDir;
|
|
85414
85875
|
const existingMetadata = await readManifest(claudeDir);
|
|
85415
85876
|
currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
|
|
85416
85877
|
} catch {}
|
|
@@ -85494,12 +85955,12 @@ function resolveGlobalTargetDir(targetAgents2) {
|
|
|
85494
85955
|
// src/commands/init/phases/sync-handler.ts
|
|
85495
85956
|
init_paths();
|
|
85496
85957
|
import { copyFile as copyFile8, mkdir as mkdir28, open as open3, readFile as readFile45, rename as rename8, stat as stat12, unlink as unlink12, writeFile as writeFile29 } from "node:fs/promises";
|
|
85497
|
-
import { dirname as dirname35, join as
|
|
85958
|
+
import { dirname as dirname35, join as join134, resolve as resolve31 } from "node:path";
|
|
85498
85959
|
|
|
85499
85960
|
// src/domains/sync/config-version-checker.ts
|
|
85500
85961
|
init_auth_client();
|
|
85501
85962
|
import { mkdir as mkdir27, readFile as readFile43, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
|
|
85502
|
-
import { join as
|
|
85963
|
+
import { join as join132 } from "node:path";
|
|
85503
85964
|
init_version_utils();
|
|
85504
85965
|
init_logger();
|
|
85505
85966
|
init_path_resolver();
|
|
@@ -85535,7 +85996,7 @@ var CACHE_FILENAME = "config-update-cache.json";
|
|
|
85535
85996
|
class ConfigVersionChecker {
|
|
85536
85997
|
static getCacheFilePath(kitType, global3) {
|
|
85537
85998
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
85538
|
-
return
|
|
85999
|
+
return join132(cacheDir, `${kitType}-${CACHE_FILENAME}`);
|
|
85539
86000
|
}
|
|
85540
86001
|
static async loadCache(kitType, global3) {
|
|
85541
86002
|
try {
|
|
@@ -85655,7 +86116,7 @@ class ConfigVersionChecker {
|
|
|
85655
86116
|
init_ownership_checker();
|
|
85656
86117
|
init_logger();
|
|
85657
86118
|
import { lstat as lstat9, readFile as readFile44, readlink, realpath as realpath3, stat as stat11 } from "node:fs/promises";
|
|
85658
|
-
import { isAbsolute as
|
|
86119
|
+
import { isAbsolute as isAbsolute7, join as join133, normalize as normalize10, relative as relative18 } from "node:path";
|
|
85659
86120
|
var MAX_SYNC_FILE_SIZE = 10 * 1024 * 1024;
|
|
85660
86121
|
var MAX_SYMLINK_DEPTH = 20;
|
|
85661
86122
|
async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
|
|
@@ -85667,10 +86128,10 @@ async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEP
|
|
|
85667
86128
|
if (!stats.isSymbolicLink())
|
|
85668
86129
|
break;
|
|
85669
86130
|
const target = await readlink(current);
|
|
85670
|
-
const resolvedTarget =
|
|
85671
|
-
const normalizedTarget =
|
|
86131
|
+
const resolvedTarget = isAbsolute7(target) ? target : join133(current, "..", target);
|
|
86132
|
+
const normalizedTarget = normalize10(resolvedTarget);
|
|
85672
86133
|
const rel = relative18(basePath, normalizedTarget);
|
|
85673
|
-
if (rel.startsWith("..") ||
|
|
86134
|
+
if (rel.startsWith("..") || isAbsolute7(rel)) {
|
|
85674
86135
|
throw new Error(`Symlink chain escapes base directory at depth ${depth}: ${path11}`);
|
|
85675
86136
|
}
|
|
85676
86137
|
current = normalizedTarget;
|
|
@@ -85696,16 +86157,16 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
85696
86157
|
if (filePath.length > 1024) {
|
|
85697
86158
|
throw new Error(`Path too long: ${filePath.slice(0, 50)}...`);
|
|
85698
86159
|
}
|
|
85699
|
-
const normalized =
|
|
85700
|
-
if (
|
|
86160
|
+
const normalized = normalize10(filePath);
|
|
86161
|
+
if (isAbsolute7(normalized)) {
|
|
85701
86162
|
throw new Error(`Absolute paths not allowed: ${filePath}`);
|
|
85702
86163
|
}
|
|
85703
86164
|
if (normalized.startsWith("..") || normalized.includes("/../")) {
|
|
85704
86165
|
throw new Error(`Path traversal not allowed: ${filePath}`);
|
|
85705
86166
|
}
|
|
85706
|
-
const fullPath =
|
|
86167
|
+
const fullPath = join133(basePath, normalized);
|
|
85707
86168
|
const rel = relative18(basePath, fullPath);
|
|
85708
|
-
if (rel.startsWith("..") ||
|
|
86169
|
+
if (rel.startsWith("..") || isAbsolute7(rel)) {
|
|
85709
86170
|
throw new Error(`Path escapes base directory: ${filePath}`);
|
|
85710
86171
|
}
|
|
85711
86172
|
await validateSymlinkChain(fullPath, basePath);
|
|
@@ -85713,17 +86174,17 @@ async function validateSyncPath(basePath, filePath) {
|
|
|
85713
86174
|
const resolvedBase = await realpath3(basePath);
|
|
85714
86175
|
const resolvedFull = await realpath3(fullPath);
|
|
85715
86176
|
const resolvedRel = relative18(resolvedBase, resolvedFull);
|
|
85716
|
-
if (resolvedRel.startsWith("..") ||
|
|
86177
|
+
if (resolvedRel.startsWith("..") || isAbsolute7(resolvedRel)) {
|
|
85717
86178
|
throw new Error(`Symlink escapes base directory: ${filePath}`);
|
|
85718
86179
|
}
|
|
85719
86180
|
} catch (error) {
|
|
85720
86181
|
if (error.code === "ENOENT") {
|
|
85721
|
-
const parentPath =
|
|
86182
|
+
const parentPath = join133(fullPath, "..");
|
|
85722
86183
|
try {
|
|
85723
86184
|
const resolvedBase = await realpath3(basePath);
|
|
85724
86185
|
const resolvedParent = await realpath3(parentPath);
|
|
85725
86186
|
const resolvedRel = relative18(resolvedBase, resolvedParent);
|
|
85726
|
-
if (resolvedRel.startsWith("..") ||
|
|
86187
|
+
if (resolvedRel.startsWith("..") || isAbsolute7(resolvedRel)) {
|
|
85727
86188
|
throw new Error(`Parent symlink escapes base directory: ${filePath}`);
|
|
85728
86189
|
}
|
|
85729
86190
|
} catch (parentError) {
|
|
@@ -86209,7 +86670,7 @@ function getLockTimeout() {
|
|
|
86209
86670
|
var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
|
|
86210
86671
|
async function acquireSyncLock(global3) {
|
|
86211
86672
|
const cacheDir = PathResolver.getCacheDir(global3);
|
|
86212
|
-
const lockPath2 =
|
|
86673
|
+
const lockPath2 = join134(cacheDir, ".sync-lock");
|
|
86213
86674
|
const startTime = Date.now();
|
|
86214
86675
|
const lockTimeout = getLockTimeout();
|
|
86215
86676
|
await mkdir28(dirname35(lockPath2), { recursive: true });
|
|
@@ -86290,7 +86751,7 @@ async function executeSyncMerge(ctx) {
|
|
|
86290
86751
|
try {
|
|
86291
86752
|
const sourcePath = await validateSyncPath(upstreamDir, file.path);
|
|
86292
86753
|
const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
|
|
86293
|
-
const targetDir =
|
|
86754
|
+
const targetDir = join134(targetPath, "..");
|
|
86294
86755
|
try {
|
|
86295
86756
|
await mkdir28(targetDir, { recursive: true });
|
|
86296
86757
|
} catch (mkdirError) {
|
|
@@ -86461,7 +86922,7 @@ async function createBackup(claudeDir, files, backupDir) {
|
|
|
86461
86922
|
const sourcePath = await validateSyncPath(claudeDir, file.path);
|
|
86462
86923
|
if (await import_fs_extra36.pathExists(sourcePath)) {
|
|
86463
86924
|
const targetPath = await validateSyncPath(backupDir, file.path);
|
|
86464
|
-
const targetDir =
|
|
86925
|
+
const targetDir = join134(targetPath, "..");
|
|
86465
86926
|
await mkdir28(targetDir, { recursive: true });
|
|
86466
86927
|
await copyFile8(sourcePath, targetPath);
|
|
86467
86928
|
}
|
|
@@ -86487,38 +86948,38 @@ init_logger();
|
|
|
86487
86948
|
init_types2();
|
|
86488
86949
|
var import_fs_extra37 = __toESM(require_lib(), 1);
|
|
86489
86950
|
import { rename as rename9, rm as rm10 } from "node:fs/promises";
|
|
86490
|
-
import { join as
|
|
86951
|
+
import { join as join135, relative as relative19 } from "node:path";
|
|
86491
86952
|
async function collectDirsToRename(extractDir, folders) {
|
|
86492
86953
|
const dirsToRename = [];
|
|
86493
86954
|
if (folders.docs !== DEFAULT_FOLDERS.docs) {
|
|
86494
|
-
const docsPath =
|
|
86955
|
+
const docsPath = join135(extractDir, DEFAULT_FOLDERS.docs);
|
|
86495
86956
|
if (await import_fs_extra37.pathExists(docsPath)) {
|
|
86496
86957
|
dirsToRename.push({
|
|
86497
86958
|
from: docsPath,
|
|
86498
|
-
to:
|
|
86959
|
+
to: join135(extractDir, folders.docs)
|
|
86499
86960
|
});
|
|
86500
86961
|
}
|
|
86501
|
-
const claudeDocsPath =
|
|
86962
|
+
const claudeDocsPath = join135(extractDir, ".claude", DEFAULT_FOLDERS.docs);
|
|
86502
86963
|
if (await import_fs_extra37.pathExists(claudeDocsPath)) {
|
|
86503
86964
|
dirsToRename.push({
|
|
86504
86965
|
from: claudeDocsPath,
|
|
86505
|
-
to:
|
|
86966
|
+
to: join135(extractDir, ".claude", folders.docs)
|
|
86506
86967
|
});
|
|
86507
86968
|
}
|
|
86508
86969
|
}
|
|
86509
86970
|
if (folders.plans !== DEFAULT_FOLDERS.plans) {
|
|
86510
|
-
const plansPath =
|
|
86971
|
+
const plansPath = join135(extractDir, DEFAULT_FOLDERS.plans);
|
|
86511
86972
|
if (await import_fs_extra37.pathExists(plansPath)) {
|
|
86512
86973
|
dirsToRename.push({
|
|
86513
86974
|
from: plansPath,
|
|
86514
|
-
to:
|
|
86975
|
+
to: join135(extractDir, folders.plans)
|
|
86515
86976
|
});
|
|
86516
86977
|
}
|
|
86517
|
-
const claudePlansPath =
|
|
86978
|
+
const claudePlansPath = join135(extractDir, ".claude", DEFAULT_FOLDERS.plans);
|
|
86518
86979
|
if (await import_fs_extra37.pathExists(claudePlansPath)) {
|
|
86519
86980
|
dirsToRename.push({
|
|
86520
86981
|
from: claudePlansPath,
|
|
86521
|
-
to:
|
|
86982
|
+
to: join135(extractDir, ".claude", folders.plans)
|
|
86522
86983
|
});
|
|
86523
86984
|
}
|
|
86524
86985
|
}
|
|
@@ -86559,7 +87020,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
|
|
|
86559
87020
|
init_logger();
|
|
86560
87021
|
init_types2();
|
|
86561
87022
|
import { readFile as readFile46, readdir as readdir30, writeFile as writeFile30 } from "node:fs/promises";
|
|
86562
|
-
import { join as
|
|
87023
|
+
import { join as join136, relative as relative20 } from "node:path";
|
|
86563
87024
|
var TRANSFORMABLE_FILE_PATTERNS = [
|
|
86564
87025
|
".md",
|
|
86565
87026
|
".txt",
|
|
@@ -86612,7 +87073,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
|
|
|
86612
87073
|
let replacementsCount = 0;
|
|
86613
87074
|
const entries = await readdir30(dir, { withFileTypes: true });
|
|
86614
87075
|
for (const entry of entries) {
|
|
86615
|
-
const fullPath =
|
|
87076
|
+
const fullPath = join136(dir, entry.name);
|
|
86616
87077
|
if (entry.isDirectory()) {
|
|
86617
87078
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
86618
87079
|
continue;
|
|
@@ -86749,7 +87210,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
|
|
|
86749
87210
|
init_logger();
|
|
86750
87211
|
import { readFile as readFile47, readdir as readdir31, writeFile as writeFile31 } from "node:fs/promises";
|
|
86751
87212
|
import { platform as platform12 } from "node:os";
|
|
86752
|
-
import { extname as extname8, join as
|
|
87213
|
+
import { extname as extname8, join as join137 } from "node:path";
|
|
86753
87214
|
var IS_WINDOWS3 = platform12() === "win32";
|
|
86754
87215
|
var HOME_PREFIX = "$HOME";
|
|
86755
87216
|
function getHomeDirPrefix() {
|
|
@@ -86838,8 +87299,8 @@ function transformContent(content) {
|
|
|
86838
87299
|
}
|
|
86839
87300
|
function shouldTransformFile3(filename) {
|
|
86840
87301
|
const ext = extname8(filename).toLowerCase();
|
|
86841
|
-
const
|
|
86842
|
-
return TRANSFORMABLE_EXTENSIONS3.has(ext) || ALWAYS_TRANSFORM_FILES.has(
|
|
87302
|
+
const basename20 = filename.split("/").pop() || filename;
|
|
87303
|
+
return TRANSFORMABLE_EXTENSIONS3.has(ext) || ALWAYS_TRANSFORM_FILES.has(basename20);
|
|
86843
87304
|
}
|
|
86844
87305
|
async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
86845
87306
|
let filesTransformed = 0;
|
|
@@ -86849,7 +87310,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
|
|
|
86849
87310
|
async function processDirectory2(dir) {
|
|
86850
87311
|
const entries = await readdir31(dir, { withFileTypes: true });
|
|
86851
87312
|
for (const entry of entries) {
|
|
86852
|
-
const fullPath =
|
|
87313
|
+
const fullPath = join137(dir, entry.name);
|
|
86853
87314
|
if (entry.isDirectory()) {
|
|
86854
87315
|
if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
|
|
86855
87316
|
continue;
|
|
@@ -86940,8 +87401,16 @@ function mapAgentToHookAgent(agent) {
|
|
|
86940
87401
|
return "codex";
|
|
86941
87402
|
return null;
|
|
86942
87403
|
}
|
|
86943
|
-
|
|
86944
|
-
const
|
|
87404
|
+
function collectKitEvalHooks(extractDir, into) {
|
|
87405
|
+
const sourceHooksDir = findExistingProjectLayoutPath(extractDir, "hooks");
|
|
87406
|
+
if (!sourceHooksDir)
|
|
87407
|
+
return;
|
|
87408
|
+
for (const entry of scanKitHookMetas(sourceHooksDir)) {
|
|
87409
|
+
into.set(entry.file, kitHookToInstallMeta(entry));
|
|
87410
|
+
}
|
|
87411
|
+
}
|
|
87412
|
+
async function installTkmHooksForAgents(targetAgents2, options2, evalHooks) {
|
|
87413
|
+
const categories = undefined;
|
|
86945
87414
|
for (const agent of targetAgents2) {
|
|
86946
87415
|
const hookAgent = mapAgentToHookAgent(agent);
|
|
86947
87416
|
if (!hookAgent)
|
|
@@ -86952,11 +87421,12 @@ async function installTkmHooksForAgents(targetAgents2, options2) {
|
|
|
86952
87421
|
global: options2.global,
|
|
86953
87422
|
dryRun: options2.dryRun,
|
|
86954
87423
|
categories,
|
|
87424
|
+
evalHooks,
|
|
86955
87425
|
yes: true
|
|
86956
87426
|
});
|
|
86957
87427
|
} catch (err) {
|
|
86958
87428
|
const message = err instanceof Error ? err.message : String(err);
|
|
86959
|
-
logger.
|
|
87429
|
+
logger.error(`[init] tkm hooks install for ${agent} FAILED — guards/session hooks may be inactive; re-run \`tkm hooks install -a ${hookAgent}\`: ${message}`);
|
|
86960
87430
|
}
|
|
86961
87431
|
}
|
|
86962
87432
|
}
|
|
@@ -87091,6 +87561,7 @@ async function executeInit(options2, prompts, deps) {
|
|
|
87091
87561
|
return;
|
|
87092
87562
|
}
|
|
87093
87563
|
const aggregatedResults = [];
|
|
87564
|
+
const discoveredEvalHooks = new Map;
|
|
87094
87565
|
let lastCtx = ctx;
|
|
87095
87566
|
for (let i = 0;i < selectedKits.length; i++) {
|
|
87096
87567
|
const currentKit = selectedKits[i];
|
|
@@ -87183,17 +87654,18 @@ async function executeInit(options2, prompts, deps) {
|
|
|
87183
87654
|
aggregatedResults.push(...kitResults);
|
|
87184
87655
|
if (kitResults.some((r2) => r2.cancelled))
|
|
87185
87656
|
return;
|
|
87657
|
+
if (lastCtx.extractDir) {
|
|
87658
|
+
collectKitEvalHooks(lastCtx.extractDir, discoveredEvalHooks);
|
|
87659
|
+
}
|
|
87186
87660
|
}
|
|
87187
87661
|
ctx = lastCtx;
|
|
87188
87662
|
const results = aggregatedResults;
|
|
87189
87663
|
ctx.installerResults = results;
|
|
87190
|
-
|
|
87191
|
-
|
|
87192
|
-
|
|
87193
|
-
|
|
87194
|
-
|
|
87195
|
-
});
|
|
87196
|
-
}
|
|
87664
|
+
await installTkmHooksForAgents(targetAgents2, {
|
|
87665
|
+
global: Boolean(ctx.options.global),
|
|
87666
|
+
dryRun: Boolean(ctx.options.dryRun),
|
|
87667
|
+
installHooks: Boolean(ctx.options.installHooks)
|
|
87668
|
+
}, [...discoveredEvalHooks.values()]);
|
|
87197
87669
|
if (targetAgents2.length > 1) {
|
|
87198
87670
|
displayMultiInstallerSummary(results);
|
|
87199
87671
|
}
|
|
@@ -87268,10 +87740,10 @@ init_dist2();
|
|
|
87268
87740
|
// src/domains/mcp/agent-detector.ts
|
|
87269
87741
|
init_environment();
|
|
87270
87742
|
import { existsSync as existsSync61 } from "node:fs";
|
|
87271
|
-
import { join as
|
|
87743
|
+
import { join as join138 } from "node:path";
|
|
87272
87744
|
|
|
87273
87745
|
// src/domains/mcp/shell-out.ts
|
|
87274
|
-
import { spawnSync as
|
|
87746
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
87275
87747
|
var DEFAULT_TIMEOUT_MS7 = 60000;
|
|
87276
87748
|
var PROBE_TIMEOUT_MS = 5000;
|
|
87277
87749
|
var SERVICE_NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
@@ -87279,7 +87751,7 @@ function isValidServiceName(name2) {
|
|
|
87279
87751
|
return SERVICE_NAME_PATTERN.test(name2);
|
|
87280
87752
|
}
|
|
87281
87753
|
function runAgentCli(bin, args, timeoutMs = DEFAULT_TIMEOUT_MS7) {
|
|
87282
|
-
const result =
|
|
87754
|
+
const result = spawnSync6(bin, args, {
|
|
87283
87755
|
timeout: timeoutMs,
|
|
87284
87756
|
encoding: "utf-8",
|
|
87285
87757
|
shell: false,
|
|
@@ -87302,7 +87774,7 @@ function runAgentCli(bin, args, timeoutMs = DEFAULT_TIMEOUT_MS7) {
|
|
|
87302
87774
|
}
|
|
87303
87775
|
function isBinaryOnPath(bin) {
|
|
87304
87776
|
const probeCmd = process.platform === "win32" ? "where" : "which";
|
|
87305
|
-
const result =
|
|
87777
|
+
const result = spawnSync6(probeCmd, [bin], {
|
|
87306
87778
|
timeout: PROBE_TIMEOUT_MS,
|
|
87307
87779
|
encoding: "utf-8",
|
|
87308
87780
|
shell: false
|
|
@@ -87358,9 +87830,9 @@ function getAgentConfigPath(agent) {
|
|
|
87358
87830
|
return null;
|
|
87359
87831
|
switch (agent) {
|
|
87360
87832
|
case "claude-code":
|
|
87361
|
-
return
|
|
87833
|
+
return join138(home6, ".claude.json");
|
|
87362
87834
|
case "codex":
|
|
87363
|
-
return
|
|
87835
|
+
return join138(home6, ".codex", "config.toml");
|
|
87364
87836
|
default: {
|
|
87365
87837
|
const _exhaustive = agent;
|
|
87366
87838
|
return _exhaustive;
|
|
@@ -87386,7 +87858,7 @@ var PROJECT_MARKERS = {
|
|
|
87386
87858
|
codex: [".codex", "AGENTS.md"]
|
|
87387
87859
|
};
|
|
87388
87860
|
function detectProjectAgents(cwd2 = process.cwd(), exists2 = existsSync61) {
|
|
87389
|
-
return ALL_MCP_AGENTS.filter((agent) => PROJECT_MARKERS[agent].some((marker) => exists2(
|
|
87861
|
+
return ALL_MCP_AGENTS.filter((agent) => PROJECT_MARKERS[agent].some((marker) => exists2(join138(cwd2, marker))));
|
|
87390
87862
|
}
|
|
87391
87863
|
|
|
87392
87864
|
// src/domains/mcp/registry-client.ts
|
|
@@ -87398,12 +87870,12 @@ init_auth_client();
|
|
|
87398
87870
|
init_logger();
|
|
87399
87871
|
init_paths2();
|
|
87400
87872
|
import { promises as fs33 } from "node:fs";
|
|
87401
|
-
import { join as
|
|
87873
|
+
import { join as join139 } from "node:path";
|
|
87402
87874
|
function getCacheDir() {
|
|
87403
|
-
return
|
|
87875
|
+
return join139(getConfigDir(), "mcp");
|
|
87404
87876
|
}
|
|
87405
87877
|
function getCachePath2() {
|
|
87406
|
-
return
|
|
87878
|
+
return join139(getCacheDir(), "registry-cache.json");
|
|
87407
87879
|
}
|
|
87408
87880
|
async function readCachedRegistry() {
|
|
87409
87881
|
try {
|
|
@@ -87534,14 +88006,14 @@ function resolveService(registry, name2) {
|
|
|
87534
88006
|
// src/domains/mcp/writers/claude-config-file.ts
|
|
87535
88007
|
import { existsSync as existsSync62 } from "node:fs";
|
|
87536
88008
|
import { mkdir as mkdir29, writeFile as writeFile32 } from "node:fs/promises";
|
|
87537
|
-
import { dirname as dirname36, join as
|
|
88009
|
+
import { dirname as dirname36, join as join140 } from "node:path";
|
|
87538
88010
|
var AGENT = "claude-code";
|
|
87539
88011
|
var LOCAL_SCOPE_FALLBACK_WARNING = "claude CLI not found; local scope isn't representable via direct file write, wrote to user-level ~/.claude.json instead";
|
|
87540
88012
|
function userConfigPath() {
|
|
87541
88013
|
return getAgentConfigPath(AGENT);
|
|
87542
88014
|
}
|
|
87543
88015
|
function projectConfigPath() {
|
|
87544
|
-
return
|
|
88016
|
+
return join140(process.cwd(), ".mcp.json");
|
|
87545
88017
|
}
|
|
87546
88018
|
function configPathFor(scope) {
|
|
87547
88019
|
return scope === "project" ? projectConfigPath() : userConfigPath();
|
|
@@ -88210,18 +88682,18 @@ async function mcpCommand(action, service, options2 = {}) {
|
|
|
88210
88682
|
// src/commands/plan/plan-command.ts
|
|
88211
88683
|
init_output_manager();
|
|
88212
88684
|
import { existsSync as existsSync68, statSync as statSync12 } from "node:fs";
|
|
88213
|
-
import { dirname as dirname42, join as
|
|
88685
|
+
import { dirname as dirname42, join as join144, parse as parse4, resolve as resolve35 } from "node:path";
|
|
88214
88686
|
|
|
88215
88687
|
// src/commands/plan/plan-read-handlers.ts
|
|
88216
88688
|
import { existsSync as existsSync67, statSync as statSync11 } from "node:fs";
|
|
88217
|
-
import { basename as
|
|
88689
|
+
import { basename as basename22, dirname as dirname41, join as join143, relative as relative21, resolve as resolve33 } from "node:path";
|
|
88218
88690
|
|
|
88219
88691
|
// src/domains/plan-parser/index.ts
|
|
88220
88692
|
import { dirname as dirname40 } from "node:path";
|
|
88221
88693
|
|
|
88222
88694
|
// src/domains/plan-parser/plan-table-parser.ts
|
|
88223
88695
|
var import_gray_matter6 = __toESM(require_gray_matter(), 1);
|
|
88224
|
-
import { readFileSync as
|
|
88696
|
+
import { readFileSync as readFileSync27 } from "node:fs";
|
|
88225
88697
|
import { dirname as dirname37, resolve as resolve32 } from "node:path";
|
|
88226
88698
|
function normalizeStatus(raw) {
|
|
88227
88699
|
const s3 = raw.toLowerCase().trim();
|
|
@@ -88587,30 +89059,30 @@ function parsePhasesFromBody(body, dir, options2) {
|
|
|
88587
89059
|
return parseFormat6(normalizedBody, dir, options2);
|
|
88588
89060
|
}
|
|
88589
89061
|
function parsePlanFile(planFilePath, options2) {
|
|
88590
|
-
const content =
|
|
89062
|
+
const content = readFileSync27(planFilePath, "utf8");
|
|
88591
89063
|
const dir = dirname37(planFilePath);
|
|
88592
89064
|
const { data: frontmatter, content: body } = import_gray_matter6.default(content);
|
|
88593
89065
|
const phases = parsePhasesFromBody(body, dir, options2);
|
|
88594
89066
|
return { frontmatter, phases };
|
|
88595
89067
|
}
|
|
88596
89068
|
// src/domains/plan-parser/plan-scanner.ts
|
|
88597
|
-
import { existsSync as existsSync64, readdirSync as
|
|
88598
|
-
import { join as
|
|
89069
|
+
import { existsSync as existsSync64, readdirSync as readdirSync12 } from "node:fs";
|
|
89070
|
+
import { join as join141 } from "node:path";
|
|
88599
89071
|
function scanPlanDir(dir) {
|
|
88600
89072
|
if (!existsSync64(dir))
|
|
88601
89073
|
return [];
|
|
88602
89074
|
try {
|
|
88603
|
-
return
|
|
89075
|
+
return readdirSync12(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join141(dir, entry.name, "plan.md")).filter(existsSync64);
|
|
88604
89076
|
} catch {
|
|
88605
89077
|
return [];
|
|
88606
89078
|
}
|
|
88607
89079
|
}
|
|
88608
89080
|
// src/domains/plan-parser/plan-validator.ts
|
|
88609
89081
|
var import_gray_matter7 = __toESM(require_gray_matter(), 1);
|
|
88610
|
-
import { existsSync as existsSync65, readFileSync as
|
|
88611
|
-
import { basename as
|
|
89082
|
+
import { existsSync as existsSync65, readFileSync as readFileSync28 } from "node:fs";
|
|
89083
|
+
import { basename as basename20, dirname as dirname38 } from "node:path";
|
|
88612
89084
|
function validatePlanFile(filePath, strict = false) {
|
|
88613
|
-
const content =
|
|
89085
|
+
const content = readFileSync28(filePath, "utf8");
|
|
88614
89086
|
const dir = dirname38(filePath);
|
|
88615
89087
|
const issues = [];
|
|
88616
89088
|
const lines = content.split(`
|
|
@@ -88648,13 +89120,13 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
88648
89120
|
}
|
|
88649
89121
|
for (const phase of phases) {
|
|
88650
89122
|
if (phase.file && !existsSync65(phase.file)) {
|
|
88651
|
-
const fileBasename =
|
|
89123
|
+
const fileBasename = basename20(phase.file);
|
|
88652
89124
|
const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
|
|
88653
89125
|
issues.push({
|
|
88654
89126
|
line: refLine >= 0 ? refLine + 1 : 1,
|
|
88655
89127
|
severity: "warning",
|
|
88656
89128
|
code: "missing-phase-file",
|
|
88657
|
-
message: `Phase ${phase.phaseId} references '${
|
|
89129
|
+
message: `Phase ${phase.phaseId} references '${basename20(phase.file)}' which doesn't exist`
|
|
88658
89130
|
});
|
|
88659
89131
|
}
|
|
88660
89132
|
}
|
|
@@ -88667,9 +89139,9 @@ function validatePlanFile(filePath, strict = false) {
|
|
|
88667
89139
|
}
|
|
88668
89140
|
// src/domains/plan-parser/plan-writer.ts
|
|
88669
89141
|
var import_gray_matter8 = __toESM(require_gray_matter(), 1);
|
|
88670
|
-
import { mkdirSync as mkdirSync10, readFileSync as
|
|
89142
|
+
import { mkdirSync as mkdirSync10, readFileSync as readFileSync29, writeFileSync as writeFileSync14 } from "node:fs";
|
|
88671
89143
|
import { existsSync as existsSync66 } from "node:fs";
|
|
88672
|
-
import { basename as
|
|
89144
|
+
import { basename as basename21, dirname as dirname39, join as join142 } from "node:path";
|
|
88673
89145
|
function phaseNameToFilename(id, name2) {
|
|
88674
89146
|
const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
|
|
88675
89147
|
const num4 = numMatch ? numMatch[1] : id;
|
|
@@ -88777,13 +89249,13 @@ function scaffoldPlan(options2) {
|
|
|
88777
89249
|
mkdirSync10(dir, { recursive: true });
|
|
88778
89250
|
const resolvedPhases = resolvePhaseIds(options2.phases);
|
|
88779
89251
|
const optionsWithResolved = { ...options2, phases: resolvedPhases };
|
|
88780
|
-
const planFile =
|
|
88781
|
-
|
|
89252
|
+
const planFile = join142(dir, "plan.md");
|
|
89253
|
+
writeFileSync14(planFile, generatePlanMd(optionsWithResolved), "utf8");
|
|
88782
89254
|
const phaseFiles = [];
|
|
88783
89255
|
for (const phase of resolvedPhases) {
|
|
88784
89256
|
const filename = phaseNameToFilename(phase.id, phase.name);
|
|
88785
|
-
const phaseFile =
|
|
88786
|
-
|
|
89257
|
+
const phaseFile = join142(dir, filename);
|
|
89258
|
+
writeFileSync14(phaseFile, generatePhaseTemplate(phase), "utf8");
|
|
88787
89259
|
phaseFiles.push(phaseFile);
|
|
88788
89260
|
}
|
|
88789
89261
|
return { planFile, phaseFiles };
|
|
@@ -88807,7 +89279,7 @@ function isCanonicalFormat(content) {
|
|
|
88807
89279
|
return /^\|\s*phase\s*\|\s*name\s*\|\s*status\s*\|/im.test(content);
|
|
88808
89280
|
}
|
|
88809
89281
|
function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
88810
|
-
const raw =
|
|
89282
|
+
const raw = readFileSync29(planFile, "utf8").replace(/\r\n/g, `
|
|
88811
89283
|
`);
|
|
88812
89284
|
if (!isCanonicalFormat(raw)) {
|
|
88813
89285
|
console.error("[!] plan.md is not in canonical format — skipping status update");
|
|
@@ -88847,7 +89319,7 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
|
|
|
88847
89319
|
}
|
|
88848
89320
|
const updatedFrontmatter = { ...frontmatter, status: planStatus };
|
|
88849
89321
|
const updatedContent = import_gray_matter8.default.stringify(updatedBody, updatedFrontmatter);
|
|
88850
|
-
|
|
89322
|
+
writeFileSync14(planFile, updatedContent, "utf8");
|
|
88851
89323
|
const planDir = dirname39(planFile);
|
|
88852
89324
|
const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
|
|
88853
89325
|
if (phaseFilename && existsSync66(phaseFilename)) {
|
|
@@ -88862,18 +89334,18 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
|
|
|
88862
89334
|
continue;
|
|
88863
89335
|
const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
|
|
88864
89336
|
if (linkMatch)
|
|
88865
|
-
return
|
|
89337
|
+
return join142(planDir, linkMatch[2]);
|
|
88866
89338
|
}
|
|
88867
89339
|
return null;
|
|
88868
89340
|
}
|
|
88869
89341
|
function updatePhaseFileFrontmatter(phaseFile, newStatus) {
|
|
88870
|
-
const raw =
|
|
89342
|
+
const raw = readFileSync29(phaseFile, "utf8");
|
|
88871
89343
|
const { data: frontmatter, content: body } = import_gray_matter8.default(raw);
|
|
88872
89344
|
const updated = { ...frontmatter, status: newStatus };
|
|
88873
|
-
|
|
89345
|
+
writeFileSync14(phaseFile, import_gray_matter8.default.stringify(body, updated), "utf8");
|
|
88874
89346
|
}
|
|
88875
89347
|
function addPhase(planFile, name2, afterId) {
|
|
88876
|
-
const raw =
|
|
89348
|
+
const raw = readFileSync29(planFile, "utf8").replace(/\r\n/g, `
|
|
88877
89349
|
`);
|
|
88878
89350
|
if (!isCanonicalFormat(raw)) {
|
|
88879
89351
|
console.error("[!] plan.md is not in canonical format — cannot add phase");
|
|
@@ -88909,7 +89381,7 @@ function addPhase(planFile, name2, afterId) {
|
|
|
88909
89381
|
insertIdx = i;
|
|
88910
89382
|
}
|
|
88911
89383
|
if (insertIdx === -1) {
|
|
88912
|
-
throw new Error(`Phase ID "${afterId}" not found in ${
|
|
89384
|
+
throw new Error(`Phase ID "${afterId}" not found in ${basename21(planFile)}`);
|
|
88913
89385
|
}
|
|
88914
89386
|
lines.splice(insertIdx + 1, 0, newRow);
|
|
88915
89387
|
updatedBody = lines.join(`
|
|
@@ -88942,9 +89414,9 @@ function addPhase(planFile, name2, afterId) {
|
|
|
88942
89414
|
updatedBody = lines.join(`
|
|
88943
89415
|
`);
|
|
88944
89416
|
}
|
|
88945
|
-
|
|
88946
|
-
const phaseFilePath =
|
|
88947
|
-
|
|
89417
|
+
writeFileSync14(planFile, import_gray_matter8.default.stringify(updatedBody, frontmatter), "utf8");
|
|
89418
|
+
const phaseFilePath = join142(planDir, filename);
|
|
89419
|
+
writeFileSync14(phaseFilePath, generatePhaseTemplate({ id: phaseId, name: name2 }), "utf8");
|
|
88948
89420
|
return { phaseId, phaseFile: phaseFilePath };
|
|
88949
89421
|
}
|
|
88950
89422
|
|
|
@@ -88992,7 +89464,7 @@ async function handleParse(target, options2) {
|
|
|
88992
89464
|
console.log(JSON.stringify({ file: relative21(process.cwd(), planFile), frontmatter, phases }, null, 2));
|
|
88993
89465
|
return;
|
|
88994
89466
|
}
|
|
88995
|
-
const title = typeof frontmatter.title === "string" ? frontmatter.title :
|
|
89467
|
+
const title = typeof frontmatter.title === "string" ? frontmatter.title : basename22(dirname41(planFile));
|
|
88996
89468
|
console.log();
|
|
88997
89469
|
console.log(import_picocolors28.default.bold(` Plan: ${title}`));
|
|
88998
89470
|
console.log(` File: ${planFile}`);
|
|
@@ -89047,7 +89519,7 @@ async function handleValidate(target, options2) {
|
|
|
89047
89519
|
}
|
|
89048
89520
|
async function handleStatus(target, options2) {
|
|
89049
89521
|
const t = target ? resolve33(target) : null;
|
|
89050
|
-
const plansDir = t && existsSync67(t) && statSync11(t).isDirectory() && !existsSync67(
|
|
89522
|
+
const plansDir = t && existsSync67(t) && statSync11(t).isDirectory() && !existsSync67(join143(t, "plan.md")) ? t : null;
|
|
89051
89523
|
if (plansDir) {
|
|
89052
89524
|
const planFiles = scanPlanDir(plansDir);
|
|
89053
89525
|
if (planFiles.length === 0) {
|
|
@@ -89072,14 +89544,14 @@ async function handleStatus(target, options2) {
|
|
|
89072
89544
|
try {
|
|
89073
89545
|
const s3 = buildPlanSummary(pf);
|
|
89074
89546
|
const bar = progressBar(s3.completed, s3.totalPhases);
|
|
89075
|
-
const title2 = s3.title ??
|
|
89547
|
+
const title2 = s3.title ?? basename22(dirname41(pf));
|
|
89076
89548
|
console.log(` ${import_picocolors28.default.bold(title2)}`);
|
|
89077
89549
|
console.log(` ${bar}`);
|
|
89078
89550
|
if (s3.inProgress > 0)
|
|
89079
89551
|
console.log(` [~] ${s3.inProgress} in progress`);
|
|
89080
89552
|
console.log();
|
|
89081
89553
|
} catch {
|
|
89082
|
-
console.log(` [X] Failed to read: ${
|
|
89554
|
+
console.log(` [X] Failed to read: ${basename22(dirname41(pf))}`);
|
|
89083
89555
|
console.log();
|
|
89084
89556
|
}
|
|
89085
89557
|
}
|
|
@@ -89103,7 +89575,7 @@ async function handleStatus(target, options2) {
|
|
|
89103
89575
|
console.log(JSON.stringify(summary, null, 2));
|
|
89104
89576
|
return;
|
|
89105
89577
|
}
|
|
89106
|
-
const title = summary.title ??
|
|
89578
|
+
const title = summary.title ?? basename22(dirname41(planFile));
|
|
89107
89579
|
console.log();
|
|
89108
89580
|
console.log(import_picocolors28.default.bold(` ${title}`));
|
|
89109
89581
|
if (summary.status)
|
|
@@ -89129,7 +89601,7 @@ async function handleKanban(target, _options) {
|
|
|
89129
89601
|
}
|
|
89130
89602
|
|
|
89131
89603
|
// src/commands/plan/plan-write-handlers.ts
|
|
89132
|
-
import { basename as
|
|
89604
|
+
import { basename as basename23, relative as relative22, resolve as resolve34 } from "node:path";
|
|
89133
89605
|
init_output_manager();
|
|
89134
89606
|
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
89135
89607
|
async function handleCreate(target, options2) {
|
|
@@ -89182,7 +89654,7 @@ async function handleCreate(target, options2) {
|
|
|
89182
89654
|
console.log(` Directory: ${resolve34(dir)}`);
|
|
89183
89655
|
console.log(` Phases: ${result.phaseFiles.length}`);
|
|
89184
89656
|
for (const f4 of result.phaseFiles) {
|
|
89185
|
-
console.log(` [ ] ${
|
|
89657
|
+
console.log(` [ ] ${basename23(f4)}`);
|
|
89186
89658
|
}
|
|
89187
89659
|
console.log();
|
|
89188
89660
|
}
|
|
@@ -89282,7 +89754,7 @@ function resolvePlanFile(target) {
|
|
|
89282
89754
|
const stat13 = statSync12(t);
|
|
89283
89755
|
if (stat13.isFile())
|
|
89284
89756
|
return t;
|
|
89285
|
-
const candidate =
|
|
89757
|
+
const candidate = join144(t, "plan.md");
|
|
89286
89758
|
if (existsSync68(candidate))
|
|
89287
89759
|
return candidate;
|
|
89288
89760
|
}
|
|
@@ -89290,7 +89762,7 @@ function resolvePlanFile(target) {
|
|
|
89290
89762
|
let dir = process.cwd();
|
|
89291
89763
|
const root = parse4(dir).root;
|
|
89292
89764
|
while (dir !== root) {
|
|
89293
|
-
const candidate =
|
|
89765
|
+
const candidate = join144(dir, "plan.md");
|
|
89294
89766
|
if (existsSync68(candidate))
|
|
89295
89767
|
return candidate;
|
|
89296
89768
|
dir = dirname42(dir);
|
|
@@ -89380,7 +89852,7 @@ async function planCommand(action, target, options2) {
|
|
|
89380
89852
|
}
|
|
89381
89853
|
// src/commands/statusline/statusline-command.ts
|
|
89382
89854
|
import { appendFileSync as appendFileSync3 } from "node:fs";
|
|
89383
|
-
import { homedir as
|
|
89855
|
+
import { homedir as homedir31 } from "node:os";
|
|
89384
89856
|
init_cache_dir();
|
|
89385
89857
|
|
|
89386
89858
|
// src/domains/statusline/config-loader.ts
|
|
@@ -89491,7 +89963,7 @@ function computeContextPercent(cw) {
|
|
|
89491
89963
|
|
|
89492
89964
|
// src/domains/statusline/git-cache.ts
|
|
89493
89965
|
import { createHash as createHash16 } from "node:crypto";
|
|
89494
|
-
import { readFileSync as
|
|
89966
|
+
import { readFileSync as readFileSync30 } from "node:fs";
|
|
89495
89967
|
init_cache_dir();
|
|
89496
89968
|
var GIT_CACHE_TTL_MS = 30000;
|
|
89497
89969
|
var MAX_UNTRACKED_FILES = 200;
|
|
@@ -89572,7 +90044,7 @@ function untrackedInsertions(cwd2) {
|
|
|
89572
90044
|
break;
|
|
89573
90045
|
let buf;
|
|
89574
90046
|
try {
|
|
89575
|
-
buf =
|
|
90047
|
+
buf = readFileSync30(`${cwd2}/${relative23}`);
|
|
89576
90048
|
} catch {
|
|
89577
90049
|
continue;
|
|
89578
90050
|
}
|
|
@@ -89754,7 +90226,7 @@ function quotaWindows(now = Date.now()) {
|
|
|
89754
90226
|
}
|
|
89755
90227
|
|
|
89756
90228
|
// src/domains/statusline/components.ts
|
|
89757
|
-
import { homedir as
|
|
90229
|
+
import { homedir as homedir30 } from "node:os";
|
|
89758
90230
|
|
|
89759
90231
|
// src/domains/statusline/colors.ts
|
|
89760
90232
|
init_help_colors();
|
|
@@ -89983,13 +90455,13 @@ function shortenLeadingDirs(path11, keepFull) {
|
|
|
89983
90455
|
return path11;
|
|
89984
90456
|
const leadCount = segments.length - keepFull;
|
|
89985
90457
|
const shortened = segments.map((seg, i) => i < leadCount ? Array.from(seg)[0] ?? seg : seg);
|
|
89986
|
-
const
|
|
89987
|
-
return `${marker}${
|
|
90458
|
+
const sep11 = marker || leadingSlash ? "/" : "";
|
|
90459
|
+
return `${marker}${sep11}${shortened.join("/")}`;
|
|
89988
90460
|
}
|
|
89989
90461
|
function renderDirectory(data, s3) {
|
|
89990
90462
|
let path11 = data.cwd || process.cwd();
|
|
89991
90463
|
if (s3.collapseHome) {
|
|
89992
|
-
const home6 =
|
|
90464
|
+
const home6 = homedir30();
|
|
89993
90465
|
if (home6 && path11.startsWith(home6))
|
|
89994
90466
|
path11 = `~${path11.slice(home6.length)}`;
|
|
89995
90467
|
}
|
|
@@ -90076,11 +90548,11 @@ function renderStatusline(data, settings) {
|
|
|
90076
90548
|
}
|
|
90077
90549
|
|
|
90078
90550
|
// src/domains/statusline/versions.ts
|
|
90079
|
-
import { join as
|
|
90551
|
+
import { join as join145 } from "node:path";
|
|
90080
90552
|
async function resolveCoreVersion(cwd2) {
|
|
90081
90553
|
try {
|
|
90082
90554
|
const { readManifest: readManifest3 } = await Promise.resolve().then(() => (init_manifest(), exports_manifest));
|
|
90083
|
-
const meta = await readManifest3(
|
|
90555
|
+
const meta = await readManifest3(join145(cwd2, ".claude"));
|
|
90084
90556
|
if (!meta)
|
|
90085
90557
|
return null;
|
|
90086
90558
|
const kits = meta.kits;
|
|
@@ -90106,7 +90578,7 @@ function writeDebug(enabled, context, err) {
|
|
|
90106
90578
|
} catch {}
|
|
90107
90579
|
}
|
|
90108
90580
|
function collapseHome(p2) {
|
|
90109
|
-
const home6 =
|
|
90581
|
+
const home6 = homedir31();
|
|
90110
90582
|
return home6 && p2.startsWith(home6) ? `~${p2.slice(home6.length)}` : p2;
|
|
90111
90583
|
}
|
|
90112
90584
|
function fallbackLine(cwd2) {
|
|
@@ -90170,24 +90642,24 @@ init_logger();
|
|
|
90170
90642
|
init_logger();
|
|
90171
90643
|
|
|
90172
90644
|
// src/commands/telemetry/shared.ts
|
|
90173
|
-
import { existsSync as existsSync69, readFileSync as
|
|
90174
|
-
import { homedir as
|
|
90175
|
-
import { join as
|
|
90645
|
+
import { existsSync as existsSync69, readFileSync as readFileSync31, readdirSync as readdirSync13 } from "node:fs";
|
|
90646
|
+
import { homedir as homedir32 } from "node:os";
|
|
90647
|
+
import { join as join146 } from "node:path";
|
|
90176
90648
|
init_token_store();
|
|
90177
90649
|
init_manifest_path_resolver();
|
|
90178
90650
|
init_takumi_constants();
|
|
90179
|
-
var USER_CACHE_PATH =
|
|
90180
|
-
var EVENT_BUFFER_DIR =
|
|
90181
|
-
var RATE_STATE_PATH =
|
|
90182
|
-
var TAKUMI_MANIFEST_PATH =
|
|
90183
|
-
var LEGACY_METADATA_PATH =
|
|
90651
|
+
var USER_CACHE_PATH = join146(homedir32(), ".claude", "sk-user.json");
|
|
90652
|
+
var EVENT_BUFFER_DIR = join146(homedir32(), ".claude", "sk-events");
|
|
90653
|
+
var RATE_STATE_PATH = join146(homedir32(), ".claude", "sk-rate-state.json");
|
|
90654
|
+
var TAKUMI_MANIFEST_PATH = join146(homedir32(), ".claude", MANIFEST_FILENAME);
|
|
90655
|
+
var LEGACY_METADATA_PATH = join146(homedir32(), ".claude", LEGACY_MANIFEST_FILENAME);
|
|
90184
90656
|
var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
|
|
90185
90657
|
var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
|
|
90186
90658
|
function readUserCache() {
|
|
90187
90659
|
try {
|
|
90188
90660
|
if (!existsSync69(USER_CACHE_PATH))
|
|
90189
90661
|
return null;
|
|
90190
|
-
const parsed = JSON.parse(
|
|
90662
|
+
const parsed = JSON.parse(readFileSync31(USER_CACHE_PATH, "utf8"));
|
|
90191
90663
|
if (!parsed || typeof parsed !== "object")
|
|
90192
90664
|
return null;
|
|
90193
90665
|
return parsed;
|
|
@@ -90199,7 +90671,7 @@ function countBufferFiles() {
|
|
|
90199
90671
|
try {
|
|
90200
90672
|
if (!existsSync69(EVENT_BUFFER_DIR))
|
|
90201
90673
|
return 0;
|
|
90202
|
-
return
|
|
90674
|
+
return readdirSync13(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
|
|
90203
90675
|
} catch {
|
|
90204
90676
|
return 0;
|
|
90205
90677
|
}
|
|
@@ -90209,9 +90681,9 @@ function readTelemetryConfig() {
|
|
|
90209
90681
|
const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
|
|
90210
90682
|
let metadata = null;
|
|
90211
90683
|
try {
|
|
90212
|
-
const resolved = findManifestPathSync(
|
|
90684
|
+
const resolved = findManifestPathSync(join146(homedir32(), ".claude"));
|
|
90213
90685
|
if (resolved) {
|
|
90214
|
-
metadata = JSON.parse(
|
|
90686
|
+
metadata = JSON.parse(readFileSync31(resolved.path, "utf8"));
|
|
90215
90687
|
}
|
|
90216
90688
|
} catch {
|
|
90217
90689
|
metadata = null;
|
|
@@ -90386,8 +90858,8 @@ init_logger();
|
|
|
90386
90858
|
init_safe_prompts();
|
|
90387
90859
|
init_safe_spinner();
|
|
90388
90860
|
var import_fs_extra39 = __toESM(require_lib(), 1);
|
|
90389
|
-
import { readdirSync as
|
|
90390
|
-
import { join as
|
|
90861
|
+
import { readdirSync as readdirSync15, rmSync as rmSync12 } from "node:fs";
|
|
90862
|
+
import { join as join148, resolve as resolve36, sep as sep11 } from "node:path";
|
|
90391
90863
|
|
|
90392
90864
|
// src/commands/uninstall/analysis-handler.ts
|
|
90393
90865
|
init_metadata_migration();
|
|
@@ -90397,8 +90869,8 @@ init_logger();
|
|
|
90397
90869
|
init_safe_prompts();
|
|
90398
90870
|
init_takumi_constants();
|
|
90399
90871
|
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
90400
|
-
import { existsSync as existsSync70, readdirSync as
|
|
90401
|
-
import { dirname as dirname43, join as
|
|
90872
|
+
import { existsSync as existsSync70, readdirSync as readdirSync14, rmSync as rmSync11 } from "node:fs";
|
|
90873
|
+
import { dirname as dirname43, join as join147 } from "node:path";
|
|
90402
90874
|
function listPresentManifestNames(installPath) {
|
|
90403
90875
|
const present = [];
|
|
90404
90876
|
if (existsSync70(getManifestPath(installPath)))
|
|
@@ -90424,9 +90896,9 @@ async function cleanupEmptyDirectories3(filePath, installationRoot) {
|
|
|
90424
90896
|
let currentDir = dirname43(filePath);
|
|
90425
90897
|
while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
|
|
90426
90898
|
try {
|
|
90427
|
-
const entries =
|
|
90899
|
+
const entries = readdirSync14(currentDir);
|
|
90428
90900
|
if (entries.length === 0) {
|
|
90429
|
-
|
|
90901
|
+
rmSync11(currentDir, { recursive: true });
|
|
90430
90902
|
cleaned++;
|
|
90431
90903
|
logger.debug(`Removed empty directory: ${currentDir}`);
|
|
90432
90904
|
currentDir = dirname43(currentDir);
|
|
@@ -90451,7 +90923,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
90451
90923
|
if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
|
|
90452
90924
|
const kitFiles = metadata.kits[kit].files || [];
|
|
90453
90925
|
for (const trackedFile of kitFiles) {
|
|
90454
|
-
const filePath =
|
|
90926
|
+
const filePath = join147(installation.path, trackedFile.path);
|
|
90455
90927
|
if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
|
|
90456
90928
|
result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
|
|
90457
90929
|
continue;
|
|
@@ -90483,7 +90955,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
|
|
|
90483
90955
|
return result;
|
|
90484
90956
|
}
|
|
90485
90957
|
for (const trackedFile of allTrackedFiles) {
|
|
90486
|
-
const filePath =
|
|
90958
|
+
const filePath = join147(installation.path, trackedFile.path);
|
|
90487
90959
|
const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
|
|
90488
90960
|
if (!ownershipResult.exists)
|
|
90489
90961
|
continue;
|
|
@@ -90541,7 +91013,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
90541
91013
|
try {
|
|
90542
91014
|
const resolvedPath = resolve36(filePath);
|
|
90543
91015
|
const resolvedBase = resolve36(baseDir);
|
|
90544
|
-
if (!resolvedPath.startsWith(resolvedBase +
|
|
91016
|
+
if (!resolvedPath.startsWith(resolvedBase + sep11) && resolvedPath !== resolvedBase) {
|
|
90545
91017
|
logger.debug(`Path outside installation directory: ${filePath}`);
|
|
90546
91018
|
return false;
|
|
90547
91019
|
}
|
|
@@ -90549,7 +91021,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
|
|
|
90549
91021
|
if (stats.isSymbolicLink()) {
|
|
90550
91022
|
const realPath = await import_fs_extra39.realpath(filePath);
|
|
90551
91023
|
const resolvedReal = resolve36(realPath);
|
|
90552
|
-
if (!resolvedReal.startsWith(resolvedBase +
|
|
91024
|
+
if (!resolvedReal.startsWith(resolvedBase + sep11) && resolvedReal !== resolvedBase) {
|
|
90553
91025
|
logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
|
|
90554
91026
|
return false;
|
|
90555
91027
|
}
|
|
@@ -90582,7 +91054,7 @@ async function removeInstallations(installations, options2) {
|
|
|
90582
91054
|
let removedCount = 0;
|
|
90583
91055
|
let cleanedDirs = 0;
|
|
90584
91056
|
for (const item of analysis.toDelete) {
|
|
90585
|
-
const filePath =
|
|
91057
|
+
const filePath = join148(installation.path, item.path);
|
|
90586
91058
|
if (!await import_fs_extra39.pathExists(filePath))
|
|
90587
91059
|
continue;
|
|
90588
91060
|
if (!await isPathSafeToRemove(filePath, installation.path)) {
|
|
@@ -90601,9 +91073,9 @@ async function removeInstallations(installations, options2) {
|
|
|
90601
91073
|
await ManifestWriter.removeKitFromManifest(installation.path, options2.kit);
|
|
90602
91074
|
}
|
|
90603
91075
|
try {
|
|
90604
|
-
const remaining =
|
|
91076
|
+
const remaining = readdirSync15(installation.path);
|
|
90605
91077
|
if (remaining.length === 0) {
|
|
90606
|
-
|
|
91078
|
+
rmSync12(installation.path, { recursive: true });
|
|
90607
91079
|
logger.debug(`Removed empty installation directory: ${installation.path}`);
|
|
90608
91080
|
}
|
|
90609
91081
|
} catch {}
|
|
@@ -91367,7 +91839,7 @@ function parsePositiveIntFlag(raw, label, example, max) {
|
|
|
91367
91839
|
}
|
|
91368
91840
|
var ARTIFACT_LIST_LIMIT_MAX = 100;
|
|
91369
91841
|
function registerCommands(cli) {
|
|
91370
|
-
cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (core, extras). Repeat the flag to install multiple kits, e.g. --kit core --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("--skill-role <role>", "Install only skills tagged with these role(s) (comma-separated or repeatable). Combines with --skill-category as a union.").option("--skill-category <category>", "Install only skills in these categor(y/ies) (comma-separated or repeatable). Combines with --skill-role as a union.").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove takumi files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--install-hooks", "
|
|
91842
|
+
cli.command("init", "Initialize or update Takumi project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit(s) to install (core, extras). Repeat the flag to install multiple kits, e.g. --kit core --kit extras.").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("--skill-role <role>", "Install only skills tagged with these role(s) (comma-separated or repeatable). Combines with --skill-category as a union.").option("--skill-category <category>", "Install only skills in these categor(y/ies) (comma-separated or repeatable). Combines with --skill-role as a union.").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove takumi files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--install-hooks", "(deprecated: no-op) The full hook set (guard, session, convention, extension, metrics, perf) installs by default.").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /tkm: prefix to all slash commands by moving them to commands/tkm/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").option("--local", "Use local monorepo as kit source (auto-detects from CLI location)").option("--use-gh", "Force GitHub release source (bypass the Worker release distribution API; default uses Worker)").option("-a, --agent <agents...>", "Target agents (claude-code, codex). Default: claude-code").action(async (options2) => {
|
|
91371
91843
|
if (options2.exclude && !Array.isArray(options2.exclude)) {
|
|
91372
91844
|
options2.exclude = [options2.exclude];
|
|
91373
91845
|
}
|
|
@@ -91439,7 +91911,7 @@ function registerCommands(cli) {
|
|
|
91439
91911
|
cli.command("telemetry [action]", "Inspect or control Takumi telemetry").option("--json", "Output in JSON format (status)").action(async (action, options2) => {
|
|
91440
91912
|
await telemetryCommand(action, options2);
|
|
91441
91913
|
});
|
|
91442
|
-
cli.command("hooks [event]", "Manage Takumi hook entries in agent settings (install|uninstall)").option("-a, --agent <agent>", "Target agent: claude or codex").option("-g, --global", "Use the user-level settings file instead of project-local").option("--dry-run", "Preview the diff without writing").option("-y, --yes", "Auto-approve diff prompts and create missing settings files").option("--bin <command>", "Override the leading binary in generated hook commands").option("--no-detach", "Force inline PUT; default behavior spawns a detached child for the network call").option("--debug", "Mirror hook logs into <sessionDir>/detach-debug.log for inspection").option("--job <data>", "Internal: base64 job payload for fork-detached PUT").action(async (event, options2 = {}) => {
|
|
91914
|
+
cli.command("hooks [event]", "Manage Takumi hook entries in agent settings (install|uninstall)").option("-a, --agent <agent>", "Target agent: claude or codex").option("-g, --global", "Use the user-level settings file instead of project-local").option("--dry-run", "Preview the diff without writing").option("-y, --yes", "Auto-approve diff prompts and create missing settings files").option("--bin <command>", "Override the leading binary in generated hook commands").option("--no-detach", "Force inline PUT; default behavior spawns a detached child for the network call").option("--debug", "Mirror hook logs into <sessionDir>/detach-debug.log for inspection").option("--job <data>", "Internal: base64 job payload for fork-detached PUT").option("--dir <path>", "Internal: hooks dir for the scan-meta eval-hook scan").option("--out <path>", "Internal: out-of-band result file for scan-meta").action(async (event, options2 = {}) => {
|
|
91443
91915
|
const agent = options2.agent === "claude" || options2.agent === "codex" ? options2.agent : undefined;
|
|
91444
91916
|
const noDetach = options2.detach === false;
|
|
91445
91917
|
await hooksCommand(event, {
|
|
@@ -91449,13 +91921,18 @@ function registerCommands(cli) {
|
|
|
91449
91921
|
yes: options2.yes,
|
|
91450
91922
|
bin: options2.bin,
|
|
91451
91923
|
noDetach,
|
|
91452
|
-
debug: options2.debug
|
|
91924
|
+
debug: options2.debug,
|
|
91925
|
+
dir: options2.dir,
|
|
91926
|
+
out: options2.out
|
|
91453
91927
|
});
|
|
91454
91928
|
});
|
|
91455
|
-
cli.command("hook-exec", "Run a Takumi hook handler for the piped stdin event (agent-invoked)").option("--hook <selector>", "Handler selector: <category>.<name> or <category>.* (wildcard)").option("--event <event>", "Fallback hook event (kebab-case); stdin hook_event_name wins").option("-a, --agent <agent>", "Target agent: claude or codex").option("--no-detach", "Force inline PUT instead of spawning a detached child").option("--debug", "Mirror hook logs into <sessionDir>/detach-debug.log").action(async (options2 = {}) => {
|
|
91929
|
+
cli.command("hook-exec", "Run a Takumi hook handler for the piped stdin event (agent-invoked)").option("--hook <selector>", "Handler selector: <category>.<name> or <category>.* (wildcard)").option("--eval <relpath>", "Run a kit JS hook file in-process (relative to the scope's hooks dir)").option("-g, --global", "Scope for --eval resolution: the global hooks dir").option("--project", "Scope for --eval resolution: the project hooks dir (default)").option("--plugin", "Scope for --eval resolution: the plugin hooks dir").option("--event <event>", "Fallback hook event (kebab-case); stdin hook_event_name wins").option("-a, --agent <agent>", "Target agent: claude or codex").option("--no-detach", "Force inline PUT instead of spawning a detached child").option("--debug", "Mirror hook logs into <sessionDir>/detach-debug.log").action(async (options2 = {}) => {
|
|
91456
91930
|
const agent = options2.agent === "claude" || options2.agent === "codex" ? options2.agent : undefined;
|
|
91931
|
+
const scope = options2.global ? "global" : options2.plugin ? "plugin" : options2.project ? "project" : undefined;
|
|
91457
91932
|
await hookExecCommand({
|
|
91458
91933
|
hook: options2.hook,
|
|
91934
|
+
eval: options2.eval,
|
|
91935
|
+
scope,
|
|
91459
91936
|
event: options2.event,
|
|
91460
91937
|
agent,
|
|
91461
91938
|
noDetach: options2.detach === false,
|
|
@@ -91522,8 +91999,8 @@ init_version_checker();
|
|
|
91522
91999
|
init_manifest_path_resolver();
|
|
91523
92000
|
init_logger();
|
|
91524
92001
|
init_types2();
|
|
91525
|
-
import { readFileSync as
|
|
91526
|
-
import { join as
|
|
92002
|
+
import { readFileSync as readFileSync32 } from "node:fs";
|
|
92003
|
+
import { join as join149 } from "node:path";
|
|
91527
92004
|
var PROVIDER_LOCAL_SUBDIRS = {
|
|
91528
92005
|
"claude-code": ".claude",
|
|
91529
92006
|
codex: ".codex"
|
|
@@ -91578,7 +92055,7 @@ async function displayVersion() {
|
|
|
91578
92055
|
const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
|
|
91579
92056
|
if (!localSubdir)
|
|
91580
92057
|
continue;
|
|
91581
|
-
const localRoot =
|
|
92058
|
+
const localRoot = join149(process.cwd(), localSubdir);
|
|
91582
92059
|
if (localRoot === inst.globalRoot())
|
|
91583
92060
|
continue;
|
|
91584
92061
|
const resolved = findManifestPathSync(localRoot);
|
|
@@ -91588,7 +92065,7 @@ async function displayVersion() {
|
|
|
91588
92065
|
}
|
|
91589
92066
|
for (const { provider, path: metaPath } of localChecks) {
|
|
91590
92067
|
try {
|
|
91591
|
-
const rawMetadata = JSON.parse(
|
|
92068
|
+
const rawMetadata = JSON.parse(readFileSync32(metaPath, "utf-8"));
|
|
91592
92069
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
91593
92070
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
91594
92071
|
if (kitsDisplay) {
|
|
@@ -91608,7 +92085,7 @@ async function displayVersion() {
|
|
|
91608
92085
|
const resolved = findManifestPathSync(installPath);
|
|
91609
92086
|
if (resolved) {
|
|
91610
92087
|
try {
|
|
91611
|
-
const rawMetadata = JSON.parse(
|
|
92088
|
+
const rawMetadata = JSON.parse(readFileSync32(resolved.path, "utf-8"));
|
|
91612
92089
|
const metadata = MetadataSchema.parse(rawMetadata);
|
|
91613
92090
|
const kitsDisplay = formatInstalledKits(metadata);
|
|
91614
92091
|
if (kitsDisplay) {
|
|
@@ -91990,7 +92467,7 @@ var output2 = new OutputManager2;
|
|
|
91990
92467
|
// src/shared/temp-cleanup.ts
|
|
91991
92468
|
init_logger();
|
|
91992
92469
|
var import_fs_extra41 = __toESM(require_lib(), 1);
|
|
91993
|
-
import { rmSync as
|
|
92470
|
+
import { rmSync as rmSync13 } from "node:fs";
|
|
91994
92471
|
var tempDirs2 = new Set;
|
|
91995
92472
|
async function cleanup() {
|
|
91996
92473
|
if (tempDirs2.size === 0)
|
|
@@ -92011,7 +92488,7 @@ function cleanupSync() {
|
|
|
92011
92488
|
return;
|
|
92012
92489
|
for (const dir of tempDirs2) {
|
|
92013
92490
|
try {
|
|
92014
|
-
|
|
92491
|
+
rmSync13(dir, { recursive: true, force: true });
|
|
92015
92492
|
} catch {}
|
|
92016
92493
|
}
|
|
92017
92494
|
tempDirs2.clear();
|