@alessandroraffa/tangyr 0.21.0 → 0.21.1
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 +460 -371
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17874,8 +17874,8 @@ async function runCacheClearCommand(options, logger) {
|
|
|
17874
17874
|
}
|
|
17875
17875
|
|
|
17876
17876
|
// src/commands/cleanup.ts
|
|
17877
|
-
import
|
|
17878
|
-
import
|
|
17877
|
+
import fs27 from "fs";
|
|
17878
|
+
import path24 from "path";
|
|
17879
17879
|
|
|
17880
17880
|
// node_modules/glob/dist/esm/index.min.js
|
|
17881
17881
|
import { fileURLToPath as Wi } from "url";
|
|
@@ -21021,8 +21021,8 @@ function removeManagedEntries(filePath, parser, serializer, removeManaged, logge
|
|
|
21021
21021
|
}
|
|
21022
21022
|
|
|
21023
21023
|
// src/commands/uninstall.ts
|
|
21024
|
-
import
|
|
21025
|
-
import
|
|
21024
|
+
import fs26 from "fs";
|
|
21025
|
+
import path23 from "path";
|
|
21026
21026
|
|
|
21027
21027
|
// src/core/managed-sources.ts
|
|
21028
21028
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
@@ -21491,25 +21491,134 @@ function reportHooksSourceConflict(report, targets, hooksDir, hookNames) {
|
|
|
21491
21491
|
return message;
|
|
21492
21492
|
}
|
|
21493
21493
|
|
|
21494
|
-
// src/
|
|
21494
|
+
// src/adapters/hook-scripts-bridge.ts
|
|
21495
|
+
import fs24 from "fs";
|
|
21496
|
+
import path22 from "path";
|
|
21497
|
+
|
|
21498
|
+
// src/utils/fs.ts
|
|
21495
21499
|
import fs23 from "fs";
|
|
21500
|
+
import path21 from "path";
|
|
21501
|
+
function ensureDir(dirPath) {
|
|
21502
|
+
fs23.mkdirSync(dirPath, { recursive: true });
|
|
21503
|
+
}
|
|
21504
|
+
function createRelativeSymlink(source, destination, type, options) {
|
|
21505
|
+
const absoluteSource = path21.resolve(source);
|
|
21506
|
+
const relative = path21.relative(
|
|
21507
|
+
realPathOrInput(path21.dirname(destination)),
|
|
21508
|
+
absoluteSource
|
|
21509
|
+
);
|
|
21510
|
+
if (process.platform === "win32" && type === "dir") {
|
|
21511
|
+
fs23.symlinkSync(absoluteSource, destination, "junction");
|
|
21512
|
+
return;
|
|
21513
|
+
}
|
|
21514
|
+
if (process.platform === "win32" && type === "file") {
|
|
21515
|
+
try {
|
|
21516
|
+
fs23.symlinkSync(relative, destination, "file");
|
|
21517
|
+
} catch (error) {
|
|
21518
|
+
if (!hasErrorCode(error, "EPERM")) {
|
|
21519
|
+
throw error;
|
|
21520
|
+
}
|
|
21521
|
+
if (!options?.provenanceMarker) {
|
|
21522
|
+
throw new Error(
|
|
21523
|
+
`${destination}: file symlink unavailable on Windows and no provenance marker was provided.`
|
|
21524
|
+
);
|
|
21525
|
+
}
|
|
21526
|
+
createManagedCopy(
|
|
21527
|
+
source,
|
|
21528
|
+
destination,
|
|
21529
|
+
options.provenanceMarker,
|
|
21530
|
+
options.logger
|
|
21531
|
+
);
|
|
21532
|
+
options.logger?.warn(
|
|
21533
|
+
`${destination}: file symlink unavailable on Windows \u2014 using managed copy with provenance metadata (behavioral contract C-09)`
|
|
21534
|
+
);
|
|
21535
|
+
}
|
|
21536
|
+
return;
|
|
21537
|
+
}
|
|
21538
|
+
fs23.symlinkSync(relative, destination, type);
|
|
21539
|
+
}
|
|
21540
|
+
function createManagedCopy(source, destination, provenanceMarker, _logger) {
|
|
21541
|
+
ensureDir(path21.dirname(destination));
|
|
21542
|
+
const content = fs23.readFileSync(source, "utf8");
|
|
21543
|
+
fs23.writeFileSync(destination, `${provenanceMarker}
|
|
21544
|
+
${content}`);
|
|
21545
|
+
}
|
|
21546
|
+
function hasErrorCode(error, expectedCode) {
|
|
21547
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === expectedCode;
|
|
21548
|
+
}
|
|
21549
|
+
function realPathOrInput(filePath) {
|
|
21550
|
+
try {
|
|
21551
|
+
return fs23.realpathSync(filePath);
|
|
21552
|
+
} catch {
|
|
21553
|
+
return filePath;
|
|
21554
|
+
}
|
|
21555
|
+
}
|
|
21556
|
+
|
|
21557
|
+
// src/adapters/hook-scripts-bridge.ts
|
|
21558
|
+
var SHARED_HOOK_SCRIPTS_KEY = "shared/hook_scripts";
|
|
21559
|
+
function syncHookScriptsBridge(args) {
|
|
21560
|
+
const { source, destination, config, sourceRoot, options, logger } = args;
|
|
21561
|
+
if (!fs24.existsSync(source)) {
|
|
21562
|
+
return {
|
|
21563
|
+
component: "hooks",
|
|
21564
|
+
status: "skipped",
|
|
21565
|
+
path: `${source}: source not configured`
|
|
21566
|
+
};
|
|
21567
|
+
}
|
|
21568
|
+
if (options.dryRun) {
|
|
21569
|
+
logger.info(`[dry-run] hooks: symlink ${source} -> ${destination}`);
|
|
21570
|
+
return { component: "hooks", status: "dry-run", path: destination };
|
|
21571
|
+
}
|
|
21572
|
+
const artifactClass = classifyArtifact(destination, config, sourceRoot);
|
|
21573
|
+
if (artifactClass === "managed-symlink" && isSymlinkTo(destination, source)) {
|
|
21574
|
+
return { component: "hooks", status: "skipped-current", path: destination };
|
|
21575
|
+
}
|
|
21576
|
+
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
21577
|
+
fs24.unlinkSync(destination);
|
|
21578
|
+
} else if (artifactClass === "unmanaged-conflict" && !args.onConflict()) {
|
|
21579
|
+
return { component: "hooks", status: "conflict", path: destination };
|
|
21580
|
+
} else if (artifactClass === "managed-symlink") {
|
|
21581
|
+
fs24.unlinkSync(destination);
|
|
21582
|
+
}
|
|
21583
|
+
ensureDir(path22.dirname(destination));
|
|
21584
|
+
createRelativeSymlink(source, destination, "dir");
|
|
21585
|
+
if (args.manifest) {
|
|
21586
|
+
addArtifactToManifest(args.manifest, {
|
|
21587
|
+
relativePath: SHARED_HOOK_SCRIPTS_KEY,
|
|
21588
|
+
hash: `dir:${source}`,
|
|
21589
|
+
origin: "tangyr-managed"
|
|
21590
|
+
});
|
|
21591
|
+
}
|
|
21592
|
+
return { component: "hooks", status: "success", path: destination };
|
|
21593
|
+
}
|
|
21594
|
+
function isSymlinkTo(linkPath, source) {
|
|
21595
|
+
try {
|
|
21596
|
+
return fs24.realpathSync(linkPath) === fs24.realpathSync(source);
|
|
21597
|
+
} catch {
|
|
21598
|
+
return false;
|
|
21599
|
+
}
|
|
21600
|
+
}
|
|
21601
|
+
|
|
21602
|
+
// src/core/remove.ts
|
|
21603
|
+
import fs25 from "fs";
|
|
21496
21604
|
function removeManagedPath(managedPath) {
|
|
21497
21605
|
let stat;
|
|
21498
21606
|
try {
|
|
21499
|
-
stat =
|
|
21607
|
+
stat = fs25.lstatSync(managedPath);
|
|
21500
21608
|
} catch {
|
|
21501
21609
|
return;
|
|
21502
21610
|
}
|
|
21503
21611
|
if (stat.isSymbolicLink() || stat.isFile()) {
|
|
21504
|
-
|
|
21612
|
+
fs25.unlinkSync(managedPath);
|
|
21505
21613
|
return;
|
|
21506
21614
|
}
|
|
21507
21615
|
if (stat.isDirectory()) {
|
|
21508
|
-
|
|
21616
|
+
fs25.rmSync(managedPath, { recursive: true, force: true });
|
|
21509
21617
|
}
|
|
21510
21618
|
}
|
|
21511
21619
|
|
|
21512
21620
|
// src/commands/uninstall.ts
|
|
21621
|
+
var SHARED_ARTIFACT_TOOL = SHARED_HOOK_SCRIPTS_KEY.split("/")[0];
|
|
21513
21622
|
var codexManagedMcpStart = "# tangyr: managed mcp start";
|
|
21514
21623
|
var codexManagedMcpEnd = "# tangyr: managed mcp end";
|
|
21515
21624
|
var legacyClaudeSharedPermission = "Read(~/.agents/**)";
|
|
@@ -21549,8 +21658,9 @@ async function runUninstallCommand(options, logger) {
|
|
|
21549
21658
|
process.exit(1);
|
|
21550
21659
|
}
|
|
21551
21660
|
const selectedTools = resolveSelectedTools(options.tools, manifest, runtime);
|
|
21661
|
+
const fullUninstall = isFullToolUninstall(manifest, selectedTools);
|
|
21552
21662
|
const manifestArtifacts = manifest.artifacts.filter(
|
|
21553
|
-
(file) => shouldRemoveManifestFile(file.relativePath, selectedTools)
|
|
21663
|
+
(file) => shouldRemoveManifestFile(file.relativePath, selectedTools, fullUninstall)
|
|
21554
21664
|
);
|
|
21555
21665
|
const kitArtifacts = runtime ? resolveKitManagedArtifacts(
|
|
21556
21666
|
runtime,
|
|
@@ -21613,7 +21723,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21613
21723
|
runtime
|
|
21614
21724
|
);
|
|
21615
21725
|
for (const actualPath of paths) {
|
|
21616
|
-
if (actualPath && (
|
|
21726
|
+
if (actualPath && (fs26.existsSync(actualPath) || isSymlink(actualPath))) {
|
|
21617
21727
|
removeManagedPath(actualPath);
|
|
21618
21728
|
logger.verbose(` removed: ${actualPath}`);
|
|
21619
21729
|
removedCount++;
|
|
@@ -21627,7 +21737,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21627
21737
|
scope,
|
|
21628
21738
|
runtime
|
|
21629
21739
|
);
|
|
21630
|
-
if (actualPath && (
|
|
21740
|
+
if (actualPath && (fs26.existsSync(actualPath) || isSymlink(actualPath))) {
|
|
21631
21741
|
removeManagedPath(actualPath);
|
|
21632
21742
|
logger.verbose(` removed: ${actualPath}`);
|
|
21633
21743
|
removedCount++;
|
|
@@ -21655,27 +21765,30 @@ async function runUninstallCommand(options, logger) {
|
|
|
21655
21765
|
);
|
|
21656
21766
|
}
|
|
21657
21767
|
}
|
|
21658
|
-
const fullUninstall = isFullToolUninstall(manifest, selectedTools);
|
|
21659
21768
|
if (fullUninstall) {
|
|
21660
21769
|
for (const backup of manifest.backups) {
|
|
21661
21770
|
restoreBackup(backup, logger);
|
|
21662
21771
|
}
|
|
21663
|
-
const manifestPath =
|
|
21664
|
-
if (
|
|
21665
|
-
|
|
21772
|
+
const manifestPath = path23.join(scopePath, "manifest.json");
|
|
21773
|
+
if (fs26.existsSync(manifestPath)) {
|
|
21774
|
+
fs26.unlinkSync(manifestPath);
|
|
21666
21775
|
logger.verbose(` removed manifest: ${manifestPath}`);
|
|
21667
21776
|
}
|
|
21668
21777
|
try {
|
|
21669
|
-
const remaining =
|
|
21778
|
+
const remaining = fs26.readdirSync(scopePath);
|
|
21670
21779
|
if (remaining.length === 0) {
|
|
21671
|
-
|
|
21780
|
+
fs26.rmdirSync(scopePath);
|
|
21672
21781
|
logger.verbose(` removed empty scope directory: ${scopePath}`);
|
|
21673
21782
|
}
|
|
21674
21783
|
} catch {
|
|
21675
21784
|
}
|
|
21676
21785
|
} else if (manifestWasPresent) {
|
|
21677
21786
|
manifest.artifacts = manifest.artifacts.filter(
|
|
21678
|
-
(file) => !shouldRemoveManifestFile(
|
|
21787
|
+
(file) => !shouldRemoveManifestFile(
|
|
21788
|
+
file.relativePath,
|
|
21789
|
+
selectedTools,
|
|
21790
|
+
fullUninstall
|
|
21791
|
+
)
|
|
21679
21792
|
);
|
|
21680
21793
|
manifest.tools = manifest.tools.filter((tool) => !selectedTools.has(tool));
|
|
21681
21794
|
writeManifest(scopePath, manifest);
|
|
@@ -21694,6 +21807,12 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21694
21807
|
const [tool, ...rest] = parts;
|
|
21695
21808
|
const component = rest.join("/");
|
|
21696
21809
|
const projectRoot = scope === "project" ? process.cwd() : void 0;
|
|
21810
|
+
if (tool === SHARED_ARTIFACT_TOOL) {
|
|
21811
|
+
if (component === "hook_scripts") {
|
|
21812
|
+
return resolveSharedHookScriptsPath(runtime, scope, projectRoot);
|
|
21813
|
+
}
|
|
21814
|
+
return null;
|
|
21815
|
+
}
|
|
21697
21816
|
if (tool === "claude-code") {
|
|
21698
21817
|
const claudePaths = resolveClaudeCodePaths(runtime, scope, projectRoot);
|
|
21699
21818
|
if (!claudePaths) {
|
|
@@ -21708,7 +21827,7 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21708
21827
|
if (!slotPath) {
|
|
21709
21828
|
return null;
|
|
21710
21829
|
}
|
|
21711
|
-
return subPath ?
|
|
21830
|
+
return subPath ? path23.join(slotPath, subPath) : slotPath;
|
|
21712
21831
|
}
|
|
21713
21832
|
if (tool === "copilot") {
|
|
21714
21833
|
const copilotPaths = resolveCopilotPaths(runtime, scope, projectRoot);
|
|
@@ -21716,20 +21835,23 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21716
21835
|
return copilotPaths.skills;
|
|
21717
21836
|
}
|
|
21718
21837
|
if (component.startsWith("agents/")) {
|
|
21719
|
-
return
|
|
21838
|
+
return path23.join(copilotPaths.agents, component.slice("agents/".length));
|
|
21720
21839
|
}
|
|
21721
21840
|
if (component.startsWith("prompts/")) {
|
|
21722
|
-
return
|
|
21841
|
+
return path23.join(
|
|
21723
21842
|
copilotPaths.prompts,
|
|
21724
21843
|
component.slice("prompts/".length)
|
|
21725
21844
|
);
|
|
21726
21845
|
}
|
|
21727
21846
|
if (component.startsWith("hooks/")) {
|
|
21728
|
-
return
|
|
21847
|
+
return path23.join(copilotPaths.hooks, component.slice("hooks/".length));
|
|
21729
21848
|
}
|
|
21730
|
-
if (component ===
|
|
21849
|
+
if (component === path23.basename(copilotPaths.mcpSharedFile)) {
|
|
21731
21850
|
return copilotPaths.mcpSharedFile;
|
|
21732
21851
|
}
|
|
21852
|
+
if (copilotPaths.instructions !== null && component === path23.basename(copilotPaths.instructions)) {
|
|
21853
|
+
return copilotPaths.instructions;
|
|
21854
|
+
}
|
|
21733
21855
|
return null;
|
|
21734
21856
|
}
|
|
21735
21857
|
if (tool === "codex") {
|
|
@@ -21741,15 +21863,15 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21741
21863
|
return codexPaths.skills;
|
|
21742
21864
|
}
|
|
21743
21865
|
if (component.startsWith("agents/")) {
|
|
21744
|
-
return
|
|
21866
|
+
return path23.join(codexPaths.agents, component.slice("agents/".length));
|
|
21745
21867
|
}
|
|
21746
21868
|
if (component.startsWith("rules/")) {
|
|
21747
|
-
return
|
|
21869
|
+
return path23.join(codexPaths.rules, component.slice("rules/".length));
|
|
21748
21870
|
}
|
|
21749
|
-
if (component ===
|
|
21871
|
+
if (component === path23.basename(codexPaths.hooksSharedFile)) {
|
|
21750
21872
|
return codexPaths.hooksSharedFile;
|
|
21751
21873
|
}
|
|
21752
|
-
if (component ===
|
|
21874
|
+
if (component === path23.basename(codexPaths.mcpSharedFile)) {
|
|
21753
21875
|
return codexPaths.mcpSharedFile;
|
|
21754
21876
|
}
|
|
21755
21877
|
return null;
|
|
@@ -21766,15 +21888,15 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21766
21888
|
return opencodePaths.skillsShared;
|
|
21767
21889
|
}
|
|
21768
21890
|
if (component.startsWith("agents/")) {
|
|
21769
|
-
return
|
|
21891
|
+
return path23.join(opencodePaths.agents, component.slice("agents/".length));
|
|
21770
21892
|
}
|
|
21771
21893
|
if (component.startsWith("commands/")) {
|
|
21772
|
-
return
|
|
21894
|
+
return path23.join(
|
|
21773
21895
|
opencodePaths.commands,
|
|
21774
21896
|
component.slice("commands/".length)
|
|
21775
21897
|
);
|
|
21776
21898
|
}
|
|
21777
|
-
if (component ===
|
|
21899
|
+
if (component === path23.basename(opencodePaths.configDoc)) {
|
|
21778
21900
|
return opencodePaths.configDoc;
|
|
21779
21901
|
}
|
|
21780
21902
|
return null;
|
|
@@ -21800,13 +21922,13 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21800
21922
|
return cursorPaths.permissionsFile;
|
|
21801
21923
|
}
|
|
21802
21924
|
if (component.startsWith("agents/")) {
|
|
21803
|
-
return
|
|
21925
|
+
return path23.join(cursorPaths.agents, component.slice("agents/".length));
|
|
21804
21926
|
}
|
|
21805
21927
|
if (component.startsWith("rules/")) {
|
|
21806
|
-
return
|
|
21928
|
+
return path23.join(cursorPaths.rules, component.slice("rules/".length));
|
|
21807
21929
|
}
|
|
21808
21930
|
if (component.startsWith("skills/")) {
|
|
21809
|
-
return
|
|
21931
|
+
return path23.join(cursorPaths.skills, component.slice("skills/".length));
|
|
21810
21932
|
}
|
|
21811
21933
|
return null;
|
|
21812
21934
|
}
|
|
@@ -21822,10 +21944,10 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21822
21944
|
return clinePaths.mcpFile;
|
|
21823
21945
|
}
|
|
21824
21946
|
if (component.startsWith("rules/")) {
|
|
21825
|
-
return
|
|
21947
|
+
return path23.join(clinePaths.rules, component.slice("rules/".length));
|
|
21826
21948
|
}
|
|
21827
21949
|
if (component.startsWith("workflows/")) {
|
|
21828
|
-
return
|
|
21950
|
+
return path23.join(
|
|
21829
21951
|
clinePaths.workflows,
|
|
21830
21952
|
component.slice("workflows/".length)
|
|
21831
21953
|
);
|
|
@@ -21859,22 +21981,22 @@ function resolveClaudeCodePaths(runtime, scope, projectRoot) {
|
|
|
21859
21981
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21860
21982
|
if (scope === "global") {
|
|
21861
21983
|
return {
|
|
21862
|
-
instructions:
|
|
21863
|
-
agents:
|
|
21864
|
-
skills:
|
|
21865
|
-
commands:
|
|
21866
|
-
rules:
|
|
21867
|
-
output_styles:
|
|
21984
|
+
instructions: path23.join(home, ".claude", "CLAUDE.md"),
|
|
21985
|
+
agents: path23.join(home, ".claude", "agents"),
|
|
21986
|
+
skills: path23.join(home, ".claude", "skills"),
|
|
21987
|
+
commands: path23.join(home, ".claude", "commands"),
|
|
21988
|
+
rules: path23.join(home, ".claude", "rules"),
|
|
21989
|
+
output_styles: path23.join(home, ".claude", "output-styles")
|
|
21868
21990
|
};
|
|
21869
21991
|
}
|
|
21870
21992
|
const root = projectRoot ?? process.cwd();
|
|
21871
21993
|
return {
|
|
21872
|
-
instructions:
|
|
21873
|
-
agents:
|
|
21874
|
-
skills:
|
|
21875
|
-
commands:
|
|
21876
|
-
rules:
|
|
21877
|
-
output_styles:
|
|
21994
|
+
instructions: path23.join(root, "CLAUDE.md"),
|
|
21995
|
+
agents: path23.join(root, ".claude", "agents"),
|
|
21996
|
+
skills: path23.join(root, ".claude", "skills"),
|
|
21997
|
+
commands: path23.join(root, ".claude", "commands"),
|
|
21998
|
+
rules: path23.join(root, ".claude", "rules"),
|
|
21999
|
+
output_styles: path23.join(root, ".claude", "output-styles")
|
|
21878
22000
|
};
|
|
21879
22001
|
}
|
|
21880
22002
|
function resolveClaudeRootsForUninstall(manifest, runtime) {
|
|
@@ -21893,12 +22015,12 @@ function resolveClaudeRootsForUninstall(manifest, runtime) {
|
|
|
21893
22015
|
projectRoot: void 0,
|
|
21894
22016
|
mappings: mappings.platformPaths
|
|
21895
22017
|
})["claude-code"];
|
|
21896
|
-
return [
|
|
22018
|
+
return [path23.dirname(profile.agents)];
|
|
21897
22019
|
} catch {
|
|
21898
22020
|
}
|
|
21899
22021
|
}
|
|
21900
22022
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21901
|
-
return [
|
|
22023
|
+
return [path23.resolve(expandHome(`${home}/.claude`))];
|
|
21902
22024
|
}
|
|
21903
22025
|
function resolveAllClaudeRoots(manifest, runtime, claudeConfigDirs) {
|
|
21904
22026
|
const home = process.env.HOME ?? process.env.USERPROFILE;
|
|
@@ -21910,13 +22032,13 @@ function resolveAllClaudeRoots(manifest, runtime, claudeConfigDirs) {
|
|
|
21910
22032
|
env: process.env.TANGYR_CLAUDE_CONFIG_DIRS,
|
|
21911
22033
|
config: runtime.config.claudeCodeGlobalPaths
|
|
21912
22034
|
})
|
|
21913
|
-
].map((root) =>
|
|
22035
|
+
].map((root) => path23.resolve(root))
|
|
21914
22036
|
);
|
|
21915
|
-
if (home &&
|
|
22037
|
+
if (home && fs26.existsSync(home)) {
|
|
21916
22038
|
try {
|
|
21917
|
-
for (const entry of
|
|
22039
|
+
for (const entry of fs26.readdirSync(home, { withFileTypes: true })) {
|
|
21918
22040
|
if (entry.isDirectory() && entry.name.startsWith(".claude-")) {
|
|
21919
|
-
roots.add(
|
|
22041
|
+
roots.add(path23.resolve(home, entry.name));
|
|
21920
22042
|
}
|
|
21921
22043
|
}
|
|
21922
22044
|
} catch {
|
|
@@ -21935,13 +22057,13 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
|
|
|
21935
22057
|
const rootsToResolve = isShared ? [claudeRoots[0]] : claudeRoots;
|
|
21936
22058
|
if (!runtime) {
|
|
21937
22059
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21938
|
-
const defaultRoot =
|
|
22060
|
+
const defaultRoot = path23.resolve(expandHome(`${home}/.claude`));
|
|
21939
22061
|
return rootsToResolve.flatMap((root) => {
|
|
21940
22062
|
const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
|
|
21941
22063
|
if (!hardcoded) {
|
|
21942
22064
|
return [];
|
|
21943
22065
|
}
|
|
21944
|
-
return [subPath ?
|
|
22066
|
+
return [subPath ? path23.join(hardcoded, subPath) : hardcoded];
|
|
21945
22067
|
});
|
|
21946
22068
|
}
|
|
21947
22069
|
try {
|
|
@@ -21960,17 +22082,17 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
|
|
|
21960
22082
|
if (!slotPath) {
|
|
21961
22083
|
return [];
|
|
21962
22084
|
}
|
|
21963
|
-
return [subPath ?
|
|
22085
|
+
return [subPath ? path23.join(slotPath, subPath) : slotPath];
|
|
21964
22086
|
});
|
|
21965
22087
|
} catch {
|
|
21966
22088
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21967
|
-
const defaultRoot =
|
|
22089
|
+
const defaultRoot = path23.resolve(expandHome(`${home}/.claude`));
|
|
21968
22090
|
return rootsToResolve.flatMap((root) => {
|
|
21969
22091
|
const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
|
|
21970
22092
|
if (!hardcoded) {
|
|
21971
22093
|
return [];
|
|
21972
22094
|
}
|
|
21973
|
-
return [subPath ?
|
|
22095
|
+
return [subPath ? path23.join(hardcoded, subPath) : hardcoded];
|
|
21974
22096
|
});
|
|
21975
22097
|
}
|
|
21976
22098
|
}
|
|
@@ -21993,9 +22115,9 @@ function resolveHardcodedClaudeSlot(root, defaultRoot, slotName) {
|
|
|
21993
22115
|
return null;
|
|
21994
22116
|
}
|
|
21995
22117
|
if (root === defaultRoot) {
|
|
21996
|
-
return
|
|
22118
|
+
return path23.join(root, relative);
|
|
21997
22119
|
}
|
|
21998
|
-
return
|
|
22120
|
+
return path23.join(root, relative);
|
|
21999
22121
|
}
|
|
22000
22122
|
function resolveRuntimeIfAvailable(options, logger) {
|
|
22001
22123
|
try {
|
|
@@ -22024,8 +22146,11 @@ function resolveSelectedTools(rawTools, manifest, runtime) {
|
|
|
22024
22146
|
}
|
|
22025
22147
|
return selectedTools;
|
|
22026
22148
|
}
|
|
22027
|
-
function shouldRemoveManifestFile(relativePath, selectedTools) {
|
|
22149
|
+
function shouldRemoveManifestFile(relativePath, selectedTools, isFullUninstall) {
|
|
22028
22150
|
const tool = relativePath.split("/")[0];
|
|
22151
|
+
if (tool === SHARED_ARTIFACT_TOOL) {
|
|
22152
|
+
return isFullUninstall;
|
|
22153
|
+
}
|
|
22029
22154
|
return selectedTools.has(tool);
|
|
22030
22155
|
}
|
|
22031
22156
|
function isFullToolUninstall(manifest, selectedTools) {
|
|
@@ -22041,7 +22166,7 @@ function addCompiledGlobPlans(artifacts, pattern, expectedTarget, component) {
|
|
|
22041
22166
|
for (const artifactPath of ts(pattern).sort()) {
|
|
22042
22167
|
let marker = null;
|
|
22043
22168
|
try {
|
|
22044
|
-
marker = extractProvenanceMarker(
|
|
22169
|
+
marker = extractProvenanceMarker(fs26.readFileSync(artifactPath, "utf8"));
|
|
22045
22170
|
} catch {
|
|
22046
22171
|
continue;
|
|
22047
22172
|
}
|
|
@@ -22061,12 +22186,12 @@ function addCompiledGlobPlans(artifacts, pattern, expectedTarget, component) {
|
|
|
22061
22186
|
function addManagedSymlinkChildren(artifacts, directory, runtime, component) {
|
|
22062
22187
|
let entries;
|
|
22063
22188
|
try {
|
|
22064
|
-
entries =
|
|
22189
|
+
entries = fs26.readdirSync(directory, { withFileTypes: true });
|
|
22065
22190
|
} catch {
|
|
22066
22191
|
return;
|
|
22067
22192
|
}
|
|
22068
22193
|
for (const entry of entries) {
|
|
22069
|
-
const artifactPath =
|
|
22194
|
+
const artifactPath = path23.join(directory, entry.name);
|
|
22070
22195
|
const artifactClass = classifyArtifact(
|
|
22071
22196
|
artifactPath,
|
|
22072
22197
|
runtime.config,
|
|
@@ -22105,8 +22230,8 @@ function collectStringValuesByKey(value, keyName, values) {
|
|
|
22105
22230
|
}
|
|
22106
22231
|
function addLegacyOperatingGuideCopies(artifacts, claudeRoot) {
|
|
22107
22232
|
for (const artifactPath of [
|
|
22108
|
-
...ts(
|
|
22109
|
-
...ts(
|
|
22233
|
+
...ts(path23.join(claudeRoot, "CLAUDE.md.bak.*")),
|
|
22234
|
+
...ts(path23.join(claudeRoot, "AGENTS.md.bak.*"))
|
|
22110
22235
|
].sort()) {
|
|
22111
22236
|
artifacts.push({
|
|
22112
22237
|
component: "claude-code legacy operating guide backup",
|
|
@@ -22160,7 +22285,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22160
22285
|
for (const skill of runtime.kitInfo.components.skills.declared) {
|
|
22161
22286
|
artifacts.push({
|
|
22162
22287
|
component: "claude-code skill",
|
|
22163
|
-
path:
|
|
22288
|
+
path: path23.join(profile.skills, skill),
|
|
22164
22289
|
kind: "direct"
|
|
22165
22290
|
});
|
|
22166
22291
|
}
|
|
@@ -22179,7 +22304,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22179
22304
|
if (isFullToolUninstall(manifest, selectedTools)) {
|
|
22180
22305
|
addLegacyOperatingGuideCopies(
|
|
22181
22306
|
artifacts,
|
|
22182
|
-
|
|
22307
|
+
path23.dirname(profile.instructions)
|
|
22183
22308
|
);
|
|
22184
22309
|
}
|
|
22185
22310
|
}
|
|
@@ -22202,20 +22327,20 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22202
22327
|
if (selectedTools.has("copilot")) {
|
|
22203
22328
|
addCompiledGlobPlans(
|
|
22204
22329
|
artifacts,
|
|
22205
|
-
|
|
22330
|
+
path23.join(copilotPaths.agents, "*.agent.md"),
|
|
22206
22331
|
"copilot",
|
|
22207
22332
|
"copilot agent residue"
|
|
22208
22333
|
);
|
|
22209
22334
|
addCompiledGlobPlans(
|
|
22210
22335
|
artifacts,
|
|
22211
|
-
|
|
22336
|
+
path23.join(copilotPaths.prompts, "*.prompt.md"),
|
|
22212
22337
|
"copilot",
|
|
22213
22338
|
"copilot prompt residue"
|
|
22214
22339
|
);
|
|
22215
22340
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
22216
22341
|
artifacts.push({
|
|
22217
22342
|
component: "copilot agent",
|
|
22218
|
-
path:
|
|
22343
|
+
path: path23.join(copilotPaths.agents, `${agentEntry}.agent.md`),
|
|
22219
22344
|
kind: "compiled",
|
|
22220
22345
|
expectedTarget: "copilot",
|
|
22221
22346
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -22224,7 +22349,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22224
22349
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
22225
22350
|
artifacts.push({
|
|
22226
22351
|
component: "copilot prompt",
|
|
22227
|
-
path:
|
|
22352
|
+
path: path23.join(copilotPaths.prompts, `${commandEntry}.prompt.md`),
|
|
22228
22353
|
kind: "compiled",
|
|
22229
22354
|
expectedTarget: "copilot",
|
|
22230
22355
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -22240,13 +22365,13 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22240
22365
|
artifacts.push(
|
|
22241
22366
|
{
|
|
22242
22367
|
component: "copilot hooks",
|
|
22243
|
-
path:
|
|
22368
|
+
path: path23.join(copilotPaths.hooks, "tangyr-managed.json"),
|
|
22244
22369
|
kind: "managed-json",
|
|
22245
22370
|
expectedTarget: "copilot"
|
|
22246
22371
|
},
|
|
22247
22372
|
{
|
|
22248
22373
|
component: "copilot legacy hooks",
|
|
22249
|
-
path:
|
|
22374
|
+
path: path23.join(copilotPaths.hooks, "proteus-managed.json"),
|
|
22250
22375
|
kind: "managed-json",
|
|
22251
22376
|
expectedTarget: "copilot"
|
|
22252
22377
|
}
|
|
@@ -22255,7 +22380,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22255
22380
|
if (hooksSourceExists(runtime.sourceRoot, runtime.config)) {
|
|
22256
22381
|
artifacts.push({
|
|
22257
22382
|
component: "copilot hooks",
|
|
22258
|
-
path:
|
|
22383
|
+
path: path23.join(copilotPaths.hooks, "tangyr-managed.json"),
|
|
22259
22384
|
kind: "compiled",
|
|
22260
22385
|
expectedTarget: "copilot",
|
|
22261
22386
|
expectedSource: hooksSource
|
|
@@ -22266,7 +22391,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22266
22391
|
runtime.config
|
|
22267
22392
|
);
|
|
22268
22393
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
22269
|
-
if (
|
|
22394
|
+
if (fs26.existsSync(mcpSourcePath)) {
|
|
22270
22395
|
artifacts.push({
|
|
22271
22396
|
component: "copilot mcp",
|
|
22272
22397
|
path: copilotPaths.mcpSharedFile,
|
|
@@ -22285,13 +22410,13 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22285
22410
|
);
|
|
22286
22411
|
addCompiledGlobPlans(
|
|
22287
22412
|
artifacts,
|
|
22288
|
-
|
|
22413
|
+
path23.join(codexPaths.agents, "*.toml"),
|
|
22289
22414
|
"codex",
|
|
22290
22415
|
"codex agent residue"
|
|
22291
22416
|
);
|
|
22292
22417
|
addCompiledGlobPlans(
|
|
22293
22418
|
artifacts,
|
|
22294
|
-
|
|
22419
|
+
path23.join(codexPaths.rules, "*.rules"),
|
|
22295
22420
|
"codex",
|
|
22296
22421
|
"codex rule residue"
|
|
22297
22422
|
);
|
|
@@ -22305,7 +22430,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22305
22430
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
22306
22431
|
artifacts.push({
|
|
22307
22432
|
component: "codex agent",
|
|
22308
|
-
path:
|
|
22433
|
+
path: path23.join(codexPaths.agents, `${agentEntry}.toml`),
|
|
22309
22434
|
kind: "compiled",
|
|
22310
22435
|
expectedTarget: "codex",
|
|
22311
22436
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -22314,7 +22439,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22314
22439
|
for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
|
|
22315
22440
|
artifacts.push({
|
|
22316
22441
|
component: "codex rule",
|
|
22317
|
-
path:
|
|
22442
|
+
path: path23.join(codexPaths.rules, `${ruleEntry}.rules`),
|
|
22318
22443
|
kind: "compiled",
|
|
22319
22444
|
expectedTarget: "codex",
|
|
22320
22445
|
expectedSource: `rules/${ruleEntry}.md`
|
|
@@ -22341,7 +22466,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22341
22466
|
runtime.config
|
|
22342
22467
|
);
|
|
22343
22468
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
22344
|
-
if (
|
|
22469
|
+
if (fs26.existsSync(mcpSourcePath)) {
|
|
22345
22470
|
artifacts.push({
|
|
22346
22471
|
component: "codex mcp",
|
|
22347
22472
|
path: codexPaths.mcpSharedFile,
|
|
@@ -22366,13 +22491,13 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22366
22491
|
);
|
|
22367
22492
|
addCompiledGlobPlans(
|
|
22368
22493
|
artifacts,
|
|
22369
|
-
|
|
22494
|
+
path23.join(opencodePaths.agents, "*.md"),
|
|
22370
22495
|
"opencode",
|
|
22371
22496
|
"opencode agent residue"
|
|
22372
22497
|
);
|
|
22373
22498
|
addCompiledGlobPlans(
|
|
22374
22499
|
artifacts,
|
|
22375
|
-
|
|
22500
|
+
path23.join(opencodePaths.commands, "*.md"),
|
|
22376
22501
|
"opencode",
|
|
22377
22502
|
"opencode command residue"
|
|
22378
22503
|
);
|
|
@@ -22391,7 +22516,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22391
22516
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
22392
22517
|
artifacts.push({
|
|
22393
22518
|
component: "opencode agent",
|
|
22394
|
-
path:
|
|
22519
|
+
path: path23.join(opencodePaths.agents, `${agentEntry}.md`),
|
|
22395
22520
|
kind: "compiled",
|
|
22396
22521
|
expectedTarget: "opencode",
|
|
22397
22522
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -22400,7 +22525,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22400
22525
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
22401
22526
|
artifacts.push({
|
|
22402
22527
|
component: "opencode command",
|
|
22403
|
-
path:
|
|
22528
|
+
path: path23.join(opencodePaths.commands, `${commandEntry}.md`),
|
|
22404
22529
|
kind: "compiled",
|
|
22405
22530
|
expectedTarget: "opencode",
|
|
22406
22531
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -22418,7 +22543,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22418
22543
|
runtime.config
|
|
22419
22544
|
);
|
|
22420
22545
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
22421
|
-
if (
|
|
22546
|
+
if (fs26.existsSync(mcpSourcePath)) {
|
|
22422
22547
|
artifacts.push({
|
|
22423
22548
|
component: "opencode config",
|
|
22424
22549
|
path: opencodePaths.configDoc,
|
|
@@ -22455,19 +22580,19 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22455
22580
|
);
|
|
22456
22581
|
addCompiledGlobPlans(
|
|
22457
22582
|
artifacts,
|
|
22458
|
-
|
|
22583
|
+
path23.join(cursorPaths.agents, "*.md"),
|
|
22459
22584
|
"cursor",
|
|
22460
22585
|
"cursor agent residue"
|
|
22461
22586
|
);
|
|
22462
22587
|
addCompiledGlobPlans(
|
|
22463
22588
|
artifacts,
|
|
22464
|
-
|
|
22589
|
+
path23.join(cursorPaths.rules, "*.mdc"),
|
|
22465
22590
|
"cursor",
|
|
22466
22591
|
"cursor rule residue"
|
|
22467
22592
|
);
|
|
22468
22593
|
addCompiledGlobPlans(
|
|
22469
22594
|
artifacts,
|
|
22470
|
-
|
|
22595
|
+
path23.join(cursorPaths.skills, "*", "SKILL.md"),
|
|
22471
22596
|
"cursor",
|
|
22472
22597
|
"cursor command residue"
|
|
22473
22598
|
);
|
|
@@ -22481,7 +22606,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22481
22606
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
22482
22607
|
artifacts.push({
|
|
22483
22608
|
component: "cursor agent",
|
|
22484
|
-
path:
|
|
22609
|
+
path: path23.join(cursorPaths.agents, `${agentEntry}.md`),
|
|
22485
22610
|
kind: "compiled",
|
|
22486
22611
|
expectedTarget: "cursor",
|
|
22487
22612
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -22499,7 +22624,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22499
22624
|
runtime.config
|
|
22500
22625
|
);
|
|
22501
22626
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
22502
|
-
if (
|
|
22627
|
+
if (fs26.existsSync(mcpSourcePath)) {
|
|
22503
22628
|
artifacts.push({
|
|
22504
22629
|
component: "cursor mcp",
|
|
22505
22630
|
path: cursorPaths.mcpFile,
|
|
@@ -22518,13 +22643,13 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22518
22643
|
);
|
|
22519
22644
|
addCompiledGlobPlans(
|
|
22520
22645
|
artifacts,
|
|
22521
|
-
|
|
22646
|
+
path23.join(clinePaths.rules, "*.md"),
|
|
22522
22647
|
"cline",
|
|
22523
22648
|
"cline rule residue"
|
|
22524
22649
|
);
|
|
22525
22650
|
addCompiledGlobPlans(
|
|
22526
22651
|
artifacts,
|
|
22527
|
-
|
|
22652
|
+
path23.join(clinePaths.workflows, "*.md"),
|
|
22528
22653
|
"cline",
|
|
22529
22654
|
"cline workflow residue"
|
|
22530
22655
|
);
|
|
@@ -22552,7 +22677,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22552
22677
|
for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
|
|
22553
22678
|
artifacts.push({
|
|
22554
22679
|
component: "cline rule",
|
|
22555
|
-
path:
|
|
22680
|
+
path: path23.join(clinePaths.rules, `${ruleEntry}.md`),
|
|
22556
22681
|
kind: "compiled",
|
|
22557
22682
|
expectedTarget: "cline",
|
|
22558
22683
|
expectedSource: `rules/${ruleEntry}.md`
|
|
@@ -22561,7 +22686,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22561
22686
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
22562
22687
|
artifacts.push({
|
|
22563
22688
|
component: "cline workflow",
|
|
22564
|
-
path:
|
|
22689
|
+
path: path23.join(clinePaths.workflows, `${commandEntry}.md`),
|
|
22565
22690
|
kind: "compiled",
|
|
22566
22691
|
expectedTarget: "cline",
|
|
22567
22692
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -22579,7 +22704,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22579
22704
|
runtime.config
|
|
22580
22705
|
);
|
|
22581
22706
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
22582
|
-
if (
|
|
22707
|
+
if (fs26.existsSync(mcpSourcePath)) {
|
|
22583
22708
|
artifacts.push({
|
|
22584
22709
|
component: "cline mcp",
|
|
22585
22710
|
path: clinePaths.mcpFile,
|
|
@@ -22603,8 +22728,9 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
|
|
|
22603
22728
|
return dedupeArtifacts(artifacts);
|
|
22604
22729
|
}
|
|
22605
22730
|
function addRecordedManifestPlans(artifacts, manifest, selectedTools, runtime) {
|
|
22731
|
+
const fullUninstall = isFullToolUninstall(manifest, selectedTools);
|
|
22606
22732
|
for (const file of manifest.artifacts) {
|
|
22607
|
-
if (file.origin !== "tangyr-managed" || !shouldRemoveManifestFile(file.relativePath, selectedTools)) {
|
|
22733
|
+
if (file.origin !== "tangyr-managed" || !shouldRemoveManifestFile(file.relativePath, selectedTools, fullUninstall)) {
|
|
22608
22734
|
continue;
|
|
22609
22735
|
}
|
|
22610
22736
|
const artifactPath = resolveManifestKeyToPath(
|
|
@@ -22661,12 +22787,12 @@ function isKitManagedArtifact(artifact, runtime) {
|
|
|
22661
22787
|
return artifactClass === "managed-symlink" || artifactClass === "managed-stale" || artifactClass === "managed-compiled";
|
|
22662
22788
|
}
|
|
22663
22789
|
if (artifact.kind === "compiled") {
|
|
22664
|
-
if (!
|
|
22790
|
+
if (!fs26.existsSync(artifact.path)) {
|
|
22665
22791
|
return false;
|
|
22666
22792
|
}
|
|
22667
22793
|
try {
|
|
22668
22794
|
const marker = extractProvenanceMarker(
|
|
22669
|
-
|
|
22795
|
+
fs26.readFileSync(artifact.path, "utf8")
|
|
22670
22796
|
);
|
|
22671
22797
|
return marker?.target === artifact.expectedTarget && marker?.source === artifact.expectedSource;
|
|
22672
22798
|
} catch {
|
|
@@ -22674,7 +22800,7 @@ function isKitManagedArtifact(artifact, runtime) {
|
|
|
22674
22800
|
}
|
|
22675
22801
|
}
|
|
22676
22802
|
if (artifact.kind === "recorded") {
|
|
22677
|
-
return
|
|
22803
|
+
return fs26.existsSync(artifact.path) || isSymlink(artifact.path);
|
|
22678
22804
|
}
|
|
22679
22805
|
if (artifact.kind === "kit-pointer") {
|
|
22680
22806
|
return isKitPointer(artifact);
|
|
@@ -22683,11 +22809,11 @@ function isKitManagedArtifact(artifact, runtime) {
|
|
|
22683
22809
|
return isLegacyOperatingGuideCopy(artifact.path);
|
|
22684
22810
|
}
|
|
22685
22811
|
if (artifact.kind === "codex-mcp") {
|
|
22686
|
-
if (!
|
|
22812
|
+
if (!fs26.existsSync(artifact.path)) {
|
|
22687
22813
|
return false;
|
|
22688
22814
|
}
|
|
22689
22815
|
const section = readManagedTomlSection(
|
|
22690
|
-
|
|
22816
|
+
fs26.readFileSync(artifact.path, "utf8")
|
|
22691
22817
|
);
|
|
22692
22818
|
const marker = section ? extractProvenanceMarker(section) : null;
|
|
22693
22819
|
return marker?.target === artifact.expectedTarget && marker?.source === artifact.expectedSource;
|
|
@@ -22713,16 +22839,16 @@ function isKitManagedArtifact(artifact, runtime) {
|
|
|
22713
22839
|
return hasManagedCodexHooks(parsed, artifact.expectedSource);
|
|
22714
22840
|
}
|
|
22715
22841
|
function removeManagedCompiledArtifact(artifact, logger) {
|
|
22716
|
-
if (!
|
|
22842
|
+
if (!fs26.existsSync(artifact.path)) {
|
|
22717
22843
|
return false;
|
|
22718
22844
|
}
|
|
22719
22845
|
const marker = extractProvenanceMarker(
|
|
22720
|
-
|
|
22846
|
+
fs26.readFileSync(artifact.path, "utf8")
|
|
22721
22847
|
);
|
|
22722
22848
|
if (marker?.target !== artifact.expectedTarget || marker?.source !== artifact.expectedSource) {
|
|
22723
22849
|
return false;
|
|
22724
22850
|
}
|
|
22725
|
-
|
|
22851
|
+
fs26.rmSync(artifact.path, { force: true });
|
|
22726
22852
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22727
22853
|
return true;
|
|
22728
22854
|
}
|
|
@@ -22793,12 +22919,12 @@ function removeManagedJsonArtifact(artifact, logger) {
|
|
|
22793
22919
|
if (!parsed || !hasManagedRootMetadata(parsed, artifact.expectedTarget)) {
|
|
22794
22920
|
return false;
|
|
22795
22921
|
}
|
|
22796
|
-
|
|
22922
|
+
fs26.rmSync(artifact.path, { force: true });
|
|
22797
22923
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22798
22924
|
return true;
|
|
22799
22925
|
}
|
|
22800
22926
|
function removeRecordedArtifact(artifact, logger) {
|
|
22801
|
-
if (!
|
|
22927
|
+
if (!fs26.existsSync(artifact.path) && !isSymlink(artifact.path)) {
|
|
22802
22928
|
return false;
|
|
22803
22929
|
}
|
|
22804
22930
|
removeManagedPath(artifact.path);
|
|
@@ -22806,10 +22932,10 @@ function removeRecordedArtifact(artifact, logger) {
|
|
|
22806
22932
|
return true;
|
|
22807
22933
|
}
|
|
22808
22934
|
function removeExactManagedFile(artifact, logger) {
|
|
22809
|
-
if (!
|
|
22935
|
+
if (!fs26.existsSync(artifact.path)) {
|
|
22810
22936
|
return false;
|
|
22811
22937
|
}
|
|
22812
|
-
|
|
22938
|
+
fs26.rmSync(artifact.path, { force: true });
|
|
22813
22939
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22814
22940
|
return true;
|
|
22815
22941
|
}
|
|
@@ -22843,10 +22969,10 @@ function removeManagedCodexHooksArtifact(artifact, logger) {
|
|
|
22843
22969
|
return true;
|
|
22844
22970
|
}
|
|
22845
22971
|
function removeManagedCodexMcpArtifact(artifact, logger) {
|
|
22846
|
-
if (!
|
|
22972
|
+
if (!fs26.existsSync(artifact.path)) {
|
|
22847
22973
|
return false;
|
|
22848
22974
|
}
|
|
22849
|
-
const content =
|
|
22975
|
+
const content = fs26.readFileSync(artifact.path, "utf8");
|
|
22850
22976
|
const managedSection = readManagedTomlSection(content);
|
|
22851
22977
|
if (!managedSection) {
|
|
22852
22978
|
return false;
|
|
@@ -22861,9 +22987,9 @@ function removeManagedCodexMcpArtifact(artifact, logger) {
|
|
|
22861
22987
|
codexManagedMcpEnd
|
|
22862
22988
|
);
|
|
22863
22989
|
if (cleaned.trim().length === 0) {
|
|
22864
|
-
|
|
22990
|
+
fs26.rmSync(artifact.path, { force: true });
|
|
22865
22991
|
} else {
|
|
22866
|
-
|
|
22992
|
+
fs26.writeFileSync(artifact.path, cleaned);
|
|
22867
22993
|
}
|
|
22868
22994
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22869
22995
|
return true;
|
|
@@ -22886,12 +23012,26 @@ function resolveCopilotPaths(runtime, scope = "global", projectRoot) {
|
|
|
22886
23012
|
prompts: profile.prompts,
|
|
22887
23013
|
skills: profile.skills,
|
|
22888
23014
|
hooks: profile.hooks,
|
|
22889
|
-
mcpSharedFile: profile.mcp_shared_file
|
|
23015
|
+
mcpSharedFile: profile.mcp_shared_file,
|
|
23016
|
+
instructions: profile.instructions
|
|
22890
23017
|
};
|
|
22891
23018
|
} catch {
|
|
22892
23019
|
}
|
|
22893
23020
|
}
|
|
23021
|
+
if (scope === "project") {
|
|
23022
|
+
const root = projectRoot ?? process.cwd();
|
|
23023
|
+
return {
|
|
23024
|
+
instructions: path23.join(root, ".github", "copilot-instructions.md"),
|
|
23025
|
+
agents: path23.join(root, ".github", "agents"),
|
|
23026
|
+
prompts: path23.join(root, ".github", "prompts"),
|
|
23027
|
+
skills: path23.join(root, ".github", "skills"),
|
|
23028
|
+
hooks: path23.join(root, ".github", "hooks"),
|
|
23029
|
+
mcpSharedFile: path23.join(root, ".vscode", "mcp.json")
|
|
23030
|
+
};
|
|
23031
|
+
}
|
|
22894
23032
|
return {
|
|
23033
|
+
// null, because Copilot's instructions surface exists only in a project.
|
|
23034
|
+
instructions: null,
|
|
22895
23035
|
agents: resolveTargetPath("$VSCODE_USER_DATA/agents"),
|
|
22896
23036
|
prompts: resolveTargetPath("$VSCODE_USER_DATA/prompts"),
|
|
22897
23037
|
skills: resolveTargetPath("~/.copilot/skills"),
|
|
@@ -22923,6 +23063,17 @@ function resolveCodexPaths(runtime, scope = "global", projectRoot) {
|
|
|
22923
23063
|
} catch {
|
|
22924
23064
|
}
|
|
22925
23065
|
}
|
|
23066
|
+
if (scope === "project") {
|
|
23067
|
+
const root = projectRoot ?? process.cwd();
|
|
23068
|
+
return {
|
|
23069
|
+
instructions: path23.join(root, "AGENTS.md"),
|
|
23070
|
+
agents: path23.join(root, ".codex", "agents"),
|
|
23071
|
+
rules: path23.join(root, ".codex", "rules"),
|
|
23072
|
+
skills: path23.join(root, ".codex", "skills"),
|
|
23073
|
+
hooksSharedFile: path23.join(root, ".codex", "hooks.json"),
|
|
23074
|
+
mcpSharedFile: path23.join(root, ".codex", "config.toml")
|
|
23075
|
+
};
|
|
23076
|
+
}
|
|
22926
23077
|
return {
|
|
22927
23078
|
instructions: resolveTargetPath("~/.codex/AGENTS.md"),
|
|
22928
23079
|
agents: resolveTargetPath("~/.codex/agents"),
|
|
@@ -22932,6 +23083,27 @@ function resolveCodexPaths(runtime, scope = "global", projectRoot) {
|
|
|
22932
23083
|
mcpSharedFile: resolveTargetPath("~/.codex/config.toml")
|
|
22933
23084
|
};
|
|
22934
23085
|
}
|
|
23086
|
+
function resolveSharedHookScriptsPath(runtime, scope, projectRoot) {
|
|
23087
|
+
if (runtime) {
|
|
23088
|
+
try {
|
|
23089
|
+
const mappings = loadMappings(
|
|
23090
|
+
runtime.sourceRoot,
|
|
23091
|
+
runtime.config,
|
|
23092
|
+
runtime.configDir
|
|
23093
|
+
);
|
|
23094
|
+
return resolveTargetPaths({
|
|
23095
|
+
scope,
|
|
23096
|
+
projectRoot,
|
|
23097
|
+
mappings: mappings.platformPaths
|
|
23098
|
+
}).codex.hook_scripts;
|
|
23099
|
+
} catch {
|
|
23100
|
+
}
|
|
23101
|
+
}
|
|
23102
|
+
if (scope === "project") {
|
|
23103
|
+
return path23.join(projectRoot ?? process.cwd(), ".agents", "hooks");
|
|
23104
|
+
}
|
|
23105
|
+
return resolveTargetPath("~/.agents/hooks");
|
|
23106
|
+
}
|
|
22935
23107
|
function resolveOpenCodePaths(runtime, scope = "global", projectRoot) {
|
|
22936
23108
|
if (runtime) {
|
|
22937
23109
|
try {
|
|
@@ -23056,11 +23228,11 @@ function managedArtifactPlanPriority(artifact) {
|
|
|
23056
23228
|
return 2;
|
|
23057
23229
|
}
|
|
23058
23230
|
function readJsonObject2(filePath) {
|
|
23059
|
-
if (!
|
|
23231
|
+
if (!fs26.existsSync(filePath)) {
|
|
23060
23232
|
return null;
|
|
23061
23233
|
}
|
|
23062
23234
|
try {
|
|
23063
|
-
const parsed = JSON.parse(
|
|
23235
|
+
const parsed = JSON.parse(fs26.readFileSync(filePath, "utf8"));
|
|
23064
23236
|
return isRecord(parsed) ? parsed : null;
|
|
23065
23237
|
} catch {
|
|
23066
23238
|
return null;
|
|
@@ -23108,22 +23280,22 @@ function removeLegacyClaudeSharedPermission(value) {
|
|
|
23108
23280
|
return Object.keys(cleaned).length === 0 ? void 0 : cleaned;
|
|
23109
23281
|
}
|
|
23110
23282
|
function isKitPointer(artifact) {
|
|
23111
|
-
if (!artifact.expectedPath || !
|
|
23283
|
+
if (!artifact.expectedPath || !fs26.existsSync(artifact.path)) {
|
|
23112
23284
|
return false;
|
|
23113
23285
|
}
|
|
23114
23286
|
try {
|
|
23115
|
-
const recordedPath =
|
|
23116
|
-
return recordedPath.length > 0 &&
|
|
23287
|
+
const recordedPath = fs26.readFileSync(artifact.path, "utf8").trim();
|
|
23288
|
+
return recordedPath.length > 0 && path23.resolve(recordedPath) === path23.resolve(artifact.expectedPath);
|
|
23117
23289
|
} catch {
|
|
23118
23290
|
return false;
|
|
23119
23291
|
}
|
|
23120
23292
|
}
|
|
23121
23293
|
function isLegacyOperatingGuideCopy(filePath) {
|
|
23122
|
-
if (!
|
|
23294
|
+
if (!fs26.existsSync(filePath)) {
|
|
23123
23295
|
return false;
|
|
23124
23296
|
}
|
|
23125
23297
|
try {
|
|
23126
|
-
return
|
|
23298
|
+
return fs26.readFileSync(filePath, "utf8").startsWith(legacyOperatingGuideSignature);
|
|
23127
23299
|
} catch {
|
|
23128
23300
|
return false;
|
|
23129
23301
|
}
|
|
@@ -23145,10 +23317,10 @@ function matchesManagedMetadata(metadata, artifact) {
|
|
|
23145
23317
|
}
|
|
23146
23318
|
function writeJsonOrRemove(filePath, parsed) {
|
|
23147
23319
|
if (isEmptyJsonValue(parsed)) {
|
|
23148
|
-
|
|
23320
|
+
fs26.rmSync(filePath, { force: true });
|
|
23149
23321
|
return;
|
|
23150
23322
|
}
|
|
23151
|
-
|
|
23323
|
+
fs26.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
23152
23324
|
`);
|
|
23153
23325
|
}
|
|
23154
23326
|
function isEmptyJsonValue(value) {
|
|
@@ -23274,20 +23446,20 @@ function removeDelimitedManagedSection(content, startMarker, endMarker) {
|
|
|
23274
23446
|
return `${content.slice(0, start)}${content.slice(removalEnd)}`;
|
|
23275
23447
|
}
|
|
23276
23448
|
function restoreBackup(backup, logger) {
|
|
23277
|
-
if (!
|
|
23449
|
+
if (!fs26.existsSync(backup.backupLocation)) {
|
|
23278
23450
|
logger.warn(` backup not found: ${backup.backupLocation}`);
|
|
23279
23451
|
return;
|
|
23280
23452
|
}
|
|
23281
|
-
const destDir =
|
|
23282
|
-
|
|
23283
|
-
|
|
23453
|
+
const destDir = path23.dirname(backup.originalPath);
|
|
23454
|
+
fs26.mkdirSync(destDir, { recursive: true });
|
|
23455
|
+
fs26.renameSync(backup.backupLocation, backup.originalPath);
|
|
23284
23456
|
logger.verbose(
|
|
23285
23457
|
` restored: ${backup.backupLocation} \u2192 ${backup.originalPath}`
|
|
23286
23458
|
);
|
|
23287
23459
|
}
|
|
23288
23460
|
function isSymlink(p) {
|
|
23289
23461
|
try {
|
|
23290
|
-
return
|
|
23462
|
+
return fs26.lstatSync(p).isSymbolicLink();
|
|
23291
23463
|
} catch {
|
|
23292
23464
|
return false;
|
|
23293
23465
|
}
|
|
@@ -23361,7 +23533,7 @@ function cleanupClaudeCode(config, sourceRoot, configDir, logger, scope) {
|
|
|
23361
23533
|
)) {
|
|
23362
23534
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
23363
23535
|
if (artifactClass === "managed-symlink" || artifactClass === "managed-compiled" || artifactClass === "managed-stale") {
|
|
23364
|
-
|
|
23536
|
+
fs27.rmSync(artifact.path, { recursive: true, force: true });
|
|
23365
23537
|
logger.info(`${artifact.component}: removed ${artifact.path}`);
|
|
23366
23538
|
}
|
|
23367
23539
|
}
|
|
@@ -23417,7 +23589,7 @@ function cleanupCopilot(config, sourceRoot, configDir, logger) {
|
|
|
23417
23589
|
logger
|
|
23418
23590
|
);
|
|
23419
23591
|
removeManagedJsonFile(
|
|
23420
|
-
|
|
23592
|
+
path24.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
23421
23593
|
"_tangyr",
|
|
23422
23594
|
logger
|
|
23423
23595
|
);
|
|
@@ -23574,40 +23746,40 @@ function removeManagedValueByKey2(value, keyName, keyValue) {
|
|
|
23574
23746
|
function removeManagedDirectPath(artifactPath, config, sourceRoot, component, logger) {
|
|
23575
23747
|
const artifactClass = classifyArtifact(artifactPath, config, sourceRoot);
|
|
23576
23748
|
if (artifactClass === "managed-symlink" || artifactClass === "managed-compiled" || artifactClass === "managed-stale") {
|
|
23577
|
-
|
|
23749
|
+
fs27.rmSync(artifactPath, { recursive: true, force: true });
|
|
23578
23750
|
logger.info(`${component}: removed ${artifactPath}`);
|
|
23579
23751
|
}
|
|
23580
23752
|
}
|
|
23581
23753
|
function removeManagedCompiledFiles(dir, pattern, expectedTarget, logger) {
|
|
23582
|
-
for (const filePath of ts(
|
|
23754
|
+
for (const filePath of ts(path24.join(dir, pattern)).sort()) {
|
|
23583
23755
|
removeManagedCompiledFile(filePath, expectedTarget, logger);
|
|
23584
23756
|
}
|
|
23585
23757
|
}
|
|
23586
23758
|
function removeManagedCompiledFile(filePath, expectedTarget, logger) {
|
|
23587
|
-
if (!
|
|
23759
|
+
if (!fs27.existsSync(filePath)) {
|
|
23588
23760
|
return;
|
|
23589
23761
|
}
|
|
23590
|
-
const marker = extractProvenanceMarker(
|
|
23762
|
+
const marker = extractProvenanceMarker(fs27.readFileSync(filePath, "utf8"));
|
|
23591
23763
|
if (marker?.target === expectedTarget) {
|
|
23592
|
-
|
|
23764
|
+
fs27.rmSync(filePath, { force: true });
|
|
23593
23765
|
logger.info(`removed ${filePath}`);
|
|
23594
23766
|
}
|
|
23595
23767
|
}
|
|
23596
23768
|
function removeManagedJsonFile(filePath, markerKey, logger) {
|
|
23597
|
-
if (!
|
|
23769
|
+
if (!fs27.existsSync(filePath)) {
|
|
23598
23770
|
return;
|
|
23599
23771
|
}
|
|
23600
23772
|
const parsed = readJsonObject(filePath);
|
|
23601
23773
|
if (isRecord(parsed[markerKey])) {
|
|
23602
|
-
|
|
23774
|
+
fs27.rmSync(filePath, { force: true });
|
|
23603
23775
|
logger.info(`removed ${filePath}`);
|
|
23604
23776
|
}
|
|
23605
23777
|
}
|
|
23606
23778
|
function removeCodexManagedTomlSection(filePath, logger) {
|
|
23607
|
-
if (!
|
|
23779
|
+
if (!fs27.existsSync(filePath)) {
|
|
23608
23780
|
return;
|
|
23609
23781
|
}
|
|
23610
|
-
const content =
|
|
23782
|
+
const content = fs27.readFileSync(filePath, "utf8");
|
|
23611
23783
|
const next = removeDelimitedManagedSection2(
|
|
23612
23784
|
content,
|
|
23613
23785
|
codexManagedMcpStart2,
|
|
@@ -23616,7 +23788,7 @@ function removeCodexManagedTomlSection(filePath, logger) {
|
|
|
23616
23788
|
if (next === content) {
|
|
23617
23789
|
return;
|
|
23618
23790
|
}
|
|
23619
|
-
|
|
23791
|
+
fs27.writeFileSync(filePath, next);
|
|
23620
23792
|
logger.info(`mcp: removed managed section from ${filePath}`);
|
|
23621
23793
|
}
|
|
23622
23794
|
function removeDelimitedManagedSection2(content, startMarker, endMarker) {
|
|
@@ -23688,9 +23860,9 @@ function toVerbosity(value) {
|
|
|
23688
23860
|
}
|
|
23689
23861
|
|
|
23690
23862
|
// src/commands/detect.ts
|
|
23691
|
-
import
|
|
23863
|
+
import fs28 from "fs";
|
|
23692
23864
|
import os5 from "os";
|
|
23693
|
-
import
|
|
23865
|
+
import path25 from "path";
|
|
23694
23866
|
import { spawnSync } from "child_process";
|
|
23695
23867
|
var copilotEditorCommands = [
|
|
23696
23868
|
"code",
|
|
@@ -23729,7 +23901,7 @@ var bundledCursorExecutablePathsByPlatform = {
|
|
|
23729
23901
|
};
|
|
23730
23902
|
function detectTargets(logger, dependencies = {}) {
|
|
23731
23903
|
const spawnSyncImpl = dependencies.spawnSyncImpl ?? defaultSpawnSync;
|
|
23732
|
-
const pathExists = dependencies.pathExists ??
|
|
23904
|
+
const pathExists = dependencies.pathExists ?? fs28.existsSync;
|
|
23733
23905
|
const homeDirectory = dependencies.homeDirectory ?? os5.homedir();
|
|
23734
23906
|
const platform = dependencies.platform ?? process.platform;
|
|
23735
23907
|
const locator = platform === "win32" ? "where.exe" : "which";
|
|
@@ -23764,8 +23936,8 @@ function detectsCopilot(logger, dependencies = {}) {
|
|
|
23764
23936
|
return detectCopilot(logger, dependencies);
|
|
23765
23937
|
}
|
|
23766
23938
|
function detectCopilot(logger, dependencies = {}) {
|
|
23767
|
-
const pathExists = dependencies.pathExists ??
|
|
23768
|
-
const readFile = dependencies.readFile ?? ((filePath) =>
|
|
23939
|
+
const pathExists = dependencies.pathExists ?? fs28.existsSync;
|
|
23940
|
+
const readFile = dependencies.readFile ?? ((filePath) => fs28.readFileSync(filePath, "utf8"));
|
|
23769
23941
|
const platform = dependencies.platform ?? process.platform;
|
|
23770
23942
|
if (detectEditorExtension(
|
|
23771
23943
|
"Copilot",
|
|
@@ -23793,8 +23965,8 @@ function detectCopilot(logger, dependencies = {}) {
|
|
|
23793
23965
|
}
|
|
23794
23966
|
function detectEditorExtension(label, matchesExtension, logger, dependencies = {}) {
|
|
23795
23967
|
const spawnSyncImpl = dependencies.spawnSyncImpl ?? defaultSpawnSync;
|
|
23796
|
-
const pathExists = dependencies.pathExists ??
|
|
23797
|
-
const readDirectory = dependencies.readDirectory ??
|
|
23968
|
+
const pathExists = dependencies.pathExists ?? fs28.existsSync;
|
|
23969
|
+
const readDirectory = dependencies.readDirectory ?? fs28.readdirSync;
|
|
23798
23970
|
const homeDirectory = dependencies.homeDirectory ?? os5.homedir();
|
|
23799
23971
|
const platform = dependencies.platform ?? process.platform;
|
|
23800
23972
|
const commandCandidates = [
|
|
@@ -23822,7 +23994,7 @@ function detectEditorExtension(label, matchesExtension, logger, dependencies = {
|
|
|
23822
23994
|
}
|
|
23823
23995
|
}
|
|
23824
23996
|
for (const relativeDirectory of copilotExtensionDirectories) {
|
|
23825
|
-
const extensionDirectory =
|
|
23997
|
+
const extensionDirectory = path25.join(homeDirectory, relativeDirectory);
|
|
23826
23998
|
if (!pathExists(extensionDirectory)) {
|
|
23827
23999
|
continue;
|
|
23828
24000
|
}
|
|
@@ -23845,7 +24017,7 @@ function cursorExecutablePaths(platform, homeDirectory) {
|
|
|
23845
24017
|
}
|
|
23846
24018
|
return [
|
|
23847
24019
|
...systemPaths,
|
|
23848
|
-
|
|
24020
|
+
path25.join(
|
|
23849
24021
|
homeDirectory,
|
|
23850
24022
|
"Applications/Cursor.app/Contents/Resources/app/bin/cursor"
|
|
23851
24023
|
)
|
|
@@ -23905,86 +24077,25 @@ function logDetectionError(attemptedCommand, error, logger) {
|
|
|
23905
24077
|
}
|
|
23906
24078
|
|
|
23907
24079
|
// src/commands/doctor.ts
|
|
23908
|
-
import
|
|
23909
|
-
import
|
|
23910
|
-
|
|
23911
|
-
// src/utils/fs.ts
|
|
23912
|
-
import fs27 from "fs";
|
|
23913
|
-
import path24 from "path";
|
|
23914
|
-
function ensureDir(dirPath) {
|
|
23915
|
-
fs27.mkdirSync(dirPath, { recursive: true });
|
|
23916
|
-
}
|
|
23917
|
-
function createRelativeSymlink(source, destination, type, options) {
|
|
23918
|
-
const absoluteSource = path24.resolve(source);
|
|
23919
|
-
const relative = path24.relative(
|
|
23920
|
-
realPathOrInput(path24.dirname(destination)),
|
|
23921
|
-
absoluteSource
|
|
23922
|
-
);
|
|
23923
|
-
if (process.platform === "win32" && type === "dir") {
|
|
23924
|
-
fs27.symlinkSync(absoluteSource, destination, "junction");
|
|
23925
|
-
return;
|
|
23926
|
-
}
|
|
23927
|
-
if (process.platform === "win32" && type === "file") {
|
|
23928
|
-
try {
|
|
23929
|
-
fs27.symlinkSync(relative, destination, "file");
|
|
23930
|
-
} catch (error) {
|
|
23931
|
-
if (!hasErrorCode(error, "EPERM")) {
|
|
23932
|
-
throw error;
|
|
23933
|
-
}
|
|
23934
|
-
if (!options?.provenanceMarker) {
|
|
23935
|
-
throw new Error(
|
|
23936
|
-
`${destination}: file symlink unavailable on Windows and no provenance marker was provided.`
|
|
23937
|
-
);
|
|
23938
|
-
}
|
|
23939
|
-
createManagedCopy(
|
|
23940
|
-
source,
|
|
23941
|
-
destination,
|
|
23942
|
-
options.provenanceMarker,
|
|
23943
|
-
options.logger
|
|
23944
|
-
);
|
|
23945
|
-
options.logger?.warn(
|
|
23946
|
-
`${destination}: file symlink unavailable on Windows \u2014 using managed copy with provenance metadata (behavioral contract C-09)`
|
|
23947
|
-
);
|
|
23948
|
-
}
|
|
23949
|
-
return;
|
|
23950
|
-
}
|
|
23951
|
-
fs27.symlinkSync(relative, destination, type);
|
|
23952
|
-
}
|
|
23953
|
-
function createManagedCopy(source, destination, provenanceMarker, _logger) {
|
|
23954
|
-
ensureDir(path24.dirname(destination));
|
|
23955
|
-
const content = fs27.readFileSync(source, "utf8");
|
|
23956
|
-
fs27.writeFileSync(destination, `${provenanceMarker}
|
|
23957
|
-
${content}`);
|
|
23958
|
-
}
|
|
23959
|
-
function hasErrorCode(error, expectedCode) {
|
|
23960
|
-
return typeof error === "object" && error !== null && "code" in error && error.code === expectedCode;
|
|
23961
|
-
}
|
|
23962
|
-
function realPathOrInput(filePath) {
|
|
23963
|
-
try {
|
|
23964
|
-
return fs27.realpathSync(filePath);
|
|
23965
|
-
} catch {
|
|
23966
|
-
return filePath;
|
|
23967
|
-
}
|
|
23968
|
-
}
|
|
23969
|
-
|
|
23970
|
-
// src/commands/doctor.ts
|
|
24080
|
+
import fs29 from "fs";
|
|
24081
|
+
import path26 from "path";
|
|
23971
24082
|
function runDoctorCommand(options, logger) {
|
|
23972
24083
|
const { config, configDir, configPath, sourceRoot } = resolveRuntime(
|
|
23973
24084
|
options,
|
|
23974
24085
|
import.meta.url
|
|
23975
24086
|
);
|
|
23976
24087
|
const findings = [];
|
|
23977
|
-
if (!
|
|
24088
|
+
if (!fs29.existsSync(configPath)) {
|
|
23978
24089
|
findings.push(`${configPath}: missing`);
|
|
23979
24090
|
}
|
|
23980
|
-
const hooksJsonPath =
|
|
24091
|
+
const hooksJsonPath = path26.join(
|
|
23981
24092
|
sourceRoot,
|
|
23982
24093
|
config.source.hooks,
|
|
23983
24094
|
"hooks.json"
|
|
23984
24095
|
);
|
|
23985
|
-
if (
|
|
24096
|
+
if (fs29.existsSync(hooksJsonPath)) {
|
|
23986
24097
|
try {
|
|
23987
|
-
JSON.parse(
|
|
24098
|
+
JSON.parse(fs29.readFileSync(hooksJsonPath, "utf8"));
|
|
23988
24099
|
} catch (err) {
|
|
23989
24100
|
findings.push(
|
|
23990
24101
|
`hooks/hooks.json: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -24049,19 +24160,19 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
|
|
|
24049
24160
|
projectRoot
|
|
24050
24161
|
)) {
|
|
24051
24162
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
24052
|
-
const sourcePath = artifact.sourceKey ?
|
|
24163
|
+
const sourcePath = artifact.sourceKey ? path26.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
|
|
24053
24164
|
if (artifactClass === "managed-stale") {
|
|
24054
24165
|
findings.push(
|
|
24055
24166
|
`${artifact.component}: managed stale artifact at ${artifact.path}`
|
|
24056
24167
|
);
|
|
24057
24168
|
if (options.fix && sourcePath && isOurStaleSymlink(
|
|
24058
24169
|
artifact.path,
|
|
24059
|
-
/* @__PURE__ */ new Set([
|
|
24170
|
+
/* @__PURE__ */ new Set([path26.resolve(artifact.path)]),
|
|
24060
24171
|
config
|
|
24061
24172
|
)) {
|
|
24062
|
-
|
|
24063
|
-
ensureDir(
|
|
24064
|
-
const symlinkType =
|
|
24173
|
+
fs29.unlinkSync(artifact.path);
|
|
24174
|
+
ensureDir(path26.dirname(artifact.path));
|
|
24175
|
+
const symlinkType = fs29.statSync(sourcePath).isDirectory() ? "dir" : "file";
|
|
24065
24176
|
createRelativeSymlink(sourcePath, artifact.path, symlinkType, {
|
|
24066
24177
|
logger,
|
|
24067
24178
|
provenanceMarker: symlinkType === "file" && artifact.sourceKey ? formatProvenanceMarker(
|
|
@@ -24074,8 +24185,8 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
|
|
|
24074
24185
|
logger.info(`${artifact.component}: recreated managed symlink`);
|
|
24075
24186
|
}
|
|
24076
24187
|
}
|
|
24077
|
-
if (options.fix && !
|
|
24078
|
-
ensureDir(
|
|
24188
|
+
if (options.fix && !fs29.existsSync(path26.dirname(artifact.path))) {
|
|
24189
|
+
ensureDir(path26.dirname(artifact.path));
|
|
24079
24190
|
}
|
|
24080
24191
|
checkParentWritablePath(artifact.path, artifact.component, findings);
|
|
24081
24192
|
}
|
|
@@ -24090,7 +24201,7 @@ function checkCopilot(config, sourceRoot, configDir, findings) {
|
|
|
24090
24201
|
continue;
|
|
24091
24202
|
}
|
|
24092
24203
|
const label = `copilot: ${rawPath}`;
|
|
24093
|
-
if (key.endsWith("_shared_file") ||
|
|
24204
|
+
if (key.endsWith("_shared_file") || path26.extname(rawPath).length > 0) {
|
|
24094
24205
|
checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
|
|
24095
24206
|
continue;
|
|
24096
24207
|
}
|
|
@@ -24110,7 +24221,7 @@ function checkCodex(config, sourceRoot, configDir, findings, logger) {
|
|
|
24110
24221
|
continue;
|
|
24111
24222
|
}
|
|
24112
24223
|
const label = `codex: ${rawPath}`;
|
|
24113
|
-
if (key.endsWith("_shared_file") ||
|
|
24224
|
+
if (key.endsWith("_shared_file") || path26.extname(rawPath).length > 0) {
|
|
24114
24225
|
checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
|
|
24115
24226
|
continue;
|
|
24116
24227
|
}
|
|
@@ -24127,33 +24238,33 @@ function resolveHooksScriptPath(config, sourceRoot, configDir) {
|
|
|
24127
24238
|
scope: "global",
|
|
24128
24239
|
mappings: mappings.platformPaths
|
|
24129
24240
|
});
|
|
24130
|
-
return
|
|
24241
|
+
return path26.join(profile["claude-code"].hooks, "scripts");
|
|
24131
24242
|
} catch {
|
|
24132
24243
|
return resolveTargetPath("~/.agents/hooks/scripts");
|
|
24133
24244
|
}
|
|
24134
24245
|
}
|
|
24135
24246
|
function checkParentWritablePath(targetPath, label, findings) {
|
|
24136
|
-
checkWritablePath(
|
|
24247
|
+
checkWritablePath(path26.dirname(targetPath), `${label} parent`, findings);
|
|
24137
24248
|
}
|
|
24138
24249
|
function checkWritablePath(checkPath, label, findings) {
|
|
24139
|
-
if (!
|
|
24250
|
+
if (!fs29.existsSync(checkPath)) {
|
|
24140
24251
|
findings.push(`${label}: path does not exist`);
|
|
24141
24252
|
return;
|
|
24142
24253
|
}
|
|
24143
24254
|
try {
|
|
24144
|
-
|
|
24255
|
+
fs29.accessSync(checkPath, fs29.constants.R_OK | fs29.constants.W_OK);
|
|
24145
24256
|
} catch {
|
|
24146
24257
|
findings.push(`${label}: path is not readable and writable`);
|
|
24147
24258
|
}
|
|
24148
24259
|
}
|
|
24149
24260
|
function walkHookScripts(dir) {
|
|
24150
|
-
if (!
|
|
24261
|
+
if (!fs29.existsSync(dir)) {
|
|
24151
24262
|
return [];
|
|
24152
24263
|
}
|
|
24153
|
-
return
|
|
24264
|
+
return fs29.readdirSync(dir).map((entry) => path26.join(dir, entry)).filter((entryPath) => fs29.statSync(entryPath).isFile());
|
|
24154
24265
|
}
|
|
24155
24266
|
function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
|
|
24156
|
-
if (!
|
|
24267
|
+
if (!fs29.existsSync(scriptRoot)) {
|
|
24157
24268
|
return;
|
|
24158
24269
|
}
|
|
24159
24270
|
if (hasSymlinkAncestor(scriptRoot, resolveTargetPath("~/.agents")) || isInside(realPathOrInput2(scriptRoot), realPathOrInput2(sourceRoot))) {
|
|
@@ -24163,49 +24274,49 @@ function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
|
|
|
24163
24274
|
return;
|
|
24164
24275
|
}
|
|
24165
24276
|
for (const scriptPath of walkHookScripts(scriptRoot)) {
|
|
24166
|
-
|
|
24277
|
+
fs29.chmodSync(scriptPath, 493);
|
|
24167
24278
|
}
|
|
24168
24279
|
}
|
|
24169
24280
|
function hasSymlinkAncestor(targetPath, stopAt) {
|
|
24170
|
-
const relative =
|
|
24171
|
-
|
|
24172
|
-
|
|
24281
|
+
const relative = path26.relative(
|
|
24282
|
+
path26.resolve(stopAt),
|
|
24283
|
+
path26.resolve(targetPath)
|
|
24173
24284
|
);
|
|
24174
|
-
if (relative.startsWith("..") ||
|
|
24285
|
+
if (relative.startsWith("..") || path26.isAbsolute(relative)) {
|
|
24175
24286
|
return false;
|
|
24176
24287
|
}
|
|
24177
|
-
return relative.split(
|
|
24178
|
-
const candidate =
|
|
24179
|
-
|
|
24288
|
+
return relative.split(path26.sep).some((_segment, index, segments) => {
|
|
24289
|
+
const candidate = path26.join(
|
|
24290
|
+
path26.resolve(stopAt),
|
|
24180
24291
|
...segments.slice(0, index + 1)
|
|
24181
24292
|
);
|
|
24182
24293
|
try {
|
|
24183
|
-
return
|
|
24294
|
+
return fs29.lstatSync(candidate).isSymbolicLink();
|
|
24184
24295
|
} catch {
|
|
24185
24296
|
return false;
|
|
24186
24297
|
}
|
|
24187
24298
|
});
|
|
24188
24299
|
}
|
|
24189
24300
|
function isInside(childPath, parentPath) {
|
|
24190
|
-
const relative =
|
|
24191
|
-
return relative.length === 0 || !relative.startsWith("..") && !
|
|
24301
|
+
const relative = path26.relative(parentPath, childPath);
|
|
24302
|
+
return relative.length === 0 || !relative.startsWith("..") && !path26.isAbsolute(relative);
|
|
24192
24303
|
}
|
|
24193
24304
|
function realPathOrInput2(filePath) {
|
|
24194
24305
|
try {
|
|
24195
|
-
return
|
|
24306
|
+
return fs29.realpathSync(filePath);
|
|
24196
24307
|
} catch {
|
|
24197
24308
|
return filePath;
|
|
24198
24309
|
}
|
|
24199
24310
|
}
|
|
24200
24311
|
|
|
24201
24312
|
// src/commands/init.ts
|
|
24202
|
-
import
|
|
24203
|
-
import
|
|
24313
|
+
import fs30 from "fs";
|
|
24314
|
+
import path27 from "path";
|
|
24204
24315
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
24205
24316
|
async function runInitCommand(_options, logger) {
|
|
24206
24317
|
const sourceRoot = await dist_default6({
|
|
24207
24318
|
message: "Canonical Tangyr kit root",
|
|
24208
|
-
default:
|
|
24319
|
+
default: path27.resolve("projects/tangyr/agent-coding")
|
|
24209
24320
|
});
|
|
24210
24321
|
const componentCount = [
|
|
24211
24322
|
"CLAUDE.md",
|
|
@@ -24215,7 +24326,7 @@ async function runInitCommand(_options, logger) {
|
|
|
24215
24326
|
"rules",
|
|
24216
24327
|
"hooks"
|
|
24217
24328
|
].filter(
|
|
24218
|
-
(relativePath) =>
|
|
24329
|
+
(relativePath) => fs30.existsSync(path27.join(sourceRoot, relativePath))
|
|
24219
24330
|
).length;
|
|
24220
24331
|
const detectedTargets = detectTargets(logger);
|
|
24221
24332
|
const enabledTargets = await dist_default4({
|
|
@@ -24235,8 +24346,8 @@ async function runInitCommand(_options, logger) {
|
|
|
24235
24346
|
value
|
|
24236
24347
|
}))
|
|
24237
24348
|
});
|
|
24238
|
-
const configPath =
|
|
24239
|
-
if (
|
|
24349
|
+
const configPath = path27.join(sourceRoot, "tangyr.config.yaml");
|
|
24350
|
+
if (fs30.existsSync(configPath)) {
|
|
24240
24351
|
const overwrite = await dist_default5({
|
|
24241
24352
|
message: `${configPath} exists. Overwrite?`,
|
|
24242
24353
|
default: false
|
|
@@ -24246,7 +24357,7 @@ async function runInitCommand(_options, logger) {
|
|
|
24246
24357
|
return;
|
|
24247
24358
|
}
|
|
24248
24359
|
}
|
|
24249
|
-
|
|
24360
|
+
fs30.writeFileSync(
|
|
24250
24361
|
configPath,
|
|
24251
24362
|
(0, import_yaml7.stringify)({
|
|
24252
24363
|
schema: 1,
|
|
@@ -24293,11 +24404,11 @@ import fs39 from "fs";
|
|
|
24293
24404
|
import path39 from "path";
|
|
24294
24405
|
|
|
24295
24406
|
// src/core/channel-state.ts
|
|
24296
|
-
import
|
|
24297
|
-
import
|
|
24407
|
+
import fs31 from "fs";
|
|
24408
|
+
import path28 from "path";
|
|
24298
24409
|
var CHANNEL_STATE_FILENAME = ".tangyr-channels.json";
|
|
24299
24410
|
function stateFilePath(cacheRoot) {
|
|
24300
|
-
return
|
|
24411
|
+
return path28.join(cacheRoot, CHANNEL_STATE_FILENAME);
|
|
24301
24412
|
}
|
|
24302
24413
|
function channelKey(kit, channel) {
|
|
24303
24414
|
return `${kit}/${channel}`;
|
|
@@ -24306,7 +24417,7 @@ function readState(cacheRoot) {
|
|
|
24306
24417
|
const filePath = stateFilePath(cacheRoot);
|
|
24307
24418
|
let raw;
|
|
24308
24419
|
try {
|
|
24309
|
-
raw =
|
|
24420
|
+
raw = fs31.readFileSync(filePath, "utf8");
|
|
24310
24421
|
} catch (err) {
|
|
24311
24422
|
if (err.code === "ENOENT") {
|
|
24312
24423
|
return { state: {} };
|
|
@@ -24353,13 +24464,13 @@ function writeChannelSequence(params) {
|
|
|
24353
24464
|
[key]: { sequence, version, seenAt: now.toISOString() }
|
|
24354
24465
|
};
|
|
24355
24466
|
const filePath = stateFilePath(cacheRoot);
|
|
24356
|
-
|
|
24467
|
+
fs31.mkdirSync(path28.dirname(filePath), { recursive: true, mode: 448 });
|
|
24357
24468
|
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
24358
|
-
|
|
24469
|
+
fs31.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
24359
24470
|
`, {
|
|
24360
24471
|
mode: 384
|
|
24361
24472
|
});
|
|
24362
|
-
|
|
24473
|
+
fs31.renameSync(tempPath, filePath);
|
|
24363
24474
|
}
|
|
24364
24475
|
function assertChannelNotRolledBack(params) {
|
|
24365
24476
|
const { originUrl, kit, channel, seen, seenVersion, incoming } = params;
|
|
@@ -24375,8 +24486,8 @@ var CHANNEL_POINTER_TYPE = "tangyr.channel-pointer.v1";
|
|
|
24375
24486
|
var DEFAULT_CHANNEL = "stable";
|
|
24376
24487
|
|
|
24377
24488
|
// src/core/materialize.ts
|
|
24378
|
-
import
|
|
24379
|
-
import
|
|
24489
|
+
import fs32 from "fs";
|
|
24490
|
+
import path29 from "path";
|
|
24380
24491
|
|
|
24381
24492
|
// src/core/integrity.ts
|
|
24382
24493
|
import crypto3 from "crypto";
|
|
@@ -24712,7 +24823,7 @@ function assertFileWithinCeiling(entryPath, byteLength) {
|
|
|
24712
24823
|
}
|
|
24713
24824
|
var WINDOWS_DRIVE_ABSOLUTE = /^[a-zA-Z]:[\\/]/u;
|
|
24714
24825
|
function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
24715
|
-
if (
|
|
24826
|
+
if (path29.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
|
|
24716
24827
|
throw new IntegrityError(
|
|
24717
24828
|
`Bundle file path "${entryPath}" is absolute \u2014 every file inside a bundle must use a relative path (REQ-INT-004).`
|
|
24718
24829
|
);
|
|
@@ -24728,13 +24839,13 @@ function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
|
24728
24839
|
`Bundle file path "${entryPath}" contains a ".." segment \u2014 directory traversal is rejected (REQ-INT-004).`
|
|
24729
24840
|
);
|
|
24730
24841
|
}
|
|
24731
|
-
const resolved =
|
|
24842
|
+
const resolved = path29.resolve(stagingDir, entryPath);
|
|
24732
24843
|
if (resolved === stagingDir) {
|
|
24733
24844
|
throw new IntegrityError(
|
|
24734
24845
|
`Bundle file path "${entryPath}" resolves to the staging directory itself \u2014 every entry must be a file inside it (REQ-INT-004).`
|
|
24735
24846
|
);
|
|
24736
24847
|
}
|
|
24737
|
-
if (!resolved.startsWith(stagingDir +
|
|
24848
|
+
if (!resolved.startsWith(stagingDir + path29.sep)) {
|
|
24738
24849
|
throw new IntegrityError(
|
|
24739
24850
|
`Bundle file path "${entryPath}" escapes the staging directory \u2014 refusing to write (REQ-INT-004).`
|
|
24740
24851
|
);
|
|
@@ -24786,10 +24897,10 @@ function verifyBundleFileHashes(bundle) {
|
|
|
24786
24897
|
function writeStagedFiles(stagingDir, decoded) {
|
|
24787
24898
|
for (const [rawPath, bytes] of decoded) {
|
|
24788
24899
|
const target = sanitizeBundleFilePath(rawPath, stagingDir);
|
|
24789
|
-
|
|
24900
|
+
fs32.mkdirSync(path29.dirname(target), { recursive: true, mode: 448 });
|
|
24790
24901
|
let existingStat;
|
|
24791
24902
|
try {
|
|
24792
|
-
existingStat =
|
|
24903
|
+
existingStat = fs32.lstatSync(target);
|
|
24793
24904
|
} catch (error) {
|
|
24794
24905
|
if (error.code !== "ENOENT") {
|
|
24795
24906
|
throw error;
|
|
@@ -24800,7 +24911,7 @@ function writeStagedFiles(stagingDir, decoded) {
|
|
|
24800
24911
|
`Refusing to write "${rawPath}" \u2014 a symbolic link already exists at the target path.`
|
|
24801
24912
|
);
|
|
24802
24913
|
}
|
|
24803
|
-
|
|
24914
|
+
fs32.writeFileSync(target, bytes, { mode: 384, flag: "wx" });
|
|
24804
24915
|
}
|
|
24805
24916
|
}
|
|
24806
24917
|
function verifyWarmCacheEntry(entryDir, reference, keys, now) {
|
|
@@ -24856,14 +24967,14 @@ async function materializeRemoteKit(params) {
|
|
|
24856
24967
|
writeStagedFiles(stagingDir, decoded);
|
|
24857
24968
|
writeBundleDocument(stagingDir, bundle);
|
|
24858
24969
|
writeCompletionMarker(stagingDir, reference);
|
|
24859
|
-
if (replace &&
|
|
24860
|
-
|
|
24970
|
+
if (replace && fs32.existsSync(entryDir)) {
|
|
24971
|
+
fs32.rmSync(entryDir, { recursive: true, force: true });
|
|
24861
24972
|
}
|
|
24862
24973
|
publishCacheEntry(stagingDir, entryDir);
|
|
24863
24974
|
return entryDir;
|
|
24864
24975
|
} catch (error) {
|
|
24865
24976
|
if (stagingDir !== void 0) {
|
|
24866
|
-
|
|
24977
|
+
fs32.rmSync(stagingDir, { recursive: true, force: true });
|
|
24867
24978
|
}
|
|
24868
24979
|
throw error;
|
|
24869
24980
|
}
|
|
@@ -25205,7 +25316,7 @@ import path33 from "path";
|
|
|
25205
25316
|
// src/compiler/agents.ts
|
|
25206
25317
|
var TOML = __toESM(require_toml(), 1);
|
|
25207
25318
|
var import_yaml8 = __toESM(require_dist(), 1);
|
|
25208
|
-
import
|
|
25319
|
+
import path30 from "path";
|
|
25209
25320
|
var writeCapabilityClasses = /* @__PURE__ */ new Set(["filesystem-write", "shell-execution"]);
|
|
25210
25321
|
var copilotToolAliasesByClass = {
|
|
25211
25322
|
delegation: "agent",
|
|
@@ -25217,7 +25328,7 @@ var copilotToolAliasesByClass = {
|
|
|
25217
25328
|
};
|
|
25218
25329
|
function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
25219
25330
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
25220
|
-
const relativeSource = `agents/${
|
|
25331
|
+
const relativeSource = `agents/${path30.basename(sourceFile)}`;
|
|
25221
25332
|
if (target === "opencode") {
|
|
25222
25333
|
return compileOpenCodeAgent(
|
|
25223
25334
|
sourceFile,
|
|
@@ -25258,7 +25369,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
25258
25369
|
mappings,
|
|
25259
25370
|
lossReport
|
|
25260
25371
|
);
|
|
25261
|
-
const overlayKey = `agents/${
|
|
25372
|
+
const overlayKey = `agents/${path30.basename(sourceFile, ".md")}.${target}.yaml`;
|
|
25262
25373
|
const targetFields = {
|
|
25263
25374
|
...translated.fields,
|
|
25264
25375
|
...extensions[overlayKey] ?? {}
|
|
@@ -25292,7 +25403,7 @@ ${TOML.stringify({
|
|
|
25292
25403
|
function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
25293
25404
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
25294
25405
|
throw new Error(
|
|
25295
|
-
`${
|
|
25406
|
+
`${path30.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
|
|
25296
25407
|
);
|
|
25297
25408
|
}
|
|
25298
25409
|
const frontmatter = {
|
|
@@ -25346,7 +25457,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
25346
25457
|
"permission",
|
|
25347
25458
|
"permission-coarsening"
|
|
25348
25459
|
),
|
|
25349
|
-
detail: `${
|
|
25460
|
+
detail: `${path30.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
|
|
25350
25461
|
}
|
|
25351
25462
|
]
|
|
25352
25463
|
});
|
|
@@ -25371,7 +25482,7 @@ ${(0, import_yaml8.stringify)(frontmatter).trim()}
|
|
|
25371
25482
|
function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
25372
25483
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
25373
25484
|
throw new Error(
|
|
25374
|
-
`${
|
|
25485
|
+
`${path30.basename(sourceFile)}: Cursor agent requires a non-empty description field`
|
|
25375
25486
|
);
|
|
25376
25487
|
}
|
|
25377
25488
|
const frontmatter = {
|
|
@@ -25408,7 +25519,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
25408
25519
|
"permission",
|
|
25409
25520
|
"permission-coarsening"
|
|
25410
25521
|
),
|
|
25411
|
-
detail: `${
|
|
25522
|
+
detail: `${path30.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
|
|
25412
25523
|
}
|
|
25413
25524
|
]
|
|
25414
25525
|
});
|
|
@@ -25427,7 +25538,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
25427
25538
|
"provider",
|
|
25428
25539
|
"provider-not-representable"
|
|
25429
25540
|
),
|
|
25430
|
-
detail: `${
|
|
25541
|
+
detail: `${path30.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
25431
25542
|
}
|
|
25432
25543
|
]
|
|
25433
25544
|
});
|
|
@@ -25459,7 +25570,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
|
|
|
25459
25570
|
"persona",
|
|
25460
25571
|
"persona-not-representable"
|
|
25461
25572
|
),
|
|
25462
|
-
detail: `${
|
|
25573
|
+
detail: `${path30.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
|
|
25463
25574
|
}
|
|
25464
25575
|
]
|
|
25465
25576
|
});
|
|
@@ -25507,7 +25618,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
25507
25618
|
field,
|
|
25508
25619
|
"model-not-representable"
|
|
25509
25620
|
),
|
|
25510
|
-
detail: `${
|
|
25621
|
+
detail: `${path30.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
|
|
25511
25622
|
});
|
|
25512
25623
|
return;
|
|
25513
25624
|
}
|
|
@@ -25525,9 +25636,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
25525
25636
|
lossReport,
|
|
25526
25637
|
target,
|
|
25527
25638
|
"agents",
|
|
25528
|
-
`agents/${
|
|
25639
|
+
`agents/${path30.basename(sourceFile)}`,
|
|
25529
25640
|
"info",
|
|
25530
|
-
`${
|
|
25641
|
+
`${path30.basename(sourceFile)}: ${field} is delivered through another managed surface.`
|
|
25531
25642
|
);
|
|
25532
25643
|
return;
|
|
25533
25644
|
}
|
|
@@ -25536,7 +25647,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
25536
25647
|
field,
|
|
25537
25648
|
action: entryType,
|
|
25538
25649
|
severity: resolveLossSeverity("agent-field", field, entryType),
|
|
25539
|
-
detail: `${
|
|
25650
|
+
detail: `${path30.basename(sourceFile)}: ${field} has no emitted field for this target.`
|
|
25540
25651
|
});
|
|
25541
25652
|
}
|
|
25542
25653
|
function mapToolsToCapabilities(value, mappings) {
|
|
@@ -25928,23 +26039,23 @@ function addHookLoss(lossReport, target, eventName, sourceLabel, severity, reaso
|
|
|
25928
26039
|
}
|
|
25929
26040
|
|
|
25930
26041
|
// src/core/hook-scripts.ts
|
|
25931
|
-
import
|
|
26042
|
+
import path31 from "path";
|
|
25932
26043
|
function hookScriptsDir(bridge, target) {
|
|
25933
26044
|
const globalBridge = resolveTargetPath("~/.agents/hooks");
|
|
25934
|
-
if (
|
|
26045
|
+
if (path31.resolve(bridge) === path31.resolve(globalBridge)) {
|
|
25935
26046
|
return { prefix: GLOBAL_HOOK_SCRIPTS_DIR, machineLocal: false };
|
|
25936
26047
|
}
|
|
25937
|
-
const relative =
|
|
25938
|
-
const insideProject = !relative.startsWith("..") && !
|
|
26048
|
+
const relative = path31.relative(process.cwd(), bridge);
|
|
26049
|
+
const insideProject = !relative.startsWith("..") && !path31.isAbsolute(relative) && relative !== "";
|
|
25939
26050
|
const variable = PROJECT_DIR_VARIABLE[target];
|
|
25940
26051
|
if (insideProject && variable) {
|
|
25941
|
-
const posix =
|
|
25942
|
-
relative.split(
|
|
26052
|
+
const posix = path31.posix.join(
|
|
26053
|
+
relative.split(path31.sep).join("/"),
|
|
25943
26054
|
"scripts"
|
|
25944
26055
|
);
|
|
25945
26056
|
return { prefix: `$${variable.slice(1)}/${posix}`, machineLocal: false };
|
|
25946
26057
|
}
|
|
25947
|
-
return { prefix:
|
|
26058
|
+
return { prefix: path31.join(bridge, "scripts"), machineLocal: true };
|
|
25948
26059
|
}
|
|
25949
26060
|
var PROJECT_DIR_VARIABLE = {
|
|
25950
26061
|
"claude-code": "$CLAUDE_PROJECT_DIR"
|
|
@@ -25953,52 +26064,6 @@ function machineLocalScriptPathNotice(target, prefix) {
|
|
|
25953
26064
|
return `The hook commands compiled for ${target} name '${prefix}', an absolute path. ${target} publishes no project-directory variable a command could use instead \u2014 measured, not assumed \u2014 and a bare relative path would resolve against whatever directory the harness runs the hook from. The compiled file is therefore correct on this machine and not on another: re-run 'tangyr sync' after cloning, and prefer keeping it out of version control.`;
|
|
25954
26065
|
}
|
|
25955
26066
|
|
|
25956
|
-
// src/adapters/hook-scripts-bridge.ts
|
|
25957
|
-
import fs32 from "fs";
|
|
25958
|
-
import path31 from "path";
|
|
25959
|
-
function syncHookScriptsBridge(args) {
|
|
25960
|
-
const { source, destination, config, sourceRoot, options, logger } = args;
|
|
25961
|
-
if (!fs32.existsSync(source)) {
|
|
25962
|
-
return {
|
|
25963
|
-
component: "hooks",
|
|
25964
|
-
status: "skipped",
|
|
25965
|
-
path: `${source}: source not configured`
|
|
25966
|
-
};
|
|
25967
|
-
}
|
|
25968
|
-
if (options.dryRun) {
|
|
25969
|
-
logger.info(`[dry-run] hooks: symlink ${source} -> ${destination}`);
|
|
25970
|
-
return { component: "hooks", status: "dry-run", path: destination };
|
|
25971
|
-
}
|
|
25972
|
-
const artifactClass = classifyArtifact(destination, config, sourceRoot);
|
|
25973
|
-
if (artifactClass === "managed-symlink" && isSymlinkTo(destination, source)) {
|
|
25974
|
-
return { component: "hooks", status: "skipped-current", path: destination };
|
|
25975
|
-
}
|
|
25976
|
-
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
25977
|
-
fs32.unlinkSync(destination);
|
|
25978
|
-
} else if (artifactClass === "unmanaged-conflict" && !args.onConflict()) {
|
|
25979
|
-
return { component: "hooks", status: "conflict", path: destination };
|
|
25980
|
-
} else if (artifactClass === "managed-symlink") {
|
|
25981
|
-
fs32.unlinkSync(destination);
|
|
25982
|
-
}
|
|
25983
|
-
ensureDir(path31.dirname(destination));
|
|
25984
|
-
createRelativeSymlink(source, destination, "dir");
|
|
25985
|
-
if (args.manifest && args.scopePath) {
|
|
25986
|
-
addArtifactToManifest(args.manifest, {
|
|
25987
|
-
relativePath: path31.relative(args.scopePath, destination),
|
|
25988
|
-
hash: `dir:${source}`,
|
|
25989
|
-
origin: "tangyr-managed"
|
|
25990
|
-
});
|
|
25991
|
-
}
|
|
25992
|
-
return { component: "hooks", status: "success", path: destination };
|
|
25993
|
-
}
|
|
25994
|
-
function isSymlinkTo(linkPath, source) {
|
|
25995
|
-
try {
|
|
25996
|
-
return fs32.realpathSync(linkPath) === fs32.realpathSync(source);
|
|
25997
|
-
} catch {
|
|
25998
|
-
return false;
|
|
25999
|
-
}
|
|
26000
|
-
}
|
|
26001
|
-
|
|
26002
26067
|
// src/compiler/mcp.ts
|
|
26003
26068
|
var TOML2 = __toESM(require_toml(), 1);
|
|
26004
26069
|
import crypto4 from "crypto";
|
|
@@ -29781,7 +29846,14 @@ function installCopilotTool(config, kitInfo, manifest, options, mappings, logger
|
|
|
29781
29846
|
manifest,
|
|
29782
29847
|
copilotScopePath
|
|
29783
29848
|
);
|
|
29784
|
-
recordInstalledArtifacts(
|
|
29849
|
+
recordInstalledArtifacts(
|
|
29850
|
+
manifest,
|
|
29851
|
+
"copilot",
|
|
29852
|
+
result.outcomes,
|
|
29853
|
+
mappings,
|
|
29854
|
+
scope,
|
|
29855
|
+
projectRoot
|
|
29856
|
+
);
|
|
29785
29857
|
return countInstalledArtifacts(result.outcomes);
|
|
29786
29858
|
}
|
|
29787
29859
|
function installCodexTool(config, kitInfo, manifest, options, mappings, logger, scope = "global", projectRoot, lossReport) {
|
|
@@ -29812,7 +29884,14 @@ function installCodexTool(config, kitInfo, manifest, options, mappings, logger,
|
|
|
29812
29884
|
manifest,
|
|
29813
29885
|
codexScopePath
|
|
29814
29886
|
);
|
|
29815
|
-
recordInstalledArtifacts(
|
|
29887
|
+
recordInstalledArtifacts(
|
|
29888
|
+
manifest,
|
|
29889
|
+
"codex",
|
|
29890
|
+
result.outcomes,
|
|
29891
|
+
mappings,
|
|
29892
|
+
scope,
|
|
29893
|
+
projectRoot
|
|
29894
|
+
);
|
|
29816
29895
|
return countInstalledArtifacts(result.outcomes);
|
|
29817
29896
|
}
|
|
29818
29897
|
function installOpenCodeTool(config, kitInfo, manifest, options, mappings, logger, scope = "global", projectRoot, lossReport) {
|
|
@@ -29974,16 +30053,16 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
29974
30053
|
throwUnrecognizedTarget(tool);
|
|
29975
30054
|
}
|
|
29976
30055
|
if (tool === "cline") {
|
|
29977
|
-
const
|
|
30056
|
+
const profile2 = resolveTargetPaths({
|
|
29978
30057
|
scope,
|
|
29979
30058
|
projectRoot,
|
|
29980
30059
|
mappings: mappings.platformPaths
|
|
29981
30060
|
}).cline;
|
|
29982
|
-
const instrFile =
|
|
29983
|
-
const rulesRoot2 = resolveTargetPath(
|
|
29984
|
-
const workflowsRoot = resolveTargetPath(
|
|
29985
|
-
const skillsRoot2 = resolveTargetPath(
|
|
29986
|
-
const mcpFile2 = resolveTargetPath(
|
|
30061
|
+
const instrFile = profile2.instructions !== null ? resolveTargetPath(profile2.instructions) : null;
|
|
30062
|
+
const rulesRoot2 = resolveTargetPath(profile2.rules);
|
|
30063
|
+
const workflowsRoot = resolveTargetPath(profile2.workflows);
|
|
30064
|
+
const skillsRoot2 = resolveTargetPath(profile2.skills);
|
|
30065
|
+
const mcpFile2 = resolveTargetPath(profile2.mcp_file);
|
|
29987
30066
|
if (instrFile !== null && outcome.path === instrFile) {
|
|
29988
30067
|
return "cline/AGENTS.md";
|
|
29989
30068
|
}
|
|
@@ -30002,19 +30081,19 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
30002
30081
|
return null;
|
|
30003
30082
|
}
|
|
30004
30083
|
if (tool === "cursor") {
|
|
30005
|
-
const
|
|
30084
|
+
const profile2 = resolveTargetPaths({
|
|
30006
30085
|
scope,
|
|
30007
30086
|
projectRoot,
|
|
30008
30087
|
mappings: mappings.platformPaths
|
|
30009
30088
|
}).cursor;
|
|
30010
|
-
const instrFile = resolveTargetPath(
|
|
30011
|
-
const agentsRoot2 = resolveTargetPath(
|
|
30012
|
-
const rulesRoot2 = resolveTargetPath(
|
|
30013
|
-
const skillsRoot2 = resolveTargetPath(
|
|
30014
|
-
const skillsSharedRoot = resolveTargetPath(
|
|
30015
|
-
const hooksFile2 = resolveTargetPath(
|
|
30016
|
-
const mcpFile2 = resolveTargetPath(
|
|
30017
|
-
const permissionsFile = resolveTargetPath(
|
|
30089
|
+
const instrFile = resolveTargetPath(profile2.instructions);
|
|
30090
|
+
const agentsRoot2 = resolveTargetPath(profile2.agents);
|
|
30091
|
+
const rulesRoot2 = resolveTargetPath(profile2.rules);
|
|
30092
|
+
const skillsRoot2 = resolveTargetPath(profile2.skills);
|
|
30093
|
+
const skillsSharedRoot = resolveTargetPath(profile2.skills_shared);
|
|
30094
|
+
const hooksFile2 = resolveTargetPath(profile2.hooks_file);
|
|
30095
|
+
const mcpFile2 = resolveTargetPath(profile2.mcp_file);
|
|
30096
|
+
const permissionsFile = resolveTargetPath(profile2.permissions_file);
|
|
30018
30097
|
if (outcome.path === instrFile) {
|
|
30019
30098
|
return "cursor/AGENTS.md";
|
|
30020
30099
|
}
|
|
@@ -30046,17 +30125,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
30046
30125
|
return null;
|
|
30047
30126
|
}
|
|
30048
30127
|
if (tool === "opencode") {
|
|
30049
|
-
const
|
|
30128
|
+
const profile2 = resolveTargetPaths({
|
|
30050
30129
|
scope,
|
|
30051
30130
|
projectRoot,
|
|
30052
30131
|
mappings: mappings.platformPaths
|
|
30053
30132
|
}).opencode;
|
|
30054
|
-
const instrFile = resolveTargetPath(
|
|
30055
|
-
const agentsRoot2 = resolveTargetPath(
|
|
30056
|
-
const commandsRoot = resolveTargetPath(
|
|
30057
|
-
const skillsRoot2 = resolveTargetPath(
|
|
30058
|
-
const skillsSharedRoot = resolveTargetPath(
|
|
30059
|
-
const configDocFile = resolveTargetPath(
|
|
30133
|
+
const instrFile = resolveTargetPath(profile2.instructions);
|
|
30134
|
+
const agentsRoot2 = resolveTargetPath(profile2.agents);
|
|
30135
|
+
const commandsRoot = resolveTargetPath(profile2.commands);
|
|
30136
|
+
const skillsRoot2 = resolveTargetPath(profile2.skills);
|
|
30137
|
+
const skillsSharedRoot = resolveTargetPath(profile2.skills_shared);
|
|
30138
|
+
const configDocFile = resolveTargetPath(profile2.config_doc);
|
|
30060
30139
|
if (outcome.path === instrFile) {
|
|
30061
30140
|
return "opencode/AGENTS.md";
|
|
30062
30141
|
}
|
|
@@ -30077,16 +30156,25 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
30077
30156
|
}
|
|
30078
30157
|
return null;
|
|
30079
30158
|
}
|
|
30080
|
-
const
|
|
30159
|
+
const profile = resolveTargetPaths({
|
|
30160
|
+
scope,
|
|
30161
|
+
projectRoot,
|
|
30162
|
+
mappings: mappings.platformPaths
|
|
30163
|
+
})[tool];
|
|
30081
30164
|
if (tool === "copilot") {
|
|
30082
|
-
const
|
|
30083
|
-
const
|
|
30084
|
-
const
|
|
30085
|
-
const
|
|
30086
|
-
const
|
|
30165
|
+
const copilot = profile;
|
|
30166
|
+
const agentsRoot2 = resolveTargetPath(copilot.agents);
|
|
30167
|
+
const promptsRoot = resolveTargetPath(copilot.prompts);
|
|
30168
|
+
const skillsRoot2 = resolveTargetPath(copilot.skills);
|
|
30169
|
+
const hooksRoot = resolveTargetPath(copilot.hooks);
|
|
30170
|
+
const mcpFile2 = resolveTargetPath(copilot.mcp_shared_file);
|
|
30171
|
+
const instructionsMirror = copilot.instructions !== null ? resolveTargetPath(copilot.instructions) : null;
|
|
30087
30172
|
if (outcome.path === skillsRoot2) {
|
|
30088
30173
|
return "copilot/skills";
|
|
30089
30174
|
}
|
|
30175
|
+
if (instructionsMirror !== null && outcome.path === instructionsMirror) {
|
|
30176
|
+
return `copilot/${path39.basename(outcome.path)}`;
|
|
30177
|
+
}
|
|
30090
30178
|
if (outcome.path.startsWith(`${agentsRoot2}${path39.sep}`)) {
|
|
30091
30179
|
return `copilot/agents/${path39.basename(outcome.path)}`;
|
|
30092
30180
|
}
|
|
@@ -30101,12 +30189,13 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
30101
30189
|
}
|
|
30102
30190
|
return null;
|
|
30103
30191
|
}
|
|
30104
|
-
const
|
|
30105
|
-
const
|
|
30106
|
-
const
|
|
30107
|
-
const
|
|
30108
|
-
const
|
|
30109
|
-
const
|
|
30192
|
+
const codex = profile;
|
|
30193
|
+
const instructionsFile = resolveTargetPath(codex.instructions);
|
|
30194
|
+
const agentsRoot = resolveTargetPath(codex.agents);
|
|
30195
|
+
const rulesRoot = resolveTargetPath(codex.rules);
|
|
30196
|
+
const skillsRoot = resolveTargetPath(codex.skills);
|
|
30197
|
+
const hooksFile = resolveTargetPath(codex.hooks_shared_file);
|
|
30198
|
+
const mcpFile = resolveTargetPath(codex.mcp_shared_file);
|
|
30110
30199
|
if (outcome.path === instructionsFile) {
|
|
30111
30200
|
return "codex/AGENTS.md";
|
|
30112
30201
|
}
|