vet-skills 0.6.0 → 0.7.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 +678 -178
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -111,7 +111,7 @@ var require_visit = __commonJS({
|
|
|
111
111
|
"use strict";
|
|
112
112
|
var identity = require_identity();
|
|
113
113
|
var BREAK = /* @__PURE__ */ Symbol("break visit");
|
|
114
|
-
var
|
|
114
|
+
var SKIP3 = /* @__PURE__ */ Symbol("skip children");
|
|
115
115
|
var REMOVE = /* @__PURE__ */ Symbol("remove node");
|
|
116
116
|
function visit(node, visitor) {
|
|
117
117
|
const visitor_ = initVisitor(visitor);
|
|
@@ -123,7 +123,7 @@ var require_visit = __commonJS({
|
|
|
123
123
|
visit_(null, node, visitor_, Object.freeze([]));
|
|
124
124
|
}
|
|
125
125
|
visit.BREAK = BREAK;
|
|
126
|
-
visit.SKIP =
|
|
126
|
+
visit.SKIP = SKIP3;
|
|
127
127
|
visit.REMOVE = REMOVE;
|
|
128
128
|
function visit_(key, node, visitor, path) {
|
|
129
129
|
const ctrl = callVisitor(key, node, visitor, path);
|
|
@@ -171,7 +171,7 @@ var require_visit = __commonJS({
|
|
|
171
171
|
await visitAsync_(null, node, visitor_, Object.freeze([]));
|
|
172
172
|
}
|
|
173
173
|
visitAsync.BREAK = BREAK;
|
|
174
|
-
visitAsync.SKIP =
|
|
174
|
+
visitAsync.SKIP = SKIP3;
|
|
175
175
|
visitAsync.REMOVE = REMOVE;
|
|
176
176
|
async function visitAsync_(key, node, visitor, path) {
|
|
177
177
|
const ctrl = await callVisitor(key, node, visitor, path);
|
|
@@ -995,13 +995,13 @@ var require_Collection = __commonJS({
|
|
|
995
995
|
var require_stringifyComment = __commonJS({
|
|
996
996
|
"../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/stringify/stringifyComment.js"(exports) {
|
|
997
997
|
"use strict";
|
|
998
|
-
var stringifyComment = (
|
|
998
|
+
var stringifyComment = (str2) => str2.replace(/^(?!$)(?: $)?/gm, "#");
|
|
999
999
|
function indentComment(comment, indent) {
|
|
1000
1000
|
if (/^\n+$/.test(comment))
|
|
1001
1001
|
return comment.substring(1);
|
|
1002
1002
|
return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
|
|
1003
1003
|
}
|
|
1004
|
-
var lineComment = (
|
|
1004
|
+
var lineComment = (str2, indent, comment) => str2.endsWith("\n") ? indentComment(comment, indent) : comment.includes("\n") ? "\n" + indentComment(comment, indent) : (str2.endsWith(" ") ? "" : " ") + comment;
|
|
1005
1005
|
exports.indentComment = indentComment;
|
|
1006
1006
|
exports.lineComment = lineComment;
|
|
1007
1007
|
exports.stringifyComment = stringifyComment;
|
|
@@ -1155,16 +1155,16 @@ var require_stringifyString = __commonJS({
|
|
|
1155
1155
|
lineWidth: ctx.options.lineWidth,
|
|
1156
1156
|
minContentWidth: ctx.options.minContentWidth
|
|
1157
1157
|
});
|
|
1158
|
-
var containsDocumentMarker = (
|
|
1159
|
-
function lineLengthOverLimit(
|
|
1158
|
+
var containsDocumentMarker = (str2) => /^(%|---|\.\.\.)/m.test(str2);
|
|
1159
|
+
function lineLengthOverLimit(str2, lineWidth, indentLength) {
|
|
1160
1160
|
if (!lineWidth || lineWidth < 0)
|
|
1161
1161
|
return false;
|
|
1162
1162
|
const limit = lineWidth - indentLength;
|
|
1163
|
-
const strLen =
|
|
1163
|
+
const strLen = str2.length;
|
|
1164
1164
|
if (strLen <= limit)
|
|
1165
1165
|
return false;
|
|
1166
1166
|
for (let i = 0, start = 0; i < strLen; ++i) {
|
|
1167
|
-
if (
|
|
1167
|
+
if (str2[i] === "\n") {
|
|
1168
1168
|
if (i - start > limit)
|
|
1169
1169
|
return true;
|
|
1170
1170
|
start = i + 1;
|
|
@@ -1181,11 +1181,11 @@ var require_stringifyString = __commonJS({
|
|
|
1181
1181
|
const { implicitKey } = ctx;
|
|
1182
1182
|
const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength;
|
|
1183
1183
|
const indent = ctx.indent || (containsDocumentMarker(value) ? " " : "");
|
|
1184
|
-
let
|
|
1184
|
+
let str2 = "";
|
|
1185
1185
|
let start = 0;
|
|
1186
1186
|
for (let i = 0, ch = json[i]; ch; ch = json[++i]) {
|
|
1187
1187
|
if (ch === " " && json[i + 1] === "\\" && json[i + 2] === "n") {
|
|
1188
|
-
|
|
1188
|
+
str2 += json.slice(start, i) + "\\ ";
|
|
1189
1189
|
i += 1;
|
|
1190
1190
|
start = i;
|
|
1191
1191
|
ch = "\\";
|
|
@@ -1194,38 +1194,38 @@ var require_stringifyString = __commonJS({
|
|
|
1194
1194
|
switch (json[i + 1]) {
|
|
1195
1195
|
case "u":
|
|
1196
1196
|
{
|
|
1197
|
-
|
|
1197
|
+
str2 += json.slice(start, i);
|
|
1198
1198
|
const code = json.substr(i + 2, 4);
|
|
1199
1199
|
switch (code) {
|
|
1200
1200
|
case "0000":
|
|
1201
|
-
|
|
1201
|
+
str2 += "\\0";
|
|
1202
1202
|
break;
|
|
1203
1203
|
case "0007":
|
|
1204
|
-
|
|
1204
|
+
str2 += "\\a";
|
|
1205
1205
|
break;
|
|
1206
1206
|
case "000b":
|
|
1207
|
-
|
|
1207
|
+
str2 += "\\v";
|
|
1208
1208
|
break;
|
|
1209
1209
|
case "001b":
|
|
1210
|
-
|
|
1210
|
+
str2 += "\\e";
|
|
1211
1211
|
break;
|
|
1212
1212
|
case "0085":
|
|
1213
|
-
|
|
1213
|
+
str2 += "\\N";
|
|
1214
1214
|
break;
|
|
1215
1215
|
case "00a0":
|
|
1216
|
-
|
|
1216
|
+
str2 += "\\_";
|
|
1217
1217
|
break;
|
|
1218
1218
|
case "2028":
|
|
1219
|
-
|
|
1219
|
+
str2 += "\\L";
|
|
1220
1220
|
break;
|
|
1221
1221
|
case "2029":
|
|
1222
|
-
|
|
1222
|
+
str2 += "\\P";
|
|
1223
1223
|
break;
|
|
1224
1224
|
default:
|
|
1225
1225
|
if (code.substr(0, 2) === "00")
|
|
1226
|
-
|
|
1226
|
+
str2 += "\\x" + code.substr(2);
|
|
1227
1227
|
else
|
|
1228
|
-
|
|
1228
|
+
str2 += json.substr(i, 6);
|
|
1229
1229
|
}
|
|
1230
1230
|
i += 5;
|
|
1231
1231
|
start = i + 1;
|
|
@@ -1235,14 +1235,14 @@ var require_stringifyString = __commonJS({
|
|
|
1235
1235
|
if (implicitKey || json[i + 2] === '"' || json.length < minMultiLineLength) {
|
|
1236
1236
|
i += 1;
|
|
1237
1237
|
} else {
|
|
1238
|
-
|
|
1238
|
+
str2 += json.slice(start, i) + "\n\n";
|
|
1239
1239
|
while (json[i + 2] === "\\" && json[i + 3] === "n" && json[i + 4] !== '"') {
|
|
1240
|
-
|
|
1240
|
+
str2 += "\n";
|
|
1241
1241
|
i += 2;
|
|
1242
1242
|
}
|
|
1243
|
-
|
|
1243
|
+
str2 += indent;
|
|
1244
1244
|
if (json[i + 2] === " ")
|
|
1245
|
-
|
|
1245
|
+
str2 += "\\";
|
|
1246
1246
|
i += 1;
|
|
1247
1247
|
start = i + 1;
|
|
1248
1248
|
}
|
|
@@ -1251,8 +1251,8 @@ var require_stringifyString = __commonJS({
|
|
|
1251
1251
|
i += 1;
|
|
1252
1252
|
}
|
|
1253
1253
|
}
|
|
1254
|
-
|
|
1255
|
-
return implicitKey ?
|
|
1254
|
+
str2 = start ? str2 + json.slice(start) : json;
|
|
1255
|
+
return implicitKey ? str2 : foldFlowLines.foldFlowLines(str2, indent, foldFlowLines.FOLD_QUOTED, getFoldOptions(ctx, false));
|
|
1256
1256
|
}
|
|
1257
1257
|
function singleQuotedString(value, ctx) {
|
|
1258
1258
|
if (ctx.options.singleQuote === false || ctx.implicitKey && value.includes("\n") || /[ \t]\n|\n[ \t]/.test(value))
|
|
@@ -1380,15 +1380,15 @@ ${indent}${start}${value}${end}`;
|
|
|
1380
1380
|
return quotedString(value, ctx);
|
|
1381
1381
|
}
|
|
1382
1382
|
}
|
|
1383
|
-
const
|
|
1383
|
+
const str2 = value.replace(/\n+/g, `$&
|
|
1384
1384
|
${indent}`);
|
|
1385
1385
|
if (actualString) {
|
|
1386
|
-
const test = (tag) => tag.default && tag.tag !== "tag:yaml.org,2002:str" && tag.test?.test(
|
|
1386
|
+
const test = (tag) => tag.default && tag.tag !== "tag:yaml.org,2002:str" && tag.test?.test(str2);
|
|
1387
1387
|
const { compat, tags } = ctx.doc.schema;
|
|
1388
1388
|
if (tags.some(test) || compat?.some(test))
|
|
1389
1389
|
return quotedString(value, ctx);
|
|
1390
1390
|
}
|
|
1391
|
-
return implicitKey ?
|
|
1391
|
+
return implicitKey ? str2 : foldFlowLines.foldFlowLines(str2, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx, false));
|
|
1392
1392
|
}
|
|
1393
1393
|
function stringifyString(item, ctx, onComment, onChompKeep) {
|
|
1394
1394
|
const { implicitKey, inFlow } = ctx;
|
|
@@ -1540,11 +1540,11 @@ var require_stringify = __commonJS({
|
|
|
1540
1540
|
const props = stringifyProps(node, tagObj, ctx);
|
|
1541
1541
|
if (props.length > 0)
|
|
1542
1542
|
ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
|
|
1543
|
-
const
|
|
1543
|
+
const str2 = typeof tagObj.stringify === "function" ? tagObj.stringify(node, ctx, onComment, onChompKeep) : identity.isScalar(node) ? stringifyString.stringifyString(node, ctx, onComment, onChompKeep) : node.toString(ctx, onComment, onChompKeep);
|
|
1544
1544
|
if (!props)
|
|
1545
|
-
return
|
|
1546
|
-
return identity.isScalar(node) ||
|
|
1547
|
-
${ctx.indent}${
|
|
1545
|
+
return str2;
|
|
1546
|
+
return identity.isScalar(node) || str2[0] === "{" || str2[0] === "[" ? `${props} ${str2}` : `${props}
|
|
1547
|
+
${ctx.indent}${str2}`;
|
|
1548
1548
|
}
|
|
1549
1549
|
exports.createStringifyContext = createStringifyContext;
|
|
1550
1550
|
exports.stringify = stringify;
|
|
@@ -1579,8 +1579,8 @@ var require_stringifyPair = __commonJS({
|
|
|
1579
1579
|
});
|
|
1580
1580
|
let keyCommentDone = false;
|
|
1581
1581
|
let chompKeep = false;
|
|
1582
|
-
let
|
|
1583
|
-
if (!explicitKey && !ctx.inFlow &&
|
|
1582
|
+
let str2 = stringify.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
|
|
1583
|
+
if (!explicitKey && !ctx.inFlow && str2.length > 1024) {
|
|
1584
1584
|
if (simpleKeys)
|
|
1585
1585
|
throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
|
|
1586
1586
|
explicitKey = true;
|
|
@@ -1589,27 +1589,27 @@ var require_stringifyPair = __commonJS({
|
|
|
1589
1589
|
if (allNullValues || value == null) {
|
|
1590
1590
|
if (keyCommentDone && onComment)
|
|
1591
1591
|
onComment();
|
|
1592
|
-
return
|
|
1592
|
+
return str2 === "" ? "?" : explicitKey ? `? ${str2}` : str2;
|
|
1593
1593
|
}
|
|
1594
1594
|
} else if (allNullValues && !simpleKeys || value == null && explicitKey) {
|
|
1595
|
-
|
|
1595
|
+
str2 = `? ${str2}`;
|
|
1596
1596
|
if (keyComment && !keyCommentDone) {
|
|
1597
|
-
|
|
1597
|
+
str2 += stringifyComment.lineComment(str2, ctx.indent, commentString(keyComment));
|
|
1598
1598
|
} else if (chompKeep && onChompKeep)
|
|
1599
1599
|
onChompKeep();
|
|
1600
|
-
return
|
|
1600
|
+
return str2;
|
|
1601
1601
|
}
|
|
1602
1602
|
if (keyCommentDone)
|
|
1603
1603
|
keyComment = null;
|
|
1604
1604
|
if (explicitKey) {
|
|
1605
1605
|
if (keyComment)
|
|
1606
|
-
|
|
1607
|
-
|
|
1606
|
+
str2 += stringifyComment.lineComment(str2, ctx.indent, commentString(keyComment));
|
|
1607
|
+
str2 = `? ${str2}
|
|
1608
1608
|
${indent}:`;
|
|
1609
1609
|
} else {
|
|
1610
|
-
|
|
1610
|
+
str2 = `${str2}:`;
|
|
1611
1611
|
if (keyComment)
|
|
1612
|
-
|
|
1612
|
+
str2 += stringifyComment.lineComment(str2, ctx.indent, commentString(keyComment));
|
|
1613
1613
|
}
|
|
1614
1614
|
let vsb, vcb, valueComment;
|
|
1615
1615
|
if (identity.isNode(value)) {
|
|
@@ -1625,7 +1625,7 @@ ${indent}:`;
|
|
|
1625
1625
|
}
|
|
1626
1626
|
ctx.implicitKey = false;
|
|
1627
1627
|
if (!explicitKey && !keyComment && identity.isScalar(value))
|
|
1628
|
-
ctx.indentAtStart =
|
|
1628
|
+
ctx.indentAtStart = str2.length + 1;
|
|
1629
1629
|
chompKeep = false;
|
|
1630
1630
|
if (!indentSeq && indentStep.length >= 2 && !ctx.inFlow && !explicitKey && identity.isSeq(value) && !value.flow && !value.tag && !value.anchor) {
|
|
1631
1631
|
ctx.indent = ctx.indent.substring(2);
|
|
@@ -1669,16 +1669,16 @@ ${ctx.indent}`;
|
|
|
1669
1669
|
} else if (valueStr === "" || valueStr[0] === "\n") {
|
|
1670
1670
|
ws = "";
|
|
1671
1671
|
}
|
|
1672
|
-
|
|
1672
|
+
str2 += ws + valueStr;
|
|
1673
1673
|
if (ctx.inFlow) {
|
|
1674
1674
|
if (valueCommentDone && onComment)
|
|
1675
1675
|
onComment();
|
|
1676
1676
|
} else if (valueComment && !valueCommentDone) {
|
|
1677
|
-
|
|
1677
|
+
str2 += stringifyComment.lineComment(str2, ctx.indent, commentString(valueComment));
|
|
1678
1678
|
} else if (chompKeep && onChompKeep) {
|
|
1679
1679
|
onChompKeep();
|
|
1680
1680
|
}
|
|
1681
|
-
return
|
|
1681
|
+
return str2;
|
|
1682
1682
|
}
|
|
1683
1683
|
exports.stringifyPair = stringifyPair;
|
|
1684
1684
|
}
|
|
@@ -1905,31 +1905,31 @@ var require_stringifyCollection = __commonJS({
|
|
|
1905
1905
|
}
|
|
1906
1906
|
}
|
|
1907
1907
|
chompKeep = false;
|
|
1908
|
-
let
|
|
1908
|
+
let str3 = stringify.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
|
|
1909
1909
|
if (comment2)
|
|
1910
|
-
|
|
1910
|
+
str3 += stringifyComment.lineComment(str3, itemIndent, commentString(comment2));
|
|
1911
1911
|
if (chompKeep && comment2)
|
|
1912
1912
|
chompKeep = false;
|
|
1913
|
-
lines.push(blockItemPrefix +
|
|
1913
|
+
lines.push(blockItemPrefix + str3);
|
|
1914
1914
|
}
|
|
1915
|
-
let
|
|
1915
|
+
let str2;
|
|
1916
1916
|
if (lines.length === 0) {
|
|
1917
|
-
|
|
1917
|
+
str2 = flowChars.start + flowChars.end;
|
|
1918
1918
|
} else {
|
|
1919
|
-
|
|
1919
|
+
str2 = lines[0];
|
|
1920
1920
|
for (let i = 1; i < lines.length; ++i) {
|
|
1921
1921
|
const line = lines[i];
|
|
1922
|
-
|
|
1922
|
+
str2 += line ? `
|
|
1923
1923
|
${indent}${line}` : "\n";
|
|
1924
1924
|
}
|
|
1925
1925
|
}
|
|
1926
1926
|
if (comment) {
|
|
1927
|
-
|
|
1927
|
+
str2 += "\n" + stringifyComment.indentComment(commentString(comment), indent);
|
|
1928
1928
|
if (onComment)
|
|
1929
1929
|
onComment();
|
|
1930
1930
|
} else if (chompKeep && onChompKeep)
|
|
1931
1931
|
onChompKeep();
|
|
1932
|
-
return
|
|
1932
|
+
return str2;
|
|
1933
1933
|
}
|
|
1934
1934
|
function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
|
|
1935
1935
|
const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
|
|
@@ -1972,21 +1972,21 @@ ${indent}${line}` : "\n";
|
|
|
1972
1972
|
}
|
|
1973
1973
|
if (comment)
|
|
1974
1974
|
reqNewline = true;
|
|
1975
|
-
let
|
|
1976
|
-
reqNewline || (reqNewline = lines.length > linesAtValue ||
|
|
1975
|
+
let str2 = stringify.stringify(item, itemCtx, () => comment = null);
|
|
1976
|
+
reqNewline || (reqNewline = lines.length > linesAtValue || str2.includes("\n"));
|
|
1977
1977
|
if (i < items.length - 1) {
|
|
1978
|
-
|
|
1978
|
+
str2 += ",";
|
|
1979
1979
|
} else if (ctx.options.trailingComma) {
|
|
1980
1980
|
if (ctx.options.lineWidth > 0) {
|
|
1981
|
-
reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (
|
|
1981
|
+
reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str2.length + 2) > ctx.options.lineWidth);
|
|
1982
1982
|
}
|
|
1983
1983
|
if (reqNewline) {
|
|
1984
|
-
|
|
1984
|
+
str2 += ",";
|
|
1985
1985
|
}
|
|
1986
1986
|
}
|
|
1987
1987
|
if (comment)
|
|
1988
|
-
|
|
1989
|
-
lines.push(
|
|
1988
|
+
str2 += stringifyComment.lineComment(str2, itemIndent, commentString(comment));
|
|
1989
|
+
lines.push(str2);
|
|
1990
1990
|
linesAtValue = lines.length;
|
|
1991
1991
|
}
|
|
1992
1992
|
const { start, end } = flowChars;
|
|
@@ -1998,11 +1998,11 @@ ${indent}${line}` : "\n";
|
|
|
1998
1998
|
reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
|
|
1999
1999
|
}
|
|
2000
2000
|
if (reqNewline) {
|
|
2001
|
-
let
|
|
2001
|
+
let str2 = start;
|
|
2002
2002
|
for (const line of lines)
|
|
2003
|
-
|
|
2003
|
+
str2 += line ? `
|
|
2004
2004
|
${indentStep}${indent}${line}` : "\n";
|
|
2005
|
-
return `${
|
|
2005
|
+
return `${str2}
|
|
2006
2006
|
${indent}${end}`;
|
|
2007
2007
|
} else {
|
|
2008
2008
|
return `${start}${fcPadding}${lines.join(" ")}${fcPadding}${end}`;
|
|
@@ -2334,7 +2334,7 @@ var require_string = __commonJS({
|
|
|
2334
2334
|
identify: (value) => typeof value === "string",
|
|
2335
2335
|
default: true,
|
|
2336
2336
|
tag: "tag:yaml.org,2002:str",
|
|
2337
|
-
resolve: (
|
|
2337
|
+
resolve: (str2) => str2,
|
|
2338
2338
|
stringify(item, ctx, onComment, onChompKeep) {
|
|
2339
2339
|
ctx = Object.assign({ actualString: true }, ctx);
|
|
2340
2340
|
return stringifyString.stringifyString(item, ctx, onComment, onChompKeep);
|
|
@@ -2372,7 +2372,7 @@ var require_bool = __commonJS({
|
|
|
2372
2372
|
default: true,
|
|
2373
2373
|
tag: "tag:yaml.org,2002:bool",
|
|
2374
2374
|
test: /^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,
|
|
2375
|
-
resolve: (
|
|
2375
|
+
resolve: (str2) => new Scalar.Scalar(str2[0] === "t" || str2[0] === "T"),
|
|
2376
2376
|
stringify({ source, value }, ctx) {
|
|
2377
2377
|
if (source && boolTag.test.test(source)) {
|
|
2378
2378
|
const sv = source[0] === "t" || source[0] === "T";
|
|
@@ -2424,7 +2424,7 @@ var require_float = __commonJS({
|
|
|
2424
2424
|
default: true,
|
|
2425
2425
|
tag: "tag:yaml.org,2002:float",
|
|
2426
2426
|
test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
|
|
2427
|
-
resolve: (
|
|
2427
|
+
resolve: (str2) => str2.slice(-3).toLowerCase() === "nan" ? NaN : str2[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
|
|
2428
2428
|
stringify: stringifyNumber.stringifyNumber
|
|
2429
2429
|
};
|
|
2430
2430
|
var floatExp = {
|
|
@@ -2433,7 +2433,7 @@ var require_float = __commonJS({
|
|
|
2433
2433
|
tag: "tag:yaml.org,2002:float",
|
|
2434
2434
|
format: "EXP",
|
|
2435
2435
|
test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
|
|
2436
|
-
resolve: (
|
|
2436
|
+
resolve: (str2) => parseFloat(str2),
|
|
2437
2437
|
stringify(node) {
|
|
2438
2438
|
const num = Number(node.value);
|
|
2439
2439
|
return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node);
|
|
@@ -2444,11 +2444,11 @@ var require_float = __commonJS({
|
|
|
2444
2444
|
default: true,
|
|
2445
2445
|
tag: "tag:yaml.org,2002:float",
|
|
2446
2446
|
test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,
|
|
2447
|
-
resolve(
|
|
2448
|
-
const node = new Scalar.Scalar(parseFloat(
|
|
2449
|
-
const dot =
|
|
2450
|
-
if (dot !== -1 &&
|
|
2451
|
-
node.minFractionDigits =
|
|
2447
|
+
resolve(str2) {
|
|
2448
|
+
const node = new Scalar.Scalar(parseFloat(str2));
|
|
2449
|
+
const dot = str2.indexOf(".");
|
|
2450
|
+
if (dot !== -1 && str2[str2.length - 1] === "0")
|
|
2451
|
+
node.minFractionDigits = str2.length - dot - 1;
|
|
2452
2452
|
return node;
|
|
2453
2453
|
},
|
|
2454
2454
|
stringify: stringifyNumber.stringifyNumber
|
|
@@ -2465,7 +2465,7 @@ var require_int = __commonJS({
|
|
|
2465
2465
|
"use strict";
|
|
2466
2466
|
var stringifyNumber = require_stringifyNumber();
|
|
2467
2467
|
var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
|
|
2468
|
-
var intResolve = (
|
|
2468
|
+
var intResolve = (str2, offset, radix, { intAsBigInt }) => intAsBigInt ? BigInt(str2) : parseInt(str2.substring(offset), radix);
|
|
2469
2469
|
function intStringify(node, radix, prefix) {
|
|
2470
2470
|
const { value } = node;
|
|
2471
2471
|
if (intIdentify(value) && value >= 0)
|
|
@@ -2478,7 +2478,7 @@ var require_int = __commonJS({
|
|
|
2478
2478
|
tag: "tag:yaml.org,2002:int",
|
|
2479
2479
|
format: "OCT",
|
|
2480
2480
|
test: /^0o[0-7]+$/,
|
|
2481
|
-
resolve: (
|
|
2481
|
+
resolve: (str2, _onError, opt) => intResolve(str2, 2, 8, opt),
|
|
2482
2482
|
stringify: (node) => intStringify(node, 8, "0o")
|
|
2483
2483
|
};
|
|
2484
2484
|
var int = {
|
|
@@ -2486,7 +2486,7 @@ var require_int = __commonJS({
|
|
|
2486
2486
|
default: true,
|
|
2487
2487
|
tag: "tag:yaml.org,2002:int",
|
|
2488
2488
|
test: /^[-+]?[0-9]+$/,
|
|
2489
|
-
resolve: (
|
|
2489
|
+
resolve: (str2, _onError, opt) => intResolve(str2, 0, 10, opt),
|
|
2490
2490
|
stringify: stringifyNumber.stringifyNumber
|
|
2491
2491
|
};
|
|
2492
2492
|
var intHex = {
|
|
@@ -2495,7 +2495,7 @@ var require_int = __commonJS({
|
|
|
2495
2495
|
tag: "tag:yaml.org,2002:int",
|
|
2496
2496
|
format: "HEX",
|
|
2497
2497
|
test: /^0x[0-9a-fA-F]+$/,
|
|
2498
|
-
resolve: (
|
|
2498
|
+
resolve: (str2, _onError, opt) => intResolve(str2, 2, 16, opt),
|
|
2499
2499
|
stringify: (node) => intStringify(node, 16, "0x")
|
|
2500
2500
|
};
|
|
2501
2501
|
exports.int = int;
|
|
@@ -2548,7 +2548,7 @@ var require_schema2 = __commonJS({
|
|
|
2548
2548
|
identify: (value) => typeof value === "string",
|
|
2549
2549
|
default: true,
|
|
2550
2550
|
tag: "tag:yaml.org,2002:str",
|
|
2551
|
-
resolve: (
|
|
2551
|
+
resolve: (str2) => str2,
|
|
2552
2552
|
stringify: stringifyJSON
|
|
2553
2553
|
},
|
|
2554
2554
|
{
|
|
@@ -2565,7 +2565,7 @@ var require_schema2 = __commonJS({
|
|
|
2565
2565
|
default: true,
|
|
2566
2566
|
tag: "tag:yaml.org,2002:bool",
|
|
2567
2567
|
test: /^true$|^false$/,
|
|
2568
|
-
resolve: (
|
|
2568
|
+
resolve: (str2) => str2 === "true",
|
|
2569
2569
|
stringify: stringifyJSON
|
|
2570
2570
|
},
|
|
2571
2571
|
{
|
|
@@ -2573,7 +2573,7 @@ var require_schema2 = __commonJS({
|
|
|
2573
2573
|
default: true,
|
|
2574
2574
|
tag: "tag:yaml.org,2002:int",
|
|
2575
2575
|
test: /^-?(?:0|[1-9][0-9]*)$/,
|
|
2576
|
-
resolve: (
|
|
2576
|
+
resolve: (str2, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str2) : parseInt(str2, 10),
|
|
2577
2577
|
stringify: ({ value }) => intIdentify(value) ? value.toString() : JSON.stringify(value)
|
|
2578
2578
|
},
|
|
2579
2579
|
{
|
|
@@ -2581,7 +2581,7 @@ var require_schema2 = __commonJS({
|
|
|
2581
2581
|
default: true,
|
|
2582
2582
|
tag: "tag:yaml.org,2002:float",
|
|
2583
2583
|
test: /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,
|
|
2584
|
-
resolve: (
|
|
2584
|
+
resolve: (str2) => parseFloat(str2),
|
|
2585
2585
|
stringify: stringifyJSON
|
|
2586
2586
|
}
|
|
2587
2587
|
];
|
|
@@ -2589,9 +2589,9 @@ var require_schema2 = __commonJS({
|
|
|
2589
2589
|
default: true,
|
|
2590
2590
|
tag: "",
|
|
2591
2591
|
test: /^/,
|
|
2592
|
-
resolve(
|
|
2593
|
-
onError(`Unresolved plain scalar ${JSON.stringify(
|
|
2594
|
-
return
|
|
2592
|
+
resolve(str2, onError) {
|
|
2593
|
+
onError(`Unresolved plain scalar ${JSON.stringify(str2)}`);
|
|
2594
|
+
return str2;
|
|
2595
2595
|
}
|
|
2596
2596
|
};
|
|
2597
2597
|
var schema = [map.map, seq.seq].concat(jsonScalars, jsonError);
|
|
@@ -2623,10 +2623,10 @@ var require_binary = __commonJS({
|
|
|
2623
2623
|
if (typeof node_buffer.Buffer === "function") {
|
|
2624
2624
|
return node_buffer.Buffer.from(src, "base64");
|
|
2625
2625
|
} else if (typeof atob === "function") {
|
|
2626
|
-
const
|
|
2627
|
-
const buffer = new Uint8Array(
|
|
2628
|
-
for (let i = 0; i <
|
|
2629
|
-
buffer[i] =
|
|
2626
|
+
const str2 = atob(src.replace(/[\n\r]/g, ""));
|
|
2627
|
+
const buffer = new Uint8Array(str2.length);
|
|
2628
|
+
for (let i = 0; i < str2.length; ++i)
|
|
2629
|
+
buffer[i] = str2.charCodeAt(i);
|
|
2630
2630
|
return buffer;
|
|
2631
2631
|
} else {
|
|
2632
2632
|
onError("This environment does not support reading binary tags; either Buffer or atob is required");
|
|
@@ -2637,28 +2637,28 @@ var require_binary = __commonJS({
|
|
|
2637
2637
|
if (!value)
|
|
2638
2638
|
return "";
|
|
2639
2639
|
const buf = value;
|
|
2640
|
-
let
|
|
2640
|
+
let str2;
|
|
2641
2641
|
if (typeof node_buffer.Buffer === "function") {
|
|
2642
|
-
|
|
2642
|
+
str2 = buf instanceof node_buffer.Buffer ? buf.toString("base64") : node_buffer.Buffer.from(buf.buffer).toString("base64");
|
|
2643
2643
|
} else if (typeof btoa === "function") {
|
|
2644
2644
|
let s = "";
|
|
2645
2645
|
for (let i = 0; i < buf.length; ++i)
|
|
2646
2646
|
s += String.fromCharCode(buf[i]);
|
|
2647
|
-
|
|
2647
|
+
str2 = btoa(s);
|
|
2648
2648
|
} else {
|
|
2649
2649
|
throw new Error("This environment does not support writing binary tags; either Buffer or btoa is required");
|
|
2650
2650
|
}
|
|
2651
2651
|
type ?? (type = Scalar.Scalar.BLOCK_LITERAL);
|
|
2652
2652
|
if (type !== Scalar.Scalar.QUOTE_DOUBLE) {
|
|
2653
2653
|
const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth);
|
|
2654
|
-
const n = Math.ceil(
|
|
2654
|
+
const n = Math.ceil(str2.length / lineWidth);
|
|
2655
2655
|
const lines = new Array(n);
|
|
2656
2656
|
for (let i = 0, o = 0; i < n; ++i, o += lineWidth) {
|
|
2657
|
-
lines[i] =
|
|
2657
|
+
lines[i] = str2.substr(o, lineWidth);
|
|
2658
2658
|
}
|
|
2659
|
-
|
|
2659
|
+
str2 = lines.join(type === Scalar.Scalar.BLOCK_LITERAL ? "\n" : " ");
|
|
2660
2660
|
}
|
|
2661
|
-
return stringifyString.stringifyString({ comment, type, value:
|
|
2661
|
+
return stringifyString.stringifyString({ comment, type, value: str2 }, ctx, onComment, onChompKeep);
|
|
2662
2662
|
}
|
|
2663
2663
|
};
|
|
2664
2664
|
exports.binary = binary;
|
|
@@ -2864,7 +2864,7 @@ var require_float2 = __commonJS({
|
|
|
2864
2864
|
default: true,
|
|
2865
2865
|
tag: "tag:yaml.org,2002:float",
|
|
2866
2866
|
test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
|
|
2867
|
-
resolve: (
|
|
2867
|
+
resolve: (str2) => str2.slice(-3).toLowerCase() === "nan" ? NaN : str2[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
|
|
2868
2868
|
stringify: stringifyNumber.stringifyNumber
|
|
2869
2869
|
};
|
|
2870
2870
|
var floatExp = {
|
|
@@ -2873,7 +2873,7 @@ var require_float2 = __commonJS({
|
|
|
2873
2873
|
tag: "tag:yaml.org,2002:float",
|
|
2874
2874
|
format: "EXP",
|
|
2875
2875
|
test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
|
|
2876
|
-
resolve: (
|
|
2876
|
+
resolve: (str2) => parseFloat(str2.replace(/_/g, "")),
|
|
2877
2877
|
stringify(node) {
|
|
2878
2878
|
const num = Number(node.value);
|
|
2879
2879
|
return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node);
|
|
@@ -2884,11 +2884,11 @@ var require_float2 = __commonJS({
|
|
|
2884
2884
|
default: true,
|
|
2885
2885
|
tag: "tag:yaml.org,2002:float",
|
|
2886
2886
|
test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,
|
|
2887
|
-
resolve(
|
|
2888
|
-
const node = new Scalar.Scalar(parseFloat(
|
|
2889
|
-
const dot =
|
|
2887
|
+
resolve(str2) {
|
|
2888
|
+
const node = new Scalar.Scalar(parseFloat(str2.replace(/_/g, "")));
|
|
2889
|
+
const dot = str2.indexOf(".");
|
|
2890
2890
|
if (dot !== -1) {
|
|
2891
|
-
const f =
|
|
2891
|
+
const f = str2.substring(dot + 1).replace(/_/g, "");
|
|
2892
2892
|
if (f[f.length - 1] === "0")
|
|
2893
2893
|
node.minFractionDigits = f.length;
|
|
2894
2894
|
}
|
|
@@ -2908,34 +2908,34 @@ var require_int2 = __commonJS({
|
|
|
2908
2908
|
"use strict";
|
|
2909
2909
|
var stringifyNumber = require_stringifyNumber();
|
|
2910
2910
|
var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
|
|
2911
|
-
function intResolve(
|
|
2912
|
-
const sign =
|
|
2911
|
+
function intResolve(str2, offset, radix, { intAsBigInt }) {
|
|
2912
|
+
const sign = str2[0];
|
|
2913
2913
|
if (sign === "-" || sign === "+")
|
|
2914
2914
|
offset += 1;
|
|
2915
|
-
|
|
2915
|
+
str2 = str2.substring(offset).replace(/_/g, "");
|
|
2916
2916
|
if (intAsBigInt) {
|
|
2917
2917
|
switch (radix) {
|
|
2918
2918
|
case 2:
|
|
2919
|
-
|
|
2919
|
+
str2 = `0b${str2}`;
|
|
2920
2920
|
break;
|
|
2921
2921
|
case 8:
|
|
2922
|
-
|
|
2922
|
+
str2 = `0o${str2}`;
|
|
2923
2923
|
break;
|
|
2924
2924
|
case 16:
|
|
2925
|
-
|
|
2925
|
+
str2 = `0x${str2}`;
|
|
2926
2926
|
break;
|
|
2927
2927
|
}
|
|
2928
|
-
const n2 = BigInt(
|
|
2928
|
+
const n2 = BigInt(str2);
|
|
2929
2929
|
return sign === "-" ? BigInt(-1) * n2 : n2;
|
|
2930
2930
|
}
|
|
2931
|
-
const n = parseInt(
|
|
2931
|
+
const n = parseInt(str2, radix);
|
|
2932
2932
|
return sign === "-" ? -1 * n : n;
|
|
2933
2933
|
}
|
|
2934
2934
|
function intStringify(node, radix, prefix) {
|
|
2935
2935
|
const { value } = node;
|
|
2936
2936
|
if (intIdentify(value)) {
|
|
2937
|
-
const
|
|
2938
|
-
return value < 0 ? "-" + prefix +
|
|
2937
|
+
const str2 = value.toString(radix);
|
|
2938
|
+
return value < 0 ? "-" + prefix + str2.substr(1) : prefix + str2;
|
|
2939
2939
|
}
|
|
2940
2940
|
return stringifyNumber.stringifyNumber(node);
|
|
2941
2941
|
}
|
|
@@ -2945,7 +2945,7 @@ var require_int2 = __commonJS({
|
|
|
2945
2945
|
tag: "tag:yaml.org,2002:int",
|
|
2946
2946
|
format: "BIN",
|
|
2947
2947
|
test: /^[-+]?0b[0-1_]+$/,
|
|
2948
|
-
resolve: (
|
|
2948
|
+
resolve: (str2, _onError, opt) => intResolve(str2, 2, 2, opt),
|
|
2949
2949
|
stringify: (node) => intStringify(node, 2, "0b")
|
|
2950
2950
|
};
|
|
2951
2951
|
var intOct = {
|
|
@@ -2954,7 +2954,7 @@ var require_int2 = __commonJS({
|
|
|
2954
2954
|
tag: "tag:yaml.org,2002:int",
|
|
2955
2955
|
format: "OCT",
|
|
2956
2956
|
test: /^[-+]?0[0-7_]+$/,
|
|
2957
|
-
resolve: (
|
|
2957
|
+
resolve: (str2, _onError, opt) => intResolve(str2, 1, 8, opt),
|
|
2958
2958
|
stringify: (node) => intStringify(node, 8, "0")
|
|
2959
2959
|
};
|
|
2960
2960
|
var int = {
|
|
@@ -2962,7 +2962,7 @@ var require_int2 = __commonJS({
|
|
|
2962
2962
|
default: true,
|
|
2963
2963
|
tag: "tag:yaml.org,2002:int",
|
|
2964
2964
|
test: /^[-+]?[0-9][0-9_]*$/,
|
|
2965
|
-
resolve: (
|
|
2965
|
+
resolve: (str2, _onError, opt) => intResolve(str2, 0, 10, opt),
|
|
2966
2966
|
stringify: stringifyNumber.stringifyNumber
|
|
2967
2967
|
};
|
|
2968
2968
|
var intHex = {
|
|
@@ -2971,7 +2971,7 @@ var require_int2 = __commonJS({
|
|
|
2971
2971
|
tag: "tag:yaml.org,2002:int",
|
|
2972
2972
|
format: "HEX",
|
|
2973
2973
|
test: /^[-+]?0x[0-9a-fA-F_]+$/,
|
|
2974
|
-
resolve: (
|
|
2974
|
+
resolve: (str2, _onError, opt) => intResolve(str2, 2, 16, opt),
|
|
2975
2975
|
stringify: (node) => intStringify(node, 16, "0x")
|
|
2976
2976
|
};
|
|
2977
2977
|
exports.int = int;
|
|
@@ -3075,9 +3075,9 @@ var require_timestamp = __commonJS({
|
|
|
3075
3075
|
"../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js"(exports) {
|
|
3076
3076
|
"use strict";
|
|
3077
3077
|
var stringifyNumber = require_stringifyNumber();
|
|
3078
|
-
function parseSexagesimal(
|
|
3079
|
-
const sign =
|
|
3080
|
-
const parts = sign === "-" || sign === "+" ?
|
|
3078
|
+
function parseSexagesimal(str2, asBigInt) {
|
|
3079
|
+
const sign = str2[0];
|
|
3080
|
+
const parts = sign === "-" || sign === "+" ? str2.substring(1) : str2;
|
|
3081
3081
|
const num = (n) => asBigInt ? BigInt(n) : Number(n);
|
|
3082
3082
|
const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num(60) + num(p), num(0));
|
|
3083
3083
|
return sign === "-" ? num(-1) * res : res;
|
|
@@ -3114,7 +3114,7 @@ var require_timestamp = __commonJS({
|
|
|
3114
3114
|
tag: "tag:yaml.org,2002:int",
|
|
3115
3115
|
format: "TIME",
|
|
3116
3116
|
test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,
|
|
3117
|
-
resolve: (
|
|
3117
|
+
resolve: (str2, _onError, { intAsBigInt }) => parseSexagesimal(str2, intAsBigInt),
|
|
3118
3118
|
stringify: stringifySexagesimal
|
|
3119
3119
|
};
|
|
3120
3120
|
var floatTime = {
|
|
@@ -3123,7 +3123,7 @@ var require_timestamp = __commonJS({
|
|
|
3123
3123
|
tag: "tag:yaml.org,2002:float",
|
|
3124
3124
|
format: "TIME",
|
|
3125
3125
|
test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,
|
|
3126
|
-
resolve: (
|
|
3126
|
+
resolve: (str2) => parseSexagesimal(str2, false),
|
|
3127
3127
|
stringify: stringifySexagesimal
|
|
3128
3128
|
};
|
|
3129
3129
|
var timestamp = {
|
|
@@ -3134,8 +3134,8 @@ var require_timestamp = __commonJS({
|
|
|
3134
3134
|
// may be omitted altogether, resulting in a date format. In such a case, the time part is
|
|
3135
3135
|
// assumed to be 00:00:00Z (start of day, UTC).
|
|
3136
3136
|
test: RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),
|
|
3137
|
-
resolve(
|
|
3138
|
-
const match =
|
|
3137
|
+
resolve(str2) {
|
|
3138
|
+
const match = str2.match(timestamp.test);
|
|
3139
3139
|
if (!match)
|
|
3140
3140
|
throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
|
|
3141
3141
|
const [, year, month, day, hour, minute, second] = match.map(Number);
|
|
@@ -5576,7 +5576,7 @@ var require_cst_visit = __commonJS({
|
|
|
5576
5576
|
"../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/parse/cst-visit.js"(exports) {
|
|
5577
5577
|
"use strict";
|
|
5578
5578
|
var BREAK = /* @__PURE__ */ Symbol("break visit");
|
|
5579
|
-
var
|
|
5579
|
+
var SKIP3 = /* @__PURE__ */ Symbol("skip children");
|
|
5580
5580
|
var REMOVE = /* @__PURE__ */ Symbol("remove item");
|
|
5581
5581
|
function visit(cst, visitor) {
|
|
5582
5582
|
if ("type" in cst && cst.type === "document")
|
|
@@ -5584,7 +5584,7 @@ var require_cst_visit = __commonJS({
|
|
|
5584
5584
|
_visit(Object.freeze([]), cst, visitor);
|
|
5585
5585
|
}
|
|
5586
5586
|
visit.BREAK = BREAK;
|
|
5587
|
-
visit.SKIP =
|
|
5587
|
+
visit.SKIP = SKIP3;
|
|
5588
5588
|
visit.REMOVE = REMOVE;
|
|
5589
5589
|
visit.itemAtPath = (cst, path) => {
|
|
5590
5590
|
let item = cst;
|
|
@@ -7378,37 +7378,317 @@ var require_dist = __commonJS({
|
|
|
7378
7378
|
}
|
|
7379
7379
|
});
|
|
7380
7380
|
|
|
7381
|
+
// ../policy/dist/discover.js
|
|
7382
|
+
function isAgentConfigPath(path) {
|
|
7383
|
+
return PROJECT_FILES.some((f) => f.re.test(path));
|
|
7384
|
+
}
|
|
7385
|
+
function agentFor(path) {
|
|
7386
|
+
const p = PROJECT_FILES.find((f) => f.re.test(path));
|
|
7387
|
+
if (p)
|
|
7388
|
+
return p.agent;
|
|
7389
|
+
const u = USER_CONFIG_FILES.find((f) => path.endsWith(f.path));
|
|
7390
|
+
return u?.agent ?? "any";
|
|
7391
|
+
}
|
|
7392
|
+
function parseJsonc(text) {
|
|
7393
|
+
try {
|
|
7394
|
+
return JSON.parse(text);
|
|
7395
|
+
} catch {
|
|
7396
|
+
}
|
|
7397
|
+
const noComments = text.replace(/("(?:\\.|[^"\\])*")|\/\/[^\n]*|\/\*[\s\S]*?\*\//g, (_m, s1) => s1 ?? "");
|
|
7398
|
+
try {
|
|
7399
|
+
return JSON.parse(noComments.replace(/,(\s*[}\]])/g, "$1"));
|
|
7400
|
+
} catch {
|
|
7401
|
+
return null;
|
|
7402
|
+
}
|
|
7403
|
+
}
|
|
7404
|
+
function stdioPackage(command, args) {
|
|
7405
|
+
const bin = command.split(/[\\/]/).pop()?.replace(/\.(cmd|exe)$/i, "") ?? "";
|
|
7406
|
+
const strip = (s) => s.replace(/(.)@[^@/]+$/, "$1");
|
|
7407
|
+
if (/^(npx|bunx|pnpx)$/.test(bin) || bin === "pnpm" && args[0] === "dlx") {
|
|
7408
|
+
const pkg = args.find((a) => !a.startsWith("-") && a !== "dlx" && a !== "exec");
|
|
7409
|
+
return pkg && /^(@[\w.-]+\/)?[\w.-]+(@[\w.^~<>=*-]+)?$/.test(pkg) ? { registry: "npm", name: strip(pkg) } : void 0;
|
|
7410
|
+
}
|
|
7411
|
+
if (/^(uvx|pipx)$/.test(bin) || bin === "uv" && args[0] === "tool") {
|
|
7412
|
+
const pkg = args.find((a) => !a.startsWith("-") && !["run", "tool"].includes(a));
|
|
7413
|
+
return pkg && /^[\w.\-[\]]+(==[\w.]+)?$/.test(pkg) ? { registry: "pypi", name: pkg.toLowerCase().replace(/\[.*\]$/, "").replace(/==.*$/, "").replace(/_/g, "-") } : void 0;
|
|
7414
|
+
}
|
|
7415
|
+
if (bin === "docker") {
|
|
7416
|
+
const img = args.find((a, i) => i > 0 && !a.startsWith("-") && /^([\w.-]+\.[\w]+\/)?[\w.-]+\/[\w.-]+(:[\w.-]+)?$/.test(a) && !/^-/.test(args[i - 1] ?? ""));
|
|
7417
|
+
if (!img)
|
|
7418
|
+
return void 0;
|
|
7419
|
+
return { registry: "docker", name: img.replace(/:[\w.-]+$/, "").replace(/^(docker\.io|ghcr\.io)\//, "") };
|
|
7420
|
+
}
|
|
7421
|
+
return void 0;
|
|
7422
|
+
}
|
|
7423
|
+
function hostOf(u) {
|
|
7424
|
+
if (!u)
|
|
7425
|
+
return void 0;
|
|
7426
|
+
try {
|
|
7427
|
+
return new URL(u).host.toLowerCase();
|
|
7428
|
+
} catch {
|
|
7429
|
+
return void 0;
|
|
7430
|
+
}
|
|
7431
|
+
}
|
|
7432
|
+
function serverComponents(servers, path, scope, agent) {
|
|
7433
|
+
if (!isObj(servers))
|
|
7434
|
+
return [];
|
|
7435
|
+
const out = [];
|
|
7436
|
+
for (const [name, raw] of Object.entries(servers).slice(0, 200)) {
|
|
7437
|
+
if (!isObj(raw))
|
|
7438
|
+
continue;
|
|
7439
|
+
const url = str(raw.url) ?? str(raw.serverUrl) ?? str(raw.httpUrl);
|
|
7440
|
+
const command = str(raw.command);
|
|
7441
|
+
const args = Array.isArray(raw.args) ? raw.args.filter((a) => typeof a === "string") : [];
|
|
7442
|
+
const envKeys = keysOf(raw.env);
|
|
7443
|
+
const headerKeys = keysOf(raw.headers);
|
|
7444
|
+
if (url)
|
|
7445
|
+
out.push({ kind: "mcp_server", name, path, scope, agent, transport: "http", urlHost: hostOf(url), envKeys, headerKeys });
|
|
7446
|
+
else if (command) {
|
|
7447
|
+
const parts = args.length ? [command, ...args] : command.split(/\s+/);
|
|
7448
|
+
const bin = parts[0];
|
|
7449
|
+
out.push({ kind: "mcp_server", name, path, scope, agent, transport: "stdio", command: bin.split(/[\\/]/).pop(), package: stdioPackage(bin, parts.slice(1)), envKeys, headerKeys });
|
|
7450
|
+
}
|
|
7451
|
+
}
|
|
7452
|
+
return out;
|
|
7453
|
+
}
|
|
7454
|
+
function claudeSettings(j, path, scope) {
|
|
7455
|
+
const out = [];
|
|
7456
|
+
const agent = "claude_code";
|
|
7457
|
+
if (isObj(j.enabledPlugins)) {
|
|
7458
|
+
for (const [id, on2] of Object.entries(j.enabledPlugins).slice(0, 200)) {
|
|
7459
|
+
if (on2 === false)
|
|
7460
|
+
continue;
|
|
7461
|
+
const [plugin, marketplace] = id.split("@");
|
|
7462
|
+
out.push({ kind: "plugin", name: plugin, path, scope, agent, envKeys: [], headerKeys: [], detail: marketplace ? `from ${marketplace}` : void 0 });
|
|
7463
|
+
}
|
|
7464
|
+
}
|
|
7465
|
+
if (isObj(j.hooks)) {
|
|
7466
|
+
for (const [event, groups] of Object.entries(j.hooks)) {
|
|
7467
|
+
if (!Array.isArray(groups))
|
|
7468
|
+
continue;
|
|
7469
|
+
for (const g of groups) {
|
|
7470
|
+
if (!isObj(g) || !Array.isArray(g.hooks))
|
|
7471
|
+
continue;
|
|
7472
|
+
for (const h of g.hooks) {
|
|
7473
|
+
if (!isObj(h))
|
|
7474
|
+
continue;
|
|
7475
|
+
const cmd2 = str(h.command);
|
|
7476
|
+
if (!cmd2)
|
|
7477
|
+
continue;
|
|
7478
|
+
const bin = cmd2.trim().split(/\s+/)[0];
|
|
7479
|
+
out.push({ kind: "hook", name: event, path, scope, agent, command: bin.split(/[\\/]/).pop(), envKeys: [], headerKeys: [], detail: str(g.matcher) ? `on ${str(g.matcher)}` : "on every tool call" });
|
|
7480
|
+
}
|
|
7481
|
+
}
|
|
7482
|
+
}
|
|
7483
|
+
}
|
|
7484
|
+
out.push(...serverComponents(j.mcpServers, path, scope, agent));
|
|
7485
|
+
return out;
|
|
7486
|
+
}
|
|
7487
|
+
function codexToml(text, path, scope) {
|
|
7488
|
+
const out = [];
|
|
7489
|
+
const blocks = text.split(/^\s*\[/m).slice(1);
|
|
7490
|
+
for (const b of blocks) {
|
|
7491
|
+
const head = b.match(/^mcp_servers\.("?)([\w.-]+)\1\]/);
|
|
7492
|
+
if (head) {
|
|
7493
|
+
const body = b.slice(b.indexOf("]") + 1);
|
|
7494
|
+
const command = body.match(/^\s*command\s*=\s*"([^"]+)"/m)?.[1];
|
|
7495
|
+
const args = [...(body.match(/^\s*args\s*=\s*\[([^\]]*)\]/m)?.[1] ?? "").matchAll(/"([^"]*)"/g)].map((m) => m[1]);
|
|
7496
|
+
const url = body.match(/^\s*url\s*=\s*"([^"]+)"/m)?.[1] ?? null;
|
|
7497
|
+
const envKeys = [...(body.match(/^\s*env\s*=\s*\{([^}]*)\}/m)?.[1] ?? "").matchAll(/([\w.-]+)\s*=/g)].map((m) => m[1]);
|
|
7498
|
+
if (url)
|
|
7499
|
+
out.push({ kind: "mcp_server", name: head[2], path, scope, agent: "codex", transport: "http", urlHost: hostOf(url), envKeys, headerKeys: [] });
|
|
7500
|
+
else if (command)
|
|
7501
|
+
out.push({ kind: "mcp_server", name: head[2], path, scope, agent: "codex", transport: "stdio", command: command.split(/[\\/]/).pop(), package: stdioPackage(command, args), envKeys, headerKeys: [] });
|
|
7502
|
+
}
|
|
7503
|
+
const envTable = b.match(/^mcp_servers\.("?)([\w.-]+)\1\.env\]/);
|
|
7504
|
+
if (envTable) {
|
|
7505
|
+
const target = out.find((c2) => c2.name === envTable[2]);
|
|
7506
|
+
if (target)
|
|
7507
|
+
target.envKeys.push(...[...b.slice(b.indexOf("]") + 1).matchAll(/^\s*([\w.-]+)\s*=/gm)].map((m) => m[1]));
|
|
7508
|
+
}
|
|
7509
|
+
}
|
|
7510
|
+
return out;
|
|
7511
|
+
}
|
|
7512
|
+
function skillName(path, text) {
|
|
7513
|
+
const fm = text.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
7514
|
+
const n = fm?.[1].match(/^name:\s*["']?([^"'\n]+)["']?\s*$/m)?.[1]?.trim();
|
|
7515
|
+
return n || path.split("/").slice(-2, -1)[0] || "skill";
|
|
7516
|
+
}
|
|
7517
|
+
function parseAgentConfig(path, text, scope = "project") {
|
|
7518
|
+
const p = path.replace(/\\/g, "/");
|
|
7519
|
+
const agent = agentFor(p);
|
|
7520
|
+
const base = p.split("/").pop() ?? p;
|
|
7521
|
+
if (/\/SKILL\.md$/i.test(p))
|
|
7522
|
+
return [{ kind: "skill", name: skillName(p, text), path: p, scope, agent: "claude_code", envKeys: [], headerKeys: [] }];
|
|
7523
|
+
if (/\.(md|mdc)$/i.test(p) || /^\.(cursorrules|windsurfrules|clinerules)$/.test(base)) {
|
|
7524
|
+
const kind = /\/\.claude\/commands\//.test(`/${p}`) ? "slash command" : /\/\.claude\/agents\//.test(`/${p}`) ? "subagent" : "instructions";
|
|
7525
|
+
return [{ kind: "instructions", name: kind === "instructions" ? base : `${kind}: ${base.replace(/\.md$/i, "")}`, path: p, scope, agent, envKeys: [], headerKeys: [], detail: `${text.length.toLocaleString("en-US")} characters` }];
|
|
7526
|
+
}
|
|
7527
|
+
if (/config\.toml$/.test(p))
|
|
7528
|
+
return codexToml(text, p, scope);
|
|
7529
|
+
const j = parseJsonc(text);
|
|
7530
|
+
if (!isObj(j))
|
|
7531
|
+
return [];
|
|
7532
|
+
if (/\.claude\/settings(\.local)?\.json$/.test(p))
|
|
7533
|
+
return claudeSettings(j, p, scope);
|
|
7534
|
+
if (/\.vscode\/mcp\.json$/.test(p))
|
|
7535
|
+
return serverComponents(j.servers, p, scope, "vscode");
|
|
7536
|
+
if (base === ".claude.json") {
|
|
7537
|
+
const out = serverComponents(j.mcpServers, p, scope, "claude_code");
|
|
7538
|
+
if (isObj(j.projects)) {
|
|
7539
|
+
for (const [proj, cfg] of Object.entries(j.projects).slice(0, 100))
|
|
7540
|
+
if (isObj(cfg))
|
|
7541
|
+
for (const c2 of serverComponents(cfg.mcpServers, p, "project", "claude_code"))
|
|
7542
|
+
out.push({ ...c2, detail: `project ${proj.split(/[\\/]/).slice(-2).join("/")}` });
|
|
7543
|
+
}
|
|
7544
|
+
return out;
|
|
7545
|
+
}
|
|
7546
|
+
return serverComponents(j.mcpServers ?? j.servers, p, scope, agent);
|
|
7547
|
+
}
|
|
7548
|
+
function classifyCredential(name) {
|
|
7549
|
+
for (const [re, c2] of CRED_RULES)
|
|
7550
|
+
if (re.test(name))
|
|
7551
|
+
return c2;
|
|
7552
|
+
return null;
|
|
7553
|
+
}
|
|
7554
|
+
function blastRadius({ component: c2, verdict, trace }) {
|
|
7555
|
+
const reasons = [];
|
|
7556
|
+
const credentials = [...c2.envKeys, ...c2.headerKeys].map((name) => ({ name, class: classifyCredential(name) })).filter((x) => !!x.class);
|
|
7557
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
7558
|
+
if (c2.urlHost)
|
|
7559
|
+
hosts.add(c2.urlHost);
|
|
7560
|
+
for (const h of trace?.egressHosts ?? [])
|
|
7561
|
+
hosts.add(h);
|
|
7562
|
+
let score = 0;
|
|
7563
|
+
const local = c2.transport === "stdio" || c2.kind === "hook";
|
|
7564
|
+
if (c2.kind === "hook") {
|
|
7565
|
+
score += 2;
|
|
7566
|
+
reasons.push(`runs \`${c2.command ?? "a command"}\` ${c2.detail ?? "on agent events"}, as the developer`);
|
|
7567
|
+
} else if (local) {
|
|
7568
|
+
score += 2;
|
|
7569
|
+
reasons.push("runs on the developer's machine with their files, network and shell");
|
|
7570
|
+
}
|
|
7571
|
+
if (c2.kind === "skill" || c2.kind === "plugin") {
|
|
7572
|
+
score += 1;
|
|
7573
|
+
reasons.push("adds instructions and scripts the agent will follow");
|
|
7574
|
+
}
|
|
7575
|
+
const strong = credentials.filter((x) => x.class !== "secret");
|
|
7576
|
+
if (credentials.length) {
|
|
7577
|
+
score += strong.some((x) => ["cloud", "source_control", "payments", "database"].includes(x.class)) ? 3 : 2;
|
|
7578
|
+
reasons.unshift(`is handed ${credentials.length === 1 ? "a credential" : `${credentials.length} credentials`}: ${credentials.slice(0, 4).map((x) => x.name).join(", ")}${credentials.length > 4 ? ", \u2026" : ""}`);
|
|
7579
|
+
}
|
|
7580
|
+
if (c2.transport === "http" && c2.urlHost) {
|
|
7581
|
+
score += 1;
|
|
7582
|
+
reasons.push(`sends the agent's tool calls and their data to ${c2.urlHost}`);
|
|
7583
|
+
}
|
|
7584
|
+
if (verdict?.label === "blocked") {
|
|
7585
|
+
score += 4;
|
|
7586
|
+
reasons.unshift(`its verdict is Blocked (${verdict.score}/100)`);
|
|
7587
|
+
} else if (verdict?.label === "caution") {
|
|
7588
|
+
score += 1;
|
|
7589
|
+
reasons.push(`its verdict is Caution (${verdict.score}/100)`);
|
|
7590
|
+
}
|
|
7591
|
+
if (trace?.credentialPathsRead.length) {
|
|
7592
|
+
score += 3;
|
|
7593
|
+
reasons.unshift(`read ${trace.credentialPathsRead.slice(0, 2).join(", ")} in the honeypot`);
|
|
7594
|
+
}
|
|
7595
|
+
if (trace?.memoryWrites) {
|
|
7596
|
+
score += 2;
|
|
7597
|
+
reasons.push("wrote to the agent's memory or instruction files in the honeypot");
|
|
7598
|
+
}
|
|
7599
|
+
if (c2.kind === "instructions")
|
|
7600
|
+
reasons.push("is read by the agent as instructions on every session");
|
|
7601
|
+
if (!verdict && c2.kind !== "instructions" && c2.kind !== "hook") {
|
|
7602
|
+
score += 1;
|
|
7603
|
+
reasons.push(c2.package || c2.kind !== "mcp_server" ? "has no KillerSkills verdict yet" : "is not a registry package, so there is no verdict to check");
|
|
7604
|
+
}
|
|
7605
|
+
const level = score >= 5 ? "high" : score >= 3 ? "medium" : "low";
|
|
7606
|
+
return { level, reasons, credentials, hosts: [...hosts].slice(0, 10) };
|
|
7607
|
+
}
|
|
7608
|
+
var PROJECT_FILES, USER_CONFIG_FILES, USER_SKILL_DIRS, isObj, str, keysOf, CRED_RULES;
|
|
7609
|
+
var init_discover = __esm({
|
|
7610
|
+
"../policy/dist/discover.js"() {
|
|
7611
|
+
"use strict";
|
|
7612
|
+
PROJECT_FILES = [
|
|
7613
|
+
{ re: /(^|\/)\.mcp\.json$/, agent: "claude_code" },
|
|
7614
|
+
{ re: /(^|\/)\.claude\/settings(\.local)?\.json$/, agent: "claude_code" },
|
|
7615
|
+
{ re: /(^|\/)\.claude\/skills\/[^/]+\/SKILL\.md$/i, agent: "claude_code" },
|
|
7616
|
+
{ re: /(^|\/)\.claude\/(commands|agents)\/[^/]+\.md$/i, agent: "claude_code" },
|
|
7617
|
+
{ re: /(^|\/)\.cursor\/mcp\.json$/, agent: "cursor" },
|
|
7618
|
+
{ re: /(^|\/)\.cursor\/rules\/[^/]+\.mdc?$/, agent: "cursor" },
|
|
7619
|
+
{ re: /(^|\/)\.vscode\/mcp\.json$/, agent: "vscode" },
|
|
7620
|
+
{ re: /(^|\/)\.gemini\/settings\.json$/, agent: "gemini_cli" },
|
|
7621
|
+
{ re: /(^|\/)\.codex\/config\.toml$/, agent: "codex" },
|
|
7622
|
+
{ re: /(^|\/)\.github\/copilot-instructions\.md$/, agent: "copilot" },
|
|
7623
|
+
{ re: /(^|\/)(CLAUDE|AGENTS|GEMINI)\.md$/, agent: "any" },
|
|
7624
|
+
{ re: /(^|\/)\.(cursorrules|windsurfrules|clinerules)$/, agent: "any" }
|
|
7625
|
+
];
|
|
7626
|
+
USER_CONFIG_FILES = [
|
|
7627
|
+
{ path: ".claude.json", agent: "claude_code" },
|
|
7628
|
+
{ path: ".claude/settings.json", agent: "claude_code" },
|
|
7629
|
+
{ path: ".claude/CLAUDE.md", agent: "claude_code" },
|
|
7630
|
+
{ path: ".cursor/mcp.json", agent: "cursor" },
|
|
7631
|
+
{ path: ".codeium/windsurf/mcp_config.json", agent: "windsurf" },
|
|
7632
|
+
{ path: ".gemini/settings.json", agent: "gemini_cli" },
|
|
7633
|
+
{ path: ".codex/config.toml", agent: "codex" },
|
|
7634
|
+
{ path: "Library/Application Support/Claude/claude_desktop_config.json", agent: "claude_desktop" },
|
|
7635
|
+
{ path: ".config/Claude/claude_desktop_config.json", agent: "claude_desktop" },
|
|
7636
|
+
{ path: "AppData/Roaming/Claude/claude_desktop_config.json", agent: "claude_desktop" }
|
|
7637
|
+
];
|
|
7638
|
+
USER_SKILL_DIRS = [".claude/skills"];
|
|
7639
|
+
isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
7640
|
+
str = (v) => typeof v === "string" ? v : null;
|
|
7641
|
+
keysOf = (v) => isObj(v) ? Object.keys(v).filter((k) => /^[\w.-]{1,120}$/.test(k)).slice(0, 50) : [];
|
|
7642
|
+
CRED_RULES = [
|
|
7643
|
+
[/^(AWS_|AZURE_|ARM_|GOOGLE_|GCP_|GCLOUD|CLOUDFLARE_|DIGITALOCEAN|DO_TOKEN|VERCEL_|NETLIFY_|HEROKU_|FLY_)/i, "cloud"],
|
|
7644
|
+
[/^(GITHUB_|GH_|GITLAB_|GL_|BITBUCKET_|GIT_)/i, "source_control"],
|
|
7645
|
+
[/^(STRIPE_|PAYPAL_|BRAINTREE_|ADYEN_|SQUARE_)/i, "payments"],
|
|
7646
|
+
[/(DATABASE_URL|_DSN$|^POSTGRES|^PG|^MYSQL|^MONGO|^REDIS|^SUPABASE_|^NEON_|^PLANETSCALE|^SNOWFLAKE_|^BIGQUERY)/i, "database"],
|
|
7647
|
+
[/^(OPENAI_|ANTHROPIC_|GEMINI_|MISTRAL_|COHERE_|GROQ_|HF_|HUGGINGFACE)/i, "ai_provider"],
|
|
7648
|
+
[/^(SLACK_|DISCORD_|TWILIO_|SENDGRID_|RESEND_|MAILGUN_|POSTMARK_)/i, "messaging"],
|
|
7649
|
+
[/(TOKEN|SECRET|PASSWORD|PASSWD|API_?KEY|PRIVATE_KEY|CREDENTIAL|AUTH)/i, "secret"]
|
|
7650
|
+
];
|
|
7651
|
+
}
|
|
7652
|
+
});
|
|
7653
|
+
|
|
7381
7654
|
// ../policy/dist/index.js
|
|
7382
7655
|
var dist_exports = {};
|
|
7383
7656
|
__export(dist_exports, {
|
|
7384
7657
|
DEFAULT_POLICY: () => DEFAULT_POLICY,
|
|
7385
7658
|
FLAG_LABEL: () => FLAG_LABEL,
|
|
7386
7659
|
SOLO_POLICY: () => SOLO_POLICY,
|
|
7660
|
+
USER_CONFIG_FILES: () => USER_CONFIG_FILES,
|
|
7661
|
+
USER_SKILL_DIRS: () => USER_SKILL_DIRS,
|
|
7662
|
+
blastRadius: () => blastRadius,
|
|
7663
|
+
classifyCredential: () => classifyCredential,
|
|
7387
7664
|
evaluate: () => evaluate,
|
|
7388
7665
|
flagsFromTrace: () => flagsFromTrace,
|
|
7666
|
+
isAgentConfigPath: () => isAgentConfigPath,
|
|
7389
7667
|
labelFor: () => labelFor,
|
|
7668
|
+
parseAgentConfig: () => parseAgentConfig,
|
|
7390
7669
|
parsePolicyYaml: () => parsePolicyYaml,
|
|
7391
7670
|
serializePolicyYaml: () => serializePolicyYaml,
|
|
7392
|
-
simulate: () => simulate
|
|
7671
|
+
simulate: () => simulate,
|
|
7672
|
+
stdioPackage: () => stdioPackage
|
|
7393
7673
|
});
|
|
7394
7674
|
function parsePolicyYaml(text) {
|
|
7395
7675
|
const y = import_yaml.default.parse(text) ?? {};
|
|
7396
7676
|
const num = (v, d) => typeof v === "number" && Number.isFinite(v) ? v : d;
|
|
7397
|
-
const
|
|
7677
|
+
const str2 = (v, allowed, d) => allowed.includes(v) ? v : d;
|
|
7398
7678
|
const list = (v) => Array.isArray(v) ? v.map(String) : [];
|
|
7399
7679
|
const b = y.behavior ?? {};
|
|
7400
7680
|
const p = y.publishers ?? {};
|
|
7401
7681
|
const a = y.approvals ?? {};
|
|
7402
7682
|
const behavior = { ...DEFAULT_POLICY.behavior };
|
|
7403
7683
|
for (const f of FLAGS)
|
|
7404
|
-
behavior[f] =
|
|
7684
|
+
behavior[f] = str2(b[f], ["block", "approval", "warn"], DEFAULT_POLICY.behavior[f]);
|
|
7405
7685
|
return {
|
|
7406
7686
|
name: typeof y.name === "string" ? y.name : DEFAULT_POLICY.name,
|
|
7407
7687
|
version: num(y.version, 1),
|
|
7408
7688
|
minScore: Math.min(100, Math.max(0, num(y.min_score, DEFAULT_POLICY.minScore))),
|
|
7409
|
-
cautionAction:
|
|
7410
|
-
unknownAction:
|
|
7411
|
-
offlineAction:
|
|
7689
|
+
cautionAction: str2(y.caution, ["sandbox", "approval", "allow", "block"], DEFAULT_POLICY.cautionAction),
|
|
7690
|
+
unknownAction: str2(y.unknown, ["detonate", "block", "approval", "allow"], DEFAULT_POLICY.unknownAction),
|
|
7691
|
+
offlineAction: str2(y.offline, ["allow", "block", "approval"], DEFAULT_POLICY.offlineAction),
|
|
7412
7692
|
behavior,
|
|
7413
7693
|
publishers: {
|
|
7414
7694
|
allow: list(p.allow),
|
|
@@ -7572,6 +7852,7 @@ var init_dist = __esm({
|
|
|
7572
7852
|
"../policy/dist/index.js"() {
|
|
7573
7853
|
"use strict";
|
|
7574
7854
|
import_yaml = __toESM(require_dist(), 1);
|
|
7855
|
+
init_discover();
|
|
7575
7856
|
DEFAULT_POLICY = {
|
|
7576
7857
|
name: "default-strict",
|
|
7577
7858
|
version: 1,
|
|
@@ -7614,11 +7895,11 @@ var init_dist = __esm({
|
|
|
7614
7895
|
init_dist();
|
|
7615
7896
|
import { parseArgs } from "node:util";
|
|
7616
7897
|
import { spawnSync } from "node:child_process";
|
|
7617
|
-
import { readFileSync as
|
|
7618
|
-
import { resolve as resolve2, join as
|
|
7898
|
+
import { readFileSync as readFileSync6, existsSync as existsSync7 } from "node:fs";
|
|
7899
|
+
import { resolve as resolve2, join as join7, dirname, basename } from "node:path";
|
|
7619
7900
|
import { hostname, platform as platform2, userInfo } from "node:os";
|
|
7620
7901
|
import { createHash as createHash2 } from "node:crypto";
|
|
7621
|
-
import { createInterface } from "node:readline";
|
|
7902
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
7622
7903
|
|
|
7623
7904
|
// src/check.ts
|
|
7624
7905
|
init_dist();
|
|
@@ -7629,7 +7910,7 @@ import { mkdirSync, readFileSync, writeFileSync, existsSync, appendFileSync, chm
|
|
|
7629
7910
|
import { homedir } from "node:os";
|
|
7630
7911
|
import { join } from "node:path";
|
|
7631
7912
|
import { randomUUID } from "node:crypto";
|
|
7632
|
-
var VERSION = "0.
|
|
7913
|
+
var VERSION = "0.7.0";
|
|
7633
7914
|
var HOME = process.env.VET_SKILLS_HOME ?? join(homedir(), ".vet-skills");
|
|
7634
7915
|
var API = (process.env.KILLERSKILLS_API ?? "https://killerskills.ai").replace(/\/$/, "");
|
|
7635
7916
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -7827,6 +8108,11 @@ function detonate(tgz, opts = {}) {
|
|
|
7827
8108
|
function sendTelemetry(body) {
|
|
7828
8109
|
return call("/api/v1/telemetry", { method: "POST", body: JSON.stringify(body) }, 1500);
|
|
7829
8110
|
}
|
|
8111
|
+
function discoverReport(components) {
|
|
8112
|
+
const org = readOrg();
|
|
8113
|
+
if (!org) return Promise.resolve({ ok: false, error: "not joined", offline: false });
|
|
8114
|
+
return call(`/api/v1/orgs/${org.slug}/agents/${org.agentId}/discover`, { method: "POST", body: JSON.stringify({ components }), headers: orgHeaders() }, 15e3);
|
|
8115
|
+
}
|
|
7830
8116
|
|
|
7831
8117
|
// src/check.ts
|
|
7832
8118
|
import { platform } from "node:os";
|
|
@@ -7879,12 +8165,12 @@ var PAYLOAD_TYPE = "application/vnd.killerskills.verdict+json";
|
|
|
7879
8165
|
var SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", ".pglite", ".next", "__pycache__", ".venv"]);
|
|
7880
8166
|
function bundleHash(root) {
|
|
7881
8167
|
const h = createHash("sha256");
|
|
7882
|
-
const
|
|
8168
|
+
const walk2 = (dir) => {
|
|
7883
8169
|
for (const name of readdirSync(dir).sort()) {
|
|
7884
8170
|
if (SKIP.has(name)) continue;
|
|
7885
8171
|
const p = join2(dir, name);
|
|
7886
8172
|
const st = statSync2(p);
|
|
7887
|
-
if (st.isDirectory())
|
|
8173
|
+
if (st.isDirectory()) walk2(p);
|
|
7888
8174
|
else if (st.isFile() && st.size <= 2 * 1024 * 1024) {
|
|
7889
8175
|
h.update(relative(root, p).split(sep).join("/"));
|
|
7890
8176
|
h.update("\0");
|
|
@@ -7893,7 +8179,7 @@ function bundleHash(root) {
|
|
|
7893
8179
|
}
|
|
7894
8180
|
}
|
|
7895
8181
|
};
|
|
7896
|
-
|
|
8182
|
+
walk2(root);
|
|
7897
8183
|
return h.digest("hex");
|
|
7898
8184
|
}
|
|
7899
8185
|
function pae(payloadType, payload) {
|
|
@@ -8183,18 +8469,183 @@ function restrictionText(r) {
|
|
|
8183
8469
|
return parts.join(" \xB7 ") || "no restrictions";
|
|
8184
8470
|
}
|
|
8185
8471
|
|
|
8472
|
+
// src/discover.ts
|
|
8473
|
+
init_dist();
|
|
8474
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync3 } from "node:fs";
|
|
8475
|
+
import { homedir as homedir3 } from "node:os";
|
|
8476
|
+
import { join as join3 } from "node:path";
|
|
8477
|
+
var MAX_BYTES = 2 * 1024 * 1024;
|
|
8478
|
+
function read(path) {
|
|
8479
|
+
try {
|
|
8480
|
+
const st = statSync3(path);
|
|
8481
|
+
if (!st.isFile() || st.size > MAX_BYTES) return null;
|
|
8482
|
+
return readFileSync3(path, "utf8");
|
|
8483
|
+
} catch {
|
|
8484
|
+
return null;
|
|
8485
|
+
}
|
|
8486
|
+
}
|
|
8487
|
+
function discoverLocal(opts = {}) {
|
|
8488
|
+
const home = opts.home ?? homedir3();
|
|
8489
|
+
const out = [];
|
|
8490
|
+
for (const f of USER_CONFIG_FILES) {
|
|
8491
|
+
const text = read(join3(home, f.path));
|
|
8492
|
+
if (text !== null) out.push(...parseAgentConfig(f.path, text, "user"));
|
|
8493
|
+
}
|
|
8494
|
+
for (const dir of USER_SKILL_DIRS) {
|
|
8495
|
+
const abs = join3(home, dir);
|
|
8496
|
+
if (!existsSync3(abs)) continue;
|
|
8497
|
+
for (const name of safeList(abs)) {
|
|
8498
|
+
const rel = `${dir}/${name}/SKILL.md`;
|
|
8499
|
+
const text = read(join3(home, rel));
|
|
8500
|
+
if (text !== null) out.push(...parseAgentConfig(rel, text, "user"));
|
|
8501
|
+
}
|
|
8502
|
+
}
|
|
8503
|
+
if (opts.project) for (const rel of walk(opts.project, "", 0)) {
|
|
8504
|
+
const text = read(join3(opts.project, rel));
|
|
8505
|
+
if (text !== null) out.push(...parseAgentConfig(rel, text, "project"));
|
|
8506
|
+
}
|
|
8507
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8508
|
+
return out.filter((c2) => {
|
|
8509
|
+
const k = `${c2.kind}|${c2.name}|${c2.path}`;
|
|
8510
|
+
if (seen.has(k)) return false;
|
|
8511
|
+
seen.add(k);
|
|
8512
|
+
return true;
|
|
8513
|
+
});
|
|
8514
|
+
}
|
|
8515
|
+
function safeList(dir) {
|
|
8516
|
+
try {
|
|
8517
|
+
return readdirSync2(dir);
|
|
8518
|
+
} catch {
|
|
8519
|
+
return [];
|
|
8520
|
+
}
|
|
8521
|
+
}
|
|
8522
|
+
var SKIP2 = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", "vendor", "target", ".venv", "venv"]);
|
|
8523
|
+
function walk(root, rel, depth) {
|
|
8524
|
+
if (depth > 6) return [];
|
|
8525
|
+
const out = [];
|
|
8526
|
+
for (const name of safeList(join3(root, rel))) {
|
|
8527
|
+
if (SKIP2.has(name)) continue;
|
|
8528
|
+
const r = rel ? `${rel}/${name}` : name;
|
|
8529
|
+
let st;
|
|
8530
|
+
try {
|
|
8531
|
+
st = statSync3(join3(root, r));
|
|
8532
|
+
} catch {
|
|
8533
|
+
continue;
|
|
8534
|
+
}
|
|
8535
|
+
if (st.isDirectory()) out.push(...walk(root, r, depth + 1));
|
|
8536
|
+
else if (isAgentConfigPath(r)) out.push(r);
|
|
8537
|
+
if (out.length > 200) break;
|
|
8538
|
+
}
|
|
8539
|
+
return out;
|
|
8540
|
+
}
|
|
8541
|
+
|
|
8542
|
+
// src/mcp.ts
|
|
8543
|
+
import { createInterface } from "node:readline";
|
|
8544
|
+
var TOOLS = [
|
|
8545
|
+
{
|
|
8546
|
+
name: "check_skill",
|
|
8547
|
+
title: "Check a skill or MCP server",
|
|
8548
|
+
description: 'Look up the KillerSkills security verdict for an agent skill, MCP server or plugin BEFORE installing it. Returns the score (0-100), label (verified / caution / blocked), what the sandbox saw it do (network hosts contacted, credential files read, memory writes), the top findings, and the last safe version when the latest is blocked. Use the package name for npm/PyPI MCP servers (e.g. "@modelcontextprotocol/server-github" with registry "npm").',
|
|
8549
|
+
inputSchema: {
|
|
8550
|
+
type: "object",
|
|
8551
|
+
properties: {
|
|
8552
|
+
name: { type: "string", description: 'Skill or package name: "name", "publisher/name", "@scope/pkg", optionally "@version".' },
|
|
8553
|
+
registry: { type: "string", enum: ["skills_sh", "clawhub", "npm", "pypi", "docker", "plugins", "partner"], description: "Registry, when known. Omit to search all public registries." }
|
|
8554
|
+
},
|
|
8555
|
+
required: ["name"]
|
|
8556
|
+
},
|
|
8557
|
+
annotations: { readOnlyHint: true, openWorldHint: true }
|
|
8558
|
+
},
|
|
8559
|
+
{
|
|
8560
|
+
name: "search_skills",
|
|
8561
|
+
title: "Search vetted skills",
|
|
8562
|
+
description: "Search the KillerSkills index (every public agent skill and MCP server, each detonated in a sandbox) by keyword. Returns the most-installed matches with their verdicts, so you can pick a verified option instead of an unvetted one.",
|
|
8563
|
+
inputSchema: { type: "object", properties: { query: { type: "string", description: 'Keywords, e.g. "postgres", "github mcp", "pdf".' } }, required: ["query"] },
|
|
8564
|
+
annotations: { readOnlyHint: true, openWorldHint: true }
|
|
8565
|
+
}
|
|
8566
|
+
];
|
|
8567
|
+
async function checkSkill(name, registry) {
|
|
8568
|
+
const r = await resolveSkill(name, registry);
|
|
8569
|
+
if (!r.ok) return r.status === 404 ? `No skill or MCP server named "${name}" is indexed by KillerSkills${registry ? ` in ${registry}` : ""}. Treat it as unvetted.` : `KillerSkills lookup failed (${r.error}). Treat "${name}" as unvetted.`;
|
|
8570
|
+
const d = r.data;
|
|
8571
|
+
const page = `${API}${d.skill.page}`;
|
|
8572
|
+
if (!d.verdict) return `${d.skill.name} (${d.skill.registry_label}, publisher ${d.publisher.handle}) is indexed but not scored yet: unvetted. ${page}`;
|
|
8573
|
+
const lines = [
|
|
8574
|
+
`${d.skill.name}@${d.version.semver} (${d.skill.registry_label}, publisher ${d.publisher.handle}${d.publisher.verified ? ", verified publisher" : ""})`,
|
|
8575
|
+
`Verdict: ${d.verdict.label.toUpperCase()} \xB7 score ${d.verdict.score}/100 \xB7 ${d.verdict.scenarios_run} sandbox scenarios`
|
|
8576
|
+
];
|
|
8577
|
+
const t = d.trace_summary;
|
|
8578
|
+
if (t) {
|
|
8579
|
+
const undeclared = t.egress_hosts.filter((h) => !h.declared).map((h) => h.host);
|
|
8580
|
+
lines.push(`Sandbox: contacted ${t.egress_hosts.length} host(s)${undeclared.length ? ` (undeclared: ${undeclared.slice(0, 5).join(", ")})` : ""}; read ${t.files_read.length} file(s); ${t.memory_writes.length} memory write(s)${t.tool_shadowing.length ? `; shadows tools: ${t.tool_shadowing.map((x) => x.tool).join(", ")}` : ""}.`);
|
|
8581
|
+
}
|
|
8582
|
+
for (const f of d.findings.slice(0, 5)) lines.push(`- [${f.severity}] ${f.title}`);
|
|
8583
|
+
if (d.verdict.label === "blocked" && d.last_safe_version) lines.push(`Last safe version: ${d.last_safe_version.semver} (score ${d.last_safe_version.score}).`);
|
|
8584
|
+
lines.push(d.verdict.label === "verified" ? "OK to install." : d.verdict.label === "caution" ? "Install only if the findings above are acceptable; tell the user what they are." : "Do not install. Tell the user why.");
|
|
8585
|
+
lines.push(`Evidence: ${page}`);
|
|
8586
|
+
return lines.join("\n");
|
|
8587
|
+
}
|
|
8588
|
+
async function searchSkills(query) {
|
|
8589
|
+
try {
|
|
8590
|
+
const res = await fetch(`${API}/api/v1/leaderboard?q=${encodeURIComponent(query)}`, { headers: { accept: "application/json", "user-agent": `vet-skills/${VERSION} mcp` }, signal: AbortSignal.timeout(1e4) });
|
|
8591
|
+
if (!res.ok) return `Search failed (HTTP ${res.status}).`;
|
|
8592
|
+
const d = await res.json();
|
|
8593
|
+
if (!d.rows.length) return `Nothing in the KillerSkills index matches "${query}".`;
|
|
8594
|
+
return [`${d.total} match(es) for "${query}", most installed first:`, ...d.rows.slice(0, 15).map((x) => `- ${x.skill.name} (${x.skill.registry}, ${x.skill.publisher}) \xB7 ${x.latest_verdict.label} ${x.latest_verdict.score} \xB7 ${x.install_count.toLocaleString()} installs \xB7 ${API}${x.skill.page}`)].join("\n");
|
|
8595
|
+
} catch (e) {
|
|
8596
|
+
return `Search failed (${e.message}).`;
|
|
8597
|
+
}
|
|
8598
|
+
}
|
|
8599
|
+
async function serveMcp() {
|
|
8600
|
+
const send = (msg) => process.stdout.write(JSON.stringify(msg) + "\n");
|
|
8601
|
+
const rl = createInterface({ input: process.stdin });
|
|
8602
|
+
for await (const line of rl) {
|
|
8603
|
+
if (!line.trim()) continue;
|
|
8604
|
+
let req;
|
|
8605
|
+
try {
|
|
8606
|
+
req = JSON.parse(line);
|
|
8607
|
+
} catch {
|
|
8608
|
+
send({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "parse error" } });
|
|
8609
|
+
continue;
|
|
8610
|
+
}
|
|
8611
|
+
if (req.id === void 0) continue;
|
|
8612
|
+
const ok = (result) => send({ jsonrpc: "2.0", id: req.id, result });
|
|
8613
|
+
switch (req.method) {
|
|
8614
|
+
case "initialize":
|
|
8615
|
+
ok({ protocolVersion: req.params?.protocolVersion ?? "2025-06-18", capabilities: { tools: {} }, serverInfo: { name: "killerskills", title: "KillerSkills", version: VERSION }, instructions: "Before installing any agent skill, plugin or MCP server, call check_skill. Do not install anything labelled blocked." });
|
|
8616
|
+
break;
|
|
8617
|
+
case "ping":
|
|
8618
|
+
ok({});
|
|
8619
|
+
break;
|
|
8620
|
+
case "tools/list":
|
|
8621
|
+
ok({ tools: TOOLS });
|
|
8622
|
+
break;
|
|
8623
|
+
case "tools/call": {
|
|
8624
|
+
const name = req.params?.name;
|
|
8625
|
+
const args = req.params?.arguments ?? {};
|
|
8626
|
+
const text = name === "check_skill" ? await checkSkill(String(args.name ?? ""), args.registry || void 0) : name === "search_skills" ? await searchSkills(String(args.query ?? "")) : null;
|
|
8627
|
+
if (text === null) send({ jsonrpc: "2.0", id: req.id, error: { code: -32602, message: `unknown tool ${name}` } });
|
|
8628
|
+
else ok({ content: [{ type: "text", text }], isError: false });
|
|
8629
|
+
break;
|
|
8630
|
+
}
|
|
8631
|
+
default:
|
|
8632
|
+
send({ jsonrpc: "2.0", id: req.id, error: { code: -32601, message: `method not found: ${req.method}` } });
|
|
8633
|
+
}
|
|
8634
|
+
}
|
|
8635
|
+
}
|
|
8636
|
+
|
|
8186
8637
|
// src/hook.ts
|
|
8187
|
-
import { existsSync as
|
|
8188
|
-
import { homedir as
|
|
8189
|
-
import { join as
|
|
8638
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
8639
|
+
import { homedir as homedir5 } from "node:os";
|
|
8640
|
+
import { join as join5 } from "node:path";
|
|
8190
8641
|
|
|
8191
8642
|
// src/sync.ts
|
|
8192
|
-
import { existsSync as
|
|
8193
|
-
import { homedir as
|
|
8194
|
-
import { join as
|
|
8643
|
+
import { existsSync as existsSync4, rmSync } from "node:fs";
|
|
8644
|
+
import { homedir as homedir4 } from "node:os";
|
|
8645
|
+
import { join as join4 } from "node:path";
|
|
8195
8646
|
function skillDirs(name) {
|
|
8196
8647
|
const bare = name.replace(/^.*\//, "").replace(/@.*$/, "");
|
|
8197
|
-
return [
|
|
8648
|
+
return [join4(homedir4(), ".claude", "skills", bare), join4(process.cwd(), ".claude", "skills", bare), join4(homedir4(), ".claude", "plugins", bare)];
|
|
8198
8649
|
}
|
|
8199
8650
|
async function applyRemovals(pending, log = () => {
|
|
8200
8651
|
}) {
|
|
@@ -8205,7 +8656,7 @@ async function applyRemovals(pending, log = () => {
|
|
|
8205
8656
|
const detail = [];
|
|
8206
8657
|
let failed = false;
|
|
8207
8658
|
for (const it of items) {
|
|
8208
|
-
const dirs = skillDirs(it.skill).filter((d) =>
|
|
8659
|
+
const dirs = skillDirs(it.skill).filter((d) => existsSync4(d));
|
|
8209
8660
|
if (!dirs.length) {
|
|
8210
8661
|
detail.push(`${it.skill}: not on disk`);
|
|
8211
8662
|
continue;
|
|
@@ -8356,13 +8807,13 @@ ${out}
|
|
|
8356
8807
|
return 0;
|
|
8357
8808
|
}
|
|
8358
8809
|
function installClaudeCodeHook() {
|
|
8359
|
-
const dir =
|
|
8360
|
-
const path =
|
|
8361
|
-
if (!
|
|
8810
|
+
const dir = join5(homedir5(), ".claude");
|
|
8811
|
+
const path = join5(dir, "settings.json");
|
|
8812
|
+
if (!existsSync5(dir)) mkdirSync2(dir, { recursive: true });
|
|
8362
8813
|
let settings = {};
|
|
8363
|
-
if (
|
|
8814
|
+
if (existsSync5(path)) {
|
|
8364
8815
|
try {
|
|
8365
|
-
settings = JSON.parse(
|
|
8816
|
+
settings = JSON.parse(readFileSync4(path, "utf8"));
|
|
8366
8817
|
} catch {
|
|
8367
8818
|
settings = {};
|
|
8368
8819
|
}
|
|
@@ -8384,25 +8835,25 @@ function installClaudeCodeHook() {
|
|
|
8384
8835
|
}
|
|
8385
8836
|
|
|
8386
8837
|
// src/runtime.ts
|
|
8387
|
-
import { existsSync as
|
|
8388
|
-
import { homedir as
|
|
8389
|
-
import { join as
|
|
8838
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5, readdirSync as readdirSync3, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
8839
|
+
import { homedir as homedir6 } from "node:os";
|
|
8840
|
+
import { join as join6 } from "node:path";
|
|
8390
8841
|
var ACTIVE_MS = 30 * 6e4;
|
|
8391
8842
|
var CRED = /(^|\/)(\.ssh|\.aws|\.npmrc|\.netrc|\.config\/gh|\.docker\/config\.json|\.kube\/config|\.gnupg|credentials|\.env(\.|$)|id_(rsa|ed25519|ecdsa)|keychain)/i;
|
|
8392
8843
|
var MEMORY = /(^|\/)(MEMORY\.md|CLAUDE\.md|AGENTS\.md|\.cursorrules|\.clinerules|\.windsurfrules|GEMINI\.md|\.github\/copilot-instructions\.md)$/i;
|
|
8393
|
-
var DIR =
|
|
8844
|
+
var DIR = join6(HOME, "runtime");
|
|
8394
8845
|
function sessionFile(id) {
|
|
8395
|
-
return
|
|
8846
|
+
return join6(DIR, `${id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 80)}.json`);
|
|
8396
8847
|
}
|
|
8397
8848
|
function readSession(id) {
|
|
8398
8849
|
try {
|
|
8399
|
-
return JSON.parse(
|
|
8850
|
+
return JSON.parse(readFileSync5(sessionFile(id), "utf8"));
|
|
8400
8851
|
} catch {
|
|
8401
8852
|
return { active: null, verdicts: {}, reported: [] };
|
|
8402
8853
|
}
|
|
8403
8854
|
}
|
|
8404
8855
|
function writeSession(id, s) {
|
|
8405
|
-
if (!
|
|
8856
|
+
if (!existsSync6(DIR)) mkdirSync3(DIR, { recursive: true });
|
|
8406
8857
|
writeFileSync4(sessionFile(id), JSON.stringify(s));
|
|
8407
8858
|
}
|
|
8408
8859
|
function hostsIn(cmd2) {
|
|
@@ -8412,16 +8863,16 @@ function hostsIn(cmd2) {
|
|
|
8412
8863
|
return [...out];
|
|
8413
8864
|
}
|
|
8414
8865
|
function pathsIn(cmd2) {
|
|
8415
|
-
const
|
|
8866
|
+
const read2 = /* @__PURE__ */ new Set();
|
|
8416
8867
|
const written = /* @__PURE__ */ new Set();
|
|
8417
8868
|
const norm = (p) => p.replace(/^\$HOME/, "~").replace(/^["']|["']$/g, "");
|
|
8418
8869
|
for (const m of cmd2.matchAll(/(?:>>?|tee\s+(?:-a\s+)?)\s*["']?((?:~|\/|\$HOME)[^\s"'|;&]+)/g)) written.add(norm(m[1]));
|
|
8419
|
-
for (const m of cmd2.matchAll(/(?:^|[\s|;&(])(?:cat|less|head|tail|grep|cp|scp|base64|xxd|od|strings|python3?|node)\s+(?:-\S+\s+)*["']?((?:~|\/|\$HOME)[^\s"'|;&]+)/g))
|
|
8420
|
-
for (const m of cmd2.matchAll(/["']?((?:~|\$HOME)\/\.(?:ssh|aws|npmrc|netrc|config\/gh|docker|kube|gnupg)[^\s"'|;&]*)/g)) if (!written.has(norm(m[1])))
|
|
8421
|
-
return { read: [...
|
|
8870
|
+
for (const m of cmd2.matchAll(/(?:^|[\s|;&(])(?:cat|less|head|tail|grep|cp|scp|base64|xxd|od|strings|python3?|node)\s+(?:-\S+\s+)*["']?((?:~|\/|\$HOME)[^\s"'|;&]+)/g)) read2.add(norm(m[1]));
|
|
8871
|
+
for (const m of cmd2.matchAll(/["']?((?:~|\$HOME)\/\.(?:ssh|aws|npmrc|netrc|config\/gh|docker|kube|gnupg)[^\s"'|;&]*)/g)) if (!written.has(norm(m[1]))) read2.add(norm(m[1]));
|
|
8872
|
+
return { read: [...read2], written: [...written] };
|
|
8422
8873
|
}
|
|
8423
8874
|
var isOutsideProject = (p) => (p.startsWith("~") || p.startsWith("/")) && !p.startsWith(process.cwd()) && !p.startsWith("/tmp") && !p.startsWith("/dev");
|
|
8424
|
-
var tilde = (p) => p.replace(
|
|
8875
|
+
var tilde = (p) => p.replace(homedir6(), "~");
|
|
8425
8876
|
function attributed(session, toolName) {
|
|
8426
8877
|
const m = toolName.match(/^mcp__([^_]+(?:_[^_]+)*?)__/);
|
|
8427
8878
|
if (m) return m[1];
|
|
@@ -8490,16 +8941,16 @@ function deviations(skill, r, o, tool, session) {
|
|
|
8490
8941
|
}
|
|
8491
8942
|
return out;
|
|
8492
8943
|
}
|
|
8493
|
-
var LOG =
|
|
8944
|
+
var LOG = join6(HOME, "runtime", "deviations.jsonl");
|
|
8494
8945
|
function appendDeviations(ds) {
|
|
8495
8946
|
if (!ds.length) return;
|
|
8496
|
-
if (!
|
|
8947
|
+
if (!existsSync6(DIR)) mkdirSync3(DIR, { recursive: true });
|
|
8497
8948
|
writeFileSync4(LOG, ds.map((d) => JSON.stringify(d)).join("\n") + "\n", { flag: "a" });
|
|
8498
8949
|
}
|
|
8499
8950
|
function readDeviations(days = 7) {
|
|
8500
|
-
if (!
|
|
8951
|
+
if (!existsSync6(LOG)) return [];
|
|
8501
8952
|
const since = Date.now() - days * 864e5;
|
|
8502
|
-
return
|
|
8953
|
+
return readFileSync5(LOG, "utf8").split("\n").filter(Boolean).map((l) => {
|
|
8503
8954
|
try {
|
|
8504
8955
|
return JSON.parse(l);
|
|
8505
8956
|
} catch {
|
|
@@ -8542,12 +8993,12 @@ async function observe(stdin) {
|
|
|
8542
8993
|
return { code: serious ? 2 : 0, lines };
|
|
8543
8994
|
}
|
|
8544
8995
|
function pruneSessions() {
|
|
8545
|
-
if (!
|
|
8546
|
-
for (const f of
|
|
8996
|
+
if (!existsSync6(DIR)) return;
|
|
8997
|
+
for (const f of readdirSync3(DIR)) {
|
|
8547
8998
|
if (!f.endsWith(".json")) continue;
|
|
8548
|
-
const p =
|
|
8999
|
+
const p = join6(DIR, f);
|
|
8549
9000
|
try {
|
|
8550
|
-
if (Date.now() -
|
|
9001
|
+
if (Date.now() - statSync4(p).mtimeMs > 864e5) writeFileSync4(p, "{}");
|
|
8551
9002
|
} catch {
|
|
8552
9003
|
}
|
|
8553
9004
|
}
|
|
@@ -8566,6 +9017,8 @@ var { values, positionals } = parseArgs({
|
|
|
8566
9017
|
ci: { type: "boolean" },
|
|
8567
9018
|
email: { type: "string" },
|
|
8568
9019
|
help: { type: "boolean", short: "h" },
|
|
9020
|
+
project: { type: "boolean" },
|
|
9021
|
+
quiet: { type: "boolean", short: "q" },
|
|
8569
9022
|
version: { type: "boolean", short: "v" },
|
|
8570
9023
|
agent: { type: "string" },
|
|
8571
9024
|
publisher: { type: "string" },
|
|
@@ -8574,7 +9027,7 @@ var { values, positionals } = parseArgs({
|
|
|
8574
9027
|
});
|
|
8575
9028
|
var [cmd, ...rest] = positionals;
|
|
8576
9029
|
async function ask(question, choices) {
|
|
8577
|
-
const rl =
|
|
9030
|
+
const rl = createInterface2({ input: process.stdin, output: process.stderr });
|
|
8578
9031
|
return new Promise((res) => rl.question(question, (a) => {
|
|
8579
9032
|
rl.close();
|
|
8580
9033
|
const k = a.trim().toLowerCase()[0];
|
|
@@ -8598,6 +9051,8 @@ Get started:
|
|
|
8598
9051
|
vet-skills policy show|set <file> view or replace the local policy
|
|
8599
9052
|
vet-skills block <skill> [--reason] add to the personal block list
|
|
8600
9053
|
vet-skills status org, policy version, last report, cache size
|
|
9054
|
+
vet-skills discover [--project] [--json] every MCP server, skill, plugin and hook on this machine, with verdicts
|
|
9055
|
+
vet-skills mcp run as an MCP server (check_skill, search_skills) for any agent
|
|
8601
9056
|
vet-skills sync pull the org policy and apply pending removals
|
|
8602
9057
|
vet-skills verify <skill|path> check the signed verdict against what is on disk
|
|
8603
9058
|
vet-skills lock pin every installed skill's hash + attestation in vet-skills.lock
|
|
@@ -8683,7 +9138,7 @@ async function main() {
|
|
|
8683
9138
|
return 1;
|
|
8684
9139
|
}
|
|
8685
9140
|
const dir = resolve2(rest[0]);
|
|
8686
|
-
if (!
|
|
9141
|
+
if (!existsSync7(join7(dir, "SKILL.md")) && !existsSync7(join7(dir, "package.json"))) {
|
|
8687
9142
|
console.log(`${c.blocked("\u2717")} ${dir} has no SKILL.md or package.json`);
|
|
8688
9143
|
return 1;
|
|
8689
9144
|
}
|
|
@@ -8726,7 +9181,7 @@ async function main() {
|
|
|
8726
9181
|
return 1;
|
|
8727
9182
|
}
|
|
8728
9183
|
const dir = resolve2(rest[0]);
|
|
8729
|
-
if (!
|
|
9184
|
+
if (!existsSync7(join7(dir, "SKILL.md"))) {
|
|
8730
9185
|
console.log(`${c.blocked("\u2717")} ${dir} has no SKILL.md (name and version come from its frontmatter)`);
|
|
8731
9186
|
return 1;
|
|
8732
9187
|
}
|
|
@@ -8818,7 +9273,7 @@ async function main() {
|
|
|
8818
9273
|
console.error("usage: vet-skills policy set <file.yaml>");
|
|
8819
9274
|
return 1;
|
|
8820
9275
|
}
|
|
8821
|
-
const text =
|
|
9276
|
+
const text = readFileSync6(rest[1], "utf8");
|
|
8822
9277
|
parsePolicyYaml(text);
|
|
8823
9278
|
writePolicy(text);
|
|
8824
9279
|
console.log(`${c.verified("\u2713")} Personal policy updated.`);
|
|
@@ -8936,6 +9391,51 @@ async function main() {
|
|
|
8936
9391
|
if (values.json) console.log(JSON.stringify(ds, null, 2));
|
|
8937
9392
|
return 0;
|
|
8938
9393
|
}
|
|
9394
|
+
case "discover": {
|
|
9395
|
+
const comps = discoverLocal({ project: values.project ? process.cwd() : void 0 });
|
|
9396
|
+
if (values.json) {
|
|
9397
|
+
console.log(JSON.stringify(comps, null, 2));
|
|
9398
|
+
} else if (!values.quiet) {
|
|
9399
|
+
if (!comps.length) console.log(c.muted("No agent configuration found in the usual places (~/.claude.json, ~/.cursor/mcp.json, Claude Desktop, Windsurf, Gemini CLI, Codex, ~/.claude/skills)."));
|
|
9400
|
+
const runnable = comps.filter((x) => x.kind === "mcp_server" || x.kind === "skill");
|
|
9401
|
+
const verdicts = /* @__PURE__ */ new Map();
|
|
9402
|
+
await Promise.all(runnable.slice(0, 40).map(async (x) => {
|
|
9403
|
+
const q = x.package ? x.package.name.replace(/^@/, "") : x.name;
|
|
9404
|
+
const r = await resolveSkill(q, x.package?.registry);
|
|
9405
|
+
const v = r.ok ? r.data.verdict : null;
|
|
9406
|
+
verdicts.set(`${x.kind}|${x.name}`, v?.label ? `${v.label} ${v.score ?? ""}`.trim() : "not vetted");
|
|
9407
|
+
}));
|
|
9408
|
+
const kinds = [["mcp_server", "MCP servers"], ["skill", "Skills"], ["plugin", "Plugins"], ["hook", "Hooks"], ["instructions", "Instruction files"]];
|
|
9409
|
+
for (const [k, label] of kinds) {
|
|
9410
|
+
const list = comps.filter((x) => x.kind === k);
|
|
9411
|
+
if (!list.length) continue;
|
|
9412
|
+
console.log(`
|
|
9413
|
+
${label} (${list.length})`);
|
|
9414
|
+
for (const x of list) {
|
|
9415
|
+
const v = verdicts.get(`${x.kind}|${x.name}`);
|
|
9416
|
+
const tone = !v ? c.muted : v.startsWith("verified") ? c.verified : v.startsWith("blocked") ? c.blocked : c.caution;
|
|
9417
|
+
const what = x.package ? `${x.package.registry}:${x.package.name}` : x.urlHost ?? x.command ?? x.detail ?? "";
|
|
9418
|
+
const keys = x.envKeys.length || x.headerKeys.length ? c.muted(` \xB7 ${[...x.envKeys, ...x.headerKeys].slice(0, 4).join(", ")}`) : "";
|
|
9419
|
+
console.log(` ${x.name.padEnd(28)} ${tone((v ?? "").padEnd(14))} ${c.muted(what)}${keys} ${c.muted(x.path)}`);
|
|
9420
|
+
}
|
|
9421
|
+
}
|
|
9422
|
+
}
|
|
9423
|
+
if (readOrg()) {
|
|
9424
|
+
const r = await discoverReport(comps);
|
|
9425
|
+
if (r.ok) {
|
|
9426
|
+
if (!values.json) console.log(`
|
|
9427
|
+
${c.verified("\u2713")} ${r.data.components} component${r.data.components === 1 ? "" : "s"} reported to ${readOrg().slug} (names only) \xB7 ${API}${r.data.dashboard}`);
|
|
9428
|
+
} else {
|
|
9429
|
+
console.error(c.caution(`report failed: ${r.error}`));
|
|
9430
|
+
return 1;
|
|
9431
|
+
}
|
|
9432
|
+
} else if (!values.json && !values.quiet) console.log(c.muted("\nNot enrolled: nothing was sent. `vet-skills join <org> --token <t>` reports this to your team's Discovery page."));
|
|
9433
|
+
return 0;
|
|
9434
|
+
}
|
|
9435
|
+
case "mcp": {
|
|
9436
|
+
await serveMcp();
|
|
9437
|
+
return 0;
|
|
9438
|
+
}
|
|
8939
9439
|
case "sync": {
|
|
8940
9440
|
if (!readOrg()) {
|
|
8941
9441
|
console.log(c.muted("Not joined to an org; nothing to sync."));
|