@alessandroraffa/tangyr 0.15.0 → 0.16.0
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 +564 -773
- 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":
|
|
@@ -23138,8 +23138,8 @@ function toConflictPolicy2(value) {
|
|
|
23138
23138
|
}
|
|
23139
23139
|
|
|
23140
23140
|
// src/commands/install.ts
|
|
23141
|
-
import
|
|
23142
|
-
import
|
|
23141
|
+
import fs36 from "fs";
|
|
23142
|
+
import path36 from "path";
|
|
23143
23143
|
|
|
23144
23144
|
// src/core/channel-state.ts
|
|
23145
23145
|
import fs28 from "fs";
|
|
@@ -23220,13 +23220,12 @@ function assertChannelNotRolledBack(params) {
|
|
|
23220
23220
|
}
|
|
23221
23221
|
|
|
23222
23222
|
// src/core/bundle.ts
|
|
23223
|
-
var DENY_LIST_TYPE = "tangyr.deny-list.v2";
|
|
23224
23223
|
var CHANNEL_POINTER_TYPE = "tangyr.channel-pointer.v1";
|
|
23225
23224
|
var DEFAULT_CHANNEL = "stable";
|
|
23226
23225
|
|
|
23227
23226
|
// src/core/materialize.ts
|
|
23228
|
-
import
|
|
23229
|
-
import
|
|
23227
|
+
import fs29 from "fs";
|
|
23228
|
+
import path27 from "path";
|
|
23230
23229
|
|
|
23231
23230
|
// src/core/integrity.ts
|
|
23232
23231
|
import crypto3 from "crypto";
|
|
@@ -23344,47 +23343,6 @@ function verifyBundle(bundle, keys, expectedIdentity, now) {
|
|
|
23344
23343
|
verifyBundleSignature(bundle, keys, now);
|
|
23345
23344
|
verifyIdentity(bundle.manifest, expectedIdentity);
|
|
23346
23345
|
}
|
|
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
23346
|
function assertFreshnessWindow(issuedAt, expiresAt, now, expiryConsequence) {
|
|
23389
23347
|
const utcDesignatorPattern = /Z|[+-]\d{2}:\d{2}$/;
|
|
23390
23348
|
if (!utcDesignatorPattern.test(issuedAt) || !utcDesignatorPattern.test(expiresAt)) {
|
|
@@ -23465,75 +23423,6 @@ function verifyChannelPointer(pointer, expectedKit, expectedChannel, keys, now)
|
|
|
23465
23423
|
return candidate;
|
|
23466
23424
|
}
|
|
23467
23425
|
|
|
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) {
|
|
23531
|
-
throw new IntegrityError(
|
|
23532
|
-
`Revocation deny-list from ${originUrl} carries sequence ${incoming}, behind the highest already accepted (${seen}). That is a replay of a superseded deny-list, which would silently un-revoke a kit \u2014 refusing (REQ-INT-009).`
|
|
23533
|
-
);
|
|
23534
|
-
}
|
|
23535
|
-
}
|
|
23536
|
-
|
|
23537
23426
|
// src/core/materialize.ts
|
|
23538
23427
|
var MAX_TOTAL_BUNDLE_BYTES = 50 * 1024 * 1024;
|
|
23539
23428
|
var MAX_BUNDLE_FILE_BYTES = 5 * 1024 * 1024;
|
|
@@ -23579,7 +23468,6 @@ async function withBoundedRetry(operation, sleep2, logger) {
|
|
|
23579
23468
|
);
|
|
23580
23469
|
}
|
|
23581
23470
|
var BUNDLE_OBJECT_PATH_PREFIX = "/v1/kits";
|
|
23582
|
-
var DENY_LIST_OBJECT_PATH = "/v1/deny-list";
|
|
23583
23471
|
async function fetchVerifiedBundle(params) {
|
|
23584
23472
|
const { originUrl, reference, transport, keys, now, logger, sleep: sleep2 } = params;
|
|
23585
23473
|
const credentials = resolveCredentialNonInteractive();
|
|
@@ -23633,76 +23521,6 @@ async function fetchVerifiedBundle(params) {
|
|
|
23633
23521
|
}
|
|
23634
23522
|
return parsed;
|
|
23635
23523
|
}
|
|
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
23524
|
function parseVersionTriple(version) {
|
|
23707
23525
|
const leading = version.split("-")[0];
|
|
23708
23526
|
const parts = leading.split(".");
|
|
@@ -23743,7 +23561,7 @@ function assertFileWithinCeiling(entryPath, byteLength) {
|
|
|
23743
23561
|
}
|
|
23744
23562
|
var WINDOWS_DRIVE_ABSOLUTE = /^[a-zA-Z]:[\\/]/u;
|
|
23745
23563
|
function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
23746
|
-
if (
|
|
23564
|
+
if (path27.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
|
|
23747
23565
|
throw new IntegrityError(
|
|
23748
23566
|
`Bundle file path "${entryPath}" is absolute \u2014 every file inside a bundle must use a relative path (REQ-INT-004).`
|
|
23749
23567
|
);
|
|
@@ -23759,13 +23577,13 @@ function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
|
23759
23577
|
`Bundle file path "${entryPath}" contains a ".." segment \u2014 directory traversal is rejected (REQ-INT-004).`
|
|
23760
23578
|
);
|
|
23761
23579
|
}
|
|
23762
|
-
const resolved =
|
|
23580
|
+
const resolved = path27.resolve(stagingDir, entryPath);
|
|
23763
23581
|
if (resolved === stagingDir) {
|
|
23764
23582
|
throw new IntegrityError(
|
|
23765
23583
|
`Bundle file path "${entryPath}" resolves to the staging directory itself \u2014 every entry must be a file inside it (REQ-INT-004).`
|
|
23766
23584
|
);
|
|
23767
23585
|
}
|
|
23768
|
-
if (!resolved.startsWith(stagingDir +
|
|
23586
|
+
if (!resolved.startsWith(stagingDir + path27.sep)) {
|
|
23769
23587
|
throw new IntegrityError(
|
|
23770
23588
|
`Bundle file path "${entryPath}" escapes the staging directory \u2014 refusing to write (REQ-INT-004).`
|
|
23771
23589
|
);
|
|
@@ -23817,10 +23635,10 @@ function verifyBundleFileHashes(bundle) {
|
|
|
23817
23635
|
function writeStagedFiles(stagingDir, decoded) {
|
|
23818
23636
|
for (const [rawPath, bytes] of decoded) {
|
|
23819
23637
|
const target = sanitizeBundleFilePath(rawPath, stagingDir);
|
|
23820
|
-
|
|
23638
|
+
fs29.mkdirSync(path27.dirname(target), { recursive: true, mode: 448 });
|
|
23821
23639
|
let existingStat;
|
|
23822
23640
|
try {
|
|
23823
|
-
existingStat =
|
|
23641
|
+
existingStat = fs29.lstatSync(target);
|
|
23824
23642
|
} catch (error) {
|
|
23825
23643
|
if (error.code !== "ENOENT") {
|
|
23826
23644
|
throw error;
|
|
@@ -23831,7 +23649,7 @@ function writeStagedFiles(stagingDir, decoded) {
|
|
|
23831
23649
|
`Refusing to write "${rawPath}" \u2014 a symbolic link already exists at the target path.`
|
|
23832
23650
|
);
|
|
23833
23651
|
}
|
|
23834
|
-
|
|
23652
|
+
fs29.writeFileSync(target, bytes, { mode: 384, flag: "wx" });
|
|
23835
23653
|
}
|
|
23836
23654
|
}
|
|
23837
23655
|
function verifyWarmCacheEntry(entryDir, reference, keys, now) {
|
|
@@ -23873,16 +23691,6 @@ async function materializeRemoteKit(params) {
|
|
|
23873
23691
|
logger,
|
|
23874
23692
|
sleep: sleep2
|
|
23875
23693
|
});
|
|
23876
|
-
await assertReferenceNotRevoked({
|
|
23877
|
-
originUrl,
|
|
23878
|
-
reference,
|
|
23879
|
-
cacheRoot,
|
|
23880
|
-
transport,
|
|
23881
|
-
keys,
|
|
23882
|
-
now,
|
|
23883
|
-
logger,
|
|
23884
|
-
sleep: sleep2
|
|
23885
|
-
});
|
|
23886
23694
|
assertCliVersionCompatible(bundle.manifest.minCliVersion, CLI_VERSION);
|
|
23887
23695
|
const decoded = verifyBundleFileHashes(bundle);
|
|
23888
23696
|
if (decoded.has(CACHE_COMPLETION_MARKER) || decoded.has(BUNDLE_DOCUMENT_FILENAME)) {
|
|
@@ -23897,14 +23705,14 @@ async function materializeRemoteKit(params) {
|
|
|
23897
23705
|
writeStagedFiles(stagingDir, decoded);
|
|
23898
23706
|
writeBundleDocument(stagingDir, bundle);
|
|
23899
23707
|
writeCompletionMarker(stagingDir, reference);
|
|
23900
|
-
if (replace &&
|
|
23901
|
-
|
|
23708
|
+
if (replace && fs29.existsSync(entryDir)) {
|
|
23709
|
+
fs29.rmSync(entryDir, { recursive: true, force: true });
|
|
23902
23710
|
}
|
|
23903
23711
|
publishCacheEntry(stagingDir, entryDir);
|
|
23904
23712
|
return entryDir;
|
|
23905
23713
|
} catch (error) {
|
|
23906
23714
|
if (stagingDir !== void 0) {
|
|
23907
|
-
|
|
23715
|
+
fs29.rmSync(stagingDir, { recursive: true, force: true });
|
|
23908
23716
|
}
|
|
23909
23717
|
throw error;
|
|
23910
23718
|
}
|
|
@@ -24081,7 +23889,7 @@ async function resolveKitSource(params) {
|
|
|
24081
23889
|
}
|
|
24082
23890
|
function degradedWarmReturn() {
|
|
24083
23891
|
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
|
|
23892
|
+
`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
23893
|
`
|
|
24086
23894
|
);
|
|
24087
23895
|
return {
|
|
@@ -24123,23 +23931,6 @@ async function resolveKitSource(params) {
|
|
|
24123
23931
|
);
|
|
24124
23932
|
}
|
|
24125
23933
|
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
23934
|
writeLastAuthorizedAt(cacheRoot, config.source.url, now);
|
|
24144
23935
|
const warning = formatAdvanceExpiryWarning(
|
|
24145
23936
|
probeOutcome.metadata.expiresAt,
|
|
@@ -24257,13 +24048,13 @@ function sleep(ms2) {
|
|
|
24257
24048
|
// src/adapters/codex.ts
|
|
24258
24049
|
var TOML3 = __toESM(require_toml(), 1);
|
|
24259
24050
|
import crypto5 from "crypto";
|
|
24260
|
-
import
|
|
24261
|
-
import
|
|
24051
|
+
import fs31 from "fs";
|
|
24052
|
+
import path30 from "path";
|
|
24262
24053
|
|
|
24263
24054
|
// src/compiler/agents.ts
|
|
24264
24055
|
var TOML = __toESM(require_toml(), 1);
|
|
24265
24056
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
24266
|
-
import
|
|
24057
|
+
import path28 from "path";
|
|
24267
24058
|
|
|
24268
24059
|
// src/compiler/loss-report.ts
|
|
24269
24060
|
function createLossReport() {
|
|
@@ -24327,7 +24118,7 @@ var copilotToolAliasesByClass = {
|
|
|
24327
24118
|
};
|
|
24328
24119
|
function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
24329
24120
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
24330
|
-
const relativeSource = `agents/${
|
|
24121
|
+
const relativeSource = `agents/${path28.basename(sourceFile)}`;
|
|
24331
24122
|
if (target === "opencode") {
|
|
24332
24123
|
return compileOpenCodeAgent(
|
|
24333
24124
|
sourceFile,
|
|
@@ -24368,7 +24159,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
24368
24159
|
mappings,
|
|
24369
24160
|
lossReport
|
|
24370
24161
|
);
|
|
24371
|
-
const overlayKey = `agents/${
|
|
24162
|
+
const overlayKey = `agents/${path28.basename(sourceFile, ".md")}.${target}.yaml`;
|
|
24372
24163
|
const targetFields = {
|
|
24373
24164
|
...translated.fields,
|
|
24374
24165
|
...extensions[overlayKey] ?? {}
|
|
@@ -24402,7 +24193,7 @@ ${TOML.stringify({
|
|
|
24402
24193
|
function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
24403
24194
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
24404
24195
|
throw new Error(
|
|
24405
|
-
`${
|
|
24196
|
+
`${path28.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
|
|
24406
24197
|
);
|
|
24407
24198
|
}
|
|
24408
24199
|
const frontmatter = {
|
|
@@ -24456,7 +24247,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
24456
24247
|
"permission",
|
|
24457
24248
|
"permission-coarsening"
|
|
24458
24249
|
),
|
|
24459
|
-
detail: `${
|
|
24250
|
+
detail: `${path28.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
|
|
24460
24251
|
}
|
|
24461
24252
|
]
|
|
24462
24253
|
});
|
|
@@ -24481,7 +24272,7 @@ ${(0, import_yaml7.stringify)(frontmatter).trim()}
|
|
|
24481
24272
|
function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
24482
24273
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
24483
24274
|
throw new Error(
|
|
24484
|
-
`${
|
|
24275
|
+
`${path28.basename(sourceFile)}: Cursor agent requires a non-empty description field`
|
|
24485
24276
|
);
|
|
24486
24277
|
}
|
|
24487
24278
|
const frontmatter = {
|
|
@@ -24518,7 +24309,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
24518
24309
|
"permission",
|
|
24519
24310
|
"permission-coarsening"
|
|
24520
24311
|
),
|
|
24521
|
-
detail: `${
|
|
24312
|
+
detail: `${path28.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
|
|
24522
24313
|
}
|
|
24523
24314
|
]
|
|
24524
24315
|
});
|
|
@@ -24537,7 +24328,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
24537
24328
|
"provider",
|
|
24538
24329
|
"provider-not-representable"
|
|
24539
24330
|
),
|
|
24540
|
-
detail: `${
|
|
24331
|
+
detail: `${path28.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
24541
24332
|
}
|
|
24542
24333
|
]
|
|
24543
24334
|
});
|
|
@@ -24569,7 +24360,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
|
|
|
24569
24360
|
"persona",
|
|
24570
24361
|
"persona-not-representable"
|
|
24571
24362
|
),
|
|
24572
|
-
detail: `${
|
|
24363
|
+
detail: `${path28.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
|
|
24573
24364
|
}
|
|
24574
24365
|
]
|
|
24575
24366
|
});
|
|
@@ -24617,7 +24408,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24617
24408
|
field,
|
|
24618
24409
|
"model-not-representable"
|
|
24619
24410
|
),
|
|
24620
|
-
detail: `${
|
|
24411
|
+
detail: `${path28.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
|
|
24621
24412
|
});
|
|
24622
24413
|
return;
|
|
24623
24414
|
}
|
|
@@ -24635,9 +24426,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24635
24426
|
lossReport,
|
|
24636
24427
|
target,
|
|
24637
24428
|
"agents",
|
|
24638
|
-
`agents/${
|
|
24429
|
+
`agents/${path28.basename(sourceFile)}`,
|
|
24639
24430
|
"info",
|
|
24640
|
-
`${
|
|
24431
|
+
`${path28.basename(sourceFile)}: ${field} is delivered through another managed surface.`
|
|
24641
24432
|
);
|
|
24642
24433
|
return;
|
|
24643
24434
|
}
|
|
@@ -24646,7 +24437,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24646
24437
|
field,
|
|
24647
24438
|
action: entryType,
|
|
24648
24439
|
severity: resolveLossSeverity("agent-field", field, entryType),
|
|
24649
|
-
detail: `${
|
|
24440
|
+
detail: `${path28.basename(sourceFile)}: ${field} has no emitted field for this target.`
|
|
24650
24441
|
});
|
|
24651
24442
|
}
|
|
24652
24443
|
function mapToolsToCapabilities(value, mappings) {
|
|
@@ -25243,9 +25034,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
|
|
|
25243
25034
|
}
|
|
25244
25035
|
|
|
25245
25036
|
// src/compiler/rules.ts
|
|
25246
|
-
import
|
|
25037
|
+
import path29 from "path";
|
|
25247
25038
|
var import_yaml8 = __toESM(require_dist(), 1);
|
|
25248
|
-
import
|
|
25039
|
+
import fs30 from "fs";
|
|
25249
25040
|
function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
25250
25041
|
if (target === "copilot") {
|
|
25251
25042
|
addLoss(lossReport, "copilot", "rules", {
|
|
@@ -25282,13 +25073,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
|
25282
25073
|
}
|
|
25283
25074
|
const appendixParts = [];
|
|
25284
25075
|
const dotRulesFiles = [];
|
|
25285
|
-
for (const ruleFile of ts(
|
|
25076
|
+
for (const ruleFile of ts(path29.join(sourceRulesDir, "*.md")).sort()) {
|
|
25286
25077
|
const parsed = parseRule(ruleFile);
|
|
25287
|
-
const name =
|
|
25078
|
+
const name = path29.basename(ruleFile, ".md");
|
|
25288
25079
|
if (parsed.mode === "exec-policy") {
|
|
25289
25080
|
dotRulesFiles.push({
|
|
25290
25081
|
name: `${name}.rules`,
|
|
25291
|
-
content: `${formatProvenanceMarker("toml", `rules/${
|
|
25082
|
+
content: `${formatProvenanceMarker("toml", `rules/${path29.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
|
|
25292
25083
|
${parsed.body}`
|
|
25293
25084
|
});
|
|
25294
25085
|
continue;
|
|
@@ -25297,7 +25088,7 @@ ${parsed.body}`
|
|
|
25297
25088
|
|
|
25298
25089
|
${parsed.body.trim()}`);
|
|
25299
25090
|
addLoss(lossReport, "codex", "rules", {
|
|
25300
|
-
source: `rules/${
|
|
25091
|
+
source: `rules/${path29.basename(ruleFile)}`,
|
|
25301
25092
|
fields: [
|
|
25302
25093
|
{
|
|
25303
25094
|
field: "mode",
|
|
@@ -25307,7 +25098,7 @@ ${parsed.body.trim()}`);
|
|
|
25307
25098
|
"mode",
|
|
25308
25099
|
"rule-as-instruction"
|
|
25309
25100
|
),
|
|
25310
|
-
detail: `${
|
|
25101
|
+
detail: `${path29.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
|
|
25311
25102
|
}
|
|
25312
25103
|
]
|
|
25313
25104
|
});
|
|
@@ -25315,7 +25106,7 @@ ${parsed.body.trim()}`);
|
|
|
25315
25106
|
return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
|
|
25316
25107
|
}
|
|
25317
25108
|
function parseRule(ruleFile) {
|
|
25318
|
-
const content =
|
|
25109
|
+
const content = fs30.readFileSync(ruleFile, "utf8");
|
|
25319
25110
|
if (!content.startsWith("---\n")) {
|
|
25320
25111
|
return { mode: "guidance", body: content };
|
|
25321
25112
|
}
|
|
@@ -25339,14 +25130,14 @@ function isRuleMode(value) {
|
|
|
25339
25130
|
}
|
|
25340
25131
|
function compileOpenCodeRules(sourceRulesDir, lossReport) {
|
|
25341
25132
|
const appendixParts = [];
|
|
25342
|
-
for (const ruleFile of ts(
|
|
25133
|
+
for (const ruleFile of ts(path29.join(sourceRulesDir, "*.md")).sort()) {
|
|
25343
25134
|
const parsed = parseRule(ruleFile);
|
|
25344
|
-
const name =
|
|
25135
|
+
const name = path29.basename(ruleFile, ".md");
|
|
25345
25136
|
appendixParts.push(`## ${name}
|
|
25346
25137
|
|
|
25347
25138
|
${parsed.body.trim()}`);
|
|
25348
25139
|
addLoss(lossReport, "opencode", "rules", {
|
|
25349
|
-
source: `rules/${
|
|
25140
|
+
source: `rules/${path29.basename(ruleFile)}`,
|
|
25350
25141
|
fields: [
|
|
25351
25142
|
{
|
|
25352
25143
|
field: "rule",
|
|
@@ -25356,7 +25147,7 @@ ${parsed.body.trim()}`);
|
|
|
25356
25147
|
"rule",
|
|
25357
25148
|
"rule-path-scoping"
|
|
25358
25149
|
),
|
|
25359
|
-
detail: `${
|
|
25150
|
+
detail: `${path29.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
|
|
25360
25151
|
}
|
|
25361
25152
|
]
|
|
25362
25153
|
});
|
|
@@ -25365,9 +25156,9 @@ ${parsed.body.trim()}`);
|
|
|
25365
25156
|
}
|
|
25366
25157
|
function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
25367
25158
|
const dotRulesFiles = [];
|
|
25368
|
-
for (const ruleFile of ts(
|
|
25369
|
-
const content =
|
|
25370
|
-
const name =
|
|
25159
|
+
for (const ruleFile of ts(path29.join(sourceRulesDir, "*.md")).sort()) {
|
|
25160
|
+
const content = fs30.readFileSync(ruleFile, "utf8");
|
|
25161
|
+
const name = path29.basename(ruleFile, ".md");
|
|
25371
25162
|
let frontmatterData = {};
|
|
25372
25163
|
let body = content;
|
|
25373
25164
|
if (content.startsWith("---\n")) {
|
|
@@ -25396,7 +25187,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
|
25396
25187
|
}
|
|
25397
25188
|
const marker = formatProvenanceMarker(
|
|
25398
25189
|
"markdown",
|
|
25399
|
-
`rules/${
|
|
25190
|
+
`rules/${path29.basename(ruleFile)}`,
|
|
25400
25191
|
computeSourceHash(ruleFile),
|
|
25401
25192
|
"cursor"
|
|
25402
25193
|
);
|
|
@@ -25412,9 +25203,9 @@ ${body}`;
|
|
|
25412
25203
|
}
|
|
25413
25204
|
function compileClineRules(sourceRulesDir, lossReport) {
|
|
25414
25205
|
const dotRulesFiles = [];
|
|
25415
|
-
for (const ruleFile of ts(
|
|
25416
|
-
const content =
|
|
25417
|
-
const name =
|
|
25206
|
+
for (const ruleFile of ts(path29.join(sourceRulesDir, "*.md")).sort()) {
|
|
25207
|
+
const content = fs30.readFileSync(ruleFile, "utf8");
|
|
25208
|
+
const name = path29.basename(ruleFile, ".md");
|
|
25418
25209
|
let frontmatterData = {};
|
|
25419
25210
|
let body = content;
|
|
25420
25211
|
if (content.startsWith("---\n")) {
|
|
@@ -25431,13 +25222,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25431
25222
|
}
|
|
25432
25223
|
const marker = formatProvenanceMarker(
|
|
25433
25224
|
"markdown",
|
|
25434
|
-
`rules/${
|
|
25225
|
+
`rules/${path29.basename(ruleFile)}`,
|
|
25435
25226
|
computeSourceHash(ruleFile),
|
|
25436
25227
|
"cline"
|
|
25437
25228
|
);
|
|
25438
25229
|
if (frontmatterData.mode === "exec-policy") {
|
|
25439
25230
|
addLoss(lossReport, "cline", "rules", {
|
|
25440
|
-
source: `rules/${
|
|
25231
|
+
source: `rules/${path29.basename(ruleFile)}`,
|
|
25441
25232
|
fields: [
|
|
25442
25233
|
{
|
|
25443
25234
|
field: "mode",
|
|
@@ -25447,7 +25238,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25447
25238
|
"mode",
|
|
25448
25239
|
"rule-mode-downgrade"
|
|
25449
25240
|
),
|
|
25450
|
-
detail: `${
|
|
25241
|
+
detail: `${path29.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
|
|
25451
25242
|
}
|
|
25452
25243
|
]
|
|
25453
25244
|
});
|
|
@@ -25492,7 +25283,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
25492
25283
|
rules: profile.rules
|
|
25493
25284
|
};
|
|
25494
25285
|
const rules = compileRules(
|
|
25495
|
-
|
|
25286
|
+
path30.join(sourceRoot, config.source.rules),
|
|
25496
25287
|
"codex",
|
|
25497
25288
|
mappings,
|
|
25498
25289
|
lossReport
|
|
@@ -25637,9 +25428,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
25637
25428
|
function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
|
|
25638
25429
|
const cp = mappings.modelTiers.custom_provider;
|
|
25639
25430
|
if (!cp) return "";
|
|
25640
|
-
const agentsDir =
|
|
25641
|
-
if (!
|
|
25642
|
-
const agentFiles = ts(
|
|
25431
|
+
const agentsDir = path30.join(sourceRoot, config.source.agents);
|
|
25432
|
+
if (!fs31.existsSync(agentsDir)) return "";
|
|
25433
|
+
const agentFiles = ts(path30.join(agentsDir, "*.md")).sort();
|
|
25643
25434
|
const hasProviderAgent = agentFiles.some((agentFile) => {
|
|
25644
25435
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
25645
25436
|
return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
@@ -25704,7 +25495,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
25704
25495
|
}
|
|
25705
25496
|
];
|
|
25706
25497
|
for (const ruleFile of rules.dotRulesFiles) {
|
|
25707
|
-
const destination =
|
|
25498
|
+
const destination = path30.join(rulesRoot, ruleFile.name);
|
|
25708
25499
|
if (options.dryRun) {
|
|
25709
25500
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
25710
25501
|
outcomes.push({
|
|
@@ -25732,15 +25523,15 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
25732
25523
|
return outcomes;
|
|
25733
25524
|
}
|
|
25734
25525
|
function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
25735
|
-
const source =
|
|
25526
|
+
const source = path30.join(sourceRoot, config.source.instructions);
|
|
25736
25527
|
const destination = resolveTargetPath(paths.instructions);
|
|
25737
|
-
const composed = `${
|
|
25528
|
+
const composed = `${fs31.readFileSync(source, "utf8").trim()}
|
|
25738
25529
|
|
|
25739
25530
|
--- tangyr managed rules ---
|
|
25740
25531
|
${agentsAppendix}`.trim();
|
|
25741
25532
|
const marker = formatProvenanceMarker(
|
|
25742
25533
|
"markdown",
|
|
25743
|
-
|
|
25534
|
+
path30.basename(config.source.instructions),
|
|
25744
25535
|
hashString(composed),
|
|
25745
25536
|
"codex"
|
|
25746
25537
|
);
|
|
@@ -25767,9 +25558,9 @@ ${composed}
|
|
|
25767
25558
|
);
|
|
25768
25559
|
}
|
|
25769
25560
|
function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
25770
|
-
const source =
|
|
25561
|
+
const source = path30.resolve(sourceRoot, config.source.skills);
|
|
25771
25562
|
const destination = resolveTargetPath(paths.skills);
|
|
25772
|
-
if (!
|
|
25563
|
+
if (!fs31.existsSync(source)) {
|
|
25773
25564
|
return skippedMissingSource("skills", source);
|
|
25774
25565
|
}
|
|
25775
25566
|
if (options.dryRun) {
|
|
@@ -25785,29 +25576,29 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
|
|
|
25785
25576
|
};
|
|
25786
25577
|
}
|
|
25787
25578
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
25788
|
-
|
|
25579
|
+
fs31.unlinkSync(destination);
|
|
25789
25580
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
25790
25581
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
25791
25582
|
return { component: "skills", status: "conflict", path: destination };
|
|
25792
25583
|
} else if (artifactClass === "managed-symlink") {
|
|
25793
|
-
|
|
25584
|
+
fs31.unlinkSync(destination);
|
|
25794
25585
|
}
|
|
25795
|
-
ensureDir(
|
|
25586
|
+
ensureDir(path30.dirname(destination));
|
|
25796
25587
|
createRelativeSymlink(source, destination, "dir");
|
|
25797
25588
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
25798
25589
|
return { component: "skills", status: "success", path: destination };
|
|
25799
25590
|
}
|
|
25800
25591
|
function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
25801
|
-
const sourceAgentsRoot =
|
|
25802
|
-
if (!
|
|
25592
|
+
const sourceAgentsRoot = path30.join(sourceRoot, config.source.agents);
|
|
25593
|
+
if (!fs31.existsSync(sourceAgentsRoot)) {
|
|
25803
25594
|
return [skippedMissingSource("agents", sourceAgentsRoot)];
|
|
25804
25595
|
}
|
|
25805
|
-
const sourceAgents = ts(
|
|
25596
|
+
const sourceAgents = ts(path30.join(sourceAgentsRoot, "*.md")).sort();
|
|
25806
25597
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
25807
25598
|
return sourceAgents.map((agentFile) => {
|
|
25808
|
-
const destination =
|
|
25599
|
+
const destination = path30.join(
|
|
25809
25600
|
agentsRoot,
|
|
25810
|
-
`${
|
|
25601
|
+
`${path30.basename(agentFile, ".md")}.toml`
|
|
25811
25602
|
);
|
|
25812
25603
|
const compiled = compileAgent(
|
|
25813
25604
|
agentFile,
|
|
@@ -25843,10 +25634,10 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
|
|
|
25843
25634
|
}
|
|
25844
25635
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
25845
25636
|
const sourceLabel = hooksSourceLabel(config);
|
|
25846
|
-
if (!
|
|
25637
|
+
if (!fs31.existsSync(source)) {
|
|
25847
25638
|
return skippedMissingSource("hooks", source);
|
|
25848
25639
|
}
|
|
25849
|
-
const sourceHooksJson = JSON.parse(
|
|
25640
|
+
const sourceHooksJson = JSON.parse(fs31.readFileSync(source, "utf8"));
|
|
25850
25641
|
const compiled = compileHooks(
|
|
25851
25642
|
sourceHooksJson,
|
|
25852
25643
|
"codex",
|
|
@@ -25868,7 +25659,7 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
|
|
|
25868
25659
|
destination,
|
|
25869
25660
|
hostHooks,
|
|
25870
25661
|
stringifyJson2,
|
|
25871
|
-
!
|
|
25662
|
+
!fs31.existsSync(destination),
|
|
25872
25663
|
logger
|
|
25873
25664
|
);
|
|
25874
25665
|
return {
|
|
@@ -25881,7 +25672,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
|
|
|
25881
25672
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
25882
25673
|
const sourceLabel = mcpSourceLabel(config);
|
|
25883
25674
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
25884
|
-
if (!
|
|
25675
|
+
if (!fs31.existsSync(source)) {
|
|
25885
25676
|
if (providerToml && !options.dryRun) {
|
|
25886
25677
|
const changed2 = writeTomlManagedSection(
|
|
25887
25678
|
destination,
|
|
@@ -25896,7 +25687,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
|
|
|
25896
25687
|
}
|
|
25897
25688
|
return skippedMissingSource("mcp", source);
|
|
25898
25689
|
}
|
|
25899
|
-
const sourceMcpJson = JSON.parse(
|
|
25690
|
+
const sourceMcpJson = JSON.parse(fs31.readFileSync(source, "utf8"));
|
|
25900
25691
|
const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
|
|
25901
25692
|
const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
|
|
25902
25693
|
if (options.dryRun) {
|
|
@@ -25918,12 +25709,12 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
|
|
|
25918
25709
|
if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
25919
25710
|
return { component, status: "conflict", path: destination };
|
|
25920
25711
|
}
|
|
25921
|
-
ensureDir(
|
|
25922
|
-
|
|
25712
|
+
ensureDir(path30.dirname(destination));
|
|
25713
|
+
fs31.writeFileSync(destination, content);
|
|
25923
25714
|
return { component, status: "success", path: destination };
|
|
25924
25715
|
}
|
|
25925
25716
|
function writeTomlManagedSection(destination, managedContent, logger) {
|
|
25926
|
-
const current =
|
|
25717
|
+
const current = fs31.existsSync(destination) ? fs31.readFileSync(destination, "utf8") : "";
|
|
25927
25718
|
const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
|
|
25928
25719
|
if (isFirstWrite) {
|
|
25929
25720
|
logger.warn(
|
|
@@ -25939,8 +25730,8 @@ ${managedMcpEnd}
|
|
|
25939
25730
|
if (current === next.trimStart()) {
|
|
25940
25731
|
return false;
|
|
25941
25732
|
}
|
|
25942
|
-
ensureDir(
|
|
25943
|
-
|
|
25733
|
+
ensureDir(path30.dirname(destination));
|
|
25734
|
+
fs31.writeFileSync(destination, next.trimStart());
|
|
25944
25735
|
return true;
|
|
25945
25736
|
}
|
|
25946
25737
|
function removeManagedTomlSection(content) {
|
|
@@ -25967,16 +25758,16 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
|
|
|
25967
25758
|
backupFile(destination, manifest);
|
|
25968
25759
|
writeManifest(scopePath, manifest);
|
|
25969
25760
|
} else {
|
|
25970
|
-
|
|
25761
|
+
fs31.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
25971
25762
|
}
|
|
25972
25763
|
return true;
|
|
25973
25764
|
}
|
|
25974
|
-
|
|
25765
|
+
fs31.rmSync(destination, { recursive: true, force: true });
|
|
25975
25766
|
return true;
|
|
25976
25767
|
}
|
|
25977
25768
|
function isCompiledCurrent(destination, expectedContent, expectedHash) {
|
|
25978
25769
|
try {
|
|
25979
|
-
const current =
|
|
25770
|
+
const current = fs31.readFileSync(destination, "utf8");
|
|
25980
25771
|
const marker = extractProvenanceMarker(current);
|
|
25981
25772
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "codex" && current === expectedContent : current === expectedContent;
|
|
25982
25773
|
} catch {
|
|
@@ -25995,16 +25786,16 @@ function shouldSkipComponent(options, component) {
|
|
|
25995
25786
|
}
|
|
25996
25787
|
function isSymlinkTo(linkPath, source) {
|
|
25997
25788
|
try {
|
|
25998
|
-
return
|
|
25789
|
+
return fs31.realpathSync(linkPath) === fs31.realpathSync(source);
|
|
25999
25790
|
} catch {
|
|
26000
25791
|
return false;
|
|
26001
25792
|
}
|
|
26002
25793
|
}
|
|
26003
25794
|
function readJsonObject3(filePath) {
|
|
26004
|
-
if (!
|
|
25795
|
+
if (!fs31.existsSync(filePath)) {
|
|
26005
25796
|
return {};
|
|
26006
25797
|
}
|
|
26007
|
-
const parsed = JSON.parse(
|
|
25798
|
+
const parsed = JSON.parse(fs31.readFileSync(filePath, "utf8"));
|
|
26008
25799
|
return isRecord4(parsed) ? parsed : {};
|
|
26009
25800
|
}
|
|
26010
25801
|
function stringifyJson2(value) {
|
|
@@ -26020,16 +25811,16 @@ function hashString(value) {
|
|
|
26020
25811
|
|
|
26021
25812
|
// src/adapters/copilot.ts
|
|
26022
25813
|
import crypto6 from "crypto";
|
|
26023
|
-
import
|
|
26024
|
-
import
|
|
25814
|
+
import fs32 from "fs";
|
|
25815
|
+
import path32 from "path";
|
|
26025
25816
|
|
|
26026
25817
|
// src/compiler/commands.ts
|
|
26027
25818
|
var import_yaml9 = __toESM(require_dist(), 1);
|
|
26028
|
-
import
|
|
25819
|
+
import path31 from "path";
|
|
26029
25820
|
function compileCommandPrompt(sourceFile) {
|
|
26030
25821
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
26031
|
-
const relativeSource = `commands/${
|
|
26032
|
-
const fields = promptFrontmatter(data,
|
|
25822
|
+
const relativeSource = `commands/${path31.basename(sourceFile)}`;
|
|
25823
|
+
const fields = promptFrontmatter(data, path31.basename(sourceFile, ".md"));
|
|
26033
25824
|
const marker = formatProvenanceMarker(
|
|
26034
25825
|
"markdown",
|
|
26035
25826
|
relativeSource,
|
|
@@ -26204,13 +25995,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
26204
25995
|
}
|
|
26205
25996
|
function syncProviderLoss(config, sourceRoot, mappings, lossReport) {
|
|
26206
25997
|
if (!mappings.modelTiers.custom_provider) return;
|
|
26207
|
-
const agentsDir =
|
|
26208
|
-
if (!
|
|
26209
|
-
for (const agentFile of ts(
|
|
25998
|
+
const agentsDir = path32.join(sourceRoot, config.source.agents);
|
|
25999
|
+
if (!fs32.existsSync(agentsDir)) return;
|
|
26000
|
+
for (const agentFile of ts(path32.join(agentsDir, "*.md")).sort()) {
|
|
26210
26001
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
26211
26002
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
26212
26003
|
if (hasProvider) {
|
|
26213
|
-
const basename =
|
|
26004
|
+
const basename = path32.basename(agentFile);
|
|
26214
26005
|
addLoss(lossReport, "copilot", "agents", {
|
|
26215
26006
|
source: `agents/${basename}`,
|
|
26216
26007
|
fields: [
|
|
@@ -26235,23 +26026,23 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
|
|
|
26235
26026
|
logger.verbose(message);
|
|
26236
26027
|
return [{ component: "instructions", status: "skipped", path: message }];
|
|
26237
26028
|
}
|
|
26238
|
-
const source =
|
|
26239
|
-
if (!
|
|
26029
|
+
const source = path32.resolve(sourceRoot, config.source.instructions);
|
|
26030
|
+
if (!fs32.existsSync(source)) {
|
|
26240
26031
|
return [skippedMissingSource2("instructions", source)];
|
|
26241
26032
|
}
|
|
26242
|
-
const rawContent =
|
|
26033
|
+
const rawContent = fs32.readFileSync(source, "utf8");
|
|
26243
26034
|
const contentHash = hashString2(rawContent);
|
|
26244
26035
|
const marker = formatProvenanceMarker(
|
|
26245
26036
|
"markdown",
|
|
26246
|
-
|
|
26037
|
+
path32.basename(config.source.instructions),
|
|
26247
26038
|
contentHash,
|
|
26248
26039
|
"copilot"
|
|
26249
26040
|
);
|
|
26250
26041
|
const composedContent = `${marker}
|
|
26251
26042
|
${rawContent}`;
|
|
26252
26043
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
26253
|
-
const agentsMdDest =
|
|
26254
|
-
const mirrorDest =
|
|
26044
|
+
const agentsMdDest = path32.resolve(projectRoot, "AGENTS.md");
|
|
26045
|
+
const mirrorDest = path32.resolve(
|
|
26255
26046
|
projectRoot,
|
|
26256
26047
|
".github",
|
|
26257
26048
|
"copilot-instructions.md"
|
|
@@ -26305,17 +26096,17 @@ function writeInstructionsFile(component, destination, content, contentHash, con
|
|
|
26305
26096
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26306
26097
|
return { component, status: "conflict", path: destination };
|
|
26307
26098
|
}
|
|
26308
|
-
ensureDir(
|
|
26309
|
-
|
|
26099
|
+
ensureDir(path32.dirname(destination));
|
|
26100
|
+
fs32.writeFileSync(destination, content);
|
|
26310
26101
|
return { component, status: "success", path: destination };
|
|
26311
26102
|
}
|
|
26312
26103
|
function hashString2(value) {
|
|
26313
26104
|
return `sha256:${crypto6.createHash("sha256").update(value).digest("hex")}`;
|
|
26314
26105
|
}
|
|
26315
26106
|
function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26316
|
-
const source =
|
|
26107
|
+
const source = path32.resolve(sourceRoot, config.source.skills);
|
|
26317
26108
|
const destination = resolveTargetPath(paths.skills);
|
|
26318
|
-
if (!
|
|
26109
|
+
if (!fs32.existsSync(source)) {
|
|
26319
26110
|
return skippedMissingSource2("skills", source);
|
|
26320
26111
|
}
|
|
26321
26112
|
if (options.dryRun) {
|
|
@@ -26331,27 +26122,27 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
26331
26122
|
};
|
|
26332
26123
|
}
|
|
26333
26124
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26334
|
-
|
|
26125
|
+
fs32.unlinkSync(destination);
|
|
26335
26126
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26336
26127
|
return { component: "skills", status: "conflict", path: destination };
|
|
26337
26128
|
} else if (artifactClass === "managed-symlink") {
|
|
26338
|
-
|
|
26129
|
+
fs32.unlinkSync(destination);
|
|
26339
26130
|
}
|
|
26340
|
-
ensureDir(
|
|
26131
|
+
ensureDir(path32.dirname(destination));
|
|
26341
26132
|
createRelativeSymlink(source, destination, "dir");
|
|
26342
26133
|
return { component: "skills", status: "success", path: destination };
|
|
26343
26134
|
}
|
|
26344
26135
|
function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26345
|
-
const sourceAgentsRoot =
|
|
26346
|
-
if (!
|
|
26136
|
+
const sourceAgentsRoot = path32.join(sourceRoot, config.source.agents);
|
|
26137
|
+
if (!fs32.existsSync(sourceAgentsRoot)) {
|
|
26347
26138
|
return [skippedMissingSource2("agents", sourceAgentsRoot)];
|
|
26348
26139
|
}
|
|
26349
|
-
const sourceAgents = ts(
|
|
26140
|
+
const sourceAgents = ts(path32.join(sourceAgentsRoot, "*.md")).sort();
|
|
26350
26141
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
26351
26142
|
return sourceAgents.map((agentFile) => {
|
|
26352
|
-
const destination =
|
|
26143
|
+
const destination = path32.join(
|
|
26353
26144
|
agentsRoot,
|
|
26354
|
-
`${
|
|
26145
|
+
`${path32.basename(agentFile, ".md")}.agent.md`
|
|
26355
26146
|
);
|
|
26356
26147
|
const compiled = compileAgent(
|
|
26357
26148
|
agentFile,
|
|
@@ -26379,16 +26170,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
26379
26170
|
});
|
|
26380
26171
|
}
|
|
26381
26172
|
function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26382
|
-
const sourceCommandsRoot =
|
|
26383
|
-
if (!
|
|
26173
|
+
const sourceCommandsRoot = path32.join(sourceRoot, config.source.commands);
|
|
26174
|
+
if (!fs32.existsSync(sourceCommandsRoot)) {
|
|
26384
26175
|
return [skippedMissingSource2("commands", sourceCommandsRoot)];
|
|
26385
26176
|
}
|
|
26386
|
-
const sourceCommands = ts(
|
|
26177
|
+
const sourceCommands = ts(path32.join(sourceCommandsRoot, "*.md")).sort();
|
|
26387
26178
|
const promptsRoot = resolveTargetPath(paths.prompts);
|
|
26388
26179
|
return sourceCommands.map((commandFile) => {
|
|
26389
|
-
const destination =
|
|
26180
|
+
const destination = path32.join(
|
|
26390
26181
|
promptsRoot,
|
|
26391
|
-
`${
|
|
26182
|
+
`${path32.basename(commandFile, ".md")}.prompt.md`
|
|
26392
26183
|
);
|
|
26393
26184
|
const compiled = compileCommandPrompt(commandFile);
|
|
26394
26185
|
if (options.dryRun) {
|
|
@@ -26414,14 +26205,14 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
|
|
|
26414
26205
|
function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, logger) {
|
|
26415
26206
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
26416
26207
|
const sourceLabel = hooksSourceLabel(config);
|
|
26417
|
-
const destination =
|
|
26208
|
+
const destination = path32.join(
|
|
26418
26209
|
resolveTargetPath(paths.hooks),
|
|
26419
26210
|
"tangyr-managed.json"
|
|
26420
26211
|
);
|
|
26421
|
-
if (!
|
|
26212
|
+
if (!fs32.existsSync(source)) {
|
|
26422
26213
|
return skippedMissingSource2("hooks", source);
|
|
26423
26214
|
}
|
|
26424
|
-
const sourceHooksJson = JSON.parse(
|
|
26215
|
+
const sourceHooksJson = JSON.parse(fs32.readFileSync(source, "utf8"));
|
|
26425
26216
|
const compiled = compileHooks(
|
|
26426
26217
|
sourceHooksJson,
|
|
26427
26218
|
"copilot",
|
|
@@ -26458,10 +26249,10 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger) {
|
|
|
26458
26249
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
26459
26250
|
const sourceLabel = mcpSourceLabel(config);
|
|
26460
26251
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
26461
|
-
if (!
|
|
26252
|
+
if (!fs32.existsSync(source)) {
|
|
26462
26253
|
return skippedMissingSource2("mcp", source);
|
|
26463
26254
|
}
|
|
26464
|
-
const sourceMcpJson = JSON.parse(
|
|
26255
|
+
const sourceMcpJson = JSON.parse(fs32.readFileSync(source, "utf8"));
|
|
26465
26256
|
const compiled = compileMcp(
|
|
26466
26257
|
sourceMcpJson,
|
|
26467
26258
|
"copilot",
|
|
@@ -26491,13 +26282,13 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
|
|
|
26491
26282
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26492
26283
|
return { component, status: "conflict", path: destination };
|
|
26493
26284
|
}
|
|
26494
|
-
ensureDir(
|
|
26495
|
-
|
|
26285
|
+
ensureDir(path32.dirname(destination));
|
|
26286
|
+
fs32.writeFileSync(destination, content);
|
|
26496
26287
|
return { component, status: "success", path: destination };
|
|
26497
26288
|
}
|
|
26498
26289
|
function isCompiledCurrent2(destination, expectedContent, expectedHash) {
|
|
26499
26290
|
try {
|
|
26500
|
-
const current =
|
|
26291
|
+
const current = fs32.readFileSync(destination, "utf8");
|
|
26501
26292
|
const marker = extractProvenanceMarker(current);
|
|
26502
26293
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "copilot" && current === expectedContent : current === expectedContent;
|
|
26503
26294
|
} catch {
|
|
@@ -26520,11 +26311,11 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
|
|
|
26520
26311
|
backupFile(destination, manifest);
|
|
26521
26312
|
writeManifest(scopePath, manifest);
|
|
26522
26313
|
} else {
|
|
26523
|
-
|
|
26314
|
+
fs32.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
26524
26315
|
}
|
|
26525
26316
|
return true;
|
|
26526
26317
|
}
|
|
26527
|
-
|
|
26318
|
+
fs32.rmSync(destination, { recursive: true, force: true });
|
|
26528
26319
|
return true;
|
|
26529
26320
|
}
|
|
26530
26321
|
function shouldSkipComponent2(options, component) {
|
|
@@ -26533,12 +26324,12 @@ function shouldSkipComponent2(options, component) {
|
|
|
26533
26324
|
function cleanupLegacyAgents(paths, options, logger) {
|
|
26534
26325
|
const currentAgentsRoot = resolveTargetPath(paths.agents);
|
|
26535
26326
|
const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
|
|
26536
|
-
if (
|
|
26327
|
+
if (path32.resolve(currentAgentsRoot) === path32.resolve(legacyAgentsRoot)) {
|
|
26537
26328
|
return [];
|
|
26538
26329
|
}
|
|
26539
26330
|
const outcomes = [];
|
|
26540
26331
|
for (const filePath of ts(
|
|
26541
|
-
|
|
26332
|
+
path32.join(legacyAgentsRoot, "*.agent.md")
|
|
26542
26333
|
).sort()) {
|
|
26543
26334
|
if (!isCopilotManagedCompiledFile(filePath)) {
|
|
26544
26335
|
continue;
|
|
@@ -26548,14 +26339,14 @@ function cleanupLegacyAgents(paths, options, logger) {
|
|
|
26548
26339
|
outcomes.push({ component: "agents", status: "dry-run", path: filePath });
|
|
26549
26340
|
continue;
|
|
26550
26341
|
}
|
|
26551
|
-
|
|
26342
|
+
fs32.rmSync(filePath, { force: true });
|
|
26552
26343
|
outcomes.push({ component: "agents", status: "success", path: filePath });
|
|
26553
26344
|
}
|
|
26554
26345
|
return outcomes;
|
|
26555
26346
|
}
|
|
26556
26347
|
function isCopilotManagedCompiledFile(filePath) {
|
|
26557
26348
|
try {
|
|
26558
|
-
return extractProvenanceMarker(
|
|
26349
|
+
return extractProvenanceMarker(fs32.readFileSync(filePath, "utf8"))?.target === "copilot";
|
|
26559
26350
|
} catch {
|
|
26560
26351
|
return false;
|
|
26561
26352
|
}
|
|
@@ -26569,7 +26360,7 @@ function skippedMissingSource2(component, source) {
|
|
|
26569
26360
|
}
|
|
26570
26361
|
function isSymlinkTo2(linkPath, source) {
|
|
26571
26362
|
try {
|
|
26572
|
-
return
|
|
26363
|
+
return fs32.realpathSync(linkPath) === fs32.realpathSync(source);
|
|
26573
26364
|
} catch {
|
|
26574
26365
|
return false;
|
|
26575
26366
|
}
|
|
@@ -26577,8 +26368,8 @@ function isSymlinkTo2(linkPath, source) {
|
|
|
26577
26368
|
|
|
26578
26369
|
// src/adapters/cursor.ts
|
|
26579
26370
|
import crypto7 from "crypto";
|
|
26580
|
-
import
|
|
26581
|
-
import
|
|
26371
|
+
import fs33 from "fs";
|
|
26372
|
+
import path33 from "path";
|
|
26582
26373
|
function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26583
26374
|
const scope = options.scope ?? "global";
|
|
26584
26375
|
const profile = resolveTargetPaths({
|
|
@@ -26729,9 +26520,9 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
|
|
|
26729
26520
|
return { target: "cursor", outcomes };
|
|
26730
26521
|
}
|
|
26731
26522
|
function syncInstructions2(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
26732
|
-
const source =
|
|
26523
|
+
const source = path33.join(sourceRoot, config.source.instructions);
|
|
26733
26524
|
const destination = resolveTargetPath(paths.instructions);
|
|
26734
|
-
const baseContent =
|
|
26525
|
+
const baseContent = fs33.existsSync(source) ? fs33.readFileSync(source, "utf8").trim() : "";
|
|
26735
26526
|
const personaContent = extractPrimaryPersonaContent(
|
|
26736
26527
|
config,
|
|
26737
26528
|
sourceRoot,
|
|
@@ -26744,7 +26535,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
|
|
|
26744
26535
|
${personaContent}`.trim() : baseContent;
|
|
26745
26536
|
const marker = formatProvenanceMarker(
|
|
26746
26537
|
"markdown",
|
|
26747
|
-
|
|
26538
|
+
path33.basename(config.source.instructions),
|
|
26748
26539
|
hashString3(composed),
|
|
26749
26540
|
"cursor"
|
|
26750
26541
|
);
|
|
@@ -26769,11 +26560,11 @@ ${composed}
|
|
|
26769
26560
|
);
|
|
26770
26561
|
}
|
|
26771
26562
|
function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
26772
|
-
const agentsDir =
|
|
26773
|
-
if (!
|
|
26563
|
+
const agentsDir = path33.join(sourceRoot, config.source.agents);
|
|
26564
|
+
if (!fs33.existsSync(agentsDir)) {
|
|
26774
26565
|
return null;
|
|
26775
26566
|
}
|
|
26776
|
-
const agentFiles = ts(
|
|
26567
|
+
const agentFiles = ts(path33.join(agentsDir, "*.md")).sort();
|
|
26777
26568
|
if (agentFiles.length === 0) {
|
|
26778
26569
|
return null;
|
|
26779
26570
|
}
|
|
@@ -26796,7 +26587,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
26796
26587
|
return null;
|
|
26797
26588
|
}
|
|
26798
26589
|
addLoss(lossReport, "cursor", "instructions", {
|
|
26799
|
-
source: `agents/${
|
|
26590
|
+
source: `agents/${path33.basename(primaryFile)}`,
|
|
26800
26591
|
fields: [
|
|
26801
26592
|
{
|
|
26802
26593
|
field: "persona",
|
|
@@ -26806,23 +26597,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
26806
26597
|
"persona",
|
|
26807
26598
|
"instructions-shim"
|
|
26808
26599
|
),
|
|
26809
|
-
detail: `Primary persona from ${
|
|
26600
|
+
detail: `Primary persona from ${path33.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
|
|
26810
26601
|
}
|
|
26811
26602
|
]
|
|
26812
26603
|
});
|
|
26813
26604
|
return body.trim();
|
|
26814
26605
|
}
|
|
26815
26606
|
function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26816
|
-
const sourceAgentsRoot =
|
|
26817
|
-
if (!
|
|
26607
|
+
const sourceAgentsRoot = path33.join(sourceRoot, config.source.agents);
|
|
26608
|
+
if (!fs33.existsSync(sourceAgentsRoot)) {
|
|
26818
26609
|
return [skippedMissingSource3("agents", sourceAgentsRoot)];
|
|
26819
26610
|
}
|
|
26820
|
-
const sourceAgents = ts(
|
|
26611
|
+
const sourceAgents = ts(path33.join(sourceAgentsRoot, "*.md")).sort();
|
|
26821
26612
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
26822
26613
|
return sourceAgents.map((agentFile) => {
|
|
26823
|
-
const destination =
|
|
26614
|
+
const destination = path33.join(
|
|
26824
26615
|
agentsRoot,
|
|
26825
|
-
`${
|
|
26616
|
+
`${path33.basename(agentFile, ".md")}.md`
|
|
26826
26617
|
);
|
|
26827
26618
|
let compiled;
|
|
26828
26619
|
try {
|
|
@@ -26863,14 +26654,14 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
26863
26654
|
});
|
|
26864
26655
|
}
|
|
26865
26656
|
function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
26866
|
-
const sourceRulesDir =
|
|
26867
|
-
if (!
|
|
26657
|
+
const sourceRulesDir = path33.join(sourceRoot, config.source.rules);
|
|
26658
|
+
if (!fs33.existsSync(sourceRulesDir)) {
|
|
26868
26659
|
return [skippedMissingSource3("rules", sourceRulesDir)];
|
|
26869
26660
|
}
|
|
26870
26661
|
const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
|
|
26871
26662
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
26872
26663
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
26873
|
-
const destination =
|
|
26664
|
+
const destination = path33.join(rulesDir, name);
|
|
26874
26665
|
if (options.dryRun) {
|
|
26875
26666
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
26876
26667
|
return {
|
|
@@ -26894,17 +26685,17 @@ function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26894
26685
|
});
|
|
26895
26686
|
}
|
|
26896
26687
|
function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26897
|
-
const sourceCommandsRoot =
|
|
26898
|
-
if (!
|
|
26688
|
+
const sourceCommandsRoot = path33.join(sourceRoot, config.source.commands);
|
|
26689
|
+
if (!fs33.existsSync(sourceCommandsRoot)) {
|
|
26899
26690
|
return [skippedMissingSource3("commands", sourceCommandsRoot)];
|
|
26900
26691
|
}
|
|
26901
|
-
const sourceCommands = ts(
|
|
26692
|
+
const sourceCommands = ts(path33.join(sourceCommandsRoot, "*.md")).sort();
|
|
26902
26693
|
const skillsRoot = resolveTargetPath(paths.skills);
|
|
26903
26694
|
return sourceCommands.map((commandFile) => {
|
|
26904
|
-
const baseName =
|
|
26905
|
-
const destination =
|
|
26906
|
-
const commandContent =
|
|
26907
|
-
const relativeSource = `commands/${
|
|
26695
|
+
const baseName = path33.basename(commandFile, ".md");
|
|
26696
|
+
const destination = path33.join(skillsRoot, baseName, "SKILL.md");
|
|
26697
|
+
const commandContent = fs33.readFileSync(commandFile, "utf8");
|
|
26698
|
+
const relativeSource = `commands/${path33.basename(commandFile)}`;
|
|
26908
26699
|
const marker = formatProvenanceMarker(
|
|
26909
26700
|
"markdown",
|
|
26910
26701
|
relativeSource,
|
|
@@ -26943,8 +26734,8 @@ ${commandContent.trim()}
|
|
|
26943
26734
|
});
|
|
26944
26735
|
}
|
|
26945
26736
|
function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
|
|
26946
|
-
const source =
|
|
26947
|
-
if (!
|
|
26737
|
+
const source = path33.resolve(sourceRoot, config.source.skills);
|
|
26738
|
+
if (!fs33.existsSync(source)) {
|
|
26948
26739
|
return skippedMissingSource3(component, source);
|
|
26949
26740
|
}
|
|
26950
26741
|
if (options.dryRun) {
|
|
@@ -26958,18 +26749,18 @@ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, c
|
|
|
26958
26749
|
return { component, status: "skipped-current", path: destination };
|
|
26959
26750
|
}
|
|
26960
26751
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26961
|
-
|
|
26752
|
+
fs33.unlinkSync(destination);
|
|
26962
26753
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
26963
26754
|
return { component, status: "conflict", path: destination };
|
|
26964
26755
|
} else if (artifactClass === "managed-symlink") {
|
|
26965
|
-
|
|
26756
|
+
fs33.unlinkSync(destination);
|
|
26966
26757
|
}
|
|
26967
|
-
ensureDir(
|
|
26758
|
+
ensureDir(path33.dirname(destination));
|
|
26968
26759
|
createRelativeSymlink(source, destination, "dir");
|
|
26969
26760
|
logger.verbose(`Skills: created shared skills symlink ${destination}`);
|
|
26970
26761
|
return { component, status: "success", path: destination };
|
|
26971
26762
|
}
|
|
26972
|
-
if (
|
|
26763
|
+
if (fs33.existsSync(destination)) {
|
|
26973
26764
|
return { component, status: "skipped-current", path: destination };
|
|
26974
26765
|
}
|
|
26975
26766
|
ensureDir(destination);
|
|
@@ -26980,7 +26771,7 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26980
26771
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
26981
26772
|
const sourceLabel = hooksSourceLabel(config);
|
|
26982
26773
|
const destination = resolveTargetPath(paths.hooks_file);
|
|
26983
|
-
const sourceHooksJson =
|
|
26774
|
+
const sourceHooksJson = fs33.existsSync(source) ? JSON.parse(fs33.readFileSync(source, "utf8")) : { hooks: {} };
|
|
26984
26775
|
const compiled = compileHooks(
|
|
26985
26776
|
sourceHooksJson,
|
|
26986
26777
|
"cursor",
|
|
@@ -26994,18 +26785,18 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26994
26785
|
}
|
|
26995
26786
|
const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
|
|
26996
26787
|
`;
|
|
26997
|
-
ensureDir(
|
|
26998
|
-
|
|
26788
|
+
ensureDir(path33.dirname(destination));
|
|
26789
|
+
fs33.writeFileSync(destination, hooksFileContent);
|
|
26999
26790
|
return { component: "hooks", status: "success", path: destination };
|
|
27000
26791
|
}
|
|
27001
26792
|
function syncMcp3(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
27002
26793
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27003
26794
|
const sourceLabel = mcpSourceLabel(config);
|
|
27004
26795
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
27005
|
-
if (!
|
|
26796
|
+
if (!fs33.existsSync(source)) {
|
|
27006
26797
|
return skippedMissingSource3("mcp", source);
|
|
27007
26798
|
}
|
|
27008
|
-
const sourceMcpJson = JSON.parse(
|
|
26799
|
+
const sourceMcpJson = JSON.parse(fs33.readFileSync(source, "utf8"));
|
|
27009
26800
|
const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
|
|
27010
26801
|
if (options.dryRun) {
|
|
27011
26802
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -27056,13 +26847,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
|
|
|
27056
26847
|
);
|
|
27057
26848
|
}
|
|
27058
26849
|
function syncProviderPin(config, sourceRoot, lossReport) {
|
|
27059
|
-
const agentsDir =
|
|
27060
|
-
if (!
|
|
27061
|
-
for (const agentFile of ts(
|
|
26850
|
+
const agentsDir = path33.join(sourceRoot, config.source.agents);
|
|
26851
|
+
if (!fs33.existsSync(agentsDir)) return;
|
|
26852
|
+
for (const agentFile of ts(path33.join(agentsDir, "*.md")).sort()) {
|
|
27062
26853
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
27063
26854
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
27064
26855
|
if (hasCustomProvider) {
|
|
27065
|
-
const relativeSource = `agents/${
|
|
26856
|
+
const relativeSource = `agents/${path33.basename(agentFile)}`;
|
|
27066
26857
|
addLoss(lossReport, "cursor", "agents", {
|
|
27067
26858
|
source: relativeSource,
|
|
27068
26859
|
fields: [
|
|
@@ -27074,7 +26865,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
|
|
|
27074
26865
|
"provider",
|
|
27075
26866
|
"provider-not-representable"
|
|
27076
26867
|
),
|
|
27077
|
-
detail: `${
|
|
26868
|
+
detail: `${path33.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
27078
26869
|
}
|
|
27079
26870
|
]
|
|
27080
26871
|
});
|
|
@@ -27089,8 +26880,8 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
|
|
|
27089
26880
|
if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
27090
26881
|
return { component, status: "conflict", path: destination };
|
|
27091
26882
|
}
|
|
27092
|
-
ensureDir(
|
|
27093
|
-
|
|
26883
|
+
ensureDir(path33.dirname(destination));
|
|
26884
|
+
fs33.writeFileSync(destination, content);
|
|
27094
26885
|
return { component, status: "success", path: destination };
|
|
27095
26886
|
}
|
|
27096
26887
|
function handleConflict3(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -27109,16 +26900,16 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
|
|
|
27109
26900
|
backupFile(destination, manifest);
|
|
27110
26901
|
writeManifest(scopePath, manifest);
|
|
27111
26902
|
} else {
|
|
27112
|
-
|
|
26903
|
+
fs33.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
27113
26904
|
}
|
|
27114
26905
|
return true;
|
|
27115
26906
|
}
|
|
27116
|
-
|
|
26907
|
+
fs33.rmSync(destination, { recursive: true, force: true });
|
|
27117
26908
|
return true;
|
|
27118
26909
|
}
|
|
27119
26910
|
function isCompiledCurrent3(destination, expectedContent, expectedHash) {
|
|
27120
26911
|
try {
|
|
27121
|
-
const current =
|
|
26912
|
+
const current = fs33.readFileSync(destination, "utf8");
|
|
27122
26913
|
const marker = extractProvenanceMarker(current);
|
|
27123
26914
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "cursor" && current === expectedContent : current === expectedContent;
|
|
27124
26915
|
} catch {
|
|
@@ -27137,7 +26928,7 @@ function shouldSkipComponent3(options, component) {
|
|
|
27137
26928
|
}
|
|
27138
26929
|
function isSymlinkTo3(linkPath, source) {
|
|
27139
26930
|
try {
|
|
27140
|
-
return
|
|
26931
|
+
return fs33.realpathSync(linkPath) === fs33.realpathSync(source);
|
|
27141
26932
|
} catch {
|
|
27142
26933
|
return false;
|
|
27143
26934
|
}
|
|
@@ -27148,8 +26939,8 @@ function hashString3(value) {
|
|
|
27148
26939
|
|
|
27149
26940
|
// src/adapters/cline.ts
|
|
27150
26941
|
import crypto8 from "crypto";
|
|
27151
|
-
import
|
|
27152
|
-
import
|
|
26942
|
+
import fs34 from "fs";
|
|
26943
|
+
import path34 from "path";
|
|
27153
26944
|
function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27154
26945
|
const scope = options.scope ?? "global";
|
|
27155
26946
|
const profile = resolveTargetPaths({
|
|
@@ -27262,7 +27053,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
27262
27053
|
function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
|
|
27263
27054
|
if (scope === "global" || paths.instructions === null) {
|
|
27264
27055
|
addLoss(lossReport, "cline", "instructions", {
|
|
27265
|
-
source:
|
|
27056
|
+
source: path34.basename(config.source.instructions),
|
|
27266
27057
|
fields: [
|
|
27267
27058
|
{
|
|
27268
27059
|
field: "instructions",
|
|
@@ -27282,12 +27073,12 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
|
|
|
27282
27073
|
path: "cline/global/instructions: no committable global path"
|
|
27283
27074
|
};
|
|
27284
27075
|
}
|
|
27285
|
-
const source =
|
|
27076
|
+
const source = path34.join(sourceRoot, config.source.instructions);
|
|
27286
27077
|
const destination = resolveTargetPath(paths.instructions);
|
|
27287
|
-
const baseContent =
|
|
27078
|
+
const baseContent = fs34.existsSync(source) ? fs34.readFileSync(source, "utf8").trim() : "";
|
|
27288
27079
|
const marker = formatProvenanceMarker(
|
|
27289
27080
|
"markdown",
|
|
27290
|
-
|
|
27081
|
+
path34.basename(config.source.instructions),
|
|
27291
27082
|
hashString4(baseContent),
|
|
27292
27083
|
"cline"
|
|
27293
27084
|
);
|
|
@@ -27312,11 +27103,11 @@ ${baseContent}
|
|
|
27312
27103
|
);
|
|
27313
27104
|
}
|
|
27314
27105
|
function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
|
|
27315
|
-
const sourceAgentsRoot =
|
|
27316
|
-
if (!
|
|
27106
|
+
const sourceAgentsRoot = path34.join(sourceRoot, config.source.agents);
|
|
27107
|
+
if (!fs34.existsSync(sourceAgentsRoot)) {
|
|
27317
27108
|
return [skippedMissingSource4("agents", sourceAgentsRoot)];
|
|
27318
27109
|
}
|
|
27319
|
-
const sourceAgents = ts(
|
|
27110
|
+
const sourceAgents = ts(path34.join(sourceAgentsRoot, "*.md")).sort();
|
|
27320
27111
|
return sourceAgents.map((agentFile) => {
|
|
27321
27112
|
compileAgent(agentFile, "cline", mappings, extensions, lossReport);
|
|
27322
27113
|
if (options.dryRun) {
|
|
@@ -27332,14 +27123,14 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
27332
27123
|
});
|
|
27333
27124
|
}
|
|
27334
27125
|
function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
27335
|
-
const sourceRulesDir =
|
|
27336
|
-
if (!
|
|
27126
|
+
const sourceRulesDir = path34.join(sourceRoot, config.source.rules);
|
|
27127
|
+
if (!fs34.existsSync(sourceRulesDir)) {
|
|
27337
27128
|
return [skippedMissingSource4("rules", sourceRulesDir)];
|
|
27338
27129
|
}
|
|
27339
27130
|
const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
|
|
27340
27131
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
27341
27132
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
27342
|
-
const destination =
|
|
27133
|
+
const destination = path34.join(rulesDir, name);
|
|
27343
27134
|
if (options.dryRun) {
|
|
27344
27135
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
27345
27136
|
return {
|
|
@@ -27363,17 +27154,17 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
27363
27154
|
});
|
|
27364
27155
|
}
|
|
27365
27156
|
function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27366
|
-
const sourceCommandsRoot =
|
|
27367
|
-
if (!
|
|
27157
|
+
const sourceCommandsRoot = path34.join(sourceRoot, config.source.commands);
|
|
27158
|
+
if (!fs34.existsSync(sourceCommandsRoot)) {
|
|
27368
27159
|
return [skippedMissingSource4("commands", sourceCommandsRoot)];
|
|
27369
27160
|
}
|
|
27370
|
-
const sourceCommands = ts(
|
|
27161
|
+
const sourceCommands = ts(path34.join(sourceCommandsRoot, "*.md")).sort();
|
|
27371
27162
|
const workflowsRoot = resolveTargetPath(paths.workflows);
|
|
27372
27163
|
return sourceCommands.map((commandFile) => {
|
|
27373
|
-
const baseName =
|
|
27374
|
-
const destination =
|
|
27375
|
-
const commandContent =
|
|
27376
|
-
const relativeSource = `commands/${
|
|
27164
|
+
const baseName = path34.basename(commandFile);
|
|
27165
|
+
const destination = path34.join(workflowsRoot, baseName);
|
|
27166
|
+
const commandContent = fs34.readFileSync(commandFile, "utf8");
|
|
27167
|
+
const relativeSource = `commands/${path34.basename(commandFile)}`;
|
|
27377
27168
|
const marker = formatProvenanceMarker(
|
|
27378
27169
|
"markdown",
|
|
27379
27170
|
relativeSource,
|
|
@@ -27408,9 +27199,9 @@ ${commandContent.trim()}
|
|
|
27408
27199
|
});
|
|
27409
27200
|
}
|
|
27410
27201
|
function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27411
|
-
const source =
|
|
27202
|
+
const source = path34.resolve(sourceRoot, config.source.skills);
|
|
27412
27203
|
const destination = resolveTargetPath(paths.skills);
|
|
27413
|
-
if (!
|
|
27204
|
+
if (!fs34.existsSync(source)) {
|
|
27414
27205
|
return skippedMissingSource4("skills", source);
|
|
27415
27206
|
}
|
|
27416
27207
|
if (options.dryRun) {
|
|
@@ -27430,9 +27221,9 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
27430
27221
|
return { component: "skills", status: "conflict", path: destination };
|
|
27431
27222
|
}
|
|
27432
27223
|
} else if (artifactClass === "managed-symlink") {
|
|
27433
|
-
|
|
27224
|
+
fs34.unlinkSync(destination);
|
|
27434
27225
|
}
|
|
27435
|
-
ensureDir(
|
|
27226
|
+
ensureDir(path34.dirname(destination));
|
|
27436
27227
|
createRelativeSymlink(source, destination, "dir");
|
|
27437
27228
|
logger.verbose(`Skills: created Cline skills symlink ${destination}`);
|
|
27438
27229
|
return { component: "skills", status: "success", path: destination };
|
|
@@ -27440,7 +27231,7 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
27440
27231
|
function syncHooks4(config, sourceRoot, mappings, options, lossReport, logger) {
|
|
27441
27232
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
27442
27233
|
const sourceLabel = hooksSourceLabel(config);
|
|
27443
|
-
const sourceHooksJson =
|
|
27234
|
+
const sourceHooksJson = fs34.existsSync(source) ? JSON.parse(fs34.readFileSync(source, "utf8")) : { hooks: {} };
|
|
27444
27235
|
compileHooks(sourceHooksJson, "cline", mappings, lossReport, sourceLabel);
|
|
27445
27236
|
if (options.dryRun) {
|
|
27446
27237
|
logger.info(`[dry-run] hooks: record hook-as-plugin loss for ${source}`);
|
|
@@ -27455,10 +27246,10 @@ function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manife
|
|
|
27455
27246
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27456
27247
|
const sourceLabel = mcpSourceLabel(config);
|
|
27457
27248
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
27458
|
-
if (!
|
|
27249
|
+
if (!fs34.existsSync(source)) {
|
|
27459
27250
|
return skippedMissingSource4("mcp", source);
|
|
27460
27251
|
}
|
|
27461
|
-
const sourceMcpJson = JSON.parse(
|
|
27252
|
+
const sourceMcpJson = JSON.parse(fs34.readFileSync(source, "utf8"));
|
|
27462
27253
|
const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
|
|
27463
27254
|
if (options.dryRun) {
|
|
27464
27255
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -27501,11 +27292,11 @@ function syncSettings(lossReport) {
|
|
|
27501
27292
|
};
|
|
27502
27293
|
}
|
|
27503
27294
|
function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
27504
|
-
const agentsDir =
|
|
27505
|
-
if (!
|
|
27506
|
-
for (const agentFile of ts(
|
|
27295
|
+
const agentsDir = path34.join(sourceRoot, config.source.agents);
|
|
27296
|
+
if (!fs34.existsSync(agentsDir)) return;
|
|
27297
|
+
for (const agentFile of ts(path34.join(agentsDir, "*.md")).sort()) {
|
|
27507
27298
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
27508
|
-
const relativeSource = `agents/${
|
|
27299
|
+
const relativeSource = `agents/${path34.basename(agentFile)}`;
|
|
27509
27300
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
27510
27301
|
if (hasCustomProvider) {
|
|
27511
27302
|
addLoss(lossReport, "cline", "agents", {
|
|
@@ -27519,7 +27310,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
27519
27310
|
"provider",
|
|
27520
27311
|
"provider-not-representable"
|
|
27521
27312
|
),
|
|
27522
|
-
detail: `${
|
|
27313
|
+
detail: `${path34.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
|
|
27523
27314
|
}
|
|
27524
27315
|
]
|
|
27525
27316
|
});
|
|
@@ -27537,7 +27328,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
27537
27328
|
"model",
|
|
27538
27329
|
"model-not-representable"
|
|
27539
27330
|
),
|
|
27540
|
-
detail: `${
|
|
27331
|
+
detail: `${path34.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
|
|
27541
27332
|
}
|
|
27542
27333
|
]
|
|
27543
27334
|
});
|
|
@@ -27552,8 +27343,8 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
|
|
|
27552
27343
|
if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
|
|
27553
27344
|
return { component, status: "conflict", path: destination };
|
|
27554
27345
|
}
|
|
27555
|
-
ensureDir(
|
|
27556
|
-
|
|
27346
|
+
ensureDir(path34.dirname(destination));
|
|
27347
|
+
fs34.writeFileSync(destination, content);
|
|
27557
27348
|
return { component, status: "success", path: destination };
|
|
27558
27349
|
}
|
|
27559
27350
|
function handleConflict4(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -27572,16 +27363,16 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
|
|
|
27572
27363
|
backupFile(destination, manifest);
|
|
27573
27364
|
writeManifest(scopePath, manifest);
|
|
27574
27365
|
} else {
|
|
27575
|
-
|
|
27366
|
+
fs34.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
27576
27367
|
}
|
|
27577
27368
|
return true;
|
|
27578
27369
|
}
|
|
27579
|
-
|
|
27370
|
+
fs34.rmSync(destination, { recursive: true, force: true });
|
|
27580
27371
|
return true;
|
|
27581
27372
|
}
|
|
27582
27373
|
function isCompiledCurrent4(destination, expectedContent, expectedHash) {
|
|
27583
27374
|
try {
|
|
27584
|
-
const current =
|
|
27375
|
+
const current = fs34.readFileSync(destination, "utf8");
|
|
27585
27376
|
const marker = extractProvenanceMarker(current);
|
|
27586
27377
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "cline" && current === expectedContent : current === expectedContent;
|
|
27587
27378
|
} catch {
|
|
@@ -27600,7 +27391,7 @@ function shouldSkipComponent4(options, component) {
|
|
|
27600
27391
|
}
|
|
27601
27392
|
function isSymlinkTo4(linkPath, source) {
|
|
27602
27393
|
try {
|
|
27603
|
-
return
|
|
27394
|
+
return fs34.realpathSync(linkPath) === fs34.realpathSync(source);
|
|
27604
27395
|
} catch {
|
|
27605
27396
|
return false;
|
|
27606
27397
|
}
|
|
@@ -27611,9 +27402,9 @@ function hashString4(value) {
|
|
|
27611
27402
|
|
|
27612
27403
|
// src/adapters/opencode.ts
|
|
27613
27404
|
import crypto9 from "crypto";
|
|
27614
|
-
import
|
|
27405
|
+
import fs35 from "fs";
|
|
27615
27406
|
import os6 from "os";
|
|
27616
|
-
import
|
|
27407
|
+
import path35 from "path";
|
|
27617
27408
|
var import_yaml10 = __toESM(require_dist(), 1);
|
|
27618
27409
|
function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27619
27410
|
const scope = options.scope ?? "global";
|
|
@@ -27631,7 +27422,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
27631
27422
|
config_doc: profile.config_doc
|
|
27632
27423
|
};
|
|
27633
27424
|
const rules = compileRules(
|
|
27634
|
-
|
|
27425
|
+
path35.join(sourceRoot, config.source.rules),
|
|
27635
27426
|
"opencode",
|
|
27636
27427
|
mappings,
|
|
27637
27428
|
lossReport
|
|
@@ -27733,16 +27524,16 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
27733
27524
|
return { target: "opencode", outcomes };
|
|
27734
27525
|
}
|
|
27735
27526
|
function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
27736
|
-
const source =
|
|
27527
|
+
const source = path35.join(sourceRoot, config.source.instructions);
|
|
27737
27528
|
const destination = resolveTargetPath(paths.instructions);
|
|
27738
|
-
const baseContent =
|
|
27529
|
+
const baseContent = fs35.existsSync(source) ? fs35.readFileSync(source, "utf8").trim() : "";
|
|
27739
27530
|
const composed = agentsAppendix ? `${baseContent}
|
|
27740
27531
|
|
|
27741
27532
|
--- tangyr managed rules ---
|
|
27742
27533
|
${agentsAppendix}`.trim() : baseContent;
|
|
27743
27534
|
const marker = formatProvenanceMarker(
|
|
27744
27535
|
"markdown",
|
|
27745
|
-
|
|
27536
|
+
path35.basename(config.source.instructions),
|
|
27746
27537
|
hashString5(composed),
|
|
27747
27538
|
"opencode"
|
|
27748
27539
|
);
|
|
@@ -27769,16 +27560,16 @@ ${composed}
|
|
|
27769
27560
|
);
|
|
27770
27561
|
}
|
|
27771
27562
|
function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27772
|
-
const sourceAgentsRoot =
|
|
27773
|
-
if (!
|
|
27563
|
+
const sourceAgentsRoot = path35.join(sourceRoot, config.source.agents);
|
|
27564
|
+
if (!fs35.existsSync(sourceAgentsRoot)) {
|
|
27774
27565
|
return [skippedMissingSource5("agents", sourceAgentsRoot)];
|
|
27775
27566
|
}
|
|
27776
|
-
const sourceAgents = ts(
|
|
27567
|
+
const sourceAgents = ts(path35.join(sourceAgentsRoot, "*.md")).sort();
|
|
27777
27568
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
27778
27569
|
return sourceAgents.map((agentFile) => {
|
|
27779
|
-
const destination =
|
|
27570
|
+
const destination = path35.join(
|
|
27780
27571
|
agentsRoot,
|
|
27781
|
-
`${
|
|
27572
|
+
`${path35.basename(agentFile, ".md")}.md`
|
|
27782
27573
|
);
|
|
27783
27574
|
let compiled;
|
|
27784
27575
|
try {
|
|
@@ -27842,11 +27633,11 @@ function applyProviderModelBinding(compiled, mappings) {
|
|
|
27842
27633
|
return `${before}${(0, import_yaml10.stringify)(fields).trim()}${after}`;
|
|
27843
27634
|
}
|
|
27844
27635
|
function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27845
|
-
const sourceCommandsRoot =
|
|
27846
|
-
if (!
|
|
27636
|
+
const sourceCommandsRoot = path35.join(sourceRoot, config.source.commands);
|
|
27637
|
+
if (!fs35.existsSync(sourceCommandsRoot)) {
|
|
27847
27638
|
return [skippedMissingSource5("commands", sourceCommandsRoot)];
|
|
27848
27639
|
}
|
|
27849
|
-
const sourceCommands = ts(
|
|
27640
|
+
const sourceCommands = ts(path35.join(sourceCommandsRoot, "*.md")).sort();
|
|
27850
27641
|
const commandsRoot = resolveTargetPath(paths.commands);
|
|
27851
27642
|
return sourceCommands.map((commandFile) => {
|
|
27852
27643
|
const { data, body } = parseCommandFile(commandFile);
|
|
@@ -27860,7 +27651,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
|
|
|
27860
27651
|
if (typeof data.model === "string") {
|
|
27861
27652
|
frontmatter.model = data.model;
|
|
27862
27653
|
}
|
|
27863
|
-
const relativeSource = `commands/${
|
|
27654
|
+
const relativeSource = `commands/${path35.basename(commandFile)}`;
|
|
27864
27655
|
const marker = formatProvenanceMarker(
|
|
27865
27656
|
"markdown",
|
|
27866
27657
|
relativeSource,
|
|
@@ -27876,9 +27667,9 @@ ${body.trimEnd()}
|
|
|
27876
27667
|
` : `${marker}
|
|
27877
27668
|
${body.trimEnd()}
|
|
27878
27669
|
`;
|
|
27879
|
-
const destination =
|
|
27670
|
+
const destination = path35.join(
|
|
27880
27671
|
commandsRoot,
|
|
27881
|
-
`${
|
|
27672
|
+
`${path35.basename(commandFile, ".md")}.md`
|
|
27882
27673
|
);
|
|
27883
27674
|
if (options.dryRun) {
|
|
27884
27675
|
logger.info(
|
|
@@ -27905,8 +27696,8 @@ ${body.trimEnd()}
|
|
|
27905
27696
|
});
|
|
27906
27697
|
}
|
|
27907
27698
|
function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, component = "skills", destination = "") {
|
|
27908
|
-
const source =
|
|
27909
|
-
if (!
|
|
27699
|
+
const source = path35.resolve(sourceRoot, config.source.skills);
|
|
27700
|
+
if (!fs35.existsSync(source)) {
|
|
27910
27701
|
return skippedMissingSource5(component, source);
|
|
27911
27702
|
}
|
|
27912
27703
|
if (options.dryRun) {
|
|
@@ -27918,13 +27709,13 @@ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scop
|
|
|
27918
27709
|
return { component, status: "skipped-current", path: destination };
|
|
27919
27710
|
}
|
|
27920
27711
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
27921
|
-
|
|
27712
|
+
fs35.unlinkSync(destination);
|
|
27922
27713
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
27923
27714
|
return { component, status: "conflict", path: destination };
|
|
27924
27715
|
} else if (artifactClass === "managed-symlink") {
|
|
27925
|
-
|
|
27716
|
+
fs35.unlinkSync(destination);
|
|
27926
27717
|
}
|
|
27927
|
-
ensureDir(
|
|
27718
|
+
ensureDir(path35.dirname(destination));
|
|
27928
27719
|
createRelativeSymlink(source, destination, "dir");
|
|
27929
27720
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
27930
27721
|
return { component, status: "success", path: destination };
|
|
@@ -27933,13 +27724,13 @@ function syncMcp5(config, sourceRoot, paths, mappings, options, lossReport, logg
|
|
|
27933
27724
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27934
27725
|
const sourceLabel = mcpSourceLabel(config);
|
|
27935
27726
|
const destination = resolveTargetPath(paths.config_doc);
|
|
27936
|
-
if (!
|
|
27727
|
+
if (!fs35.existsSync(source)) {
|
|
27937
27728
|
if (!options.dryRun) {
|
|
27938
27729
|
syncConfigDoc(paths, {}, lossReport, {}, mappings);
|
|
27939
27730
|
}
|
|
27940
27731
|
return skippedMissingSource5("mcp", source);
|
|
27941
27732
|
}
|
|
27942
|
-
const sourceMcpJson = JSON.parse(
|
|
27733
|
+
const sourceMcpJson = JSON.parse(fs35.readFileSync(source, "utf8"));
|
|
27943
27734
|
const mcpJson = compileMcp(
|
|
27944
27735
|
sourceMcpJson,
|
|
27945
27736
|
"opencode",
|
|
@@ -27970,7 +27761,7 @@ function syncPermissions2(config, _sourceRoot, paths, options, lossReport, logge
|
|
|
27970
27761
|
function syncHooks5(config, sourceRoot, mappings, options, lossReport) {
|
|
27971
27762
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
27972
27763
|
const sourceLabel = hooksSourceLabel(config);
|
|
27973
|
-
const sourceHooksJson =
|
|
27764
|
+
const sourceHooksJson = fs35.existsSync(source) ? JSON.parse(fs35.readFileSync(source, "utf8")) : { hooks: {} };
|
|
27974
27765
|
compileHooks(sourceHooksJson, "opencode", mappings, lossReport, sourceLabel);
|
|
27975
27766
|
const message = "hooks: Skip \u2014 OpenCode exposes hooks only as plugin code (hook-as-plugin loss recorded)";
|
|
27976
27767
|
return { component: "hooks", status: "skipped", path: message };
|
|
@@ -28004,9 +27795,9 @@ function syncProviderBlock(mappings) {
|
|
|
28004
27795
|
function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
|
|
28005
27796
|
const destination = resolveTargetPath(paths.config_doc);
|
|
28006
27797
|
let existing = {};
|
|
28007
|
-
if (
|
|
27798
|
+
if (fs35.existsSync(destination)) {
|
|
28008
27799
|
try {
|
|
28009
|
-
existing = JSON.parse(
|
|
27800
|
+
existing = JSON.parse(fs35.readFileSync(destination, "utf8"));
|
|
28010
27801
|
} catch {
|
|
28011
27802
|
existing = {};
|
|
28012
27803
|
}
|
|
@@ -28031,8 +27822,8 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
|
|
|
28031
27822
|
};
|
|
28032
27823
|
}
|
|
28033
27824
|
}
|
|
28034
|
-
ensureDir(
|
|
28035
|
-
|
|
27825
|
+
ensureDir(path35.dirname(destination));
|
|
27826
|
+
fs35.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
|
|
28036
27827
|
`);
|
|
28037
27828
|
}
|
|
28038
27829
|
function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
|
|
@@ -28043,8 +27834,8 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
|
|
|
28043
27834
|
if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
28044
27835
|
return { component, status: "conflict", path: destination };
|
|
28045
27836
|
}
|
|
28046
|
-
ensureDir(
|
|
28047
|
-
|
|
27837
|
+
ensureDir(path35.dirname(destination));
|
|
27838
|
+
fs35.writeFileSync(destination, content);
|
|
28048
27839
|
return { component, status: "success", path: destination };
|
|
28049
27840
|
}
|
|
28050
27841
|
function handleConflict5(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -28063,16 +27854,16 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
|
|
|
28063
27854
|
backupFile(destination, manifest);
|
|
28064
27855
|
writeManifest(scopePath, manifest);
|
|
28065
27856
|
} else {
|
|
28066
|
-
|
|
27857
|
+
fs35.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
28067
27858
|
}
|
|
28068
27859
|
return true;
|
|
28069
27860
|
}
|
|
28070
|
-
|
|
27861
|
+
fs35.rmSync(destination, { recursive: true, force: true });
|
|
28071
27862
|
return true;
|
|
28072
27863
|
}
|
|
28073
27864
|
function isCompiledCurrent5(destination, expectedContent, expectedHash) {
|
|
28074
27865
|
try {
|
|
28075
|
-
const current =
|
|
27866
|
+
const current = fs35.readFileSync(destination, "utf8");
|
|
28076
27867
|
const marker = extractProvenanceMarker(current);
|
|
28077
27868
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "opencode" && current === expectedContent : current === expectedContent;
|
|
28078
27869
|
} catch {
|
|
@@ -28091,7 +27882,7 @@ function shouldSkipComponent5(options, component) {
|
|
|
28091
27882
|
}
|
|
28092
27883
|
function isSymlinkTo5(linkPath, source) {
|
|
28093
27884
|
try {
|
|
28094
|
-
return
|
|
27885
|
+
return fs35.realpathSync(linkPath) === fs35.realpathSync(source);
|
|
28095
27886
|
} catch {
|
|
28096
27887
|
return false;
|
|
28097
27888
|
}
|
|
@@ -28100,7 +27891,7 @@ function hashString5(value) {
|
|
|
28100
27891
|
return `sha256:${crypto9.createHash("sha256").update(value).digest("hex")}`;
|
|
28101
27892
|
}
|
|
28102
27893
|
function parseCommandFile(commandFile) {
|
|
28103
|
-
const content =
|
|
27894
|
+
const content = fs35.readFileSync(commandFile, "utf8");
|
|
28104
27895
|
if (!content.startsWith("---\n")) {
|
|
28105
27896
|
return { data: {}, body: content };
|
|
28106
27897
|
}
|
|
@@ -28120,10 +27911,10 @@ function parseCommandFile(commandFile) {
|
|
|
28120
27911
|
// src/commands/install.ts
|
|
28121
27912
|
function isBackupableFile(targetPath) {
|
|
28122
27913
|
try {
|
|
28123
|
-
const lstat =
|
|
27914
|
+
const lstat = fs36.lstatSync(targetPath);
|
|
28124
27915
|
if (lstat.isDirectory()) return false;
|
|
28125
27916
|
if (lstat.isSymbolicLink()) {
|
|
28126
|
-
const stat =
|
|
27917
|
+
const stat = fs36.statSync(targetPath);
|
|
28127
27918
|
return stat.isFile();
|
|
28128
27919
|
}
|
|
28129
27920
|
return lstat.isFile();
|
|
@@ -28133,10 +27924,10 @@ function isBackupableFile(targetPath) {
|
|
|
28133
27924
|
}
|
|
28134
27925
|
function backupConflictingTarget(targetPath, scopePath) {
|
|
28135
27926
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/gu, "").replace("T", "T").replace(/\.\d+Z$/u, "Z");
|
|
28136
|
-
const relativeToRoot =
|
|
28137
|
-
const backupPath =
|
|
28138
|
-
|
|
28139
|
-
|
|
27927
|
+
const relativeToRoot = path36.relative("/", targetPath).replace(/^\.\.\/+/gu, "");
|
|
27928
|
+
const backupPath = path36.join(scopePath, "backups", ts2, relativeToRoot);
|
|
27929
|
+
fs36.mkdirSync(path36.dirname(backupPath), { recursive: true });
|
|
27930
|
+
fs36.copyFileSync(targetPath, backupPath);
|
|
28140
27931
|
return backupPath;
|
|
28141
27932
|
}
|
|
28142
27933
|
async function runInstallCommand(options, logger) {
|
|
@@ -28165,7 +27956,7 @@ async function runInstallCommand(options, logger) {
|
|
|
28165
27956
|
);
|
|
28166
27957
|
}
|
|
28167
27958
|
const kitName = resolvedKitName ?? config.kit;
|
|
28168
|
-
const kitPath = kitPathOverride ?? (options.kitPath ?
|
|
27959
|
+
const kitPath = kitPathOverride ?? (options.kitPath ? path36.resolve(options.kitPath) : config.kitPath);
|
|
28169
27960
|
if (!kitName && !kitPath) {
|
|
28170
27961
|
logger.error(
|
|
28171
27962
|
"No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
|
|
@@ -28306,7 +28097,7 @@ ACCEPTED CONFLICTS (backup-and-replace applied to ${conflictingFindings.length}
|
|
|
28306
28097
|
logger.info(` source: ${finding.tool}`);
|
|
28307
28098
|
logger.info(` action: backup-and-replace`);
|
|
28308
28099
|
logger.info(` backup: ${backupLocation}`);
|
|
28309
|
-
} else if (
|
|
28100
|
+
} else if (fs36.existsSync(finding.path)) {
|
|
28310
28101
|
logger.info(` - ${finding.path}`);
|
|
28311
28102
|
logger.info(` source: ${finding.tool}`);
|
|
28312
28103
|
logger.info(
|
|
@@ -28417,7 +28208,7 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
|
|
|
28417
28208
|
writeManifest(scopePath, manifest);
|
|
28418
28209
|
logger.info(`
|
|
28419
28210
|
Installation complete: ${installedCount} files installed.`);
|
|
28420
|
-
logger.info(`Manifest written to ${
|
|
28211
|
+
logger.info(`Manifest written to ${path36.join(scopePath, "manifest.json")}`);
|
|
28421
28212
|
logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
|
|
28422
28213
|
logger.info(`Scope: ${scope}`);
|
|
28423
28214
|
logger.info(`Tools: ${tools.join(", ")}`);
|
|
@@ -28559,13 +28350,13 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
28559
28350
|
logger.verbose(` skipped (operator choice): ${placement.destination}`);
|
|
28560
28351
|
continue;
|
|
28561
28352
|
}
|
|
28562
|
-
const destDir =
|
|
28563
|
-
|
|
28353
|
+
const destDir = path36.dirname(placement.destination);
|
|
28354
|
+
fs36.mkdirSync(destDir, { recursive: true });
|
|
28564
28355
|
if (placement.type === "symlink") {
|
|
28565
|
-
if (
|
|
28356
|
+
if (fs36.existsSync(placement.destination) || isSymlink2(placement.destination)) {
|
|
28566
28357
|
removeManagedPath(placement.destination);
|
|
28567
28358
|
}
|
|
28568
|
-
|
|
28359
|
+
fs36.symlinkSync(
|
|
28569
28360
|
placement.source,
|
|
28570
28361
|
placement.destination,
|
|
28571
28362
|
placement.isDir ? "dir" : "file"
|
|
@@ -28574,12 +28365,12 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
28574
28365
|
` symlink: ${placement.source} \u2192 ${placement.destination}`
|
|
28575
28366
|
);
|
|
28576
28367
|
} else {
|
|
28577
|
-
|
|
28368
|
+
fs36.copyFileSync(placement.source, placement.destination);
|
|
28578
28369
|
logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
|
|
28579
28370
|
}
|
|
28580
28371
|
addArtifactToManifest(manifest, {
|
|
28581
28372
|
relativePath: placement.manifestKey,
|
|
28582
|
-
hash:
|
|
28373
|
+
hash: fs36.statSync(placement.source).isDirectory() ? `dir:${placement.source}` : computeSourceHash(placement.source),
|
|
28583
28374
|
origin: "tangyr-managed"
|
|
28584
28375
|
});
|
|
28585
28376
|
count++;
|
|
@@ -28826,11 +28617,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28826
28617
|
if (outcome.path === mcpFile2) {
|
|
28827
28618
|
return "cline/mcp.json";
|
|
28828
28619
|
}
|
|
28829
|
-
if (outcome.path.startsWith(`${workflowsRoot}${
|
|
28830
|
-
return `cline/workflows/${
|
|
28620
|
+
if (outcome.path.startsWith(`${workflowsRoot}${path36.sep}`)) {
|
|
28621
|
+
return `cline/workflows/${path36.basename(outcome.path)}`;
|
|
28831
28622
|
}
|
|
28832
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
28833
|
-
return `cline/rules/${
|
|
28623
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path36.sep}`)) {
|
|
28624
|
+
return `cline/rules/${path36.basename(outcome.path)}`;
|
|
28834
28625
|
}
|
|
28835
28626
|
return null;
|
|
28836
28627
|
}
|
|
@@ -28866,14 +28657,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28866
28657
|
if (outcome.path === permissionsFile) {
|
|
28867
28658
|
return "cursor/permissions.json";
|
|
28868
28659
|
}
|
|
28869
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28870
|
-
return `cursor/agents/${
|
|
28660
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path36.sep}`)) {
|
|
28661
|
+
return `cursor/agents/${path36.basename(outcome.path)}`;
|
|
28871
28662
|
}
|
|
28872
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
28873
|
-
return `cursor/rules/${
|
|
28663
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path36.sep}`)) {
|
|
28664
|
+
return `cursor/rules/${path36.basename(outcome.path)}`;
|
|
28874
28665
|
}
|
|
28875
|
-
if (outcome.path.startsWith(`${skillsRoot2}${
|
|
28876
|
-
const rel =
|
|
28666
|
+
if (outcome.path.startsWith(`${skillsRoot2}${path36.sep}`)) {
|
|
28667
|
+
const rel = path36.relative(skillsRoot2, outcome.path);
|
|
28877
28668
|
return `cursor/skills/${rel}`;
|
|
28878
28669
|
}
|
|
28879
28670
|
return null;
|
|
@@ -28899,14 +28690,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28899
28690
|
if (outcome.path === skillsSharedRoot) {
|
|
28900
28691
|
return "opencode/skills_shared";
|
|
28901
28692
|
}
|
|
28902
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28903
|
-
return `opencode/agents/${
|
|
28693
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path36.sep}`)) {
|
|
28694
|
+
return `opencode/agents/${path36.basename(outcome.path)}`;
|
|
28904
28695
|
}
|
|
28905
|
-
if (outcome.path.startsWith(`${commandsRoot}${
|
|
28906
|
-
return `opencode/commands/${
|
|
28696
|
+
if (outcome.path.startsWith(`${commandsRoot}${path36.sep}`)) {
|
|
28697
|
+
return `opencode/commands/${path36.basename(outcome.path)}`;
|
|
28907
28698
|
}
|
|
28908
28699
|
if (outcome.path === configDocFile) {
|
|
28909
|
-
return `opencode/${
|
|
28700
|
+
return `opencode/${path36.basename(outcome.path)}`;
|
|
28910
28701
|
}
|
|
28911
28702
|
return null;
|
|
28912
28703
|
}
|
|
@@ -28920,17 +28711,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28920
28711
|
if (outcome.path === skillsRoot2) {
|
|
28921
28712
|
return "copilot/skills";
|
|
28922
28713
|
}
|
|
28923
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28924
|
-
return `copilot/agents/${
|
|
28714
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path36.sep}`)) {
|
|
28715
|
+
return `copilot/agents/${path36.basename(outcome.path)}`;
|
|
28925
28716
|
}
|
|
28926
|
-
if (outcome.path.startsWith(`${promptsRoot}${
|
|
28927
|
-
return `copilot/prompts/${
|
|
28717
|
+
if (outcome.path.startsWith(`${promptsRoot}${path36.sep}`)) {
|
|
28718
|
+
return `copilot/prompts/${path36.basename(outcome.path)}`;
|
|
28928
28719
|
}
|
|
28929
|
-
if (outcome.path.startsWith(`${hooksRoot}${
|
|
28930
|
-
return `copilot/hooks/${
|
|
28720
|
+
if (outcome.path.startsWith(`${hooksRoot}${path36.sep}`)) {
|
|
28721
|
+
return `copilot/hooks/${path36.basename(outcome.path)}`;
|
|
28931
28722
|
}
|
|
28932
28723
|
if (outcome.path === mcpFile2) {
|
|
28933
|
-
return `copilot/${
|
|
28724
|
+
return `copilot/${path36.basename(outcome.path)}`;
|
|
28934
28725
|
}
|
|
28935
28726
|
return null;
|
|
28936
28727
|
}
|
|
@@ -28946,17 +28737,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28946
28737
|
if (outcome.path === skillsRoot) {
|
|
28947
28738
|
return "codex/skills";
|
|
28948
28739
|
}
|
|
28949
|
-
if (outcome.path.startsWith(`${agentsRoot}${
|
|
28950
|
-
return `codex/agents/${
|
|
28740
|
+
if (outcome.path.startsWith(`${agentsRoot}${path36.sep}`)) {
|
|
28741
|
+
return `codex/agents/${path36.basename(outcome.path)}`;
|
|
28951
28742
|
}
|
|
28952
|
-
if (outcome.path.startsWith(`${rulesRoot}${
|
|
28953
|
-
return `codex/rules/${
|
|
28743
|
+
if (outcome.path.startsWith(`${rulesRoot}${path36.sep}`)) {
|
|
28744
|
+
return `codex/rules/${path36.basename(outcome.path)}`;
|
|
28954
28745
|
}
|
|
28955
28746
|
if (outcome.path === hooksFile) {
|
|
28956
|
-
return `codex/${
|
|
28747
|
+
return `codex/${path36.basename(outcome.path)}`;
|
|
28957
28748
|
}
|
|
28958
28749
|
if (outcome.path === mcpFile) {
|
|
28959
|
-
return `codex/${
|
|
28750
|
+
return `codex/${path36.basename(outcome.path)}`;
|
|
28960
28751
|
}
|
|
28961
28752
|
return null;
|
|
28962
28753
|
}
|
|
@@ -28991,8 +28782,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28991
28782
|
};
|
|
28992
28783
|
}
|
|
28993
28784
|
const placements = [];
|
|
28994
|
-
const claudeMd =
|
|
28995
|
-
if (
|
|
28785
|
+
const claudeMd = path36.join(kitInfo.path, "CLAUDE.md");
|
|
28786
|
+
if (fs36.existsSync(claudeMd)) {
|
|
28996
28787
|
placements.push({
|
|
28997
28788
|
source: claudeMd,
|
|
28998
28789
|
destination: resolvedPaths.instructions,
|
|
@@ -29008,8 +28799,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
29008
28799
|
rules: resolvedPaths.rules
|
|
29009
28800
|
};
|
|
29010
28801
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
29011
|
-
const componentDir =
|
|
29012
|
-
if (
|
|
28802
|
+
const componentDir = path36.join(kitInfo.path, component);
|
|
28803
|
+
if (fs36.existsSync(componentDir) && fs36.statSync(componentDir).isDirectory()) {
|
|
29013
28804
|
placements.push({
|
|
29014
28805
|
source: componentDir,
|
|
29015
28806
|
destination: targetPath,
|
|
@@ -29023,8 +28814,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
29023
28814
|
}
|
|
29024
28815
|
function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
29025
28816
|
const placements = [];
|
|
29026
|
-
const claudeMd =
|
|
29027
|
-
if (
|
|
28817
|
+
const claudeMd = path36.join(kitInfo.path, "CLAUDE.md");
|
|
28818
|
+
if (fs36.existsSync(claudeMd)) {
|
|
29028
28819
|
placements.push({
|
|
29029
28820
|
source: claudeMd,
|
|
29030
28821
|
destination: profile.instructions,
|
|
@@ -29040,8 +28831,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
|
29040
28831
|
rules: profile.rules
|
|
29041
28832
|
};
|
|
29042
28833
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
29043
|
-
const componentDir =
|
|
29044
|
-
if (
|
|
28834
|
+
const componentDir = path36.join(kitInfo.path, component);
|
|
28835
|
+
if (fs36.existsSync(componentDir) && fs36.statSync(componentDir).isDirectory()) {
|
|
29045
28836
|
placements.push({
|
|
29046
28837
|
source: componentDir,
|
|
29047
28838
|
destination: targetPath,
|
|
@@ -29055,8 +28846,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
|
29055
28846
|
}
|
|
29056
28847
|
function collectAllFiles(kitInfo) {
|
|
29057
28848
|
const files = /* @__PURE__ */ new Map();
|
|
29058
|
-
const claudeMd =
|
|
29059
|
-
if (
|
|
28849
|
+
const claudeMd = path36.join(kitInfo.path, "CLAUDE.md");
|
|
28850
|
+
if (fs36.existsSync(claudeMd)) {
|
|
29060
28851
|
files.set("CLAUDE.md", claudeMd);
|
|
29061
28852
|
}
|
|
29062
28853
|
for (const [component, reconciliation] of Object.entries(
|
|
@@ -29066,15 +28857,15 @@ function collectAllFiles(kitInfo) {
|
|
|
29066
28857
|
const missingSet = new Set(reconciliation.missing);
|
|
29067
28858
|
for (const entry of reconciliation.declared) {
|
|
29068
28859
|
if (missingSet.has(entry)) continue;
|
|
29069
|
-
const relPath = isSkills ?
|
|
29070
|
-
files.set(relPath,
|
|
28860
|
+
const relPath = isSkills ? path36.join(component, entry) : path36.join(component, `${entry}.md`);
|
|
28861
|
+
files.set(relPath, path36.join(kitInfo.path, relPath));
|
|
29071
28862
|
}
|
|
29072
28863
|
}
|
|
29073
28864
|
return files;
|
|
29074
28865
|
}
|
|
29075
28866
|
function isSymlink2(p) {
|
|
29076
28867
|
try {
|
|
29077
|
-
return
|
|
28868
|
+
return fs36.lstatSync(p).isSymbolicLink();
|
|
29078
28869
|
} catch {
|
|
29079
28870
|
return false;
|
|
29080
28871
|
}
|
|
@@ -29119,14 +28910,14 @@ async function runKitUpdateCommand(options, logger) {
|
|
|
29119
28910
|
}
|
|
29120
28911
|
|
|
29121
28912
|
// src/commands/list.ts
|
|
29122
|
-
import
|
|
28913
|
+
import path37 from "path";
|
|
29123
28914
|
function runListCommand(options, logger) {
|
|
29124
28915
|
let searchPaths = [];
|
|
29125
|
-
let directKitPath = options.kitPath ?
|
|
28916
|
+
let directKitPath = options.kitPath ? path37.resolve(options.kitPath) : void 0;
|
|
29126
28917
|
try {
|
|
29127
28918
|
const { config, configDir } = resolveConfig(options.config);
|
|
29128
28919
|
searchPaths = config.kitSearchPaths ?? [
|
|
29129
|
-
|
|
28920
|
+
path37.join(configDir, "operating-kits")
|
|
29130
28921
|
];
|
|
29131
28922
|
directKitPath = directKitPath ?? config.kitPath;
|
|
29132
28923
|
} catch (err) {
|
|
@@ -29201,7 +28992,7 @@ function withDirectKit(kits, directKitPath) {
|
|
|
29201
28992
|
return kits;
|
|
29202
28993
|
}
|
|
29203
28994
|
const directKit = loadKit(directKitPath);
|
|
29204
|
-
if (kits.some((kit) =>
|
|
28995
|
+
if (kits.some((kit) => path37.resolve(kit.path) === directKit.path)) {
|
|
29205
28996
|
return kits;
|
|
29206
28997
|
}
|
|
29207
28998
|
return [...kits, directKit];
|
|
@@ -29209,12 +29000,12 @@ function withDirectKit(kits, directKitPath) {
|
|
|
29209
29000
|
|
|
29210
29001
|
// src/commands/probe.ts
|
|
29211
29002
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
29212
|
-
import
|
|
29213
|
-
import
|
|
29003
|
+
import fs37 from "fs";
|
|
29004
|
+
import path38 from "path";
|
|
29214
29005
|
function runProbeCommand(options, logger) {
|
|
29215
29006
|
const { config, configDir, sourceRoot } = resolveRuntime(options, import.meta.url);
|
|
29216
29007
|
const platformPaths = readYamlObject(
|
|
29217
|
-
|
|
29008
|
+
path38.join(
|
|
29218
29009
|
resolveConfiguredPath(config.mappings, configDir, sourceRoot, "mappings"),
|
|
29219
29010
|
"platform-paths.yaml"
|
|
29220
29011
|
)
|
|
@@ -29248,12 +29039,12 @@ function toProbeRow(target, key, rawPath) {
|
|
|
29248
29039
|
const resolved = resolveTargetPath(rawPath);
|
|
29249
29040
|
let accessible = false;
|
|
29250
29041
|
try {
|
|
29251
|
-
|
|
29042
|
+
fs37.accessSync(resolved);
|
|
29252
29043
|
accessible = true;
|
|
29253
29044
|
} catch {
|
|
29254
29045
|
accessible = false;
|
|
29255
29046
|
}
|
|
29256
|
-
return { target, key, path: resolved, exists:
|
|
29047
|
+
return { target, key, path: resolved, exists: fs37.existsSync(resolved), accessible };
|
|
29257
29048
|
}
|
|
29258
29049
|
function codexRuntimeProbeRows() {
|
|
29259
29050
|
const rows = commandProbeRows("codex", "binary", process.platform === "win32" ? "where.exe" : "which", ["codex"]);
|
|
@@ -29264,7 +29055,7 @@ function codexRuntimeProbeRows() {
|
|
|
29264
29055
|
["binary_snap", "/snap/bin/codex"],
|
|
29265
29056
|
["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
|
|
29266
29057
|
]) {
|
|
29267
|
-
if (
|
|
29058
|
+
if (fs37.existsSync(candidatePath)) {
|
|
29268
29059
|
rows.push(toProbeRow("codex", key, candidatePath));
|
|
29269
29060
|
}
|
|
29270
29061
|
}
|
|
@@ -29280,8 +29071,8 @@ function commandProbeRows(target, key, command, args) {
|
|
|
29280
29071
|
|
|
29281
29072
|
// src/commands/status.ts
|
|
29282
29073
|
import crypto10 from "crypto";
|
|
29283
|
-
import
|
|
29284
|
-
import
|
|
29074
|
+
import fs38 from "fs";
|
|
29075
|
+
import path39 from "path";
|
|
29285
29076
|
function runStatusCommand(options, logger) {
|
|
29286
29077
|
const { config, configDir, sourceRoot } = resolveRuntime(
|
|
29287
29078
|
options,
|
|
@@ -29360,21 +29151,21 @@ function classifyCodexFiles(config, sourceRoot, configDir) {
|
|
|
29360
29151
|
rules: paths.rules
|
|
29361
29152
|
};
|
|
29362
29153
|
const rules = compileRules(
|
|
29363
|
-
|
|
29154
|
+
path39.join(sourceRoot, config.source.rules),
|
|
29364
29155
|
"codex",
|
|
29365
29156
|
mappings,
|
|
29366
29157
|
createLossReport()
|
|
29367
29158
|
);
|
|
29368
|
-
const instructionsSource =
|
|
29159
|
+
const instructionsSource = fs38.readFileSync(path39.join(sourceRoot, config.source.instructions), "utf8").trim();
|
|
29369
29160
|
const composedInstructions = `${instructionsSource}
|
|
29370
29161
|
|
|
29371
29162
|
--- tangyr managed rules ---
|
|
29372
29163
|
${rules.agentsAppendix}`.trim();
|
|
29373
29164
|
const agentFiles = ts(
|
|
29374
|
-
|
|
29165
|
+
path39.join(sourceRoot, config.source.agents, "*.md")
|
|
29375
29166
|
).sort();
|
|
29376
|
-
const hooksSource =
|
|
29377
|
-
const mcpSource =
|
|
29167
|
+
const hooksSource = path39.join(sourceRoot, config.source.hooks, "hooks.json");
|
|
29168
|
+
const mcpSource = path39.join(sourceRoot, config.source.mcp);
|
|
29378
29169
|
const ruleRows = rules.dotRulesFiles.length === 0 ? [
|
|
29379
29170
|
{
|
|
29380
29171
|
component: "rules",
|
|
@@ -29385,7 +29176,7 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29385
29176
|
] : rules.dotRulesFiles.map(
|
|
29386
29177
|
(ruleFile) => classifyCompiledFile(
|
|
29387
29178
|
`rules/${ruleFile.name}`,
|
|
29388
|
-
|
|
29179
|
+
path39.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
|
|
29389
29180
|
"codex",
|
|
29390
29181
|
void 0,
|
|
29391
29182
|
config,
|
|
@@ -29403,10 +29194,10 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29403
29194
|
),
|
|
29404
29195
|
...agentFiles.map(
|
|
29405
29196
|
(agentFile) => classifyCompiledFile(
|
|
29406
|
-
`agents/${
|
|
29407
|
-
|
|
29197
|
+
`agents/${path39.basename(agentFile, ".md")}`,
|
|
29198
|
+
path39.join(
|
|
29408
29199
|
resolveTargetPath(codexPaths.agents),
|
|
29409
|
-
`${
|
|
29200
|
+
`${path39.basename(agentFile, ".md")}.toml`
|
|
29410
29201
|
),
|
|
29411
29202
|
"codex",
|
|
29412
29203
|
computeSourceHash(agentFile),
|
|
@@ -29430,11 +29221,11 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29430
29221
|
config,
|
|
29431
29222
|
sourceRoot
|
|
29432
29223
|
),
|
|
29433
|
-
|
|
29224
|
+
fs38.existsSync(hooksSource) ? classifyCodexHooksFile(resolveTargetPath(codexPaths.hooksSharedFile)) : notConfiguredRow(
|
|
29434
29225
|
"hooks",
|
|
29435
29226
|
resolveTargetPath(codexPaths.hooksSharedFile)
|
|
29436
29227
|
),
|
|
29437
|
-
|
|
29228
|
+
fs38.existsSync(mcpSource) ? classifyCompiledFile(
|
|
29438
29229
|
"mcp",
|
|
29439
29230
|
resolveTargetPath(codexPaths.mcpSharedFile),
|
|
29440
29231
|
"codex",
|
|
@@ -29454,7 +29245,7 @@ function classifyCodexHooksFile(filePath) {
|
|
|
29454
29245
|
conformant: true
|
|
29455
29246
|
};
|
|
29456
29247
|
}
|
|
29457
|
-
if (!
|
|
29248
|
+
if (!fs38.existsSync(filePath)) {
|
|
29458
29249
|
return {
|
|
29459
29250
|
component: "hooks",
|
|
29460
29251
|
className: "missing",
|
|
@@ -29486,20 +29277,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29486
29277
|
mcpSharedFile: paths.mcp_shared_file
|
|
29487
29278
|
};
|
|
29488
29279
|
const agentFiles = ts(
|
|
29489
|
-
|
|
29280
|
+
path39.join(sourceRoot, config.source.agents, "*.md")
|
|
29490
29281
|
).sort();
|
|
29491
29282
|
const commandFiles = ts(
|
|
29492
|
-
|
|
29283
|
+
path39.join(sourceRoot, config.source.commands, "*.md")
|
|
29493
29284
|
).sort();
|
|
29494
|
-
const hooksSource =
|
|
29495
|
-
const mcpSource =
|
|
29285
|
+
const hooksSource = path39.join(sourceRoot, config.source.hooks, "hooks.json");
|
|
29286
|
+
const mcpSource = path39.join(sourceRoot, config.source.mcp);
|
|
29496
29287
|
return [
|
|
29497
29288
|
...agentFiles.map(
|
|
29498
29289
|
(agentFile) => classifyCompiledFile(
|
|
29499
|
-
`agents/${
|
|
29500
|
-
|
|
29290
|
+
`agents/${path39.basename(agentFile, ".md")}`,
|
|
29291
|
+
path39.join(
|
|
29501
29292
|
resolveTargetPath(copilotPaths.agents),
|
|
29502
|
-
`${
|
|
29293
|
+
`${path39.basename(agentFile, ".md")}.agent.md`
|
|
29503
29294
|
),
|
|
29504
29295
|
"copilot",
|
|
29505
29296
|
computeSourceHash(agentFile),
|
|
@@ -29516,10 +29307,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29516
29307
|
),
|
|
29517
29308
|
...commandFiles.map(
|
|
29518
29309
|
(commandFile) => classifyCompiledFile(
|
|
29519
|
-
`commands/${
|
|
29520
|
-
|
|
29310
|
+
`commands/${path39.basename(commandFile, ".md")}`,
|
|
29311
|
+
path39.join(
|
|
29521
29312
|
resolveTargetPath(copilotPaths.prompts),
|
|
29522
|
-
`${
|
|
29313
|
+
`${path39.basename(commandFile, ".md")}.prompt.md`
|
|
29523
29314
|
),
|
|
29524
29315
|
"copilot",
|
|
29525
29316
|
computeSourceHash(commandFile),
|
|
@@ -29537,9 +29328,9 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29537
29328
|
config,
|
|
29538
29329
|
sourceRoot
|
|
29539
29330
|
),
|
|
29540
|
-
|
|
29331
|
+
fs38.existsSync(hooksSource) ? classifyCompiledFile(
|
|
29541
29332
|
"hooks",
|
|
29542
|
-
|
|
29333
|
+
path39.join(
|
|
29543
29334
|
resolveTargetPath(copilotPaths.hooks),
|
|
29544
29335
|
"tangyr-managed.json"
|
|
29545
29336
|
),
|
|
@@ -29549,12 +29340,12 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29549
29340
|
sourceRoot
|
|
29550
29341
|
) : notConfiguredRow(
|
|
29551
29342
|
"hooks",
|
|
29552
|
-
|
|
29343
|
+
path39.join(
|
|
29553
29344
|
resolveTargetPath(copilotPaths.hooks),
|
|
29554
29345
|
"tangyr-managed.json"
|
|
29555
29346
|
)
|
|
29556
29347
|
),
|
|
29557
|
-
|
|
29348
|
+
fs38.existsSync(mcpSource) ? classifyCompiledFile(
|
|
29558
29349
|
"mcp",
|
|
29559
29350
|
resolveTargetPath(copilotPaths.mcpSharedFile),
|
|
29560
29351
|
"copilot",
|
|
@@ -29574,7 +29365,7 @@ function notConfiguredRow(component, filePath) {
|
|
|
29574
29365
|
}
|
|
29575
29366
|
function classifyDirectArtifact(artifact, config, sourceRoot) {
|
|
29576
29367
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
29577
|
-
const sourcePath = artifact.sourceKey ?
|
|
29368
|
+
const sourcePath = artifact.sourceKey ? path39.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
|
|
29578
29369
|
if (artifactClass === "managed-symlink" && sourcePath && !isSymlinkCurrent(artifact.path, sourcePath)) {
|
|
29579
29370
|
return {
|
|
29580
29371
|
component: artifact.component,
|
|
@@ -29663,9 +29454,9 @@ function classifyClaudeSharedFiles(config, sourceRoot) {
|
|
|
29663
29454
|
classifyHooks(settingsPath),
|
|
29664
29455
|
classifySettings(
|
|
29665
29456
|
settingsPath,
|
|
29666
|
-
|
|
29457
|
+
path39.resolve(sourceRoot, config.source.settings)
|
|
29667
29458
|
),
|
|
29668
|
-
classifyMcp(claudeJsonPath,
|
|
29459
|
+
classifyMcp(claudeJsonPath, path39.resolve(sourceRoot, config.source.mcp))
|
|
29669
29460
|
];
|
|
29670
29461
|
}
|
|
29671
29462
|
function classifyHooks(filePath) {
|
|
@@ -29729,14 +29520,14 @@ function classifyMcp(filePath, sourcePath) {
|
|
|
29729
29520
|
}
|
|
29730
29521
|
function isSymlinkCurrent(linkPath, sourcePath) {
|
|
29731
29522
|
try {
|
|
29732
|
-
return
|
|
29523
|
+
return fs38.realpathSync(linkPath) === fs38.realpathSync(sourcePath);
|
|
29733
29524
|
} catch {
|
|
29734
29525
|
return false;
|
|
29735
29526
|
}
|
|
29736
29527
|
}
|
|
29737
29528
|
function isCompiledCurrent6(filePath, sourcePath) {
|
|
29738
29529
|
try {
|
|
29739
|
-
const marker = extractProvenanceMarker(
|
|
29530
|
+
const marker = extractProvenanceMarker(fs38.readFileSync(filePath, "utf8"));
|
|
29740
29531
|
return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
|
|
29741
29532
|
} catch {
|
|
29742
29533
|
return false;
|
|
@@ -29766,7 +29557,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
|
|
|
29766
29557
|
}
|
|
29767
29558
|
function readCompiledContent(filePath) {
|
|
29768
29559
|
try {
|
|
29769
|
-
return
|
|
29560
|
+
return fs38.readFileSync(filePath, "utf8");
|
|
29770
29561
|
} catch {
|
|
29771
29562
|
return null;
|
|
29772
29563
|
}
|
|
@@ -29797,8 +29588,8 @@ function hashString6(value) {
|
|
|
29797
29588
|
}
|
|
29798
29589
|
|
|
29799
29590
|
// src/commands/sync.ts
|
|
29800
|
-
import
|
|
29801
|
-
import
|
|
29591
|
+
import fs41 from "fs";
|
|
29592
|
+
import path42 from "path";
|
|
29802
29593
|
|
|
29803
29594
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
29804
29595
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -30296,8 +30087,8 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
30296
30087
|
var source_default = chalk;
|
|
30297
30088
|
|
|
30298
30089
|
// src/adapters/claude-code.ts
|
|
30299
|
-
import
|
|
30300
|
-
import
|
|
30090
|
+
import fs40 from "fs";
|
|
30091
|
+
import path41 from "path";
|
|
30301
30092
|
|
|
30302
30093
|
// src/core/shim.ts
|
|
30303
30094
|
import crypto11 from "crypto";
|
|
@@ -30314,12 +30105,12 @@ ${SHIM_BODY}`;
|
|
|
30314
30105
|
|
|
30315
30106
|
// src/compiler/hook-components.ts
|
|
30316
30107
|
var import_yaml11 = __toESM(require_dist(), 1);
|
|
30317
|
-
import
|
|
30318
|
-
import
|
|
30108
|
+
import fs39 from "fs";
|
|
30109
|
+
import path40 from "path";
|
|
30319
30110
|
function parseHookDeclaration(filePath) {
|
|
30320
30111
|
let raw;
|
|
30321
30112
|
try {
|
|
30322
|
-
raw =
|
|
30113
|
+
raw = fs39.readFileSync(filePath, "utf8");
|
|
30323
30114
|
} catch {
|
|
30324
30115
|
return null;
|
|
30325
30116
|
}
|
|
@@ -30402,9 +30193,9 @@ function synthesizeHooksJson(declarations) {
|
|
|
30402
30193
|
return { hooks };
|
|
30403
30194
|
}
|
|
30404
30195
|
function loadSourceHooks(hooksDir, hookNames) {
|
|
30405
|
-
const hooksJsonPath =
|
|
30406
|
-
if (
|
|
30407
|
-
const raw =
|
|
30196
|
+
const hooksJsonPath = path40.join(hooksDir, "hooks.json");
|
|
30197
|
+
if (fs39.existsSync(hooksJsonPath)) {
|
|
30198
|
+
const raw = fs39.readFileSync(hooksJsonPath, "utf8");
|
|
30408
30199
|
return JSON.parse(raw);
|
|
30409
30200
|
}
|
|
30410
30201
|
const declarations = loadHookDeclarations(hooksDir, hookNames);
|
|
@@ -30415,14 +30206,14 @@ function loadHookDeclarations(hooksDir, hookNames) {
|
|
|
30415
30206
|
if (hookNames && hookNames.length > 0) {
|
|
30416
30207
|
names = hookNames;
|
|
30417
30208
|
} else {
|
|
30418
|
-
if (!
|
|
30209
|
+
if (!fs39.existsSync(hooksDir) || !fs39.statSync(hooksDir).isDirectory()) {
|
|
30419
30210
|
return [];
|
|
30420
30211
|
}
|
|
30421
|
-
names =
|
|
30212
|
+
names = fs39.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
|
|
30422
30213
|
}
|
|
30423
30214
|
const declarations = [];
|
|
30424
30215
|
for (const name of names) {
|
|
30425
|
-
const filePath =
|
|
30216
|
+
const filePath = path40.join(hooksDir, `${name}.md`);
|
|
30426
30217
|
const decl = parseHookDeclaration(filePath);
|
|
30427
30218
|
if (decl) {
|
|
30428
30219
|
declarations.push(decl);
|
|
@@ -30546,7 +30337,7 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
30546
30337
|
}
|
|
30547
30338
|
if (!shouldSkipComponent6(options, "instructions") && manifest && scopePath) {
|
|
30548
30339
|
const shimPath = profile.instructions_shim;
|
|
30549
|
-
const agentsMdPath =
|
|
30340
|
+
const agentsMdPath = path41.resolve(sourceRoot, config.source.instructions);
|
|
30550
30341
|
if (!options.dryRun) {
|
|
30551
30342
|
applyClaudeCodeShimUpgrade(
|
|
30552
30343
|
shimPath,
|
|
@@ -30600,13 +30391,13 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
30600
30391
|
}
|
|
30601
30392
|
function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
|
|
30602
30393
|
if (!mappings.modelTiers.custom_provider) return;
|
|
30603
|
-
const agentsDir =
|
|
30604
|
-
if (!
|
|
30605
|
-
for (const agentFile of ts(
|
|
30394
|
+
const agentsDir = path41.join(sourceRoot, config.source.agents);
|
|
30395
|
+
if (!fs40.existsSync(agentsDir)) return;
|
|
30396
|
+
for (const agentFile of ts(path41.join(agentsDir, "*.md")).sort()) {
|
|
30606
30397
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
30607
30398
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
30608
30399
|
if (hasProvider) {
|
|
30609
|
-
const basename =
|
|
30400
|
+
const basename = path41.basename(agentFile);
|
|
30610
30401
|
addLoss(lossReport, "claude-code", "agents", {
|
|
30611
30402
|
source: `agents/${basename}`,
|
|
30612
30403
|
fields: [
|
|
@@ -30631,19 +30422,19 @@ function shouldSkipComponent6(options, component) {
|
|
|
30631
30422
|
function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath, logger) {
|
|
30632
30423
|
const expectedBodyHash = shimBodyHash();
|
|
30633
30424
|
const shimContent = buildAgentsMdShim(shimPath, agentsMdPath, "claude-code");
|
|
30634
|
-
if (!
|
|
30425
|
+
if (!fs40.existsSync(shimPath)) {
|
|
30635
30426
|
manifest.artifacts.push({
|
|
30636
|
-
relativePath:
|
|
30427
|
+
relativePath: path41.relative(scopePath, shimPath),
|
|
30637
30428
|
hash: expectedBodyHash,
|
|
30638
30429
|
origin: "tangyr-managed"
|
|
30639
30430
|
});
|
|
30640
30431
|
writeManifest(scopePath, manifest);
|
|
30641
|
-
|
|
30642
|
-
|
|
30432
|
+
fs40.mkdirSync(path41.dirname(shimPath), { recursive: true });
|
|
30433
|
+
fs40.writeFileSync(shimPath, shimContent);
|
|
30643
30434
|
logger?.verbose(`instructions-shim: wrote @AGENTS.md shim -> ${shimPath}`);
|
|
30644
30435
|
return;
|
|
30645
30436
|
}
|
|
30646
|
-
const existing =
|
|
30437
|
+
const existing = fs40.readFileSync(shimPath, "utf8");
|
|
30647
30438
|
const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
30648
30439
|
const marker = extractProvenanceMarker(firstNonEmptyLine);
|
|
30649
30440
|
if (marker !== null && marker.hash === expectedBodyHash) {
|
|
@@ -30654,21 +30445,21 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
30654
30445
|
}
|
|
30655
30446
|
backupFile(shimPath, manifest);
|
|
30656
30447
|
writeManifest(scopePath, manifest);
|
|
30657
|
-
|
|
30448
|
+
fs40.writeFileSync(shimPath, shimContent);
|
|
30658
30449
|
manifest.artifacts.push({
|
|
30659
|
-
relativePath:
|
|
30450
|
+
relativePath: path41.relative(scopePath, shimPath),
|
|
30660
30451
|
hash: expectedBodyHash,
|
|
30661
30452
|
origin: "tangyr-managed"
|
|
30662
30453
|
});
|
|
30663
30454
|
logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
|
|
30664
30455
|
}
|
|
30665
30456
|
function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
|
|
30666
|
-
const source =
|
|
30457
|
+
const source = path41.resolve(
|
|
30667
30458
|
sourceRoot,
|
|
30668
30459
|
config.source[directComponent.sourceKey]
|
|
30669
30460
|
);
|
|
30670
30461
|
const destination = directComponent.destination;
|
|
30671
|
-
if (!
|
|
30462
|
+
if (!fs40.existsSync(source)) {
|
|
30672
30463
|
return skippedMissingSource6(directComponent.component, source);
|
|
30673
30464
|
}
|
|
30674
30465
|
if (options.dryRun) {
|
|
@@ -30690,7 +30481,7 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30690
30481
|
};
|
|
30691
30482
|
}
|
|
30692
30483
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
30693
|
-
|
|
30484
|
+
fs40.unlinkSync(destination);
|
|
30694
30485
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
30695
30486
|
return {
|
|
30696
30487
|
component: directComponent.component,
|
|
@@ -30698,9 +30489,9 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30698
30489
|
path: destination
|
|
30699
30490
|
};
|
|
30700
30491
|
} else if (artifactClass === "managed-symlink") {
|
|
30701
|
-
|
|
30492
|
+
fs40.unlinkSync(destination);
|
|
30702
30493
|
}
|
|
30703
|
-
ensureDir(
|
|
30494
|
+
ensureDir(path41.dirname(destination));
|
|
30704
30495
|
createRelativeSymlink(source, destination, directComponent.type, {
|
|
30705
30496
|
logger,
|
|
30706
30497
|
provenanceMarker: directComponent.type === "file" ? formatProvenanceMarker(
|
|
@@ -30717,8 +30508,8 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30717
30508
|
};
|
|
30718
30509
|
}
|
|
30719
30510
|
function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination, manifest, scopePath) {
|
|
30720
|
-
const source =
|
|
30721
|
-
if (!
|
|
30511
|
+
const source = path41.resolve(sourceRoot, config.source.skills);
|
|
30512
|
+
if (!fs40.existsSync(source)) {
|
|
30722
30513
|
return [skippedMissingSource6("skills", source)];
|
|
30723
30514
|
}
|
|
30724
30515
|
const declaredNames = resolveKitSkillNames(sourceRoot);
|
|
@@ -30728,7 +30519,7 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30728
30519
|
if (isLegacyWholesaleSymlink) {
|
|
30729
30520
|
for (const name of foreignSkillNames(source, declaredNames)) {
|
|
30730
30521
|
logger.info(
|
|
30731
|
-
`[dry-run] skills: migrate foreign skill ${
|
|
30522
|
+
`[dry-run] skills: migrate foreign skill ${path41.join(source, name)} -> ${path41.join(destination, name)}`
|
|
30732
30523
|
);
|
|
30733
30524
|
}
|
|
30734
30525
|
logger.info(
|
|
@@ -30736,9 +30527,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30736
30527
|
);
|
|
30737
30528
|
}
|
|
30738
30529
|
for (const name of declaredNames ?? listSkillDirNames(source)) {
|
|
30739
|
-
const skillDestination =
|
|
30530
|
+
const skillDestination = path41.join(destination, name);
|
|
30740
30531
|
logger.info(
|
|
30741
|
-
`[dry-run] skills: symlink ${
|
|
30532
|
+
`[dry-run] skills: symlink ${path41.join(source, name)} -> ${skillDestination}`
|
|
30742
30533
|
);
|
|
30743
30534
|
outcomes2.push({
|
|
30744
30535
|
component: "skills",
|
|
@@ -30771,9 +30562,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30771
30562
|
return outcomes;
|
|
30772
30563
|
}
|
|
30773
30564
|
function syncSingleSkill(config, sourceRoot, options, logger, source, destination, name, manifest, scopePath) {
|
|
30774
|
-
const skillSource =
|
|
30775
|
-
const skillDestination =
|
|
30776
|
-
if (!
|
|
30565
|
+
const skillSource = path41.join(source, name);
|
|
30566
|
+
const skillDestination = path41.join(destination, name);
|
|
30567
|
+
if (!fs40.existsSync(skillSource)) {
|
|
30777
30568
|
return skippedMissingSource6("skills", skillSource);
|
|
30778
30569
|
}
|
|
30779
30570
|
const artifactClass = classifyArtifact(skillDestination, config, sourceRoot);
|
|
@@ -30785,7 +30576,7 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
|
|
|
30785
30576
|
};
|
|
30786
30577
|
}
|
|
30787
30578
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(skillDestination, /* @__PURE__ */ new Set([skillDestination]), config)) {
|
|
30788
|
-
|
|
30579
|
+
fs40.unlinkSync(skillDestination);
|
|
30789
30580
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(
|
|
30790
30581
|
skillDestination,
|
|
30791
30582
|
config,
|
|
@@ -30796,25 +30587,25 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
|
|
|
30796
30587
|
)) {
|
|
30797
30588
|
return { component: "skills", status: "conflict", path: skillDestination };
|
|
30798
30589
|
} else if (artifactClass === "managed-symlink") {
|
|
30799
|
-
|
|
30590
|
+
fs40.unlinkSync(skillDestination);
|
|
30800
30591
|
}
|
|
30801
30592
|
createRelativeSymlink(skillSource, skillDestination, "dir");
|
|
30802
30593
|
return { component: "skills", status: "success", path: skillDestination };
|
|
30803
30594
|
}
|
|
30804
30595
|
function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger) {
|
|
30805
30596
|
const foreignNames = foreignSkillNames(source, declaredNames);
|
|
30806
|
-
|
|
30597
|
+
fs40.unlinkSync(destination);
|
|
30807
30598
|
ensureDir(destination);
|
|
30808
30599
|
for (const name of foreignNames) {
|
|
30809
|
-
const from =
|
|
30810
|
-
const to =
|
|
30811
|
-
if (
|
|
30600
|
+
const from = path41.join(source, name);
|
|
30601
|
+
const to = path41.join(destination, name);
|
|
30602
|
+
if (fs40.existsSync(to)) {
|
|
30812
30603
|
logger.warn(
|
|
30813
30604
|
`skills migration: ${to} already exists \u2014 skipping move of ${from} to avoid overwrite`
|
|
30814
30605
|
);
|
|
30815
30606
|
continue;
|
|
30816
30607
|
}
|
|
30817
|
-
|
|
30608
|
+
fs40.renameSync(from, to);
|
|
30818
30609
|
logger.info(`skills migration: moved ${from} -> ${to}`);
|
|
30819
30610
|
}
|
|
30820
30611
|
}
|
|
@@ -30826,21 +30617,21 @@ function foreignSkillNames(source, declaredNames) {
|
|
|
30826
30617
|
return listSkillDirNames(source).filter((name) => !declaredSet.has(name));
|
|
30827
30618
|
}
|
|
30828
30619
|
function listSkillDirNames(dir) {
|
|
30829
|
-
if (!
|
|
30620
|
+
if (!fs40.existsSync(dir)) {
|
|
30830
30621
|
return [];
|
|
30831
30622
|
}
|
|
30832
|
-
return
|
|
30623
|
+
return fs40.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
30833
30624
|
}
|
|
30834
30625
|
function isSymlinkPath(filePath) {
|
|
30835
30626
|
try {
|
|
30836
|
-
return
|
|
30627
|
+
return fs40.lstatSync(filePath).isSymbolicLink();
|
|
30837
30628
|
} catch {
|
|
30838
30629
|
return false;
|
|
30839
30630
|
}
|
|
30840
30631
|
}
|
|
30841
30632
|
function syncHookScriptsBridge(config, sourceRoot, options, logger, destination, manifest, scopePath) {
|
|
30842
|
-
const source =
|
|
30843
|
-
if (!
|
|
30633
|
+
const source = path41.resolve(sourceRoot, config.source.hooks);
|
|
30634
|
+
if (!fs40.existsSync(source)) {
|
|
30844
30635
|
return skippedMissingSource6("hooks", source);
|
|
30845
30636
|
}
|
|
30846
30637
|
if (options.dryRun) {
|
|
@@ -30852,13 +30643,13 @@ function syncHookScriptsBridge(config, sourceRoot, options, logger, destination,
|
|
|
30852
30643
|
return { component: "hooks", status: "skipped-current", path: destination };
|
|
30853
30644
|
}
|
|
30854
30645
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
30855
|
-
|
|
30646
|
+
fs40.unlinkSync(destination);
|
|
30856
30647
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
30857
30648
|
return { component: "hooks", status: "conflict", path: destination };
|
|
30858
30649
|
} else if (artifactClass === "managed-symlink") {
|
|
30859
|
-
|
|
30650
|
+
fs40.unlinkSync(destination);
|
|
30860
30651
|
}
|
|
30861
|
-
ensureDir(
|
|
30652
|
+
ensureDir(path41.dirname(destination));
|
|
30862
30653
|
createRelativeSymlink(source, destination, "dir");
|
|
30863
30654
|
return { component: "hooks", status: "success", path: destination };
|
|
30864
30655
|
}
|
|
@@ -30881,7 +30672,7 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
|
|
|
30881
30672
|
destination,
|
|
30882
30673
|
settings,
|
|
30883
30674
|
stringifyJson3,
|
|
30884
|
-
!
|
|
30675
|
+
!fs40.existsSync(destination),
|
|
30885
30676
|
logger
|
|
30886
30677
|
);
|
|
30887
30678
|
return {
|
|
@@ -30891,8 +30682,8 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
|
|
|
30891
30682
|
};
|
|
30892
30683
|
}
|
|
30893
30684
|
function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
30894
|
-
const source =
|
|
30895
|
-
if (!
|
|
30685
|
+
const source = path41.resolve(sourceRoot, config.source.mcp);
|
|
30686
|
+
if (!fs40.existsSync(source)) {
|
|
30896
30687
|
return skippedMissingSource6("mcp", source);
|
|
30897
30688
|
}
|
|
30898
30689
|
if (options.dryRun) {
|
|
@@ -30917,7 +30708,7 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
|
30917
30708
|
destination,
|
|
30918
30709
|
hostConfig,
|
|
30919
30710
|
stringifyJson3,
|
|
30920
|
-
!
|
|
30711
|
+
!fs40.existsSync(destination),
|
|
30921
30712
|
logger
|
|
30922
30713
|
);
|
|
30923
30714
|
return {
|
|
@@ -30927,8 +30718,8 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
|
30927
30718
|
};
|
|
30928
30719
|
}
|
|
30929
30720
|
function syncSettings2(config, sourceRoot, options, logger, destination) {
|
|
30930
|
-
const source =
|
|
30931
|
-
if (!
|
|
30721
|
+
const source = path41.resolve(sourceRoot, config.source.settings);
|
|
30722
|
+
if (!fs40.existsSync(source)) {
|
|
30932
30723
|
return skippedMissingSource6("settings", source);
|
|
30933
30724
|
}
|
|
30934
30725
|
if (options.dryRun) {
|
|
@@ -30946,7 +30737,7 @@ function syncSettings2(config, sourceRoot, options, logger, destination) {
|
|
|
30946
30737
|
destination,
|
|
30947
30738
|
settings,
|
|
30948
30739
|
stringifyJson3,
|
|
30949
|
-
!
|
|
30740
|
+
!fs40.existsSync(destination),
|
|
30950
30741
|
logger
|
|
30951
30742
|
);
|
|
30952
30743
|
return {
|
|
@@ -30971,11 +30762,11 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
|
|
|
30971
30762
|
backupFile(destination, manifest);
|
|
30972
30763
|
writeManifest(scopePath, manifest);
|
|
30973
30764
|
} else {
|
|
30974
|
-
|
|
30765
|
+
fs40.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
30975
30766
|
}
|
|
30976
30767
|
return true;
|
|
30977
30768
|
}
|
|
30978
|
-
|
|
30769
|
+
fs40.rmSync(destination, { recursive: true, force: true });
|
|
30979
30770
|
return true;
|
|
30980
30771
|
}
|
|
30981
30772
|
function skippedMissingSource6(component, source) {
|
|
@@ -30987,16 +30778,16 @@ function skippedMissingSource6(component, source) {
|
|
|
30987
30778
|
}
|
|
30988
30779
|
function isSymlinkTo6(linkPath, source) {
|
|
30989
30780
|
try {
|
|
30990
|
-
return
|
|
30781
|
+
return fs40.realpathSync(linkPath) === fs40.realpathSync(source);
|
|
30991
30782
|
} catch {
|
|
30992
30783
|
return false;
|
|
30993
30784
|
}
|
|
30994
30785
|
}
|
|
30995
30786
|
function readJsonObject4(filePath) {
|
|
30996
|
-
if (!
|
|
30787
|
+
if (!fs40.existsSync(filePath)) {
|
|
30997
30788
|
return {};
|
|
30998
30789
|
}
|
|
30999
|
-
const parsed = JSON.parse(
|
|
30790
|
+
const parsed = JSON.parse(fs40.readFileSync(filePath, "utf8"));
|
|
31000
30791
|
return isRecord5(parsed) ? parsed : {};
|
|
31001
30792
|
}
|
|
31002
30793
|
function markManaged(value) {
|
|
@@ -31262,7 +31053,7 @@ function writeLossReport(filePath, report) {
|
|
|
31262
31053
|
if (!filePath) {
|
|
31263
31054
|
return;
|
|
31264
31055
|
}
|
|
31265
|
-
|
|
31056
|
+
fs41.writeFileSync(filePath, `${JSON.stringify(report, null, 2)}
|
|
31266
31057
|
`);
|
|
31267
31058
|
}
|
|
31268
31059
|
function prepareKitManifest(scope, projectRoot, kitInfo) {
|
|
@@ -31303,8 +31094,8 @@ function updateManifest(kitInfo, kitSync) {
|
|
|
31303
31094
|
writeManifest(kitSync.scopePath, kitSync.manifest);
|
|
31304
31095
|
}
|
|
31305
31096
|
function resolveKitFilePath(kitPath, relativePath) {
|
|
31306
|
-
const fullPath =
|
|
31307
|
-
return
|
|
31097
|
+
const fullPath = path42.join(kitPath, relativePath);
|
|
31098
|
+
return fs41.existsSync(fullPath) ? fullPath : null;
|
|
31308
31099
|
}
|
|
31309
31100
|
function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
|
|
31310
31101
|
if (removedSourcePaths.length === 0 || !mappings) {
|
|
@@ -31365,9 +31156,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31365
31156
|
}
|
|
31366
31157
|
if (relativePath.startsWith("agents/")) {
|
|
31367
31158
|
removeManagedCompiledArtifact2(
|
|
31368
|
-
|
|
31159
|
+
path42.join(
|
|
31369
31160
|
resolveTargetPath(paths.agents ?? ""),
|
|
31370
|
-
`${
|
|
31161
|
+
`${path42.parse(relativePath).name}.agent.md`
|
|
31371
31162
|
),
|
|
31372
31163
|
"copilot",
|
|
31373
31164
|
relativePath,
|
|
@@ -31377,9 +31168,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31377
31168
|
}
|
|
31378
31169
|
if (relativePath.startsWith("commands/")) {
|
|
31379
31170
|
removeManagedCompiledArtifact2(
|
|
31380
|
-
|
|
31171
|
+
path42.join(
|
|
31381
31172
|
resolveTargetPath(paths.prompts ?? ""),
|
|
31382
|
-
`${
|
|
31173
|
+
`${path42.parse(relativePath).name}.prompt.md`
|
|
31383
31174
|
),
|
|
31384
31175
|
"copilot",
|
|
31385
31176
|
relativePath,
|
|
@@ -31389,7 +31180,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31389
31180
|
}
|
|
31390
31181
|
if (relativePath.endsWith("hooks.json")) {
|
|
31391
31182
|
removeManagedCompiledArtifact2(
|
|
31392
|
-
|
|
31183
|
+
path42.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
31393
31184
|
"copilot",
|
|
31394
31185
|
relativePath,
|
|
31395
31186
|
logger
|
|
@@ -31419,9 +31210,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
31419
31210
|
}
|
|
31420
31211
|
if (relativePath.startsWith("agents/")) {
|
|
31421
31212
|
removeManagedCompiledArtifact2(
|
|
31422
|
-
|
|
31213
|
+
path42.join(
|
|
31423
31214
|
resolveTargetPath(paths.agents ?? ""),
|
|
31424
|
-
`${
|
|
31215
|
+
`${path42.parse(relativePath).name}.toml`
|
|
31425
31216
|
),
|
|
31426
31217
|
"codex",
|
|
31427
31218
|
relativePath,
|
|
@@ -31431,9 +31222,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
31431
31222
|
}
|
|
31432
31223
|
if (relativePath.startsWith("rules/")) {
|
|
31433
31224
|
removeManagedCompiledArtifact2(
|
|
31434
|
-
|
|
31225
|
+
path42.join(
|
|
31435
31226
|
resolveTargetPath(paths.rules ?? ""),
|
|
31436
|
-
`${
|
|
31227
|
+
`${path42.parse(relativePath).name}.rules`
|
|
31437
31228
|
),
|
|
31438
31229
|
"codex",
|
|
31439
31230
|
relativePath,
|
|
@@ -31472,9 +31263,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
31472
31263
|
}
|
|
31473
31264
|
if (relativePath.startsWith("agents/")) {
|
|
31474
31265
|
removeManagedCompiledArtifact2(
|
|
31475
|
-
|
|
31266
|
+
path42.join(
|
|
31476
31267
|
resolveTargetPath(paths.agents ?? ""),
|
|
31477
|
-
`${
|
|
31268
|
+
`${path42.parse(relativePath).name}.md`
|
|
31478
31269
|
),
|
|
31479
31270
|
"opencode",
|
|
31480
31271
|
relativePath,
|
|
@@ -31484,9 +31275,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
31484
31275
|
}
|
|
31485
31276
|
if (relativePath.startsWith("commands/")) {
|
|
31486
31277
|
removeManagedCompiledArtifact2(
|
|
31487
|
-
|
|
31278
|
+
path42.join(
|
|
31488
31279
|
resolveTargetPath(paths.commands ?? ""),
|
|
31489
|
-
`${
|
|
31280
|
+
`${path42.parse(relativePath).name}.md`
|
|
31490
31281
|
),
|
|
31491
31282
|
"opencode",
|
|
31492
31283
|
relativePath,
|
|
@@ -31518,9 +31309,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31518
31309
|
}
|
|
31519
31310
|
if (relativePath.startsWith("agents/")) {
|
|
31520
31311
|
removeManagedCompiledArtifact2(
|
|
31521
|
-
|
|
31312
|
+
path42.join(
|
|
31522
31313
|
resolveTargetPath(paths.agents ?? ""),
|
|
31523
|
-
`${
|
|
31314
|
+
`${path42.parse(relativePath).name}.md`
|
|
31524
31315
|
),
|
|
31525
31316
|
"cursor",
|
|
31526
31317
|
relativePath,
|
|
@@ -31530,9 +31321,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31530
31321
|
}
|
|
31531
31322
|
if (relativePath.startsWith("rules/")) {
|
|
31532
31323
|
removeManagedCompiledArtifact2(
|
|
31533
|
-
|
|
31324
|
+
path42.join(
|
|
31534
31325
|
resolveTargetPath(paths.rules ?? ""),
|
|
31535
|
-
`${
|
|
31326
|
+
`${path42.parse(relativePath).name}.mdc`
|
|
31536
31327
|
),
|
|
31537
31328
|
"cursor",
|
|
31538
31329
|
relativePath,
|
|
@@ -31542,9 +31333,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31542
31333
|
}
|
|
31543
31334
|
if (relativePath.startsWith("commands/")) {
|
|
31544
31335
|
removeManagedCompiledArtifact2(
|
|
31545
|
-
|
|
31336
|
+
path42.join(
|
|
31546
31337
|
resolveTargetPath(paths.skills ?? ""),
|
|
31547
|
-
|
|
31338
|
+
path42.parse(relativePath).name,
|
|
31548
31339
|
"SKILL.md"
|
|
31549
31340
|
),
|
|
31550
31341
|
"cursor",
|
|
@@ -31588,9 +31379,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31588
31379
|
}
|
|
31589
31380
|
if (relativePath.startsWith("rules/")) {
|
|
31590
31381
|
removeManagedCompiledArtifact2(
|
|
31591
|
-
|
|
31382
|
+
path42.join(
|
|
31592
31383
|
resolveTargetPath(paths.rules ?? ""),
|
|
31593
|
-
`${
|
|
31384
|
+
`${path42.parse(relativePath).name}.md`
|
|
31594
31385
|
),
|
|
31595
31386
|
"cline",
|
|
31596
31387
|
relativePath,
|
|
@@ -31600,9 +31391,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31600
31391
|
}
|
|
31601
31392
|
if (relativePath.startsWith("commands/")) {
|
|
31602
31393
|
removeManagedCompiledArtifact2(
|
|
31603
|
-
|
|
31394
|
+
path42.join(
|
|
31604
31395
|
resolveTargetPath(paths.workflows ?? ""),
|
|
31605
|
-
|
|
31396
|
+
path42.basename(relativePath)
|
|
31606
31397
|
),
|
|
31607
31398
|
"cline",
|
|
31608
31399
|
relativePath,
|
|
@@ -31620,17 +31411,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31620
31411
|
}
|
|
31621
31412
|
}
|
|
31622
31413
|
function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
|
|
31623
|
-
if (!
|
|
31414
|
+
if (!fs41.existsSync(artifactPath)) {
|
|
31624
31415
|
return;
|
|
31625
31416
|
}
|
|
31626
|
-
if (!
|
|
31417
|
+
if (!fs41.statSync(artifactPath).isFile()) {
|
|
31627
31418
|
return;
|
|
31628
31419
|
}
|
|
31629
|
-
const marker = extractProvenanceMarker(
|
|
31420
|
+
const marker = extractProvenanceMarker(fs41.readFileSync(artifactPath, "utf8"));
|
|
31630
31421
|
if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
|
|
31631
31422
|
return;
|
|
31632
31423
|
}
|
|
31633
|
-
|
|
31424
|
+
fs41.rmSync(artifactPath, { force: true });
|
|
31634
31425
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31635
31426
|
}
|
|
31636
31427
|
function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
@@ -31661,10 +31452,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
|
|
|
31661
31452
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31662
31453
|
}
|
|
31663
31454
|
function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
31664
|
-
if (!
|
|
31455
|
+
if (!fs41.existsSync(artifactPath)) {
|
|
31665
31456
|
return;
|
|
31666
31457
|
}
|
|
31667
|
-
const content =
|
|
31458
|
+
const content = fs41.readFileSync(artifactPath, "utf8");
|
|
31668
31459
|
const startMarker = "# tangyr: managed mcp start";
|
|
31669
31460
|
const endMarker = "# tangyr: managed mcp end";
|
|
31670
31461
|
const startIndex = content.indexOf(startMarker);
|
|
@@ -31681,19 +31472,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
|
31681
31472
|
const after = content.slice(endIndex + endMarker.length).trimStart();
|
|
31682
31473
|
const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
|
|
31683
31474
|
if (cleaned.length === 0) {
|
|
31684
|
-
|
|
31475
|
+
fs41.rmSync(artifactPath, { force: true });
|
|
31685
31476
|
} else {
|
|
31686
|
-
|
|
31477
|
+
fs41.writeFileSync(artifactPath, `${cleaned}
|
|
31687
31478
|
`);
|
|
31688
31479
|
}
|
|
31689
31480
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31690
31481
|
}
|
|
31691
31482
|
function readJsonObject5(filePath) {
|
|
31692
|
-
if (!
|
|
31483
|
+
if (!fs41.existsSync(filePath)) {
|
|
31693
31484
|
return null;
|
|
31694
31485
|
}
|
|
31695
31486
|
try {
|
|
31696
|
-
const parsed = JSON.parse(
|
|
31487
|
+
const parsed = JSON.parse(fs41.readFileSync(filePath, "utf8"));
|
|
31697
31488
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
31698
31489
|
} catch {
|
|
31699
31490
|
return null;
|
|
@@ -31707,10 +31498,10 @@ function readJsonMetadata(value) {
|
|
|
31707
31498
|
}
|
|
31708
31499
|
function writeJsonOrRemove2(filePath, parsed) {
|
|
31709
31500
|
if (isEmptyJsonValue2(parsed)) {
|
|
31710
|
-
|
|
31501
|
+
fs41.rmSync(filePath, { force: true });
|
|
31711
31502
|
return;
|
|
31712
31503
|
}
|
|
31713
|
-
|
|
31504
|
+
fs41.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
31714
31505
|
`);
|
|
31715
31506
|
}
|
|
31716
31507
|
function isEmptyJsonValue2(value) {
|
|
@@ -31770,8 +31561,8 @@ function removeManagedHookEntries(value, expectedSource) {
|
|
|
31770
31561
|
}
|
|
31771
31562
|
|
|
31772
31563
|
// src/commands/validate.ts
|
|
31773
|
-
import
|
|
31774
|
-
import
|
|
31564
|
+
import fs42 from "fs";
|
|
31565
|
+
import path43 from "path";
|
|
31775
31566
|
var SUPPORTED_KIT_FORMATS2 = [1];
|
|
31776
31567
|
var SUPPORTED_DISCIPLINE_VERSIONS = [
|
|
31777
31568
|
"0.14.0",
|
|
@@ -31855,8 +31646,8 @@ function checkKitFormatSupported(kit) {
|
|
|
31855
31646
|
}
|
|
31856
31647
|
function checkEntrypointExists(kit) {
|
|
31857
31648
|
const entrypoint = "CLAUDE.md";
|
|
31858
|
-
const entrypointPath =
|
|
31859
|
-
if (!
|
|
31649
|
+
const entrypointPath = path43.join(kit.path, entrypoint);
|
|
31650
|
+
if (!fs42.existsSync(entrypointPath)) {
|
|
31860
31651
|
return {
|
|
31861
31652
|
code: "entrypoint-missing",
|
|
31862
31653
|
location: entrypoint,
|
|
@@ -31913,9 +31704,9 @@ function checkComponentFrontmatter(kit) {
|
|
|
31913
31704
|
const missingSet = new Set(kit.components[cat].missing);
|
|
31914
31705
|
for (const name of kit.components[cat].declared) {
|
|
31915
31706
|
if (missingSet.has(name)) continue;
|
|
31916
|
-
const filePath = cat === "skills" ?
|
|
31917
|
-
if (!
|
|
31918
|
-
const relPath =
|
|
31707
|
+
const filePath = cat === "skills" ? path43.join(kit.path, cat, name, "SKILL.md") : path43.join(kit.path, cat, `${name}.md`);
|
|
31708
|
+
if (!fs42.existsSync(filePath)) continue;
|
|
31709
|
+
const relPath = path43.relative(kit.path, filePath);
|
|
31919
31710
|
try {
|
|
31920
31711
|
const { data } = parseMarkdownFrontmatter(filePath);
|
|
31921
31712
|
for (const field of requiredFields) {
|
|
@@ -31940,10 +31731,10 @@ function checkComponentFrontmatter(kit) {
|
|
|
31940
31731
|
}
|
|
31941
31732
|
function checkReservedRootNames(kit) {
|
|
31942
31733
|
const violations = [];
|
|
31943
|
-
if (!
|
|
31734
|
+
if (!fs42.existsSync(kit.path) || !fs42.statSync(kit.path).isDirectory()) {
|
|
31944
31735
|
return violations;
|
|
31945
31736
|
}
|
|
31946
|
-
const entries =
|
|
31737
|
+
const entries = fs42.readdirSync(kit.path, { withFileTypes: true });
|
|
31947
31738
|
for (const entry of entries) {
|
|
31948
31739
|
if (RESERVED_ROOT_NAMES.includes(entry.name)) {
|
|
31949
31740
|
violations.push({
|
|
@@ -31960,8 +31751,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31960
31751
|
const missingSet = new Set(kit.components.commands.missing);
|
|
31961
31752
|
for (const name of kit.components.commands.declared) {
|
|
31962
31753
|
if (missingSet.has(name)) continue;
|
|
31963
|
-
const filePath =
|
|
31964
|
-
if (!
|
|
31754
|
+
const filePath = path43.join(kit.path, "commands", `${name}.md`);
|
|
31755
|
+
if (!fs42.existsSync(filePath)) continue;
|
|
31965
31756
|
let data;
|
|
31966
31757
|
try {
|
|
31967
31758
|
({ data } = parseMarkdownFrontmatter(filePath));
|
|
@@ -31974,7 +31765,7 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31974
31765
|
if (!barred) {
|
|
31975
31766
|
violations.push({
|
|
31976
31767
|
code: "command-human-only-model-invocable",
|
|
31977
|
-
location:
|
|
31768
|
+
location: path43.relative(kit.path, filePath),
|
|
31978
31769
|
message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
|
|
31979
31770
|
});
|
|
31980
31771
|
}
|
|
@@ -31983,8 +31774,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31983
31774
|
}
|
|
31984
31775
|
|
|
31985
31776
|
// src/commands/verify.ts
|
|
31986
|
-
import
|
|
31987
|
-
import
|
|
31777
|
+
import fs43 from "fs";
|
|
31778
|
+
import path44 from "path";
|
|
31988
31779
|
function runVerifyCommand(options, logger) {
|
|
31989
31780
|
const { config, configDir, sourceRoot, kitInfo } = resolveRuntime(
|
|
31990
31781
|
options,
|
|
@@ -32075,8 +31866,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
|
|
|
32075
31866
|
if (!slotPath) {
|
|
32076
31867
|
continue;
|
|
32077
31868
|
}
|
|
32078
|
-
const fullPath = subPath ?
|
|
32079
|
-
if (!
|
|
31869
|
+
const fullPath = subPath ? path44.join(slotPath, subPath) : slotPath;
|
|
31870
|
+
if (!fs43.existsSync(fullPath)) {
|
|
32080
31871
|
failures.push(
|
|
32081
31872
|
`claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
|
|
32082
31873
|
);
|