@fro.bot/systematic 2.3.1 → 2.3.2
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/cli.js +1 -1
- package/dist/index-3h7kpmfa.js +1480 -0
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/index-5wn35nny.js +0 -675
|
@@ -0,0 +1,1480 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/lib/config.ts
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import path from "path";
|
|
6
|
+
|
|
7
|
+
// node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
8
|
+
function createScanner(text, ignoreTrivia = false) {
|
|
9
|
+
const len = text.length;
|
|
10
|
+
let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
|
|
11
|
+
function scanHexDigits(count, exact) {
|
|
12
|
+
let digits = 0;
|
|
13
|
+
let value2 = 0;
|
|
14
|
+
while (digits < count || !exact) {
|
|
15
|
+
let ch = text.charCodeAt(pos);
|
|
16
|
+
if (ch >= 48 && ch <= 57) {
|
|
17
|
+
value2 = value2 * 16 + ch - 48;
|
|
18
|
+
} else if (ch >= 65 && ch <= 70) {
|
|
19
|
+
value2 = value2 * 16 + ch - 65 + 10;
|
|
20
|
+
} else if (ch >= 97 && ch <= 102) {
|
|
21
|
+
value2 = value2 * 16 + ch - 97 + 10;
|
|
22
|
+
} else {
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
pos++;
|
|
26
|
+
digits++;
|
|
27
|
+
}
|
|
28
|
+
if (digits < count) {
|
|
29
|
+
value2 = -1;
|
|
30
|
+
}
|
|
31
|
+
return value2;
|
|
32
|
+
}
|
|
33
|
+
function setPosition(newPosition) {
|
|
34
|
+
pos = newPosition;
|
|
35
|
+
value = "";
|
|
36
|
+
tokenOffset = 0;
|
|
37
|
+
token = 16;
|
|
38
|
+
scanError = 0;
|
|
39
|
+
}
|
|
40
|
+
function scanNumber() {
|
|
41
|
+
let start = pos;
|
|
42
|
+
if (text.charCodeAt(pos) === 48) {
|
|
43
|
+
pos++;
|
|
44
|
+
} else {
|
|
45
|
+
pos++;
|
|
46
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
47
|
+
pos++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (pos < text.length && text.charCodeAt(pos) === 46) {
|
|
51
|
+
pos++;
|
|
52
|
+
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
53
|
+
pos++;
|
|
54
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
55
|
+
pos++;
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
scanError = 3;
|
|
59
|
+
return text.substring(start, pos);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
let end = pos;
|
|
63
|
+
if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
|
|
64
|
+
pos++;
|
|
65
|
+
if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
|
|
66
|
+
pos++;
|
|
67
|
+
}
|
|
68
|
+
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
69
|
+
pos++;
|
|
70
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
71
|
+
pos++;
|
|
72
|
+
}
|
|
73
|
+
end = pos;
|
|
74
|
+
} else {
|
|
75
|
+
scanError = 3;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return text.substring(start, end);
|
|
79
|
+
}
|
|
80
|
+
function scanString() {
|
|
81
|
+
let result = "", start = pos;
|
|
82
|
+
while (true) {
|
|
83
|
+
if (pos >= len) {
|
|
84
|
+
result += text.substring(start, pos);
|
|
85
|
+
scanError = 2;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
const ch = text.charCodeAt(pos);
|
|
89
|
+
if (ch === 34) {
|
|
90
|
+
result += text.substring(start, pos);
|
|
91
|
+
pos++;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if (ch === 92) {
|
|
95
|
+
result += text.substring(start, pos);
|
|
96
|
+
pos++;
|
|
97
|
+
if (pos >= len) {
|
|
98
|
+
scanError = 2;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
const ch2 = text.charCodeAt(pos++);
|
|
102
|
+
switch (ch2) {
|
|
103
|
+
case 34:
|
|
104
|
+
result += '"';
|
|
105
|
+
break;
|
|
106
|
+
case 92:
|
|
107
|
+
result += "\\";
|
|
108
|
+
break;
|
|
109
|
+
case 47:
|
|
110
|
+
result += "/";
|
|
111
|
+
break;
|
|
112
|
+
case 98:
|
|
113
|
+
result += "\b";
|
|
114
|
+
break;
|
|
115
|
+
case 102:
|
|
116
|
+
result += "\f";
|
|
117
|
+
break;
|
|
118
|
+
case 110:
|
|
119
|
+
result += `
|
|
120
|
+
`;
|
|
121
|
+
break;
|
|
122
|
+
case 114:
|
|
123
|
+
result += "\r";
|
|
124
|
+
break;
|
|
125
|
+
case 116:
|
|
126
|
+
result += "\t";
|
|
127
|
+
break;
|
|
128
|
+
case 117:
|
|
129
|
+
const ch3 = scanHexDigits(4, true);
|
|
130
|
+
if (ch3 >= 0) {
|
|
131
|
+
result += String.fromCharCode(ch3);
|
|
132
|
+
} else {
|
|
133
|
+
scanError = 4;
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
default:
|
|
137
|
+
scanError = 5;
|
|
138
|
+
}
|
|
139
|
+
start = pos;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (ch >= 0 && ch <= 31) {
|
|
143
|
+
if (isLineBreak(ch)) {
|
|
144
|
+
result += text.substring(start, pos);
|
|
145
|
+
scanError = 2;
|
|
146
|
+
break;
|
|
147
|
+
} else {
|
|
148
|
+
scanError = 6;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
pos++;
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
function scanNext() {
|
|
156
|
+
value = "";
|
|
157
|
+
scanError = 0;
|
|
158
|
+
tokenOffset = pos;
|
|
159
|
+
lineStartOffset = lineNumber;
|
|
160
|
+
prevTokenLineStartOffset = tokenLineStartOffset;
|
|
161
|
+
if (pos >= len) {
|
|
162
|
+
tokenOffset = len;
|
|
163
|
+
return token = 17;
|
|
164
|
+
}
|
|
165
|
+
let code = text.charCodeAt(pos);
|
|
166
|
+
if (isWhiteSpace(code)) {
|
|
167
|
+
do {
|
|
168
|
+
pos++;
|
|
169
|
+
value += String.fromCharCode(code);
|
|
170
|
+
code = text.charCodeAt(pos);
|
|
171
|
+
} while (isWhiteSpace(code));
|
|
172
|
+
return token = 15;
|
|
173
|
+
}
|
|
174
|
+
if (isLineBreak(code)) {
|
|
175
|
+
pos++;
|
|
176
|
+
value += String.fromCharCode(code);
|
|
177
|
+
if (code === 13 && text.charCodeAt(pos) === 10) {
|
|
178
|
+
pos++;
|
|
179
|
+
value += `
|
|
180
|
+
`;
|
|
181
|
+
}
|
|
182
|
+
lineNumber++;
|
|
183
|
+
tokenLineStartOffset = pos;
|
|
184
|
+
return token = 14;
|
|
185
|
+
}
|
|
186
|
+
switch (code) {
|
|
187
|
+
case 123:
|
|
188
|
+
pos++;
|
|
189
|
+
return token = 1;
|
|
190
|
+
case 125:
|
|
191
|
+
pos++;
|
|
192
|
+
return token = 2;
|
|
193
|
+
case 91:
|
|
194
|
+
pos++;
|
|
195
|
+
return token = 3;
|
|
196
|
+
case 93:
|
|
197
|
+
pos++;
|
|
198
|
+
return token = 4;
|
|
199
|
+
case 58:
|
|
200
|
+
pos++;
|
|
201
|
+
return token = 6;
|
|
202
|
+
case 44:
|
|
203
|
+
pos++;
|
|
204
|
+
return token = 5;
|
|
205
|
+
case 34:
|
|
206
|
+
pos++;
|
|
207
|
+
value = scanString();
|
|
208
|
+
return token = 10;
|
|
209
|
+
case 47:
|
|
210
|
+
const start = pos - 1;
|
|
211
|
+
if (text.charCodeAt(pos + 1) === 47) {
|
|
212
|
+
pos += 2;
|
|
213
|
+
while (pos < len) {
|
|
214
|
+
if (isLineBreak(text.charCodeAt(pos))) {
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
pos++;
|
|
218
|
+
}
|
|
219
|
+
value = text.substring(start, pos);
|
|
220
|
+
return token = 12;
|
|
221
|
+
}
|
|
222
|
+
if (text.charCodeAt(pos + 1) === 42) {
|
|
223
|
+
pos += 2;
|
|
224
|
+
const safeLength = len - 1;
|
|
225
|
+
let commentClosed = false;
|
|
226
|
+
while (pos < safeLength) {
|
|
227
|
+
const ch = text.charCodeAt(pos);
|
|
228
|
+
if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
|
|
229
|
+
pos += 2;
|
|
230
|
+
commentClosed = true;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
pos++;
|
|
234
|
+
if (isLineBreak(ch)) {
|
|
235
|
+
if (ch === 13 && text.charCodeAt(pos) === 10) {
|
|
236
|
+
pos++;
|
|
237
|
+
}
|
|
238
|
+
lineNumber++;
|
|
239
|
+
tokenLineStartOffset = pos;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (!commentClosed) {
|
|
243
|
+
pos++;
|
|
244
|
+
scanError = 1;
|
|
245
|
+
}
|
|
246
|
+
value = text.substring(start, pos);
|
|
247
|
+
return token = 13;
|
|
248
|
+
}
|
|
249
|
+
value += String.fromCharCode(code);
|
|
250
|
+
pos++;
|
|
251
|
+
return token = 16;
|
|
252
|
+
case 45:
|
|
253
|
+
value += String.fromCharCode(code);
|
|
254
|
+
pos++;
|
|
255
|
+
if (pos === len || !isDigit(text.charCodeAt(pos))) {
|
|
256
|
+
return token = 16;
|
|
257
|
+
}
|
|
258
|
+
case 48:
|
|
259
|
+
case 49:
|
|
260
|
+
case 50:
|
|
261
|
+
case 51:
|
|
262
|
+
case 52:
|
|
263
|
+
case 53:
|
|
264
|
+
case 54:
|
|
265
|
+
case 55:
|
|
266
|
+
case 56:
|
|
267
|
+
case 57:
|
|
268
|
+
value += scanNumber();
|
|
269
|
+
return token = 11;
|
|
270
|
+
default:
|
|
271
|
+
while (pos < len && isUnknownContentCharacter(code)) {
|
|
272
|
+
pos++;
|
|
273
|
+
code = text.charCodeAt(pos);
|
|
274
|
+
}
|
|
275
|
+
if (tokenOffset !== pos) {
|
|
276
|
+
value = text.substring(tokenOffset, pos);
|
|
277
|
+
switch (value) {
|
|
278
|
+
case "true":
|
|
279
|
+
return token = 8;
|
|
280
|
+
case "false":
|
|
281
|
+
return token = 9;
|
|
282
|
+
case "null":
|
|
283
|
+
return token = 7;
|
|
284
|
+
}
|
|
285
|
+
return token = 16;
|
|
286
|
+
}
|
|
287
|
+
value += String.fromCharCode(code);
|
|
288
|
+
pos++;
|
|
289
|
+
return token = 16;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function isUnknownContentCharacter(code) {
|
|
293
|
+
if (isWhiteSpace(code) || isLineBreak(code)) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
switch (code) {
|
|
297
|
+
case 125:
|
|
298
|
+
case 93:
|
|
299
|
+
case 123:
|
|
300
|
+
case 91:
|
|
301
|
+
case 34:
|
|
302
|
+
case 58:
|
|
303
|
+
case 44:
|
|
304
|
+
case 47:
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
function scanNextNonTrivia() {
|
|
310
|
+
let result;
|
|
311
|
+
do {
|
|
312
|
+
result = scanNext();
|
|
313
|
+
} while (result >= 12 && result <= 15);
|
|
314
|
+
return result;
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
setPosition,
|
|
318
|
+
getPosition: () => pos,
|
|
319
|
+
scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
|
|
320
|
+
getToken: () => token,
|
|
321
|
+
getTokenValue: () => value,
|
|
322
|
+
getTokenOffset: () => tokenOffset,
|
|
323
|
+
getTokenLength: () => pos - tokenOffset,
|
|
324
|
+
getTokenStartLine: () => lineStartOffset,
|
|
325
|
+
getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,
|
|
326
|
+
getTokenError: () => scanError
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
function isWhiteSpace(ch) {
|
|
330
|
+
return ch === 32 || ch === 9;
|
|
331
|
+
}
|
|
332
|
+
function isLineBreak(ch) {
|
|
333
|
+
return ch === 10 || ch === 13;
|
|
334
|
+
}
|
|
335
|
+
function isDigit(ch) {
|
|
336
|
+
return ch >= 48 && ch <= 57;
|
|
337
|
+
}
|
|
338
|
+
var CharacterCodes;
|
|
339
|
+
(function(CharacterCodes2) {
|
|
340
|
+
CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed";
|
|
341
|
+
CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn";
|
|
342
|
+
CharacterCodes2[CharacterCodes2["space"] = 32] = "space";
|
|
343
|
+
CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0";
|
|
344
|
+
CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1";
|
|
345
|
+
CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2";
|
|
346
|
+
CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3";
|
|
347
|
+
CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4";
|
|
348
|
+
CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5";
|
|
349
|
+
CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6";
|
|
350
|
+
CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7";
|
|
351
|
+
CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8";
|
|
352
|
+
CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9";
|
|
353
|
+
CharacterCodes2[CharacterCodes2["a"] = 97] = "a";
|
|
354
|
+
CharacterCodes2[CharacterCodes2["b"] = 98] = "b";
|
|
355
|
+
CharacterCodes2[CharacterCodes2["c"] = 99] = "c";
|
|
356
|
+
CharacterCodes2[CharacterCodes2["d"] = 100] = "d";
|
|
357
|
+
CharacterCodes2[CharacterCodes2["e"] = 101] = "e";
|
|
358
|
+
CharacterCodes2[CharacterCodes2["f"] = 102] = "f";
|
|
359
|
+
CharacterCodes2[CharacterCodes2["g"] = 103] = "g";
|
|
360
|
+
CharacterCodes2[CharacterCodes2["h"] = 104] = "h";
|
|
361
|
+
CharacterCodes2[CharacterCodes2["i"] = 105] = "i";
|
|
362
|
+
CharacterCodes2[CharacterCodes2["j"] = 106] = "j";
|
|
363
|
+
CharacterCodes2[CharacterCodes2["k"] = 107] = "k";
|
|
364
|
+
CharacterCodes2[CharacterCodes2["l"] = 108] = "l";
|
|
365
|
+
CharacterCodes2[CharacterCodes2["m"] = 109] = "m";
|
|
366
|
+
CharacterCodes2[CharacterCodes2["n"] = 110] = "n";
|
|
367
|
+
CharacterCodes2[CharacterCodes2["o"] = 111] = "o";
|
|
368
|
+
CharacterCodes2[CharacterCodes2["p"] = 112] = "p";
|
|
369
|
+
CharacterCodes2[CharacterCodes2["q"] = 113] = "q";
|
|
370
|
+
CharacterCodes2[CharacterCodes2["r"] = 114] = "r";
|
|
371
|
+
CharacterCodes2[CharacterCodes2["s"] = 115] = "s";
|
|
372
|
+
CharacterCodes2[CharacterCodes2["t"] = 116] = "t";
|
|
373
|
+
CharacterCodes2[CharacterCodes2["u"] = 117] = "u";
|
|
374
|
+
CharacterCodes2[CharacterCodes2["v"] = 118] = "v";
|
|
375
|
+
CharacterCodes2[CharacterCodes2["w"] = 119] = "w";
|
|
376
|
+
CharacterCodes2[CharacterCodes2["x"] = 120] = "x";
|
|
377
|
+
CharacterCodes2[CharacterCodes2["y"] = 121] = "y";
|
|
378
|
+
CharacterCodes2[CharacterCodes2["z"] = 122] = "z";
|
|
379
|
+
CharacterCodes2[CharacterCodes2["A"] = 65] = "A";
|
|
380
|
+
CharacterCodes2[CharacterCodes2["B"] = 66] = "B";
|
|
381
|
+
CharacterCodes2[CharacterCodes2["C"] = 67] = "C";
|
|
382
|
+
CharacterCodes2[CharacterCodes2["D"] = 68] = "D";
|
|
383
|
+
CharacterCodes2[CharacterCodes2["E"] = 69] = "E";
|
|
384
|
+
CharacterCodes2[CharacterCodes2["F"] = 70] = "F";
|
|
385
|
+
CharacterCodes2[CharacterCodes2["G"] = 71] = "G";
|
|
386
|
+
CharacterCodes2[CharacterCodes2["H"] = 72] = "H";
|
|
387
|
+
CharacterCodes2[CharacterCodes2["I"] = 73] = "I";
|
|
388
|
+
CharacterCodes2[CharacterCodes2["J"] = 74] = "J";
|
|
389
|
+
CharacterCodes2[CharacterCodes2["K"] = 75] = "K";
|
|
390
|
+
CharacterCodes2[CharacterCodes2["L"] = 76] = "L";
|
|
391
|
+
CharacterCodes2[CharacterCodes2["M"] = 77] = "M";
|
|
392
|
+
CharacterCodes2[CharacterCodes2["N"] = 78] = "N";
|
|
393
|
+
CharacterCodes2[CharacterCodes2["O"] = 79] = "O";
|
|
394
|
+
CharacterCodes2[CharacterCodes2["P"] = 80] = "P";
|
|
395
|
+
CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q";
|
|
396
|
+
CharacterCodes2[CharacterCodes2["R"] = 82] = "R";
|
|
397
|
+
CharacterCodes2[CharacterCodes2["S"] = 83] = "S";
|
|
398
|
+
CharacterCodes2[CharacterCodes2["T"] = 84] = "T";
|
|
399
|
+
CharacterCodes2[CharacterCodes2["U"] = 85] = "U";
|
|
400
|
+
CharacterCodes2[CharacterCodes2["V"] = 86] = "V";
|
|
401
|
+
CharacterCodes2[CharacterCodes2["W"] = 87] = "W";
|
|
402
|
+
CharacterCodes2[CharacterCodes2["X"] = 88] = "X";
|
|
403
|
+
CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y";
|
|
404
|
+
CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z";
|
|
405
|
+
CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk";
|
|
406
|
+
CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash";
|
|
407
|
+
CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace";
|
|
408
|
+
CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket";
|
|
409
|
+
CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon";
|
|
410
|
+
CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma";
|
|
411
|
+
CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot";
|
|
412
|
+
CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote";
|
|
413
|
+
CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus";
|
|
414
|
+
CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace";
|
|
415
|
+
CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket";
|
|
416
|
+
CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus";
|
|
417
|
+
CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash";
|
|
418
|
+
CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed";
|
|
419
|
+
CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab";
|
|
420
|
+
})(CharacterCodes || (CharacterCodes = {}));
|
|
421
|
+
|
|
422
|
+
// node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/string-intern.js
|
|
423
|
+
var cachedSpaces = new Array(20).fill(0).map((_, index) => {
|
|
424
|
+
return " ".repeat(index);
|
|
425
|
+
});
|
|
426
|
+
var maxCachedValues = 200;
|
|
427
|
+
var cachedBreakLinesWithSpaces = {
|
|
428
|
+
" ": {
|
|
429
|
+
"\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
430
|
+
return `
|
|
431
|
+
` + " ".repeat(index);
|
|
432
|
+
}),
|
|
433
|
+
"\r": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
434
|
+
return "\r" + " ".repeat(index);
|
|
435
|
+
}),
|
|
436
|
+
"\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
437
|
+
return `\r
|
|
438
|
+
` + " ".repeat(index);
|
|
439
|
+
})
|
|
440
|
+
},
|
|
441
|
+
"\t": {
|
|
442
|
+
"\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
443
|
+
return `
|
|
444
|
+
` + "\t".repeat(index);
|
|
445
|
+
}),
|
|
446
|
+
"\r": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
447
|
+
return "\r" + "\t".repeat(index);
|
|
448
|
+
}),
|
|
449
|
+
"\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
450
|
+
return `\r
|
|
451
|
+
` + "\t".repeat(index);
|
|
452
|
+
})
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
// node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/parser.js
|
|
457
|
+
var ParseOptions;
|
|
458
|
+
(function(ParseOptions2) {
|
|
459
|
+
ParseOptions2.DEFAULT = {
|
|
460
|
+
allowTrailingComma: false
|
|
461
|
+
};
|
|
462
|
+
})(ParseOptions || (ParseOptions = {}));
|
|
463
|
+
function parse(text, errors = [], options = ParseOptions.DEFAULT) {
|
|
464
|
+
let currentProperty = null;
|
|
465
|
+
let currentParent = [];
|
|
466
|
+
const previousParents = [];
|
|
467
|
+
function onValue(value) {
|
|
468
|
+
if (Array.isArray(currentParent)) {
|
|
469
|
+
currentParent.push(value);
|
|
470
|
+
} else if (currentProperty !== null) {
|
|
471
|
+
currentParent[currentProperty] = value;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
const visitor = {
|
|
475
|
+
onObjectBegin: () => {
|
|
476
|
+
const object = {};
|
|
477
|
+
onValue(object);
|
|
478
|
+
previousParents.push(currentParent);
|
|
479
|
+
currentParent = object;
|
|
480
|
+
currentProperty = null;
|
|
481
|
+
},
|
|
482
|
+
onObjectProperty: (name) => {
|
|
483
|
+
currentProperty = name;
|
|
484
|
+
},
|
|
485
|
+
onObjectEnd: () => {
|
|
486
|
+
currentParent = previousParents.pop();
|
|
487
|
+
},
|
|
488
|
+
onArrayBegin: () => {
|
|
489
|
+
const array = [];
|
|
490
|
+
onValue(array);
|
|
491
|
+
previousParents.push(currentParent);
|
|
492
|
+
currentParent = array;
|
|
493
|
+
currentProperty = null;
|
|
494
|
+
},
|
|
495
|
+
onArrayEnd: () => {
|
|
496
|
+
currentParent = previousParents.pop();
|
|
497
|
+
},
|
|
498
|
+
onLiteralValue: onValue,
|
|
499
|
+
onError: (error, offset, length) => {
|
|
500
|
+
errors.push({ error, offset, length });
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
visit(text, visitor, options);
|
|
504
|
+
return currentParent[0];
|
|
505
|
+
}
|
|
506
|
+
function visit(text, visitor, options = ParseOptions.DEFAULT) {
|
|
507
|
+
const _scanner = createScanner(text, false);
|
|
508
|
+
const _jsonPath = [];
|
|
509
|
+
let suppressedCallbacks = 0;
|
|
510
|
+
function toNoArgVisit(visitFunction) {
|
|
511
|
+
return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
|
|
512
|
+
}
|
|
513
|
+
function toOneArgVisit(visitFunction) {
|
|
514
|
+
return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
|
|
515
|
+
}
|
|
516
|
+
function toOneArgVisitWithPath(visitFunction) {
|
|
517
|
+
return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;
|
|
518
|
+
}
|
|
519
|
+
function toBeginVisit(visitFunction) {
|
|
520
|
+
return visitFunction ? () => {
|
|
521
|
+
if (suppressedCallbacks > 0) {
|
|
522
|
+
suppressedCallbacks++;
|
|
523
|
+
} else {
|
|
524
|
+
let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());
|
|
525
|
+
if (cbReturn === false) {
|
|
526
|
+
suppressedCallbacks = 1;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
} : () => true;
|
|
530
|
+
}
|
|
531
|
+
function toEndVisit(visitFunction) {
|
|
532
|
+
return visitFunction ? () => {
|
|
533
|
+
if (suppressedCallbacks > 0) {
|
|
534
|
+
suppressedCallbacks--;
|
|
535
|
+
}
|
|
536
|
+
if (suppressedCallbacks === 0) {
|
|
537
|
+
visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
|
|
538
|
+
}
|
|
539
|
+
} : () => true;
|
|
540
|
+
}
|
|
541
|
+
const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);
|
|
542
|
+
const disallowComments = options && options.disallowComments;
|
|
543
|
+
const allowTrailingComma = options && options.allowTrailingComma;
|
|
544
|
+
function scanNext() {
|
|
545
|
+
while (true) {
|
|
546
|
+
const token = _scanner.scan();
|
|
547
|
+
switch (_scanner.getTokenError()) {
|
|
548
|
+
case 4:
|
|
549
|
+
handleError(14);
|
|
550
|
+
break;
|
|
551
|
+
case 5:
|
|
552
|
+
handleError(15);
|
|
553
|
+
break;
|
|
554
|
+
case 3:
|
|
555
|
+
handleError(13);
|
|
556
|
+
break;
|
|
557
|
+
case 1:
|
|
558
|
+
if (!disallowComments) {
|
|
559
|
+
handleError(11);
|
|
560
|
+
}
|
|
561
|
+
break;
|
|
562
|
+
case 2:
|
|
563
|
+
handleError(12);
|
|
564
|
+
break;
|
|
565
|
+
case 6:
|
|
566
|
+
handleError(16);
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
switch (token) {
|
|
570
|
+
case 12:
|
|
571
|
+
case 13:
|
|
572
|
+
if (disallowComments) {
|
|
573
|
+
handleError(10);
|
|
574
|
+
} else {
|
|
575
|
+
onComment();
|
|
576
|
+
}
|
|
577
|
+
break;
|
|
578
|
+
case 16:
|
|
579
|
+
handleError(1);
|
|
580
|
+
break;
|
|
581
|
+
case 15:
|
|
582
|
+
case 14:
|
|
583
|
+
break;
|
|
584
|
+
default:
|
|
585
|
+
return token;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
function handleError(error, skipUntilAfter = [], skipUntil = []) {
|
|
590
|
+
onError(error);
|
|
591
|
+
if (skipUntilAfter.length + skipUntil.length > 0) {
|
|
592
|
+
let token = _scanner.getToken();
|
|
593
|
+
while (token !== 17) {
|
|
594
|
+
if (skipUntilAfter.indexOf(token) !== -1) {
|
|
595
|
+
scanNext();
|
|
596
|
+
break;
|
|
597
|
+
} else if (skipUntil.indexOf(token) !== -1) {
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
token = scanNext();
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
function parseString(isValue) {
|
|
605
|
+
const value = _scanner.getTokenValue();
|
|
606
|
+
if (isValue) {
|
|
607
|
+
onLiteralValue(value);
|
|
608
|
+
} else {
|
|
609
|
+
onObjectProperty(value);
|
|
610
|
+
_jsonPath.push(value);
|
|
611
|
+
}
|
|
612
|
+
scanNext();
|
|
613
|
+
return true;
|
|
614
|
+
}
|
|
615
|
+
function parseLiteral() {
|
|
616
|
+
switch (_scanner.getToken()) {
|
|
617
|
+
case 11:
|
|
618
|
+
const tokenValue = _scanner.getTokenValue();
|
|
619
|
+
let value = Number(tokenValue);
|
|
620
|
+
if (isNaN(value)) {
|
|
621
|
+
handleError(2);
|
|
622
|
+
value = 0;
|
|
623
|
+
}
|
|
624
|
+
onLiteralValue(value);
|
|
625
|
+
break;
|
|
626
|
+
case 7:
|
|
627
|
+
onLiteralValue(null);
|
|
628
|
+
break;
|
|
629
|
+
case 8:
|
|
630
|
+
onLiteralValue(true);
|
|
631
|
+
break;
|
|
632
|
+
case 9:
|
|
633
|
+
onLiteralValue(false);
|
|
634
|
+
break;
|
|
635
|
+
default:
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
scanNext();
|
|
639
|
+
return true;
|
|
640
|
+
}
|
|
641
|
+
function parseProperty() {
|
|
642
|
+
if (_scanner.getToken() !== 10) {
|
|
643
|
+
handleError(3, [], [2, 5]);
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
parseString(false);
|
|
647
|
+
if (_scanner.getToken() === 6) {
|
|
648
|
+
onSeparator(":");
|
|
649
|
+
scanNext();
|
|
650
|
+
if (!parseValue()) {
|
|
651
|
+
handleError(4, [], [2, 5]);
|
|
652
|
+
}
|
|
653
|
+
} else {
|
|
654
|
+
handleError(5, [], [2, 5]);
|
|
655
|
+
}
|
|
656
|
+
_jsonPath.pop();
|
|
657
|
+
return true;
|
|
658
|
+
}
|
|
659
|
+
function parseObject() {
|
|
660
|
+
onObjectBegin();
|
|
661
|
+
scanNext();
|
|
662
|
+
let needsComma = false;
|
|
663
|
+
while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
|
|
664
|
+
if (_scanner.getToken() === 5) {
|
|
665
|
+
if (!needsComma) {
|
|
666
|
+
handleError(4, [], []);
|
|
667
|
+
}
|
|
668
|
+
onSeparator(",");
|
|
669
|
+
scanNext();
|
|
670
|
+
if (_scanner.getToken() === 2 && allowTrailingComma) {
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
673
|
+
} else if (needsComma) {
|
|
674
|
+
handleError(6, [], []);
|
|
675
|
+
}
|
|
676
|
+
if (!parseProperty()) {
|
|
677
|
+
handleError(4, [], [2, 5]);
|
|
678
|
+
}
|
|
679
|
+
needsComma = true;
|
|
680
|
+
}
|
|
681
|
+
onObjectEnd();
|
|
682
|
+
if (_scanner.getToken() !== 2) {
|
|
683
|
+
handleError(7, [2], []);
|
|
684
|
+
} else {
|
|
685
|
+
scanNext();
|
|
686
|
+
}
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
function parseArray() {
|
|
690
|
+
onArrayBegin();
|
|
691
|
+
scanNext();
|
|
692
|
+
let isFirstElement = true;
|
|
693
|
+
let needsComma = false;
|
|
694
|
+
while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
|
|
695
|
+
if (_scanner.getToken() === 5) {
|
|
696
|
+
if (!needsComma) {
|
|
697
|
+
handleError(4, [], []);
|
|
698
|
+
}
|
|
699
|
+
onSeparator(",");
|
|
700
|
+
scanNext();
|
|
701
|
+
if (_scanner.getToken() === 4 && allowTrailingComma) {
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
704
|
+
} else if (needsComma) {
|
|
705
|
+
handleError(6, [], []);
|
|
706
|
+
}
|
|
707
|
+
if (isFirstElement) {
|
|
708
|
+
_jsonPath.push(0);
|
|
709
|
+
isFirstElement = false;
|
|
710
|
+
} else {
|
|
711
|
+
_jsonPath[_jsonPath.length - 1]++;
|
|
712
|
+
}
|
|
713
|
+
if (!parseValue()) {
|
|
714
|
+
handleError(4, [], [4, 5]);
|
|
715
|
+
}
|
|
716
|
+
needsComma = true;
|
|
717
|
+
}
|
|
718
|
+
onArrayEnd();
|
|
719
|
+
if (!isFirstElement) {
|
|
720
|
+
_jsonPath.pop();
|
|
721
|
+
}
|
|
722
|
+
if (_scanner.getToken() !== 4) {
|
|
723
|
+
handleError(8, [4], []);
|
|
724
|
+
} else {
|
|
725
|
+
scanNext();
|
|
726
|
+
}
|
|
727
|
+
return true;
|
|
728
|
+
}
|
|
729
|
+
function parseValue() {
|
|
730
|
+
switch (_scanner.getToken()) {
|
|
731
|
+
case 3:
|
|
732
|
+
return parseArray();
|
|
733
|
+
case 1:
|
|
734
|
+
return parseObject();
|
|
735
|
+
case 10:
|
|
736
|
+
return parseString(true);
|
|
737
|
+
default:
|
|
738
|
+
return parseLiteral();
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
scanNext();
|
|
742
|
+
if (_scanner.getToken() === 17) {
|
|
743
|
+
if (options.allowEmptyContent) {
|
|
744
|
+
return true;
|
|
745
|
+
}
|
|
746
|
+
handleError(4, [], []);
|
|
747
|
+
return false;
|
|
748
|
+
}
|
|
749
|
+
if (!parseValue()) {
|
|
750
|
+
handleError(4, [], []);
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
753
|
+
if (_scanner.getToken() !== 17) {
|
|
754
|
+
handleError(9, [], []);
|
|
755
|
+
}
|
|
756
|
+
return true;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/main.js
|
|
760
|
+
var ScanError;
|
|
761
|
+
(function(ScanError2) {
|
|
762
|
+
ScanError2[ScanError2["None"] = 0] = "None";
|
|
763
|
+
ScanError2[ScanError2["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
|
|
764
|
+
ScanError2[ScanError2["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
|
|
765
|
+
ScanError2[ScanError2["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
|
|
766
|
+
ScanError2[ScanError2["InvalidUnicode"] = 4] = "InvalidUnicode";
|
|
767
|
+
ScanError2[ScanError2["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
|
|
768
|
+
ScanError2[ScanError2["InvalidCharacter"] = 6] = "InvalidCharacter";
|
|
769
|
+
})(ScanError || (ScanError = {}));
|
|
770
|
+
var SyntaxKind;
|
|
771
|
+
(function(SyntaxKind2) {
|
|
772
|
+
SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 1] = "OpenBraceToken";
|
|
773
|
+
SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 2] = "CloseBraceToken";
|
|
774
|
+
SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 3] = "OpenBracketToken";
|
|
775
|
+
SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 4] = "CloseBracketToken";
|
|
776
|
+
SyntaxKind2[SyntaxKind2["CommaToken"] = 5] = "CommaToken";
|
|
777
|
+
SyntaxKind2[SyntaxKind2["ColonToken"] = 6] = "ColonToken";
|
|
778
|
+
SyntaxKind2[SyntaxKind2["NullKeyword"] = 7] = "NullKeyword";
|
|
779
|
+
SyntaxKind2[SyntaxKind2["TrueKeyword"] = 8] = "TrueKeyword";
|
|
780
|
+
SyntaxKind2[SyntaxKind2["FalseKeyword"] = 9] = "FalseKeyword";
|
|
781
|
+
SyntaxKind2[SyntaxKind2["StringLiteral"] = 10] = "StringLiteral";
|
|
782
|
+
SyntaxKind2[SyntaxKind2["NumericLiteral"] = 11] = "NumericLiteral";
|
|
783
|
+
SyntaxKind2[SyntaxKind2["LineCommentTrivia"] = 12] = "LineCommentTrivia";
|
|
784
|
+
SyntaxKind2[SyntaxKind2["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
|
|
785
|
+
SyntaxKind2[SyntaxKind2["LineBreakTrivia"] = 14] = "LineBreakTrivia";
|
|
786
|
+
SyntaxKind2[SyntaxKind2["Trivia"] = 15] = "Trivia";
|
|
787
|
+
SyntaxKind2[SyntaxKind2["Unknown"] = 16] = "Unknown";
|
|
788
|
+
SyntaxKind2[SyntaxKind2["EOF"] = 17] = "EOF";
|
|
789
|
+
})(SyntaxKind || (SyntaxKind = {}));
|
|
790
|
+
var parse2 = parse;
|
|
791
|
+
var ParseErrorCode;
|
|
792
|
+
(function(ParseErrorCode2) {
|
|
793
|
+
ParseErrorCode2[ParseErrorCode2["InvalidSymbol"] = 1] = "InvalidSymbol";
|
|
794
|
+
ParseErrorCode2[ParseErrorCode2["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
|
|
795
|
+
ParseErrorCode2[ParseErrorCode2["PropertyNameExpected"] = 3] = "PropertyNameExpected";
|
|
796
|
+
ParseErrorCode2[ParseErrorCode2["ValueExpected"] = 4] = "ValueExpected";
|
|
797
|
+
ParseErrorCode2[ParseErrorCode2["ColonExpected"] = 5] = "ColonExpected";
|
|
798
|
+
ParseErrorCode2[ParseErrorCode2["CommaExpected"] = 6] = "CommaExpected";
|
|
799
|
+
ParseErrorCode2[ParseErrorCode2["CloseBraceExpected"] = 7] = "CloseBraceExpected";
|
|
800
|
+
ParseErrorCode2[ParseErrorCode2["CloseBracketExpected"] = 8] = "CloseBracketExpected";
|
|
801
|
+
ParseErrorCode2[ParseErrorCode2["EndOfFileExpected"] = 9] = "EndOfFileExpected";
|
|
802
|
+
ParseErrorCode2[ParseErrorCode2["InvalidCommentToken"] = 10] = "InvalidCommentToken";
|
|
803
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
|
|
804
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
|
|
805
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
|
|
806
|
+
ParseErrorCode2[ParseErrorCode2["InvalidUnicode"] = 14] = "InvalidUnicode";
|
|
807
|
+
ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
|
|
808
|
+
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
809
|
+
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
810
|
+
|
|
811
|
+
// src/lib/config.ts
|
|
812
|
+
var DEFAULT_CONFIG = {
|
|
813
|
+
disabled_skills: [],
|
|
814
|
+
disabled_agents: [],
|
|
815
|
+
disabled_commands: [],
|
|
816
|
+
bootstrap: {
|
|
817
|
+
enabled: true
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
function loadJsoncFile(filePath) {
|
|
821
|
+
try {
|
|
822
|
+
if (!fs.existsSync(filePath))
|
|
823
|
+
return null;
|
|
824
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
825
|
+
return parse2(content);
|
|
826
|
+
} catch {
|
|
827
|
+
return null;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
function mergeArraysUnique(arr1, arr2) {
|
|
831
|
+
const set = new Set;
|
|
832
|
+
if (arr1)
|
|
833
|
+
for (const item of arr1)
|
|
834
|
+
set.add(item);
|
|
835
|
+
if (arr2)
|
|
836
|
+
for (const item of arr2)
|
|
837
|
+
set.add(item);
|
|
838
|
+
return Array.from(set);
|
|
839
|
+
}
|
|
840
|
+
function loadConfig(projectDir) {
|
|
841
|
+
const paths = getConfigPaths(projectDir);
|
|
842
|
+
const userConfig = loadJsoncFile(paths.userConfig);
|
|
843
|
+
const projectConfig = loadJsoncFile(paths.projectConfig);
|
|
844
|
+
const customConfig = paths.customConfig ? loadJsoncFile(paths.customConfig) : null;
|
|
845
|
+
const result = {
|
|
846
|
+
disabled_skills: mergeArraysUnique(mergeArraysUnique(mergeArraysUnique(DEFAULT_CONFIG.disabled_skills, userConfig?.disabled_skills), projectConfig?.disabled_skills), customConfig?.disabled_skills),
|
|
847
|
+
disabled_agents: mergeArraysUnique(mergeArraysUnique(mergeArraysUnique(DEFAULT_CONFIG.disabled_agents, userConfig?.disabled_agents), projectConfig?.disabled_agents), customConfig?.disabled_agents),
|
|
848
|
+
disabled_commands: mergeArraysUnique(mergeArraysUnique(mergeArraysUnique(DEFAULT_CONFIG.disabled_commands, userConfig?.disabled_commands), projectConfig?.disabled_commands), customConfig?.disabled_commands),
|
|
849
|
+
bootstrap: {
|
|
850
|
+
...DEFAULT_CONFIG.bootstrap,
|
|
851
|
+
...userConfig?.bootstrap,
|
|
852
|
+
...projectConfig?.bootstrap,
|
|
853
|
+
...customConfig?.bootstrap
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
return result;
|
|
857
|
+
}
|
|
858
|
+
function getConfigPaths(projectDir) {
|
|
859
|
+
const homeDir = os.homedir();
|
|
860
|
+
const customConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
861
|
+
const result = {
|
|
862
|
+
userConfig: path.join(homeDir, ".config/opencode/systematic.json"),
|
|
863
|
+
projectConfig: path.join(projectDir, ".opencode/systematic.json"),
|
|
864
|
+
userDir: path.join(homeDir, ".config/opencode/systematic"),
|
|
865
|
+
projectDir: path.join(projectDir, ".opencode/systematic"),
|
|
866
|
+
...customConfigDir && {
|
|
867
|
+
customConfig: path.join(customConfigDir, "systematic.json"),
|
|
868
|
+
customDir: path.join(customConfigDir, "systematic")
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
return result;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// src/lib/frontmatter.ts
|
|
875
|
+
import yaml from "js-yaml";
|
|
876
|
+
function parseFrontmatter(content) {
|
|
877
|
+
const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n?---\r?\n([\s\S]*)$/;
|
|
878
|
+
const match = content.match(frontmatterRegex);
|
|
879
|
+
if (!match) {
|
|
880
|
+
return {
|
|
881
|
+
data: {},
|
|
882
|
+
body: content,
|
|
883
|
+
hadFrontmatter: false,
|
|
884
|
+
parseError: false
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
const yamlContent = match[1];
|
|
888
|
+
const body = match[2];
|
|
889
|
+
try {
|
|
890
|
+
const parsed = yaml.load(yamlContent, { schema: yaml.JSON_SCHEMA });
|
|
891
|
+
const data = parsed ?? {};
|
|
892
|
+
return { data, body, hadFrontmatter: true, parseError: false };
|
|
893
|
+
} catch {
|
|
894
|
+
return { data: {}, body, hadFrontmatter: true, parseError: true };
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
function formatFrontmatter(data) {
|
|
898
|
+
if (Object.keys(data).length === 0) {
|
|
899
|
+
return ["---", "---"].join(`
|
|
900
|
+
`);
|
|
901
|
+
}
|
|
902
|
+
const yamlContent = yaml.dump(data, {
|
|
903
|
+
schema: yaml.JSON_SCHEMA,
|
|
904
|
+
lineWidth: -1,
|
|
905
|
+
noRefs: true
|
|
906
|
+
}).trimEnd();
|
|
907
|
+
return ["---", yamlContent, "---"].join(`
|
|
908
|
+
`);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// src/lib/validation.ts
|
|
912
|
+
function isRecord(value) {
|
|
913
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
914
|
+
}
|
|
915
|
+
function isPermissionSetting(value) {
|
|
916
|
+
return value === "ask" || value === "allow" || value === "deny";
|
|
917
|
+
}
|
|
918
|
+
function isToolsMap(value) {
|
|
919
|
+
if (!isRecord(value))
|
|
920
|
+
return false;
|
|
921
|
+
return Object.values(value).every((entry) => typeof entry === "boolean");
|
|
922
|
+
}
|
|
923
|
+
function isAgentMode(value) {
|
|
924
|
+
return value === "subagent" || value === "primary" || value === "all";
|
|
925
|
+
}
|
|
926
|
+
function extractSimplePermission(data, key) {
|
|
927
|
+
if (!(key in data))
|
|
928
|
+
return;
|
|
929
|
+
const value = data[key];
|
|
930
|
+
return isPermissionSetting(value) ? value : null;
|
|
931
|
+
}
|
|
932
|
+
function extractBashPermission(data) {
|
|
933
|
+
if (!("bash" in data))
|
|
934
|
+
return;
|
|
935
|
+
const bash = data.bash;
|
|
936
|
+
if (isPermissionSetting(bash))
|
|
937
|
+
return bash;
|
|
938
|
+
if (isRecord(bash)) {
|
|
939
|
+
const entries = Object.entries(bash);
|
|
940
|
+
if (entries.every(([, setting]) => isPermissionSetting(setting))) {
|
|
941
|
+
return Object.fromEntries(entries);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
function buildPermissionObject(edit, bash, webfetch, doom_loop, external_directory, task, skill) {
|
|
947
|
+
const permission = {};
|
|
948
|
+
if (edit)
|
|
949
|
+
permission.edit = edit;
|
|
950
|
+
if (bash)
|
|
951
|
+
permission.bash = bash;
|
|
952
|
+
if (webfetch)
|
|
953
|
+
permission.webfetch = webfetch;
|
|
954
|
+
if (doom_loop)
|
|
955
|
+
permission.doom_loop = doom_loop;
|
|
956
|
+
if (external_directory)
|
|
957
|
+
permission.external_directory = external_directory;
|
|
958
|
+
if (task)
|
|
959
|
+
permission.task = task;
|
|
960
|
+
if (skill)
|
|
961
|
+
permission.skill = skill;
|
|
962
|
+
return Object.keys(permission).length > 0 ? permission : undefined;
|
|
963
|
+
}
|
|
964
|
+
function normalizePermission(value) {
|
|
965
|
+
if (!isRecord(value))
|
|
966
|
+
return;
|
|
967
|
+
const bash = extractBashPermission(value);
|
|
968
|
+
if (bash === null)
|
|
969
|
+
return;
|
|
970
|
+
const edit = extractSimplePermission(value, "edit");
|
|
971
|
+
if (edit === null)
|
|
972
|
+
return;
|
|
973
|
+
const webfetch = extractSimplePermission(value, "webfetch");
|
|
974
|
+
if (webfetch === null)
|
|
975
|
+
return;
|
|
976
|
+
const doom_loop = extractSimplePermission(value, "doom_loop");
|
|
977
|
+
if (doom_loop === null)
|
|
978
|
+
return;
|
|
979
|
+
const external_directory = extractSimplePermission(value, "external_directory");
|
|
980
|
+
if (external_directory === null)
|
|
981
|
+
return;
|
|
982
|
+
const task = extractSimplePermission(value, "task");
|
|
983
|
+
if (task === null)
|
|
984
|
+
return;
|
|
985
|
+
const skill = extractSimplePermission(value, "skill");
|
|
986
|
+
if (skill === null)
|
|
987
|
+
return;
|
|
988
|
+
return buildPermissionObject(edit, bash, webfetch, doom_loop, external_directory, task, skill);
|
|
989
|
+
}
|
|
990
|
+
function extractString(data, key, fallback = "") {
|
|
991
|
+
const value = data[key];
|
|
992
|
+
return typeof value === "string" ? value : fallback;
|
|
993
|
+
}
|
|
994
|
+
function extractNonEmptyString(data, key) {
|
|
995
|
+
const value = data[key];
|
|
996
|
+
if (typeof value !== "string")
|
|
997
|
+
return;
|
|
998
|
+
const trimmed = value.trim();
|
|
999
|
+
return trimmed !== "" ? trimmed : undefined;
|
|
1000
|
+
}
|
|
1001
|
+
function extractNumber(data, key) {
|
|
1002
|
+
const value = data[key];
|
|
1003
|
+
return typeof value === "number" ? value : undefined;
|
|
1004
|
+
}
|
|
1005
|
+
function extractBoolean(data, key) {
|
|
1006
|
+
const value = data[key];
|
|
1007
|
+
if (typeof value === "boolean")
|
|
1008
|
+
return value;
|
|
1009
|
+
if (typeof value === "string") {
|
|
1010
|
+
const normalized = value.trim().toLowerCase();
|
|
1011
|
+
if (normalized === "true")
|
|
1012
|
+
return true;
|
|
1013
|
+
if (normalized === "false")
|
|
1014
|
+
return false;
|
|
1015
|
+
}
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// src/lib/walk-dir.ts
|
|
1020
|
+
import fs2 from "fs";
|
|
1021
|
+
import path2 from "path";
|
|
1022
|
+
function walkDir(rootDir, options = {}) {
|
|
1023
|
+
const { maxDepth = 3, filter } = options;
|
|
1024
|
+
const results = [];
|
|
1025
|
+
if (!fs2.existsSync(rootDir))
|
|
1026
|
+
return results;
|
|
1027
|
+
function recurse(currentDir, depth, category) {
|
|
1028
|
+
if (depth > maxDepth)
|
|
1029
|
+
return;
|
|
1030
|
+
const entries = fs2.readdirSync(currentDir, { withFileTypes: true });
|
|
1031
|
+
for (const entry of entries) {
|
|
1032
|
+
const fullPath = path2.join(currentDir, entry.name);
|
|
1033
|
+
const walkEntry = {
|
|
1034
|
+
path: fullPath,
|
|
1035
|
+
name: entry.name,
|
|
1036
|
+
isDirectory: entry.isDirectory(),
|
|
1037
|
+
depth,
|
|
1038
|
+
category
|
|
1039
|
+
};
|
|
1040
|
+
if (!filter || filter(walkEntry)) {
|
|
1041
|
+
results.push(walkEntry);
|
|
1042
|
+
}
|
|
1043
|
+
if (entry.isDirectory()) {
|
|
1044
|
+
recurse(fullPath, depth + 1, entry.name);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
recurse(rootDir, 0);
|
|
1049
|
+
return results;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// src/lib/agents.ts
|
|
1053
|
+
function findAgentsInDir(dir, maxDepth = 2) {
|
|
1054
|
+
const entries = walkDir(dir, {
|
|
1055
|
+
maxDepth,
|
|
1056
|
+
filter: (e) => !e.isDirectory && e.name.endsWith(".md")
|
|
1057
|
+
});
|
|
1058
|
+
return entries.map((entry) => ({
|
|
1059
|
+
name: entry.name.replace(/\.md$/, ""),
|
|
1060
|
+
file: entry.path,
|
|
1061
|
+
category: entry.category
|
|
1062
|
+
}));
|
|
1063
|
+
}
|
|
1064
|
+
function extractAgentFrontmatter(content) {
|
|
1065
|
+
const { data, parseError, body } = parseFrontmatter(content);
|
|
1066
|
+
if (parseError) {
|
|
1067
|
+
return { name: "", description: "", prompt: body.trim() };
|
|
1068
|
+
}
|
|
1069
|
+
return {
|
|
1070
|
+
name: extractString(data, "name"),
|
|
1071
|
+
description: extractString(data, "description"),
|
|
1072
|
+
prompt: body.trim(),
|
|
1073
|
+
model: extractNonEmptyString(data, "model"),
|
|
1074
|
+
temperature: extractNumber(data, "temperature"),
|
|
1075
|
+
top_p: extractNumber(data, "top_p"),
|
|
1076
|
+
tools: isToolsMap(data.tools) ? data.tools : undefined,
|
|
1077
|
+
disable: extractBoolean(data, "disable"),
|
|
1078
|
+
mode: isAgentMode(data.mode) ? data.mode : undefined,
|
|
1079
|
+
color: extractNonEmptyString(data, "color"),
|
|
1080
|
+
steps: extractNumber(data, "steps"),
|
|
1081
|
+
hidden: extractBoolean(data, "hidden") ?? undefined,
|
|
1082
|
+
permission: normalizePermission(data.permission)
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// src/lib/commands.ts
|
|
1087
|
+
function findCommandsInDir(dir, maxDepth = 2) {
|
|
1088
|
+
const entries = walkDir(dir, {
|
|
1089
|
+
maxDepth,
|
|
1090
|
+
filter: (e) => !e.isDirectory && e.name.endsWith(".md")
|
|
1091
|
+
});
|
|
1092
|
+
return entries.map((entry) => {
|
|
1093
|
+
const baseName = entry.name.replace(/\.md$/, "");
|
|
1094
|
+
const commandName = entry.category ? `/${entry.category}:${baseName}` : `/${baseName}`;
|
|
1095
|
+
return {
|
|
1096
|
+
name: commandName,
|
|
1097
|
+
file: entry.path,
|
|
1098
|
+
category: entry.category
|
|
1099
|
+
};
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
function extractCommandFrontmatter(content) {
|
|
1103
|
+
const { data, parseError } = parseFrontmatter(content);
|
|
1104
|
+
if (parseError) {
|
|
1105
|
+
return {
|
|
1106
|
+
name: "",
|
|
1107
|
+
description: "",
|
|
1108
|
+
argumentHint: "",
|
|
1109
|
+
agent: undefined,
|
|
1110
|
+
model: undefined,
|
|
1111
|
+
subtask: undefined
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
const argumentHintRaw = extractString(data, "argument-hint");
|
|
1115
|
+
return {
|
|
1116
|
+
name: extractString(data, "name"),
|
|
1117
|
+
description: extractString(data, "description"),
|
|
1118
|
+
argumentHint: argumentHintRaw.replace(/^["']|["']$/g, ""),
|
|
1119
|
+
agent: extractNonEmptyString(data, "agent"),
|
|
1120
|
+
model: extractNonEmptyString(data, "model"),
|
|
1121
|
+
subtask: extractBoolean(data, "subtask")
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// src/lib/converter.ts
|
|
1126
|
+
import fs3 from "fs";
|
|
1127
|
+
var CONVERTER_VERSION = 2;
|
|
1128
|
+
var cache = new Map;
|
|
1129
|
+
var TOOL_MAPPINGS = [
|
|
1130
|
+
[/\bTask\s+tool\b/gi, "task tool"],
|
|
1131
|
+
[/\bTask\s+([\w-]+)\s*:/g, "task $1:"],
|
|
1132
|
+
[/\bTask\s+([\w-]+)\s*\(/g, "task $1("],
|
|
1133
|
+
[/\bTask\s*\(/g, "task("],
|
|
1134
|
+
[/\bTask\b(?=\s+to\s+\w)/g, "task"],
|
|
1135
|
+
[/\bTodoWrite\b/g, "todowrite"],
|
|
1136
|
+
[/\bAskUserQuestion\b/g, "question"],
|
|
1137
|
+
[/\bWebSearch\b/g, "google_search"],
|
|
1138
|
+
[/\bRead\b(?=\s+tool|\s+to\s+|\()/g, "read"],
|
|
1139
|
+
[/\bWrite\b(?=\s+tool|\s+to\s+|\()/g, "write"],
|
|
1140
|
+
[/\bEdit\b(?=\s+tool|\s+to\s+|\()/g, "edit"],
|
|
1141
|
+
[/\bBash\b(?=\s+tool|\s+to\s+|\()/g, "bash"],
|
|
1142
|
+
[/\bGrep\b(?=\s+tool|\s+to\s+|\()/g, "grep"],
|
|
1143
|
+
[/\bGlob\b(?=\s+tool|\s+to\s+|\()/g, "glob"],
|
|
1144
|
+
[/\bWebFetch\b/g, "webfetch"],
|
|
1145
|
+
[/\bSkill\b(?=\s+tool|\s*\()/g, "skill"]
|
|
1146
|
+
];
|
|
1147
|
+
var PATH_REPLACEMENTS = [
|
|
1148
|
+
[/\.claude\/skills\//g, ".opencode/skills/"],
|
|
1149
|
+
[/\.claude\/commands\//g, ".opencode/commands/"],
|
|
1150
|
+
[/\.claude\/agents\//g, ".opencode/agents/"],
|
|
1151
|
+
[/~\/\.claude\//g, "~/.config/opencode/"],
|
|
1152
|
+
[/CLAUDE\.md/g, "AGENTS.md"],
|
|
1153
|
+
[/\/compound-engineering:/g, "/systematic:"],
|
|
1154
|
+
[/compound-engineering:/g, "systematic:"]
|
|
1155
|
+
];
|
|
1156
|
+
var TOOL_NAME_MAP = {
|
|
1157
|
+
task: "task",
|
|
1158
|
+
todowrite: "todowrite",
|
|
1159
|
+
askuserquestion: "question",
|
|
1160
|
+
websearch: "google_search",
|
|
1161
|
+
webfetch: "webfetch",
|
|
1162
|
+
skill: "skill",
|
|
1163
|
+
read: "read",
|
|
1164
|
+
write: "write",
|
|
1165
|
+
edit: "edit",
|
|
1166
|
+
bash: "bash",
|
|
1167
|
+
grep: "grep",
|
|
1168
|
+
glob: "glob"
|
|
1169
|
+
};
|
|
1170
|
+
var PERMISSION_MODE_MAP = {
|
|
1171
|
+
full: {
|
|
1172
|
+
edit: "allow",
|
|
1173
|
+
bash: "allow",
|
|
1174
|
+
webfetch: "allow"
|
|
1175
|
+
},
|
|
1176
|
+
default: {
|
|
1177
|
+
edit: "ask",
|
|
1178
|
+
bash: "ask",
|
|
1179
|
+
webfetch: "ask"
|
|
1180
|
+
},
|
|
1181
|
+
plan: {
|
|
1182
|
+
edit: "deny",
|
|
1183
|
+
bash: "deny",
|
|
1184
|
+
webfetch: "ask"
|
|
1185
|
+
},
|
|
1186
|
+
bypassPermissions: {
|
|
1187
|
+
edit: "allow",
|
|
1188
|
+
bash: "allow",
|
|
1189
|
+
webfetch: "allow"
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
function inferTemperature(name, description) {
|
|
1193
|
+
const sample = `${name} ${description ?? ""}`.toLowerCase();
|
|
1194
|
+
if (/(review|audit|security|sentinel|oracle|lint|verification|guardian)/.test(sample)) {
|
|
1195
|
+
return 0.1;
|
|
1196
|
+
}
|
|
1197
|
+
if (/(plan|planning|architecture|strategist|analysis|research)/.test(sample)) {
|
|
1198
|
+
return 0.2;
|
|
1199
|
+
}
|
|
1200
|
+
if (/(doc|readme|changelog|editor|writer)/.test(sample)) {
|
|
1201
|
+
return 0.3;
|
|
1202
|
+
}
|
|
1203
|
+
if (/(brainstorm|creative|ideate|design|concept)/.test(sample)) {
|
|
1204
|
+
return 0.6;
|
|
1205
|
+
}
|
|
1206
|
+
return 0.3;
|
|
1207
|
+
}
|
|
1208
|
+
var CODE_BLOCK_PATTERN = /```[\s\S]*?```|`[^`\n]+`/g;
|
|
1209
|
+
function transformBody(body) {
|
|
1210
|
+
const codeBlocks = [];
|
|
1211
|
+
let placeholderIndex = 0;
|
|
1212
|
+
const withPlaceholders = body.replace(CODE_BLOCK_PATTERN, (match) => {
|
|
1213
|
+
codeBlocks.push(match);
|
|
1214
|
+
return `__CODE_BLOCK_${placeholderIndex++}__`;
|
|
1215
|
+
});
|
|
1216
|
+
let result = withPlaceholders;
|
|
1217
|
+
for (const [pattern, replacement] of TOOL_MAPPINGS) {
|
|
1218
|
+
result = result.replace(pattern, replacement);
|
|
1219
|
+
}
|
|
1220
|
+
for (const [pattern, replacement] of PATH_REPLACEMENTS) {
|
|
1221
|
+
result = result.replace(pattern, replacement);
|
|
1222
|
+
}
|
|
1223
|
+
for (let i = 0;i < codeBlocks.length; i++) {
|
|
1224
|
+
result = result.replace(`__CODE_BLOCK_${i}__`, codeBlocks[i]);
|
|
1225
|
+
}
|
|
1226
|
+
return result;
|
|
1227
|
+
}
|
|
1228
|
+
function normalizeModel(model) {
|
|
1229
|
+
if (model.includes("/"))
|
|
1230
|
+
return model;
|
|
1231
|
+
if (model === "inherit")
|
|
1232
|
+
return model;
|
|
1233
|
+
if (/^claude-/.test(model))
|
|
1234
|
+
return `anthropic/${model}`;
|
|
1235
|
+
if (/^(gpt-|o1-|o3-)/.test(model))
|
|
1236
|
+
return `openai/${model}`;
|
|
1237
|
+
if (/^gemini-/.test(model))
|
|
1238
|
+
return `google/${model}`;
|
|
1239
|
+
return `anthropic/${model}`;
|
|
1240
|
+
}
|
|
1241
|
+
function canonicalizeToolName(name) {
|
|
1242
|
+
const lower = name.trim().toLowerCase();
|
|
1243
|
+
return TOOL_NAME_MAP[lower] ?? lower;
|
|
1244
|
+
}
|
|
1245
|
+
function isValidSteps(value) {
|
|
1246
|
+
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value > 0;
|
|
1247
|
+
}
|
|
1248
|
+
function mapStepsField(data) {
|
|
1249
|
+
if (data.steps !== undefined) {
|
|
1250
|
+
if (isValidSteps(data.steps)) {
|
|
1251
|
+
delete data.maxTurns;
|
|
1252
|
+
delete data.maxSteps;
|
|
1253
|
+
}
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
const candidates = [];
|
|
1257
|
+
if (isValidSteps(data.maxTurns))
|
|
1258
|
+
candidates.push(data.maxTurns);
|
|
1259
|
+
if (isValidSteps(data.maxSteps))
|
|
1260
|
+
candidates.push(data.maxSteps);
|
|
1261
|
+
if (candidates.length > 0) {
|
|
1262
|
+
data.steps = Math.min(...candidates);
|
|
1263
|
+
delete data.maxTurns;
|
|
1264
|
+
delete data.maxSteps;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
function mapToolsField(data) {
|
|
1268
|
+
if (data.tools !== undefined && !Array.isArray(data.tools)) {
|
|
1269
|
+
if (isToolsMap(data.tools)) {
|
|
1270
|
+
mergeDisallowedTools(data);
|
|
1271
|
+
}
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1274
|
+
if (Array.isArray(data.tools)) {
|
|
1275
|
+
const toolsMap = {};
|
|
1276
|
+
for (const tool of data.tools) {
|
|
1277
|
+
if (typeof tool === "string") {
|
|
1278
|
+
toolsMap[canonicalizeToolName(tool)] = true;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
if (Object.keys(toolsMap).length > 0) {
|
|
1282
|
+
data.tools = toolsMap;
|
|
1283
|
+
} else {
|
|
1284
|
+
delete data.tools;
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
mergeDisallowedTools(data);
|
|
1288
|
+
}
|
|
1289
|
+
function mergeDisallowedTools(data) {
|
|
1290
|
+
if (!Array.isArray(data.disallowedTools))
|
|
1291
|
+
return;
|
|
1292
|
+
const existing = isToolsMap(data.tools) ? data.tools : {};
|
|
1293
|
+
for (const tool of data.disallowedTools) {
|
|
1294
|
+
if (typeof tool === "string") {
|
|
1295
|
+
existing[canonicalizeToolName(tool)] = false;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
if (Object.keys(existing).length > 0) {
|
|
1299
|
+
data.tools = existing;
|
|
1300
|
+
}
|
|
1301
|
+
delete data.disallowedTools;
|
|
1302
|
+
}
|
|
1303
|
+
function mapPermissionMode(data) {
|
|
1304
|
+
if (data.permission !== undefined) {
|
|
1305
|
+
const normalized = normalizePermission(data.permission);
|
|
1306
|
+
if (normalized) {
|
|
1307
|
+
data.permission = normalized;
|
|
1308
|
+
delete data.permissionMode;
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
if (typeof data.permissionMode !== "string")
|
|
1313
|
+
return;
|
|
1314
|
+
const mapped = PERMISSION_MODE_MAP[data.permissionMode];
|
|
1315
|
+
data.permission = mapped ?? { edit: "ask", bash: "ask", webfetch: "ask" };
|
|
1316
|
+
delete data.permissionMode;
|
|
1317
|
+
}
|
|
1318
|
+
function mapHiddenField(data) {
|
|
1319
|
+
if (data["disable-model-invocation"] === true || data.disableModelInvocation === true) {
|
|
1320
|
+
data.hidden = true;
|
|
1321
|
+
delete data["disable-model-invocation"];
|
|
1322
|
+
delete data.disableModelInvocation;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
function normalizeModelField(data) {
|
|
1326
|
+
if (typeof data.model === "string" && data.model !== "inherit") {
|
|
1327
|
+
data.model = normalizeModel(data.model);
|
|
1328
|
+
} else if (data.model === "inherit") {
|
|
1329
|
+
delete data.model;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
function transformAgentFrontmatter(data, agentMode) {
|
|
1333
|
+
const result = { ...data };
|
|
1334
|
+
result.mode = isAgentMode(data.mode) ? data.mode : agentMode;
|
|
1335
|
+
const name = typeof data.name === "string" ? data.name : "";
|
|
1336
|
+
const description = typeof data.description === "string" ? data.description : "";
|
|
1337
|
+
if (description) {
|
|
1338
|
+
result.description = description;
|
|
1339
|
+
} else if (name) {
|
|
1340
|
+
result.description = `${name} agent`;
|
|
1341
|
+
}
|
|
1342
|
+
normalizeModelField(result);
|
|
1343
|
+
result.temperature = typeof data.temperature === "number" ? data.temperature : inferTemperature(name, description);
|
|
1344
|
+
mapStepsField(result);
|
|
1345
|
+
mapToolsField(result);
|
|
1346
|
+
mapPermissionMode(result);
|
|
1347
|
+
mapHiddenField(result);
|
|
1348
|
+
return result;
|
|
1349
|
+
}
|
|
1350
|
+
function transformSkillFrontmatter(data) {
|
|
1351
|
+
const result = { ...data };
|
|
1352
|
+
normalizeModelField(result);
|
|
1353
|
+
if (result.context === "fork") {
|
|
1354
|
+
result.subtask = true;
|
|
1355
|
+
}
|
|
1356
|
+
return result;
|
|
1357
|
+
}
|
|
1358
|
+
function transformCommandFrontmatter(data) {
|
|
1359
|
+
const result = { ...data };
|
|
1360
|
+
normalizeModelField(result);
|
|
1361
|
+
return result;
|
|
1362
|
+
}
|
|
1363
|
+
function convertContent(content, type, options = {}) {
|
|
1364
|
+
if (content === "")
|
|
1365
|
+
return "";
|
|
1366
|
+
const { data, body, hadFrontmatter, parseError } = parseFrontmatter(content);
|
|
1367
|
+
if (!hadFrontmatter) {
|
|
1368
|
+
return options.skipBodyTransform ? content : transformBody(content);
|
|
1369
|
+
}
|
|
1370
|
+
if (parseError) {
|
|
1371
|
+
return options.skipBodyTransform ? content : transformBody(content);
|
|
1372
|
+
}
|
|
1373
|
+
const shouldTransformBody = !options.skipBodyTransform;
|
|
1374
|
+
const transformedBody = shouldTransformBody ? transformBody(body) : body;
|
|
1375
|
+
if (type === "agent") {
|
|
1376
|
+
const agentMode = options.agentMode ?? "subagent";
|
|
1377
|
+
const transformedData = transformAgentFrontmatter(data, agentMode);
|
|
1378
|
+
return `${formatFrontmatter(transformedData)}
|
|
1379
|
+
${transformedBody}`;
|
|
1380
|
+
}
|
|
1381
|
+
if (type === "skill") {
|
|
1382
|
+
const transformedData = transformSkillFrontmatter(data);
|
|
1383
|
+
return `${formatFrontmatter(transformedData)}
|
|
1384
|
+
${transformedBody}`;
|
|
1385
|
+
}
|
|
1386
|
+
if (type === "command") {
|
|
1387
|
+
const transformedData = transformCommandFrontmatter(data);
|
|
1388
|
+
return `${formatFrontmatter(transformedData)}
|
|
1389
|
+
${transformedBody}`;
|
|
1390
|
+
}
|
|
1391
|
+
return content;
|
|
1392
|
+
}
|
|
1393
|
+
function convertFileWithCache(filePath, type, options = {}) {
|
|
1394
|
+
const fd = fs3.openSync(filePath, "r");
|
|
1395
|
+
try {
|
|
1396
|
+
const stats = fs3.fstatSync(fd);
|
|
1397
|
+
const cacheKey = `${CONVERTER_VERSION}:${filePath}:${type}:${options.source ?? "bundled"}:${options.agentMode ?? "subagent"}:${options.skipBodyTransform ?? false}`;
|
|
1398
|
+
const cached = cache.get(cacheKey);
|
|
1399
|
+
if (cached != null && cached.mtimeMs === stats.mtimeMs) {
|
|
1400
|
+
return cached.converted;
|
|
1401
|
+
}
|
|
1402
|
+
const content = fs3.readFileSync(fd, "utf8");
|
|
1403
|
+
const converted = convertContent(content, type, options);
|
|
1404
|
+
cache.set(cacheKey, { mtimeMs: stats.mtimeMs, converted });
|
|
1405
|
+
return converted;
|
|
1406
|
+
} finally {
|
|
1407
|
+
fs3.closeSync(fd);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// src/lib/skills.ts
|
|
1412
|
+
import fs4 from "fs";
|
|
1413
|
+
import path3 from "path";
|
|
1414
|
+
function extractFrontmatter(filePath) {
|
|
1415
|
+
try {
|
|
1416
|
+
const content = fs4.readFileSync(filePath, "utf8");
|
|
1417
|
+
const { data, parseError } = parseFrontmatter(content);
|
|
1418
|
+
if (parseError) {
|
|
1419
|
+
return { name: "", description: "" };
|
|
1420
|
+
}
|
|
1421
|
+
const metadataRaw = data.metadata;
|
|
1422
|
+
let metadata;
|
|
1423
|
+
if (isRecord(metadataRaw)) {
|
|
1424
|
+
const entries = Object.entries(metadataRaw);
|
|
1425
|
+
if (entries.every(([, v]) => typeof v === "string")) {
|
|
1426
|
+
metadata = Object.fromEntries(entries);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
const argumentHintRaw = extractNonEmptyString(data, "argument-hint");
|
|
1430
|
+
const argumentHint = argumentHintRaw?.replace(/^["']|["']$/g, "") || undefined;
|
|
1431
|
+
return {
|
|
1432
|
+
name: extractString(data, "name"),
|
|
1433
|
+
description: extractString(data, "description"),
|
|
1434
|
+
license: extractNonEmptyString(data, "license"),
|
|
1435
|
+
compatibility: extractNonEmptyString(data, "compatibility"),
|
|
1436
|
+
metadata,
|
|
1437
|
+
disableModelInvocation: extractBoolean(data, "disable-model-invocation"),
|
|
1438
|
+
userInvocable: extractBoolean(data, "user-invocable"),
|
|
1439
|
+
subtask: data.context === "fork" ? true : undefined,
|
|
1440
|
+
agent: extractNonEmptyString(data, "agent"),
|
|
1441
|
+
model: extractNonEmptyString(data, "model"),
|
|
1442
|
+
argumentHint: argumentHint !== "" ? argumentHint : undefined,
|
|
1443
|
+
allowedTools: extractNonEmptyString(data, "allowed-tools")
|
|
1444
|
+
};
|
|
1445
|
+
} catch {
|
|
1446
|
+
return { name: "", description: "" };
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
function findSkillsInDir(dir, maxDepth = 3) {
|
|
1450
|
+
const skills = [];
|
|
1451
|
+
const entries = walkDir(dir, {
|
|
1452
|
+
maxDepth,
|
|
1453
|
+
filter: (e) => e.isDirectory
|
|
1454
|
+
});
|
|
1455
|
+
for (const entry of entries) {
|
|
1456
|
+
const skillFile = path3.join(entry.path, "SKILL.md");
|
|
1457
|
+
if (fs4.existsSync(skillFile)) {
|
|
1458
|
+
const frontmatter = extractFrontmatter(skillFile);
|
|
1459
|
+
skills.push({
|
|
1460
|
+
path: entry.path,
|
|
1461
|
+
skillFile,
|
|
1462
|
+
name: frontmatter.name || entry.name,
|
|
1463
|
+
description: frontmatter.description || "",
|
|
1464
|
+
license: frontmatter.license,
|
|
1465
|
+
compatibility: frontmatter.compatibility,
|
|
1466
|
+
metadata: frontmatter.metadata,
|
|
1467
|
+
disableModelInvocation: frontmatter.disableModelInvocation,
|
|
1468
|
+
userInvocable: frontmatter.userInvocable,
|
|
1469
|
+
subtask: frontmatter.subtask,
|
|
1470
|
+
agent: frontmatter.agent,
|
|
1471
|
+
model: frontmatter.model,
|
|
1472
|
+
argumentHint: frontmatter.argumentHint,
|
|
1473
|
+
allowedTools: frontmatter.allowedTools
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
return skills;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
export { parseFrontmatter, loadConfig, getConfigPaths, findAgentsInDir, extractAgentFrontmatter, findCommandsInDir, extractCommandFrontmatter, convertContent, convertFileWithCache, findSkillsInDir };
|