@alessandroraffa/tangyr 0.14.0 → 0.15.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 +1012 -577
- 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 path46 = __require("path");
|
|
1376
|
+
var fs45 = __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 (fs45.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 = path46.resolve(baseDir, baseName);
|
|
2389
|
+
if (fs45.existsSync(localBin)) return localBin;
|
|
2390
|
+
if (sourceExt.includes(path46.extname(baseName))) return void 0;
|
|
2391
2391
|
const foundExt = sourceExt.find(
|
|
2392
|
-
(ext) =>
|
|
2392
|
+
(ext) => fs45.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 = fs45.realpathSync(this._scriptPath);
|
|
2405
2405
|
} catch {
|
|
2406
2406
|
resolvedScriptPath = this._scriptPath;
|
|
2407
2407
|
}
|
|
2408
|
-
executableDir =
|
|
2409
|
-
|
|
2408
|
+
executableDir = path46.resolve(
|
|
2409
|
+
path46.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 = path46.basename(
|
|
2417
2417
|
this._scriptPath,
|
|
2418
|
-
|
|
2418
|
+
path46.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(path46.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 = path46.basename(filename, path46.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(path47) {
|
|
3359
|
+
if (path47 === void 0) return this._executableDir;
|
|
3360
|
+
this._executableDir = path47;
|
|
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, path46) {
|
|
3717
|
+
const ctrl = callVisitor(key, node, visitor, path46);
|
|
3718
3718
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
3719
|
-
replaceNode(key,
|
|
3720
|
-
return visit_(key, ctrl, visitor,
|
|
3719
|
+
replaceNode(key, path46, ctrl);
|
|
3720
|
+
return visit_(key, ctrl, visitor, path46);
|
|
3721
3721
|
}
|
|
3722
3722
|
if (typeof ctrl !== "symbol") {
|
|
3723
3723
|
if (identity.isCollection(node)) {
|
|
3724
|
-
|
|
3724
|
+
path46 = Object.freeze(path46.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, path46);
|
|
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
|
+
path46 = Object.freeze(path46.concat(node));
|
|
3738
|
+
const ck = visit_("key", node.key, visitor, path46);
|
|
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, path46);
|
|
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, path46) {
|
|
3765
|
+
const ctrl = await callVisitor(key, node, visitor, path46);
|
|
3766
3766
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
3767
|
-
replaceNode(key,
|
|
3768
|
-
return visitAsync_(key, ctrl, visitor,
|
|
3767
|
+
replaceNode(key, path46, ctrl);
|
|
3768
|
+
return visitAsync_(key, ctrl, visitor, path46);
|
|
3769
3769
|
}
|
|
3770
3770
|
if (typeof ctrl !== "symbol") {
|
|
3771
3771
|
if (identity.isCollection(node)) {
|
|
3772
|
-
|
|
3772
|
+
path46 = Object.freeze(path46.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, path46);
|
|
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
|
+
path46 = Object.freeze(path46.concat(node));
|
|
3786
|
+
const ck = await visitAsync_("key", node.key, visitor, path46);
|
|
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, path46);
|
|
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, path46) {
|
|
3819
3819
|
if (typeof visitor === "function")
|
|
3820
|
-
return visitor(key, node,
|
|
3820
|
+
return visitor(key, node, path46);
|
|
3821
3821
|
if (identity.isMap(node))
|
|
3822
|
-
return visitor.Map?.(key, node,
|
|
3822
|
+
return visitor.Map?.(key, node, path46);
|
|
3823
3823
|
if (identity.isSeq(node))
|
|
3824
|
-
return visitor.Seq?.(key, node,
|
|
3824
|
+
return visitor.Seq?.(key, node, path46);
|
|
3825
3825
|
if (identity.isPair(node))
|
|
3826
|
-
return visitor.Pair?.(key, node,
|
|
3826
|
+
return visitor.Pair?.(key, node, path46);
|
|
3827
3827
|
if (identity.isScalar(node))
|
|
3828
|
-
return visitor.Scalar?.(key, node,
|
|
3828
|
+
return visitor.Scalar?.(key, node, path46);
|
|
3829
3829
|
if (identity.isAlias(node))
|
|
3830
|
-
return visitor.Alias?.(key, node,
|
|
3830
|
+
return visitor.Alias?.(key, node, path46);
|
|
3831
3831
|
return void 0;
|
|
3832
3832
|
}
|
|
3833
|
-
function replaceNode(key,
|
|
3834
|
-
const parent =
|
|
3833
|
+
function replaceNode(key, path46, node) {
|
|
3834
|
+
const parent = path46[path46.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, path46, value) {
|
|
4443
4443
|
let v2 = value;
|
|
4444
|
-
for (let i =
|
|
4445
|
-
const k2 =
|
|
4444
|
+
for (let i = path46.length - 1; i >= 0; --i) {
|
|
4445
|
+
const k2 = path46[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 = (path46) => path46 == null || typeof path46 === "object" && !!path46[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(path46, value) {
|
|
4495
|
+
if (isEmptyPath(path46))
|
|
4496
4496
|
this.add(value);
|
|
4497
4497
|
else {
|
|
4498
|
-
const [key, ...rest] =
|
|
4498
|
+
const [key, ...rest] = path46;
|
|
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(path46) {
|
|
4513
|
+
const [key, ...rest] = path46;
|
|
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(path46, keepScalar) {
|
|
4528
|
+
const [key, ...rest] = path46;
|
|
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(path46) {
|
|
4547
|
+
const [key, ...rest] = path46;
|
|
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(path46, value) {
|
|
4558
|
+
const [key, ...rest] = path46;
|
|
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(path46, value) {
|
|
7071
7071
|
if (assertCollection(this.contents))
|
|
7072
|
-
this.contents.addIn(
|
|
7072
|
+
this.contents.addIn(path46, 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(path46) {
|
|
7148
|
+
if (Collection.isEmptyPath(path46)) {
|
|
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(path46) : 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(path46, keepScalar) {
|
|
7170
|
+
if (Collection.isEmptyPath(path46))
|
|
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(path46, 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(path46) {
|
|
7184
|
+
if (Collection.isEmptyPath(path46))
|
|
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(path46) : 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(path46, value) {
|
|
7204
|
+
if (Collection.isEmptyPath(path46)) {
|
|
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(path46), value);
|
|
7208
7208
|
} else if (assertCollection(this.contents)) {
|
|
7209
|
-
this.contents.setIn(
|
|
7209
|
+
this.contents.setIn(path46, 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, path46) => {
|
|
9167
9167
|
let item = cst;
|
|
9168
|
-
for (const [field, index] of
|
|
9168
|
+
for (const [field, index] of path46) {
|
|
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, path46) => {
|
|
9178
|
+
const parent = visit.itemAtPath(cst, path46.slice(0, -1));
|
|
9179
|
+
const field = path46[path46.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(path46, item, visitor) {
|
|
9186
|
+
let ctrl = visitor(item, path46);
|
|
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(path46.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, path46);
|
|
9205
9205
|
}
|
|
9206
9206
|
}
|
|
9207
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
9207
|
+
return typeof ctrl === "function" ? ctrl(item, path46) : 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 fs45 = this.flowScalar(this.type);
|
|
10493
10493
|
if (atNextItem || it2.value) {
|
|
10494
|
-
map.items.push({ start, key:
|
|
10494
|
+
map.items.push({ start, key: fs45, sep: [] });
|
|
10495
10495
|
this.onKeyLine = true;
|
|
10496
10496
|
} else if (it2.sep) {
|
|
10497
|
-
this.stack.push(
|
|
10497
|
+
this.stack.push(fs45);
|
|
10498
10498
|
} else {
|
|
10499
|
-
Object.assign(it2, { key:
|
|
10499
|
+
Object.assign(it2, { key: fs45, 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 fs45 = this.flowScalar(this.type);
|
|
10628
10628
|
if (!it2 || it2.value)
|
|
10629
|
-
fc.items.push({ start: [], key:
|
|
10629
|
+
fc.items.push({ start: [], key: fs45, sep: [] });
|
|
10630
10630
|
else if (it2.sep)
|
|
10631
|
-
this.stack.push(
|
|
10631
|
+
this.stack.push(fs45);
|
|
10632
10632
|
else
|
|
10633
|
-
Object.assign(it2, { key:
|
|
10633
|
+
Object.assign(it2, { key: fs45, sep: [] });
|
|
10634
10634
|
return;
|
|
10635
10635
|
}
|
|
10636
10636
|
case "flow-map-end":
|
|
@@ -15090,6 +15090,13 @@ function normalizeSource(declared) {
|
|
|
15090
15090
|
"Configuration declares source.type: remote but no source.url. Set source.url to the https endpoint of your kit origin."
|
|
15091
15091
|
);
|
|
15092
15092
|
}
|
|
15093
|
+
if (source.channel !== void 0) {
|
|
15094
|
+
if (!/^[a-z0-9][a-z0-9-]{0,31}$/u.test(source.channel)) {
|
|
15095
|
+
throw new Error(
|
|
15096
|
+
`Configuration declares source.channel "${source.channel}", which must be lowercase alphanumeric with hyphens, 1-32 characters.`
|
|
15097
|
+
);
|
|
15098
|
+
}
|
|
15099
|
+
}
|
|
15093
15100
|
return source;
|
|
15094
15101
|
}
|
|
15095
15102
|
function findConfigPath(explicitPath) {
|
|
@@ -17577,6 +17584,24 @@ import path15 from "path";
|
|
|
17577
17584
|
|
|
17578
17585
|
// src/core/kit-reference.ts
|
|
17579
17586
|
var BARE_URL = /^https?:\/\//u;
|
|
17587
|
+
function parseKitSelector(raw) {
|
|
17588
|
+
if (BARE_URL.test(raw)) {
|
|
17589
|
+
throw new Error(
|
|
17590
|
+
"A bare URL is not a kit reference. Configure source.url in tangyr.config.yaml and reference the kit as --kit <name> or --kit <name>@<version>."
|
|
17591
|
+
);
|
|
17592
|
+
}
|
|
17593
|
+
if (raw.length === 0) {
|
|
17594
|
+
throw new Error(
|
|
17595
|
+
"No kit was named. Pass --kit <name> to resolve the configured channel, or --kit <name>@<version> for an exact version."
|
|
17596
|
+
);
|
|
17597
|
+
}
|
|
17598
|
+
const separator = raw.lastIndexOf("@");
|
|
17599
|
+
if (separator === -1) {
|
|
17600
|
+
assertPathSafeComponent("name", raw);
|
|
17601
|
+
return { name: raw };
|
|
17602
|
+
}
|
|
17603
|
+
return parseKitReference(raw);
|
|
17604
|
+
}
|
|
17580
17605
|
function parseKitReference(raw) {
|
|
17581
17606
|
if (BARE_URL.test(raw)) {
|
|
17582
17607
|
throw new Error(
|
|
@@ -23113,12 +23138,95 @@ function toConflictPolicy2(value) {
|
|
|
23113
23138
|
}
|
|
23114
23139
|
|
|
23115
23140
|
// src/commands/install.ts
|
|
23116
|
-
import
|
|
23117
|
-
import
|
|
23141
|
+
import fs37 from "fs";
|
|
23142
|
+
import path37 from "path";
|
|
23118
23143
|
|
|
23119
|
-
// src/core/
|
|
23144
|
+
// src/core/channel-state.ts
|
|
23120
23145
|
import fs28 from "fs";
|
|
23121
23146
|
import path26 from "path";
|
|
23147
|
+
var CHANNEL_STATE_FILENAME = ".tangyr-channels.json";
|
|
23148
|
+
function stateFilePath(cacheRoot) {
|
|
23149
|
+
return path26.join(cacheRoot, CHANNEL_STATE_FILENAME);
|
|
23150
|
+
}
|
|
23151
|
+
function channelKey(kit, channel) {
|
|
23152
|
+
return `${kit}/${channel}`;
|
|
23153
|
+
}
|
|
23154
|
+
function readState(cacheRoot) {
|
|
23155
|
+
const filePath = stateFilePath(cacheRoot);
|
|
23156
|
+
let raw;
|
|
23157
|
+
try {
|
|
23158
|
+
raw = fs28.readFileSync(filePath, "utf8");
|
|
23159
|
+
} catch (err) {
|
|
23160
|
+
if (err.code === "ENOENT") {
|
|
23161
|
+
return { state: {} };
|
|
23162
|
+
}
|
|
23163
|
+
return {
|
|
23164
|
+
state: {},
|
|
23165
|
+
warning: `Could not read ${filePath} (${err.message}); the channel downgrade guard starts from nothing for this run.`
|
|
23166
|
+
};
|
|
23167
|
+
}
|
|
23168
|
+
let parsed;
|
|
23169
|
+
try {
|
|
23170
|
+
parsed = JSON.parse(raw);
|
|
23171
|
+
} catch {
|
|
23172
|
+
return {
|
|
23173
|
+
state: {},
|
|
23174
|
+
warning: `${filePath} is not valid JSON; the channel downgrade guard starts from nothing for this run.`
|
|
23175
|
+
};
|
|
23176
|
+
}
|
|
23177
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
23178
|
+
return {
|
|
23179
|
+
state: {},
|
|
23180
|
+
warning: `${filePath} does not contain an object; the channel downgrade guard starts from nothing for this run.`
|
|
23181
|
+
};
|
|
23182
|
+
}
|
|
23183
|
+
return { state: parsed };
|
|
23184
|
+
}
|
|
23185
|
+
function readChannelSequence(cacheRoot, originUrl, kit, channel) {
|
|
23186
|
+
const { state, warning } = readState(cacheRoot);
|
|
23187
|
+
const record = state[originUrl]?.[channelKey(kit, channel)];
|
|
23188
|
+
const usable = record !== void 0 && Number.isSafeInteger(record.sequence) && typeof record.version === "string" && record.version.length > 0;
|
|
23189
|
+
const result = usable ? { sequence: record.sequence, version: record.version } : { sequence: void 0, version: void 0 };
|
|
23190
|
+
return warning === void 0 ? result : { ...result, warning };
|
|
23191
|
+
}
|
|
23192
|
+
function writeChannelSequence(params) {
|
|
23193
|
+
const { cacheRoot, originUrl, kit, channel, sequence, version, now } = params;
|
|
23194
|
+
const { state } = readState(cacheRoot);
|
|
23195
|
+
const key = channelKey(kit, channel);
|
|
23196
|
+
const existing = state[originUrl]?.[key]?.sequence;
|
|
23197
|
+
if (existing !== void 0 && existing > sequence) {
|
|
23198
|
+
return;
|
|
23199
|
+
}
|
|
23200
|
+
state[originUrl] = {
|
|
23201
|
+
...state[originUrl],
|
|
23202
|
+
[key]: { sequence, version, seenAt: now.toISOString() }
|
|
23203
|
+
};
|
|
23204
|
+
const filePath = stateFilePath(cacheRoot);
|
|
23205
|
+
fs28.mkdirSync(path26.dirname(filePath), { recursive: true, mode: 448 });
|
|
23206
|
+
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
23207
|
+
fs28.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
23208
|
+
`, {
|
|
23209
|
+
mode: 384
|
|
23210
|
+
});
|
|
23211
|
+
fs28.renameSync(tempPath, filePath);
|
|
23212
|
+
}
|
|
23213
|
+
function assertChannelNotRolledBack(params) {
|
|
23214
|
+
const { originUrl, kit, channel, seen, seenVersion, incoming } = params;
|
|
23215
|
+
if (seen !== void 0 && incoming < seen) {
|
|
23216
|
+
throw new IntegrityError(
|
|
23217
|
+
`Channel pointer for ${kit}/${channel} from ${originUrl} carries sequence ${incoming}, behind the highest already accepted (${seen}${seenVersion === void 0 ? "" : `, naming ${kit}@${seenVersion}`}). That is a replay of a superseded pointer, which would pin this machine to ${kit}@${params.incomingVersion} and hide every version published since \u2014 refusing.`
|
|
23218
|
+
);
|
|
23219
|
+
}
|
|
23220
|
+
}
|
|
23221
|
+
|
|
23222
|
+
// src/core/bundle.ts
|
|
23223
|
+
var DENY_LIST_TYPE = "tangyr.deny-list.v2";
|
|
23224
|
+
var CHANNEL_POINTER_TYPE = "tangyr.channel-pointer.v1";
|
|
23225
|
+
var DEFAULT_CHANNEL = "stable";
|
|
23226
|
+
|
|
23227
|
+
// src/core/materialize.ts
|
|
23228
|
+
import fs30 from "fs";
|
|
23229
|
+
import path28 from "path";
|
|
23122
23230
|
|
|
23123
23231
|
// src/core/integrity.ts
|
|
23124
23232
|
import crypto3 from "crypto";
|
|
@@ -23237,21 +23345,193 @@ function verifyBundle(bundle, keys, expectedIdentity, now) {
|
|
|
23237
23345
|
verifyIdentity(bundle.manifest, expectedIdentity);
|
|
23238
23346
|
}
|
|
23239
23347
|
function verifyDenyList(denyList, keys, now) {
|
|
23240
|
-
|
|
23241
|
-
(
|
|
23242
|
-
|
|
23243
|
-
|
|
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])) {
|
|
23244
23362
|
throw new IntegrityError(
|
|
23245
|
-
|
|
23363
|
+
`${DENY_LIST_MALFORMED} Expected exactly [${expectedKeys.join(", ")}], got [${actualKeys.join(", ")}].`
|
|
23246
23364
|
);
|
|
23247
23365
|
}
|
|
23248
23366
|
const list = denyList;
|
|
23249
|
-
const
|
|
23250
|
-
|
|
23251
|
-
|
|
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
|
+
function assertFreshnessWindow(issuedAt, expiresAt, now, expiryConsequence) {
|
|
23389
|
+
const utcDesignatorPattern = /Z|[+-]\d{2}:\d{2}$/;
|
|
23390
|
+
if (!utcDesignatorPattern.test(issuedAt) || !utcDesignatorPattern.test(expiresAt)) {
|
|
23391
|
+
throw new IntegrityError(
|
|
23392
|
+
`Signed document has a timezone-ambiguous validity window (issuedAt "${issuedAt}", expiresAt "${expiresAt}") \u2014 an explicit UTC designator ("Z") or numeric offset is required.`
|
|
23393
|
+
);
|
|
23394
|
+
}
|
|
23395
|
+
const issued = new Date(issuedAt);
|
|
23396
|
+
const expires = new Date(expiresAt);
|
|
23397
|
+
if (Number.isNaN(issued.getTime()) || Number.isNaN(expires.getTime())) {
|
|
23398
|
+
throw new IntegrityError(
|
|
23399
|
+
`Signed document has an unparseable validity window (issuedAt "${issuedAt}", expiresAt "${expiresAt}").`
|
|
23400
|
+
);
|
|
23401
|
+
}
|
|
23402
|
+
if (expires.getTime() < issued.getTime()) {
|
|
23403
|
+
throw new IntegrityError(
|
|
23404
|
+
`Signed document expires (${expiresAt}) before it was issued (${issuedAt}) \u2014 refusing.`
|
|
23405
|
+
);
|
|
23406
|
+
}
|
|
23407
|
+
if (now.getTime() > expires.getTime()) {
|
|
23408
|
+
throw new IntegrityError(
|
|
23409
|
+
`Signed document expired at ${expiresAt} (now ${now.toISOString()}). ${expiryConsequence}`
|
|
23410
|
+
);
|
|
23411
|
+
}
|
|
23412
|
+
if (now.getTime() < issued.getTime()) {
|
|
23413
|
+
throw new IntegrityError(
|
|
23414
|
+
`Signed document is not yet valid: issued at ${issuedAt}, now ${now.toISOString()}. Check the local clock.`
|
|
23415
|
+
);
|
|
23416
|
+
}
|
|
23417
|
+
}
|
|
23418
|
+
var CHANNEL_POINTER_MALFORMED = "Channel pointer from the origin is malformed.";
|
|
23419
|
+
function verifyChannelPointer(pointer, expectedKit, expectedChannel, keys, now) {
|
|
23420
|
+
if (pointer === null || typeof pointer !== "object") {
|
|
23421
|
+
throw new IntegrityError(CHANNEL_POINTER_MALFORMED);
|
|
23422
|
+
}
|
|
23423
|
+
const actualKeys = Object.keys(pointer).sort();
|
|
23424
|
+
const expectedKeys = [
|
|
23425
|
+
"channel",
|
|
23426
|
+
"expiresAt",
|
|
23427
|
+
"issuedAt",
|
|
23428
|
+
"keyId",
|
|
23429
|
+
"kit",
|
|
23430
|
+
"sequence",
|
|
23431
|
+
"signature",
|
|
23432
|
+
"type",
|
|
23433
|
+
"version"
|
|
23434
|
+
];
|
|
23435
|
+
if (actualKeys.length !== expectedKeys.length || actualKeys.some((key, index) => key !== expectedKeys[index])) {
|
|
23436
|
+
throw new IntegrityError(
|
|
23437
|
+
`${CHANNEL_POINTER_MALFORMED} Expected exactly [${expectedKeys.join(", ")}], got [${actualKeys.join(", ")}].`
|
|
23438
|
+
);
|
|
23439
|
+
}
|
|
23440
|
+
const candidate = pointer;
|
|
23441
|
+
const shapeOk = candidate.type === CHANNEL_POINTER_TYPE && typeof candidate.keyId === "string" && typeof candidate.kit === "string" && candidate.kit.length > 0 && typeof candidate.channel === "string" && candidate.channel.length > 0 && typeof candidate.version === "string" && candidate.version.length > 0 && typeof candidate.signature === "string" && candidate.signature.length > 0 && Number.isSafeInteger(candidate.sequence) && candidate.sequence >= 0 && typeof candidate.issuedAt === "string" && typeof candidate.expiresAt === "string";
|
|
23442
|
+
if (!shapeOk) {
|
|
23443
|
+
throw new IntegrityError(CHANNEL_POINTER_MALFORMED);
|
|
23444
|
+
}
|
|
23445
|
+
const { signature, ...signed } = candidate;
|
|
23446
|
+
verifySignedPayload(
|
|
23447
|
+
canonicalJsonBytes(signed),
|
|
23448
|
+
signature,
|
|
23449
|
+
candidate.keyId,
|
|
23450
|
+
keys,
|
|
23451
|
+
now
|
|
23452
|
+
);
|
|
23453
|
+
if (candidate.kit !== expectedKit || candidate.channel !== expectedChannel) {
|
|
23454
|
+
throw new IntegrityError(
|
|
23455
|
+
`Channel pointer is signed for ${candidate.kit}/${candidate.channel} but was served as ${expectedKit}/${expectedChannel}. A pointer the publisher signed for one channel is being presented as another's \u2014 refusing.`
|
|
23456
|
+
);
|
|
23457
|
+
}
|
|
23458
|
+
assertPathSafeComponent("version", candidate.version);
|
|
23459
|
+
assertFreshnessWindow(
|
|
23460
|
+
candidate.issuedAt,
|
|
23461
|
+
candidate.expiresAt,
|
|
23462
|
+
now,
|
|
23463
|
+
"An expired channel pointer is not evidence that it still names the newest version \u2014 the publisher must re-sign and republish it."
|
|
23464
|
+
);
|
|
23465
|
+
return candidate;
|
|
23466
|
+
}
|
|
23467
|
+
|
|
23468
|
+
// src/core/revocation-state.ts
|
|
23469
|
+
import fs29 from "fs";
|
|
23470
|
+
import path27 from "path";
|
|
23471
|
+
var REVOCATION_STATE_FILENAME = ".tangyr-revocation.json";
|
|
23472
|
+
function stateFilePath2(cacheRoot) {
|
|
23473
|
+
return path27.join(cacheRoot, REVOCATION_STATE_FILENAME);
|
|
23474
|
+
}
|
|
23475
|
+
function readState2(cacheRoot) {
|
|
23476
|
+
const filePath = stateFilePath2(cacheRoot);
|
|
23477
|
+
let raw;
|
|
23478
|
+
try {
|
|
23479
|
+
raw = fs29.readFileSync(filePath, "utf8");
|
|
23480
|
+
} catch (err) {
|
|
23481
|
+
if (err.code === "ENOENT") {
|
|
23482
|
+
return { state: {} };
|
|
23483
|
+
}
|
|
23484
|
+
return {
|
|
23485
|
+
state: {},
|
|
23486
|
+
warning: `Could not read ${filePath} (${err.message}); the deny-list replay guard starts from nothing for this run.`
|
|
23487
|
+
};
|
|
23488
|
+
}
|
|
23489
|
+
let parsed;
|
|
23490
|
+
try {
|
|
23491
|
+
parsed = JSON.parse(raw);
|
|
23492
|
+
} catch {
|
|
23493
|
+
return {
|
|
23494
|
+
state: {},
|
|
23495
|
+
warning: `${filePath} is not valid JSON; the deny-list replay guard starts from nothing for this run.`
|
|
23496
|
+
};
|
|
23497
|
+
}
|
|
23498
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
23499
|
+
return {
|
|
23500
|
+
state: {},
|
|
23501
|
+
warning: `${filePath} does not contain an object; the deny-list replay guard starts from nothing for this run.`
|
|
23502
|
+
};
|
|
23503
|
+
}
|
|
23504
|
+
return { state: parsed };
|
|
23505
|
+
}
|
|
23506
|
+
function readRevocationSequence(cacheRoot, originUrl) {
|
|
23507
|
+
const { state, warning } = readState2(cacheRoot);
|
|
23508
|
+
const record = state[originUrl];
|
|
23509
|
+
const sequence = record !== void 0 && Number.isSafeInteger(record.sequence) ? record.sequence : void 0;
|
|
23510
|
+
return warning === void 0 ? { sequence } : { sequence, warning };
|
|
23511
|
+
}
|
|
23512
|
+
function writeRevocationSequence(cacheRoot, originUrl, sequence, now) {
|
|
23513
|
+
const { state } = readState2(cacheRoot);
|
|
23514
|
+
const existing = state[originUrl]?.sequence;
|
|
23515
|
+
if (existing !== void 0 && existing >= sequence) {
|
|
23516
|
+
return;
|
|
23517
|
+
}
|
|
23518
|
+
state[originUrl] = { sequence, seenAt: now.toISOString() };
|
|
23519
|
+
const filePath = stateFilePath2(cacheRoot);
|
|
23520
|
+
fs29.mkdirSync(path27.dirname(filePath), { recursive: true, mode: 448 });
|
|
23521
|
+
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
23522
|
+
fs29.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
23523
|
+
`, {
|
|
23524
|
+
mode: 384
|
|
23252
23525
|
});
|
|
23253
|
-
|
|
23254
|
-
|
|
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
|
+
}
|
|
23255
23535
|
}
|
|
23256
23536
|
|
|
23257
23537
|
// src/core/materialize.ts
|
|
@@ -23365,7 +23645,7 @@ async function assertReferenceNotRevoked(params) {
|
|
|
23365
23645
|
sleep: sleep2
|
|
23366
23646
|
} = params;
|
|
23367
23647
|
const credentials = resolveCredentialNonInteractive();
|
|
23368
|
-
const
|
|
23648
|
+
const denyList = await withBoundedRetry(
|
|
23369
23649
|
async () => {
|
|
23370
23650
|
const controller = new AbortController();
|
|
23371
23651
|
const response = await transport.fetchObjectStream(
|
|
@@ -23402,11 +23682,21 @@ async function assertReferenceNotRevoked(params) {
|
|
|
23402
23682
|
sleep2,
|
|
23403
23683
|
logger
|
|
23404
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);
|
|
23405
23695
|
const key = `${reference.name}@${reference.version}`;
|
|
23406
|
-
if (
|
|
23696
|
+
if (denyList.entries.includes(key)) {
|
|
23407
23697
|
const entryDir = cacheEntryPath(cacheRoot, reference);
|
|
23408
|
-
if (
|
|
23409
|
-
|
|
23698
|
+
if (fs30.existsSync(entryDir)) {
|
|
23699
|
+
fs30.rmSync(entryDir, { recursive: true, force: true });
|
|
23410
23700
|
}
|
|
23411
23701
|
throw new IntegrityError(
|
|
23412
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).`
|
|
@@ -23453,7 +23743,7 @@ function assertFileWithinCeiling(entryPath, byteLength) {
|
|
|
23453
23743
|
}
|
|
23454
23744
|
var WINDOWS_DRIVE_ABSOLUTE = /^[a-zA-Z]:[\\/]/u;
|
|
23455
23745
|
function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
23456
|
-
if (
|
|
23746
|
+
if (path28.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
|
|
23457
23747
|
throw new IntegrityError(
|
|
23458
23748
|
`Bundle file path "${entryPath}" is absolute \u2014 every file inside a bundle must use a relative path (REQ-INT-004).`
|
|
23459
23749
|
);
|
|
@@ -23469,13 +23759,13 @@ function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
|
23469
23759
|
`Bundle file path "${entryPath}" contains a ".." segment \u2014 directory traversal is rejected (REQ-INT-004).`
|
|
23470
23760
|
);
|
|
23471
23761
|
}
|
|
23472
|
-
const resolved =
|
|
23762
|
+
const resolved = path28.resolve(stagingDir, entryPath);
|
|
23473
23763
|
if (resolved === stagingDir) {
|
|
23474
23764
|
throw new IntegrityError(
|
|
23475
23765
|
`Bundle file path "${entryPath}" resolves to the staging directory itself \u2014 every entry must be a file inside it (REQ-INT-004).`
|
|
23476
23766
|
);
|
|
23477
23767
|
}
|
|
23478
|
-
if (!resolved.startsWith(stagingDir +
|
|
23768
|
+
if (!resolved.startsWith(stagingDir + path28.sep)) {
|
|
23479
23769
|
throw new IntegrityError(
|
|
23480
23770
|
`Bundle file path "${entryPath}" escapes the staging directory \u2014 refusing to write (REQ-INT-004).`
|
|
23481
23771
|
);
|
|
@@ -23527,10 +23817,10 @@ function verifyBundleFileHashes(bundle) {
|
|
|
23527
23817
|
function writeStagedFiles(stagingDir, decoded) {
|
|
23528
23818
|
for (const [rawPath, bytes] of decoded) {
|
|
23529
23819
|
const target = sanitizeBundleFilePath(rawPath, stagingDir);
|
|
23530
|
-
|
|
23820
|
+
fs30.mkdirSync(path28.dirname(target), { recursive: true, mode: 448 });
|
|
23531
23821
|
let existingStat;
|
|
23532
23822
|
try {
|
|
23533
|
-
existingStat =
|
|
23823
|
+
existingStat = fs30.lstatSync(target);
|
|
23534
23824
|
} catch (error) {
|
|
23535
23825
|
if (error.code !== "ENOENT") {
|
|
23536
23826
|
throw error;
|
|
@@ -23541,7 +23831,7 @@ function writeStagedFiles(stagingDir, decoded) {
|
|
|
23541
23831
|
`Refusing to write "${rawPath}" \u2014 a symbolic link already exists at the target path.`
|
|
23542
23832
|
);
|
|
23543
23833
|
}
|
|
23544
|
-
|
|
23834
|
+
fs30.writeFileSync(target, bytes, { mode: 384, flag: "wx" });
|
|
23545
23835
|
}
|
|
23546
23836
|
}
|
|
23547
23837
|
function verifyWarmCacheEntry(entryDir, reference, keys, now) {
|
|
@@ -23607,18 +23897,103 @@ async function materializeRemoteKit(params) {
|
|
|
23607
23897
|
writeStagedFiles(stagingDir, decoded);
|
|
23608
23898
|
writeBundleDocument(stagingDir, bundle);
|
|
23609
23899
|
writeCompletionMarker(stagingDir, reference);
|
|
23610
|
-
if (replace &&
|
|
23611
|
-
|
|
23900
|
+
if (replace && fs30.existsSync(entryDir)) {
|
|
23901
|
+
fs30.rmSync(entryDir, { recursive: true, force: true });
|
|
23612
23902
|
}
|
|
23613
23903
|
publishCacheEntry(stagingDir, entryDir);
|
|
23614
23904
|
return entryDir;
|
|
23615
23905
|
} catch (error) {
|
|
23616
23906
|
if (stagingDir !== void 0) {
|
|
23617
|
-
|
|
23907
|
+
fs30.rmSync(stagingDir, { recursive: true, force: true });
|
|
23618
23908
|
}
|
|
23619
23909
|
throw error;
|
|
23620
23910
|
}
|
|
23621
23911
|
}
|
|
23912
|
+
var CHANNEL_OBJECT_PATH_PREFIX = "/v1/channels";
|
|
23913
|
+
var MAX_CHANNEL_POINTER_BYTES = 64 * 1024;
|
|
23914
|
+
async function resolveChannelVersion(params) {
|
|
23915
|
+
const {
|
|
23916
|
+
originUrl,
|
|
23917
|
+
kit,
|
|
23918
|
+
channel,
|
|
23919
|
+
cacheRoot,
|
|
23920
|
+
transport,
|
|
23921
|
+
keys,
|
|
23922
|
+
now,
|
|
23923
|
+
logger,
|
|
23924
|
+
sleep: sleep2
|
|
23925
|
+
} = params;
|
|
23926
|
+
const credentials = resolveCredentialNonInteractive();
|
|
23927
|
+
const objectPath = `${CHANNEL_OBJECT_PATH_PREFIX}/${kit}/${channel}.json`;
|
|
23928
|
+
const pointer = await withBoundedRetry(
|
|
23929
|
+
async () => {
|
|
23930
|
+
const controller = new AbortController();
|
|
23931
|
+
const response = await transport.fetchObjectStream(
|
|
23932
|
+
originUrl,
|
|
23933
|
+
objectPath,
|
|
23934
|
+
credentials,
|
|
23935
|
+
controller.signal
|
|
23936
|
+
);
|
|
23937
|
+
if (response.status === 401 || response.status === 403) {
|
|
23938
|
+
throw new AuthenticationError(
|
|
23939
|
+
`The origin rejected the credential (HTTP ${response.status}) resolving ${kit}/${channel}. Set TANGYR_ACCESS_CLIENT_ID and TANGYR_ACCESS_CLIENT_SECRET, or run 'tangyr auth login'.`
|
|
23940
|
+
);
|
|
23941
|
+
}
|
|
23942
|
+
if (response.status === 404) {
|
|
23943
|
+
throw new IntegrityError(
|
|
23944
|
+
`The origin has no ${channel} channel for "${kit}" (HTTP 404 at ${originUrl}${objectPath}). Either the publisher has not published that channel, or the kit name is wrong. Reference an explicit version as --kit ${kit}@<version> if you know one.`
|
|
23945
|
+
);
|
|
23946
|
+
}
|
|
23947
|
+
if (response.status !== 200) {
|
|
23948
|
+
throw new Error(
|
|
23949
|
+
`Unexpected HTTP ${response.status} resolving ${kit}/${channel} from ${originUrl}${objectPath}.`
|
|
23950
|
+
);
|
|
23951
|
+
}
|
|
23952
|
+
const buffer = await readBoundedStream(
|
|
23953
|
+
response.body,
|
|
23954
|
+
MAX_CHANNEL_POINTER_BYTES,
|
|
23955
|
+
() => controller.abort()
|
|
23956
|
+
);
|
|
23957
|
+
let parsed;
|
|
23958
|
+
try {
|
|
23959
|
+
parsed = JSON.parse(buffer.toString("utf8"));
|
|
23960
|
+
} catch {
|
|
23961
|
+
throw new IntegrityError(
|
|
23962
|
+
`Channel pointer for ${kit}/${channel} is not valid JSON \u2014 rejecting.`
|
|
23963
|
+
);
|
|
23964
|
+
}
|
|
23965
|
+
return verifyChannelPointer(parsed, kit, channel, keys, now);
|
|
23966
|
+
},
|
|
23967
|
+
sleep2,
|
|
23968
|
+
logger
|
|
23969
|
+
);
|
|
23970
|
+
const seen = readChannelSequence(cacheRoot, originUrl, kit, channel);
|
|
23971
|
+
if (seen.warning) {
|
|
23972
|
+
logger.warn(seen.warning);
|
|
23973
|
+
}
|
|
23974
|
+
assertChannelNotRolledBack({
|
|
23975
|
+
originUrl,
|
|
23976
|
+
kit,
|
|
23977
|
+
channel,
|
|
23978
|
+
seen: seen.sequence,
|
|
23979
|
+
seenVersion: seen.version,
|
|
23980
|
+
incoming: pointer.sequence,
|
|
23981
|
+
incomingVersion: pointer.version
|
|
23982
|
+
});
|
|
23983
|
+
writeChannelSequence({
|
|
23984
|
+
cacheRoot,
|
|
23985
|
+
originUrl,
|
|
23986
|
+
kit,
|
|
23987
|
+
channel,
|
|
23988
|
+
sequence: pointer.sequence,
|
|
23989
|
+
version: pointer.version,
|
|
23990
|
+
now
|
|
23991
|
+
});
|
|
23992
|
+
logger.verbose(
|
|
23993
|
+
`Resolved ${kit}/${channel} to ${kit}@${pointer.version} (pointer sequence ${pointer.sequence}).`
|
|
23994
|
+
);
|
|
23995
|
+
return pointer.version;
|
|
23996
|
+
}
|
|
23622
23997
|
|
|
23623
23998
|
// src/core/kit-source.ts
|
|
23624
23999
|
function resolveCacheOnly(entryDir, reference, keys, now) {
|
|
@@ -23657,13 +24032,25 @@ async function resolveKitSource(params) {
|
|
|
23657
24032
|
if (config.source.type !== "remote") {
|
|
23658
24033
|
return { kitName: kitOption };
|
|
23659
24034
|
}
|
|
23660
|
-
const
|
|
24035
|
+
const selector = parseKitSelector(kitOption ?? "");
|
|
23661
24036
|
if (!config.source.url) {
|
|
23662
24037
|
throw new Error(
|
|
23663
24038
|
"Configuration declares source.type: remote but no source.url. Set source.url to the https endpoint of your kit origin."
|
|
23664
24039
|
);
|
|
23665
24040
|
}
|
|
23666
24041
|
const cacheRoot = resolveCacheRoot(env2);
|
|
24042
|
+
const reference = selector.version === void 0 ? await resolveThroughChannel({
|
|
24043
|
+
name: selector.name,
|
|
24044
|
+
channel: config.source.channel ?? DEFAULT_CHANNEL,
|
|
24045
|
+
originUrl: config.source.url,
|
|
24046
|
+
cacheRoot,
|
|
24047
|
+
offline: offline === true,
|
|
24048
|
+
transport,
|
|
24049
|
+
keys,
|
|
24050
|
+
now,
|
|
24051
|
+
logger,
|
|
24052
|
+
sleep: sleep2
|
|
24053
|
+
}) : { name: selector.name, version: selector.version };
|
|
23667
24054
|
const entryDir = cacheEntryPath(cacheRoot, reference);
|
|
23668
24055
|
if (offline) {
|
|
23669
24056
|
return resolveCacheOnly(entryDir, reference, keys, now);
|
|
@@ -23801,6 +24188,54 @@ async function resolveKitSource(params) {
|
|
|
23801
24188
|
writeLastAuthorizedAt(cacheRoot, config.source.url, now);
|
|
23802
24189
|
return { kitPathOverride, kitName: reference.name };
|
|
23803
24190
|
}
|
|
24191
|
+
async function resolveThroughChannel(params) {
|
|
24192
|
+
const { name, channel, originUrl, cacheRoot, offline, logger } = params;
|
|
24193
|
+
const lastSeenVersion = () => {
|
|
24194
|
+
const seen = readChannelSequence(cacheRoot, originUrl, name, channel);
|
|
24195
|
+
if (seen.warning) {
|
|
24196
|
+
logger.warn(seen.warning);
|
|
24197
|
+
}
|
|
24198
|
+
return seen.version;
|
|
24199
|
+
};
|
|
24200
|
+
if (offline) {
|
|
24201
|
+
const version = lastSeenVersion();
|
|
24202
|
+
if (version === void 0) {
|
|
24203
|
+
throw new OfflineCacheMissError(
|
|
24204
|
+
`--offline cannot resolve ${name}/${channel}: this machine has never resolved that channel, and a channel pointer is never cached. Run once with network access, or name a version as --kit ${name}@<version>.`
|
|
24205
|
+
);
|
|
24206
|
+
}
|
|
24207
|
+
logger.warn(
|
|
24208
|
+
`--offline: using ${name}@${version}, the last version this machine saw on ${channel}. A newer one may exist.`
|
|
24209
|
+
);
|
|
24210
|
+
return { name, version };
|
|
24211
|
+
}
|
|
24212
|
+
try {
|
|
24213
|
+
const version = await resolveChannelVersion({
|
|
24214
|
+
originUrl,
|
|
24215
|
+
kit: name,
|
|
24216
|
+
channel,
|
|
24217
|
+
cacheRoot,
|
|
24218
|
+
transport: params.transport,
|
|
24219
|
+
keys: params.keys,
|
|
24220
|
+
now: params.now,
|
|
24221
|
+
logger,
|
|
24222
|
+
sleep: params.sleep
|
|
24223
|
+
});
|
|
24224
|
+
return { name, version };
|
|
24225
|
+
} catch (error) {
|
|
24226
|
+
if (!(error instanceof RemoteUnavailableError)) {
|
|
24227
|
+
throw error;
|
|
24228
|
+
}
|
|
24229
|
+
const version = lastSeenVersion();
|
|
24230
|
+
if (version === void 0) {
|
|
24231
|
+
throw error;
|
|
24232
|
+
}
|
|
24233
|
+
logger.warn(
|
|
24234
|
+
`Could not reach the origin to resolve ${name}/${channel}; falling back to ${name}@${version}, the last version this machine saw. A newer one may exist.`
|
|
24235
|
+
);
|
|
24236
|
+
return { name, version };
|
|
24237
|
+
}
|
|
24238
|
+
}
|
|
23804
24239
|
|
|
23805
24240
|
// src/core/keys.ts
|
|
23806
24241
|
var PINNED_PUBLISHER_KEYS = [
|
|
@@ -23822,13 +24257,13 @@ function sleep(ms2) {
|
|
|
23822
24257
|
// src/adapters/codex.ts
|
|
23823
24258
|
var TOML3 = __toESM(require_toml(), 1);
|
|
23824
24259
|
import crypto5 from "crypto";
|
|
23825
|
-
import
|
|
23826
|
-
import
|
|
24260
|
+
import fs32 from "fs";
|
|
24261
|
+
import path31 from "path";
|
|
23827
24262
|
|
|
23828
24263
|
// src/compiler/agents.ts
|
|
23829
24264
|
var TOML = __toESM(require_toml(), 1);
|
|
23830
24265
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
23831
|
-
import
|
|
24266
|
+
import path29 from "path";
|
|
23832
24267
|
|
|
23833
24268
|
// src/compiler/loss-report.ts
|
|
23834
24269
|
function createLossReport() {
|
|
@@ -23892,7 +24327,7 @@ var copilotToolAliasesByClass = {
|
|
|
23892
24327
|
};
|
|
23893
24328
|
function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
23894
24329
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
23895
|
-
const relativeSource = `agents/${
|
|
24330
|
+
const relativeSource = `agents/${path29.basename(sourceFile)}`;
|
|
23896
24331
|
if (target === "opencode") {
|
|
23897
24332
|
return compileOpenCodeAgent(
|
|
23898
24333
|
sourceFile,
|
|
@@ -23933,7 +24368,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
23933
24368
|
mappings,
|
|
23934
24369
|
lossReport
|
|
23935
24370
|
);
|
|
23936
|
-
const overlayKey = `agents/${
|
|
24371
|
+
const overlayKey = `agents/${path29.basename(sourceFile, ".md")}.${target}.yaml`;
|
|
23937
24372
|
const targetFields = {
|
|
23938
24373
|
...translated.fields,
|
|
23939
24374
|
...extensions[overlayKey] ?? {}
|
|
@@ -23967,7 +24402,7 @@ ${TOML.stringify({
|
|
|
23967
24402
|
function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
23968
24403
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
23969
24404
|
throw new Error(
|
|
23970
|
-
`${
|
|
24405
|
+
`${path29.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
|
|
23971
24406
|
);
|
|
23972
24407
|
}
|
|
23973
24408
|
const frontmatter = {
|
|
@@ -24021,7 +24456,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
24021
24456
|
"permission",
|
|
24022
24457
|
"permission-coarsening"
|
|
24023
24458
|
),
|
|
24024
|
-
detail: `${
|
|
24459
|
+
detail: `${path29.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
|
|
24025
24460
|
}
|
|
24026
24461
|
]
|
|
24027
24462
|
});
|
|
@@ -24046,7 +24481,7 @@ ${(0, import_yaml7.stringify)(frontmatter).trim()}
|
|
|
24046
24481
|
function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
24047
24482
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
24048
24483
|
throw new Error(
|
|
24049
|
-
`${
|
|
24484
|
+
`${path29.basename(sourceFile)}: Cursor agent requires a non-empty description field`
|
|
24050
24485
|
);
|
|
24051
24486
|
}
|
|
24052
24487
|
const frontmatter = {
|
|
@@ -24083,7 +24518,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
24083
24518
|
"permission",
|
|
24084
24519
|
"permission-coarsening"
|
|
24085
24520
|
),
|
|
24086
|
-
detail: `${
|
|
24521
|
+
detail: `${path29.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
|
|
24087
24522
|
}
|
|
24088
24523
|
]
|
|
24089
24524
|
});
|
|
@@ -24102,7 +24537,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
24102
24537
|
"provider",
|
|
24103
24538
|
"provider-not-representable"
|
|
24104
24539
|
),
|
|
24105
|
-
detail: `${
|
|
24540
|
+
detail: `${path29.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
24106
24541
|
}
|
|
24107
24542
|
]
|
|
24108
24543
|
});
|
|
@@ -24134,7 +24569,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
|
|
|
24134
24569
|
"persona",
|
|
24135
24570
|
"persona-not-representable"
|
|
24136
24571
|
),
|
|
24137
|
-
detail: `${
|
|
24572
|
+
detail: `${path29.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
|
|
24138
24573
|
}
|
|
24139
24574
|
]
|
|
24140
24575
|
});
|
|
@@ -24182,7 +24617,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24182
24617
|
field,
|
|
24183
24618
|
"model-not-representable"
|
|
24184
24619
|
),
|
|
24185
|
-
detail: `${
|
|
24620
|
+
detail: `${path29.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
|
|
24186
24621
|
});
|
|
24187
24622
|
return;
|
|
24188
24623
|
}
|
|
@@ -24200,9 +24635,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24200
24635
|
lossReport,
|
|
24201
24636
|
target,
|
|
24202
24637
|
"agents",
|
|
24203
|
-
`agents/${
|
|
24638
|
+
`agents/${path29.basename(sourceFile)}`,
|
|
24204
24639
|
"info",
|
|
24205
|
-
`${
|
|
24640
|
+
`${path29.basename(sourceFile)}: ${field} is delivered through another managed surface.`
|
|
24206
24641
|
);
|
|
24207
24642
|
return;
|
|
24208
24643
|
}
|
|
@@ -24211,7 +24646,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24211
24646
|
field,
|
|
24212
24647
|
action: entryType,
|
|
24213
24648
|
severity: resolveLossSeverity("agent-field", field, entryType),
|
|
24214
|
-
detail: `${
|
|
24649
|
+
detail: `${path29.basename(sourceFile)}: ${field} has no emitted field for this target.`
|
|
24215
24650
|
});
|
|
24216
24651
|
}
|
|
24217
24652
|
function mapToolsToCapabilities(value, mappings) {
|
|
@@ -24808,9 +25243,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
|
|
|
24808
25243
|
}
|
|
24809
25244
|
|
|
24810
25245
|
// src/compiler/rules.ts
|
|
24811
|
-
import
|
|
25246
|
+
import path30 from "path";
|
|
24812
25247
|
var import_yaml8 = __toESM(require_dist(), 1);
|
|
24813
|
-
import
|
|
25248
|
+
import fs31 from "fs";
|
|
24814
25249
|
function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
24815
25250
|
if (target === "copilot") {
|
|
24816
25251
|
addLoss(lossReport, "copilot", "rules", {
|
|
@@ -24847,13 +25282,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
|
24847
25282
|
}
|
|
24848
25283
|
const appendixParts = [];
|
|
24849
25284
|
const dotRulesFiles = [];
|
|
24850
|
-
for (const ruleFile of ts(
|
|
25285
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
24851
25286
|
const parsed = parseRule(ruleFile);
|
|
24852
|
-
const name =
|
|
25287
|
+
const name = path30.basename(ruleFile, ".md");
|
|
24853
25288
|
if (parsed.mode === "exec-policy") {
|
|
24854
25289
|
dotRulesFiles.push({
|
|
24855
25290
|
name: `${name}.rules`,
|
|
24856
|
-
content: `${formatProvenanceMarker("toml", `rules/${
|
|
25291
|
+
content: `${formatProvenanceMarker("toml", `rules/${path30.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
|
|
24857
25292
|
${parsed.body}`
|
|
24858
25293
|
});
|
|
24859
25294
|
continue;
|
|
@@ -24862,7 +25297,7 @@ ${parsed.body}`
|
|
|
24862
25297
|
|
|
24863
25298
|
${parsed.body.trim()}`);
|
|
24864
25299
|
addLoss(lossReport, "codex", "rules", {
|
|
24865
|
-
source: `rules/${
|
|
25300
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
24866
25301
|
fields: [
|
|
24867
25302
|
{
|
|
24868
25303
|
field: "mode",
|
|
@@ -24872,7 +25307,7 @@ ${parsed.body.trim()}`);
|
|
|
24872
25307
|
"mode",
|
|
24873
25308
|
"rule-as-instruction"
|
|
24874
25309
|
),
|
|
24875
|
-
detail: `${
|
|
25310
|
+
detail: `${path30.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
|
|
24876
25311
|
}
|
|
24877
25312
|
]
|
|
24878
25313
|
});
|
|
@@ -24880,7 +25315,7 @@ ${parsed.body.trim()}`);
|
|
|
24880
25315
|
return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
|
|
24881
25316
|
}
|
|
24882
25317
|
function parseRule(ruleFile) {
|
|
24883
|
-
const content =
|
|
25318
|
+
const content = fs31.readFileSync(ruleFile, "utf8");
|
|
24884
25319
|
if (!content.startsWith("---\n")) {
|
|
24885
25320
|
return { mode: "guidance", body: content };
|
|
24886
25321
|
}
|
|
@@ -24904,14 +25339,14 @@ function isRuleMode(value) {
|
|
|
24904
25339
|
}
|
|
24905
25340
|
function compileOpenCodeRules(sourceRulesDir, lossReport) {
|
|
24906
25341
|
const appendixParts = [];
|
|
24907
|
-
for (const ruleFile of ts(
|
|
25342
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
24908
25343
|
const parsed = parseRule(ruleFile);
|
|
24909
|
-
const name =
|
|
25344
|
+
const name = path30.basename(ruleFile, ".md");
|
|
24910
25345
|
appendixParts.push(`## ${name}
|
|
24911
25346
|
|
|
24912
25347
|
${parsed.body.trim()}`);
|
|
24913
25348
|
addLoss(lossReport, "opencode", "rules", {
|
|
24914
|
-
source: `rules/${
|
|
25349
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
24915
25350
|
fields: [
|
|
24916
25351
|
{
|
|
24917
25352
|
field: "rule",
|
|
@@ -24921,7 +25356,7 @@ ${parsed.body.trim()}`);
|
|
|
24921
25356
|
"rule",
|
|
24922
25357
|
"rule-path-scoping"
|
|
24923
25358
|
),
|
|
24924
|
-
detail: `${
|
|
25359
|
+
detail: `${path30.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
|
|
24925
25360
|
}
|
|
24926
25361
|
]
|
|
24927
25362
|
});
|
|
@@ -24930,9 +25365,9 @@ ${parsed.body.trim()}`);
|
|
|
24930
25365
|
}
|
|
24931
25366
|
function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
24932
25367
|
const dotRulesFiles = [];
|
|
24933
|
-
for (const ruleFile of ts(
|
|
24934
|
-
const content =
|
|
24935
|
-
const name =
|
|
25368
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
25369
|
+
const content = fs31.readFileSync(ruleFile, "utf8");
|
|
25370
|
+
const name = path30.basename(ruleFile, ".md");
|
|
24936
25371
|
let frontmatterData = {};
|
|
24937
25372
|
let body = content;
|
|
24938
25373
|
if (content.startsWith("---\n")) {
|
|
@@ -24961,7 +25396,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
|
24961
25396
|
}
|
|
24962
25397
|
const marker = formatProvenanceMarker(
|
|
24963
25398
|
"markdown",
|
|
24964
|
-
`rules/${
|
|
25399
|
+
`rules/${path30.basename(ruleFile)}`,
|
|
24965
25400
|
computeSourceHash(ruleFile),
|
|
24966
25401
|
"cursor"
|
|
24967
25402
|
);
|
|
@@ -24977,9 +25412,9 @@ ${body}`;
|
|
|
24977
25412
|
}
|
|
24978
25413
|
function compileClineRules(sourceRulesDir, lossReport) {
|
|
24979
25414
|
const dotRulesFiles = [];
|
|
24980
|
-
for (const ruleFile of ts(
|
|
24981
|
-
const content =
|
|
24982
|
-
const name =
|
|
25415
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
25416
|
+
const content = fs31.readFileSync(ruleFile, "utf8");
|
|
25417
|
+
const name = path30.basename(ruleFile, ".md");
|
|
24983
25418
|
let frontmatterData = {};
|
|
24984
25419
|
let body = content;
|
|
24985
25420
|
if (content.startsWith("---\n")) {
|
|
@@ -24996,13 +25431,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
24996
25431
|
}
|
|
24997
25432
|
const marker = formatProvenanceMarker(
|
|
24998
25433
|
"markdown",
|
|
24999
|
-
`rules/${
|
|
25434
|
+
`rules/${path30.basename(ruleFile)}`,
|
|
25000
25435
|
computeSourceHash(ruleFile),
|
|
25001
25436
|
"cline"
|
|
25002
25437
|
);
|
|
25003
25438
|
if (frontmatterData.mode === "exec-policy") {
|
|
25004
25439
|
addLoss(lossReport, "cline", "rules", {
|
|
25005
|
-
source: `rules/${
|
|
25440
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
25006
25441
|
fields: [
|
|
25007
25442
|
{
|
|
25008
25443
|
field: "mode",
|
|
@@ -25012,7 +25447,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25012
25447
|
"mode",
|
|
25013
25448
|
"rule-mode-downgrade"
|
|
25014
25449
|
),
|
|
25015
|
-
detail: `${
|
|
25450
|
+
detail: `${path30.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
|
|
25016
25451
|
}
|
|
25017
25452
|
]
|
|
25018
25453
|
});
|
|
@@ -25057,7 +25492,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
25057
25492
|
rules: profile.rules
|
|
25058
25493
|
};
|
|
25059
25494
|
const rules = compileRules(
|
|
25060
|
-
|
|
25495
|
+
path31.join(sourceRoot, config.source.rules),
|
|
25061
25496
|
"codex",
|
|
25062
25497
|
mappings,
|
|
25063
25498
|
lossReport
|
|
@@ -25202,9 +25637,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
25202
25637
|
function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
|
|
25203
25638
|
const cp = mappings.modelTiers.custom_provider;
|
|
25204
25639
|
if (!cp) return "";
|
|
25205
|
-
const agentsDir =
|
|
25206
|
-
if (!
|
|
25207
|
-
const agentFiles = ts(
|
|
25640
|
+
const agentsDir = path31.join(sourceRoot, config.source.agents);
|
|
25641
|
+
if (!fs32.existsSync(agentsDir)) return "";
|
|
25642
|
+
const agentFiles = ts(path31.join(agentsDir, "*.md")).sort();
|
|
25208
25643
|
const hasProviderAgent = agentFiles.some((agentFile) => {
|
|
25209
25644
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
25210
25645
|
return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
@@ -25269,7 +25704,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
25269
25704
|
}
|
|
25270
25705
|
];
|
|
25271
25706
|
for (const ruleFile of rules.dotRulesFiles) {
|
|
25272
|
-
const destination =
|
|
25707
|
+
const destination = path31.join(rulesRoot, ruleFile.name);
|
|
25273
25708
|
if (options.dryRun) {
|
|
25274
25709
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
25275
25710
|
outcomes.push({
|
|
@@ -25297,15 +25732,15 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
25297
25732
|
return outcomes;
|
|
25298
25733
|
}
|
|
25299
25734
|
function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
25300
|
-
const source =
|
|
25735
|
+
const source = path31.join(sourceRoot, config.source.instructions);
|
|
25301
25736
|
const destination = resolveTargetPath(paths.instructions);
|
|
25302
|
-
const composed = `${
|
|
25737
|
+
const composed = `${fs32.readFileSync(source, "utf8").trim()}
|
|
25303
25738
|
|
|
25304
25739
|
--- tangyr managed rules ---
|
|
25305
25740
|
${agentsAppendix}`.trim();
|
|
25306
25741
|
const marker = formatProvenanceMarker(
|
|
25307
25742
|
"markdown",
|
|
25308
|
-
|
|
25743
|
+
path31.basename(config.source.instructions),
|
|
25309
25744
|
hashString(composed),
|
|
25310
25745
|
"codex"
|
|
25311
25746
|
);
|
|
@@ -25332,9 +25767,9 @@ ${composed}
|
|
|
25332
25767
|
);
|
|
25333
25768
|
}
|
|
25334
25769
|
function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
25335
|
-
const source =
|
|
25770
|
+
const source = path31.resolve(sourceRoot, config.source.skills);
|
|
25336
25771
|
const destination = resolveTargetPath(paths.skills);
|
|
25337
|
-
if (!
|
|
25772
|
+
if (!fs32.existsSync(source)) {
|
|
25338
25773
|
return skippedMissingSource("skills", source);
|
|
25339
25774
|
}
|
|
25340
25775
|
if (options.dryRun) {
|
|
@@ -25350,29 +25785,29 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
|
|
|
25350
25785
|
};
|
|
25351
25786
|
}
|
|
25352
25787
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
25353
|
-
|
|
25788
|
+
fs32.unlinkSync(destination);
|
|
25354
25789
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
25355
25790
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
25356
25791
|
return { component: "skills", status: "conflict", path: destination };
|
|
25357
25792
|
} else if (artifactClass === "managed-symlink") {
|
|
25358
|
-
|
|
25793
|
+
fs32.unlinkSync(destination);
|
|
25359
25794
|
}
|
|
25360
|
-
ensureDir(
|
|
25795
|
+
ensureDir(path31.dirname(destination));
|
|
25361
25796
|
createRelativeSymlink(source, destination, "dir");
|
|
25362
25797
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
25363
25798
|
return { component: "skills", status: "success", path: destination };
|
|
25364
25799
|
}
|
|
25365
25800
|
function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
25366
|
-
const sourceAgentsRoot =
|
|
25367
|
-
if (!
|
|
25801
|
+
const sourceAgentsRoot = path31.join(sourceRoot, config.source.agents);
|
|
25802
|
+
if (!fs32.existsSync(sourceAgentsRoot)) {
|
|
25368
25803
|
return [skippedMissingSource("agents", sourceAgentsRoot)];
|
|
25369
25804
|
}
|
|
25370
|
-
const sourceAgents = ts(
|
|
25805
|
+
const sourceAgents = ts(path31.join(sourceAgentsRoot, "*.md")).sort();
|
|
25371
25806
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
25372
25807
|
return sourceAgents.map((agentFile) => {
|
|
25373
|
-
const destination =
|
|
25808
|
+
const destination = path31.join(
|
|
25374
25809
|
agentsRoot,
|
|
25375
|
-
`${
|
|
25810
|
+
`${path31.basename(agentFile, ".md")}.toml`
|
|
25376
25811
|
);
|
|
25377
25812
|
const compiled = compileAgent(
|
|
25378
25813
|
agentFile,
|
|
@@ -25408,10 +25843,10 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
|
|
|
25408
25843
|
}
|
|
25409
25844
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
25410
25845
|
const sourceLabel = hooksSourceLabel(config);
|
|
25411
|
-
if (!
|
|
25846
|
+
if (!fs32.existsSync(source)) {
|
|
25412
25847
|
return skippedMissingSource("hooks", source);
|
|
25413
25848
|
}
|
|
25414
|
-
const sourceHooksJson = JSON.parse(
|
|
25849
|
+
const sourceHooksJson = JSON.parse(fs32.readFileSync(source, "utf8"));
|
|
25415
25850
|
const compiled = compileHooks(
|
|
25416
25851
|
sourceHooksJson,
|
|
25417
25852
|
"codex",
|
|
@@ -25433,7 +25868,7 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
|
|
|
25433
25868
|
destination,
|
|
25434
25869
|
hostHooks,
|
|
25435
25870
|
stringifyJson2,
|
|
25436
|
-
!
|
|
25871
|
+
!fs32.existsSync(destination),
|
|
25437
25872
|
logger
|
|
25438
25873
|
);
|
|
25439
25874
|
return {
|
|
@@ -25446,7 +25881,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
|
|
|
25446
25881
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
25447
25882
|
const sourceLabel = mcpSourceLabel(config);
|
|
25448
25883
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
25449
|
-
if (!
|
|
25884
|
+
if (!fs32.existsSync(source)) {
|
|
25450
25885
|
if (providerToml && !options.dryRun) {
|
|
25451
25886
|
const changed2 = writeTomlManagedSection(
|
|
25452
25887
|
destination,
|
|
@@ -25461,7 +25896,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
|
|
|
25461
25896
|
}
|
|
25462
25897
|
return skippedMissingSource("mcp", source);
|
|
25463
25898
|
}
|
|
25464
|
-
const sourceMcpJson = JSON.parse(
|
|
25899
|
+
const sourceMcpJson = JSON.parse(fs32.readFileSync(source, "utf8"));
|
|
25465
25900
|
const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
|
|
25466
25901
|
const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
|
|
25467
25902
|
if (options.dryRun) {
|
|
@@ -25483,12 +25918,12 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
|
|
|
25483
25918
|
if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
25484
25919
|
return { component, status: "conflict", path: destination };
|
|
25485
25920
|
}
|
|
25486
|
-
ensureDir(
|
|
25487
|
-
|
|
25921
|
+
ensureDir(path31.dirname(destination));
|
|
25922
|
+
fs32.writeFileSync(destination, content);
|
|
25488
25923
|
return { component, status: "success", path: destination };
|
|
25489
25924
|
}
|
|
25490
25925
|
function writeTomlManagedSection(destination, managedContent, logger) {
|
|
25491
|
-
const current =
|
|
25926
|
+
const current = fs32.existsSync(destination) ? fs32.readFileSync(destination, "utf8") : "";
|
|
25492
25927
|
const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
|
|
25493
25928
|
if (isFirstWrite) {
|
|
25494
25929
|
logger.warn(
|
|
@@ -25504,8 +25939,8 @@ ${managedMcpEnd}
|
|
|
25504
25939
|
if (current === next.trimStart()) {
|
|
25505
25940
|
return false;
|
|
25506
25941
|
}
|
|
25507
|
-
ensureDir(
|
|
25508
|
-
|
|
25942
|
+
ensureDir(path31.dirname(destination));
|
|
25943
|
+
fs32.writeFileSync(destination, next.trimStart());
|
|
25509
25944
|
return true;
|
|
25510
25945
|
}
|
|
25511
25946
|
function removeManagedTomlSection(content) {
|
|
@@ -25532,16 +25967,16 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
|
|
|
25532
25967
|
backupFile(destination, manifest);
|
|
25533
25968
|
writeManifest(scopePath, manifest);
|
|
25534
25969
|
} else {
|
|
25535
|
-
|
|
25970
|
+
fs32.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
25536
25971
|
}
|
|
25537
25972
|
return true;
|
|
25538
25973
|
}
|
|
25539
|
-
|
|
25974
|
+
fs32.rmSync(destination, { recursive: true, force: true });
|
|
25540
25975
|
return true;
|
|
25541
25976
|
}
|
|
25542
25977
|
function isCompiledCurrent(destination, expectedContent, expectedHash) {
|
|
25543
25978
|
try {
|
|
25544
|
-
const current =
|
|
25979
|
+
const current = fs32.readFileSync(destination, "utf8");
|
|
25545
25980
|
const marker = extractProvenanceMarker(current);
|
|
25546
25981
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "codex" && current === expectedContent : current === expectedContent;
|
|
25547
25982
|
} catch {
|
|
@@ -25560,16 +25995,16 @@ function shouldSkipComponent(options, component) {
|
|
|
25560
25995
|
}
|
|
25561
25996
|
function isSymlinkTo(linkPath, source) {
|
|
25562
25997
|
try {
|
|
25563
|
-
return
|
|
25998
|
+
return fs32.realpathSync(linkPath) === fs32.realpathSync(source);
|
|
25564
25999
|
} catch {
|
|
25565
26000
|
return false;
|
|
25566
26001
|
}
|
|
25567
26002
|
}
|
|
25568
26003
|
function readJsonObject3(filePath) {
|
|
25569
|
-
if (!
|
|
26004
|
+
if (!fs32.existsSync(filePath)) {
|
|
25570
26005
|
return {};
|
|
25571
26006
|
}
|
|
25572
|
-
const parsed = JSON.parse(
|
|
26007
|
+
const parsed = JSON.parse(fs32.readFileSync(filePath, "utf8"));
|
|
25573
26008
|
return isRecord4(parsed) ? parsed : {};
|
|
25574
26009
|
}
|
|
25575
26010
|
function stringifyJson2(value) {
|
|
@@ -25585,16 +26020,16 @@ function hashString(value) {
|
|
|
25585
26020
|
|
|
25586
26021
|
// src/adapters/copilot.ts
|
|
25587
26022
|
import crypto6 from "crypto";
|
|
25588
|
-
import
|
|
25589
|
-
import
|
|
26023
|
+
import fs33 from "fs";
|
|
26024
|
+
import path33 from "path";
|
|
25590
26025
|
|
|
25591
26026
|
// src/compiler/commands.ts
|
|
25592
26027
|
var import_yaml9 = __toESM(require_dist(), 1);
|
|
25593
|
-
import
|
|
26028
|
+
import path32 from "path";
|
|
25594
26029
|
function compileCommandPrompt(sourceFile) {
|
|
25595
26030
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
25596
|
-
const relativeSource = `commands/${
|
|
25597
|
-
const fields = promptFrontmatter(data,
|
|
26031
|
+
const relativeSource = `commands/${path32.basename(sourceFile)}`;
|
|
26032
|
+
const fields = promptFrontmatter(data, path32.basename(sourceFile, ".md"));
|
|
25598
26033
|
const marker = formatProvenanceMarker(
|
|
25599
26034
|
"markdown",
|
|
25600
26035
|
relativeSource,
|
|
@@ -25769,13 +26204,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
25769
26204
|
}
|
|
25770
26205
|
function syncProviderLoss(config, sourceRoot, mappings, lossReport) {
|
|
25771
26206
|
if (!mappings.modelTiers.custom_provider) return;
|
|
25772
|
-
const agentsDir =
|
|
25773
|
-
if (!
|
|
25774
|
-
for (const agentFile of ts(
|
|
26207
|
+
const agentsDir = path33.join(sourceRoot, config.source.agents);
|
|
26208
|
+
if (!fs33.existsSync(agentsDir)) return;
|
|
26209
|
+
for (const agentFile of ts(path33.join(agentsDir, "*.md")).sort()) {
|
|
25775
26210
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
25776
26211
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
25777
26212
|
if (hasProvider) {
|
|
25778
|
-
const basename =
|
|
26213
|
+
const basename = path33.basename(agentFile);
|
|
25779
26214
|
addLoss(lossReport, "copilot", "agents", {
|
|
25780
26215
|
source: `agents/${basename}`,
|
|
25781
26216
|
fields: [
|
|
@@ -25800,23 +26235,23 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
|
|
|
25800
26235
|
logger.verbose(message);
|
|
25801
26236
|
return [{ component: "instructions", status: "skipped", path: message }];
|
|
25802
26237
|
}
|
|
25803
|
-
const source =
|
|
25804
|
-
if (!
|
|
26238
|
+
const source = path33.resolve(sourceRoot, config.source.instructions);
|
|
26239
|
+
if (!fs33.existsSync(source)) {
|
|
25805
26240
|
return [skippedMissingSource2("instructions", source)];
|
|
25806
26241
|
}
|
|
25807
|
-
const rawContent =
|
|
26242
|
+
const rawContent = fs33.readFileSync(source, "utf8");
|
|
25808
26243
|
const contentHash = hashString2(rawContent);
|
|
25809
26244
|
const marker = formatProvenanceMarker(
|
|
25810
26245
|
"markdown",
|
|
25811
|
-
|
|
26246
|
+
path33.basename(config.source.instructions),
|
|
25812
26247
|
contentHash,
|
|
25813
26248
|
"copilot"
|
|
25814
26249
|
);
|
|
25815
26250
|
const composedContent = `${marker}
|
|
25816
26251
|
${rawContent}`;
|
|
25817
26252
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
25818
|
-
const agentsMdDest =
|
|
25819
|
-
const mirrorDest =
|
|
26253
|
+
const agentsMdDest = path33.resolve(projectRoot, "AGENTS.md");
|
|
26254
|
+
const mirrorDest = path33.resolve(
|
|
25820
26255
|
projectRoot,
|
|
25821
26256
|
".github",
|
|
25822
26257
|
"copilot-instructions.md"
|
|
@@ -25870,17 +26305,17 @@ function writeInstructionsFile(component, destination, content, contentHash, con
|
|
|
25870
26305
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
25871
26306
|
return { component, status: "conflict", path: destination };
|
|
25872
26307
|
}
|
|
25873
|
-
ensureDir(
|
|
25874
|
-
|
|
26308
|
+
ensureDir(path33.dirname(destination));
|
|
26309
|
+
fs33.writeFileSync(destination, content);
|
|
25875
26310
|
return { component, status: "success", path: destination };
|
|
25876
26311
|
}
|
|
25877
26312
|
function hashString2(value) {
|
|
25878
26313
|
return `sha256:${crypto6.createHash("sha256").update(value).digest("hex")}`;
|
|
25879
26314
|
}
|
|
25880
26315
|
function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
25881
|
-
const source =
|
|
26316
|
+
const source = path33.resolve(sourceRoot, config.source.skills);
|
|
25882
26317
|
const destination = resolveTargetPath(paths.skills);
|
|
25883
|
-
if (!
|
|
26318
|
+
if (!fs33.existsSync(source)) {
|
|
25884
26319
|
return skippedMissingSource2("skills", source);
|
|
25885
26320
|
}
|
|
25886
26321
|
if (options.dryRun) {
|
|
@@ -25896,27 +26331,27 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
25896
26331
|
};
|
|
25897
26332
|
}
|
|
25898
26333
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
25899
|
-
|
|
26334
|
+
fs33.unlinkSync(destination);
|
|
25900
26335
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
25901
26336
|
return { component: "skills", status: "conflict", path: destination };
|
|
25902
26337
|
} else if (artifactClass === "managed-symlink") {
|
|
25903
|
-
|
|
26338
|
+
fs33.unlinkSync(destination);
|
|
25904
26339
|
}
|
|
25905
|
-
ensureDir(
|
|
26340
|
+
ensureDir(path33.dirname(destination));
|
|
25906
26341
|
createRelativeSymlink(source, destination, "dir");
|
|
25907
26342
|
return { component: "skills", status: "success", path: destination };
|
|
25908
26343
|
}
|
|
25909
26344
|
function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
25910
|
-
const sourceAgentsRoot =
|
|
25911
|
-
if (!
|
|
26345
|
+
const sourceAgentsRoot = path33.join(sourceRoot, config.source.agents);
|
|
26346
|
+
if (!fs33.existsSync(sourceAgentsRoot)) {
|
|
25912
26347
|
return [skippedMissingSource2("agents", sourceAgentsRoot)];
|
|
25913
26348
|
}
|
|
25914
|
-
const sourceAgents = ts(
|
|
26349
|
+
const sourceAgents = ts(path33.join(sourceAgentsRoot, "*.md")).sort();
|
|
25915
26350
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
25916
26351
|
return sourceAgents.map((agentFile) => {
|
|
25917
|
-
const destination =
|
|
26352
|
+
const destination = path33.join(
|
|
25918
26353
|
agentsRoot,
|
|
25919
|
-
`${
|
|
26354
|
+
`${path33.basename(agentFile, ".md")}.agent.md`
|
|
25920
26355
|
);
|
|
25921
26356
|
const compiled = compileAgent(
|
|
25922
26357
|
agentFile,
|
|
@@ -25944,16 +26379,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
25944
26379
|
});
|
|
25945
26380
|
}
|
|
25946
26381
|
function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
25947
|
-
const sourceCommandsRoot =
|
|
25948
|
-
if (!
|
|
26382
|
+
const sourceCommandsRoot = path33.join(sourceRoot, config.source.commands);
|
|
26383
|
+
if (!fs33.existsSync(sourceCommandsRoot)) {
|
|
25949
26384
|
return [skippedMissingSource2("commands", sourceCommandsRoot)];
|
|
25950
26385
|
}
|
|
25951
|
-
const sourceCommands = ts(
|
|
26386
|
+
const sourceCommands = ts(path33.join(sourceCommandsRoot, "*.md")).sort();
|
|
25952
26387
|
const promptsRoot = resolveTargetPath(paths.prompts);
|
|
25953
26388
|
return sourceCommands.map((commandFile) => {
|
|
25954
|
-
const destination =
|
|
26389
|
+
const destination = path33.join(
|
|
25955
26390
|
promptsRoot,
|
|
25956
|
-
`${
|
|
26391
|
+
`${path33.basename(commandFile, ".md")}.prompt.md`
|
|
25957
26392
|
);
|
|
25958
26393
|
const compiled = compileCommandPrompt(commandFile);
|
|
25959
26394
|
if (options.dryRun) {
|
|
@@ -25979,14 +26414,14 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
|
|
|
25979
26414
|
function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, logger) {
|
|
25980
26415
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
25981
26416
|
const sourceLabel = hooksSourceLabel(config);
|
|
25982
|
-
const destination =
|
|
26417
|
+
const destination = path33.join(
|
|
25983
26418
|
resolveTargetPath(paths.hooks),
|
|
25984
26419
|
"tangyr-managed.json"
|
|
25985
26420
|
);
|
|
25986
|
-
if (!
|
|
26421
|
+
if (!fs33.existsSync(source)) {
|
|
25987
26422
|
return skippedMissingSource2("hooks", source);
|
|
25988
26423
|
}
|
|
25989
|
-
const sourceHooksJson = JSON.parse(
|
|
26424
|
+
const sourceHooksJson = JSON.parse(fs33.readFileSync(source, "utf8"));
|
|
25990
26425
|
const compiled = compileHooks(
|
|
25991
26426
|
sourceHooksJson,
|
|
25992
26427
|
"copilot",
|
|
@@ -26023,10 +26458,10 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger) {
|
|
|
26023
26458
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
26024
26459
|
const sourceLabel = mcpSourceLabel(config);
|
|
26025
26460
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
26026
|
-
if (!
|
|
26461
|
+
if (!fs33.existsSync(source)) {
|
|
26027
26462
|
return skippedMissingSource2("mcp", source);
|
|
26028
26463
|
}
|
|
26029
|
-
const sourceMcpJson = JSON.parse(
|
|
26464
|
+
const sourceMcpJson = JSON.parse(fs33.readFileSync(source, "utf8"));
|
|
26030
26465
|
const compiled = compileMcp(
|
|
26031
26466
|
sourceMcpJson,
|
|
26032
26467
|
"copilot",
|
|
@@ -26056,13 +26491,13 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
|
|
|
26056
26491
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26057
26492
|
return { component, status: "conflict", path: destination };
|
|
26058
26493
|
}
|
|
26059
|
-
ensureDir(
|
|
26060
|
-
|
|
26494
|
+
ensureDir(path33.dirname(destination));
|
|
26495
|
+
fs33.writeFileSync(destination, content);
|
|
26061
26496
|
return { component, status: "success", path: destination };
|
|
26062
26497
|
}
|
|
26063
26498
|
function isCompiledCurrent2(destination, expectedContent, expectedHash) {
|
|
26064
26499
|
try {
|
|
26065
|
-
const current =
|
|
26500
|
+
const current = fs33.readFileSync(destination, "utf8");
|
|
26066
26501
|
const marker = extractProvenanceMarker(current);
|
|
26067
26502
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "copilot" && current === expectedContent : current === expectedContent;
|
|
26068
26503
|
} catch {
|
|
@@ -26085,11 +26520,11 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
|
|
|
26085
26520
|
backupFile(destination, manifest);
|
|
26086
26521
|
writeManifest(scopePath, manifest);
|
|
26087
26522
|
} else {
|
|
26088
|
-
|
|
26523
|
+
fs33.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
26089
26524
|
}
|
|
26090
26525
|
return true;
|
|
26091
26526
|
}
|
|
26092
|
-
|
|
26527
|
+
fs33.rmSync(destination, { recursive: true, force: true });
|
|
26093
26528
|
return true;
|
|
26094
26529
|
}
|
|
26095
26530
|
function shouldSkipComponent2(options, component) {
|
|
@@ -26098,12 +26533,12 @@ function shouldSkipComponent2(options, component) {
|
|
|
26098
26533
|
function cleanupLegacyAgents(paths, options, logger) {
|
|
26099
26534
|
const currentAgentsRoot = resolveTargetPath(paths.agents);
|
|
26100
26535
|
const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
|
|
26101
|
-
if (
|
|
26536
|
+
if (path33.resolve(currentAgentsRoot) === path33.resolve(legacyAgentsRoot)) {
|
|
26102
26537
|
return [];
|
|
26103
26538
|
}
|
|
26104
26539
|
const outcomes = [];
|
|
26105
26540
|
for (const filePath of ts(
|
|
26106
|
-
|
|
26541
|
+
path33.join(legacyAgentsRoot, "*.agent.md")
|
|
26107
26542
|
).sort()) {
|
|
26108
26543
|
if (!isCopilotManagedCompiledFile(filePath)) {
|
|
26109
26544
|
continue;
|
|
@@ -26113,14 +26548,14 @@ function cleanupLegacyAgents(paths, options, logger) {
|
|
|
26113
26548
|
outcomes.push({ component: "agents", status: "dry-run", path: filePath });
|
|
26114
26549
|
continue;
|
|
26115
26550
|
}
|
|
26116
|
-
|
|
26551
|
+
fs33.rmSync(filePath, { force: true });
|
|
26117
26552
|
outcomes.push({ component: "agents", status: "success", path: filePath });
|
|
26118
26553
|
}
|
|
26119
26554
|
return outcomes;
|
|
26120
26555
|
}
|
|
26121
26556
|
function isCopilotManagedCompiledFile(filePath) {
|
|
26122
26557
|
try {
|
|
26123
|
-
return extractProvenanceMarker(
|
|
26558
|
+
return extractProvenanceMarker(fs33.readFileSync(filePath, "utf8"))?.target === "copilot";
|
|
26124
26559
|
} catch {
|
|
26125
26560
|
return false;
|
|
26126
26561
|
}
|
|
@@ -26134,7 +26569,7 @@ function skippedMissingSource2(component, source) {
|
|
|
26134
26569
|
}
|
|
26135
26570
|
function isSymlinkTo2(linkPath, source) {
|
|
26136
26571
|
try {
|
|
26137
|
-
return
|
|
26572
|
+
return fs33.realpathSync(linkPath) === fs33.realpathSync(source);
|
|
26138
26573
|
} catch {
|
|
26139
26574
|
return false;
|
|
26140
26575
|
}
|
|
@@ -26142,8 +26577,8 @@ function isSymlinkTo2(linkPath, source) {
|
|
|
26142
26577
|
|
|
26143
26578
|
// src/adapters/cursor.ts
|
|
26144
26579
|
import crypto7 from "crypto";
|
|
26145
|
-
import
|
|
26146
|
-
import
|
|
26580
|
+
import fs34 from "fs";
|
|
26581
|
+
import path34 from "path";
|
|
26147
26582
|
function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26148
26583
|
const scope = options.scope ?? "global";
|
|
26149
26584
|
const profile = resolveTargetPaths({
|
|
@@ -26294,9 +26729,9 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
|
|
|
26294
26729
|
return { target: "cursor", outcomes };
|
|
26295
26730
|
}
|
|
26296
26731
|
function syncInstructions2(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
26297
|
-
const source =
|
|
26732
|
+
const source = path34.join(sourceRoot, config.source.instructions);
|
|
26298
26733
|
const destination = resolveTargetPath(paths.instructions);
|
|
26299
|
-
const baseContent =
|
|
26734
|
+
const baseContent = fs34.existsSync(source) ? fs34.readFileSync(source, "utf8").trim() : "";
|
|
26300
26735
|
const personaContent = extractPrimaryPersonaContent(
|
|
26301
26736
|
config,
|
|
26302
26737
|
sourceRoot,
|
|
@@ -26309,7 +26744,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
|
|
|
26309
26744
|
${personaContent}`.trim() : baseContent;
|
|
26310
26745
|
const marker = formatProvenanceMarker(
|
|
26311
26746
|
"markdown",
|
|
26312
|
-
|
|
26747
|
+
path34.basename(config.source.instructions),
|
|
26313
26748
|
hashString3(composed),
|
|
26314
26749
|
"cursor"
|
|
26315
26750
|
);
|
|
@@ -26334,11 +26769,11 @@ ${composed}
|
|
|
26334
26769
|
);
|
|
26335
26770
|
}
|
|
26336
26771
|
function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
26337
|
-
const agentsDir =
|
|
26338
|
-
if (!
|
|
26772
|
+
const agentsDir = path34.join(sourceRoot, config.source.agents);
|
|
26773
|
+
if (!fs34.existsSync(agentsDir)) {
|
|
26339
26774
|
return null;
|
|
26340
26775
|
}
|
|
26341
|
-
const agentFiles = ts(
|
|
26776
|
+
const agentFiles = ts(path34.join(agentsDir, "*.md")).sort();
|
|
26342
26777
|
if (agentFiles.length === 0) {
|
|
26343
26778
|
return null;
|
|
26344
26779
|
}
|
|
@@ -26361,7 +26796,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
26361
26796
|
return null;
|
|
26362
26797
|
}
|
|
26363
26798
|
addLoss(lossReport, "cursor", "instructions", {
|
|
26364
|
-
source: `agents/${
|
|
26799
|
+
source: `agents/${path34.basename(primaryFile)}`,
|
|
26365
26800
|
fields: [
|
|
26366
26801
|
{
|
|
26367
26802
|
field: "persona",
|
|
@@ -26371,23 +26806,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
26371
26806
|
"persona",
|
|
26372
26807
|
"instructions-shim"
|
|
26373
26808
|
),
|
|
26374
|
-
detail: `Primary persona from ${
|
|
26809
|
+
detail: `Primary persona from ${path34.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
|
|
26375
26810
|
}
|
|
26376
26811
|
]
|
|
26377
26812
|
});
|
|
26378
26813
|
return body.trim();
|
|
26379
26814
|
}
|
|
26380
26815
|
function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26381
|
-
const sourceAgentsRoot =
|
|
26382
|
-
if (!
|
|
26816
|
+
const sourceAgentsRoot = path34.join(sourceRoot, config.source.agents);
|
|
26817
|
+
if (!fs34.existsSync(sourceAgentsRoot)) {
|
|
26383
26818
|
return [skippedMissingSource3("agents", sourceAgentsRoot)];
|
|
26384
26819
|
}
|
|
26385
|
-
const sourceAgents = ts(
|
|
26820
|
+
const sourceAgents = ts(path34.join(sourceAgentsRoot, "*.md")).sort();
|
|
26386
26821
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
26387
26822
|
return sourceAgents.map((agentFile) => {
|
|
26388
|
-
const destination =
|
|
26823
|
+
const destination = path34.join(
|
|
26389
26824
|
agentsRoot,
|
|
26390
|
-
`${
|
|
26825
|
+
`${path34.basename(agentFile, ".md")}.md`
|
|
26391
26826
|
);
|
|
26392
26827
|
let compiled;
|
|
26393
26828
|
try {
|
|
@@ -26428,14 +26863,14 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
26428
26863
|
});
|
|
26429
26864
|
}
|
|
26430
26865
|
function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
26431
|
-
const sourceRulesDir =
|
|
26432
|
-
if (!
|
|
26866
|
+
const sourceRulesDir = path34.join(sourceRoot, config.source.rules);
|
|
26867
|
+
if (!fs34.existsSync(sourceRulesDir)) {
|
|
26433
26868
|
return [skippedMissingSource3("rules", sourceRulesDir)];
|
|
26434
26869
|
}
|
|
26435
26870
|
const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
|
|
26436
26871
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
26437
26872
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
26438
|
-
const destination =
|
|
26873
|
+
const destination = path34.join(rulesDir, name);
|
|
26439
26874
|
if (options.dryRun) {
|
|
26440
26875
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
26441
26876
|
return {
|
|
@@ -26459,17 +26894,17 @@ function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26459
26894
|
});
|
|
26460
26895
|
}
|
|
26461
26896
|
function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26462
|
-
const sourceCommandsRoot =
|
|
26463
|
-
if (!
|
|
26897
|
+
const sourceCommandsRoot = path34.join(sourceRoot, config.source.commands);
|
|
26898
|
+
if (!fs34.existsSync(sourceCommandsRoot)) {
|
|
26464
26899
|
return [skippedMissingSource3("commands", sourceCommandsRoot)];
|
|
26465
26900
|
}
|
|
26466
|
-
const sourceCommands = ts(
|
|
26901
|
+
const sourceCommands = ts(path34.join(sourceCommandsRoot, "*.md")).sort();
|
|
26467
26902
|
const skillsRoot = resolveTargetPath(paths.skills);
|
|
26468
26903
|
return sourceCommands.map((commandFile) => {
|
|
26469
|
-
const baseName =
|
|
26470
|
-
const destination =
|
|
26471
|
-
const commandContent =
|
|
26472
|
-
const relativeSource = `commands/${
|
|
26904
|
+
const baseName = path34.basename(commandFile, ".md");
|
|
26905
|
+
const destination = path34.join(skillsRoot, baseName, "SKILL.md");
|
|
26906
|
+
const commandContent = fs34.readFileSync(commandFile, "utf8");
|
|
26907
|
+
const relativeSource = `commands/${path34.basename(commandFile)}`;
|
|
26473
26908
|
const marker = formatProvenanceMarker(
|
|
26474
26909
|
"markdown",
|
|
26475
26910
|
relativeSource,
|
|
@@ -26508,8 +26943,8 @@ ${commandContent.trim()}
|
|
|
26508
26943
|
});
|
|
26509
26944
|
}
|
|
26510
26945
|
function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
|
|
26511
|
-
const source =
|
|
26512
|
-
if (!
|
|
26946
|
+
const source = path34.resolve(sourceRoot, config.source.skills);
|
|
26947
|
+
if (!fs34.existsSync(source)) {
|
|
26513
26948
|
return skippedMissingSource3(component, source);
|
|
26514
26949
|
}
|
|
26515
26950
|
if (options.dryRun) {
|
|
@@ -26523,18 +26958,18 @@ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, c
|
|
|
26523
26958
|
return { component, status: "skipped-current", path: destination };
|
|
26524
26959
|
}
|
|
26525
26960
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26526
|
-
|
|
26961
|
+
fs34.unlinkSync(destination);
|
|
26527
26962
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
26528
26963
|
return { component, status: "conflict", path: destination };
|
|
26529
26964
|
} else if (artifactClass === "managed-symlink") {
|
|
26530
|
-
|
|
26965
|
+
fs34.unlinkSync(destination);
|
|
26531
26966
|
}
|
|
26532
|
-
ensureDir(
|
|
26967
|
+
ensureDir(path34.dirname(destination));
|
|
26533
26968
|
createRelativeSymlink(source, destination, "dir");
|
|
26534
26969
|
logger.verbose(`Skills: created shared skills symlink ${destination}`);
|
|
26535
26970
|
return { component, status: "success", path: destination };
|
|
26536
26971
|
}
|
|
26537
|
-
if (
|
|
26972
|
+
if (fs34.existsSync(destination)) {
|
|
26538
26973
|
return { component, status: "skipped-current", path: destination };
|
|
26539
26974
|
}
|
|
26540
26975
|
ensureDir(destination);
|
|
@@ -26545,7 +26980,7 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26545
26980
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
26546
26981
|
const sourceLabel = hooksSourceLabel(config);
|
|
26547
26982
|
const destination = resolveTargetPath(paths.hooks_file);
|
|
26548
|
-
const sourceHooksJson =
|
|
26983
|
+
const sourceHooksJson = fs34.existsSync(source) ? JSON.parse(fs34.readFileSync(source, "utf8")) : { hooks: {} };
|
|
26549
26984
|
const compiled = compileHooks(
|
|
26550
26985
|
sourceHooksJson,
|
|
26551
26986
|
"cursor",
|
|
@@ -26559,18 +26994,18 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26559
26994
|
}
|
|
26560
26995
|
const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
|
|
26561
26996
|
`;
|
|
26562
|
-
ensureDir(
|
|
26563
|
-
|
|
26997
|
+
ensureDir(path34.dirname(destination));
|
|
26998
|
+
fs34.writeFileSync(destination, hooksFileContent);
|
|
26564
26999
|
return { component: "hooks", status: "success", path: destination };
|
|
26565
27000
|
}
|
|
26566
27001
|
function syncMcp3(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
26567
27002
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
26568
27003
|
const sourceLabel = mcpSourceLabel(config);
|
|
26569
27004
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
26570
|
-
if (!
|
|
27005
|
+
if (!fs34.existsSync(source)) {
|
|
26571
27006
|
return skippedMissingSource3("mcp", source);
|
|
26572
27007
|
}
|
|
26573
|
-
const sourceMcpJson = JSON.parse(
|
|
27008
|
+
const sourceMcpJson = JSON.parse(fs34.readFileSync(source, "utf8"));
|
|
26574
27009
|
const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
|
|
26575
27010
|
if (options.dryRun) {
|
|
26576
27011
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -26621,13 +27056,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
|
|
|
26621
27056
|
);
|
|
26622
27057
|
}
|
|
26623
27058
|
function syncProviderPin(config, sourceRoot, lossReport) {
|
|
26624
|
-
const agentsDir =
|
|
26625
|
-
if (!
|
|
26626
|
-
for (const agentFile of ts(
|
|
27059
|
+
const agentsDir = path34.join(sourceRoot, config.source.agents);
|
|
27060
|
+
if (!fs34.existsSync(agentsDir)) return;
|
|
27061
|
+
for (const agentFile of ts(path34.join(agentsDir, "*.md")).sort()) {
|
|
26627
27062
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
26628
27063
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
26629
27064
|
if (hasCustomProvider) {
|
|
26630
|
-
const relativeSource = `agents/${
|
|
27065
|
+
const relativeSource = `agents/${path34.basename(agentFile)}`;
|
|
26631
27066
|
addLoss(lossReport, "cursor", "agents", {
|
|
26632
27067
|
source: relativeSource,
|
|
26633
27068
|
fields: [
|
|
@@ -26639,7 +27074,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
|
|
|
26639
27074
|
"provider",
|
|
26640
27075
|
"provider-not-representable"
|
|
26641
27076
|
),
|
|
26642
|
-
detail: `${
|
|
27077
|
+
detail: `${path34.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
26643
27078
|
}
|
|
26644
27079
|
]
|
|
26645
27080
|
});
|
|
@@ -26654,8 +27089,8 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
|
|
|
26654
27089
|
if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
26655
27090
|
return { component, status: "conflict", path: destination };
|
|
26656
27091
|
}
|
|
26657
|
-
ensureDir(
|
|
26658
|
-
|
|
27092
|
+
ensureDir(path34.dirname(destination));
|
|
27093
|
+
fs34.writeFileSync(destination, content);
|
|
26659
27094
|
return { component, status: "success", path: destination };
|
|
26660
27095
|
}
|
|
26661
27096
|
function handleConflict3(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -26674,16 +27109,16 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
|
|
|
26674
27109
|
backupFile(destination, manifest);
|
|
26675
27110
|
writeManifest(scopePath, manifest);
|
|
26676
27111
|
} else {
|
|
26677
|
-
|
|
27112
|
+
fs34.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
26678
27113
|
}
|
|
26679
27114
|
return true;
|
|
26680
27115
|
}
|
|
26681
|
-
|
|
27116
|
+
fs34.rmSync(destination, { recursive: true, force: true });
|
|
26682
27117
|
return true;
|
|
26683
27118
|
}
|
|
26684
27119
|
function isCompiledCurrent3(destination, expectedContent, expectedHash) {
|
|
26685
27120
|
try {
|
|
26686
|
-
const current =
|
|
27121
|
+
const current = fs34.readFileSync(destination, "utf8");
|
|
26687
27122
|
const marker = extractProvenanceMarker(current);
|
|
26688
27123
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "cursor" && current === expectedContent : current === expectedContent;
|
|
26689
27124
|
} catch {
|
|
@@ -26702,7 +27137,7 @@ function shouldSkipComponent3(options, component) {
|
|
|
26702
27137
|
}
|
|
26703
27138
|
function isSymlinkTo3(linkPath, source) {
|
|
26704
27139
|
try {
|
|
26705
|
-
return
|
|
27140
|
+
return fs34.realpathSync(linkPath) === fs34.realpathSync(source);
|
|
26706
27141
|
} catch {
|
|
26707
27142
|
return false;
|
|
26708
27143
|
}
|
|
@@ -26713,8 +27148,8 @@ function hashString3(value) {
|
|
|
26713
27148
|
|
|
26714
27149
|
// src/adapters/cline.ts
|
|
26715
27150
|
import crypto8 from "crypto";
|
|
26716
|
-
import
|
|
26717
|
-
import
|
|
27151
|
+
import fs35 from "fs";
|
|
27152
|
+
import path35 from "path";
|
|
26718
27153
|
function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26719
27154
|
const scope = options.scope ?? "global";
|
|
26720
27155
|
const profile = resolveTargetPaths({
|
|
@@ -26827,7 +27262,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
26827
27262
|
function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
|
|
26828
27263
|
if (scope === "global" || paths.instructions === null) {
|
|
26829
27264
|
addLoss(lossReport, "cline", "instructions", {
|
|
26830
|
-
source:
|
|
27265
|
+
source: path35.basename(config.source.instructions),
|
|
26831
27266
|
fields: [
|
|
26832
27267
|
{
|
|
26833
27268
|
field: "instructions",
|
|
@@ -26847,12 +27282,12 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
|
|
|
26847
27282
|
path: "cline/global/instructions: no committable global path"
|
|
26848
27283
|
};
|
|
26849
27284
|
}
|
|
26850
|
-
const source =
|
|
27285
|
+
const source = path35.join(sourceRoot, config.source.instructions);
|
|
26851
27286
|
const destination = resolveTargetPath(paths.instructions);
|
|
26852
|
-
const baseContent =
|
|
27287
|
+
const baseContent = fs35.existsSync(source) ? fs35.readFileSync(source, "utf8").trim() : "";
|
|
26853
27288
|
const marker = formatProvenanceMarker(
|
|
26854
27289
|
"markdown",
|
|
26855
|
-
|
|
27290
|
+
path35.basename(config.source.instructions),
|
|
26856
27291
|
hashString4(baseContent),
|
|
26857
27292
|
"cline"
|
|
26858
27293
|
);
|
|
@@ -26877,11 +27312,11 @@ ${baseContent}
|
|
|
26877
27312
|
);
|
|
26878
27313
|
}
|
|
26879
27314
|
function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
|
|
26880
|
-
const sourceAgentsRoot =
|
|
26881
|
-
if (!
|
|
27315
|
+
const sourceAgentsRoot = path35.join(sourceRoot, config.source.agents);
|
|
27316
|
+
if (!fs35.existsSync(sourceAgentsRoot)) {
|
|
26882
27317
|
return [skippedMissingSource4("agents", sourceAgentsRoot)];
|
|
26883
27318
|
}
|
|
26884
|
-
const sourceAgents = ts(
|
|
27319
|
+
const sourceAgents = ts(path35.join(sourceAgentsRoot, "*.md")).sort();
|
|
26885
27320
|
return sourceAgents.map((agentFile) => {
|
|
26886
27321
|
compileAgent(agentFile, "cline", mappings, extensions, lossReport);
|
|
26887
27322
|
if (options.dryRun) {
|
|
@@ -26897,14 +27332,14 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
26897
27332
|
});
|
|
26898
27333
|
}
|
|
26899
27334
|
function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
26900
|
-
const sourceRulesDir =
|
|
26901
|
-
if (!
|
|
27335
|
+
const sourceRulesDir = path35.join(sourceRoot, config.source.rules);
|
|
27336
|
+
if (!fs35.existsSync(sourceRulesDir)) {
|
|
26902
27337
|
return [skippedMissingSource4("rules", sourceRulesDir)];
|
|
26903
27338
|
}
|
|
26904
27339
|
const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
|
|
26905
27340
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
26906
27341
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
26907
|
-
const destination =
|
|
27342
|
+
const destination = path35.join(rulesDir, name);
|
|
26908
27343
|
if (options.dryRun) {
|
|
26909
27344
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
26910
27345
|
return {
|
|
@@ -26928,17 +27363,17 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26928
27363
|
});
|
|
26929
27364
|
}
|
|
26930
27365
|
function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26931
|
-
const sourceCommandsRoot =
|
|
26932
|
-
if (!
|
|
27366
|
+
const sourceCommandsRoot = path35.join(sourceRoot, config.source.commands);
|
|
27367
|
+
if (!fs35.existsSync(sourceCommandsRoot)) {
|
|
26933
27368
|
return [skippedMissingSource4("commands", sourceCommandsRoot)];
|
|
26934
27369
|
}
|
|
26935
|
-
const sourceCommands = ts(
|
|
27370
|
+
const sourceCommands = ts(path35.join(sourceCommandsRoot, "*.md")).sort();
|
|
26936
27371
|
const workflowsRoot = resolveTargetPath(paths.workflows);
|
|
26937
27372
|
return sourceCommands.map((commandFile) => {
|
|
26938
|
-
const baseName =
|
|
26939
|
-
const destination =
|
|
26940
|
-
const commandContent =
|
|
26941
|
-
const relativeSource = `commands/${
|
|
27373
|
+
const baseName = path35.basename(commandFile);
|
|
27374
|
+
const destination = path35.join(workflowsRoot, baseName);
|
|
27375
|
+
const commandContent = fs35.readFileSync(commandFile, "utf8");
|
|
27376
|
+
const relativeSource = `commands/${path35.basename(commandFile)}`;
|
|
26942
27377
|
const marker = formatProvenanceMarker(
|
|
26943
27378
|
"markdown",
|
|
26944
27379
|
relativeSource,
|
|
@@ -26973,9 +27408,9 @@ ${commandContent.trim()}
|
|
|
26973
27408
|
});
|
|
26974
27409
|
}
|
|
26975
27410
|
function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26976
|
-
const source =
|
|
27411
|
+
const source = path35.resolve(sourceRoot, config.source.skills);
|
|
26977
27412
|
const destination = resolveTargetPath(paths.skills);
|
|
26978
|
-
if (!
|
|
27413
|
+
if (!fs35.existsSync(source)) {
|
|
26979
27414
|
return skippedMissingSource4("skills", source);
|
|
26980
27415
|
}
|
|
26981
27416
|
if (options.dryRun) {
|
|
@@ -26995,9 +27430,9 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
26995
27430
|
return { component: "skills", status: "conflict", path: destination };
|
|
26996
27431
|
}
|
|
26997
27432
|
} else if (artifactClass === "managed-symlink") {
|
|
26998
|
-
|
|
27433
|
+
fs35.unlinkSync(destination);
|
|
26999
27434
|
}
|
|
27000
|
-
ensureDir(
|
|
27435
|
+
ensureDir(path35.dirname(destination));
|
|
27001
27436
|
createRelativeSymlink(source, destination, "dir");
|
|
27002
27437
|
logger.verbose(`Skills: created Cline skills symlink ${destination}`);
|
|
27003
27438
|
return { component: "skills", status: "success", path: destination };
|
|
@@ -27005,7 +27440,7 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
27005
27440
|
function syncHooks4(config, sourceRoot, mappings, options, lossReport, logger) {
|
|
27006
27441
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
27007
27442
|
const sourceLabel = hooksSourceLabel(config);
|
|
27008
|
-
const sourceHooksJson =
|
|
27443
|
+
const sourceHooksJson = fs35.existsSync(source) ? JSON.parse(fs35.readFileSync(source, "utf8")) : { hooks: {} };
|
|
27009
27444
|
compileHooks(sourceHooksJson, "cline", mappings, lossReport, sourceLabel);
|
|
27010
27445
|
if (options.dryRun) {
|
|
27011
27446
|
logger.info(`[dry-run] hooks: record hook-as-plugin loss for ${source}`);
|
|
@@ -27020,10 +27455,10 @@ function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manife
|
|
|
27020
27455
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27021
27456
|
const sourceLabel = mcpSourceLabel(config);
|
|
27022
27457
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
27023
|
-
if (!
|
|
27458
|
+
if (!fs35.existsSync(source)) {
|
|
27024
27459
|
return skippedMissingSource4("mcp", source);
|
|
27025
27460
|
}
|
|
27026
|
-
const sourceMcpJson = JSON.parse(
|
|
27461
|
+
const sourceMcpJson = JSON.parse(fs35.readFileSync(source, "utf8"));
|
|
27027
27462
|
const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
|
|
27028
27463
|
if (options.dryRun) {
|
|
27029
27464
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -27066,11 +27501,11 @@ function syncSettings(lossReport) {
|
|
|
27066
27501
|
};
|
|
27067
27502
|
}
|
|
27068
27503
|
function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
27069
|
-
const agentsDir =
|
|
27070
|
-
if (!
|
|
27071
|
-
for (const agentFile of ts(
|
|
27504
|
+
const agentsDir = path35.join(sourceRoot, config.source.agents);
|
|
27505
|
+
if (!fs35.existsSync(agentsDir)) return;
|
|
27506
|
+
for (const agentFile of ts(path35.join(agentsDir, "*.md")).sort()) {
|
|
27072
27507
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
27073
|
-
const relativeSource = `agents/${
|
|
27508
|
+
const relativeSource = `agents/${path35.basename(agentFile)}`;
|
|
27074
27509
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
27075
27510
|
if (hasCustomProvider) {
|
|
27076
27511
|
addLoss(lossReport, "cline", "agents", {
|
|
@@ -27084,7 +27519,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
27084
27519
|
"provider",
|
|
27085
27520
|
"provider-not-representable"
|
|
27086
27521
|
),
|
|
27087
|
-
detail: `${
|
|
27522
|
+
detail: `${path35.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
|
|
27088
27523
|
}
|
|
27089
27524
|
]
|
|
27090
27525
|
});
|
|
@@ -27102,7 +27537,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
27102
27537
|
"model",
|
|
27103
27538
|
"model-not-representable"
|
|
27104
27539
|
),
|
|
27105
|
-
detail: `${
|
|
27540
|
+
detail: `${path35.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
|
|
27106
27541
|
}
|
|
27107
27542
|
]
|
|
27108
27543
|
});
|
|
@@ -27117,8 +27552,8 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
|
|
|
27117
27552
|
if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
|
|
27118
27553
|
return { component, status: "conflict", path: destination };
|
|
27119
27554
|
}
|
|
27120
|
-
ensureDir(
|
|
27121
|
-
|
|
27555
|
+
ensureDir(path35.dirname(destination));
|
|
27556
|
+
fs35.writeFileSync(destination, content);
|
|
27122
27557
|
return { component, status: "success", path: destination };
|
|
27123
27558
|
}
|
|
27124
27559
|
function handleConflict4(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -27137,16 +27572,16 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
|
|
|
27137
27572
|
backupFile(destination, manifest);
|
|
27138
27573
|
writeManifest(scopePath, manifest);
|
|
27139
27574
|
} else {
|
|
27140
|
-
|
|
27575
|
+
fs35.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
27141
27576
|
}
|
|
27142
27577
|
return true;
|
|
27143
27578
|
}
|
|
27144
|
-
|
|
27579
|
+
fs35.rmSync(destination, { recursive: true, force: true });
|
|
27145
27580
|
return true;
|
|
27146
27581
|
}
|
|
27147
27582
|
function isCompiledCurrent4(destination, expectedContent, expectedHash) {
|
|
27148
27583
|
try {
|
|
27149
|
-
const current =
|
|
27584
|
+
const current = fs35.readFileSync(destination, "utf8");
|
|
27150
27585
|
const marker = extractProvenanceMarker(current);
|
|
27151
27586
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "cline" && current === expectedContent : current === expectedContent;
|
|
27152
27587
|
} catch {
|
|
@@ -27165,7 +27600,7 @@ function shouldSkipComponent4(options, component) {
|
|
|
27165
27600
|
}
|
|
27166
27601
|
function isSymlinkTo4(linkPath, source) {
|
|
27167
27602
|
try {
|
|
27168
|
-
return
|
|
27603
|
+
return fs35.realpathSync(linkPath) === fs35.realpathSync(source);
|
|
27169
27604
|
} catch {
|
|
27170
27605
|
return false;
|
|
27171
27606
|
}
|
|
@@ -27176,9 +27611,9 @@ function hashString4(value) {
|
|
|
27176
27611
|
|
|
27177
27612
|
// src/adapters/opencode.ts
|
|
27178
27613
|
import crypto9 from "crypto";
|
|
27179
|
-
import
|
|
27614
|
+
import fs36 from "fs";
|
|
27180
27615
|
import os6 from "os";
|
|
27181
|
-
import
|
|
27616
|
+
import path36 from "path";
|
|
27182
27617
|
var import_yaml10 = __toESM(require_dist(), 1);
|
|
27183
27618
|
function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27184
27619
|
const scope = options.scope ?? "global";
|
|
@@ -27196,7 +27631,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
27196
27631
|
config_doc: profile.config_doc
|
|
27197
27632
|
};
|
|
27198
27633
|
const rules = compileRules(
|
|
27199
|
-
|
|
27634
|
+
path36.join(sourceRoot, config.source.rules),
|
|
27200
27635
|
"opencode",
|
|
27201
27636
|
mappings,
|
|
27202
27637
|
lossReport
|
|
@@ -27298,16 +27733,16 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
27298
27733
|
return { target: "opencode", outcomes };
|
|
27299
27734
|
}
|
|
27300
27735
|
function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
27301
|
-
const source =
|
|
27736
|
+
const source = path36.join(sourceRoot, config.source.instructions);
|
|
27302
27737
|
const destination = resolveTargetPath(paths.instructions);
|
|
27303
|
-
const baseContent =
|
|
27738
|
+
const baseContent = fs36.existsSync(source) ? fs36.readFileSync(source, "utf8").trim() : "";
|
|
27304
27739
|
const composed = agentsAppendix ? `${baseContent}
|
|
27305
27740
|
|
|
27306
27741
|
--- tangyr managed rules ---
|
|
27307
27742
|
${agentsAppendix}`.trim() : baseContent;
|
|
27308
27743
|
const marker = formatProvenanceMarker(
|
|
27309
27744
|
"markdown",
|
|
27310
|
-
|
|
27745
|
+
path36.basename(config.source.instructions),
|
|
27311
27746
|
hashString5(composed),
|
|
27312
27747
|
"opencode"
|
|
27313
27748
|
);
|
|
@@ -27334,16 +27769,16 @@ ${composed}
|
|
|
27334
27769
|
);
|
|
27335
27770
|
}
|
|
27336
27771
|
function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27337
|
-
const sourceAgentsRoot =
|
|
27338
|
-
if (!
|
|
27772
|
+
const sourceAgentsRoot = path36.join(sourceRoot, config.source.agents);
|
|
27773
|
+
if (!fs36.existsSync(sourceAgentsRoot)) {
|
|
27339
27774
|
return [skippedMissingSource5("agents", sourceAgentsRoot)];
|
|
27340
27775
|
}
|
|
27341
|
-
const sourceAgents = ts(
|
|
27776
|
+
const sourceAgents = ts(path36.join(sourceAgentsRoot, "*.md")).sort();
|
|
27342
27777
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
27343
27778
|
return sourceAgents.map((agentFile) => {
|
|
27344
|
-
const destination =
|
|
27779
|
+
const destination = path36.join(
|
|
27345
27780
|
agentsRoot,
|
|
27346
|
-
`${
|
|
27781
|
+
`${path36.basename(agentFile, ".md")}.md`
|
|
27347
27782
|
);
|
|
27348
27783
|
let compiled;
|
|
27349
27784
|
try {
|
|
@@ -27407,11 +27842,11 @@ function applyProviderModelBinding(compiled, mappings) {
|
|
|
27407
27842
|
return `${before}${(0, import_yaml10.stringify)(fields).trim()}${after}`;
|
|
27408
27843
|
}
|
|
27409
27844
|
function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27410
|
-
const sourceCommandsRoot =
|
|
27411
|
-
if (!
|
|
27845
|
+
const sourceCommandsRoot = path36.join(sourceRoot, config.source.commands);
|
|
27846
|
+
if (!fs36.existsSync(sourceCommandsRoot)) {
|
|
27412
27847
|
return [skippedMissingSource5("commands", sourceCommandsRoot)];
|
|
27413
27848
|
}
|
|
27414
|
-
const sourceCommands = ts(
|
|
27849
|
+
const sourceCommands = ts(path36.join(sourceCommandsRoot, "*.md")).sort();
|
|
27415
27850
|
const commandsRoot = resolveTargetPath(paths.commands);
|
|
27416
27851
|
return sourceCommands.map((commandFile) => {
|
|
27417
27852
|
const { data, body } = parseCommandFile(commandFile);
|
|
@@ -27425,7 +27860,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
|
|
|
27425
27860
|
if (typeof data.model === "string") {
|
|
27426
27861
|
frontmatter.model = data.model;
|
|
27427
27862
|
}
|
|
27428
|
-
const relativeSource = `commands/${
|
|
27863
|
+
const relativeSource = `commands/${path36.basename(commandFile)}`;
|
|
27429
27864
|
const marker = formatProvenanceMarker(
|
|
27430
27865
|
"markdown",
|
|
27431
27866
|
relativeSource,
|
|
@@ -27441,9 +27876,9 @@ ${body.trimEnd()}
|
|
|
27441
27876
|
` : `${marker}
|
|
27442
27877
|
${body.trimEnd()}
|
|
27443
27878
|
`;
|
|
27444
|
-
const destination =
|
|
27879
|
+
const destination = path36.join(
|
|
27445
27880
|
commandsRoot,
|
|
27446
|
-
`${
|
|
27881
|
+
`${path36.basename(commandFile, ".md")}.md`
|
|
27447
27882
|
);
|
|
27448
27883
|
if (options.dryRun) {
|
|
27449
27884
|
logger.info(
|
|
@@ -27470,8 +27905,8 @@ ${body.trimEnd()}
|
|
|
27470
27905
|
});
|
|
27471
27906
|
}
|
|
27472
27907
|
function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, component = "skills", destination = "") {
|
|
27473
|
-
const source =
|
|
27474
|
-
if (!
|
|
27908
|
+
const source = path36.resolve(sourceRoot, config.source.skills);
|
|
27909
|
+
if (!fs36.existsSync(source)) {
|
|
27475
27910
|
return skippedMissingSource5(component, source);
|
|
27476
27911
|
}
|
|
27477
27912
|
if (options.dryRun) {
|
|
@@ -27483,13 +27918,13 @@ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scop
|
|
|
27483
27918
|
return { component, status: "skipped-current", path: destination };
|
|
27484
27919
|
}
|
|
27485
27920
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
27486
|
-
|
|
27921
|
+
fs36.unlinkSync(destination);
|
|
27487
27922
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
27488
27923
|
return { component, status: "conflict", path: destination };
|
|
27489
27924
|
} else if (artifactClass === "managed-symlink") {
|
|
27490
|
-
|
|
27925
|
+
fs36.unlinkSync(destination);
|
|
27491
27926
|
}
|
|
27492
|
-
ensureDir(
|
|
27927
|
+
ensureDir(path36.dirname(destination));
|
|
27493
27928
|
createRelativeSymlink(source, destination, "dir");
|
|
27494
27929
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
27495
27930
|
return { component, status: "success", path: destination };
|
|
@@ -27498,13 +27933,13 @@ function syncMcp5(config, sourceRoot, paths, mappings, options, lossReport, logg
|
|
|
27498
27933
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27499
27934
|
const sourceLabel = mcpSourceLabel(config);
|
|
27500
27935
|
const destination = resolveTargetPath(paths.config_doc);
|
|
27501
|
-
if (!
|
|
27936
|
+
if (!fs36.existsSync(source)) {
|
|
27502
27937
|
if (!options.dryRun) {
|
|
27503
27938
|
syncConfigDoc(paths, {}, lossReport, {}, mappings);
|
|
27504
27939
|
}
|
|
27505
27940
|
return skippedMissingSource5("mcp", source);
|
|
27506
27941
|
}
|
|
27507
|
-
const sourceMcpJson = JSON.parse(
|
|
27942
|
+
const sourceMcpJson = JSON.parse(fs36.readFileSync(source, "utf8"));
|
|
27508
27943
|
const mcpJson = compileMcp(
|
|
27509
27944
|
sourceMcpJson,
|
|
27510
27945
|
"opencode",
|
|
@@ -27535,7 +27970,7 @@ function syncPermissions2(config, _sourceRoot, paths, options, lossReport, logge
|
|
|
27535
27970
|
function syncHooks5(config, sourceRoot, mappings, options, lossReport) {
|
|
27536
27971
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
27537
27972
|
const sourceLabel = hooksSourceLabel(config);
|
|
27538
|
-
const sourceHooksJson =
|
|
27973
|
+
const sourceHooksJson = fs36.existsSync(source) ? JSON.parse(fs36.readFileSync(source, "utf8")) : { hooks: {} };
|
|
27539
27974
|
compileHooks(sourceHooksJson, "opencode", mappings, lossReport, sourceLabel);
|
|
27540
27975
|
const message = "hooks: Skip \u2014 OpenCode exposes hooks only as plugin code (hook-as-plugin loss recorded)";
|
|
27541
27976
|
return { component: "hooks", status: "skipped", path: message };
|
|
@@ -27569,9 +28004,9 @@ function syncProviderBlock(mappings) {
|
|
|
27569
28004
|
function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
|
|
27570
28005
|
const destination = resolveTargetPath(paths.config_doc);
|
|
27571
28006
|
let existing = {};
|
|
27572
|
-
if (
|
|
28007
|
+
if (fs36.existsSync(destination)) {
|
|
27573
28008
|
try {
|
|
27574
|
-
existing = JSON.parse(
|
|
28009
|
+
existing = JSON.parse(fs36.readFileSync(destination, "utf8"));
|
|
27575
28010
|
} catch {
|
|
27576
28011
|
existing = {};
|
|
27577
28012
|
}
|
|
@@ -27596,8 +28031,8 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
|
|
|
27596
28031
|
};
|
|
27597
28032
|
}
|
|
27598
28033
|
}
|
|
27599
|
-
ensureDir(
|
|
27600
|
-
|
|
28034
|
+
ensureDir(path36.dirname(destination));
|
|
28035
|
+
fs36.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
|
|
27601
28036
|
`);
|
|
27602
28037
|
}
|
|
27603
28038
|
function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
|
|
@@ -27608,8 +28043,8 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
|
|
|
27608
28043
|
if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
27609
28044
|
return { component, status: "conflict", path: destination };
|
|
27610
28045
|
}
|
|
27611
|
-
ensureDir(
|
|
27612
|
-
|
|
28046
|
+
ensureDir(path36.dirname(destination));
|
|
28047
|
+
fs36.writeFileSync(destination, content);
|
|
27613
28048
|
return { component, status: "success", path: destination };
|
|
27614
28049
|
}
|
|
27615
28050
|
function handleConflict5(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -27628,16 +28063,16 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
|
|
|
27628
28063
|
backupFile(destination, manifest);
|
|
27629
28064
|
writeManifest(scopePath, manifest);
|
|
27630
28065
|
} else {
|
|
27631
|
-
|
|
28066
|
+
fs36.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
27632
28067
|
}
|
|
27633
28068
|
return true;
|
|
27634
28069
|
}
|
|
27635
|
-
|
|
28070
|
+
fs36.rmSync(destination, { recursive: true, force: true });
|
|
27636
28071
|
return true;
|
|
27637
28072
|
}
|
|
27638
28073
|
function isCompiledCurrent5(destination, expectedContent, expectedHash) {
|
|
27639
28074
|
try {
|
|
27640
|
-
const current =
|
|
28075
|
+
const current = fs36.readFileSync(destination, "utf8");
|
|
27641
28076
|
const marker = extractProvenanceMarker(current);
|
|
27642
28077
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "opencode" && current === expectedContent : current === expectedContent;
|
|
27643
28078
|
} catch {
|
|
@@ -27656,7 +28091,7 @@ function shouldSkipComponent5(options, component) {
|
|
|
27656
28091
|
}
|
|
27657
28092
|
function isSymlinkTo5(linkPath, source) {
|
|
27658
28093
|
try {
|
|
27659
|
-
return
|
|
28094
|
+
return fs36.realpathSync(linkPath) === fs36.realpathSync(source);
|
|
27660
28095
|
} catch {
|
|
27661
28096
|
return false;
|
|
27662
28097
|
}
|
|
@@ -27665,7 +28100,7 @@ function hashString5(value) {
|
|
|
27665
28100
|
return `sha256:${crypto9.createHash("sha256").update(value).digest("hex")}`;
|
|
27666
28101
|
}
|
|
27667
28102
|
function parseCommandFile(commandFile) {
|
|
27668
|
-
const content =
|
|
28103
|
+
const content = fs36.readFileSync(commandFile, "utf8");
|
|
27669
28104
|
if (!content.startsWith("---\n")) {
|
|
27670
28105
|
return { data: {}, body: content };
|
|
27671
28106
|
}
|
|
@@ -27685,10 +28120,10 @@ function parseCommandFile(commandFile) {
|
|
|
27685
28120
|
// src/commands/install.ts
|
|
27686
28121
|
function isBackupableFile(targetPath) {
|
|
27687
28122
|
try {
|
|
27688
|
-
const lstat =
|
|
28123
|
+
const lstat = fs37.lstatSync(targetPath);
|
|
27689
28124
|
if (lstat.isDirectory()) return false;
|
|
27690
28125
|
if (lstat.isSymbolicLink()) {
|
|
27691
|
-
const stat =
|
|
28126
|
+
const stat = fs37.statSync(targetPath);
|
|
27692
28127
|
return stat.isFile();
|
|
27693
28128
|
}
|
|
27694
28129
|
return lstat.isFile();
|
|
@@ -27698,10 +28133,10 @@ function isBackupableFile(targetPath) {
|
|
|
27698
28133
|
}
|
|
27699
28134
|
function backupConflictingTarget(targetPath, scopePath) {
|
|
27700
28135
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/gu, "").replace("T", "T").replace(/\.\d+Z$/u, "Z");
|
|
27701
|
-
const relativeToRoot =
|
|
27702
|
-
const backupPath =
|
|
27703
|
-
|
|
27704
|
-
|
|
28136
|
+
const relativeToRoot = path37.relative("/", targetPath).replace(/^\.\.\/+/gu, "");
|
|
28137
|
+
const backupPath = path37.join(scopePath, "backups", ts2, relativeToRoot);
|
|
28138
|
+
fs37.mkdirSync(path37.dirname(backupPath), { recursive: true });
|
|
28139
|
+
fs37.copyFileSync(targetPath, backupPath);
|
|
27705
28140
|
return backupPath;
|
|
27706
28141
|
}
|
|
27707
28142
|
async function runInstallCommand(options, logger) {
|
|
@@ -27730,7 +28165,7 @@ async function runInstallCommand(options, logger) {
|
|
|
27730
28165
|
);
|
|
27731
28166
|
}
|
|
27732
28167
|
const kitName = resolvedKitName ?? config.kit;
|
|
27733
|
-
const kitPath = kitPathOverride ?? (options.kitPath ?
|
|
28168
|
+
const kitPath = kitPathOverride ?? (options.kitPath ? path37.resolve(options.kitPath) : config.kitPath);
|
|
27734
28169
|
if (!kitName && !kitPath) {
|
|
27735
28170
|
logger.error(
|
|
27736
28171
|
"No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
|
|
@@ -27871,7 +28306,7 @@ ACCEPTED CONFLICTS (backup-and-replace applied to ${conflictingFindings.length}
|
|
|
27871
28306
|
logger.info(` source: ${finding.tool}`);
|
|
27872
28307
|
logger.info(` action: backup-and-replace`);
|
|
27873
28308
|
logger.info(` backup: ${backupLocation}`);
|
|
27874
|
-
} else if (
|
|
28309
|
+
} else if (fs37.existsSync(finding.path)) {
|
|
27875
28310
|
logger.info(` - ${finding.path}`);
|
|
27876
28311
|
logger.info(` source: ${finding.tool}`);
|
|
27877
28312
|
logger.info(
|
|
@@ -27982,7 +28417,7 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
|
|
|
27982
28417
|
writeManifest(scopePath, manifest);
|
|
27983
28418
|
logger.info(`
|
|
27984
28419
|
Installation complete: ${installedCount} files installed.`);
|
|
27985
|
-
logger.info(`Manifest written to ${
|
|
28420
|
+
logger.info(`Manifest written to ${path37.join(scopePath, "manifest.json")}`);
|
|
27986
28421
|
logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
|
|
27987
28422
|
logger.info(`Scope: ${scope}`);
|
|
27988
28423
|
logger.info(`Tools: ${tools.join(", ")}`);
|
|
@@ -28124,13 +28559,13 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
28124
28559
|
logger.verbose(` skipped (operator choice): ${placement.destination}`);
|
|
28125
28560
|
continue;
|
|
28126
28561
|
}
|
|
28127
|
-
const destDir =
|
|
28128
|
-
|
|
28562
|
+
const destDir = path37.dirname(placement.destination);
|
|
28563
|
+
fs37.mkdirSync(destDir, { recursive: true });
|
|
28129
28564
|
if (placement.type === "symlink") {
|
|
28130
|
-
if (
|
|
28565
|
+
if (fs37.existsSync(placement.destination) || isSymlink2(placement.destination)) {
|
|
28131
28566
|
removeManagedPath(placement.destination);
|
|
28132
28567
|
}
|
|
28133
|
-
|
|
28568
|
+
fs37.symlinkSync(
|
|
28134
28569
|
placement.source,
|
|
28135
28570
|
placement.destination,
|
|
28136
28571
|
placement.isDir ? "dir" : "file"
|
|
@@ -28139,12 +28574,12 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
28139
28574
|
` symlink: ${placement.source} \u2192 ${placement.destination}`
|
|
28140
28575
|
);
|
|
28141
28576
|
} else {
|
|
28142
|
-
|
|
28577
|
+
fs37.copyFileSync(placement.source, placement.destination);
|
|
28143
28578
|
logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
|
|
28144
28579
|
}
|
|
28145
28580
|
addArtifactToManifest(manifest, {
|
|
28146
28581
|
relativePath: placement.manifestKey,
|
|
28147
|
-
hash:
|
|
28582
|
+
hash: fs37.statSync(placement.source).isDirectory() ? `dir:${placement.source}` : computeSourceHash(placement.source),
|
|
28148
28583
|
origin: "tangyr-managed"
|
|
28149
28584
|
});
|
|
28150
28585
|
count++;
|
|
@@ -28391,11 +28826,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28391
28826
|
if (outcome.path === mcpFile2) {
|
|
28392
28827
|
return "cline/mcp.json";
|
|
28393
28828
|
}
|
|
28394
|
-
if (outcome.path.startsWith(`${workflowsRoot}${
|
|
28395
|
-
return `cline/workflows/${
|
|
28829
|
+
if (outcome.path.startsWith(`${workflowsRoot}${path37.sep}`)) {
|
|
28830
|
+
return `cline/workflows/${path37.basename(outcome.path)}`;
|
|
28396
28831
|
}
|
|
28397
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
28398
|
-
return `cline/rules/${
|
|
28832
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path37.sep}`)) {
|
|
28833
|
+
return `cline/rules/${path37.basename(outcome.path)}`;
|
|
28399
28834
|
}
|
|
28400
28835
|
return null;
|
|
28401
28836
|
}
|
|
@@ -28431,14 +28866,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28431
28866
|
if (outcome.path === permissionsFile) {
|
|
28432
28867
|
return "cursor/permissions.json";
|
|
28433
28868
|
}
|
|
28434
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28435
|
-
return `cursor/agents/${
|
|
28869
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
28870
|
+
return `cursor/agents/${path37.basename(outcome.path)}`;
|
|
28436
28871
|
}
|
|
28437
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
28438
|
-
return `cursor/rules/${
|
|
28872
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path37.sep}`)) {
|
|
28873
|
+
return `cursor/rules/${path37.basename(outcome.path)}`;
|
|
28439
28874
|
}
|
|
28440
|
-
if (outcome.path.startsWith(`${skillsRoot2}${
|
|
28441
|
-
const rel =
|
|
28875
|
+
if (outcome.path.startsWith(`${skillsRoot2}${path37.sep}`)) {
|
|
28876
|
+
const rel = path37.relative(skillsRoot2, outcome.path);
|
|
28442
28877
|
return `cursor/skills/${rel}`;
|
|
28443
28878
|
}
|
|
28444
28879
|
return null;
|
|
@@ -28464,14 +28899,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28464
28899
|
if (outcome.path === skillsSharedRoot) {
|
|
28465
28900
|
return "opencode/skills_shared";
|
|
28466
28901
|
}
|
|
28467
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28468
|
-
return `opencode/agents/${
|
|
28902
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
28903
|
+
return `opencode/agents/${path37.basename(outcome.path)}`;
|
|
28469
28904
|
}
|
|
28470
|
-
if (outcome.path.startsWith(`${commandsRoot}${
|
|
28471
|
-
return `opencode/commands/${
|
|
28905
|
+
if (outcome.path.startsWith(`${commandsRoot}${path37.sep}`)) {
|
|
28906
|
+
return `opencode/commands/${path37.basename(outcome.path)}`;
|
|
28472
28907
|
}
|
|
28473
28908
|
if (outcome.path === configDocFile) {
|
|
28474
|
-
return `opencode/${
|
|
28909
|
+
return `opencode/${path37.basename(outcome.path)}`;
|
|
28475
28910
|
}
|
|
28476
28911
|
return null;
|
|
28477
28912
|
}
|
|
@@ -28485,17 +28920,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28485
28920
|
if (outcome.path === skillsRoot2) {
|
|
28486
28921
|
return "copilot/skills";
|
|
28487
28922
|
}
|
|
28488
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28489
|
-
return `copilot/agents/${
|
|
28923
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
28924
|
+
return `copilot/agents/${path37.basename(outcome.path)}`;
|
|
28490
28925
|
}
|
|
28491
|
-
if (outcome.path.startsWith(`${promptsRoot}${
|
|
28492
|
-
return `copilot/prompts/${
|
|
28926
|
+
if (outcome.path.startsWith(`${promptsRoot}${path37.sep}`)) {
|
|
28927
|
+
return `copilot/prompts/${path37.basename(outcome.path)}`;
|
|
28493
28928
|
}
|
|
28494
|
-
if (outcome.path.startsWith(`${hooksRoot}${
|
|
28495
|
-
return `copilot/hooks/${
|
|
28929
|
+
if (outcome.path.startsWith(`${hooksRoot}${path37.sep}`)) {
|
|
28930
|
+
return `copilot/hooks/${path37.basename(outcome.path)}`;
|
|
28496
28931
|
}
|
|
28497
28932
|
if (outcome.path === mcpFile2) {
|
|
28498
|
-
return `copilot/${
|
|
28933
|
+
return `copilot/${path37.basename(outcome.path)}`;
|
|
28499
28934
|
}
|
|
28500
28935
|
return null;
|
|
28501
28936
|
}
|
|
@@ -28511,17 +28946,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28511
28946
|
if (outcome.path === skillsRoot) {
|
|
28512
28947
|
return "codex/skills";
|
|
28513
28948
|
}
|
|
28514
|
-
if (outcome.path.startsWith(`${agentsRoot}${
|
|
28515
|
-
return `codex/agents/${
|
|
28949
|
+
if (outcome.path.startsWith(`${agentsRoot}${path37.sep}`)) {
|
|
28950
|
+
return `codex/agents/${path37.basename(outcome.path)}`;
|
|
28516
28951
|
}
|
|
28517
|
-
if (outcome.path.startsWith(`${rulesRoot}${
|
|
28518
|
-
return `codex/rules/${
|
|
28952
|
+
if (outcome.path.startsWith(`${rulesRoot}${path37.sep}`)) {
|
|
28953
|
+
return `codex/rules/${path37.basename(outcome.path)}`;
|
|
28519
28954
|
}
|
|
28520
28955
|
if (outcome.path === hooksFile) {
|
|
28521
|
-
return `codex/${
|
|
28956
|
+
return `codex/${path37.basename(outcome.path)}`;
|
|
28522
28957
|
}
|
|
28523
28958
|
if (outcome.path === mcpFile) {
|
|
28524
|
-
return `codex/${
|
|
28959
|
+
return `codex/${path37.basename(outcome.path)}`;
|
|
28525
28960
|
}
|
|
28526
28961
|
return null;
|
|
28527
28962
|
}
|
|
@@ -28556,8 +28991,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28556
28991
|
};
|
|
28557
28992
|
}
|
|
28558
28993
|
const placements = [];
|
|
28559
|
-
const claudeMd =
|
|
28560
|
-
if (
|
|
28994
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
28995
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28561
28996
|
placements.push({
|
|
28562
28997
|
source: claudeMd,
|
|
28563
28998
|
destination: resolvedPaths.instructions,
|
|
@@ -28573,8 +29008,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28573
29008
|
rules: resolvedPaths.rules
|
|
28574
29009
|
};
|
|
28575
29010
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
28576
|
-
const componentDir =
|
|
28577
|
-
if (
|
|
29011
|
+
const componentDir = path37.join(kitInfo.path, component);
|
|
29012
|
+
if (fs37.existsSync(componentDir) && fs37.statSync(componentDir).isDirectory()) {
|
|
28578
29013
|
placements.push({
|
|
28579
29014
|
source: componentDir,
|
|
28580
29015
|
destination: targetPath,
|
|
@@ -28588,8 +29023,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28588
29023
|
}
|
|
28589
29024
|
function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
28590
29025
|
const placements = [];
|
|
28591
|
-
const claudeMd =
|
|
28592
|
-
if (
|
|
29026
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
29027
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28593
29028
|
placements.push({
|
|
28594
29029
|
source: claudeMd,
|
|
28595
29030
|
destination: profile.instructions,
|
|
@@ -28605,8 +29040,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
|
28605
29040
|
rules: profile.rules
|
|
28606
29041
|
};
|
|
28607
29042
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
28608
|
-
const componentDir =
|
|
28609
|
-
if (
|
|
29043
|
+
const componentDir = path37.join(kitInfo.path, component);
|
|
29044
|
+
if (fs37.existsSync(componentDir) && fs37.statSync(componentDir).isDirectory()) {
|
|
28610
29045
|
placements.push({
|
|
28611
29046
|
source: componentDir,
|
|
28612
29047
|
destination: targetPath,
|
|
@@ -28620,8 +29055,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
|
28620
29055
|
}
|
|
28621
29056
|
function collectAllFiles(kitInfo) {
|
|
28622
29057
|
const files = /* @__PURE__ */ new Map();
|
|
28623
|
-
const claudeMd =
|
|
28624
|
-
if (
|
|
29058
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
29059
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28625
29060
|
files.set("CLAUDE.md", claudeMd);
|
|
28626
29061
|
}
|
|
28627
29062
|
for (const [component, reconciliation] of Object.entries(
|
|
@@ -28631,15 +29066,15 @@ function collectAllFiles(kitInfo) {
|
|
|
28631
29066
|
const missingSet = new Set(reconciliation.missing);
|
|
28632
29067
|
for (const entry of reconciliation.declared) {
|
|
28633
29068
|
if (missingSet.has(entry)) continue;
|
|
28634
|
-
const relPath = isSkills ?
|
|
28635
|
-
files.set(relPath,
|
|
29069
|
+
const relPath = isSkills ? path37.join(component, entry) : path37.join(component, `${entry}.md`);
|
|
29070
|
+
files.set(relPath, path37.join(kitInfo.path, relPath));
|
|
28636
29071
|
}
|
|
28637
29072
|
}
|
|
28638
29073
|
return files;
|
|
28639
29074
|
}
|
|
28640
29075
|
function isSymlink2(p) {
|
|
28641
29076
|
try {
|
|
28642
|
-
return
|
|
29077
|
+
return fs37.lstatSync(p).isSymbolicLink();
|
|
28643
29078
|
} catch {
|
|
28644
29079
|
return false;
|
|
28645
29080
|
}
|
|
@@ -28684,14 +29119,14 @@ async function runKitUpdateCommand(options, logger) {
|
|
|
28684
29119
|
}
|
|
28685
29120
|
|
|
28686
29121
|
// src/commands/list.ts
|
|
28687
|
-
import
|
|
29122
|
+
import path38 from "path";
|
|
28688
29123
|
function runListCommand(options, logger) {
|
|
28689
29124
|
let searchPaths = [];
|
|
28690
|
-
let directKitPath = options.kitPath ?
|
|
29125
|
+
let directKitPath = options.kitPath ? path38.resolve(options.kitPath) : void 0;
|
|
28691
29126
|
try {
|
|
28692
29127
|
const { config, configDir } = resolveConfig(options.config);
|
|
28693
29128
|
searchPaths = config.kitSearchPaths ?? [
|
|
28694
|
-
|
|
29129
|
+
path38.join(configDir, "operating-kits")
|
|
28695
29130
|
];
|
|
28696
29131
|
directKitPath = directKitPath ?? config.kitPath;
|
|
28697
29132
|
} catch (err) {
|
|
@@ -28766,7 +29201,7 @@ function withDirectKit(kits, directKitPath) {
|
|
|
28766
29201
|
return kits;
|
|
28767
29202
|
}
|
|
28768
29203
|
const directKit = loadKit(directKitPath);
|
|
28769
|
-
if (kits.some((kit) =>
|
|
29204
|
+
if (kits.some((kit) => path38.resolve(kit.path) === directKit.path)) {
|
|
28770
29205
|
return kits;
|
|
28771
29206
|
}
|
|
28772
29207
|
return [...kits, directKit];
|
|
@@ -28774,12 +29209,12 @@ function withDirectKit(kits, directKitPath) {
|
|
|
28774
29209
|
|
|
28775
29210
|
// src/commands/probe.ts
|
|
28776
29211
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
28777
|
-
import
|
|
28778
|
-
import
|
|
29212
|
+
import fs38 from "fs";
|
|
29213
|
+
import path39 from "path";
|
|
28779
29214
|
function runProbeCommand(options, logger) {
|
|
28780
29215
|
const { config, configDir, sourceRoot } = resolveRuntime(options, import.meta.url);
|
|
28781
29216
|
const platformPaths = readYamlObject(
|
|
28782
|
-
|
|
29217
|
+
path39.join(
|
|
28783
29218
|
resolveConfiguredPath(config.mappings, configDir, sourceRoot, "mappings"),
|
|
28784
29219
|
"platform-paths.yaml"
|
|
28785
29220
|
)
|
|
@@ -28813,12 +29248,12 @@ function toProbeRow(target, key, rawPath) {
|
|
|
28813
29248
|
const resolved = resolveTargetPath(rawPath);
|
|
28814
29249
|
let accessible = false;
|
|
28815
29250
|
try {
|
|
28816
|
-
|
|
29251
|
+
fs38.accessSync(resolved);
|
|
28817
29252
|
accessible = true;
|
|
28818
29253
|
} catch {
|
|
28819
29254
|
accessible = false;
|
|
28820
29255
|
}
|
|
28821
|
-
return { target, key, path: resolved, exists:
|
|
29256
|
+
return { target, key, path: resolved, exists: fs38.existsSync(resolved), accessible };
|
|
28822
29257
|
}
|
|
28823
29258
|
function codexRuntimeProbeRows() {
|
|
28824
29259
|
const rows = commandProbeRows("codex", "binary", process.platform === "win32" ? "where.exe" : "which", ["codex"]);
|
|
@@ -28829,7 +29264,7 @@ function codexRuntimeProbeRows() {
|
|
|
28829
29264
|
["binary_snap", "/snap/bin/codex"],
|
|
28830
29265
|
["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
|
|
28831
29266
|
]) {
|
|
28832
|
-
if (
|
|
29267
|
+
if (fs38.existsSync(candidatePath)) {
|
|
28833
29268
|
rows.push(toProbeRow("codex", key, candidatePath));
|
|
28834
29269
|
}
|
|
28835
29270
|
}
|
|
@@ -28845,8 +29280,8 @@ function commandProbeRows(target, key, command, args) {
|
|
|
28845
29280
|
|
|
28846
29281
|
// src/commands/status.ts
|
|
28847
29282
|
import crypto10 from "crypto";
|
|
28848
|
-
import
|
|
28849
|
-
import
|
|
29283
|
+
import fs39 from "fs";
|
|
29284
|
+
import path40 from "path";
|
|
28850
29285
|
function runStatusCommand(options, logger) {
|
|
28851
29286
|
const { config, configDir, sourceRoot } = resolveRuntime(
|
|
28852
29287
|
options,
|
|
@@ -28925,21 +29360,21 @@ function classifyCodexFiles(config, sourceRoot, configDir) {
|
|
|
28925
29360
|
rules: paths.rules
|
|
28926
29361
|
};
|
|
28927
29362
|
const rules = compileRules(
|
|
28928
|
-
|
|
29363
|
+
path40.join(sourceRoot, config.source.rules),
|
|
28929
29364
|
"codex",
|
|
28930
29365
|
mappings,
|
|
28931
29366
|
createLossReport()
|
|
28932
29367
|
);
|
|
28933
|
-
const instructionsSource =
|
|
29368
|
+
const instructionsSource = fs39.readFileSync(path40.join(sourceRoot, config.source.instructions), "utf8").trim();
|
|
28934
29369
|
const composedInstructions = `${instructionsSource}
|
|
28935
29370
|
|
|
28936
29371
|
--- tangyr managed rules ---
|
|
28937
29372
|
${rules.agentsAppendix}`.trim();
|
|
28938
29373
|
const agentFiles = ts(
|
|
28939
|
-
|
|
29374
|
+
path40.join(sourceRoot, config.source.agents, "*.md")
|
|
28940
29375
|
).sort();
|
|
28941
|
-
const hooksSource =
|
|
28942
|
-
const mcpSource =
|
|
29376
|
+
const hooksSource = path40.join(sourceRoot, config.source.hooks, "hooks.json");
|
|
29377
|
+
const mcpSource = path40.join(sourceRoot, config.source.mcp);
|
|
28943
29378
|
const ruleRows = rules.dotRulesFiles.length === 0 ? [
|
|
28944
29379
|
{
|
|
28945
29380
|
component: "rules",
|
|
@@ -28950,7 +29385,7 @@ ${rules.agentsAppendix}`.trim();
|
|
|
28950
29385
|
] : rules.dotRulesFiles.map(
|
|
28951
29386
|
(ruleFile) => classifyCompiledFile(
|
|
28952
29387
|
`rules/${ruleFile.name}`,
|
|
28953
|
-
|
|
29388
|
+
path40.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
|
|
28954
29389
|
"codex",
|
|
28955
29390
|
void 0,
|
|
28956
29391
|
config,
|
|
@@ -28968,10 +29403,10 @@ ${rules.agentsAppendix}`.trim();
|
|
|
28968
29403
|
),
|
|
28969
29404
|
...agentFiles.map(
|
|
28970
29405
|
(agentFile) => classifyCompiledFile(
|
|
28971
|
-
`agents/${
|
|
28972
|
-
|
|
29406
|
+
`agents/${path40.basename(agentFile, ".md")}`,
|
|
29407
|
+
path40.join(
|
|
28973
29408
|
resolveTargetPath(codexPaths.agents),
|
|
28974
|
-
`${
|
|
29409
|
+
`${path40.basename(agentFile, ".md")}.toml`
|
|
28975
29410
|
),
|
|
28976
29411
|
"codex",
|
|
28977
29412
|
computeSourceHash(agentFile),
|
|
@@ -28995,11 +29430,11 @@ ${rules.agentsAppendix}`.trim();
|
|
|
28995
29430
|
config,
|
|
28996
29431
|
sourceRoot
|
|
28997
29432
|
),
|
|
28998
|
-
|
|
29433
|
+
fs39.existsSync(hooksSource) ? classifyCodexHooksFile(resolveTargetPath(codexPaths.hooksSharedFile)) : notConfiguredRow(
|
|
28999
29434
|
"hooks",
|
|
29000
29435
|
resolveTargetPath(codexPaths.hooksSharedFile)
|
|
29001
29436
|
),
|
|
29002
|
-
|
|
29437
|
+
fs39.existsSync(mcpSource) ? classifyCompiledFile(
|
|
29003
29438
|
"mcp",
|
|
29004
29439
|
resolveTargetPath(codexPaths.mcpSharedFile),
|
|
29005
29440
|
"codex",
|
|
@@ -29019,7 +29454,7 @@ function classifyCodexHooksFile(filePath) {
|
|
|
29019
29454
|
conformant: true
|
|
29020
29455
|
};
|
|
29021
29456
|
}
|
|
29022
|
-
if (!
|
|
29457
|
+
if (!fs39.existsSync(filePath)) {
|
|
29023
29458
|
return {
|
|
29024
29459
|
component: "hooks",
|
|
29025
29460
|
className: "missing",
|
|
@@ -29051,20 +29486,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29051
29486
|
mcpSharedFile: paths.mcp_shared_file
|
|
29052
29487
|
};
|
|
29053
29488
|
const agentFiles = ts(
|
|
29054
|
-
|
|
29489
|
+
path40.join(sourceRoot, config.source.agents, "*.md")
|
|
29055
29490
|
).sort();
|
|
29056
29491
|
const commandFiles = ts(
|
|
29057
|
-
|
|
29492
|
+
path40.join(sourceRoot, config.source.commands, "*.md")
|
|
29058
29493
|
).sort();
|
|
29059
|
-
const hooksSource =
|
|
29060
|
-
const mcpSource =
|
|
29494
|
+
const hooksSource = path40.join(sourceRoot, config.source.hooks, "hooks.json");
|
|
29495
|
+
const mcpSource = path40.join(sourceRoot, config.source.mcp);
|
|
29061
29496
|
return [
|
|
29062
29497
|
...agentFiles.map(
|
|
29063
29498
|
(agentFile) => classifyCompiledFile(
|
|
29064
|
-
`agents/${
|
|
29065
|
-
|
|
29499
|
+
`agents/${path40.basename(agentFile, ".md")}`,
|
|
29500
|
+
path40.join(
|
|
29066
29501
|
resolveTargetPath(copilotPaths.agents),
|
|
29067
|
-
`${
|
|
29502
|
+
`${path40.basename(agentFile, ".md")}.agent.md`
|
|
29068
29503
|
),
|
|
29069
29504
|
"copilot",
|
|
29070
29505
|
computeSourceHash(agentFile),
|
|
@@ -29081,10 +29516,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29081
29516
|
),
|
|
29082
29517
|
...commandFiles.map(
|
|
29083
29518
|
(commandFile) => classifyCompiledFile(
|
|
29084
|
-
`commands/${
|
|
29085
|
-
|
|
29519
|
+
`commands/${path40.basename(commandFile, ".md")}`,
|
|
29520
|
+
path40.join(
|
|
29086
29521
|
resolveTargetPath(copilotPaths.prompts),
|
|
29087
|
-
`${
|
|
29522
|
+
`${path40.basename(commandFile, ".md")}.prompt.md`
|
|
29088
29523
|
),
|
|
29089
29524
|
"copilot",
|
|
29090
29525
|
computeSourceHash(commandFile),
|
|
@@ -29102,9 +29537,9 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29102
29537
|
config,
|
|
29103
29538
|
sourceRoot
|
|
29104
29539
|
),
|
|
29105
|
-
|
|
29540
|
+
fs39.existsSync(hooksSource) ? classifyCompiledFile(
|
|
29106
29541
|
"hooks",
|
|
29107
|
-
|
|
29542
|
+
path40.join(
|
|
29108
29543
|
resolveTargetPath(copilotPaths.hooks),
|
|
29109
29544
|
"tangyr-managed.json"
|
|
29110
29545
|
),
|
|
@@ -29114,12 +29549,12 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29114
29549
|
sourceRoot
|
|
29115
29550
|
) : notConfiguredRow(
|
|
29116
29551
|
"hooks",
|
|
29117
|
-
|
|
29552
|
+
path40.join(
|
|
29118
29553
|
resolveTargetPath(copilotPaths.hooks),
|
|
29119
29554
|
"tangyr-managed.json"
|
|
29120
29555
|
)
|
|
29121
29556
|
),
|
|
29122
|
-
|
|
29557
|
+
fs39.existsSync(mcpSource) ? classifyCompiledFile(
|
|
29123
29558
|
"mcp",
|
|
29124
29559
|
resolveTargetPath(copilotPaths.mcpSharedFile),
|
|
29125
29560
|
"copilot",
|
|
@@ -29139,7 +29574,7 @@ function notConfiguredRow(component, filePath) {
|
|
|
29139
29574
|
}
|
|
29140
29575
|
function classifyDirectArtifact(artifact, config, sourceRoot) {
|
|
29141
29576
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
29142
|
-
const sourcePath = artifact.sourceKey ?
|
|
29577
|
+
const sourcePath = artifact.sourceKey ? path40.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
|
|
29143
29578
|
if (artifactClass === "managed-symlink" && sourcePath && !isSymlinkCurrent(artifact.path, sourcePath)) {
|
|
29144
29579
|
return {
|
|
29145
29580
|
component: artifact.component,
|
|
@@ -29228,9 +29663,9 @@ function classifyClaudeSharedFiles(config, sourceRoot) {
|
|
|
29228
29663
|
classifyHooks(settingsPath),
|
|
29229
29664
|
classifySettings(
|
|
29230
29665
|
settingsPath,
|
|
29231
|
-
|
|
29666
|
+
path40.resolve(sourceRoot, config.source.settings)
|
|
29232
29667
|
),
|
|
29233
|
-
classifyMcp(claudeJsonPath,
|
|
29668
|
+
classifyMcp(claudeJsonPath, path40.resolve(sourceRoot, config.source.mcp))
|
|
29234
29669
|
];
|
|
29235
29670
|
}
|
|
29236
29671
|
function classifyHooks(filePath) {
|
|
@@ -29294,14 +29729,14 @@ function classifyMcp(filePath, sourcePath) {
|
|
|
29294
29729
|
}
|
|
29295
29730
|
function isSymlinkCurrent(linkPath, sourcePath) {
|
|
29296
29731
|
try {
|
|
29297
|
-
return
|
|
29732
|
+
return fs39.realpathSync(linkPath) === fs39.realpathSync(sourcePath);
|
|
29298
29733
|
} catch {
|
|
29299
29734
|
return false;
|
|
29300
29735
|
}
|
|
29301
29736
|
}
|
|
29302
29737
|
function isCompiledCurrent6(filePath, sourcePath) {
|
|
29303
29738
|
try {
|
|
29304
|
-
const marker = extractProvenanceMarker(
|
|
29739
|
+
const marker = extractProvenanceMarker(fs39.readFileSync(filePath, "utf8"));
|
|
29305
29740
|
return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
|
|
29306
29741
|
} catch {
|
|
29307
29742
|
return false;
|
|
@@ -29331,7 +29766,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
|
|
|
29331
29766
|
}
|
|
29332
29767
|
function readCompiledContent(filePath) {
|
|
29333
29768
|
try {
|
|
29334
|
-
return
|
|
29769
|
+
return fs39.readFileSync(filePath, "utf8");
|
|
29335
29770
|
} catch {
|
|
29336
29771
|
return null;
|
|
29337
29772
|
}
|
|
@@ -29362,8 +29797,8 @@ function hashString6(value) {
|
|
|
29362
29797
|
}
|
|
29363
29798
|
|
|
29364
29799
|
// src/commands/sync.ts
|
|
29365
|
-
import
|
|
29366
|
-
import
|
|
29800
|
+
import fs42 from "fs";
|
|
29801
|
+
import path43 from "path";
|
|
29367
29802
|
|
|
29368
29803
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
29369
29804
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -29861,8 +30296,8 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
29861
30296
|
var source_default = chalk;
|
|
29862
30297
|
|
|
29863
30298
|
// src/adapters/claude-code.ts
|
|
29864
|
-
import
|
|
29865
|
-
import
|
|
30299
|
+
import fs41 from "fs";
|
|
30300
|
+
import path42 from "path";
|
|
29866
30301
|
|
|
29867
30302
|
// src/core/shim.ts
|
|
29868
30303
|
import crypto11 from "crypto";
|
|
@@ -29879,12 +30314,12 @@ ${SHIM_BODY}`;
|
|
|
29879
30314
|
|
|
29880
30315
|
// src/compiler/hook-components.ts
|
|
29881
30316
|
var import_yaml11 = __toESM(require_dist(), 1);
|
|
29882
|
-
import
|
|
29883
|
-
import
|
|
30317
|
+
import fs40 from "fs";
|
|
30318
|
+
import path41 from "path";
|
|
29884
30319
|
function parseHookDeclaration(filePath) {
|
|
29885
30320
|
let raw;
|
|
29886
30321
|
try {
|
|
29887
|
-
raw =
|
|
30322
|
+
raw = fs40.readFileSync(filePath, "utf8");
|
|
29888
30323
|
} catch {
|
|
29889
30324
|
return null;
|
|
29890
30325
|
}
|
|
@@ -29967,9 +30402,9 @@ function synthesizeHooksJson(declarations) {
|
|
|
29967
30402
|
return { hooks };
|
|
29968
30403
|
}
|
|
29969
30404
|
function loadSourceHooks(hooksDir, hookNames) {
|
|
29970
|
-
const hooksJsonPath =
|
|
29971
|
-
if (
|
|
29972
|
-
const raw =
|
|
30405
|
+
const hooksJsonPath = path41.join(hooksDir, "hooks.json");
|
|
30406
|
+
if (fs40.existsSync(hooksJsonPath)) {
|
|
30407
|
+
const raw = fs40.readFileSync(hooksJsonPath, "utf8");
|
|
29973
30408
|
return JSON.parse(raw);
|
|
29974
30409
|
}
|
|
29975
30410
|
const declarations = loadHookDeclarations(hooksDir, hookNames);
|
|
@@ -29980,14 +30415,14 @@ function loadHookDeclarations(hooksDir, hookNames) {
|
|
|
29980
30415
|
if (hookNames && hookNames.length > 0) {
|
|
29981
30416
|
names = hookNames;
|
|
29982
30417
|
} else {
|
|
29983
|
-
if (!
|
|
30418
|
+
if (!fs40.existsSync(hooksDir) || !fs40.statSync(hooksDir).isDirectory()) {
|
|
29984
30419
|
return [];
|
|
29985
30420
|
}
|
|
29986
|
-
names =
|
|
30421
|
+
names = fs40.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
|
|
29987
30422
|
}
|
|
29988
30423
|
const declarations = [];
|
|
29989
30424
|
for (const name of names) {
|
|
29990
|
-
const filePath =
|
|
30425
|
+
const filePath = path41.join(hooksDir, `${name}.md`);
|
|
29991
30426
|
const decl = parseHookDeclaration(filePath);
|
|
29992
30427
|
if (decl) {
|
|
29993
30428
|
declarations.push(decl);
|
|
@@ -30111,7 +30546,7 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
30111
30546
|
}
|
|
30112
30547
|
if (!shouldSkipComponent6(options, "instructions") && manifest && scopePath) {
|
|
30113
30548
|
const shimPath = profile.instructions_shim;
|
|
30114
|
-
const agentsMdPath =
|
|
30549
|
+
const agentsMdPath = path42.resolve(sourceRoot, config.source.instructions);
|
|
30115
30550
|
if (!options.dryRun) {
|
|
30116
30551
|
applyClaudeCodeShimUpgrade(
|
|
30117
30552
|
shimPath,
|
|
@@ -30165,13 +30600,13 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
30165
30600
|
}
|
|
30166
30601
|
function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
|
|
30167
30602
|
if (!mappings.modelTiers.custom_provider) return;
|
|
30168
|
-
const agentsDir =
|
|
30169
|
-
if (!
|
|
30170
|
-
for (const agentFile of ts(
|
|
30603
|
+
const agentsDir = path42.join(sourceRoot, config.source.agents);
|
|
30604
|
+
if (!fs41.existsSync(agentsDir)) return;
|
|
30605
|
+
for (const agentFile of ts(path42.join(agentsDir, "*.md")).sort()) {
|
|
30171
30606
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
30172
30607
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
30173
30608
|
if (hasProvider) {
|
|
30174
|
-
const basename =
|
|
30609
|
+
const basename = path42.basename(agentFile);
|
|
30175
30610
|
addLoss(lossReport, "claude-code", "agents", {
|
|
30176
30611
|
source: `agents/${basename}`,
|
|
30177
30612
|
fields: [
|
|
@@ -30196,19 +30631,19 @@ function shouldSkipComponent6(options, component) {
|
|
|
30196
30631
|
function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath, logger) {
|
|
30197
30632
|
const expectedBodyHash = shimBodyHash();
|
|
30198
30633
|
const shimContent = buildAgentsMdShim(shimPath, agentsMdPath, "claude-code");
|
|
30199
|
-
if (!
|
|
30634
|
+
if (!fs41.existsSync(shimPath)) {
|
|
30200
30635
|
manifest.artifacts.push({
|
|
30201
|
-
relativePath:
|
|
30636
|
+
relativePath: path42.relative(scopePath, shimPath),
|
|
30202
30637
|
hash: expectedBodyHash,
|
|
30203
30638
|
origin: "tangyr-managed"
|
|
30204
30639
|
});
|
|
30205
30640
|
writeManifest(scopePath, manifest);
|
|
30206
|
-
|
|
30207
|
-
|
|
30641
|
+
fs41.mkdirSync(path42.dirname(shimPath), { recursive: true });
|
|
30642
|
+
fs41.writeFileSync(shimPath, shimContent);
|
|
30208
30643
|
logger?.verbose(`instructions-shim: wrote @AGENTS.md shim -> ${shimPath}`);
|
|
30209
30644
|
return;
|
|
30210
30645
|
}
|
|
30211
|
-
const existing =
|
|
30646
|
+
const existing = fs41.readFileSync(shimPath, "utf8");
|
|
30212
30647
|
const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
30213
30648
|
const marker = extractProvenanceMarker(firstNonEmptyLine);
|
|
30214
30649
|
if (marker !== null && marker.hash === expectedBodyHash) {
|
|
@@ -30219,21 +30654,21 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
30219
30654
|
}
|
|
30220
30655
|
backupFile(shimPath, manifest);
|
|
30221
30656
|
writeManifest(scopePath, manifest);
|
|
30222
|
-
|
|
30657
|
+
fs41.writeFileSync(shimPath, shimContent);
|
|
30223
30658
|
manifest.artifacts.push({
|
|
30224
|
-
relativePath:
|
|
30659
|
+
relativePath: path42.relative(scopePath, shimPath),
|
|
30225
30660
|
hash: expectedBodyHash,
|
|
30226
30661
|
origin: "tangyr-managed"
|
|
30227
30662
|
});
|
|
30228
30663
|
logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
|
|
30229
30664
|
}
|
|
30230
30665
|
function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
|
|
30231
|
-
const source =
|
|
30666
|
+
const source = path42.resolve(
|
|
30232
30667
|
sourceRoot,
|
|
30233
30668
|
config.source[directComponent.sourceKey]
|
|
30234
30669
|
);
|
|
30235
30670
|
const destination = directComponent.destination;
|
|
30236
|
-
if (!
|
|
30671
|
+
if (!fs41.existsSync(source)) {
|
|
30237
30672
|
return skippedMissingSource6(directComponent.component, source);
|
|
30238
30673
|
}
|
|
30239
30674
|
if (options.dryRun) {
|
|
@@ -30255,7 +30690,7 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30255
30690
|
};
|
|
30256
30691
|
}
|
|
30257
30692
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
30258
|
-
|
|
30693
|
+
fs41.unlinkSync(destination);
|
|
30259
30694
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
30260
30695
|
return {
|
|
30261
30696
|
component: directComponent.component,
|
|
@@ -30263,9 +30698,9 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30263
30698
|
path: destination
|
|
30264
30699
|
};
|
|
30265
30700
|
} else if (artifactClass === "managed-symlink") {
|
|
30266
|
-
|
|
30701
|
+
fs41.unlinkSync(destination);
|
|
30267
30702
|
}
|
|
30268
|
-
ensureDir(
|
|
30703
|
+
ensureDir(path42.dirname(destination));
|
|
30269
30704
|
createRelativeSymlink(source, destination, directComponent.type, {
|
|
30270
30705
|
logger,
|
|
30271
30706
|
provenanceMarker: directComponent.type === "file" ? formatProvenanceMarker(
|
|
@@ -30282,8 +30717,8 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30282
30717
|
};
|
|
30283
30718
|
}
|
|
30284
30719
|
function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination, manifest, scopePath) {
|
|
30285
|
-
const source =
|
|
30286
|
-
if (!
|
|
30720
|
+
const source = path42.resolve(sourceRoot, config.source.skills);
|
|
30721
|
+
if (!fs41.existsSync(source)) {
|
|
30287
30722
|
return [skippedMissingSource6("skills", source)];
|
|
30288
30723
|
}
|
|
30289
30724
|
const declaredNames = resolveKitSkillNames(sourceRoot);
|
|
@@ -30293,7 +30728,7 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30293
30728
|
if (isLegacyWholesaleSymlink) {
|
|
30294
30729
|
for (const name of foreignSkillNames(source, declaredNames)) {
|
|
30295
30730
|
logger.info(
|
|
30296
|
-
`[dry-run] skills: migrate foreign skill ${
|
|
30731
|
+
`[dry-run] skills: migrate foreign skill ${path42.join(source, name)} -> ${path42.join(destination, name)}`
|
|
30297
30732
|
);
|
|
30298
30733
|
}
|
|
30299
30734
|
logger.info(
|
|
@@ -30301,9 +30736,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30301
30736
|
);
|
|
30302
30737
|
}
|
|
30303
30738
|
for (const name of declaredNames ?? listSkillDirNames(source)) {
|
|
30304
|
-
const skillDestination =
|
|
30739
|
+
const skillDestination = path42.join(destination, name);
|
|
30305
30740
|
logger.info(
|
|
30306
|
-
`[dry-run] skills: symlink ${
|
|
30741
|
+
`[dry-run] skills: symlink ${path42.join(source, name)} -> ${skillDestination}`
|
|
30307
30742
|
);
|
|
30308
30743
|
outcomes2.push({
|
|
30309
30744
|
component: "skills",
|
|
@@ -30336,9 +30771,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30336
30771
|
return outcomes;
|
|
30337
30772
|
}
|
|
30338
30773
|
function syncSingleSkill(config, sourceRoot, options, logger, source, destination, name, manifest, scopePath) {
|
|
30339
|
-
const skillSource =
|
|
30340
|
-
const skillDestination =
|
|
30341
|
-
if (!
|
|
30774
|
+
const skillSource = path42.join(source, name);
|
|
30775
|
+
const skillDestination = path42.join(destination, name);
|
|
30776
|
+
if (!fs41.existsSync(skillSource)) {
|
|
30342
30777
|
return skippedMissingSource6("skills", skillSource);
|
|
30343
30778
|
}
|
|
30344
30779
|
const artifactClass = classifyArtifact(skillDestination, config, sourceRoot);
|
|
@@ -30350,7 +30785,7 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
|
|
|
30350
30785
|
};
|
|
30351
30786
|
}
|
|
30352
30787
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(skillDestination, /* @__PURE__ */ new Set([skillDestination]), config)) {
|
|
30353
|
-
|
|
30788
|
+
fs41.unlinkSync(skillDestination);
|
|
30354
30789
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(
|
|
30355
30790
|
skillDestination,
|
|
30356
30791
|
config,
|
|
@@ -30361,25 +30796,25 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
|
|
|
30361
30796
|
)) {
|
|
30362
30797
|
return { component: "skills", status: "conflict", path: skillDestination };
|
|
30363
30798
|
} else if (artifactClass === "managed-symlink") {
|
|
30364
|
-
|
|
30799
|
+
fs41.unlinkSync(skillDestination);
|
|
30365
30800
|
}
|
|
30366
30801
|
createRelativeSymlink(skillSource, skillDestination, "dir");
|
|
30367
30802
|
return { component: "skills", status: "success", path: skillDestination };
|
|
30368
30803
|
}
|
|
30369
30804
|
function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger) {
|
|
30370
30805
|
const foreignNames = foreignSkillNames(source, declaredNames);
|
|
30371
|
-
|
|
30806
|
+
fs41.unlinkSync(destination);
|
|
30372
30807
|
ensureDir(destination);
|
|
30373
30808
|
for (const name of foreignNames) {
|
|
30374
|
-
const from =
|
|
30375
|
-
const to =
|
|
30376
|
-
if (
|
|
30809
|
+
const from = path42.join(source, name);
|
|
30810
|
+
const to = path42.join(destination, name);
|
|
30811
|
+
if (fs41.existsSync(to)) {
|
|
30377
30812
|
logger.warn(
|
|
30378
30813
|
`skills migration: ${to} already exists \u2014 skipping move of ${from} to avoid overwrite`
|
|
30379
30814
|
);
|
|
30380
30815
|
continue;
|
|
30381
30816
|
}
|
|
30382
|
-
|
|
30817
|
+
fs41.renameSync(from, to);
|
|
30383
30818
|
logger.info(`skills migration: moved ${from} -> ${to}`);
|
|
30384
30819
|
}
|
|
30385
30820
|
}
|
|
@@ -30391,21 +30826,21 @@ function foreignSkillNames(source, declaredNames) {
|
|
|
30391
30826
|
return listSkillDirNames(source).filter((name) => !declaredSet.has(name));
|
|
30392
30827
|
}
|
|
30393
30828
|
function listSkillDirNames(dir) {
|
|
30394
|
-
if (!
|
|
30829
|
+
if (!fs41.existsSync(dir)) {
|
|
30395
30830
|
return [];
|
|
30396
30831
|
}
|
|
30397
|
-
return
|
|
30832
|
+
return fs41.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
30398
30833
|
}
|
|
30399
30834
|
function isSymlinkPath(filePath) {
|
|
30400
30835
|
try {
|
|
30401
|
-
return
|
|
30836
|
+
return fs41.lstatSync(filePath).isSymbolicLink();
|
|
30402
30837
|
} catch {
|
|
30403
30838
|
return false;
|
|
30404
30839
|
}
|
|
30405
30840
|
}
|
|
30406
30841
|
function syncHookScriptsBridge(config, sourceRoot, options, logger, destination, manifest, scopePath) {
|
|
30407
|
-
const source =
|
|
30408
|
-
if (!
|
|
30842
|
+
const source = path42.resolve(sourceRoot, config.source.hooks);
|
|
30843
|
+
if (!fs41.existsSync(source)) {
|
|
30409
30844
|
return skippedMissingSource6("hooks", source);
|
|
30410
30845
|
}
|
|
30411
30846
|
if (options.dryRun) {
|
|
@@ -30417,13 +30852,13 @@ function syncHookScriptsBridge(config, sourceRoot, options, logger, destination,
|
|
|
30417
30852
|
return { component: "hooks", status: "skipped-current", path: destination };
|
|
30418
30853
|
}
|
|
30419
30854
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
30420
|
-
|
|
30855
|
+
fs41.unlinkSync(destination);
|
|
30421
30856
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
30422
30857
|
return { component: "hooks", status: "conflict", path: destination };
|
|
30423
30858
|
} else if (artifactClass === "managed-symlink") {
|
|
30424
|
-
|
|
30859
|
+
fs41.unlinkSync(destination);
|
|
30425
30860
|
}
|
|
30426
|
-
ensureDir(
|
|
30861
|
+
ensureDir(path42.dirname(destination));
|
|
30427
30862
|
createRelativeSymlink(source, destination, "dir");
|
|
30428
30863
|
return { component: "hooks", status: "success", path: destination };
|
|
30429
30864
|
}
|
|
@@ -30446,7 +30881,7 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
|
|
|
30446
30881
|
destination,
|
|
30447
30882
|
settings,
|
|
30448
30883
|
stringifyJson3,
|
|
30449
|
-
!
|
|
30884
|
+
!fs41.existsSync(destination),
|
|
30450
30885
|
logger
|
|
30451
30886
|
);
|
|
30452
30887
|
return {
|
|
@@ -30456,8 +30891,8 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
|
|
|
30456
30891
|
};
|
|
30457
30892
|
}
|
|
30458
30893
|
function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
30459
|
-
const source =
|
|
30460
|
-
if (!
|
|
30894
|
+
const source = path42.resolve(sourceRoot, config.source.mcp);
|
|
30895
|
+
if (!fs41.existsSync(source)) {
|
|
30461
30896
|
return skippedMissingSource6("mcp", source);
|
|
30462
30897
|
}
|
|
30463
30898
|
if (options.dryRun) {
|
|
@@ -30482,7 +30917,7 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
|
30482
30917
|
destination,
|
|
30483
30918
|
hostConfig,
|
|
30484
30919
|
stringifyJson3,
|
|
30485
|
-
!
|
|
30920
|
+
!fs41.existsSync(destination),
|
|
30486
30921
|
logger
|
|
30487
30922
|
);
|
|
30488
30923
|
return {
|
|
@@ -30492,8 +30927,8 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
|
30492
30927
|
};
|
|
30493
30928
|
}
|
|
30494
30929
|
function syncSettings2(config, sourceRoot, options, logger, destination) {
|
|
30495
|
-
const source =
|
|
30496
|
-
if (!
|
|
30930
|
+
const source = path42.resolve(sourceRoot, config.source.settings);
|
|
30931
|
+
if (!fs41.existsSync(source)) {
|
|
30497
30932
|
return skippedMissingSource6("settings", source);
|
|
30498
30933
|
}
|
|
30499
30934
|
if (options.dryRun) {
|
|
@@ -30511,7 +30946,7 @@ function syncSettings2(config, sourceRoot, options, logger, destination) {
|
|
|
30511
30946
|
destination,
|
|
30512
30947
|
settings,
|
|
30513
30948
|
stringifyJson3,
|
|
30514
|
-
!
|
|
30949
|
+
!fs41.existsSync(destination),
|
|
30515
30950
|
logger
|
|
30516
30951
|
);
|
|
30517
30952
|
return {
|
|
@@ -30536,11 +30971,11 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
|
|
|
30536
30971
|
backupFile(destination, manifest);
|
|
30537
30972
|
writeManifest(scopePath, manifest);
|
|
30538
30973
|
} else {
|
|
30539
|
-
|
|
30974
|
+
fs41.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
30540
30975
|
}
|
|
30541
30976
|
return true;
|
|
30542
30977
|
}
|
|
30543
|
-
|
|
30978
|
+
fs41.rmSync(destination, { recursive: true, force: true });
|
|
30544
30979
|
return true;
|
|
30545
30980
|
}
|
|
30546
30981
|
function skippedMissingSource6(component, source) {
|
|
@@ -30552,16 +30987,16 @@ function skippedMissingSource6(component, source) {
|
|
|
30552
30987
|
}
|
|
30553
30988
|
function isSymlinkTo6(linkPath, source) {
|
|
30554
30989
|
try {
|
|
30555
|
-
return
|
|
30990
|
+
return fs41.realpathSync(linkPath) === fs41.realpathSync(source);
|
|
30556
30991
|
} catch {
|
|
30557
30992
|
return false;
|
|
30558
30993
|
}
|
|
30559
30994
|
}
|
|
30560
30995
|
function readJsonObject4(filePath) {
|
|
30561
|
-
if (!
|
|
30996
|
+
if (!fs41.existsSync(filePath)) {
|
|
30562
30997
|
return {};
|
|
30563
30998
|
}
|
|
30564
|
-
const parsed = JSON.parse(
|
|
30999
|
+
const parsed = JSON.parse(fs41.readFileSync(filePath, "utf8"));
|
|
30565
31000
|
return isRecord5(parsed) ? parsed : {};
|
|
30566
31001
|
}
|
|
30567
31002
|
function markManaged(value) {
|
|
@@ -30827,7 +31262,7 @@ function writeLossReport(filePath, report) {
|
|
|
30827
31262
|
if (!filePath) {
|
|
30828
31263
|
return;
|
|
30829
31264
|
}
|
|
30830
|
-
|
|
31265
|
+
fs42.writeFileSync(filePath, `${JSON.stringify(report, null, 2)}
|
|
30831
31266
|
`);
|
|
30832
31267
|
}
|
|
30833
31268
|
function prepareKitManifest(scope, projectRoot, kitInfo) {
|
|
@@ -30868,8 +31303,8 @@ function updateManifest(kitInfo, kitSync) {
|
|
|
30868
31303
|
writeManifest(kitSync.scopePath, kitSync.manifest);
|
|
30869
31304
|
}
|
|
30870
31305
|
function resolveKitFilePath(kitPath, relativePath) {
|
|
30871
|
-
const fullPath =
|
|
30872
|
-
return
|
|
31306
|
+
const fullPath = path43.join(kitPath, relativePath);
|
|
31307
|
+
return fs42.existsSync(fullPath) ? fullPath : null;
|
|
30873
31308
|
}
|
|
30874
31309
|
function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
|
|
30875
31310
|
if (removedSourcePaths.length === 0 || !mappings) {
|
|
@@ -30930,9 +31365,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
30930
31365
|
}
|
|
30931
31366
|
if (relativePath.startsWith("agents/")) {
|
|
30932
31367
|
removeManagedCompiledArtifact2(
|
|
30933
|
-
|
|
31368
|
+
path43.join(
|
|
30934
31369
|
resolveTargetPath(paths.agents ?? ""),
|
|
30935
|
-
`${
|
|
31370
|
+
`${path43.parse(relativePath).name}.agent.md`
|
|
30936
31371
|
),
|
|
30937
31372
|
"copilot",
|
|
30938
31373
|
relativePath,
|
|
@@ -30942,9 +31377,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
30942
31377
|
}
|
|
30943
31378
|
if (relativePath.startsWith("commands/")) {
|
|
30944
31379
|
removeManagedCompiledArtifact2(
|
|
30945
|
-
|
|
31380
|
+
path43.join(
|
|
30946
31381
|
resolveTargetPath(paths.prompts ?? ""),
|
|
30947
|
-
`${
|
|
31382
|
+
`${path43.parse(relativePath).name}.prompt.md`
|
|
30948
31383
|
),
|
|
30949
31384
|
"copilot",
|
|
30950
31385
|
relativePath,
|
|
@@ -30954,7 +31389,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
30954
31389
|
}
|
|
30955
31390
|
if (relativePath.endsWith("hooks.json")) {
|
|
30956
31391
|
removeManagedCompiledArtifact2(
|
|
30957
|
-
|
|
31392
|
+
path43.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
30958
31393
|
"copilot",
|
|
30959
31394
|
relativePath,
|
|
30960
31395
|
logger
|
|
@@ -30984,9 +31419,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
30984
31419
|
}
|
|
30985
31420
|
if (relativePath.startsWith("agents/")) {
|
|
30986
31421
|
removeManagedCompiledArtifact2(
|
|
30987
|
-
|
|
31422
|
+
path43.join(
|
|
30988
31423
|
resolveTargetPath(paths.agents ?? ""),
|
|
30989
|
-
`${
|
|
31424
|
+
`${path43.parse(relativePath).name}.toml`
|
|
30990
31425
|
),
|
|
30991
31426
|
"codex",
|
|
30992
31427
|
relativePath,
|
|
@@ -30996,9 +31431,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
30996
31431
|
}
|
|
30997
31432
|
if (relativePath.startsWith("rules/")) {
|
|
30998
31433
|
removeManagedCompiledArtifact2(
|
|
30999
|
-
|
|
31434
|
+
path43.join(
|
|
31000
31435
|
resolveTargetPath(paths.rules ?? ""),
|
|
31001
|
-
`${
|
|
31436
|
+
`${path43.parse(relativePath).name}.rules`
|
|
31002
31437
|
),
|
|
31003
31438
|
"codex",
|
|
31004
31439
|
relativePath,
|
|
@@ -31037,9 +31472,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
31037
31472
|
}
|
|
31038
31473
|
if (relativePath.startsWith("agents/")) {
|
|
31039
31474
|
removeManagedCompiledArtifact2(
|
|
31040
|
-
|
|
31475
|
+
path43.join(
|
|
31041
31476
|
resolveTargetPath(paths.agents ?? ""),
|
|
31042
|
-
`${
|
|
31477
|
+
`${path43.parse(relativePath).name}.md`
|
|
31043
31478
|
),
|
|
31044
31479
|
"opencode",
|
|
31045
31480
|
relativePath,
|
|
@@ -31049,9 +31484,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
31049
31484
|
}
|
|
31050
31485
|
if (relativePath.startsWith("commands/")) {
|
|
31051
31486
|
removeManagedCompiledArtifact2(
|
|
31052
|
-
|
|
31487
|
+
path43.join(
|
|
31053
31488
|
resolveTargetPath(paths.commands ?? ""),
|
|
31054
|
-
`${
|
|
31489
|
+
`${path43.parse(relativePath).name}.md`
|
|
31055
31490
|
),
|
|
31056
31491
|
"opencode",
|
|
31057
31492
|
relativePath,
|
|
@@ -31083,9 +31518,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31083
31518
|
}
|
|
31084
31519
|
if (relativePath.startsWith("agents/")) {
|
|
31085
31520
|
removeManagedCompiledArtifact2(
|
|
31086
|
-
|
|
31521
|
+
path43.join(
|
|
31087
31522
|
resolveTargetPath(paths.agents ?? ""),
|
|
31088
|
-
`${
|
|
31523
|
+
`${path43.parse(relativePath).name}.md`
|
|
31089
31524
|
),
|
|
31090
31525
|
"cursor",
|
|
31091
31526
|
relativePath,
|
|
@@ -31095,9 +31530,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31095
31530
|
}
|
|
31096
31531
|
if (relativePath.startsWith("rules/")) {
|
|
31097
31532
|
removeManagedCompiledArtifact2(
|
|
31098
|
-
|
|
31533
|
+
path43.join(
|
|
31099
31534
|
resolveTargetPath(paths.rules ?? ""),
|
|
31100
|
-
`${
|
|
31535
|
+
`${path43.parse(relativePath).name}.mdc`
|
|
31101
31536
|
),
|
|
31102
31537
|
"cursor",
|
|
31103
31538
|
relativePath,
|
|
@@ -31107,9 +31542,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31107
31542
|
}
|
|
31108
31543
|
if (relativePath.startsWith("commands/")) {
|
|
31109
31544
|
removeManagedCompiledArtifact2(
|
|
31110
|
-
|
|
31545
|
+
path43.join(
|
|
31111
31546
|
resolveTargetPath(paths.skills ?? ""),
|
|
31112
|
-
|
|
31547
|
+
path43.parse(relativePath).name,
|
|
31113
31548
|
"SKILL.md"
|
|
31114
31549
|
),
|
|
31115
31550
|
"cursor",
|
|
@@ -31153,9 +31588,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31153
31588
|
}
|
|
31154
31589
|
if (relativePath.startsWith("rules/")) {
|
|
31155
31590
|
removeManagedCompiledArtifact2(
|
|
31156
|
-
|
|
31591
|
+
path43.join(
|
|
31157
31592
|
resolveTargetPath(paths.rules ?? ""),
|
|
31158
|
-
`${
|
|
31593
|
+
`${path43.parse(relativePath).name}.md`
|
|
31159
31594
|
),
|
|
31160
31595
|
"cline",
|
|
31161
31596
|
relativePath,
|
|
@@ -31165,9 +31600,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31165
31600
|
}
|
|
31166
31601
|
if (relativePath.startsWith("commands/")) {
|
|
31167
31602
|
removeManagedCompiledArtifact2(
|
|
31168
|
-
|
|
31603
|
+
path43.join(
|
|
31169
31604
|
resolveTargetPath(paths.workflows ?? ""),
|
|
31170
|
-
|
|
31605
|
+
path43.basename(relativePath)
|
|
31171
31606
|
),
|
|
31172
31607
|
"cline",
|
|
31173
31608
|
relativePath,
|
|
@@ -31185,17 +31620,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31185
31620
|
}
|
|
31186
31621
|
}
|
|
31187
31622
|
function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
|
|
31188
|
-
if (!
|
|
31623
|
+
if (!fs42.existsSync(artifactPath)) {
|
|
31189
31624
|
return;
|
|
31190
31625
|
}
|
|
31191
|
-
if (!
|
|
31626
|
+
if (!fs42.statSync(artifactPath).isFile()) {
|
|
31192
31627
|
return;
|
|
31193
31628
|
}
|
|
31194
|
-
const marker = extractProvenanceMarker(
|
|
31629
|
+
const marker = extractProvenanceMarker(fs42.readFileSync(artifactPath, "utf8"));
|
|
31195
31630
|
if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
|
|
31196
31631
|
return;
|
|
31197
31632
|
}
|
|
31198
|
-
|
|
31633
|
+
fs42.rmSync(artifactPath, { force: true });
|
|
31199
31634
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31200
31635
|
}
|
|
31201
31636
|
function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
@@ -31226,10 +31661,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
|
|
|
31226
31661
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31227
31662
|
}
|
|
31228
31663
|
function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
31229
|
-
if (!
|
|
31664
|
+
if (!fs42.existsSync(artifactPath)) {
|
|
31230
31665
|
return;
|
|
31231
31666
|
}
|
|
31232
|
-
const content =
|
|
31667
|
+
const content = fs42.readFileSync(artifactPath, "utf8");
|
|
31233
31668
|
const startMarker = "# tangyr: managed mcp start";
|
|
31234
31669
|
const endMarker = "# tangyr: managed mcp end";
|
|
31235
31670
|
const startIndex = content.indexOf(startMarker);
|
|
@@ -31246,19 +31681,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
|
31246
31681
|
const after = content.slice(endIndex + endMarker.length).trimStart();
|
|
31247
31682
|
const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
|
|
31248
31683
|
if (cleaned.length === 0) {
|
|
31249
|
-
|
|
31684
|
+
fs42.rmSync(artifactPath, { force: true });
|
|
31250
31685
|
} else {
|
|
31251
|
-
|
|
31686
|
+
fs42.writeFileSync(artifactPath, `${cleaned}
|
|
31252
31687
|
`);
|
|
31253
31688
|
}
|
|
31254
31689
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31255
31690
|
}
|
|
31256
31691
|
function readJsonObject5(filePath) {
|
|
31257
|
-
if (!
|
|
31692
|
+
if (!fs42.existsSync(filePath)) {
|
|
31258
31693
|
return null;
|
|
31259
31694
|
}
|
|
31260
31695
|
try {
|
|
31261
|
-
const parsed = JSON.parse(
|
|
31696
|
+
const parsed = JSON.parse(fs42.readFileSync(filePath, "utf8"));
|
|
31262
31697
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
31263
31698
|
} catch {
|
|
31264
31699
|
return null;
|
|
@@ -31272,10 +31707,10 @@ function readJsonMetadata(value) {
|
|
|
31272
31707
|
}
|
|
31273
31708
|
function writeJsonOrRemove2(filePath, parsed) {
|
|
31274
31709
|
if (isEmptyJsonValue2(parsed)) {
|
|
31275
|
-
|
|
31710
|
+
fs42.rmSync(filePath, { force: true });
|
|
31276
31711
|
return;
|
|
31277
31712
|
}
|
|
31278
|
-
|
|
31713
|
+
fs42.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
31279
31714
|
`);
|
|
31280
31715
|
}
|
|
31281
31716
|
function isEmptyJsonValue2(value) {
|
|
@@ -31335,8 +31770,8 @@ function removeManagedHookEntries(value, expectedSource) {
|
|
|
31335
31770
|
}
|
|
31336
31771
|
|
|
31337
31772
|
// src/commands/validate.ts
|
|
31338
|
-
import
|
|
31339
|
-
import
|
|
31773
|
+
import fs43 from "fs";
|
|
31774
|
+
import path44 from "path";
|
|
31340
31775
|
var SUPPORTED_KIT_FORMATS2 = [1];
|
|
31341
31776
|
var SUPPORTED_DISCIPLINE_VERSIONS = [
|
|
31342
31777
|
"0.14.0",
|
|
@@ -31420,8 +31855,8 @@ function checkKitFormatSupported(kit) {
|
|
|
31420
31855
|
}
|
|
31421
31856
|
function checkEntrypointExists(kit) {
|
|
31422
31857
|
const entrypoint = "CLAUDE.md";
|
|
31423
|
-
const entrypointPath =
|
|
31424
|
-
if (!
|
|
31858
|
+
const entrypointPath = path44.join(kit.path, entrypoint);
|
|
31859
|
+
if (!fs43.existsSync(entrypointPath)) {
|
|
31425
31860
|
return {
|
|
31426
31861
|
code: "entrypoint-missing",
|
|
31427
31862
|
location: entrypoint,
|
|
@@ -31478,9 +31913,9 @@ function checkComponentFrontmatter(kit) {
|
|
|
31478
31913
|
const missingSet = new Set(kit.components[cat].missing);
|
|
31479
31914
|
for (const name of kit.components[cat].declared) {
|
|
31480
31915
|
if (missingSet.has(name)) continue;
|
|
31481
|
-
const filePath = cat === "skills" ?
|
|
31482
|
-
if (!
|
|
31483
|
-
const relPath =
|
|
31916
|
+
const filePath = cat === "skills" ? path44.join(kit.path, cat, name, "SKILL.md") : path44.join(kit.path, cat, `${name}.md`);
|
|
31917
|
+
if (!fs43.existsSync(filePath)) continue;
|
|
31918
|
+
const relPath = path44.relative(kit.path, filePath);
|
|
31484
31919
|
try {
|
|
31485
31920
|
const { data } = parseMarkdownFrontmatter(filePath);
|
|
31486
31921
|
for (const field of requiredFields) {
|
|
@@ -31505,10 +31940,10 @@ function checkComponentFrontmatter(kit) {
|
|
|
31505
31940
|
}
|
|
31506
31941
|
function checkReservedRootNames(kit) {
|
|
31507
31942
|
const violations = [];
|
|
31508
|
-
if (!
|
|
31943
|
+
if (!fs43.existsSync(kit.path) || !fs43.statSync(kit.path).isDirectory()) {
|
|
31509
31944
|
return violations;
|
|
31510
31945
|
}
|
|
31511
|
-
const entries =
|
|
31946
|
+
const entries = fs43.readdirSync(kit.path, { withFileTypes: true });
|
|
31512
31947
|
for (const entry of entries) {
|
|
31513
31948
|
if (RESERVED_ROOT_NAMES.includes(entry.name)) {
|
|
31514
31949
|
violations.push({
|
|
@@ -31525,8 +31960,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31525
31960
|
const missingSet = new Set(kit.components.commands.missing);
|
|
31526
31961
|
for (const name of kit.components.commands.declared) {
|
|
31527
31962
|
if (missingSet.has(name)) continue;
|
|
31528
|
-
const filePath =
|
|
31529
|
-
if (!
|
|
31963
|
+
const filePath = path44.join(kit.path, "commands", `${name}.md`);
|
|
31964
|
+
if (!fs43.existsSync(filePath)) continue;
|
|
31530
31965
|
let data;
|
|
31531
31966
|
try {
|
|
31532
31967
|
({ data } = parseMarkdownFrontmatter(filePath));
|
|
@@ -31539,7 +31974,7 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31539
31974
|
if (!barred) {
|
|
31540
31975
|
violations.push({
|
|
31541
31976
|
code: "command-human-only-model-invocable",
|
|
31542
|
-
location:
|
|
31977
|
+
location: path44.relative(kit.path, filePath),
|
|
31543
31978
|
message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
|
|
31544
31979
|
});
|
|
31545
31980
|
}
|
|
@@ -31548,8 +31983,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31548
31983
|
}
|
|
31549
31984
|
|
|
31550
31985
|
// src/commands/verify.ts
|
|
31551
|
-
import
|
|
31552
|
-
import
|
|
31986
|
+
import fs44 from "fs";
|
|
31987
|
+
import path45 from "path";
|
|
31553
31988
|
function runVerifyCommand(options, logger) {
|
|
31554
31989
|
const { config, configDir, sourceRoot, kitInfo } = resolveRuntime(
|
|
31555
31990
|
options,
|
|
@@ -31640,8 +32075,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
|
|
|
31640
32075
|
if (!slotPath) {
|
|
31641
32076
|
continue;
|
|
31642
32077
|
}
|
|
31643
|
-
const fullPath = subPath ?
|
|
31644
|
-
if (!
|
|
32078
|
+
const fullPath = subPath ? path45.join(slotPath, subPath) : slotPath;
|
|
32079
|
+
if (!fs44.existsSync(fullPath)) {
|
|
31645
32080
|
failures.push(
|
|
31646
32081
|
`claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
|
|
31647
32082
|
);
|