@kaitranntt/ccs 8.8.1-dev.21 → 8.8.1-dev.22
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/auth/auth-commands.js +3 -3
- package/dist/auth/auth-commands.js.map +1 -1
- package/dist/config/schemas/auth.d.ts +2 -2
- package/dist/config/schemas/auth.d.ts.map +1 -1
- package/dist/management/instance-directory.d.ts +19 -0
- package/dist/management/instance-directory.d.ts.map +1 -1
- package/dist/management/instance-directory.js +130 -7
- package/dist/management/instance-directory.js.map +1 -1
- package/dist/management/instance-manager.d.ts +2 -5
- package/dist/management/instance-manager.d.ts.map +1 -1
- package/dist/management/instance-manager.js +26 -27
- package/dist/management/instance-manager.js.map +1 -1
- package/dist/management/shared-manager/canonical-first-file-claims.d.ts +6 -0
- package/dist/management/shared-manager/canonical-first-file-claims.d.ts.map +1 -0
- package/dist/management/shared-manager/canonical-first-file-claims.js +143 -0
- package/dist/management/shared-manager/canonical-first-file-claims.js.map +1 -0
- package/dist/management/shared-manager/canonical-first-file-reconciler.d.ts +15 -0
- package/dist/management/shared-manager/canonical-first-file-reconciler.d.ts.map +1 -0
- package/dist/management/shared-manager/canonical-first-file-reconciler.js +131 -0
- package/dist/management/shared-manager/canonical-first-file-reconciler.js.map +1 -0
- package/dist/management/shared-manager/plugin-layout-internals.d.ts +1 -1
- package/dist/management/shared-manager/plugin-layout-internals.d.ts.map +1 -1
- package/dist/management/shared-manager/plugin-layout-internals.js +25 -9
- package/dist/management/shared-manager/plugin-layout-internals.js.map +1 -1
- package/dist/management/shared-manager/shared-dir-linker.d.ts +1 -1
- package/dist/management/shared-manager/shared-dir-linker.d.ts.map +1 -1
- package/dist/management/shared-manager/shared-dir-linker.js +140 -107
- package/dist/management/shared-manager/shared-dir-linker.js.map +1 -1
- package/dist/management/shared-manager/types.d.ts +12 -1
- package/dist/management/shared-manager/types.d.ts.map +1 -1
- package/dist/management/shared-manager/types.js +12 -1
- package/dist/management/shared-manager/types.js.map +1 -1
- package/dist/types/config.d.ts +2 -2
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface CanonicalFirstRoots {
|
|
2
|
+
claudeDir: string;
|
|
3
|
+
sharedDir: string;
|
|
4
|
+
instancesDir: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Reconcile a canonical-first shared file before any seed or symlink mutation.
|
|
8
|
+
* Existing canonical content always wins. With no canonical, one unique byte
|
|
9
|
+
* variant is adopted; conflicting variants are all quarantined for recovery.
|
|
10
|
+
*/
|
|
11
|
+
export declare function reconcileCanonicalFirstFile(roots: CanonicalFirstRoots, fileName: string): void;
|
|
12
|
+
/** Preserve a later divergent copy without allowing it to replace canonical content. */
|
|
13
|
+
export declare function preserveCanonicalFirstDivergence(divergedPath: string, canonicalPath: string): boolean;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=canonical-first-file-reconciler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-first-file-reconciler.d.ts","sourceRoot":"","sources":["../../../src/management/shared-manager/canonical-first-file-reconciler.ts"],"names":[],"mappings":"AAmBA,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AA6CD;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAiD9F;AAED,wFAAwF;AACxF,wBAAgB,gCAAgC,CAC9C,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,OAAO,CAaT"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.preserveCanonicalFirstDivergence = exports.reconcileCanonicalFirstFile = void 0;
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
const path = __importStar(require("path"));
|
|
32
|
+
const ui_1 = require("../../utils/ui");
|
|
33
|
+
const profile_registry_1 = __importDefault(require("../../auth/profile-registry"));
|
|
34
|
+
const shared_resource_policy_1 = require("../../auth/shared-resource-policy");
|
|
35
|
+
const instance_directory_1 = require("../instance-directory");
|
|
36
|
+
const diverged_file_adopter_1 = require("./diverged-file-adopter");
|
|
37
|
+
const fs_helpers_1 = require("./fs-helpers");
|
|
38
|
+
const canonical_first_file_claims_1 = require("./canonical-first-file-claims");
|
|
39
|
+
function candidatePaths(roots, fileName) {
|
|
40
|
+
const profiles = new profile_registry_1.default().getAllProfilesMerged();
|
|
41
|
+
const profilesByInstanceName = new Map();
|
|
42
|
+
for (const [profileName, profile] of Object.entries(profiles)) {
|
|
43
|
+
const instanceName = (0, instance_directory_1.normalizeAccountInstanceName)(profileName);
|
|
44
|
+
const matches = profilesByInstanceName.get(instanceName) ?? [];
|
|
45
|
+
matches.push(profile);
|
|
46
|
+
profilesByInstanceName.set(instanceName, matches);
|
|
47
|
+
}
|
|
48
|
+
return [
|
|
49
|
+
path.join(roots.sharedDir, fileName),
|
|
50
|
+
...(0, instance_directory_1.listAccountInstancePaths)(roots.instancesDir)
|
|
51
|
+
.filter((instancePath) => {
|
|
52
|
+
const instanceName = (0, instance_directory_1.normalizeAccountInstanceName)(path.basename(instancePath));
|
|
53
|
+
const matches = profilesByInstanceName.get(instanceName) ?? [];
|
|
54
|
+
if (matches.length > 1)
|
|
55
|
+
return false;
|
|
56
|
+
return matches.length === 0 || !(0, shared_resource_policy_1.isProfileLocalSharedResourceMode)(matches[0]);
|
|
57
|
+
})
|
|
58
|
+
.map((instancePath) => path.join(instancePath, fileName)),
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
function reconcileCandidatesAgainstCanonical(canonicalPath, candidates) {
|
|
62
|
+
let canonicalContent = null;
|
|
63
|
+
try {
|
|
64
|
+
canonicalContent = fs.readFileSync(canonicalPath);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// A present but unreadable or dangling canonical path still owns precedence.
|
|
68
|
+
}
|
|
69
|
+
for (const candidatePath of candidates) {
|
|
70
|
+
(0, canonical_first_file_claims_1.claimCanonicalFirstCopy)(candidatePath, canonicalContent, `Canonical ${path.basename(canonicalPath)} wins over divergent copy at ${candidatePath}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Reconcile a canonical-first shared file before any seed or symlink mutation.
|
|
75
|
+
* Existing canonical content always wins. With no canonical, one unique byte
|
|
76
|
+
* variant is adopted; conflicting variants are all quarantined for recovery.
|
|
77
|
+
*/
|
|
78
|
+
function reconcileCanonicalFirstFile(roots, fileName) {
|
|
79
|
+
const canonicalPath = path.join(roots.claudeDir, fileName);
|
|
80
|
+
const candidates = candidatePaths(roots, fileName);
|
|
81
|
+
for (const candidatePath of candidates) {
|
|
82
|
+
if (candidatePath !== path.join(roots.sharedDir, fileName)) {
|
|
83
|
+
const instancePath = path.dirname(candidatePath);
|
|
84
|
+
if (!(0, instance_directory_1.isSafeAccountInstancePath)(roots.instancesDir, instancePath))
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
(0, canonical_first_file_claims_1.recoverInterruptedClaims)(candidatePath);
|
|
88
|
+
}
|
|
89
|
+
if ((0, fs_helpers_1.getLstatSync)(canonicalPath)) {
|
|
90
|
+
reconcileCandidatesAgainstCanonical(canonicalPath, candidates);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const variants = [];
|
|
94
|
+
for (const candidatePath of candidates) {
|
|
95
|
+
const content = (0, canonical_first_file_claims_1.readRegularFileContent)(candidatePath);
|
|
96
|
+
if (content)
|
|
97
|
+
variants.push({ path: candidatePath, content });
|
|
98
|
+
}
|
|
99
|
+
if (variants.length === 0)
|
|
100
|
+
return;
|
|
101
|
+
const uniqueContents = [];
|
|
102
|
+
for (const variant of variants) {
|
|
103
|
+
if (!uniqueContents.some((content) => content.equals(variant.content))) {
|
|
104
|
+
uniqueContents.push(variant.content);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (uniqueContents.length === 1) {
|
|
108
|
+
(0, diverged_file_adopter_1.adoptDivergedFileContent)(variants[0].path, canonicalPath);
|
|
109
|
+
reconcileCandidatesAgainstCanonical(canonicalPath, candidates);
|
|
110
|
+
console.log((0, ui_1.info)(`Adopted the only existing ${fileName} variant as canonical content`));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
for (const variant of variants) {
|
|
114
|
+
(0, canonical_first_file_claims_1.claimCanonicalFirstCopy)(variant.path, null, `Conflicting ${fileName} variants found while no canonical file exists`);
|
|
115
|
+
}
|
|
116
|
+
console.log((0, ui_1.warn)(`No ${fileName} variant was selected; recover one of the .ccs-shared-conflict files explicitly`));
|
|
117
|
+
}
|
|
118
|
+
exports.reconcileCanonicalFirstFile = reconcileCanonicalFirstFile;
|
|
119
|
+
/** Preserve a later divergent copy without allowing it to replace canonical content. */
|
|
120
|
+
function preserveCanonicalFirstDivergence(divergedPath, canonicalPath) {
|
|
121
|
+
let canonicalContent = null;
|
|
122
|
+
try {
|
|
123
|
+
canonicalContent = fs.readFileSync(canonicalPath);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Preserve the divergence when canonical cannot be compared safely.
|
|
127
|
+
}
|
|
128
|
+
return (0, canonical_first_file_claims_1.claimCanonicalFirstCopy)(divergedPath, canonicalContent, `Canonical ${path.basename(canonicalPath)} wins over divergent copy at ${divergedPath}`);
|
|
129
|
+
}
|
|
130
|
+
exports.preserveCanonicalFirstDivergence = preserveCanonicalFirstDivergence;
|
|
131
|
+
//# sourceMappingURL=canonical-first-file-reconciler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-first-file-reconciler.js","sourceRoot":"","sources":["../../../src/management/shared-manager/canonical-first-file-reconciler.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAE7B,uCAA4C;AAC5C,mFAA0D;AAC1D,8EAAqF;AACrF,8DAI+B;AAC/B,mEAAmE;AACnE,6CAA4C;AAC5C,+EAIuC;AAQvC,SAAS,cAAc,CAAC,KAA0B,EAAE,QAAgB;IAClE,MAAM,QAAQ,GAAG,IAAI,0BAAe,EAAE,CAAC,oBAAoB,EAAE,CAAC;IAC9D,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAA4C,CAAC;IACnF,KAAK,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9D,MAAM,YAAY,GAAG,IAAA,iDAA4B,EAAC,WAAW,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC;QACpC,GAAG,IAAA,6CAAwB,EAAC,KAAK,CAAC,YAAY,CAAC;aAC5C,MAAM,CAAC,CAAC,YAAY,EAAE,EAAE;YACvB,MAAM,YAAY,GAAG,IAAA,iDAA4B,EAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;YAC/E,MAAM,OAAO,GAAG,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YAC/D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;YACrC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAA,yDAAgC,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,CAAC,CAAC;aACD,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,SAAS,mCAAmC,CAC1C,aAAqB,EACrB,UAA6B;IAE7B,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAC3C,IAAI,CAAC;QACH,gBAAgB,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;IAC/E,CAAC;IAED,KAAK,MAAM,aAAa,IAAI,UAAU,EAAE,CAAC;QACvC,IAAA,qDAAuB,EACrB,aAAa,EACb,gBAAgB,EAChB,aAAa,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,gCAAgC,aAAa,EAAE,CACzF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,2BAA2B,CAAC,KAA0B,EAAE,QAAgB;IACtF,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnD,KAAK,MAAM,aAAa,IAAI,UAAU,EAAE,CAAC;QACvC,IAAI,aAAa,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YACjD,IAAI,CAAC,IAAA,8CAAyB,EAAC,KAAK,CAAC,YAAY,EAAE,YAAY,CAAC;gBAAE,SAAS;QAC7E,CAAC;QACD,IAAA,sDAAwB,EAAC,aAAa,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,IAAA,yBAAY,EAAC,aAAa,CAAC,EAAE,CAAC;QAChC,mCAAmC,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAA6C,EAAE,CAAC;IAC9D,KAAK,MAAM,aAAa,IAAI,UAAU,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,IAAA,oDAAsB,EAAC,aAAa,CAAC,CAAC;QACtD,IAAI,OAAO;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAElC,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACvE,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,IAAA,gDAAwB,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QAC1D,mCAAmC,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,IAAA,SAAI,EAAC,6BAA6B,QAAQ,+BAA+B,CAAC,CAAC,CAAC;QACxF,OAAO;IACT,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAA,qDAAuB,EACrB,OAAO,CAAC,IAAI,EACZ,IAAI,EACJ,eAAe,QAAQ,gDAAgD,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,CACT,IAAA,SAAI,EACF,MAAM,QAAQ,iFAAiF,CAChG,CACF,CAAC;AACJ,CAAC;AAjDD,kEAiDC;AAED,wFAAwF;AACxF,SAAgB,gCAAgC,CAC9C,YAAoB,EACpB,aAAqB;IAErB,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAC3C,IAAI,CAAC;QACH,gBAAgB,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;IACtE,CAAC;IAED,OAAO,IAAA,qDAAuB,EAC5B,YAAY,EACZ,gBAAgB,EAChB,aAAa,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,gCAAgC,YAAY,EAAE,CACxF,CAAC;AACJ,CAAC;AAhBD,4EAgBC"}
|
|
@@ -25,7 +25,7 @@ export declare function ensureSharedPluginLayoutDefaults(claudeDir: string): voi
|
|
|
25
25
|
* Link shared plugins directory entries into an instance, creating the
|
|
26
26
|
* instance plugins directory first if needed.
|
|
27
27
|
*/
|
|
28
|
-
export declare function linkInstancePlugins(roots: PluginLayoutRoots, instancePath: string): void;
|
|
28
|
+
export declare function linkInstancePlugins(roots: PluginLayoutRoots, instancePath: string, assertInstanceIdentity?: () => void): void;
|
|
29
29
|
/**
|
|
30
30
|
* Build the list of plugin entries to link from the shared plugins dir.
|
|
31
31
|
* Always includes the default SHARED_PLUGIN_ENTRIES; adds any additional
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-layout-internals.d.ts","sourceRoot":"","sources":["../../../src/management/shared-manager/plugin-layout-internals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAOxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin-layout-internals.d.ts","sourceRoot":"","sources":["../../../src/management/shared-manager/plugin-layout-internals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAOxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAcpD;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAyBxE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,iBAAiB,EACxB,YAAY,EAAE,MAAM,EACpB,sBAAsB,CAAC,EAAE,MAAM,IAAI,GAClC,IAAI,CAsFN;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE,CAyCxE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAgD9F"}
|
|
@@ -42,6 +42,15 @@ const diverged_file_adopter_1 = require("./diverged-file-adopter");
|
|
|
42
42
|
const fs_helpers_1 = require("./fs-helpers");
|
|
43
43
|
const plugin_metadata_normalizer_1 = require("./plugin-metadata-normalizer");
|
|
44
44
|
const types_1 = require("./types");
|
|
45
|
+
function runGuardedInstanceMutation(assertInstanceIdentity, operation) {
|
|
46
|
+
assertInstanceIdentity?.();
|
|
47
|
+
try {
|
|
48
|
+
return operation();
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
assertInstanceIdentity?.();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
45
54
|
/**
|
|
46
55
|
* Ensure the plugin layout default directories (cache, marketplaces) and
|
|
47
56
|
* registry files (installed_plugins.json, known_marketplaces.json) exist
|
|
@@ -74,7 +83,7 @@ exports.ensureSharedPluginLayoutDefaults = ensureSharedPluginLayoutDefaults;
|
|
|
74
83
|
* Link shared plugins directory entries into an instance, creating the
|
|
75
84
|
* instance plugins directory first if needed.
|
|
76
85
|
*/
|
|
77
|
-
function linkInstancePlugins(roots, instancePath) {
|
|
86
|
+
function linkInstancePlugins(roots, instancePath, assertInstanceIdentity) {
|
|
78
87
|
const linkPath = path.join(instancePath, 'plugins');
|
|
79
88
|
const targetPath = path.join(roots.sharedDir, 'plugins');
|
|
80
89
|
let linkStats = null;
|
|
@@ -86,35 +95,41 @@ function linkInstancePlugins(roots, instancePath) {
|
|
|
86
95
|
throw err;
|
|
87
96
|
}
|
|
88
97
|
}
|
|
98
|
+
assertInstanceIdentity?.();
|
|
89
99
|
if (linkStats?.isSymbolicLink() || (linkStats && !linkStats.isDirectory())) {
|
|
90
|
-
|
|
100
|
+
const existingType = linkStats.isDirectory() ? 'directory' : 'file';
|
|
101
|
+
runGuardedInstanceMutation(assertInstanceIdentity, () => (0, fs_helpers_1.removeExistingPath)(linkPath, existingType));
|
|
91
102
|
}
|
|
92
103
|
if (!linkStats || !linkStats.isDirectory()) {
|
|
93
|
-
fs.mkdirSync(linkPath, { recursive: true, mode: 0o700 });
|
|
104
|
+
runGuardedInstanceMutation(assertInstanceIdentity, () => fs.mkdirSync(linkPath, { recursive: true, mode: 0o700 }));
|
|
94
105
|
}
|
|
95
|
-
|
|
106
|
+
const linkItems = getSharedPluginLinkItems(roots.sharedDir);
|
|
107
|
+
assertInstanceIdentity?.();
|
|
108
|
+
for (const item of linkItems) {
|
|
96
109
|
const targetEntryPath = path.join(targetPath, item.name);
|
|
97
110
|
const linkEntryPath = path.join(linkPath, item.name);
|
|
98
111
|
let adoption = 'not-claimed';
|
|
99
112
|
if (item.type === 'file') {
|
|
100
|
-
adoption = (0, diverged_file_adopter_1.adoptDivergedFileContent)(linkEntryPath, path.join(roots.claudeDir, 'plugins', item.name));
|
|
113
|
+
adoption = runGuardedInstanceMutation(assertInstanceIdentity, () => (0, diverged_file_adopter_1.adoptDivergedFileContent)(linkEntryPath, path.join(roots.claudeDir, 'plugins', item.name)));
|
|
101
114
|
if (adoption === 'not-claimed') {
|
|
102
|
-
(0, fs_helpers_1.removeExistingPath)(linkEntryPath, item.type);
|
|
115
|
+
runGuardedInstanceMutation(assertInstanceIdentity, () => (0, fs_helpers_1.removeExistingPath)(linkEntryPath, item.type));
|
|
103
116
|
}
|
|
104
117
|
}
|
|
105
118
|
else {
|
|
106
|
-
(0, fs_helpers_1.removeExistingPath)(linkEntryPath, item.type);
|
|
119
|
+
runGuardedInstanceMutation(assertInstanceIdentity, () => (0, fs_helpers_1.removeExistingPath)(linkEntryPath, item.type));
|
|
107
120
|
}
|
|
108
121
|
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(linkEntryPath, adoption);
|
|
109
122
|
if ((0, fs_helpers_1.getLstatSync)(linkEntryPath)) {
|
|
110
123
|
console.log((0, ui_1.warn)(`Skipping plugins/${item.name}: path reappeared during reconciliation`));
|
|
111
124
|
continue;
|
|
112
125
|
}
|
|
126
|
+
assertInstanceIdentity?.();
|
|
113
127
|
try {
|
|
114
128
|
const symlinkType = item.type === 'directory' ? 'dir' : 'file';
|
|
115
129
|
fs.symlinkSync(targetEntryPath, linkEntryPath, symlinkType);
|
|
116
130
|
}
|
|
117
131
|
catch (_err) {
|
|
132
|
+
assertInstanceIdentity?.();
|
|
118
133
|
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(linkEntryPath, adoption);
|
|
119
134
|
if ((0, fs_helpers_1.getLstatSync)(linkEntryPath)) {
|
|
120
135
|
console.log((0, ui_1.warn)(`Skipping plugins/${item.name}: path reappeared during reconciliation`));
|
|
@@ -122,10 +137,10 @@ function linkInstancePlugins(roots, instancePath) {
|
|
|
122
137
|
}
|
|
123
138
|
if (process.platform === 'win32') {
|
|
124
139
|
if (item.type === 'directory') {
|
|
125
|
-
(0, fs_helpers_1.copyDirectoryFallback)(targetEntryPath, linkEntryPath);
|
|
140
|
+
runGuardedInstanceMutation(assertInstanceIdentity, () => (0, fs_helpers_1.copyDirectoryFallback)(targetEntryPath, linkEntryPath));
|
|
126
141
|
}
|
|
127
142
|
else {
|
|
128
|
-
fs.copyFileSync(targetEntryPath, linkEntryPath, fs.constants.COPYFILE_EXCL);
|
|
143
|
+
runGuardedInstanceMutation(assertInstanceIdentity, () => fs.copyFileSync(targetEntryPath, linkEntryPath, fs.constants.COPYFILE_EXCL));
|
|
129
144
|
}
|
|
130
145
|
console.log((0, ui_1.warn)(`Symlink failed for plugins/${item.name}, copied instead (enable Developer Mode)`));
|
|
131
146
|
}
|
|
@@ -133,6 +148,7 @@ function linkInstancePlugins(roots, instancePath) {
|
|
|
133
148
|
throw _err;
|
|
134
149
|
}
|
|
135
150
|
}
|
|
151
|
+
assertInstanceIdentity?.();
|
|
136
152
|
}
|
|
137
153
|
}
|
|
138
154
|
exports.linkInstancePlugins = linkInstancePlugins;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-layout-internals.js","sourceRoot":"","sources":["../../../src/management/shared-manager/plugin-layout-internals.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAE7B,uCAAsC;AACtC,mEAIiC;AACjC,6CAKsB;AAEtB,6EAAiF;AACjF,mCAIiB;AAQjB;;;;GAIG;AACH,SAAgB,gCAAgC,CAAC,SAAiB;IAChE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACnD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAE3D,KAAK,MAAM,KAAK,IAAI,6BAAqB,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,IAAA,qDAA6B,EAAC,SAAS,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1D,SAAS;QACX,CAAC;QAED,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,yCAAiC,EAAE,MAAM,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,uBAAuB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,yBAAyB,CAAC,CAAC;IACjF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,uBAAuB,CAAC,EAAE,CAAC;QAC5C,EAAE,CAAC,aAAa,CAAC,uBAAuB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAzBD,4EAyBC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"plugin-layout-internals.js","sourceRoot":"","sources":["../../../src/management/shared-manager/plugin-layout-internals.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAE7B,uCAAsC;AACtC,mEAIiC;AACjC,6CAKsB;AAEtB,6EAAiF;AACjF,mCAIiB;AAQjB,SAAS,0BAA0B,CACjC,sBAAgD,EAChD,SAAkB;IAElB,sBAAsB,EAAE,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,SAAS,EAAE,CAAC;IACrB,CAAC;YAAS,CAAC;QACT,sBAAsB,EAAE,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,gCAAgC,CAAC,SAAiB;IAChE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACnD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAE3D,KAAK,MAAM,KAAK,IAAI,6BAAqB,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,IAAA,qDAA6B,EAAC,SAAS,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1D,SAAS;QACX,CAAC;QAED,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,yCAAiC,EAAE,MAAM,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,uBAAuB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,yBAAyB,CAAC,CAAC;IACjF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,uBAAuB,CAAC,EAAE,CAAC;QAC5C,EAAE,CAAC,aAAa,CAAC,uBAAuB,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAzBD,4EAyBC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CACjC,KAAwB,EACxB,YAAoB,EACpB,sBAAmC;IAEnC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACzD,IAAI,SAAS,GAAoB,IAAI,CAAC;IAEtC,IAAI,CAAC;QACH,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,sBAAsB,EAAE,EAAE,CAAC;IAE3B,IAAI,SAAS,EAAE,cAAc,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAC3E,MAAM,YAAY,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;QACpE,0BAA0B,CAAC,sBAAsB,EAAE,GAAG,EAAE,CACtD,IAAA,+BAAkB,EAAC,QAAQ,EAAE,YAAY,CAAC,CAC3C,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3C,0BAA0B,CAAC,sBAAsB,EAAE,GAAG,EAAE,CACtD,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CACzD,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,wBAAwB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC5D,sBAAsB,EAAE,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,QAAQ,GAAgD,aAAa,CAAC;QAE1E,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,QAAQ,GAAG,0BAA0B,CAAC,sBAAsB,EAAE,GAAG,EAAE,CACjE,IAAA,gDAAwB,EAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAC1F,CAAC;YACF,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;gBAC/B,0BAA0B,CAAC,sBAAsB,EAAE,GAAG,EAAE,CACtD,IAAA,+BAAkB,EAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAC7C,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,0BAA0B,CAAC,sBAAsB,EAAE,GAAG,EAAE,CACtD,IAAA,+BAAkB,EAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAC7C,CAAC;QACJ,CAAC;QACD,IAAA,gDAAwB,EAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAElD,IAAI,IAAA,yBAAY,EAAC,aAAa,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,IAAA,SAAI,EAAC,oBAAoB,IAAI,CAAC,IAAI,yCAAyC,CAAC,CAAC,CAAC;YAC1F,SAAS;QACX,CAAC;QAED,sBAAsB,EAAE,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;YAC/D,EAAE,CAAC,WAAW,CAAC,eAAe,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,IAAI,EAAE,CAAC;YACd,sBAAsB,EAAE,EAAE,CAAC;YAC3B,IAAA,gDAAwB,EAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;YAClD,IAAI,IAAA,yBAAY,EAAC,aAAa,CAAC,EAAE,CAAC;gBAChC,OAAO,CAAC,GAAG,CAAC,IAAA,SAAI,EAAC,oBAAoB,IAAI,CAAC,IAAI,yCAAyC,CAAC,CAAC,CAAC;gBAC1F,SAAS;YACX,CAAC;YACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACjC,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBAC9B,0BAA0B,CAAC,sBAAsB,EAAE,GAAG,EAAE,CACtD,IAAA,kCAAqB,EAAC,eAAe,EAAE,aAAa,CAAC,CACtD,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,0BAA0B,CAAC,sBAAsB,EAAE,GAAG,EAAE,CACtD,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,aAAa,EAAE,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,CAC5E,CAAC;gBACJ,CAAC;gBACD,OAAO,CAAC,GAAG,CACT,IAAA,SAAI,EAAC,8BAA8B,IAAI,CAAC,IAAI,0CAA0C,CAAC,CACxF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC;YACb,CAAC;QACH,CAAC;QACD,sBAAsB,EAAE,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC;AA1FD,kDA0FC;AAED;;;;GAIG;AACH,SAAgB,wBAAwB,CAAC,SAAiB;IACxD,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,GAAG,CACnB,6BAAqB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CACjE,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,iBAAiB,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/E,IACE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YACrB,4CAAoC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAClC,CAAC;YACD,SAAS;QACX,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,KAAe,CAAC;QACpB,IAAI,CAAC;YACH,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;YACjD,OAAO,CAAC,GAAG,CACT,IAAA,SAAI,EACF,oBAAoB,KAAK,CAAC,IAAI,0CAA0C,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACnG,CACF,CAAC;YACF,SAAS;QACX,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM;SACjD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7B,CAAC;AAzCD,4DAyCC;AAED;;;;;GAKG;AACH,SAAgB,yBAAyB,CAAC,KAAwB,EAAE,YAAoB;IACtF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACxC,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAEhE,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;QAC3B,IAAI,IAAA,4BAAe,EAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,CAAC;YACpD,IAAA,+BAAkB,EAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACzB,OAAO;IACT,CAAC;IAED,IAAI,qBAAqB,GAAG,KAAK,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,wBAAwB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7D,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACpC,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GAAG,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC;YACjC,SAAS;QACX,CAAC;QAED,IAAI,IAAA,4BAAe,EAAC,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC9E,IAAA,+BAAkB,EAAC,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/C,qBAAqB,GAAG,IAAI,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,IAAA,8DAAiC,EAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAEvD,IAAI,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7C,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAhDD,8DAgDC"}
|
|
@@ -28,7 +28,7 @@ export declare function detectCircularSymlink(target: string, sharedDir: string)
|
|
|
28
28
|
* Ensure shared directories exist as symlinks to ~/.claude/ and that the
|
|
29
29
|
* plugin layout default directories and registry files are present.
|
|
30
30
|
*/
|
|
31
|
-
export declare function ensureSharedDirectories(roots: LinkerRoots): void;
|
|
31
|
+
export declare function ensureSharedDirectories(roots: LinkerRoots, assertInstanceIdentity?: () => void): void;
|
|
32
32
|
/**
|
|
33
33
|
* Link shared directories into a specific instance path.
|
|
34
34
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-dir-linker.d.ts","sourceRoot":"","sources":["../../../src/management/shared-manager/shared-dir-linker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"shared-dir-linker.d.ts","sourceRoot":"","sources":["../../../src/management/shared-manager/shared-dir-linker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAuBH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAgBxE;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAc9C;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAsChF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,WAAW,EAClB,sBAAsB,CAAC,EAAE,MAAM,IAAI,GAClC,IAAI,CA2GN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CA0EpF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAyBtF"}
|
|
@@ -42,11 +42,22 @@ exports.detachSharedDirectories = exports.linkSharedDirectories = exports.ensure
|
|
|
42
42
|
const fs = __importStar(require("fs"));
|
|
43
43
|
const path = __importStar(require("path"));
|
|
44
44
|
const ui_1 = require("../../utils/ui");
|
|
45
|
+
const instance_directory_1 = require("../instance-directory");
|
|
45
46
|
const diverged_file_adopter_1 = require("./diverged-file-adopter");
|
|
46
47
|
const fs_helpers_1 = require("./fs-helpers");
|
|
47
48
|
const plugin_metadata_normalizer_1 = require("./plugin-metadata-normalizer");
|
|
48
49
|
const plugin_layout_internals_1 = require("./plugin-layout-internals");
|
|
50
|
+
const canonical_first_file_reconciler_1 = require("./canonical-first-file-reconciler");
|
|
49
51
|
const types_1 = require("./types");
|
|
52
|
+
function runInstanceMutationStage(assertInstanceIdentity, operation) {
|
|
53
|
+
assertInstanceIdentity?.();
|
|
54
|
+
try {
|
|
55
|
+
return operation();
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
assertInstanceIdentity?.();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
50
61
|
/**
|
|
51
62
|
* Detect a circular symlink before creation. A symlink is circular when its
|
|
52
63
|
* target (raw or canonical) points back inside the shared root.
|
|
@@ -91,90 +102,102 @@ exports.detectCircularSymlink = detectCircularSymlink;
|
|
|
91
102
|
* Ensure shared directories exist as symlinks to ~/.claude/ and that the
|
|
92
103
|
* plugin layout default directories and registry files are present.
|
|
93
104
|
*/
|
|
94
|
-
function ensureSharedDirectories(roots) {
|
|
105
|
+
function ensureSharedDirectories(roots, assertInstanceIdentity) {
|
|
95
106
|
const claudeDir = roots.claudeDir;
|
|
96
107
|
const sharedDir = roots.sharedDir;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (!(0, fs_helpers_1.getLstatSync)(sharedDir)) {
|
|
102
|
-
fs.mkdirSync(sharedDir, { recursive: true, mode: 0o700 });
|
|
103
|
-
}
|
|
104
|
-
(0, plugin_layout_internals_1.ensureSharedPluginLayoutDefaults)(claudeDir);
|
|
105
|
-
for (const item of types_1.SHARED_ITEMS) {
|
|
106
|
-
const claudePath = path.join(claudeDir, item.name);
|
|
107
|
-
const sharedPath = path.join(sharedDir, item.name);
|
|
108
|
-
if (item.type === 'file') {
|
|
109
|
-
(0, diverged_file_adopter_1.recoverOrphanedCanonicalClaim)(claudePath);
|
|
108
|
+
runInstanceMutationStage(assertInstanceIdentity, () => {
|
|
109
|
+
if (!(0, fs_helpers_1.getLstatSync)(claudeDir)) {
|
|
110
|
+
console.log((0, ui_1.info)('Creating ~/.claude/ directory structure'));
|
|
111
|
+
fs.mkdirSync(claudeDir, { recursive: true, mode: 0o700 });
|
|
110
112
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
else if (item.type === 'file') {
|
|
116
|
-
fs.writeFileSync(claudePath, JSON.stringify({}, null, 2), 'utf8');
|
|
117
|
-
}
|
|
113
|
+
});
|
|
114
|
+
runInstanceMutationStage(assertInstanceIdentity, () => {
|
|
115
|
+
if (!(0, fs_helpers_1.getLstatSync)(sharedDir)) {
|
|
116
|
+
fs.mkdirSync(sharedDir, { recursive: true, mode: 0o700 });
|
|
118
117
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const stats = fs.lstatSync(sharedPath);
|
|
128
|
-
if (stats.isSymbolicLink()) {
|
|
129
|
-
const currentTarget = fs.readlinkSync(sharedPath);
|
|
130
|
-
const resolvedTarget = path.resolve(path.dirname(sharedPath), currentTarget);
|
|
131
|
-
if (resolvedTarget === claudePath) {
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
118
|
+
});
|
|
119
|
+
runInstanceMutationStage(assertInstanceIdentity, () => (0, plugin_layout_internals_1.ensureSharedPluginLayoutDefaults)(claudeDir));
|
|
120
|
+
for (const item of types_1.SHARED_ITEMS) {
|
|
121
|
+
runInstanceMutationStage(assertInstanceIdentity, () => {
|
|
122
|
+
const claudePath = path.join(claudeDir, item.name);
|
|
123
|
+
const sharedPath = path.join(sharedDir, item.name);
|
|
124
|
+
if (item.type === 'file') {
|
|
125
|
+
(0, diverged_file_adopter_1.recoverOrphanedCanonicalClaim)(claudePath);
|
|
135
126
|
}
|
|
136
|
-
|
|
137
|
-
|
|
127
|
+
if (item.type === 'file' && item.divergencePolicy === 'canonical-first') {
|
|
128
|
+
(0, canonical_first_file_reconciler_1.reconcileCanonicalFirstFile)(roots, item.name);
|
|
138
129
|
}
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
130
|
+
if (!(0, fs_helpers_1.getLstatSync)(claudePath)) {
|
|
131
|
+
if (item.type === 'directory') {
|
|
132
|
+
fs.mkdirSync(claudePath, { recursive: true, mode: 0o700 });
|
|
133
|
+
}
|
|
134
|
+
else if (item.type === 'file') {
|
|
135
|
+
fs.writeFileSync(claudePath, item.seedContent, 'utf8');
|
|
136
|
+
}
|
|
142
137
|
}
|
|
143
|
-
if (
|
|
144
|
-
|
|
138
|
+
if (detectCircularSymlink(claudePath, sharedDir)) {
|
|
139
|
+
console.log((0, ui_1.warn)(`Skipping ${item.name}: circular symlink detected`));
|
|
140
|
+
return;
|
|
145
141
|
}
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
let sharedAdoption = 'not-claimed';
|
|
143
|
+
if ((0, fs_helpers_1.getLstatSync)(sharedPath)) {
|
|
144
|
+
let removeExisting = true;
|
|
145
|
+
try {
|
|
146
|
+
const stats = fs.lstatSync(sharedPath);
|
|
147
|
+
if (stats.isSymbolicLink()) {
|
|
148
|
+
const currentTarget = fs.readlinkSync(sharedPath);
|
|
149
|
+
const resolvedTarget = path.resolve(path.dirname(sharedPath), currentTarget);
|
|
150
|
+
if (resolvedTarget === claudePath) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (_err) {
|
|
156
|
+
// Continue to recreate
|
|
157
|
+
}
|
|
158
|
+
if (item.type === 'file' && item.divergencePolicy === 'canonical-first') {
|
|
159
|
+
removeExisting = !(0, canonical_first_file_reconciler_1.preserveCanonicalFirstDivergence)(sharedPath, claudePath);
|
|
160
|
+
}
|
|
161
|
+
else if (item.type === 'file') {
|
|
162
|
+
sharedAdoption = (0, diverged_file_adopter_1.adoptDivergedFileContent)(sharedPath, claudePath);
|
|
163
|
+
removeExisting = sharedAdoption === 'not-claimed';
|
|
164
|
+
}
|
|
165
|
+
if (item.type === 'directory' && removeExisting) {
|
|
166
|
+
fs.rmSync(sharedPath, { recursive: true, force: true });
|
|
167
|
+
}
|
|
168
|
+
else if (removeExisting) {
|
|
169
|
+
fs.unlinkSync(sharedPath);
|
|
170
|
+
}
|
|
171
|
+
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(sharedPath, sharedAdoption);
|
|
148
172
|
}
|
|
149
|
-
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(sharedPath, sharedAdoption);
|
|
150
|
-
}
|
|
151
|
-
if ((0, fs_helpers_1.getLstatSync)(sharedPath)) {
|
|
152
|
-
console.log((0, ui_1.warn)(`Skipping ${item.name}: path reappeared during reconciliation`));
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
155
|
-
try {
|
|
156
|
-
const symlinkType = item.type === 'directory' ? 'dir' : 'file';
|
|
157
|
-
fs.symlinkSync(claudePath, sharedPath, symlinkType);
|
|
158
|
-
}
|
|
159
|
-
catch (_err) {
|
|
160
|
-
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(sharedPath, sharedAdoption);
|
|
161
173
|
if ((0, fs_helpers_1.getLstatSync)(sharedPath)) {
|
|
162
174
|
console.log((0, ui_1.warn)(`Skipping ${item.name}: path reappeared during reconciliation`));
|
|
163
|
-
|
|
175
|
+
return;
|
|
164
176
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
177
|
+
try {
|
|
178
|
+
const symlinkType = item.type === 'directory' ? 'dir' : 'file';
|
|
179
|
+
fs.symlinkSync(claudePath, sharedPath, symlinkType);
|
|
180
|
+
}
|
|
181
|
+
catch (_err) {
|
|
182
|
+
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(sharedPath, sharedAdoption);
|
|
183
|
+
if ((0, fs_helpers_1.getLstatSync)(sharedPath)) {
|
|
184
|
+
console.log((0, ui_1.warn)(`Skipping ${item.name}: path reappeared during reconciliation`));
|
|
185
|
+
return;
|
|
168
186
|
}
|
|
169
|
-
|
|
170
|
-
|
|
187
|
+
if (process.platform === 'win32') {
|
|
188
|
+
if (item.type === 'directory') {
|
|
189
|
+
(0, fs_helpers_1.copyDirectoryFallback)(claudePath, sharedPath);
|
|
190
|
+
}
|
|
191
|
+
else if (item.type === 'file') {
|
|
192
|
+
fs.copyFileSync(claudePath, sharedPath, fs.constants.COPYFILE_EXCL);
|
|
193
|
+
}
|
|
194
|
+
console.log((0, ui_1.warn)(`Symlink failed for ${item.name}, copied instead (enable Developer Mode)`));
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
throw _err;
|
|
171
198
|
}
|
|
172
|
-
console.log((0, ui_1.warn)(`Symlink failed for ${item.name}, copied instead (enable Developer Mode)`));
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
throw _err;
|
|
176
199
|
}
|
|
177
|
-
}
|
|
200
|
+
});
|
|
178
201
|
}
|
|
179
202
|
}
|
|
180
203
|
exports.ensureSharedDirectories = ensureSharedDirectories;
|
|
@@ -182,59 +205,69 @@ exports.ensureSharedDirectories = ensureSharedDirectories;
|
|
|
182
205
|
* Link shared directories into a specific instance path.
|
|
183
206
|
*/
|
|
184
207
|
function linkSharedDirectories(roots, instancePath) {
|
|
185
|
-
|
|
208
|
+
const instanceIdentity = (0, instance_directory_1.captureSafeAccountInstanceIdentity)(roots.instancesDir, instancePath);
|
|
209
|
+
const assertInstanceIdentity = () => (0, instance_directory_1.assertAccountInstanceIdentity)(roots.instancesDir, instancePath, instanceIdentity);
|
|
210
|
+
ensureSharedDirectories(roots, assertInstanceIdentity);
|
|
211
|
+
assertInstanceIdentity();
|
|
186
212
|
const sharedDir = roots.sharedDir;
|
|
187
213
|
for (const item of types_1.SHARED_ITEMS) {
|
|
188
|
-
|
|
189
|
-
(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
214
|
+
runInstanceMutationStage(assertInstanceIdentity, () => {
|
|
215
|
+
if (item.name === 'plugins') {
|
|
216
|
+
(0, plugin_layout_internals_1.linkInstancePlugins)(roots, instancePath, assertInstanceIdentity);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const linkPath = path.join(instancePath, item.name);
|
|
220
|
+
const targetPath = path.join(sharedDir, item.name);
|
|
221
|
+
let adoption = 'not-claimed';
|
|
222
|
+
if (item.type === 'file' && item.divergencePolicy === 'canonical-first') {
|
|
223
|
+
if (!(0, canonical_first_file_reconciler_1.preserveCanonicalFirstDivergence)(linkPath, path.join(roots.claudeDir, item.name))) {
|
|
224
|
+
(0, fs_helpers_1.removeExistingPath)(linkPath, item.type);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else if (item.type === 'file') {
|
|
228
|
+
adoption = (0, diverged_file_adopter_1.adoptDivergedFileContent)(linkPath, path.join(roots.claudeDir, item.name));
|
|
229
|
+
if (adoption === 'not-claimed') {
|
|
230
|
+
(0, fs_helpers_1.removeExistingPath)(linkPath, item.type);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
198
234
|
(0, fs_helpers_1.removeExistingPath)(linkPath, item.type);
|
|
199
235
|
}
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
(0, fs_helpers_1.removeExistingPath)(linkPath, item.type);
|
|
203
|
-
}
|
|
204
|
-
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(linkPath, adoption);
|
|
205
|
-
if ((0, fs_helpers_1.getLstatSync)(linkPath)) {
|
|
206
|
-
console.log((0, ui_1.warn)(`Skipping ${item.name}: path reappeared during reconciliation`));
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
try {
|
|
210
|
-
const symlinkType = item.type === 'directory' ? 'dir' : 'file';
|
|
211
|
-
fs.symlinkSync(targetPath, linkPath, symlinkType);
|
|
212
|
-
}
|
|
213
|
-
catch (_err) {
|
|
214
236
|
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(linkPath, adoption);
|
|
215
237
|
if ((0, fs_helpers_1.getLstatSync)(linkPath)) {
|
|
216
238
|
console.log((0, ui_1.warn)(`Skipping ${item.name}: path reappeared during reconciliation`));
|
|
217
|
-
|
|
239
|
+
return;
|
|
218
240
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
241
|
+
try {
|
|
242
|
+
const symlinkType = item.type === 'directory' ? 'dir' : 'file';
|
|
243
|
+
fs.symlinkSync(targetPath, linkPath, symlinkType);
|
|
244
|
+
}
|
|
245
|
+
catch (_err) {
|
|
246
|
+
(0, diverged_file_adopter_1.assertAdoptionPathAbsent)(linkPath, adoption);
|
|
247
|
+
if ((0, fs_helpers_1.getLstatSync)(linkPath)) {
|
|
248
|
+
console.log((0, ui_1.warn)(`Skipping ${item.name}: path reappeared during reconciliation`));
|
|
249
|
+
return;
|
|
222
250
|
}
|
|
223
|
-
|
|
224
|
-
|
|
251
|
+
if (process.platform === 'win32') {
|
|
252
|
+
if (item.type === 'directory') {
|
|
253
|
+
(0, fs_helpers_1.copyDirectoryFallback)(targetPath, linkPath);
|
|
254
|
+
}
|
|
255
|
+
else if (item.type === 'file') {
|
|
256
|
+
fs.copyFileSync(targetPath, linkPath, fs.constants.COPYFILE_EXCL);
|
|
257
|
+
}
|
|
258
|
+
console.log((0, ui_1.warn)(`Symlink failed for ${item.name}, copied instead (enable Developer Mode)`));
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
throw _err;
|
|
225
262
|
}
|
|
226
|
-
console.log((0, ui_1.warn)(`Symlink failed for ${item.name}, copied instead (enable Developer Mode)`));
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
throw _err;
|
|
230
263
|
}
|
|
231
|
-
}
|
|
264
|
+
});
|
|
232
265
|
}
|
|
233
266
|
// Preserve original behavior: linkSharedDirectories always concludes by
|
|
234
267
|
// normalizing plugin + marketplace metadata for the freshly linked
|
|
235
268
|
// instance. migrateFromV311 relies on this side effect.
|
|
236
|
-
(0, plugin_metadata_normalizer_1.normalizePluginRegistryPaths)(roots, instancePath);
|
|
237
|
-
(0, plugin_metadata_normalizer_1.normalizeMarketplaceRegistryPaths)(roots, instancePath);
|
|
269
|
+
runInstanceMutationStage(assertInstanceIdentity, () => (0, plugin_metadata_normalizer_1.normalizePluginRegistryPaths)(roots, instancePath));
|
|
270
|
+
runInstanceMutationStage(assertInstanceIdentity, () => (0, plugin_metadata_normalizer_1.normalizeMarketplaceRegistryPaths)(roots, instancePath));
|
|
238
271
|
}
|
|
239
272
|
exports.linkSharedDirectories = linkSharedDirectories;
|
|
240
273
|
/**
|