deepseek-web-retrieval 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +187 -1
- package/README.md +13 -9
- package/dist/cli.js +4228 -178
- package/docs/adr/0001-refuse-drift-between-plan-and-apply.md +29 -0
- package/docs/agents/codex.md +193 -0
- package/docs/agents/domain.md +51 -0
- package/docs/agents/issue-tracker.md +45 -0
- package/docs/{opencode-v2.md → agents/opencode-v2.md} +30 -7
- package/docs/{pi.md → agents/pi.md} +35 -7
- package/docs/agents/triage-labels.md +15 -0
- package/docs/design/installer-design.md +184 -0
- package/docs/hosts.jsonc +59 -33
- package/docs/integration.md +45 -52
- package/docs/research/control-matrix.md +257 -0
- package/docs/{mcp-compatibility.md → research/mcp-compatibility.md} +39 -108
- package/package.json +5 -3
- package/src/core/auth.ts +1 -1
- package/src/core/client.ts +42 -249
- package/src/core/constants.ts +5 -0
- package/src/core/descriptions.ts +19 -0
- package/src/core/format.ts +31 -1
- package/src/core/jsonc.ts +16 -0
- package/src/core/options.ts +2 -3
- package/src/core/search.ts +5 -7
- package/src/core/transport.ts +253 -0
- package/src/core/types.ts +13 -11
- package/src/installer/apply.ts +176 -0
- package/src/installer/cli.ts +215 -0
- package/src/installer/detect.ts +85 -0
- package/src/installer/formats/index.ts +58 -0
- package/src/installer/formats/json.ts +151 -0
- package/src/installer/formats/rules.ts +62 -0
- package/src/installer/formats/toml.ts +163 -0
- package/src/installer/formats/value.ts +57 -0
- package/src/installer/hosts/codex.ts +128 -0
- package/src/installer/hosts/index.ts +134 -0
- package/src/installer/hosts/opencode.ts +118 -0
- package/src/installer/hosts/pi.ts +115 -0
- package/src/installer/hosts/shared.ts +31 -0
- package/src/installer/paths.ts +18 -0
- package/src/installer/render.ts +62 -0
- package/src/installer/revert.ts +61 -0
- package/src/installer/rulesContent.ts +32 -0
- package/src/installer/state.ts +63 -0
- package/src/installer/types.ts +126 -0
- package/src/installer/uninstall.ts +33 -0
- package/src/mcp/auth.ts +2 -1
- package/src/mcp/cli.ts +21 -5
- package/src/mcp/config.ts +70 -27
- package/src/mcp/server.ts +81 -65
- package/src/opencode/auth.ts +3 -2
- package/src/opencode/plugin.ts +93 -56
- package/src/mcp/format.ts +0 -31
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,3998 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
|
+
|
|
18
|
+
// src/core/constants.ts
|
|
19
|
+
var SEARCH_ENDPOINT = "https://api.deepseek.com/v1/tools/search", FETCH_ENDPOINT = "https://api.deepseek.com/v1/tools/fetch", DEFAULT_SEARCH_COUNT = 10, DEFAULT_MAX_RESULTS = 5, DEFAULT_MIN_RERANK = 1.5, DEFAULT_MIN_AUTHORITY = 2, DEFAULT_MAX_SUMMARY_CHARS = 1200, DEFAULT_FETCH_MAX_CHARS = 16000, DEFAULT_TIMEOUT_MS = 30000, MIN_TIMEOUT_MS = 1000, MAX_TIMEOUT_MS = 120000, MAX_QUERY_CHARS = 128, MAX_URL_CHARS = 8192, MAX_ERROR_BODY_CHARS = 2000, MAX_RESPONSE_BYTES, FETCH_TRUNCATION_MARKER = `
|
|
20
|
+
|
|
21
|
+
[content truncated]`, DEFAULT_API_KEY_SOURCE = "auto", DEFAULT_MAX_RETRIES = 0, MAX_RETRIES = 5, DEFAULT_RETRY_BASE_DELAY_MS = 250, MAX_RETRY_DELAY_MS = 1e4, API_KEY_ENV = "DEEPSEEK_API_KEY", ENABLE_SEARCH_ENV = "DEEPSEEK_ENABLE_SEARCH", ENABLE_FETCH_ENV = "DEEPSEEK_ENABLE_FETCH";
|
|
22
|
+
var init_constants = __esm(() => {
|
|
23
|
+
MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
27
|
+
function createScanner(text, ignoreTrivia = false) {
|
|
28
|
+
const len = text.length;
|
|
29
|
+
let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
|
|
30
|
+
function scanHexDigits(count, exact) {
|
|
31
|
+
let digits = 0;
|
|
32
|
+
let value2 = 0;
|
|
33
|
+
while (digits < count || !exact) {
|
|
34
|
+
let ch = text.charCodeAt(pos);
|
|
35
|
+
if (ch >= 48 && ch <= 57) {
|
|
36
|
+
value2 = value2 * 16 + ch - 48;
|
|
37
|
+
} else if (ch >= 65 && ch <= 70) {
|
|
38
|
+
value2 = value2 * 16 + ch - 65 + 10;
|
|
39
|
+
} else if (ch >= 97 && ch <= 102) {
|
|
40
|
+
value2 = value2 * 16 + ch - 97 + 10;
|
|
41
|
+
} else {
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
pos++;
|
|
45
|
+
digits++;
|
|
46
|
+
}
|
|
47
|
+
if (digits < count) {
|
|
48
|
+
value2 = -1;
|
|
49
|
+
}
|
|
50
|
+
return value2;
|
|
51
|
+
}
|
|
52
|
+
function setPosition(newPosition) {
|
|
53
|
+
pos = newPosition;
|
|
54
|
+
value = "";
|
|
55
|
+
tokenOffset = 0;
|
|
56
|
+
token = 16;
|
|
57
|
+
scanError = 0;
|
|
58
|
+
}
|
|
59
|
+
function scanNumber() {
|
|
60
|
+
let start = pos;
|
|
61
|
+
if (text.charCodeAt(pos) === 48) {
|
|
62
|
+
pos++;
|
|
63
|
+
} else {
|
|
64
|
+
pos++;
|
|
65
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
66
|
+
pos++;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (pos < text.length && text.charCodeAt(pos) === 46) {
|
|
70
|
+
pos++;
|
|
71
|
+
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
72
|
+
pos++;
|
|
73
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
74
|
+
pos++;
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
scanError = 3;
|
|
78
|
+
return text.substring(start, pos);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
let end = pos;
|
|
82
|
+
if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
|
|
83
|
+
pos++;
|
|
84
|
+
if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
|
|
85
|
+
pos++;
|
|
86
|
+
}
|
|
87
|
+
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
88
|
+
pos++;
|
|
89
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
90
|
+
pos++;
|
|
91
|
+
}
|
|
92
|
+
end = pos;
|
|
93
|
+
} else {
|
|
94
|
+
scanError = 3;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return text.substring(start, end);
|
|
98
|
+
}
|
|
99
|
+
function scanString() {
|
|
100
|
+
let result = "", start = pos;
|
|
101
|
+
while (true) {
|
|
102
|
+
if (pos >= len) {
|
|
103
|
+
result += text.substring(start, pos);
|
|
104
|
+
scanError = 2;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
const ch = text.charCodeAt(pos);
|
|
108
|
+
if (ch === 34) {
|
|
109
|
+
result += text.substring(start, pos);
|
|
110
|
+
pos++;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
if (ch === 92) {
|
|
114
|
+
result += text.substring(start, pos);
|
|
115
|
+
pos++;
|
|
116
|
+
if (pos >= len) {
|
|
117
|
+
scanError = 2;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
const ch2 = text.charCodeAt(pos++);
|
|
121
|
+
switch (ch2) {
|
|
122
|
+
case 34:
|
|
123
|
+
result += '"';
|
|
124
|
+
break;
|
|
125
|
+
case 92:
|
|
126
|
+
result += "\\";
|
|
127
|
+
break;
|
|
128
|
+
case 47:
|
|
129
|
+
result += "/";
|
|
130
|
+
break;
|
|
131
|
+
case 98:
|
|
132
|
+
result += "\b";
|
|
133
|
+
break;
|
|
134
|
+
case 102:
|
|
135
|
+
result += "\f";
|
|
136
|
+
break;
|
|
137
|
+
case 110:
|
|
138
|
+
result += `
|
|
139
|
+
`;
|
|
140
|
+
break;
|
|
141
|
+
case 114:
|
|
142
|
+
result += "\r";
|
|
143
|
+
break;
|
|
144
|
+
case 116:
|
|
145
|
+
result += "\t";
|
|
146
|
+
break;
|
|
147
|
+
case 117:
|
|
148
|
+
const ch3 = scanHexDigits(4, true);
|
|
149
|
+
if (ch3 >= 0) {
|
|
150
|
+
result += String.fromCharCode(ch3);
|
|
151
|
+
} else {
|
|
152
|
+
scanError = 4;
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
155
|
+
default:
|
|
156
|
+
scanError = 5;
|
|
157
|
+
}
|
|
158
|
+
start = pos;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (ch >= 0 && ch <= 31) {
|
|
162
|
+
if (isLineBreak(ch)) {
|
|
163
|
+
result += text.substring(start, pos);
|
|
164
|
+
scanError = 2;
|
|
165
|
+
break;
|
|
166
|
+
} else {
|
|
167
|
+
scanError = 6;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
pos++;
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
function scanNext() {
|
|
175
|
+
value = "";
|
|
176
|
+
scanError = 0;
|
|
177
|
+
tokenOffset = pos;
|
|
178
|
+
lineStartOffset = lineNumber;
|
|
179
|
+
prevTokenLineStartOffset = tokenLineStartOffset;
|
|
180
|
+
if (pos >= len) {
|
|
181
|
+
tokenOffset = len;
|
|
182
|
+
return token = 17;
|
|
183
|
+
}
|
|
184
|
+
let code = text.charCodeAt(pos);
|
|
185
|
+
if (isWhiteSpace(code)) {
|
|
186
|
+
do {
|
|
187
|
+
pos++;
|
|
188
|
+
value += String.fromCharCode(code);
|
|
189
|
+
code = text.charCodeAt(pos);
|
|
190
|
+
} while (isWhiteSpace(code));
|
|
191
|
+
return token = 15;
|
|
192
|
+
}
|
|
193
|
+
if (isLineBreak(code)) {
|
|
194
|
+
pos++;
|
|
195
|
+
value += String.fromCharCode(code);
|
|
196
|
+
if (code === 13 && text.charCodeAt(pos) === 10) {
|
|
197
|
+
pos++;
|
|
198
|
+
value += `
|
|
199
|
+
`;
|
|
200
|
+
}
|
|
201
|
+
lineNumber++;
|
|
202
|
+
tokenLineStartOffset = pos;
|
|
203
|
+
return token = 14;
|
|
204
|
+
}
|
|
205
|
+
switch (code) {
|
|
206
|
+
case 123:
|
|
207
|
+
pos++;
|
|
208
|
+
return token = 1;
|
|
209
|
+
case 125:
|
|
210
|
+
pos++;
|
|
211
|
+
return token = 2;
|
|
212
|
+
case 91:
|
|
213
|
+
pos++;
|
|
214
|
+
return token = 3;
|
|
215
|
+
case 93:
|
|
216
|
+
pos++;
|
|
217
|
+
return token = 4;
|
|
218
|
+
case 58:
|
|
219
|
+
pos++;
|
|
220
|
+
return token = 6;
|
|
221
|
+
case 44:
|
|
222
|
+
pos++;
|
|
223
|
+
return token = 5;
|
|
224
|
+
case 34:
|
|
225
|
+
pos++;
|
|
226
|
+
value = scanString();
|
|
227
|
+
return token = 10;
|
|
228
|
+
case 47:
|
|
229
|
+
const start = pos - 1;
|
|
230
|
+
if (text.charCodeAt(pos + 1) === 47) {
|
|
231
|
+
pos += 2;
|
|
232
|
+
while (pos < len) {
|
|
233
|
+
if (isLineBreak(text.charCodeAt(pos))) {
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
pos++;
|
|
237
|
+
}
|
|
238
|
+
value = text.substring(start, pos);
|
|
239
|
+
return token = 12;
|
|
240
|
+
}
|
|
241
|
+
if (text.charCodeAt(pos + 1) === 42) {
|
|
242
|
+
pos += 2;
|
|
243
|
+
const safeLength = len - 1;
|
|
244
|
+
let commentClosed = false;
|
|
245
|
+
while (pos < safeLength) {
|
|
246
|
+
const ch = text.charCodeAt(pos);
|
|
247
|
+
if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
|
|
248
|
+
pos += 2;
|
|
249
|
+
commentClosed = true;
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
pos++;
|
|
253
|
+
if (isLineBreak(ch)) {
|
|
254
|
+
if (ch === 13 && text.charCodeAt(pos) === 10) {
|
|
255
|
+
pos++;
|
|
256
|
+
}
|
|
257
|
+
lineNumber++;
|
|
258
|
+
tokenLineStartOffset = pos;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (!commentClosed) {
|
|
262
|
+
pos++;
|
|
263
|
+
scanError = 1;
|
|
264
|
+
}
|
|
265
|
+
value = text.substring(start, pos);
|
|
266
|
+
return token = 13;
|
|
267
|
+
}
|
|
268
|
+
value += String.fromCharCode(code);
|
|
269
|
+
pos++;
|
|
270
|
+
return token = 16;
|
|
271
|
+
case 45:
|
|
272
|
+
value += String.fromCharCode(code);
|
|
273
|
+
pos++;
|
|
274
|
+
if (pos === len || !isDigit(text.charCodeAt(pos))) {
|
|
275
|
+
return token = 16;
|
|
276
|
+
}
|
|
277
|
+
case 48:
|
|
278
|
+
case 49:
|
|
279
|
+
case 50:
|
|
280
|
+
case 51:
|
|
281
|
+
case 52:
|
|
282
|
+
case 53:
|
|
283
|
+
case 54:
|
|
284
|
+
case 55:
|
|
285
|
+
case 56:
|
|
286
|
+
case 57:
|
|
287
|
+
value += scanNumber();
|
|
288
|
+
return token = 11;
|
|
289
|
+
default:
|
|
290
|
+
while (pos < len && isUnknownContentCharacter(code)) {
|
|
291
|
+
pos++;
|
|
292
|
+
code = text.charCodeAt(pos);
|
|
293
|
+
}
|
|
294
|
+
if (tokenOffset !== pos) {
|
|
295
|
+
value = text.substring(tokenOffset, pos);
|
|
296
|
+
switch (value) {
|
|
297
|
+
case "true":
|
|
298
|
+
return token = 8;
|
|
299
|
+
case "false":
|
|
300
|
+
return token = 9;
|
|
301
|
+
case "null":
|
|
302
|
+
return token = 7;
|
|
303
|
+
}
|
|
304
|
+
return token = 16;
|
|
305
|
+
}
|
|
306
|
+
value += String.fromCharCode(code);
|
|
307
|
+
pos++;
|
|
308
|
+
return token = 16;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function isUnknownContentCharacter(code) {
|
|
312
|
+
if (isWhiteSpace(code) || isLineBreak(code)) {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
switch (code) {
|
|
316
|
+
case 125:
|
|
317
|
+
case 93:
|
|
318
|
+
case 123:
|
|
319
|
+
case 91:
|
|
320
|
+
case 34:
|
|
321
|
+
case 58:
|
|
322
|
+
case 44:
|
|
323
|
+
case 47:
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
function scanNextNonTrivia() {
|
|
329
|
+
let result;
|
|
330
|
+
do {
|
|
331
|
+
result = scanNext();
|
|
332
|
+
} while (result >= 12 && result <= 15);
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
setPosition,
|
|
337
|
+
getPosition: () => pos,
|
|
338
|
+
scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
|
|
339
|
+
getToken: () => token,
|
|
340
|
+
getTokenValue: () => value,
|
|
341
|
+
getTokenOffset: () => tokenOffset,
|
|
342
|
+
getTokenLength: () => pos - tokenOffset,
|
|
343
|
+
getTokenStartLine: () => lineStartOffset,
|
|
344
|
+
getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,
|
|
345
|
+
getTokenError: () => scanError
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function isWhiteSpace(ch) {
|
|
349
|
+
return ch === 32 || ch === 9;
|
|
350
|
+
}
|
|
351
|
+
function isLineBreak(ch) {
|
|
352
|
+
return ch === 10 || ch === 13;
|
|
353
|
+
}
|
|
354
|
+
function isDigit(ch) {
|
|
355
|
+
return ch >= 48 && ch <= 57;
|
|
356
|
+
}
|
|
357
|
+
var CharacterCodes;
|
|
358
|
+
var init_scanner = __esm(() => {
|
|
359
|
+
(function(CharacterCodes2) {
|
|
360
|
+
CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed";
|
|
361
|
+
CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn";
|
|
362
|
+
CharacterCodes2[CharacterCodes2["space"] = 32] = "space";
|
|
363
|
+
CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0";
|
|
364
|
+
CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1";
|
|
365
|
+
CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2";
|
|
366
|
+
CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3";
|
|
367
|
+
CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4";
|
|
368
|
+
CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5";
|
|
369
|
+
CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6";
|
|
370
|
+
CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7";
|
|
371
|
+
CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8";
|
|
372
|
+
CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9";
|
|
373
|
+
CharacterCodes2[CharacterCodes2["a"] = 97] = "a";
|
|
374
|
+
CharacterCodes2[CharacterCodes2["b"] = 98] = "b";
|
|
375
|
+
CharacterCodes2[CharacterCodes2["c"] = 99] = "c";
|
|
376
|
+
CharacterCodes2[CharacterCodes2["d"] = 100] = "d";
|
|
377
|
+
CharacterCodes2[CharacterCodes2["e"] = 101] = "e";
|
|
378
|
+
CharacterCodes2[CharacterCodes2["f"] = 102] = "f";
|
|
379
|
+
CharacterCodes2[CharacterCodes2["g"] = 103] = "g";
|
|
380
|
+
CharacterCodes2[CharacterCodes2["h"] = 104] = "h";
|
|
381
|
+
CharacterCodes2[CharacterCodes2["i"] = 105] = "i";
|
|
382
|
+
CharacterCodes2[CharacterCodes2["j"] = 106] = "j";
|
|
383
|
+
CharacterCodes2[CharacterCodes2["k"] = 107] = "k";
|
|
384
|
+
CharacterCodes2[CharacterCodes2["l"] = 108] = "l";
|
|
385
|
+
CharacterCodes2[CharacterCodes2["m"] = 109] = "m";
|
|
386
|
+
CharacterCodes2[CharacterCodes2["n"] = 110] = "n";
|
|
387
|
+
CharacterCodes2[CharacterCodes2["o"] = 111] = "o";
|
|
388
|
+
CharacterCodes2[CharacterCodes2["p"] = 112] = "p";
|
|
389
|
+
CharacterCodes2[CharacterCodes2["q"] = 113] = "q";
|
|
390
|
+
CharacterCodes2[CharacterCodes2["r"] = 114] = "r";
|
|
391
|
+
CharacterCodes2[CharacterCodes2["s"] = 115] = "s";
|
|
392
|
+
CharacterCodes2[CharacterCodes2["t"] = 116] = "t";
|
|
393
|
+
CharacterCodes2[CharacterCodes2["u"] = 117] = "u";
|
|
394
|
+
CharacterCodes2[CharacterCodes2["v"] = 118] = "v";
|
|
395
|
+
CharacterCodes2[CharacterCodes2["w"] = 119] = "w";
|
|
396
|
+
CharacterCodes2[CharacterCodes2["x"] = 120] = "x";
|
|
397
|
+
CharacterCodes2[CharacterCodes2["y"] = 121] = "y";
|
|
398
|
+
CharacterCodes2[CharacterCodes2["z"] = 122] = "z";
|
|
399
|
+
CharacterCodes2[CharacterCodes2["A"] = 65] = "A";
|
|
400
|
+
CharacterCodes2[CharacterCodes2["B"] = 66] = "B";
|
|
401
|
+
CharacterCodes2[CharacterCodes2["C"] = 67] = "C";
|
|
402
|
+
CharacterCodes2[CharacterCodes2["D"] = 68] = "D";
|
|
403
|
+
CharacterCodes2[CharacterCodes2["E"] = 69] = "E";
|
|
404
|
+
CharacterCodes2[CharacterCodes2["F"] = 70] = "F";
|
|
405
|
+
CharacterCodes2[CharacterCodes2["G"] = 71] = "G";
|
|
406
|
+
CharacterCodes2[CharacterCodes2["H"] = 72] = "H";
|
|
407
|
+
CharacterCodes2[CharacterCodes2["I"] = 73] = "I";
|
|
408
|
+
CharacterCodes2[CharacterCodes2["J"] = 74] = "J";
|
|
409
|
+
CharacterCodes2[CharacterCodes2["K"] = 75] = "K";
|
|
410
|
+
CharacterCodes2[CharacterCodes2["L"] = 76] = "L";
|
|
411
|
+
CharacterCodes2[CharacterCodes2["M"] = 77] = "M";
|
|
412
|
+
CharacterCodes2[CharacterCodes2["N"] = 78] = "N";
|
|
413
|
+
CharacterCodes2[CharacterCodes2["O"] = 79] = "O";
|
|
414
|
+
CharacterCodes2[CharacterCodes2["P"] = 80] = "P";
|
|
415
|
+
CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q";
|
|
416
|
+
CharacterCodes2[CharacterCodes2["R"] = 82] = "R";
|
|
417
|
+
CharacterCodes2[CharacterCodes2["S"] = 83] = "S";
|
|
418
|
+
CharacterCodes2[CharacterCodes2["T"] = 84] = "T";
|
|
419
|
+
CharacterCodes2[CharacterCodes2["U"] = 85] = "U";
|
|
420
|
+
CharacterCodes2[CharacterCodes2["V"] = 86] = "V";
|
|
421
|
+
CharacterCodes2[CharacterCodes2["W"] = 87] = "W";
|
|
422
|
+
CharacterCodes2[CharacterCodes2["X"] = 88] = "X";
|
|
423
|
+
CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y";
|
|
424
|
+
CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z";
|
|
425
|
+
CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk";
|
|
426
|
+
CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash";
|
|
427
|
+
CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace";
|
|
428
|
+
CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket";
|
|
429
|
+
CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon";
|
|
430
|
+
CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma";
|
|
431
|
+
CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot";
|
|
432
|
+
CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote";
|
|
433
|
+
CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus";
|
|
434
|
+
CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace";
|
|
435
|
+
CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket";
|
|
436
|
+
CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus";
|
|
437
|
+
CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash";
|
|
438
|
+
CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed";
|
|
439
|
+
CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab";
|
|
440
|
+
})(CharacterCodes || (CharacterCodes = {}));
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// node_modules/jsonc-parser/lib/esm/impl/string-intern.js
|
|
444
|
+
var cachedSpaces, maxCachedValues = 200, cachedBreakLinesWithSpaces, supportedEols;
|
|
445
|
+
var init_string_intern = __esm(() => {
|
|
446
|
+
cachedSpaces = new Array(20).fill(0).map((_, index) => {
|
|
447
|
+
return " ".repeat(index);
|
|
448
|
+
});
|
|
449
|
+
cachedBreakLinesWithSpaces = {
|
|
450
|
+
" ": {
|
|
451
|
+
"\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
452
|
+
return `
|
|
453
|
+
` + " ".repeat(index);
|
|
454
|
+
}),
|
|
455
|
+
"\r": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
456
|
+
return "\r" + " ".repeat(index);
|
|
457
|
+
}),
|
|
458
|
+
"\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
459
|
+
return `\r
|
|
460
|
+
` + " ".repeat(index);
|
|
461
|
+
})
|
|
462
|
+
},
|
|
463
|
+
"\t": {
|
|
464
|
+
"\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
465
|
+
return `
|
|
466
|
+
` + "\t".repeat(index);
|
|
467
|
+
}),
|
|
468
|
+
"\r": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
469
|
+
return "\r" + "\t".repeat(index);
|
|
470
|
+
}),
|
|
471
|
+
"\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
472
|
+
return `\r
|
|
473
|
+
` + "\t".repeat(index);
|
|
474
|
+
})
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
supportedEols = [`
|
|
478
|
+
`, "\r", `\r
|
|
479
|
+
`];
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
// node_modules/jsonc-parser/lib/esm/impl/format.js
|
|
483
|
+
function format(documentText, range, options) {
|
|
484
|
+
let initialIndentLevel;
|
|
485
|
+
let formatText;
|
|
486
|
+
let formatTextStart;
|
|
487
|
+
let rangeStart;
|
|
488
|
+
let rangeEnd;
|
|
489
|
+
if (range) {
|
|
490
|
+
rangeStart = range.offset;
|
|
491
|
+
rangeEnd = rangeStart + range.length;
|
|
492
|
+
formatTextStart = rangeStart;
|
|
493
|
+
while (formatTextStart > 0 && !isEOL(documentText, formatTextStart - 1)) {
|
|
494
|
+
formatTextStart--;
|
|
495
|
+
}
|
|
496
|
+
let endOffset = rangeEnd;
|
|
497
|
+
while (endOffset < documentText.length && !isEOL(documentText, endOffset)) {
|
|
498
|
+
endOffset++;
|
|
499
|
+
}
|
|
500
|
+
formatText = documentText.substring(formatTextStart, endOffset);
|
|
501
|
+
initialIndentLevel = computeIndentLevel(formatText, options);
|
|
502
|
+
} else {
|
|
503
|
+
formatText = documentText;
|
|
504
|
+
initialIndentLevel = 0;
|
|
505
|
+
formatTextStart = 0;
|
|
506
|
+
rangeStart = 0;
|
|
507
|
+
rangeEnd = documentText.length;
|
|
508
|
+
}
|
|
509
|
+
const eol = getEOL(options, documentText);
|
|
510
|
+
const eolFastPathSupported = supportedEols.includes(eol);
|
|
511
|
+
let numberLineBreaks = 0;
|
|
512
|
+
let indentLevel = 0;
|
|
513
|
+
let indentValue;
|
|
514
|
+
if (options.insertSpaces) {
|
|
515
|
+
indentValue = cachedSpaces[options.tabSize || 4] ?? repeat(cachedSpaces[1], options.tabSize || 4);
|
|
516
|
+
} else {
|
|
517
|
+
indentValue = "\t";
|
|
518
|
+
}
|
|
519
|
+
const indentType = indentValue === "\t" ? "\t" : " ";
|
|
520
|
+
let scanner = createScanner(formatText, false);
|
|
521
|
+
let hasError = false;
|
|
522
|
+
function newLinesAndIndent() {
|
|
523
|
+
if (numberLineBreaks > 1) {
|
|
524
|
+
return repeat(eol, numberLineBreaks) + repeat(indentValue, initialIndentLevel + indentLevel);
|
|
525
|
+
}
|
|
526
|
+
const amountOfSpaces = indentValue.length * (initialIndentLevel + indentLevel);
|
|
527
|
+
if (!eolFastPathSupported || amountOfSpaces > cachedBreakLinesWithSpaces[indentType][eol].length) {
|
|
528
|
+
return eol + repeat(indentValue, initialIndentLevel + indentLevel);
|
|
529
|
+
}
|
|
530
|
+
if (amountOfSpaces <= 0) {
|
|
531
|
+
return eol;
|
|
532
|
+
}
|
|
533
|
+
return cachedBreakLinesWithSpaces[indentType][eol][amountOfSpaces];
|
|
534
|
+
}
|
|
535
|
+
function scanNext() {
|
|
536
|
+
let token = scanner.scan();
|
|
537
|
+
numberLineBreaks = 0;
|
|
538
|
+
while (token === 15 || token === 14) {
|
|
539
|
+
if (token === 14 && options.keepLines) {
|
|
540
|
+
numberLineBreaks += 1;
|
|
541
|
+
} else if (token === 14) {
|
|
542
|
+
numberLineBreaks = 1;
|
|
543
|
+
}
|
|
544
|
+
token = scanner.scan();
|
|
545
|
+
}
|
|
546
|
+
hasError = token === 16 || scanner.getTokenError() !== 0;
|
|
547
|
+
return token;
|
|
548
|
+
}
|
|
549
|
+
const editOperations = [];
|
|
550
|
+
function addEdit(text, startOffset, endOffset) {
|
|
551
|
+
if (!hasError && (!range || startOffset < rangeEnd && endOffset > rangeStart) && documentText.substring(startOffset, endOffset) !== text) {
|
|
552
|
+
editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text });
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
let firstToken = scanNext();
|
|
556
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
557
|
+
addEdit(repeat(eol, numberLineBreaks), 0, 0);
|
|
558
|
+
}
|
|
559
|
+
if (firstToken !== 17) {
|
|
560
|
+
let firstTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
561
|
+
let initialIndent = indentValue.length * initialIndentLevel < 20 && options.insertSpaces ? cachedSpaces[indentValue.length * initialIndentLevel] : repeat(indentValue, initialIndentLevel);
|
|
562
|
+
addEdit(initialIndent, formatTextStart, firstTokenStart);
|
|
563
|
+
}
|
|
564
|
+
while (firstToken !== 17) {
|
|
565
|
+
let firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
|
|
566
|
+
let secondToken = scanNext();
|
|
567
|
+
let replaceContent = "";
|
|
568
|
+
let needsLineBreak = false;
|
|
569
|
+
while (numberLineBreaks === 0 && (secondToken === 12 || secondToken === 13)) {
|
|
570
|
+
let commentTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
571
|
+
addEdit(cachedSpaces[1], firstTokenEnd, commentTokenStart);
|
|
572
|
+
firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
|
|
573
|
+
needsLineBreak = secondToken === 12;
|
|
574
|
+
replaceContent = needsLineBreak ? newLinesAndIndent() : "";
|
|
575
|
+
secondToken = scanNext();
|
|
576
|
+
}
|
|
577
|
+
if (secondToken === 2) {
|
|
578
|
+
if (firstToken !== 1) {
|
|
579
|
+
indentLevel--;
|
|
580
|
+
}
|
|
581
|
+
if (options.keepLines && numberLineBreaks > 0 || !options.keepLines && firstToken !== 1) {
|
|
582
|
+
replaceContent = newLinesAndIndent();
|
|
583
|
+
} else if (options.keepLines) {
|
|
584
|
+
replaceContent = cachedSpaces[1];
|
|
585
|
+
}
|
|
586
|
+
} else if (secondToken === 4) {
|
|
587
|
+
if (firstToken !== 3) {
|
|
588
|
+
indentLevel--;
|
|
589
|
+
}
|
|
590
|
+
if (options.keepLines && numberLineBreaks > 0 || !options.keepLines && firstToken !== 3) {
|
|
591
|
+
replaceContent = newLinesAndIndent();
|
|
592
|
+
} else if (options.keepLines) {
|
|
593
|
+
replaceContent = cachedSpaces[1];
|
|
594
|
+
}
|
|
595
|
+
} else {
|
|
596
|
+
switch (firstToken) {
|
|
597
|
+
case 3:
|
|
598
|
+
case 1:
|
|
599
|
+
indentLevel++;
|
|
600
|
+
if (options.keepLines && numberLineBreaks > 0 || !options.keepLines) {
|
|
601
|
+
replaceContent = newLinesAndIndent();
|
|
602
|
+
} else {
|
|
603
|
+
replaceContent = cachedSpaces[1];
|
|
604
|
+
}
|
|
605
|
+
break;
|
|
606
|
+
case 5:
|
|
607
|
+
if (options.keepLines && numberLineBreaks > 0 || !options.keepLines) {
|
|
608
|
+
replaceContent = newLinesAndIndent();
|
|
609
|
+
} else {
|
|
610
|
+
replaceContent = cachedSpaces[1];
|
|
611
|
+
}
|
|
612
|
+
break;
|
|
613
|
+
case 12:
|
|
614
|
+
replaceContent = newLinesAndIndent();
|
|
615
|
+
break;
|
|
616
|
+
case 13:
|
|
617
|
+
if (numberLineBreaks > 0) {
|
|
618
|
+
replaceContent = newLinesAndIndent();
|
|
619
|
+
} else if (!needsLineBreak) {
|
|
620
|
+
replaceContent = cachedSpaces[1];
|
|
621
|
+
}
|
|
622
|
+
break;
|
|
623
|
+
case 6:
|
|
624
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
625
|
+
replaceContent = newLinesAndIndent();
|
|
626
|
+
} else if (!needsLineBreak) {
|
|
627
|
+
replaceContent = cachedSpaces[1];
|
|
628
|
+
}
|
|
629
|
+
break;
|
|
630
|
+
case 10:
|
|
631
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
632
|
+
replaceContent = newLinesAndIndent();
|
|
633
|
+
} else if (secondToken === 6 && !needsLineBreak) {
|
|
634
|
+
replaceContent = "";
|
|
635
|
+
}
|
|
636
|
+
break;
|
|
637
|
+
case 7:
|
|
638
|
+
case 8:
|
|
639
|
+
case 9:
|
|
640
|
+
case 11:
|
|
641
|
+
case 2:
|
|
642
|
+
case 4:
|
|
643
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
644
|
+
replaceContent = newLinesAndIndent();
|
|
645
|
+
} else {
|
|
646
|
+
if ((secondToken === 12 || secondToken === 13) && !needsLineBreak) {
|
|
647
|
+
replaceContent = cachedSpaces[1];
|
|
648
|
+
} else if (secondToken !== 5 && secondToken !== 17) {
|
|
649
|
+
hasError = true;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
break;
|
|
653
|
+
case 16:
|
|
654
|
+
hasError = true;
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
if (numberLineBreaks > 0 && (secondToken === 12 || secondToken === 13)) {
|
|
658
|
+
replaceContent = newLinesAndIndent();
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if (secondToken === 17) {
|
|
662
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
663
|
+
replaceContent = newLinesAndIndent();
|
|
664
|
+
} else {
|
|
665
|
+
replaceContent = options.insertFinalNewline ? eol : "";
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
const secondTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
669
|
+
addEdit(replaceContent, firstTokenEnd, secondTokenStart);
|
|
670
|
+
firstToken = secondToken;
|
|
671
|
+
}
|
|
672
|
+
return editOperations;
|
|
673
|
+
}
|
|
674
|
+
function repeat(s, count) {
|
|
675
|
+
let result = "";
|
|
676
|
+
for (let i = 0;i < count; i++) {
|
|
677
|
+
result += s;
|
|
678
|
+
}
|
|
679
|
+
return result;
|
|
680
|
+
}
|
|
681
|
+
function computeIndentLevel(content, options) {
|
|
682
|
+
let i = 0;
|
|
683
|
+
let nChars = 0;
|
|
684
|
+
const tabSize = options.tabSize || 4;
|
|
685
|
+
while (i < content.length) {
|
|
686
|
+
let ch = content.charAt(i);
|
|
687
|
+
if (ch === cachedSpaces[1]) {
|
|
688
|
+
nChars++;
|
|
689
|
+
} else if (ch === "\t") {
|
|
690
|
+
nChars += tabSize;
|
|
691
|
+
} else {
|
|
692
|
+
break;
|
|
693
|
+
}
|
|
694
|
+
i++;
|
|
695
|
+
}
|
|
696
|
+
return Math.floor(nChars / tabSize);
|
|
697
|
+
}
|
|
698
|
+
function getEOL(options, text) {
|
|
699
|
+
for (let i = 0;i < text.length; i++) {
|
|
700
|
+
const ch = text.charAt(i);
|
|
701
|
+
if (ch === "\r") {
|
|
702
|
+
if (i + 1 < text.length && text.charAt(i + 1) === `
|
|
703
|
+
`) {
|
|
704
|
+
return `\r
|
|
705
|
+
`;
|
|
706
|
+
}
|
|
707
|
+
return "\r";
|
|
708
|
+
} else if (ch === `
|
|
709
|
+
`) {
|
|
710
|
+
return `
|
|
711
|
+
`;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return options && options.eol || `
|
|
715
|
+
`;
|
|
716
|
+
}
|
|
717
|
+
function isEOL(text, offset) {
|
|
718
|
+
return `\r
|
|
719
|
+
`.indexOf(text.charAt(offset)) !== -1;
|
|
720
|
+
}
|
|
721
|
+
var init_format = __esm(() => {
|
|
722
|
+
init_scanner();
|
|
723
|
+
init_string_intern();
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
// node_modules/jsonc-parser/lib/esm/impl/parser.js
|
|
727
|
+
function parse(text, errors = [], options = ParseOptions.DEFAULT) {
|
|
728
|
+
let currentProperty = null;
|
|
729
|
+
let currentParent = [];
|
|
730
|
+
const previousParents = [];
|
|
731
|
+
function onValue(value) {
|
|
732
|
+
if (Array.isArray(currentParent)) {
|
|
733
|
+
currentParent.push(value);
|
|
734
|
+
} else if (currentProperty !== null) {
|
|
735
|
+
currentParent[currentProperty] = value;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
const visitor = {
|
|
739
|
+
onObjectBegin: () => {
|
|
740
|
+
const object2 = {};
|
|
741
|
+
onValue(object2);
|
|
742
|
+
previousParents.push(currentParent);
|
|
743
|
+
currentParent = object2;
|
|
744
|
+
currentProperty = null;
|
|
745
|
+
},
|
|
746
|
+
onObjectProperty: (name) => {
|
|
747
|
+
currentProperty = name;
|
|
748
|
+
},
|
|
749
|
+
onObjectEnd: () => {
|
|
750
|
+
currentParent = previousParents.pop();
|
|
751
|
+
},
|
|
752
|
+
onArrayBegin: () => {
|
|
753
|
+
const array2 = [];
|
|
754
|
+
onValue(array2);
|
|
755
|
+
previousParents.push(currentParent);
|
|
756
|
+
currentParent = array2;
|
|
757
|
+
currentProperty = null;
|
|
758
|
+
},
|
|
759
|
+
onArrayEnd: () => {
|
|
760
|
+
currentParent = previousParents.pop();
|
|
761
|
+
},
|
|
762
|
+
onLiteralValue: onValue,
|
|
763
|
+
onError: (error, offset, length) => {
|
|
764
|
+
errors.push({ error, offset, length });
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
visit(text, visitor, options);
|
|
768
|
+
return currentParent[0];
|
|
769
|
+
}
|
|
770
|
+
function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {
|
|
771
|
+
let currentParent = { type: "array", offset: -1, length: -1, children: [], parent: undefined };
|
|
772
|
+
function ensurePropertyComplete(endOffset) {
|
|
773
|
+
if (currentParent.type === "property") {
|
|
774
|
+
currentParent.length = endOffset - currentParent.offset;
|
|
775
|
+
currentParent = currentParent.parent;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
function onValue(valueNode) {
|
|
779
|
+
currentParent.children.push(valueNode);
|
|
780
|
+
return valueNode;
|
|
781
|
+
}
|
|
782
|
+
const visitor = {
|
|
783
|
+
onObjectBegin: (offset) => {
|
|
784
|
+
currentParent = onValue({ type: "object", offset, length: -1, parent: currentParent, children: [] });
|
|
785
|
+
},
|
|
786
|
+
onObjectProperty: (name, offset, length) => {
|
|
787
|
+
currentParent = onValue({ type: "property", offset, length: -1, parent: currentParent, children: [] });
|
|
788
|
+
currentParent.children.push({ type: "string", value: name, offset, length, parent: currentParent });
|
|
789
|
+
},
|
|
790
|
+
onObjectEnd: (offset, length) => {
|
|
791
|
+
ensurePropertyComplete(offset + length);
|
|
792
|
+
currentParent.length = offset + length - currentParent.offset;
|
|
793
|
+
currentParent = currentParent.parent;
|
|
794
|
+
ensurePropertyComplete(offset + length);
|
|
795
|
+
},
|
|
796
|
+
onArrayBegin: (offset, length) => {
|
|
797
|
+
currentParent = onValue({ type: "array", offset, length: -1, parent: currentParent, children: [] });
|
|
798
|
+
},
|
|
799
|
+
onArrayEnd: (offset, length) => {
|
|
800
|
+
currentParent.length = offset + length - currentParent.offset;
|
|
801
|
+
currentParent = currentParent.parent;
|
|
802
|
+
ensurePropertyComplete(offset + length);
|
|
803
|
+
},
|
|
804
|
+
onLiteralValue: (value, offset, length) => {
|
|
805
|
+
onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });
|
|
806
|
+
ensurePropertyComplete(offset + length);
|
|
807
|
+
},
|
|
808
|
+
onSeparator: (sep, offset, length) => {
|
|
809
|
+
if (currentParent.type === "property") {
|
|
810
|
+
if (sep === ":") {
|
|
811
|
+
currentParent.colonOffset = offset;
|
|
812
|
+
} else if (sep === ",") {
|
|
813
|
+
ensurePropertyComplete(offset);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
},
|
|
817
|
+
onError: (error, offset, length) => {
|
|
818
|
+
errors.push({ error, offset, length });
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
visit(text, visitor, options);
|
|
822
|
+
const result = currentParent.children[0];
|
|
823
|
+
if (result) {
|
|
824
|
+
delete result.parent;
|
|
825
|
+
}
|
|
826
|
+
return result;
|
|
827
|
+
}
|
|
828
|
+
function findNodeAtLocation(root, path) {
|
|
829
|
+
if (!root) {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
let node = root;
|
|
833
|
+
for (let segment of path) {
|
|
834
|
+
if (typeof segment === "string") {
|
|
835
|
+
if (node.type !== "object" || !Array.isArray(node.children)) {
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
let found = false;
|
|
839
|
+
for (const propertyNode of node.children) {
|
|
840
|
+
if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {
|
|
841
|
+
node = propertyNode.children[1];
|
|
842
|
+
found = true;
|
|
843
|
+
break;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (!found) {
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
} else {
|
|
850
|
+
const index = segment;
|
|
851
|
+
if (node.type !== "array" || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
node = node.children[index];
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
return node;
|
|
858
|
+
}
|
|
859
|
+
function visit(text, visitor, options = ParseOptions.DEFAULT) {
|
|
860
|
+
const _scanner = createScanner(text, false);
|
|
861
|
+
const _jsonPath = [];
|
|
862
|
+
let suppressedCallbacks = 0;
|
|
863
|
+
function toNoArgVisit(visitFunction) {
|
|
864
|
+
return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
|
|
865
|
+
}
|
|
866
|
+
function toOneArgVisit(visitFunction) {
|
|
867
|
+
return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
|
|
868
|
+
}
|
|
869
|
+
function toOneArgVisitWithPath(visitFunction) {
|
|
870
|
+
return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;
|
|
871
|
+
}
|
|
872
|
+
function toBeginVisit(visitFunction) {
|
|
873
|
+
return visitFunction ? () => {
|
|
874
|
+
if (suppressedCallbacks > 0) {
|
|
875
|
+
suppressedCallbacks++;
|
|
876
|
+
} else {
|
|
877
|
+
let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());
|
|
878
|
+
if (cbReturn === false) {
|
|
879
|
+
suppressedCallbacks = 1;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
} : () => true;
|
|
883
|
+
}
|
|
884
|
+
function toEndVisit(visitFunction) {
|
|
885
|
+
return visitFunction ? () => {
|
|
886
|
+
if (suppressedCallbacks > 0) {
|
|
887
|
+
suppressedCallbacks--;
|
|
888
|
+
}
|
|
889
|
+
if (suppressedCallbacks === 0) {
|
|
890
|
+
visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
|
|
891
|
+
}
|
|
892
|
+
} : () => true;
|
|
893
|
+
}
|
|
894
|
+
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);
|
|
895
|
+
const disallowComments = options && options.disallowComments;
|
|
896
|
+
const allowTrailingComma = options && options.allowTrailingComma;
|
|
897
|
+
function scanNext() {
|
|
898
|
+
while (true) {
|
|
899
|
+
const token = _scanner.scan();
|
|
900
|
+
switch (_scanner.getTokenError()) {
|
|
901
|
+
case 4:
|
|
902
|
+
handleError(14);
|
|
903
|
+
break;
|
|
904
|
+
case 5:
|
|
905
|
+
handleError(15);
|
|
906
|
+
break;
|
|
907
|
+
case 3:
|
|
908
|
+
handleError(13);
|
|
909
|
+
break;
|
|
910
|
+
case 1:
|
|
911
|
+
if (!disallowComments) {
|
|
912
|
+
handleError(11);
|
|
913
|
+
}
|
|
914
|
+
break;
|
|
915
|
+
case 2:
|
|
916
|
+
handleError(12);
|
|
917
|
+
break;
|
|
918
|
+
case 6:
|
|
919
|
+
handleError(16);
|
|
920
|
+
break;
|
|
921
|
+
}
|
|
922
|
+
switch (token) {
|
|
923
|
+
case 12:
|
|
924
|
+
case 13:
|
|
925
|
+
if (disallowComments) {
|
|
926
|
+
handleError(10);
|
|
927
|
+
} else {
|
|
928
|
+
onComment();
|
|
929
|
+
}
|
|
930
|
+
break;
|
|
931
|
+
case 16:
|
|
932
|
+
handleError(1);
|
|
933
|
+
break;
|
|
934
|
+
case 15:
|
|
935
|
+
case 14:
|
|
936
|
+
break;
|
|
937
|
+
default:
|
|
938
|
+
return token;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
function handleError(error, skipUntilAfter = [], skipUntil = []) {
|
|
943
|
+
onError(error);
|
|
944
|
+
if (skipUntilAfter.length + skipUntil.length > 0) {
|
|
945
|
+
let token = _scanner.getToken();
|
|
946
|
+
while (token !== 17) {
|
|
947
|
+
if (skipUntilAfter.indexOf(token) !== -1) {
|
|
948
|
+
scanNext();
|
|
949
|
+
break;
|
|
950
|
+
} else if (skipUntil.indexOf(token) !== -1) {
|
|
951
|
+
break;
|
|
952
|
+
}
|
|
953
|
+
token = scanNext();
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
function parseString(isValue) {
|
|
958
|
+
const value = _scanner.getTokenValue();
|
|
959
|
+
if (isValue) {
|
|
960
|
+
onLiteralValue(value);
|
|
961
|
+
} else {
|
|
962
|
+
onObjectProperty(value);
|
|
963
|
+
_jsonPath.push(value);
|
|
964
|
+
}
|
|
965
|
+
scanNext();
|
|
966
|
+
return true;
|
|
967
|
+
}
|
|
968
|
+
function parseLiteral() {
|
|
969
|
+
switch (_scanner.getToken()) {
|
|
970
|
+
case 11:
|
|
971
|
+
const tokenValue = _scanner.getTokenValue();
|
|
972
|
+
let value = Number(tokenValue);
|
|
973
|
+
if (isNaN(value)) {
|
|
974
|
+
handleError(2);
|
|
975
|
+
value = 0;
|
|
976
|
+
}
|
|
977
|
+
onLiteralValue(value);
|
|
978
|
+
break;
|
|
979
|
+
case 7:
|
|
980
|
+
onLiteralValue(null);
|
|
981
|
+
break;
|
|
982
|
+
case 8:
|
|
983
|
+
onLiteralValue(true);
|
|
984
|
+
break;
|
|
985
|
+
case 9:
|
|
986
|
+
onLiteralValue(false);
|
|
987
|
+
break;
|
|
988
|
+
default:
|
|
989
|
+
return false;
|
|
990
|
+
}
|
|
991
|
+
scanNext();
|
|
992
|
+
return true;
|
|
993
|
+
}
|
|
994
|
+
function parseProperty() {
|
|
995
|
+
if (_scanner.getToken() !== 10) {
|
|
996
|
+
handleError(3, [], [2, 5]);
|
|
997
|
+
return false;
|
|
998
|
+
}
|
|
999
|
+
parseString(false);
|
|
1000
|
+
if (_scanner.getToken() === 6) {
|
|
1001
|
+
onSeparator(":");
|
|
1002
|
+
scanNext();
|
|
1003
|
+
if (!parseValue()) {
|
|
1004
|
+
handleError(4, [], [2, 5]);
|
|
1005
|
+
}
|
|
1006
|
+
} else {
|
|
1007
|
+
handleError(5, [], [2, 5]);
|
|
1008
|
+
}
|
|
1009
|
+
_jsonPath.pop();
|
|
1010
|
+
return true;
|
|
1011
|
+
}
|
|
1012
|
+
function parseObject() {
|
|
1013
|
+
onObjectBegin();
|
|
1014
|
+
scanNext();
|
|
1015
|
+
let needsComma = false;
|
|
1016
|
+
while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
|
|
1017
|
+
if (_scanner.getToken() === 5) {
|
|
1018
|
+
if (!needsComma) {
|
|
1019
|
+
handleError(4, [], []);
|
|
1020
|
+
}
|
|
1021
|
+
onSeparator(",");
|
|
1022
|
+
scanNext();
|
|
1023
|
+
if (_scanner.getToken() === 2 && allowTrailingComma) {
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
} else if (needsComma) {
|
|
1027
|
+
handleError(6, [], []);
|
|
1028
|
+
}
|
|
1029
|
+
if (!parseProperty()) {
|
|
1030
|
+
handleError(4, [], [2, 5]);
|
|
1031
|
+
}
|
|
1032
|
+
needsComma = true;
|
|
1033
|
+
}
|
|
1034
|
+
onObjectEnd();
|
|
1035
|
+
if (_scanner.getToken() !== 2) {
|
|
1036
|
+
handleError(7, [2], []);
|
|
1037
|
+
} else {
|
|
1038
|
+
scanNext();
|
|
1039
|
+
}
|
|
1040
|
+
return true;
|
|
1041
|
+
}
|
|
1042
|
+
function parseArray() {
|
|
1043
|
+
onArrayBegin();
|
|
1044
|
+
scanNext();
|
|
1045
|
+
let isFirstElement = true;
|
|
1046
|
+
let needsComma = false;
|
|
1047
|
+
while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
|
|
1048
|
+
if (_scanner.getToken() === 5) {
|
|
1049
|
+
if (!needsComma) {
|
|
1050
|
+
handleError(4, [], []);
|
|
1051
|
+
}
|
|
1052
|
+
onSeparator(",");
|
|
1053
|
+
scanNext();
|
|
1054
|
+
if (_scanner.getToken() === 4 && allowTrailingComma) {
|
|
1055
|
+
break;
|
|
1056
|
+
}
|
|
1057
|
+
} else if (needsComma) {
|
|
1058
|
+
handleError(6, [], []);
|
|
1059
|
+
}
|
|
1060
|
+
if (isFirstElement) {
|
|
1061
|
+
_jsonPath.push(0);
|
|
1062
|
+
isFirstElement = false;
|
|
1063
|
+
} else {
|
|
1064
|
+
_jsonPath[_jsonPath.length - 1]++;
|
|
1065
|
+
}
|
|
1066
|
+
if (!parseValue()) {
|
|
1067
|
+
handleError(4, [], [4, 5]);
|
|
1068
|
+
}
|
|
1069
|
+
needsComma = true;
|
|
1070
|
+
}
|
|
1071
|
+
onArrayEnd();
|
|
1072
|
+
if (!isFirstElement) {
|
|
1073
|
+
_jsonPath.pop();
|
|
1074
|
+
}
|
|
1075
|
+
if (_scanner.getToken() !== 4) {
|
|
1076
|
+
handleError(8, [4], []);
|
|
1077
|
+
} else {
|
|
1078
|
+
scanNext();
|
|
1079
|
+
}
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
function parseValue() {
|
|
1083
|
+
switch (_scanner.getToken()) {
|
|
1084
|
+
case 3:
|
|
1085
|
+
return parseArray();
|
|
1086
|
+
case 1:
|
|
1087
|
+
return parseObject();
|
|
1088
|
+
case 10:
|
|
1089
|
+
return parseString(true);
|
|
1090
|
+
default:
|
|
1091
|
+
return parseLiteral();
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
scanNext();
|
|
1095
|
+
if (_scanner.getToken() === 17) {
|
|
1096
|
+
if (options.allowEmptyContent) {
|
|
1097
|
+
return true;
|
|
1098
|
+
}
|
|
1099
|
+
handleError(4, [], []);
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
if (!parseValue()) {
|
|
1103
|
+
handleError(4, [], []);
|
|
1104
|
+
return false;
|
|
1105
|
+
}
|
|
1106
|
+
if (_scanner.getToken() !== 17) {
|
|
1107
|
+
handleError(9, [], []);
|
|
1108
|
+
}
|
|
1109
|
+
return true;
|
|
1110
|
+
}
|
|
1111
|
+
function getNodeType(value) {
|
|
1112
|
+
switch (typeof value) {
|
|
1113
|
+
case "boolean":
|
|
1114
|
+
return "boolean";
|
|
1115
|
+
case "number":
|
|
1116
|
+
return "number";
|
|
1117
|
+
case "string":
|
|
1118
|
+
return "string";
|
|
1119
|
+
case "object": {
|
|
1120
|
+
if (!value) {
|
|
1121
|
+
return "null";
|
|
1122
|
+
} else if (Array.isArray(value)) {
|
|
1123
|
+
return "array";
|
|
1124
|
+
}
|
|
1125
|
+
return "object";
|
|
1126
|
+
}
|
|
1127
|
+
default:
|
|
1128
|
+
return "null";
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
var ParseOptions;
|
|
1132
|
+
var init_parser = __esm(() => {
|
|
1133
|
+
init_scanner();
|
|
1134
|
+
(function(ParseOptions2) {
|
|
1135
|
+
ParseOptions2.DEFAULT = {
|
|
1136
|
+
allowTrailingComma: false
|
|
1137
|
+
};
|
|
1138
|
+
})(ParseOptions || (ParseOptions = {}));
|
|
1139
|
+
});
|
|
1140
|
+
|
|
1141
|
+
// node_modules/jsonc-parser/lib/esm/impl/edit.js
|
|
1142
|
+
function setProperty(text, originalPath, value, options) {
|
|
1143
|
+
const path = originalPath.slice();
|
|
1144
|
+
const errors = [];
|
|
1145
|
+
const root = parseTree(text, errors);
|
|
1146
|
+
let parent = undefined;
|
|
1147
|
+
let lastSegment = undefined;
|
|
1148
|
+
while (path.length > 0) {
|
|
1149
|
+
lastSegment = path.pop();
|
|
1150
|
+
parent = findNodeAtLocation(root, path);
|
|
1151
|
+
if (parent === undefined && value !== undefined) {
|
|
1152
|
+
if (typeof lastSegment === "string") {
|
|
1153
|
+
value = { [lastSegment]: value };
|
|
1154
|
+
} else {
|
|
1155
|
+
value = [value];
|
|
1156
|
+
}
|
|
1157
|
+
} else {
|
|
1158
|
+
break;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
if (!parent) {
|
|
1162
|
+
if (value === undefined) {
|
|
1163
|
+
throw new Error("Can not delete in empty document");
|
|
1164
|
+
}
|
|
1165
|
+
return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, options);
|
|
1166
|
+
} else if (parent.type === "object" && typeof lastSegment === "string" && Array.isArray(parent.children)) {
|
|
1167
|
+
const existing = findNodeAtLocation(parent, [lastSegment]);
|
|
1168
|
+
if (existing !== undefined) {
|
|
1169
|
+
if (value === undefined) {
|
|
1170
|
+
if (!existing.parent) {
|
|
1171
|
+
throw new Error("Malformed AST");
|
|
1172
|
+
}
|
|
1173
|
+
const propertyIndex = parent.children.indexOf(existing.parent);
|
|
1174
|
+
let removeBegin;
|
|
1175
|
+
let removeEnd = existing.parent.offset + existing.parent.length;
|
|
1176
|
+
if (propertyIndex > 0) {
|
|
1177
|
+
let previous = parent.children[propertyIndex - 1];
|
|
1178
|
+
removeBegin = previous.offset + previous.length;
|
|
1179
|
+
} else {
|
|
1180
|
+
removeBegin = parent.offset + 1;
|
|
1181
|
+
if (parent.children.length > 1) {
|
|
1182
|
+
let next = parent.children[1];
|
|
1183
|
+
removeEnd = next.offset;
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
return withFormatting(text, { offset: removeBegin, length: removeEnd - removeBegin, content: "" }, options);
|
|
1187
|
+
} else {
|
|
1188
|
+
return withFormatting(text, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, options);
|
|
1189
|
+
}
|
|
1190
|
+
} else {
|
|
1191
|
+
if (value === undefined) {
|
|
1192
|
+
return [];
|
|
1193
|
+
}
|
|
1194
|
+
const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
|
|
1195
|
+
const index = options.getInsertionIndex ? options.getInsertionIndex(parent.children.map((p) => p.children[0].value)) : parent.children.length;
|
|
1196
|
+
let edit;
|
|
1197
|
+
if (index > 0) {
|
|
1198
|
+
let previous = parent.children[index - 1];
|
|
1199
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1200
|
+
} else if (parent.children.length === 0) {
|
|
1201
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
1202
|
+
} else {
|
|
1203
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty + "," };
|
|
1204
|
+
}
|
|
1205
|
+
return withFormatting(text, edit, options);
|
|
1206
|
+
}
|
|
1207
|
+
} else if (parent.type === "array" && typeof lastSegment === "number" && Array.isArray(parent.children)) {
|
|
1208
|
+
const insertIndex = lastSegment;
|
|
1209
|
+
if (insertIndex === -1) {
|
|
1210
|
+
const newProperty = `${JSON.stringify(value)}`;
|
|
1211
|
+
let edit;
|
|
1212
|
+
if (parent.children.length === 0) {
|
|
1213
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
1214
|
+
} else {
|
|
1215
|
+
const previous = parent.children[parent.children.length - 1];
|
|
1216
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1217
|
+
}
|
|
1218
|
+
return withFormatting(text, edit, options);
|
|
1219
|
+
} else if (value === undefined && parent.children.length >= 0) {
|
|
1220
|
+
const removalIndex = lastSegment;
|
|
1221
|
+
const toRemove = parent.children[removalIndex];
|
|
1222
|
+
let edit;
|
|
1223
|
+
if (parent.children.length === 1) {
|
|
1224
|
+
edit = { offset: parent.offset + 1, length: parent.length - 2, content: "" };
|
|
1225
|
+
} else if (parent.children.length - 1 === removalIndex) {
|
|
1226
|
+
let previous = parent.children[removalIndex - 1];
|
|
1227
|
+
let offset = previous.offset + previous.length;
|
|
1228
|
+
let parentEndOffset = parent.offset + parent.length;
|
|
1229
|
+
edit = { offset, length: parentEndOffset - 2 - offset, content: "" };
|
|
1230
|
+
} else {
|
|
1231
|
+
edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: "" };
|
|
1232
|
+
}
|
|
1233
|
+
return withFormatting(text, edit, options);
|
|
1234
|
+
} else if (value !== undefined) {
|
|
1235
|
+
let edit;
|
|
1236
|
+
const newProperty = `${JSON.stringify(value)}`;
|
|
1237
|
+
if (!options.isArrayInsertion && parent.children.length > lastSegment) {
|
|
1238
|
+
const toModify = parent.children[lastSegment];
|
|
1239
|
+
edit = { offset: toModify.offset, length: toModify.length, content: newProperty };
|
|
1240
|
+
} else if (parent.children.length === 0 || lastSegment === 0) {
|
|
1241
|
+
edit = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + "," };
|
|
1242
|
+
} else {
|
|
1243
|
+
const index = lastSegment > parent.children.length ? parent.children.length : lastSegment;
|
|
1244
|
+
const previous = parent.children[index - 1];
|
|
1245
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
1246
|
+
}
|
|
1247
|
+
return withFormatting(text, edit, options);
|
|
1248
|
+
} else {
|
|
1249
|
+
throw new Error(`Can not ${value === undefined ? "remove" : options.isArrayInsertion ? "insert" : "modify"} Array index ${insertIndex} as length is not sufficient`);
|
|
1250
|
+
}
|
|
1251
|
+
} else {
|
|
1252
|
+
throw new Error(`Can not add ${typeof lastSegment !== "number" ? "index" : "property"} to parent of type ${parent.type}`);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
function withFormatting(text, edit, options) {
|
|
1256
|
+
if (!options.formattingOptions) {
|
|
1257
|
+
return [edit];
|
|
1258
|
+
}
|
|
1259
|
+
let newText = applyEdit(text, edit);
|
|
1260
|
+
let begin = edit.offset;
|
|
1261
|
+
let end = edit.offset + edit.content.length;
|
|
1262
|
+
if (edit.length === 0 || edit.content.length === 0) {
|
|
1263
|
+
while (begin > 0 && !isEOL(newText, begin - 1)) {
|
|
1264
|
+
begin--;
|
|
1265
|
+
}
|
|
1266
|
+
while (end < newText.length && !isEOL(newText, end)) {
|
|
1267
|
+
end++;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
const edits = format(newText, { offset: begin, length: end - begin }, { ...options.formattingOptions, keepLines: false });
|
|
1271
|
+
for (let i = edits.length - 1;i >= 0; i--) {
|
|
1272
|
+
const edit2 = edits[i];
|
|
1273
|
+
newText = applyEdit(newText, edit2);
|
|
1274
|
+
begin = Math.min(begin, edit2.offset);
|
|
1275
|
+
end = Math.max(end, edit2.offset + edit2.length);
|
|
1276
|
+
end += edit2.content.length - edit2.length;
|
|
1277
|
+
}
|
|
1278
|
+
const editLength = text.length - (newText.length - end) - begin;
|
|
1279
|
+
return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }];
|
|
1280
|
+
}
|
|
1281
|
+
function applyEdit(text, edit) {
|
|
1282
|
+
return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
|
|
1283
|
+
}
|
|
1284
|
+
var init_edit = __esm(() => {
|
|
1285
|
+
init_format();
|
|
1286
|
+
init_parser();
|
|
1287
|
+
});
|
|
1288
|
+
|
|
1289
|
+
// node_modules/jsonc-parser/lib/esm/main.js
|
|
1290
|
+
function modify(text, path, value, options) {
|
|
1291
|
+
return setProperty(text, path, value, options);
|
|
1292
|
+
}
|
|
1293
|
+
function applyEdits(text, edits) {
|
|
1294
|
+
let sortedEdits = edits.slice(0).sort((a, b) => {
|
|
1295
|
+
const diff = a.offset - b.offset;
|
|
1296
|
+
if (diff === 0) {
|
|
1297
|
+
return a.length - b.length;
|
|
1298
|
+
}
|
|
1299
|
+
return diff;
|
|
1300
|
+
});
|
|
1301
|
+
let lastModifiedOffset = text.length;
|
|
1302
|
+
for (let i = sortedEdits.length - 1;i >= 0; i--) {
|
|
1303
|
+
let e = sortedEdits[i];
|
|
1304
|
+
if (e.offset + e.length <= lastModifiedOffset) {
|
|
1305
|
+
text = applyEdit(text, e);
|
|
1306
|
+
} else {
|
|
1307
|
+
throw new Error("Overlapping edit");
|
|
1308
|
+
}
|
|
1309
|
+
lastModifiedOffset = e.offset;
|
|
1310
|
+
}
|
|
1311
|
+
return text;
|
|
1312
|
+
}
|
|
1313
|
+
var ScanError, SyntaxKind, parse2, ParseErrorCode;
|
|
1314
|
+
var init_main = __esm(() => {
|
|
1315
|
+
init_format();
|
|
1316
|
+
init_edit();
|
|
1317
|
+
init_scanner();
|
|
1318
|
+
init_parser();
|
|
1319
|
+
(function(ScanError2) {
|
|
1320
|
+
ScanError2[ScanError2["None"] = 0] = "None";
|
|
1321
|
+
ScanError2[ScanError2["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
|
|
1322
|
+
ScanError2[ScanError2["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
|
|
1323
|
+
ScanError2[ScanError2["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
|
|
1324
|
+
ScanError2[ScanError2["InvalidUnicode"] = 4] = "InvalidUnicode";
|
|
1325
|
+
ScanError2[ScanError2["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
|
|
1326
|
+
ScanError2[ScanError2["InvalidCharacter"] = 6] = "InvalidCharacter";
|
|
1327
|
+
})(ScanError || (ScanError = {}));
|
|
1328
|
+
(function(SyntaxKind2) {
|
|
1329
|
+
SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 1] = "OpenBraceToken";
|
|
1330
|
+
SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 2] = "CloseBraceToken";
|
|
1331
|
+
SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 3] = "OpenBracketToken";
|
|
1332
|
+
SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 4] = "CloseBracketToken";
|
|
1333
|
+
SyntaxKind2[SyntaxKind2["CommaToken"] = 5] = "CommaToken";
|
|
1334
|
+
SyntaxKind2[SyntaxKind2["ColonToken"] = 6] = "ColonToken";
|
|
1335
|
+
SyntaxKind2[SyntaxKind2["NullKeyword"] = 7] = "NullKeyword";
|
|
1336
|
+
SyntaxKind2[SyntaxKind2["TrueKeyword"] = 8] = "TrueKeyword";
|
|
1337
|
+
SyntaxKind2[SyntaxKind2["FalseKeyword"] = 9] = "FalseKeyword";
|
|
1338
|
+
SyntaxKind2[SyntaxKind2["StringLiteral"] = 10] = "StringLiteral";
|
|
1339
|
+
SyntaxKind2[SyntaxKind2["NumericLiteral"] = 11] = "NumericLiteral";
|
|
1340
|
+
SyntaxKind2[SyntaxKind2["LineCommentTrivia"] = 12] = "LineCommentTrivia";
|
|
1341
|
+
SyntaxKind2[SyntaxKind2["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
|
|
1342
|
+
SyntaxKind2[SyntaxKind2["LineBreakTrivia"] = 14] = "LineBreakTrivia";
|
|
1343
|
+
SyntaxKind2[SyntaxKind2["Trivia"] = 15] = "Trivia";
|
|
1344
|
+
SyntaxKind2[SyntaxKind2["Unknown"] = 16] = "Unknown";
|
|
1345
|
+
SyntaxKind2[SyntaxKind2["EOF"] = 17] = "EOF";
|
|
1346
|
+
})(SyntaxKind || (SyntaxKind = {}));
|
|
1347
|
+
parse2 = parse;
|
|
1348
|
+
(function(ParseErrorCode2) {
|
|
1349
|
+
ParseErrorCode2[ParseErrorCode2["InvalidSymbol"] = 1] = "InvalidSymbol";
|
|
1350
|
+
ParseErrorCode2[ParseErrorCode2["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
|
|
1351
|
+
ParseErrorCode2[ParseErrorCode2["PropertyNameExpected"] = 3] = "PropertyNameExpected";
|
|
1352
|
+
ParseErrorCode2[ParseErrorCode2["ValueExpected"] = 4] = "ValueExpected";
|
|
1353
|
+
ParseErrorCode2[ParseErrorCode2["ColonExpected"] = 5] = "ColonExpected";
|
|
1354
|
+
ParseErrorCode2[ParseErrorCode2["CommaExpected"] = 6] = "CommaExpected";
|
|
1355
|
+
ParseErrorCode2[ParseErrorCode2["CloseBraceExpected"] = 7] = "CloseBraceExpected";
|
|
1356
|
+
ParseErrorCode2[ParseErrorCode2["CloseBracketExpected"] = 8] = "CloseBracketExpected";
|
|
1357
|
+
ParseErrorCode2[ParseErrorCode2["EndOfFileExpected"] = 9] = "EndOfFileExpected";
|
|
1358
|
+
ParseErrorCode2[ParseErrorCode2["InvalidCommentToken"] = 10] = "InvalidCommentToken";
|
|
1359
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
|
|
1360
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
|
|
1361
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
|
|
1362
|
+
ParseErrorCode2[ParseErrorCode2["InvalidUnicode"] = 14] = "InvalidUnicode";
|
|
1363
|
+
ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
|
|
1364
|
+
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
1365
|
+
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
1366
|
+
});
|
|
1367
|
+
|
|
1368
|
+
// src/core/jsonc.ts
|
|
1369
|
+
function parseJsonc(text) {
|
|
1370
|
+
const errors = [];
|
|
1371
|
+
const value = parse2(text, errors, { allowTrailingComma: true });
|
|
1372
|
+
if (errors.length > 0) {
|
|
1373
|
+
const first = errors[0];
|
|
1374
|
+
throw new SyntaxError(`JSONC parse error at offset ${first.offset} (code ${first.error})`);
|
|
1375
|
+
}
|
|
1376
|
+
return value;
|
|
1377
|
+
}
|
|
1378
|
+
var init_jsonc = __esm(() => {
|
|
1379
|
+
init_main();
|
|
1380
|
+
});
|
|
1381
|
+
|
|
1382
|
+
// src/installer/formats/value.ts
|
|
1383
|
+
function isPlainObject(value) {
|
|
1384
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1385
|
+
}
|
|
1386
|
+
function deepEqual(a, b) {
|
|
1387
|
+
if (a === b)
|
|
1388
|
+
return true;
|
|
1389
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object")
|
|
1390
|
+
return false;
|
|
1391
|
+
const aArray = Array.isArray(a);
|
|
1392
|
+
const bArray = Array.isArray(b);
|
|
1393
|
+
if (aArray !== bArray)
|
|
1394
|
+
return false;
|
|
1395
|
+
if (aArray && bArray) {
|
|
1396
|
+
const x2 = a;
|
|
1397
|
+
const y2 = b;
|
|
1398
|
+
return x2.length === y2.length && x2.every((item, index) => deepEqual(item, y2[index]));
|
|
1399
|
+
}
|
|
1400
|
+
const x = a;
|
|
1401
|
+
const y = b;
|
|
1402
|
+
const xKeys = Object.keys(x);
|
|
1403
|
+
const yKeys = Object.keys(y);
|
|
1404
|
+
return xKeys.length === yKeys.length && xKeys.every((key) => deepEqual(x[key], y[key]));
|
|
1405
|
+
}
|
|
1406
|
+
function valueAt(value, path) {
|
|
1407
|
+
let node = value;
|
|
1408
|
+
for (const key of path) {
|
|
1409
|
+
if (Array.isArray(node)) {
|
|
1410
|
+
const index = Number(key);
|
|
1411
|
+
node = Number.isInteger(index) ? node[index] : undefined;
|
|
1412
|
+
} else if (isPlainObject(node)) {
|
|
1413
|
+
node = node[key];
|
|
1414
|
+
} else {
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
if (node === undefined)
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1420
|
+
return node;
|
|
1421
|
+
}
|
|
1422
|
+
function removeAt(value, path) {
|
|
1423
|
+
const parent = valueAt(value, path.slice(0, -1));
|
|
1424
|
+
if (isPlainObject(parent))
|
|
1425
|
+
delete parent[path[path.length - 1]];
|
|
1426
|
+
}
|
|
1427
|
+
function appendEntries(existing, entries, path) {
|
|
1428
|
+
if (existing !== undefined && !Array.isArray(existing)) {
|
|
1429
|
+
throw new Error(`cannot append to ${path.join(".")}: it is a ${typeof existing}, not an array`);
|
|
1430
|
+
}
|
|
1431
|
+
const list = Array.isArray(existing) ? existing : [];
|
|
1432
|
+
const appended = entries.filter((entry) => !list.some((item) => deepEqual(item, entry)));
|
|
1433
|
+
return { list, appended };
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
// src/installer/formats/json.ts
|
|
1437
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
1438
|
+
function loadJson(file) {
|
|
1439
|
+
if (!existsSync(file))
|
|
1440
|
+
return { exists: false, text: "", value: {}, lossy: false };
|
|
1441
|
+
const text = readFileSync(file, "utf8");
|
|
1442
|
+
try {
|
|
1443
|
+
return { exists: true, text, value: parseJsonc(text), lossy: false };
|
|
1444
|
+
} catch (error) {
|
|
1445
|
+
const parseError = error instanceof Error ? error.message : String(error);
|
|
1446
|
+
return { exists: true, text, value: {}, lossy: false, parseError };
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
function jsonGet(text, path) {
|
|
1450
|
+
const root = parse2(text, undefined, { allowTrailingComma: true });
|
|
1451
|
+
return valueAt(root, path);
|
|
1452
|
+
}
|
|
1453
|
+
function applyJsonOps(text, ops) {
|
|
1454
|
+
let current = text.trim().length > 0 ? text : `{}
|
|
1455
|
+
`;
|
|
1456
|
+
const recorded = [];
|
|
1457
|
+
const createdParents = [];
|
|
1458
|
+
for (const op of ops) {
|
|
1459
|
+
const path = op.path;
|
|
1460
|
+
if (op.op === "set") {
|
|
1461
|
+
current = ensureParents(current, op.path, createdParents);
|
|
1462
|
+
const previous = jsonGet(current, op.path);
|
|
1463
|
+
current = edit(current, path, op.value);
|
|
1464
|
+
recorded.push({ op: "set", path: op.path, applied: structuredClone(op.value), previous });
|
|
1465
|
+
continue;
|
|
1466
|
+
}
|
|
1467
|
+
current = ensureParents(current, op.path, createdParents);
|
|
1468
|
+
const existing = jsonGet(current, op.path);
|
|
1469
|
+
const { list, appended } = appendEntries(existing, op.entries ?? [], op.path);
|
|
1470
|
+
if (existing === undefined) {
|
|
1471
|
+
current = edit(current, path, []);
|
|
1472
|
+
createdParents.push(op.path);
|
|
1473
|
+
}
|
|
1474
|
+
let index = list.length;
|
|
1475
|
+
for (const entry of appended) {
|
|
1476
|
+
current = edit(current, [...path, index], entry);
|
|
1477
|
+
index += 1;
|
|
1478
|
+
}
|
|
1479
|
+
recorded.push({ op: "append-array", path: op.path, applied: appended, previous: undefined });
|
|
1480
|
+
}
|
|
1481
|
+
return { text: current, recorded, createdParents };
|
|
1482
|
+
}
|
|
1483
|
+
function revertJsonOps(text, ops, createdParents) {
|
|
1484
|
+
let current = text;
|
|
1485
|
+
const notes = [];
|
|
1486
|
+
for (const record of [...ops].reverse()) {
|
|
1487
|
+
const path = record.path;
|
|
1488
|
+
if (record.op === "set") {
|
|
1489
|
+
const now = jsonGet(current, record.path);
|
|
1490
|
+
if (now === undefined)
|
|
1491
|
+
continue;
|
|
1492
|
+
if (!deepEqual(now, record.applied)) {
|
|
1493
|
+
notes.push(`${record.path.join(".")}: current value differs from what the installer wrote; left untouched`);
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
current = record.previous === undefined ? edit(current, path, undefined) : edit(current, path, record.previous);
|
|
1497
|
+
} else {
|
|
1498
|
+
const entries = Array.isArray(record.applied) ? record.applied : [];
|
|
1499
|
+
for (const entry of [...entries].reverse()) {
|
|
1500
|
+
const list = jsonGet(current, record.path);
|
|
1501
|
+
if (!Array.isArray(list))
|
|
1502
|
+
continue;
|
|
1503
|
+
const index = list.findIndex((item) => deepEqual(item, entry));
|
|
1504
|
+
if (index === -1)
|
|
1505
|
+
continue;
|
|
1506
|
+
current = edit(current, [...path, index], undefined);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
for (const parent of [...createdParents].reverse()) {
|
|
1511
|
+
const value = jsonGet(current, parent);
|
|
1512
|
+
const isEmptyObject = isPlainObject(value) && Object.keys(value).length === 0;
|
|
1513
|
+
const isEmptyArray = Array.isArray(value) && value.length === 0;
|
|
1514
|
+
if (isEmptyObject || isEmptyArray) {
|
|
1515
|
+
current = edit(current, parent, undefined);
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
return { text: current, notes };
|
|
1519
|
+
}
|
|
1520
|
+
function edit(text, path, value) {
|
|
1521
|
+
return applyEdits(text, modify(text, path, value, { formattingOptions: JSON_FORMATTING }));
|
|
1522
|
+
}
|
|
1523
|
+
function ensureParents(text, path, created) {
|
|
1524
|
+
let current = text;
|
|
1525
|
+
for (let depth = 0;depth < path.length - 1; depth += 1) {
|
|
1526
|
+
const prefix = path.slice(0, depth + 1);
|
|
1527
|
+
const existing = jsonGet(current, prefix);
|
|
1528
|
+
if (existing !== undefined && typeof existing !== "object") {
|
|
1529
|
+
throw new Error(`cannot descend into ${prefix.join(".")}: it is a ${typeof existing}, not an object`);
|
|
1530
|
+
}
|
|
1531
|
+
if (existing !== undefined)
|
|
1532
|
+
continue;
|
|
1533
|
+
const nextSegmentIsIndex = Number.isInteger(Number(path[depth + 1]));
|
|
1534
|
+
const placeholder = nextSegmentIsIndex ? [] : {};
|
|
1535
|
+
current = edit(current, prefix, placeholder);
|
|
1536
|
+
created.push(prefix);
|
|
1537
|
+
}
|
|
1538
|
+
return current;
|
|
1539
|
+
}
|
|
1540
|
+
function jsonOpHolds(text, op) {
|
|
1541
|
+
if (op.op === "set")
|
|
1542
|
+
return deepEqual(jsonGet(text, op.path), op.value);
|
|
1543
|
+
const list = jsonGet(text, op.path);
|
|
1544
|
+
return Array.isArray(list) && (op.entries ?? []).every((entry) => list.some((item) => deepEqual(item, entry)));
|
|
1545
|
+
}
|
|
1546
|
+
var JSON_FORMATTING, jsonCodec;
|
|
1547
|
+
var init_json = __esm(() => {
|
|
1548
|
+
init_main();
|
|
1549
|
+
init_jsonc();
|
|
1550
|
+
JSON_FORMATTING = { insertSpaces: true, tabSize: 2, insertFinalNewline: false };
|
|
1551
|
+
jsonCodec = {
|
|
1552
|
+
format: "json",
|
|
1553
|
+
load: loadJson,
|
|
1554
|
+
apply: (text, edit2) => {
|
|
1555
|
+
if (edit2.format !== "json")
|
|
1556
|
+
throw new Error(`json codec cannot apply a ${edit2.format} edit`);
|
|
1557
|
+
const result = applyJsonOps(text, edit2.ops);
|
|
1558
|
+
return { text: result.text, recorded: result.recorded, createdParents: result.createdParents };
|
|
1559
|
+
},
|
|
1560
|
+
verify: (text, edit2, op) => {
|
|
1561
|
+
if (edit2.format !== "json")
|
|
1562
|
+
throw new Error(`json codec cannot verify a ${edit2.format} edit`);
|
|
1563
|
+
const ops = op === undefined ? edit2.ops : [op];
|
|
1564
|
+
return ops.every((candidate) => jsonOpHolds(text, candidate));
|
|
1565
|
+
},
|
|
1566
|
+
revert: (text, recorded) => revertJsonOps(text, recorded.ops, recorded.createdParents ?? []),
|
|
1567
|
+
isEffectivelyEmpty: (text) => text.replace(/[{}\s]/g, "").length === 0
|
|
1568
|
+
};
|
|
1569
|
+
});
|
|
1570
|
+
|
|
1571
|
+
// src/installer/formats/rules.ts
|
|
1572
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
1573
|
+
function rulesMarkers(host) {
|
|
1574
|
+
return {
|
|
1575
|
+
begin: `<!-- deepseek-web-retrieval:${host}:rules:begin -->`,
|
|
1576
|
+
end: `<!-- deepseek-web-retrieval:${host}:rules:end -->`
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
function buildRulesBlock(host, lines) {
|
|
1580
|
+
const markers = rulesMarkers(host);
|
|
1581
|
+
return [markers.begin, ...lines, markers.end].join(`
|
|
1582
|
+
`);
|
|
1583
|
+
}
|
|
1584
|
+
function upsertBlock(host, text, block) {
|
|
1585
|
+
const without = removeBlock(host, text);
|
|
1586
|
+
const trimmed = without.trimEnd();
|
|
1587
|
+
return trimmed ? `${trimmed}
|
|
1588
|
+
|
|
1589
|
+
${block}
|
|
1590
|
+
` : `${block}
|
|
1591
|
+
`;
|
|
1592
|
+
}
|
|
1593
|
+
function removeBlock(host, text) {
|
|
1594
|
+
const markers = rulesMarkers(host);
|
|
1595
|
+
const start = text.indexOf(markers.begin);
|
|
1596
|
+
if (start === -1)
|
|
1597
|
+
return text;
|
|
1598
|
+
const end = text.indexOf(markers.end);
|
|
1599
|
+
if (end === -1)
|
|
1600
|
+
return text.slice(0, start);
|
|
1601
|
+
let after = text.slice(end + markers.end.length);
|
|
1602
|
+
after = after.replace(/^\n{1,2}/, "");
|
|
1603
|
+
const before = text.slice(0, start);
|
|
1604
|
+
return before.endsWith(`
|
|
1605
|
+
|
|
1606
|
+
`) ? `${before.slice(0, -1)}${after}` : before + after;
|
|
1607
|
+
}
|
|
1608
|
+
function hasBlock(host, text) {
|
|
1609
|
+
const markers = rulesMarkers(host);
|
|
1610
|
+
return text.includes(markers.begin) && text.includes(markers.end);
|
|
1611
|
+
}
|
|
1612
|
+
function rulesCodec(host) {
|
|
1613
|
+
return {
|
|
1614
|
+
format: "rules",
|
|
1615
|
+
load: (file) => existsSync2(file) ? { exists: true, text: readFileSync2(file, "utf8"), value: {}, lossy: false } : { exists: false, text: "", value: {}, lossy: false },
|
|
1616
|
+
apply: (text, edit2) => {
|
|
1617
|
+
if (edit2.format !== "rules")
|
|
1618
|
+
throw new Error(`rules codec cannot apply a ${edit2.format} edit`);
|
|
1619
|
+
return { text: upsertBlock(host, text, edit2.block), recorded: [], createdParents: [] };
|
|
1620
|
+
},
|
|
1621
|
+
verify: (text) => hasBlock(host, text),
|
|
1622
|
+
revert: (text) => ({ text: removeBlock(host, text), notes: [] }),
|
|
1623
|
+
isEffectivelyEmpty: (text) => text.trim().length === 0
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
var init_rules = () => {};
|
|
1627
|
+
|
|
1628
|
+
// node_modules/smol-toml/dist/error.js
|
|
1629
|
+
function getLineColFromPtr(string2, ptr) {
|
|
1630
|
+
let lines = string2.slice(0, ptr).split(/\r?\n/);
|
|
1631
|
+
return [lines.length, lines.pop().length + 1];
|
|
1632
|
+
}
|
|
1633
|
+
function makeCodeBlock(string2, line, column) {
|
|
1634
|
+
let lines = string2.split(/\r?\n/);
|
|
1635
|
+
let codeblock = "";
|
|
1636
|
+
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
1637
|
+
for (let i = line - 1;i <= line + 1; i++) {
|
|
1638
|
+
let l = lines[i - 1];
|
|
1639
|
+
if (!l)
|
|
1640
|
+
continue;
|
|
1641
|
+
codeblock += i.toString().padEnd(numberLen, " ");
|
|
1642
|
+
codeblock += ": ";
|
|
1643
|
+
codeblock += l;
|
|
1644
|
+
codeblock += `
|
|
1645
|
+
`;
|
|
1646
|
+
if (i === line) {
|
|
1647
|
+
codeblock += " ".repeat(numberLen + column + 2);
|
|
1648
|
+
codeblock += `^
|
|
1649
|
+
`;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
return codeblock;
|
|
1653
|
+
}
|
|
1654
|
+
var TomlError;
|
|
1655
|
+
var init_error = __esm(() => {
|
|
1656
|
+
/*!
|
|
1657
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
1658
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
1659
|
+
*
|
|
1660
|
+
* Redistribution and use in source and binary forms, with or without
|
|
1661
|
+
* modification, are permitted provided that the following conditions are met:
|
|
1662
|
+
*
|
|
1663
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
1664
|
+
* list of conditions and the following disclaimer.
|
|
1665
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
1666
|
+
* this list of conditions and the following disclaimer in the
|
|
1667
|
+
* documentation and/or other materials provided with the distribution.
|
|
1668
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
1669
|
+
* may be used to endorse or promote products derived from this software without
|
|
1670
|
+
* specific prior written permission.
|
|
1671
|
+
*
|
|
1672
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
1673
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
1674
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
1675
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
1676
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
1677
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
1678
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
1679
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
1680
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1681
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1682
|
+
*/
|
|
1683
|
+
TomlError = class TomlError extends Error {
|
|
1684
|
+
line;
|
|
1685
|
+
column;
|
|
1686
|
+
codeblock;
|
|
1687
|
+
constructor(message, options) {
|
|
1688
|
+
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
|
1689
|
+
const codeblock = makeCodeBlock(options.toml, line, column);
|
|
1690
|
+
super(`Invalid TOML document: ${message}
|
|
1691
|
+
|
|
1692
|
+
${codeblock}`, options);
|
|
1693
|
+
this.line = line;
|
|
1694
|
+
this.column = column;
|
|
1695
|
+
this.codeblock = codeblock;
|
|
1696
|
+
}
|
|
1697
|
+
static x(message, ctx, ptr) {
|
|
1698
|
+
throw new TomlError(message, { toml: ctx.s, ptr: ptr ?? ctx.p });
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1701
|
+
});
|
|
1702
|
+
|
|
1703
|
+
// node_modules/smol-toml/dist/primitive.js
|
|
1704
|
+
function parseString(ctx) {
|
|
1705
|
+
let startPtr = ctx.p;
|
|
1706
|
+
let c = ctx.s.charCodeAt(ctx.p++);
|
|
1707
|
+
let first = c;
|
|
1708
|
+
let isLiteral = c === 39;
|
|
1709
|
+
let isMultiline = c === ctx.s.charCodeAt(ctx.p) && c === ctx.s.charCodeAt(ctx.p + 1);
|
|
1710
|
+
if (isMultiline) {
|
|
1711
|
+
if ((c = ctx.s.charCodeAt(ctx.p += 2)) === 10)
|
|
1712
|
+
ctx.p++;
|
|
1713
|
+
else if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)
|
|
1714
|
+
ctx.p += 2;
|
|
1715
|
+
}
|
|
1716
|
+
let parsed = "";
|
|
1717
|
+
let sliceStart = ctx.p;
|
|
1718
|
+
let state = 0;
|
|
1719
|
+
for (;ctx.p < ctx.s.length; ctx.p++) {
|
|
1720
|
+
c = ctx.s.charCodeAt(ctx.p);
|
|
1721
|
+
if (isMultiline && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)) {
|
|
1722
|
+
state = state && 3;
|
|
1723
|
+
} else if (c < 32 && c !== 9 || c === 127) {
|
|
1724
|
+
TomlError.x("control characters are not allowed in strings", ctx);
|
|
1725
|
+
} else if ((!state || state === 3) && c === first && (!isMultiline || ctx.s.charCodeAt(ctx.p + 1) === first && ctx.s.charCodeAt(ctx.p + 2) === first)) {
|
|
1726
|
+
if (isMultiline) {
|
|
1727
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first)
|
|
1728
|
+
ctx.p++;
|
|
1729
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first)
|
|
1730
|
+
ctx.p++;
|
|
1731
|
+
}
|
|
1732
|
+
if (!state) {
|
|
1733
|
+
let s = ctx.s.slice(sliceStart, ctx.p);
|
|
1734
|
+
parsed = parsed ? parsed + s : s;
|
|
1735
|
+
}
|
|
1736
|
+
ctx.p += isMultiline ? 3 : 1;
|
|
1737
|
+
return parsed;
|
|
1738
|
+
} else if (!state) {
|
|
1739
|
+
if (!isLiteral && c === 92) {
|
|
1740
|
+
parsed += ctx.s.slice(sliceStart, sliceStart = ctx.p);
|
|
1741
|
+
state = 1;
|
|
1742
|
+
}
|
|
1743
|
+
} else if (state === 1) {
|
|
1744
|
+
if (c === 120 || c === 117 || c === 85) {
|
|
1745
|
+
let errPtr = ctx.p++ - 1;
|
|
1746
|
+
let value = 0;
|
|
1747
|
+
let len = c === 120 ? 2 : c === 117 ? 4 : 8;
|
|
1748
|
+
for (let j = 0;j < len; j++, ctx.p++) {
|
|
1749
|
+
let hex = ctx.s.charCodeAt(ctx.p);
|
|
1750
|
+
let digit = hex >= 48 && hex <= 57 ? hex - 48 : hex >= 65 && hex <= 70 ? hex - 65 + 10 : hex >= 97 && hex <= 102 ? hex - 97 + 10 : -1;
|
|
1751
|
+
if (digit < 0)
|
|
1752
|
+
TomlError.x("invalid non-hex character in unicode escape", ctx);
|
|
1753
|
+
value = value << 4 | digit;
|
|
1754
|
+
}
|
|
1755
|
+
if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
|
|
1756
|
+
TomlError.x("invalid unicode escape", ctx, errPtr);
|
|
1757
|
+
}
|
|
1758
|
+
parsed += String.fromCodePoint(value);
|
|
1759
|
+
sliceStart = ctx.p--;
|
|
1760
|
+
state = 0;
|
|
1761
|
+
} else if (isMultiline && (c === 32 || c === 9)) {
|
|
1762
|
+
state = 2;
|
|
1763
|
+
} else {
|
|
1764
|
+
if (c === 98)
|
|
1765
|
+
parsed += "\b";
|
|
1766
|
+
else if (c === 116)
|
|
1767
|
+
parsed += "\t";
|
|
1768
|
+
else if (c === 110)
|
|
1769
|
+
parsed += `
|
|
1770
|
+
`;
|
|
1771
|
+
else if (c === 102)
|
|
1772
|
+
parsed += "\f";
|
|
1773
|
+
else if (c === 114)
|
|
1774
|
+
parsed += "\r";
|
|
1775
|
+
else if (c === 101)
|
|
1776
|
+
parsed += "\x1B";
|
|
1777
|
+
else if (c === 34)
|
|
1778
|
+
parsed += '"';
|
|
1779
|
+
else if (c === 92)
|
|
1780
|
+
parsed += "\\";
|
|
1781
|
+
else
|
|
1782
|
+
TomlError.x("unrecognised escape sequence", ctx);
|
|
1783
|
+
sliceStart = ctx.p + 1;
|
|
1784
|
+
state = 0;
|
|
1785
|
+
}
|
|
1786
|
+
} else if (c !== 32 && c !== 9) {
|
|
1787
|
+
if (state === 2)
|
|
1788
|
+
TomlError.x("invalid escape: only line-ending whitespace may be escaped", ctx, sliceStart);
|
|
1789
|
+
state = !isLiteral && c === 92 ? 1 : 0;
|
|
1790
|
+
sliceStart = ctx.p;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
TomlError.x("unfinished string", ctx, startPtr);
|
|
1794
|
+
}
|
|
1795
|
+
var init_primitive = __esm(() => {
|
|
1796
|
+
init_error();
|
|
1797
|
+
/*!
|
|
1798
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
1799
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
1800
|
+
*
|
|
1801
|
+
* Redistribution and use in source and binary forms, with or without
|
|
1802
|
+
* modification, are permitted provided that the following conditions are met:
|
|
1803
|
+
*
|
|
1804
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
1805
|
+
* list of conditions and the following disclaimer.
|
|
1806
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
1807
|
+
* this list of conditions and the following disclaimer in the
|
|
1808
|
+
* documentation and/or other materials provided with the distribution.
|
|
1809
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
1810
|
+
* may be used to endorse or promote products derived from this software without
|
|
1811
|
+
* specific prior written permission.
|
|
1812
|
+
*
|
|
1813
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
1814
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
1815
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
1816
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
1817
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
1818
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
1819
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
1820
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
1821
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1822
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1823
|
+
*/
|
|
1824
|
+
});
|
|
1825
|
+
|
|
1826
|
+
// node_modules/smol-toml/dist/date.js
|
|
1827
|
+
var DATE_TIME_RE, TomlDate;
|
|
1828
|
+
var init_date = __esm(() => {
|
|
1829
|
+
/*!
|
|
1830
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
1831
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
1832
|
+
*
|
|
1833
|
+
* Redistribution and use in source and binary forms, with or without
|
|
1834
|
+
* modification, are permitted provided that the following conditions are met:
|
|
1835
|
+
*
|
|
1836
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
1837
|
+
* list of conditions and the following disclaimer.
|
|
1838
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
1839
|
+
* this list of conditions and the following disclaimer in the
|
|
1840
|
+
* documentation and/or other materials provided with the distribution.
|
|
1841
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
1842
|
+
* may be used to endorse or promote products derived from this software without
|
|
1843
|
+
* specific prior written permission.
|
|
1844
|
+
*
|
|
1845
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
1846
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
1847
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
1848
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
1849
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
1850
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
1851
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
1852
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
1853
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1854
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1855
|
+
*/
|
|
1856
|
+
DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i;
|
|
1857
|
+
TomlDate = class TomlDate extends Date {
|
|
1858
|
+
#hasDate = false;
|
|
1859
|
+
#hasTime = false;
|
|
1860
|
+
#offset = null;
|
|
1861
|
+
constructor(date, fasttype, unsafeDelim) {
|
|
1862
|
+
let hasDate = true;
|
|
1863
|
+
let hasTime = true;
|
|
1864
|
+
let offset = "Z";
|
|
1865
|
+
let c;
|
|
1866
|
+
if (typeof date === "string") {
|
|
1867
|
+
if (fasttype)
|
|
1868
|
+
prep: {
|
|
1869
|
+
if (fasttype < 3) {
|
|
1870
|
+
if (+date.slice(11, 13) > 23) {
|
|
1871
|
+
date = "";
|
|
1872
|
+
break prep;
|
|
1873
|
+
}
|
|
1874
|
+
if (fasttype === 2) {
|
|
1875
|
+
offset = null;
|
|
1876
|
+
date += "Z";
|
|
1877
|
+
} else if ((c = date.charCodeAt(date.length - 1)) !== 90 && c !== 122) {
|
|
1878
|
+
offset = date.slice(date.length - 6);
|
|
1879
|
+
}
|
|
1880
|
+
if (unsafeDelim)
|
|
1881
|
+
date = date.slice(0, 10) + "T" + date.slice(11);
|
|
1882
|
+
} else if (fasttype === 4) {
|
|
1883
|
+
date = +date.slice(0, 2) > 23 ? "" : `0000-01-01T${date}Z`;
|
|
1884
|
+
}
|
|
1885
|
+
hasDate = fasttype !== 4;
|
|
1886
|
+
hasTime = fasttype !== 3;
|
|
1887
|
+
}
|
|
1888
|
+
else {
|
|
1889
|
+
let match = date.match(DATE_TIME_RE);
|
|
1890
|
+
if (match) {
|
|
1891
|
+
if (!match[1]) {
|
|
1892
|
+
hasDate = false;
|
|
1893
|
+
date = `0000-01-01T${date}`;
|
|
1894
|
+
}
|
|
1895
|
+
hasTime = !!match[2];
|
|
1896
|
+
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
1897
|
+
if (match[2] && +match[2] > 23) {
|
|
1898
|
+
date = "";
|
|
1899
|
+
} else {
|
|
1900
|
+
offset = match[3] || null;
|
|
1901
|
+
if (!offset && hasTime)
|
|
1902
|
+
date += "Z";
|
|
1903
|
+
}
|
|
1904
|
+
} else {
|
|
1905
|
+
date = "";
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
super(date);
|
|
1910
|
+
if (!isNaN(this.getTime())) {
|
|
1911
|
+
this.#hasDate = hasDate;
|
|
1912
|
+
this.#hasTime = hasTime;
|
|
1913
|
+
this.#offset = offset;
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
isDateTime() {
|
|
1917
|
+
return this.#hasDate && this.#hasTime;
|
|
1918
|
+
}
|
|
1919
|
+
isLocal() {
|
|
1920
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
1921
|
+
}
|
|
1922
|
+
isDate() {
|
|
1923
|
+
return this.#hasDate && !this.#hasTime;
|
|
1924
|
+
}
|
|
1925
|
+
isTime() {
|
|
1926
|
+
return this.#hasTime && !this.#hasDate;
|
|
1927
|
+
}
|
|
1928
|
+
isValid() {
|
|
1929
|
+
return this.#hasDate || this.#hasTime;
|
|
1930
|
+
}
|
|
1931
|
+
toISOString() {
|
|
1932
|
+
let iso = super.toISOString();
|
|
1933
|
+
if (this.isDate())
|
|
1934
|
+
return iso.slice(0, 10);
|
|
1935
|
+
if (this.isTime())
|
|
1936
|
+
return iso.slice(11, 23);
|
|
1937
|
+
if (this.#offset === null)
|
|
1938
|
+
return iso.slice(0, -1);
|
|
1939
|
+
if (this.#offset === "Z" || this.#offset === "z")
|
|
1940
|
+
return iso;
|
|
1941
|
+
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
1942
|
+
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
1943
|
+
let offsetDate = new Date(this.getTime() - offset * 60000);
|
|
1944
|
+
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
1945
|
+
}
|
|
1946
|
+
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
1947
|
+
let date = new TomlDate(jsDate);
|
|
1948
|
+
date.#offset = offset;
|
|
1949
|
+
return date;
|
|
1950
|
+
}
|
|
1951
|
+
static wrapAsLocalDateTime(jsDate) {
|
|
1952
|
+
let date = new TomlDate(jsDate);
|
|
1953
|
+
date.#offset = null;
|
|
1954
|
+
return date;
|
|
1955
|
+
}
|
|
1956
|
+
static wrapAsLocalDate(jsDate) {
|
|
1957
|
+
let date = new TomlDate(jsDate);
|
|
1958
|
+
date.#hasTime = false;
|
|
1959
|
+
date.#offset = null;
|
|
1960
|
+
return date;
|
|
1961
|
+
}
|
|
1962
|
+
static wrapAsLocalTime(jsDate) {
|
|
1963
|
+
let date = new TomlDate(jsDate);
|
|
1964
|
+
date.#hasDate = false;
|
|
1965
|
+
date.#offset = null;
|
|
1966
|
+
return date;
|
|
1967
|
+
}
|
|
1968
|
+
};
|
|
1969
|
+
});
|
|
1970
|
+
|
|
1971
|
+
// node_modules/smol-toml/dist/extract.js
|
|
1972
|
+
function isDigit2(char, base = 10) {
|
|
1973
|
+
return base === 16 ? char > 47 && char < 58 || char > 64 && char < 71 || char > 96 && char < 103 : char > 47 && char < 48 + base;
|
|
1974
|
+
}
|
|
1975
|
+
function isEndOfValue(char, delim) {
|
|
1976
|
+
return char === 32 || char === 9 || char === 10 || char === 13 || delim && (char === delim || char === 44) || char === 35;
|
|
1977
|
+
}
|
|
1978
|
+
function extractValue(ctx, end) {
|
|
1979
|
+
let errPtr = ctx.p;
|
|
1980
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
1981
|
+
if (c === 91 || c === 123) {
|
|
1982
|
+
ctx.d-- || TomlError.x("document contains excessively nested structures. aborting.", ctx);
|
|
1983
|
+
let value = c === 91 ? parseArray(ctx) : parseInlineTable(ctx);
|
|
1984
|
+
ctx.d++;
|
|
1985
|
+
return value;
|
|
1986
|
+
}
|
|
1987
|
+
if (c === 34 || c === 39) {
|
|
1988
|
+
return parseString(ctx);
|
|
1989
|
+
}
|
|
1990
|
+
if (c === 116) {
|
|
1991
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 114 || ctx.s.charCodeAt(++ctx.p) !== 117 || ctx.s.charCodeAt(++ctx.p) !== 101)
|
|
1992
|
+
TomlError.x("invalid value", ctx, errPtr);
|
|
1993
|
+
return ctx.p++, true;
|
|
1994
|
+
}
|
|
1995
|
+
if (c === 102) {
|
|
1996
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 108 || ctx.s.charCodeAt(++ctx.p) !== 115 || ctx.s.charCodeAt(++ctx.p) !== 101)
|
|
1997
|
+
TomlError.x("invalid value", ctx, errPtr);
|
|
1998
|
+
return ctx.p++, false;
|
|
1999
|
+
}
|
|
2000
|
+
if (c === 43 || c === 45) {
|
|
2001
|
+
return parseNumber(ctx, ctx.p, ctx.s.charCodeAt(++ctx.p), 44 - c, end);
|
|
2002
|
+
}
|
|
2003
|
+
if (ctx.s.charCodeAt(ctx.p + 4) === 45 && ctx.s.charCodeAt(ctx.p + 7) === 45) {
|
|
2004
|
+
return parseDate(ctx, c, end);
|
|
2005
|
+
}
|
|
2006
|
+
if (ctx.s.charCodeAt(ctx.p + 2) === 58) {
|
|
2007
|
+
return parseTime(ctx, c, end);
|
|
2008
|
+
}
|
|
2009
|
+
return parseNumber(ctx, ctx.p, c, 0, end);
|
|
2010
|
+
}
|
|
2011
|
+
function parseNumber(ctx, startPtr, startChr, sign, endChr) {
|
|
2012
|
+
let c = startChr;
|
|
2013
|
+
let state = 0;
|
|
2014
|
+
let hasUnderscores = false;
|
|
2015
|
+
if (c === 105) {
|
|
2016
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 110 || ctx.s.charCodeAt(++ctx.p) !== 102)
|
|
2017
|
+
TomlError.x("invalid value", ctx, startPtr);
|
|
2018
|
+
return ctx.p++, (sign || 1) / 0;
|
|
2019
|
+
}
|
|
2020
|
+
if (c === 110) {
|
|
2021
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 110)
|
|
2022
|
+
TomlError.x("invalid value", ctx, startPtr);
|
|
2023
|
+
return ctx.p++, NaN;
|
|
2024
|
+
}
|
|
2025
|
+
if (c === 48) {
|
|
2026
|
+
if (++ctx.p >= ctx.s.length || isEndOfValue(c = ctx.s.charCodeAt(ctx.p), endChr))
|
|
2027
|
+
return ctx.bi === true ? 0n : 0;
|
|
2028
|
+
if (!sign) {
|
|
2029
|
+
if (c === 120)
|
|
2030
|
+
return parseIntegerBaseN(ctx, startPtr, 16, endChr);
|
|
2031
|
+
else if (c === 98)
|
|
2032
|
+
return parseIntegerBaseN(ctx, startPtr, 2, endChr);
|
|
2033
|
+
else if (c === 111)
|
|
2034
|
+
return parseIntegerBaseN(ctx, startPtr, 8, endChr);
|
|
2035
|
+
}
|
|
2036
|
+
if (c === 46)
|
|
2037
|
+
state = 2;
|
|
2038
|
+
else if (c === 101 || c === 69)
|
|
2039
|
+
state = 4;
|
|
2040
|
+
else
|
|
2041
|
+
TomlError.x("illegal leading zero", ctx, startPtr);
|
|
2042
|
+
} else if (!isDigit2(c))
|
|
2043
|
+
TomlError.x("invalid value", ctx, startPtr);
|
|
2044
|
+
while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
|
|
2045
|
+
if (!state)
|
|
2046
|
+
state = 1;
|
|
2047
|
+
if (c === 95) {
|
|
2048
|
+
if (!(state & 1))
|
|
2049
|
+
TomlError.x("illegal underscore", ctx);
|
|
2050
|
+
state += 11;
|
|
2051
|
+
hasUnderscores = true;
|
|
2052
|
+
} else if (state === 1 && c === 46)
|
|
2053
|
+
state = 2;
|
|
2054
|
+
else if ((state === 1 || state === 3) && (c === 101 || c === 69))
|
|
2055
|
+
state = 4;
|
|
2056
|
+
else if (state === 4 && (c === 43 || c === 45)) {
|
|
2057
|
+
state = 6;
|
|
2058
|
+
} else if (!isDigit2(c))
|
|
2059
|
+
TomlError.x(`illegal character in numeric literal`, ctx);
|
|
2060
|
+
else if (state > 9)
|
|
2061
|
+
state -= 11;
|
|
2062
|
+
else if (!(state & 1))
|
|
2063
|
+
state++;
|
|
2064
|
+
}
|
|
2065
|
+
if (!state) {
|
|
2066
|
+
let val = (startChr - 48) * (sign || 1);
|
|
2067
|
+
return ctx.bi === true ? BigInt(val) : val;
|
|
2068
|
+
}
|
|
2069
|
+
if (!(state & 1))
|
|
2070
|
+
TomlError.x("unfinished numeric value", ctx, startPtr);
|
|
2071
|
+
let str = ctx.s.slice(startPtr, ctx.p);
|
|
2072
|
+
if (hasUnderscores)
|
|
2073
|
+
str = str.replaceAll("_", "");
|
|
2074
|
+
return state > 1 ? parseFloat(str) : parseInteger(ctx, str, 10, startPtr);
|
|
2075
|
+
}
|
|
2076
|
+
function parseIntegerBaseN(ctx, startPtr, base, endChr) {
|
|
2077
|
+
let c, underscore = 1;
|
|
2078
|
+
while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
|
|
2079
|
+
if (c === 95) {
|
|
2080
|
+
if (underscore & 1)
|
|
2081
|
+
TomlError.x("illegal underscore", ctx);
|
|
2082
|
+
underscore = 3;
|
|
2083
|
+
} else if (!isDigit2(c, base))
|
|
2084
|
+
TomlError.x(`illegal character in numeric literal`, ctx);
|
|
2085
|
+
else if (underscore & 1)
|
|
2086
|
+
underscore--;
|
|
2087
|
+
}
|
|
2088
|
+
if (underscore & 1)
|
|
2089
|
+
TomlError.x("unfinished numeric value", ctx);
|
|
2090
|
+
let str = ctx.s.slice(startPtr + 2, ctx.p);
|
|
2091
|
+
if (underscore)
|
|
2092
|
+
str = str.replaceAll("_", "");
|
|
2093
|
+
return parseInteger(ctx, str, base, startPtr);
|
|
2094
|
+
}
|
|
2095
|
+
function parseInteger(ctx, str, base, startPtr) {
|
|
2096
|
+
if (ctx.bi !== true)
|
|
2097
|
+
int: {
|
|
2098
|
+
let val = parseInt(str, base);
|
|
2099
|
+
if (!Number.isSafeInteger(val)) {
|
|
2100
|
+
if (ctx.bi)
|
|
2101
|
+
break int;
|
|
2102
|
+
TomlError.x("integer value cannot be represented losslessly", ctx, startPtr);
|
|
2103
|
+
}
|
|
2104
|
+
return val;
|
|
2105
|
+
}
|
|
2106
|
+
return base === 10 ? BigInt(str) : BigInt((base === 2 ? "0b" : base === 8 ? "0o" : "0x") + str);
|
|
2107
|
+
}
|
|
2108
|
+
function parseDate(ctx, c, endChr) {
|
|
2109
|
+
let startPtr = ctx.p++, unsafeSeparator;
|
|
2110
|
+
if (!isDigit2(c) || !isDigit2(ctx.s.charCodeAt(ctx.p++)) || !isDigit2(ctx.s.charCodeAt(ctx.p++)) || !isDigit2(ctx.s.charCodeAt(ctx.p++))) {
|
|
2111
|
+
return parseNumber(ctx, ctx.p = startPtr, c, 0, endChr);
|
|
2112
|
+
}
|
|
2113
|
+
ctx.p += 5;
|
|
2114
|
+
if (!isDigit2(ctx.s.charCodeAt(ctx.p++)))
|
|
2115
|
+
TomlError.x("invalid date-time: date part is malformed", ctx, startPtr);
|
|
2116
|
+
if (ctx.p >= ctx.s.length || ((c = ctx.s.charCodeAt(ctx.p)) !== 32 || (unsafeSeparator = true, !isDigit2(ctx.s.charCodeAt(ctx.p + 1)))) && c !== 84 && c !== 116) {
|
|
2117
|
+
let t2 = ctx.s.slice(startPtr, ctx.p);
|
|
2118
|
+
return readDate(ctx, t2, 3, false, startPtr);
|
|
2119
|
+
}
|
|
2120
|
+
if (ctx.s.charCodeAt(ctx.p += 3) !== 58)
|
|
2121
|
+
TomlError.x("invalid date-time: time part is malformed", ctx, startPtr);
|
|
2122
|
+
if (ctx.s.charCodeAt(ctx.p += 3) === 58)
|
|
2123
|
+
ctx.p += 3;
|
|
2124
|
+
if (ctx.s.charCodeAt(ctx.p) === 46)
|
|
2125
|
+
while (isDigit2(ctx.s.charCodeAt(++ctx.p)))
|
|
2126
|
+
;
|
|
2127
|
+
if (c = ctx.s.charCodeAt(ctx.p)) {
|
|
2128
|
+
if (c === 90 || c === 122) {
|
|
2129
|
+
let t2 = ctx.s.slice(startPtr, ++ctx.p);
|
|
2130
|
+
return readDate(ctx, t2, 1, unsafeSeparator, startPtr, "[+00:00]");
|
|
2131
|
+
}
|
|
2132
|
+
if (c === 43 || c === 45) {
|
|
2133
|
+
let t2 = ctx.s.slice(startPtr, ctx.p += 6);
|
|
2134
|
+
return readDate(ctx, t2, 1, unsafeSeparator, startPtr, !ctx.ld && "[" + ctx.s.slice(ctx.p - 6, ctx.p) + "]");
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
let t = ctx.s.slice(startPtr, ctx.p);
|
|
2138
|
+
return readDate(ctx, t, 2, unsafeSeparator, startPtr);
|
|
2139
|
+
}
|
|
2140
|
+
function parseTime(ctx, c, endChr) {
|
|
2141
|
+
let start = ctx.p;
|
|
2142
|
+
if (!isDigit2(c) || !isDigit2(ctx.s.charCodeAt(++ctx.p))) {
|
|
2143
|
+
return parseNumber(ctx, --ctx.p, c, 0, endChr);
|
|
2144
|
+
}
|
|
2145
|
+
if (ctx.s.charCodeAt(ctx.p += 4) === 58)
|
|
2146
|
+
ctx.p += 3;
|
|
2147
|
+
if (ctx.s.charCodeAt(ctx.p) === 46)
|
|
2148
|
+
while (isDigit2(ctx.s.charCodeAt(++ctx.p)))
|
|
2149
|
+
;
|
|
2150
|
+
let t = ctx.s.slice(start, ctx.p);
|
|
2151
|
+
return readDate(ctx, t, 4, false, start);
|
|
2152
|
+
}
|
|
2153
|
+
function readDate(ctx, str, type, unsafeDelim, errPtr, temporalSuffix) {
|
|
2154
|
+
if (ctx.ld) {
|
|
2155
|
+
let date = new TomlDate(str, type, unsafeDelim);
|
|
2156
|
+
if (!date.isValid())
|
|
2157
|
+
TomlError.x("invalid date", ctx, errPtr);
|
|
2158
|
+
return date;
|
|
2159
|
+
}
|
|
2160
|
+
try {
|
|
2161
|
+
if (temporalSuffix)
|
|
2162
|
+
str += temporalSuffix;
|
|
2163
|
+
switch (type) {
|
|
2164
|
+
case 1:
|
|
2165
|
+
return Temporal.ZonedDateTime.from(str);
|
|
2166
|
+
case 2:
|
|
2167
|
+
return Temporal.PlainDateTime.from(str);
|
|
2168
|
+
case 3:
|
|
2169
|
+
return Temporal.PlainDate.from(str);
|
|
2170
|
+
case 4:
|
|
2171
|
+
return Temporal.PlainTime.from(str);
|
|
2172
|
+
}
|
|
2173
|
+
} catch (e) {
|
|
2174
|
+
TomlError.x(e instanceof Error ? e.message : "" + e, ctx, errPtr);
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
var init_extract = __esm(() => {
|
|
2178
|
+
init_primitive();
|
|
2179
|
+
init_struct();
|
|
2180
|
+
init_error();
|
|
2181
|
+
init_date();
|
|
2182
|
+
/*!
|
|
2183
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2184
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2185
|
+
*
|
|
2186
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2187
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2188
|
+
*
|
|
2189
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2190
|
+
* list of conditions and the following disclaimer.
|
|
2191
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2192
|
+
* this list of conditions and the following disclaimer in the
|
|
2193
|
+
* documentation and/or other materials provided with the distribution.
|
|
2194
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2195
|
+
* may be used to endorse or promote products derived from this software without
|
|
2196
|
+
* specific prior written permission.
|
|
2197
|
+
*
|
|
2198
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2199
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2200
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2201
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2202
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2203
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2204
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2205
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2206
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2207
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2208
|
+
*/
|
|
2209
|
+
});
|
|
2210
|
+
|
|
2211
|
+
// node_modules/smol-toml/dist/util.js
|
|
2212
|
+
function skipComment(ctx) {
|
|
2213
|
+
for (;ctx.p < ctx.s.length; ctx.p++) {
|
|
2214
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
2215
|
+
if (c === 10)
|
|
2216
|
+
break;
|
|
2217
|
+
if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) {
|
|
2218
|
+
ctx.p++;
|
|
2219
|
+
break;
|
|
2220
|
+
}
|
|
2221
|
+
if (c < 32 && c !== 9 || c === 127) {
|
|
2222
|
+
TomlError.x("control characters are not allowed in comments", ctx);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
function skipVoid(ctx, banNewLines, banComments) {
|
|
2227
|
+
let c;
|
|
2228
|
+
while (ctx.p < ctx.s.length) {
|
|
2229
|
+
while (ctx.p < ctx.s.length && ((c = ctx.s.charCodeAt(ctx.p)) === 32 || c === 9 || !banNewLines && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)))
|
|
2230
|
+
ctx.p++;
|
|
2231
|
+
if (banComments || c !== 35)
|
|
2232
|
+
break;
|
|
2233
|
+
skipComment(ctx);
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
var init_util = __esm(() => {
|
|
2237
|
+
init_error();
|
|
2238
|
+
/*!
|
|
2239
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2240
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2241
|
+
*
|
|
2242
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2243
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2244
|
+
*
|
|
2245
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2246
|
+
* list of conditions and the following disclaimer.
|
|
2247
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2248
|
+
* this list of conditions and the following disclaimer in the
|
|
2249
|
+
* documentation and/or other materials provided with the distribution.
|
|
2250
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2251
|
+
* may be used to endorse or promote products derived from this software without
|
|
2252
|
+
* specific prior written permission.
|
|
2253
|
+
*
|
|
2254
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2255
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2256
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2257
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2258
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2259
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2260
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2261
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2262
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2263
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2264
|
+
*/
|
|
2265
|
+
});
|
|
2266
|
+
|
|
2267
|
+
// node_modules/smol-toml/dist/struct.js
|
|
2268
|
+
function parseKey(ctx, end = 61) {
|
|
2269
|
+
let startPtr;
|
|
2270
|
+
let state = 0;
|
|
2271
|
+
let parsed = [];
|
|
2272
|
+
let sliceStart;
|
|
2273
|
+
let c = ctx.s.charCodeAt(startPtr = ctx.p);
|
|
2274
|
+
do {
|
|
2275
|
+
if (c === end) {
|
|
2276
|
+
if (!state)
|
|
2277
|
+
TomlError.x("unexpected end of key", ctx);
|
|
2278
|
+
if (state === 1)
|
|
2279
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
2280
|
+
return ctx.p++, parsed;
|
|
2281
|
+
} else if (c === 46) {
|
|
2282
|
+
if (!state)
|
|
2283
|
+
TomlError.x("illegal empty bare key", ctx);
|
|
2284
|
+
if (state === 1)
|
|
2285
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
2286
|
+
state = 0;
|
|
2287
|
+
} else if (!state && (c === 34 || c === 39)) {
|
|
2288
|
+
if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2))
|
|
2289
|
+
TomlError.x("illegal quoted key: multiline strings are not allowed", ctx);
|
|
2290
|
+
parsed.push(parseString(ctx));
|
|
2291
|
+
state = 2;
|
|
2292
|
+
ctx.p--;
|
|
2293
|
+
} else if (c === 32 || c === 9) {
|
|
2294
|
+
if (state === 1) {
|
|
2295
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
2296
|
+
state = 2;
|
|
2297
|
+
}
|
|
2298
|
+
} else if (state === 2 || c < 48 && c !== 45 || c > 57 && c < 65 || c > 90 && c < 97 && c !== 95 || c > 122) {
|
|
2299
|
+
TomlError.x("illegal character in key", ctx);
|
|
2300
|
+
} else if (!state) {
|
|
2301
|
+
state = 1;
|
|
2302
|
+
sliceStart = ctx.p;
|
|
2303
|
+
}
|
|
2304
|
+
} while (c = ctx.s.charCodeAt(++ctx.p));
|
|
2305
|
+
TomlError.x("incomplete key-value: cannot find end of key", ctx, startPtr);
|
|
2306
|
+
}
|
|
2307
|
+
function parseInlineTable(ctx) {
|
|
2308
|
+
let startPtr = ctx.p++;
|
|
2309
|
+
let res = Object.create(null);
|
|
2310
|
+
let seen = new Set;
|
|
2311
|
+
let c;
|
|
2312
|
+
while (ctx.p < ctx.s.length) {
|
|
2313
|
+
skipVoid(ctx);
|
|
2314
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 125) {
|
|
2315
|
+
ctx.p++;
|
|
2316
|
+
return res;
|
|
2317
|
+
}
|
|
2318
|
+
let k;
|
|
2319
|
+
let t = res;
|
|
2320
|
+
let hasOwn = false;
|
|
2321
|
+
let errPtr = ctx.p;
|
|
2322
|
+
let key = parseKey(ctx);
|
|
2323
|
+
for (let i = 0;i < key.length; i++) {
|
|
2324
|
+
if (i)
|
|
2325
|
+
t = hasOwn ? t[k] : t[k] = Object.create(null);
|
|
2326
|
+
k = key[i];
|
|
2327
|
+
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
|
|
2328
|
+
TomlError.x("trying to redefine an already defined value", ctx, errPtr);
|
|
2329
|
+
}
|
|
2330
|
+
let unsafe = k === "__proto__";
|
|
2331
|
+
if (ctx.uk && (unsafe || k === "constructor")) {
|
|
2332
|
+
t = ctx.uk !== 1 && TomlError.x("document contains an unsafe property", ctx, errPtr);
|
|
2333
|
+
break;
|
|
2334
|
+
}
|
|
2335
|
+
if (!hasOwn && unsafe) {
|
|
2336
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
if (hasOwn) {
|
|
2340
|
+
TomlError.x("trying to redefine an already defined value", ctx, errPtr);
|
|
2341
|
+
}
|
|
2342
|
+
skipVoid(ctx, true, true);
|
|
2343
|
+
let value = extractValue(ctx, 125);
|
|
2344
|
+
if (t && typeof (t[k] = value) === "object")
|
|
2345
|
+
seen.add(value);
|
|
2346
|
+
skipVoid(ctx);
|
|
2347
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 125) {
|
|
2348
|
+
return res;
|
|
2349
|
+
}
|
|
2350
|
+
if (c !== 44)
|
|
2351
|
+
TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
|
|
2352
|
+
}
|
|
2353
|
+
TomlError.x("unfinished table", ctx, startPtr);
|
|
2354
|
+
}
|
|
2355
|
+
function parseArray(ctx) {
|
|
2356
|
+
let startPtr = ctx.p++;
|
|
2357
|
+
let res = [];
|
|
2358
|
+
let c;
|
|
2359
|
+
while (ctx.p < ctx.s.length) {
|
|
2360
|
+
skipVoid(ctx);
|
|
2361
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 93) {
|
|
2362
|
+
ctx.p++;
|
|
2363
|
+
return res;
|
|
2364
|
+
}
|
|
2365
|
+
res.push(extractValue(ctx, 93));
|
|
2366
|
+
skipVoid(ctx);
|
|
2367
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 93) {
|
|
2368
|
+
return res;
|
|
2369
|
+
}
|
|
2370
|
+
if (c !== 44)
|
|
2371
|
+
TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
|
|
2372
|
+
}
|
|
2373
|
+
TomlError.x("unfinished array", ctx, startPtr);
|
|
2374
|
+
}
|
|
2375
|
+
var init_struct = __esm(() => {
|
|
2376
|
+
init_primitive();
|
|
2377
|
+
init_extract();
|
|
2378
|
+
init_util();
|
|
2379
|
+
init_error();
|
|
2380
|
+
/*!
|
|
2381
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2382
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2383
|
+
*
|
|
2384
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2385
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2386
|
+
*
|
|
2387
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2388
|
+
* list of conditions and the following disclaimer.
|
|
2389
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2390
|
+
* this list of conditions and the following disclaimer in the
|
|
2391
|
+
* documentation and/or other materials provided with the distribution.
|
|
2392
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2393
|
+
* may be used to endorse or promote products derived from this software without
|
|
2394
|
+
* specific prior written permission.
|
|
2395
|
+
*
|
|
2396
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2397
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2398
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2399
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2400
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2401
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2402
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2403
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2404
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2405
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2406
|
+
*/
|
|
2407
|
+
});
|
|
2408
|
+
|
|
2409
|
+
// node_modules/smol-toml/dist/parse.js
|
|
2410
|
+
function peekTable(ctx, key, table, meta, type) {
|
|
2411
|
+
let t = table;
|
|
2412
|
+
let m = meta;
|
|
2413
|
+
let k;
|
|
2414
|
+
let hasOwn = false;
|
|
2415
|
+
let state;
|
|
2416
|
+
for (let i = 0;i < key.length; i++) {
|
|
2417
|
+
if (i) {
|
|
2418
|
+
t = hasOwn ? t[k] : t[k] = Object.create(null);
|
|
2419
|
+
m = (state = m[k]).c;
|
|
2420
|
+
if (type === 0 && (state.t === 1 || state.t === 2)) {
|
|
2421
|
+
return null;
|
|
2422
|
+
}
|
|
2423
|
+
if (state.t === 2) {
|
|
2424
|
+
let l = t.length - 1;
|
|
2425
|
+
t = t[l];
|
|
2426
|
+
m = m[l].c;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
k = key[i];
|
|
2430
|
+
if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) {
|
|
2431
|
+
return null;
|
|
2432
|
+
}
|
|
2433
|
+
if (!hasOwn) {
|
|
2434
|
+
let unsafe = k === "__proto__";
|
|
2435
|
+
if (ctx.uk && (unsafe || k === "constructor"))
|
|
2436
|
+
return false;
|
|
2437
|
+
if (unsafe) {
|
|
2438
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
2439
|
+
Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
|
|
2440
|
+
}
|
|
2441
|
+
m[k] = {
|
|
2442
|
+
t: i < key.length - 1 && type === 2 ? 3 : type,
|
|
2443
|
+
d: false,
|
|
2444
|
+
i: 0,
|
|
2445
|
+
c: Object.create(null)
|
|
2446
|
+
};
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
state = m[k];
|
|
2450
|
+
if (state.t !== type && !(type === 1 && state.t === 3)) {
|
|
2451
|
+
return null;
|
|
2452
|
+
}
|
|
2453
|
+
if (type === 2) {
|
|
2454
|
+
if (!state.d) {
|
|
2455
|
+
state.d = true;
|
|
2456
|
+
t[k] = [];
|
|
2457
|
+
}
|
|
2458
|
+
t[k].push(t = Object.create(null));
|
|
2459
|
+
state.c[state.i++] = state = { t: 1, d: false, i: 0, c: Object.create(null) };
|
|
2460
|
+
}
|
|
2461
|
+
if (state.d) {
|
|
2462
|
+
return null;
|
|
2463
|
+
}
|
|
2464
|
+
state.d = true;
|
|
2465
|
+
if (type === 1) {
|
|
2466
|
+
t = hasOwn ? t[k] : t[k] = Object.create(null);
|
|
2467
|
+
} else if (type === 0 && hasOwn) {
|
|
2468
|
+
return null;
|
|
2469
|
+
}
|
|
2470
|
+
return [k, t, state.c];
|
|
2471
|
+
}
|
|
2472
|
+
function validateTablePeek(ctx, peek, ptr) {
|
|
2473
|
+
if (peek === null || ctx.uk === 2)
|
|
2474
|
+
TomlError.x(peek === null ? "trying to redefine an already defined table or value" : "document contains an unsafe property", ctx, ptr);
|
|
2475
|
+
}
|
|
2476
|
+
function parse3(toml, options = {}) {
|
|
2477
|
+
let ctx = {
|
|
2478
|
+
s: toml,
|
|
2479
|
+
p: 0,
|
|
2480
|
+
d: options.maxDepth ?? 1000,
|
|
2481
|
+
bi: options.integersAsBigInt ?? false,
|
|
2482
|
+
ld: options.useLegacyDate ?? true,
|
|
2483
|
+
uk: options.unsafeKeyBehaviour === "throw" ? 2 : options.unsafeKeyBehaviour === "drop" ? 1 : 0
|
|
2484
|
+
};
|
|
2485
|
+
let res = Object.create(null);
|
|
2486
|
+
let meta = Object.create(null);
|
|
2487
|
+
let tmp;
|
|
2488
|
+
let skipping = false;
|
|
2489
|
+
let tbl = res;
|
|
2490
|
+
let m = meta;
|
|
2491
|
+
if (toml.charCodeAt(0) === 65279)
|
|
2492
|
+
ctx.p++;
|
|
2493
|
+
skipVoid(ctx);
|
|
2494
|
+
while (ctx.p < toml.length) {
|
|
2495
|
+
if (toml.charCodeAt(ctx.p) === 91) {
|
|
2496
|
+
let isTableArray = toml.charCodeAt(++ctx.p) === 91;
|
|
2497
|
+
tmp = ctx.p += +isTableArray;
|
|
2498
|
+
skipping = false;
|
|
2499
|
+
let k = parseKey(ctx, 93);
|
|
2500
|
+
if (isTableArray) {
|
|
2501
|
+
if (toml.charCodeAt(ctx.p) !== 93) {
|
|
2502
|
+
TomlError.x("expected end of table array declaration", ctx);
|
|
2503
|
+
}
|
|
2504
|
+
ctx.p++;
|
|
2505
|
+
}
|
|
2506
|
+
let p = peekTable(ctx, k, res, meta, isTableArray ? 2 : 1);
|
|
2507
|
+
if (!p) {
|
|
2508
|
+
validateTablePeek(ctx, p, tmp);
|
|
2509
|
+
skipping = true;
|
|
2510
|
+
} else {
|
|
2511
|
+
m = p[2];
|
|
2512
|
+
tbl = p[1];
|
|
2513
|
+
}
|
|
2514
|
+
} else {
|
|
2515
|
+
tmp = ctx.p;
|
|
2516
|
+
let k = parseKey(ctx);
|
|
2517
|
+
let p = peekTable(ctx, k, tbl, m, 0);
|
|
2518
|
+
if (!p && !skipping)
|
|
2519
|
+
validateTablePeek(ctx, p, tmp);
|
|
2520
|
+
skipVoid(ctx, true, true);
|
|
2521
|
+
let v = extractValue(ctx, undefined);
|
|
2522
|
+
if (p && !skipping)
|
|
2523
|
+
p[1][p[0]] = v;
|
|
2524
|
+
}
|
|
2525
|
+
skipVoid(ctx, true);
|
|
2526
|
+
if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 10 && (tmp !== 13 || toml.charCodeAt(ctx.p + 1) !== 10)) {
|
|
2527
|
+
TomlError.x("each key-value declaration must be followed by an end-of-line", ctx);
|
|
2528
|
+
}
|
|
2529
|
+
skipVoid(ctx);
|
|
2530
|
+
}
|
|
2531
|
+
return res;
|
|
2532
|
+
}
|
|
2533
|
+
var init_parse = __esm(() => {
|
|
2534
|
+
init_struct();
|
|
2535
|
+
init_extract();
|
|
2536
|
+
init_util();
|
|
2537
|
+
init_error();
|
|
2538
|
+
/*!
|
|
2539
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2540
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2541
|
+
*
|
|
2542
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2543
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2544
|
+
*
|
|
2545
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2546
|
+
* list of conditions and the following disclaimer.
|
|
2547
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2548
|
+
* this list of conditions and the following disclaimer in the
|
|
2549
|
+
* documentation and/or other materials provided with the distribution.
|
|
2550
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2551
|
+
* may be used to endorse or promote products derived from this software without
|
|
2552
|
+
* specific prior written permission.
|
|
2553
|
+
*
|
|
2554
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2555
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2556
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2557
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2558
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2559
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2560
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2561
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2562
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2563
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2564
|
+
*/
|
|
2565
|
+
});
|
|
2566
|
+
|
|
2567
|
+
// node_modules/smol-toml/dist/stringify.js
|
|
2568
|
+
function extendedTypeOf(obj) {
|
|
2569
|
+
let type = typeof obj;
|
|
2570
|
+
if (type === "object") {
|
|
2571
|
+
if (Array.isArray(obj))
|
|
2572
|
+
return "array";
|
|
2573
|
+
if (typeof obj.getUTCDate === "function" && obj instanceof Date)
|
|
2574
|
+
return "date";
|
|
2575
|
+
if (globalThis.Temporal) {
|
|
2576
|
+
if (obj.until) {
|
|
2577
|
+
if (obj instanceof Temporal.ZonedDateTime)
|
|
2578
|
+
return "temporal/tz+uc";
|
|
2579
|
+
if (obj instanceof Temporal.PlainDateTime || obj instanceof Temporal.PlainDate)
|
|
2580
|
+
return "temporal/uc";
|
|
2581
|
+
if (obj instanceof Temporal.PlainTime || obj instanceof Temporal.Instant)
|
|
2582
|
+
return "temporal";
|
|
2583
|
+
if (obj instanceof Temporal.PlainYearMonth)
|
|
2584
|
+
return "temporal/x";
|
|
2585
|
+
} else if (obj.toPlainDate && obj instanceof Temporal.PlainMonthDay || obj.negated && obj instanceof Temporal.Duration) {
|
|
2586
|
+
return "temporal/x";
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
return type;
|
|
2591
|
+
}
|
|
2592
|
+
function isArrayOfTables(obj) {
|
|
2593
|
+
for (let i = 0;i < obj.length; i++) {
|
|
2594
|
+
if (extendedTypeOf(obj[i]) !== "object")
|
|
2595
|
+
return false;
|
|
2596
|
+
}
|
|
2597
|
+
return obj.length != 0;
|
|
2598
|
+
}
|
|
2599
|
+
function formatWellFormedStringUnchecked(s) {
|
|
2600
|
+
return JSON.stringify(s).replaceAll("", "\\u007f");
|
|
2601
|
+
}
|
|
2602
|
+
function formatString(s) {
|
|
2603
|
+
return formatWellFormedStringUnchecked(HAS_WELLFORMED ? s.toWellFormed() : s);
|
|
2604
|
+
}
|
|
2605
|
+
function formatKey(s) {
|
|
2606
|
+
if (BARE_KEY.test(s))
|
|
2607
|
+
return s;
|
|
2608
|
+
if (HAS_WELLFORMED && !s.isWellFormed())
|
|
2609
|
+
throw new RangeError("key contains illegal lone surrogates");
|
|
2610
|
+
return formatWellFormedStringUnchecked(s);
|
|
2611
|
+
}
|
|
2612
|
+
function stringifyValue(val, type, depth, numberAsFloat, strictTemporal) {
|
|
2613
|
+
if (depth === 0) {
|
|
2614
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
2615
|
+
}
|
|
2616
|
+
switch (type) {
|
|
2617
|
+
case "number":
|
|
2618
|
+
if (isNaN(val))
|
|
2619
|
+
return "nan";
|
|
2620
|
+
if (val === Infinity)
|
|
2621
|
+
return "inf";
|
|
2622
|
+
if (val === -Infinity)
|
|
2623
|
+
return "-inf";
|
|
2624
|
+
if (Number.isInteger(val) && (numberAsFloat || !Number.isSafeInteger(val)))
|
|
2625
|
+
return val.toFixed(1);
|
|
2626
|
+
case "bigint":
|
|
2627
|
+
case "boolean":
|
|
2628
|
+
case "temporal":
|
|
2629
|
+
return val.toString();
|
|
2630
|
+
case "string":
|
|
2631
|
+
return formatString(val);
|
|
2632
|
+
case "date":
|
|
2633
|
+
if (isNaN(val.getTime()))
|
|
2634
|
+
throw new TypeError("cannot serialize invalid date");
|
|
2635
|
+
return val.toISOString();
|
|
2636
|
+
case "object":
|
|
2637
|
+
return stringifyInlineTable(val, depth, numberAsFloat, strictTemporal);
|
|
2638
|
+
case "array":
|
|
2639
|
+
return stringifyArray(val, depth, numberAsFloat, strictTemporal);
|
|
2640
|
+
case "temporal/tz+uc":
|
|
2641
|
+
if (strictTemporal) {
|
|
2642
|
+
let tz = val.timeZoneId;
|
|
2643
|
+
let tzc = tz.charCodeAt(0);
|
|
2644
|
+
if (tzc !== 43 && tzc !== 45 && (tzc !== 85 && tzc !== 71 && tzc !== 90 && tzc !== 69 || tz !== "UTC" && tz !== "UCT" && tz !== "Universal" && tz !== "Zulu" && !tz.startsWith("GMT") && tz !== "Greenwich" && !tz.startsWith("Etc/"))) {
|
|
2645
|
+
throw new TypeError("Temporal objects with an IANA timezone are not allowed in Temporal strict mode");
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
case "temporal/uc":
|
|
2649
|
+
if (strictTemporal && val.calendarId !== "iso8601")
|
|
2650
|
+
throw new TypeError("Temporal objects with a non-default calendar are not allowed in Temporal strict mode");
|
|
2651
|
+
return val.toString({
|
|
2652
|
+
calendarName: "never",
|
|
2653
|
+
timeZoneName: "never"
|
|
2654
|
+
});
|
|
2655
|
+
case "temporal/x":
|
|
2656
|
+
throw new TypeError("Unsupported " + val[Symbol.toStringTag]);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
function stringifyInlineTable(obj, depth, numberAsFloat, strictTemporal) {
|
|
2660
|
+
let keys = Object.keys(obj);
|
|
2661
|
+
if (keys.length === 0)
|
|
2662
|
+
return "{}";
|
|
2663
|
+
let res = "{ ";
|
|
2664
|
+
for (let i = 0;i < keys.length; i++) {
|
|
2665
|
+
let k = keys[i];
|
|
2666
|
+
if (i)
|
|
2667
|
+
res += ", ";
|
|
2668
|
+
res += formatKey(k) + " = " + stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat, strictTemporal);
|
|
2669
|
+
}
|
|
2670
|
+
return res + " }";
|
|
2671
|
+
}
|
|
2672
|
+
function stringifyArray(array2, depth, numberAsFloat, strictTemporal) {
|
|
2673
|
+
if (array2.length === 0)
|
|
2674
|
+
return "[]";
|
|
2675
|
+
let res = "[ ";
|
|
2676
|
+
for (let i = 0;i < array2.length; i++) {
|
|
2677
|
+
if (i)
|
|
2678
|
+
res += ", ";
|
|
2679
|
+
if (array2[i] === null || array2[i] === undefined) {
|
|
2680
|
+
throw new TypeError("arrays cannot contain null or undefined values");
|
|
2681
|
+
}
|
|
2682
|
+
res += stringifyValue(array2[i], extendedTypeOf(array2[i]), depth - 1, numberAsFloat, strictTemporal);
|
|
2683
|
+
}
|
|
2684
|
+
return res + " ]";
|
|
2685
|
+
}
|
|
2686
|
+
function stringifyArrayTable(array2, key, depth, numberAsFloat, strictTemporal) {
|
|
2687
|
+
if (depth === 0) {
|
|
2688
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
2689
|
+
}
|
|
2690
|
+
let res = "";
|
|
2691
|
+
for (let i = 0;i < array2.length; i++) {
|
|
2692
|
+
res += `${res && `
|
|
2693
|
+
`}[[${key}]]
|
|
2694
|
+
`;
|
|
2695
|
+
res += stringifyTable(0, array2[i], key, depth, numberAsFloat, strictTemporal);
|
|
2696
|
+
}
|
|
2697
|
+
return res;
|
|
2698
|
+
}
|
|
2699
|
+
function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat, strictTemporal) {
|
|
2700
|
+
if (depth === 0) {
|
|
2701
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
2702
|
+
}
|
|
2703
|
+
let preamble = "";
|
|
2704
|
+
let tables = "";
|
|
2705
|
+
let keys = Object.keys(obj);
|
|
2706
|
+
for (let i = 0;i < keys.length; i++) {
|
|
2707
|
+
let k = keys[i];
|
|
2708
|
+
if (obj[k] !== null && obj[k] !== undefined) {
|
|
2709
|
+
let type = extendedTypeOf(obj[k]);
|
|
2710
|
+
if (type === "symbol" || type === "function") {
|
|
2711
|
+
throw new TypeError(`cannot serialize values of type '${type}'`);
|
|
2712
|
+
}
|
|
2713
|
+
let key = formatKey(k);
|
|
2714
|
+
if (type === "array" && isArrayOfTables(obj[k])) {
|
|
2715
|
+
tables += (tables && `
|
|
2716
|
+
`) + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat, strictTemporal);
|
|
2717
|
+
} else if (type === "object") {
|
|
2718
|
+
let tblKey = prefix ? `${prefix}.${key}` : key;
|
|
2719
|
+
tables += (tables && `
|
|
2720
|
+
`) + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat, strictTemporal);
|
|
2721
|
+
} else {
|
|
2722
|
+
preamble += key;
|
|
2723
|
+
preamble += " = ";
|
|
2724
|
+
preamble += stringifyValue(obj[k], type, depth, numberAsFloat, strictTemporal);
|
|
2725
|
+
preamble += `
|
|
2726
|
+
`;
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
if (tableKey && (preamble || !tables))
|
|
2731
|
+
preamble = preamble ? `[${tableKey}]
|
|
2732
|
+
${preamble}` : `[${tableKey}]`;
|
|
2733
|
+
return preamble && tables ? `${preamble}
|
|
2734
|
+
${tables}` : preamble || tables;
|
|
2735
|
+
}
|
|
2736
|
+
function stringify(obj, { maxDepth = 1000, numbersAsFloat = false, strictTemporal = false } = {}) {
|
|
2737
|
+
if (extendedTypeOf(obj) !== "object") {
|
|
2738
|
+
throw new TypeError("stringify can only be called with an object");
|
|
2739
|
+
}
|
|
2740
|
+
let str = stringifyTable(0, obj, "", maxDepth, numbersAsFloat, strictTemporal);
|
|
2741
|
+
if (str[str.length - 1] !== `
|
|
2742
|
+
`)
|
|
2743
|
+
return str + `
|
|
2744
|
+
`;
|
|
2745
|
+
return str;
|
|
2746
|
+
}
|
|
2747
|
+
var BARE_KEY, HAS_WELLFORMED;
|
|
2748
|
+
var init_stringify = __esm(() => {
|
|
2749
|
+
/*!
|
|
2750
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2751
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2752
|
+
*
|
|
2753
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2754
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2755
|
+
*
|
|
2756
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2757
|
+
* list of conditions and the following disclaimer.
|
|
2758
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2759
|
+
* this list of conditions and the following disclaimer in the
|
|
2760
|
+
* documentation and/or other materials provided with the distribution.
|
|
2761
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2762
|
+
* may be used to endorse or promote products derived from this software without
|
|
2763
|
+
* specific prior written permission.
|
|
2764
|
+
*
|
|
2765
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2766
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2767
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2768
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2769
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2770
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2771
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2772
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2773
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2774
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2775
|
+
*/
|
|
2776
|
+
BARE_KEY = /^[a-z0-9-_]+$/i;
|
|
2777
|
+
HAS_WELLFORMED = !!"".isWellFormed;
|
|
2778
|
+
});
|
|
2779
|
+
|
|
2780
|
+
// node_modules/smol-toml/dist/index.js
|
|
2781
|
+
var init_dist = __esm(() => {
|
|
2782
|
+
init_parse();
|
|
2783
|
+
init_stringify();
|
|
2784
|
+
init_date();
|
|
2785
|
+
init_error();
|
|
2786
|
+
/*!
|
|
2787
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2788
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2789
|
+
*
|
|
2790
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2791
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2792
|
+
*
|
|
2793
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2794
|
+
* list of conditions and the following disclaimer.
|
|
2795
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2796
|
+
* this list of conditions and the following disclaimer in the
|
|
2797
|
+
* documentation and/or other materials provided with the distribution.
|
|
2798
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2799
|
+
* may be used to endorse or promote products derived from this software without
|
|
2800
|
+
* specific prior written permission.
|
|
2801
|
+
*
|
|
2802
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2803
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2804
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2805
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2806
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2807
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2808
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2809
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2810
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2811
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2812
|
+
*/
|
|
2813
|
+
});
|
|
2814
|
+
|
|
2815
|
+
// src/installer/formats/toml.ts
|
|
2816
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
2817
|
+
function loadToml(file) {
|
|
2818
|
+
if (!existsSync3(file))
|
|
2819
|
+
return { exists: false, text: "", value: {}, lossy: false };
|
|
2820
|
+
const text = readFileSync3(file, "utf8");
|
|
2821
|
+
try {
|
|
2822
|
+
return { exists: true, text, value: parse3(text), lossy: hasTomlComment(text) };
|
|
2823
|
+
} catch (error) {
|
|
2824
|
+
const parseError = error instanceof Error ? error.message : String(error);
|
|
2825
|
+
return { exists: true, text, value: {}, lossy: false, parseError };
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
function hasTomlComment(text) {
|
|
2829
|
+
let inBasic = false;
|
|
2830
|
+
let inLiteral = false;
|
|
2831
|
+
for (let i = 0;i < text.length; i += 1) {
|
|
2832
|
+
const ch = text[i];
|
|
2833
|
+
if (inBasic) {
|
|
2834
|
+
if (ch === "\\")
|
|
2835
|
+
i += 1;
|
|
2836
|
+
else if (ch === '"')
|
|
2837
|
+
inBasic = false;
|
|
2838
|
+
continue;
|
|
2839
|
+
}
|
|
2840
|
+
if (inLiteral) {
|
|
2841
|
+
if (ch === "'")
|
|
2842
|
+
inLiteral = false;
|
|
2843
|
+
continue;
|
|
2844
|
+
}
|
|
2845
|
+
if (ch === '"')
|
|
2846
|
+
inBasic = true;
|
|
2847
|
+
else if (ch === "'")
|
|
2848
|
+
inLiteral = true;
|
|
2849
|
+
else if (ch === "#")
|
|
2850
|
+
return true;
|
|
2851
|
+
}
|
|
2852
|
+
return false;
|
|
2853
|
+
}
|
|
2854
|
+
function serializeToml(value) {
|
|
2855
|
+
return `${stringify(value)}
|
|
2856
|
+
`;
|
|
2857
|
+
}
|
|
2858
|
+
function applyTomlOps(value, ops) {
|
|
2859
|
+
const target = structuredClone(value);
|
|
2860
|
+
const recorded = [];
|
|
2861
|
+
const createdParents = [];
|
|
2862
|
+
for (const op of ops) {
|
|
2863
|
+
const parent = navigate(target, op.path, createdParents);
|
|
2864
|
+
const key = op.path[op.path.length - 1];
|
|
2865
|
+
if (op.op === "set") {
|
|
2866
|
+
const previous = Object.prototype.hasOwnProperty.call(parent, key) ? parent[key] : undefined;
|
|
2867
|
+
parent[key] = structuredClone(op.value);
|
|
2868
|
+
recorded.push({ op: "set", path: op.path, applied: structuredClone(op.value), previous });
|
|
2869
|
+
continue;
|
|
2870
|
+
}
|
|
2871
|
+
const existing = parent[key];
|
|
2872
|
+
if (existing === undefined)
|
|
2873
|
+
createdParents.push(op.path);
|
|
2874
|
+
const { list, appended } = appendEntries(existing, op.entries ?? [], op.path);
|
|
2875
|
+
parent[key] = [...list, ...appended.map((entry) => structuredClone(entry))];
|
|
2876
|
+
recorded.push({ op: "append-array", path: op.path, applied: appended, previous: undefined });
|
|
2877
|
+
}
|
|
2878
|
+
return { value: target, recorded, createdParents };
|
|
2879
|
+
}
|
|
2880
|
+
function navigate(root, path, created) {
|
|
2881
|
+
let node = root;
|
|
2882
|
+
for (let depth = 0;depth < path.length - 1; depth += 1) {
|
|
2883
|
+
const key = path[depth];
|
|
2884
|
+
const next = node[key];
|
|
2885
|
+
if (next === undefined) {
|
|
2886
|
+
node[key] = {};
|
|
2887
|
+
created.push(path.slice(0, depth + 1));
|
|
2888
|
+
} else if (!isPlainObject(next)) {
|
|
2889
|
+
throw new Error(`cannot descend into ${path.slice(0, depth + 1).join(".")}: it is ${Array.isArray(next) ? "an array" : `a ${typeof next}`}, not a table`);
|
|
2890
|
+
}
|
|
2891
|
+
node = node[key];
|
|
2892
|
+
}
|
|
2893
|
+
return node;
|
|
2894
|
+
}
|
|
2895
|
+
function revertTomlOps(value, ops) {
|
|
2896
|
+
const notes = [];
|
|
2897
|
+
for (const record of [...ops].reverse()) {
|
|
2898
|
+
if (record.op === "set") {
|
|
2899
|
+
const now = valueAt(value, record.path);
|
|
2900
|
+
if (now === undefined)
|
|
2901
|
+
continue;
|
|
2902
|
+
if (!deepEqual(now, record.applied)) {
|
|
2903
|
+
notes.push(`${record.path.join(".")}: current value differs from what the installer wrote; left untouched`);
|
|
2904
|
+
continue;
|
|
2905
|
+
}
|
|
2906
|
+
if (record.previous === undefined) {
|
|
2907
|
+
removeAt(value, record.path);
|
|
2908
|
+
} else {
|
|
2909
|
+
setValueAt(value, record.path, record.previous);
|
|
2910
|
+
}
|
|
2911
|
+
} else {
|
|
2912
|
+
const entries = Array.isArray(record.applied) ? record.applied : [];
|
|
2913
|
+
for (const entry of entries) {
|
|
2914
|
+
const list = valueAt(value, record.path);
|
|
2915
|
+
if (!Array.isArray(list))
|
|
2916
|
+
continue;
|
|
2917
|
+
const index = list.findIndex((item) => deepEqual(item, entry));
|
|
2918
|
+
if (index === -1)
|
|
2919
|
+
continue;
|
|
2920
|
+
list.splice(index, 1);
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
return notes;
|
|
2925
|
+
}
|
|
2926
|
+
function pruneCreatedParents(value, parents) {
|
|
2927
|
+
for (const parent of [...parents].reverse()) {
|
|
2928
|
+
const current = valueAt(value, parent);
|
|
2929
|
+
if (isPlainObject(current) && Object.keys(current).length === 0)
|
|
2930
|
+
removeAt(value, parent);
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
function setValueAt(value, path, replacement) {
|
|
2934
|
+
const parent = valueAt(value, path.slice(0, -1));
|
|
2935
|
+
if (isPlainObject(parent))
|
|
2936
|
+
parent[path[path.length - 1]] = replacement;
|
|
2937
|
+
}
|
|
2938
|
+
function tomlOpHolds(text, op) {
|
|
2939
|
+
const value = parse3(text);
|
|
2940
|
+
const current = valueAt(value, op.path);
|
|
2941
|
+
if (op.op === "set")
|
|
2942
|
+
return deepEqual(current, op.value);
|
|
2943
|
+
return Array.isArray(current) && (op.entries ?? []).every((entry) => current.some((item) => deepEqual(item, entry)));
|
|
2944
|
+
}
|
|
2945
|
+
var tomlCodec;
|
|
2946
|
+
var init_toml = __esm(() => {
|
|
2947
|
+
init_dist();
|
|
2948
|
+
tomlCodec = {
|
|
2949
|
+
format: "toml",
|
|
2950
|
+
load: loadToml,
|
|
2951
|
+
apply: (text, edit2) => {
|
|
2952
|
+
if (edit2.format !== "toml")
|
|
2953
|
+
throw new Error(`toml codec cannot apply a ${edit2.format} edit`);
|
|
2954
|
+
const result = applyTomlOps(parse3(text), edit2.ops);
|
|
2955
|
+
return { text: serializeToml(result.value), recorded: result.recorded, createdParents: result.createdParents };
|
|
2956
|
+
},
|
|
2957
|
+
verify: (text, edit2, op) => {
|
|
2958
|
+
if (edit2.format !== "toml")
|
|
2959
|
+
throw new Error(`toml codec cannot verify a ${edit2.format} edit`);
|
|
2960
|
+
const ops = op === undefined ? edit2.ops : [op];
|
|
2961
|
+
return ops.every((candidate) => tomlOpHolds(text, candidate));
|
|
2962
|
+
},
|
|
2963
|
+
revert: (text, recorded) => {
|
|
2964
|
+
const value = parse3(text);
|
|
2965
|
+
const notes = revertTomlOps(value, recorded.ops);
|
|
2966
|
+
pruneCreatedParents(value, recorded.createdParents ?? []);
|
|
2967
|
+
return { text: serializeToml(value), notes };
|
|
2968
|
+
},
|
|
2969
|
+
isEffectivelyEmpty: (text) => Object.keys(parse3(text)).length === 0
|
|
2970
|
+
};
|
|
2971
|
+
});
|
|
2972
|
+
|
|
2973
|
+
// src/installer/formats/index.ts
|
|
2974
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2975
|
+
import { dirname } from "node:path";
|
|
2976
|
+
function writeConfig(file, serialized) {
|
|
2977
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
2978
|
+
writeFileSync(file, serialized);
|
|
2979
|
+
}
|
|
2980
|
+
function codecFor(format2, host) {
|
|
2981
|
+
if (format2 === "json")
|
|
2982
|
+
return jsonCodec;
|
|
2983
|
+
if (format2 === "toml")
|
|
2984
|
+
return tomlCodec;
|
|
2985
|
+
return rulesCodec(host);
|
|
2986
|
+
}
|
|
2987
|
+
var init_formats = __esm(() => {
|
|
2988
|
+
init_json();
|
|
2989
|
+
init_rules();
|
|
2990
|
+
init_toml();
|
|
2991
|
+
});
|
|
2992
|
+
|
|
2993
|
+
// src/installer/detect.ts
|
|
2994
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
2995
|
+
function replacingExistingEntryNote(path) {
|
|
2996
|
+
return `An existing ${path} entry is being replaced; its previous form is recorded for uninstall.`;
|
|
2997
|
+
}
|
|
2998
|
+
function othersStayRegisteredNote(others) {
|
|
2999
|
+
return `Other MCP servers stay registered (${others.join(", ")}); routing to DeepSeek is not exclusive while they offer web tools.`;
|
|
3000
|
+
}
|
|
3001
|
+
function looksWebCapable(name, entry) {
|
|
3002
|
+
if (WEB_TOOL_HINT.test(name))
|
|
3003
|
+
return true;
|
|
3004
|
+
if (!isPlainObject(entry))
|
|
3005
|
+
return false;
|
|
3006
|
+
const command = typeof entry.command === "string" ? entry.command : "";
|
|
3007
|
+
const url = typeof entry.url === "string" ? entry.url : "";
|
|
3008
|
+
const args = Array.isArray(entry.args) ? entry.args.filter((arg) => typeof arg === "string").join(" ") : "";
|
|
3009
|
+
return WEB_TOOL_HINT.test(`${command} ${args} ${url}`);
|
|
3010
|
+
}
|
|
3011
|
+
function findCompetitorSteering(host, file) {
|
|
3012
|
+
if (!existsSync4(file))
|
|
3013
|
+
return [];
|
|
3014
|
+
let text;
|
|
3015
|
+
try {
|
|
3016
|
+
text = readFileSync4(file, "utf8");
|
|
3017
|
+
} catch {
|
|
3018
|
+
return [];
|
|
3019
|
+
}
|
|
3020
|
+
return removeBlock(host, text).split(`
|
|
3021
|
+
`).map((line) => line.trim()).filter((line) => line.length > 0 && STEERING_HINT.test(line) && !line.includes("deepseek")).slice(0, 2);
|
|
3022
|
+
}
|
|
3023
|
+
function competitorSteeringNote(file, lines) {
|
|
3024
|
+
const quoted = lines.map((line) => `"${line}"`).join(", ");
|
|
3025
|
+
return `Existing rules in ${file} steer toward other web tools (${quoted}); the plan surfaces this conflict — it does not resolve it.`;
|
|
3026
|
+
}
|
|
3027
|
+
function splitCompetitors(servers) {
|
|
3028
|
+
const competitors = [];
|
|
3029
|
+
const bystanders = [];
|
|
3030
|
+
for (const [name, entry] of Object.entries(servers)) {
|
|
3031
|
+
if (name === "deepseek")
|
|
3032
|
+
continue;
|
|
3033
|
+
(looksWebCapable(name, entry) ? competitors : bystanders).push(name);
|
|
3034
|
+
}
|
|
3035
|
+
return { competitors, bystanders };
|
|
3036
|
+
}
|
|
3037
|
+
var BOTH_CAPABILITIES_OFF = "Both capabilities are off; nothing would be installed.", FORCED_COST_NOTE, WEB_TOOL_HINT, STEERING_HINT;
|
|
3038
|
+
var init_detect = __esm(() => {
|
|
3039
|
+
init_rules();
|
|
3040
|
+
FORCED_COST_NOTE = "Forced routing is deterministic, and Search and Fetch are billed per successful request — " + `see the README's "Privacy and cost" section before applying.`;
|
|
3041
|
+
WEB_TOOL_HINT = /(web[_ -]?(search|fetch)|search|fetch|browse|scrape|crawl|tavily|brave|exa|perplexity|firecrawl|jina|serp|duckduckgo|reader)/i;
|
|
3042
|
+
STEERING_HINT = /(web[_ ]?(search|fetch)|websearch|webfetch|tavily|exa|brave|perplexity|firecrawl|jina|serp|duckduckgo|google|bing)/i;
|
|
3043
|
+
});
|
|
3044
|
+
|
|
3045
|
+
// src/installer/paths.ts
|
|
3046
|
+
function join(...parts) {
|
|
3047
|
+
return parts.filter((part) => part.length > 0).join("/");
|
|
3048
|
+
}
|
|
3049
|
+
function configHome(roots) {
|
|
3050
|
+
return roots.configHome ?? join(roots.home, ".config");
|
|
3051
|
+
}
|
|
3052
|
+
function stateDir(roots, scope) {
|
|
3053
|
+
return scope === "global" ? join(configHome(roots), "deepseek-web-retrieval") : join(roots.cwd, ".deepseek-web-retrieval");
|
|
3054
|
+
}
|
|
3055
|
+
|
|
3056
|
+
// src/installer/rulesContent.ts
|
|
3057
|
+
function rulesLines(ids, search, fetch) {
|
|
3058
|
+
const lines = ["DeepSeek retrieval guidance:"];
|
|
3059
|
+
if (search !== "off") {
|
|
3060
|
+
lines.push(`- Use ${ids.search} when the task needs fresh external information: current docs, version numbers,`, " changelogs, or anything you cannot know from the repository alone. Do not search for facts already", " present locally.");
|
|
3061
|
+
}
|
|
3062
|
+
if (fetch !== "off") {
|
|
3063
|
+
lines.push(`- Use ${ids.fetch} to read a specific public web page as Markdown when its content is needed.`);
|
|
3064
|
+
}
|
|
3065
|
+
lines.push("- Never send localhost or private-network URLs to the DeepSeek tools; use local tools for those (the", " server blocks private hosts by default).", "- DeepSeek requests are billed per successful call; retrieve only what the task needs.");
|
|
3066
|
+
return lines;
|
|
3067
|
+
}
|
|
3068
|
+
var MCP_TOOL_IDS;
|
|
3069
|
+
var init_rulesContent = __esm(() => {
|
|
3070
|
+
MCP_TOOL_IDS = { search: "mcp__deepseek__deepseek_web_search", fetch: "mcp__deepseek__deepseek_fetch" };
|
|
3071
|
+
});
|
|
3072
|
+
|
|
3073
|
+
// src/installer/hosts/shared.ts
|
|
3074
|
+
function planHeader(input, paths, loaded, dialect) {
|
|
3075
|
+
const notes = [];
|
|
3076
|
+
const errors = [];
|
|
3077
|
+
if (loaded.parseError) {
|
|
3078
|
+
errors.push({ message: `${paths.config} exists but does not parse as ${dialect}: ${loaded.parseError}` });
|
|
3079
|
+
return { notes, errors, abort: true };
|
|
3080
|
+
}
|
|
3081
|
+
if (input.search === "off" && input.fetch === "off") {
|
|
3082
|
+
errors.push({ message: BOTH_CAPABILITIES_OFF });
|
|
3083
|
+
}
|
|
3084
|
+
const steering = findCompetitorSteering(input.host, paths.rules);
|
|
3085
|
+
if (steering.length > 0)
|
|
3086
|
+
notes.push(competitorSteeringNote(paths.rules, steering));
|
|
3087
|
+
return { notes, errors, abort: false };
|
|
3088
|
+
}
|
|
3089
|
+
var init_shared = __esm(() => {
|
|
3090
|
+
init_detect();
|
|
3091
|
+
});
|
|
3092
|
+
|
|
3093
|
+
// src/installer/hosts/codex.ts
|
|
3094
|
+
function codexPaths(input) {
|
|
3095
|
+
return {
|
|
3096
|
+
config: join(input.home, ".codex/config.toml"),
|
|
3097
|
+
rules: input.scope === "global" ? join(input.home, ".codex/AGENTS.md") : join(input.cwd, "AGENTS.md")
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
3100
|
+
function planCodex(input, _previous) {
|
|
3101
|
+
const paths = codexPaths(input);
|
|
3102
|
+
const loaded = codecFor("toml", input.host).load(paths.config);
|
|
3103
|
+
const tiers = { search: input.search, fetch: input.fetch };
|
|
3104
|
+
const header = planHeader(input, paths, loaded, "TOML");
|
|
3105
|
+
if (header.abort) {
|
|
3106
|
+
return { host: "codex", scope: input.scope, tiers, edits: [], notes: header.notes, errors: header.errors };
|
|
3107
|
+
}
|
|
3108
|
+
const notes = [...header.notes];
|
|
3109
|
+
const errors = [...header.errors];
|
|
3110
|
+
const edits = [];
|
|
3111
|
+
const tools = loaded.value.tools;
|
|
3112
|
+
if (isPlainObject(tools) && "web_search" in tools) {
|
|
3113
|
+
errors.push({
|
|
3114
|
+
message: `${paths.config} sets [tools] web_search, which is a silent no-op at Codex 0.163.0 (only the top-level ` + "web_search key controls the tool). Remove it first so the config cannot mislead."
|
|
3115
|
+
});
|
|
3116
|
+
}
|
|
3117
|
+
const servers = loaded.value.mcp_servers;
|
|
3118
|
+
if (isPlainObject(servers)) {
|
|
3119
|
+
if ("deepseek" in servers)
|
|
3120
|
+
notes.push(replacingExistingEntryNote("mcp_servers.deepseek"));
|
|
3121
|
+
const { competitors, bystanders } = splitCompetitors(servers);
|
|
3122
|
+
if ((input.search === "forced" || input.fetch === "forced") && competitors.length > 0) {
|
|
3123
|
+
errors.push({
|
|
3124
|
+
message: `Forced cannot deliver exclusive routing: [mcp_servers.${competitors.join("], [mcp_servers.")}] look(s) web-capable, ` + "and Codex offers no per-server kill switch. Remove the server(s), disable their tools by hand via their " + "disabled_tools key, or choose a lower tier."
|
|
3125
|
+
});
|
|
3126
|
+
}
|
|
3127
|
+
const stayRegistered = input.search === "forced" || input.fetch === "forced" ? bystanders : [...competitors, ...bystanders];
|
|
3128
|
+
if (stayRegistered.length > 0)
|
|
3129
|
+
notes.push(othersStayRegisteredNote(stayRegistered));
|
|
3130
|
+
}
|
|
3131
|
+
const env = {};
|
|
3132
|
+
if (input.search === "off")
|
|
3133
|
+
env[ENABLE_SEARCH_ENV] = "false";
|
|
3134
|
+
if (input.fetch === "off")
|
|
3135
|
+
env[ENABLE_FETCH_ENV] = "false";
|
|
3136
|
+
const entry = {
|
|
3137
|
+
command: "npx",
|
|
3138
|
+
args: ["-y", input.packageRef],
|
|
3139
|
+
...Object.keys(env).length > 0 ? { env } : {},
|
|
3140
|
+
env_vars: [API_KEY_ENV]
|
|
3141
|
+
};
|
|
3142
|
+
const existingEntry = isPlainObject(servers) ? servers.deepseek : undefined;
|
|
3143
|
+
const ops = [
|
|
3144
|
+
{ op: "set", path: ["mcp_servers", "deepseek"], value: entry, previous: existingEntry }
|
|
3145
|
+
];
|
|
3146
|
+
if (input.search === "forced") {
|
|
3147
|
+
const previous = typeof loaded.value.web_search === "string" ? loaded.value.web_search : undefined;
|
|
3148
|
+
ops.push({ op: "set", path: ["web_search"], value: "disabled", previous });
|
|
3149
|
+
notes.push(previous === undefined ? 'web_search is being set to "disabled" (no previous value existed; the default is "cached").' : `web_search is being set to "disabled"; the previous value "${previous}" is snapshotted for uninstall.`);
|
|
3150
|
+
}
|
|
3151
|
+
edits.push({ file: paths.config, format: "toml", ops });
|
|
3152
|
+
notes.push(`Codex stdio children do not inherit the parent environment, so the entry forwards ${API_KEY_ENV} explicitly ` + "via env_vars; the key must be set in the shell that launches Codex.");
|
|
3153
|
+
if (input.scope === "project") {
|
|
3154
|
+
notes.push("Codex config lives in ~/.codex/config.toml only (user level), so the server registration and kill switch are " + "written there even for a project-scope install; the rules file stays project-local.");
|
|
3155
|
+
}
|
|
3156
|
+
if (loaded.lossy) {
|
|
3157
|
+
notes.push(`${paths.config} contains comments; the TOML rewrite will drop them.`);
|
|
3158
|
+
}
|
|
3159
|
+
if (input.search === "forced" || input.fetch === "forced") {
|
|
3160
|
+
notes.push('Forced search is exclusion: the built-in web_search tool is disabled ("disabled" mode). ' + FORCED_COST_NOTE);
|
|
3161
|
+
}
|
|
3162
|
+
if (input.search === "optional" || input.fetch === "optional") {
|
|
3163
|
+
notes.push('Note: Codex ships a built-in web_search tool (default "cached" mode, an OpenAI index) that stays available ' + "alongside the DeepSeek tools under the optional tier.");
|
|
3164
|
+
}
|
|
3165
|
+
if (input.search === "preferred" || input.fetch === "preferred") {
|
|
3166
|
+
edits.push({
|
|
3167
|
+
file: paths.rules,
|
|
3168
|
+
format: "rules",
|
|
3169
|
+
block: buildRulesBlock(input.host, rulesLines(MCP_TOOL_IDS, input.search, input.fetch))
|
|
3170
|
+
});
|
|
3171
|
+
notes.push(input.scope === "global" ? `Rules block upserted in ${paths.rules}; Codex reads ~/.codex/AGENTS.md plus every AGENTS.md from the project root to the cwd.` : `Rules block upserted in ${paths.rules}; Codex reads every AGENTS.md from the project root to the cwd.`);
|
|
3172
|
+
}
|
|
3173
|
+
return { host: "codex", scope: input.scope, tiers, edits, notes, errors };
|
|
3174
|
+
}
|
|
3175
|
+
var init_codex = __esm(() => {
|
|
3176
|
+
init_formats();
|
|
3177
|
+
init_detect();
|
|
3178
|
+
init_constants();
|
|
3179
|
+
init_rules();
|
|
3180
|
+
init_rulesContent();
|
|
3181
|
+
init_shared();
|
|
3182
|
+
});
|
|
3183
|
+
|
|
3184
|
+
// src/installer/hosts/opencode.ts
|
|
3185
|
+
function opencodePaths(input) {
|
|
3186
|
+
return input.scope === "global" ? { config: join(configHome(input), "opencode/opencode.jsonc"), rules: join(configHome(input), "opencode/AGENTS.md") } : { config: join(input.cwd, "opencode.jsonc"), rules: join(input.cwd, "AGENTS.md") };
|
|
3187
|
+
}
|
|
3188
|
+
function planOpenCode(input, previous) {
|
|
3189
|
+
const paths = opencodePaths(input);
|
|
3190
|
+
const loaded = codecFor("json", input.host).load(paths.config);
|
|
3191
|
+
const tiers = { search: input.search, fetch: input.fetch };
|
|
3192
|
+
const header = planHeader(input, paths, loaded, "JSONC");
|
|
3193
|
+
if (header.abort) {
|
|
3194
|
+
return { host: "opencode", scope: input.scope, tiers, edits: [], notes: header.notes, errors: header.errors };
|
|
3195
|
+
}
|
|
3196
|
+
const notes = [...header.notes];
|
|
3197
|
+
const errors = [...header.errors];
|
|
3198
|
+
const edits = [];
|
|
3199
|
+
if (input.search === "preferred") {
|
|
3200
|
+
errors.push({
|
|
3201
|
+
message: "OpenCode search has no preferred tier: the websearch provider is host-level config, so the model never " + "chooses between engines. Use --search optional (provider registered, built-in stays default), " + "--search forced (replace the engine), or --search off."
|
|
3202
|
+
});
|
|
3203
|
+
}
|
|
3204
|
+
const plugins = Array.isArray(loaded.value.plugins) ? loaded.value.plugins : [];
|
|
3205
|
+
const alreadyInstalled = plugins.some((entry) => isPlainObject(entry) && typeof entry.package === "string" && entry.package.includes("deepseek-web-retrieval"));
|
|
3206
|
+
if (alreadyInstalled && previous === undefined) {
|
|
3207
|
+
errors.push({
|
|
3208
|
+
message: `${paths.config} already has a plugins entry referencing deepseek-web-retrieval that this installer did not ` + "write. Remove it (or run uninstall if it came from a previous init), then retry."
|
|
3209
|
+
});
|
|
3210
|
+
}
|
|
3211
|
+
if (alreadyInstalled && errors.length === 0) {
|
|
3212
|
+
notes.push("A previous init wrote the plugins entry; re-applying updates it and carries the original snapshots over.");
|
|
3213
|
+
}
|
|
3214
|
+
if (errors.length > 0) {
|
|
3215
|
+
return { host: "opencode", scope: input.scope, tiers, edits, notes, errors };
|
|
3216
|
+
}
|
|
3217
|
+
const options = {};
|
|
3218
|
+
if (input.search === "forced")
|
|
3219
|
+
options.setDefaultWebsearch = true;
|
|
3220
|
+
if (input.search === "off")
|
|
3221
|
+
options.searchEnabled = false;
|
|
3222
|
+
if (input.fetch === "forced")
|
|
3223
|
+
options.fetchOverrideWebfetch = true;
|
|
3224
|
+
if (input.fetch === "off")
|
|
3225
|
+
options.fetchEnabled = false;
|
|
3226
|
+
const ops = [
|
|
3227
|
+
{
|
|
3228
|
+
op: "append-array",
|
|
3229
|
+
path: ["plugins"],
|
|
3230
|
+
entries: [{ package: input.packageRef, options }],
|
|
3231
|
+
existingCount: plugins.length
|
|
3232
|
+
}
|
|
3233
|
+
];
|
|
3234
|
+
const permissions = [];
|
|
3235
|
+
if (input.search !== "off")
|
|
3236
|
+
permissions.push({ action: "websearch", resource: "*", effect: "allow" });
|
|
3237
|
+
if (input.fetch !== "off")
|
|
3238
|
+
permissions.push({ action: "deepseek_fetch", resource: "*", effect: "allow" });
|
|
3239
|
+
if (input.fetch === "forced")
|
|
3240
|
+
permissions.push({ action: "webfetch", resource: "*", effect: "allow" });
|
|
3241
|
+
const existingPermissions = Array.isArray(loaded.value.permissions) ? loaded.value.permissions.length : 0;
|
|
3242
|
+
if (permissions.length > 0) {
|
|
3243
|
+
ops.push({ op: "append-array", path: ["permissions"], entries: permissions, existingCount: existingPermissions });
|
|
3244
|
+
}
|
|
3245
|
+
if (input.search === "forced") {
|
|
3246
|
+
const currentProvider = isPlainObject(loaded.value.websearch) ? loaded.value.websearch.provider : undefined;
|
|
3247
|
+
ops.push({ op: "set", path: ["websearch", "provider"], value: "deepseek", previous: currentProvider });
|
|
3248
|
+
notes.push(currentProvider === undefined ? "websearch.provider is being set to deepseek (no previous value existed)." : `websearch.provider is being set to deepseek; the previous value "${String(currentProvider)}" is snapshotted for uninstall.`);
|
|
3249
|
+
}
|
|
3250
|
+
edits.push({ file: paths.config, format: "json", ops });
|
|
3251
|
+
notes.push("The plugin entry uses the object form so options are honored; auto-discovered plugins cannot receive options.");
|
|
3252
|
+
if (input.search === "optional") {
|
|
3253
|
+
notes.push("Search tier optional: the deepseek provider is registered but the built-in provider stays the default engine; " + "set websearch.provider to deepseek (or rerun with --search forced) to route search through DeepSeek.");
|
|
3254
|
+
}
|
|
3255
|
+
if (input.search === "forced" || input.fetch === "forced") {
|
|
3256
|
+
notes.push("Forced tier replaces built-in routing. " + FORCED_COST_NOTE);
|
|
3257
|
+
}
|
|
3258
|
+
if (input.fetch === "preferred") {
|
|
3259
|
+
edits.push({
|
|
3260
|
+
file: paths.rules,
|
|
3261
|
+
format: "rules",
|
|
3262
|
+
block: buildRulesBlock(input.host, rulesLines(OPENCODE_TOOL_IDS, input.search, input.fetch))
|
|
3263
|
+
});
|
|
3264
|
+
notes.push(`Rules block upserted in ${paths.rules}; OpenCode loads AGENTS.md only (no CLAUDE.md fallback in v2).`);
|
|
3265
|
+
}
|
|
3266
|
+
return { host: "opencode", scope: input.scope, tiers, edits, notes, errors };
|
|
3267
|
+
}
|
|
3268
|
+
var OPENCODE_TOOL_IDS;
|
|
3269
|
+
var init_opencode = __esm(() => {
|
|
3270
|
+
init_formats();
|
|
3271
|
+
init_detect();
|
|
3272
|
+
init_rules();
|
|
3273
|
+
init_rulesContent();
|
|
3274
|
+
init_shared();
|
|
3275
|
+
OPENCODE_TOOL_IDS = { search: "websearch (provider deepseek)", fetch: "deepseek_fetch" };
|
|
3276
|
+
});
|
|
3277
|
+
|
|
3278
|
+
// src/installer/hosts/pi.ts
|
|
3279
|
+
function piPaths(input) {
|
|
3280
|
+
return input.scope === "global" ? { config: join(input.home, ".pi/agent/mcp.json"), rules: join(input.home, ".pi/agent/AGENTS.md") } : { config: join(input.cwd, ".pi/mcp.json"), rules: join(input.cwd, "AGENTS.md") };
|
|
3281
|
+
}
|
|
3282
|
+
function planPi(input, _previous) {
|
|
3283
|
+
const paths = piPaths(input);
|
|
3284
|
+
const loaded = codecFor("json", input.host).load(paths.config);
|
|
3285
|
+
const tiers = { search: input.search, fetch: input.fetch };
|
|
3286
|
+
const header = planHeader(input, paths, loaded, "JSON");
|
|
3287
|
+
if (header.abort) {
|
|
3288
|
+
return { host: "pi", scope: input.scope, tiers, edits: [], notes: header.notes, errors: header.errors };
|
|
3289
|
+
}
|
|
3290
|
+
const notes = [...header.notes];
|
|
3291
|
+
const errors = [...header.errors];
|
|
3292
|
+
const edits = [];
|
|
3293
|
+
const env = { [API_KEY_ENV]: `\${${API_KEY_ENV}}` };
|
|
3294
|
+
if (input.search === "off")
|
|
3295
|
+
env[ENABLE_SEARCH_ENV] = "false";
|
|
3296
|
+
if (input.fetch === "off")
|
|
3297
|
+
env[ENABLE_FETCH_ENV] = "false";
|
|
3298
|
+
const entry = {
|
|
3299
|
+
command: "npx",
|
|
3300
|
+
args: ["-y", input.packageRef],
|
|
3301
|
+
env,
|
|
3302
|
+
exposure: "direct",
|
|
3303
|
+
enabled: true
|
|
3304
|
+
};
|
|
3305
|
+
const servers = loaded.value.mcpServers;
|
|
3306
|
+
const existingEntry = isPlainObject(servers) ? servers.deepseek : undefined;
|
|
3307
|
+
const ops = [
|
|
3308
|
+
{ op: "set", path: ["mcpServers", "deepseek"], value: entry, previous: existingEntry }
|
|
3309
|
+
];
|
|
3310
|
+
edits.push({ file: paths.config, format: "json", ops });
|
|
3311
|
+
if (isPlainObject(servers)) {
|
|
3312
|
+
if (servers.deepseek !== undefined)
|
|
3313
|
+
notes.push(replacingExistingEntryNote("mcpServers.deepseek"));
|
|
3314
|
+
const { competitors, bystanders } = splitCompetitors(servers);
|
|
3315
|
+
const forced = input.search === "forced" || input.fetch === "forced";
|
|
3316
|
+
if (forced) {
|
|
3317
|
+
const excluded = [];
|
|
3318
|
+
const unexcludable = [];
|
|
3319
|
+
for (const name of competitors) {
|
|
3320
|
+
const current = servers[name];
|
|
3321
|
+
if (!isPlainObject(current)) {
|
|
3322
|
+
unexcludable.push(name);
|
|
3323
|
+
continue;
|
|
3324
|
+
}
|
|
3325
|
+
const previous = typeof current.enabled === "boolean" ? current.enabled : undefined;
|
|
3326
|
+
if (previous === false)
|
|
3327
|
+
continue;
|
|
3328
|
+
ops.push({ op: "set", path: ["mcpServers", name, "enabled"], value: false, previous });
|
|
3329
|
+
excluded.push(name);
|
|
3330
|
+
}
|
|
3331
|
+
if (excluded.length > 0) {
|
|
3332
|
+
notes.push(`Forced tier: web-capable MCP servers are disabled so DeepSeek routing is exclusive (${excluded.join(", ")}; ` + "prior enabled values are snapshotted for uninstall).");
|
|
3333
|
+
}
|
|
3334
|
+
if (unexcludable.length > 0) {
|
|
3335
|
+
errors.push({
|
|
3336
|
+
message: `Forced cannot deliver exclusive routing: mcpServers entries ${unexcludable.join(", ")} look web-capable ` + "but are not objects, so the plan cannot set their enabled key. Fix or remove them, or choose a lower tier."
|
|
3337
|
+
});
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
const stayRegistered = forced ? bystanders : [...competitors, ...bystanders];
|
|
3341
|
+
if (stayRegistered.length > 0)
|
|
3342
|
+
notes.push(othersStayRegisteredNote(stayRegistered));
|
|
3343
|
+
}
|
|
3344
|
+
notes.push('"exposure": "direct" is required: Pi 1.3.0 defaults MCP tools to codemode, which hides them from the model.');
|
|
3345
|
+
notes.push(`\`${API_KEY_ENV}\` is written as "\${${API_KEY_ENV}}" so the key expands from the shell that launches Pi and stays out of the file.`);
|
|
3346
|
+
if (loaded.lossy) {
|
|
3347
|
+
notes.push(`${paths.config} contains comments; the JSON edit preserves them.`);
|
|
3348
|
+
}
|
|
3349
|
+
if (input.search === "preferred" || input.fetch === "preferred") {
|
|
3350
|
+
edits.push({
|
|
3351
|
+
file: paths.rules,
|
|
3352
|
+
format: "rules",
|
|
3353
|
+
block: buildRulesBlock(input.host, rulesLines(MCP_TOOL_IDS, input.search, input.fetch))
|
|
3354
|
+
});
|
|
3355
|
+
notes.push(`Rules block upserted in ${paths.rules}; Pi loads AGENTS.md context files from the working directory and its parents.`);
|
|
3356
|
+
}
|
|
3357
|
+
if (input.search === "forced" || input.fetch === "forced") {
|
|
3358
|
+
notes.push("Forced tier: Pi 1.3.0 ships no built-in web tool, so the registered tools are the only web path (de-facto). " + FORCED_COST_NOTE);
|
|
3359
|
+
}
|
|
3360
|
+
return { host: "pi", scope: input.scope, tiers, edits, notes, errors };
|
|
3361
|
+
}
|
|
3362
|
+
var init_pi = __esm(() => {
|
|
3363
|
+
init_formats();
|
|
3364
|
+
init_detect();
|
|
3365
|
+
init_constants();
|
|
3366
|
+
init_rules();
|
|
3367
|
+
init_rulesContent();
|
|
3368
|
+
init_shared();
|
|
3369
|
+
});
|
|
3370
|
+
|
|
3371
|
+
// src/installer/state.ts
|
|
3372
|
+
import { chmodSync, existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync5, readdirSync, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3373
|
+
import { join as join2 } from "node:path";
|
|
3374
|
+
function statePathFor(input) {
|
|
3375
|
+
return join2(stateDir(input, input.scope), `install.${input.host}.json`);
|
|
3376
|
+
}
|
|
3377
|
+
function readRecord(input) {
|
|
3378
|
+
const file = statePathFor(input);
|
|
3379
|
+
if (!existsSync5(file))
|
|
3380
|
+
return;
|
|
3381
|
+
try {
|
|
3382
|
+
return JSON.parse(readFileSync5(file, "utf8"));
|
|
3383
|
+
} catch {
|
|
3384
|
+
return;
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
function claimedByOtherScope(input, files) {
|
|
3388
|
+
const other = input.scope === "global" ? "project" : "global";
|
|
3389
|
+
const record = readRecord({ ...input, scope: other });
|
|
3390
|
+
if (record === undefined)
|
|
3391
|
+
return [];
|
|
3392
|
+
return files.filter((file) => record.files.some((candidate) => candidate.file === file));
|
|
3393
|
+
}
|
|
3394
|
+
function writeRecord(input, record) {
|
|
3395
|
+
const file = statePathFor(input);
|
|
3396
|
+
mkdirSync2(join2(file, ".."), { recursive: true });
|
|
3397
|
+
writeFileSync2(file, `${JSON.stringify(record, null, 2)}
|
|
3398
|
+
`, { mode: 384 });
|
|
3399
|
+
chmodSync(file, 384);
|
|
3400
|
+
}
|
|
3401
|
+
function deleteRecord(input) {
|
|
3402
|
+
const file = statePathFor(input);
|
|
3403
|
+
if (existsSync5(file))
|
|
3404
|
+
rmSync(file);
|
|
3405
|
+
}
|
|
3406
|
+
function listRecords(roots) {
|
|
3407
|
+
const records = [];
|
|
3408
|
+
for (const scope of ["global", "project"]) {
|
|
3409
|
+
const dir = stateDir(roots, scope);
|
|
3410
|
+
if (!existsSync5(dir))
|
|
3411
|
+
continue;
|
|
3412
|
+
for (const name of readdirSync(dir)) {
|
|
3413
|
+
if (!name.startsWith("install.") || !name.endsWith(".json"))
|
|
3414
|
+
continue;
|
|
3415
|
+
try {
|
|
3416
|
+
records.push(JSON.parse(readFileSync5(join2(dir, name), "utf8")));
|
|
3417
|
+
} catch {}
|
|
3418
|
+
}
|
|
3419
|
+
}
|
|
3420
|
+
return records;
|
|
3421
|
+
}
|
|
3422
|
+
var init_state = () => {};
|
|
3423
|
+
|
|
3424
|
+
// src/installer/hosts/index.ts
|
|
3425
|
+
function planForHost(host, input) {
|
|
3426
|
+
const previous = readRecord(input);
|
|
3427
|
+
const planned = withCrossScopeGuard(HOST_PLANNERS[host](input, previous), input);
|
|
3428
|
+
return withSecretGuard(withOrphanReverts(planned, input, previous));
|
|
3429
|
+
}
|
|
3430
|
+
function withCrossScopeGuard(plan, input) {
|
|
3431
|
+
if (plan.errors.length > 0)
|
|
3432
|
+
return plan;
|
|
3433
|
+
const other = input.scope === "global" ? "project" : "global";
|
|
3434
|
+
const overlap = claimedByOtherScope(input, plan.edits.map((edit2) => edit2.file));
|
|
3435
|
+
if (overlap.length === 0)
|
|
3436
|
+
return plan;
|
|
3437
|
+
return {
|
|
3438
|
+
...plan,
|
|
3439
|
+
edits: [],
|
|
3440
|
+
reverts: undefined,
|
|
3441
|
+
errors: [
|
|
3442
|
+
{
|
|
3443
|
+
message: `A ${plan.host} install is already recorded at the ${other} scope and claims the same file(s): ${overlap.join(", ")}. ` + `Uninstall it first (deepseek-web-retrieval uninstall --host ${plan.host} --scope ${other}), ` + `or re-run with --scope ${other} to update it in place — two scopes must not edit one file.`
|
|
3444
|
+
}
|
|
3445
|
+
]
|
|
3446
|
+
};
|
|
3447
|
+
}
|
|
3448
|
+
function withSecretGuard(plan) {
|
|
3449
|
+
for (const edit2 of plan.edits) {
|
|
3450
|
+
if (edit2.format === "rules")
|
|
3451
|
+
continue;
|
|
3452
|
+
for (const op of edit2.ops) {
|
|
3453
|
+
if (op.op !== "set" || op.previous === undefined)
|
|
3454
|
+
continue;
|
|
3455
|
+
const offender = findSecretLike(op.previous, op.path.join("."));
|
|
3456
|
+
if (offender !== undefined) {
|
|
3457
|
+
return {
|
|
3458
|
+
...plan,
|
|
3459
|
+
edits: [],
|
|
3460
|
+
reverts: undefined,
|
|
3461
|
+
errors: [
|
|
3462
|
+
{
|
|
3463
|
+
message: `${edit2.file}: the existing value at ${op.path.join(".")} contains a credential-looking key ` + `(${offender}). The installer refuses to snapshot secrets into its state file. Move the key to ` + `environment indirection ("\${${API_KEY_ENV}}" expansion or env_vars) and re-run.`
|
|
3464
|
+
}
|
|
3465
|
+
]
|
|
3466
|
+
};
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
return plan;
|
|
3471
|
+
}
|
|
3472
|
+
function findSecretLike(value, at) {
|
|
3473
|
+
if (typeof value !== "object" || value === null)
|
|
3474
|
+
return;
|
|
3475
|
+
for (const [key, child] of Object.entries(value)) {
|
|
3476
|
+
const path = `${at}.${key}`;
|
|
3477
|
+
if (/(api[_-]?key|token|secret|password|credential)/i.test(key) && typeof child === "string" && child.length > 0 && !/^\$\{[^}]+\}$/.test(child)) {
|
|
3478
|
+
return path;
|
|
3479
|
+
}
|
|
3480
|
+
const nested = findSecretLike(child, path);
|
|
3481
|
+
if (nested !== undefined)
|
|
3482
|
+
return nested;
|
|
3483
|
+
}
|
|
3484
|
+
return;
|
|
3485
|
+
}
|
|
3486
|
+
function withOrphanReverts(plan, input, previous) {
|
|
3487
|
+
if (plan.errors.length > 0)
|
|
3488
|
+
return plan;
|
|
3489
|
+
if (previous === undefined)
|
|
3490
|
+
return plan;
|
|
3491
|
+
const reverts = [];
|
|
3492
|
+
for (const file of previous.files) {
|
|
3493
|
+
const edit2 = plan.edits.find((candidate) => candidate.file === file.file);
|
|
3494
|
+
if (edit2 === undefined) {
|
|
3495
|
+
reverts.push(file);
|
|
3496
|
+
continue;
|
|
3497
|
+
}
|
|
3498
|
+
if (edit2.format === "rules" || file.format === "rules")
|
|
3499
|
+
continue;
|
|
3500
|
+
const orphanOps = file.ops.filter((op) => !edit2.ops.some((candidate) => candidate.op === op.op && candidate.path.join("\x00") === op.path.join("\x00")));
|
|
3501
|
+
if (orphanOps.length > 0)
|
|
3502
|
+
reverts.push({ ...file, ops: orphanOps });
|
|
3503
|
+
}
|
|
3504
|
+
if (reverts.length === 0)
|
|
3505
|
+
return plan;
|
|
3506
|
+
return { ...plan, reverts };
|
|
3507
|
+
}
|
|
3508
|
+
var HOST_PLANNERS;
|
|
3509
|
+
var init_hosts = __esm(() => {
|
|
3510
|
+
init_codex();
|
|
3511
|
+
init_opencode();
|
|
3512
|
+
init_pi();
|
|
3513
|
+
init_constants();
|
|
3514
|
+
init_state();
|
|
3515
|
+
HOST_PLANNERS = {
|
|
3516
|
+
opencode: planOpenCode,
|
|
3517
|
+
pi: planPi,
|
|
3518
|
+
codex: planCodex
|
|
3519
|
+
};
|
|
3520
|
+
});
|
|
3521
|
+
|
|
3522
|
+
// src/installer/revert.ts
|
|
3523
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, rmdirSync, unlinkSync } from "node:fs";
|
|
3524
|
+
import { dirname as dirname2 } from "node:path";
|
|
3525
|
+
function pruneEmptyDir(dir) {
|
|
3526
|
+
try {
|
|
3527
|
+
rmdirSync(dir);
|
|
3528
|
+
} catch {}
|
|
3529
|
+
}
|
|
3530
|
+
function revertRecordedFile(file, host, opts) {
|
|
3531
|
+
const lines = [];
|
|
3532
|
+
if (!existsSync6(file.file)) {
|
|
3533
|
+
lines.push(`already absent: ${file.file}${opts.label}`);
|
|
3534
|
+
return lines;
|
|
3535
|
+
}
|
|
3536
|
+
const codec = codecFor(file.format, host);
|
|
3537
|
+
const text = readFileSync6(file.file, "utf8");
|
|
3538
|
+
if (file.format === "rules") {
|
|
3539
|
+
const edit2 = { file: file.file, format: "rules", block: file.blockApplied ?? "" };
|
|
3540
|
+
if (!codec.verify(text, edit2)) {
|
|
3541
|
+
lines.push(`no rules block${opts.label} in ${file.file}; left untouched`);
|
|
3542
|
+
return lines;
|
|
3543
|
+
}
|
|
3544
|
+
const updated = codec.revert(text, file).text;
|
|
3545
|
+
if (opts.whole && codec.isEffectivelyEmpty(updated)) {
|
|
3546
|
+
unlinkSync(file.file);
|
|
3547
|
+
pruneEmptyDir(dirname2(file.file));
|
|
3548
|
+
lines.push(`deleted ${file.file} (installer-created, now empty)`);
|
|
3549
|
+
} else {
|
|
3550
|
+
writeConfig(file.file, updated);
|
|
3551
|
+
lines.push(`removed rules block${opts.label} from ${file.file}`);
|
|
3552
|
+
}
|
|
3553
|
+
return lines;
|
|
3554
|
+
}
|
|
3555
|
+
const reverted = codec.revert(text, file);
|
|
3556
|
+
if (opts.whole && file.created && codec.isEffectivelyEmpty(reverted.text)) {
|
|
3557
|
+
unlinkSync(file.file);
|
|
3558
|
+
pruneEmptyDir(dirname2(file.file));
|
|
3559
|
+
lines.push(`deleted ${file.file} (installer-created, now empty)`);
|
|
3560
|
+
} else {
|
|
3561
|
+
writeConfig(file.file, reverted.text);
|
|
3562
|
+
lines.push(`reverted artifacts${opts.label} in ${file.file}`);
|
|
3563
|
+
}
|
|
3564
|
+
lines.push(...reverted.notes.map((note) => ` note: ${note}`));
|
|
3565
|
+
return lines;
|
|
3566
|
+
}
|
|
3567
|
+
var init_revert = __esm(() => {
|
|
3568
|
+
init_formats();
|
|
3569
|
+
});
|
|
3570
|
+
|
|
3571
|
+
// src/installer/apply.ts
|
|
3572
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
|
|
3573
|
+
function applyPlan(plan, input) {
|
|
3574
|
+
if (plan.errors.length > 0) {
|
|
3575
|
+
throw new Error(`refusing to apply a plan with errors: ${plan.errors.map((error) => error.message).join("; ")}`);
|
|
3576
|
+
}
|
|
3577
|
+
assertNoDrift(plan);
|
|
3578
|
+
const previous = readRecord(input);
|
|
3579
|
+
const prepared = plan.edits.map((edit2) => prepareEdit(edit2, plan.host));
|
|
3580
|
+
const files = [];
|
|
3581
|
+
const lines = [];
|
|
3582
|
+
for (const item of prepared) {
|
|
3583
|
+
item.write();
|
|
3584
|
+
files.push(mergeRecorded(item.recorded, previous?.files.find((file) => file.file === item.edit.file)));
|
|
3585
|
+
lines.push(`${item.recorded.created ? "created" : "updated"} ${item.edit.file}`);
|
|
3586
|
+
}
|
|
3587
|
+
if ((plan.reverts ?? []).length > 0) {
|
|
3588
|
+
lines.push(...applyReverts(plan));
|
|
3589
|
+
}
|
|
3590
|
+
const record = {
|
|
3591
|
+
version: 1,
|
|
3592
|
+
host: plan.host,
|
|
3593
|
+
scope: plan.scope,
|
|
3594
|
+
tiers: plan.tiers,
|
|
3595
|
+
createdAt: new Date().toISOString(),
|
|
3596
|
+
files
|
|
3597
|
+
};
|
|
3598
|
+
writeRecord(input, record);
|
|
3599
|
+
const verification = verifyEdits(plan.edits, plan.host);
|
|
3600
|
+
lines.push(...verification.lines);
|
|
3601
|
+
return { lines, ok: verification.ok };
|
|
3602
|
+
}
|
|
3603
|
+
function assertNoDrift(plan) {
|
|
3604
|
+
const drifts = [];
|
|
3605
|
+
for (const edit2 of plan.edits) {
|
|
3606
|
+
if (edit2.format === "rules")
|
|
3607
|
+
continue;
|
|
3608
|
+
const loaded = codecFor(edit2.format, plan.host).load(edit2.file);
|
|
3609
|
+
if (loaded.parseError) {
|
|
3610
|
+
drifts.push(`${edit2.file} no longer parses (${loaded.parseError})`);
|
|
3611
|
+
continue;
|
|
3612
|
+
}
|
|
3613
|
+
for (const op of edit2.ops) {
|
|
3614
|
+
if (op.op !== "set")
|
|
3615
|
+
continue;
|
|
3616
|
+
const current = valueAt(loaded.value, op.path);
|
|
3617
|
+
if (!deepEqual(current, op.previous)) {
|
|
3618
|
+
drifts.push(`${edit2.file}: ${op.path.join(".")} changed since the plan was rendered`);
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
if (drifts.length > 0) {
|
|
3623
|
+
throw new Error(`refusing to apply — the config changed since the plan was rendered: ${drifts.join("; ")}. ` + "Re-run init to re-plan against the current files.");
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
function prepareEdit(edit2, host) {
|
|
3627
|
+
const codec = codecFor(edit2.format, host);
|
|
3628
|
+
const loaded = codec.load(edit2.file);
|
|
3629
|
+
if (loaded.parseError) {
|
|
3630
|
+
throw new Error(`${edit2.file} does not parse: ${loaded.parseError}`);
|
|
3631
|
+
}
|
|
3632
|
+
const applied = codec.apply(loaded.text, edit2);
|
|
3633
|
+
const recorded = edit2.format === "rules" ? { file: edit2.file, format: "rules", created: !loaded.exists, ops: [], blockApplied: edit2.block } : { file: edit2.file, format: edit2.format, created: !loaded.exists, ops: applied.recorded, createdParents: applied.createdParents };
|
|
3634
|
+
return {
|
|
3635
|
+
edit: edit2,
|
|
3636
|
+
recorded,
|
|
3637
|
+
write: () => writeConfig(edit2.file, applied.text)
|
|
3638
|
+
};
|
|
3639
|
+
}
|
|
3640
|
+
function applyReverts(plan) {
|
|
3641
|
+
const lines = [];
|
|
3642
|
+
for (const revert of plan.reverts ?? []) {
|
|
3643
|
+
const whole = !plan.edits.some((edit2) => edit2.file === revert.file);
|
|
3644
|
+
lines.push(...revertRecordedFile(revert, plan.host, { label: " (previous init)", whole }));
|
|
3645
|
+
}
|
|
3646
|
+
return lines;
|
|
3647
|
+
}
|
|
3648
|
+
function mergeRecorded(current, before) {
|
|
3649
|
+
if (before === undefined)
|
|
3650
|
+
return current;
|
|
3651
|
+
const ops = current.ops.map((op) => {
|
|
3652
|
+
const old = before.ops.find((candidate) => candidate.op === op.op && candidate.path.join("\x00") === op.path.join("\x00"));
|
|
3653
|
+
if (old === undefined)
|
|
3654
|
+
return op;
|
|
3655
|
+
if (op.op === "set" && old.op === "set" && deepEqual(op.previous, old.applied)) {
|
|
3656
|
+
return { ...op, previous: old.previous };
|
|
3657
|
+
}
|
|
3658
|
+
if (op.op === "append-array" && old.op === "append-array") {
|
|
3659
|
+
return { ...op, applied: [...old.applied, ...op.applied] };
|
|
3660
|
+
}
|
|
3661
|
+
return op;
|
|
3662
|
+
});
|
|
3663
|
+
return {
|
|
3664
|
+
...current,
|
|
3665
|
+
created: before.created,
|
|
3666
|
+
ops,
|
|
3667
|
+
createdParents: [...before.createdParents ?? [], ...current.createdParents ?? []]
|
|
3668
|
+
};
|
|
3669
|
+
}
|
|
3670
|
+
function verifyEdits(edits, host) {
|
|
3671
|
+
const lines = [];
|
|
3672
|
+
let ok = true;
|
|
3673
|
+
for (const edit2 of edits) {
|
|
3674
|
+
if (!existsSync7(edit2.file)) {
|
|
3675
|
+
lines.push(`FAIL ${edit2.file} does not exist after apply`);
|
|
3676
|
+
ok = false;
|
|
3677
|
+
continue;
|
|
3678
|
+
}
|
|
3679
|
+
const codec = codecFor(edit2.format, host);
|
|
3680
|
+
const text = readFileSync7(edit2.file, "utf8");
|
|
3681
|
+
if (edit2.format === "rules") {
|
|
3682
|
+
const good = codec.verify(text, edit2);
|
|
3683
|
+
lines.push(`${good ? "pass" : "FAIL"} ${edit2.file}: rules block ${good ? "present" : "missing"}`);
|
|
3684
|
+
ok = ok && good;
|
|
3685
|
+
continue;
|
|
3686
|
+
}
|
|
3687
|
+
for (const op of edit2.ops) {
|
|
3688
|
+
const good = codec.verify(text, edit2, op);
|
|
3689
|
+
lines.push(`${good ? "pass" : "FAIL"} ${edit2.file}: ${describeOp(op)} ${good ? "holds" : "missing"}`);
|
|
3690
|
+
ok = ok && good;
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
return { lines, ok };
|
|
3694
|
+
}
|
|
3695
|
+
function describeOp(op) {
|
|
3696
|
+
if (op.op === "set")
|
|
3697
|
+
return `set ${op.path.join(".")}`;
|
|
3698
|
+
return `append ${op.path.join(".")}`;
|
|
3699
|
+
}
|
|
3700
|
+
var init_apply = __esm(() => {
|
|
3701
|
+
init_formats();
|
|
3702
|
+
init_revert();
|
|
3703
|
+
init_state();
|
|
3704
|
+
});
|
|
3705
|
+
|
|
3706
|
+
// src/installer/render.ts
|
|
3707
|
+
function renderPlan(plan) {
|
|
3708
|
+
const lines = [];
|
|
3709
|
+
lines.push(`Install plan: ${plan.host} (${plan.scope} scope)`);
|
|
3710
|
+
lines.push(`Tiers: search=${plan.tiers.search}, fetch=${plan.tiers.fetch}`);
|
|
3711
|
+
lines.push("");
|
|
3712
|
+
lines.push("Files:");
|
|
3713
|
+
for (const edit2 of plan.edits) {
|
|
3714
|
+
lines.push(` ${edit2.file}`);
|
|
3715
|
+
if (edit2.format === "rules") {
|
|
3716
|
+
lines.push(" upsert marked rules block");
|
|
3717
|
+
continue;
|
|
3718
|
+
}
|
|
3719
|
+
for (const op of edit2.ops) {
|
|
3720
|
+
if (op.op === "set") {
|
|
3721
|
+
const was = op.previous === undefined ? "(absent)" : preview(op.previous);
|
|
3722
|
+
lines.push(` set ${op.path.join(".")} = ${preview(op.value)} (was ${was})`);
|
|
3723
|
+
} else {
|
|
3724
|
+
const count = (op.entries ?? []).length;
|
|
3725
|
+
const kept = op.existingCount !== undefined ? ` (${op.existingCount} existing kept)` : "";
|
|
3726
|
+
lines.push(` append ${count} entr${count === 1 ? "y" : "ies"} to ${op.path.join(".")}${kept}`);
|
|
3727
|
+
for (const entry of op.entries ?? [])
|
|
3728
|
+
lines.push(` + ${preview(entry)}`);
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
if (plan.reverts && plan.reverts.length > 0) {
|
|
3733
|
+
lines.push("");
|
|
3734
|
+
lines.push("Reverts (artifacts from the previous init that this plan no longer wants):");
|
|
3735
|
+
for (const revert of plan.reverts) {
|
|
3736
|
+
lines.push(` ${revert.file}`);
|
|
3737
|
+
if (revert.format === "rules") {
|
|
3738
|
+
lines.push(" remove rules block");
|
|
3739
|
+
continue;
|
|
3740
|
+
}
|
|
3741
|
+
for (const op of revert.ops) {
|
|
3742
|
+
if (op.op === "set") {
|
|
3743
|
+
lines.push(op.previous === undefined ? ` remove ${op.path.join(".")} (was not set before this install)` : ` restore ${op.path.join(".")} = ${preview(op.previous)}`);
|
|
3744
|
+
} else {
|
|
3745
|
+
const count = Array.isArray(op.applied) ? op.applied.length : 0;
|
|
3746
|
+
lines.push(` remove ${count} appended entr${count === 1 ? "y" : "ies"} from ${op.path.join(".")}`);
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
if (plan.notes.length > 0) {
|
|
3752
|
+
lines.push("");
|
|
3753
|
+
lines.push("Notes:");
|
|
3754
|
+
for (const note of plan.notes)
|
|
3755
|
+
lines.push(` - ${note}`);
|
|
3756
|
+
}
|
|
3757
|
+
return lines.join(`
|
|
3758
|
+
`);
|
|
3759
|
+
}
|
|
3760
|
+
function preview(value) {
|
|
3761
|
+
const text = JSON.stringify(value) ?? String(value);
|
|
3762
|
+
return text.length > 100 ? `${text.slice(0, 97)}...` : text;
|
|
3763
|
+
}
|
|
3764
|
+
|
|
3765
|
+
// src/installer/uninstall.ts
|
|
3766
|
+
function uninstall(input) {
|
|
3767
|
+
const record = readRecord(input);
|
|
3768
|
+
if (record === undefined) {
|
|
3769
|
+
throw new Error(`No ${input.host} install is recorded for the ${input.scope} scope.`);
|
|
3770
|
+
}
|
|
3771
|
+
const other = input.scope === "global" ? "project" : "global";
|
|
3772
|
+
const overlap = claimedByOtherScope(input, record.files.map((file) => file.file));
|
|
3773
|
+
if (overlap.length > 0) {
|
|
3774
|
+
throw new Error(`A ${input.host} install is also recorded at the ${other} scope and claims the same file(s): ${overlap.join(", ")}. ` + `Uninstall the ${other}-scope install first so this rollback cannot clobber its entries.`);
|
|
3775
|
+
}
|
|
3776
|
+
const lines = [];
|
|
3777
|
+
for (const file of [...record.files].reverse()) {
|
|
3778
|
+
lines.push(...revertRecordedFile(file, record.host, { label: "", whole: true }));
|
|
3779
|
+
}
|
|
3780
|
+
deleteRecord(input);
|
|
3781
|
+
pruneEmptyDir(stateDir(input, input.scope));
|
|
3782
|
+
lines.push(`removed install record (${input.host}, ${input.scope})`);
|
|
3783
|
+
return lines;
|
|
3784
|
+
}
|
|
3785
|
+
var init_uninstall = __esm(() => {
|
|
3786
|
+
init_revert();
|
|
3787
|
+
init_state();
|
|
3788
|
+
});
|
|
3789
|
+
|
|
3790
|
+
// src/installer/cli.ts
|
|
3791
|
+
var exports_cli = {};
|
|
3792
|
+
__export(exports_cli, {
|
|
3793
|
+
runInstallerCli: () => runInstallerCli
|
|
3794
|
+
});
|
|
3795
|
+
import { homedir } from "node:os";
|
|
3796
|
+
import { resolve } from "node:path";
|
|
3797
|
+
function parseFlags(args) {
|
|
3798
|
+
const values = new Map;
|
|
3799
|
+
const booleans = new Set;
|
|
3800
|
+
const problems = [];
|
|
3801
|
+
for (let i = 0;i < args.length; i += 1) {
|
|
3802
|
+
const arg = args[i];
|
|
3803
|
+
if (!arg.startsWith("--")) {
|
|
3804
|
+
problems.push(`unexpected argument "${arg}" (flags only)`);
|
|
3805
|
+
continue;
|
|
3806
|
+
}
|
|
3807
|
+
const eq = arg.indexOf("=");
|
|
3808
|
+
const name = eq === -1 ? arg.slice(2) : arg.slice(2, eq);
|
|
3809
|
+
if (BOOLEAN_FLAGS.has(name)) {
|
|
3810
|
+
booleans.add(name);
|
|
3811
|
+
continue;
|
|
3812
|
+
}
|
|
3813
|
+
if (!VALUE_FLAGS.has(name)) {
|
|
3814
|
+
problems.push(`unknown flag --${name}`);
|
|
3815
|
+
continue;
|
|
3816
|
+
}
|
|
3817
|
+
if (eq !== -1) {
|
|
3818
|
+
values.set(name, arg.slice(eq + 1));
|
|
3819
|
+
continue;
|
|
3820
|
+
}
|
|
3821
|
+
const next = args[i + 1];
|
|
3822
|
+
if (next === undefined || next.startsWith("--")) {
|
|
3823
|
+
problems.push(`--${name} requires a value`);
|
|
3824
|
+
continue;
|
|
3825
|
+
}
|
|
3826
|
+
values.set(name, next);
|
|
3827
|
+
i += 1;
|
|
3828
|
+
}
|
|
3829
|
+
return { values, booleans, problems };
|
|
3830
|
+
}
|
|
3831
|
+
async function runInstallerCli(argv, io = {}) {
|
|
3832
|
+
const out = io.out ?? ((line) => console.log(line));
|
|
3833
|
+
const err = io.err ?? ((line) => console.error(line));
|
|
3834
|
+
const [command, ...rest] = argv;
|
|
3835
|
+
if (command === undefined || command === "help" || command === "--help") {
|
|
3836
|
+
out(USAGE);
|
|
3837
|
+
return command === undefined ? 1 : 0;
|
|
3838
|
+
}
|
|
3839
|
+
const flags = parseFlags(rest);
|
|
3840
|
+
if (flags.problems.length > 0) {
|
|
3841
|
+
for (const problem of flags.problems)
|
|
3842
|
+
err(`error: ${problem}`);
|
|
3843
|
+
err(`
|
|
3844
|
+
${USAGE}`);
|
|
3845
|
+
return 1;
|
|
3846
|
+
}
|
|
3847
|
+
const cwd = resolve(flags.values.get("cwd") ?? process.cwd());
|
|
3848
|
+
const home = process.env.HOME ?? homedir();
|
|
3849
|
+
const configHome2 = resolveConfigHome(home);
|
|
3850
|
+
if (command === "list") {
|
|
3851
|
+
const records = listRecords({ home, cwd, configHome: configHome2 });
|
|
3852
|
+
if (records.length === 0) {
|
|
3853
|
+
out("No installs recorded.");
|
|
3854
|
+
return 0;
|
|
3855
|
+
}
|
|
3856
|
+
for (const record of records) {
|
|
3857
|
+
out(`${record.host} (${record.scope}) — search=${record.tiers.search}, fetch=${record.tiers.fetch}, installed ${record.createdAt}`);
|
|
3858
|
+
for (const file of record.files)
|
|
3859
|
+
out(` ${file.created ? "created" : "modified"} ${file.file}`);
|
|
3860
|
+
}
|
|
3861
|
+
return 0;
|
|
3862
|
+
}
|
|
3863
|
+
if (command === "uninstall") {
|
|
3864
|
+
const required2 = requireInput(flags, cwd, home, configHome2, false);
|
|
3865
|
+
if (!required2.ok)
|
|
3866
|
+
return usageError(required2.problems, err);
|
|
3867
|
+
try {
|
|
3868
|
+
for (const line of uninstall(required2.input))
|
|
3869
|
+
out(line);
|
|
3870
|
+
return 0;
|
|
3871
|
+
} catch (error) {
|
|
3872
|
+
err(error instanceof Error ? error.message : String(error));
|
|
3873
|
+
return 1;
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
if (command !== "init") {
|
|
3877
|
+
err(`Unknown command "${command}".
|
|
3878
|
+
|
|
3879
|
+
${USAGE}`);
|
|
3880
|
+
return 1;
|
|
3881
|
+
}
|
|
3882
|
+
const required = requireInput(flags, cwd, home, configHome2, true);
|
|
3883
|
+
if (!required.ok)
|
|
3884
|
+
return usageError(required.problems, err);
|
|
3885
|
+
const { input } = required;
|
|
3886
|
+
const plan = planForHost(input.host, input);
|
|
3887
|
+
if (plan.errors.length > 0) {
|
|
3888
|
+
for (const error of plan.errors)
|
|
3889
|
+
err(`error: ${error.message}`);
|
|
3890
|
+
err("Nothing was written.");
|
|
3891
|
+
return 1;
|
|
3892
|
+
}
|
|
3893
|
+
out(renderPlan(plan));
|
|
3894
|
+
if (!flags.booleans.has("apply")) {
|
|
3895
|
+
out(`
|
|
3896
|
+
Plan only — re-run with --apply to write these changes.`);
|
|
3897
|
+
return 0;
|
|
3898
|
+
}
|
|
3899
|
+
try {
|
|
3900
|
+
const result = applyPlan(plan, input);
|
|
3901
|
+
for (const line of result.lines)
|
|
3902
|
+
out(line);
|
|
3903
|
+
return result.ok ? 0 : 1;
|
|
3904
|
+
} catch (error) {
|
|
3905
|
+
err(error instanceof Error ? error.message : String(error));
|
|
3906
|
+
return 1;
|
|
3907
|
+
}
|
|
3908
|
+
}
|
|
3909
|
+
function usageError(problems, err) {
|
|
3910
|
+
for (const problem of problems)
|
|
3911
|
+
err(`error: ${problem}`);
|
|
3912
|
+
err(`
|
|
3913
|
+
${USAGE}`);
|
|
3914
|
+
return 1;
|
|
3915
|
+
}
|
|
3916
|
+
function resolveConfigHome(home) {
|
|
3917
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
3918
|
+
if (xdg && home === (process.env.HOME ?? ""))
|
|
3919
|
+
return xdg;
|
|
3920
|
+
return;
|
|
3921
|
+
}
|
|
3922
|
+
function requireInput(flags, cwd, home, configHome2, needsTiers) {
|
|
3923
|
+
const problems = [];
|
|
3924
|
+
const host = flags.values.get("host");
|
|
3925
|
+
const scope = flags.values.get("scope");
|
|
3926
|
+
const search = needsTiers ? flags.values.get("search") ?? "" : "optional";
|
|
3927
|
+
const fetch = needsTiers ? flags.values.get("fetch") ?? "" : "optional";
|
|
3928
|
+
if (host === undefined)
|
|
3929
|
+
problems.push(`--host is required (one of: ${HOSTS.join(", ")})`);
|
|
3930
|
+
else if (!HOSTS.includes(host))
|
|
3931
|
+
problems.push(`invalid --host value "${host}" (one of: ${HOSTS.join(", ")})`);
|
|
3932
|
+
if (scope === undefined)
|
|
3933
|
+
problems.push(`--scope is required (one of: ${SCOPES.join(", ")})`);
|
|
3934
|
+
else if (!SCOPES.includes(scope))
|
|
3935
|
+
problems.push(`invalid --scope value "${scope}" (one of: ${SCOPES.join(", ")})`);
|
|
3936
|
+
if (needsTiers) {
|
|
3937
|
+
if (!TIERS.includes(search)) {
|
|
3938
|
+
problems.push(flags.values.has("search") ? `invalid --search value "${search}" (one of: ${TIERS.join(", ")})` : `--search is required (one of: ${TIERS.join(", ")})`);
|
|
3939
|
+
}
|
|
3940
|
+
if (!TIERS.includes(fetch)) {
|
|
3941
|
+
problems.push(flags.values.has("fetch") ? `invalid --fetch value "${fetch}" (one of: ${TIERS.join(", ")})` : `--fetch is required (one of: ${TIERS.join(", ")})`);
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
if (home === "")
|
|
3945
|
+
problems.push("HOME is not set and the user home cannot be resolved; cannot proceed");
|
|
3946
|
+
if (problems.length > 0)
|
|
3947
|
+
return { ok: false, problems };
|
|
3948
|
+
return {
|
|
3949
|
+
ok: true,
|
|
3950
|
+
input: {
|
|
3951
|
+
host,
|
|
3952
|
+
scope,
|
|
3953
|
+
search,
|
|
3954
|
+
fetch,
|
|
3955
|
+
packageRef: flags.values.get("package") ?? "deepseek-web-retrieval",
|
|
3956
|
+
home,
|
|
3957
|
+
cwd,
|
|
3958
|
+
configHome: configHome2
|
|
3959
|
+
}
|
|
3960
|
+
};
|
|
3961
|
+
}
|
|
3962
|
+
var HOSTS, HOST_CHOICES, SCOPES, TIERS, USAGE, VALUE_FLAGS, BOOLEAN_FLAGS;
|
|
3963
|
+
var init_cli = __esm(() => {
|
|
3964
|
+
init_hosts();
|
|
3965
|
+
init_apply();
|
|
3966
|
+
init_state();
|
|
3967
|
+
init_uninstall();
|
|
3968
|
+
HOSTS = Object.keys(HOST_PLANNERS);
|
|
3969
|
+
HOST_CHOICES = `<${HOSTS.join("|")}>`;
|
|
3970
|
+
SCOPES = ["project", "global"];
|
|
3971
|
+
TIERS = ["optional", "preferred", "forced", "off"];
|
|
3972
|
+
USAGE = `Usage:
|
|
3973
|
+
deepseek-web-retrieval init --host ${HOST_CHOICES} --scope <project|global> --search <optional|preferred|forced|off> --fetch <optional|preferred|forced|off> [--package <npm ref>] [--cwd <dir>] [--apply]
|
|
3974
|
+
deepseek-web-retrieval uninstall --host ${HOST_CHOICES} --scope <project|global> [--cwd <dir>]
|
|
3975
|
+
deepseek-web-retrieval list [--cwd <dir>]
|
|
3976
|
+
|
|
3977
|
+
init prints the full plan (every file, old value → new value) and writes nothing
|
|
3978
|
+
until --apply is passed. uninstall restores what the plan applied.`;
|
|
3979
|
+
VALUE_FLAGS = new Set(["host", "scope", "search", "fetch", "package", "cwd"]);
|
|
3980
|
+
BOOLEAN_FLAGS = new Set(["apply"]);
|
|
3981
|
+
});
|
|
2
3982
|
|
|
3
3983
|
// src/mcp/cli.ts
|
|
4
3984
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
5
3985
|
|
|
6
3986
|
// src/core/auth.ts
|
|
7
|
-
|
|
3987
|
+
init_constants();
|
|
8
3988
|
function apiKeyFromEnv(env = process.env) {
|
|
9
3989
|
const key = env[API_KEY_ENV]?.trim();
|
|
10
3990
|
return key ? key : undefined;
|
|
11
3991
|
}
|
|
12
3992
|
|
|
13
3993
|
// src/mcp/auth.ts
|
|
14
|
-
|
|
3994
|
+
init_constants();
|
|
3995
|
+
var MISSING_API_KEY_MESSAGE = `DeepSeek API key not found. Set ${API_KEY_ENV} in the MCP server's env configuration.`;
|
|
15
3996
|
function requireApiKey(env) {
|
|
16
3997
|
const apiKey = apiKeyFromEnv(env);
|
|
17
3998
|
if (!apiKey)
|
|
@@ -19,30 +4000,11 @@ function requireApiKey(env) {
|
|
|
19
4000
|
return apiKey;
|
|
20
4001
|
}
|
|
21
4002
|
|
|
22
|
-
// src/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
var DEFAULT_MIN_RERANK = 1.5;
|
|
28
|
-
var DEFAULT_MIN_AUTHORITY = 2;
|
|
29
|
-
var DEFAULT_MAX_SUMMARY_CHARS = 1200;
|
|
30
|
-
var DEFAULT_FETCH_MAX_CHARS = 16000;
|
|
31
|
-
var DEFAULT_TIMEOUT_MS = 30000;
|
|
32
|
-
var MIN_TIMEOUT_MS = 1000;
|
|
33
|
-
var MAX_TIMEOUT_MS = 120000;
|
|
34
|
-
var MAX_QUERY_CHARS = 128;
|
|
35
|
-
var MAX_URL_CHARS = 8192;
|
|
36
|
-
var MAX_ERROR_BODY_CHARS = 2000;
|
|
37
|
-
var MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
38
|
-
var FETCH_TRUNCATION_MARKER = `
|
|
39
|
-
|
|
40
|
-
[content truncated]`;
|
|
41
|
-
var DEFAULT_API_KEY_SOURCE = "auto";
|
|
42
|
-
var DEFAULT_MAX_RETRIES = 0;
|
|
43
|
-
var MAX_RETRIES = 5;
|
|
44
|
-
var DEFAULT_RETRY_BASE_DELAY_MS = 250;
|
|
45
|
-
var MAX_RETRY_DELAY_MS = 1e4;
|
|
4003
|
+
// src/mcp/config.ts
|
|
4004
|
+
init_constants();
|
|
4005
|
+
|
|
4006
|
+
// src/core/options.ts
|
|
4007
|
+
init_constants();
|
|
46
4008
|
|
|
47
4009
|
// src/core/domains.ts
|
|
48
4010
|
import { isIP } from "node:net";
|
|
@@ -172,7 +4134,7 @@ function resolveSearchOptions(input) {
|
|
|
172
4134
|
language: optionalText(input?.language),
|
|
173
4135
|
maxSummaryChars: clampInt(input?.maxSummaryChars, DEFAULT_MAX_SUMMARY_CHARS, 0, 1e6),
|
|
174
4136
|
timeoutMs: clampInt(input?.searchTimeoutMs, DEFAULT_TIMEOUT_MS, MIN_TIMEOUT_MS, MAX_TIMEOUT_MS),
|
|
175
|
-
|
|
4137
|
+
enabled: input?.searchEnabled !== false
|
|
176
4138
|
};
|
|
177
4139
|
}
|
|
178
4140
|
function resolveFetchOptions(input) {
|
|
@@ -181,9 +4143,8 @@ function resolveFetchOptions(input) {
|
|
|
181
4143
|
allowedDomains: normalizeDomains(input?.fetchAllowedDomains),
|
|
182
4144
|
blockedDomains: normalizeDomains(input?.fetchBlockedDomains),
|
|
183
4145
|
timeoutMs: clampInt(input?.fetchTimeoutMs, DEFAULT_TIMEOUT_MS, MIN_TIMEOUT_MS, MAX_TIMEOUT_MS),
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
blockPrivateHosts: input?.fetchBlockPrivateHosts !== false
|
|
4146
|
+
blockPrivateHosts: input?.fetchBlockPrivateHosts !== false,
|
|
4147
|
+
enabled: input?.fetchEnabled !== false
|
|
187
4148
|
};
|
|
188
4149
|
}
|
|
189
4150
|
function resolveAuthOptions(input) {
|
|
@@ -213,33 +4174,63 @@ function clampInt(value, fallback, min, max) {
|
|
|
213
4174
|
}
|
|
214
4175
|
|
|
215
4176
|
// src/mcp/config.ts
|
|
4177
|
+
var NUMBER_ENV = {
|
|
4178
|
+
count: "DEEPSEEK_SEARCH_COUNT",
|
|
4179
|
+
maxResults: "DEEPSEEK_SEARCH_MAX_RESULTS",
|
|
4180
|
+
minRerank: "DEEPSEEK_SEARCH_MIN_RERANK",
|
|
4181
|
+
minAuthority: "DEEPSEEK_SEARCH_MIN_AUTHORITY",
|
|
4182
|
+
maxSummaryChars: "DEEPSEEK_SEARCH_MAX_SUMMARY_CHARS",
|
|
4183
|
+
searchTimeoutMs: "DEEPSEEK_SEARCH_TIMEOUT_MS",
|
|
4184
|
+
fetchMaxChars: "DEEPSEEK_FETCH_MAX_CHARS",
|
|
4185
|
+
fetchTimeoutMs: "DEEPSEEK_FETCH_TIMEOUT_MS",
|
|
4186
|
+
maxRetries: "DEEPSEEK_MAX_RETRIES",
|
|
4187
|
+
retryBaseDelayMs: "DEEPSEEK_RETRY_BASE_DELAY_MS"
|
|
4188
|
+
};
|
|
4189
|
+
var TEXT_ENV = {
|
|
4190
|
+
language: "DEEPSEEK_SEARCH_LANGUAGE"
|
|
4191
|
+
};
|
|
4192
|
+
var DOMAINS_ENV = {
|
|
4193
|
+
blockedDomains: "DEEPSEEK_SEARCH_BLOCKED_DOMAINS",
|
|
4194
|
+
includeDomains: "DEEPSEEK_SEARCH_INCLUDE_DOMAINS",
|
|
4195
|
+
fetchAllowedDomains: "DEEPSEEK_FETCH_ALLOWED_DOMAINS",
|
|
4196
|
+
fetchBlockedDomains: "DEEPSEEK_FETCH_BLOCKED_DOMAINS"
|
|
4197
|
+
};
|
|
4198
|
+
var FLAG_ENV = {
|
|
4199
|
+
allowUnknownAuthority: "DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY"
|
|
4200
|
+
};
|
|
4201
|
+
var FALSE_ONLY_ENV = {
|
|
4202
|
+
fetchBlockPrivateHosts: "DEEPSEEK_FETCH_BLOCK_PRIVATE_HOSTS",
|
|
4203
|
+
searchEnabled: ENABLE_SEARCH_ENV,
|
|
4204
|
+
fetchEnabled: ENABLE_FETCH_ENV
|
|
4205
|
+
};
|
|
216
4206
|
function resolveEnvOptions(env = process.env) {
|
|
217
4207
|
return resolvePluginOptions(pluginOptionsFromEnv(env));
|
|
218
4208
|
}
|
|
219
4209
|
function pluginOptionsFromEnv(env) {
|
|
220
4210
|
const options = {};
|
|
221
|
-
putNumber(options, "count", env
|
|
222
|
-
putNumber(options, "maxResults", env
|
|
223
|
-
putNumber(options, "minRerank", env
|
|
224
|
-
putNumber(options, "minAuthority", env
|
|
225
|
-
putBoolean(options, "allowUnknownAuthority", env
|
|
226
|
-
putDomains(options, "blockedDomains", env
|
|
227
|
-
putDomains(options, "includeDomains", env
|
|
228
|
-
putText(options, "language", env
|
|
229
|
-
putNumber(options, "maxSummaryChars", env
|
|
230
|
-
putNumber(options, "searchTimeoutMs", env
|
|
231
|
-
putNumber(options, "fetchMaxChars", env
|
|
232
|
-
putDomains(options, "fetchAllowedDomains", env
|
|
233
|
-
putDomains(options, "fetchBlockedDomains", env
|
|
234
|
-
putNumber(options, "fetchTimeoutMs", env
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
putNumber(options, "maxRetries", env
|
|
239
|
-
putNumber(options, "retryBaseDelayMs", env
|
|
4211
|
+
putNumber(options, "count", env);
|
|
4212
|
+
putNumber(options, "maxResults", env);
|
|
4213
|
+
putNumber(options, "minRerank", env);
|
|
4214
|
+
putNumber(options, "minAuthority", env);
|
|
4215
|
+
putBoolean(options, "allowUnknownAuthority", env);
|
|
4216
|
+
putDomains(options, "blockedDomains", env);
|
|
4217
|
+
putDomains(options, "includeDomains", env);
|
|
4218
|
+
putText(options, "language", env);
|
|
4219
|
+
putNumber(options, "maxSummaryChars", env);
|
|
4220
|
+
putNumber(options, "searchTimeoutMs", env);
|
|
4221
|
+
putNumber(options, "fetchMaxChars", env);
|
|
4222
|
+
putDomains(options, "fetchAllowedDomains", env);
|
|
4223
|
+
putDomains(options, "fetchBlockedDomains", env);
|
|
4224
|
+
putNumber(options, "fetchTimeoutMs", env);
|
|
4225
|
+
putFalseOnly(options, "fetchBlockPrivateHosts", env);
|
|
4226
|
+
putFalseOnly(options, "searchEnabled", env);
|
|
4227
|
+
putFalseOnly(options, "fetchEnabled", env);
|
|
4228
|
+
putNumber(options, "maxRetries", env);
|
|
4229
|
+
putNumber(options, "retryBaseDelayMs", env);
|
|
240
4230
|
return options;
|
|
241
4231
|
}
|
|
242
|
-
function putNumber(target, key,
|
|
4232
|
+
function putNumber(target, key, env) {
|
|
4233
|
+
const value = env[NUMBER_ENV[key]];
|
|
243
4234
|
if (value === undefined)
|
|
244
4235
|
return;
|
|
245
4236
|
const trimmed = value.trim();
|
|
@@ -249,18 +4240,24 @@ function putNumber(target, key, value) {
|
|
|
249
4240
|
if (Number.isFinite(parsed))
|
|
250
4241
|
target[key] = parsed;
|
|
251
4242
|
}
|
|
252
|
-
function putText(target, key,
|
|
4243
|
+
function putText(target, key, env) {
|
|
4244
|
+
const value = env[TEXT_ENV[key]];
|
|
253
4245
|
if (value === undefined)
|
|
254
4246
|
return;
|
|
255
4247
|
const trimmed = value.trim();
|
|
256
4248
|
if (trimmed)
|
|
257
4249
|
target[key] = trimmed;
|
|
258
4250
|
}
|
|
259
|
-
function putBoolean(target, key,
|
|
260
|
-
if (isTrueValue(
|
|
4251
|
+
function putBoolean(target, key, env) {
|
|
4252
|
+
if (isTrueValue(env[FLAG_ENV[key]]))
|
|
261
4253
|
target[key] = true;
|
|
262
4254
|
}
|
|
263
|
-
function
|
|
4255
|
+
function putFalseOnly(target, key, env) {
|
|
4256
|
+
if (isFalseValue(env[FALSE_ONLY_ENV[key]]))
|
|
4257
|
+
target[key] = false;
|
|
4258
|
+
}
|
|
4259
|
+
function putDomains(target, key, env) {
|
|
4260
|
+
const value = env[DOMAINS_ENV[key]];
|
|
264
4261
|
if (value === undefined || !value.trim())
|
|
265
4262
|
return;
|
|
266
4263
|
const domains = value.split(",").map((domain) => domain.trim()).filter((domain) => domain.length > 0);
|
|
@@ -280,7 +4277,11 @@ function isFalseValue(value) {
|
|
|
280
4277
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
281
4278
|
import * as z from "zod/v4";
|
|
282
4279
|
|
|
4280
|
+
// src/core/client.ts
|
|
4281
|
+
init_constants();
|
|
4282
|
+
|
|
283
4283
|
// src/core/format.ts
|
|
4284
|
+
init_constants();
|
|
284
4285
|
function truncate(value, maxChars) {
|
|
285
4286
|
if (maxChars <= 0)
|
|
286
4287
|
return "";
|
|
@@ -337,8 +4338,34 @@ function formatApiError(operation, status, body) {
|
|
|
337
4338
|
function formatTimeoutError(operation, timeoutMs) {
|
|
338
4339
|
return `${operation} timed out after ${timeoutMs} ms`;
|
|
339
4340
|
}
|
|
4341
|
+
function formatSearchResults(results) {
|
|
4342
|
+
if (results.length === 0)
|
|
4343
|
+
return "No results found.";
|
|
4344
|
+
return results.map((result, index) => {
|
|
4345
|
+
const title = result.title?.trim() || result.url;
|
|
4346
|
+
const lines = [`${index + 1}. [${escapeBrackets(title)}](${result.url})`];
|
|
4347
|
+
if (result.content) {
|
|
4348
|
+
lines.push(` ${result.content.replaceAll(`
|
|
4349
|
+
`, " ")}`);
|
|
4350
|
+
}
|
|
4351
|
+
if (result.published !== undefined) {
|
|
4352
|
+
lines.push(` Published: ${formatPublished(result.published)}`);
|
|
4353
|
+
}
|
|
4354
|
+
return lines.join(`
|
|
4355
|
+
`);
|
|
4356
|
+
}).join(`
|
|
4357
|
+
|
|
4358
|
+
`);
|
|
4359
|
+
}
|
|
4360
|
+
function escapeBrackets(value) {
|
|
4361
|
+
return value.replaceAll("[", "\\[").replaceAll("]", "\\]");
|
|
4362
|
+
}
|
|
4363
|
+
function formatPublished(epochMs) {
|
|
4364
|
+
return new Date(epochMs).toISOString().slice(0, 10);
|
|
4365
|
+
}
|
|
340
4366
|
|
|
341
4367
|
// src/core/url.ts
|
|
4368
|
+
init_constants();
|
|
342
4369
|
function parseFetchUrl(value) {
|
|
343
4370
|
const input = value.trim();
|
|
344
4371
|
if (!input)
|
|
@@ -424,16 +4451,13 @@ function processResults(raw, options) {
|
|
|
424
4451
|
}
|
|
425
4452
|
seen.add(url);
|
|
426
4453
|
const content = truncate(optionalText2(item.summary) ?? optionalText2(item.snippet) ?? "", options.maxSummaryChars);
|
|
427
|
-
const time = {};
|
|
428
4454
|
const published = parsePublished(item.date);
|
|
429
|
-
if (published !== undefined)
|
|
430
|
-
time.published = published;
|
|
431
4455
|
const title = optionalText2(item.title);
|
|
432
4456
|
results.push({
|
|
433
4457
|
url,
|
|
434
4458
|
...title ? { title } : {},
|
|
435
4459
|
...content ? { content } : {},
|
|
436
|
-
|
|
4460
|
+
...published !== undefined ? { published } : {}
|
|
437
4461
|
});
|
|
438
4462
|
}
|
|
439
4463
|
return results;
|
|
@@ -445,7 +4469,8 @@ function optionalText2(value) {
|
|
|
445
4469
|
return trimmed ? trimmed : undefined;
|
|
446
4470
|
}
|
|
447
4471
|
|
|
448
|
-
// src/core/
|
|
4472
|
+
// src/core/transport.ts
|
|
4473
|
+
init_constants();
|
|
449
4474
|
class DeepSeekApiError extends Error {
|
|
450
4475
|
operation;
|
|
451
4476
|
status;
|
|
@@ -463,63 +4488,32 @@ class DeepSeekApiError extends Error {
|
|
|
463
4488
|
this.retryAfterMs = input.retryAfterMs;
|
|
464
4489
|
}
|
|
465
4490
|
}
|
|
466
|
-
async function
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
throw new Error("DeepSeek search query must not be empty");
|
|
470
|
-
if (Array.from(trimmed).length > MAX_QUERY_CHARS) {
|
|
471
|
-
throw new Error(`DeepSeek search query must be ${MAX_QUERY_CHARS} characters or fewer`);
|
|
472
|
-
}
|
|
473
|
-
const builtQuery = buildQuery(trimmed, options);
|
|
474
|
-
const builtQueryLength = Array.from(builtQuery).length;
|
|
475
|
-
if (builtQueryLength > MAX_QUERY_CHARS) {
|
|
476
|
-
throw new Error(`DeepSeek search query must be ${MAX_QUERY_CHARS} characters or fewer after applying ` + `blockedDomains, includeDomains, and language ` + `(built query is ${builtQueryLength} characters)`);
|
|
477
|
-
}
|
|
478
|
-
const payload = await postJson(SEARCH_ENDPOINT, {
|
|
479
|
-
query: builtQuery,
|
|
480
|
-
count: options.count,
|
|
481
|
-
need_content: false
|
|
482
|
-
}, "DeepSeek Search", request, options.timeoutMs);
|
|
483
|
-
if (!Array.isArray(payload.results)) {
|
|
484
|
-
throw new Error("DeepSeek Search returned a response without a results array");
|
|
485
|
-
}
|
|
486
|
-
return processResults(payload.results, options);
|
|
487
|
-
}
|
|
488
|
-
async function fetchPage(url, options, request) {
|
|
489
|
-
assertFetchHostPolicy(url, options);
|
|
490
|
-
const payload = await postJson(FETCH_ENDPOINT, { url: url.href }, "DeepSeek Fetch", request, options.timeoutMs);
|
|
491
|
-
const title = typeof payload.title === "string" ? payload.title.trim() : "";
|
|
492
|
-
const content = typeof payload.content === "string" ? payload.content : "";
|
|
493
|
-
if (!content.trim()) {
|
|
494
|
-
throw new Error("DeepSeek Fetch returned no page content (the page may be empty or unavailable)");
|
|
495
|
-
}
|
|
496
|
-
return { url: url.href, title, content };
|
|
497
|
-
}
|
|
498
|
-
async function postJson(endpoint, body, operation, options, timeoutMs) {
|
|
499
|
-
const attempts = options.retry.maxRetries + 1;
|
|
4491
|
+
async function postJson(endpoint, body, operation, opts) {
|
|
4492
|
+
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
4493
|
+
const attempts = opts.retry.maxRetries + 1;
|
|
500
4494
|
let lastError;
|
|
501
4495
|
for (let attempt = 0;attempt < attempts; attempt++) {
|
|
502
4496
|
try {
|
|
503
|
-
return await requestOnce(endpoint, body, operation,
|
|
4497
|
+
return await requestOnce(endpoint, body, operation, opts, fetchImpl);
|
|
504
4498
|
} catch (error) {
|
|
505
4499
|
lastError = error;
|
|
506
4500
|
if (!(error instanceof DeepSeekApiError) || !error.retryable || attempt === attempts - 1) {
|
|
507
4501
|
throw error;
|
|
508
4502
|
}
|
|
509
|
-
await sleep(retryDelay(error.retryAfterMs,
|
|
4503
|
+
await sleep(retryDelay(error.retryAfterMs, opts.retry.baseDelayMs, attempt), opts.signal);
|
|
510
4504
|
}
|
|
511
4505
|
}
|
|
512
4506
|
throw lastError;
|
|
513
4507
|
}
|
|
514
|
-
async function requestOnce(endpoint, body, operation,
|
|
4508
|
+
async function requestOnce(endpoint, body, operation, opts, fetchImpl) {
|
|
515
4509
|
return fetchWithTimeout(endpoint, {
|
|
516
4510
|
method: "POST",
|
|
517
4511
|
headers: {
|
|
518
|
-
Authorization: `Bearer ${
|
|
4512
|
+
Authorization: `Bearer ${opts.auth.apiKey}`,
|
|
519
4513
|
"Content-Type": "application/json"
|
|
520
4514
|
},
|
|
521
4515
|
body: JSON.stringify(body)
|
|
522
|
-
},
|
|
4516
|
+
}, opts.signal, opts.timeoutMs, operation, fetchImpl, async (response) => {
|
|
523
4517
|
if (!response.ok) {
|
|
524
4518
|
const text2 = await readBoundedText(response, MAX_ERROR_BODY_CHARS);
|
|
525
4519
|
throw new DeepSeekApiError({
|
|
@@ -539,7 +4533,7 @@ async function requestOnce(endpoint, body, operation, options, timeoutMs) {
|
|
|
539
4533
|
}
|
|
540
4534
|
});
|
|
541
4535
|
}
|
|
542
|
-
async function fetchWithTimeout(endpoint, init, signal, timeoutMs, operation, handleResponse) {
|
|
4536
|
+
async function fetchWithTimeout(endpoint, init, signal, timeoutMs, operation, fetchImpl, handleResponse) {
|
|
543
4537
|
const controller = new AbortController;
|
|
544
4538
|
let timedOut = false;
|
|
545
4539
|
const forwardAbort = () => controller.abort(signal.reason);
|
|
@@ -552,7 +4546,7 @@ async function fetchWithTimeout(endpoint, init, signal, timeoutMs, operation, ha
|
|
|
552
4546
|
controller.abort(new Error("timeout"));
|
|
553
4547
|
}, timeoutMs);
|
|
554
4548
|
try {
|
|
555
|
-
const response = await
|
|
4549
|
+
const response = await fetchImpl(endpoint, { ...init, signal: controller.signal });
|
|
556
4550
|
return await handleResponse(response);
|
|
557
4551
|
} catch (error) {
|
|
558
4552
|
if (timedOut)
|
|
@@ -666,11 +4660,72 @@ async function readResponseText(response, maxBytes, operation) {
|
|
|
666
4660
|
}
|
|
667
4661
|
return text;
|
|
668
4662
|
}
|
|
4663
|
+
|
|
4664
|
+
// src/core/client.ts
|
|
4665
|
+
function effectiveTimeout(configuredMs, perCallMs) {
|
|
4666
|
+
return perCallMs === undefined ? configuredMs : Math.min(configuredMs, perCallMs);
|
|
4667
|
+
}
|
|
4668
|
+
async function searchWeb(query, options, request) {
|
|
4669
|
+
const trimmed = query.trim();
|
|
4670
|
+
if (!trimmed)
|
|
4671
|
+
throw new Error("DeepSeek search query must not be empty");
|
|
4672
|
+
if (Array.from(trimmed).length > MAX_QUERY_CHARS) {
|
|
4673
|
+
throw new Error(`DeepSeek search query must be ${MAX_QUERY_CHARS} characters or fewer`);
|
|
4674
|
+
}
|
|
4675
|
+
const builtQuery = buildQuery(trimmed, options);
|
|
4676
|
+
const builtQueryLength = Array.from(builtQuery).length;
|
|
4677
|
+
if (builtQueryLength > MAX_QUERY_CHARS) {
|
|
4678
|
+
throw new Error(`DeepSeek search query must be ${MAX_QUERY_CHARS} characters or fewer after applying ` + `blockedDomains, includeDomains, and language ` + `(built query is ${builtQueryLength} characters)`);
|
|
4679
|
+
}
|
|
4680
|
+
const timeout = effectiveTimeout(options.timeoutMs, request.timeoutMs);
|
|
4681
|
+
const payload = await postJson(SEARCH_ENDPOINT, {
|
|
4682
|
+
query: builtQuery,
|
|
4683
|
+
count: options.count,
|
|
4684
|
+
need_content: false
|
|
4685
|
+
}, "DeepSeek Search", { signal: request.signal, auth: request.auth, retry: request.retry, timeoutMs: timeout });
|
|
4686
|
+
if (!Array.isArray(payload.results)) {
|
|
4687
|
+
throw new Error("DeepSeek Search returned a response without a results array");
|
|
4688
|
+
}
|
|
4689
|
+
return processResults(payload.results, options);
|
|
4690
|
+
}
|
|
4691
|
+
async function fetchPage(url, options, request) {
|
|
4692
|
+
assertFetchHostPolicy(url, options);
|
|
4693
|
+
const timeout = effectiveTimeout(options.timeoutMs, request.timeoutMs);
|
|
4694
|
+
const payload = await postJson(FETCH_ENDPOINT, { url: url.href }, "DeepSeek Fetch", { signal: request.signal, auth: request.auth, retry: request.retry, timeoutMs: timeout });
|
|
4695
|
+
const title = typeof payload.title === "string" ? payload.title.trim() : "";
|
|
4696
|
+
const content = typeof payload.content === "string" ? payload.content : "";
|
|
4697
|
+
if (!content.trim()) {
|
|
4698
|
+
throw new Error("DeepSeek Fetch returned no page content (the page may be empty or unavailable)");
|
|
4699
|
+
}
|
|
4700
|
+
return { url: url.href, title, content };
|
|
4701
|
+
}
|
|
4702
|
+
async function fetchDocument(url, options, request) {
|
|
4703
|
+
if (typeof url !== "string" && !(url instanceof URL))
|
|
4704
|
+
throw new Error('"url" must be a string or URL');
|
|
4705
|
+
const page = await fetchPage(url instanceof URL ? url : parseFetchUrl(url), options, request);
|
|
4706
|
+
const formatted = formatFetchedContent(page.title, page.content, options.maxChars);
|
|
4707
|
+
return {
|
|
4708
|
+
url: page.url,
|
|
4709
|
+
title: page.title,
|
|
4710
|
+
content: formatted.content,
|
|
4711
|
+
truncated: formatted.truncated
|
|
4712
|
+
};
|
|
4713
|
+
}
|
|
4714
|
+
|
|
4715
|
+
// src/mcp/server.ts
|
|
4716
|
+
init_constants();
|
|
4717
|
+
|
|
4718
|
+
// src/core/descriptions.ts
|
|
4719
|
+
var FETCH_SERVICE_LIMITS = "DeepSeek does not render JavaScript and cannot reach private networks; PDFs, images, and other binary files are unsupported.";
|
|
4720
|
+
var FETCH_OUTPUT_TRUNCATED = "Output is truncated to the configured size.";
|
|
4721
|
+
var SEARCH_RANKED_FILTERED = "Results are ranked by relevance and source authority, deduplicated by URL, and capped at the configured maximum.";
|
|
4722
|
+
var SEARCH_EMPTY_IS_NORMAL = "An empty result list is normal, not an error.";
|
|
4723
|
+
var SEARCH_QUERY_OPERATORS = "Use site:/-site: operators in the query to include or exclude domains; the full query must stay within 128 characters.";
|
|
669
4724
|
// package.json
|
|
670
4725
|
var package_default = {
|
|
671
4726
|
$schema: "https://json.schemastore.org/package.json",
|
|
672
4727
|
name: "deepseek-web-retrieval",
|
|
673
|
-
version: "0.
|
|
4728
|
+
version: "0.3.0",
|
|
674
4729
|
description: "Token-efficient DeepSeek Search and Fetch for coding agents, starting with OpenCode v2.",
|
|
675
4730
|
type: "module",
|
|
676
4731
|
license: "MIT",
|
|
@@ -695,7 +4750,7 @@ var package_default = {
|
|
|
695
4750
|
"./mcp": "./src/mcp/server.ts"
|
|
696
4751
|
},
|
|
697
4752
|
bin: {
|
|
698
|
-
"deepseek-web-retrieval": "
|
|
4753
|
+
"deepseek-web-retrieval": "dist/cli.js"
|
|
699
4754
|
},
|
|
700
4755
|
files: [
|
|
701
4756
|
"index.ts",
|
|
@@ -715,7 +4770,7 @@ var package_default = {
|
|
|
715
4770
|
"test:e2e": "bun run test/e2e/run.ts",
|
|
716
4771
|
"docs:matrix": "bun run scripts/render-matrix.ts",
|
|
717
4772
|
"test:coverage": "bun test --coverage",
|
|
718
|
-
check: "bun run typecheck && bun run build && bun test"
|
|
4773
|
+
check: "bun run typecheck && bun run docs:matrix --check && bun run build && bun test"
|
|
719
4774
|
},
|
|
720
4775
|
peerDependencies: {
|
|
721
4776
|
"@opencode/plugin": "^2.0.32"
|
|
@@ -733,37 +4788,12 @@ var package_default = {
|
|
|
733
4788
|
},
|
|
734
4789
|
dependencies: {
|
|
735
4790
|
"@modelcontextprotocol/server": "^2.3.1",
|
|
4791
|
+
"jsonc-parser": "^3.3.1",
|
|
4792
|
+
"smol-toml": "^1.9.1",
|
|
736
4793
|
zod: "^4"
|
|
737
4794
|
}
|
|
738
4795
|
};
|
|
739
4796
|
|
|
740
|
-
// src/mcp/format.ts
|
|
741
|
-
function formatSearchResults(results) {
|
|
742
|
-
if (results.length === 0)
|
|
743
|
-
return "No results found.";
|
|
744
|
-
return results.map((result, index) => {
|
|
745
|
-
const title = result.title?.trim() || result.url;
|
|
746
|
-
const lines = [`${index + 1}. [${escapeBrackets(title)}](${result.url})`];
|
|
747
|
-
if (result.content) {
|
|
748
|
-
lines.push(` ${result.content.replaceAll(`
|
|
749
|
-
`, " ")}`);
|
|
750
|
-
}
|
|
751
|
-
if (result.time.published !== undefined) {
|
|
752
|
-
lines.push(` Published: ${formatPublished(result.time.published)}`);
|
|
753
|
-
}
|
|
754
|
-
return lines.join(`
|
|
755
|
-
`);
|
|
756
|
-
}).join(`
|
|
757
|
-
|
|
758
|
-
`);
|
|
759
|
-
}
|
|
760
|
-
function escapeBrackets(value) {
|
|
761
|
-
return value.replaceAll("[", "\\[").replaceAll("]", "\\]");
|
|
762
|
-
}
|
|
763
|
-
function formatPublished(epochMs) {
|
|
764
|
-
return new Date(epochMs).toISOString().slice(0, 10);
|
|
765
|
-
}
|
|
766
|
-
|
|
767
4797
|
// src/mcp/server.ts
|
|
768
4798
|
var MCP_SERVER_NAME = "deepseek-web-retrieval";
|
|
769
4799
|
var SEARCH_INPUT = z.object({
|
|
@@ -786,54 +4816,55 @@ var FETCH_OUTPUT = z.object({
|
|
|
786
4816
|
content: z.string(),
|
|
787
4817
|
truncated: z.boolean()
|
|
788
4818
|
});
|
|
789
|
-
var SEARCH_DESCRIPTION = "Search the web with DeepSeek's in-house search engine and return a short, filtered result " + "list (title, URL, summary).
|
|
790
|
-
var FETCH_DESCRIPTION = "Fetch one web page as clean Markdown through DeepSeek's Fetch API.
|
|
4819
|
+
var SEARCH_DESCRIPTION = "Search the web with DeepSeek's in-house search engine and return a short, filtered result " + "list (title, URL, summary). " + `${SEARCH_RANKED_FILTERED} ` + `${SEARCH_EMPTY_IS_NORMAL} ` + `${SEARCH_QUERY_OPERATORS} ` + "To read a full page, pass a result URL to the deepseek_fetch tool.";
|
|
4820
|
+
var FETCH_DESCRIPTION = "Fetch one web page as clean Markdown through DeepSeek's Fetch API. " + `${FETCH_SERVICE_LIMITS} ` + `${FETCH_OUTPUT_TRUNCATED}`;
|
|
791
4821
|
function createDeepSeekServer(config, env = process.env) {
|
|
792
4822
|
const server = new McpServer({ name: MCP_SERVER_NAME, version: package_default.version });
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
4823
|
+
if (config.search.enabled) {
|
|
4824
|
+
server.registerTool("deepseek_web_search", {
|
|
4825
|
+
title: "DeepSeek Web Search",
|
|
4826
|
+
description: SEARCH_DESCRIPTION,
|
|
4827
|
+
inputSchema: SEARCH_INPUT,
|
|
4828
|
+
outputSchema: SEARCH_OUTPUT,
|
|
4829
|
+
annotations: { readOnlyHint: true }
|
|
4830
|
+
}, async ({ query }, ctx) => {
|
|
4831
|
+
try {
|
|
4832
|
+
const request = requestContext(config, env, ctx.mcpReq.signal);
|
|
4833
|
+
const results = await searchWeb(query, config.search, request);
|
|
4834
|
+
return {
|
|
4835
|
+
content: [{ type: "text", text: formatSearchResults(results) }],
|
|
4836
|
+
structuredContent: { results: results.map(toStructuredResult) }
|
|
4837
|
+
};
|
|
4838
|
+
} catch (error) {
|
|
4839
|
+
return toErrorResult(error);
|
|
4840
|
+
}
|
|
4841
|
+
});
|
|
4842
|
+
}
|
|
4843
|
+
if (config.fetch.enabled) {
|
|
4844
|
+
server.registerTool("deepseek_fetch", {
|
|
4845
|
+
title: "DeepSeek Fetch",
|
|
4846
|
+
description: FETCH_DESCRIPTION,
|
|
4847
|
+
inputSchema: FETCH_INPUT,
|
|
4848
|
+
outputSchema: FETCH_OUTPUT,
|
|
4849
|
+
annotations: { readOnlyHint: true }
|
|
4850
|
+
}, async ({ url }, ctx) => {
|
|
4851
|
+
try {
|
|
4852
|
+
const request = requestContext(config, env, ctx.mcpReq.signal);
|
|
4853
|
+
const page = await fetchDocument(url, config.fetch, request);
|
|
4854
|
+
return {
|
|
4855
|
+
content: [{ type: "text", text: page.content }],
|
|
4856
|
+
structuredContent: {
|
|
4857
|
+
url: page.url,
|
|
4858
|
+
title: page.title,
|
|
4859
|
+
content: page.content,
|
|
4860
|
+
truncated: page.truncated
|
|
4861
|
+
}
|
|
4862
|
+
};
|
|
4863
|
+
} catch (error) {
|
|
4864
|
+
return toErrorResult(error);
|
|
4865
|
+
}
|
|
4866
|
+
});
|
|
4867
|
+
}
|
|
837
4868
|
return server;
|
|
838
4869
|
}
|
|
839
4870
|
function requestContext(config, env, signal) {
|
|
@@ -844,22 +4875,41 @@ function toStructuredResult(result) {
|
|
|
844
4875
|
url: result.url,
|
|
845
4876
|
...result.title ? { title: result.title } : {},
|
|
846
4877
|
...result.content ? { content: result.content } : {},
|
|
847
|
-
...result.
|
|
4878
|
+
...result.published !== undefined ? { published: result.published } : {}
|
|
848
4879
|
};
|
|
849
4880
|
}
|
|
4881
|
+
function servePrecheck(config) {
|
|
4882
|
+
if (config.search.enabled || config.fetch.enabled)
|
|
4883
|
+
return;
|
|
4884
|
+
return `Both tools are disabled (${ENABLE_SEARCH_ENV} and ${ENABLE_FETCH_ENV} are false); ` + "at least one must stay enabled.";
|
|
4885
|
+
}
|
|
850
4886
|
function toErrorResult(error) {
|
|
851
4887
|
const message = error instanceof Error ? error.message : String(error);
|
|
852
4888
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
853
4889
|
}
|
|
854
4890
|
|
|
855
4891
|
// src/mcp/cli.ts
|
|
4892
|
+
var subcommand = process.argv[2];
|
|
4893
|
+
if (subcommand === "init" || subcommand === "uninstall" || subcommand === "list") {
|
|
4894
|
+
const { runInstallerCli: runInstallerCli2 } = await Promise.resolve().then(() => (init_cli(), exports_cli));
|
|
4895
|
+
process.exit(await runInstallerCli2(process.argv.slice(2)));
|
|
4896
|
+
}
|
|
856
4897
|
var env = process.env;
|
|
857
4898
|
if (!apiKeyFromEnv(env)) {
|
|
858
4899
|
console.error(MISSING_API_KEY_MESSAGE);
|
|
859
4900
|
process.exit(1);
|
|
860
4901
|
}
|
|
861
4902
|
var config = resolveEnvOptions(env);
|
|
4903
|
+
var precheck = servePrecheck(config);
|
|
4904
|
+
if (precheck) {
|
|
4905
|
+
console.error(precheck);
|
|
4906
|
+
process.exit(1);
|
|
4907
|
+
}
|
|
862
4908
|
var handle = serveStdio(() => createDeepSeekServer(config, env));
|
|
863
|
-
|
|
4909
|
+
var tools = [
|
|
4910
|
+
config.search.enabled ? `search (max ${config.search.maxResults} results)` : null,
|
|
4911
|
+
config.fetch.enabled ? `fetch (max ${config.fetch.maxChars} chars)` : null
|
|
4912
|
+
].filter(Boolean).join(", ");
|
|
4913
|
+
console.error(`deepseek-web-retrieval MCP server on stdio (${tools})`);
|
|
864
4914
|
process.on("SIGINT", () => void handle.close());
|
|
865
4915
|
process.on("SIGTERM", () => void handle.close());
|