@alessandroraffa/tangyr 0.14.1 → 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 +888 -586
- 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,20 +23138,98 @@ function toConflictPolicy2(value) {
|
|
|
23113
23138
|
}
|
|
23114
23139
|
|
|
23115
23140
|
// src/commands/install.ts
|
|
23116
|
-
import
|
|
23117
|
-
import
|
|
23118
|
-
|
|
23119
|
-
// src/core/materialize.ts
|
|
23120
|
-
import fs29 from "fs";
|
|
23121
|
-
import path27 from "path";
|
|
23141
|
+
import fs37 from "fs";
|
|
23142
|
+
import path37 from "path";
|
|
23122
23143
|
|
|
23123
|
-
// src/core/
|
|
23124
|
-
import
|
|
23144
|
+
// src/core/channel-state.ts
|
|
23145
|
+
import fs28 from "fs";
|
|
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
|
+
}
|
|
23125
23221
|
|
|
23126
23222
|
// src/core/bundle.ts
|
|
23127
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";
|
|
23128
23230
|
|
|
23129
23231
|
// src/core/integrity.ts
|
|
23232
|
+
import crypto3 from "crypto";
|
|
23130
23233
|
function canonicalize(value) {
|
|
23131
23234
|
if (Array.isArray(value)) {
|
|
23132
23235
|
return value.map(canonicalize);
|
|
@@ -23273,11 +23376,16 @@ function verifyDenyList(denyList, keys, now) {
|
|
|
23273
23376
|
keys,
|
|
23274
23377
|
now
|
|
23275
23378
|
);
|
|
23276
|
-
assertFreshnessWindow(
|
|
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
|
+
);
|
|
23277
23385
|
return list;
|
|
23278
23386
|
}
|
|
23279
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).";
|
|
23280
|
-
function assertFreshnessWindow(issuedAt, expiresAt, now) {
|
|
23388
|
+
function assertFreshnessWindow(issuedAt, expiresAt, now, expiryConsequence) {
|
|
23281
23389
|
const utcDesignatorPattern = /Z|[+-]\d{2}:\d{2}$/;
|
|
23282
23390
|
if (!utcDesignatorPattern.test(issuedAt) || !utcDesignatorPattern.test(expiresAt)) {
|
|
23283
23391
|
throw new IntegrityError(
|
|
@@ -23298,7 +23406,7 @@ function assertFreshnessWindow(issuedAt, expiresAt, now) {
|
|
|
23298
23406
|
}
|
|
23299
23407
|
if (now.getTime() > expires.getTime()) {
|
|
23300
23408
|
throw new IntegrityError(
|
|
23301
|
-
`Signed document expired at ${expiresAt} (now ${now.toISOString()}).
|
|
23409
|
+
`Signed document expired at ${expiresAt} (now ${now.toISOString()}). ${expiryConsequence}`
|
|
23302
23410
|
);
|
|
23303
23411
|
}
|
|
23304
23412
|
if (now.getTime() < issued.getTime()) {
|
|
@@ -23307,19 +23415,68 @@ function assertFreshnessWindow(issuedAt, expiresAt, now) {
|
|
|
23307
23415
|
);
|
|
23308
23416
|
}
|
|
23309
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
|
+
}
|
|
23310
23467
|
|
|
23311
23468
|
// src/core/revocation-state.ts
|
|
23312
|
-
import
|
|
23313
|
-
import
|
|
23469
|
+
import fs29 from "fs";
|
|
23470
|
+
import path27 from "path";
|
|
23314
23471
|
var REVOCATION_STATE_FILENAME = ".tangyr-revocation.json";
|
|
23315
|
-
function
|
|
23316
|
-
return
|
|
23472
|
+
function stateFilePath2(cacheRoot) {
|
|
23473
|
+
return path27.join(cacheRoot, REVOCATION_STATE_FILENAME);
|
|
23317
23474
|
}
|
|
23318
|
-
function
|
|
23319
|
-
const filePath =
|
|
23475
|
+
function readState2(cacheRoot) {
|
|
23476
|
+
const filePath = stateFilePath2(cacheRoot);
|
|
23320
23477
|
let raw;
|
|
23321
23478
|
try {
|
|
23322
|
-
raw =
|
|
23479
|
+
raw = fs29.readFileSync(filePath, "utf8");
|
|
23323
23480
|
} catch (err) {
|
|
23324
23481
|
if (err.code === "ENOENT") {
|
|
23325
23482
|
return { state: {} };
|
|
@@ -23347,26 +23504,26 @@ function readState(cacheRoot) {
|
|
|
23347
23504
|
return { state: parsed };
|
|
23348
23505
|
}
|
|
23349
23506
|
function readRevocationSequence(cacheRoot, originUrl) {
|
|
23350
|
-
const { state, warning } =
|
|
23507
|
+
const { state, warning } = readState2(cacheRoot);
|
|
23351
23508
|
const record = state[originUrl];
|
|
23352
23509
|
const sequence = record !== void 0 && Number.isSafeInteger(record.sequence) ? record.sequence : void 0;
|
|
23353
23510
|
return warning === void 0 ? { sequence } : { sequence, warning };
|
|
23354
23511
|
}
|
|
23355
23512
|
function writeRevocationSequence(cacheRoot, originUrl, sequence, now) {
|
|
23356
|
-
const { state } =
|
|
23513
|
+
const { state } = readState2(cacheRoot);
|
|
23357
23514
|
const existing = state[originUrl]?.sequence;
|
|
23358
23515
|
if (existing !== void 0 && existing >= sequence) {
|
|
23359
23516
|
return;
|
|
23360
23517
|
}
|
|
23361
23518
|
state[originUrl] = { sequence, seenAt: now.toISOString() };
|
|
23362
|
-
const filePath =
|
|
23363
|
-
|
|
23519
|
+
const filePath = stateFilePath2(cacheRoot);
|
|
23520
|
+
fs29.mkdirSync(path27.dirname(filePath), { recursive: true, mode: 448 });
|
|
23364
23521
|
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
23365
|
-
|
|
23522
|
+
fs29.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
23366
23523
|
`, {
|
|
23367
23524
|
mode: 384
|
|
23368
23525
|
});
|
|
23369
|
-
|
|
23526
|
+
fs29.renameSync(tempPath, filePath);
|
|
23370
23527
|
}
|
|
23371
23528
|
function assertSequenceNotReplayed(params) {
|
|
23372
23529
|
const { originUrl, seen, incoming } = params;
|
|
@@ -23538,8 +23695,8 @@ async function assertReferenceNotRevoked(params) {
|
|
|
23538
23695
|
const key = `${reference.name}@${reference.version}`;
|
|
23539
23696
|
if (denyList.entries.includes(key)) {
|
|
23540
23697
|
const entryDir = cacheEntryPath(cacheRoot, reference);
|
|
23541
|
-
if (
|
|
23542
|
-
|
|
23698
|
+
if (fs30.existsSync(entryDir)) {
|
|
23699
|
+
fs30.rmSync(entryDir, { recursive: true, force: true });
|
|
23543
23700
|
}
|
|
23544
23701
|
throw new IntegrityError(
|
|
23545
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).`
|
|
@@ -23586,7 +23743,7 @@ function assertFileWithinCeiling(entryPath, byteLength) {
|
|
|
23586
23743
|
}
|
|
23587
23744
|
var WINDOWS_DRIVE_ABSOLUTE = /^[a-zA-Z]:[\\/]/u;
|
|
23588
23745
|
function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
23589
|
-
if (
|
|
23746
|
+
if (path28.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
|
|
23590
23747
|
throw new IntegrityError(
|
|
23591
23748
|
`Bundle file path "${entryPath}" is absolute \u2014 every file inside a bundle must use a relative path (REQ-INT-004).`
|
|
23592
23749
|
);
|
|
@@ -23602,13 +23759,13 @@ function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
|
23602
23759
|
`Bundle file path "${entryPath}" contains a ".." segment \u2014 directory traversal is rejected (REQ-INT-004).`
|
|
23603
23760
|
);
|
|
23604
23761
|
}
|
|
23605
|
-
const resolved =
|
|
23762
|
+
const resolved = path28.resolve(stagingDir, entryPath);
|
|
23606
23763
|
if (resolved === stagingDir) {
|
|
23607
23764
|
throw new IntegrityError(
|
|
23608
23765
|
`Bundle file path "${entryPath}" resolves to the staging directory itself \u2014 every entry must be a file inside it (REQ-INT-004).`
|
|
23609
23766
|
);
|
|
23610
23767
|
}
|
|
23611
|
-
if (!resolved.startsWith(stagingDir +
|
|
23768
|
+
if (!resolved.startsWith(stagingDir + path28.sep)) {
|
|
23612
23769
|
throw new IntegrityError(
|
|
23613
23770
|
`Bundle file path "${entryPath}" escapes the staging directory \u2014 refusing to write (REQ-INT-004).`
|
|
23614
23771
|
);
|
|
@@ -23660,10 +23817,10 @@ function verifyBundleFileHashes(bundle) {
|
|
|
23660
23817
|
function writeStagedFiles(stagingDir, decoded) {
|
|
23661
23818
|
for (const [rawPath, bytes] of decoded) {
|
|
23662
23819
|
const target = sanitizeBundleFilePath(rawPath, stagingDir);
|
|
23663
|
-
|
|
23820
|
+
fs30.mkdirSync(path28.dirname(target), { recursive: true, mode: 448 });
|
|
23664
23821
|
let existingStat;
|
|
23665
23822
|
try {
|
|
23666
|
-
existingStat =
|
|
23823
|
+
existingStat = fs30.lstatSync(target);
|
|
23667
23824
|
} catch (error) {
|
|
23668
23825
|
if (error.code !== "ENOENT") {
|
|
23669
23826
|
throw error;
|
|
@@ -23674,7 +23831,7 @@ function writeStagedFiles(stagingDir, decoded) {
|
|
|
23674
23831
|
`Refusing to write "${rawPath}" \u2014 a symbolic link already exists at the target path.`
|
|
23675
23832
|
);
|
|
23676
23833
|
}
|
|
23677
|
-
|
|
23834
|
+
fs30.writeFileSync(target, bytes, { mode: 384, flag: "wx" });
|
|
23678
23835
|
}
|
|
23679
23836
|
}
|
|
23680
23837
|
function verifyWarmCacheEntry(entryDir, reference, keys, now) {
|
|
@@ -23740,18 +23897,103 @@ async function materializeRemoteKit(params) {
|
|
|
23740
23897
|
writeStagedFiles(stagingDir, decoded);
|
|
23741
23898
|
writeBundleDocument(stagingDir, bundle);
|
|
23742
23899
|
writeCompletionMarker(stagingDir, reference);
|
|
23743
|
-
if (replace &&
|
|
23744
|
-
|
|
23900
|
+
if (replace && fs30.existsSync(entryDir)) {
|
|
23901
|
+
fs30.rmSync(entryDir, { recursive: true, force: true });
|
|
23745
23902
|
}
|
|
23746
23903
|
publishCacheEntry(stagingDir, entryDir);
|
|
23747
23904
|
return entryDir;
|
|
23748
23905
|
} catch (error) {
|
|
23749
23906
|
if (stagingDir !== void 0) {
|
|
23750
|
-
|
|
23907
|
+
fs30.rmSync(stagingDir, { recursive: true, force: true });
|
|
23751
23908
|
}
|
|
23752
23909
|
throw error;
|
|
23753
23910
|
}
|
|
23754
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
|
+
}
|
|
23755
23997
|
|
|
23756
23998
|
// src/core/kit-source.ts
|
|
23757
23999
|
function resolveCacheOnly(entryDir, reference, keys, now) {
|
|
@@ -23790,13 +24032,25 @@ async function resolveKitSource(params) {
|
|
|
23790
24032
|
if (config.source.type !== "remote") {
|
|
23791
24033
|
return { kitName: kitOption };
|
|
23792
24034
|
}
|
|
23793
|
-
const
|
|
24035
|
+
const selector = parseKitSelector(kitOption ?? "");
|
|
23794
24036
|
if (!config.source.url) {
|
|
23795
24037
|
throw new Error(
|
|
23796
24038
|
"Configuration declares source.type: remote but no source.url. Set source.url to the https endpoint of your kit origin."
|
|
23797
24039
|
);
|
|
23798
24040
|
}
|
|
23799
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 };
|
|
23800
24054
|
const entryDir = cacheEntryPath(cacheRoot, reference);
|
|
23801
24055
|
if (offline) {
|
|
23802
24056
|
return resolveCacheOnly(entryDir, reference, keys, now);
|
|
@@ -23934,6 +24188,54 @@ async function resolveKitSource(params) {
|
|
|
23934
24188
|
writeLastAuthorizedAt(cacheRoot, config.source.url, now);
|
|
23935
24189
|
return { kitPathOverride, kitName: reference.name };
|
|
23936
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
|
+
}
|
|
23937
24239
|
|
|
23938
24240
|
// src/core/keys.ts
|
|
23939
24241
|
var PINNED_PUBLISHER_KEYS = [
|
|
@@ -23955,13 +24257,13 @@ function sleep(ms2) {
|
|
|
23955
24257
|
// src/adapters/codex.ts
|
|
23956
24258
|
var TOML3 = __toESM(require_toml(), 1);
|
|
23957
24259
|
import crypto5 from "crypto";
|
|
23958
|
-
import
|
|
23959
|
-
import
|
|
24260
|
+
import fs32 from "fs";
|
|
24261
|
+
import path31 from "path";
|
|
23960
24262
|
|
|
23961
24263
|
// src/compiler/agents.ts
|
|
23962
24264
|
var TOML = __toESM(require_toml(), 1);
|
|
23963
24265
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
23964
|
-
import
|
|
24266
|
+
import path29 from "path";
|
|
23965
24267
|
|
|
23966
24268
|
// src/compiler/loss-report.ts
|
|
23967
24269
|
function createLossReport() {
|
|
@@ -24025,7 +24327,7 @@ var copilotToolAliasesByClass = {
|
|
|
24025
24327
|
};
|
|
24026
24328
|
function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
24027
24329
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
24028
|
-
const relativeSource = `agents/${
|
|
24330
|
+
const relativeSource = `agents/${path29.basename(sourceFile)}`;
|
|
24029
24331
|
if (target === "opencode") {
|
|
24030
24332
|
return compileOpenCodeAgent(
|
|
24031
24333
|
sourceFile,
|
|
@@ -24066,7 +24368,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
24066
24368
|
mappings,
|
|
24067
24369
|
lossReport
|
|
24068
24370
|
);
|
|
24069
|
-
const overlayKey = `agents/${
|
|
24371
|
+
const overlayKey = `agents/${path29.basename(sourceFile, ".md")}.${target}.yaml`;
|
|
24070
24372
|
const targetFields = {
|
|
24071
24373
|
...translated.fields,
|
|
24072
24374
|
...extensions[overlayKey] ?? {}
|
|
@@ -24100,7 +24402,7 @@ ${TOML.stringify({
|
|
|
24100
24402
|
function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
24101
24403
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
24102
24404
|
throw new Error(
|
|
24103
|
-
`${
|
|
24405
|
+
`${path29.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
|
|
24104
24406
|
);
|
|
24105
24407
|
}
|
|
24106
24408
|
const frontmatter = {
|
|
@@ -24154,7 +24456,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
24154
24456
|
"permission",
|
|
24155
24457
|
"permission-coarsening"
|
|
24156
24458
|
),
|
|
24157
|
-
detail: `${
|
|
24459
|
+
detail: `${path29.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
|
|
24158
24460
|
}
|
|
24159
24461
|
]
|
|
24160
24462
|
});
|
|
@@ -24179,7 +24481,7 @@ ${(0, import_yaml7.stringify)(frontmatter).trim()}
|
|
|
24179
24481
|
function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
24180
24482
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
24181
24483
|
throw new Error(
|
|
24182
|
-
`${
|
|
24484
|
+
`${path29.basename(sourceFile)}: Cursor agent requires a non-empty description field`
|
|
24183
24485
|
);
|
|
24184
24486
|
}
|
|
24185
24487
|
const frontmatter = {
|
|
@@ -24216,7 +24518,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
24216
24518
|
"permission",
|
|
24217
24519
|
"permission-coarsening"
|
|
24218
24520
|
),
|
|
24219
|
-
detail: `${
|
|
24521
|
+
detail: `${path29.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
|
|
24220
24522
|
}
|
|
24221
24523
|
]
|
|
24222
24524
|
});
|
|
@@ -24235,7 +24537,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
24235
24537
|
"provider",
|
|
24236
24538
|
"provider-not-representable"
|
|
24237
24539
|
),
|
|
24238
|
-
detail: `${
|
|
24540
|
+
detail: `${path29.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
24239
24541
|
}
|
|
24240
24542
|
]
|
|
24241
24543
|
});
|
|
@@ -24267,7 +24569,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
|
|
|
24267
24569
|
"persona",
|
|
24268
24570
|
"persona-not-representable"
|
|
24269
24571
|
),
|
|
24270
|
-
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.`
|
|
24271
24573
|
}
|
|
24272
24574
|
]
|
|
24273
24575
|
});
|
|
@@ -24315,7 +24617,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24315
24617
|
field,
|
|
24316
24618
|
"model-not-representable"
|
|
24317
24619
|
),
|
|
24318
|
-
detail: `${
|
|
24620
|
+
detail: `${path29.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
|
|
24319
24621
|
});
|
|
24320
24622
|
return;
|
|
24321
24623
|
}
|
|
@@ -24333,9 +24635,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24333
24635
|
lossReport,
|
|
24334
24636
|
target,
|
|
24335
24637
|
"agents",
|
|
24336
|
-
`agents/${
|
|
24638
|
+
`agents/${path29.basename(sourceFile)}`,
|
|
24337
24639
|
"info",
|
|
24338
|
-
`${
|
|
24640
|
+
`${path29.basename(sourceFile)}: ${field} is delivered through another managed surface.`
|
|
24339
24641
|
);
|
|
24340
24642
|
return;
|
|
24341
24643
|
}
|
|
@@ -24344,7 +24646,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24344
24646
|
field,
|
|
24345
24647
|
action: entryType,
|
|
24346
24648
|
severity: resolveLossSeverity("agent-field", field, entryType),
|
|
24347
|
-
detail: `${
|
|
24649
|
+
detail: `${path29.basename(sourceFile)}: ${field} has no emitted field for this target.`
|
|
24348
24650
|
});
|
|
24349
24651
|
}
|
|
24350
24652
|
function mapToolsToCapabilities(value, mappings) {
|
|
@@ -24941,9 +25243,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
|
|
|
24941
25243
|
}
|
|
24942
25244
|
|
|
24943
25245
|
// src/compiler/rules.ts
|
|
24944
|
-
import
|
|
25246
|
+
import path30 from "path";
|
|
24945
25247
|
var import_yaml8 = __toESM(require_dist(), 1);
|
|
24946
|
-
import
|
|
25248
|
+
import fs31 from "fs";
|
|
24947
25249
|
function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
24948
25250
|
if (target === "copilot") {
|
|
24949
25251
|
addLoss(lossReport, "copilot", "rules", {
|
|
@@ -24980,13 +25282,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
|
24980
25282
|
}
|
|
24981
25283
|
const appendixParts = [];
|
|
24982
25284
|
const dotRulesFiles = [];
|
|
24983
|
-
for (const ruleFile of ts(
|
|
25285
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
24984
25286
|
const parsed = parseRule(ruleFile);
|
|
24985
|
-
const name =
|
|
25287
|
+
const name = path30.basename(ruleFile, ".md");
|
|
24986
25288
|
if (parsed.mode === "exec-policy") {
|
|
24987
25289
|
dotRulesFiles.push({
|
|
24988
25290
|
name: `${name}.rules`,
|
|
24989
|
-
content: `${formatProvenanceMarker("toml", `rules/${
|
|
25291
|
+
content: `${formatProvenanceMarker("toml", `rules/${path30.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
|
|
24990
25292
|
${parsed.body}`
|
|
24991
25293
|
});
|
|
24992
25294
|
continue;
|
|
@@ -24995,7 +25297,7 @@ ${parsed.body}`
|
|
|
24995
25297
|
|
|
24996
25298
|
${parsed.body.trim()}`);
|
|
24997
25299
|
addLoss(lossReport, "codex", "rules", {
|
|
24998
|
-
source: `rules/${
|
|
25300
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
24999
25301
|
fields: [
|
|
25000
25302
|
{
|
|
25001
25303
|
field: "mode",
|
|
@@ -25005,7 +25307,7 @@ ${parsed.body.trim()}`);
|
|
|
25005
25307
|
"mode",
|
|
25006
25308
|
"rule-as-instruction"
|
|
25007
25309
|
),
|
|
25008
|
-
detail: `${
|
|
25310
|
+
detail: `${path30.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
|
|
25009
25311
|
}
|
|
25010
25312
|
]
|
|
25011
25313
|
});
|
|
@@ -25013,7 +25315,7 @@ ${parsed.body.trim()}`);
|
|
|
25013
25315
|
return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
|
|
25014
25316
|
}
|
|
25015
25317
|
function parseRule(ruleFile) {
|
|
25016
|
-
const content =
|
|
25318
|
+
const content = fs31.readFileSync(ruleFile, "utf8");
|
|
25017
25319
|
if (!content.startsWith("---\n")) {
|
|
25018
25320
|
return { mode: "guidance", body: content };
|
|
25019
25321
|
}
|
|
@@ -25037,14 +25339,14 @@ function isRuleMode(value) {
|
|
|
25037
25339
|
}
|
|
25038
25340
|
function compileOpenCodeRules(sourceRulesDir, lossReport) {
|
|
25039
25341
|
const appendixParts = [];
|
|
25040
|
-
for (const ruleFile of ts(
|
|
25342
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
25041
25343
|
const parsed = parseRule(ruleFile);
|
|
25042
|
-
const name =
|
|
25344
|
+
const name = path30.basename(ruleFile, ".md");
|
|
25043
25345
|
appendixParts.push(`## ${name}
|
|
25044
25346
|
|
|
25045
25347
|
${parsed.body.trim()}`);
|
|
25046
25348
|
addLoss(lossReport, "opencode", "rules", {
|
|
25047
|
-
source: `rules/${
|
|
25349
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
25048
25350
|
fields: [
|
|
25049
25351
|
{
|
|
25050
25352
|
field: "rule",
|
|
@@ -25054,7 +25356,7 @@ ${parsed.body.trim()}`);
|
|
|
25054
25356
|
"rule",
|
|
25055
25357
|
"rule-path-scoping"
|
|
25056
25358
|
),
|
|
25057
|
-
detail: `${
|
|
25359
|
+
detail: `${path30.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
|
|
25058
25360
|
}
|
|
25059
25361
|
]
|
|
25060
25362
|
});
|
|
@@ -25063,9 +25365,9 @@ ${parsed.body.trim()}`);
|
|
|
25063
25365
|
}
|
|
25064
25366
|
function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
25065
25367
|
const dotRulesFiles = [];
|
|
25066
|
-
for (const ruleFile of ts(
|
|
25067
|
-
const content =
|
|
25068
|
-
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");
|
|
25069
25371
|
let frontmatterData = {};
|
|
25070
25372
|
let body = content;
|
|
25071
25373
|
if (content.startsWith("---\n")) {
|
|
@@ -25094,7 +25396,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
|
25094
25396
|
}
|
|
25095
25397
|
const marker = formatProvenanceMarker(
|
|
25096
25398
|
"markdown",
|
|
25097
|
-
`rules/${
|
|
25399
|
+
`rules/${path30.basename(ruleFile)}`,
|
|
25098
25400
|
computeSourceHash(ruleFile),
|
|
25099
25401
|
"cursor"
|
|
25100
25402
|
);
|
|
@@ -25110,9 +25412,9 @@ ${body}`;
|
|
|
25110
25412
|
}
|
|
25111
25413
|
function compileClineRules(sourceRulesDir, lossReport) {
|
|
25112
25414
|
const dotRulesFiles = [];
|
|
25113
|
-
for (const ruleFile of ts(
|
|
25114
|
-
const content =
|
|
25115
|
-
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");
|
|
25116
25418
|
let frontmatterData = {};
|
|
25117
25419
|
let body = content;
|
|
25118
25420
|
if (content.startsWith("---\n")) {
|
|
@@ -25129,13 +25431,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25129
25431
|
}
|
|
25130
25432
|
const marker = formatProvenanceMarker(
|
|
25131
25433
|
"markdown",
|
|
25132
|
-
`rules/${
|
|
25434
|
+
`rules/${path30.basename(ruleFile)}`,
|
|
25133
25435
|
computeSourceHash(ruleFile),
|
|
25134
25436
|
"cline"
|
|
25135
25437
|
);
|
|
25136
25438
|
if (frontmatterData.mode === "exec-policy") {
|
|
25137
25439
|
addLoss(lossReport, "cline", "rules", {
|
|
25138
|
-
source: `rules/${
|
|
25440
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
25139
25441
|
fields: [
|
|
25140
25442
|
{
|
|
25141
25443
|
field: "mode",
|
|
@@ -25145,7 +25447,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25145
25447
|
"mode",
|
|
25146
25448
|
"rule-mode-downgrade"
|
|
25147
25449
|
),
|
|
25148
|
-
detail: `${
|
|
25450
|
+
detail: `${path30.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
|
|
25149
25451
|
}
|
|
25150
25452
|
]
|
|
25151
25453
|
});
|
|
@@ -25190,7 +25492,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
25190
25492
|
rules: profile.rules
|
|
25191
25493
|
};
|
|
25192
25494
|
const rules = compileRules(
|
|
25193
|
-
|
|
25495
|
+
path31.join(sourceRoot, config.source.rules),
|
|
25194
25496
|
"codex",
|
|
25195
25497
|
mappings,
|
|
25196
25498
|
lossReport
|
|
@@ -25335,9 +25637,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
25335
25637
|
function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
|
|
25336
25638
|
const cp = mappings.modelTiers.custom_provider;
|
|
25337
25639
|
if (!cp) return "";
|
|
25338
|
-
const agentsDir =
|
|
25339
|
-
if (!
|
|
25340
|
-
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();
|
|
25341
25643
|
const hasProviderAgent = agentFiles.some((agentFile) => {
|
|
25342
25644
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
25343
25645
|
return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
@@ -25402,7 +25704,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
25402
25704
|
}
|
|
25403
25705
|
];
|
|
25404
25706
|
for (const ruleFile of rules.dotRulesFiles) {
|
|
25405
|
-
const destination =
|
|
25707
|
+
const destination = path31.join(rulesRoot, ruleFile.name);
|
|
25406
25708
|
if (options.dryRun) {
|
|
25407
25709
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
25408
25710
|
outcomes.push({
|
|
@@ -25430,15 +25732,15 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
25430
25732
|
return outcomes;
|
|
25431
25733
|
}
|
|
25432
25734
|
function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
25433
|
-
const source =
|
|
25735
|
+
const source = path31.join(sourceRoot, config.source.instructions);
|
|
25434
25736
|
const destination = resolveTargetPath(paths.instructions);
|
|
25435
|
-
const composed = `${
|
|
25737
|
+
const composed = `${fs32.readFileSync(source, "utf8").trim()}
|
|
25436
25738
|
|
|
25437
25739
|
--- tangyr managed rules ---
|
|
25438
25740
|
${agentsAppendix}`.trim();
|
|
25439
25741
|
const marker = formatProvenanceMarker(
|
|
25440
25742
|
"markdown",
|
|
25441
|
-
|
|
25743
|
+
path31.basename(config.source.instructions),
|
|
25442
25744
|
hashString(composed),
|
|
25443
25745
|
"codex"
|
|
25444
25746
|
);
|
|
@@ -25465,9 +25767,9 @@ ${composed}
|
|
|
25465
25767
|
);
|
|
25466
25768
|
}
|
|
25467
25769
|
function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
25468
|
-
const source =
|
|
25770
|
+
const source = path31.resolve(sourceRoot, config.source.skills);
|
|
25469
25771
|
const destination = resolveTargetPath(paths.skills);
|
|
25470
|
-
if (!
|
|
25772
|
+
if (!fs32.existsSync(source)) {
|
|
25471
25773
|
return skippedMissingSource("skills", source);
|
|
25472
25774
|
}
|
|
25473
25775
|
if (options.dryRun) {
|
|
@@ -25483,29 +25785,29 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
|
|
|
25483
25785
|
};
|
|
25484
25786
|
}
|
|
25485
25787
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
25486
|
-
|
|
25788
|
+
fs32.unlinkSync(destination);
|
|
25487
25789
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
25488
25790
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
25489
25791
|
return { component: "skills", status: "conflict", path: destination };
|
|
25490
25792
|
} else if (artifactClass === "managed-symlink") {
|
|
25491
|
-
|
|
25793
|
+
fs32.unlinkSync(destination);
|
|
25492
25794
|
}
|
|
25493
|
-
ensureDir(
|
|
25795
|
+
ensureDir(path31.dirname(destination));
|
|
25494
25796
|
createRelativeSymlink(source, destination, "dir");
|
|
25495
25797
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
25496
25798
|
return { component: "skills", status: "success", path: destination };
|
|
25497
25799
|
}
|
|
25498
25800
|
function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
25499
|
-
const sourceAgentsRoot =
|
|
25500
|
-
if (!
|
|
25801
|
+
const sourceAgentsRoot = path31.join(sourceRoot, config.source.agents);
|
|
25802
|
+
if (!fs32.existsSync(sourceAgentsRoot)) {
|
|
25501
25803
|
return [skippedMissingSource("agents", sourceAgentsRoot)];
|
|
25502
25804
|
}
|
|
25503
|
-
const sourceAgents = ts(
|
|
25805
|
+
const sourceAgents = ts(path31.join(sourceAgentsRoot, "*.md")).sort();
|
|
25504
25806
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
25505
25807
|
return sourceAgents.map((agentFile) => {
|
|
25506
|
-
const destination =
|
|
25808
|
+
const destination = path31.join(
|
|
25507
25809
|
agentsRoot,
|
|
25508
|
-
`${
|
|
25810
|
+
`${path31.basename(agentFile, ".md")}.toml`
|
|
25509
25811
|
);
|
|
25510
25812
|
const compiled = compileAgent(
|
|
25511
25813
|
agentFile,
|
|
@@ -25541,10 +25843,10 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
|
|
|
25541
25843
|
}
|
|
25542
25844
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
25543
25845
|
const sourceLabel = hooksSourceLabel(config);
|
|
25544
|
-
if (!
|
|
25846
|
+
if (!fs32.existsSync(source)) {
|
|
25545
25847
|
return skippedMissingSource("hooks", source);
|
|
25546
25848
|
}
|
|
25547
|
-
const sourceHooksJson = JSON.parse(
|
|
25849
|
+
const sourceHooksJson = JSON.parse(fs32.readFileSync(source, "utf8"));
|
|
25548
25850
|
const compiled = compileHooks(
|
|
25549
25851
|
sourceHooksJson,
|
|
25550
25852
|
"codex",
|
|
@@ -25566,7 +25868,7 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
|
|
|
25566
25868
|
destination,
|
|
25567
25869
|
hostHooks,
|
|
25568
25870
|
stringifyJson2,
|
|
25569
|
-
!
|
|
25871
|
+
!fs32.existsSync(destination),
|
|
25570
25872
|
logger
|
|
25571
25873
|
);
|
|
25572
25874
|
return {
|
|
@@ -25579,7 +25881,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
|
|
|
25579
25881
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
25580
25882
|
const sourceLabel = mcpSourceLabel(config);
|
|
25581
25883
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
25582
|
-
if (!
|
|
25884
|
+
if (!fs32.existsSync(source)) {
|
|
25583
25885
|
if (providerToml && !options.dryRun) {
|
|
25584
25886
|
const changed2 = writeTomlManagedSection(
|
|
25585
25887
|
destination,
|
|
@@ -25594,7 +25896,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
|
|
|
25594
25896
|
}
|
|
25595
25897
|
return skippedMissingSource("mcp", source);
|
|
25596
25898
|
}
|
|
25597
|
-
const sourceMcpJson = JSON.parse(
|
|
25899
|
+
const sourceMcpJson = JSON.parse(fs32.readFileSync(source, "utf8"));
|
|
25598
25900
|
const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
|
|
25599
25901
|
const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
|
|
25600
25902
|
if (options.dryRun) {
|
|
@@ -25616,12 +25918,12 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
|
|
|
25616
25918
|
if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
25617
25919
|
return { component, status: "conflict", path: destination };
|
|
25618
25920
|
}
|
|
25619
|
-
ensureDir(
|
|
25620
|
-
|
|
25921
|
+
ensureDir(path31.dirname(destination));
|
|
25922
|
+
fs32.writeFileSync(destination, content);
|
|
25621
25923
|
return { component, status: "success", path: destination };
|
|
25622
25924
|
}
|
|
25623
25925
|
function writeTomlManagedSection(destination, managedContent, logger) {
|
|
25624
|
-
const current =
|
|
25926
|
+
const current = fs32.existsSync(destination) ? fs32.readFileSync(destination, "utf8") : "";
|
|
25625
25927
|
const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
|
|
25626
25928
|
if (isFirstWrite) {
|
|
25627
25929
|
logger.warn(
|
|
@@ -25637,8 +25939,8 @@ ${managedMcpEnd}
|
|
|
25637
25939
|
if (current === next.trimStart()) {
|
|
25638
25940
|
return false;
|
|
25639
25941
|
}
|
|
25640
|
-
ensureDir(
|
|
25641
|
-
|
|
25942
|
+
ensureDir(path31.dirname(destination));
|
|
25943
|
+
fs32.writeFileSync(destination, next.trimStart());
|
|
25642
25944
|
return true;
|
|
25643
25945
|
}
|
|
25644
25946
|
function removeManagedTomlSection(content) {
|
|
@@ -25665,16 +25967,16 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
|
|
|
25665
25967
|
backupFile(destination, manifest);
|
|
25666
25968
|
writeManifest(scopePath, manifest);
|
|
25667
25969
|
} else {
|
|
25668
|
-
|
|
25970
|
+
fs32.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
25669
25971
|
}
|
|
25670
25972
|
return true;
|
|
25671
25973
|
}
|
|
25672
|
-
|
|
25974
|
+
fs32.rmSync(destination, { recursive: true, force: true });
|
|
25673
25975
|
return true;
|
|
25674
25976
|
}
|
|
25675
25977
|
function isCompiledCurrent(destination, expectedContent, expectedHash) {
|
|
25676
25978
|
try {
|
|
25677
|
-
const current =
|
|
25979
|
+
const current = fs32.readFileSync(destination, "utf8");
|
|
25678
25980
|
const marker = extractProvenanceMarker(current);
|
|
25679
25981
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "codex" && current === expectedContent : current === expectedContent;
|
|
25680
25982
|
} catch {
|
|
@@ -25693,16 +25995,16 @@ function shouldSkipComponent(options, component) {
|
|
|
25693
25995
|
}
|
|
25694
25996
|
function isSymlinkTo(linkPath, source) {
|
|
25695
25997
|
try {
|
|
25696
|
-
return
|
|
25998
|
+
return fs32.realpathSync(linkPath) === fs32.realpathSync(source);
|
|
25697
25999
|
} catch {
|
|
25698
26000
|
return false;
|
|
25699
26001
|
}
|
|
25700
26002
|
}
|
|
25701
26003
|
function readJsonObject3(filePath) {
|
|
25702
|
-
if (!
|
|
26004
|
+
if (!fs32.existsSync(filePath)) {
|
|
25703
26005
|
return {};
|
|
25704
26006
|
}
|
|
25705
|
-
const parsed = JSON.parse(
|
|
26007
|
+
const parsed = JSON.parse(fs32.readFileSync(filePath, "utf8"));
|
|
25706
26008
|
return isRecord4(parsed) ? parsed : {};
|
|
25707
26009
|
}
|
|
25708
26010
|
function stringifyJson2(value) {
|
|
@@ -25718,16 +26020,16 @@ function hashString(value) {
|
|
|
25718
26020
|
|
|
25719
26021
|
// src/adapters/copilot.ts
|
|
25720
26022
|
import crypto6 from "crypto";
|
|
25721
|
-
import
|
|
25722
|
-
import
|
|
26023
|
+
import fs33 from "fs";
|
|
26024
|
+
import path33 from "path";
|
|
25723
26025
|
|
|
25724
26026
|
// src/compiler/commands.ts
|
|
25725
26027
|
var import_yaml9 = __toESM(require_dist(), 1);
|
|
25726
|
-
import
|
|
26028
|
+
import path32 from "path";
|
|
25727
26029
|
function compileCommandPrompt(sourceFile) {
|
|
25728
26030
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
25729
|
-
const relativeSource = `commands/${
|
|
25730
|
-
const fields = promptFrontmatter(data,
|
|
26031
|
+
const relativeSource = `commands/${path32.basename(sourceFile)}`;
|
|
26032
|
+
const fields = promptFrontmatter(data, path32.basename(sourceFile, ".md"));
|
|
25731
26033
|
const marker = formatProvenanceMarker(
|
|
25732
26034
|
"markdown",
|
|
25733
26035
|
relativeSource,
|
|
@@ -25902,13 +26204,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
25902
26204
|
}
|
|
25903
26205
|
function syncProviderLoss(config, sourceRoot, mappings, lossReport) {
|
|
25904
26206
|
if (!mappings.modelTiers.custom_provider) return;
|
|
25905
|
-
const agentsDir =
|
|
25906
|
-
if (!
|
|
25907
|
-
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()) {
|
|
25908
26210
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
25909
26211
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
25910
26212
|
if (hasProvider) {
|
|
25911
|
-
const basename =
|
|
26213
|
+
const basename = path33.basename(agentFile);
|
|
25912
26214
|
addLoss(lossReport, "copilot", "agents", {
|
|
25913
26215
|
source: `agents/${basename}`,
|
|
25914
26216
|
fields: [
|
|
@@ -25933,23 +26235,23 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
|
|
|
25933
26235
|
logger.verbose(message);
|
|
25934
26236
|
return [{ component: "instructions", status: "skipped", path: message }];
|
|
25935
26237
|
}
|
|
25936
|
-
const source =
|
|
25937
|
-
if (!
|
|
26238
|
+
const source = path33.resolve(sourceRoot, config.source.instructions);
|
|
26239
|
+
if (!fs33.existsSync(source)) {
|
|
25938
26240
|
return [skippedMissingSource2("instructions", source)];
|
|
25939
26241
|
}
|
|
25940
|
-
const rawContent =
|
|
26242
|
+
const rawContent = fs33.readFileSync(source, "utf8");
|
|
25941
26243
|
const contentHash = hashString2(rawContent);
|
|
25942
26244
|
const marker = formatProvenanceMarker(
|
|
25943
26245
|
"markdown",
|
|
25944
|
-
|
|
26246
|
+
path33.basename(config.source.instructions),
|
|
25945
26247
|
contentHash,
|
|
25946
26248
|
"copilot"
|
|
25947
26249
|
);
|
|
25948
26250
|
const composedContent = `${marker}
|
|
25949
26251
|
${rawContent}`;
|
|
25950
26252
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
25951
|
-
const agentsMdDest =
|
|
25952
|
-
const mirrorDest =
|
|
26253
|
+
const agentsMdDest = path33.resolve(projectRoot, "AGENTS.md");
|
|
26254
|
+
const mirrorDest = path33.resolve(
|
|
25953
26255
|
projectRoot,
|
|
25954
26256
|
".github",
|
|
25955
26257
|
"copilot-instructions.md"
|
|
@@ -26003,17 +26305,17 @@ function writeInstructionsFile(component, destination, content, contentHash, con
|
|
|
26003
26305
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26004
26306
|
return { component, status: "conflict", path: destination };
|
|
26005
26307
|
}
|
|
26006
|
-
ensureDir(
|
|
26007
|
-
|
|
26308
|
+
ensureDir(path33.dirname(destination));
|
|
26309
|
+
fs33.writeFileSync(destination, content);
|
|
26008
26310
|
return { component, status: "success", path: destination };
|
|
26009
26311
|
}
|
|
26010
26312
|
function hashString2(value) {
|
|
26011
26313
|
return `sha256:${crypto6.createHash("sha256").update(value).digest("hex")}`;
|
|
26012
26314
|
}
|
|
26013
26315
|
function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26014
|
-
const source =
|
|
26316
|
+
const source = path33.resolve(sourceRoot, config.source.skills);
|
|
26015
26317
|
const destination = resolveTargetPath(paths.skills);
|
|
26016
|
-
if (!
|
|
26318
|
+
if (!fs33.existsSync(source)) {
|
|
26017
26319
|
return skippedMissingSource2("skills", source);
|
|
26018
26320
|
}
|
|
26019
26321
|
if (options.dryRun) {
|
|
@@ -26029,27 +26331,27 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
26029
26331
|
};
|
|
26030
26332
|
}
|
|
26031
26333
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26032
|
-
|
|
26334
|
+
fs33.unlinkSync(destination);
|
|
26033
26335
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26034
26336
|
return { component: "skills", status: "conflict", path: destination };
|
|
26035
26337
|
} else if (artifactClass === "managed-symlink") {
|
|
26036
|
-
|
|
26338
|
+
fs33.unlinkSync(destination);
|
|
26037
26339
|
}
|
|
26038
|
-
ensureDir(
|
|
26340
|
+
ensureDir(path33.dirname(destination));
|
|
26039
26341
|
createRelativeSymlink(source, destination, "dir");
|
|
26040
26342
|
return { component: "skills", status: "success", path: destination };
|
|
26041
26343
|
}
|
|
26042
26344
|
function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26043
|
-
const sourceAgentsRoot =
|
|
26044
|
-
if (!
|
|
26345
|
+
const sourceAgentsRoot = path33.join(sourceRoot, config.source.agents);
|
|
26346
|
+
if (!fs33.existsSync(sourceAgentsRoot)) {
|
|
26045
26347
|
return [skippedMissingSource2("agents", sourceAgentsRoot)];
|
|
26046
26348
|
}
|
|
26047
|
-
const sourceAgents = ts(
|
|
26349
|
+
const sourceAgents = ts(path33.join(sourceAgentsRoot, "*.md")).sort();
|
|
26048
26350
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
26049
26351
|
return sourceAgents.map((agentFile) => {
|
|
26050
|
-
const destination =
|
|
26352
|
+
const destination = path33.join(
|
|
26051
26353
|
agentsRoot,
|
|
26052
|
-
`${
|
|
26354
|
+
`${path33.basename(agentFile, ".md")}.agent.md`
|
|
26053
26355
|
);
|
|
26054
26356
|
const compiled = compileAgent(
|
|
26055
26357
|
agentFile,
|
|
@@ -26077,16 +26379,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
26077
26379
|
});
|
|
26078
26380
|
}
|
|
26079
26381
|
function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26080
|
-
const sourceCommandsRoot =
|
|
26081
|
-
if (!
|
|
26382
|
+
const sourceCommandsRoot = path33.join(sourceRoot, config.source.commands);
|
|
26383
|
+
if (!fs33.existsSync(sourceCommandsRoot)) {
|
|
26082
26384
|
return [skippedMissingSource2("commands", sourceCommandsRoot)];
|
|
26083
26385
|
}
|
|
26084
|
-
const sourceCommands = ts(
|
|
26386
|
+
const sourceCommands = ts(path33.join(sourceCommandsRoot, "*.md")).sort();
|
|
26085
26387
|
const promptsRoot = resolveTargetPath(paths.prompts);
|
|
26086
26388
|
return sourceCommands.map((commandFile) => {
|
|
26087
|
-
const destination =
|
|
26389
|
+
const destination = path33.join(
|
|
26088
26390
|
promptsRoot,
|
|
26089
|
-
`${
|
|
26391
|
+
`${path33.basename(commandFile, ".md")}.prompt.md`
|
|
26090
26392
|
);
|
|
26091
26393
|
const compiled = compileCommandPrompt(commandFile);
|
|
26092
26394
|
if (options.dryRun) {
|
|
@@ -26112,14 +26414,14 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
|
|
|
26112
26414
|
function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, logger) {
|
|
26113
26415
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
26114
26416
|
const sourceLabel = hooksSourceLabel(config);
|
|
26115
|
-
const destination =
|
|
26417
|
+
const destination = path33.join(
|
|
26116
26418
|
resolveTargetPath(paths.hooks),
|
|
26117
26419
|
"tangyr-managed.json"
|
|
26118
26420
|
);
|
|
26119
|
-
if (!
|
|
26421
|
+
if (!fs33.existsSync(source)) {
|
|
26120
26422
|
return skippedMissingSource2("hooks", source);
|
|
26121
26423
|
}
|
|
26122
|
-
const sourceHooksJson = JSON.parse(
|
|
26424
|
+
const sourceHooksJson = JSON.parse(fs33.readFileSync(source, "utf8"));
|
|
26123
26425
|
const compiled = compileHooks(
|
|
26124
26426
|
sourceHooksJson,
|
|
26125
26427
|
"copilot",
|
|
@@ -26156,10 +26458,10 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger) {
|
|
|
26156
26458
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
26157
26459
|
const sourceLabel = mcpSourceLabel(config);
|
|
26158
26460
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
26159
|
-
if (!
|
|
26461
|
+
if (!fs33.existsSync(source)) {
|
|
26160
26462
|
return skippedMissingSource2("mcp", source);
|
|
26161
26463
|
}
|
|
26162
|
-
const sourceMcpJson = JSON.parse(
|
|
26464
|
+
const sourceMcpJson = JSON.parse(fs33.readFileSync(source, "utf8"));
|
|
26163
26465
|
const compiled = compileMcp(
|
|
26164
26466
|
sourceMcpJson,
|
|
26165
26467
|
"copilot",
|
|
@@ -26189,13 +26491,13 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
|
|
|
26189
26491
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26190
26492
|
return { component, status: "conflict", path: destination };
|
|
26191
26493
|
}
|
|
26192
|
-
ensureDir(
|
|
26193
|
-
|
|
26494
|
+
ensureDir(path33.dirname(destination));
|
|
26495
|
+
fs33.writeFileSync(destination, content);
|
|
26194
26496
|
return { component, status: "success", path: destination };
|
|
26195
26497
|
}
|
|
26196
26498
|
function isCompiledCurrent2(destination, expectedContent, expectedHash) {
|
|
26197
26499
|
try {
|
|
26198
|
-
const current =
|
|
26500
|
+
const current = fs33.readFileSync(destination, "utf8");
|
|
26199
26501
|
const marker = extractProvenanceMarker(current);
|
|
26200
26502
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "copilot" && current === expectedContent : current === expectedContent;
|
|
26201
26503
|
} catch {
|
|
@@ -26218,11 +26520,11 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
|
|
|
26218
26520
|
backupFile(destination, manifest);
|
|
26219
26521
|
writeManifest(scopePath, manifest);
|
|
26220
26522
|
} else {
|
|
26221
|
-
|
|
26523
|
+
fs33.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
26222
26524
|
}
|
|
26223
26525
|
return true;
|
|
26224
26526
|
}
|
|
26225
|
-
|
|
26527
|
+
fs33.rmSync(destination, { recursive: true, force: true });
|
|
26226
26528
|
return true;
|
|
26227
26529
|
}
|
|
26228
26530
|
function shouldSkipComponent2(options, component) {
|
|
@@ -26231,12 +26533,12 @@ function shouldSkipComponent2(options, component) {
|
|
|
26231
26533
|
function cleanupLegacyAgents(paths, options, logger) {
|
|
26232
26534
|
const currentAgentsRoot = resolveTargetPath(paths.agents);
|
|
26233
26535
|
const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
|
|
26234
|
-
if (
|
|
26536
|
+
if (path33.resolve(currentAgentsRoot) === path33.resolve(legacyAgentsRoot)) {
|
|
26235
26537
|
return [];
|
|
26236
26538
|
}
|
|
26237
26539
|
const outcomes = [];
|
|
26238
26540
|
for (const filePath of ts(
|
|
26239
|
-
|
|
26541
|
+
path33.join(legacyAgentsRoot, "*.agent.md")
|
|
26240
26542
|
).sort()) {
|
|
26241
26543
|
if (!isCopilotManagedCompiledFile(filePath)) {
|
|
26242
26544
|
continue;
|
|
@@ -26246,14 +26548,14 @@ function cleanupLegacyAgents(paths, options, logger) {
|
|
|
26246
26548
|
outcomes.push({ component: "agents", status: "dry-run", path: filePath });
|
|
26247
26549
|
continue;
|
|
26248
26550
|
}
|
|
26249
|
-
|
|
26551
|
+
fs33.rmSync(filePath, { force: true });
|
|
26250
26552
|
outcomes.push({ component: "agents", status: "success", path: filePath });
|
|
26251
26553
|
}
|
|
26252
26554
|
return outcomes;
|
|
26253
26555
|
}
|
|
26254
26556
|
function isCopilotManagedCompiledFile(filePath) {
|
|
26255
26557
|
try {
|
|
26256
|
-
return extractProvenanceMarker(
|
|
26558
|
+
return extractProvenanceMarker(fs33.readFileSync(filePath, "utf8"))?.target === "copilot";
|
|
26257
26559
|
} catch {
|
|
26258
26560
|
return false;
|
|
26259
26561
|
}
|
|
@@ -26267,7 +26569,7 @@ function skippedMissingSource2(component, source) {
|
|
|
26267
26569
|
}
|
|
26268
26570
|
function isSymlinkTo2(linkPath, source) {
|
|
26269
26571
|
try {
|
|
26270
|
-
return
|
|
26572
|
+
return fs33.realpathSync(linkPath) === fs33.realpathSync(source);
|
|
26271
26573
|
} catch {
|
|
26272
26574
|
return false;
|
|
26273
26575
|
}
|
|
@@ -26275,8 +26577,8 @@ function isSymlinkTo2(linkPath, source) {
|
|
|
26275
26577
|
|
|
26276
26578
|
// src/adapters/cursor.ts
|
|
26277
26579
|
import crypto7 from "crypto";
|
|
26278
|
-
import
|
|
26279
|
-
import
|
|
26580
|
+
import fs34 from "fs";
|
|
26581
|
+
import path34 from "path";
|
|
26280
26582
|
function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26281
26583
|
const scope = options.scope ?? "global";
|
|
26282
26584
|
const profile = resolveTargetPaths({
|
|
@@ -26427,9 +26729,9 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
|
|
|
26427
26729
|
return { target: "cursor", outcomes };
|
|
26428
26730
|
}
|
|
26429
26731
|
function syncInstructions2(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
26430
|
-
const source =
|
|
26732
|
+
const source = path34.join(sourceRoot, config.source.instructions);
|
|
26431
26733
|
const destination = resolveTargetPath(paths.instructions);
|
|
26432
|
-
const baseContent =
|
|
26734
|
+
const baseContent = fs34.existsSync(source) ? fs34.readFileSync(source, "utf8").trim() : "";
|
|
26433
26735
|
const personaContent = extractPrimaryPersonaContent(
|
|
26434
26736
|
config,
|
|
26435
26737
|
sourceRoot,
|
|
@@ -26442,7 +26744,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
|
|
|
26442
26744
|
${personaContent}`.trim() : baseContent;
|
|
26443
26745
|
const marker = formatProvenanceMarker(
|
|
26444
26746
|
"markdown",
|
|
26445
|
-
|
|
26747
|
+
path34.basename(config.source.instructions),
|
|
26446
26748
|
hashString3(composed),
|
|
26447
26749
|
"cursor"
|
|
26448
26750
|
);
|
|
@@ -26467,11 +26769,11 @@ ${composed}
|
|
|
26467
26769
|
);
|
|
26468
26770
|
}
|
|
26469
26771
|
function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
26470
|
-
const agentsDir =
|
|
26471
|
-
if (!
|
|
26772
|
+
const agentsDir = path34.join(sourceRoot, config.source.agents);
|
|
26773
|
+
if (!fs34.existsSync(agentsDir)) {
|
|
26472
26774
|
return null;
|
|
26473
26775
|
}
|
|
26474
|
-
const agentFiles = ts(
|
|
26776
|
+
const agentFiles = ts(path34.join(agentsDir, "*.md")).sort();
|
|
26475
26777
|
if (agentFiles.length === 0) {
|
|
26476
26778
|
return null;
|
|
26477
26779
|
}
|
|
@@ -26494,7 +26796,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
26494
26796
|
return null;
|
|
26495
26797
|
}
|
|
26496
26798
|
addLoss(lossReport, "cursor", "instructions", {
|
|
26497
|
-
source: `agents/${
|
|
26799
|
+
source: `agents/${path34.basename(primaryFile)}`,
|
|
26498
26800
|
fields: [
|
|
26499
26801
|
{
|
|
26500
26802
|
field: "persona",
|
|
@@ -26504,23 +26806,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
26504
26806
|
"persona",
|
|
26505
26807
|
"instructions-shim"
|
|
26506
26808
|
),
|
|
26507
|
-
detail: `Primary persona from ${
|
|
26809
|
+
detail: `Primary persona from ${path34.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
|
|
26508
26810
|
}
|
|
26509
26811
|
]
|
|
26510
26812
|
});
|
|
26511
26813
|
return body.trim();
|
|
26512
26814
|
}
|
|
26513
26815
|
function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26514
|
-
const sourceAgentsRoot =
|
|
26515
|
-
if (!
|
|
26816
|
+
const sourceAgentsRoot = path34.join(sourceRoot, config.source.agents);
|
|
26817
|
+
if (!fs34.existsSync(sourceAgentsRoot)) {
|
|
26516
26818
|
return [skippedMissingSource3("agents", sourceAgentsRoot)];
|
|
26517
26819
|
}
|
|
26518
|
-
const sourceAgents = ts(
|
|
26820
|
+
const sourceAgents = ts(path34.join(sourceAgentsRoot, "*.md")).sort();
|
|
26519
26821
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
26520
26822
|
return sourceAgents.map((agentFile) => {
|
|
26521
|
-
const destination =
|
|
26823
|
+
const destination = path34.join(
|
|
26522
26824
|
agentsRoot,
|
|
26523
|
-
`${
|
|
26825
|
+
`${path34.basename(agentFile, ".md")}.md`
|
|
26524
26826
|
);
|
|
26525
26827
|
let compiled;
|
|
26526
26828
|
try {
|
|
@@ -26561,14 +26863,14 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
26561
26863
|
});
|
|
26562
26864
|
}
|
|
26563
26865
|
function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
26564
|
-
const sourceRulesDir =
|
|
26565
|
-
if (!
|
|
26866
|
+
const sourceRulesDir = path34.join(sourceRoot, config.source.rules);
|
|
26867
|
+
if (!fs34.existsSync(sourceRulesDir)) {
|
|
26566
26868
|
return [skippedMissingSource3("rules", sourceRulesDir)];
|
|
26567
26869
|
}
|
|
26568
26870
|
const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
|
|
26569
26871
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
26570
26872
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
26571
|
-
const destination =
|
|
26873
|
+
const destination = path34.join(rulesDir, name);
|
|
26572
26874
|
if (options.dryRun) {
|
|
26573
26875
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
26574
26876
|
return {
|
|
@@ -26592,17 +26894,17 @@ function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26592
26894
|
});
|
|
26593
26895
|
}
|
|
26594
26896
|
function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26595
|
-
const sourceCommandsRoot =
|
|
26596
|
-
if (!
|
|
26897
|
+
const sourceCommandsRoot = path34.join(sourceRoot, config.source.commands);
|
|
26898
|
+
if (!fs34.existsSync(sourceCommandsRoot)) {
|
|
26597
26899
|
return [skippedMissingSource3("commands", sourceCommandsRoot)];
|
|
26598
26900
|
}
|
|
26599
|
-
const sourceCommands = ts(
|
|
26901
|
+
const sourceCommands = ts(path34.join(sourceCommandsRoot, "*.md")).sort();
|
|
26600
26902
|
const skillsRoot = resolveTargetPath(paths.skills);
|
|
26601
26903
|
return sourceCommands.map((commandFile) => {
|
|
26602
|
-
const baseName =
|
|
26603
|
-
const destination =
|
|
26604
|
-
const commandContent =
|
|
26605
|
-
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)}`;
|
|
26606
26908
|
const marker = formatProvenanceMarker(
|
|
26607
26909
|
"markdown",
|
|
26608
26910
|
relativeSource,
|
|
@@ -26641,8 +26943,8 @@ ${commandContent.trim()}
|
|
|
26641
26943
|
});
|
|
26642
26944
|
}
|
|
26643
26945
|
function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
|
|
26644
|
-
const source =
|
|
26645
|
-
if (!
|
|
26946
|
+
const source = path34.resolve(sourceRoot, config.source.skills);
|
|
26947
|
+
if (!fs34.existsSync(source)) {
|
|
26646
26948
|
return skippedMissingSource3(component, source);
|
|
26647
26949
|
}
|
|
26648
26950
|
if (options.dryRun) {
|
|
@@ -26656,18 +26958,18 @@ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, c
|
|
|
26656
26958
|
return { component, status: "skipped-current", path: destination };
|
|
26657
26959
|
}
|
|
26658
26960
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26659
|
-
|
|
26961
|
+
fs34.unlinkSync(destination);
|
|
26660
26962
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
26661
26963
|
return { component, status: "conflict", path: destination };
|
|
26662
26964
|
} else if (artifactClass === "managed-symlink") {
|
|
26663
|
-
|
|
26965
|
+
fs34.unlinkSync(destination);
|
|
26664
26966
|
}
|
|
26665
|
-
ensureDir(
|
|
26967
|
+
ensureDir(path34.dirname(destination));
|
|
26666
26968
|
createRelativeSymlink(source, destination, "dir");
|
|
26667
26969
|
logger.verbose(`Skills: created shared skills symlink ${destination}`);
|
|
26668
26970
|
return { component, status: "success", path: destination };
|
|
26669
26971
|
}
|
|
26670
|
-
if (
|
|
26972
|
+
if (fs34.existsSync(destination)) {
|
|
26671
26973
|
return { component, status: "skipped-current", path: destination };
|
|
26672
26974
|
}
|
|
26673
26975
|
ensureDir(destination);
|
|
@@ -26678,7 +26980,7 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26678
26980
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
26679
26981
|
const sourceLabel = hooksSourceLabel(config);
|
|
26680
26982
|
const destination = resolveTargetPath(paths.hooks_file);
|
|
26681
|
-
const sourceHooksJson =
|
|
26983
|
+
const sourceHooksJson = fs34.existsSync(source) ? JSON.parse(fs34.readFileSync(source, "utf8")) : { hooks: {} };
|
|
26682
26984
|
const compiled = compileHooks(
|
|
26683
26985
|
sourceHooksJson,
|
|
26684
26986
|
"cursor",
|
|
@@ -26692,18 +26994,18 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26692
26994
|
}
|
|
26693
26995
|
const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
|
|
26694
26996
|
`;
|
|
26695
|
-
ensureDir(
|
|
26696
|
-
|
|
26997
|
+
ensureDir(path34.dirname(destination));
|
|
26998
|
+
fs34.writeFileSync(destination, hooksFileContent);
|
|
26697
26999
|
return { component: "hooks", status: "success", path: destination };
|
|
26698
27000
|
}
|
|
26699
27001
|
function syncMcp3(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
26700
27002
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
26701
27003
|
const sourceLabel = mcpSourceLabel(config);
|
|
26702
27004
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
26703
|
-
if (!
|
|
27005
|
+
if (!fs34.existsSync(source)) {
|
|
26704
27006
|
return skippedMissingSource3("mcp", source);
|
|
26705
27007
|
}
|
|
26706
|
-
const sourceMcpJson = JSON.parse(
|
|
27008
|
+
const sourceMcpJson = JSON.parse(fs34.readFileSync(source, "utf8"));
|
|
26707
27009
|
const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
|
|
26708
27010
|
if (options.dryRun) {
|
|
26709
27011
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -26754,13 +27056,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
|
|
|
26754
27056
|
);
|
|
26755
27057
|
}
|
|
26756
27058
|
function syncProviderPin(config, sourceRoot, lossReport) {
|
|
26757
|
-
const agentsDir =
|
|
26758
|
-
if (!
|
|
26759
|
-
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()) {
|
|
26760
27062
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
26761
27063
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
26762
27064
|
if (hasCustomProvider) {
|
|
26763
|
-
const relativeSource = `agents/${
|
|
27065
|
+
const relativeSource = `agents/${path34.basename(agentFile)}`;
|
|
26764
27066
|
addLoss(lossReport, "cursor", "agents", {
|
|
26765
27067
|
source: relativeSource,
|
|
26766
27068
|
fields: [
|
|
@@ -26772,7 +27074,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
|
|
|
26772
27074
|
"provider",
|
|
26773
27075
|
"provider-not-representable"
|
|
26774
27076
|
),
|
|
26775
|
-
detail: `${
|
|
27077
|
+
detail: `${path34.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
26776
27078
|
}
|
|
26777
27079
|
]
|
|
26778
27080
|
});
|
|
@@ -26787,8 +27089,8 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
|
|
|
26787
27089
|
if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
26788
27090
|
return { component, status: "conflict", path: destination };
|
|
26789
27091
|
}
|
|
26790
|
-
ensureDir(
|
|
26791
|
-
|
|
27092
|
+
ensureDir(path34.dirname(destination));
|
|
27093
|
+
fs34.writeFileSync(destination, content);
|
|
26792
27094
|
return { component, status: "success", path: destination };
|
|
26793
27095
|
}
|
|
26794
27096
|
function handleConflict3(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -26807,16 +27109,16 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
|
|
|
26807
27109
|
backupFile(destination, manifest);
|
|
26808
27110
|
writeManifest(scopePath, manifest);
|
|
26809
27111
|
} else {
|
|
26810
|
-
|
|
27112
|
+
fs34.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
26811
27113
|
}
|
|
26812
27114
|
return true;
|
|
26813
27115
|
}
|
|
26814
|
-
|
|
27116
|
+
fs34.rmSync(destination, { recursive: true, force: true });
|
|
26815
27117
|
return true;
|
|
26816
27118
|
}
|
|
26817
27119
|
function isCompiledCurrent3(destination, expectedContent, expectedHash) {
|
|
26818
27120
|
try {
|
|
26819
|
-
const current =
|
|
27121
|
+
const current = fs34.readFileSync(destination, "utf8");
|
|
26820
27122
|
const marker = extractProvenanceMarker(current);
|
|
26821
27123
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "cursor" && current === expectedContent : current === expectedContent;
|
|
26822
27124
|
} catch {
|
|
@@ -26835,7 +27137,7 @@ function shouldSkipComponent3(options, component) {
|
|
|
26835
27137
|
}
|
|
26836
27138
|
function isSymlinkTo3(linkPath, source) {
|
|
26837
27139
|
try {
|
|
26838
|
-
return
|
|
27140
|
+
return fs34.realpathSync(linkPath) === fs34.realpathSync(source);
|
|
26839
27141
|
} catch {
|
|
26840
27142
|
return false;
|
|
26841
27143
|
}
|
|
@@ -26846,8 +27148,8 @@ function hashString3(value) {
|
|
|
26846
27148
|
|
|
26847
27149
|
// src/adapters/cline.ts
|
|
26848
27150
|
import crypto8 from "crypto";
|
|
26849
|
-
import
|
|
26850
|
-
import
|
|
27151
|
+
import fs35 from "fs";
|
|
27152
|
+
import path35 from "path";
|
|
26851
27153
|
function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26852
27154
|
const scope = options.scope ?? "global";
|
|
26853
27155
|
const profile = resolveTargetPaths({
|
|
@@ -26960,7 +27262,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
26960
27262
|
function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
|
|
26961
27263
|
if (scope === "global" || paths.instructions === null) {
|
|
26962
27264
|
addLoss(lossReport, "cline", "instructions", {
|
|
26963
|
-
source:
|
|
27265
|
+
source: path35.basename(config.source.instructions),
|
|
26964
27266
|
fields: [
|
|
26965
27267
|
{
|
|
26966
27268
|
field: "instructions",
|
|
@@ -26980,12 +27282,12 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
|
|
|
26980
27282
|
path: "cline/global/instructions: no committable global path"
|
|
26981
27283
|
};
|
|
26982
27284
|
}
|
|
26983
|
-
const source =
|
|
27285
|
+
const source = path35.join(sourceRoot, config.source.instructions);
|
|
26984
27286
|
const destination = resolveTargetPath(paths.instructions);
|
|
26985
|
-
const baseContent =
|
|
27287
|
+
const baseContent = fs35.existsSync(source) ? fs35.readFileSync(source, "utf8").trim() : "";
|
|
26986
27288
|
const marker = formatProvenanceMarker(
|
|
26987
27289
|
"markdown",
|
|
26988
|
-
|
|
27290
|
+
path35.basename(config.source.instructions),
|
|
26989
27291
|
hashString4(baseContent),
|
|
26990
27292
|
"cline"
|
|
26991
27293
|
);
|
|
@@ -27010,11 +27312,11 @@ ${baseContent}
|
|
|
27010
27312
|
);
|
|
27011
27313
|
}
|
|
27012
27314
|
function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
|
|
27013
|
-
const sourceAgentsRoot =
|
|
27014
|
-
if (!
|
|
27315
|
+
const sourceAgentsRoot = path35.join(sourceRoot, config.source.agents);
|
|
27316
|
+
if (!fs35.existsSync(sourceAgentsRoot)) {
|
|
27015
27317
|
return [skippedMissingSource4("agents", sourceAgentsRoot)];
|
|
27016
27318
|
}
|
|
27017
|
-
const sourceAgents = ts(
|
|
27319
|
+
const sourceAgents = ts(path35.join(sourceAgentsRoot, "*.md")).sort();
|
|
27018
27320
|
return sourceAgents.map((agentFile) => {
|
|
27019
27321
|
compileAgent(agentFile, "cline", mappings, extensions, lossReport);
|
|
27020
27322
|
if (options.dryRun) {
|
|
@@ -27030,14 +27332,14 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
27030
27332
|
});
|
|
27031
27333
|
}
|
|
27032
27334
|
function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
27033
|
-
const sourceRulesDir =
|
|
27034
|
-
if (!
|
|
27335
|
+
const sourceRulesDir = path35.join(sourceRoot, config.source.rules);
|
|
27336
|
+
if (!fs35.existsSync(sourceRulesDir)) {
|
|
27035
27337
|
return [skippedMissingSource4("rules", sourceRulesDir)];
|
|
27036
27338
|
}
|
|
27037
27339
|
const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
|
|
27038
27340
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
27039
27341
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
27040
|
-
const destination =
|
|
27342
|
+
const destination = path35.join(rulesDir, name);
|
|
27041
27343
|
if (options.dryRun) {
|
|
27042
27344
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
27043
27345
|
return {
|
|
@@ -27061,17 +27363,17 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
27061
27363
|
});
|
|
27062
27364
|
}
|
|
27063
27365
|
function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27064
|
-
const sourceCommandsRoot =
|
|
27065
|
-
if (!
|
|
27366
|
+
const sourceCommandsRoot = path35.join(sourceRoot, config.source.commands);
|
|
27367
|
+
if (!fs35.existsSync(sourceCommandsRoot)) {
|
|
27066
27368
|
return [skippedMissingSource4("commands", sourceCommandsRoot)];
|
|
27067
27369
|
}
|
|
27068
|
-
const sourceCommands = ts(
|
|
27370
|
+
const sourceCommands = ts(path35.join(sourceCommandsRoot, "*.md")).sort();
|
|
27069
27371
|
const workflowsRoot = resolveTargetPath(paths.workflows);
|
|
27070
27372
|
return sourceCommands.map((commandFile) => {
|
|
27071
|
-
const baseName =
|
|
27072
|
-
const destination =
|
|
27073
|
-
const commandContent =
|
|
27074
|
-
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)}`;
|
|
27075
27377
|
const marker = formatProvenanceMarker(
|
|
27076
27378
|
"markdown",
|
|
27077
27379
|
relativeSource,
|
|
@@ -27106,9 +27408,9 @@ ${commandContent.trim()}
|
|
|
27106
27408
|
});
|
|
27107
27409
|
}
|
|
27108
27410
|
function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27109
|
-
const source =
|
|
27411
|
+
const source = path35.resolve(sourceRoot, config.source.skills);
|
|
27110
27412
|
const destination = resolveTargetPath(paths.skills);
|
|
27111
|
-
if (!
|
|
27413
|
+
if (!fs35.existsSync(source)) {
|
|
27112
27414
|
return skippedMissingSource4("skills", source);
|
|
27113
27415
|
}
|
|
27114
27416
|
if (options.dryRun) {
|
|
@@ -27128,9 +27430,9 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
27128
27430
|
return { component: "skills", status: "conflict", path: destination };
|
|
27129
27431
|
}
|
|
27130
27432
|
} else if (artifactClass === "managed-symlink") {
|
|
27131
|
-
|
|
27433
|
+
fs35.unlinkSync(destination);
|
|
27132
27434
|
}
|
|
27133
|
-
ensureDir(
|
|
27435
|
+
ensureDir(path35.dirname(destination));
|
|
27134
27436
|
createRelativeSymlink(source, destination, "dir");
|
|
27135
27437
|
logger.verbose(`Skills: created Cline skills symlink ${destination}`);
|
|
27136
27438
|
return { component: "skills", status: "success", path: destination };
|
|
@@ -27138,7 +27440,7 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
27138
27440
|
function syncHooks4(config, sourceRoot, mappings, options, lossReport, logger) {
|
|
27139
27441
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
27140
27442
|
const sourceLabel = hooksSourceLabel(config);
|
|
27141
|
-
const sourceHooksJson =
|
|
27443
|
+
const sourceHooksJson = fs35.existsSync(source) ? JSON.parse(fs35.readFileSync(source, "utf8")) : { hooks: {} };
|
|
27142
27444
|
compileHooks(sourceHooksJson, "cline", mappings, lossReport, sourceLabel);
|
|
27143
27445
|
if (options.dryRun) {
|
|
27144
27446
|
logger.info(`[dry-run] hooks: record hook-as-plugin loss for ${source}`);
|
|
@@ -27153,10 +27455,10 @@ function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manife
|
|
|
27153
27455
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27154
27456
|
const sourceLabel = mcpSourceLabel(config);
|
|
27155
27457
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
27156
|
-
if (!
|
|
27458
|
+
if (!fs35.existsSync(source)) {
|
|
27157
27459
|
return skippedMissingSource4("mcp", source);
|
|
27158
27460
|
}
|
|
27159
|
-
const sourceMcpJson = JSON.parse(
|
|
27461
|
+
const sourceMcpJson = JSON.parse(fs35.readFileSync(source, "utf8"));
|
|
27160
27462
|
const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
|
|
27161
27463
|
if (options.dryRun) {
|
|
27162
27464
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -27199,11 +27501,11 @@ function syncSettings(lossReport) {
|
|
|
27199
27501
|
};
|
|
27200
27502
|
}
|
|
27201
27503
|
function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
27202
|
-
const agentsDir =
|
|
27203
|
-
if (!
|
|
27204
|
-
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()) {
|
|
27205
27507
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
27206
|
-
const relativeSource = `agents/${
|
|
27508
|
+
const relativeSource = `agents/${path35.basename(agentFile)}`;
|
|
27207
27509
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
27208
27510
|
if (hasCustomProvider) {
|
|
27209
27511
|
addLoss(lossReport, "cline", "agents", {
|
|
@@ -27217,7 +27519,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
27217
27519
|
"provider",
|
|
27218
27520
|
"provider-not-representable"
|
|
27219
27521
|
),
|
|
27220
|
-
detail: `${
|
|
27522
|
+
detail: `${path35.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
|
|
27221
27523
|
}
|
|
27222
27524
|
]
|
|
27223
27525
|
});
|
|
@@ -27235,7 +27537,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
27235
27537
|
"model",
|
|
27236
27538
|
"model-not-representable"
|
|
27237
27539
|
),
|
|
27238
|
-
detail: `${
|
|
27540
|
+
detail: `${path35.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
|
|
27239
27541
|
}
|
|
27240
27542
|
]
|
|
27241
27543
|
});
|
|
@@ -27250,8 +27552,8 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
|
|
|
27250
27552
|
if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
|
|
27251
27553
|
return { component, status: "conflict", path: destination };
|
|
27252
27554
|
}
|
|
27253
|
-
ensureDir(
|
|
27254
|
-
|
|
27555
|
+
ensureDir(path35.dirname(destination));
|
|
27556
|
+
fs35.writeFileSync(destination, content);
|
|
27255
27557
|
return { component, status: "success", path: destination };
|
|
27256
27558
|
}
|
|
27257
27559
|
function handleConflict4(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -27270,16 +27572,16 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
|
|
|
27270
27572
|
backupFile(destination, manifest);
|
|
27271
27573
|
writeManifest(scopePath, manifest);
|
|
27272
27574
|
} else {
|
|
27273
|
-
|
|
27575
|
+
fs35.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
27274
27576
|
}
|
|
27275
27577
|
return true;
|
|
27276
27578
|
}
|
|
27277
|
-
|
|
27579
|
+
fs35.rmSync(destination, { recursive: true, force: true });
|
|
27278
27580
|
return true;
|
|
27279
27581
|
}
|
|
27280
27582
|
function isCompiledCurrent4(destination, expectedContent, expectedHash) {
|
|
27281
27583
|
try {
|
|
27282
|
-
const current =
|
|
27584
|
+
const current = fs35.readFileSync(destination, "utf8");
|
|
27283
27585
|
const marker = extractProvenanceMarker(current);
|
|
27284
27586
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "cline" && current === expectedContent : current === expectedContent;
|
|
27285
27587
|
} catch {
|
|
@@ -27298,7 +27600,7 @@ function shouldSkipComponent4(options, component) {
|
|
|
27298
27600
|
}
|
|
27299
27601
|
function isSymlinkTo4(linkPath, source) {
|
|
27300
27602
|
try {
|
|
27301
|
-
return
|
|
27603
|
+
return fs35.realpathSync(linkPath) === fs35.realpathSync(source);
|
|
27302
27604
|
} catch {
|
|
27303
27605
|
return false;
|
|
27304
27606
|
}
|
|
@@ -27309,9 +27611,9 @@ function hashString4(value) {
|
|
|
27309
27611
|
|
|
27310
27612
|
// src/adapters/opencode.ts
|
|
27311
27613
|
import crypto9 from "crypto";
|
|
27312
|
-
import
|
|
27614
|
+
import fs36 from "fs";
|
|
27313
27615
|
import os6 from "os";
|
|
27314
|
-
import
|
|
27616
|
+
import path36 from "path";
|
|
27315
27617
|
var import_yaml10 = __toESM(require_dist(), 1);
|
|
27316
27618
|
function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27317
27619
|
const scope = options.scope ?? "global";
|
|
@@ -27329,7 +27631,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
27329
27631
|
config_doc: profile.config_doc
|
|
27330
27632
|
};
|
|
27331
27633
|
const rules = compileRules(
|
|
27332
|
-
|
|
27634
|
+
path36.join(sourceRoot, config.source.rules),
|
|
27333
27635
|
"opencode",
|
|
27334
27636
|
mappings,
|
|
27335
27637
|
lossReport
|
|
@@ -27431,16 +27733,16 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
27431
27733
|
return { target: "opencode", outcomes };
|
|
27432
27734
|
}
|
|
27433
27735
|
function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
27434
|
-
const source =
|
|
27736
|
+
const source = path36.join(sourceRoot, config.source.instructions);
|
|
27435
27737
|
const destination = resolveTargetPath(paths.instructions);
|
|
27436
|
-
const baseContent =
|
|
27738
|
+
const baseContent = fs36.existsSync(source) ? fs36.readFileSync(source, "utf8").trim() : "";
|
|
27437
27739
|
const composed = agentsAppendix ? `${baseContent}
|
|
27438
27740
|
|
|
27439
27741
|
--- tangyr managed rules ---
|
|
27440
27742
|
${agentsAppendix}`.trim() : baseContent;
|
|
27441
27743
|
const marker = formatProvenanceMarker(
|
|
27442
27744
|
"markdown",
|
|
27443
|
-
|
|
27745
|
+
path36.basename(config.source.instructions),
|
|
27444
27746
|
hashString5(composed),
|
|
27445
27747
|
"opencode"
|
|
27446
27748
|
);
|
|
@@ -27467,16 +27769,16 @@ ${composed}
|
|
|
27467
27769
|
);
|
|
27468
27770
|
}
|
|
27469
27771
|
function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27470
|
-
const sourceAgentsRoot =
|
|
27471
|
-
if (!
|
|
27772
|
+
const sourceAgentsRoot = path36.join(sourceRoot, config.source.agents);
|
|
27773
|
+
if (!fs36.existsSync(sourceAgentsRoot)) {
|
|
27472
27774
|
return [skippedMissingSource5("agents", sourceAgentsRoot)];
|
|
27473
27775
|
}
|
|
27474
|
-
const sourceAgents = ts(
|
|
27776
|
+
const sourceAgents = ts(path36.join(sourceAgentsRoot, "*.md")).sort();
|
|
27475
27777
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
27476
27778
|
return sourceAgents.map((agentFile) => {
|
|
27477
|
-
const destination =
|
|
27779
|
+
const destination = path36.join(
|
|
27478
27780
|
agentsRoot,
|
|
27479
|
-
`${
|
|
27781
|
+
`${path36.basename(agentFile, ".md")}.md`
|
|
27480
27782
|
);
|
|
27481
27783
|
let compiled;
|
|
27482
27784
|
try {
|
|
@@ -27540,11 +27842,11 @@ function applyProviderModelBinding(compiled, mappings) {
|
|
|
27540
27842
|
return `${before}${(0, import_yaml10.stringify)(fields).trim()}${after}`;
|
|
27541
27843
|
}
|
|
27542
27844
|
function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27543
|
-
const sourceCommandsRoot =
|
|
27544
|
-
if (!
|
|
27845
|
+
const sourceCommandsRoot = path36.join(sourceRoot, config.source.commands);
|
|
27846
|
+
if (!fs36.existsSync(sourceCommandsRoot)) {
|
|
27545
27847
|
return [skippedMissingSource5("commands", sourceCommandsRoot)];
|
|
27546
27848
|
}
|
|
27547
|
-
const sourceCommands = ts(
|
|
27849
|
+
const sourceCommands = ts(path36.join(sourceCommandsRoot, "*.md")).sort();
|
|
27548
27850
|
const commandsRoot = resolveTargetPath(paths.commands);
|
|
27549
27851
|
return sourceCommands.map((commandFile) => {
|
|
27550
27852
|
const { data, body } = parseCommandFile(commandFile);
|
|
@@ -27558,7 +27860,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
|
|
|
27558
27860
|
if (typeof data.model === "string") {
|
|
27559
27861
|
frontmatter.model = data.model;
|
|
27560
27862
|
}
|
|
27561
|
-
const relativeSource = `commands/${
|
|
27863
|
+
const relativeSource = `commands/${path36.basename(commandFile)}`;
|
|
27562
27864
|
const marker = formatProvenanceMarker(
|
|
27563
27865
|
"markdown",
|
|
27564
27866
|
relativeSource,
|
|
@@ -27574,9 +27876,9 @@ ${body.trimEnd()}
|
|
|
27574
27876
|
` : `${marker}
|
|
27575
27877
|
${body.trimEnd()}
|
|
27576
27878
|
`;
|
|
27577
|
-
const destination =
|
|
27879
|
+
const destination = path36.join(
|
|
27578
27880
|
commandsRoot,
|
|
27579
|
-
`${
|
|
27881
|
+
`${path36.basename(commandFile, ".md")}.md`
|
|
27580
27882
|
);
|
|
27581
27883
|
if (options.dryRun) {
|
|
27582
27884
|
logger.info(
|
|
@@ -27603,8 +27905,8 @@ ${body.trimEnd()}
|
|
|
27603
27905
|
});
|
|
27604
27906
|
}
|
|
27605
27907
|
function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, component = "skills", destination = "") {
|
|
27606
|
-
const source =
|
|
27607
|
-
if (!
|
|
27908
|
+
const source = path36.resolve(sourceRoot, config.source.skills);
|
|
27909
|
+
if (!fs36.existsSync(source)) {
|
|
27608
27910
|
return skippedMissingSource5(component, source);
|
|
27609
27911
|
}
|
|
27610
27912
|
if (options.dryRun) {
|
|
@@ -27616,13 +27918,13 @@ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scop
|
|
|
27616
27918
|
return { component, status: "skipped-current", path: destination };
|
|
27617
27919
|
}
|
|
27618
27920
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
27619
|
-
|
|
27921
|
+
fs36.unlinkSync(destination);
|
|
27620
27922
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
27621
27923
|
return { component, status: "conflict", path: destination };
|
|
27622
27924
|
} else if (artifactClass === "managed-symlink") {
|
|
27623
|
-
|
|
27925
|
+
fs36.unlinkSync(destination);
|
|
27624
27926
|
}
|
|
27625
|
-
ensureDir(
|
|
27927
|
+
ensureDir(path36.dirname(destination));
|
|
27626
27928
|
createRelativeSymlink(source, destination, "dir");
|
|
27627
27929
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
27628
27930
|
return { component, status: "success", path: destination };
|
|
@@ -27631,13 +27933,13 @@ function syncMcp5(config, sourceRoot, paths, mappings, options, lossReport, logg
|
|
|
27631
27933
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27632
27934
|
const sourceLabel = mcpSourceLabel(config);
|
|
27633
27935
|
const destination = resolveTargetPath(paths.config_doc);
|
|
27634
|
-
if (!
|
|
27936
|
+
if (!fs36.existsSync(source)) {
|
|
27635
27937
|
if (!options.dryRun) {
|
|
27636
27938
|
syncConfigDoc(paths, {}, lossReport, {}, mappings);
|
|
27637
27939
|
}
|
|
27638
27940
|
return skippedMissingSource5("mcp", source);
|
|
27639
27941
|
}
|
|
27640
|
-
const sourceMcpJson = JSON.parse(
|
|
27942
|
+
const sourceMcpJson = JSON.parse(fs36.readFileSync(source, "utf8"));
|
|
27641
27943
|
const mcpJson = compileMcp(
|
|
27642
27944
|
sourceMcpJson,
|
|
27643
27945
|
"opencode",
|
|
@@ -27668,7 +27970,7 @@ function syncPermissions2(config, _sourceRoot, paths, options, lossReport, logge
|
|
|
27668
27970
|
function syncHooks5(config, sourceRoot, mappings, options, lossReport) {
|
|
27669
27971
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
27670
27972
|
const sourceLabel = hooksSourceLabel(config);
|
|
27671
|
-
const sourceHooksJson =
|
|
27973
|
+
const sourceHooksJson = fs36.existsSync(source) ? JSON.parse(fs36.readFileSync(source, "utf8")) : { hooks: {} };
|
|
27672
27974
|
compileHooks(sourceHooksJson, "opencode", mappings, lossReport, sourceLabel);
|
|
27673
27975
|
const message = "hooks: Skip \u2014 OpenCode exposes hooks only as plugin code (hook-as-plugin loss recorded)";
|
|
27674
27976
|
return { component: "hooks", status: "skipped", path: message };
|
|
@@ -27702,9 +28004,9 @@ function syncProviderBlock(mappings) {
|
|
|
27702
28004
|
function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
|
|
27703
28005
|
const destination = resolveTargetPath(paths.config_doc);
|
|
27704
28006
|
let existing = {};
|
|
27705
|
-
if (
|
|
28007
|
+
if (fs36.existsSync(destination)) {
|
|
27706
28008
|
try {
|
|
27707
|
-
existing = JSON.parse(
|
|
28009
|
+
existing = JSON.parse(fs36.readFileSync(destination, "utf8"));
|
|
27708
28010
|
} catch {
|
|
27709
28011
|
existing = {};
|
|
27710
28012
|
}
|
|
@@ -27729,8 +28031,8 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
|
|
|
27729
28031
|
};
|
|
27730
28032
|
}
|
|
27731
28033
|
}
|
|
27732
|
-
ensureDir(
|
|
27733
|
-
|
|
28034
|
+
ensureDir(path36.dirname(destination));
|
|
28035
|
+
fs36.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
|
|
27734
28036
|
`);
|
|
27735
28037
|
}
|
|
27736
28038
|
function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
|
|
@@ -27741,8 +28043,8 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
|
|
|
27741
28043
|
if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
27742
28044
|
return { component, status: "conflict", path: destination };
|
|
27743
28045
|
}
|
|
27744
|
-
ensureDir(
|
|
27745
|
-
|
|
28046
|
+
ensureDir(path36.dirname(destination));
|
|
28047
|
+
fs36.writeFileSync(destination, content);
|
|
27746
28048
|
return { component, status: "success", path: destination };
|
|
27747
28049
|
}
|
|
27748
28050
|
function handleConflict5(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -27761,16 +28063,16 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
|
|
|
27761
28063
|
backupFile(destination, manifest);
|
|
27762
28064
|
writeManifest(scopePath, manifest);
|
|
27763
28065
|
} else {
|
|
27764
|
-
|
|
28066
|
+
fs36.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
27765
28067
|
}
|
|
27766
28068
|
return true;
|
|
27767
28069
|
}
|
|
27768
|
-
|
|
28070
|
+
fs36.rmSync(destination, { recursive: true, force: true });
|
|
27769
28071
|
return true;
|
|
27770
28072
|
}
|
|
27771
28073
|
function isCompiledCurrent5(destination, expectedContent, expectedHash) {
|
|
27772
28074
|
try {
|
|
27773
|
-
const current =
|
|
28075
|
+
const current = fs36.readFileSync(destination, "utf8");
|
|
27774
28076
|
const marker = extractProvenanceMarker(current);
|
|
27775
28077
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "opencode" && current === expectedContent : current === expectedContent;
|
|
27776
28078
|
} catch {
|
|
@@ -27789,7 +28091,7 @@ function shouldSkipComponent5(options, component) {
|
|
|
27789
28091
|
}
|
|
27790
28092
|
function isSymlinkTo5(linkPath, source) {
|
|
27791
28093
|
try {
|
|
27792
|
-
return
|
|
28094
|
+
return fs36.realpathSync(linkPath) === fs36.realpathSync(source);
|
|
27793
28095
|
} catch {
|
|
27794
28096
|
return false;
|
|
27795
28097
|
}
|
|
@@ -27798,7 +28100,7 @@ function hashString5(value) {
|
|
|
27798
28100
|
return `sha256:${crypto9.createHash("sha256").update(value).digest("hex")}`;
|
|
27799
28101
|
}
|
|
27800
28102
|
function parseCommandFile(commandFile) {
|
|
27801
|
-
const content =
|
|
28103
|
+
const content = fs36.readFileSync(commandFile, "utf8");
|
|
27802
28104
|
if (!content.startsWith("---\n")) {
|
|
27803
28105
|
return { data: {}, body: content };
|
|
27804
28106
|
}
|
|
@@ -27818,10 +28120,10 @@ function parseCommandFile(commandFile) {
|
|
|
27818
28120
|
// src/commands/install.ts
|
|
27819
28121
|
function isBackupableFile(targetPath) {
|
|
27820
28122
|
try {
|
|
27821
|
-
const lstat =
|
|
28123
|
+
const lstat = fs37.lstatSync(targetPath);
|
|
27822
28124
|
if (lstat.isDirectory()) return false;
|
|
27823
28125
|
if (lstat.isSymbolicLink()) {
|
|
27824
|
-
const stat =
|
|
28126
|
+
const stat = fs37.statSync(targetPath);
|
|
27825
28127
|
return stat.isFile();
|
|
27826
28128
|
}
|
|
27827
28129
|
return lstat.isFile();
|
|
@@ -27831,10 +28133,10 @@ function isBackupableFile(targetPath) {
|
|
|
27831
28133
|
}
|
|
27832
28134
|
function backupConflictingTarget(targetPath, scopePath) {
|
|
27833
28135
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/gu, "").replace("T", "T").replace(/\.\d+Z$/u, "Z");
|
|
27834
|
-
const relativeToRoot =
|
|
27835
|
-
const backupPath =
|
|
27836
|
-
|
|
27837
|
-
|
|
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);
|
|
27838
28140
|
return backupPath;
|
|
27839
28141
|
}
|
|
27840
28142
|
async function runInstallCommand(options, logger) {
|
|
@@ -27863,7 +28165,7 @@ async function runInstallCommand(options, logger) {
|
|
|
27863
28165
|
);
|
|
27864
28166
|
}
|
|
27865
28167
|
const kitName = resolvedKitName ?? config.kit;
|
|
27866
|
-
const kitPath = kitPathOverride ?? (options.kitPath ?
|
|
28168
|
+
const kitPath = kitPathOverride ?? (options.kitPath ? path37.resolve(options.kitPath) : config.kitPath);
|
|
27867
28169
|
if (!kitName && !kitPath) {
|
|
27868
28170
|
logger.error(
|
|
27869
28171
|
"No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
|
|
@@ -28004,7 +28306,7 @@ ACCEPTED CONFLICTS (backup-and-replace applied to ${conflictingFindings.length}
|
|
|
28004
28306
|
logger.info(` source: ${finding.tool}`);
|
|
28005
28307
|
logger.info(` action: backup-and-replace`);
|
|
28006
28308
|
logger.info(` backup: ${backupLocation}`);
|
|
28007
|
-
} else if (
|
|
28309
|
+
} else if (fs37.existsSync(finding.path)) {
|
|
28008
28310
|
logger.info(` - ${finding.path}`);
|
|
28009
28311
|
logger.info(` source: ${finding.tool}`);
|
|
28010
28312
|
logger.info(
|
|
@@ -28115,7 +28417,7 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
|
|
|
28115
28417
|
writeManifest(scopePath, manifest);
|
|
28116
28418
|
logger.info(`
|
|
28117
28419
|
Installation complete: ${installedCount} files installed.`);
|
|
28118
|
-
logger.info(`Manifest written to ${
|
|
28420
|
+
logger.info(`Manifest written to ${path37.join(scopePath, "manifest.json")}`);
|
|
28119
28421
|
logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
|
|
28120
28422
|
logger.info(`Scope: ${scope}`);
|
|
28121
28423
|
logger.info(`Tools: ${tools.join(", ")}`);
|
|
@@ -28257,13 +28559,13 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
28257
28559
|
logger.verbose(` skipped (operator choice): ${placement.destination}`);
|
|
28258
28560
|
continue;
|
|
28259
28561
|
}
|
|
28260
|
-
const destDir =
|
|
28261
|
-
|
|
28562
|
+
const destDir = path37.dirname(placement.destination);
|
|
28563
|
+
fs37.mkdirSync(destDir, { recursive: true });
|
|
28262
28564
|
if (placement.type === "symlink") {
|
|
28263
|
-
if (
|
|
28565
|
+
if (fs37.existsSync(placement.destination) || isSymlink2(placement.destination)) {
|
|
28264
28566
|
removeManagedPath(placement.destination);
|
|
28265
28567
|
}
|
|
28266
|
-
|
|
28568
|
+
fs37.symlinkSync(
|
|
28267
28569
|
placement.source,
|
|
28268
28570
|
placement.destination,
|
|
28269
28571
|
placement.isDir ? "dir" : "file"
|
|
@@ -28272,12 +28574,12 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
28272
28574
|
` symlink: ${placement.source} \u2192 ${placement.destination}`
|
|
28273
28575
|
);
|
|
28274
28576
|
} else {
|
|
28275
|
-
|
|
28577
|
+
fs37.copyFileSync(placement.source, placement.destination);
|
|
28276
28578
|
logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
|
|
28277
28579
|
}
|
|
28278
28580
|
addArtifactToManifest(manifest, {
|
|
28279
28581
|
relativePath: placement.manifestKey,
|
|
28280
|
-
hash:
|
|
28582
|
+
hash: fs37.statSync(placement.source).isDirectory() ? `dir:${placement.source}` : computeSourceHash(placement.source),
|
|
28281
28583
|
origin: "tangyr-managed"
|
|
28282
28584
|
});
|
|
28283
28585
|
count++;
|
|
@@ -28524,11 +28826,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28524
28826
|
if (outcome.path === mcpFile2) {
|
|
28525
28827
|
return "cline/mcp.json";
|
|
28526
28828
|
}
|
|
28527
|
-
if (outcome.path.startsWith(`${workflowsRoot}${
|
|
28528
|
-
return `cline/workflows/${
|
|
28829
|
+
if (outcome.path.startsWith(`${workflowsRoot}${path37.sep}`)) {
|
|
28830
|
+
return `cline/workflows/${path37.basename(outcome.path)}`;
|
|
28529
28831
|
}
|
|
28530
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
28531
|
-
return `cline/rules/${
|
|
28832
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path37.sep}`)) {
|
|
28833
|
+
return `cline/rules/${path37.basename(outcome.path)}`;
|
|
28532
28834
|
}
|
|
28533
28835
|
return null;
|
|
28534
28836
|
}
|
|
@@ -28564,14 +28866,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28564
28866
|
if (outcome.path === permissionsFile) {
|
|
28565
28867
|
return "cursor/permissions.json";
|
|
28566
28868
|
}
|
|
28567
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28568
|
-
return `cursor/agents/${
|
|
28869
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
28870
|
+
return `cursor/agents/${path37.basename(outcome.path)}`;
|
|
28569
28871
|
}
|
|
28570
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
28571
|
-
return `cursor/rules/${
|
|
28872
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path37.sep}`)) {
|
|
28873
|
+
return `cursor/rules/${path37.basename(outcome.path)}`;
|
|
28572
28874
|
}
|
|
28573
|
-
if (outcome.path.startsWith(`${skillsRoot2}${
|
|
28574
|
-
const rel =
|
|
28875
|
+
if (outcome.path.startsWith(`${skillsRoot2}${path37.sep}`)) {
|
|
28876
|
+
const rel = path37.relative(skillsRoot2, outcome.path);
|
|
28575
28877
|
return `cursor/skills/${rel}`;
|
|
28576
28878
|
}
|
|
28577
28879
|
return null;
|
|
@@ -28597,14 +28899,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28597
28899
|
if (outcome.path === skillsSharedRoot) {
|
|
28598
28900
|
return "opencode/skills_shared";
|
|
28599
28901
|
}
|
|
28600
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28601
|
-
return `opencode/agents/${
|
|
28902
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
28903
|
+
return `opencode/agents/${path37.basename(outcome.path)}`;
|
|
28602
28904
|
}
|
|
28603
|
-
if (outcome.path.startsWith(`${commandsRoot}${
|
|
28604
|
-
return `opencode/commands/${
|
|
28905
|
+
if (outcome.path.startsWith(`${commandsRoot}${path37.sep}`)) {
|
|
28906
|
+
return `opencode/commands/${path37.basename(outcome.path)}`;
|
|
28605
28907
|
}
|
|
28606
28908
|
if (outcome.path === configDocFile) {
|
|
28607
|
-
return `opencode/${
|
|
28909
|
+
return `opencode/${path37.basename(outcome.path)}`;
|
|
28608
28910
|
}
|
|
28609
28911
|
return null;
|
|
28610
28912
|
}
|
|
@@ -28618,17 +28920,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28618
28920
|
if (outcome.path === skillsRoot2) {
|
|
28619
28921
|
return "copilot/skills";
|
|
28620
28922
|
}
|
|
28621
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28622
|
-
return `copilot/agents/${
|
|
28923
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
28924
|
+
return `copilot/agents/${path37.basename(outcome.path)}`;
|
|
28623
28925
|
}
|
|
28624
|
-
if (outcome.path.startsWith(`${promptsRoot}${
|
|
28625
|
-
return `copilot/prompts/${
|
|
28926
|
+
if (outcome.path.startsWith(`${promptsRoot}${path37.sep}`)) {
|
|
28927
|
+
return `copilot/prompts/${path37.basename(outcome.path)}`;
|
|
28626
28928
|
}
|
|
28627
|
-
if (outcome.path.startsWith(`${hooksRoot}${
|
|
28628
|
-
return `copilot/hooks/${
|
|
28929
|
+
if (outcome.path.startsWith(`${hooksRoot}${path37.sep}`)) {
|
|
28930
|
+
return `copilot/hooks/${path37.basename(outcome.path)}`;
|
|
28629
28931
|
}
|
|
28630
28932
|
if (outcome.path === mcpFile2) {
|
|
28631
|
-
return `copilot/${
|
|
28933
|
+
return `copilot/${path37.basename(outcome.path)}`;
|
|
28632
28934
|
}
|
|
28633
28935
|
return null;
|
|
28634
28936
|
}
|
|
@@ -28644,17 +28946,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28644
28946
|
if (outcome.path === skillsRoot) {
|
|
28645
28947
|
return "codex/skills";
|
|
28646
28948
|
}
|
|
28647
|
-
if (outcome.path.startsWith(`${agentsRoot}${
|
|
28648
|
-
return `codex/agents/${
|
|
28949
|
+
if (outcome.path.startsWith(`${agentsRoot}${path37.sep}`)) {
|
|
28950
|
+
return `codex/agents/${path37.basename(outcome.path)}`;
|
|
28649
28951
|
}
|
|
28650
|
-
if (outcome.path.startsWith(`${rulesRoot}${
|
|
28651
|
-
return `codex/rules/${
|
|
28952
|
+
if (outcome.path.startsWith(`${rulesRoot}${path37.sep}`)) {
|
|
28953
|
+
return `codex/rules/${path37.basename(outcome.path)}`;
|
|
28652
28954
|
}
|
|
28653
28955
|
if (outcome.path === hooksFile) {
|
|
28654
|
-
return `codex/${
|
|
28956
|
+
return `codex/${path37.basename(outcome.path)}`;
|
|
28655
28957
|
}
|
|
28656
28958
|
if (outcome.path === mcpFile) {
|
|
28657
|
-
return `codex/${
|
|
28959
|
+
return `codex/${path37.basename(outcome.path)}`;
|
|
28658
28960
|
}
|
|
28659
28961
|
return null;
|
|
28660
28962
|
}
|
|
@@ -28689,8 +28991,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28689
28991
|
};
|
|
28690
28992
|
}
|
|
28691
28993
|
const placements = [];
|
|
28692
|
-
const claudeMd =
|
|
28693
|
-
if (
|
|
28994
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
28995
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28694
28996
|
placements.push({
|
|
28695
28997
|
source: claudeMd,
|
|
28696
28998
|
destination: resolvedPaths.instructions,
|
|
@@ -28706,8 +29008,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28706
29008
|
rules: resolvedPaths.rules
|
|
28707
29009
|
};
|
|
28708
29010
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
28709
|
-
const componentDir =
|
|
28710
|
-
if (
|
|
29011
|
+
const componentDir = path37.join(kitInfo.path, component);
|
|
29012
|
+
if (fs37.existsSync(componentDir) && fs37.statSync(componentDir).isDirectory()) {
|
|
28711
29013
|
placements.push({
|
|
28712
29014
|
source: componentDir,
|
|
28713
29015
|
destination: targetPath,
|
|
@@ -28721,8 +29023,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28721
29023
|
}
|
|
28722
29024
|
function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
28723
29025
|
const placements = [];
|
|
28724
|
-
const claudeMd =
|
|
28725
|
-
if (
|
|
29026
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
29027
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28726
29028
|
placements.push({
|
|
28727
29029
|
source: claudeMd,
|
|
28728
29030
|
destination: profile.instructions,
|
|
@@ -28738,8 +29040,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
|
28738
29040
|
rules: profile.rules
|
|
28739
29041
|
};
|
|
28740
29042
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
28741
|
-
const componentDir =
|
|
28742
|
-
if (
|
|
29043
|
+
const componentDir = path37.join(kitInfo.path, component);
|
|
29044
|
+
if (fs37.existsSync(componentDir) && fs37.statSync(componentDir).isDirectory()) {
|
|
28743
29045
|
placements.push({
|
|
28744
29046
|
source: componentDir,
|
|
28745
29047
|
destination: targetPath,
|
|
@@ -28753,8 +29055,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
|
28753
29055
|
}
|
|
28754
29056
|
function collectAllFiles(kitInfo) {
|
|
28755
29057
|
const files = /* @__PURE__ */ new Map();
|
|
28756
|
-
const claudeMd =
|
|
28757
|
-
if (
|
|
29058
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
29059
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28758
29060
|
files.set("CLAUDE.md", claudeMd);
|
|
28759
29061
|
}
|
|
28760
29062
|
for (const [component, reconciliation] of Object.entries(
|
|
@@ -28764,15 +29066,15 @@ function collectAllFiles(kitInfo) {
|
|
|
28764
29066
|
const missingSet = new Set(reconciliation.missing);
|
|
28765
29067
|
for (const entry of reconciliation.declared) {
|
|
28766
29068
|
if (missingSet.has(entry)) continue;
|
|
28767
|
-
const relPath = isSkills ?
|
|
28768
|
-
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));
|
|
28769
29071
|
}
|
|
28770
29072
|
}
|
|
28771
29073
|
return files;
|
|
28772
29074
|
}
|
|
28773
29075
|
function isSymlink2(p) {
|
|
28774
29076
|
try {
|
|
28775
|
-
return
|
|
29077
|
+
return fs37.lstatSync(p).isSymbolicLink();
|
|
28776
29078
|
} catch {
|
|
28777
29079
|
return false;
|
|
28778
29080
|
}
|
|
@@ -28817,14 +29119,14 @@ async function runKitUpdateCommand(options, logger) {
|
|
|
28817
29119
|
}
|
|
28818
29120
|
|
|
28819
29121
|
// src/commands/list.ts
|
|
28820
|
-
import
|
|
29122
|
+
import path38 from "path";
|
|
28821
29123
|
function runListCommand(options, logger) {
|
|
28822
29124
|
let searchPaths = [];
|
|
28823
|
-
let directKitPath = options.kitPath ?
|
|
29125
|
+
let directKitPath = options.kitPath ? path38.resolve(options.kitPath) : void 0;
|
|
28824
29126
|
try {
|
|
28825
29127
|
const { config, configDir } = resolveConfig(options.config);
|
|
28826
29128
|
searchPaths = config.kitSearchPaths ?? [
|
|
28827
|
-
|
|
29129
|
+
path38.join(configDir, "operating-kits")
|
|
28828
29130
|
];
|
|
28829
29131
|
directKitPath = directKitPath ?? config.kitPath;
|
|
28830
29132
|
} catch (err) {
|
|
@@ -28899,7 +29201,7 @@ function withDirectKit(kits, directKitPath) {
|
|
|
28899
29201
|
return kits;
|
|
28900
29202
|
}
|
|
28901
29203
|
const directKit = loadKit(directKitPath);
|
|
28902
|
-
if (kits.some((kit) =>
|
|
29204
|
+
if (kits.some((kit) => path38.resolve(kit.path) === directKit.path)) {
|
|
28903
29205
|
return kits;
|
|
28904
29206
|
}
|
|
28905
29207
|
return [...kits, directKit];
|
|
@@ -28907,12 +29209,12 @@ function withDirectKit(kits, directKitPath) {
|
|
|
28907
29209
|
|
|
28908
29210
|
// src/commands/probe.ts
|
|
28909
29211
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
28910
|
-
import
|
|
28911
|
-
import
|
|
29212
|
+
import fs38 from "fs";
|
|
29213
|
+
import path39 from "path";
|
|
28912
29214
|
function runProbeCommand(options, logger) {
|
|
28913
29215
|
const { config, configDir, sourceRoot } = resolveRuntime(options, import.meta.url);
|
|
28914
29216
|
const platformPaths = readYamlObject(
|
|
28915
|
-
|
|
29217
|
+
path39.join(
|
|
28916
29218
|
resolveConfiguredPath(config.mappings, configDir, sourceRoot, "mappings"),
|
|
28917
29219
|
"platform-paths.yaml"
|
|
28918
29220
|
)
|
|
@@ -28946,12 +29248,12 @@ function toProbeRow(target, key, rawPath) {
|
|
|
28946
29248
|
const resolved = resolveTargetPath(rawPath);
|
|
28947
29249
|
let accessible = false;
|
|
28948
29250
|
try {
|
|
28949
|
-
|
|
29251
|
+
fs38.accessSync(resolved);
|
|
28950
29252
|
accessible = true;
|
|
28951
29253
|
} catch {
|
|
28952
29254
|
accessible = false;
|
|
28953
29255
|
}
|
|
28954
|
-
return { target, key, path: resolved, exists:
|
|
29256
|
+
return { target, key, path: resolved, exists: fs38.existsSync(resolved), accessible };
|
|
28955
29257
|
}
|
|
28956
29258
|
function codexRuntimeProbeRows() {
|
|
28957
29259
|
const rows = commandProbeRows("codex", "binary", process.platform === "win32" ? "where.exe" : "which", ["codex"]);
|
|
@@ -28962,7 +29264,7 @@ function codexRuntimeProbeRows() {
|
|
|
28962
29264
|
["binary_snap", "/snap/bin/codex"],
|
|
28963
29265
|
["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
|
|
28964
29266
|
]) {
|
|
28965
|
-
if (
|
|
29267
|
+
if (fs38.existsSync(candidatePath)) {
|
|
28966
29268
|
rows.push(toProbeRow("codex", key, candidatePath));
|
|
28967
29269
|
}
|
|
28968
29270
|
}
|
|
@@ -28978,8 +29280,8 @@ function commandProbeRows(target, key, command, args) {
|
|
|
28978
29280
|
|
|
28979
29281
|
// src/commands/status.ts
|
|
28980
29282
|
import crypto10 from "crypto";
|
|
28981
|
-
import
|
|
28982
|
-
import
|
|
29283
|
+
import fs39 from "fs";
|
|
29284
|
+
import path40 from "path";
|
|
28983
29285
|
function runStatusCommand(options, logger) {
|
|
28984
29286
|
const { config, configDir, sourceRoot } = resolveRuntime(
|
|
28985
29287
|
options,
|
|
@@ -29058,21 +29360,21 @@ function classifyCodexFiles(config, sourceRoot, configDir) {
|
|
|
29058
29360
|
rules: paths.rules
|
|
29059
29361
|
};
|
|
29060
29362
|
const rules = compileRules(
|
|
29061
|
-
|
|
29363
|
+
path40.join(sourceRoot, config.source.rules),
|
|
29062
29364
|
"codex",
|
|
29063
29365
|
mappings,
|
|
29064
29366
|
createLossReport()
|
|
29065
29367
|
);
|
|
29066
|
-
const instructionsSource =
|
|
29368
|
+
const instructionsSource = fs39.readFileSync(path40.join(sourceRoot, config.source.instructions), "utf8").trim();
|
|
29067
29369
|
const composedInstructions = `${instructionsSource}
|
|
29068
29370
|
|
|
29069
29371
|
--- tangyr managed rules ---
|
|
29070
29372
|
${rules.agentsAppendix}`.trim();
|
|
29071
29373
|
const agentFiles = ts(
|
|
29072
|
-
|
|
29374
|
+
path40.join(sourceRoot, config.source.agents, "*.md")
|
|
29073
29375
|
).sort();
|
|
29074
|
-
const hooksSource =
|
|
29075
|
-
const mcpSource =
|
|
29376
|
+
const hooksSource = path40.join(sourceRoot, config.source.hooks, "hooks.json");
|
|
29377
|
+
const mcpSource = path40.join(sourceRoot, config.source.mcp);
|
|
29076
29378
|
const ruleRows = rules.dotRulesFiles.length === 0 ? [
|
|
29077
29379
|
{
|
|
29078
29380
|
component: "rules",
|
|
@@ -29083,7 +29385,7 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29083
29385
|
] : rules.dotRulesFiles.map(
|
|
29084
29386
|
(ruleFile) => classifyCompiledFile(
|
|
29085
29387
|
`rules/${ruleFile.name}`,
|
|
29086
|
-
|
|
29388
|
+
path40.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
|
|
29087
29389
|
"codex",
|
|
29088
29390
|
void 0,
|
|
29089
29391
|
config,
|
|
@@ -29101,10 +29403,10 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29101
29403
|
),
|
|
29102
29404
|
...agentFiles.map(
|
|
29103
29405
|
(agentFile) => classifyCompiledFile(
|
|
29104
|
-
`agents/${
|
|
29105
|
-
|
|
29406
|
+
`agents/${path40.basename(agentFile, ".md")}`,
|
|
29407
|
+
path40.join(
|
|
29106
29408
|
resolveTargetPath(codexPaths.agents),
|
|
29107
|
-
`${
|
|
29409
|
+
`${path40.basename(agentFile, ".md")}.toml`
|
|
29108
29410
|
),
|
|
29109
29411
|
"codex",
|
|
29110
29412
|
computeSourceHash(agentFile),
|
|
@@ -29128,11 +29430,11 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29128
29430
|
config,
|
|
29129
29431
|
sourceRoot
|
|
29130
29432
|
),
|
|
29131
|
-
|
|
29433
|
+
fs39.existsSync(hooksSource) ? classifyCodexHooksFile(resolveTargetPath(codexPaths.hooksSharedFile)) : notConfiguredRow(
|
|
29132
29434
|
"hooks",
|
|
29133
29435
|
resolveTargetPath(codexPaths.hooksSharedFile)
|
|
29134
29436
|
),
|
|
29135
|
-
|
|
29437
|
+
fs39.existsSync(mcpSource) ? classifyCompiledFile(
|
|
29136
29438
|
"mcp",
|
|
29137
29439
|
resolveTargetPath(codexPaths.mcpSharedFile),
|
|
29138
29440
|
"codex",
|
|
@@ -29152,7 +29454,7 @@ function classifyCodexHooksFile(filePath) {
|
|
|
29152
29454
|
conformant: true
|
|
29153
29455
|
};
|
|
29154
29456
|
}
|
|
29155
|
-
if (!
|
|
29457
|
+
if (!fs39.existsSync(filePath)) {
|
|
29156
29458
|
return {
|
|
29157
29459
|
component: "hooks",
|
|
29158
29460
|
className: "missing",
|
|
@@ -29184,20 +29486,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29184
29486
|
mcpSharedFile: paths.mcp_shared_file
|
|
29185
29487
|
};
|
|
29186
29488
|
const agentFiles = ts(
|
|
29187
|
-
|
|
29489
|
+
path40.join(sourceRoot, config.source.agents, "*.md")
|
|
29188
29490
|
).sort();
|
|
29189
29491
|
const commandFiles = ts(
|
|
29190
|
-
|
|
29492
|
+
path40.join(sourceRoot, config.source.commands, "*.md")
|
|
29191
29493
|
).sort();
|
|
29192
|
-
const hooksSource =
|
|
29193
|
-
const mcpSource =
|
|
29494
|
+
const hooksSource = path40.join(sourceRoot, config.source.hooks, "hooks.json");
|
|
29495
|
+
const mcpSource = path40.join(sourceRoot, config.source.mcp);
|
|
29194
29496
|
return [
|
|
29195
29497
|
...agentFiles.map(
|
|
29196
29498
|
(agentFile) => classifyCompiledFile(
|
|
29197
|
-
`agents/${
|
|
29198
|
-
|
|
29499
|
+
`agents/${path40.basename(agentFile, ".md")}`,
|
|
29500
|
+
path40.join(
|
|
29199
29501
|
resolveTargetPath(copilotPaths.agents),
|
|
29200
|
-
`${
|
|
29502
|
+
`${path40.basename(agentFile, ".md")}.agent.md`
|
|
29201
29503
|
),
|
|
29202
29504
|
"copilot",
|
|
29203
29505
|
computeSourceHash(agentFile),
|
|
@@ -29214,10 +29516,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29214
29516
|
),
|
|
29215
29517
|
...commandFiles.map(
|
|
29216
29518
|
(commandFile) => classifyCompiledFile(
|
|
29217
|
-
`commands/${
|
|
29218
|
-
|
|
29519
|
+
`commands/${path40.basename(commandFile, ".md")}`,
|
|
29520
|
+
path40.join(
|
|
29219
29521
|
resolveTargetPath(copilotPaths.prompts),
|
|
29220
|
-
`${
|
|
29522
|
+
`${path40.basename(commandFile, ".md")}.prompt.md`
|
|
29221
29523
|
),
|
|
29222
29524
|
"copilot",
|
|
29223
29525
|
computeSourceHash(commandFile),
|
|
@@ -29235,9 +29537,9 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29235
29537
|
config,
|
|
29236
29538
|
sourceRoot
|
|
29237
29539
|
),
|
|
29238
|
-
|
|
29540
|
+
fs39.existsSync(hooksSource) ? classifyCompiledFile(
|
|
29239
29541
|
"hooks",
|
|
29240
|
-
|
|
29542
|
+
path40.join(
|
|
29241
29543
|
resolveTargetPath(copilotPaths.hooks),
|
|
29242
29544
|
"tangyr-managed.json"
|
|
29243
29545
|
),
|
|
@@ -29247,12 +29549,12 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29247
29549
|
sourceRoot
|
|
29248
29550
|
) : notConfiguredRow(
|
|
29249
29551
|
"hooks",
|
|
29250
|
-
|
|
29552
|
+
path40.join(
|
|
29251
29553
|
resolveTargetPath(copilotPaths.hooks),
|
|
29252
29554
|
"tangyr-managed.json"
|
|
29253
29555
|
)
|
|
29254
29556
|
),
|
|
29255
|
-
|
|
29557
|
+
fs39.existsSync(mcpSource) ? classifyCompiledFile(
|
|
29256
29558
|
"mcp",
|
|
29257
29559
|
resolveTargetPath(copilotPaths.mcpSharedFile),
|
|
29258
29560
|
"copilot",
|
|
@@ -29272,7 +29574,7 @@ function notConfiguredRow(component, filePath) {
|
|
|
29272
29574
|
}
|
|
29273
29575
|
function classifyDirectArtifact(artifact, config, sourceRoot) {
|
|
29274
29576
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
29275
|
-
const sourcePath = artifact.sourceKey ?
|
|
29577
|
+
const sourcePath = artifact.sourceKey ? path40.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
|
|
29276
29578
|
if (artifactClass === "managed-symlink" && sourcePath && !isSymlinkCurrent(artifact.path, sourcePath)) {
|
|
29277
29579
|
return {
|
|
29278
29580
|
component: artifact.component,
|
|
@@ -29361,9 +29663,9 @@ function classifyClaudeSharedFiles(config, sourceRoot) {
|
|
|
29361
29663
|
classifyHooks(settingsPath),
|
|
29362
29664
|
classifySettings(
|
|
29363
29665
|
settingsPath,
|
|
29364
|
-
|
|
29666
|
+
path40.resolve(sourceRoot, config.source.settings)
|
|
29365
29667
|
),
|
|
29366
|
-
classifyMcp(claudeJsonPath,
|
|
29668
|
+
classifyMcp(claudeJsonPath, path40.resolve(sourceRoot, config.source.mcp))
|
|
29367
29669
|
];
|
|
29368
29670
|
}
|
|
29369
29671
|
function classifyHooks(filePath) {
|
|
@@ -29427,14 +29729,14 @@ function classifyMcp(filePath, sourcePath) {
|
|
|
29427
29729
|
}
|
|
29428
29730
|
function isSymlinkCurrent(linkPath, sourcePath) {
|
|
29429
29731
|
try {
|
|
29430
|
-
return
|
|
29732
|
+
return fs39.realpathSync(linkPath) === fs39.realpathSync(sourcePath);
|
|
29431
29733
|
} catch {
|
|
29432
29734
|
return false;
|
|
29433
29735
|
}
|
|
29434
29736
|
}
|
|
29435
29737
|
function isCompiledCurrent6(filePath, sourcePath) {
|
|
29436
29738
|
try {
|
|
29437
|
-
const marker = extractProvenanceMarker(
|
|
29739
|
+
const marker = extractProvenanceMarker(fs39.readFileSync(filePath, "utf8"));
|
|
29438
29740
|
return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
|
|
29439
29741
|
} catch {
|
|
29440
29742
|
return false;
|
|
@@ -29464,7 +29766,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
|
|
|
29464
29766
|
}
|
|
29465
29767
|
function readCompiledContent(filePath) {
|
|
29466
29768
|
try {
|
|
29467
|
-
return
|
|
29769
|
+
return fs39.readFileSync(filePath, "utf8");
|
|
29468
29770
|
} catch {
|
|
29469
29771
|
return null;
|
|
29470
29772
|
}
|
|
@@ -29495,8 +29797,8 @@ function hashString6(value) {
|
|
|
29495
29797
|
}
|
|
29496
29798
|
|
|
29497
29799
|
// src/commands/sync.ts
|
|
29498
|
-
import
|
|
29499
|
-
import
|
|
29800
|
+
import fs42 from "fs";
|
|
29801
|
+
import path43 from "path";
|
|
29500
29802
|
|
|
29501
29803
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
29502
29804
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -29994,8 +30296,8 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
29994
30296
|
var source_default = chalk;
|
|
29995
30297
|
|
|
29996
30298
|
// src/adapters/claude-code.ts
|
|
29997
|
-
import
|
|
29998
|
-
import
|
|
30299
|
+
import fs41 from "fs";
|
|
30300
|
+
import path42 from "path";
|
|
29999
30301
|
|
|
30000
30302
|
// src/core/shim.ts
|
|
30001
30303
|
import crypto11 from "crypto";
|
|
@@ -30012,12 +30314,12 @@ ${SHIM_BODY}`;
|
|
|
30012
30314
|
|
|
30013
30315
|
// src/compiler/hook-components.ts
|
|
30014
30316
|
var import_yaml11 = __toESM(require_dist(), 1);
|
|
30015
|
-
import
|
|
30016
|
-
import
|
|
30317
|
+
import fs40 from "fs";
|
|
30318
|
+
import path41 from "path";
|
|
30017
30319
|
function parseHookDeclaration(filePath) {
|
|
30018
30320
|
let raw;
|
|
30019
30321
|
try {
|
|
30020
|
-
raw =
|
|
30322
|
+
raw = fs40.readFileSync(filePath, "utf8");
|
|
30021
30323
|
} catch {
|
|
30022
30324
|
return null;
|
|
30023
30325
|
}
|
|
@@ -30100,9 +30402,9 @@ function synthesizeHooksJson(declarations) {
|
|
|
30100
30402
|
return { hooks };
|
|
30101
30403
|
}
|
|
30102
30404
|
function loadSourceHooks(hooksDir, hookNames) {
|
|
30103
|
-
const hooksJsonPath =
|
|
30104
|
-
if (
|
|
30105
|
-
const raw =
|
|
30405
|
+
const hooksJsonPath = path41.join(hooksDir, "hooks.json");
|
|
30406
|
+
if (fs40.existsSync(hooksJsonPath)) {
|
|
30407
|
+
const raw = fs40.readFileSync(hooksJsonPath, "utf8");
|
|
30106
30408
|
return JSON.parse(raw);
|
|
30107
30409
|
}
|
|
30108
30410
|
const declarations = loadHookDeclarations(hooksDir, hookNames);
|
|
@@ -30113,14 +30415,14 @@ function loadHookDeclarations(hooksDir, hookNames) {
|
|
|
30113
30415
|
if (hookNames && hookNames.length > 0) {
|
|
30114
30416
|
names = hookNames;
|
|
30115
30417
|
} else {
|
|
30116
|
-
if (!
|
|
30418
|
+
if (!fs40.existsSync(hooksDir) || !fs40.statSync(hooksDir).isDirectory()) {
|
|
30117
30419
|
return [];
|
|
30118
30420
|
}
|
|
30119
|
-
names =
|
|
30421
|
+
names = fs40.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
|
|
30120
30422
|
}
|
|
30121
30423
|
const declarations = [];
|
|
30122
30424
|
for (const name of names) {
|
|
30123
|
-
const filePath =
|
|
30425
|
+
const filePath = path41.join(hooksDir, `${name}.md`);
|
|
30124
30426
|
const decl = parseHookDeclaration(filePath);
|
|
30125
30427
|
if (decl) {
|
|
30126
30428
|
declarations.push(decl);
|
|
@@ -30244,7 +30546,7 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
30244
30546
|
}
|
|
30245
30547
|
if (!shouldSkipComponent6(options, "instructions") && manifest && scopePath) {
|
|
30246
30548
|
const shimPath = profile.instructions_shim;
|
|
30247
|
-
const agentsMdPath =
|
|
30549
|
+
const agentsMdPath = path42.resolve(sourceRoot, config.source.instructions);
|
|
30248
30550
|
if (!options.dryRun) {
|
|
30249
30551
|
applyClaudeCodeShimUpgrade(
|
|
30250
30552
|
shimPath,
|
|
@@ -30298,13 +30600,13 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
30298
30600
|
}
|
|
30299
30601
|
function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
|
|
30300
30602
|
if (!mappings.modelTiers.custom_provider) return;
|
|
30301
|
-
const agentsDir =
|
|
30302
|
-
if (!
|
|
30303
|
-
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()) {
|
|
30304
30606
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
30305
30607
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
30306
30608
|
if (hasProvider) {
|
|
30307
|
-
const basename =
|
|
30609
|
+
const basename = path42.basename(agentFile);
|
|
30308
30610
|
addLoss(lossReport, "claude-code", "agents", {
|
|
30309
30611
|
source: `agents/${basename}`,
|
|
30310
30612
|
fields: [
|
|
@@ -30329,19 +30631,19 @@ function shouldSkipComponent6(options, component) {
|
|
|
30329
30631
|
function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath, logger) {
|
|
30330
30632
|
const expectedBodyHash = shimBodyHash();
|
|
30331
30633
|
const shimContent = buildAgentsMdShim(shimPath, agentsMdPath, "claude-code");
|
|
30332
|
-
if (!
|
|
30634
|
+
if (!fs41.existsSync(shimPath)) {
|
|
30333
30635
|
manifest.artifacts.push({
|
|
30334
|
-
relativePath:
|
|
30636
|
+
relativePath: path42.relative(scopePath, shimPath),
|
|
30335
30637
|
hash: expectedBodyHash,
|
|
30336
30638
|
origin: "tangyr-managed"
|
|
30337
30639
|
});
|
|
30338
30640
|
writeManifest(scopePath, manifest);
|
|
30339
|
-
|
|
30340
|
-
|
|
30641
|
+
fs41.mkdirSync(path42.dirname(shimPath), { recursive: true });
|
|
30642
|
+
fs41.writeFileSync(shimPath, shimContent);
|
|
30341
30643
|
logger?.verbose(`instructions-shim: wrote @AGENTS.md shim -> ${shimPath}`);
|
|
30342
30644
|
return;
|
|
30343
30645
|
}
|
|
30344
|
-
const existing =
|
|
30646
|
+
const existing = fs41.readFileSync(shimPath, "utf8");
|
|
30345
30647
|
const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
30346
30648
|
const marker = extractProvenanceMarker(firstNonEmptyLine);
|
|
30347
30649
|
if (marker !== null && marker.hash === expectedBodyHash) {
|
|
@@ -30352,21 +30654,21 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
30352
30654
|
}
|
|
30353
30655
|
backupFile(shimPath, manifest);
|
|
30354
30656
|
writeManifest(scopePath, manifest);
|
|
30355
|
-
|
|
30657
|
+
fs41.writeFileSync(shimPath, shimContent);
|
|
30356
30658
|
manifest.artifacts.push({
|
|
30357
|
-
relativePath:
|
|
30659
|
+
relativePath: path42.relative(scopePath, shimPath),
|
|
30358
30660
|
hash: expectedBodyHash,
|
|
30359
30661
|
origin: "tangyr-managed"
|
|
30360
30662
|
});
|
|
30361
30663
|
logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
|
|
30362
30664
|
}
|
|
30363
30665
|
function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
|
|
30364
|
-
const source =
|
|
30666
|
+
const source = path42.resolve(
|
|
30365
30667
|
sourceRoot,
|
|
30366
30668
|
config.source[directComponent.sourceKey]
|
|
30367
30669
|
);
|
|
30368
30670
|
const destination = directComponent.destination;
|
|
30369
|
-
if (!
|
|
30671
|
+
if (!fs41.existsSync(source)) {
|
|
30370
30672
|
return skippedMissingSource6(directComponent.component, source);
|
|
30371
30673
|
}
|
|
30372
30674
|
if (options.dryRun) {
|
|
@@ -30388,7 +30690,7 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30388
30690
|
};
|
|
30389
30691
|
}
|
|
30390
30692
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
30391
|
-
|
|
30693
|
+
fs41.unlinkSync(destination);
|
|
30392
30694
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
30393
30695
|
return {
|
|
30394
30696
|
component: directComponent.component,
|
|
@@ -30396,9 +30698,9 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30396
30698
|
path: destination
|
|
30397
30699
|
};
|
|
30398
30700
|
} else if (artifactClass === "managed-symlink") {
|
|
30399
|
-
|
|
30701
|
+
fs41.unlinkSync(destination);
|
|
30400
30702
|
}
|
|
30401
|
-
ensureDir(
|
|
30703
|
+
ensureDir(path42.dirname(destination));
|
|
30402
30704
|
createRelativeSymlink(source, destination, directComponent.type, {
|
|
30403
30705
|
logger,
|
|
30404
30706
|
provenanceMarker: directComponent.type === "file" ? formatProvenanceMarker(
|
|
@@ -30415,8 +30717,8 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
30415
30717
|
};
|
|
30416
30718
|
}
|
|
30417
30719
|
function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination, manifest, scopePath) {
|
|
30418
|
-
const source =
|
|
30419
|
-
if (!
|
|
30720
|
+
const source = path42.resolve(sourceRoot, config.source.skills);
|
|
30721
|
+
if (!fs41.existsSync(source)) {
|
|
30420
30722
|
return [skippedMissingSource6("skills", source)];
|
|
30421
30723
|
}
|
|
30422
30724
|
const declaredNames = resolveKitSkillNames(sourceRoot);
|
|
@@ -30426,7 +30728,7 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30426
30728
|
if (isLegacyWholesaleSymlink) {
|
|
30427
30729
|
for (const name of foreignSkillNames(source, declaredNames)) {
|
|
30428
30730
|
logger.info(
|
|
30429
|
-
`[dry-run] skills: migrate foreign skill ${
|
|
30731
|
+
`[dry-run] skills: migrate foreign skill ${path42.join(source, name)} -> ${path42.join(destination, name)}`
|
|
30430
30732
|
);
|
|
30431
30733
|
}
|
|
30432
30734
|
logger.info(
|
|
@@ -30434,9 +30736,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30434
30736
|
);
|
|
30435
30737
|
}
|
|
30436
30738
|
for (const name of declaredNames ?? listSkillDirNames(source)) {
|
|
30437
|
-
const skillDestination =
|
|
30739
|
+
const skillDestination = path42.join(destination, name);
|
|
30438
30740
|
logger.info(
|
|
30439
|
-
`[dry-run] skills: symlink ${
|
|
30741
|
+
`[dry-run] skills: symlink ${path42.join(source, name)} -> ${skillDestination}`
|
|
30440
30742
|
);
|
|
30441
30743
|
outcomes2.push({
|
|
30442
30744
|
component: "skills",
|
|
@@ -30469,9 +30771,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
30469
30771
|
return outcomes;
|
|
30470
30772
|
}
|
|
30471
30773
|
function syncSingleSkill(config, sourceRoot, options, logger, source, destination, name, manifest, scopePath) {
|
|
30472
|
-
const skillSource =
|
|
30473
|
-
const skillDestination =
|
|
30474
|
-
if (!
|
|
30774
|
+
const skillSource = path42.join(source, name);
|
|
30775
|
+
const skillDestination = path42.join(destination, name);
|
|
30776
|
+
if (!fs41.existsSync(skillSource)) {
|
|
30475
30777
|
return skippedMissingSource6("skills", skillSource);
|
|
30476
30778
|
}
|
|
30477
30779
|
const artifactClass = classifyArtifact(skillDestination, config, sourceRoot);
|
|
@@ -30483,7 +30785,7 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
|
|
|
30483
30785
|
};
|
|
30484
30786
|
}
|
|
30485
30787
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(skillDestination, /* @__PURE__ */ new Set([skillDestination]), config)) {
|
|
30486
|
-
|
|
30788
|
+
fs41.unlinkSync(skillDestination);
|
|
30487
30789
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(
|
|
30488
30790
|
skillDestination,
|
|
30489
30791
|
config,
|
|
@@ -30494,25 +30796,25 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
|
|
|
30494
30796
|
)) {
|
|
30495
30797
|
return { component: "skills", status: "conflict", path: skillDestination };
|
|
30496
30798
|
} else if (artifactClass === "managed-symlink") {
|
|
30497
|
-
|
|
30799
|
+
fs41.unlinkSync(skillDestination);
|
|
30498
30800
|
}
|
|
30499
30801
|
createRelativeSymlink(skillSource, skillDestination, "dir");
|
|
30500
30802
|
return { component: "skills", status: "success", path: skillDestination };
|
|
30501
30803
|
}
|
|
30502
30804
|
function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger) {
|
|
30503
30805
|
const foreignNames = foreignSkillNames(source, declaredNames);
|
|
30504
|
-
|
|
30806
|
+
fs41.unlinkSync(destination);
|
|
30505
30807
|
ensureDir(destination);
|
|
30506
30808
|
for (const name of foreignNames) {
|
|
30507
|
-
const from =
|
|
30508
|
-
const to =
|
|
30509
|
-
if (
|
|
30809
|
+
const from = path42.join(source, name);
|
|
30810
|
+
const to = path42.join(destination, name);
|
|
30811
|
+
if (fs41.existsSync(to)) {
|
|
30510
30812
|
logger.warn(
|
|
30511
30813
|
`skills migration: ${to} already exists \u2014 skipping move of ${from} to avoid overwrite`
|
|
30512
30814
|
);
|
|
30513
30815
|
continue;
|
|
30514
30816
|
}
|
|
30515
|
-
|
|
30817
|
+
fs41.renameSync(from, to);
|
|
30516
30818
|
logger.info(`skills migration: moved ${from} -> ${to}`);
|
|
30517
30819
|
}
|
|
30518
30820
|
}
|
|
@@ -30524,21 +30826,21 @@ function foreignSkillNames(source, declaredNames) {
|
|
|
30524
30826
|
return listSkillDirNames(source).filter((name) => !declaredSet.has(name));
|
|
30525
30827
|
}
|
|
30526
30828
|
function listSkillDirNames(dir) {
|
|
30527
|
-
if (!
|
|
30829
|
+
if (!fs41.existsSync(dir)) {
|
|
30528
30830
|
return [];
|
|
30529
30831
|
}
|
|
30530
|
-
return
|
|
30832
|
+
return fs41.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
30531
30833
|
}
|
|
30532
30834
|
function isSymlinkPath(filePath) {
|
|
30533
30835
|
try {
|
|
30534
|
-
return
|
|
30836
|
+
return fs41.lstatSync(filePath).isSymbolicLink();
|
|
30535
30837
|
} catch {
|
|
30536
30838
|
return false;
|
|
30537
30839
|
}
|
|
30538
30840
|
}
|
|
30539
30841
|
function syncHookScriptsBridge(config, sourceRoot, options, logger, destination, manifest, scopePath) {
|
|
30540
|
-
const source =
|
|
30541
|
-
if (!
|
|
30842
|
+
const source = path42.resolve(sourceRoot, config.source.hooks);
|
|
30843
|
+
if (!fs41.existsSync(source)) {
|
|
30542
30844
|
return skippedMissingSource6("hooks", source);
|
|
30543
30845
|
}
|
|
30544
30846
|
if (options.dryRun) {
|
|
@@ -30550,13 +30852,13 @@ function syncHookScriptsBridge(config, sourceRoot, options, logger, destination,
|
|
|
30550
30852
|
return { component: "hooks", status: "skipped-current", path: destination };
|
|
30551
30853
|
}
|
|
30552
30854
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
30553
|
-
|
|
30855
|
+
fs41.unlinkSync(destination);
|
|
30554
30856
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
30555
30857
|
return { component: "hooks", status: "conflict", path: destination };
|
|
30556
30858
|
} else if (artifactClass === "managed-symlink") {
|
|
30557
|
-
|
|
30859
|
+
fs41.unlinkSync(destination);
|
|
30558
30860
|
}
|
|
30559
|
-
ensureDir(
|
|
30861
|
+
ensureDir(path42.dirname(destination));
|
|
30560
30862
|
createRelativeSymlink(source, destination, "dir");
|
|
30561
30863
|
return { component: "hooks", status: "success", path: destination };
|
|
30562
30864
|
}
|
|
@@ -30579,7 +30881,7 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
|
|
|
30579
30881
|
destination,
|
|
30580
30882
|
settings,
|
|
30581
30883
|
stringifyJson3,
|
|
30582
|
-
!
|
|
30884
|
+
!fs41.existsSync(destination),
|
|
30583
30885
|
logger
|
|
30584
30886
|
);
|
|
30585
30887
|
return {
|
|
@@ -30589,8 +30891,8 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
|
|
|
30589
30891
|
};
|
|
30590
30892
|
}
|
|
30591
30893
|
function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
30592
|
-
const source =
|
|
30593
|
-
if (!
|
|
30894
|
+
const source = path42.resolve(sourceRoot, config.source.mcp);
|
|
30895
|
+
if (!fs41.existsSync(source)) {
|
|
30594
30896
|
return skippedMissingSource6("mcp", source);
|
|
30595
30897
|
}
|
|
30596
30898
|
if (options.dryRun) {
|
|
@@ -30615,7 +30917,7 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
|
30615
30917
|
destination,
|
|
30616
30918
|
hostConfig,
|
|
30617
30919
|
stringifyJson3,
|
|
30618
|
-
!
|
|
30920
|
+
!fs41.existsSync(destination),
|
|
30619
30921
|
logger
|
|
30620
30922
|
);
|
|
30621
30923
|
return {
|
|
@@ -30625,8 +30927,8 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
|
|
|
30625
30927
|
};
|
|
30626
30928
|
}
|
|
30627
30929
|
function syncSettings2(config, sourceRoot, options, logger, destination) {
|
|
30628
|
-
const source =
|
|
30629
|
-
if (!
|
|
30930
|
+
const source = path42.resolve(sourceRoot, config.source.settings);
|
|
30931
|
+
if (!fs41.existsSync(source)) {
|
|
30630
30932
|
return skippedMissingSource6("settings", source);
|
|
30631
30933
|
}
|
|
30632
30934
|
if (options.dryRun) {
|
|
@@ -30644,7 +30946,7 @@ function syncSettings2(config, sourceRoot, options, logger, destination) {
|
|
|
30644
30946
|
destination,
|
|
30645
30947
|
settings,
|
|
30646
30948
|
stringifyJson3,
|
|
30647
|
-
!
|
|
30949
|
+
!fs41.existsSync(destination),
|
|
30648
30950
|
logger
|
|
30649
30951
|
);
|
|
30650
30952
|
return {
|
|
@@ -30669,11 +30971,11 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
|
|
|
30669
30971
|
backupFile(destination, manifest);
|
|
30670
30972
|
writeManifest(scopePath, manifest);
|
|
30671
30973
|
} else {
|
|
30672
|
-
|
|
30974
|
+
fs41.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
30673
30975
|
}
|
|
30674
30976
|
return true;
|
|
30675
30977
|
}
|
|
30676
|
-
|
|
30978
|
+
fs41.rmSync(destination, { recursive: true, force: true });
|
|
30677
30979
|
return true;
|
|
30678
30980
|
}
|
|
30679
30981
|
function skippedMissingSource6(component, source) {
|
|
@@ -30685,16 +30987,16 @@ function skippedMissingSource6(component, source) {
|
|
|
30685
30987
|
}
|
|
30686
30988
|
function isSymlinkTo6(linkPath, source) {
|
|
30687
30989
|
try {
|
|
30688
|
-
return
|
|
30990
|
+
return fs41.realpathSync(linkPath) === fs41.realpathSync(source);
|
|
30689
30991
|
} catch {
|
|
30690
30992
|
return false;
|
|
30691
30993
|
}
|
|
30692
30994
|
}
|
|
30693
30995
|
function readJsonObject4(filePath) {
|
|
30694
|
-
if (!
|
|
30996
|
+
if (!fs41.existsSync(filePath)) {
|
|
30695
30997
|
return {};
|
|
30696
30998
|
}
|
|
30697
|
-
const parsed = JSON.parse(
|
|
30999
|
+
const parsed = JSON.parse(fs41.readFileSync(filePath, "utf8"));
|
|
30698
31000
|
return isRecord5(parsed) ? parsed : {};
|
|
30699
31001
|
}
|
|
30700
31002
|
function markManaged(value) {
|
|
@@ -30960,7 +31262,7 @@ function writeLossReport(filePath, report) {
|
|
|
30960
31262
|
if (!filePath) {
|
|
30961
31263
|
return;
|
|
30962
31264
|
}
|
|
30963
|
-
|
|
31265
|
+
fs42.writeFileSync(filePath, `${JSON.stringify(report, null, 2)}
|
|
30964
31266
|
`);
|
|
30965
31267
|
}
|
|
30966
31268
|
function prepareKitManifest(scope, projectRoot, kitInfo) {
|
|
@@ -31001,8 +31303,8 @@ function updateManifest(kitInfo, kitSync) {
|
|
|
31001
31303
|
writeManifest(kitSync.scopePath, kitSync.manifest);
|
|
31002
31304
|
}
|
|
31003
31305
|
function resolveKitFilePath(kitPath, relativePath) {
|
|
31004
|
-
const fullPath =
|
|
31005
|
-
return
|
|
31306
|
+
const fullPath = path43.join(kitPath, relativePath);
|
|
31307
|
+
return fs42.existsSync(fullPath) ? fullPath : null;
|
|
31006
31308
|
}
|
|
31007
31309
|
function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
|
|
31008
31310
|
if (removedSourcePaths.length === 0 || !mappings) {
|
|
@@ -31063,9 +31365,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31063
31365
|
}
|
|
31064
31366
|
if (relativePath.startsWith("agents/")) {
|
|
31065
31367
|
removeManagedCompiledArtifact2(
|
|
31066
|
-
|
|
31368
|
+
path43.join(
|
|
31067
31369
|
resolveTargetPath(paths.agents ?? ""),
|
|
31068
|
-
`${
|
|
31370
|
+
`${path43.parse(relativePath).name}.agent.md`
|
|
31069
31371
|
),
|
|
31070
31372
|
"copilot",
|
|
31071
31373
|
relativePath,
|
|
@@ -31075,9 +31377,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31075
31377
|
}
|
|
31076
31378
|
if (relativePath.startsWith("commands/")) {
|
|
31077
31379
|
removeManagedCompiledArtifact2(
|
|
31078
|
-
|
|
31380
|
+
path43.join(
|
|
31079
31381
|
resolveTargetPath(paths.prompts ?? ""),
|
|
31080
|
-
`${
|
|
31382
|
+
`${path43.parse(relativePath).name}.prompt.md`
|
|
31081
31383
|
),
|
|
31082
31384
|
"copilot",
|
|
31083
31385
|
relativePath,
|
|
@@ -31087,7 +31389,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
31087
31389
|
}
|
|
31088
31390
|
if (relativePath.endsWith("hooks.json")) {
|
|
31089
31391
|
removeManagedCompiledArtifact2(
|
|
31090
|
-
|
|
31392
|
+
path43.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
31091
31393
|
"copilot",
|
|
31092
31394
|
relativePath,
|
|
31093
31395
|
logger
|
|
@@ -31117,9 +31419,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
31117
31419
|
}
|
|
31118
31420
|
if (relativePath.startsWith("agents/")) {
|
|
31119
31421
|
removeManagedCompiledArtifact2(
|
|
31120
|
-
|
|
31422
|
+
path43.join(
|
|
31121
31423
|
resolveTargetPath(paths.agents ?? ""),
|
|
31122
|
-
`${
|
|
31424
|
+
`${path43.parse(relativePath).name}.toml`
|
|
31123
31425
|
),
|
|
31124
31426
|
"codex",
|
|
31125
31427
|
relativePath,
|
|
@@ -31129,9 +31431,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
31129
31431
|
}
|
|
31130
31432
|
if (relativePath.startsWith("rules/")) {
|
|
31131
31433
|
removeManagedCompiledArtifact2(
|
|
31132
|
-
|
|
31434
|
+
path43.join(
|
|
31133
31435
|
resolveTargetPath(paths.rules ?? ""),
|
|
31134
|
-
`${
|
|
31436
|
+
`${path43.parse(relativePath).name}.rules`
|
|
31135
31437
|
),
|
|
31136
31438
|
"codex",
|
|
31137
31439
|
relativePath,
|
|
@@ -31170,9 +31472,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
31170
31472
|
}
|
|
31171
31473
|
if (relativePath.startsWith("agents/")) {
|
|
31172
31474
|
removeManagedCompiledArtifact2(
|
|
31173
|
-
|
|
31475
|
+
path43.join(
|
|
31174
31476
|
resolveTargetPath(paths.agents ?? ""),
|
|
31175
|
-
`${
|
|
31477
|
+
`${path43.parse(relativePath).name}.md`
|
|
31176
31478
|
),
|
|
31177
31479
|
"opencode",
|
|
31178
31480
|
relativePath,
|
|
@@ -31182,9 +31484,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
31182
31484
|
}
|
|
31183
31485
|
if (relativePath.startsWith("commands/")) {
|
|
31184
31486
|
removeManagedCompiledArtifact2(
|
|
31185
|
-
|
|
31487
|
+
path43.join(
|
|
31186
31488
|
resolveTargetPath(paths.commands ?? ""),
|
|
31187
|
-
`${
|
|
31489
|
+
`${path43.parse(relativePath).name}.md`
|
|
31188
31490
|
),
|
|
31189
31491
|
"opencode",
|
|
31190
31492
|
relativePath,
|
|
@@ -31216,9 +31518,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31216
31518
|
}
|
|
31217
31519
|
if (relativePath.startsWith("agents/")) {
|
|
31218
31520
|
removeManagedCompiledArtifact2(
|
|
31219
|
-
|
|
31521
|
+
path43.join(
|
|
31220
31522
|
resolveTargetPath(paths.agents ?? ""),
|
|
31221
|
-
`${
|
|
31523
|
+
`${path43.parse(relativePath).name}.md`
|
|
31222
31524
|
),
|
|
31223
31525
|
"cursor",
|
|
31224
31526
|
relativePath,
|
|
@@ -31228,9 +31530,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31228
31530
|
}
|
|
31229
31531
|
if (relativePath.startsWith("rules/")) {
|
|
31230
31532
|
removeManagedCompiledArtifact2(
|
|
31231
|
-
|
|
31533
|
+
path43.join(
|
|
31232
31534
|
resolveTargetPath(paths.rules ?? ""),
|
|
31233
|
-
`${
|
|
31535
|
+
`${path43.parse(relativePath).name}.mdc`
|
|
31234
31536
|
),
|
|
31235
31537
|
"cursor",
|
|
31236
31538
|
relativePath,
|
|
@@ -31240,9 +31542,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
31240
31542
|
}
|
|
31241
31543
|
if (relativePath.startsWith("commands/")) {
|
|
31242
31544
|
removeManagedCompiledArtifact2(
|
|
31243
|
-
|
|
31545
|
+
path43.join(
|
|
31244
31546
|
resolveTargetPath(paths.skills ?? ""),
|
|
31245
|
-
|
|
31547
|
+
path43.parse(relativePath).name,
|
|
31246
31548
|
"SKILL.md"
|
|
31247
31549
|
),
|
|
31248
31550
|
"cursor",
|
|
@@ -31286,9 +31588,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31286
31588
|
}
|
|
31287
31589
|
if (relativePath.startsWith("rules/")) {
|
|
31288
31590
|
removeManagedCompiledArtifact2(
|
|
31289
|
-
|
|
31591
|
+
path43.join(
|
|
31290
31592
|
resolveTargetPath(paths.rules ?? ""),
|
|
31291
|
-
`${
|
|
31593
|
+
`${path43.parse(relativePath).name}.md`
|
|
31292
31594
|
),
|
|
31293
31595
|
"cline",
|
|
31294
31596
|
relativePath,
|
|
@@ -31298,9 +31600,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31298
31600
|
}
|
|
31299
31601
|
if (relativePath.startsWith("commands/")) {
|
|
31300
31602
|
removeManagedCompiledArtifact2(
|
|
31301
|
-
|
|
31603
|
+
path43.join(
|
|
31302
31604
|
resolveTargetPath(paths.workflows ?? ""),
|
|
31303
|
-
|
|
31605
|
+
path43.basename(relativePath)
|
|
31304
31606
|
),
|
|
31305
31607
|
"cline",
|
|
31306
31608
|
relativePath,
|
|
@@ -31318,17 +31620,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
31318
31620
|
}
|
|
31319
31621
|
}
|
|
31320
31622
|
function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
|
|
31321
|
-
if (!
|
|
31623
|
+
if (!fs42.existsSync(artifactPath)) {
|
|
31322
31624
|
return;
|
|
31323
31625
|
}
|
|
31324
|
-
if (!
|
|
31626
|
+
if (!fs42.statSync(artifactPath).isFile()) {
|
|
31325
31627
|
return;
|
|
31326
31628
|
}
|
|
31327
|
-
const marker = extractProvenanceMarker(
|
|
31629
|
+
const marker = extractProvenanceMarker(fs42.readFileSync(artifactPath, "utf8"));
|
|
31328
31630
|
if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
|
|
31329
31631
|
return;
|
|
31330
31632
|
}
|
|
31331
|
-
|
|
31633
|
+
fs42.rmSync(artifactPath, { force: true });
|
|
31332
31634
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31333
31635
|
}
|
|
31334
31636
|
function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
@@ -31359,10 +31661,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
|
|
|
31359
31661
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31360
31662
|
}
|
|
31361
31663
|
function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
31362
|
-
if (!
|
|
31664
|
+
if (!fs42.existsSync(artifactPath)) {
|
|
31363
31665
|
return;
|
|
31364
31666
|
}
|
|
31365
|
-
const content =
|
|
31667
|
+
const content = fs42.readFileSync(artifactPath, "utf8");
|
|
31366
31668
|
const startMarker = "# tangyr: managed mcp start";
|
|
31367
31669
|
const endMarker = "# tangyr: managed mcp end";
|
|
31368
31670
|
const startIndex = content.indexOf(startMarker);
|
|
@@ -31379,19 +31681,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
|
31379
31681
|
const after = content.slice(endIndex + endMarker.length).trimStart();
|
|
31380
31682
|
const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
|
|
31381
31683
|
if (cleaned.length === 0) {
|
|
31382
|
-
|
|
31684
|
+
fs42.rmSync(artifactPath, { force: true });
|
|
31383
31685
|
} else {
|
|
31384
|
-
|
|
31686
|
+
fs42.writeFileSync(artifactPath, `${cleaned}
|
|
31385
31687
|
`);
|
|
31386
31688
|
}
|
|
31387
31689
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
31388
31690
|
}
|
|
31389
31691
|
function readJsonObject5(filePath) {
|
|
31390
|
-
if (!
|
|
31692
|
+
if (!fs42.existsSync(filePath)) {
|
|
31391
31693
|
return null;
|
|
31392
31694
|
}
|
|
31393
31695
|
try {
|
|
31394
|
-
const parsed = JSON.parse(
|
|
31696
|
+
const parsed = JSON.parse(fs42.readFileSync(filePath, "utf8"));
|
|
31395
31697
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
31396
31698
|
} catch {
|
|
31397
31699
|
return null;
|
|
@@ -31405,10 +31707,10 @@ function readJsonMetadata(value) {
|
|
|
31405
31707
|
}
|
|
31406
31708
|
function writeJsonOrRemove2(filePath, parsed) {
|
|
31407
31709
|
if (isEmptyJsonValue2(parsed)) {
|
|
31408
|
-
|
|
31710
|
+
fs42.rmSync(filePath, { force: true });
|
|
31409
31711
|
return;
|
|
31410
31712
|
}
|
|
31411
|
-
|
|
31713
|
+
fs42.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
31412
31714
|
`);
|
|
31413
31715
|
}
|
|
31414
31716
|
function isEmptyJsonValue2(value) {
|
|
@@ -31468,8 +31770,8 @@ function removeManagedHookEntries(value, expectedSource) {
|
|
|
31468
31770
|
}
|
|
31469
31771
|
|
|
31470
31772
|
// src/commands/validate.ts
|
|
31471
|
-
import
|
|
31472
|
-
import
|
|
31773
|
+
import fs43 from "fs";
|
|
31774
|
+
import path44 from "path";
|
|
31473
31775
|
var SUPPORTED_KIT_FORMATS2 = [1];
|
|
31474
31776
|
var SUPPORTED_DISCIPLINE_VERSIONS = [
|
|
31475
31777
|
"0.14.0",
|
|
@@ -31553,8 +31855,8 @@ function checkKitFormatSupported(kit) {
|
|
|
31553
31855
|
}
|
|
31554
31856
|
function checkEntrypointExists(kit) {
|
|
31555
31857
|
const entrypoint = "CLAUDE.md";
|
|
31556
|
-
const entrypointPath =
|
|
31557
|
-
if (!
|
|
31858
|
+
const entrypointPath = path44.join(kit.path, entrypoint);
|
|
31859
|
+
if (!fs43.existsSync(entrypointPath)) {
|
|
31558
31860
|
return {
|
|
31559
31861
|
code: "entrypoint-missing",
|
|
31560
31862
|
location: entrypoint,
|
|
@@ -31611,9 +31913,9 @@ function checkComponentFrontmatter(kit) {
|
|
|
31611
31913
|
const missingSet = new Set(kit.components[cat].missing);
|
|
31612
31914
|
for (const name of kit.components[cat].declared) {
|
|
31613
31915
|
if (missingSet.has(name)) continue;
|
|
31614
|
-
const filePath = cat === "skills" ?
|
|
31615
|
-
if (!
|
|
31616
|
-
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);
|
|
31617
31919
|
try {
|
|
31618
31920
|
const { data } = parseMarkdownFrontmatter(filePath);
|
|
31619
31921
|
for (const field of requiredFields) {
|
|
@@ -31638,10 +31940,10 @@ function checkComponentFrontmatter(kit) {
|
|
|
31638
31940
|
}
|
|
31639
31941
|
function checkReservedRootNames(kit) {
|
|
31640
31942
|
const violations = [];
|
|
31641
|
-
if (!
|
|
31943
|
+
if (!fs43.existsSync(kit.path) || !fs43.statSync(kit.path).isDirectory()) {
|
|
31642
31944
|
return violations;
|
|
31643
31945
|
}
|
|
31644
|
-
const entries =
|
|
31946
|
+
const entries = fs43.readdirSync(kit.path, { withFileTypes: true });
|
|
31645
31947
|
for (const entry of entries) {
|
|
31646
31948
|
if (RESERVED_ROOT_NAMES.includes(entry.name)) {
|
|
31647
31949
|
violations.push({
|
|
@@ -31658,8 +31960,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31658
31960
|
const missingSet = new Set(kit.components.commands.missing);
|
|
31659
31961
|
for (const name of kit.components.commands.declared) {
|
|
31660
31962
|
if (missingSet.has(name)) continue;
|
|
31661
|
-
const filePath =
|
|
31662
|
-
if (!
|
|
31963
|
+
const filePath = path44.join(kit.path, "commands", `${name}.md`);
|
|
31964
|
+
if (!fs43.existsSync(filePath)) continue;
|
|
31663
31965
|
let data;
|
|
31664
31966
|
try {
|
|
31665
31967
|
({ data } = parseMarkdownFrontmatter(filePath));
|
|
@@ -31672,7 +31974,7 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31672
31974
|
if (!barred) {
|
|
31673
31975
|
violations.push({
|
|
31674
31976
|
code: "command-human-only-model-invocable",
|
|
31675
|
-
location:
|
|
31977
|
+
location: path44.relative(kit.path, filePath),
|
|
31676
31978
|
message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
|
|
31677
31979
|
});
|
|
31678
31980
|
}
|
|
@@ -31681,8 +31983,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
31681
31983
|
}
|
|
31682
31984
|
|
|
31683
31985
|
// src/commands/verify.ts
|
|
31684
|
-
import
|
|
31685
|
-
import
|
|
31986
|
+
import fs44 from "fs";
|
|
31987
|
+
import path45 from "path";
|
|
31686
31988
|
function runVerifyCommand(options, logger) {
|
|
31687
31989
|
const { config, configDir, sourceRoot, kitInfo } = resolveRuntime(
|
|
31688
31990
|
options,
|
|
@@ -31773,8 +32075,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
|
|
|
31773
32075
|
if (!slotPath) {
|
|
31774
32076
|
continue;
|
|
31775
32077
|
}
|
|
31776
|
-
const fullPath = subPath ?
|
|
31777
|
-
if (!
|
|
32078
|
+
const fullPath = subPath ? path45.join(slotPath, subPath) : slotPath;
|
|
32079
|
+
if (!fs44.existsSync(fullPath)) {
|
|
31778
32080
|
failures.push(
|
|
31779
32081
|
`claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
|
|
31780
32082
|
);
|