@alessandroraffa/tangyr 0.15.0 → 0.16.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 +1298 -803
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1372,8 +1372,8 @@ var require_command = __commonJS({
|
|
|
1372
1372
|
"use strict";
|
|
1373
1373
|
var EventEmitter = __require("events").EventEmitter;
|
|
1374
1374
|
var childProcess = __require("child_process");
|
|
1375
|
-
var
|
|
1376
|
-
var
|
|
1375
|
+
var path45 = __require("path");
|
|
1376
|
+
var fs44 = __require("fs");
|
|
1377
1377
|
var process5 = __require("process");
|
|
1378
1378
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1379
1379
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2367,7 +2367,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2367
2367
|
* @param {string} subcommandName
|
|
2368
2368
|
*/
|
|
2369
2369
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2370
|
-
if (
|
|
2370
|
+
if (fs44.existsSync(executableFile)) return;
|
|
2371
2371
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2372
2372
|
const executableMissing = `'${executableFile}' does not exist
|
|
2373
2373
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2385,11 +2385,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2385
2385
|
let launchWithNode = false;
|
|
2386
2386
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2387
2387
|
function findFile(baseDir, baseName) {
|
|
2388
|
-
const localBin =
|
|
2389
|
-
if (
|
|
2390
|
-
if (sourceExt.includes(
|
|
2388
|
+
const localBin = path45.resolve(baseDir, baseName);
|
|
2389
|
+
if (fs44.existsSync(localBin)) return localBin;
|
|
2390
|
+
if (sourceExt.includes(path45.extname(baseName))) return void 0;
|
|
2391
2391
|
const foundExt = sourceExt.find(
|
|
2392
|
-
(ext) =>
|
|
2392
|
+
(ext) => fs44.existsSync(`${localBin}${ext}`)
|
|
2393
2393
|
);
|
|
2394
2394
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2395
2395
|
return void 0;
|
|
@@ -2401,21 +2401,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2401
2401
|
if (this._scriptPath) {
|
|
2402
2402
|
let resolvedScriptPath;
|
|
2403
2403
|
try {
|
|
2404
|
-
resolvedScriptPath =
|
|
2404
|
+
resolvedScriptPath = fs44.realpathSync(this._scriptPath);
|
|
2405
2405
|
} catch {
|
|
2406
2406
|
resolvedScriptPath = this._scriptPath;
|
|
2407
2407
|
}
|
|
2408
|
-
executableDir =
|
|
2409
|
-
|
|
2408
|
+
executableDir = path45.resolve(
|
|
2409
|
+
path45.dirname(resolvedScriptPath),
|
|
2410
2410
|
executableDir
|
|
2411
2411
|
);
|
|
2412
2412
|
}
|
|
2413
2413
|
if (executableDir) {
|
|
2414
2414
|
let localFile = findFile(executableDir, executableFile);
|
|
2415
2415
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2416
|
-
const legacyName =
|
|
2416
|
+
const legacyName = path45.basename(
|
|
2417
2417
|
this._scriptPath,
|
|
2418
|
-
|
|
2418
|
+
path45.extname(this._scriptPath)
|
|
2419
2419
|
);
|
|
2420
2420
|
if (legacyName !== this._name) {
|
|
2421
2421
|
localFile = findFile(
|
|
@@ -2426,7 +2426,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2426
2426
|
}
|
|
2427
2427
|
executableFile = localFile || executableFile;
|
|
2428
2428
|
}
|
|
2429
|
-
launchWithNode = sourceExt.includes(
|
|
2429
|
+
launchWithNode = sourceExt.includes(path45.extname(executableFile));
|
|
2430
2430
|
let proc;
|
|
2431
2431
|
if (process5.platform !== "win32") {
|
|
2432
2432
|
if (launchWithNode) {
|
|
@@ -3341,7 +3341,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3341
3341
|
* @return {Command}
|
|
3342
3342
|
*/
|
|
3343
3343
|
nameFromFilename(filename) {
|
|
3344
|
-
this._name =
|
|
3344
|
+
this._name = path45.basename(filename, path45.extname(filename));
|
|
3345
3345
|
return this;
|
|
3346
3346
|
}
|
|
3347
3347
|
/**
|
|
@@ -3355,9 +3355,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3355
3355
|
* @param {string} [path]
|
|
3356
3356
|
* @return {(string|null|Command)}
|
|
3357
3357
|
*/
|
|
3358
|
-
executableDir(
|
|
3359
|
-
if (
|
|
3360
|
-
this._executableDir =
|
|
3358
|
+
executableDir(path46) {
|
|
3359
|
+
if (path46 === void 0) return this._executableDir;
|
|
3360
|
+
this._executableDir = path46;
|
|
3361
3361
|
return this;
|
|
3362
3362
|
}
|
|
3363
3363
|
/**
|
|
@@ -3713,17 +3713,17 @@ var require_visit = __commonJS({
|
|
|
3713
3713
|
visit.BREAK = BREAK;
|
|
3714
3714
|
visit.SKIP = SKIP;
|
|
3715
3715
|
visit.REMOVE = REMOVE;
|
|
3716
|
-
function visit_(key, node, visitor,
|
|
3717
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
3716
|
+
function visit_(key, node, visitor, path45) {
|
|
3717
|
+
const ctrl = callVisitor(key, node, visitor, path45);
|
|
3718
3718
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
3719
|
-
replaceNode(key,
|
|
3720
|
-
return visit_(key, ctrl, visitor,
|
|
3719
|
+
replaceNode(key, path45, ctrl);
|
|
3720
|
+
return visit_(key, ctrl, visitor, path45);
|
|
3721
3721
|
}
|
|
3722
3722
|
if (typeof ctrl !== "symbol") {
|
|
3723
3723
|
if (identity.isCollection(node)) {
|
|
3724
|
-
|
|
3724
|
+
path45 = Object.freeze(path45.concat(node));
|
|
3725
3725
|
for (let i = 0; i < node.items.length; ++i) {
|
|
3726
|
-
const ci2 = visit_(i, node.items[i], visitor,
|
|
3726
|
+
const ci2 = visit_(i, node.items[i], visitor, path45);
|
|
3727
3727
|
if (typeof ci2 === "number")
|
|
3728
3728
|
i = ci2 - 1;
|
|
3729
3729
|
else if (ci2 === BREAK)
|
|
@@ -3734,13 +3734,13 @@ var require_visit = __commonJS({
|
|
|
3734
3734
|
}
|
|
3735
3735
|
}
|
|
3736
3736
|
} else if (identity.isPair(node)) {
|
|
3737
|
-
|
|
3738
|
-
const ck = visit_("key", node.key, visitor,
|
|
3737
|
+
path45 = Object.freeze(path45.concat(node));
|
|
3738
|
+
const ck = visit_("key", node.key, visitor, path45);
|
|
3739
3739
|
if (ck === BREAK)
|
|
3740
3740
|
return BREAK;
|
|
3741
3741
|
else if (ck === REMOVE)
|
|
3742
3742
|
node.key = null;
|
|
3743
|
-
const cv = visit_("value", node.value, visitor,
|
|
3743
|
+
const cv = visit_("value", node.value, visitor, path45);
|
|
3744
3744
|
if (cv === BREAK)
|
|
3745
3745
|
return BREAK;
|
|
3746
3746
|
else if (cv === REMOVE)
|
|
@@ -3761,17 +3761,17 @@ var require_visit = __commonJS({
|
|
|
3761
3761
|
visitAsync.BREAK = BREAK;
|
|
3762
3762
|
visitAsync.SKIP = SKIP;
|
|
3763
3763
|
visitAsync.REMOVE = REMOVE;
|
|
3764
|
-
async function visitAsync_(key, node, visitor,
|
|
3765
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
3764
|
+
async function visitAsync_(key, node, visitor, path45) {
|
|
3765
|
+
const ctrl = await callVisitor(key, node, visitor, path45);
|
|
3766
3766
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
3767
|
-
replaceNode(key,
|
|
3768
|
-
return visitAsync_(key, ctrl, visitor,
|
|
3767
|
+
replaceNode(key, path45, ctrl);
|
|
3768
|
+
return visitAsync_(key, ctrl, visitor, path45);
|
|
3769
3769
|
}
|
|
3770
3770
|
if (typeof ctrl !== "symbol") {
|
|
3771
3771
|
if (identity.isCollection(node)) {
|
|
3772
|
-
|
|
3772
|
+
path45 = Object.freeze(path45.concat(node));
|
|
3773
3773
|
for (let i = 0; i < node.items.length; ++i) {
|
|
3774
|
-
const ci2 = await visitAsync_(i, node.items[i], visitor,
|
|
3774
|
+
const ci2 = await visitAsync_(i, node.items[i], visitor, path45);
|
|
3775
3775
|
if (typeof ci2 === "number")
|
|
3776
3776
|
i = ci2 - 1;
|
|
3777
3777
|
else if (ci2 === BREAK)
|
|
@@ -3782,13 +3782,13 @@ var require_visit = __commonJS({
|
|
|
3782
3782
|
}
|
|
3783
3783
|
}
|
|
3784
3784
|
} else if (identity.isPair(node)) {
|
|
3785
|
-
|
|
3786
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
3785
|
+
path45 = Object.freeze(path45.concat(node));
|
|
3786
|
+
const ck = await visitAsync_("key", node.key, visitor, path45);
|
|
3787
3787
|
if (ck === BREAK)
|
|
3788
3788
|
return BREAK;
|
|
3789
3789
|
else if (ck === REMOVE)
|
|
3790
3790
|
node.key = null;
|
|
3791
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
3791
|
+
const cv = await visitAsync_("value", node.value, visitor, path45);
|
|
3792
3792
|
if (cv === BREAK)
|
|
3793
3793
|
return BREAK;
|
|
3794
3794
|
else if (cv === REMOVE)
|
|
@@ -3815,23 +3815,23 @@ var require_visit = __commonJS({
|
|
|
3815
3815
|
}
|
|
3816
3816
|
return visitor;
|
|
3817
3817
|
}
|
|
3818
|
-
function callVisitor(key, node, visitor,
|
|
3818
|
+
function callVisitor(key, node, visitor, path45) {
|
|
3819
3819
|
if (typeof visitor === "function")
|
|
3820
|
-
return visitor(key, node,
|
|
3820
|
+
return visitor(key, node, path45);
|
|
3821
3821
|
if (identity.isMap(node))
|
|
3822
|
-
return visitor.Map?.(key, node,
|
|
3822
|
+
return visitor.Map?.(key, node, path45);
|
|
3823
3823
|
if (identity.isSeq(node))
|
|
3824
|
-
return visitor.Seq?.(key, node,
|
|
3824
|
+
return visitor.Seq?.(key, node, path45);
|
|
3825
3825
|
if (identity.isPair(node))
|
|
3826
|
-
return visitor.Pair?.(key, node,
|
|
3826
|
+
return visitor.Pair?.(key, node, path45);
|
|
3827
3827
|
if (identity.isScalar(node))
|
|
3828
|
-
return visitor.Scalar?.(key, node,
|
|
3828
|
+
return visitor.Scalar?.(key, node, path45);
|
|
3829
3829
|
if (identity.isAlias(node))
|
|
3830
|
-
return visitor.Alias?.(key, node,
|
|
3830
|
+
return visitor.Alias?.(key, node, path45);
|
|
3831
3831
|
return void 0;
|
|
3832
3832
|
}
|
|
3833
|
-
function replaceNode(key,
|
|
3834
|
-
const parent =
|
|
3833
|
+
function replaceNode(key, path45, node) {
|
|
3834
|
+
const parent = path45[path45.length - 1];
|
|
3835
3835
|
if (identity.isCollection(parent)) {
|
|
3836
3836
|
parent.items[key] = node;
|
|
3837
3837
|
} else if (identity.isPair(parent)) {
|
|
@@ -4439,10 +4439,10 @@ var require_Collection = __commonJS({
|
|
|
4439
4439
|
var createNode = require_createNode();
|
|
4440
4440
|
var identity = require_identity();
|
|
4441
4441
|
var Node = require_Node();
|
|
4442
|
-
function collectionFromPath(schema,
|
|
4442
|
+
function collectionFromPath(schema, path45, value) {
|
|
4443
4443
|
let v2 = value;
|
|
4444
|
-
for (let i =
|
|
4445
|
-
const k2 =
|
|
4444
|
+
for (let i = path45.length - 1; i >= 0; --i) {
|
|
4445
|
+
const k2 = path45[i];
|
|
4446
4446
|
if (typeof k2 === "number" && Number.isInteger(k2) && k2 >= 0) {
|
|
4447
4447
|
const a = [];
|
|
4448
4448
|
a[k2] = v2;
|
|
@@ -4461,7 +4461,7 @@ var require_Collection = __commonJS({
|
|
|
4461
4461
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
4462
4462
|
});
|
|
4463
4463
|
}
|
|
4464
|
-
var isEmptyPath = (
|
|
4464
|
+
var isEmptyPath = (path45) => path45 == null || typeof path45 === "object" && !!path45[Symbol.iterator]().next().done;
|
|
4465
4465
|
var Collection = class extends Node.NodeBase {
|
|
4466
4466
|
constructor(type, schema) {
|
|
4467
4467
|
super(type);
|
|
@@ -4491,11 +4491,11 @@ var require_Collection = __commonJS({
|
|
|
4491
4491
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
4492
4492
|
* that already exists in the map.
|
|
4493
4493
|
*/
|
|
4494
|
-
addIn(
|
|
4495
|
-
if (isEmptyPath(
|
|
4494
|
+
addIn(path45, value) {
|
|
4495
|
+
if (isEmptyPath(path45))
|
|
4496
4496
|
this.add(value);
|
|
4497
4497
|
else {
|
|
4498
|
-
const [key, ...rest] =
|
|
4498
|
+
const [key, ...rest] = path45;
|
|
4499
4499
|
const node = this.get(key, true);
|
|
4500
4500
|
if (identity.isCollection(node))
|
|
4501
4501
|
node.addIn(rest, value);
|
|
@@ -4509,8 +4509,8 @@ var require_Collection = __commonJS({
|
|
|
4509
4509
|
* Removes a value from the collection.
|
|
4510
4510
|
* @returns `true` if the item was found and removed.
|
|
4511
4511
|
*/
|
|
4512
|
-
deleteIn(
|
|
4513
|
-
const [key, ...rest] =
|
|
4512
|
+
deleteIn(path45) {
|
|
4513
|
+
const [key, ...rest] = path45;
|
|
4514
4514
|
if (rest.length === 0)
|
|
4515
4515
|
return this.delete(key);
|
|
4516
4516
|
const node = this.get(key, true);
|
|
@@ -4524,8 +4524,8 @@ var require_Collection = __commonJS({
|
|
|
4524
4524
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
4525
4525
|
* `true` (collections are always returned intact).
|
|
4526
4526
|
*/
|
|
4527
|
-
getIn(
|
|
4528
|
-
const [key, ...rest] =
|
|
4527
|
+
getIn(path45, keepScalar) {
|
|
4528
|
+
const [key, ...rest] = path45;
|
|
4529
4529
|
const node = this.get(key, true);
|
|
4530
4530
|
if (rest.length === 0)
|
|
4531
4531
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -4543,8 +4543,8 @@ var require_Collection = __commonJS({
|
|
|
4543
4543
|
/**
|
|
4544
4544
|
* Checks if the collection includes a value with the key `key`.
|
|
4545
4545
|
*/
|
|
4546
|
-
hasIn(
|
|
4547
|
-
const [key, ...rest] =
|
|
4546
|
+
hasIn(path45) {
|
|
4547
|
+
const [key, ...rest] = path45;
|
|
4548
4548
|
if (rest.length === 0)
|
|
4549
4549
|
return this.has(key);
|
|
4550
4550
|
const node = this.get(key, true);
|
|
@@ -4554,8 +4554,8 @@ var require_Collection = __commonJS({
|
|
|
4554
4554
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
4555
4555
|
* boolean to add/remove the item from the set.
|
|
4556
4556
|
*/
|
|
4557
|
-
setIn(
|
|
4558
|
-
const [key, ...rest] =
|
|
4557
|
+
setIn(path45, value) {
|
|
4558
|
+
const [key, ...rest] = path45;
|
|
4559
4559
|
if (rest.length === 0) {
|
|
4560
4560
|
this.set(key, value);
|
|
4561
4561
|
} else {
|
|
@@ -7067,9 +7067,9 @@ var require_Document = __commonJS({
|
|
|
7067
7067
|
this.contents.add(value);
|
|
7068
7068
|
}
|
|
7069
7069
|
/** Adds a value to the document. */
|
|
7070
|
-
addIn(
|
|
7070
|
+
addIn(path45, value) {
|
|
7071
7071
|
if (assertCollection(this.contents))
|
|
7072
|
-
this.contents.addIn(
|
|
7072
|
+
this.contents.addIn(path45, value);
|
|
7073
7073
|
}
|
|
7074
7074
|
/**
|
|
7075
7075
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -7144,14 +7144,14 @@ var require_Document = __commonJS({
|
|
|
7144
7144
|
* Removes a value from the document.
|
|
7145
7145
|
* @returns `true` if the item was found and removed.
|
|
7146
7146
|
*/
|
|
7147
|
-
deleteIn(
|
|
7148
|
-
if (Collection.isEmptyPath(
|
|
7147
|
+
deleteIn(path45) {
|
|
7148
|
+
if (Collection.isEmptyPath(path45)) {
|
|
7149
7149
|
if (this.contents == null)
|
|
7150
7150
|
return false;
|
|
7151
7151
|
this.contents = null;
|
|
7152
7152
|
return true;
|
|
7153
7153
|
}
|
|
7154
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
7154
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path45) : false;
|
|
7155
7155
|
}
|
|
7156
7156
|
/**
|
|
7157
7157
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -7166,10 +7166,10 @@ var require_Document = __commonJS({
|
|
|
7166
7166
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
7167
7167
|
* `true` (collections are always returned intact).
|
|
7168
7168
|
*/
|
|
7169
|
-
getIn(
|
|
7170
|
-
if (Collection.isEmptyPath(
|
|
7169
|
+
getIn(path45, keepScalar) {
|
|
7170
|
+
if (Collection.isEmptyPath(path45))
|
|
7171
7171
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
7172
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
7172
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path45, keepScalar) : void 0;
|
|
7173
7173
|
}
|
|
7174
7174
|
/**
|
|
7175
7175
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -7180,10 +7180,10 @@ var require_Document = __commonJS({
|
|
|
7180
7180
|
/**
|
|
7181
7181
|
* Checks if the document includes a value at `path`.
|
|
7182
7182
|
*/
|
|
7183
|
-
hasIn(
|
|
7184
|
-
if (Collection.isEmptyPath(
|
|
7183
|
+
hasIn(path45) {
|
|
7184
|
+
if (Collection.isEmptyPath(path45))
|
|
7185
7185
|
return this.contents !== void 0;
|
|
7186
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
7186
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path45) : false;
|
|
7187
7187
|
}
|
|
7188
7188
|
/**
|
|
7189
7189
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -7200,13 +7200,13 @@ var require_Document = __commonJS({
|
|
|
7200
7200
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
7201
7201
|
* boolean to add/remove the item from the set.
|
|
7202
7202
|
*/
|
|
7203
|
-
setIn(
|
|
7204
|
-
if (Collection.isEmptyPath(
|
|
7203
|
+
setIn(path45, value) {
|
|
7204
|
+
if (Collection.isEmptyPath(path45)) {
|
|
7205
7205
|
this.contents = value;
|
|
7206
7206
|
} else if (this.contents == null) {
|
|
7207
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
7207
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path45), value);
|
|
7208
7208
|
} else if (assertCollection(this.contents)) {
|
|
7209
|
-
this.contents.setIn(
|
|
7209
|
+
this.contents.setIn(path45, value);
|
|
7210
7210
|
}
|
|
7211
7211
|
}
|
|
7212
7212
|
/**
|
|
@@ -9163,9 +9163,9 @@ var require_cst_visit = __commonJS({
|
|
|
9163
9163
|
visit.BREAK = BREAK;
|
|
9164
9164
|
visit.SKIP = SKIP;
|
|
9165
9165
|
visit.REMOVE = REMOVE;
|
|
9166
|
-
visit.itemAtPath = (cst,
|
|
9166
|
+
visit.itemAtPath = (cst, path45) => {
|
|
9167
9167
|
let item = cst;
|
|
9168
|
-
for (const [field, index] of
|
|
9168
|
+
for (const [field, index] of path45) {
|
|
9169
9169
|
const tok = item?.[field];
|
|
9170
9170
|
if (tok && "items" in tok) {
|
|
9171
9171
|
item = tok.items[index];
|
|
@@ -9174,23 +9174,23 @@ var require_cst_visit = __commonJS({
|
|
|
9174
9174
|
}
|
|
9175
9175
|
return item;
|
|
9176
9176
|
};
|
|
9177
|
-
visit.parentCollection = (cst,
|
|
9178
|
-
const parent = visit.itemAtPath(cst,
|
|
9179
|
-
const field =
|
|
9177
|
+
visit.parentCollection = (cst, path45) => {
|
|
9178
|
+
const parent = visit.itemAtPath(cst, path45.slice(0, -1));
|
|
9179
|
+
const field = path45[path45.length - 1][0];
|
|
9180
9180
|
const coll = parent?.[field];
|
|
9181
9181
|
if (coll && "items" in coll)
|
|
9182
9182
|
return coll;
|
|
9183
9183
|
throw new Error("Parent collection not found");
|
|
9184
9184
|
};
|
|
9185
|
-
function _visit(
|
|
9186
|
-
let ctrl = visitor(item,
|
|
9185
|
+
function _visit(path45, item, visitor) {
|
|
9186
|
+
let ctrl = visitor(item, path45);
|
|
9187
9187
|
if (typeof ctrl === "symbol")
|
|
9188
9188
|
return ctrl;
|
|
9189
9189
|
for (const field of ["key", "value"]) {
|
|
9190
9190
|
const token = item[field];
|
|
9191
9191
|
if (token && "items" in token) {
|
|
9192
9192
|
for (let i = 0; i < token.items.length; ++i) {
|
|
9193
|
-
const ci2 = _visit(Object.freeze(
|
|
9193
|
+
const ci2 = _visit(Object.freeze(path45.concat([[field, i]])), token.items[i], visitor);
|
|
9194
9194
|
if (typeof ci2 === "number")
|
|
9195
9195
|
i = ci2 - 1;
|
|
9196
9196
|
else if (ci2 === BREAK)
|
|
@@ -9201,10 +9201,10 @@ var require_cst_visit = __commonJS({
|
|
|
9201
9201
|
}
|
|
9202
9202
|
}
|
|
9203
9203
|
if (typeof ctrl === "function" && field === "key")
|
|
9204
|
-
ctrl = ctrl(item,
|
|
9204
|
+
ctrl = ctrl(item, path45);
|
|
9205
9205
|
}
|
|
9206
9206
|
}
|
|
9207
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
9207
|
+
return typeof ctrl === "function" ? ctrl(item, path45) : ctrl;
|
|
9208
9208
|
}
|
|
9209
9209
|
exports2.visit = visit;
|
|
9210
9210
|
}
|
|
@@ -10489,14 +10489,14 @@ var require_parser = __commonJS({
|
|
|
10489
10489
|
case "scalar":
|
|
10490
10490
|
case "single-quoted-scalar":
|
|
10491
10491
|
case "double-quoted-scalar": {
|
|
10492
|
-
const
|
|
10492
|
+
const fs44 = this.flowScalar(this.type);
|
|
10493
10493
|
if (atNextItem || it2.value) {
|
|
10494
|
-
map.items.push({ start, key:
|
|
10494
|
+
map.items.push({ start, key: fs44, sep: [] });
|
|
10495
10495
|
this.onKeyLine = true;
|
|
10496
10496
|
} else if (it2.sep) {
|
|
10497
|
-
this.stack.push(
|
|
10497
|
+
this.stack.push(fs44);
|
|
10498
10498
|
} else {
|
|
10499
|
-
Object.assign(it2, { key:
|
|
10499
|
+
Object.assign(it2, { key: fs44, sep: [] });
|
|
10500
10500
|
this.onKeyLine = true;
|
|
10501
10501
|
}
|
|
10502
10502
|
return;
|
|
@@ -10624,13 +10624,13 @@ var require_parser = __commonJS({
|
|
|
10624
10624
|
case "scalar":
|
|
10625
10625
|
case "single-quoted-scalar":
|
|
10626
10626
|
case "double-quoted-scalar": {
|
|
10627
|
-
const
|
|
10627
|
+
const fs44 = this.flowScalar(this.type);
|
|
10628
10628
|
if (!it2 || it2.value)
|
|
10629
|
-
fc.items.push({ start: [], key:
|
|
10629
|
+
fc.items.push({ start: [], key: fs44, sep: [] });
|
|
10630
10630
|
else if (it2.sep)
|
|
10631
|
-
this.stack.push(
|
|
10631
|
+
this.stack.push(fs44);
|
|
10632
10632
|
else
|
|
10633
|
-
Object.assign(it2, { key:
|
|
10633
|
+
Object.assign(it2, { key: fs44, sep: [] });
|
|
10634
10634
|
return;
|
|
10635
10635
|
}
|
|
10636
10636
|
case "flow-map-end":
|
|
@@ -17834,8 +17834,8 @@ async function runCacheClearCommand(options, logger) {
|
|
|
17834
17834
|
}
|
|
17835
17835
|
|
|
17836
17836
|
// src/commands/cleanup.ts
|
|
17837
|
-
import
|
|
17838
|
-
import
|
|
17837
|
+
import fs24 from "fs";
|
|
17838
|
+
import path22 from "path";
|
|
17839
17839
|
|
|
17840
17840
|
// node_modules/glob/dist/esm/index.min.js
|
|
17841
17841
|
import { fileURLToPath as Wi } from "url";
|
|
@@ -20832,6 +20832,7 @@ var KNOWN_COMPONENTS = /* @__PURE__ */ new Set([
|
|
|
20832
20832
|
"hooks",
|
|
20833
20833
|
"output-styles"
|
|
20834
20834
|
]);
|
|
20835
|
+
var KNOWN_INSTRUCTION_FILES = /* @__PURE__ */ new Set(["AGENTS.md", "CLAUDE.md"]);
|
|
20835
20836
|
var LEGACY_SOURCE_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
20836
20837
|
"operational-framework",
|
|
20837
20838
|
"operational-machinery"
|
|
@@ -20891,7 +20892,7 @@ function isOurStaleSymlink(linkPath, managedPaths, config) {
|
|
|
20891
20892
|
const lastSegment = path17.basename(linkTarget);
|
|
20892
20893
|
const parentSegment = path17.basename(path17.dirname(linkTarget));
|
|
20893
20894
|
if (isBroken) {
|
|
20894
|
-
return KNOWN_COMPONENTS.has(lastSegment) || KNOWN_COMPONENTS.has(parentSegment) || knownFiles.has(lastSegment);
|
|
20895
|
+
return KNOWN_COMPONENTS.has(lastSegment) || KNOWN_COMPONENTS.has(parentSegment) || KNOWN_INSTRUCTION_FILES.has(lastSegment) || knownFiles.has(lastSegment);
|
|
20895
20896
|
}
|
|
20896
20897
|
const targetSegments = absoluteTarget.split(path17.sep);
|
|
20897
20898
|
const traversesLegacyRoot = targetSegments.some(
|
|
@@ -20980,8 +20981,8 @@ function removeManagedEntries(filePath, parser, serializer, removeManaged, logge
|
|
|
20980
20981
|
}
|
|
20981
20982
|
|
|
20982
20983
|
// src/commands/uninstall.ts
|
|
20983
|
-
import
|
|
20984
|
-
import
|
|
20984
|
+
import fs23 from "fs";
|
|
20985
|
+
import path21 from "path";
|
|
20985
20986
|
|
|
20986
20987
|
// src/core/managed-sources.ts
|
|
20987
20988
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
@@ -21047,38 +21048,195 @@ function normalizeManagedSourcePath(rawPath) {
|
|
|
21047
21048
|
return normalized.startsWith("./") ? normalized.slice(2) : normalized;
|
|
21048
21049
|
}
|
|
21049
21050
|
|
|
21050
|
-
// src/
|
|
21051
|
+
// src/compiler/hook-components.ts
|
|
21052
|
+
var import_yaml6 = __toESM(require_dist(), 1);
|
|
21051
21053
|
import fs21 from "fs";
|
|
21054
|
+
import path20 from "path";
|
|
21055
|
+
function parseHookDeclaration(filePath) {
|
|
21056
|
+
let raw;
|
|
21057
|
+
try {
|
|
21058
|
+
raw = fs21.readFileSync(filePath, "utf8");
|
|
21059
|
+
} catch {
|
|
21060
|
+
return null;
|
|
21061
|
+
}
|
|
21062
|
+
const fm = extractFrontmatter(raw);
|
|
21063
|
+
if (!fm) {
|
|
21064
|
+
return null;
|
|
21065
|
+
}
|
|
21066
|
+
const { name, description, events } = fm;
|
|
21067
|
+
if (typeof name !== "string" || !name.trim()) {
|
|
21068
|
+
return null;
|
|
21069
|
+
}
|
|
21070
|
+
if (typeof description !== "string" || !description.trim()) {
|
|
21071
|
+
return null;
|
|
21072
|
+
}
|
|
21073
|
+
if (!Array.isArray(events) || events.length === 0) {
|
|
21074
|
+
return null;
|
|
21075
|
+
}
|
|
21076
|
+
const parsedEvents = [];
|
|
21077
|
+
for (const entry of events) {
|
|
21078
|
+
if (!entry || typeof entry !== "object") {
|
|
21079
|
+
return null;
|
|
21080
|
+
}
|
|
21081
|
+
const ev = entry;
|
|
21082
|
+
if (typeof ev.event !== "string" || !ev.event.trim()) {
|
|
21083
|
+
return null;
|
|
21084
|
+
}
|
|
21085
|
+
if (typeof ev.timeout !== "number") {
|
|
21086
|
+
return null;
|
|
21087
|
+
}
|
|
21088
|
+
if (typeof ev.statusMessage !== "string" || !ev.statusMessage.trim()) {
|
|
21089
|
+
return null;
|
|
21090
|
+
}
|
|
21091
|
+
const parsed = {
|
|
21092
|
+
event: ev.event,
|
|
21093
|
+
timeout: ev.timeout,
|
|
21094
|
+
statusMessage: ev.statusMessage
|
|
21095
|
+
};
|
|
21096
|
+
if (typeof ev.matcher === "string" && ev.matcher.trim()) {
|
|
21097
|
+
parsed.matcher = ev.matcher;
|
|
21098
|
+
}
|
|
21099
|
+
parsedEvents.push(parsed);
|
|
21100
|
+
}
|
|
21101
|
+
return {
|
|
21102
|
+
name: name.trim(),
|
|
21103
|
+
description: description.trim(),
|
|
21104
|
+
events: parsedEvents
|
|
21105
|
+
};
|
|
21106
|
+
}
|
|
21107
|
+
function hookCommand(name) {
|
|
21108
|
+
return `npx tsx ~/.agents/hooks/scripts/${name}.ts`;
|
|
21109
|
+
}
|
|
21110
|
+
function synthesizeHooksJson(declarations) {
|
|
21111
|
+
const hooks = {};
|
|
21112
|
+
for (const decl of declarations) {
|
|
21113
|
+
for (const ev of decl.events) {
|
|
21114
|
+
if (!hooks[ev.event]) {
|
|
21115
|
+
hooks[ev.event] = [];
|
|
21116
|
+
}
|
|
21117
|
+
const entry = {
|
|
21118
|
+
hooks: [
|
|
21119
|
+
{
|
|
21120
|
+
type: "command",
|
|
21121
|
+
command: hookCommand(decl.name),
|
|
21122
|
+
timeout: ev.timeout,
|
|
21123
|
+
statusMessage: ev.statusMessage
|
|
21124
|
+
}
|
|
21125
|
+
]
|
|
21126
|
+
};
|
|
21127
|
+
if (ev.matcher !== void 0) {
|
|
21128
|
+
const ordered = {
|
|
21129
|
+
matcher: ev.matcher,
|
|
21130
|
+
hooks: entry.hooks
|
|
21131
|
+
};
|
|
21132
|
+
hooks[ev.event].push(ordered);
|
|
21133
|
+
} else {
|
|
21134
|
+
hooks[ev.event].push(entry);
|
|
21135
|
+
}
|
|
21136
|
+
}
|
|
21137
|
+
}
|
|
21138
|
+
return { hooks };
|
|
21139
|
+
}
|
|
21140
|
+
function loadSourceHooks(hooksDir, hookNames) {
|
|
21141
|
+
const hooksJsonPath = path20.join(hooksDir, "hooks.json");
|
|
21142
|
+
if (fs21.existsSync(hooksJsonPath)) {
|
|
21143
|
+
const raw = fs21.readFileSync(hooksJsonPath, "utf8");
|
|
21144
|
+
return JSON.parse(raw);
|
|
21145
|
+
}
|
|
21146
|
+
const declarations = loadHookDeclarations(hooksDir, hookNames);
|
|
21147
|
+
return synthesizeHooksJson(declarations);
|
|
21148
|
+
}
|
|
21149
|
+
function loadHookDeclarations(hooksDir, hookNames) {
|
|
21150
|
+
let names;
|
|
21151
|
+
if (hookNames && hookNames.length > 0) {
|
|
21152
|
+
names = hookNames;
|
|
21153
|
+
} else {
|
|
21154
|
+
if (!fs21.existsSync(hooksDir) || !fs21.statSync(hooksDir).isDirectory()) {
|
|
21155
|
+
return [];
|
|
21156
|
+
}
|
|
21157
|
+
names = fs21.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
|
|
21158
|
+
}
|
|
21159
|
+
const declarations = [];
|
|
21160
|
+
for (const name of names) {
|
|
21161
|
+
const filePath = path20.join(hooksDir, `${name}.md`);
|
|
21162
|
+
const decl = parseHookDeclaration(filePath);
|
|
21163
|
+
if (decl) {
|
|
21164
|
+
declarations.push(decl);
|
|
21165
|
+
}
|
|
21166
|
+
}
|
|
21167
|
+
return declarations;
|
|
21168
|
+
}
|
|
21169
|
+
function extractFrontmatter(content) {
|
|
21170
|
+
if (!content.startsWith("---\n")) {
|
|
21171
|
+
return null;
|
|
21172
|
+
}
|
|
21173
|
+
const endIndex = content.indexOf("\n---", 4);
|
|
21174
|
+
if (endIndex === -1) {
|
|
21175
|
+
return null;
|
|
21176
|
+
}
|
|
21177
|
+
const rawFm = content.slice(4, endIndex);
|
|
21178
|
+
let parsed;
|
|
21179
|
+
try {
|
|
21180
|
+
parsed = (0, import_yaml6.parse)(rawFm);
|
|
21181
|
+
} catch {
|
|
21182
|
+
return null;
|
|
21183
|
+
}
|
|
21184
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
21185
|
+
return null;
|
|
21186
|
+
}
|
|
21187
|
+
return parsed;
|
|
21188
|
+
}
|
|
21189
|
+
|
|
21190
|
+
// src/core/remove.ts
|
|
21191
|
+
import fs22 from "fs";
|
|
21052
21192
|
function removeManagedPath(managedPath) {
|
|
21053
21193
|
let stat;
|
|
21054
21194
|
try {
|
|
21055
|
-
stat =
|
|
21195
|
+
stat = fs22.lstatSync(managedPath);
|
|
21056
21196
|
} catch {
|
|
21057
21197
|
return;
|
|
21058
21198
|
}
|
|
21059
21199
|
if (stat.isSymbolicLink() || stat.isFile()) {
|
|
21060
|
-
|
|
21200
|
+
fs22.unlinkSync(managedPath);
|
|
21061
21201
|
return;
|
|
21062
21202
|
}
|
|
21063
21203
|
if (stat.isDirectory()) {
|
|
21064
|
-
|
|
21204
|
+
fs22.rmSync(managedPath, { recursive: true, force: true });
|
|
21065
21205
|
}
|
|
21066
21206
|
}
|
|
21067
21207
|
|
|
21068
21208
|
// src/commands/uninstall.ts
|
|
21069
21209
|
var codexManagedMcpStart = "# tangyr: managed mcp start";
|
|
21070
21210
|
var codexManagedMcpEnd = "# tangyr: managed mcp end";
|
|
21211
|
+
var legacyClaudeSharedPermission = "Read(~/.agents/**)";
|
|
21212
|
+
var legacyOperatingGuideSignature = "# Agent Coding \u2014 Operating Guide\n\n_Structured authoring with LLM agents across the full artifact continuum._";
|
|
21071
21213
|
var SHARED_CLAUDE_SLOTS = /* @__PURE__ */ new Set([
|
|
21072
21214
|
"mcp_shared_file",
|
|
21073
21215
|
"hooks"
|
|
21074
21216
|
]);
|
|
21217
|
+
function resolveClaudeCodePathsForRoots(roots, mappings) {
|
|
21218
|
+
return roots.map((root) => resolveClaudeCodeProfileForRoot(root, mappings));
|
|
21219
|
+
}
|
|
21075
21220
|
async function runUninstallCommand(options, logger) {
|
|
21076
21221
|
const scope = options.scope === "global" ? "global" : "project";
|
|
21077
21222
|
const scopePath = resolveScopePath(
|
|
21078
21223
|
scope,
|
|
21079
21224
|
scope === "project" ? process.cwd() : void 0
|
|
21080
21225
|
);
|
|
21081
|
-
const
|
|
21226
|
+
const runtime = resolveRuntimeIfAvailable(options, logger);
|
|
21227
|
+
const persistedManifest = readStrictManifest(scopePath);
|
|
21228
|
+
const manifestWasPresent = persistedManifest !== null;
|
|
21229
|
+
let manifest = persistedManifest;
|
|
21230
|
+
if (!manifest && scope === "global" && runtime?.kitInfo) {
|
|
21231
|
+
manifest = createEmptyManifest(
|
|
21232
|
+
runtime.kitInfo.archetype,
|
|
21233
|
+
runtime.kitInfo.kitFormat,
|
|
21234
|
+
"global"
|
|
21235
|
+
);
|
|
21236
|
+
logger.warn(
|
|
21237
|
+
`No Tangyr manifest found in ${scope} scope; reconciling ownership evidence on disk.`
|
|
21238
|
+
);
|
|
21239
|
+
}
|
|
21082
21240
|
if (!manifest) {
|
|
21083
21241
|
logger.error(
|
|
21084
21242
|
`No Tangyr installation found in ${scope} scope (${scopePath}).`
|
|
@@ -21086,15 +21244,25 @@ async function runUninstallCommand(options, logger) {
|
|
|
21086
21244
|
logger.info("Nothing to uninstall.");
|
|
21087
21245
|
process.exit(1);
|
|
21088
21246
|
}
|
|
21089
|
-
const runtime = resolveRuntimeIfAvailable(options, logger);
|
|
21090
21247
|
const selectedTools = resolveSelectedTools(options.tools, manifest, runtime);
|
|
21091
21248
|
const manifestArtifacts = manifest.artifacts.filter(
|
|
21092
21249
|
(file) => shouldRemoveManifestFile(file.relativePath, selectedTools)
|
|
21093
21250
|
);
|
|
21094
|
-
const kitArtifacts = runtime ? resolveKitManagedArtifacts(
|
|
21095
|
-
|
|
21096
|
-
|
|
21097
|
-
|
|
21251
|
+
const kitArtifacts = runtime ? resolveKitManagedArtifacts(
|
|
21252
|
+
runtime,
|
|
21253
|
+
scope,
|
|
21254
|
+
selectedTools,
|
|
21255
|
+
manifest,
|
|
21256
|
+
options.claudeConfigDir
|
|
21257
|
+
).filter((artifact) => isKitManagedArtifact(artifact, runtime)) : [];
|
|
21258
|
+
const useManifestPathRemoval = scope !== "global" || runtime === void 0;
|
|
21259
|
+
if (manifestWasPresent) {
|
|
21260
|
+
logger.info(
|
|
21261
|
+
`Found Tangyr installation: archetype ${manifest.archetype}, version ${manifest.version}`
|
|
21262
|
+
);
|
|
21263
|
+
} else {
|
|
21264
|
+
logger.info(`Scanning Tangyr residue for archetype ${manifest.archetype}`);
|
|
21265
|
+
}
|
|
21098
21266
|
logger.info(`Scope: ${scope} (${scopePath})`);
|
|
21099
21267
|
logger.info(
|
|
21100
21268
|
`Tools: ${Array.from(selectedTools).join(", ") || manifest.tools.join(", ") || "(none)"}`
|
|
@@ -21105,8 +21273,10 @@ async function runUninstallCommand(options, logger) {
|
|
|
21105
21273
|
}
|
|
21106
21274
|
if (options.dryRun) {
|
|
21107
21275
|
logger.info("\n[dry-run] Would remove:");
|
|
21108
|
-
|
|
21109
|
-
|
|
21276
|
+
if (useManifestPathRemoval) {
|
|
21277
|
+
for (const file of manifestArtifacts) {
|
|
21278
|
+
logger.info(` ${file.relativePath}`);
|
|
21279
|
+
}
|
|
21110
21280
|
}
|
|
21111
21281
|
for (const artifact of kitArtifacts) {
|
|
21112
21282
|
logger.info(` ${artifact.path}`);
|
|
@@ -21121,7 +21291,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21121
21291
|
}
|
|
21122
21292
|
if (!options.yes) {
|
|
21123
21293
|
const proceed = await dist_default5({
|
|
21124
|
-
message: `Remove Tangyr from ${scope} scope? This will delete ${manifestArtifacts.length + kitArtifacts.length} managed file(s).`
|
|
21294
|
+
message: `Remove Tangyr from ${scope} scope? This will delete ${(useManifestPathRemoval ? manifestArtifacts.length : 0) + kitArtifacts.length} managed file(s).`
|
|
21125
21295
|
});
|
|
21126
21296
|
if (!proceed) {
|
|
21127
21297
|
logger.info("Uninstallation aborted.");
|
|
@@ -21130,7 +21300,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21130
21300
|
}
|
|
21131
21301
|
const claudeRoots = scope === "global" && selectedTools.has("claude-code") ? resolveClaudeRootsForUninstall(manifest, runtime) : [];
|
|
21132
21302
|
let removedCount = 0;
|
|
21133
|
-
for (const file of manifestArtifacts) {
|
|
21303
|
+
for (const file of useManifestPathRemoval ? manifestArtifacts : []) {
|
|
21134
21304
|
const isClaudeGlobal = file.relativePath.startsWith("claude-code/") && scope === "global";
|
|
21135
21305
|
if (isClaudeGlobal && claudeRoots.length > 0) {
|
|
21136
21306
|
const paths = resolveManifestKeyToMultiPaths(
|
|
@@ -21139,7 +21309,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21139
21309
|
runtime
|
|
21140
21310
|
);
|
|
21141
21311
|
for (const actualPath of paths) {
|
|
21142
|
-
if (actualPath && (
|
|
21312
|
+
if (actualPath && (fs23.existsSync(actualPath) || isSymlink(actualPath))) {
|
|
21143
21313
|
removeManagedPath(actualPath);
|
|
21144
21314
|
logger.verbose(` removed: ${actualPath}`);
|
|
21145
21315
|
removedCount++;
|
|
@@ -21153,7 +21323,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21153
21323
|
scope,
|
|
21154
21324
|
runtime
|
|
21155
21325
|
);
|
|
21156
|
-
if (actualPath && (
|
|
21326
|
+
if (actualPath && (fs23.existsSync(actualPath) || isSymlink(actualPath))) {
|
|
21157
21327
|
removeManagedPath(actualPath);
|
|
21158
21328
|
logger.verbose(` removed: ${actualPath}`);
|
|
21159
21329
|
removedCount++;
|
|
@@ -21168,32 +21338,46 @@ async function runUninstallCommand(options, logger) {
|
|
|
21168
21338
|
removedCount++;
|
|
21169
21339
|
}
|
|
21170
21340
|
}
|
|
21341
|
+
const residuals = resolveKitManagedArtifacts(
|
|
21342
|
+
runtime,
|
|
21343
|
+
scope,
|
|
21344
|
+
selectedTools,
|
|
21345
|
+
manifest,
|
|
21346
|
+
options.claudeConfigDir
|
|
21347
|
+
).filter((artifact) => isKitManagedArtifact(artifact, runtime));
|
|
21348
|
+
if (residuals.length > 0) {
|
|
21349
|
+
throw new Error(
|
|
21350
|
+
`Uninstall incomplete: ${residuals.length} managed artifact(s) remain: ${residuals.map((artifact) => artifact.path).join(", ")}`
|
|
21351
|
+
);
|
|
21352
|
+
}
|
|
21171
21353
|
}
|
|
21172
21354
|
const fullUninstall = isFullToolUninstall(manifest, selectedTools);
|
|
21173
21355
|
if (fullUninstall) {
|
|
21174
21356
|
for (const backup of manifest.backups) {
|
|
21175
21357
|
restoreBackup(backup, logger);
|
|
21176
21358
|
}
|
|
21177
|
-
const manifestPath =
|
|
21178
|
-
if (
|
|
21179
|
-
|
|
21359
|
+
const manifestPath = path21.join(scopePath, "manifest.json");
|
|
21360
|
+
if (fs23.existsSync(manifestPath)) {
|
|
21361
|
+
fs23.unlinkSync(manifestPath);
|
|
21180
21362
|
logger.verbose(` removed manifest: ${manifestPath}`);
|
|
21181
21363
|
}
|
|
21182
21364
|
try {
|
|
21183
|
-
const remaining =
|
|
21365
|
+
const remaining = fs23.readdirSync(scopePath);
|
|
21184
21366
|
if (remaining.length === 0) {
|
|
21185
|
-
|
|
21367
|
+
fs23.rmdirSync(scopePath);
|
|
21186
21368
|
logger.verbose(` removed empty scope directory: ${scopePath}`);
|
|
21187
21369
|
}
|
|
21188
21370
|
} catch {
|
|
21189
21371
|
}
|
|
21190
|
-
} else {
|
|
21372
|
+
} else if (manifestWasPresent) {
|
|
21191
21373
|
manifest.artifacts = manifest.artifacts.filter(
|
|
21192
21374
|
(file) => !shouldRemoveManifestFile(file.relativePath, selectedTools)
|
|
21193
21375
|
);
|
|
21194
21376
|
manifest.tools = manifest.tools.filter((tool) => !selectedTools.has(tool));
|
|
21195
21377
|
writeManifest(scopePath, manifest);
|
|
21196
21378
|
logger.verbose(" updated manifest for partial uninstall");
|
|
21379
|
+
} else {
|
|
21380
|
+
logger.verbose(" no manifest to update after partial residue cleanup");
|
|
21197
21381
|
}
|
|
21198
21382
|
logger.info(`
|
|
21199
21383
|
Uninstallation complete: ${removedCount} file(s) removed.`);
|
|
@@ -21220,7 +21404,7 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21220
21404
|
if (!slotPath) {
|
|
21221
21405
|
return null;
|
|
21222
21406
|
}
|
|
21223
|
-
return subPath ?
|
|
21407
|
+
return subPath ? path21.join(slotPath, subPath) : slotPath;
|
|
21224
21408
|
}
|
|
21225
21409
|
if (tool === "copilot") {
|
|
21226
21410
|
const copilotPaths = resolveCopilotPaths(runtime, scope, projectRoot);
|
|
@@ -21228,18 +21412,18 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21228
21412
|
return copilotPaths.skills;
|
|
21229
21413
|
}
|
|
21230
21414
|
if (component.startsWith("agents/")) {
|
|
21231
|
-
return
|
|
21415
|
+
return path21.join(copilotPaths.agents, component.slice("agents/".length));
|
|
21232
21416
|
}
|
|
21233
21417
|
if (component.startsWith("prompts/")) {
|
|
21234
|
-
return
|
|
21418
|
+
return path21.join(
|
|
21235
21419
|
copilotPaths.prompts,
|
|
21236
21420
|
component.slice("prompts/".length)
|
|
21237
21421
|
);
|
|
21238
21422
|
}
|
|
21239
21423
|
if (component.startsWith("hooks/")) {
|
|
21240
|
-
return
|
|
21424
|
+
return path21.join(copilotPaths.hooks, component.slice("hooks/".length));
|
|
21241
21425
|
}
|
|
21242
|
-
if (component ===
|
|
21426
|
+
if (component === path21.basename(copilotPaths.mcpSharedFile)) {
|
|
21243
21427
|
return copilotPaths.mcpSharedFile;
|
|
21244
21428
|
}
|
|
21245
21429
|
return null;
|
|
@@ -21253,15 +21437,15 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21253
21437
|
return codexPaths.skills;
|
|
21254
21438
|
}
|
|
21255
21439
|
if (component.startsWith("agents/")) {
|
|
21256
|
-
return
|
|
21440
|
+
return path21.join(codexPaths.agents, component.slice("agents/".length));
|
|
21257
21441
|
}
|
|
21258
21442
|
if (component.startsWith("rules/")) {
|
|
21259
|
-
return
|
|
21443
|
+
return path21.join(codexPaths.rules, component.slice("rules/".length));
|
|
21260
21444
|
}
|
|
21261
|
-
if (component ===
|
|
21445
|
+
if (component === path21.basename(codexPaths.hooksSharedFile)) {
|
|
21262
21446
|
return codexPaths.hooksSharedFile;
|
|
21263
21447
|
}
|
|
21264
|
-
if (component ===
|
|
21448
|
+
if (component === path21.basename(codexPaths.mcpSharedFile)) {
|
|
21265
21449
|
return codexPaths.mcpSharedFile;
|
|
21266
21450
|
}
|
|
21267
21451
|
return null;
|
|
@@ -21278,15 +21462,15 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21278
21462
|
return opencodePaths.skillsShared;
|
|
21279
21463
|
}
|
|
21280
21464
|
if (component.startsWith("agents/")) {
|
|
21281
|
-
return
|
|
21465
|
+
return path21.join(opencodePaths.agents, component.slice("agents/".length));
|
|
21282
21466
|
}
|
|
21283
21467
|
if (component.startsWith("commands/")) {
|
|
21284
|
-
return
|
|
21468
|
+
return path21.join(
|
|
21285
21469
|
opencodePaths.commands,
|
|
21286
21470
|
component.slice("commands/".length)
|
|
21287
21471
|
);
|
|
21288
21472
|
}
|
|
21289
|
-
if (component ===
|
|
21473
|
+
if (component === path21.basename(opencodePaths.configDoc)) {
|
|
21290
21474
|
return opencodePaths.configDoc;
|
|
21291
21475
|
}
|
|
21292
21476
|
return null;
|
|
@@ -21312,13 +21496,13 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21312
21496
|
return cursorPaths.permissionsFile;
|
|
21313
21497
|
}
|
|
21314
21498
|
if (component.startsWith("agents/")) {
|
|
21315
|
-
return
|
|
21499
|
+
return path21.join(cursorPaths.agents, component.slice("agents/".length));
|
|
21316
21500
|
}
|
|
21317
21501
|
if (component.startsWith("rules/")) {
|
|
21318
|
-
return
|
|
21502
|
+
return path21.join(cursorPaths.rules, component.slice("rules/".length));
|
|
21319
21503
|
}
|
|
21320
21504
|
if (component.startsWith("skills/")) {
|
|
21321
|
-
return
|
|
21505
|
+
return path21.join(cursorPaths.skills, component.slice("skills/".length));
|
|
21322
21506
|
}
|
|
21323
21507
|
return null;
|
|
21324
21508
|
}
|
|
@@ -21334,10 +21518,10 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21334
21518
|
return clinePaths.mcpFile;
|
|
21335
21519
|
}
|
|
21336
21520
|
if (component.startsWith("rules/")) {
|
|
21337
|
-
return
|
|
21521
|
+
return path21.join(clinePaths.rules, component.slice("rules/".length));
|
|
21338
21522
|
}
|
|
21339
21523
|
if (component.startsWith("workflows/")) {
|
|
21340
|
-
return
|
|
21524
|
+
return path21.join(
|
|
21341
21525
|
clinePaths.workflows,
|
|
21342
21526
|
component.slice("workflows/".length)
|
|
21343
21527
|
);
|
|
@@ -21371,22 +21555,22 @@ function resolveClaudeCodePaths(runtime, scope, projectRoot) {
|
|
|
21371
21555
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21372
21556
|
if (scope === "global") {
|
|
21373
21557
|
return {
|
|
21374
|
-
instructions:
|
|
21375
|
-
agents:
|
|
21376
|
-
skills:
|
|
21377
|
-
commands:
|
|
21378
|
-
rules:
|
|
21379
|
-
output_styles:
|
|
21558
|
+
instructions: path21.join(home, ".claude", "CLAUDE.md"),
|
|
21559
|
+
agents: path21.join(home, ".claude", "agents"),
|
|
21560
|
+
skills: path21.join(home, ".claude", "skills"),
|
|
21561
|
+
commands: path21.join(home, ".claude", "commands"),
|
|
21562
|
+
rules: path21.join(home, ".claude", "rules"),
|
|
21563
|
+
output_styles: path21.join(home, ".claude", "output-styles")
|
|
21380
21564
|
};
|
|
21381
21565
|
}
|
|
21382
21566
|
const root = projectRoot ?? process.cwd();
|
|
21383
21567
|
return {
|
|
21384
|
-
instructions:
|
|
21385
|
-
agents:
|
|
21386
|
-
skills:
|
|
21387
|
-
commands:
|
|
21388
|
-
rules:
|
|
21389
|
-
output_styles:
|
|
21568
|
+
instructions: path21.join(root, "CLAUDE.md"),
|
|
21569
|
+
agents: path21.join(root, ".claude", "agents"),
|
|
21570
|
+
skills: path21.join(root, ".claude", "skills"),
|
|
21571
|
+
commands: path21.join(root, ".claude", "commands"),
|
|
21572
|
+
rules: path21.join(root, ".claude", "rules"),
|
|
21573
|
+
output_styles: path21.join(root, ".claude", "output-styles")
|
|
21390
21574
|
};
|
|
21391
21575
|
}
|
|
21392
21576
|
function resolveClaudeRootsForUninstall(manifest, runtime) {
|
|
@@ -21405,12 +21589,36 @@ function resolveClaudeRootsForUninstall(manifest, runtime) {
|
|
|
21405
21589
|
projectRoot: void 0,
|
|
21406
21590
|
mappings: mappings.platformPaths
|
|
21407
21591
|
})["claude-code"];
|
|
21408
|
-
return [
|
|
21592
|
+
return [path21.dirname(profile.agents)];
|
|
21409
21593
|
} catch {
|
|
21410
21594
|
}
|
|
21411
21595
|
}
|
|
21412
21596
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21413
|
-
return [
|
|
21597
|
+
return [path21.resolve(expandHome(`${home}/.claude`))];
|
|
21598
|
+
}
|
|
21599
|
+
function resolveAllClaudeRoots(manifest, runtime, claudeConfigDirs) {
|
|
21600
|
+
const home = process.env.HOME ?? process.env.USERPROFILE;
|
|
21601
|
+
const roots = new Set(
|
|
21602
|
+
[
|
|
21603
|
+
...resolveClaudeRootsForUninstall(manifest, runtime),
|
|
21604
|
+
...resolveClaudeGlobalRoots({
|
|
21605
|
+
flag: claudeConfigDirs,
|
|
21606
|
+
env: process.env.TANGYR_CLAUDE_CONFIG_DIRS,
|
|
21607
|
+
config: runtime.config.claudeCodeGlobalPaths
|
|
21608
|
+
})
|
|
21609
|
+
].map((root) => path21.resolve(root))
|
|
21610
|
+
);
|
|
21611
|
+
if (home && fs23.existsSync(home)) {
|
|
21612
|
+
try {
|
|
21613
|
+
for (const entry of fs23.readdirSync(home, { withFileTypes: true })) {
|
|
21614
|
+
if (entry.isDirectory() && entry.name.startsWith(".claude-")) {
|
|
21615
|
+
roots.add(path21.resolve(home, entry.name));
|
|
21616
|
+
}
|
|
21617
|
+
}
|
|
21618
|
+
} catch {
|
|
21619
|
+
}
|
|
21620
|
+
}
|
|
21621
|
+
return Array.from(roots).sort();
|
|
21414
21622
|
}
|
|
21415
21623
|
function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
|
|
21416
21624
|
if (claudeRoots.length === 0) {
|
|
@@ -21423,13 +21631,13 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
|
|
|
21423
21631
|
const rootsToResolve = isShared ? [claudeRoots[0]] : claudeRoots;
|
|
21424
21632
|
if (!runtime) {
|
|
21425
21633
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21426
|
-
const defaultRoot =
|
|
21634
|
+
const defaultRoot = path21.resolve(expandHome(`${home}/.claude`));
|
|
21427
21635
|
return rootsToResolve.flatMap((root) => {
|
|
21428
21636
|
const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
|
|
21429
21637
|
if (!hardcoded) {
|
|
21430
21638
|
return [];
|
|
21431
21639
|
}
|
|
21432
|
-
return [subPath ?
|
|
21640
|
+
return [subPath ? path21.join(hardcoded, subPath) : hardcoded];
|
|
21433
21641
|
});
|
|
21434
21642
|
}
|
|
21435
21643
|
try {
|
|
@@ -21448,17 +21656,17 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
|
|
|
21448
21656
|
if (!slotPath) {
|
|
21449
21657
|
return [];
|
|
21450
21658
|
}
|
|
21451
|
-
return [subPath ?
|
|
21659
|
+
return [subPath ? path21.join(slotPath, subPath) : slotPath];
|
|
21452
21660
|
});
|
|
21453
21661
|
} catch {
|
|
21454
21662
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21455
|
-
const defaultRoot =
|
|
21663
|
+
const defaultRoot = path21.resolve(expandHome(`${home}/.claude`));
|
|
21456
21664
|
return rootsToResolve.flatMap((root) => {
|
|
21457
21665
|
const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
|
|
21458
21666
|
if (!hardcoded) {
|
|
21459
21667
|
return [];
|
|
21460
21668
|
}
|
|
21461
|
-
return [subPath ?
|
|
21669
|
+
return [subPath ? path21.join(hardcoded, subPath) : hardcoded];
|
|
21462
21670
|
});
|
|
21463
21671
|
}
|
|
21464
21672
|
}
|
|
@@ -21481,9 +21689,9 @@ function resolveHardcodedClaudeSlot(root, defaultRoot, slotName) {
|
|
|
21481
21689
|
return null;
|
|
21482
21690
|
}
|
|
21483
21691
|
if (root === defaultRoot) {
|
|
21484
|
-
return
|
|
21692
|
+
return path21.join(root, relative);
|
|
21485
21693
|
}
|
|
21486
|
-
return
|
|
21694
|
+
return path21.join(root, relative);
|
|
21487
21695
|
}
|
|
21488
21696
|
function resolveRuntimeIfAvailable(options, logger) {
|
|
21489
21697
|
try {
|
|
@@ -21502,6 +21710,9 @@ function resolveSelectedTools(rawTools, manifest, runtime) {
|
|
|
21502
21710
|
);
|
|
21503
21711
|
}
|
|
21504
21712
|
const selectedTools = new Set(manifest.tools);
|
|
21713
|
+
if (selectedTools.size === 0) {
|
|
21714
|
+
return new Set(ALL_TARGETS);
|
|
21715
|
+
}
|
|
21505
21716
|
if (runtime) {
|
|
21506
21717
|
for (const tool of activeTargets(runtime.config)) {
|
|
21507
21718
|
selectedTools.add(tool);
|
|
@@ -21514,9 +21725,93 @@ function shouldRemoveManifestFile(relativePath, selectedTools) {
|
|
|
21514
21725
|
return selectedTools.has(tool);
|
|
21515
21726
|
}
|
|
21516
21727
|
function isFullToolUninstall(manifest, selectedTools) {
|
|
21728
|
+
if (manifest.tools.length === 0) {
|
|
21729
|
+
return ALL_TARGETS.every((tool) => selectedTools.has(tool));
|
|
21730
|
+
}
|
|
21517
21731
|
return manifest.tools.every((tool) => selectedTools.has(tool));
|
|
21518
21732
|
}
|
|
21519
|
-
function
|
|
21733
|
+
function addCompiledPathPlan(artifacts, artifactPath, expectedTarget, component) {
|
|
21734
|
+
addCompiledGlobPlans(artifacts, artifactPath, expectedTarget, component);
|
|
21735
|
+
}
|
|
21736
|
+
function addCompiledGlobPlans(artifacts, pattern, expectedTarget, component) {
|
|
21737
|
+
for (const artifactPath of ts(pattern).sort()) {
|
|
21738
|
+
let marker = null;
|
|
21739
|
+
try {
|
|
21740
|
+
marker = extractProvenanceMarker(fs23.readFileSync(artifactPath, "utf8"));
|
|
21741
|
+
} catch {
|
|
21742
|
+
continue;
|
|
21743
|
+
}
|
|
21744
|
+
if (marker?.target !== expectedTarget) {
|
|
21745
|
+
continue;
|
|
21746
|
+
}
|
|
21747
|
+
artifacts.push({
|
|
21748
|
+
component,
|
|
21749
|
+
path: artifactPath,
|
|
21750
|
+
kind: "compiled",
|
|
21751
|
+
expectedTarget,
|
|
21752
|
+
expectedSource: marker.source,
|
|
21753
|
+
observed: true
|
|
21754
|
+
});
|
|
21755
|
+
}
|
|
21756
|
+
}
|
|
21757
|
+
function addManagedSymlinkChildren(artifacts, directory, runtime, component) {
|
|
21758
|
+
let entries;
|
|
21759
|
+
try {
|
|
21760
|
+
entries = fs23.readdirSync(directory, { withFileTypes: true });
|
|
21761
|
+
} catch {
|
|
21762
|
+
return;
|
|
21763
|
+
}
|
|
21764
|
+
for (const entry of entries) {
|
|
21765
|
+
const artifactPath = path21.join(directory, entry.name);
|
|
21766
|
+
const artifactClass = classifyArtifact(
|
|
21767
|
+
artifactPath,
|
|
21768
|
+
runtime.config,
|
|
21769
|
+
runtime.sourceRoot
|
|
21770
|
+
);
|
|
21771
|
+
if (artifactClass === "managed-symlink" || artifactClass === "managed-stale") {
|
|
21772
|
+
artifacts.push({ component, path: artifactPath, kind: "direct" });
|
|
21773
|
+
}
|
|
21774
|
+
}
|
|
21775
|
+
}
|
|
21776
|
+
function resolveLegacyClaudeHookCommands(runtime) {
|
|
21777
|
+
const parsed = loadSourceHooks(
|
|
21778
|
+
resolveHooksSourceDir(runtime.sourceRoot, runtime.config),
|
|
21779
|
+
resolveKitHookNames(runtime.sourceRoot)
|
|
21780
|
+
);
|
|
21781
|
+
const commands = /* @__PURE__ */ new Set();
|
|
21782
|
+
collectStringValuesByKey(parsed, "command", commands);
|
|
21783
|
+
return Array.from(commands).sort();
|
|
21784
|
+
}
|
|
21785
|
+
function collectStringValuesByKey(value, keyName, values) {
|
|
21786
|
+
if (Array.isArray(value)) {
|
|
21787
|
+
for (const entry of value) {
|
|
21788
|
+
collectStringValuesByKey(entry, keyName, values);
|
|
21789
|
+
}
|
|
21790
|
+
return;
|
|
21791
|
+
}
|
|
21792
|
+
if (!isRecord(value)) {
|
|
21793
|
+
return;
|
|
21794
|
+
}
|
|
21795
|
+
if (typeof value[keyName] === "string") {
|
|
21796
|
+
values.add(value[keyName]);
|
|
21797
|
+
}
|
|
21798
|
+
for (const entry of Object.values(value)) {
|
|
21799
|
+
collectStringValuesByKey(entry, keyName, values);
|
|
21800
|
+
}
|
|
21801
|
+
}
|
|
21802
|
+
function addLegacyOperatingGuideCopies(artifacts, claudeRoot) {
|
|
21803
|
+
for (const artifactPath of [
|
|
21804
|
+
...ts(path21.join(claudeRoot, "CLAUDE.md.bak.*")),
|
|
21805
|
+
...ts(path21.join(claudeRoot, "AGENTS.md.bak.*"))
|
|
21806
|
+
].sort()) {
|
|
21807
|
+
artifacts.push({
|
|
21808
|
+
component: "claude-code legacy operating guide backup",
|
|
21809
|
+
path: artifactPath,
|
|
21810
|
+
kind: "legacy-kit-copy"
|
|
21811
|
+
});
|
|
21812
|
+
}
|
|
21813
|
+
}
|
|
21814
|
+
function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, claudeConfigDirs) {
|
|
21520
21815
|
if (!runtime.kitInfo || scope !== "global") {
|
|
21521
21816
|
return [];
|
|
21522
21817
|
}
|
|
@@ -21526,11 +21821,97 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21526
21821
|
const opencodePaths = resolveOpenCodePaths(runtime);
|
|
21527
21822
|
const cursorPaths = resolveCursorPaths(runtime);
|
|
21528
21823
|
const clinePaths = resolveClinePaths(runtime);
|
|
21824
|
+
if (selectedTools.has("claude-code")) {
|
|
21825
|
+
const mappings = loadMappings(
|
|
21826
|
+
runtime.sourceRoot,
|
|
21827
|
+
runtime.config,
|
|
21828
|
+
runtime.configDir
|
|
21829
|
+
);
|
|
21830
|
+
const claudeRoots = resolveAllClaudeRoots(
|
|
21831
|
+
manifest,
|
|
21832
|
+
runtime,
|
|
21833
|
+
claudeConfigDirs
|
|
21834
|
+
);
|
|
21835
|
+
const profiles = resolveClaudeCodePathsForRoots(
|
|
21836
|
+
claudeRoots,
|
|
21837
|
+
mappings.platformPaths
|
|
21838
|
+
);
|
|
21839
|
+
const legacyHookCommands = resolveLegacyClaudeHookCommands(runtime);
|
|
21840
|
+
for (const profile of profiles) {
|
|
21841
|
+
for (const [component, artifactPath] of [
|
|
21842
|
+
["instructions", profile.instructions],
|
|
21843
|
+
["instructions shim", profile.instructions_shim],
|
|
21844
|
+
["agents", profile.agents],
|
|
21845
|
+
["commands", profile.commands],
|
|
21846
|
+
["rules", profile.rules],
|
|
21847
|
+
["output styles", profile.output_styles],
|
|
21848
|
+
["skills", profile.skills]
|
|
21849
|
+
]) {
|
|
21850
|
+
artifacts.push({
|
|
21851
|
+
component: `claude-code ${component}`,
|
|
21852
|
+
path: artifactPath,
|
|
21853
|
+
kind: "direct"
|
|
21854
|
+
});
|
|
21855
|
+
}
|
|
21856
|
+
for (const skill of runtime.kitInfo.components.skills.declared) {
|
|
21857
|
+
artifacts.push({
|
|
21858
|
+
component: "claude-code skill",
|
|
21859
|
+
path: path21.join(profile.skills, skill),
|
|
21860
|
+
kind: "direct"
|
|
21861
|
+
});
|
|
21862
|
+
}
|
|
21863
|
+
addManagedSymlinkChildren(
|
|
21864
|
+
artifacts,
|
|
21865
|
+
profile.skills,
|
|
21866
|
+
runtime,
|
|
21867
|
+
"claude-code skill residue"
|
|
21868
|
+
);
|
|
21869
|
+
artifacts.push({
|
|
21870
|
+
component: "claude-code settings",
|
|
21871
|
+
path: profile.hooks_shared_file,
|
|
21872
|
+
kind: "claude-hooks",
|
|
21873
|
+
legacyHookCommands
|
|
21874
|
+
});
|
|
21875
|
+
if (isFullToolUninstall(manifest, selectedTools)) {
|
|
21876
|
+
addLegacyOperatingGuideCopies(
|
|
21877
|
+
artifacts,
|
|
21878
|
+
path21.dirname(profile.instructions)
|
|
21879
|
+
);
|
|
21880
|
+
}
|
|
21881
|
+
}
|
|
21882
|
+
const sharedProfile = profiles[0];
|
|
21883
|
+
if (sharedProfile) {
|
|
21884
|
+
artifacts.push(
|
|
21885
|
+
{
|
|
21886
|
+
component: "claude-code hooks bridge",
|
|
21887
|
+
path: sharedProfile.hooks,
|
|
21888
|
+
kind: "direct"
|
|
21889
|
+
},
|
|
21890
|
+
{
|
|
21891
|
+
component: "claude-code mcp",
|
|
21892
|
+
path: sharedProfile.mcp_shared_file,
|
|
21893
|
+
kind: "claude-mcp"
|
|
21894
|
+
}
|
|
21895
|
+
);
|
|
21896
|
+
}
|
|
21897
|
+
}
|
|
21529
21898
|
if (selectedTools.has("copilot")) {
|
|
21899
|
+
addCompiledGlobPlans(
|
|
21900
|
+
artifacts,
|
|
21901
|
+
path21.join(copilotPaths.agents, "*.agent.md"),
|
|
21902
|
+
"copilot",
|
|
21903
|
+
"copilot agent residue"
|
|
21904
|
+
);
|
|
21905
|
+
addCompiledGlobPlans(
|
|
21906
|
+
artifacts,
|
|
21907
|
+
path21.join(copilotPaths.prompts, "*.prompt.md"),
|
|
21908
|
+
"copilot",
|
|
21909
|
+
"copilot prompt residue"
|
|
21910
|
+
);
|
|
21530
21911
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
21531
21912
|
artifacts.push({
|
|
21532
21913
|
component: "copilot agent",
|
|
21533
|
-
path:
|
|
21914
|
+
path: path21.join(copilotPaths.agents, `${agentEntry}.agent.md`),
|
|
21534
21915
|
kind: "compiled",
|
|
21535
21916
|
expectedTarget: "copilot",
|
|
21536
21917
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -21539,7 +21920,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21539
21920
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
21540
21921
|
artifacts.push({
|
|
21541
21922
|
component: "copilot prompt",
|
|
21542
|
-
path:
|
|
21923
|
+
path: path21.join(copilotPaths.prompts, `${commandEntry}.prompt.md`),
|
|
21543
21924
|
kind: "compiled",
|
|
21544
21925
|
expectedTarget: "copilot",
|
|
21545
21926
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -21552,15 +21933,29 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21552
21933
|
kind: "direct"
|
|
21553
21934
|
});
|
|
21554
21935
|
}
|
|
21936
|
+
artifacts.push(
|
|
21937
|
+
{
|
|
21938
|
+
component: "copilot hooks",
|
|
21939
|
+
path: path21.join(copilotPaths.hooks, "tangyr-managed.json"),
|
|
21940
|
+
kind: "managed-json",
|
|
21941
|
+
expectedTarget: "copilot"
|
|
21942
|
+
},
|
|
21943
|
+
{
|
|
21944
|
+
component: "copilot legacy hooks",
|
|
21945
|
+
path: path21.join(copilotPaths.hooks, "proteus-managed.json"),
|
|
21946
|
+
kind: "managed-json",
|
|
21947
|
+
expectedTarget: "copilot"
|
|
21948
|
+
}
|
|
21949
|
+
);
|
|
21555
21950
|
const hooksSourcePath = resolveHooksSourceFile(
|
|
21556
21951
|
runtime.sourceRoot,
|
|
21557
21952
|
runtime.config
|
|
21558
21953
|
);
|
|
21559
21954
|
const hooksSource = hooksSourceLabel(runtime.config);
|
|
21560
|
-
if (
|
|
21955
|
+
if (fs23.existsSync(hooksSourcePath)) {
|
|
21561
21956
|
artifacts.push({
|
|
21562
21957
|
component: "copilot hooks",
|
|
21563
|
-
path:
|
|
21958
|
+
path: path21.join(copilotPaths.hooks, "tangyr-managed.json"),
|
|
21564
21959
|
kind: "compiled",
|
|
21565
21960
|
expectedTarget: "copilot",
|
|
21566
21961
|
expectedSource: hooksSource
|
|
@@ -21571,7 +21966,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21571
21966
|
runtime.config
|
|
21572
21967
|
);
|
|
21573
21968
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21574
|
-
if (
|
|
21969
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21575
21970
|
artifacts.push({
|
|
21576
21971
|
component: "copilot mcp",
|
|
21577
21972
|
path: copilotPaths.mcpSharedFile,
|
|
@@ -21582,6 +21977,24 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21582
21977
|
}
|
|
21583
21978
|
}
|
|
21584
21979
|
if (selectedTools.has("codex")) {
|
|
21980
|
+
addCompiledPathPlan(
|
|
21981
|
+
artifacts,
|
|
21982
|
+
codexPaths.instructions,
|
|
21983
|
+
"codex",
|
|
21984
|
+
"codex instruction residue"
|
|
21985
|
+
);
|
|
21986
|
+
addCompiledGlobPlans(
|
|
21987
|
+
artifacts,
|
|
21988
|
+
path21.join(codexPaths.agents, "*.toml"),
|
|
21989
|
+
"codex",
|
|
21990
|
+
"codex agent residue"
|
|
21991
|
+
);
|
|
21992
|
+
addCompiledGlobPlans(
|
|
21993
|
+
artifacts,
|
|
21994
|
+
path21.join(codexPaths.rules, "*.rules"),
|
|
21995
|
+
"codex",
|
|
21996
|
+
"codex rule residue"
|
|
21997
|
+
);
|
|
21585
21998
|
artifacts.push({
|
|
21586
21999
|
component: "codex instructions",
|
|
21587
22000
|
path: codexPaths.instructions,
|
|
@@ -21592,7 +22005,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21592
22005
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
21593
22006
|
artifacts.push({
|
|
21594
22007
|
component: "codex agent",
|
|
21595
|
-
path:
|
|
22008
|
+
path: path21.join(codexPaths.agents, `${agentEntry}.toml`),
|
|
21596
22009
|
kind: "compiled",
|
|
21597
22010
|
expectedTarget: "codex",
|
|
21598
22011
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -21601,7 +22014,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21601
22014
|
for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
|
|
21602
22015
|
artifacts.push({
|
|
21603
22016
|
component: "codex rule",
|
|
21604
|
-
path:
|
|
22017
|
+
path: path21.join(codexPaths.rules, `${ruleEntry}.rules`),
|
|
21605
22018
|
kind: "compiled",
|
|
21606
22019
|
expectedTarget: "codex",
|
|
21607
22020
|
expectedSource: `rules/${ruleEntry}.md`
|
|
@@ -21619,7 +22032,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21619
22032
|
runtime.config
|
|
21620
22033
|
);
|
|
21621
22034
|
const hooksSource = hooksSourceLabel(runtime.config);
|
|
21622
|
-
if (
|
|
22035
|
+
if (fs23.existsSync(hooksSourcePath)) {
|
|
21623
22036
|
artifacts.push({
|
|
21624
22037
|
component: "codex hooks",
|
|
21625
22038
|
path: codexPaths.hooksSharedFile,
|
|
@@ -21632,7 +22045,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21632
22045
|
runtime.config
|
|
21633
22046
|
);
|
|
21634
22047
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21635
|
-
if (
|
|
22048
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21636
22049
|
artifacts.push({
|
|
21637
22050
|
component: "codex mcp",
|
|
21638
22051
|
path: codexPaths.mcpSharedFile,
|
|
@@ -21643,8 +22056,37 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21643
22056
|
}
|
|
21644
22057
|
}
|
|
21645
22058
|
if (selectedTools.has("opencode")) {
|
|
21646
|
-
|
|
21647
|
-
|
|
22059
|
+
addCompiledPathPlan(
|
|
22060
|
+
artifacts,
|
|
22061
|
+
opencodePaths.instructions,
|
|
22062
|
+
"opencode",
|
|
22063
|
+
"opencode instruction residue"
|
|
22064
|
+
);
|
|
22065
|
+
addCompiledPathPlan(
|
|
22066
|
+
artifacts,
|
|
22067
|
+
opencodePaths.configDoc,
|
|
22068
|
+
"opencode",
|
|
22069
|
+
"opencode config residue"
|
|
22070
|
+
);
|
|
22071
|
+
addCompiledGlobPlans(
|
|
22072
|
+
artifacts,
|
|
22073
|
+
path21.join(opencodePaths.agents, "*.md"),
|
|
22074
|
+
"opencode",
|
|
22075
|
+
"opencode agent residue"
|
|
22076
|
+
);
|
|
22077
|
+
addCompiledGlobPlans(
|
|
22078
|
+
artifacts,
|
|
22079
|
+
path21.join(opencodePaths.commands, "*.md"),
|
|
22080
|
+
"opencode",
|
|
22081
|
+
"opencode command residue"
|
|
22082
|
+
);
|
|
22083
|
+
artifacts.push({
|
|
22084
|
+
component: "opencode shared skills",
|
|
22085
|
+
path: opencodePaths.skillsShared,
|
|
22086
|
+
kind: "direct"
|
|
22087
|
+
});
|
|
22088
|
+
artifacts.push({
|
|
22089
|
+
component: "opencode instructions",
|
|
21648
22090
|
path: opencodePaths.instructions,
|
|
21649
22091
|
kind: "compiled",
|
|
21650
22092
|
expectedTarget: "opencode",
|
|
@@ -21653,7 +22095,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21653
22095
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
21654
22096
|
artifacts.push({
|
|
21655
22097
|
component: "opencode agent",
|
|
21656
|
-
path:
|
|
22098
|
+
path: path21.join(opencodePaths.agents, `${agentEntry}.md`),
|
|
21657
22099
|
kind: "compiled",
|
|
21658
22100
|
expectedTarget: "opencode",
|
|
21659
22101
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -21662,7 +22104,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21662
22104
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
21663
22105
|
artifacts.push({
|
|
21664
22106
|
component: "opencode command",
|
|
21665
|
-
path:
|
|
22107
|
+
path: path21.join(opencodePaths.commands, `${commandEntry}.md`),
|
|
21666
22108
|
kind: "compiled",
|
|
21667
22109
|
expectedTarget: "opencode",
|
|
21668
22110
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -21680,7 +22122,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21680
22122
|
runtime.config
|
|
21681
22123
|
);
|
|
21682
22124
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21683
|
-
if (
|
|
22125
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21684
22126
|
artifacts.push({
|
|
21685
22127
|
component: "opencode config",
|
|
21686
22128
|
path: opencodePaths.configDoc,
|
|
@@ -21691,6 +22133,48 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21691
22133
|
}
|
|
21692
22134
|
}
|
|
21693
22135
|
if (selectedTools.has("cursor")) {
|
|
22136
|
+
addCompiledPathPlan(
|
|
22137
|
+
artifacts,
|
|
22138
|
+
cursorPaths.instructions,
|
|
22139
|
+
"cursor",
|
|
22140
|
+
"cursor instruction residue"
|
|
22141
|
+
);
|
|
22142
|
+
addCompiledPathPlan(
|
|
22143
|
+
artifacts,
|
|
22144
|
+
cursorPaths.mcpFile,
|
|
22145
|
+
"cursor",
|
|
22146
|
+
"cursor mcp residue"
|
|
22147
|
+
);
|
|
22148
|
+
artifacts.push(
|
|
22149
|
+
{
|
|
22150
|
+
component: "cursor agent directory residue",
|
|
22151
|
+
path: cursorPaths.agents,
|
|
22152
|
+
kind: "direct"
|
|
22153
|
+
},
|
|
22154
|
+
{
|
|
22155
|
+
component: "cursor shared skills",
|
|
22156
|
+
path: cursorPaths.skillsShared,
|
|
22157
|
+
kind: "direct"
|
|
22158
|
+
}
|
|
22159
|
+
);
|
|
22160
|
+
addCompiledGlobPlans(
|
|
22161
|
+
artifacts,
|
|
22162
|
+
path21.join(cursorPaths.agents, "*.md"),
|
|
22163
|
+
"cursor",
|
|
22164
|
+
"cursor agent residue"
|
|
22165
|
+
);
|
|
22166
|
+
addCompiledGlobPlans(
|
|
22167
|
+
artifacts,
|
|
22168
|
+
path21.join(cursorPaths.rules, "*.mdc"),
|
|
22169
|
+
"cursor",
|
|
22170
|
+
"cursor rule residue"
|
|
22171
|
+
);
|
|
22172
|
+
addCompiledGlobPlans(
|
|
22173
|
+
artifacts,
|
|
22174
|
+
path21.join(cursorPaths.skills, "*", "SKILL.md"),
|
|
22175
|
+
"cursor",
|
|
22176
|
+
"cursor command residue"
|
|
22177
|
+
);
|
|
21694
22178
|
artifacts.push({
|
|
21695
22179
|
component: "cursor instructions",
|
|
21696
22180
|
path: cursorPaths.instructions,
|
|
@@ -21701,7 +22185,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21701
22185
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
21702
22186
|
artifacts.push({
|
|
21703
22187
|
component: "cursor agent",
|
|
21704
|
-
path:
|
|
22188
|
+
path: path21.join(cursorPaths.agents, `${agentEntry}.md`),
|
|
21705
22189
|
kind: "compiled",
|
|
21706
22190
|
expectedTarget: "cursor",
|
|
21707
22191
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -21719,7 +22203,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21719
22203
|
runtime.config
|
|
21720
22204
|
);
|
|
21721
22205
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21722
|
-
if (
|
|
22206
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21723
22207
|
artifacts.push({
|
|
21724
22208
|
component: "cursor mcp",
|
|
21725
22209
|
path: cursorPaths.mcpFile,
|
|
@@ -21730,6 +22214,36 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21730
22214
|
}
|
|
21731
22215
|
}
|
|
21732
22216
|
if (selectedTools.has("cline")) {
|
|
22217
|
+
addCompiledPathPlan(
|
|
22218
|
+
artifacts,
|
|
22219
|
+
clinePaths.mcpFile,
|
|
22220
|
+
"cline",
|
|
22221
|
+
"cline mcp residue"
|
|
22222
|
+
);
|
|
22223
|
+
addCompiledGlobPlans(
|
|
22224
|
+
artifacts,
|
|
22225
|
+
path21.join(clinePaths.rules, "*.md"),
|
|
22226
|
+
"cline",
|
|
22227
|
+
"cline rule residue"
|
|
22228
|
+
);
|
|
22229
|
+
addCompiledGlobPlans(
|
|
22230
|
+
artifacts,
|
|
22231
|
+
path21.join(clinePaths.workflows, "*.md"),
|
|
22232
|
+
"cline",
|
|
22233
|
+
"cline workflow residue"
|
|
22234
|
+
);
|
|
22235
|
+
addManagedSymlinkChildren(
|
|
22236
|
+
artifacts,
|
|
22237
|
+
clinePaths.rules,
|
|
22238
|
+
runtime,
|
|
22239
|
+
"cline rule symlink residue"
|
|
22240
|
+
);
|
|
22241
|
+
addManagedSymlinkChildren(
|
|
22242
|
+
artifacts,
|
|
22243
|
+
clinePaths.workflows,
|
|
22244
|
+
runtime,
|
|
22245
|
+
"cline workflow symlink residue"
|
|
22246
|
+
);
|
|
21733
22247
|
if (clinePaths.instructions !== null) {
|
|
21734
22248
|
artifacts.push({
|
|
21735
22249
|
component: "cline instructions",
|
|
@@ -21742,7 +22256,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21742
22256
|
for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
|
|
21743
22257
|
artifacts.push({
|
|
21744
22258
|
component: "cline rule",
|
|
21745
|
-
path:
|
|
22259
|
+
path: path21.join(clinePaths.rules, `${ruleEntry}.md`),
|
|
21746
22260
|
kind: "compiled",
|
|
21747
22261
|
expectedTarget: "cline",
|
|
21748
22262
|
expectedSource: `rules/${ruleEntry}.md`
|
|
@@ -21751,7 +22265,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21751
22265
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
21752
22266
|
artifacts.push({
|
|
21753
22267
|
component: "cline workflow",
|
|
21754
|
-
path:
|
|
22268
|
+
path: path21.join(clinePaths.workflows, `${commandEntry}.md`),
|
|
21755
22269
|
kind: "compiled",
|
|
21756
22270
|
expectedTarget: "cline",
|
|
21757
22271
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -21769,7 +22283,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21769
22283
|
runtime.config
|
|
21770
22284
|
);
|
|
21771
22285
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21772
|
-
if (
|
|
22286
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21773
22287
|
artifacts.push({
|
|
21774
22288
|
component: "cline mcp",
|
|
21775
22289
|
path: clinePaths.mcpFile,
|
|
@@ -21779,12 +22293,57 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21779
22293
|
});
|
|
21780
22294
|
}
|
|
21781
22295
|
}
|
|
22296
|
+
if (isFullToolUninstall(manifest, selectedTools)) {
|
|
22297
|
+
for (const pointerName of [".operating-kit-root", ".framework-root"]) {
|
|
22298
|
+
artifacts.push({
|
|
22299
|
+
component: `shared kit pointer ${pointerName}`,
|
|
22300
|
+
path: resolveTargetPath(`~/.agents/${pointerName}`),
|
|
22301
|
+
kind: "kit-pointer",
|
|
22302
|
+
expectedPath: runtime.sourceRoot
|
|
22303
|
+
});
|
|
22304
|
+
}
|
|
22305
|
+
}
|
|
22306
|
+
addRecordedManifestPlans(artifacts, manifest, selectedTools, runtime);
|
|
21782
22307
|
return dedupeArtifacts(artifacts);
|
|
21783
22308
|
}
|
|
22309
|
+
function addRecordedManifestPlans(artifacts, manifest, selectedTools, runtime) {
|
|
22310
|
+
for (const file of manifest.artifacts) {
|
|
22311
|
+
if (file.origin !== "tangyr-managed" || !shouldRemoveManifestFile(file.relativePath, selectedTools)) {
|
|
22312
|
+
continue;
|
|
22313
|
+
}
|
|
22314
|
+
const artifactPath = resolveManifestKeyToPath(
|
|
22315
|
+
file.relativePath,
|
|
22316
|
+
"global",
|
|
22317
|
+
runtime
|
|
22318
|
+
);
|
|
22319
|
+
if (artifactPath) {
|
|
22320
|
+
artifacts.push({
|
|
22321
|
+
component: `${file.relativePath} (manifest)`,
|
|
22322
|
+
path: artifactPath,
|
|
22323
|
+
kind: "recorded"
|
|
22324
|
+
});
|
|
22325
|
+
}
|
|
22326
|
+
}
|
|
22327
|
+
}
|
|
21784
22328
|
function removeKitManagedArtifact(artifact, runtime, logger) {
|
|
21785
22329
|
if (artifact.kind === "compiled") {
|
|
21786
22330
|
return removeManagedCompiledArtifact(artifact, logger);
|
|
21787
22331
|
}
|
|
22332
|
+
if (artifact.kind === "claude-hooks") {
|
|
22333
|
+
return removeManagedClaudeHooksArtifact(artifact, logger);
|
|
22334
|
+
}
|
|
22335
|
+
if (artifact.kind === "claude-mcp") {
|
|
22336
|
+
return removeManagedClaudeMcpArtifact(artifact, logger);
|
|
22337
|
+
}
|
|
22338
|
+
if (artifact.kind === "managed-json") {
|
|
22339
|
+
return removeManagedJsonArtifact(artifact, logger);
|
|
22340
|
+
}
|
|
22341
|
+
if (artifact.kind === "recorded") {
|
|
22342
|
+
return removeRecordedArtifact(artifact, logger);
|
|
22343
|
+
}
|
|
22344
|
+
if (artifact.kind === "kit-pointer" || artifact.kind === "legacy-kit-copy") {
|
|
22345
|
+
return removeExactManagedFile(artifact, logger);
|
|
22346
|
+
}
|
|
21788
22347
|
if (artifact.kind === "copilot-mcp") {
|
|
21789
22348
|
return removeManagedCopilotMcpArtifact(artifact, logger);
|
|
21790
22349
|
}
|
|
@@ -21796,17 +22355,78 @@ function removeKitManagedArtifact(artifact, runtime, logger) {
|
|
|
21796
22355
|
}
|
|
21797
22356
|
return removeManagedDirectArtifact(artifact, runtime, logger);
|
|
21798
22357
|
}
|
|
22358
|
+
function isKitManagedArtifact(artifact, runtime) {
|
|
22359
|
+
if (artifact.kind === "direct") {
|
|
22360
|
+
const artifactClass = classifyArtifact(
|
|
22361
|
+
artifact.path,
|
|
22362
|
+
runtime.config,
|
|
22363
|
+
runtime.sourceRoot
|
|
22364
|
+
);
|
|
22365
|
+
return artifactClass === "managed-symlink" || artifactClass === "managed-stale" || artifactClass === "managed-compiled";
|
|
22366
|
+
}
|
|
22367
|
+
if (artifact.kind === "compiled") {
|
|
22368
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
22369
|
+
return false;
|
|
22370
|
+
}
|
|
22371
|
+
try {
|
|
22372
|
+
const marker = extractProvenanceMarker(
|
|
22373
|
+
fs23.readFileSync(artifact.path, "utf8")
|
|
22374
|
+
);
|
|
22375
|
+
return marker?.target === artifact.expectedTarget && marker?.source === artifact.expectedSource;
|
|
22376
|
+
} catch {
|
|
22377
|
+
return false;
|
|
22378
|
+
}
|
|
22379
|
+
}
|
|
22380
|
+
if (artifact.kind === "recorded") {
|
|
22381
|
+
return fs23.existsSync(artifact.path) || isSymlink(artifact.path);
|
|
22382
|
+
}
|
|
22383
|
+
if (artifact.kind === "kit-pointer") {
|
|
22384
|
+
return isKitPointer(artifact);
|
|
22385
|
+
}
|
|
22386
|
+
if (artifact.kind === "legacy-kit-copy") {
|
|
22387
|
+
return isLegacyOperatingGuideCopy(artifact.path);
|
|
22388
|
+
}
|
|
22389
|
+
if (artifact.kind === "codex-mcp") {
|
|
22390
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
22391
|
+
return false;
|
|
22392
|
+
}
|
|
22393
|
+
const section = readManagedTomlSection(
|
|
22394
|
+
fs23.readFileSync(artifact.path, "utf8")
|
|
22395
|
+
);
|
|
22396
|
+
const marker = section ? extractProvenanceMarker(section) : null;
|
|
22397
|
+
return marker?.target === artifact.expectedTarget && marker?.source === artifact.expectedSource;
|
|
22398
|
+
}
|
|
22399
|
+
const parsed = readJsonObject2(artifact.path);
|
|
22400
|
+
if (!parsed) {
|
|
22401
|
+
return false;
|
|
22402
|
+
}
|
|
22403
|
+
if (artifact.kind === "claude-hooks") {
|
|
22404
|
+
return containsValueByKey(parsed.hooks, "_tangyr", true) || containsValueByKey(parsed.hooks, "_proteus", true) || (artifact.legacyHookCommands ?? []).some(
|
|
22405
|
+
(command) => containsValueByKey(parsed.hooks, "command", command)
|
|
22406
|
+
) || hasLegacyClaudeSharedPermission(parsed);
|
|
22407
|
+
}
|
|
22408
|
+
if (artifact.kind === "claude-mcp") {
|
|
22409
|
+
return hasManagedClaudeMcpServer(parsed);
|
|
22410
|
+
}
|
|
22411
|
+
if (artifact.kind === "managed-json") {
|
|
22412
|
+
return hasManagedRootMetadata(parsed, artifact.expectedTarget);
|
|
22413
|
+
}
|
|
22414
|
+
if (artifact.kind === "copilot-mcp") {
|
|
22415
|
+
return matchesManagedMetadata(metadataRecord(parsed._tangyr), artifact) || matchesManagedMetadata(metadataRecord(parsed._proteus), artifact);
|
|
22416
|
+
}
|
|
22417
|
+
return hasManagedCodexHooks(parsed, artifact.expectedSource);
|
|
22418
|
+
}
|
|
21799
22419
|
function removeManagedCompiledArtifact(artifact, logger) {
|
|
21800
|
-
if (!
|
|
22420
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
21801
22421
|
return false;
|
|
21802
22422
|
}
|
|
21803
22423
|
const marker = extractProvenanceMarker(
|
|
21804
|
-
|
|
22424
|
+
fs23.readFileSync(artifact.path, "utf8")
|
|
21805
22425
|
);
|
|
21806
22426
|
if (marker?.target !== artifact.expectedTarget || marker?.source !== artifact.expectedSource) {
|
|
21807
22427
|
return false;
|
|
21808
22428
|
}
|
|
21809
|
-
|
|
22429
|
+
fs23.rmSync(artifact.path, { force: true });
|
|
21810
22430
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
21811
22431
|
return true;
|
|
21812
22432
|
}
|
|
@@ -21823,6 +22443,80 @@ function removeManagedDirectArtifact(artifact, runtime, logger) {
|
|
|
21823
22443
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
21824
22444
|
return true;
|
|
21825
22445
|
}
|
|
22446
|
+
function removeManagedClaudeHooksArtifact(artifact, logger) {
|
|
22447
|
+
const parsed = readJsonObject2(artifact.path);
|
|
22448
|
+
if (!parsed) {
|
|
22449
|
+
return false;
|
|
22450
|
+
}
|
|
22451
|
+
const legacyHookCommands = new Set(artifact.legacyHookCommands ?? []);
|
|
22452
|
+
const hooks = removeManagedClaudeHookEntries(parsed.hooks, (entry) => {
|
|
22453
|
+
return entry._tangyr === true || entry._proteus === true || typeof entry.command === "string" && legacyHookCommands.has(entry.command);
|
|
22454
|
+
});
|
|
22455
|
+
const permissions = removeLegacyClaudeSharedPermission(parsed.permissions);
|
|
22456
|
+
const cleaned = { ...parsed };
|
|
22457
|
+
if (hooks === void 0) {
|
|
22458
|
+
delete cleaned.hooks;
|
|
22459
|
+
} else {
|
|
22460
|
+
cleaned.hooks = hooks;
|
|
22461
|
+
}
|
|
22462
|
+
if (permissions === void 0) {
|
|
22463
|
+
delete cleaned.permissions;
|
|
22464
|
+
} else {
|
|
22465
|
+
cleaned.permissions = permissions;
|
|
22466
|
+
}
|
|
22467
|
+
if (JSON.stringify(cleaned) === JSON.stringify(parsed)) {
|
|
22468
|
+
return false;
|
|
22469
|
+
}
|
|
22470
|
+
writeJsonOrRemove(artifact.path, cleaned);
|
|
22471
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22472
|
+
return true;
|
|
22473
|
+
}
|
|
22474
|
+
function removeManagedClaudeMcpArtifact(artifact, logger) {
|
|
22475
|
+
const parsed = readJsonObject2(artifact.path);
|
|
22476
|
+
if (!parsed || !isRecord(parsed.mcpServers)) {
|
|
22477
|
+
return false;
|
|
22478
|
+
}
|
|
22479
|
+
const retainedServers = Object.fromEntries(
|
|
22480
|
+
Object.entries(parsed.mcpServers).filter(([, server]) => {
|
|
22481
|
+
if (!isRecord(server)) {
|
|
22482
|
+
return true;
|
|
22483
|
+
}
|
|
22484
|
+
return !isRecord(server._tangyr) && !isRecord(server._proteus);
|
|
22485
|
+
})
|
|
22486
|
+
);
|
|
22487
|
+
if (Object.keys(retainedServers).length === Object.keys(parsed.mcpServers).length) {
|
|
22488
|
+
return false;
|
|
22489
|
+
}
|
|
22490
|
+
const cleaned = { ...parsed, mcpServers: retainedServers };
|
|
22491
|
+
writeJsonOrRemove(artifact.path, cleaned);
|
|
22492
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22493
|
+
return true;
|
|
22494
|
+
}
|
|
22495
|
+
function removeManagedJsonArtifact(artifact, logger) {
|
|
22496
|
+
const parsed = readJsonObject2(artifact.path);
|
|
22497
|
+
if (!parsed || !hasManagedRootMetadata(parsed, artifact.expectedTarget)) {
|
|
22498
|
+
return false;
|
|
22499
|
+
}
|
|
22500
|
+
fs23.rmSync(artifact.path, { force: true });
|
|
22501
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22502
|
+
return true;
|
|
22503
|
+
}
|
|
22504
|
+
function removeRecordedArtifact(artifact, logger) {
|
|
22505
|
+
if (!fs23.existsSync(artifact.path) && !isSymlink(artifact.path)) {
|
|
22506
|
+
return false;
|
|
22507
|
+
}
|
|
22508
|
+
removeManagedPath(artifact.path);
|
|
22509
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22510
|
+
return true;
|
|
22511
|
+
}
|
|
22512
|
+
function removeExactManagedFile(artifact, logger) {
|
|
22513
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
22514
|
+
return false;
|
|
22515
|
+
}
|
|
22516
|
+
fs23.rmSync(artifact.path, { force: true });
|
|
22517
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22518
|
+
return true;
|
|
22519
|
+
}
|
|
21826
22520
|
function removeManagedCopilotMcpArtifact(artifact, logger) {
|
|
21827
22521
|
const parsed = readJsonObject2(artifact.path);
|
|
21828
22522
|
if (!parsed) {
|
|
@@ -21853,10 +22547,10 @@ function removeManagedCodexHooksArtifact(artifact, logger) {
|
|
|
21853
22547
|
return true;
|
|
21854
22548
|
}
|
|
21855
22549
|
function removeManagedCodexMcpArtifact(artifact, logger) {
|
|
21856
|
-
if (!
|
|
22550
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
21857
22551
|
return false;
|
|
21858
22552
|
}
|
|
21859
|
-
const content =
|
|
22553
|
+
const content = fs23.readFileSync(artifact.path, "utf8");
|
|
21860
22554
|
const managedSection = readManagedTomlSection(content);
|
|
21861
22555
|
if (!managedSection) {
|
|
21862
22556
|
return false;
|
|
@@ -21871,9 +22565,9 @@ function removeManagedCodexMcpArtifact(artifact, logger) {
|
|
|
21871
22565
|
codexManagedMcpEnd
|
|
21872
22566
|
);
|
|
21873
22567
|
if (cleaned.trim().length === 0) {
|
|
21874
|
-
|
|
22568
|
+
fs23.rmSync(artifact.path, { force: true });
|
|
21875
22569
|
} else {
|
|
21876
|
-
|
|
22570
|
+
fs23.writeFileSync(artifact.path, cleaned);
|
|
21877
22571
|
}
|
|
21878
22572
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
21879
22573
|
return true;
|
|
@@ -22046,16 +22740,31 @@ function resolveClinePaths(runtime, scope = "global", projectRoot) {
|
|
|
22046
22740
|
function dedupeArtifacts(artifacts) {
|
|
22047
22741
|
const byPath = /* @__PURE__ */ new Map();
|
|
22048
22742
|
for (const artifact of artifacts) {
|
|
22049
|
-
byPath.
|
|
22743
|
+
const current = byPath.get(artifact.path);
|
|
22744
|
+
if (!current || managedArtifactPlanPriority(artifact) > managedArtifactPlanPriority(current)) {
|
|
22745
|
+
byPath.set(artifact.path, artifact);
|
|
22746
|
+
}
|
|
22050
22747
|
}
|
|
22051
22748
|
return Array.from(byPath.values());
|
|
22052
22749
|
}
|
|
22750
|
+
function managedArtifactPlanPriority(artifact) {
|
|
22751
|
+
if (artifact.observed) {
|
|
22752
|
+
return 3;
|
|
22753
|
+
}
|
|
22754
|
+
if (artifact.kind === "compiled") {
|
|
22755
|
+
return 0;
|
|
22756
|
+
}
|
|
22757
|
+
if (artifact.kind === "recorded") {
|
|
22758
|
+
return 1;
|
|
22759
|
+
}
|
|
22760
|
+
return 2;
|
|
22761
|
+
}
|
|
22053
22762
|
function readJsonObject2(filePath) {
|
|
22054
|
-
if (!
|
|
22763
|
+
if (!fs23.existsSync(filePath)) {
|
|
22055
22764
|
return null;
|
|
22056
22765
|
}
|
|
22057
22766
|
try {
|
|
22058
|
-
const parsed = JSON.parse(
|
|
22767
|
+
const parsed = JSON.parse(fs23.readFileSync(filePath, "utf8"));
|
|
22059
22768
|
return isRecord(parsed) ? parsed : null;
|
|
22060
22769
|
} catch {
|
|
22061
22770
|
return null;
|
|
@@ -22064,15 +22773,86 @@ function readJsonObject2(filePath) {
|
|
|
22064
22773
|
function metadataRecord(value) {
|
|
22065
22774
|
return isRecord(value) ? value : void 0;
|
|
22066
22775
|
}
|
|
22776
|
+
function containsValueByKey(value, keyName, keyValue) {
|
|
22777
|
+
if (Array.isArray(value)) {
|
|
22778
|
+
return value.some((entry) => containsValueByKey(entry, keyName, keyValue));
|
|
22779
|
+
}
|
|
22780
|
+
if (!isRecord(value)) {
|
|
22781
|
+
return false;
|
|
22782
|
+
}
|
|
22783
|
+
if (value[keyName] === keyValue) {
|
|
22784
|
+
return true;
|
|
22785
|
+
}
|
|
22786
|
+
return Object.values(value).some(
|
|
22787
|
+
(entry) => containsValueByKey(entry, keyName, keyValue)
|
|
22788
|
+
);
|
|
22789
|
+
}
|
|
22790
|
+
function hasLegacyClaudeSharedPermission(parsed) {
|
|
22791
|
+
if (!isRecord(parsed.permissions) || !Array.isArray(parsed.permissions.allow)) {
|
|
22792
|
+
return false;
|
|
22793
|
+
}
|
|
22794
|
+
return parsed.permissions.allow.includes(legacyClaudeSharedPermission);
|
|
22795
|
+
}
|
|
22796
|
+
function removeLegacyClaudeSharedPermission(value) {
|
|
22797
|
+
if (!isRecord(value) || !Array.isArray(value.allow)) {
|
|
22798
|
+
return value;
|
|
22799
|
+
}
|
|
22800
|
+
const retainedAllow = value.allow.filter(
|
|
22801
|
+
(entry) => entry !== legacyClaudeSharedPermission
|
|
22802
|
+
);
|
|
22803
|
+
if (retainedAllow.length === value.allow.length) {
|
|
22804
|
+
return value;
|
|
22805
|
+
}
|
|
22806
|
+
const cleaned = { ...value };
|
|
22807
|
+
if (retainedAllow.length === 0) {
|
|
22808
|
+
delete cleaned.allow;
|
|
22809
|
+
} else {
|
|
22810
|
+
cleaned.allow = retainedAllow;
|
|
22811
|
+
}
|
|
22812
|
+
return Object.keys(cleaned).length === 0 ? void 0 : cleaned;
|
|
22813
|
+
}
|
|
22814
|
+
function isKitPointer(artifact) {
|
|
22815
|
+
if (!artifact.expectedPath || !fs23.existsSync(artifact.path)) {
|
|
22816
|
+
return false;
|
|
22817
|
+
}
|
|
22818
|
+
try {
|
|
22819
|
+
const recordedPath = fs23.readFileSync(artifact.path, "utf8").trim();
|
|
22820
|
+
return recordedPath.length > 0 && path21.resolve(recordedPath) === path21.resolve(artifact.expectedPath);
|
|
22821
|
+
} catch {
|
|
22822
|
+
return false;
|
|
22823
|
+
}
|
|
22824
|
+
}
|
|
22825
|
+
function isLegacyOperatingGuideCopy(filePath) {
|
|
22826
|
+
if (!fs23.existsSync(filePath)) {
|
|
22827
|
+
return false;
|
|
22828
|
+
}
|
|
22829
|
+
try {
|
|
22830
|
+
return fs23.readFileSync(filePath, "utf8").startsWith(legacyOperatingGuideSignature);
|
|
22831
|
+
} catch {
|
|
22832
|
+
return false;
|
|
22833
|
+
}
|
|
22834
|
+
}
|
|
22835
|
+
function hasManagedClaudeMcpServer(parsed) {
|
|
22836
|
+
if (!isRecord(parsed.mcpServers)) {
|
|
22837
|
+
return false;
|
|
22838
|
+
}
|
|
22839
|
+
return Object.values(parsed.mcpServers).some(
|
|
22840
|
+
(server) => isRecord(server) && (isRecord(server._tangyr) || isRecord(server._proteus))
|
|
22841
|
+
);
|
|
22842
|
+
}
|
|
22843
|
+
function hasManagedRootMetadata(parsed, expectedTarget) {
|
|
22844
|
+
const metadata = [parsed._tangyr, parsed._proteus].map(metadataRecord).find((entry) => entry?.target === expectedTarget);
|
|
22845
|
+
return metadata !== void 0;
|
|
22846
|
+
}
|
|
22067
22847
|
function matchesManagedMetadata(metadata, artifact) {
|
|
22068
22848
|
return metadata?.source === artifact.expectedSource && metadata?.target === artifact.expectedTarget;
|
|
22069
22849
|
}
|
|
22070
22850
|
function writeJsonOrRemove(filePath, parsed) {
|
|
22071
22851
|
if (isEmptyJsonValue(parsed)) {
|
|
22072
|
-
|
|
22852
|
+
fs23.rmSync(filePath, { force: true });
|
|
22073
22853
|
return;
|
|
22074
22854
|
}
|
|
22075
|
-
|
|
22855
|
+
fs23.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
22076
22856
|
`);
|
|
22077
22857
|
}
|
|
22078
22858
|
function isEmptyJsonValue(value) {
|
|
@@ -22152,6 +22932,31 @@ function removeManagedValueByKey(value, keyName, keyValue) {
|
|
|
22152
22932
|
});
|
|
22153
22933
|
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
22154
22934
|
}
|
|
22935
|
+
function removeManagedClaudeHookEntries(value, isManagedEntry) {
|
|
22936
|
+
if (Array.isArray(value)) {
|
|
22937
|
+
const retained = value.flatMap((entry) => {
|
|
22938
|
+
const cleaned2 = removeManagedClaudeHookEntries(entry, isManagedEntry);
|
|
22939
|
+
return cleaned2 === void 0 ? [] : [cleaned2];
|
|
22940
|
+
});
|
|
22941
|
+
return retained.length > 0 ? retained : void 0;
|
|
22942
|
+
}
|
|
22943
|
+
if (!isRecord(value)) {
|
|
22944
|
+
return value;
|
|
22945
|
+
}
|
|
22946
|
+
if (isManagedEntry(value)) {
|
|
22947
|
+
return void 0;
|
|
22948
|
+
}
|
|
22949
|
+
const hadHookChildren = Object.hasOwn(value, "hooks");
|
|
22950
|
+
const entries = Object.entries(value).flatMap(([key, entry]) => {
|
|
22951
|
+
const cleaned2 = removeManagedClaudeHookEntries(entry, isManagedEntry);
|
|
22952
|
+
return cleaned2 === void 0 ? [] : [[key, cleaned2]];
|
|
22953
|
+
});
|
|
22954
|
+
const cleaned = entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
22955
|
+
if (hadHookChildren && (!cleaned || !("hooks" in cleaned))) {
|
|
22956
|
+
return void 0;
|
|
22957
|
+
}
|
|
22958
|
+
return cleaned;
|
|
22959
|
+
}
|
|
22155
22960
|
function readManagedTomlSection(content) {
|
|
22156
22961
|
const start = content.indexOf(codexManagedMcpStart);
|
|
22157
22962
|
const end = content.indexOf(codexManagedMcpEnd);
|
|
@@ -22173,20 +22978,20 @@ function removeDelimitedManagedSection(content, startMarker, endMarker) {
|
|
|
22173
22978
|
return `${content.slice(0, start)}${content.slice(removalEnd)}`;
|
|
22174
22979
|
}
|
|
22175
22980
|
function restoreBackup(backup, logger) {
|
|
22176
|
-
if (!
|
|
22981
|
+
if (!fs23.existsSync(backup.backupLocation)) {
|
|
22177
22982
|
logger.warn(` backup not found: ${backup.backupLocation}`);
|
|
22178
22983
|
return;
|
|
22179
22984
|
}
|
|
22180
|
-
const destDir =
|
|
22181
|
-
|
|
22182
|
-
|
|
22985
|
+
const destDir = path21.dirname(backup.originalPath);
|
|
22986
|
+
fs23.mkdirSync(destDir, { recursive: true });
|
|
22987
|
+
fs23.renameSync(backup.backupLocation, backup.originalPath);
|
|
22183
22988
|
logger.verbose(
|
|
22184
22989
|
` restored: ${backup.backupLocation} \u2192 ${backup.originalPath}`
|
|
22185
22990
|
);
|
|
22186
22991
|
}
|
|
22187
22992
|
function isSymlink(p) {
|
|
22188
22993
|
try {
|
|
22189
|
-
return
|
|
22994
|
+
return fs23.lstatSync(p).isSymbolicLink();
|
|
22190
22995
|
} catch {
|
|
22191
22996
|
return false;
|
|
22192
22997
|
}
|
|
@@ -22260,7 +23065,7 @@ function cleanupClaudeCode(config, sourceRoot, configDir, logger, scope) {
|
|
|
22260
23065
|
)) {
|
|
22261
23066
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
22262
23067
|
if (artifactClass === "managed-symlink" || artifactClass === "managed-compiled" || artifactClass === "managed-stale") {
|
|
22263
|
-
|
|
23068
|
+
fs24.rmSync(artifact.path, { recursive: true, force: true });
|
|
22264
23069
|
logger.info(`${artifact.component}: removed ${artifact.path}`);
|
|
22265
23070
|
}
|
|
22266
23071
|
}
|
|
@@ -22316,7 +23121,7 @@ function cleanupCopilot(config, sourceRoot, configDir, logger) {
|
|
|
22316
23121
|
logger
|
|
22317
23122
|
);
|
|
22318
23123
|
removeManagedJsonFile(
|
|
22319
|
-
|
|
23124
|
+
path22.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
22320
23125
|
"_tangyr",
|
|
22321
23126
|
logger
|
|
22322
23127
|
);
|
|
@@ -22473,40 +23278,40 @@ function removeManagedValueByKey2(value, keyName, keyValue) {
|
|
|
22473
23278
|
function removeManagedDirectPath(artifactPath, config, sourceRoot, component, logger) {
|
|
22474
23279
|
const artifactClass = classifyArtifact(artifactPath, config, sourceRoot);
|
|
22475
23280
|
if (artifactClass === "managed-symlink" || artifactClass === "managed-compiled" || artifactClass === "managed-stale") {
|
|
22476
|
-
|
|
23281
|
+
fs24.rmSync(artifactPath, { recursive: true, force: true });
|
|
22477
23282
|
logger.info(`${component}: removed ${artifactPath}`);
|
|
22478
23283
|
}
|
|
22479
23284
|
}
|
|
22480
23285
|
function removeManagedCompiledFiles(dir, pattern, expectedTarget, logger) {
|
|
22481
|
-
for (const filePath of ts(
|
|
23286
|
+
for (const filePath of ts(path22.join(dir, pattern)).sort()) {
|
|
22482
23287
|
removeManagedCompiledFile(filePath, expectedTarget, logger);
|
|
22483
23288
|
}
|
|
22484
23289
|
}
|
|
22485
23290
|
function removeManagedCompiledFile(filePath, expectedTarget, logger) {
|
|
22486
|
-
if (!
|
|
23291
|
+
if (!fs24.existsSync(filePath)) {
|
|
22487
23292
|
return;
|
|
22488
23293
|
}
|
|
22489
|
-
const marker = extractProvenanceMarker(
|
|
23294
|
+
const marker = extractProvenanceMarker(fs24.readFileSync(filePath, "utf8"));
|
|
22490
23295
|
if (marker?.target === expectedTarget) {
|
|
22491
|
-
|
|
23296
|
+
fs24.rmSync(filePath, { force: true });
|
|
22492
23297
|
logger.info(`removed ${filePath}`);
|
|
22493
23298
|
}
|
|
22494
23299
|
}
|
|
22495
23300
|
function removeManagedJsonFile(filePath, markerKey, logger) {
|
|
22496
|
-
if (!
|
|
23301
|
+
if (!fs24.existsSync(filePath)) {
|
|
22497
23302
|
return;
|
|
22498
23303
|
}
|
|
22499
23304
|
const parsed = readJsonObject(filePath);
|
|
22500
23305
|
if (isRecord(parsed[markerKey])) {
|
|
22501
|
-
|
|
23306
|
+
fs24.rmSync(filePath, { force: true });
|
|
22502
23307
|
logger.info(`removed ${filePath}`);
|
|
22503
23308
|
}
|
|
22504
23309
|
}
|
|
22505
23310
|
function removeCodexManagedTomlSection(filePath, logger) {
|
|
22506
|
-
if (!
|
|
23311
|
+
if (!fs24.existsSync(filePath)) {
|
|
22507
23312
|
return;
|
|
22508
23313
|
}
|
|
22509
|
-
const content =
|
|
23314
|
+
const content = fs24.readFileSync(filePath, "utf8");
|
|
22510
23315
|
const next = removeDelimitedManagedSection2(
|
|
22511
23316
|
content,
|
|
22512
23317
|
codexManagedMcpStart2,
|
|
@@ -22515,7 +23320,7 @@ function removeCodexManagedTomlSection(filePath, logger) {
|
|
|
22515
23320
|
if (next === content) {
|
|
22516
23321
|
return;
|
|
22517
23322
|
}
|
|
22518
|
-
|
|
23323
|
+
fs24.writeFileSync(filePath, next);
|
|
22519
23324
|
logger.info(`mcp: removed managed section from ${filePath}`);
|
|
22520
23325
|
}
|
|
22521
23326
|
function removeDelimitedManagedSection2(content, startMarker, endMarker) {
|
|
@@ -22587,9 +23392,9 @@ function toVerbosity(value) {
|
|
|
22587
23392
|
}
|
|
22588
23393
|
|
|
22589
23394
|
// src/commands/detect.ts
|
|
22590
|
-
import
|
|
23395
|
+
import fs25 from "fs";
|
|
22591
23396
|
import os5 from "os";
|
|
22592
|
-
import
|
|
23397
|
+
import path23 from "path";
|
|
22593
23398
|
import { spawnSync } from "child_process";
|
|
22594
23399
|
var copilotEditorCommands = [
|
|
22595
23400
|
"code",
|
|
@@ -22623,18 +23428,27 @@ var bundledCopilotManifestPathsByPlatform = {
|
|
|
22623
23428
|
"/Applications/Windsurf.app/Contents/Resources/app/extensions/copilot/package.json"
|
|
22624
23429
|
]
|
|
22625
23430
|
};
|
|
22626
|
-
|
|
23431
|
+
var bundledCursorExecutablePathsByPlatform = {
|
|
23432
|
+
darwin: ["/Applications/Cursor.app/Contents/Resources/app/bin/cursor"]
|
|
23433
|
+
};
|
|
23434
|
+
function detectTargets(logger, dependencies = {}) {
|
|
23435
|
+
const spawnSyncImpl = dependencies.spawnSyncImpl ?? defaultSpawnSync;
|
|
23436
|
+
const pathExists = dependencies.pathExists ?? fs25.existsSync;
|
|
23437
|
+
const homeDirectory = dependencies.homeDirectory ?? os5.homedir();
|
|
23438
|
+
const platform = dependencies.platform ?? process.platform;
|
|
23439
|
+
const locator = platform === "win32" ? "where.exe" : "which";
|
|
23440
|
+
const hasCommand = (command) => commandExists(locator, [command], logger, spawnSyncImpl);
|
|
22627
23441
|
const result = {
|
|
22628
|
-
"claude-code":
|
|
22629
|
-
|
|
22630
|
-
|
|
22631
|
-
|
|
22632
|
-
),
|
|
22633
|
-
|
|
22634
|
-
|
|
22635
|
-
|
|
22636
|
-
|
|
22637
|
-
|
|
23442
|
+
"claude-code": hasCommand("claude"),
|
|
23443
|
+
copilot: detectsCopilot(logger, dependencies),
|
|
23444
|
+
codex: hasCommand("codex"),
|
|
23445
|
+
opencode: hasCommand("opencode"),
|
|
23446
|
+
cursor: hasCommand("cursor") || cursorExecutablePaths(platform, homeDirectory).some(pathExists),
|
|
23447
|
+
cline: hasCommand("cline") || detectEditorExtension(
|
|
23448
|
+
"Cline",
|
|
23449
|
+
isClineExtensionEntry,
|
|
23450
|
+
logger,
|
|
23451
|
+
dependencies
|
|
22638
23452
|
)
|
|
22639
23453
|
};
|
|
22640
23454
|
return result;
|
|
@@ -22650,14 +23464,41 @@ function runDetectCommand(options, logger) {
|
|
|
22650
23464
|
}
|
|
22651
23465
|
process.exitCode = Object.values(result).some(Boolean) ? 0 : 3;
|
|
22652
23466
|
}
|
|
22653
|
-
function detectsCopilot(logger) {
|
|
22654
|
-
return detectCopilot(logger);
|
|
23467
|
+
function detectsCopilot(logger, dependencies = {}) {
|
|
23468
|
+
return detectCopilot(logger, dependencies);
|
|
22655
23469
|
}
|
|
22656
23470
|
function detectCopilot(logger, dependencies = {}) {
|
|
23471
|
+
const pathExists = dependencies.pathExists ?? fs25.existsSync;
|
|
23472
|
+
const readFile = dependencies.readFile ?? ((filePath) => fs25.readFileSync(filePath, "utf8"));
|
|
23473
|
+
const platform = dependencies.platform ?? process.platform;
|
|
23474
|
+
if (detectEditorExtension(
|
|
23475
|
+
"Copilot",
|
|
23476
|
+
isCopilotExtensionEntry,
|
|
23477
|
+
logger,
|
|
23478
|
+
dependencies
|
|
23479
|
+
)) {
|
|
23480
|
+
return true;
|
|
23481
|
+
}
|
|
23482
|
+
for (const manifestPath of bundledCopilotManifestPathsByPlatform[platform] ?? []) {
|
|
23483
|
+
if (!pathExists(manifestPath)) {
|
|
23484
|
+
continue;
|
|
23485
|
+
}
|
|
23486
|
+
try {
|
|
23487
|
+
if (isBundledCopilotManifest(readFile(manifestPath))) {
|
|
23488
|
+
return true;
|
|
23489
|
+
}
|
|
23490
|
+
} catch (error) {
|
|
23491
|
+
logger?.verbose(
|
|
23492
|
+
`${manifestPath}: failed to inspect bundled Copilot runtime (${formatReadError(error)})`
|
|
23493
|
+
);
|
|
23494
|
+
}
|
|
23495
|
+
}
|
|
23496
|
+
return false;
|
|
23497
|
+
}
|
|
23498
|
+
function detectEditorExtension(label, matchesExtension, logger, dependencies = {}) {
|
|
22657
23499
|
const spawnSyncImpl = dependencies.spawnSyncImpl ?? defaultSpawnSync;
|
|
22658
|
-
const pathExists = dependencies.pathExists ??
|
|
22659
|
-
const readDirectory = dependencies.readDirectory ??
|
|
22660
|
-
const readFile = dependencies.readFile ?? ((filePath) => fs24.readFileSync(filePath, "utf8"));
|
|
23500
|
+
const pathExists = dependencies.pathExists ?? fs25.existsSync;
|
|
23501
|
+
const readDirectory = dependencies.readDirectory ?? fs25.readdirSync;
|
|
22661
23502
|
const homeDirectory = dependencies.homeDirectory ?? os5.homedir();
|
|
22662
23503
|
const platform = dependencies.platform ?? process.platform;
|
|
22663
23504
|
const commandCandidates = [
|
|
@@ -22680,41 +23521,40 @@ function detectCopilot(logger, dependencies = {}) {
|
|
|
22680
23521
|
if (result.status !== 0) {
|
|
22681
23522
|
continue;
|
|
22682
23523
|
}
|
|
22683
|
-
if (splitOutputEntries(result.stdout).some(
|
|
23524
|
+
if (splitOutputEntries(result.stdout).some(matchesExtension)) {
|
|
22684
23525
|
return true;
|
|
22685
23526
|
}
|
|
22686
23527
|
}
|
|
22687
23528
|
for (const relativeDirectory of copilotExtensionDirectories) {
|
|
22688
|
-
const extensionDirectory =
|
|
23529
|
+
const extensionDirectory = path23.join(homeDirectory, relativeDirectory);
|
|
22689
23530
|
if (!pathExists(extensionDirectory)) {
|
|
22690
23531
|
continue;
|
|
22691
23532
|
}
|
|
22692
23533
|
try {
|
|
22693
|
-
if (readDirectory(extensionDirectory).some(
|
|
23534
|
+
if (readDirectory(extensionDirectory).some(matchesExtension)) {
|
|
22694
23535
|
return true;
|
|
22695
23536
|
}
|
|
22696
23537
|
} catch (error) {
|
|
22697
23538
|
logger?.verbose(
|
|
22698
|
-
`${extensionDirectory}: failed to inspect
|
|
22699
|
-
);
|
|
22700
|
-
}
|
|
22701
|
-
}
|
|
22702
|
-
for (const manifestPath of bundledCopilotManifestPathsByPlatform[platform] ?? []) {
|
|
22703
|
-
if (!pathExists(manifestPath)) {
|
|
22704
|
-
continue;
|
|
22705
|
-
}
|
|
22706
|
-
try {
|
|
22707
|
-
if (isBundledCopilotManifest(readFile(manifestPath))) {
|
|
22708
|
-
return true;
|
|
22709
|
-
}
|
|
22710
|
-
} catch (error) {
|
|
22711
|
-
logger?.verbose(
|
|
22712
|
-
`${manifestPath}: failed to inspect bundled Copilot runtime (${formatReadError(error)})`
|
|
23539
|
+
`${extensionDirectory}: failed to inspect ${label} extensions (${formatReadError(error)})`
|
|
22713
23540
|
);
|
|
22714
23541
|
}
|
|
22715
23542
|
}
|
|
22716
23543
|
return false;
|
|
22717
23544
|
}
|
|
23545
|
+
function cursorExecutablePaths(platform, homeDirectory) {
|
|
23546
|
+
const systemPaths = bundledCursorExecutablePathsByPlatform[platform] ?? [];
|
|
23547
|
+
if (platform !== "darwin") {
|
|
23548
|
+
return [...systemPaths];
|
|
23549
|
+
}
|
|
23550
|
+
return [
|
|
23551
|
+
...systemPaths,
|
|
23552
|
+
path23.join(
|
|
23553
|
+
homeDirectory,
|
|
23554
|
+
"Applications/Cursor.app/Contents/Resources/app/bin/cursor"
|
|
23555
|
+
)
|
|
23556
|
+
];
|
|
23557
|
+
}
|
|
22718
23558
|
function defaultSpawnSync(command, args) {
|
|
22719
23559
|
return spawnSync(command, args, { encoding: "utf8" });
|
|
22720
23560
|
}
|
|
@@ -22727,6 +23567,9 @@ function splitOutputEntries(stdout) {
|
|
|
22727
23567
|
function isCopilotExtensionEntry(entry) {
|
|
22728
23568
|
return /^github\.copilot(?:-chat)?(?:@|-)/u.test(entry);
|
|
22729
23569
|
}
|
|
23570
|
+
function isClineExtensionEntry(entry) {
|
|
23571
|
+
return /^saoudrizwan\.claude-dev(?:@|-)/u.test(entry);
|
|
23572
|
+
}
|
|
22730
23573
|
function isBundledCopilotManifest(rawManifest) {
|
|
22731
23574
|
const parsed = JSON.parse(rawManifest);
|
|
22732
23575
|
if (!isRecord2(parsed)) {
|
|
@@ -22745,8 +23588,8 @@ function formatReadError(error) {
|
|
|
22745
23588
|
}
|
|
22746
23589
|
return String(error);
|
|
22747
23590
|
}
|
|
22748
|
-
function commandExists(command, args, logger) {
|
|
22749
|
-
const result =
|
|
23591
|
+
function commandExists(command, args, logger, spawnSyncImpl = defaultSpawnSync) {
|
|
23592
|
+
const result = spawnSyncImpl(command, args);
|
|
22750
23593
|
if (result.error) {
|
|
22751
23594
|
logDetectionError(`${command} ${args.join(" ")}`, result.error, logger);
|
|
22752
23595
|
return false;
|
|
@@ -22766,25 +23609,25 @@ function logDetectionError(attemptedCommand, error, logger) {
|
|
|
22766
23609
|
}
|
|
22767
23610
|
|
|
22768
23611
|
// src/commands/doctor.ts
|
|
22769
|
-
import
|
|
22770
|
-
import
|
|
23612
|
+
import fs27 from "fs";
|
|
23613
|
+
import path25 from "path";
|
|
22771
23614
|
|
|
22772
23615
|
// src/utils/fs.ts
|
|
22773
|
-
import
|
|
22774
|
-
import
|
|
23616
|
+
import fs26 from "fs";
|
|
23617
|
+
import path24 from "path";
|
|
22775
23618
|
function ensureDir(dirPath) {
|
|
22776
|
-
|
|
23619
|
+
fs26.mkdirSync(dirPath, { recursive: true });
|
|
22777
23620
|
}
|
|
22778
23621
|
function createRelativeSymlink(source, destination, type, options) {
|
|
22779
|
-
const absoluteSource =
|
|
22780
|
-
const relative =
|
|
23622
|
+
const absoluteSource = path24.resolve(source);
|
|
23623
|
+
const relative = path24.relative(realPathOrInput(path24.dirname(destination)), absoluteSource);
|
|
22781
23624
|
if (process.platform === "win32" && type === "dir") {
|
|
22782
|
-
|
|
23625
|
+
fs26.symlinkSync(absoluteSource, destination, "junction");
|
|
22783
23626
|
return;
|
|
22784
23627
|
}
|
|
22785
23628
|
if (process.platform === "win32" && type === "file") {
|
|
22786
23629
|
try {
|
|
22787
|
-
|
|
23630
|
+
fs26.symlinkSync(relative, destination, "file");
|
|
22788
23631
|
} catch (error) {
|
|
22789
23632
|
if (!hasErrorCode(error, "EPERM")) {
|
|
22790
23633
|
throw error;
|
|
@@ -22799,12 +23642,12 @@ function createRelativeSymlink(source, destination, type, options) {
|
|
|
22799
23642
|
}
|
|
22800
23643
|
return;
|
|
22801
23644
|
}
|
|
22802
|
-
|
|
23645
|
+
fs26.symlinkSync(relative, destination, type);
|
|
22803
23646
|
}
|
|
22804
23647
|
function createManagedCopy(source, destination, provenanceMarker, _logger) {
|
|
22805
|
-
ensureDir(
|
|
22806
|
-
const content =
|
|
22807
|
-
|
|
23648
|
+
ensureDir(path24.dirname(destination));
|
|
23649
|
+
const content = fs26.readFileSync(source, "utf8");
|
|
23650
|
+
fs26.writeFileSync(destination, `${provenanceMarker}
|
|
22808
23651
|
${content}`);
|
|
22809
23652
|
}
|
|
22810
23653
|
function hasErrorCode(error, expectedCode) {
|
|
@@ -22812,7 +23655,7 @@ function hasErrorCode(error, expectedCode) {
|
|
|
22812
23655
|
}
|
|
22813
23656
|
function realPathOrInput(filePath) {
|
|
22814
23657
|
try {
|
|
22815
|
-
return
|
|
23658
|
+
return fs26.realpathSync(filePath);
|
|
22816
23659
|
} catch {
|
|
22817
23660
|
return filePath;
|
|
22818
23661
|
}
|
|
@@ -22825,17 +23668,17 @@ function runDoctorCommand(options, logger) {
|
|
|
22825
23668
|
import.meta.url
|
|
22826
23669
|
);
|
|
22827
23670
|
const findings = [];
|
|
22828
|
-
if (!
|
|
23671
|
+
if (!fs27.existsSync(configPath)) {
|
|
22829
23672
|
findings.push(`${configPath}: missing`);
|
|
22830
23673
|
}
|
|
22831
|
-
const hooksJsonPath =
|
|
23674
|
+
const hooksJsonPath = path25.join(
|
|
22832
23675
|
sourceRoot,
|
|
22833
23676
|
config.source.hooks,
|
|
22834
23677
|
"hooks.json"
|
|
22835
23678
|
);
|
|
22836
|
-
if (
|
|
23679
|
+
if (fs27.existsSync(hooksJsonPath)) {
|
|
22837
23680
|
try {
|
|
22838
|
-
JSON.parse(
|
|
23681
|
+
JSON.parse(fs27.readFileSync(hooksJsonPath, "utf8"));
|
|
22839
23682
|
} catch (err) {
|
|
22840
23683
|
findings.push(
|
|
22841
23684
|
`hooks/hooks.json: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -22900,19 +23743,19 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
|
|
|
22900
23743
|
projectRoot
|
|
22901
23744
|
)) {
|
|
22902
23745
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
22903
|
-
const sourcePath = artifact.sourceKey ?
|
|
23746
|
+
const sourcePath = artifact.sourceKey ? path25.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
|
|
22904
23747
|
if (artifactClass === "managed-stale") {
|
|
22905
23748
|
findings.push(
|
|
22906
23749
|
`${artifact.component}: managed stale artifact at ${artifact.path}`
|
|
22907
23750
|
);
|
|
22908
23751
|
if (options.fix && sourcePath && isOurStaleSymlink(
|
|
22909
23752
|
artifact.path,
|
|
22910
|
-
/* @__PURE__ */ new Set([
|
|
23753
|
+
/* @__PURE__ */ new Set([path25.resolve(artifact.path)]),
|
|
22911
23754
|
config
|
|
22912
23755
|
)) {
|
|
22913
|
-
|
|
22914
|
-
ensureDir(
|
|
22915
|
-
const symlinkType =
|
|
23756
|
+
fs27.unlinkSync(artifact.path);
|
|
23757
|
+
ensureDir(path25.dirname(artifact.path));
|
|
23758
|
+
const symlinkType = fs27.statSync(sourcePath).isDirectory() ? "dir" : "file";
|
|
22916
23759
|
createRelativeSymlink(sourcePath, artifact.path, symlinkType, {
|
|
22917
23760
|
logger,
|
|
22918
23761
|
provenanceMarker: symlinkType === "file" && artifact.sourceKey ? formatProvenanceMarker(
|
|
@@ -22925,8 +23768,8 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
|
|
|
22925
23768
|
logger.info(`${artifact.component}: recreated managed symlink`);
|
|
22926
23769
|
}
|
|
22927
23770
|
}
|
|
22928
|
-
if (options.fix && !
|
|
22929
|
-
ensureDir(
|
|
23771
|
+
if (options.fix && !fs27.existsSync(path25.dirname(artifact.path))) {
|
|
23772
|
+
ensureDir(path25.dirname(artifact.path));
|
|
22930
23773
|
}
|
|
22931
23774
|
checkParentWritablePath(artifact.path, artifact.component, findings);
|
|
22932
23775
|
}
|
|
@@ -22941,7 +23784,7 @@ function checkCopilot(config, sourceRoot, configDir, findings) {
|
|
|
22941
23784
|
continue;
|
|
22942
23785
|
}
|
|
22943
23786
|
const label = `copilot: ${rawPath}`;
|
|
22944
|
-
if (key.endsWith("_shared_file") ||
|
|
23787
|
+
if (key.endsWith("_shared_file") || path25.extname(rawPath).length > 0) {
|
|
22945
23788
|
checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
|
|
22946
23789
|
continue;
|
|
22947
23790
|
}
|
|
@@ -22961,7 +23804,7 @@ function checkCodex(config, sourceRoot, configDir, findings, logger) {
|
|
|
22961
23804
|
continue;
|
|
22962
23805
|
}
|
|
22963
23806
|
const label = `codex: ${rawPath}`;
|
|
22964
|
-
if (key.endsWith("_shared_file") ||
|
|
23807
|
+
if (key.endsWith("_shared_file") || path25.extname(rawPath).length > 0) {
|
|
22965
23808
|
checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
|
|
22966
23809
|
continue;
|
|
22967
23810
|
}
|
|
@@ -22978,33 +23821,33 @@ function resolveHooksScriptPath(config, sourceRoot, configDir) {
|
|
|
22978
23821
|
scope: "global",
|
|
22979
23822
|
mappings: mappings.platformPaths
|
|
22980
23823
|
});
|
|
22981
|
-
return
|
|
23824
|
+
return path25.join(profile["claude-code"].hooks, "scripts");
|
|
22982
23825
|
} catch {
|
|
22983
23826
|
return resolveTargetPath("~/.agents/hooks/scripts");
|
|
22984
23827
|
}
|
|
22985
23828
|
}
|
|
22986
23829
|
function checkParentWritablePath(targetPath, label, findings) {
|
|
22987
|
-
checkWritablePath(
|
|
23830
|
+
checkWritablePath(path25.dirname(targetPath), `${label} parent`, findings);
|
|
22988
23831
|
}
|
|
22989
23832
|
function checkWritablePath(checkPath, label, findings) {
|
|
22990
|
-
if (!
|
|
23833
|
+
if (!fs27.existsSync(checkPath)) {
|
|
22991
23834
|
findings.push(`${label}: path does not exist`);
|
|
22992
23835
|
return;
|
|
22993
23836
|
}
|
|
22994
23837
|
try {
|
|
22995
|
-
|
|
23838
|
+
fs27.accessSync(checkPath, fs27.constants.R_OK | fs27.constants.W_OK);
|
|
22996
23839
|
} catch {
|
|
22997
23840
|
findings.push(`${label}: path is not readable and writable`);
|
|
22998
23841
|
}
|
|
22999
23842
|
}
|
|
23000
23843
|
function walkHookScripts(dir) {
|
|
23001
|
-
if (!
|
|
23844
|
+
if (!fs27.existsSync(dir)) {
|
|
23002
23845
|
return [];
|
|
23003
23846
|
}
|
|
23004
|
-
return
|
|
23847
|
+
return fs27.readdirSync(dir).map((entry) => path25.join(dir, entry)).filter((entryPath) => fs27.statSync(entryPath).isFile());
|
|
23005
23848
|
}
|
|
23006
23849
|
function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
|
|
23007
|
-
if (!
|
|
23850
|
+
if (!fs27.existsSync(scriptRoot)) {
|
|
23008
23851
|
return;
|
|
23009
23852
|
}
|
|
23010
23853
|
if (hasSymlinkAncestor(scriptRoot, resolveTargetPath("~/.agents")) || isInside(realPathOrInput2(scriptRoot), realPathOrInput2(sourceRoot))) {
|
|
@@ -23014,49 +23857,49 @@ function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
|
|
|
23014
23857
|
return;
|
|
23015
23858
|
}
|
|
23016
23859
|
for (const scriptPath of walkHookScripts(scriptRoot)) {
|
|
23017
|
-
|
|
23860
|
+
fs27.chmodSync(scriptPath, 493);
|
|
23018
23861
|
}
|
|
23019
23862
|
}
|
|
23020
23863
|
function hasSymlinkAncestor(targetPath, stopAt) {
|
|
23021
|
-
const relative =
|
|
23022
|
-
|
|
23023
|
-
|
|
23864
|
+
const relative = path25.relative(
|
|
23865
|
+
path25.resolve(stopAt),
|
|
23866
|
+
path25.resolve(targetPath)
|
|
23024
23867
|
);
|
|
23025
|
-
if (relative.startsWith("..") ||
|
|
23868
|
+
if (relative.startsWith("..") || path25.isAbsolute(relative)) {
|
|
23026
23869
|
return false;
|
|
23027
23870
|
}
|
|
23028
|
-
return relative.split(
|
|
23029
|
-
const candidate =
|
|
23030
|
-
|
|
23871
|
+
return relative.split(path25.sep).some((_segment, index, segments) => {
|
|
23872
|
+
const candidate = path25.join(
|
|
23873
|
+
path25.resolve(stopAt),
|
|
23031
23874
|
...segments.slice(0, index + 1)
|
|
23032
23875
|
);
|
|
23033
23876
|
try {
|
|
23034
|
-
return
|
|
23877
|
+
return fs27.lstatSync(candidate).isSymbolicLink();
|
|
23035
23878
|
} catch {
|
|
23036
23879
|
return false;
|
|
23037
23880
|
}
|
|
23038
23881
|
});
|
|
23039
23882
|
}
|
|
23040
23883
|
function isInside(childPath, parentPath) {
|
|
23041
|
-
const relative =
|
|
23042
|
-
return relative.length === 0 || !relative.startsWith("..") && !
|
|
23884
|
+
const relative = path25.relative(parentPath, childPath);
|
|
23885
|
+
return relative.length === 0 || !relative.startsWith("..") && !path25.isAbsolute(relative);
|
|
23043
23886
|
}
|
|
23044
23887
|
function realPathOrInput2(filePath) {
|
|
23045
23888
|
try {
|
|
23046
|
-
return
|
|
23889
|
+
return fs27.realpathSync(filePath);
|
|
23047
23890
|
} catch {
|
|
23048
23891
|
return filePath;
|
|
23049
23892
|
}
|
|
23050
23893
|
}
|
|
23051
23894
|
|
|
23052
23895
|
// src/commands/init.ts
|
|
23053
|
-
import
|
|
23054
|
-
import
|
|
23055
|
-
var
|
|
23896
|
+
import fs28 from "fs";
|
|
23897
|
+
import path26 from "path";
|
|
23898
|
+
var import_yaml7 = __toESM(require_dist(), 1);
|
|
23056
23899
|
async function runInitCommand(_options, logger) {
|
|
23057
23900
|
const sourceRoot = await dist_default6({
|
|
23058
23901
|
message: "Canonical Tangyr kit root",
|
|
23059
|
-
default:
|
|
23902
|
+
default: path26.resolve("projects/tangyr/agent-coding")
|
|
23060
23903
|
});
|
|
23061
23904
|
const componentCount = [
|
|
23062
23905
|
"CLAUDE.md",
|
|
@@ -23066,7 +23909,7 @@ async function runInitCommand(_options, logger) {
|
|
|
23066
23909
|
"rules",
|
|
23067
23910
|
"hooks"
|
|
23068
23911
|
].filter(
|
|
23069
|
-
(relativePath) =>
|
|
23912
|
+
(relativePath) => fs28.existsSync(path26.join(sourceRoot, relativePath))
|
|
23070
23913
|
).length;
|
|
23071
23914
|
const detectedTargets = detectTargets(logger);
|
|
23072
23915
|
const enabledTargets = await dist_default4({
|
|
@@ -23084,8 +23927,8 @@ async function runInitCommand(_options, logger) {
|
|
|
23084
23927
|
value
|
|
23085
23928
|
}))
|
|
23086
23929
|
});
|
|
23087
|
-
const configPath =
|
|
23088
|
-
if (
|
|
23930
|
+
const configPath = path26.join(sourceRoot, "tangyr.config.yaml");
|
|
23931
|
+
if (fs28.existsSync(configPath)) {
|
|
23089
23932
|
const overwrite = await dist_default5({
|
|
23090
23933
|
message: `${configPath} exists. Overwrite?`,
|
|
23091
23934
|
default: false
|
|
@@ -23095,9 +23938,9 @@ async function runInitCommand(_options, logger) {
|
|
|
23095
23938
|
return;
|
|
23096
23939
|
}
|
|
23097
23940
|
}
|
|
23098
|
-
|
|
23941
|
+
fs28.writeFileSync(
|
|
23099
23942
|
configPath,
|
|
23100
|
-
(0,
|
|
23943
|
+
(0, import_yaml7.stringify)({
|
|
23101
23944
|
schema: 1,
|
|
23102
23945
|
kitPath: ".",
|
|
23103
23946
|
source: {
|
|
@@ -23142,11 +23985,11 @@ import fs37 from "fs";
|
|
|
23142
23985
|
import path37 from "path";
|
|
23143
23986
|
|
|
23144
23987
|
// src/core/channel-state.ts
|
|
23145
|
-
import
|
|
23146
|
-
import
|
|
23988
|
+
import fs29 from "fs";
|
|
23989
|
+
import path27 from "path";
|
|
23147
23990
|
var CHANNEL_STATE_FILENAME = ".tangyr-channels.json";
|
|
23148
23991
|
function stateFilePath(cacheRoot) {
|
|
23149
|
-
return
|
|
23992
|
+
return path27.join(cacheRoot, CHANNEL_STATE_FILENAME);
|
|
23150
23993
|
}
|
|
23151
23994
|
function channelKey(kit, channel) {
|
|
23152
23995
|
return `${kit}/${channel}`;
|
|
@@ -23155,7 +23998,7 @@ function readState(cacheRoot) {
|
|
|
23155
23998
|
const filePath = stateFilePath(cacheRoot);
|
|
23156
23999
|
let raw;
|
|
23157
24000
|
try {
|
|
23158
|
-
raw =
|
|
24001
|
+
raw = fs29.readFileSync(filePath, "utf8");
|
|
23159
24002
|
} catch (err) {
|
|
23160
24003
|
if (err.code === "ENOENT") {
|
|
23161
24004
|
return { state: {} };
|
|
@@ -23202,13 +24045,13 @@ function writeChannelSequence(params) {
|
|
|
23202
24045
|
[key]: { sequence, version, seenAt: now.toISOString() }
|
|
23203
24046
|
};
|
|
23204
24047
|
const filePath = stateFilePath(cacheRoot);
|
|
23205
|
-
|
|
24048
|
+
fs29.mkdirSync(path27.dirname(filePath), { recursive: true, mode: 448 });
|
|
23206
24049
|
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
23207
|
-
|
|
24050
|
+
fs29.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
23208
24051
|
`, {
|
|
23209
24052
|
mode: 384
|
|
23210
24053
|
});
|
|
23211
|
-
|
|
24054
|
+
fs29.renameSync(tempPath, filePath);
|
|
23212
24055
|
}
|
|
23213
24056
|
function assertChannelNotRolledBack(params) {
|
|
23214
24057
|
const { originUrl, kit, channel, seen, seenVersion, incoming } = params;
|
|
@@ -23220,7 +24063,6 @@ function assertChannelNotRolledBack(params) {
|
|
|
23220
24063
|
}
|
|
23221
24064
|
|
|
23222
24065
|
// src/core/bundle.ts
|
|
23223
|
-
var DENY_LIST_TYPE = "tangyr.deny-list.v2";
|
|
23224
24066
|
var CHANNEL_POINTER_TYPE = "tangyr.channel-pointer.v1";
|
|
23225
24067
|
var DEFAULT_CHANNEL = "stable";
|
|
23226
24068
|
|
|
@@ -23344,47 +24186,6 @@ function verifyBundle(bundle, keys, expectedIdentity, now) {
|
|
|
23344
24186
|
verifyBundleSignature(bundle, keys, now);
|
|
23345
24187
|
verifyIdentity(bundle.manifest, expectedIdentity);
|
|
23346
24188
|
}
|
|
23347
|
-
function verifyDenyList(denyList, keys, now) {
|
|
23348
|
-
if (denyList === null || typeof denyList !== "object") {
|
|
23349
|
-
throw new IntegrityError(DENY_LIST_MALFORMED);
|
|
23350
|
-
}
|
|
23351
|
-
const actualKeys = Object.keys(denyList).sort();
|
|
23352
|
-
const expectedKeys = [
|
|
23353
|
-
"entries",
|
|
23354
|
-
"expiresAt",
|
|
23355
|
-
"issuedAt",
|
|
23356
|
-
"keyId",
|
|
23357
|
-
"sequence",
|
|
23358
|
-
"signature",
|
|
23359
|
-
"type"
|
|
23360
|
-
];
|
|
23361
|
-
if (actualKeys.length !== expectedKeys.length || actualKeys.some((key, index) => key !== expectedKeys[index])) {
|
|
23362
|
-
throw new IntegrityError(
|
|
23363
|
-
`${DENY_LIST_MALFORMED} Expected exactly [${expectedKeys.join(", ")}], got [${actualKeys.join(", ")}].`
|
|
23364
|
-
);
|
|
23365
|
-
}
|
|
23366
|
-
const list = denyList;
|
|
23367
|
-
const shapeOk = list.type === DENY_LIST_TYPE && typeof list.keyId === "string" && typeof list.signature === "string" && list.signature.length > 0 && Number.isSafeInteger(list.sequence) && list.sequence >= 0 && typeof list.issuedAt === "string" && typeof list.expiresAt === "string" && Array.isArray(list.entries) && list.entries.every((entry) => typeof entry === "string");
|
|
23368
|
-
if (!shapeOk) {
|
|
23369
|
-
throw new IntegrityError(DENY_LIST_MALFORMED);
|
|
23370
|
-
}
|
|
23371
|
-
const { signature, ...signed } = list;
|
|
23372
|
-
verifySignedPayload(
|
|
23373
|
-
canonicalJsonBytes(signed),
|
|
23374
|
-
signature,
|
|
23375
|
-
list.keyId,
|
|
23376
|
-
keys,
|
|
23377
|
-
now
|
|
23378
|
-
);
|
|
23379
|
-
assertFreshnessWindow(
|
|
23380
|
-
list.issuedAt,
|
|
23381
|
-
list.expiresAt,
|
|
23382
|
-
now,
|
|
23383
|
-
"An expired revocation deny-list is not evidence that nothing is revoked \u2014 the publisher must re-sign and republish it."
|
|
23384
|
-
);
|
|
23385
|
-
return list;
|
|
23386
|
-
}
|
|
23387
|
-
var DENY_LIST_MALFORMED = "Revocation deny-list response is malformed, unsigned, or corrupted \u2014 treated as an integrity failure, never as an absent deny-list (REQ-INT-009).";
|
|
23388
24189
|
function assertFreshnessWindow(issuedAt, expiresAt, now, expiryConsequence) {
|
|
23389
24190
|
const utcDesignatorPattern = /Z|[+-]\d{2}:\d{2}$/;
|
|
23390
24191
|
if (!utcDesignatorPattern.test(issuedAt) || !utcDesignatorPattern.test(expiresAt)) {
|
|
@@ -23437,101 +24238,32 @@ function verifyChannelPointer(pointer, expectedKit, expectedChannel, keys, now)
|
|
|
23437
24238
|
`${CHANNEL_POINTER_MALFORMED} Expected exactly [${expectedKeys.join(", ")}], got [${actualKeys.join(", ")}].`
|
|
23438
24239
|
);
|
|
23439
24240
|
}
|
|
23440
|
-
const candidate = pointer;
|
|
23441
|
-
const shapeOk = candidate.type === CHANNEL_POINTER_TYPE && typeof candidate.keyId === "string" && typeof candidate.kit === "string" && candidate.kit.length > 0 && typeof candidate.channel === "string" && candidate.channel.length > 0 && typeof candidate.version === "string" && candidate.version.length > 0 && typeof candidate.signature === "string" && candidate.signature.length > 0 && Number.isSafeInteger(candidate.sequence) && candidate.sequence >= 0 && typeof candidate.issuedAt === "string" && typeof candidate.expiresAt === "string";
|
|
23442
|
-
if (!shapeOk) {
|
|
23443
|
-
throw new IntegrityError(CHANNEL_POINTER_MALFORMED);
|
|
23444
|
-
}
|
|
23445
|
-
const { signature, ...signed } = candidate;
|
|
23446
|
-
verifySignedPayload(
|
|
23447
|
-
canonicalJsonBytes(signed),
|
|
23448
|
-
signature,
|
|
23449
|
-
candidate.keyId,
|
|
23450
|
-
keys,
|
|
23451
|
-
now
|
|
23452
|
-
);
|
|
23453
|
-
if (candidate.kit !== expectedKit || candidate.channel !== expectedChannel) {
|
|
23454
|
-
throw new IntegrityError(
|
|
23455
|
-
`Channel pointer is signed for ${candidate.kit}/${candidate.channel} but was served as ${expectedKit}/${expectedChannel}. A pointer the publisher signed for one channel is being presented as another's \u2014 refusing.`
|
|
23456
|
-
);
|
|
23457
|
-
}
|
|
23458
|
-
assertPathSafeComponent("version", candidate.version);
|
|
23459
|
-
assertFreshnessWindow(
|
|
23460
|
-
candidate.issuedAt,
|
|
23461
|
-
candidate.expiresAt,
|
|
23462
|
-
now,
|
|
23463
|
-
"An expired channel pointer is not evidence that it still names the newest version \u2014 the publisher must re-sign and republish it."
|
|
23464
|
-
);
|
|
23465
|
-
return candidate;
|
|
23466
|
-
}
|
|
23467
|
-
|
|
23468
|
-
// src/core/revocation-state.ts
|
|
23469
|
-
import fs29 from "fs";
|
|
23470
|
-
import path27 from "path";
|
|
23471
|
-
var REVOCATION_STATE_FILENAME = ".tangyr-revocation.json";
|
|
23472
|
-
function stateFilePath2(cacheRoot) {
|
|
23473
|
-
return path27.join(cacheRoot, REVOCATION_STATE_FILENAME);
|
|
23474
|
-
}
|
|
23475
|
-
function readState2(cacheRoot) {
|
|
23476
|
-
const filePath = stateFilePath2(cacheRoot);
|
|
23477
|
-
let raw;
|
|
23478
|
-
try {
|
|
23479
|
-
raw = fs29.readFileSync(filePath, "utf8");
|
|
23480
|
-
} catch (err) {
|
|
23481
|
-
if (err.code === "ENOENT") {
|
|
23482
|
-
return { state: {} };
|
|
23483
|
-
}
|
|
23484
|
-
return {
|
|
23485
|
-
state: {},
|
|
23486
|
-
warning: `Could not read ${filePath} (${err.message}); the deny-list replay guard starts from nothing for this run.`
|
|
23487
|
-
};
|
|
23488
|
-
}
|
|
23489
|
-
let parsed;
|
|
23490
|
-
try {
|
|
23491
|
-
parsed = JSON.parse(raw);
|
|
23492
|
-
} catch {
|
|
23493
|
-
return {
|
|
23494
|
-
state: {},
|
|
23495
|
-
warning: `${filePath} is not valid JSON; the deny-list replay guard starts from nothing for this run.`
|
|
23496
|
-
};
|
|
23497
|
-
}
|
|
23498
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
23499
|
-
return {
|
|
23500
|
-
state: {},
|
|
23501
|
-
warning: `${filePath} does not contain an object; the deny-list replay guard starts from nothing for this run.`
|
|
23502
|
-
};
|
|
23503
|
-
}
|
|
23504
|
-
return { state: parsed };
|
|
23505
|
-
}
|
|
23506
|
-
function readRevocationSequence(cacheRoot, originUrl) {
|
|
23507
|
-
const { state, warning } = readState2(cacheRoot);
|
|
23508
|
-
const record = state[originUrl];
|
|
23509
|
-
const sequence = record !== void 0 && Number.isSafeInteger(record.sequence) ? record.sequence : void 0;
|
|
23510
|
-
return warning === void 0 ? { sequence } : { sequence, warning };
|
|
23511
|
-
}
|
|
23512
|
-
function writeRevocationSequence(cacheRoot, originUrl, sequence, now) {
|
|
23513
|
-
const { state } = readState2(cacheRoot);
|
|
23514
|
-
const existing = state[originUrl]?.sequence;
|
|
23515
|
-
if (existing !== void 0 && existing >= sequence) {
|
|
23516
|
-
return;
|
|
23517
|
-
}
|
|
23518
|
-
state[originUrl] = { sequence, seenAt: now.toISOString() };
|
|
23519
|
-
const filePath = stateFilePath2(cacheRoot);
|
|
23520
|
-
fs29.mkdirSync(path27.dirname(filePath), { recursive: true, mode: 448 });
|
|
23521
|
-
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
23522
|
-
fs29.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
23523
|
-
`, {
|
|
23524
|
-
mode: 384
|
|
23525
|
-
});
|
|
23526
|
-
fs29.renameSync(tempPath, filePath);
|
|
23527
|
-
}
|
|
23528
|
-
function assertSequenceNotReplayed(params) {
|
|
23529
|
-
const { originUrl, seen, incoming } = params;
|
|
23530
|
-
if (seen !== void 0 && incoming < seen) {
|
|
24241
|
+
const candidate = pointer;
|
|
24242
|
+
const shapeOk = candidate.type === CHANNEL_POINTER_TYPE && typeof candidate.keyId === "string" && typeof candidate.kit === "string" && candidate.kit.length > 0 && typeof candidate.channel === "string" && candidate.channel.length > 0 && typeof candidate.version === "string" && candidate.version.length > 0 && typeof candidate.signature === "string" && candidate.signature.length > 0 && Number.isSafeInteger(candidate.sequence) && candidate.sequence >= 0 && typeof candidate.issuedAt === "string" && typeof candidate.expiresAt === "string";
|
|
24243
|
+
if (!shapeOk) {
|
|
24244
|
+
throw new IntegrityError(CHANNEL_POINTER_MALFORMED);
|
|
24245
|
+
}
|
|
24246
|
+
const { signature, ...signed } = candidate;
|
|
24247
|
+
verifySignedPayload(
|
|
24248
|
+
canonicalJsonBytes(signed),
|
|
24249
|
+
signature,
|
|
24250
|
+
candidate.keyId,
|
|
24251
|
+
keys,
|
|
24252
|
+
now
|
|
24253
|
+
);
|
|
24254
|
+
if (candidate.kit !== expectedKit || candidate.channel !== expectedChannel) {
|
|
23531
24255
|
throw new IntegrityError(
|
|
23532
|
-
`
|
|
24256
|
+
`Channel pointer is signed for ${candidate.kit}/${candidate.channel} but was served as ${expectedKit}/${expectedChannel}. A pointer the publisher signed for one channel is being presented as another's \u2014 refusing.`
|
|
23533
24257
|
);
|
|
23534
24258
|
}
|
|
24259
|
+
assertPathSafeComponent("version", candidate.version);
|
|
24260
|
+
assertFreshnessWindow(
|
|
24261
|
+
candidate.issuedAt,
|
|
24262
|
+
candidate.expiresAt,
|
|
24263
|
+
now,
|
|
24264
|
+
"An expired channel pointer is not evidence that it still names the newest version \u2014 the publisher must re-sign and republish it."
|
|
24265
|
+
);
|
|
24266
|
+
return candidate;
|
|
23535
24267
|
}
|
|
23536
24268
|
|
|
23537
24269
|
// src/core/materialize.ts
|
|
@@ -23579,7 +24311,6 @@ async function withBoundedRetry(operation, sleep2, logger) {
|
|
|
23579
24311
|
);
|
|
23580
24312
|
}
|
|
23581
24313
|
var BUNDLE_OBJECT_PATH_PREFIX = "/v1/kits";
|
|
23582
|
-
var DENY_LIST_OBJECT_PATH = "/v1/deny-list";
|
|
23583
24314
|
async function fetchVerifiedBundle(params) {
|
|
23584
24315
|
const { originUrl, reference, transport, keys, now, logger, sleep: sleep2 } = params;
|
|
23585
24316
|
const credentials = resolveCredentialNonInteractive();
|
|
@@ -23633,76 +24364,6 @@ async function fetchVerifiedBundle(params) {
|
|
|
23633
24364
|
}
|
|
23634
24365
|
return parsed;
|
|
23635
24366
|
}
|
|
23636
|
-
async function assertReferenceNotRevoked(params) {
|
|
23637
|
-
const {
|
|
23638
|
-
originUrl,
|
|
23639
|
-
reference,
|
|
23640
|
-
cacheRoot,
|
|
23641
|
-
transport,
|
|
23642
|
-
keys,
|
|
23643
|
-
now,
|
|
23644
|
-
logger,
|
|
23645
|
-
sleep: sleep2
|
|
23646
|
-
} = params;
|
|
23647
|
-
const credentials = resolveCredentialNonInteractive();
|
|
23648
|
-
const denyList = await withBoundedRetry(
|
|
23649
|
-
async () => {
|
|
23650
|
-
const controller = new AbortController();
|
|
23651
|
-
const response = await transport.fetchObjectStream(
|
|
23652
|
-
originUrl,
|
|
23653
|
-
DENY_LIST_OBJECT_PATH,
|
|
23654
|
-
credentials,
|
|
23655
|
-
controller.signal
|
|
23656
|
-
);
|
|
23657
|
-
if (response.status === 401 || response.status === 403) {
|
|
23658
|
-
throw new AuthenticationError(
|
|
23659
|
-
`The origin rejected the credential (HTTP ${response.status}) fetching the revocation deny-list. Set TANGYR_ACCESS_CLIENT_ID and TANGYR_ACCESS_CLIENT_SECRET, or run 'tangyr auth login'.`
|
|
23660
|
-
);
|
|
23661
|
-
}
|
|
23662
|
-
if (response.status !== 200) {
|
|
23663
|
-
throw new Error(
|
|
23664
|
-
`Unexpected HTTP ${response.status} fetching the revocation deny-list from ${originUrl}${DENY_LIST_OBJECT_PATH}.`
|
|
23665
|
-
);
|
|
23666
|
-
}
|
|
23667
|
-
const buffer = await readBoundedStream(
|
|
23668
|
-
response.body,
|
|
23669
|
-
MAX_TOTAL_BUNDLE_BYTES,
|
|
23670
|
-
() => controller.abort()
|
|
23671
|
-
);
|
|
23672
|
-
let parsed;
|
|
23673
|
-
try {
|
|
23674
|
-
parsed = JSON.parse(buffer.toString("utf8"));
|
|
23675
|
-
} catch {
|
|
23676
|
-
throw new IntegrityError(
|
|
23677
|
-
"Revocation deny-list response is not valid JSON \u2014 rejecting (REQ-INT-009)."
|
|
23678
|
-
);
|
|
23679
|
-
}
|
|
23680
|
-
return verifyDenyList(parsed, keys, now);
|
|
23681
|
-
},
|
|
23682
|
-
sleep2,
|
|
23683
|
-
logger
|
|
23684
|
-
);
|
|
23685
|
-
const seen = readRevocationSequence(cacheRoot, originUrl);
|
|
23686
|
-
if (seen.warning) {
|
|
23687
|
-
logger.warn(seen.warning);
|
|
23688
|
-
}
|
|
23689
|
-
assertSequenceNotReplayed({
|
|
23690
|
-
originUrl,
|
|
23691
|
-
seen: seen.sequence,
|
|
23692
|
-
incoming: denyList.sequence
|
|
23693
|
-
});
|
|
23694
|
-
writeRevocationSequence(cacheRoot, originUrl, denyList.sequence, now);
|
|
23695
|
-
const key = `${reference.name}@${reference.version}`;
|
|
23696
|
-
if (denyList.entries.includes(key)) {
|
|
23697
|
-
const entryDir = cacheEntryPath(cacheRoot, reference);
|
|
23698
|
-
if (fs30.existsSync(entryDir)) {
|
|
23699
|
-
fs30.rmSync(entryDir, { recursive: true, force: true });
|
|
23700
|
-
}
|
|
23701
|
-
throw new IntegrityError(
|
|
23702
|
-
`"${key}" is present on the signed revocation deny-list \u2014 refusing to materialize or install; any existing cache entry has been invalidated (REQ-INT-009).`
|
|
23703
|
-
);
|
|
23704
|
-
}
|
|
23705
|
-
}
|
|
23706
24367
|
function parseVersionTriple(version) {
|
|
23707
24368
|
const leading = version.split("-")[0];
|
|
23708
24369
|
const parts = leading.split(".");
|
|
@@ -23873,16 +24534,6 @@ async function materializeRemoteKit(params) {
|
|
|
23873
24534
|
logger,
|
|
23874
24535
|
sleep: sleep2
|
|
23875
24536
|
});
|
|
23876
|
-
await assertReferenceNotRevoked({
|
|
23877
|
-
originUrl,
|
|
23878
|
-
reference,
|
|
23879
|
-
cacheRoot,
|
|
23880
|
-
transport,
|
|
23881
|
-
keys,
|
|
23882
|
-
now,
|
|
23883
|
-
logger,
|
|
23884
|
-
sleep: sleep2
|
|
23885
|
-
});
|
|
23886
24537
|
assertCliVersionCompatible(bundle.manifest.minCliVersion, CLI_VERSION);
|
|
23887
24538
|
const decoded = verifyBundleFileHashes(bundle);
|
|
23888
24539
|
if (decoded.has(CACHE_COMPLETION_MARKER) || decoded.has(BUNDLE_DOCUMENT_FILENAME)) {
|
|
@@ -24081,7 +24732,7 @@ async function resolveKitSource(params) {
|
|
|
24081
24732
|
}
|
|
24082
24733
|
function degradedWarmReturn() {
|
|
24083
24734
|
process.stderr.write(
|
|
24084
|
-
`Degraded: proceeding on the warm cache for "${reference.name}@${reference.version}" after a network failure during the authorization-freshness re-check \u2014
|
|
24735
|
+
`Degraded: proceeding on the warm cache for "${reference.name}@${reference.version}" after a network failure during the authorization-freshness re-check \u2014 freshness was not re-checked. Run with --refresh once connectivity is restored.
|
|
24085
24736
|
`
|
|
24086
24737
|
);
|
|
24087
24738
|
return {
|
|
@@ -24123,23 +24774,6 @@ async function resolveKitSource(params) {
|
|
|
24123
24774
|
);
|
|
24124
24775
|
}
|
|
24125
24776
|
if (probeOutcome.outcome === "success") {
|
|
24126
|
-
try {
|
|
24127
|
-
await assertReferenceNotRevoked({
|
|
24128
|
-
originUrl: config.source.url,
|
|
24129
|
-
reference,
|
|
24130
|
-
cacheRoot,
|
|
24131
|
-
transport,
|
|
24132
|
-
keys,
|
|
24133
|
-
now,
|
|
24134
|
-
logger,
|
|
24135
|
-
sleep: sleep2
|
|
24136
|
-
});
|
|
24137
|
-
} catch (error) {
|
|
24138
|
-
if (!(error instanceof RemoteUnavailableError)) {
|
|
24139
|
-
throw error;
|
|
24140
|
-
}
|
|
24141
|
-
return degradedWarmReturn();
|
|
24142
|
-
}
|
|
24143
24777
|
writeLastAuthorizedAt(cacheRoot, config.source.url, now);
|
|
24144
24778
|
const warning = formatAdvanceExpiryWarning(
|
|
24145
24779
|
probeOutcome.metadata.expiresAt,
|
|
@@ -24262,7 +24896,7 @@ import path31 from "path";
|
|
|
24262
24896
|
|
|
24263
24897
|
// src/compiler/agents.ts
|
|
24264
24898
|
var TOML = __toESM(require_toml(), 1);
|
|
24265
|
-
var
|
|
24899
|
+
var import_yaml8 = __toESM(require_dist(), 1);
|
|
24266
24900
|
import path29 from "path";
|
|
24267
24901
|
|
|
24268
24902
|
// src/compiler/loss-report.ts
|
|
@@ -24388,7 +25022,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
24388
25022
|
if (target === "copilot") {
|
|
24389
25023
|
return `${marker}
|
|
24390
25024
|
---
|
|
24391
|
-
${(0,
|
|
25025
|
+
${(0, import_yaml8.stringify)(targetFields).trim()}
|
|
24392
25026
|
---
|
|
24393
25027
|
|
|
24394
25028
|
${body}`;
|
|
@@ -24474,7 +25108,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
24474
25108
|
);
|
|
24475
25109
|
return `${marker}
|
|
24476
25110
|
---
|
|
24477
|
-
${(0,
|
|
25111
|
+
${(0, import_yaml8.stringify)(frontmatter).trim()}
|
|
24478
25112
|
---
|
|
24479
25113
|
`;
|
|
24480
25114
|
}
|
|
@@ -24553,7 +25187,7 @@ ${body.trim()}
|
|
|
24553
25187
|
` : "";
|
|
24554
25188
|
return `${marker}
|
|
24555
25189
|
---
|
|
24556
|
-
${(0,
|
|
25190
|
+
${(0, import_yaml8.stringify)(frontmatter).trim()}
|
|
24557
25191
|
---
|
|
24558
25192
|
${bodySection}`;
|
|
24559
25193
|
}
|
|
@@ -25244,7 +25878,7 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
|
|
|
25244
25878
|
|
|
25245
25879
|
// src/compiler/rules.ts
|
|
25246
25880
|
import path30 from "path";
|
|
25247
|
-
var
|
|
25881
|
+
var import_yaml9 = __toESM(require_dist(), 1);
|
|
25248
25882
|
import fs31 from "fs";
|
|
25249
25883
|
function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
25250
25884
|
if (target === "copilot") {
|
|
@@ -25323,7 +25957,7 @@ function parseRule(ruleFile) {
|
|
|
25323
25957
|
if (endIndex === -1) {
|
|
25324
25958
|
throw new Error(`${ruleFile}: frontmatter is not closed`);
|
|
25325
25959
|
}
|
|
25326
|
-
const frontmatter = (0,
|
|
25960
|
+
const frontmatter = (0, import_yaml9.parse)(content.slice(4, endIndex));
|
|
25327
25961
|
const mode = isRuleMode(frontmatter) ? frontmatter.mode : "guidance";
|
|
25328
25962
|
return {
|
|
25329
25963
|
mode,
|
|
@@ -25375,7 +26009,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
|
25375
26009
|
if (endIndex !== -1) {
|
|
25376
26010
|
const frontmatterStr = content.slice(4, endIndex);
|
|
25377
26011
|
try {
|
|
25378
|
-
frontmatterData = (0,
|
|
26012
|
+
frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
|
|
25379
26013
|
} catch {
|
|
25380
26014
|
frontmatterData = {};
|
|
25381
26015
|
}
|
|
@@ -25422,7 +26056,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25422
26056
|
if (endIndex !== -1) {
|
|
25423
26057
|
const frontmatterStr = content.slice(4, endIndex);
|
|
25424
26058
|
try {
|
|
25425
|
-
frontmatterData = (0,
|
|
26059
|
+
frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
|
|
25426
26060
|
} catch {
|
|
25427
26061
|
frontmatterData = {};
|
|
25428
26062
|
}
|
|
@@ -26024,7 +26658,7 @@ import fs33 from "fs";
|
|
|
26024
26658
|
import path33 from "path";
|
|
26025
26659
|
|
|
26026
26660
|
// src/compiler/commands.ts
|
|
26027
|
-
var
|
|
26661
|
+
var import_yaml10 = __toESM(require_dist(), 1);
|
|
26028
26662
|
import path32 from "path";
|
|
26029
26663
|
function compileCommandPrompt(sourceFile) {
|
|
26030
26664
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
@@ -26038,7 +26672,7 @@ function compileCommandPrompt(sourceFile) {
|
|
|
26038
26672
|
);
|
|
26039
26673
|
return `${marker}
|
|
26040
26674
|
---
|
|
26041
|
-
${(0,
|
|
26675
|
+
${(0, import_yaml10.stringify)(fields).trim()}
|
|
26042
26676
|
---
|
|
26043
26677
|
|
|
26044
26678
|
${body.trimEnd()}
|
|
@@ -27614,7 +28248,7 @@ import crypto9 from "crypto";
|
|
|
27614
28248
|
import fs36 from "fs";
|
|
27615
28249
|
import os6 from "os";
|
|
27616
28250
|
import path36 from "path";
|
|
27617
|
-
var
|
|
28251
|
+
var import_yaml11 = __toESM(require_dist(), 1);
|
|
27618
28252
|
function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27619
28253
|
const scope = options.scope ?? "global";
|
|
27620
28254
|
const profile = resolveTargetPaths({
|
|
@@ -27834,12 +28468,12 @@ function applyProviderModelBinding(compiled, mappings) {
|
|
|
27834
28468
|
const after = compiled.slice(fmEnd);
|
|
27835
28469
|
let fields;
|
|
27836
28470
|
try {
|
|
27837
|
-
fields = (0,
|
|
28471
|
+
fields = (0, import_yaml11.parse)(yamlBlock) ?? {};
|
|
27838
28472
|
} catch {
|
|
27839
28473
|
return compiled;
|
|
27840
28474
|
}
|
|
27841
28475
|
fields.model = modelValue;
|
|
27842
|
-
return `${before}${(0,
|
|
28476
|
+
return `${before}${(0, import_yaml11.stringify)(fields).trim()}${after}`;
|
|
27843
28477
|
}
|
|
27844
28478
|
function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27845
28479
|
const sourceCommandsRoot = path36.join(sourceRoot, config.source.commands);
|
|
@@ -27869,7 +28503,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
|
|
|
27869
28503
|
);
|
|
27870
28504
|
const content = Object.keys(frontmatter).length > 0 ? `${marker}
|
|
27871
28505
|
---
|
|
27872
|
-
${(0,
|
|
28506
|
+
${(0, import_yaml11.stringify)(frontmatter).trim()}
|
|
27873
28507
|
---
|
|
27874
28508
|
|
|
27875
28509
|
${body.trimEnd()}
|
|
@@ -28109,7 +28743,7 @@ function parseCommandFile(commandFile) {
|
|
|
28109
28743
|
return { data: {}, body: content };
|
|
28110
28744
|
}
|
|
28111
28745
|
try {
|
|
28112
|
-
const data = (0,
|
|
28746
|
+
const data = (0, import_yaml11.parse)(content.slice(4, endIndex)) ?? {};
|
|
28113
28747
|
const body = content.slice(endIndex + "\n---".length).replace(/^\n/u, "");
|
|
28114
28748
|
return { data, body };
|
|
28115
28749
|
} catch {
|
|
@@ -29797,8 +30431,8 @@ function hashString6(value) {
|
|
|
29797
30431
|
}
|
|
29798
30432
|
|
|
29799
30433
|
// src/commands/sync.ts
|
|
29800
|
-
import
|
|
29801
|
-
import
|
|
30434
|
+
import fs41 from "fs";
|
|
30435
|
+
import path42 from "path";
|
|
29802
30436
|
|
|
29803
30437
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
29804
30438
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -30296,8 +30930,8 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
30296
30930
|
var source_default = chalk;
|
|
30297
30931
|
|
|
30298
30932
|
// src/adapters/claude-code.ts
|
|
30299
|
-
import
|
|
30300
|
-
import
|
|
30933
|
+
import fs40 from "fs";
|
|
30934
|
+
import path41 from "path";
|
|
30301
30935
|
|
|
30302
30936
|
// src/core/shim.ts
|
|
30303
30937
|
import crypto11 from "crypto";
|
|
@@ -30312,145 +30946,6 @@ function buildAgentsMdShim(shimPath, _agentsMdPath, target) {
|
|
|
30312
30946
|
${SHIM_BODY}`;
|
|
30313
30947
|
}
|
|
30314
30948
|
|
|
30315
|
-
// src/compiler/hook-components.ts
|
|
30316
|
-
var import_yaml11 = __toESM(require_dist(), 1);
|
|
30317
|
-
import fs40 from "fs";
|
|
30318
|
-
import path41 from "path";
|
|
30319
|
-
function parseHookDeclaration(filePath) {
|
|
30320
|
-
let raw;
|
|
30321
|
-
try {
|
|
30322
|
-
raw = fs40.readFileSync(filePath, "utf8");
|
|
30323
|
-
} catch {
|
|
30324
|
-
return null;
|
|
30325
|
-
}
|
|
30326
|
-
const fm = extractFrontmatter(raw);
|
|
30327
|
-
if (!fm) {
|
|
30328
|
-
return null;
|
|
30329
|
-
}
|
|
30330
|
-
const { name, description, events } = fm;
|
|
30331
|
-
if (typeof name !== "string" || !name.trim()) {
|
|
30332
|
-
return null;
|
|
30333
|
-
}
|
|
30334
|
-
if (typeof description !== "string" || !description.trim()) {
|
|
30335
|
-
return null;
|
|
30336
|
-
}
|
|
30337
|
-
if (!Array.isArray(events) || events.length === 0) {
|
|
30338
|
-
return null;
|
|
30339
|
-
}
|
|
30340
|
-
const parsedEvents = [];
|
|
30341
|
-
for (const entry of events) {
|
|
30342
|
-
if (!entry || typeof entry !== "object") {
|
|
30343
|
-
return null;
|
|
30344
|
-
}
|
|
30345
|
-
const ev = entry;
|
|
30346
|
-
if (typeof ev.event !== "string" || !ev.event.trim()) {
|
|
30347
|
-
return null;
|
|
30348
|
-
}
|
|
30349
|
-
if (typeof ev.timeout !== "number") {
|
|
30350
|
-
return null;
|
|
30351
|
-
}
|
|
30352
|
-
if (typeof ev.statusMessage !== "string" || !ev.statusMessage.trim()) {
|
|
30353
|
-
return null;
|
|
30354
|
-
}
|
|
30355
|
-
const parsed = {
|
|
30356
|
-
event: ev.event,
|
|
30357
|
-
timeout: ev.timeout,
|
|
30358
|
-
statusMessage: ev.statusMessage
|
|
30359
|
-
};
|
|
30360
|
-
if (typeof ev.matcher === "string" && ev.matcher.trim()) {
|
|
30361
|
-
parsed.matcher = ev.matcher;
|
|
30362
|
-
}
|
|
30363
|
-
parsedEvents.push(parsed);
|
|
30364
|
-
}
|
|
30365
|
-
return {
|
|
30366
|
-
name: name.trim(),
|
|
30367
|
-
description: description.trim(),
|
|
30368
|
-
events: parsedEvents
|
|
30369
|
-
};
|
|
30370
|
-
}
|
|
30371
|
-
function hookCommand(name) {
|
|
30372
|
-
return `npx tsx ~/.agents/hooks/scripts/${name}.ts`;
|
|
30373
|
-
}
|
|
30374
|
-
function synthesizeHooksJson(declarations) {
|
|
30375
|
-
const hooks = {};
|
|
30376
|
-
for (const decl of declarations) {
|
|
30377
|
-
for (const ev of decl.events) {
|
|
30378
|
-
if (!hooks[ev.event]) {
|
|
30379
|
-
hooks[ev.event] = [];
|
|
30380
|
-
}
|
|
30381
|
-
const entry = {
|
|
30382
|
-
hooks: [
|
|
30383
|
-
{
|
|
30384
|
-
type: "command",
|
|
30385
|
-
command: hookCommand(decl.name),
|
|
30386
|
-
timeout: ev.timeout,
|
|
30387
|
-
statusMessage: ev.statusMessage
|
|
30388
|
-
}
|
|
30389
|
-
]
|
|
30390
|
-
};
|
|
30391
|
-
if (ev.matcher !== void 0) {
|
|
30392
|
-
const ordered = {
|
|
30393
|
-
matcher: ev.matcher,
|
|
30394
|
-
hooks: entry.hooks
|
|
30395
|
-
};
|
|
30396
|
-
hooks[ev.event].push(ordered);
|
|
30397
|
-
} else {
|
|
30398
|
-
hooks[ev.event].push(entry);
|
|
30399
|
-
}
|
|
30400
|
-
}
|
|
30401
|
-
}
|
|
30402
|
-
return { hooks };
|
|
30403
|
-
}
|
|
30404
|
-
function loadSourceHooks(hooksDir, hookNames) {
|
|
30405
|
-
const hooksJsonPath = path41.join(hooksDir, "hooks.json");
|
|
30406
|
-
if (fs40.existsSync(hooksJsonPath)) {
|
|
30407
|
-
const raw = fs40.readFileSync(hooksJsonPath, "utf8");
|
|
30408
|
-
return JSON.parse(raw);
|
|
30409
|
-
}
|
|
30410
|
-
const declarations = loadHookDeclarations(hooksDir, hookNames);
|
|
30411
|
-
return synthesizeHooksJson(declarations);
|
|
30412
|
-
}
|
|
30413
|
-
function loadHookDeclarations(hooksDir, hookNames) {
|
|
30414
|
-
let names;
|
|
30415
|
-
if (hookNames && hookNames.length > 0) {
|
|
30416
|
-
names = hookNames;
|
|
30417
|
-
} else {
|
|
30418
|
-
if (!fs40.existsSync(hooksDir) || !fs40.statSync(hooksDir).isDirectory()) {
|
|
30419
|
-
return [];
|
|
30420
|
-
}
|
|
30421
|
-
names = fs40.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
|
|
30422
|
-
}
|
|
30423
|
-
const declarations = [];
|
|
30424
|
-
for (const name of names) {
|
|
30425
|
-
const filePath = path41.join(hooksDir, `${name}.md`);
|
|
30426
|
-
const decl = parseHookDeclaration(filePath);
|
|
30427
|
-
if (decl) {
|
|
30428
|
-
declarations.push(decl);
|
|
30429
|
-
}
|
|
30430
|
-
}
|
|
30431
|
-
return declarations;
|
|
30432
|
-
}
|
|
30433
|
-
function extractFrontmatter(content) {
|
|
30434
|
-
if (!content.startsWith("---\n")) {
|
|
30435
|
-
return null;
|
|
30436
|
-
}
|
|
30437
|
-
const endIndex = content.indexOf("\n---", 4);
|
|
30438
|
-
if (endIndex === -1) {
|
|
30439
|
-
return null;
|
|
30440
|
-
}
|
|
30441
|
-
const rawFm = content.slice(4, endIndex);
|
|
30442
|
-
let parsed;
|
|
30443
|
-
try {
|
|
30444
|
-
parsed = (0, import_yaml11.parse)(rawFm);
|
|
30445
|
-
} catch {
|
|
30446
|
-
return null;
|
|
30447
|
-
}
|
|
30448
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
30449
|
-
return null;
|
|
30450
|
-
}
|
|
30451
|
-
return parsed;
|
|
30452
|
-
}
|
|
30453
|
-
|
|
30454
30949
|
// src/adapters/claude-code.ts
|
|
30455
30950
|
function buildDirectComponents(profile) {
|
|
30456
30951
|
return [
|
|
@@ -30546,7 +31041,7 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
30546
31041
|
}
|
|
30547
31042
|
if (!shouldSkipComponent6(options, "instructions") && manifest && scopePath) {
|
|
30548
31043
|
const shimPath = profile.instructions_shim;
|
|
30549
|
-
const agentsMdPath =
|
|
31044
|
+
const agentsMdPath = path41.resolve(sourceRoot, config.source.instructions);
|
|
30550
31045
|
if (!options.dryRun) {
|
|
30551
31046
|
applyClaudeCodeShimUpgrade(
|
|
30552
31047
|
shimPath,
|
|
@@ -30600,13 +31095,13 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
30600
31095
|
}
|
|
30601
31096
|
function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
|
|
30602
31097
|
if (!mappings.modelTiers.custom_provider) return;
|
|
30603
|
-
const agentsDir =
|
|
30604
|
-
if (!
|
|
30605
|
-
for (const agentFile of ts(
|
|
31098
|
+
const agentsDir = path41.join(sourceRoot, config.source.agents);
|
|
31099
|
+
if (!fs40.existsSync(agentsDir)) return;
|
|
31100
|
+
for (const agentFile of ts(path41.join(agentsDir, "*.md")).sort()) {
|
|
30606
31101
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
30607
31102
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
30608
31103
|
if (hasProvider) {
|
|
30609
|
-
const basename =
|
|
31104
|
+
const basename = path41.basename(agentFile);
|
|
30610
31105
|
addLoss(lossReport, "claude-code", "agents", {
|
|
30611
31106
|
source: `agents/${basename}`,
|
|
30612
31107
|
fields: [
|
|
@@ -30631,19 +31126,19 @@ function shouldSkipComponent6(options, component) {
|
|
|
30631
31126
|
function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath, logger) {
|
|
30632
31127
|
const expectedBodyHash = shimBodyHash();
|
|
30633
31128
|
const shimContent = buildAgentsMdShim(shimPath, agentsMdPath, "claude-code");
|
|
30634
|
-
if (!
|
|
31129
|
+
if (!fs40.existsSync(shimPath)) {
|
|
30635
31130
|
manifest.artifacts.push({
|
|
30636
|
-
relativePath:
|
|
31131
|
+
relativePath: path41.relative(scopePath, shimPath),
|
|
30637
31132
|
hash: expectedBodyHash,
|
|
30638
31133
|
origin: "tangyr-managed"
|
|
30639
31134
|
});
|
|
30640
31135
|
writeManifest(scopePath, manifest);
|
|
30641
|
-
|
|
30642
|
-
|
|
31136
|
+
fs40.mkdirSync(path41.dirname(shimPath), { recursive: true });
|
|
31137
|
+
fs40.writeFileSync(shimPath, shimContent);
|
|
30643
31138
|
logger?.verbose(`instructions-shim: wrote @AGENTS.md shim -> ${shimPath}`);
|
|
30644
31139
|
return;
|
|
30645
31140
|
}
|
|
30646
|
-
const existing =
|
|
31141
|
+
const existing = fs40.readFileSync(shimPath, "utf8");
|
|
30647
31142
|
const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
30648
31143
|
const marker = extractProvenanceMarker(firstNonEmptyLine);
|
|
30649
31144
|
if (marker !== null && marker.hash === expectedBodyHash) {
|
|
@@ -30654,21 +31149,21 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
30654
31149
|
}
|
|
30655
31150
|
backupFile(shimPath, manifest);
|
|
30656
31151
|
writeManifest(scopePath, manifest);
|
|
30657
|
-
|
|
31152
|
+
fs40.writeFileSync(shimPath, shimContent);
|
|
30658
31153
|
manifest.artifacts.push({
|
|
30659
|
-
relativePath:
|
|
31154
|
+
relativePath: path41.relative(scopePath, shimPath),
|
|
30660
31155
|
hash: expectedBodyHash,
|
|
30661
31156
|
origin: "tangyr-managed"
|
|
30662
31157
|
});
|
|
30663
31158
|
logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
|
|
30664
31159
|
}
|
|
30665
31160
|
function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
|
|
30666
|
-
const source =
|
|
31161
|
+
const source = path41.resolve(
|
|
30667
31162
|
sourceRoot,
|
|
30668
31163
|
config.source[directComponent.sourceKey]
|
|
30669
31164
|
);
|
|
30670
31165
|
const destination = directComponent.destination;
|
|
30671
|
-
if (!
|
|
31166
|
+
if (!fs40.existsSync(source)) {
|
|
30672
31167
|
return skippedMissingSource6(directComponent.component, source);
|
|
30673
31168
|
}
|
|
30674
31169
|
if (options.dryRun) {
|
|
@@ -30690,7 +31185,7 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30690
31185
|
};
|
|
30691
31186
|
}
|
|
30692
31187
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
30693
|
-
|
|
31188
|
+
fs40.unlinkSync(destination);
|
|
30694
31189
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
30695
31190
|
return {
|
|
30696
31191
|
component: directComponent.component,
|
|
@@ -30698,9 +31193,9 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30698
31193
|
path: destination
|
|
30699
31194
|
};
|
|
30700
31195
|
} else if (artifactClass === "managed-symlink") {
|
|
30701
|
-
|
|
31196
|
+
fs40.unlinkSync(destination);
|
|
30702
31197
|
}
|
|
30703
|
-
ensureDir(
|
|
31198
|
+
ensureDir(path41.dirname(destination));
|
|
30704
31199
|
createRelativeSymlink(source, destination, directComponent.type, {
|
|
30705
31200
|
logger,
|
|
30706
31201
|
provenanceMarker: directComponent.type === "file" ? formatProvenanceMarker(
|
|
@@ -30717,8 +31212,8 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30717
31212
|
};
|
|
30718
31213
|
}
|
|
30719
31214
|
function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination, manifest, scopePath) {
|
|
30720
|
-
const source =
|
|
30721
|
-
if (!
|
|
31215
|
+
const source = path41.resolve(sourceRoot, config.source.skills);
|
|
31216
|
+
if (!fs40.existsSync(source)) {
|
|
30722
31217
|
return [skippedMissingSource6("skills", source)];
|
|
30723
31218
|
}
|
|
30724
31219
|
const declaredNames = resolveKitSkillNames(sourceRoot);
|
|
@@ -30728,7 +31223,7 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30728
31223
|
if (isLegacyWholesaleSymlink) {
|
|
30729
31224
|
for (const name of foreignSkillNames(source, declaredNames)) {
|
|
30730
31225
|
logger.info(
|
|
30731
|
-
`[dry-run] skills: migrate foreign skill ${
|
|
31226
|
+
`[dry-run] skills: migrate foreign skill ${path41.join(source, name)} -> ${path41.join(destination, name)}`
|
|
30732
31227
|
);
|
|
30733
31228
|
}
|
|
30734
31229
|
logger.info(
|
|
@@ -30736,9 +31231,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30736
31231
|
);
|
|
30737
31232
|
}
|
|
30738
31233
|
for (const name of declaredNames ?? listSkillDirNames(source)) {
|
|
30739
|
-
const skillDestination =
|
|
31234
|
+
const skillDestination = path41.join(destination, name);
|
|
30740
31235
|
logger.info(
|
|
30741
|
-
`[dry-run] skills: symlink ${
|
|
31236
|
+
`[dry-run] skills: symlink ${path41.join(source, name)} -> ${skillDestination}`
|
|
30742
31237
|
);
|
|
30743
31238
|
outcomes2.push({
|
|
30744
31239
|
component: "skills",
|
|
@@ -30771,9 +31266,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30771
31266
|
return outcomes;
|
|
30772
31267
|
}
|
|
30773
31268
|
function syncSingleSkill(config, sourceRoot, options, logger, source, destination, name, manifest, scopePath) {
|
|
30774
|
-
const skillSource =
|
|
30775
|
-
const skillDestination =
|
|
30776
|
-
if (!
|
|
31269
|
+
const skillSource = path41.join(source, name);
|
|
31270
|
+
const skillDestination = path41.join(destination, name);
|
|
31271
|
+
if (!fs40.existsSync(skillSource)) {
|
|
30777
31272
|
return skippedMissingSource6("skills", skillSource);
|
|
30778
31273
|
}
|
|
30779
31274
|
const artifactClass = classifyArtifact(skillDestination, config, sourceRoot);
|
|
@@ -30785,7 +31280,7 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
|
|
|
30785
31280
|
};
|
|
30786
31281
|
}
|
|
30787
31282
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(skillDestination, /* @__PURE__ */ new Set([skillDestination]), config)) {
|
|
30788
|
-
|
|
31283
|
+
fs40.unlinkSync(skillDestination);
|
|
30789
31284
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(
|
|
30790
31285
|
skillDestination,
|
|
30791
31286
|
config,
|
|
@@ -30796,25 +31291,25 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
|
|
|
30796
31291
|
)) {
|
|
30797
31292
|
return { component: "skills", status: "conflict", path: skillDestination };
|
|
30798
31293
|
} else if (artifactClass === "managed-symlink") {
|
|
30799
|
-
|
|
31294
|
+
fs40.unlinkSync(skillDestination);
|
|
30800
31295
|
}
|
|
30801
31296
|
createRelativeSymlink(skillSource, skillDestination, "dir");
|
|
30802
31297
|
return { component: "skills", status: "success", path: skillDestination };
|
|
30803
31298
|
}
|
|
30804
31299
|
function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger) {
|
|
30805
31300
|
const foreignNames = foreignSkillNames(source, declaredNames);
|
|
30806
|
-
|
|
31301
|
+
fs40.unlinkSync(destination);
|
|
30807
31302
|
ensureDir(destination);
|
|
30808
31303
|
for (const name of foreignNames) {
|
|
30809
|
-
const from =
|
|
30810
|
-
const to =
|
|
30811
|
-
if (
|
|
31304
|
+
const from = path41.join(source, name);
|
|
31305
|
+
const to = path41.join(destination, name);
|
|
31306
|
+
if (fs40.existsSync(to)) {
|
|
30812
31307
|
logger.warn(
|
|
30813
31308
|
`skills migration: ${to} already exists \u2014 skipping move of ${from} to avoid overwrite`
|
|
30814
31309
|
);
|
|
30815
31310
|
continue;
|
|
30816
31311
|
}
|
|
30817
|
-
|
|
31312
|
+
fs40.renameSync(from, to);
|
|
30818
31313
|
logger.info(`skills migration: moved ${from} -> ${to}`);
|
|
30819
31314
|
}
|
|
30820
31315
|
}
|
|
@@ -30826,21 +31321,21 @@ function foreignSkillNames(source, declaredNames) {
|
|
|
30826
31321
|
return listSkillDirNames(source).filter((name) => !declaredSet.has(name));
|
|
30827
31322
|
}
|
|
30828
31323
|
function listSkillDirNames(dir) {
|
|
30829
|
-
if (!
|
|
31324
|
+
if (!fs40.existsSync(dir)) {
|
|
30830
31325
|
return [];
|
|
30831
31326
|
}
|
|
30832
|
-
return
|
|
31327
|
+
return fs40.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
30833
31328
|
}
|
|
30834
31329
|
function isSymlinkPath(filePath) {
|
|
30835
31330
|
try {
|
|
30836
|
-
return
|
|
31331
|
+
return fs40.lstatSync(filePath).isSymbolicLink();
|
|
30837
31332
|
} catch {
|
|
30838
31333
|
return false;
|
|
30839
31334
|
}
|
|
30840
31335
|
}
|
|
30841
31336
|
function syncHookScriptsBridge(config, sourceRoot, options, logger, destination, manifest, scopePath) {
|
|
30842
|
-
const source =
|
|
30843
|
-
if (!
|
|
31337
|
+
const source = path41.resolve(sourceRoot, config.source.hooks);
|
|
31338
|
+
if (!fs40.existsSync(source)) {
|
|
30844
31339
|
return skippedMissingSource6("hooks", source);
|
|
30845
31340
|
}
|
|
30846
31341
|
if (options.dryRun) {
|
|
@@ -30852,13 +31347,13 @@ function syncHookScriptsBridge(config, sourceRoot, options, logger, destination,
|
|
|
30852
31347
|
return { component: "hooks", status: "skipped-current", path: destination };
|
|
30853
31348
|
}
|
|
30854
31349
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
30855
|
-
|
|
31350
|
+
fs40.unlinkSync(destination);
|
|
30856
31351
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
30857
31352
|
return { component: "hooks", status: "conflict", path: destination };
|
|
30858
31353
|
} else if (artifactClass === "managed-symlink") {
|
|
30859
|
-
|
|
31354
|
+
fs40.unlinkSync(destination);
|
|
30860
31355
|
}
|
|
30861
|
-
ensureDir(
|
|
31356
|
+
ensureDir(path41.dirname(destination));
|
|
30862
31357
|
createRelativeSymlink(source, destination, "dir");
|
|
30863
31358
|
return { component: "hooks", status: "success", path: destination };
|
|
30864
31359
|
}
|
|
@@ -30881,7 +31376,7 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
|
|
|
30881
31376
|
destination,
|
|
30882
31377
|
settings,
|
|
30883
31378
|
stringifyJson3,
|
|
30884
|
-
!
|
|
31379
|
+
!fs40.existsSync(destination),
|
|
30885
31380
|
logger
|
|
30886
31381
|
);
|
|
30887
31382
|
return {
|
|
@@ -30891,8 +31386,8 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
|
|
|
30891
31386
|
};
|
|
30892
31387
|
}
|
|
30893
31388
|
function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
30894
|
-
const source =
|
|
30895
|
-
if (!
|
|
31389
|
+
const source = path41.resolve(sourceRoot, config.source.mcp);
|
|
31390
|
+
if (!fs40.existsSync(source)) {
|
|
30896
31391
|
return skippedMissingSource6("mcp", source);
|
|
30897
31392
|
}
|
|
30898
31393
|
if (options.dryRun) {
|
|
@@ -30917,7 +31412,7 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
|
30917
31412
|
destination,
|
|
30918
31413
|
hostConfig,
|
|
30919
31414
|
stringifyJson3,
|
|
30920
|
-
!
|
|
31415
|
+
!fs40.existsSync(destination),
|
|
30921
31416
|
logger
|
|
30922
31417
|
);
|
|
30923
31418
|
return {
|
|
@@ -30927,8 +31422,8 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
|
30927
31422
|
};
|
|
30928
31423
|
}
|
|
30929
31424
|
function syncSettings2(config, sourceRoot, options, logger, destination) {
|
|
30930
|
-
const source =
|
|
30931
|
-
if (!
|
|
31425
|
+
const source = path41.resolve(sourceRoot, config.source.settings);
|
|
31426
|
+
if (!fs40.existsSync(source)) {
|
|
30932
31427
|
return skippedMissingSource6("settings", source);
|
|
30933
31428
|
}
|
|
30934
31429
|
if (options.dryRun) {
|
|
@@ -30946,7 +31441,7 @@ function syncSettings2(config, sourceRoot, options, logger, destination) {
|
|
|
30946
31441
|
destination,
|
|
30947
31442
|
settings,
|
|
30948
31443
|
stringifyJson3,
|
|
30949
|
-
!
|
|
31444
|
+
!fs40.existsSync(destination),
|
|
30950
31445
|
logger
|
|
30951
31446
|
);
|
|
30952
31447
|
return {
|
|
@@ -30971,11 +31466,11 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
|
|
|
30971
31466
|
backupFile(destination, manifest);
|
|
30972
31467
|
writeManifest(scopePath, manifest);
|
|
30973
31468
|
} else {
|
|
30974
|
-
|
|
31469
|
+
fs40.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
30975
31470
|
}
|
|
30976
31471
|
return true;
|
|
30977
31472
|
}
|
|
30978
|
-
|
|
31473
|
+
fs40.rmSync(destination, { recursive: true, force: true });
|
|
30979
31474
|
return true;
|
|
30980
31475
|
}
|
|
30981
31476
|
function skippedMissingSource6(component, source) {
|
|
@@ -30987,16 +31482,16 @@ function skippedMissingSource6(component, source) {
|
|
|
30987
31482
|
}
|
|
30988
31483
|
function isSymlinkTo6(linkPath, source) {
|
|
30989
31484
|
try {
|
|
30990
|
-
return
|
|
31485
|
+
return fs40.realpathSync(linkPath) === fs40.realpathSync(source);
|
|
30991
31486
|
} catch {
|
|
30992
31487
|
return false;
|
|
30993
31488
|
}
|
|
30994
31489
|
}
|
|
30995
31490
|
function readJsonObject4(filePath) {
|
|
30996
|
-
if (!
|
|
31491
|
+
if (!fs40.existsSync(filePath)) {
|
|
30997
31492
|
return {};
|
|
30998
31493
|
}
|
|
30999
|
-
const parsed = JSON.parse(
|
|
31494
|
+
const parsed = JSON.parse(fs40.readFileSync(filePath, "utf8"));
|
|
31000
31495
|
return isRecord5(parsed) ? parsed : {};
|
|
31001
31496
|
}
|
|
31002
31497
|
function markManaged(value) {
|
|
@@ -31262,7 +31757,7 @@ function writeLossReport(filePath, report) {
|
|
|
31262
31757
|
if (!filePath) {
|
|
31263
31758
|
return;
|
|
31264
31759
|
}
|
|
31265
|
-
|
|
31760
|
+
fs41.writeFileSync(filePath, `${JSON.stringify(report, null, 2)}
|
|
31266
31761
|
`);
|
|
31267
31762
|
}
|
|
31268
31763
|
function prepareKitManifest(scope, projectRoot, kitInfo) {
|
|
@@ -31303,8 +31798,8 @@ function updateManifest(kitInfo, kitSync) {
|
|
|
31303
31798
|
writeManifest(kitSync.scopePath, kitSync.manifest);
|
|
31304
31799
|
}
|
|
31305
31800
|
function resolveKitFilePath(kitPath, relativePath) {
|
|
31306
|
-
const fullPath =
|
|
31307
|
-
return
|
|
31801
|
+
const fullPath = path42.join(kitPath, relativePath);
|
|
31802
|
+
return fs41.existsSync(fullPath) ? fullPath : null;
|
|
31308
31803
|
}
|
|
31309
31804
|
function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
|
|
31310
31805
|
if (removedSourcePaths.length === 0 || !mappings) {
|
|
@@ -31365,9 +31860,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31365
31860
|
}
|
|
31366
31861
|
if (relativePath.startsWith("agents/")) {
|
|
31367
31862
|
removeManagedCompiledArtifact2(
|
|
31368
|
-
|
|
31863
|
+
path42.join(
|
|
31369
31864
|
resolveTargetPath(paths.agents ?? ""),
|
|
31370
|
-
`${
|
|
31865
|
+
`${path42.parse(relativePath).name}.agent.md`
|
|
31371
31866
|
),
|
|
31372
31867
|
"copilot",
|
|
31373
31868
|
relativePath,
|
|
@@ -31377,9 +31872,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31377
31872
|
}
|
|
31378
31873
|
if (relativePath.startsWith("commands/")) {
|
|
31379
31874
|
removeManagedCompiledArtifact2(
|
|
31380
|
-
|
|
31875
|
+
path42.join(
|
|
31381
31876
|
resolveTargetPath(paths.prompts ?? ""),
|
|
31382
|
-
`${
|
|
31877
|
+
`${path42.parse(relativePath).name}.prompt.md`
|
|
31383
31878
|
),
|
|
31384
31879
|
"copilot",
|
|
31385
31880
|
relativePath,
|
|
@@ -31389,7 +31884,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31389
31884
|
}
|
|
31390
31885
|
if (relativePath.endsWith("hooks.json")) {
|
|
31391
31886
|
removeManagedCompiledArtifact2(
|
|
31392
|
-
|
|
31887
|
+
path42.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
31393
31888
|
"copilot",
|
|
31394
31889
|
relativePath,
|
|
31395
31890
|
logger
|
|
@@ -31419,9 +31914,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
31419
31914
|
}
|
|
31420
31915
|
if (relativePath.startsWith("agents/")) {
|
|
31421
31916
|
removeManagedCompiledArtifact2(
|
|
31422
|
-
|
|
31917
|
+
path42.join(
|
|
31423
31918
|
resolveTargetPath(paths.agents ?? ""),
|
|
31424
|
-
`${
|
|
31919
|
+
`${path42.parse(relativePath).name}.toml`
|
|
31425
31920
|
),
|
|
31426
31921
|
"codex",
|
|
31427
31922
|
relativePath,
|
|
@@ -31431,9 +31926,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
31431
31926
|
}
|
|
31432
31927
|
if (relativePath.startsWith("rules/")) {
|
|
31433
31928
|
removeManagedCompiledArtifact2(
|
|
31434
|
-
|
|
31929
|
+
path42.join(
|
|
31435
31930
|
resolveTargetPath(paths.rules ?? ""),
|
|
31436
|
-
`${
|
|
31931
|
+
`${path42.parse(relativePath).name}.rules`
|
|
31437
31932
|
),
|
|
31438
31933
|
"codex",
|
|
31439
31934
|
relativePath,
|
|
@@ -31472,9 +31967,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
31472
31967
|
}
|
|
31473
31968
|
if (relativePath.startsWith("agents/")) {
|
|
31474
31969
|
removeManagedCompiledArtifact2(
|
|
31475
|
-
|
|
31970
|
+
path42.join(
|
|
31476
31971
|
resolveTargetPath(paths.agents ?? ""),
|
|
31477
|
-
`${
|
|
31972
|
+
`${path42.parse(relativePath).name}.md`
|
|
31478
31973
|
),
|
|
31479
31974
|
"opencode",
|
|
31480
31975
|
relativePath,
|
|
@@ -31484,9 +31979,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
31484
31979
|
}
|
|
31485
31980
|
if (relativePath.startsWith("commands/")) {
|
|
31486
31981
|
removeManagedCompiledArtifact2(
|
|
31487
|
-
|
|
31982
|
+
path42.join(
|
|
31488
31983
|
resolveTargetPath(paths.commands ?? ""),
|
|
31489
|
-
`${
|
|
31984
|
+
`${path42.parse(relativePath).name}.md`
|
|
31490
31985
|
),
|
|
31491
31986
|
"opencode",
|
|
31492
31987
|
relativePath,
|
|
@@ -31518,9 +32013,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31518
32013
|
}
|
|
31519
32014
|
if (relativePath.startsWith("agents/")) {
|
|
31520
32015
|
removeManagedCompiledArtifact2(
|
|
31521
|
-
|
|
32016
|
+
path42.join(
|
|
31522
32017
|
resolveTargetPath(paths.agents ?? ""),
|
|
31523
|
-
`${
|
|
32018
|
+
`${path42.parse(relativePath).name}.md`
|
|
31524
32019
|
),
|
|
31525
32020
|
"cursor",
|
|
31526
32021
|
relativePath,
|
|
@@ -31530,9 +32025,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31530
32025
|
}
|
|
31531
32026
|
if (relativePath.startsWith("rules/")) {
|
|
31532
32027
|
removeManagedCompiledArtifact2(
|
|
31533
|
-
|
|
32028
|
+
path42.join(
|
|
31534
32029
|
resolveTargetPath(paths.rules ?? ""),
|
|
31535
|
-
`${
|
|
32030
|
+
`${path42.parse(relativePath).name}.mdc`
|
|
31536
32031
|
),
|
|
31537
32032
|
"cursor",
|
|
31538
32033
|
relativePath,
|
|
@@ -31542,9 +32037,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31542
32037
|
}
|
|
31543
32038
|
if (relativePath.startsWith("commands/")) {
|
|
31544
32039
|
removeManagedCompiledArtifact2(
|
|
31545
|
-
|
|
32040
|
+
path42.join(
|
|
31546
32041
|
resolveTargetPath(paths.skills ?? ""),
|
|
31547
|
-
|
|
32042
|
+
path42.parse(relativePath).name,
|
|
31548
32043
|
"SKILL.md"
|
|
31549
32044
|
),
|
|
31550
32045
|
"cursor",
|
|
@@ -31588,9 +32083,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31588
32083
|
}
|
|
31589
32084
|
if (relativePath.startsWith("rules/")) {
|
|
31590
32085
|
removeManagedCompiledArtifact2(
|
|
31591
|
-
|
|
32086
|
+
path42.join(
|
|
31592
32087
|
resolveTargetPath(paths.rules ?? ""),
|
|
31593
|
-
`${
|
|
32088
|
+
`${path42.parse(relativePath).name}.md`
|
|
31594
32089
|
),
|
|
31595
32090
|
"cline",
|
|
31596
32091
|
relativePath,
|
|
@@ -31600,9 +32095,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31600
32095
|
}
|
|
31601
32096
|
if (relativePath.startsWith("commands/")) {
|
|
31602
32097
|
removeManagedCompiledArtifact2(
|
|
31603
|
-
|
|
32098
|
+
path42.join(
|
|
31604
32099
|
resolveTargetPath(paths.workflows ?? ""),
|
|
31605
|
-
|
|
32100
|
+
path42.basename(relativePath)
|
|
31606
32101
|
),
|
|
31607
32102
|
"cline",
|
|
31608
32103
|
relativePath,
|
|
@@ -31620,17 +32115,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31620
32115
|
}
|
|
31621
32116
|
}
|
|
31622
32117
|
function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
|
|
31623
|
-
if (!
|
|
32118
|
+
if (!fs41.existsSync(artifactPath)) {
|
|
31624
32119
|
return;
|
|
31625
32120
|
}
|
|
31626
|
-
if (!
|
|
32121
|
+
if (!fs41.statSync(artifactPath).isFile()) {
|
|
31627
32122
|
return;
|
|
31628
32123
|
}
|
|
31629
|
-
const marker = extractProvenanceMarker(
|
|
32124
|
+
const marker = extractProvenanceMarker(fs41.readFileSync(artifactPath, "utf8"));
|
|
31630
32125
|
if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
|
|
31631
32126
|
return;
|
|
31632
32127
|
}
|
|
31633
|
-
|
|
32128
|
+
fs41.rmSync(artifactPath, { force: true });
|
|
31634
32129
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31635
32130
|
}
|
|
31636
32131
|
function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
@@ -31661,10 +32156,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
|
|
|
31661
32156
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31662
32157
|
}
|
|
31663
32158
|
function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
31664
|
-
if (!
|
|
32159
|
+
if (!fs41.existsSync(artifactPath)) {
|
|
31665
32160
|
return;
|
|
31666
32161
|
}
|
|
31667
|
-
const content =
|
|
32162
|
+
const content = fs41.readFileSync(artifactPath, "utf8");
|
|
31668
32163
|
const startMarker = "# tangyr: managed mcp start";
|
|
31669
32164
|
const endMarker = "# tangyr: managed mcp end";
|
|
31670
32165
|
const startIndex = content.indexOf(startMarker);
|
|
@@ -31681,19 +32176,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
|
31681
32176
|
const after = content.slice(endIndex + endMarker.length).trimStart();
|
|
31682
32177
|
const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
|
|
31683
32178
|
if (cleaned.length === 0) {
|
|
31684
|
-
|
|
32179
|
+
fs41.rmSync(artifactPath, { force: true });
|
|
31685
32180
|
} else {
|
|
31686
|
-
|
|
32181
|
+
fs41.writeFileSync(artifactPath, `${cleaned}
|
|
31687
32182
|
`);
|
|
31688
32183
|
}
|
|
31689
32184
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31690
32185
|
}
|
|
31691
32186
|
function readJsonObject5(filePath) {
|
|
31692
|
-
if (!
|
|
32187
|
+
if (!fs41.existsSync(filePath)) {
|
|
31693
32188
|
return null;
|
|
31694
32189
|
}
|
|
31695
32190
|
try {
|
|
31696
|
-
const parsed = JSON.parse(
|
|
32191
|
+
const parsed = JSON.parse(fs41.readFileSync(filePath, "utf8"));
|
|
31697
32192
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
31698
32193
|
} catch {
|
|
31699
32194
|
return null;
|
|
@@ -31707,10 +32202,10 @@ function readJsonMetadata(value) {
|
|
|
31707
32202
|
}
|
|
31708
32203
|
function writeJsonOrRemove2(filePath, parsed) {
|
|
31709
32204
|
if (isEmptyJsonValue2(parsed)) {
|
|
31710
|
-
|
|
32205
|
+
fs41.rmSync(filePath, { force: true });
|
|
31711
32206
|
return;
|
|
31712
32207
|
}
|
|
31713
|
-
|
|
32208
|
+
fs41.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
31714
32209
|
`);
|
|
31715
32210
|
}
|
|
31716
32211
|
function isEmptyJsonValue2(value) {
|
|
@@ -31770,8 +32265,8 @@ function removeManagedHookEntries(value, expectedSource) {
|
|
|
31770
32265
|
}
|
|
31771
32266
|
|
|
31772
32267
|
// src/commands/validate.ts
|
|
31773
|
-
import
|
|
31774
|
-
import
|
|
32268
|
+
import fs42 from "fs";
|
|
32269
|
+
import path43 from "path";
|
|
31775
32270
|
var SUPPORTED_KIT_FORMATS2 = [1];
|
|
31776
32271
|
var SUPPORTED_DISCIPLINE_VERSIONS = [
|
|
31777
32272
|
"0.14.0",
|
|
@@ -31855,8 +32350,8 @@ function checkKitFormatSupported(kit) {
|
|
|
31855
32350
|
}
|
|
31856
32351
|
function checkEntrypointExists(kit) {
|
|
31857
32352
|
const entrypoint = "CLAUDE.md";
|
|
31858
|
-
const entrypointPath =
|
|
31859
|
-
if (!
|
|
32353
|
+
const entrypointPath = path43.join(kit.path, entrypoint);
|
|
32354
|
+
if (!fs42.existsSync(entrypointPath)) {
|
|
31860
32355
|
return {
|
|
31861
32356
|
code: "entrypoint-missing",
|
|
31862
32357
|
location: entrypoint,
|
|
@@ -31913,9 +32408,9 @@ function checkComponentFrontmatter(kit) {
|
|
|
31913
32408
|
const missingSet = new Set(kit.components[cat].missing);
|
|
31914
32409
|
for (const name of kit.components[cat].declared) {
|
|
31915
32410
|
if (missingSet.has(name)) continue;
|
|
31916
|
-
const filePath = cat === "skills" ?
|
|
31917
|
-
if (!
|
|
31918
|
-
const relPath =
|
|
32411
|
+
const filePath = cat === "skills" ? path43.join(kit.path, cat, name, "SKILL.md") : path43.join(kit.path, cat, `${name}.md`);
|
|
32412
|
+
if (!fs42.existsSync(filePath)) continue;
|
|
32413
|
+
const relPath = path43.relative(kit.path, filePath);
|
|
31919
32414
|
try {
|
|
31920
32415
|
const { data } = parseMarkdownFrontmatter(filePath);
|
|
31921
32416
|
for (const field of requiredFields) {
|
|
@@ -31940,10 +32435,10 @@ function checkComponentFrontmatter(kit) {
|
|
|
31940
32435
|
}
|
|
31941
32436
|
function checkReservedRootNames(kit) {
|
|
31942
32437
|
const violations = [];
|
|
31943
|
-
if (!
|
|
32438
|
+
if (!fs42.existsSync(kit.path) || !fs42.statSync(kit.path).isDirectory()) {
|
|
31944
32439
|
return violations;
|
|
31945
32440
|
}
|
|
31946
|
-
const entries =
|
|
32441
|
+
const entries = fs42.readdirSync(kit.path, { withFileTypes: true });
|
|
31947
32442
|
for (const entry of entries) {
|
|
31948
32443
|
if (RESERVED_ROOT_NAMES.includes(entry.name)) {
|
|
31949
32444
|
violations.push({
|
|
@@ -31960,8 +32455,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31960
32455
|
const missingSet = new Set(kit.components.commands.missing);
|
|
31961
32456
|
for (const name of kit.components.commands.declared) {
|
|
31962
32457
|
if (missingSet.has(name)) continue;
|
|
31963
|
-
const filePath =
|
|
31964
|
-
if (!
|
|
32458
|
+
const filePath = path43.join(kit.path, "commands", `${name}.md`);
|
|
32459
|
+
if (!fs42.existsSync(filePath)) continue;
|
|
31965
32460
|
let data;
|
|
31966
32461
|
try {
|
|
31967
32462
|
({ data } = parseMarkdownFrontmatter(filePath));
|
|
@@ -31974,7 +32469,7 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31974
32469
|
if (!barred) {
|
|
31975
32470
|
violations.push({
|
|
31976
32471
|
code: "command-human-only-model-invocable",
|
|
31977
|
-
location:
|
|
32472
|
+
location: path43.relative(kit.path, filePath),
|
|
31978
32473
|
message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
|
|
31979
32474
|
});
|
|
31980
32475
|
}
|
|
@@ -31983,8 +32478,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31983
32478
|
}
|
|
31984
32479
|
|
|
31985
32480
|
// src/commands/verify.ts
|
|
31986
|
-
import
|
|
31987
|
-
import
|
|
32481
|
+
import fs43 from "fs";
|
|
32482
|
+
import path44 from "path";
|
|
31988
32483
|
function runVerifyCommand(options, logger) {
|
|
31989
32484
|
const { config, configDir, sourceRoot, kitInfo } = resolveRuntime(
|
|
31990
32485
|
options,
|
|
@@ -32075,8 +32570,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
|
|
|
32075
32570
|
if (!slotPath) {
|
|
32076
32571
|
continue;
|
|
32077
32572
|
}
|
|
32078
|
-
const fullPath = subPath ?
|
|
32079
|
-
if (!
|
|
32573
|
+
const fullPath = subPath ? path44.join(slotPath, subPath) : slotPath;
|
|
32574
|
+
if (!fs43.existsSync(fullPath)) {
|
|
32080
32575
|
failures.push(
|
|
32081
32576
|
`claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
|
|
32082
32577
|
);
|