@ksm0709/context 0.0.22 → 0.0.23
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/README.md +4 -0
- package/dist/cli/index.js +7 -116
- package/dist/index.js +59 -1238
- package/dist/mcp.js +33061 -0
- package/dist/omx/index.mjs +50 -359
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -1,838 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/index.ts
|
|
3
|
-
import { existsSync as
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
// node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
7
|
-
function createScanner(text, ignoreTrivia = false) {
|
|
8
|
-
const len = text.length;
|
|
9
|
-
let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
|
|
10
|
-
function scanHexDigits(count, exact) {
|
|
11
|
-
let digits = 0;
|
|
12
|
-
let value2 = 0;
|
|
13
|
-
while (digits < count || !exact) {
|
|
14
|
-
let ch = text.charCodeAt(pos);
|
|
15
|
-
if (ch >= 48 && ch <= 57) {
|
|
16
|
-
value2 = value2 * 16 + ch - 48;
|
|
17
|
-
} else if (ch >= 65 && ch <= 70) {
|
|
18
|
-
value2 = value2 * 16 + ch - 65 + 10;
|
|
19
|
-
} else if (ch >= 97 && ch <= 102) {
|
|
20
|
-
value2 = value2 * 16 + ch - 97 + 10;
|
|
21
|
-
} else {
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
24
|
-
pos++;
|
|
25
|
-
digits++;
|
|
26
|
-
}
|
|
27
|
-
if (digits < count) {
|
|
28
|
-
value2 = -1;
|
|
29
|
-
}
|
|
30
|
-
return value2;
|
|
31
|
-
}
|
|
32
|
-
function setPosition(newPosition) {
|
|
33
|
-
pos = newPosition;
|
|
34
|
-
value = "";
|
|
35
|
-
tokenOffset = 0;
|
|
36
|
-
token = 16;
|
|
37
|
-
scanError = 0;
|
|
38
|
-
}
|
|
39
|
-
function scanNumber() {
|
|
40
|
-
let start = pos;
|
|
41
|
-
if (text.charCodeAt(pos) === 48) {
|
|
42
|
-
pos++;
|
|
43
|
-
} else {
|
|
44
|
-
pos++;
|
|
45
|
-
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
46
|
-
pos++;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
if (pos < text.length && text.charCodeAt(pos) === 46) {
|
|
50
|
-
pos++;
|
|
51
|
-
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
52
|
-
pos++;
|
|
53
|
-
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
54
|
-
pos++;
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
scanError = 3;
|
|
58
|
-
return text.substring(start, pos);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
let end = pos;
|
|
62
|
-
if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
|
|
63
|
-
pos++;
|
|
64
|
-
if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
|
|
65
|
-
pos++;
|
|
66
|
-
}
|
|
67
|
-
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
68
|
-
pos++;
|
|
69
|
-
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
70
|
-
pos++;
|
|
71
|
-
}
|
|
72
|
-
end = pos;
|
|
73
|
-
} else {
|
|
74
|
-
scanError = 3;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return text.substring(start, end);
|
|
78
|
-
}
|
|
79
|
-
function scanString() {
|
|
80
|
-
let result = "", start = pos;
|
|
81
|
-
while (true) {
|
|
82
|
-
if (pos >= len) {
|
|
83
|
-
result += text.substring(start, pos);
|
|
84
|
-
scanError = 2;
|
|
85
|
-
break;
|
|
86
|
-
}
|
|
87
|
-
const ch = text.charCodeAt(pos);
|
|
88
|
-
if (ch === 34) {
|
|
89
|
-
result += text.substring(start, pos);
|
|
90
|
-
pos++;
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
if (ch === 92) {
|
|
94
|
-
result += text.substring(start, pos);
|
|
95
|
-
pos++;
|
|
96
|
-
if (pos >= len) {
|
|
97
|
-
scanError = 2;
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
const ch2 = text.charCodeAt(pos++);
|
|
101
|
-
switch (ch2) {
|
|
102
|
-
case 34:
|
|
103
|
-
result += '"';
|
|
104
|
-
break;
|
|
105
|
-
case 92:
|
|
106
|
-
result += "\\";
|
|
107
|
-
break;
|
|
108
|
-
case 47:
|
|
109
|
-
result += "/";
|
|
110
|
-
break;
|
|
111
|
-
case 98:
|
|
112
|
-
result += "\b";
|
|
113
|
-
break;
|
|
114
|
-
case 102:
|
|
115
|
-
result += "\f";
|
|
116
|
-
break;
|
|
117
|
-
case 110:
|
|
118
|
-
result += `
|
|
119
|
-
`;
|
|
120
|
-
break;
|
|
121
|
-
case 114:
|
|
122
|
-
result += "\r";
|
|
123
|
-
break;
|
|
124
|
-
case 116:
|
|
125
|
-
result += "\t";
|
|
126
|
-
break;
|
|
127
|
-
case 117:
|
|
128
|
-
const ch3 = scanHexDigits(4, true);
|
|
129
|
-
if (ch3 >= 0) {
|
|
130
|
-
result += String.fromCharCode(ch3);
|
|
131
|
-
} else {
|
|
132
|
-
scanError = 4;
|
|
133
|
-
}
|
|
134
|
-
break;
|
|
135
|
-
default:
|
|
136
|
-
scanError = 5;
|
|
137
|
-
}
|
|
138
|
-
start = pos;
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
if (ch >= 0 && ch <= 31) {
|
|
142
|
-
if (isLineBreak(ch)) {
|
|
143
|
-
result += text.substring(start, pos);
|
|
144
|
-
scanError = 2;
|
|
145
|
-
break;
|
|
146
|
-
} else {
|
|
147
|
-
scanError = 6;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
pos++;
|
|
151
|
-
}
|
|
152
|
-
return result;
|
|
153
|
-
}
|
|
154
|
-
function scanNext() {
|
|
155
|
-
value = "";
|
|
156
|
-
scanError = 0;
|
|
157
|
-
tokenOffset = pos;
|
|
158
|
-
lineStartOffset = lineNumber;
|
|
159
|
-
prevTokenLineStartOffset = tokenLineStartOffset;
|
|
160
|
-
if (pos >= len) {
|
|
161
|
-
tokenOffset = len;
|
|
162
|
-
return token = 17;
|
|
163
|
-
}
|
|
164
|
-
let code = text.charCodeAt(pos);
|
|
165
|
-
if (isWhiteSpace(code)) {
|
|
166
|
-
do {
|
|
167
|
-
pos++;
|
|
168
|
-
value += String.fromCharCode(code);
|
|
169
|
-
code = text.charCodeAt(pos);
|
|
170
|
-
} while (isWhiteSpace(code));
|
|
171
|
-
return token = 15;
|
|
172
|
-
}
|
|
173
|
-
if (isLineBreak(code)) {
|
|
174
|
-
pos++;
|
|
175
|
-
value += String.fromCharCode(code);
|
|
176
|
-
if (code === 13 && text.charCodeAt(pos) === 10) {
|
|
177
|
-
pos++;
|
|
178
|
-
value += `
|
|
179
|
-
`;
|
|
180
|
-
}
|
|
181
|
-
lineNumber++;
|
|
182
|
-
tokenLineStartOffset = pos;
|
|
183
|
-
return token = 14;
|
|
184
|
-
}
|
|
185
|
-
switch (code) {
|
|
186
|
-
case 123:
|
|
187
|
-
pos++;
|
|
188
|
-
return token = 1;
|
|
189
|
-
case 125:
|
|
190
|
-
pos++;
|
|
191
|
-
return token = 2;
|
|
192
|
-
case 91:
|
|
193
|
-
pos++;
|
|
194
|
-
return token = 3;
|
|
195
|
-
case 93:
|
|
196
|
-
pos++;
|
|
197
|
-
return token = 4;
|
|
198
|
-
case 58:
|
|
199
|
-
pos++;
|
|
200
|
-
return token = 6;
|
|
201
|
-
case 44:
|
|
202
|
-
pos++;
|
|
203
|
-
return token = 5;
|
|
204
|
-
case 34:
|
|
205
|
-
pos++;
|
|
206
|
-
value = scanString();
|
|
207
|
-
return token = 10;
|
|
208
|
-
case 47:
|
|
209
|
-
const start = pos - 1;
|
|
210
|
-
if (text.charCodeAt(pos + 1) === 47) {
|
|
211
|
-
pos += 2;
|
|
212
|
-
while (pos < len) {
|
|
213
|
-
if (isLineBreak(text.charCodeAt(pos))) {
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
pos++;
|
|
217
|
-
}
|
|
218
|
-
value = text.substring(start, pos);
|
|
219
|
-
return token = 12;
|
|
220
|
-
}
|
|
221
|
-
if (text.charCodeAt(pos + 1) === 42) {
|
|
222
|
-
pos += 2;
|
|
223
|
-
const safeLength = len - 1;
|
|
224
|
-
let commentClosed = false;
|
|
225
|
-
while (pos < safeLength) {
|
|
226
|
-
const ch = text.charCodeAt(pos);
|
|
227
|
-
if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
|
|
228
|
-
pos += 2;
|
|
229
|
-
commentClosed = true;
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
pos++;
|
|
233
|
-
if (isLineBreak(ch)) {
|
|
234
|
-
if (ch === 13 && text.charCodeAt(pos) === 10) {
|
|
235
|
-
pos++;
|
|
236
|
-
}
|
|
237
|
-
lineNumber++;
|
|
238
|
-
tokenLineStartOffset = pos;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
if (!commentClosed) {
|
|
242
|
-
pos++;
|
|
243
|
-
scanError = 1;
|
|
244
|
-
}
|
|
245
|
-
value = text.substring(start, pos);
|
|
246
|
-
return token = 13;
|
|
247
|
-
}
|
|
248
|
-
value += String.fromCharCode(code);
|
|
249
|
-
pos++;
|
|
250
|
-
return token = 16;
|
|
251
|
-
case 45:
|
|
252
|
-
value += String.fromCharCode(code);
|
|
253
|
-
pos++;
|
|
254
|
-
if (pos === len || !isDigit(text.charCodeAt(pos))) {
|
|
255
|
-
return token = 16;
|
|
256
|
-
}
|
|
257
|
-
case 48:
|
|
258
|
-
case 49:
|
|
259
|
-
case 50:
|
|
260
|
-
case 51:
|
|
261
|
-
case 52:
|
|
262
|
-
case 53:
|
|
263
|
-
case 54:
|
|
264
|
-
case 55:
|
|
265
|
-
case 56:
|
|
266
|
-
case 57:
|
|
267
|
-
value += scanNumber();
|
|
268
|
-
return token = 11;
|
|
269
|
-
default:
|
|
270
|
-
while (pos < len && isUnknownContentCharacter(code)) {
|
|
271
|
-
pos++;
|
|
272
|
-
code = text.charCodeAt(pos);
|
|
273
|
-
}
|
|
274
|
-
if (tokenOffset !== pos) {
|
|
275
|
-
value = text.substring(tokenOffset, pos);
|
|
276
|
-
switch (value) {
|
|
277
|
-
case "true":
|
|
278
|
-
return token = 8;
|
|
279
|
-
case "false":
|
|
280
|
-
return token = 9;
|
|
281
|
-
case "null":
|
|
282
|
-
return token = 7;
|
|
283
|
-
}
|
|
284
|
-
return token = 16;
|
|
285
|
-
}
|
|
286
|
-
value += String.fromCharCode(code);
|
|
287
|
-
pos++;
|
|
288
|
-
return token = 16;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
function isUnknownContentCharacter(code) {
|
|
292
|
-
if (isWhiteSpace(code) || isLineBreak(code)) {
|
|
293
|
-
return false;
|
|
294
|
-
}
|
|
295
|
-
switch (code) {
|
|
296
|
-
case 125:
|
|
297
|
-
case 93:
|
|
298
|
-
case 123:
|
|
299
|
-
case 91:
|
|
300
|
-
case 34:
|
|
301
|
-
case 58:
|
|
302
|
-
case 44:
|
|
303
|
-
case 47:
|
|
304
|
-
return false;
|
|
305
|
-
}
|
|
306
|
-
return true;
|
|
307
|
-
}
|
|
308
|
-
function scanNextNonTrivia() {
|
|
309
|
-
let result;
|
|
310
|
-
do {
|
|
311
|
-
result = scanNext();
|
|
312
|
-
} while (result >= 12 && result <= 15);
|
|
313
|
-
return result;
|
|
314
|
-
}
|
|
315
|
-
return {
|
|
316
|
-
setPosition,
|
|
317
|
-
getPosition: () => pos,
|
|
318
|
-
scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
|
|
319
|
-
getToken: () => token,
|
|
320
|
-
getTokenValue: () => value,
|
|
321
|
-
getTokenOffset: () => tokenOffset,
|
|
322
|
-
getTokenLength: () => pos - tokenOffset,
|
|
323
|
-
getTokenStartLine: () => lineStartOffset,
|
|
324
|
-
getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,
|
|
325
|
-
getTokenError: () => scanError
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
function isWhiteSpace(ch) {
|
|
329
|
-
return ch === 32 || ch === 9;
|
|
330
|
-
}
|
|
331
|
-
function isLineBreak(ch) {
|
|
332
|
-
return ch === 10 || ch === 13;
|
|
333
|
-
}
|
|
334
|
-
function isDigit(ch) {
|
|
335
|
-
return ch >= 48 && ch <= 57;
|
|
336
|
-
}
|
|
337
|
-
var CharacterCodes;
|
|
338
|
-
(function(CharacterCodes2) {
|
|
339
|
-
CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed";
|
|
340
|
-
CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn";
|
|
341
|
-
CharacterCodes2[CharacterCodes2["space"] = 32] = "space";
|
|
342
|
-
CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0";
|
|
343
|
-
CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1";
|
|
344
|
-
CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2";
|
|
345
|
-
CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3";
|
|
346
|
-
CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4";
|
|
347
|
-
CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5";
|
|
348
|
-
CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6";
|
|
349
|
-
CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7";
|
|
350
|
-
CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8";
|
|
351
|
-
CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9";
|
|
352
|
-
CharacterCodes2[CharacterCodes2["a"] = 97] = "a";
|
|
353
|
-
CharacterCodes2[CharacterCodes2["b"] = 98] = "b";
|
|
354
|
-
CharacterCodes2[CharacterCodes2["c"] = 99] = "c";
|
|
355
|
-
CharacterCodes2[CharacterCodes2["d"] = 100] = "d";
|
|
356
|
-
CharacterCodes2[CharacterCodes2["e"] = 101] = "e";
|
|
357
|
-
CharacterCodes2[CharacterCodes2["f"] = 102] = "f";
|
|
358
|
-
CharacterCodes2[CharacterCodes2["g"] = 103] = "g";
|
|
359
|
-
CharacterCodes2[CharacterCodes2["h"] = 104] = "h";
|
|
360
|
-
CharacterCodes2[CharacterCodes2["i"] = 105] = "i";
|
|
361
|
-
CharacterCodes2[CharacterCodes2["j"] = 106] = "j";
|
|
362
|
-
CharacterCodes2[CharacterCodes2["k"] = 107] = "k";
|
|
363
|
-
CharacterCodes2[CharacterCodes2["l"] = 108] = "l";
|
|
364
|
-
CharacterCodes2[CharacterCodes2["m"] = 109] = "m";
|
|
365
|
-
CharacterCodes2[CharacterCodes2["n"] = 110] = "n";
|
|
366
|
-
CharacterCodes2[CharacterCodes2["o"] = 111] = "o";
|
|
367
|
-
CharacterCodes2[CharacterCodes2["p"] = 112] = "p";
|
|
368
|
-
CharacterCodes2[CharacterCodes2["q"] = 113] = "q";
|
|
369
|
-
CharacterCodes2[CharacterCodes2["r"] = 114] = "r";
|
|
370
|
-
CharacterCodes2[CharacterCodes2["s"] = 115] = "s";
|
|
371
|
-
CharacterCodes2[CharacterCodes2["t"] = 116] = "t";
|
|
372
|
-
CharacterCodes2[CharacterCodes2["u"] = 117] = "u";
|
|
373
|
-
CharacterCodes2[CharacterCodes2["v"] = 118] = "v";
|
|
374
|
-
CharacterCodes2[CharacterCodes2["w"] = 119] = "w";
|
|
375
|
-
CharacterCodes2[CharacterCodes2["x"] = 120] = "x";
|
|
376
|
-
CharacterCodes2[CharacterCodes2["y"] = 121] = "y";
|
|
377
|
-
CharacterCodes2[CharacterCodes2["z"] = 122] = "z";
|
|
378
|
-
CharacterCodes2[CharacterCodes2["A"] = 65] = "A";
|
|
379
|
-
CharacterCodes2[CharacterCodes2["B"] = 66] = "B";
|
|
380
|
-
CharacterCodes2[CharacterCodes2["C"] = 67] = "C";
|
|
381
|
-
CharacterCodes2[CharacterCodes2["D"] = 68] = "D";
|
|
382
|
-
CharacterCodes2[CharacterCodes2["E"] = 69] = "E";
|
|
383
|
-
CharacterCodes2[CharacterCodes2["F"] = 70] = "F";
|
|
384
|
-
CharacterCodes2[CharacterCodes2["G"] = 71] = "G";
|
|
385
|
-
CharacterCodes2[CharacterCodes2["H"] = 72] = "H";
|
|
386
|
-
CharacterCodes2[CharacterCodes2["I"] = 73] = "I";
|
|
387
|
-
CharacterCodes2[CharacterCodes2["J"] = 74] = "J";
|
|
388
|
-
CharacterCodes2[CharacterCodes2["K"] = 75] = "K";
|
|
389
|
-
CharacterCodes2[CharacterCodes2["L"] = 76] = "L";
|
|
390
|
-
CharacterCodes2[CharacterCodes2["M"] = 77] = "M";
|
|
391
|
-
CharacterCodes2[CharacterCodes2["N"] = 78] = "N";
|
|
392
|
-
CharacterCodes2[CharacterCodes2["O"] = 79] = "O";
|
|
393
|
-
CharacterCodes2[CharacterCodes2["P"] = 80] = "P";
|
|
394
|
-
CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q";
|
|
395
|
-
CharacterCodes2[CharacterCodes2["R"] = 82] = "R";
|
|
396
|
-
CharacterCodes2[CharacterCodes2["S"] = 83] = "S";
|
|
397
|
-
CharacterCodes2[CharacterCodes2["T"] = 84] = "T";
|
|
398
|
-
CharacterCodes2[CharacterCodes2["U"] = 85] = "U";
|
|
399
|
-
CharacterCodes2[CharacterCodes2["V"] = 86] = "V";
|
|
400
|
-
CharacterCodes2[CharacterCodes2["W"] = 87] = "W";
|
|
401
|
-
CharacterCodes2[CharacterCodes2["X"] = 88] = "X";
|
|
402
|
-
CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y";
|
|
403
|
-
CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z";
|
|
404
|
-
CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk";
|
|
405
|
-
CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash";
|
|
406
|
-
CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace";
|
|
407
|
-
CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket";
|
|
408
|
-
CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon";
|
|
409
|
-
CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma";
|
|
410
|
-
CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot";
|
|
411
|
-
CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote";
|
|
412
|
-
CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus";
|
|
413
|
-
CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace";
|
|
414
|
-
CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket";
|
|
415
|
-
CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus";
|
|
416
|
-
CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash";
|
|
417
|
-
CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed";
|
|
418
|
-
CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab";
|
|
419
|
-
})(CharacterCodes || (CharacterCodes = {}));
|
|
420
|
-
|
|
421
|
-
// node_modules/jsonc-parser/lib/esm/impl/string-intern.js
|
|
422
|
-
var cachedSpaces = new Array(20).fill(0).map((_, index) => {
|
|
423
|
-
return " ".repeat(index);
|
|
424
|
-
});
|
|
425
|
-
var maxCachedValues = 200;
|
|
426
|
-
var cachedBreakLinesWithSpaces = {
|
|
427
|
-
" ": {
|
|
428
|
-
"\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
429
|
-
return `
|
|
430
|
-
` + " ".repeat(index);
|
|
431
|
-
}),
|
|
432
|
-
"\r": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
433
|
-
return "\r" + " ".repeat(index);
|
|
434
|
-
}),
|
|
435
|
-
"\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
436
|
-
return `\r
|
|
437
|
-
` + " ".repeat(index);
|
|
438
|
-
})
|
|
439
|
-
},
|
|
440
|
-
"\t": {
|
|
441
|
-
"\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
442
|
-
return `
|
|
443
|
-
` + "\t".repeat(index);
|
|
444
|
-
}),
|
|
445
|
-
"\r": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
446
|
-
return "\r" + "\t".repeat(index);
|
|
447
|
-
}),
|
|
448
|
-
"\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
449
|
-
return `\r
|
|
450
|
-
` + "\t".repeat(index);
|
|
451
|
-
})
|
|
452
|
-
}
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
// node_modules/jsonc-parser/lib/esm/impl/parser.js
|
|
456
|
-
var ParseOptions;
|
|
457
|
-
(function(ParseOptions2) {
|
|
458
|
-
ParseOptions2.DEFAULT = {
|
|
459
|
-
allowTrailingComma: false
|
|
460
|
-
};
|
|
461
|
-
})(ParseOptions || (ParseOptions = {}));
|
|
462
|
-
function parse(text, errors = [], options = ParseOptions.DEFAULT) {
|
|
463
|
-
let currentProperty = null;
|
|
464
|
-
let currentParent = [];
|
|
465
|
-
const previousParents = [];
|
|
466
|
-
function onValue(value) {
|
|
467
|
-
if (Array.isArray(currentParent)) {
|
|
468
|
-
currentParent.push(value);
|
|
469
|
-
} else if (currentProperty !== null) {
|
|
470
|
-
currentParent[currentProperty] = value;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
const visitor = {
|
|
474
|
-
onObjectBegin: () => {
|
|
475
|
-
const object = {};
|
|
476
|
-
onValue(object);
|
|
477
|
-
previousParents.push(currentParent);
|
|
478
|
-
currentParent = object;
|
|
479
|
-
currentProperty = null;
|
|
480
|
-
},
|
|
481
|
-
onObjectProperty: (name) => {
|
|
482
|
-
currentProperty = name;
|
|
483
|
-
},
|
|
484
|
-
onObjectEnd: () => {
|
|
485
|
-
currentParent = previousParents.pop();
|
|
486
|
-
},
|
|
487
|
-
onArrayBegin: () => {
|
|
488
|
-
const array = [];
|
|
489
|
-
onValue(array);
|
|
490
|
-
previousParents.push(currentParent);
|
|
491
|
-
currentParent = array;
|
|
492
|
-
currentProperty = null;
|
|
493
|
-
},
|
|
494
|
-
onArrayEnd: () => {
|
|
495
|
-
currentParent = previousParents.pop();
|
|
496
|
-
},
|
|
497
|
-
onLiteralValue: onValue,
|
|
498
|
-
onError: (error, offset, length) => {
|
|
499
|
-
errors.push({ error, offset, length });
|
|
500
|
-
}
|
|
501
|
-
};
|
|
502
|
-
visit(text, visitor, options);
|
|
503
|
-
return currentParent[0];
|
|
504
|
-
}
|
|
505
|
-
function visit(text, visitor, options = ParseOptions.DEFAULT) {
|
|
506
|
-
const _scanner = createScanner(text, false);
|
|
507
|
-
const _jsonPath = [];
|
|
508
|
-
let suppressedCallbacks = 0;
|
|
509
|
-
function toNoArgVisit(visitFunction) {
|
|
510
|
-
return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
|
|
511
|
-
}
|
|
512
|
-
function toOneArgVisit(visitFunction) {
|
|
513
|
-
return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
|
|
514
|
-
}
|
|
515
|
-
function toOneArgVisitWithPath(visitFunction) {
|
|
516
|
-
return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;
|
|
517
|
-
}
|
|
518
|
-
function toBeginVisit(visitFunction) {
|
|
519
|
-
return visitFunction ? () => {
|
|
520
|
-
if (suppressedCallbacks > 0) {
|
|
521
|
-
suppressedCallbacks++;
|
|
522
|
-
} else {
|
|
523
|
-
let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());
|
|
524
|
-
if (cbReturn === false) {
|
|
525
|
-
suppressedCallbacks = 1;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
} : () => true;
|
|
529
|
-
}
|
|
530
|
-
function toEndVisit(visitFunction) {
|
|
531
|
-
return visitFunction ? () => {
|
|
532
|
-
if (suppressedCallbacks > 0) {
|
|
533
|
-
suppressedCallbacks--;
|
|
534
|
-
}
|
|
535
|
-
if (suppressedCallbacks === 0) {
|
|
536
|
-
visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
|
|
537
|
-
}
|
|
538
|
-
} : () => true;
|
|
539
|
-
}
|
|
540
|
-
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);
|
|
541
|
-
const disallowComments = options && options.disallowComments;
|
|
542
|
-
const allowTrailingComma = options && options.allowTrailingComma;
|
|
543
|
-
function scanNext() {
|
|
544
|
-
while (true) {
|
|
545
|
-
const token = _scanner.scan();
|
|
546
|
-
switch (_scanner.getTokenError()) {
|
|
547
|
-
case 4:
|
|
548
|
-
handleError(14);
|
|
549
|
-
break;
|
|
550
|
-
case 5:
|
|
551
|
-
handleError(15);
|
|
552
|
-
break;
|
|
553
|
-
case 3:
|
|
554
|
-
handleError(13);
|
|
555
|
-
break;
|
|
556
|
-
case 1:
|
|
557
|
-
if (!disallowComments) {
|
|
558
|
-
handleError(11);
|
|
559
|
-
}
|
|
560
|
-
break;
|
|
561
|
-
case 2:
|
|
562
|
-
handleError(12);
|
|
563
|
-
break;
|
|
564
|
-
case 6:
|
|
565
|
-
handleError(16);
|
|
566
|
-
break;
|
|
567
|
-
}
|
|
568
|
-
switch (token) {
|
|
569
|
-
case 12:
|
|
570
|
-
case 13:
|
|
571
|
-
if (disallowComments) {
|
|
572
|
-
handleError(10);
|
|
573
|
-
} else {
|
|
574
|
-
onComment();
|
|
575
|
-
}
|
|
576
|
-
break;
|
|
577
|
-
case 16:
|
|
578
|
-
handleError(1);
|
|
579
|
-
break;
|
|
580
|
-
case 15:
|
|
581
|
-
case 14:
|
|
582
|
-
break;
|
|
583
|
-
default:
|
|
584
|
-
return token;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
function handleError(error, skipUntilAfter = [], skipUntil = []) {
|
|
589
|
-
onError(error);
|
|
590
|
-
if (skipUntilAfter.length + skipUntil.length > 0) {
|
|
591
|
-
let token = _scanner.getToken();
|
|
592
|
-
while (token !== 17) {
|
|
593
|
-
if (skipUntilAfter.indexOf(token) !== -1) {
|
|
594
|
-
scanNext();
|
|
595
|
-
break;
|
|
596
|
-
} else if (skipUntil.indexOf(token) !== -1) {
|
|
597
|
-
break;
|
|
598
|
-
}
|
|
599
|
-
token = scanNext();
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
function parseString(isValue) {
|
|
604
|
-
const value = _scanner.getTokenValue();
|
|
605
|
-
if (isValue) {
|
|
606
|
-
onLiteralValue(value);
|
|
607
|
-
} else {
|
|
608
|
-
onObjectProperty(value);
|
|
609
|
-
_jsonPath.push(value);
|
|
610
|
-
}
|
|
611
|
-
scanNext();
|
|
612
|
-
return true;
|
|
613
|
-
}
|
|
614
|
-
function parseLiteral() {
|
|
615
|
-
switch (_scanner.getToken()) {
|
|
616
|
-
case 11:
|
|
617
|
-
const tokenValue = _scanner.getTokenValue();
|
|
618
|
-
let value = Number(tokenValue);
|
|
619
|
-
if (isNaN(value)) {
|
|
620
|
-
handleError(2);
|
|
621
|
-
value = 0;
|
|
622
|
-
}
|
|
623
|
-
onLiteralValue(value);
|
|
624
|
-
break;
|
|
625
|
-
case 7:
|
|
626
|
-
onLiteralValue(null);
|
|
627
|
-
break;
|
|
628
|
-
case 8:
|
|
629
|
-
onLiteralValue(true);
|
|
630
|
-
break;
|
|
631
|
-
case 9:
|
|
632
|
-
onLiteralValue(false);
|
|
633
|
-
break;
|
|
634
|
-
default:
|
|
635
|
-
return false;
|
|
636
|
-
}
|
|
637
|
-
scanNext();
|
|
638
|
-
return true;
|
|
639
|
-
}
|
|
640
|
-
function parseProperty() {
|
|
641
|
-
if (_scanner.getToken() !== 10) {
|
|
642
|
-
handleError(3, [], [2, 5]);
|
|
643
|
-
return false;
|
|
644
|
-
}
|
|
645
|
-
parseString(false);
|
|
646
|
-
if (_scanner.getToken() === 6) {
|
|
647
|
-
onSeparator(":");
|
|
648
|
-
scanNext();
|
|
649
|
-
if (!parseValue()) {
|
|
650
|
-
handleError(4, [], [2, 5]);
|
|
651
|
-
}
|
|
652
|
-
} else {
|
|
653
|
-
handleError(5, [], [2, 5]);
|
|
654
|
-
}
|
|
655
|
-
_jsonPath.pop();
|
|
656
|
-
return true;
|
|
657
|
-
}
|
|
658
|
-
function parseObject() {
|
|
659
|
-
onObjectBegin();
|
|
660
|
-
scanNext();
|
|
661
|
-
let needsComma = false;
|
|
662
|
-
while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
|
|
663
|
-
if (_scanner.getToken() === 5) {
|
|
664
|
-
if (!needsComma) {
|
|
665
|
-
handleError(4, [], []);
|
|
666
|
-
}
|
|
667
|
-
onSeparator(",");
|
|
668
|
-
scanNext();
|
|
669
|
-
if (_scanner.getToken() === 2 && allowTrailingComma) {
|
|
670
|
-
break;
|
|
671
|
-
}
|
|
672
|
-
} else if (needsComma) {
|
|
673
|
-
handleError(6, [], []);
|
|
674
|
-
}
|
|
675
|
-
if (!parseProperty()) {
|
|
676
|
-
handleError(4, [], [2, 5]);
|
|
677
|
-
}
|
|
678
|
-
needsComma = true;
|
|
679
|
-
}
|
|
680
|
-
onObjectEnd();
|
|
681
|
-
if (_scanner.getToken() !== 2) {
|
|
682
|
-
handleError(7, [2], []);
|
|
683
|
-
} else {
|
|
684
|
-
scanNext();
|
|
685
|
-
}
|
|
686
|
-
return true;
|
|
687
|
-
}
|
|
688
|
-
function parseArray() {
|
|
689
|
-
onArrayBegin();
|
|
690
|
-
scanNext();
|
|
691
|
-
let isFirstElement = true;
|
|
692
|
-
let needsComma = false;
|
|
693
|
-
while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
|
|
694
|
-
if (_scanner.getToken() === 5) {
|
|
695
|
-
if (!needsComma) {
|
|
696
|
-
handleError(4, [], []);
|
|
697
|
-
}
|
|
698
|
-
onSeparator(",");
|
|
699
|
-
scanNext();
|
|
700
|
-
if (_scanner.getToken() === 4 && allowTrailingComma) {
|
|
701
|
-
break;
|
|
702
|
-
}
|
|
703
|
-
} else if (needsComma) {
|
|
704
|
-
handleError(6, [], []);
|
|
705
|
-
}
|
|
706
|
-
if (isFirstElement) {
|
|
707
|
-
_jsonPath.push(0);
|
|
708
|
-
isFirstElement = false;
|
|
709
|
-
} else {
|
|
710
|
-
_jsonPath[_jsonPath.length - 1]++;
|
|
711
|
-
}
|
|
712
|
-
if (!parseValue()) {
|
|
713
|
-
handleError(4, [], [4, 5]);
|
|
714
|
-
}
|
|
715
|
-
needsComma = true;
|
|
716
|
-
}
|
|
717
|
-
onArrayEnd();
|
|
718
|
-
if (!isFirstElement) {
|
|
719
|
-
_jsonPath.pop();
|
|
720
|
-
}
|
|
721
|
-
if (_scanner.getToken() !== 4) {
|
|
722
|
-
handleError(8, [4], []);
|
|
723
|
-
} else {
|
|
724
|
-
scanNext();
|
|
725
|
-
}
|
|
726
|
-
return true;
|
|
727
|
-
}
|
|
728
|
-
function parseValue() {
|
|
729
|
-
switch (_scanner.getToken()) {
|
|
730
|
-
case 3:
|
|
731
|
-
return parseArray();
|
|
732
|
-
case 1:
|
|
733
|
-
return parseObject();
|
|
734
|
-
case 10:
|
|
735
|
-
return parseString(true);
|
|
736
|
-
default:
|
|
737
|
-
return parseLiteral();
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
scanNext();
|
|
741
|
-
if (_scanner.getToken() === 17) {
|
|
742
|
-
if (options.allowEmptyContent) {
|
|
743
|
-
return true;
|
|
744
|
-
}
|
|
745
|
-
handleError(4, [], []);
|
|
746
|
-
return false;
|
|
747
|
-
}
|
|
748
|
-
if (!parseValue()) {
|
|
749
|
-
handleError(4, [], []);
|
|
750
|
-
return false;
|
|
751
|
-
}
|
|
752
|
-
if (_scanner.getToken() !== 17) {
|
|
753
|
-
handleError(9, [], []);
|
|
754
|
-
}
|
|
755
|
-
return true;
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
// node_modules/jsonc-parser/lib/esm/main.js
|
|
759
|
-
var ScanError;
|
|
760
|
-
(function(ScanError2) {
|
|
761
|
-
ScanError2[ScanError2["None"] = 0] = "None";
|
|
762
|
-
ScanError2[ScanError2["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
|
|
763
|
-
ScanError2[ScanError2["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
|
|
764
|
-
ScanError2[ScanError2["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
|
|
765
|
-
ScanError2[ScanError2["InvalidUnicode"] = 4] = "InvalidUnicode";
|
|
766
|
-
ScanError2[ScanError2["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
|
|
767
|
-
ScanError2[ScanError2["InvalidCharacter"] = 6] = "InvalidCharacter";
|
|
768
|
-
})(ScanError || (ScanError = {}));
|
|
769
|
-
var SyntaxKind;
|
|
770
|
-
(function(SyntaxKind2) {
|
|
771
|
-
SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 1] = "OpenBraceToken";
|
|
772
|
-
SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 2] = "CloseBraceToken";
|
|
773
|
-
SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 3] = "OpenBracketToken";
|
|
774
|
-
SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 4] = "CloseBracketToken";
|
|
775
|
-
SyntaxKind2[SyntaxKind2["CommaToken"] = 5] = "CommaToken";
|
|
776
|
-
SyntaxKind2[SyntaxKind2["ColonToken"] = 6] = "ColonToken";
|
|
777
|
-
SyntaxKind2[SyntaxKind2["NullKeyword"] = 7] = "NullKeyword";
|
|
778
|
-
SyntaxKind2[SyntaxKind2["TrueKeyword"] = 8] = "TrueKeyword";
|
|
779
|
-
SyntaxKind2[SyntaxKind2["FalseKeyword"] = 9] = "FalseKeyword";
|
|
780
|
-
SyntaxKind2[SyntaxKind2["StringLiteral"] = 10] = "StringLiteral";
|
|
781
|
-
SyntaxKind2[SyntaxKind2["NumericLiteral"] = 11] = "NumericLiteral";
|
|
782
|
-
SyntaxKind2[SyntaxKind2["LineCommentTrivia"] = 12] = "LineCommentTrivia";
|
|
783
|
-
SyntaxKind2[SyntaxKind2["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
|
|
784
|
-
SyntaxKind2[SyntaxKind2["LineBreakTrivia"] = 14] = "LineBreakTrivia";
|
|
785
|
-
SyntaxKind2[SyntaxKind2["Trivia"] = 15] = "Trivia";
|
|
786
|
-
SyntaxKind2[SyntaxKind2["Unknown"] = 16] = "Unknown";
|
|
787
|
-
SyntaxKind2[SyntaxKind2["EOF"] = 17] = "EOF";
|
|
788
|
-
})(SyntaxKind || (SyntaxKind = {}));
|
|
789
|
-
var parse2 = parse;
|
|
790
|
-
var ParseErrorCode;
|
|
791
|
-
(function(ParseErrorCode2) {
|
|
792
|
-
ParseErrorCode2[ParseErrorCode2["InvalidSymbol"] = 1] = "InvalidSymbol";
|
|
793
|
-
ParseErrorCode2[ParseErrorCode2["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
|
|
794
|
-
ParseErrorCode2[ParseErrorCode2["PropertyNameExpected"] = 3] = "PropertyNameExpected";
|
|
795
|
-
ParseErrorCode2[ParseErrorCode2["ValueExpected"] = 4] = "ValueExpected";
|
|
796
|
-
ParseErrorCode2[ParseErrorCode2["ColonExpected"] = 5] = "ColonExpected";
|
|
797
|
-
ParseErrorCode2[ParseErrorCode2["CommaExpected"] = 6] = "CommaExpected";
|
|
798
|
-
ParseErrorCode2[ParseErrorCode2["CloseBraceExpected"] = 7] = "CloseBraceExpected";
|
|
799
|
-
ParseErrorCode2[ParseErrorCode2["CloseBracketExpected"] = 8] = "CloseBracketExpected";
|
|
800
|
-
ParseErrorCode2[ParseErrorCode2["EndOfFileExpected"] = 9] = "EndOfFileExpected";
|
|
801
|
-
ParseErrorCode2[ParseErrorCode2["InvalidCommentToken"] = 10] = "InvalidCommentToken";
|
|
802
|
-
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
|
|
803
|
-
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
|
|
804
|
-
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
|
|
805
|
-
ParseErrorCode2[ParseErrorCode2["InvalidUnicode"] = 14] = "InvalidUnicode";
|
|
806
|
-
ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
|
|
807
|
-
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
808
|
-
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
809
|
-
|
|
810
|
-
// src/lib/config.ts
|
|
811
|
-
import { readFileSync } from "fs";
|
|
812
|
-
import { join as join2 } from "path";
|
|
813
|
-
|
|
814
|
-
// src/constants.ts
|
|
815
|
-
var DEFAULTS = {
|
|
816
|
-
configPath: ".context/config.jsonc",
|
|
817
|
-
promptDir: ".context/prompts",
|
|
818
|
-
turnStartFile: "turn-start.md",
|
|
819
|
-
turnEndFile: "turn-end.md",
|
|
820
|
-
knowledgeSources: ["AGENTS.md"],
|
|
821
|
-
templateDir: ".context/templates",
|
|
822
|
-
indexFilename: "INDEX.md",
|
|
823
|
-
maxDomainDepth: 2,
|
|
824
|
-
knowledgeDir: "docs",
|
|
825
|
-
guidesDir: ".context/guides",
|
|
826
|
-
workCompleteFile: ".context/.work-complete"
|
|
827
|
-
};
|
|
828
|
-
var LIMITS = {
|
|
829
|
-
maxPromptFileSize: 64 * 1024,
|
|
830
|
-
maxIndexEntries: 100,
|
|
831
|
-
maxTotalInjectionSize: 128 * 1024,
|
|
832
|
-
maxScanDepth: 3,
|
|
833
|
-
maxSummaryLength: 100,
|
|
834
|
-
maxIndexFileSize: 32 * 1024
|
|
835
|
-
};
|
|
3
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, statSync, unlinkSync } from "fs";
|
|
4
|
+
import { join as join3, dirname } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
836
6
|
|
|
837
7
|
// src/lib/context-dir.ts
|
|
838
8
|
import { existsSync } from "fs";
|
|
@@ -849,287 +19,13 @@ function resolveContextDir(projectDir) {
|
|
|
849
19
|
return nextContextDir;
|
|
850
20
|
}
|
|
851
21
|
|
|
852
|
-
// src/lib/config.ts
|
|
853
|
-
function getDefaultConfig() {
|
|
854
|
-
return {
|
|
855
|
-
prompts: {
|
|
856
|
-
turnStart: join2(DEFAULTS.promptDir, DEFAULTS.turnStartFile),
|
|
857
|
-
turnEnd: join2(DEFAULTS.promptDir, DEFAULTS.turnEndFile)
|
|
858
|
-
},
|
|
859
|
-
knowledge: {
|
|
860
|
-
dir: "docs",
|
|
861
|
-
sources: [...DEFAULTS.knowledgeSources],
|
|
862
|
-
mode: "auto",
|
|
863
|
-
indexFilename: DEFAULTS.indexFilename,
|
|
864
|
-
maxDomainDepth: DEFAULTS.maxDomainDepth
|
|
865
|
-
},
|
|
866
|
-
omx: {
|
|
867
|
-
turnEnd: {
|
|
868
|
-
strategy: "turn-complete-sendkeys"
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
};
|
|
872
|
-
}
|
|
873
|
-
function mergeWithDefaults(partial) {
|
|
874
|
-
const defaults = getDefaultConfig();
|
|
875
|
-
return {
|
|
876
|
-
prompts: {
|
|
877
|
-
turnStart: partial.prompts?.turnStart ?? defaults.prompts.turnStart,
|
|
878
|
-
turnEnd: partial.prompts?.turnEnd ?? defaults.prompts.turnEnd
|
|
879
|
-
},
|
|
880
|
-
knowledge: {
|
|
881
|
-
dir: partial.knowledge?.dir ?? defaults.knowledge.dir,
|
|
882
|
-
sources: partial.knowledge?.sources ?? defaults.knowledge.sources,
|
|
883
|
-
mode: partial.knowledge?.mode ?? defaults.knowledge.mode,
|
|
884
|
-
indexFilename: partial.knowledge?.indexFilename ?? defaults.knowledge.indexFilename,
|
|
885
|
-
maxDomainDepth: partial.knowledge?.maxDomainDepth ?? defaults.knowledge.maxDomainDepth
|
|
886
|
-
},
|
|
887
|
-
omx: {
|
|
888
|
-
turnEnd: {
|
|
889
|
-
strategy: partial.omx?.turnEnd?.strategy ?? defaults.omx?.turnEnd?.strategy
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
};
|
|
893
|
-
}
|
|
894
|
-
function loadConfig(projectDir) {
|
|
895
|
-
const configPath = join2(projectDir, resolveContextDir(projectDir), "config.jsonc");
|
|
896
|
-
try {
|
|
897
|
-
const raw = readFileSync(configPath, "utf-8");
|
|
898
|
-
const parsed = parse2(raw);
|
|
899
|
-
if (!parsed || typeof parsed !== "object")
|
|
900
|
-
return getDefaultConfig();
|
|
901
|
-
return mergeWithDefaults(parsed);
|
|
902
|
-
} catch {
|
|
903
|
-
return getDefaultConfig();
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
// src/lib/knowledge-index.ts
|
|
908
|
-
import { readdirSync, readFileSync as readFileSync2, statSync, existsSync as existsSync2 } from "fs";
|
|
909
|
-
import { join as join3, relative, extname } from "path";
|
|
910
|
-
function extractSummary(filePath) {
|
|
911
|
-
try {
|
|
912
|
-
const content = readFileSync2(filePath, "utf-8");
|
|
913
|
-
const firstNonEmpty = content.split(`
|
|
914
|
-
`).find((line) => line.trim().length > 0);
|
|
915
|
-
if (!firstNonEmpty)
|
|
916
|
-
return "";
|
|
917
|
-
return firstNonEmpty.trim().slice(0, LIMITS.maxSummaryLength);
|
|
918
|
-
} catch {
|
|
919
|
-
return "";
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
function scanDir(dir, projectDir, depth, entries) {
|
|
923
|
-
if (depth > LIMITS.maxScanDepth)
|
|
924
|
-
return;
|
|
925
|
-
if (entries.length >= LIMITS.maxIndexEntries)
|
|
926
|
-
return;
|
|
927
|
-
try {
|
|
928
|
-
const items = readdirSync(dir);
|
|
929
|
-
for (const item of items) {
|
|
930
|
-
if (entries.length >= LIMITS.maxIndexEntries)
|
|
931
|
-
break;
|
|
932
|
-
const fullPath = join3(dir, item);
|
|
933
|
-
try {
|
|
934
|
-
const stat = statSync(fullPath);
|
|
935
|
-
if (stat.isDirectory()) {
|
|
936
|
-
scanDir(fullPath, projectDir, depth + 1, entries);
|
|
937
|
-
} else if (stat.isFile() && extname(item) === ".md") {
|
|
938
|
-
entries.push({
|
|
939
|
-
filename: relative(projectDir, fullPath),
|
|
940
|
-
summary: extractSummary(fullPath)
|
|
941
|
-
});
|
|
942
|
-
}
|
|
943
|
-
} catch {}
|
|
944
|
-
}
|
|
945
|
-
} catch {}
|
|
946
|
-
}
|
|
947
|
-
function buildKnowledgeIndex(projectDir, sources) {
|
|
948
|
-
const entries = [];
|
|
949
|
-
for (const source of sources) {
|
|
950
|
-
if (entries.length >= LIMITS.maxIndexEntries)
|
|
951
|
-
break;
|
|
952
|
-
const fullPath = join3(projectDir, source);
|
|
953
|
-
if (!existsSync2(fullPath))
|
|
954
|
-
continue;
|
|
955
|
-
try {
|
|
956
|
-
const stat = statSync(fullPath);
|
|
957
|
-
if (stat.isFile() && extname(source) === ".md") {
|
|
958
|
-
entries.push({
|
|
959
|
-
filename: source,
|
|
960
|
-
summary: extractSummary(fullPath)
|
|
961
|
-
});
|
|
962
|
-
} else if (stat.isDirectory()) {
|
|
963
|
-
scanDir(fullPath, projectDir, 1, entries);
|
|
964
|
-
}
|
|
965
|
-
} catch {}
|
|
966
|
-
}
|
|
967
|
-
return entries;
|
|
968
|
-
}
|
|
969
|
-
function formatKnowledgeIndex(entries) {
|
|
970
|
-
if (entries.length === 0)
|
|
971
|
-
return "";
|
|
972
|
-
const lines = ["## Available Knowledge", ""];
|
|
973
|
-
for (const entry of entries) {
|
|
974
|
-
lines.push(`- ${entry.filename}${entry.summary ? ` \u2014 ${entry.summary}` : ""}`);
|
|
975
|
-
}
|
|
976
|
-
return lines.join(`
|
|
977
|
-
`);
|
|
978
|
-
}
|
|
979
|
-
function countMdFiles(dir, indexFilename) {
|
|
980
|
-
try {
|
|
981
|
-
const items = readdirSync(dir);
|
|
982
|
-
return items.filter((item) => extname(item) === ".md" && item !== indexFilename && statSync(join3(dir, item)).isFile()).length;
|
|
983
|
-
} catch {
|
|
984
|
-
return 0;
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
function scanDomainsRecursive(baseDir, projectDir, indexFilename, currentDepth, maxDepth, results) {
|
|
988
|
-
if (currentDepth > maxDepth)
|
|
989
|
-
return;
|
|
990
|
-
try {
|
|
991
|
-
const items = readdirSync(baseDir);
|
|
992
|
-
for (const item of items) {
|
|
993
|
-
const fullPath = join3(baseDir, item);
|
|
994
|
-
try {
|
|
995
|
-
if (!statSync(fullPath).isDirectory())
|
|
996
|
-
continue;
|
|
997
|
-
const indexPath = join3(fullPath, indexFilename);
|
|
998
|
-
if (existsSync2(indexPath) && statSync(indexPath).isFile()) {
|
|
999
|
-
const rawContent = readFileSync2(indexPath, "utf-8");
|
|
1000
|
-
const indexContent = rawContent.slice(0, LIMITS.maxIndexFileSize);
|
|
1001
|
-
results.push({
|
|
1002
|
-
domain: item,
|
|
1003
|
-
path: relative(projectDir, fullPath),
|
|
1004
|
-
indexContent,
|
|
1005
|
-
noteCount: countMdFiles(fullPath, indexFilename)
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1008
|
-
scanDomainsRecursive(fullPath, projectDir, indexFilename, currentDepth + 1, maxDepth, results);
|
|
1009
|
-
} catch {}
|
|
1010
|
-
}
|
|
1011
|
-
} catch {}
|
|
1012
|
-
}
|
|
1013
|
-
function scanDomains(projectDir, knowledgeDir, indexFilename, maxDepth) {
|
|
1014
|
-
const baseDir = join3(projectDir, knowledgeDir);
|
|
1015
|
-
if (!existsSync2(baseDir))
|
|
1016
|
-
return [];
|
|
1017
|
-
const results = [];
|
|
1018
|
-
scanDomainsRecursive(baseDir, projectDir, indexFilename, 1, maxDepth, results);
|
|
1019
|
-
return results;
|
|
1020
|
-
}
|
|
1021
|
-
function detectKnowledgeMode(projectDir, knowledgeDir, indexFilename, configMode) {
|
|
1022
|
-
if (configMode !== "auto")
|
|
1023
|
-
return configMode;
|
|
1024
|
-
const domains = scanDomains(projectDir, knowledgeDir, indexFilename, 1);
|
|
1025
|
-
return domains.length > 0 ? "domain" : "flat";
|
|
1026
|
-
}
|
|
1027
|
-
function formatDomainIndex(index) {
|
|
1028
|
-
const hasDomains = index.domains.length > 0;
|
|
1029
|
-
const hasFiles = index.individualFiles.length > 0;
|
|
1030
|
-
if (!hasDomains && !hasFiles)
|
|
1031
|
-
return "";
|
|
1032
|
-
const lines = ["## Available Knowledge", ""];
|
|
1033
|
-
if (hasDomains) {
|
|
1034
|
-
lines.push("### Domains", "");
|
|
1035
|
-
for (const domain of index.domains) {
|
|
1036
|
-
lines.push(`#### ${domain.path}/ (${domain.noteCount} notes)`, "");
|
|
1037
|
-
lines.push(domain.indexContent, "");
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
if (hasFiles) {
|
|
1041
|
-
if (hasDomains) {
|
|
1042
|
-
lines.push("### Individual Files", "");
|
|
1043
|
-
}
|
|
1044
|
-
for (const file of index.individualFiles) {
|
|
1045
|
-
lines.push(`- ${file.filename}${file.summary ? ` \u2014 ${file.summary}` : ""}`);
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
return lines.join(`
|
|
1049
|
-
`);
|
|
1050
|
-
}
|
|
1051
|
-
function collectRootFiles(projectDir, knowledgeDir, indexFilename) {
|
|
1052
|
-
const baseDir = join3(projectDir, knowledgeDir);
|
|
1053
|
-
if (!existsSync2(baseDir))
|
|
1054
|
-
return [];
|
|
1055
|
-
const entries = [];
|
|
1056
|
-
try {
|
|
1057
|
-
const items = readdirSync(baseDir);
|
|
1058
|
-
for (const item of items) {
|
|
1059
|
-
const fullPath = join3(baseDir, item);
|
|
1060
|
-
try {
|
|
1061
|
-
const stat = statSync(fullPath);
|
|
1062
|
-
if (stat.isFile() && extname(item) === ".md" && item !== indexFilename) {
|
|
1063
|
-
entries.push({
|
|
1064
|
-
filename: relative(projectDir, fullPath),
|
|
1065
|
-
summary: extractSummary(fullPath)
|
|
1066
|
-
});
|
|
1067
|
-
}
|
|
1068
|
-
} catch {}
|
|
1069
|
-
}
|
|
1070
|
-
} catch {}
|
|
1071
|
-
return entries;
|
|
1072
|
-
}
|
|
1073
|
-
function buildKnowledgeIndexV2(projectDir, knowledgeConfig) {
|
|
1074
|
-
const dir = knowledgeConfig.dir ?? "docs";
|
|
1075
|
-
const indexFilename = knowledgeConfig.indexFilename ?? "INDEX.md";
|
|
1076
|
-
const maxDepth = knowledgeConfig.maxDomainDepth ?? 2;
|
|
1077
|
-
const configMode = knowledgeConfig.mode ?? "auto";
|
|
1078
|
-
const mode = detectKnowledgeMode(projectDir, dir, indexFilename, configMode);
|
|
1079
|
-
if (mode === "flat") {
|
|
1080
|
-
const allSources = [dir, ...knowledgeConfig.sources].filter(Boolean);
|
|
1081
|
-
const entries = buildKnowledgeIndex(projectDir, allSources);
|
|
1082
|
-
return { mode: "flat", domains: [], individualFiles: entries };
|
|
1083
|
-
}
|
|
1084
|
-
const domains = scanDomains(projectDir, dir, indexFilename, maxDepth);
|
|
1085
|
-
const rootFiles = collectRootFiles(projectDir, dir, indexFilename);
|
|
1086
|
-
const sourcesEntries = [];
|
|
1087
|
-
for (const source of knowledgeConfig.sources) {
|
|
1088
|
-
const fullPath = join3(projectDir, source);
|
|
1089
|
-
if (!existsSync2(fullPath))
|
|
1090
|
-
continue;
|
|
1091
|
-
try {
|
|
1092
|
-
const stat = statSync(fullPath);
|
|
1093
|
-
if (stat.isFile() && extname(source) === ".md") {
|
|
1094
|
-
sourcesEntries.push({
|
|
1095
|
-
filename: source,
|
|
1096
|
-
summary: extractSummary(fullPath)
|
|
1097
|
-
});
|
|
1098
|
-
}
|
|
1099
|
-
} catch {}
|
|
1100
|
-
}
|
|
1101
|
-
const individualFiles = [...rootFiles, ...sourcesEntries];
|
|
1102
|
-
return { mode: "domain", domains, individualFiles };
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
// src/lib/prompt-reader.ts
|
|
1106
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
1107
|
-
function readPromptFile(filePath) {
|
|
1108
|
-
try {
|
|
1109
|
-
const content = readFileSync3(filePath, "utf-8");
|
|
1110
|
-
if (content.length > LIMITS.maxPromptFileSize) {
|
|
1111
|
-
return content.slice(0, LIMITS.maxPromptFileSize);
|
|
1112
|
-
}
|
|
1113
|
-
return content;
|
|
1114
|
-
} catch {
|
|
1115
|
-
return "";
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
function resolvePromptVariables(content, vars) {
|
|
1119
|
-
const normalized = (vars.knowledgeDir || "docs").replace(/\\/g, "/").replace(/\/+$/, "");
|
|
1120
|
-
let resolved = content.replaceAll("{{knowledgeDir}}", normalized);
|
|
1121
|
-
resolved = resolved.replaceAll("{{sessionId}}", vars.sessionId ?? "");
|
|
1122
|
-
resolved = resolved.replaceAll("{{turnId}}", vars.turnId ?? "");
|
|
1123
|
-
return resolved;
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
22
|
// src/lib/scaffold.ts
|
|
1127
|
-
import { existsSync as
|
|
1128
|
-
import { join as
|
|
23
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
24
|
+
import { join as join2 } from "path";
|
|
1129
25
|
// package.json
|
|
1130
26
|
var package_default = {
|
|
1131
27
|
name: "@ksm0709/context",
|
|
1132
|
-
version: "0.0.
|
|
28
|
+
version: "0.0.23",
|
|
1133
29
|
author: {
|
|
1134
30
|
name: "TaehoKang",
|
|
1135
31
|
email: "ksm07091@gmail.com"
|
|
@@ -1159,10 +55,10 @@ var package_default = {
|
|
|
1159
55
|
access: "public"
|
|
1160
56
|
},
|
|
1161
57
|
scripts: {
|
|
1162
|
-
build: "bun build ./src/index.ts --outdir dist --target bun && bun build ./src/cli/index.ts --outdir dist/cli --target bun && bun build ./src/omx/index.ts --outdir dist/omx --target node --format esm --external jsonc-parser && mv dist/omx/index.js dist/omx/index.mjs",
|
|
58
|
+
build: "bun build ./src/index.ts --outdir dist --target bun && bun build ./src/mcp.ts --outdir dist --target bun && bun build ./src/cli/index.ts --outdir dist/cli --target bun && bun build ./src/omx/index.ts --outdir dist/omx --target node --format esm --external jsonc-parser && mv dist/omx/index.js dist/omx/index.mjs",
|
|
1163
59
|
test: "vitest run",
|
|
1164
60
|
lint: "eslint src --ext .ts",
|
|
1165
|
-
prepublishOnly: "bun build ./src/index.ts --outdir dist --target bun && bun build ./src/cli/index.ts --outdir dist/cli --target bun && bun build ./src/omx/index.ts --outdir dist/omx --target node --format esm --external jsonc-parser && mv dist/omx/index.js dist/omx/index.mjs"
|
|
61
|
+
prepublishOnly: "bun build ./src/index.ts --outdir dist --target bun && bun build ./src/mcp.ts --outdir dist --target bun && bun build ./src/cli/index.ts --outdir dist/cli --target bun && bun build ./src/omx/index.ts --outdir dist/omx --target node --format esm --external jsonc-parser && mv dist/omx/index.js dist/omx/index.mjs"
|
|
1166
62
|
},
|
|
1167
63
|
files: [
|
|
1168
64
|
"dist"
|
|
@@ -1171,7 +67,8 @@ var package_default = {
|
|
|
1171
67
|
"@opencode-ai/plugin": ">=1.0.0"
|
|
1172
68
|
},
|
|
1173
69
|
dependencies: {
|
|
1174
|
-
"@ksm0709/context": "^0.0.
|
|
70
|
+
"@ksm0709/context": "^0.0.22",
|
|
71
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
1175
72
|
"jsonc-parser": "^3.0.0"
|
|
1176
73
|
},
|
|
1177
74
|
devDependencies: {
|
|
@@ -1196,10 +93,6 @@ var PLUGIN_VERSION = package_default.version;
|
|
|
1196
93
|
var DEFAULT_CONFIG = `{
|
|
1197
94
|
// Context Plugin Configuration
|
|
1198
95
|
// See: https://github.com/ksm0709/context
|
|
1199
|
-
"prompts": {
|
|
1200
|
-
"turnStart": "prompts/turn-start.md",
|
|
1201
|
-
"turnEnd": "prompts/turn-end.md"
|
|
1202
|
-
},
|
|
1203
96
|
"knowledge": {
|
|
1204
97
|
"dir": ".context/memory",
|
|
1205
98
|
"sources": ["AGENTS.md"]
|
|
@@ -1211,53 +104,6 @@ var DEFAULT_CONFIG = `{
|
|
|
1211
104
|
}
|
|
1212
105
|
}
|
|
1213
106
|
}`;
|
|
1214
|
-
var DEFAULT_TURN_START = `## Knowledge Context
|
|
1215
|
-
|
|
1216
|
-
\uC774 \uD504\uB85C\uC81D\uD2B8\uB294 **\uC81C\uD154\uCE74\uC2A4\uD150(Zettelkasten)** \uBC29\uC2DD\uC73C\uB85C \uC9C0\uC2DD\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4.
|
|
1217
|
-
\uC138\uC158 \uAC04 \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uBCF4\uC874\uD558\uC5EC, \uC774\uC804 \uC138\uC158\uC758 \uACB0\uC815/\uD328\uD134/\uC2E4\uC218\uAC00 \uB2E4\uC74C \uC138\uC158\uC5D0\uC11C \uC7AC\uD65C\uC6A9\uB429\uB2C8\uB2E4.
|
|
1218
|
-
|
|
1219
|
-
### \uC81C\uD154\uCE74\uC2A4\uD150 \uD575\uC2EC \uC6D0\uCE59
|
|
1220
|
-
|
|
1221
|
-
1. **\uC6D0\uC790\uC131** -- \uD558\uB098\uC758 \uB178\uD2B8 = \uD558\uB098\uC758 \uC8FC\uC81C. \uC5EC\uB7EC \uC8FC\uC81C\uB97C \uC11E\uC9C0 \uB9C8\uC138\uC694.
|
|
1222
|
-
2. **\uC5F0\uACB0** -- \uBAA8\uB4E0 \uB178\uD2B8\uB294 [[wikilink]]\uB85C \uAD00\uB828 \uB178\uD2B8\uC5D0 \uC5F0\uACB0. \uACE0\uB9BD\uB41C \uB178\uD2B8\uB294 \uBC1C\uACAC\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
|
1223
|
-
3. **\uC790\uAE30 \uC5B8\uC5B4** -- \uBCF5\uC0AC-\uBD99\uC5EC\uB123\uAE30\uAC00 \uC544\uB2CC, \uD575\uC2EC\uC744 \uC774\uD574\uD558\uACE0 \uAC04\uACB0\uD558\uAC8C \uC11C\uC220\uD558\uC138\uC694.
|
|
1224
|
-
|
|
1225
|
-
### \uC791\uC5C5 \uC804 \uD544\uC218
|
|
1226
|
-
|
|
1227
|
-
- **\uB370\uC77C\uB9AC \uB178\uD2B8 \uD655\uC778**: \uAC00\uC7A5 \uCD5C\uADFC\uC758 \uB370\uC77C\uB9AC \uB178\uD2B8(\`{{knowledgeDir}}/daily/YYYY-MM-DD.md\`)\uB97C \uC77D\uACE0 \uC774\uC804 \uC138\uC158\uC758 \uCEE8\uD14D\uC2A4\uD2B8\uC640 \uBBF8\uD574\uACB0 \uC774\uC288\uB97C \uD30C\uC545\uD558\uC138\uC694
|
|
1228
|
-
- **\uC791\uC5C5 \uC758\uB3C4 \uC120\uC5B8**: \uC791\uC5C5 \uC2DC\uC791 \uC804, \uD604\uC7AC \uC138\uC158\uC758 \uBAA9\uD45C\uC640 \uC791\uC5C5 \uC758\uB3C4\uB97C \uBA85\uD655\uD788 \uD30C\uC545\uD558\uACE0 \uC120\uC5B8\uD558\uC138\uC694 (\uCD94\uD6C4 \uC791\uC5C5 \uACBD\uB85C \uAC80\uC99D \uC2DC \uAE30\uC900\uC774 \uB429\uB2C8\uB2E4)
|
|
1229
|
-
- \uBA54\uC778 \uC5D0\uC774\uC804\uD2B8\uAC00 \uC544\uB798 **Available Knowledge** \uBAA9\uB85D\uC5D0\uC11C \uD604\uC7AC \uC791\uC5C5\uACFC \uAD00\uB828\uB41C \uBB38\uC11C\uB97C **\uC9C1\uC811 \uBA3C\uC800** \uC77D\uC73C\uC138\uC694
|
|
1230
|
-
- \uB3C4\uBA54\uC778 \uD3F4\uB354 \uAD6C\uC870\uAC00 \uC788\uB2E4\uBA74 INDEX.md\uC758 \uC694\uC57D\uC744 \uCC38\uACE0\uD558\uC5EC \uD544\uC694\uD55C \uB178\uD2B8\uB9CC \uC120\uD0DD\uC801\uC73C\uB85C \uC77D\uC73C\uC138\uC694
|
|
1231
|
-
- \uBB38\uC11C \uB0B4 [[\uB9C1\uD06C]]\uB97C \uB530\uB77C\uAC00\uBA70 \uAD00\uB828 \uB178\uD2B8\uB97C \uD0D0\uC0C9\uD558\uC138\uC694 -- \uB9C1\uD06C\uB97C \uB193\uCE58\uBA74 \uC911\uC694\uD55C \uB9E5\uB77D\uC744 \uC783\uC2B5\uB2C8\uB2E4
|
|
1232
|
-
- \uC9C0\uC2DD \uD30C\uC77C\uC5D0 \uAE30\uB85D\uB41C \uC544\uD0A4\uD14D\uCC98 \uACB0\uC815, \uD328\uD134, \uC81C\uC57D\uC0AC\uD56D\uC744 \uBC18\uB4DC\uC2DC \uB530\uB974\uC138\uC694
|
|
1233
|
-
- \uC77D\uC740 \uC9C0\uC2DD\uC744 \uD604\uC7AC \uC791\uC5C5\uC758 \uC124\uACC4, \uAD6C\uD604, \uAC80\uC99D\uC5D0 \uC9C1\uC811 \uBC18\uC601\uD558\uC138\uC694
|
|
1234
|
-
|
|
1235
|
-
### \uAC1C\uBC1C \uC6D0\uCE59
|
|
1236
|
-
|
|
1237
|
-
- **TDD** (Test-Driven Development): \uD14C\uC2A4\uD2B8\uB97C \uBA3C\uC800 \uC791\uC131\uD558\uACE0(RED), \uAD6C\uD604\uD558\uC5EC \uD1B5\uACFC\uC2DC\uD0A8 \uB4A4(GREEN), \uB9AC\uD329\uD1A0\uB9C1\uD558\uC138\uC694
|
|
1238
|
-
- **DDD** (Domain-Driven Design): \uB3C4\uBA54\uC778 \uAC1C\uB150\uC744 \uCF54\uB4DC \uAD6C\uC870\uC5D0 \uBC18\uC601\uD558\uC138\uC694. \uD0C0\uC785\uACFC \uBAA8\uB4C8\uC740 \uBE44\uC988\uB2C8\uC2A4 \uB3C4\uBA54\uC778\uC744 \uAE30\uC900\uC73C\uB85C \uBD84\uB9AC\uD558\uC138\uC694
|
|
1239
|
-
- **\uD14C\uC2A4\uD2B8 \uCEE4\uBC84\uB9AC\uC9C0**: \uC0C8\uB85C \uC791\uC131\uD558\uAC70\uB098 \uBCC0\uACBD\uD55C \uCF54\uB4DC\uB294 \uD14C\uC2A4\uD2B8 \uCEE4\uBC84\uB9AC\uC9C0 80% \uC774\uC0C1\uC744 \uBAA9\uD45C\uB85C \uD558\uC138\uC694. \uAD6C\uD604 \uC804\uC5D0 \uD14C\uC2A4\uD2B8\uBD80\uD130 \uC791\uC131\uD558\uBA74 \uC790\uC5F0\uC2A4\uB7FD\uAC8C \uB2EC\uC131\uB429\uB2C8\uB2E4
|
|
1240
|
-
|
|
1241
|
-
### \uC6B0\uC120\uC21C\uC704
|
|
1242
|
-
|
|
1243
|
-
- AGENTS.md\uC758 \uC9C0\uC2DC\uC0AC\uD56D\uC774 \uD56D\uC0C1 \uCD5C\uC6B0\uC120
|
|
1244
|
-
- \uC9C0\uC2DD \uB178\uD2B8\uC758 \uACB0\uC815\uC0AC\uD56D > \uC77C\uBC18\uC801 \uAD00\uD589
|
|
1245
|
-
- \uC9C0\uC2DD \uB178\uD2B8\uC5D0 \uC5C6\uB294 \uC0C8\uB85C\uC6B4 \uACB0\uC815\uC774\uB098 \uBC18\uBCF5 \uAC00\uCE58\uAC00 \uC788\uB294 \uBC1C\uACAC\uC740 \uC791\uC5C5 \uBA54\uBAA8\uB098 \uC9C0\uC2DD \uB178\uD2B8 \uD6C4\uBCF4\uB85C \uAE30\uB85D\uD558\uC138\uC694
|
|
1246
|
-
`;
|
|
1247
|
-
var DEFAULT_TURN_END = `## TURN END \uC791\uC5C5 \uC9C0\uCE68
|
|
1248
|
-
\uC774 \uC9C0\uCE68\uC740 \uC5D0\uC774\uC804\uD2B8\uB97C \uC704\uD55C \uAC83\uC774\uBA70, \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC9C1\uC811\uC801\uC73C\uB85C \uB178\uCD9C\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
|
1249
|
-
\uC544\uB798 \uBA54\uB274 \uC911 \uD558\uB098\uB97C \uC120\uD0DD\uD574 \uC9C4\uD589 \uC0C1\uD669\uC5D0 \uB9DE\uAC8C \uC218\uD589\uD558\uC138\uC694.
|
|
1250
|
-
**\uBC18\uB4DC\uC2DC \uB9C1\uD06C\uB41C \uAC00\uC774\uB4DC\uB97C \uCC38\uACE0\uD558\uC5EC \uC815\uD655\uD788 \uC218\uD589\uD574\uC57C \uD569\uB2C8\uB2E4.**
|
|
1251
|
-
|
|
1252
|
-
1. **\uACC4\uC18D \uC791\uC5C5**: \uAE30\uC874 \uC791\uC5C5\uC774 \uC644\uB8CC\uB418\uC9C0 \uC54A\uC558\uACE0 \uC544\uC9C1 \uC544\uB798 \uC561\uC158\uC744 \uCDE8\uD560 \uB2E8\uACC4\uAC00 \uC544\uB2C8\uB77C\uBA74 \uC791\uC5C5 \uC18D\uAC1C.
|
|
1253
|
-
2. **\uB370\uC77C\uB9AC \uB178\uD2B8 \uAE30\uB85D**: [.context/guides/daily-note-guide.md] \uB370\uC77C\uB9AC \uB178\uD2B8\uC5D0 \uC911\uC694\uD55C \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uAE30\uB85D\uD558\uC5EC \uB2E4\uC74C \uC138\uC158\uC774\uB098 \uC5D0\uC774\uC804\uD2B8 \uD300\uC774 \uCC38\uACE0\uD560 \uC218 \uC788\uB3C4\uB85D \uD558\uC138\uC694. \uAE30\uC874 \uB0B4\uC6A9 \uC218\uC815\uC740 \uBD88\uAC00\uD558\uBA70, \uC0C8\uB85C\uC6B4 \uBA54\uBAA8\uB97C \uCD94\uAC00 \uD558\uB294\uAC83\uB9CC \uAC00\uB2A5\uD569\uB2C8\uB2E4. \uAC04\uB7B5\uD55C \uD55C \uB450 \uBB38\uC7A5\uC73C\uB85C \uC791\uC131\uD558\uC5EC \uD575\uC2EC \uCEE8\uD14D\uC2A4\uD2B8\uAC00 \uBA85\uD655\uD788 \uC804\uB2EC\uB418\uB3C4\uB85D \uD558\uC138\uC694.
|
|
1254
|
-
3. **\uC9C0\uC2DD \uB178\uD2B8 \uC791\uC131**: [.context/guides/note-guide.md] \uC791\uC5C5\uAE30\uC5B5(\uB370\uC77C\uB9AC\uB178\uD2B8, \uC138\uC158 \uCEE8\uD14D\uC2A4\uD2B8)\uBCF4\uB2E4 \uC624\uB798 \uAE30\uC5B5\uB418\uC5B4\uC57C \uD558\uB294 \uC911\uC694\uD55C \uACB0\uC815, \uD328\uD134, \uC2E4\uC218, \uBC1C\uACAC\uC740 \uC9C0\uC2DD \uB178\uD2B8\uB85C \uAE30\uB85D\uD558\uC5EC \uD504\uB85C\uC81D\uD2B8\uC758 \uC9D1\uB2E8 \uC9C0\uC2DD\uC73C\uB85C \uB0A8\uAE30\uC138\uC694.
|
|
1255
|
-
4. **\uB178\uD2B8/\uC2A4\uD0AC \uAC80\uC0C9 \uBC0F \uC77D\uAE30**: [.context/guides/search-guide.md] \uC5B4\uB824\uC6C0\uC5D0 \uCC98\uD588\uB2E4\uBA74 \uD604\uC7AC \uC9C4\uD589 \uC0C1\uD669\uC5D0 \uD544\uC694\uD55C \uC9C0\uC2DD\uC774\uB098 \uC2A4\uD0AC\uC774 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uACE0, \uAD00\uB828 \uB178\uD2B8\uB97C \uC77D\uC5B4\uBCF4\uC138\uC694. \uC0C8\uB85C\uC6B4 \uC544\uC774\uB514\uC5B4\uB098 \uD574\uACB0\uCC45\uC774 \uB5A0\uC624\uB97C \uC218 \uC788\uC2B5\uB2C8\uB2E4.
|
|
1256
|
-
5. **\uC791\uC5C5 \uACBD\uB85C \uB9AC\uBDF0**: [.context/guides/scope-review.md] \uC0AC\uC6A9\uC790\uAC00 \uC758\uB3C4\uD55C \uC791\uC5C5 \uBC94\uC704\uB97C \uBC97\uC5B4\uB098\uC9C0 \uC54A\uC558\uB294\uC9C0, \uC791\uC5C5\uC774 \uB108\uBB34 \uD06C\uAC70\uB098 \uBCF5\uC7A1\uD574\uC9C0\uC9C0\uB294 \uC54A\uC558\uB294\uC9C0 \uAC80\uD1A0\uD558\uC138\uC694.
|
|
1257
|
-
6. **\uCCB4\uD06C\uD3EC\uC778\uD2B8 \uCEE4\uBC0B**: [.context/guides/commit-guide.md] \uC791\uC5C5\uC774 \uAE38\uC5B4\uC9C8 \uACBD\uC6B0, \uC911\uC694\uD55C \uB2E8\uACC4\uB9C8\uB2E4 \uCCB4\uD06C\uD3EC\uC778\uD2B8 \uCEE4\uBC0B\uC744 \uD558\uC5EC \uC791\uC5C5 \uB0B4\uC6A9\uC744 \uC548\uC804\uD558\uAC8C \uC800\uC7A5\uD558\uACE0, \uD544\uC694 \uC2DC \uC774\uC804 \uC0C1\uD0DC\uB85C \uB3CC\uC544\uAC08 \uC218 \uC788\uB3C4\uB85D \uD558\uC138\uC694.
|
|
1258
|
-
7. **\uD004\uB9AC\uD2F0 \uAC80\uC99D**: [.context/guides/quality-check.md] **\uC791\uC5C5 \uC644\uB8CC \uC804\uC5D0 \uBC18\uB4DC\uC2DC \uC218\uD589\uD558\uC138\uC694**. \uCF54\uB4DC \uB9B0\uD2B8, \uD3EC\uB9F7\uD130, \uD14C\uC2A4\uD2B8, \uBE4C\uB4DC, \uCF54\uB4DC\uB9AC\uBDF0\uB97C \uC2E4\uD589\uD558\uC5EC \uC791\uC5C5 \uACB0\uACFC\uBB3C\uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uD488\uC9C8 \uAE30\uC900\uC744 \uCDA9\uC871\uD558\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694.
|
|
1259
|
-
8. **\uC791\uC5C5 \uC644\uB8CC**: [.context/guides/complete-guide.md] \uBAA8\uB4E0 \uC791\uC5C5\uC774 \uC644\uB8CC\uB418\uC5C8\uB2E4\uBA74, \uC774 \uAC00\uC774\uB4DC\uB97C \uB530\uB974\uC138\uC694. \uC774 \uC791\uC5C5 \uC9C0\uCE68\uC774 \uB354\uC774\uC0C1 \uD2B8\uB9AC\uAC70\uB418\uC9C0 \uC54A\uC744 \uAC83\uC785\uB2C8\uB2E4.
|
|
1260
|
-
`;
|
|
1261
107
|
var DEFAULT_ADR_TEMPLATE = `# ADR-NNN: [\uC81C\uBAA9]
|
|
1262
108
|
|
|
1263
109
|
## \uC0C1\uD0DC
|
|
@@ -1549,25 +395,21 @@ var TEMPLATE_FILES = {
|
|
|
1549
395
|
"work-complete.txt": DEFAULT_WORK_COMPLETE_TEMPLATE
|
|
1550
396
|
};
|
|
1551
397
|
function scaffoldIfNeeded(projectDir) {
|
|
1552
|
-
const contextDir =
|
|
1553
|
-
if (
|
|
398
|
+
const contextDir = join2(projectDir, resolveContextDir(projectDir));
|
|
399
|
+
if (existsSync2(contextDir)) {
|
|
1554
400
|
return false;
|
|
1555
401
|
}
|
|
1556
402
|
try {
|
|
1557
|
-
const
|
|
1558
|
-
mkdirSync(promptsDir, { recursive: true });
|
|
1559
|
-
const templatesDir = join4(contextDir, "templates");
|
|
403
|
+
const templatesDir = join2(contextDir, "templates");
|
|
1560
404
|
mkdirSync(templatesDir, { recursive: true });
|
|
1561
|
-
const guidesDir =
|
|
405
|
+
const guidesDir = join2(contextDir, "guides");
|
|
1562
406
|
mkdirSync(guidesDir, { recursive: true });
|
|
1563
|
-
writeFileSync(
|
|
1564
|
-
writeFileSync(join4(promptsDir, DEFAULTS.turnStartFile), DEFAULT_TURN_START, "utf-8");
|
|
1565
|
-
writeFileSync(join4(promptsDir, DEFAULTS.turnEndFile), DEFAULT_TURN_END, "utf-8");
|
|
407
|
+
writeFileSync(join2(contextDir, "config.jsonc"), DEFAULT_CONFIG, "utf-8");
|
|
1566
408
|
for (const [filename, content] of Object.entries(TEMPLATE_FILES)) {
|
|
1567
|
-
writeFileSync(
|
|
409
|
+
writeFileSync(join2(templatesDir, filename), content, "utf-8");
|
|
1568
410
|
}
|
|
1569
411
|
for (const [filename, content] of Object.entries(GUIDE_FILES)) {
|
|
1570
|
-
writeFileSync(
|
|
412
|
+
writeFileSync(join2(guidesDir, filename), content, "utf-8");
|
|
1571
413
|
}
|
|
1572
414
|
writeVersion(contextDir, PLUGIN_VERSION);
|
|
1573
415
|
return true;
|
|
@@ -1577,35 +419,32 @@ function scaffoldIfNeeded(projectDir) {
|
|
|
1577
419
|
}
|
|
1578
420
|
function getStoredVersion(projectDir) {
|
|
1579
421
|
try {
|
|
1580
|
-
return
|
|
422
|
+
return readFileSync(join2(projectDir, resolveContextDir(projectDir), ".version"), "utf-8").trim();
|
|
1581
423
|
} catch {
|
|
1582
424
|
return null;
|
|
1583
425
|
}
|
|
1584
426
|
}
|
|
1585
427
|
function writeVersion(contextDir, version) {
|
|
1586
|
-
writeFileSync(
|
|
428
|
+
writeFileSync(join2(contextDir, ".version"), version, "utf-8");
|
|
1587
429
|
}
|
|
1588
430
|
function autoUpdateTemplates(projectDir) {
|
|
1589
|
-
const contextDir =
|
|
1590
|
-
if (!
|
|
431
|
+
const contextDir = join2(projectDir, resolveContextDir(projectDir));
|
|
432
|
+
if (!existsSync2(contextDir))
|
|
1591
433
|
return [];
|
|
1592
434
|
const stored = getStoredVersion(projectDir);
|
|
1593
435
|
if (stored === PLUGIN_VERSION)
|
|
1594
436
|
return [];
|
|
1595
|
-
mkdirSync(
|
|
1596
|
-
mkdirSync(
|
|
1597
|
-
mkdirSync(join4(contextDir, "guides"), { recursive: true });
|
|
437
|
+
mkdirSync(join2(contextDir, "templates"), { recursive: true });
|
|
438
|
+
mkdirSync(join2(contextDir, "guides"), { recursive: true });
|
|
1598
439
|
const filesToUpdate = {
|
|
1599
|
-
[`prompts/${DEFAULTS.turnStartFile}`]: DEFAULT_TURN_START,
|
|
1600
|
-
[`prompts/${DEFAULTS.turnEndFile}`]: DEFAULT_TURN_END,
|
|
1601
440
|
...Object.fromEntries(Object.entries(TEMPLATE_FILES).map(([f, c]) => [`templates/${f}`, c])),
|
|
1602
441
|
...Object.fromEntries(Object.entries(GUIDE_FILES).map(([f, c]) => [`guides/${f}`, c]))
|
|
1603
442
|
};
|
|
1604
443
|
const updated = [];
|
|
1605
444
|
for (const [path, content] of Object.entries(filesToUpdate)) {
|
|
1606
|
-
const filePath =
|
|
445
|
+
const filePath = join2(contextDir, path);
|
|
1607
446
|
try {
|
|
1608
|
-
const existing =
|
|
447
|
+
const existing = readFileSync(filePath, "utf-8");
|
|
1609
448
|
if (existing === content)
|
|
1610
449
|
continue;
|
|
1611
450
|
} catch {}
|
|
@@ -1616,15 +455,29 @@ function autoUpdateTemplates(projectDir) {
|
|
|
1616
455
|
return updated;
|
|
1617
456
|
}
|
|
1618
457
|
|
|
458
|
+
// src/constants.ts
|
|
459
|
+
var DEFAULTS = {
|
|
460
|
+
configPath: ".context/config.jsonc",
|
|
461
|
+
knowledgeSources: ["AGENTS.md"],
|
|
462
|
+
templateDir: ".context/templates",
|
|
463
|
+
indexFilename: "INDEX.md",
|
|
464
|
+
maxDomainDepth: 2,
|
|
465
|
+
knowledgeDir: "docs",
|
|
466
|
+
guidesDir: ".context/guides",
|
|
467
|
+
workCompleteFile: ".context/.work-complete"
|
|
468
|
+
};
|
|
469
|
+
var LIMITS = {
|
|
470
|
+
maxPromptFileSize: 64 * 1024,
|
|
471
|
+
maxIndexEntries: 100,
|
|
472
|
+
maxTotalInjectionSize: 128 * 1024,
|
|
473
|
+
maxScanDepth: 3,
|
|
474
|
+
maxSummaryLength: 100,
|
|
475
|
+
maxIndexFileSize: 32 * 1024
|
|
476
|
+
};
|
|
477
|
+
|
|
1619
478
|
// src/index.ts
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
return promptPath;
|
|
1623
|
-
if (promptPath.startsWith(".context/") || promptPath.startsWith(".opencode/")) {
|
|
1624
|
-
return join5(directory, promptPath);
|
|
1625
|
-
}
|
|
1626
|
-
return join5(directory, contextDir, promptPath);
|
|
1627
|
-
}
|
|
479
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
480
|
+
var __dirname2 = dirname(__filename2);
|
|
1628
481
|
var plugin = async ({ directory, client }) => {
|
|
1629
482
|
const scaffolded = scaffoldIfNeeded(directory);
|
|
1630
483
|
const contextDir = resolveContextDir(directory);
|
|
@@ -1648,19 +501,17 @@ var plugin = async ({ directory, client }) => {
|
|
|
1648
501
|
});
|
|
1649
502
|
}
|
|
1650
503
|
}
|
|
1651
|
-
const config = loadConfig(directory);
|
|
1652
504
|
return {
|
|
505
|
+
config: async (config) => {
|
|
506
|
+
config.mcp = config.mcp || {};
|
|
507
|
+
config.mcp["context-mcp"] = {
|
|
508
|
+
type: "local",
|
|
509
|
+
command: ["bun", join3(__dirname2, "mcp.js")]
|
|
510
|
+
};
|
|
511
|
+
},
|
|
1653
512
|
"experimental.chat.messages.transform": async (_input, output) => {
|
|
1654
513
|
if (process.env.OMX_HOOK_PLUGINS)
|
|
1655
514
|
return;
|
|
1656
|
-
let skipTurnStart = false;
|
|
1657
|
-
const agentsMdPath = join5(directory, "AGENTS.md");
|
|
1658
|
-
if (existsSync4(agentsMdPath)) {
|
|
1659
|
-
const content = readFileSync5(agentsMdPath, "utf-8");
|
|
1660
|
-
if (content.includes("<!-- context:start -->") && content.includes("<!-- context:end -->")) {
|
|
1661
|
-
skipTurnStart = true;
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
515
|
if (output.messages.length === 0)
|
|
1665
516
|
return;
|
|
1666
517
|
const lastUserMsg = output.messages.filter((m) => m.info.role === "user").at(-1);
|
|
@@ -1670,36 +521,13 @@ var plugin = async ({ directory, client }) => {
|
|
|
1670
521
|
if (isTurnEndMessage) {
|
|
1671
522
|
return;
|
|
1672
523
|
}
|
|
1673
|
-
const
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
};
|
|
1677
|
-
if (!skipTurnStart) {
|
|
1678
|
-
const turnStartPath = resolvePromptPath(directory, contextDir, config.prompts.turnStart ?? join5(DEFAULTS.promptDir, DEFAULTS.turnStartFile));
|
|
1679
|
-
const turnStartRaw = readPromptFile(turnStartPath) ?? "";
|
|
1680
|
-
const turnStart = resolvePromptVariables(turnStartRaw, promptVars);
|
|
1681
|
-
const knowledgeIndex = buildKnowledgeIndexV2(directory, config.knowledge);
|
|
1682
|
-
const indexContent = knowledgeIndex.mode === "flat" ? formatKnowledgeIndex(knowledgeIndex.individualFiles) : formatDomainIndex(knowledgeIndex);
|
|
1683
|
-
const combinedContent = [turnStart, indexContent].filter(Boolean).join(`
|
|
1684
|
-
|
|
1685
|
-
`);
|
|
1686
|
-
if (combinedContent) {
|
|
1687
|
-
lastUserMsg.parts.push({
|
|
1688
|
-
id: `context-turn-start-${Date.now()}`,
|
|
1689
|
-
sessionID: lastUserMsg.info.sessionID,
|
|
1690
|
-
messageID: lastUserMsg.info.id,
|
|
1691
|
-
type: "text",
|
|
1692
|
-
text: combinedContent
|
|
1693
|
-
});
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
const signalPath = join5(directory, DEFAULTS.workCompleteFile);
|
|
1697
|
-
if (existsSync4(signalPath)) {
|
|
1698
|
-
const content = readFileSync5(signalPath, "utf-8");
|
|
524
|
+
const signalPath = join3(directory, DEFAULTS.workCompleteFile);
|
|
525
|
+
if (existsSync3(signalPath)) {
|
|
526
|
+
const content = readFileSync2(signalPath, "utf-8");
|
|
1699
527
|
const match = content.match(/^session_id=(.*)$/m);
|
|
1700
528
|
const fileSessionId = match ? match[1].trim() : undefined;
|
|
1701
529
|
if (fileSessionId && fileSessionId !== lastUserMsg.info.sessionID) {} else {
|
|
1702
|
-
const { mtimeMs } =
|
|
530
|
+
const { mtimeMs } = statSync(signalPath);
|
|
1703
531
|
const userCreatedAt = lastUserMsg.info.time.created;
|
|
1704
532
|
if (mtimeMs >= userCreatedAt) {
|
|
1705
533
|
return;
|
|
@@ -1707,11 +535,6 @@ var plugin = async ({ directory, client }) => {
|
|
|
1707
535
|
unlinkSync(signalPath);
|
|
1708
536
|
}
|
|
1709
537
|
}
|
|
1710
|
-
const turnEndPath = resolvePromptPath(directory, contextDir, config.prompts.turnEnd ?? join5(DEFAULTS.promptDir, DEFAULTS.turnEndFile));
|
|
1711
|
-
const turnEndRaw = readPromptFile(turnEndPath);
|
|
1712
|
-
if (!turnEndRaw)
|
|
1713
|
-
return;
|
|
1714
|
-
const turnEnd = resolvePromptVariables(turnEndRaw, promptVars);
|
|
1715
538
|
const msgId = `context-turn-end-${Date.now()}`;
|
|
1716
539
|
output.messages.push({
|
|
1717
540
|
info: {
|
|
@@ -1728,9 +551,7 @@ var plugin = async ({ directory, client }) => {
|
|
|
1728
551
|
sessionID: lastUserMsg.info.sessionID,
|
|
1729
552
|
messageID: msgId,
|
|
1730
553
|
type: "text",
|
|
1731
|
-
text: `<system-reminder>
|
|
1732
|
-
${turnEnd}
|
|
1733
|
-
</system-reminder>`
|
|
554
|
+
text: `<system-reminder> TURN END. You MUST call the 'submit_turn_complete' MCP tool to finalize your work and record notes. Do not wait for user input. </system-reminder>`
|
|
1734
555
|
}
|
|
1735
556
|
]
|
|
1736
557
|
});
|