@alessandroraffa/tangyr 1.0.1 → 1.0.3
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 +152 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17378,21 +17378,33 @@ function collectProjectScopeFindings(projectRoot, tools, options) {
|
|
|
17378
17378
|
) : void 0;
|
|
17379
17379
|
const probePaths = buildProjectProbes(tool, projectRoot, profile);
|
|
17380
17380
|
for (const { resolvedPath, description, classification } of probePaths) {
|
|
17381
|
-
|
|
17381
|
+
let stat;
|
|
17382
|
+
try {
|
|
17383
|
+
stat = fs11.lstatSync(resolvedPath);
|
|
17384
|
+
} catch {
|
|
17382
17385
|
continue;
|
|
17383
17386
|
}
|
|
17384
|
-
const
|
|
17387
|
+
const type = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "directory" : "file";
|
|
17388
|
+
const ours = type === "file" && carriesTangyrMarker(resolvedPath);
|
|
17385
17389
|
findings.push({
|
|
17386
17390
|
path: resolvedPath,
|
|
17387
17391
|
tool,
|
|
17388
|
-
type
|
|
17389
|
-
classification,
|
|
17390
|
-
description
|
|
17392
|
+
type,
|
|
17393
|
+
classification: ours ? "compatible" : classification,
|
|
17394
|
+
description: ours ? `${description} (written by Tangyr)` : description
|
|
17391
17395
|
});
|
|
17392
17396
|
}
|
|
17393
17397
|
}
|
|
17394
17398
|
return findings;
|
|
17395
17399
|
}
|
|
17400
|
+
function carriesTangyrMarker(filePath) {
|
|
17401
|
+
try {
|
|
17402
|
+
const firstNonEmpty = fs11.readFileSync(filePath, "utf8").split("\n").find((line) => line.trim().length > 0) ?? "";
|
|
17403
|
+
return extractProvenanceMarker(firstNonEmpty) !== null;
|
|
17404
|
+
} catch {
|
|
17405
|
+
return false;
|
|
17406
|
+
}
|
|
17407
|
+
}
|
|
17396
17408
|
function requestedAssessTools(toolFilter) {
|
|
17397
17409
|
return toolFilter ?? [...DEFAULT_ASSESS_TARGETS];
|
|
17398
17410
|
}
|
|
@@ -22182,11 +22194,23 @@ async function runUninstallCommand(options, logger) {
|
|
|
22182
22194
|
}
|
|
22183
22195
|
const claudeRoots = scope === "global" && selectedTools.has("claude-code") ? resolveClaudeRootsForUninstall(manifest, runtime) : [];
|
|
22184
22196
|
let removedCount = 0;
|
|
22197
|
+
const removedParentDirs = /* @__PURE__ */ new Set();
|
|
22185
22198
|
for (const file of useManifestPathRemoval ? manifestArtifacts : []) {
|
|
22186
22199
|
if (isMergeSurfaceKey(file.relativePath)) {
|
|
22187
|
-
|
|
22188
|
-
|
|
22200
|
+
const surfacePath = file.path ?? resolveManifestKeyToPath(
|
|
22201
|
+
file.relativePath,
|
|
22202
|
+
scope,
|
|
22203
|
+
runtime,
|
|
22204
|
+
uninstallProjectRoot
|
|
22189
22205
|
);
|
|
22206
|
+
if (surfacePath && stripTangyrFromMergeSurface(surfacePath, logger)) {
|
|
22207
|
+
removedParentDirs.add(path24.dirname(surfacePath));
|
|
22208
|
+
removedCount++;
|
|
22209
|
+
} else {
|
|
22210
|
+
logger.verbose(
|
|
22211
|
+
` left in place (merge surface, nothing of ours in it): ${surfacePath ?? file.relativePath}`
|
|
22212
|
+
);
|
|
22213
|
+
}
|
|
22190
22214
|
continue;
|
|
22191
22215
|
}
|
|
22192
22216
|
const isClaudeGlobal = file.relativePath.startsWith("claude-code/") && scope === "global";
|
|
@@ -22199,6 +22223,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
22199
22223
|
for (const actualPath of paths) {
|
|
22200
22224
|
if (actualPath && (fs27.existsSync(actualPath) || isSymlink(actualPath))) {
|
|
22201
22225
|
removeManagedPath(actualPath);
|
|
22226
|
+
removedParentDirs.add(path24.dirname(actualPath));
|
|
22202
22227
|
logger.verbose(` removed: ${actualPath}`);
|
|
22203
22228
|
removedCount++;
|
|
22204
22229
|
} else {
|
|
@@ -22220,6 +22245,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
22220
22245
|
continue;
|
|
22221
22246
|
}
|
|
22222
22247
|
removeManagedPath(actualPath);
|
|
22248
|
+
removedParentDirs.add(path24.dirname(actualPath));
|
|
22223
22249
|
logger.verbose(` removed: ${actualPath}`);
|
|
22224
22250
|
removedCount++;
|
|
22225
22251
|
} else {
|
|
@@ -22270,6 +22296,11 @@ async function runUninstallCommand(options, logger) {
|
|
|
22270
22296
|
fs27.unlinkSync(manifestPath);
|
|
22271
22297
|
logger.verbose(` removed manifest: ${manifestPath}`);
|
|
22272
22298
|
}
|
|
22299
|
+
pruneEmptyDirs(path24.join(scopePath, "backups"), logger);
|
|
22300
|
+
const pruneBoundary = path24.dirname(scopePath);
|
|
22301
|
+
for (const dir of removedParentDirs) {
|
|
22302
|
+
pruneEmptyAncestors(dir, pruneBoundary, logger);
|
|
22303
|
+
}
|
|
22273
22304
|
try {
|
|
22274
22305
|
const remaining = fs27.readdirSync(scopePath);
|
|
22275
22306
|
if (remaining.length === 0) {
|
|
@@ -22649,6 +22680,79 @@ var MERGE_SURFACE_SLOTS = /* @__PURE__ */ new Set([
|
|
|
22649
22680
|
"mcp_shared_file",
|
|
22650
22681
|
"mcp_file"
|
|
22651
22682
|
]);
|
|
22683
|
+
function stripTangyrFromMergeSurface(filePath, logger) {
|
|
22684
|
+
const parsed = readJsonObject2(filePath);
|
|
22685
|
+
if (!parsed) {
|
|
22686
|
+
return false;
|
|
22687
|
+
}
|
|
22688
|
+
const cleaned = { ...parsed };
|
|
22689
|
+
const hooks = removeManagedClaudeHookEntries(
|
|
22690
|
+
parsed.hooks,
|
|
22691
|
+
(entry) => entry._tangyr === true || entry._proteus === true
|
|
22692
|
+
);
|
|
22693
|
+
if (hooks === void 0) {
|
|
22694
|
+
delete cleaned.hooks;
|
|
22695
|
+
} else {
|
|
22696
|
+
cleaned.hooks = hooks;
|
|
22697
|
+
}
|
|
22698
|
+
if (isRecord(parsed.mcpServers)) {
|
|
22699
|
+
const kept = Object.fromEntries(
|
|
22700
|
+
Object.entries(parsed.mcpServers).filter(
|
|
22701
|
+
([, server]) => !isRecord(server) || !isRecord(server._tangyr) && !isRecord(server._proteus)
|
|
22702
|
+
)
|
|
22703
|
+
);
|
|
22704
|
+
if (Object.keys(kept).length === 0) {
|
|
22705
|
+
delete cleaned.mcpServers;
|
|
22706
|
+
} else {
|
|
22707
|
+
cleaned.mcpServers = kept;
|
|
22708
|
+
}
|
|
22709
|
+
}
|
|
22710
|
+
delete cleaned._tangyr;
|
|
22711
|
+
delete cleaned._proteus;
|
|
22712
|
+
if (JSON.stringify(cleaned) === JSON.stringify(parsed)) {
|
|
22713
|
+
return false;
|
|
22714
|
+
}
|
|
22715
|
+
writeJsonOrRemove(filePath, cleaned);
|
|
22716
|
+
logger.verbose(` stripped Tangyr's block from: ${filePath}`);
|
|
22717
|
+
return true;
|
|
22718
|
+
}
|
|
22719
|
+
function pruneEmptyAncestors(startDir, stopAt, logger) {
|
|
22720
|
+
const boundary = path24.resolve(stopAt);
|
|
22721
|
+
let current = path24.resolve(startDir);
|
|
22722
|
+
while (current !== boundary && current.startsWith(`${boundary}${path24.sep}`)) {
|
|
22723
|
+
try {
|
|
22724
|
+
if (fs27.readdirSync(current).length > 0) {
|
|
22725
|
+
return;
|
|
22726
|
+
}
|
|
22727
|
+
fs27.rmdirSync(current);
|
|
22728
|
+
logger.verbose(` removed empty directory: ${current}`);
|
|
22729
|
+
} catch {
|
|
22730
|
+
return;
|
|
22731
|
+
}
|
|
22732
|
+
current = path24.dirname(current);
|
|
22733
|
+
}
|
|
22734
|
+
}
|
|
22735
|
+
function pruneEmptyDirs(dir, logger) {
|
|
22736
|
+
let stat;
|
|
22737
|
+
try {
|
|
22738
|
+
stat = fs27.lstatSync(dir);
|
|
22739
|
+
} catch {
|
|
22740
|
+
return;
|
|
22741
|
+
}
|
|
22742
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
22743
|
+
return;
|
|
22744
|
+
}
|
|
22745
|
+
for (const entry of fs27.readdirSync(dir, { withFileTypes: true })) {
|
|
22746
|
+
if (entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
22747
|
+
pruneEmptyDirs(path24.join(dir, entry.name), logger);
|
|
22748
|
+
}
|
|
22749
|
+
}
|
|
22750
|
+
try {
|
|
22751
|
+
fs27.rmdirSync(dir);
|
|
22752
|
+
logger.verbose(` removed empty directory: ${dir}`);
|
|
22753
|
+
} catch {
|
|
22754
|
+
}
|
|
22755
|
+
}
|
|
22652
22756
|
function stillMatchesRecord(artifactPath, recorded) {
|
|
22653
22757
|
if (isLegacyArtifactState(recorded)) {
|
|
22654
22758
|
return true;
|
|
@@ -24987,6 +25091,7 @@ function toConflictPolicy2(value) {
|
|
|
24987
25091
|
}
|
|
24988
25092
|
|
|
24989
25093
|
// src/commands/install.ts
|
|
25094
|
+
import crypto11 from "crypto";
|
|
24990
25095
|
import fs43 from "fs";
|
|
24991
25096
|
import path43 from "path";
|
|
24992
25097
|
|
|
@@ -26127,7 +26232,11 @@ function resolveInstructionsSource(kitRoot, config) {
|
|
|
26127
26232
|
"source.instructions in tangyr.config.yaml"
|
|
26128
26233
|
);
|
|
26129
26234
|
}
|
|
26130
|
-
return {
|
|
26235
|
+
return {
|
|
26236
|
+
file,
|
|
26237
|
+
label: normalizeLabel(kitRoot, file),
|
|
26238
|
+
origin: "config-override"
|
|
26239
|
+
};
|
|
26131
26240
|
}
|
|
26132
26241
|
const declared = resolveKitEntrypointName(kitRoot);
|
|
26133
26242
|
if (declared !== void 0) {
|
|
@@ -26139,7 +26248,11 @@ function resolveInstructionsSource(kitRoot, config) {
|
|
|
26139
26248
|
"entrypoint in tangyr-kit.yaml"
|
|
26140
26249
|
);
|
|
26141
26250
|
}
|
|
26142
|
-
return {
|
|
26251
|
+
return {
|
|
26252
|
+
file,
|
|
26253
|
+
label: normalizeLabel(kitRoot, file),
|
|
26254
|
+
origin: "manifest-entrypoint"
|
|
26255
|
+
};
|
|
26143
26256
|
}
|
|
26144
26257
|
for (const name of [DEFAULT_ENTRYPOINT, PORTABLE_INSTRUCTIONS_NAME]) {
|
|
26145
26258
|
const file = path33.resolve(kitRoot, name);
|
|
@@ -26398,6 +26511,12 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26398
26511
|
const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
26399
26512
|
const marker = extractProvenanceMarker(firstNonEmptyLine);
|
|
26400
26513
|
if (marker !== null && marker.hash === expectedBodyHash) {
|
|
26514
|
+
addArtifactToManifest(manifest, {
|
|
26515
|
+
relativePath: SHIM_MANIFEST_KEY,
|
|
26516
|
+
path: shimPath,
|
|
26517
|
+
hash: expectedBodyHash,
|
|
26518
|
+
origin: "tangyr-managed"
|
|
26519
|
+
});
|
|
26401
26520
|
logger?.verbose(
|
|
26402
26521
|
`instructions-shim: already current, skipped -> ${shimPath}`
|
|
26403
26522
|
);
|
|
@@ -30731,7 +30850,12 @@ function isBackupablePath(targetPath) {
|
|
|
30731
30850
|
}
|
|
30732
30851
|
function backupConflictingTarget(targetPath, scopePath) {
|
|
30733
30852
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/gu, "").replace("T", "T").replace(/\.\d+Z$/u, "Z");
|
|
30734
|
-
const
|
|
30853
|
+
const scopeRoot = path43.dirname(scopePath);
|
|
30854
|
+
let relativeToRoot = path43.relative(scopeRoot, targetPath);
|
|
30855
|
+
if (relativeToRoot.startsWith("..") || path43.isAbsolute(relativeToRoot)) {
|
|
30856
|
+
const digest = crypto11.createHash("sha256").update(path43.dirname(targetPath)).digest("hex").slice(0, 12);
|
|
30857
|
+
relativeToRoot = path43.join(`_outside-${digest}`, path43.basename(targetPath));
|
|
30858
|
+
}
|
|
30735
30859
|
const backupPath = path43.join(scopePath, "backups", ts2, relativeToRoot);
|
|
30736
30860
|
fs43.mkdirSync(path43.dirname(backupPath), { recursive: true });
|
|
30737
30861
|
const stat = fs43.lstatSync(targetPath);
|
|
@@ -30953,14 +31077,14 @@ async function runInstallCommand(options, logger) {
|
|
|
30953
31077
|
return;
|
|
30954
31078
|
}
|
|
30955
31079
|
if (conflictingFindings.length > 0) {
|
|
31080
|
+
const toolsByPath = /* @__PURE__ */ new Map();
|
|
31081
|
+
for (const finding of conflictingFindings) {
|
|
31082
|
+
const tools2 = toolsByPath.get(finding.path) ?? [];
|
|
31083
|
+
tools2.push(finding.tool);
|
|
31084
|
+
toolsByPath.set(finding.path, tools2);
|
|
31085
|
+
}
|
|
30956
31086
|
if (options.yes) {
|
|
30957
31087
|
const decidedPaths = /* @__PURE__ */ new Set();
|
|
30958
|
-
const toolsByPath = /* @__PURE__ */ new Map();
|
|
30959
|
-
for (const finding of conflictingFindings) {
|
|
30960
|
-
const tools2 = toolsByPath.get(finding.path) ?? [];
|
|
30961
|
-
tools2.push(finding.tool);
|
|
30962
|
-
toolsByPath.set(finding.path, tools2);
|
|
30963
|
-
}
|
|
30964
31088
|
const posture = config.onConflict === "ask" ? "skip" : config.onConflict;
|
|
30965
31089
|
const replaceable = Array.from(toolsByPath.keys()).filter(
|
|
30966
31090
|
(p) => !foreignSkillsSlots.has(p)
|
|
@@ -31039,10 +31163,11 @@ ACCEPTED CONFLICTS (posture: ${posture}; ${replaceable.length} target(s)):`
|
|
|
31039
31163
|
} else {
|
|
31040
31164
|
logger.info(
|
|
31041
31165
|
`
|
|
31042
|
-
Found ${
|
|
31166
|
+
Found ${toolsByPath.size} conflicting target(s). Please choose an action for each:
|
|
31043
31167
|
`
|
|
31044
31168
|
);
|
|
31045
|
-
for (const
|
|
31169
|
+
for (const [conflictPath, claimingTools] of toolsByPath) {
|
|
31170
|
+
const finding = { path: conflictPath, tool: claimingTools.join(", ") };
|
|
31046
31171
|
const choice = await dist_default8({
|
|
31047
31172
|
message: `Conflict: ${finding.path} (${finding.tool})
|
|
31048
31173
|
Choose an action:`,
|
|
@@ -31440,7 +31565,12 @@ function installClaudeCodeAdapterSlots(args) {
|
|
|
31440
31565
|
if (outcome.status !== "success" && outcome.status !== "skipped-current") {
|
|
31441
31566
|
continue;
|
|
31442
31567
|
}
|
|
31443
|
-
const key = claudeCodeOutcomeToManifestKey(
|
|
31568
|
+
const key = claudeCodeOutcomeToManifestKey(
|
|
31569
|
+
profile,
|
|
31570
|
+
outcome,
|
|
31571
|
+
scope,
|
|
31572
|
+
projectRoot
|
|
31573
|
+
);
|
|
31444
31574
|
if (!key) {
|
|
31445
31575
|
continue;
|
|
31446
31576
|
}
|
|
@@ -32358,7 +32488,7 @@ function commandProbeRows(target, key, command, args) {
|
|
|
32358
32488
|
}
|
|
32359
32489
|
|
|
32360
32490
|
// src/commands/status.ts
|
|
32361
|
-
import
|
|
32491
|
+
import crypto12 from "crypto";
|
|
32362
32492
|
import fs45 from "fs";
|
|
32363
32493
|
import path46 from "path";
|
|
32364
32494
|
function runStatusCommand(options, logger) {
|
|
@@ -33482,7 +33612,7 @@ function containsTangyrSource(value) {
|
|
|
33482
33612
|
return typeof value._tangyr_source === "string" || typeof value._proteus_source === "string" || Object.values(value).some((entry) => containsTangyrSource(entry));
|
|
33483
33613
|
}
|
|
33484
33614
|
function hashString6(value) {
|
|
33485
|
-
return `sha256:${
|
|
33615
|
+
return `sha256:${crypto12.createHash("sha256").update(value).digest("hex")}`;
|
|
33486
33616
|
}
|
|
33487
33617
|
|
|
33488
33618
|
// src/commands/sync.ts
|
|
@@ -34020,10 +34150,7 @@ async function runSyncCommand(options, logger) {
|
|
|
34020
34150
|
}
|
|
34021
34151
|
options.kitPath = kitPathOverride;
|
|
34022
34152
|
options.kit = kitName;
|
|
34023
|
-
const { config, configDir, configSource, sourceRoot, kitInfo } = resolveRuntime(
|
|
34024
|
-
options,
|
|
34025
|
-
import.meta.url
|
|
34026
|
-
);
|
|
34153
|
+
const { config, configDir, configSource, sourceRoot, kitInfo } = resolveRuntime(options, import.meta.url);
|
|
34027
34154
|
const syncOptions = toSyncOptions(options, config, configDir, configSource);
|
|
34028
34155
|
const targets = activeTargets(config, options.target);
|
|
34029
34156
|
const results = [];
|