tabby-mcp-server 1.4.2 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -197,6 +197,17 @@ var requestPrototype = {
197
197
  }
198
198
  });
199
199
  });
200
+ Object.defineProperty(requestPrototype, Symbol.for("nodejs.util.inspect.custom"), {
201
+ value: function(depth, options, inspectFn) {
202
+ const props = {
203
+ method: this.method,
204
+ url: this.url,
205
+ headers: this.headers,
206
+ nativeRequest: this[requestCache]
207
+ };
208
+ return `Request (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
209
+ }
210
+ });
200
211
  Object.setPrototypeOf(requestPrototype, Request.prototype);
201
212
  var newRequest = (incoming, defaultHostname) => {
202
213
  const req = Object.create(requestPrototype);
@@ -265,15 +276,17 @@ var Response2 = class _Response {
265
276
  this.#init = init;
266
277
  }
267
278
  if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) {
268
- headers ||= init?.headers || { "content-type": "text/plain; charset=UTF-8" };
269
- this[cacheKey] = [init?.status || 200, body, headers];
279
+ ;
280
+ this[cacheKey] = [init?.status || 200, body, headers || init?.headers];
270
281
  }
271
282
  }
272
283
  get headers() {
273
284
  const cache = this[cacheKey];
274
285
  if (cache) {
275
286
  if (!(cache[2] instanceof Headers)) {
276
- cache[2] = new Headers(cache[2]);
287
+ cache[2] = new Headers(
288
+ cache[2] || { "content-type": "text/plain; charset=UTF-8" }
289
+ );
277
290
  }
278
291
  return cache[2];
279
292
  }
@@ -301,6 +314,17 @@ var Response2 = class _Response {
301
314
  }
302
315
  });
303
316
  });
317
+ Object.defineProperty(Response2.prototype, Symbol.for("nodejs.util.inspect.custom"), {
318
+ value: function(depth, options, inspectFn) {
319
+ const props = {
320
+ status: this.status,
321
+ headers: this.headers,
322
+ ok: this.ok,
323
+ nativeResponse: this[responseCache]
324
+ };
325
+ return `Response (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
326
+ }
327
+ });
304
328
  Object.setPrototypeOf(Response2, GlobalResponse);
305
329
  Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
306
330
 
@@ -381,6 +405,50 @@ if (typeof global.crypto === "undefined") {
381
405
 
382
406
  // src/listener.ts
383
407
  var outgoingEnded = Symbol("outgoingEnded");
408
+ var incomingDraining = Symbol("incomingDraining");
409
+ var DRAIN_TIMEOUT_MS = 500;
410
+ var MAX_DRAIN_BYTES = 64 * 1024 * 1024;
411
+ var drainIncoming = (incoming) => {
412
+ const incomingWithDrainState = incoming;
413
+ if (incoming.destroyed || incomingWithDrainState[incomingDraining]) {
414
+ return;
415
+ }
416
+ incomingWithDrainState[incomingDraining] = true;
417
+ if (incoming instanceof import_node_http22.Http2ServerRequest) {
418
+ try {
419
+ ;
420
+ incoming.stream?.close?.(import_node_http22.constants.NGHTTP2_NO_ERROR);
421
+ } catch {
422
+ }
423
+ return;
424
+ }
425
+ let bytesRead = 0;
426
+ const cleanup = () => {
427
+ clearTimeout(timer);
428
+ incoming.off("data", onData);
429
+ incoming.off("end", cleanup);
430
+ incoming.off("error", cleanup);
431
+ };
432
+ const forceClose = () => {
433
+ cleanup();
434
+ const socket = incoming.socket;
435
+ if (socket && !socket.destroyed) {
436
+ socket.destroySoon();
437
+ }
438
+ };
439
+ const timer = setTimeout(forceClose, DRAIN_TIMEOUT_MS);
440
+ timer.unref?.();
441
+ const onData = (chunk) => {
442
+ bytesRead += chunk.length;
443
+ if (bytesRead > MAX_DRAIN_BYTES) {
444
+ forceClose();
445
+ }
446
+ };
447
+ incoming.on("data", onData);
448
+ incoming.on("end", cleanup);
449
+ incoming.on("error", cleanup);
450
+ incoming.resume();
451
+ };
384
452
  var handleRequestError = () => new Response(null, {
385
453
  status: 400
386
454
  });
@@ -407,15 +475,32 @@ var flushHeaders = (outgoing) => {
407
475
  };
408
476
  var responseViaCache = async (res, outgoing) => {
409
477
  let [status, body, header] = res[cacheKey];
410
- if (header instanceof Headers) {
478
+ let hasContentLength = false;
479
+ if (!header) {
480
+ header = { "content-type": "text/plain; charset=UTF-8" };
481
+ } else if (header instanceof Headers) {
482
+ hasContentLength = header.has("content-length");
411
483
  header = buildOutgoingHttpHeaders(header);
484
+ } else if (Array.isArray(header)) {
485
+ const headerObj = new Headers(header);
486
+ hasContentLength = headerObj.has("content-length");
487
+ header = buildOutgoingHttpHeaders(headerObj);
488
+ } else {
489
+ for (const key in header) {
490
+ if (key.length === 14 && key.toLowerCase() === "content-length") {
491
+ hasContentLength = true;
492
+ break;
493
+ }
494
+ }
412
495
  }
413
- if (typeof body === "string") {
414
- header["Content-Length"] = Buffer.byteLength(body);
415
- } else if (body instanceof Uint8Array) {
416
- header["Content-Length"] = body.byteLength;
417
- } else if (body instanceof Blob) {
418
- header["Content-Length"] = body.size;
496
+ if (!hasContentLength) {
497
+ if (typeof body === "string") {
498
+ header["Content-Length"] = Buffer.byteLength(body);
499
+ } else if (body instanceof Uint8Array) {
500
+ header["Content-Length"] = body.byteLength;
501
+ } else if (body instanceof Blob) {
502
+ header["Content-Length"] = body.size;
503
+ }
419
504
  }
420
505
  outgoing.writeHead(status, header);
421
506
  if (typeof body === "string" || body instanceof Uint8Array) {
@@ -535,14 +620,18 @@ var getRequestListener = (fetchCallback, options = {}) => {
535
620
  setTimeout(() => {
536
621
  if (!incomingEnded) {
537
622
  setTimeout(() => {
538
- incoming.destroy();
539
- outgoing.destroy();
623
+ drainIncoming(incoming);
540
624
  });
541
625
  }
542
626
  });
543
627
  }
544
628
  };
545
629
  }
630
+ outgoing.on("finish", () => {
631
+ if (!incomingEnded) {
632
+ drainIncoming(incoming);
633
+ }
634
+ });
546
635
  }
547
636
  outgoing.on("close", () => {
548
637
  const abortController = req[abortControllerKey];
@@ -557,7 +646,7 @@ var getRequestListener = (fetchCallback, options = {}) => {
557
646
  setTimeout(() => {
558
647
  if (!incomingEnded) {
559
648
  setTimeout(() => {
560
- incoming.destroy();
649
+ drainIncoming(incoming);
561
650
  });
562
651
  }
563
652
  });
@@ -875,8 +964,9 @@ function validMime (type) {
875
964
  (__unused_webpack_module, exports) {
876
965
 
877
966
  "use strict";
967
+ var __webpack_unused_export__;
878
968
 
879
- Object.defineProperty(exports, "__esModule", ({ value: true }));
969
+ __webpack_unused_export__ = ({ value: true });
880
970
  exports.formatNames = exports.fastFormats = exports.fullFormats = void 0;
881
971
  function fmtDef(validate, compare) {
882
972
  return { validate, compare };
@@ -1134,9 +1224,10 @@ exports["default"] = formatsPlugin;
1134
1224
  (__unused_webpack_module, exports, __webpack_require__) {
1135
1225
 
1136
1226
  "use strict";
1227
+ var __webpack_unused_export__;
1137
1228
 
1138
- Object.defineProperty(exports, "__esModule", ({ value: true }));
1139
- exports.formatLimitDefinition = void 0;
1229
+ __webpack_unused_export__ = ({ value: true });
1230
+ exports.A = void 0;
1140
1231
  const ajv_1 = __webpack_require__(3282);
1141
1232
  const codegen_1 = __webpack_require__(1410);
1142
1233
  const ops = codegen_1.operators;
@@ -1150,7 +1241,7 @@ const error = {
1150
1241
  message: ({ keyword, schemaCode }) => (0, codegen_1.str) `should be ${KWDs[keyword].okStr} ${schemaCode}`,
1151
1242
  params: ({ keyword, schemaCode }) => (0, codegen_1._) `{comparison: ${KWDs[keyword].okStr}, limit: ${schemaCode}}`,
1152
1243
  };
1153
- exports.formatLimitDefinition = {
1244
+ exports.A = {
1154
1245
  keyword: Object.keys(KWDs),
1155
1246
  type: "string",
1156
1247
  schemaType: "string",
@@ -1198,7 +1289,7 @@ exports.formatLimitDefinition = {
1198
1289
  dependencies: ["format"],
1199
1290
  };
1200
1291
  const formatLimitPlugin = (ajv) => {
1201
- ajv.addKeyword(exports.formatLimitDefinition);
1292
+ ajv.addKeyword(exports.A);
1202
1293
  return ajv;
1203
1294
  };
1204
1295
  exports["default"] = formatLimitPlugin;
@@ -2284,13 +2375,14 @@ exports.ValueScope = ValueScope;
2284
2375
  (__unused_webpack_module, exports, __webpack_require__) {
2285
2376
 
2286
2377
  "use strict";
2378
+ var __webpack_unused_export__;
2287
2379
 
2288
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2289
- exports.extendErrors = exports.resetErrorsCount = exports.reportExtraError = exports.reportError = exports.keyword$DataError = exports.keywordError = void 0;
2380
+ __webpack_unused_export__ = ({ value: true });
2381
+ exports.extendErrors = exports.resetErrorsCount = exports.reportExtraError = exports.reportError = exports.keyword$DataError = exports.y = void 0;
2290
2382
  const codegen_1 = __webpack_require__(1410);
2291
2383
  const util_1 = __webpack_require__(4227);
2292
2384
  const names_1 = __webpack_require__(2023);
2293
- exports.keywordError = {
2385
+ exports.y = {
2294
2386
  message: ({ keyword }) => (0, codegen_1.str) `must pass "${keyword}" keyword validation`,
2295
2387
  };
2296
2388
  exports.keyword$DataError = {
@@ -2298,7 +2390,7 @@ exports.keyword$DataError = {
2298
2390
  ? (0, codegen_1.str) `"${keyword}" keyword must be ${schemaType} ($data)`
2299
2391
  : (0, codegen_1.str) `"${keyword}" keyword is invalid ($data)`,
2300
2392
  };
2301
- function reportError(cxt, error = exports.keywordError, errorPaths, overrideAllErrors) {
2393
+ function reportError(cxt, error = exports.y, errorPaths, overrideAllErrors) {
2302
2394
  const { it } = cxt;
2303
2395
  const { gen, compositeRule, allErrors } = it;
2304
2396
  const errObj = errorObjectCode(cxt, error, errorPaths);
@@ -2310,7 +2402,7 @@ function reportError(cxt, error = exports.keywordError, errorPaths, overrideAllE
2310
2402
  }
2311
2403
  }
2312
2404
  exports.reportError = reportError;
2313
- function reportExtraError(cxt, error = exports.keywordError, errorPaths) {
2405
+ function reportExtraError(cxt, error = exports.y, errorPaths) {
2314
2406
  const { it } = cxt;
2315
2407
  const { gen, compositeRule, allErrors } = it;
2316
2408
  const errObj = errorObjectCode(cxt, error, errorPaths);
@@ -2414,9 +2506,10 @@ function extraErrorProps(cxt, { params, message }, keyValues) {
2414
2506
  (__unused_webpack_module, exports, __webpack_require__) {
2415
2507
 
2416
2508
  "use strict";
2509
+ var __webpack_unused_export__;
2417
2510
 
2418
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2419
- exports.resolveSchema = exports.getCompilingSchema = exports.resolveRef = exports.compileSchema = exports.SchemaEnv = void 0;
2511
+ __webpack_unused_export__ = ({ value: true });
2512
+ exports.resolveSchema = __webpack_unused_export__ = exports.resolveRef = exports.compileSchema = exports.SchemaEnv = void 0;
2420
2513
  const codegen_1 = __webpack_require__(1410);
2421
2514
  const validation_error_1 = __webpack_require__(3558);
2422
2515
  const names_1 = __webpack_require__(2023);
@@ -2570,7 +2663,7 @@ function getCompilingSchema(schEnv) {
2570
2663
  return sch;
2571
2664
  }
2572
2665
  }
2573
- exports.getCompilingSchema = getCompilingSchema;
2666
+ __webpack_unused_export__ = getCompilingSchema;
2574
2667
  function sameSchemaEnv(s1, s2) {
2575
2668
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
2576
2669
  }
@@ -2663,8 +2756,9 @@ function getJsonPointer(parsedRef, { baseId, schema, root }) {
2663
2756
  (__unused_webpack_module, exports, __webpack_require__) {
2664
2757
 
2665
2758
  "use strict";
2759
+ var __webpack_unused_export__;
2666
2760
 
2667
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2761
+ __webpack_unused_export__ = ({ value: true });
2668
2762
  const codegen_1 = __webpack_require__(1410);
2669
2763
  const names = {
2670
2764
  // validation function arguments
@@ -2717,8 +2811,9 @@ exports["default"] = MissingRefError;
2717
2811
  (__unused_webpack_module, exports, __webpack_require__) {
2718
2812
 
2719
2813
  "use strict";
2814
+ var __webpack_unused_export__;
2720
2815
 
2721
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2816
+ __webpack_unused_export__ = ({ value: true });
2722
2817
  exports.getSchemaRefs = exports.resolveUrl = exports.normalizeId = exports._getFullPath = exports.getFullPath = exports.inlineRef = void 0;
2723
2818
  const util_1 = __webpack_require__(4227);
2724
2819
  const equal = __webpack_require__(4398);
@@ -2879,8 +2974,9 @@ exports.getSchemaRefs = getSchemaRefs;
2879
2974
  (__unused_webpack_module, exports) {
2880
2975
 
2881
2976
  "use strict";
2977
+ var __webpack_unused_export__;
2882
2978
 
2883
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2979
+ __webpack_unused_export__ = ({ value: true });
2884
2980
  exports.getRules = exports.isJSONType = void 0;
2885
2981
  const _jsonTypes = ["string", "number", "integer", "boolean", "null", "object", "array"];
2886
2982
  const jsonTypes = new Set(_jsonTypes);
@@ -2912,9 +3008,10 @@ exports.getRules = getRules;
2912
3008
  (__unused_webpack_module, exports, __webpack_require__) {
2913
3009
 
2914
3010
  "use strict";
3011
+ var __webpack_unused_export__;
2915
3012
 
2916
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2917
- exports.checkStrictMode = exports.getErrorPath = exports.Type = exports.useFunc = exports.setEvaluated = exports.evaluatedPropsToName = exports.mergeEvaluated = exports.eachItem = exports.unescapeJsonPointer = exports.escapeJsonPointer = exports.escapeFragment = exports.unescapeFragment = exports.schemaRefOrVal = exports.schemaHasRulesButRef = exports.schemaHasRules = exports.checkUnknownRules = exports.alwaysValidSchema = exports.toHash = void 0;
3013
+ __webpack_unused_export__ = ({ value: true });
3014
+ exports.checkStrictMode = exports.getErrorPath = exports.Type = exports.useFunc = __webpack_unused_export__ = exports.evaluatedPropsToName = exports.mergeEvaluated = exports.eachItem = exports.unescapeJsonPointer = __webpack_unused_export__ = exports.escapeFragment = exports.unescapeFragment = exports.schemaRefOrVal = exports.schemaHasRulesButRef = __webpack_unused_export__ = exports.checkUnknownRules = exports.alwaysValidSchema = exports.toHash = void 0;
2918
3015
  const codegen_1 = __webpack_require__(1410);
2919
3016
  const code_1 = __webpack_require__(1520);
2920
3017
  // TODO refactor to use Set
@@ -2955,7 +3052,7 @@ function schemaHasRules(schema, rules) {
2955
3052
  return true;
2956
3053
  return false;
2957
3054
  }
2958
- exports.schemaHasRules = schemaHasRules;
3055
+ __webpack_unused_export__ = schemaHasRules;
2959
3056
  function schemaHasRulesButRef(schema, RULES) {
2960
3057
  if (typeof schema == "boolean")
2961
3058
  return !schema;
@@ -2988,7 +3085,7 @@ function escapeJsonPointer(str) {
2988
3085
  return `${str}`;
2989
3086
  return str.replace(/~/g, "~0").replace(/\//g, "~1");
2990
3087
  }
2991
- exports.escapeJsonPointer = escapeJsonPointer;
3088
+ __webpack_unused_export__ = escapeJsonPointer;
2992
3089
  function unescapeJsonPointer(str) {
2993
3090
  return str.replace(/~1/g, "/").replace(/~0/g, "~");
2994
3091
  }
@@ -3051,7 +3148,7 @@ exports.evaluatedPropsToName = evaluatedPropsToName;
3051
3148
  function setEvaluated(gen, props, ps) {
3052
3149
  Object.keys(ps).forEach((p) => gen.assign((0, codegen_1._) `${props}${(0, codegen_1.getProperty)(p)}`, true));
3053
3150
  }
3054
- exports.setEvaluated = setEvaluated;
3151
+ __webpack_unused_export__ = setEvaluated;
3055
3152
  const snippets = {};
3056
3153
  function useFunc(gen, f) {
3057
3154
  return gen.scopeValue("func", {
@@ -3097,8 +3194,9 @@ exports.checkStrictMode = checkStrictMode;
3097
3194
  (__unused_webpack_module, exports) {
3098
3195
 
3099
3196
  "use strict";
3197
+ var __webpack_unused_export__;
3100
3198
 
3101
- Object.defineProperty(exports, "__esModule", ({ value: true }));
3199
+ __webpack_unused_export__ = ({ value: true });
3102
3200
  exports.shouldUseRule = exports.shouldUseGroup = exports.schemaHasRulesForType = void 0;
3103
3201
  function schemaHasRulesForType({ schema, self }, type) {
3104
3202
  const group = self.RULES.types[type];
@@ -3123,8 +3221,9 @@ exports.shouldUseRule = shouldUseRule;
3123
3221
  (__unused_webpack_module, exports, __webpack_require__) {
3124
3222
 
3125
3223
  "use strict";
3224
+ var __webpack_unused_export__;
3126
3225
 
3127
- Object.defineProperty(exports, "__esModule", ({ value: true }));
3226
+ __webpack_unused_export__ = ({ value: true });
3128
3227
  exports.boolOrEmptySchema = exports.topBoolOrEmptySchema = void 0;
3129
3228
  const errors_1 = __webpack_require__(8708);
3130
3229
  const codegen_1 = __webpack_require__(1410);
@@ -3180,8 +3279,9 @@ function falseSchemaError(it, overrideAllErrors) {
3180
3279
  (__unused_webpack_module, exports, __webpack_require__) {
3181
3280
 
3182
3281
  "use strict";
3282
+ var __webpack_unused_export__;
3183
3283
 
3184
- Object.defineProperty(exports, "__esModule", ({ value: true }));
3284
+ __webpack_unused_export__ = ({ value: true });
3185
3285
  exports.reportTypeError = exports.checkDataTypes = exports.checkDataType = exports.coerceAndCheckDataType = exports.getJSONTypes = exports.getSchemaTypes = exports.DataType = void 0;
3186
3286
  const rules_1 = __webpack_require__(396);
3187
3287
  const applicability_1 = __webpack_require__(7887);
@@ -3390,8 +3490,9 @@ function getTypeErrorContext(it) {
3390
3490
  (__unused_webpack_module, exports, __webpack_require__) {
3391
3491
 
3392
3492
  "use strict";
3493
+ var __webpack_unused_export__;
3393
3494
 
3394
- Object.defineProperty(exports, "__esModule", ({ value: true }));
3495
+ __webpack_unused_export__ = ({ value: true });
3395
3496
  exports.assignDefaults = void 0;
3396
3497
  const codegen_1 = __webpack_require__(1410);
3397
3498
  const util_1 = __webpack_require__(4227);
@@ -3959,8 +4060,9 @@ exports.getData = getData;
3959
4060
  (__unused_webpack_module, exports, __webpack_require__) {
3960
4061
 
3961
4062
  "use strict";
4063
+ var __webpack_unused_export__;
3962
4064
 
3963
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4065
+ __webpack_unused_export__ = ({ value: true });
3964
4066
  exports.validateKeywordUsage = exports.validSchemaType = exports.funcKeywordCode = exports.macroKeywordCode = void 0;
3965
4067
  const codegen_1 = __webpack_require__(1410);
3966
4068
  const names_1 = __webpack_require__(2023);
@@ -4090,8 +4192,9 @@ exports.validateKeywordUsage = validateKeywordUsage;
4090
4192
  (__unused_webpack_module, exports, __webpack_require__) {
4091
4193
 
4092
4194
  "use strict";
4195
+ var __webpack_unused_export__;
4093
4196
 
4094
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4197
+ __webpack_unused_export__ = ({ value: true });
4095
4198
  exports.extendSubschemaMode = exports.extendSubschemaData = exports.getSubschema = void 0;
4096
4199
  const codegen_1 = __webpack_require__(1410);
4097
4200
  const util_1 = __webpack_require__(4227);
@@ -4178,18 +4281,19 @@ exports.extendSubschemaMode = extendSubschemaMode;
4178
4281
  (__unused_webpack_module, exports, __webpack_require__) {
4179
4282
 
4180
4283
  "use strict";
4284
+ var __webpack_unused_export__;
4181
4285
 
4182
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4183
- exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = void 0;
4286
+ __webpack_unused_export__ = ({ value: true });
4287
+ __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = __webpack_unused_export__ = void 0;
4184
4288
  var validate_1 = __webpack_require__(2586);
4185
- Object.defineProperty(exports, "KeywordCxt", ({ enumerable: true, get: function () { return validate_1.KeywordCxt; } }));
4289
+ __webpack_unused_export__ = ({ enumerable: true, get: function () { return validate_1.KeywordCxt; } });
4186
4290
  var codegen_1 = __webpack_require__(1410);
4187
- Object.defineProperty(exports, "_", ({ enumerable: true, get: function () { return codegen_1._; } }));
4188
- Object.defineProperty(exports, "str", ({ enumerable: true, get: function () { return codegen_1.str; } }));
4189
- Object.defineProperty(exports, "stringify", ({ enumerable: true, get: function () { return codegen_1.stringify; } }));
4190
- Object.defineProperty(exports, "nil", ({ enumerable: true, get: function () { return codegen_1.nil; } }));
4191
- Object.defineProperty(exports, "Name", ({ enumerable: true, get: function () { return codegen_1.Name; } }));
4192
- Object.defineProperty(exports, "CodeGen", ({ enumerable: true, get: function () { return codegen_1.CodeGen; } }));
4291
+ __webpack_unused_export__ = ({ enumerable: true, get: function () { return codegen_1._; } });
4292
+ __webpack_unused_export__ = ({ enumerable: true, get: function () { return codegen_1.str; } });
4293
+ __webpack_unused_export__ = ({ enumerable: true, get: function () { return codegen_1.stringify; } });
4294
+ __webpack_unused_export__ = ({ enumerable: true, get: function () { return codegen_1.nil; } });
4295
+ __webpack_unused_export__ = ({ enumerable: true, get: function () { return codegen_1.Name; } });
4296
+ __webpack_unused_export__ = ({ enumerable: true, get: function () { return codegen_1.CodeGen; } });
4193
4297
  const validation_error_1 = __webpack_require__(3558);
4194
4298
  const ref_error_1 = __webpack_require__(4551);
4195
4299
  const rules_1 = __webpack_require__(396);
@@ -4274,7 +4378,7 @@ class Ajv {
4274
4378
  constructor(opts = {}) {
4275
4379
  this.schemas = {};
4276
4380
  this.refs = {};
4277
- this.formats = {};
4381
+ this.formats = Object.create(null);
4278
4382
  this._compilations = new Set();
4279
4383
  this._loading = {};
4280
4384
  this._cache = new Map();
@@ -4803,8 +4907,9 @@ function schemaOrData(schema) {
4803
4907
  (__unused_webpack_module, exports, __webpack_require__) {
4804
4908
 
4805
4909
  "use strict";
4910
+ var __webpack_unused_export__;
4806
4911
 
4807
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4912
+ __webpack_unused_export__ = ({ value: true });
4808
4913
  // https://github.com/ajv-validator/ajv/issues/889
4809
4914
  const equal = __webpack_require__(4398);
4810
4915
  equal.code = 'require("ajv/dist/runtime/equal").default';
@@ -4817,8 +4922,9 @@ exports["default"] = equal;
4817
4922
  (__unused_webpack_module, exports) {
4818
4923
 
4819
4924
  "use strict";
4925
+ var __webpack_unused_export__;
4820
4926
 
4821
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4927
+ __webpack_unused_export__ = ({ value: true });
4822
4928
  // https://mathiasbynens.be/notes/javascript-encoding
4823
4929
  // https://github.com/bestiejs/punycode.js - punycode.ucs2.decode
4824
4930
  function ucs2length(str) {
@@ -4848,8 +4954,9 @@ ucs2length.code = 'require("ajv/dist/runtime/ucs2length").default';
4848
4954
  (__unused_webpack_module, exports, __webpack_require__) {
4849
4955
 
4850
4956
  "use strict";
4957
+ var __webpack_unused_export__;
4851
4958
 
4852
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4959
+ __webpack_unused_export__ = ({ value: true });
4853
4960
  const uri = __webpack_require__(8343);
4854
4961
  uri.code = 'require("ajv/dist/runtime/uri").default';
4855
4962
  exports["default"] = uri;
@@ -4879,8 +4986,9 @@ exports["default"] = ValidationError;
4879
4986
  (__unused_webpack_module, exports, __webpack_require__) {
4880
4987
 
4881
4988
  "use strict";
4989
+ var __webpack_unused_export__;
4882
4990
 
4883
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4991
+ __webpack_unused_export__ = ({ value: true });
4884
4992
  exports.validateAdditionalItems = void 0;
4885
4993
  const codegen_1 = __webpack_require__(1410);
4886
4994
  const util_1 = __webpack_require__(4227);
@@ -4935,8 +5043,9 @@ exports["default"] = def;
4935
5043
  (__unused_webpack_module, exports, __webpack_require__) {
4936
5044
 
4937
5045
  "use strict";
5046
+ var __webpack_unused_export__;
4938
5047
 
4939
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5048
+ __webpack_unused_export__ = ({ value: true });
4940
5049
  const code_1 = __webpack_require__(5765);
4941
5050
  const codegen_1 = __webpack_require__(1410);
4942
5051
  const names_1 = __webpack_require__(2023);
@@ -5048,8 +5157,9 @@ exports["default"] = def;
5048
5157
  (__unused_webpack_module, exports, __webpack_require__) {
5049
5158
 
5050
5159
  "use strict";
5160
+ var __webpack_unused_export__;
5051
5161
 
5052
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5162
+ __webpack_unused_export__ = ({ value: true });
5053
5163
  const util_1 = __webpack_require__(4227);
5054
5164
  const def = {
5055
5165
  keyword: "allOf",
@@ -5078,8 +5188,9 @@ exports["default"] = def;
5078
5188
  (__unused_webpack_module, exports, __webpack_require__) {
5079
5189
 
5080
5190
  "use strict";
5191
+ var __webpack_unused_export__;
5081
5192
 
5082
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5193
+ __webpack_unused_export__ = ({ value: true });
5083
5194
  const code_1 = __webpack_require__(5765);
5084
5195
  const def = {
5085
5196
  keyword: "anyOf",
@@ -5097,8 +5208,9 @@ exports["default"] = def;
5097
5208
  (__unused_webpack_module, exports, __webpack_require__) {
5098
5209
 
5099
5210
  "use strict";
5211
+ var __webpack_unused_export__;
5100
5212
 
5101
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5213
+ __webpack_unused_export__ = ({ value: true });
5102
5214
  const codegen_1 = __webpack_require__(1410);
5103
5215
  const util_1 = __webpack_require__(4227);
5104
5216
  const error = {
@@ -5199,13 +5311,14 @@ exports["default"] = def;
5199
5311
  (__unused_webpack_module, exports, __webpack_require__) {
5200
5312
 
5201
5313
  "use strict";
5314
+ var __webpack_unused_export__;
5202
5315
 
5203
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5204
- exports.validateSchemaDeps = exports.validatePropertyDeps = exports.error = void 0;
5316
+ __webpack_unused_export__ = ({ value: true });
5317
+ __webpack_unused_export__ = __webpack_unused_export__ = exports.z3 = void 0;
5205
5318
  const codegen_1 = __webpack_require__(1410);
5206
5319
  const util_1 = __webpack_require__(4227);
5207
5320
  const code_1 = __webpack_require__(5765);
5208
- exports.error = {
5321
+ exports.z3 = {
5209
5322
  message: ({ params: { property, depsCount, deps } }) => {
5210
5323
  const property_ies = depsCount === 1 ? "property" : "properties";
5211
5324
  return (0, codegen_1.str) `must have ${property_ies} ${deps} when property ${property} is present`;
@@ -5219,7 +5332,7 @@ const def = {
5219
5332
  keyword: "dependencies",
5220
5333
  type: "object",
5221
5334
  schemaType: "object",
5222
- error: exports.error,
5335
+ error: exports.z3,
5223
5336
  code(cxt) {
5224
5337
  const [propDeps, schDeps] = splitDependencies(cxt);
5225
5338
  validatePropertyDeps(cxt, propDeps);
@@ -5266,7 +5379,7 @@ function validatePropertyDeps(cxt, propertyDeps = cxt.schema) {
5266
5379
  }
5267
5380
  }
5268
5381
  }
5269
- exports.validatePropertyDeps = validatePropertyDeps;
5382
+ __webpack_unused_export__ = validatePropertyDeps;
5270
5383
  function validateSchemaDeps(cxt, schemaDeps = cxt.schema) {
5271
5384
  const { gen, data, keyword, it } = cxt;
5272
5385
  const valid = gen.name("valid");
@@ -5281,7 +5394,7 @@ function validateSchemaDeps(cxt, schemaDeps = cxt.schema) {
5281
5394
  cxt.ok(valid);
5282
5395
  }
5283
5396
  }
5284
- exports.validateSchemaDeps = validateSchemaDeps;
5397
+ __webpack_unused_export__ = validateSchemaDeps;
5285
5398
  exports["default"] = def;
5286
5399
  //# sourceMappingURL=dependencies.js.map
5287
5400
 
@@ -5291,8 +5404,9 @@ exports["default"] = def;
5291
5404
  (__unused_webpack_module, exports, __webpack_require__) {
5292
5405
 
5293
5406
  "use strict";
5407
+ var __webpack_unused_export__;
5294
5408
 
5295
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5409
+ __webpack_unused_export__ = ({ value: true });
5296
5410
  const codegen_1 = __webpack_require__(1410);
5297
5411
  const util_1 = __webpack_require__(4227);
5298
5412
  const error = {
@@ -5364,8 +5478,9 @@ exports["default"] = def;
5364
5478
  (__unused_webpack_module, exports, __webpack_require__) {
5365
5479
 
5366
5480
  "use strict";
5481
+ var __webpack_unused_export__;
5367
5482
 
5368
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5483
+ __webpack_unused_export__ = ({ value: true });
5369
5484
  const additionalItems_1 = __webpack_require__(5457);
5370
5485
  const prefixItems_1 = __webpack_require__(5354);
5371
5486
  const items_1 = __webpack_require__(494);
@@ -5415,8 +5530,9 @@ exports["default"] = getApplicator;
5415
5530
  (__unused_webpack_module, exports, __webpack_require__) {
5416
5531
 
5417
5532
  "use strict";
5533
+ var __webpack_unused_export__;
5418
5534
 
5419
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5535
+ __webpack_unused_export__ = ({ value: true });
5420
5536
  exports.validateTuple = void 0;
5421
5537
  const codegen_1 = __webpack_require__(1410);
5422
5538
  const util_1 = __webpack_require__(4227);
@@ -5474,8 +5590,9 @@ exports["default"] = def;
5474
5590
  (__unused_webpack_module, exports, __webpack_require__) {
5475
5591
 
5476
5592
  "use strict";
5593
+ var __webpack_unused_export__;
5477
5594
 
5478
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5595
+ __webpack_unused_export__ = ({ value: true });
5479
5596
  const codegen_1 = __webpack_require__(1410);
5480
5597
  const util_1 = __webpack_require__(4227);
5481
5598
  const code_1 = __webpack_require__(5765);
@@ -5511,8 +5628,9 @@ exports["default"] = def;
5511
5628
  (__unused_webpack_module, exports, __webpack_require__) {
5512
5629
 
5513
5630
  "use strict";
5631
+ var __webpack_unused_export__;
5514
5632
 
5515
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5633
+ __webpack_unused_export__ = ({ value: true });
5516
5634
  const util_1 = __webpack_require__(4227);
5517
5635
  const def = {
5518
5636
  keyword: "not",
@@ -5544,8 +5662,9 @@ exports["default"] = def;
5544
5662
  (__unused_webpack_module, exports, __webpack_require__) {
5545
5663
 
5546
5664
  "use strict";
5665
+ var __webpack_unused_export__;
5547
5666
 
5548
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5667
+ __webpack_unused_export__ = ({ value: true });
5549
5668
  const codegen_1 = __webpack_require__(1410);
5550
5669
  const util_1 = __webpack_require__(4227);
5551
5670
  const error = {
@@ -5611,8 +5730,9 @@ exports["default"] = def;
5611
5730
  (__unused_webpack_module, exports, __webpack_require__) {
5612
5731
 
5613
5732
  "use strict";
5733
+ var __webpack_unused_export__;
5614
5734
 
5615
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5735
+ __webpack_unused_export__ = ({ value: true });
5616
5736
  const code_1 = __webpack_require__(5765);
5617
5737
  const codegen_1 = __webpack_require__(1410);
5618
5738
  const util_1 = __webpack_require__(4227);
@@ -5693,8 +5813,9 @@ exports["default"] = def;
5693
5813
  (__unused_webpack_module, exports, __webpack_require__) {
5694
5814
 
5695
5815
  "use strict";
5816
+ var __webpack_unused_export__;
5696
5817
 
5697
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5818
+ __webpack_unused_export__ = ({ value: true });
5698
5819
  const items_1 = __webpack_require__(494);
5699
5820
  const def = {
5700
5821
  keyword: "prefixItems",
@@ -5712,8 +5833,9 @@ exports["default"] = def;
5712
5833
  (__unused_webpack_module, exports, __webpack_require__) {
5713
5834
 
5714
5835
  "use strict";
5836
+ var __webpack_unused_export__;
5715
5837
 
5716
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5838
+ __webpack_unused_export__ = ({ value: true });
5717
5839
  const validate_1 = __webpack_require__(2586);
5718
5840
  const code_1 = __webpack_require__(5765);
5719
5841
  const util_1 = __webpack_require__(4227);
@@ -5773,8 +5895,9 @@ exports["default"] = def;
5773
5895
  (__unused_webpack_module, exports, __webpack_require__) {
5774
5896
 
5775
5897
  "use strict";
5898
+ var __webpack_unused_export__;
5776
5899
 
5777
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5900
+ __webpack_unused_export__ = ({ value: true });
5778
5901
  const codegen_1 = __webpack_require__(1410);
5779
5902
  const util_1 = __webpack_require__(4227);
5780
5903
  const error = {
@@ -5818,8 +5941,9 @@ exports["default"] = def;
5818
5941
  (__unused_webpack_module, exports, __webpack_require__) {
5819
5942
 
5820
5943
  "use strict";
5944
+ var __webpack_unused_export__;
5821
5945
 
5822
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5946
+ __webpack_unused_export__ = ({ value: true });
5823
5947
  const util_1 = __webpack_require__(4227);
5824
5948
  const def = {
5825
5949
  keyword: ["then", "else"],
@@ -5838,9 +5962,10 @@ exports["default"] = def;
5838
5962
  (__unused_webpack_module, exports, __webpack_require__) {
5839
5963
 
5840
5964
  "use strict";
5965
+ var __webpack_unused_export__;
5841
5966
 
5842
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5843
- exports.validateUnion = exports.validateArray = exports.usePattern = exports.callValidateCode = exports.schemaProperties = exports.allSchemaProperties = exports.noPropertyInData = exports.propertyInData = exports.isOwnProperty = exports.hasPropFunc = exports.reportMissingProp = exports.checkMissingProp = exports.checkReportMissingProp = void 0;
5967
+ __webpack_unused_export__ = ({ value: true });
5968
+ exports.validateUnion = exports.validateArray = exports.usePattern = exports.callValidateCode = __webpack_unused_export__ = exports.allSchemaProperties = exports.noPropertyInData = exports.propertyInData = exports.isOwnProperty = __webpack_unused_export__ = exports.reportMissingProp = exports.checkMissingProp = exports.checkReportMissingProp = void 0;
5844
5969
  const codegen_1 = __webpack_require__(1410);
5845
5970
  const util_1 = __webpack_require__(4227);
5846
5971
  const names_1 = __webpack_require__(2023);
@@ -5869,7 +5994,7 @@ function hasPropFunc(gen) {
5869
5994
  code: (0, codegen_1._) `Object.prototype.hasOwnProperty`,
5870
5995
  });
5871
5996
  }
5872
- exports.hasPropFunc = hasPropFunc;
5997
+ __webpack_unused_export__ = hasPropFunc;
5873
5998
  function isOwnProperty(gen, data, property) {
5874
5999
  return (0, codegen_1._) `${hasPropFunc(gen)}.call(${data}, ${property})`;
5875
6000
  }
@@ -5891,7 +6016,7 @@ exports.allSchemaProperties = allSchemaProperties;
5891
6016
  function schemaProperties(it, schemaMap) {
5892
6017
  return allSchemaProperties(schemaMap).filter((p) => !(0, util_1.alwaysValidSchema)(it, schemaMap[p]));
5893
6018
  }
5894
- exports.schemaProperties = schemaProperties;
6019
+ __webpack_unused_export__ = schemaProperties;
5895
6020
  function callValidateCode({ schemaCode, data, it: { gen, topSchemaRef, schemaPath, errorPath }, it }, func, context, passSchema) {
5896
6021
  const dataAndSchema = passSchema ? (0, codegen_1._) `${schemaCode}, ${data}, ${topSchemaRef}${schemaPath}` : data;
5897
6022
  const valCxt = [
@@ -5976,8 +6101,9 @@ exports.validateUnion = validateUnion;
5976
6101
  (__unused_webpack_module, exports) {
5977
6102
 
5978
6103
  "use strict";
6104
+ var __webpack_unused_export__;
5979
6105
 
5980
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6106
+ __webpack_unused_export__ = ({ value: true });
5981
6107
  const def = {
5982
6108
  keyword: "id",
5983
6109
  code() {
@@ -5993,8 +6119,9 @@ exports["default"] = def;
5993
6119
  (__unused_webpack_module, exports, __webpack_require__) {
5994
6120
 
5995
6121
  "use strict";
6122
+ var __webpack_unused_export__;
5996
6123
 
5997
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6124
+ __webpack_unused_export__ = ({ value: true });
5998
6125
  const id_1 = __webpack_require__(3463);
5999
6126
  const ref_1 = __webpack_require__(3693);
6000
6127
  const core = [
@@ -6016,9 +6143,10 @@ exports["default"] = core;
6016
6143
  (__unused_webpack_module, exports, __webpack_require__) {
6017
6144
 
6018
6145
  "use strict";
6146
+ var __webpack_unused_export__;
6019
6147
 
6020
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6021
- exports.callRef = exports.getValidate = void 0;
6148
+ __webpack_unused_export__ = ({ value: true });
6149
+ __webpack_unused_export__ = __webpack_unused_export__ = void 0;
6022
6150
  const ref_error_1 = __webpack_require__(4551);
6023
6151
  const code_1 = __webpack_require__(5765);
6024
6152
  const codegen_1 = __webpack_require__(1410);
@@ -6071,7 +6199,7 @@ function getValidate(cxt, sch) {
6071
6199
  ? gen.scopeValue("validate", { ref: sch.validate })
6072
6200
  : (0, codegen_1._) `${gen.scopeValue("wrapper", { ref: sch })}.validate`;
6073
6201
  }
6074
- exports.getValidate = getValidate;
6202
+ __webpack_unused_export__ = getValidate;
6075
6203
  function callRef(cxt, v, sch, $async) {
6076
6204
  const { gen, it } = cxt;
6077
6205
  const { allErrors, schemaEnv: env, opts } = it;
@@ -6135,7 +6263,7 @@ function callRef(cxt, v, sch, $async) {
6135
6263
  }
6136
6264
  }
6137
6265
  }
6138
- exports.callRef = callRef;
6266
+ __webpack_unused_export__ = callRef;
6139
6267
  exports["default"] = def;
6140
6268
  //# sourceMappingURL=ref.js.map
6141
6269
 
@@ -6145,8 +6273,9 @@ exports["default"] = def;
6145
6273
  (__unused_webpack_module, exports, __webpack_require__) {
6146
6274
 
6147
6275
  "use strict";
6276
+ var __webpack_unused_export__;
6148
6277
 
6149
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6278
+ __webpack_unused_export__ = ({ value: true });
6150
6279
  const codegen_1 = __webpack_require__(1410);
6151
6280
  const types_1 = __webpack_require__(7652);
6152
6281
  const compile_1 = __webpack_require__(3835);
@@ -6256,8 +6385,9 @@ exports["default"] = def;
6256
6385
  (__unused_webpack_module, exports) {
6257
6386
 
6258
6387
  "use strict";
6388
+ var __webpack_unused_export__;
6259
6389
 
6260
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6390
+ __webpack_unused_export__ = ({ value: true });
6261
6391
  exports.DiscrError = void 0;
6262
6392
  var DiscrError;
6263
6393
  (function (DiscrError) {
@@ -6272,8 +6402,9 @@ var DiscrError;
6272
6402
  (__unused_webpack_module, exports, __webpack_require__) {
6273
6403
 
6274
6404
  "use strict";
6405
+ var __webpack_unused_export__;
6275
6406
 
6276
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6407
+ __webpack_unused_export__ = ({ value: true });
6277
6408
  const core_1 = __webpack_require__(2128);
6278
6409
  const validation_1 = __webpack_require__(7060);
6279
6410
  const applicator_1 = __webpack_require__(6378);
@@ -6296,8 +6427,9 @@ exports["default"] = draft7Vocabularies;
6296
6427
  (__unused_webpack_module, exports, __webpack_require__) {
6297
6428
 
6298
6429
  "use strict";
6430
+ var __webpack_unused_export__;
6299
6431
 
6300
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6432
+ __webpack_unused_export__ = ({ value: true });
6301
6433
  const codegen_1 = __webpack_require__(1410);
6302
6434
  const error = {
6303
6435
  message: ({ schemaCode }) => (0, codegen_1.str) `must match format "${schemaCode}"`,
@@ -6395,8 +6527,9 @@ exports["default"] = def;
6395
6527
  (__unused_webpack_module, exports, __webpack_require__) {
6396
6528
 
6397
6529
  "use strict";
6530
+ var __webpack_unused_export__;
6398
6531
 
6399
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6532
+ __webpack_unused_export__ = ({ value: true });
6400
6533
  const format_1 = __webpack_require__(4737);
6401
6534
  const format = [format_1.default];
6402
6535
  exports["default"] = format;
@@ -6408,8 +6541,9 @@ exports["default"] = format;
6408
6541
  (__unused_webpack_module, exports) {
6409
6542
 
6410
6543
  "use strict";
6544
+ var __webpack_unused_export__;
6411
6545
 
6412
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6546
+ __webpack_unused_export__ = ({ value: true });
6413
6547
  exports.contentVocabulary = exports.metadataVocabulary = void 0;
6414
6548
  exports.metadataVocabulary = [
6415
6549
  "title",
@@ -6433,8 +6567,9 @@ exports.contentVocabulary = [
6433
6567
  (__unused_webpack_module, exports, __webpack_require__) {
6434
6568
 
6435
6569
  "use strict";
6570
+ var __webpack_unused_export__;
6436
6571
 
6437
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6572
+ __webpack_unused_export__ = ({ value: true });
6438
6573
  const codegen_1 = __webpack_require__(1410);
6439
6574
  const util_1 = __webpack_require__(4227);
6440
6575
  const equal_1 = __webpack_require__(6250);
@@ -6465,8 +6600,9 @@ exports["default"] = def;
6465
6600
  (__unused_webpack_module, exports, __webpack_require__) {
6466
6601
 
6467
6602
  "use strict";
6603
+ var __webpack_unused_export__;
6468
6604
 
6469
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6605
+ __webpack_unused_export__ = ({ value: true });
6470
6606
  const codegen_1 = __webpack_require__(1410);
6471
6607
  const util_1 = __webpack_require__(4227);
6472
6608
  const equal_1 = __webpack_require__(6250);
@@ -6520,8 +6656,9 @@ exports["default"] = def;
6520
6656
  (__unused_webpack_module, exports, __webpack_require__) {
6521
6657
 
6522
6658
  "use strict";
6659
+ var __webpack_unused_export__;
6523
6660
 
6524
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6661
+ __webpack_unused_export__ = ({ value: true });
6525
6662
  const limitNumber_1 = __webpack_require__(5882);
6526
6663
  const multipleOf_1 = __webpack_require__(3439);
6527
6664
  const limitLength_1 = __webpack_require__(7307);
@@ -6560,8 +6697,9 @@ exports["default"] = validation;
6560
6697
  (__unused_webpack_module, exports, __webpack_require__) {
6561
6698
 
6562
6699
  "use strict";
6700
+ var __webpack_unused_export__;
6563
6701
 
6564
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6702
+ __webpack_unused_export__ = ({ value: true });
6565
6703
  const codegen_1 = __webpack_require__(1410);
6566
6704
  const error = {
6567
6705
  message({ keyword, schemaCode }) {
@@ -6591,8 +6729,9 @@ exports["default"] = def;
6591
6729
  (__unused_webpack_module, exports, __webpack_require__) {
6592
6730
 
6593
6731
  "use strict";
6732
+ var __webpack_unused_export__;
6594
6733
 
6595
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6734
+ __webpack_unused_export__ = ({ value: true });
6596
6735
  const codegen_1 = __webpack_require__(1410);
6597
6736
  const util_1 = __webpack_require__(4227);
6598
6737
  const ucs2length_1 = __webpack_require__(3853);
@@ -6625,8 +6764,9 @@ exports["default"] = def;
6625
6764
  (__unused_webpack_module, exports, __webpack_require__) {
6626
6765
 
6627
6766
  "use strict";
6767
+ var __webpack_unused_export__;
6628
6768
 
6629
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6769
+ __webpack_unused_export__ = ({ value: true });
6630
6770
  const codegen_1 = __webpack_require__(1410);
6631
6771
  const ops = codegen_1.operators;
6632
6772
  const KWDs = {
@@ -6659,8 +6799,9 @@ exports["default"] = def;
6659
6799
  (__unused_webpack_module, exports, __webpack_require__) {
6660
6800
 
6661
6801
  "use strict";
6802
+ var __webpack_unused_export__;
6662
6803
 
6663
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6804
+ __webpack_unused_export__ = ({ value: true });
6664
6805
  const codegen_1 = __webpack_require__(1410);
6665
6806
  const error = {
6666
6807
  message({ keyword, schemaCode }) {
@@ -6690,8 +6831,9 @@ exports["default"] = def;
6690
6831
  (__unused_webpack_module, exports, __webpack_require__) {
6691
6832
 
6692
6833
  "use strict";
6834
+ var __webpack_unused_export__;
6693
6835
 
6694
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6836
+ __webpack_unused_export__ = ({ value: true });
6695
6837
  const codegen_1 = __webpack_require__(1410);
6696
6838
  const error = {
6697
6839
  message: ({ schemaCode }) => (0, codegen_1.str) `must be multiple of ${schemaCode}`,
@@ -6723,8 +6865,9 @@ exports["default"] = def;
6723
6865
  (__unused_webpack_module, exports, __webpack_require__) {
6724
6866
 
6725
6867
  "use strict";
6868
+ var __webpack_unused_export__;
6726
6869
 
6727
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6870
+ __webpack_unused_export__ = ({ value: true });
6728
6871
  const code_1 = __webpack_require__(5765);
6729
6872
  const util_1 = __webpack_require__(4227);
6730
6873
  const codegen_1 = __webpack_require__(1410);
@@ -6763,8 +6906,9 @@ exports["default"] = def;
6763
6906
  (__unused_webpack_module, exports, __webpack_require__) {
6764
6907
 
6765
6908
  "use strict";
6909
+ var __webpack_unused_export__;
6766
6910
 
6767
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6911
+ __webpack_unused_export__ = ({ value: true });
6768
6912
  const code_1 = __webpack_require__(5765);
6769
6913
  const codegen_1 = __webpack_require__(1410);
6770
6914
  const util_1 = __webpack_require__(4227);
@@ -6849,8 +6993,9 @@ exports["default"] = def;
6849
6993
  (__unused_webpack_module, exports, __webpack_require__) {
6850
6994
 
6851
6995
  "use strict";
6996
+ var __webpack_unused_export__;
6852
6997
 
6853
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6998
+ __webpack_unused_export__ = ({ value: true });
6854
6999
  const dataType_1 = __webpack_require__(208);
6855
7000
  const codegen_1 = __webpack_require__(1410);
6856
7001
  const util_1 = __webpack_require__(4227);
@@ -7529,11 +7674,7 @@ function createStrictSyntaxError (str, char) {
7529
7674
  var partial = ''
7530
7675
 
7531
7676
  if (index !== -1) {
7532
- partial = str.substring(0, index) + JSON_SYNTAX_CHAR
7533
-
7534
- for (var i = index + 1; i < str.length; i++) {
7535
- partial += JSON_SYNTAX_CHAR
7536
- }
7677
+ partial = str.substring(0, index) + new Array(str.length - index + 1).join(JSON_SYNTAX_CHAR)
7537
7678
  }
7538
7679
 
7539
7680
  try {
@@ -8070,16 +8211,15 @@ function getCharset (req) {
8070
8211
 
8071
8212
  function parameterCount (body, limit) {
8072
8213
  var count = 0
8073
- var index = 0
8214
+ var index = -1
8074
8215
 
8075
- while ((index = body.indexOf('&', index)) !== -1) {
8216
+ do {
8076
8217
  count++
8077
- index++
8078
-
8079
- if (count === limit) {
8218
+ if (count > limit) {
8080
8219
  return undefined
8081
8220
  }
8082
- }
8221
+ index = body.indexOf('&', index + 1)
8222
+ } while (index !== -1)
8083
8223
 
8084
8224
  return count
8085
8225
  }
@@ -16056,7 +16196,8 @@ function createETagGenerator (options) {
16056
16196
 
16057
16197
  function parseExtendedQueryString(str) {
16058
16198
  return qs.parse(str, {
16059
- allowPrototypes: true
16199
+ allowPrototypes: true,
16200
+ arrayLimit: 1000
16060
16201
  });
16061
16202
  }
16062
16203
 
@@ -24513,6 +24654,7 @@ function pathToRegexp(path, keys, options) {
24513
24654
  pos = offset + match.length;
24514
24655
 
24515
24656
  if (match === '*') {
24657
+ backtrack = '';
24516
24658
  extraOffset += 3;
24517
24659
  return '(.*)';
24518
24660
  }
@@ -24542,6 +24684,7 @@ function pathToRegexp(path, keys, options) {
24542
24684
  + ')'
24543
24685
  + optional;
24544
24686
 
24687
+ backtrack = '';
24545
24688
  extraOffset += result.length - match.length;
24546
24689
 
24547
24690
  return result;
@@ -24993,6 +25136,7 @@ var defaults = {
24993
25136
  parseArrays: true,
24994
25137
  plainObjects: false,
24995
25138
  strictDepth: false,
25139
+ strictMerge: true,
24996
25140
  strictNullHandling: false,
24997
25141
  throwOnLimitExceeded: false
24998
25142
  };
@@ -25034,10 +25178,10 @@ var parseValues = function parseQueryStringValues(str, options) {
25034
25178
  var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
25035
25179
  var parts = cleanStr.split(
25036
25180
  options.delimiter,
25037
- options.throwOnLimitExceeded ? limit + 1 : limit
25181
+ options.throwOnLimitExceeded && typeof limit !== 'undefined' ? limit + 1 : limit
25038
25182
  );
25039
25183
 
25040
- if (options.throwOnLimitExceeded && parts.length > limit) {
25184
+ if (options.throwOnLimitExceeded && typeof limit !== 'undefined' && parts.length > limit) {
25041
25185
  throw new RangeError('Parameter limit exceeded. Only ' + limit + ' parameter' + (limit === 1 ? '' : 's') + ' allowed.');
25042
25186
  }
25043
25187
 
@@ -25107,7 +25251,7 @@ var parseValues = function parseQueryStringValues(str, options) {
25107
25251
 
25108
25252
  if (key !== null) {
25109
25253
  var existing = has.call(obj, key);
25110
- if (existing && options.duplicates === 'combine') {
25254
+ if (existing && (options.duplicates === 'combine' || part.indexOf('[]=') > -1)) {
25111
25255
  obj[key] = utils.combine(
25112
25256
  obj[key],
25113
25257
  val,
@@ -25181,9 +25325,12 @@ var parseObject = function (chain, val, options, valuesParsed) {
25181
25325
  return leaf;
25182
25326
  };
25183
25327
 
25184
- var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
25185
- var key = options.allowDots ? givenKey.replace(/\.([^.[]+)/g, '[$1]') : givenKey;
25328
+ // Split a key like "a[b][c[]]" into ['a', '[b]', '[c[]]'] while preserving
25329
+ // qs parse semantics for depth/prototype guards.
25330
+ var splitKeyIntoSegments = function splitKeyIntoSegments(originalKey, options) {
25331
+ var key = options.allowDots ? originalKey.replace(/\.([^.[]+)/g, '[$1]') : originalKey;
25186
25332
 
25333
+ // depth <= 0 keeps the whole key as one segment
25187
25334
  if (options.depth <= 0) {
25188
25335
  if (!options.plainObjects && has.call(Object.prototype, key)) {
25189
25336
  if (!options.allowPrototypes) {
@@ -25194,14 +25341,11 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
25194
25341
  return [key];
25195
25342
  }
25196
25343
 
25197
- var brackets = /(\[[^[\]]*])/;
25198
- var child = /(\[[^[\]]*])/g;
25199
-
25200
- var segment = brackets.exec(key);
25201
- var parent = segment ? key.slice(0, segment.index) : key;
25202
-
25203
- var keys = [];
25344
+ var segments = [];
25204
25345
 
25346
+ // parent before the first '[' (may be empty if key starts with '[')
25347
+ var first = key.indexOf('[');
25348
+ var parent = first >= 0 ? key.slice(0, first) : key;
25205
25349
  if (parent) {
25206
25350
  if (!options.plainObjects && has.call(Object.prototype, parent)) {
25207
25351
  if (!options.allowPrototypes) {
@@ -25209,32 +25353,62 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
25209
25353
  }
25210
25354
  }
25211
25355
 
25212
- keys[keys.length] = parent;
25356
+ segments[segments.length] = parent;
25213
25357
  }
25214
25358
 
25215
- var i = 0;
25216
- while ((segment = child.exec(key)) !== null && i < options.depth) {
25217
- i += 1;
25359
+ var n = key.length;
25360
+ var open = first;
25361
+ var collected = 0;
25218
25362
 
25219
- var segmentContent = segment[1].slice(1, -1);
25220
- if (!options.plainObjects && has.call(Object.prototype, segmentContent)) {
25221
- if (!options.allowPrototypes) {
25222
- return;
25363
+ while (open >= 0 && collected < options.depth) {
25364
+ var level = 1;
25365
+ var i = open + 1;
25366
+ var close = -1;
25367
+
25368
+ // balance nested '[' and ']' inside this bracket group using a nesting level counter
25369
+ while (i < n && close < 0) {
25370
+ var cu = key.charCodeAt(i);
25371
+ if (cu === 0x5B) { // '['
25372
+ level += 1;
25373
+ } else if (cu === 0x5D) { // ']'
25374
+ level -= 1;
25375
+ if (level === 0) {
25376
+ close = i; // found matching close; loop will exit by condition
25377
+ }
25223
25378
  }
25379
+ i += 1;
25380
+ }
25381
+
25382
+ if (close < 0) {
25383
+ // Unterminated group: wrap the raw remainder in one bracket pair so it stays
25384
+ // a single literal segment (e.g. "[[]b" -> "[[]b]"); we do not infer missing ']'.
25385
+ segments[segments.length] = '[' + key.slice(open) + ']';
25386
+ return segments;
25224
25387
  }
25225
25388
 
25226
- keys[keys.length] = segment[1];
25389
+ var seg = key.slice(open, close + 1);
25390
+ // prototype guard for the content of this group
25391
+ var content = seg.slice(1, -1);
25392
+ if (!options.plainObjects && has.call(Object.prototype, content) && !options.allowPrototypes) {
25393
+ return;
25394
+ }
25395
+
25396
+ segments[segments.length] = seg;
25397
+ collected += 1;
25398
+
25399
+ // find the next '[' after this balanced group
25400
+ open = key.indexOf('[', close + 1);
25227
25401
  }
25228
25402
 
25229
- if (segment) {
25403
+ if (open >= 0) {
25230
25404
  if (options.strictDepth === true) {
25231
25405
  throw new RangeError('Input depth exceeded depth option of ' + options.depth + ' and strictDepth is true');
25232
25406
  }
25233
25407
 
25234
- keys[keys.length] = '[' + key.slice(segment.index) + ']';
25408
+ segments[segments.length] = '[' + key.slice(open) + ']';
25235
25409
  }
25236
25410
 
25237
- return keys;
25411
+ return segments;
25238
25412
  };
25239
25413
 
25240
25414
  var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) {
@@ -25307,6 +25481,7 @@ var normalizeParseOptions = function normalizeParseOptions(opts) {
25307
25481
  parseArrays: opts.parseArrays !== false,
25308
25482
  plainObjects: typeof opts.plainObjects === 'boolean' ? opts.plainObjects : defaults.plainObjects,
25309
25483
  strictDepth: typeof opts.strictDepth === 'boolean' ? !!opts.strictDepth : defaults.strictDepth,
25484
+ strictMerge: typeof opts.strictMerge === 'boolean' ? !!opts.strictMerge : defaults.strictMerge,
25310
25485
  strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling,
25311
25486
  throwOnLimitExceeded: typeof opts.throwOnLimitExceeded === 'boolean' ? opts.throwOnLimitExceeded : false
25312
25487
  };
@@ -25465,7 +25640,7 @@ var stringify = function stringify(
25465
25640
 
25466
25641
  if (obj === null) {
25467
25642
  if (strictNullHandling) {
25468
- return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix;
25643
+ return formatter(encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix);
25469
25644
  }
25470
25645
 
25471
25646
  obj = '';
@@ -25489,7 +25664,9 @@ var stringify = function stringify(
25489
25664
  if (generateArrayPrefix === 'comma' && isArray(obj)) {
25490
25665
  // we need to join elements in
25491
25666
  if (encodeValuesOnly && encoder) {
25492
- obj = utils.maybeMap(obj, encoder);
25667
+ obj = utils.maybeMap(obj, function (v) {
25668
+ return v == null ? v : encoder(v);
25669
+ });
25493
25670
  }
25494
25671
  objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];
25495
25672
  } else if (isArray(filter)) {
@@ -25659,6 +25836,11 @@ module.exports = function (object, opts) {
25659
25836
  var sideChannel = getSideChannel();
25660
25837
  for (var i = 0; i < objKeys.length; ++i) {
25661
25838
  var key = objKeys[i];
25839
+
25840
+ if (typeof key === 'undefined' || key === null) {
25841
+ continue;
25842
+ }
25843
+
25662
25844
  var value = obj[key];
25663
25845
 
25664
25846
  if (options.skipNulls && value === null) {
@@ -25692,10 +25874,10 @@ module.exports = function (object, opts) {
25692
25874
  if (options.charsetSentinel) {
25693
25875
  if (options.charset === 'iso-8859-1') {
25694
25876
  // encodeURIComponent('&#10003;'), the "numeric entity" representation of a checkmark
25695
- prefix += 'utf8=%26%2310003%3B&';
25877
+ prefix += 'utf8=%26%2310003%3B' + options.delimiter;
25696
25878
  } else {
25697
25879
  // encodeURIComponent('✓')
25698
- prefix += 'utf8=%E2%9C%93&';
25880
+ prefix += 'utf8=%E2%9C%93' + options.delimiter;
25699
25881
  }
25700
25882
  }
25701
25883
 
@@ -25796,6 +25978,8 @@ var merge = function merge(target, source, options) {
25796
25978
  var newIndex = getMaxIndex(target) + 1;
25797
25979
  target[newIndex] = source;
25798
25980
  setMaxIndex(target, newIndex);
25981
+ } else if (options && options.strictMerge) {
25982
+ return [target, source];
25799
25983
  } else if (
25800
25984
  (options && (options.plainObjects || options.allowPrototypes))
25801
25985
  || !has.call(Object.prototype, source)
@@ -31272,9 +31456,8 @@ module.exports = function getSideChannelList() {
31272
31456
  }
31273
31457
  },
31274
31458
  'delete': function (key) {
31275
- var root = $o && $o.next;
31276
31459
  var deletedNode = listDelete($o, key);
31277
- if (deletedNode && root && root === deletedNode) {
31460
+ if (deletedNode && $o && !$o.next) {
31278
31461
  $o = void undefined;
31279
31462
  }
31280
31463
  return !!deletedNode;
@@ -31296,7 +31479,6 @@ module.exports = function getSideChannelList() {
31296
31479
  listSet(/** @type {NonNullable<typeof $o>} */ ($o), key, value);
31297
31480
  }
31298
31481
  };
31299
- // @ts-expect-error TODO: figure out why this is erroring
31300
31482
  return channel;
31301
31483
  };
31302
31484
 
@@ -32058,6 +32240,7 @@ let McpSettingsTabComponent = class McpSettingsTabComponent {
32058
32240
  this.sftpTools = sftpTools;
32059
32241
  this.version = version_1.PLUGIN_VERSION;
32060
32242
  this.saveMessage = '';
32243
+ this.lastEnvironmentDetectionEnabled = false;
32061
32244
  // ============== Connection Monitor ==============
32062
32245
  this.showMonitor = false;
32063
32246
  this.sessions = [];
@@ -32100,6 +32283,14 @@ let McpSettingsTabComponent = class McpSettingsTabComponent {
32100
32283
  timeout: 60000
32101
32284
  };
32102
32285
  }
32286
+ // Ensure environmentDetection config exists
32287
+ if (!this.config.store.mcp.environmentDetection) {
32288
+ this.config.store.mcp.environmentDetection = {
32289
+ enabled: false,
32290
+ useEnhancedHeuristics: true,
32291
+ mode: 'heuristic'
32292
+ };
32293
+ }
32103
32294
  // Ensure new fields exist on existing config
32104
32295
  if (this.config.store.mcp.sftp.maxUploadSize === undefined) {
32105
32296
  this.config.store.mcp.sftp.maxUploadSize = 10 * 1024 * 1024 * 1024;
@@ -32107,6 +32298,7 @@ let McpSettingsTabComponent = class McpSettingsTabComponent {
32107
32298
  if (this.config.store.mcp.sftp.maxDownloadSize === undefined) {
32108
32299
  this.config.store.mcp.sftp.maxDownloadSize = 10 * 1024 * 1024 * 1024;
32109
32300
  }
32301
+ this.lastEnvironmentDetectionEnabled = this.config.store.mcp.environmentDetection.enabled === true;
32110
32302
  }
32111
32303
  ngOnDestroy() {
32112
32304
  this.configSub?.unsubscribe();
@@ -32174,10 +32366,25 @@ let McpSettingsTabComponent = class McpSettingsTabComponent {
32174
32366
  window.open(url, '_blank');
32175
32367
  }
32176
32368
  }
32177
- saveConfig() {
32178
- this.config.save();
32179
- this.saveMessage = this.t('mcp.common.saved');
32180
- setTimeout(() => { this.saveMessage = ''; }, 2000);
32369
+ async saveConfig() {
32370
+ const environmentDetectionEnabled = this.config.store.mcp?.environmentDetection?.enabled === true;
32371
+ const environmentDetectionChanged = environmentDetectionEnabled !== this.lastEnvironmentDetectionEnabled;
32372
+ await this.config.save();
32373
+ this.lastEnvironmentDetectionEnabled = environmentDetectionEnabled;
32374
+ if (environmentDetectionChanged && this.isRunning) {
32375
+ const shouldRestart = confirm(this.t('mcp.environmentDetection.restart.confirm'));
32376
+ if (shouldRestart) {
32377
+ await this.restartServer();
32378
+ this.saveMessage = this.t('mcp.environmentDetection.restart.done');
32379
+ }
32380
+ else {
32381
+ this.saveMessage = this.t('mcp.environmentDetection.restart.later');
32382
+ }
32383
+ }
32384
+ else {
32385
+ this.saveMessage = this.t('mcp.common.saved');
32386
+ }
32387
+ setTimeout(() => { this.saveMessage = ''; }, 3000);
32181
32388
  }
32182
32389
  // ============== Size conversion helpers (MB <-> Bytes) ==============
32183
32390
  getMaxFileSizeMB() {
@@ -32498,6 +32705,58 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
32498
32705
 
32499
32706
  <hr />
32500
32707
 
32708
+ <h4>🧭 {{ t('mcp.environmentDetection.title') }}</h4>
32709
+ <small class="form-text text-muted mb-2">
32710
+ {{ t('mcp.environmentDetection.desc') }}
32711
+ </small>
32712
+
32713
+ <div class="form-group">
32714
+ <div class="checkbox">
32715
+ <label>
32716
+ <input type="checkbox" [(ngModel)]="config.store.mcp.environmentDetection.enabled" (change)="saveConfig()">
32717
+ {{ t('mcp.environmentDetection.enable') }}
32718
+ </label>
32719
+ </div>
32720
+ <small class="form-text text-muted">
32721
+ {{ t('mcp.environmentDetection.enable.desc') }}
32722
+ </small>
32723
+ </div>
32724
+
32725
+ <div class="form-group" *ngIf="config.store.mcp.environmentDetection.enabled">
32726
+ <div class="checkbox">
32727
+ <label>
32728
+ <input type="checkbox" [(ngModel)]="config.store.mcp.environmentDetection.useEnhancedHeuristics" (change)="saveConfig()">
32729
+ {{ t('mcp.environmentDetection.enhanced') }}
32730
+ </label>
32731
+ </div>
32732
+ <small class="form-text text-muted">
32733
+ {{ t('mcp.environmentDetection.enhanced.desc') }}
32734
+ </small>
32735
+ </div>
32736
+
32737
+ <div class="form-group" *ngIf="config.store.mcp.environmentDetection.enabled">
32738
+ <label>{{ t('mcp.environmentDetection.mode') }}</label>
32739
+ <select class="form-control" [(ngModel)]="config.store.mcp.environmentDetection.mode" (change)="saveConfig()">
32740
+ <option value="heuristic">{{ t('mcp.environmentDetection.mode.heuristic') }}</option>
32741
+ <option value="active">{{ t('mcp.environmentDetection.mode.active') }}</option>
32742
+ </select>
32743
+ <small class="form-text text-muted">
32744
+ {{ t('mcp.environmentDetection.mode.desc') }}
32745
+ </small>
32746
+ </div>
32747
+
32748
+ <div class="alert alert-warning" *ngIf="config.store.mcp.environmentDetection.enabled">
32749
+ <strong>⚠️ {{ t('mcp.environmentDetection.warning.title') }}</strong>
32750
+ <ul class="mb-0">
32751
+ <li>{{ t('mcp.environmentDetection.warning.heuristic') }}</li>
32752
+ <li>{{ t('mcp.environmentDetection.warning.transient') }}</li>
32753
+ <li>{{ t('mcp.environmentDetection.warning.customPrompt') }}</li>
32754
+ <li>{{ t('mcp.environmentDetection.warning.verify') }}</li>
32755
+ </ul>
32756
+ </div>
32757
+
32758
+ <hr />
32759
+
32501
32760
  <h4>🧪 {{ t('mcp.experimental.title') || 'Experimental Features' }}</h4>
32502
32761
 
32503
32762
  <div class="form-group">
@@ -33198,6 +33457,10 @@ let McpModule = class McpModule {
33198
33457
  this.tabManagementTools = tabManagementTools;
33199
33458
  this.sftpTools = sftpTools;
33200
33459
  this.initialized = false;
33460
+ this.shutdownInProgress = false;
33461
+ this.handleBeforeUnload = () => {
33462
+ this.shutdownServer('window unload');
33463
+ };
33201
33464
  this.logger.info('MCP Module loading...');
33202
33465
  // Register all tool categories with MCP service
33203
33466
  this.mcpService.registerToolCategory(this.terminalTools);
@@ -33208,11 +33471,15 @@ let McpModule = class McpModule {
33208
33471
  this.logger.info('SFTP tools registered');
33209
33472
  }
33210
33473
  // Initialize server after app is ready
33211
- this.app.ready$.subscribe(() => {
33474
+ this.appReadySubscription = this.app.ready$.subscribe(() => {
33212
33475
  this.config.ready$.toPromise().then(() => {
33213
33476
  this.initializeOnBoot();
33214
33477
  });
33215
33478
  });
33479
+ if (typeof window !== 'undefined') {
33480
+ window.addEventListener('beforeunload', this.handleBeforeUnload);
33481
+ window.addEventListener('unload', this.handleBeforeUnload);
33482
+ }
33216
33483
  }
33217
33484
  /**
33218
33485
  * Initialize MCP server on application boot
@@ -33241,6 +33508,22 @@ let McpModule = class McpModule {
33241
33508
  this.logger.error('Failed to start MCP server on boot:', error);
33242
33509
  }
33243
33510
  }
33511
+ ngOnDestroy() {
33512
+ this.appReadySubscription?.unsubscribe();
33513
+ if (typeof window !== 'undefined') {
33514
+ window.removeEventListener('beforeunload', this.handleBeforeUnload);
33515
+ window.removeEventListener('unload', this.handleBeforeUnload);
33516
+ }
33517
+ this.shutdownServer('module destroy');
33518
+ }
33519
+ shutdownServer(reason) {
33520
+ if (this.shutdownInProgress || !this.mcpService.isServerRunning()) {
33521
+ return;
33522
+ }
33523
+ this.shutdownInProgress = true;
33524
+ this.logger.info(`Stopping MCP server due to ${reason}...`);
33525
+ this.mcpService.stopServerSync(reason);
33526
+ }
33244
33527
  };
33245
33528
  McpModule = __decorate([
33246
33529
  (0, core_1.NgModule)({
@@ -33491,6 +33774,12 @@ let McpConfigProvider = class McpConfigProvider extends tabby_core_1.ConfigProvi
33491
33774
  maxUploadSize: 10 * 1024 * 1024 * 1024, // Default: 10GB
33492
33775
  maxDownloadSize: 10 * 1024 * 1024 * 1024, // Default: 10GB
33493
33776
  timeout: 60000 // SFTP operation timeout in ms
33777
+ },
33778
+ // Environment detection configuration
33779
+ environmentDetection: {
33780
+ enabled: false, // Default off: detection is optional and should not confuse clients unless explicitly enabled
33781
+ useEnhancedHeuristics: true, // Normalize ANSI/control sequences and scan recent prompt lines
33782
+ mode: 'heuristic' // heuristic = passive buffer analysis, active = add low-risk probing for shell sessions
33494
33783
  }
33495
33784
  }
33496
33785
  };
@@ -33710,6 +33999,15 @@ const version_1 = __webpack_require__(5672);
33710
33999
  * - Legacy SSE: GET /sse + POST /messages (backwards compatible)
33711
34000
  */
33712
34001
  let McpService = class McpService {
34002
+ isToolEnabled(toolName) {
34003
+ if (toolName === 'get_session_environment') {
34004
+ return this.config?.store?.mcp?.environmentDetection?.enabled === true;
34005
+ }
34006
+ return true;
34007
+ }
34008
+ getEnabledToolsFromCategory(category) {
34009
+ return category.mcpTools.filter(tool => this.isToolEnabled(tool.name));
34010
+ }
33713
34011
  constructor(config, logger) {
33714
34012
  this.config = config;
33715
34013
  this.logger = logger;
@@ -33723,6 +34021,8 @@ let McpService = class McpService {
33723
34021
  this.toolCategories = [];
33724
34022
  // Store tool definitions for registering with each new server
33725
34023
  this.registeredTools = [];
34024
+ // Track whether tool endpoints have been registered to prevent duplicates on restart
34025
+ this.toolEndpointsConfigured = false;
33726
34026
  // ============================================================
33727
34027
  // CONNECTION MONITORING & MANAGEMENT
33728
34028
  // ============================================================
@@ -33746,8 +34046,8 @@ let McpService = class McpService {
33746
34046
  name: 'Tabby MCP',
33747
34047
  version: version_1.PLUGIN_VERSION
33748
34048
  });
33749
- // Register all tools with this server instance
33750
- for (const toolDef of this.registeredTools) {
34049
+ // Register enabled tools with this server instance
34050
+ for (const toolDef of this.registeredTools.filter(tool => this.isToolEnabled(tool.name))) {
33751
34051
  server.tool(toolDef.name, toolDef.description, toolDef.schema, toolDef.handler);
33752
34052
  }
33753
34053
  this.sessionServers[sessionId] = server;
@@ -33831,7 +34131,7 @@ let McpService = class McpService {
33831
34131
  legacySse: '/sse',
33832
34132
  legacyMessages: '/messages'
33833
34133
  },
33834
- tools: this.toolCategories.flatMap(c => c.mcpTools.map(t => ({
34134
+ tools: this.toolCategories.flatMap(c => this.getEnabledToolsFromCategory(c).map(t => ({
33835
34135
  name: t.name,
33836
34136
  description: t.description
33837
34137
  })))
@@ -33840,10 +34140,10 @@ let McpService = class McpService {
33840
34140
  // Tools list endpoint (for debugging)
33841
34141
  this.app.get('/tools', (_, res) => {
33842
34142
  res.status(200).json({
33843
- count: this.toolCategories.reduce((sum, c) => sum + c.mcpTools.length, 0),
34143
+ count: this.toolCategories.reduce((sum, c) => sum + this.getEnabledToolsFromCategory(c).length, 0),
33844
34144
  categories: this.toolCategories.map(c => ({
33845
34145
  name: c.name,
33846
- tools: c.mcpTools.map(t => t.name)
34146
+ tools: this.getEnabledToolsFromCategory(c).map(t => t.name)
33847
34147
  }))
33848
34148
  });
33849
34149
  });
@@ -34055,8 +34355,6 @@ let McpService = class McpService {
34055
34355
  this.logger.debug(`Legacy SSE: Message received for sessionId=${sessionId}`);
34056
34356
  await transport.handlePostMessage(req, res);
34057
34357
  });
34058
- // Configure API endpoints for direct tool access
34059
- this.configureToolEndpoints();
34060
34358
  }
34061
34359
  /**
34062
34360
  * Validate origin header for security
@@ -34092,9 +34390,20 @@ let McpService = class McpService {
34092
34390
  * Configure HTTP API endpoints for direct tool access
34093
34391
  */
34094
34392
  configureToolEndpoints() {
34393
+ if (this.toolEndpointsConfigured) {
34394
+ this.logger.debug('Tool endpoints already configured, skipping');
34395
+ return;
34396
+ }
34095
34397
  this.toolCategories.forEach(category => {
34096
34398
  category.mcpTools.forEach(tool => {
34097
34399
  this.app.post(`/api/tool/${tool.name}`, async (req, res) => {
34400
+ if (!this.isToolEnabled(tool.name)) {
34401
+ res.status(404).json({
34402
+ error: `Tool not available: ${tool.name}`,
34403
+ hint: 'The corresponding feature may be disabled in Settings → MCP.'
34404
+ });
34405
+ return;
34406
+ }
34098
34407
  try {
34099
34408
  this.logger.info(`API call: ${tool.name}`, req.body);
34100
34409
  const result = await tool.handler(req.body, {});
@@ -34107,6 +34416,8 @@ let McpService = class McpService {
34107
34416
  });
34108
34417
  });
34109
34418
  });
34419
+ this.toolEndpointsConfigured = true;
34420
+ this.logger.info(`Configured ${this.toolCategories.reduce((s, c) => s + c.mcpTools.length, 0)} tool API endpoints`);
34110
34421
  }
34111
34422
  /**
34112
34423
  * Start the MCP server
@@ -34117,6 +34428,10 @@ let McpService = class McpService {
34117
34428
  return;
34118
34429
  }
34119
34430
  const serverPort = port || this.config.store.mcp?.port || 3001;
34431
+ // Configure API endpoints for direct tool access
34432
+ // Must be called here (not in configureExpress) because tools are registered
34433
+ // by McpModule constructor AFTER McpService constructor runs (Issue #4)
34434
+ this.configureToolEndpoints();
34120
34435
  return new Promise((resolve, reject) => {
34121
34436
  try {
34122
34437
  this.httpServer = http.createServer(this.app);
@@ -34156,6 +34471,16 @@ let McpService = class McpService {
34156
34471
  * Stop the MCP server
34157
34472
  */
34158
34473
  async stopServer() {
34474
+ await this.stopServerInternal(false, 'manual stop');
34475
+ }
34476
+ /**
34477
+ * Best-effort synchronous cleanup for window/application shutdown.
34478
+ * Avoids awaiting async transport closes during unload while still releasing the port.
34479
+ */
34480
+ stopServerSync(reason = 'shutdown') {
34481
+ void this.stopServerInternal(true, reason);
34482
+ }
34483
+ async stopServerInternal(forceImmediate, reason) {
34159
34484
  if (!this.isRunning) {
34160
34485
  this.logger.info('MCP server is not running');
34161
34486
  return;
@@ -34172,15 +34497,21 @@ let McpService = class McpService {
34172
34497
  });
34173
34498
  this.legacyTransports = {};
34174
34499
  // Close all streamable transports
34175
- for (const [sessionId, transport] of Object.entries(this.streamableTransports)) {
34500
+ for (const transport of Object.values(this.streamableTransports)) {
34176
34501
  try {
34177
- await transport.close();
34502
+ if (forceImmediate) {
34503
+ void transport.close().catch(() => undefined);
34504
+ }
34505
+ else {
34506
+ await transport.close();
34507
+ }
34178
34508
  }
34179
34509
  catch (e) {
34180
34510
  // Ignore close errors
34181
34511
  }
34182
34512
  }
34183
34513
  this.streamableTransports = {};
34514
+ this.sessionMetadata.clear();
34184
34515
  // Clear all per-session servers
34185
34516
  this.sessionServers = {};
34186
34517
  this.logger.debug('Cleared all per-session McpServer instances');
@@ -34194,13 +34525,27 @@ let McpService = class McpService {
34194
34525
  }
34195
34526
  // Close HTTP server
34196
34527
  if (this.httpServer) {
34197
- await new Promise((resolve) => {
34198
- this.httpServer.close(() => resolve());
34199
- });
34528
+ const server = this.httpServer;
34200
34529
  this.httpServer = undefined;
34530
+ this.isRunning = false;
34531
+ if (forceImmediate) {
34532
+ try {
34533
+ server.close();
34534
+ }
34535
+ catch (e) {
34536
+ // Ignore close errors
34537
+ }
34538
+ }
34539
+ else {
34540
+ await new Promise((resolve) => {
34541
+ server.close(() => resolve());
34542
+ });
34543
+ }
34201
34544
  }
34202
- this.isRunning = false;
34203
- this.logger.info('MCP server stopped');
34545
+ else {
34546
+ this.isRunning = false;
34547
+ }
34548
+ this.logger.info(`MCP server stopped (${reason})`);
34204
34549
  }
34205
34550
  catch (err) {
34206
34551
  this.logger.error('Error stopping MCP server:', err);
@@ -34328,8 +34673,9 @@ exports.McpSettingsTabProvider = McpSettingsTabProvider = __decorate([
34328
34673
  (__unused_webpack_module, exports) {
34329
34674
 
34330
34675
  "use strict";
34676
+ var __webpack_unused_export__;
34331
34677
 
34332
- Object.defineProperty(exports, "__esModule", ({ value: true }));
34678
+ __webpack_unused_export__ = ({ value: true });
34333
34679
  exports.BaseToolCategory = void 0;
34334
34680
  /**
34335
34681
  * Base class for tool categories
@@ -35861,6 +36207,281 @@ let TabManagementToolCategory = class TabManagementToolCategory extends base_too
35861
36207
  this.logger.debug(`No tab found for locator: ${JSON.stringify(locator)}`);
35862
36208
  return null;
35863
36209
  }
36210
+ getQuickConnectProviders() {
36211
+ return this.profilesService.getProviders().filter(provider => provider.supportsQuickConnect);
36212
+ }
36213
+ getQuickConnectProvider(providerId) {
36214
+ return this.getQuickConnectProviders().find(provider => provider.id === providerId) ?? null;
36215
+ }
36216
+ buildSshQuickConnectProfile(query) {
36217
+ let user = undefined;
36218
+ let host = query;
36219
+ let port = 22;
36220
+ if (!host.trim()) {
36221
+ return null;
36222
+ }
36223
+ if (host.includes('@')) {
36224
+ const parts = host.split(/@/g);
36225
+ host = parts[parts.length - 1];
36226
+ user = parts.slice(0, parts.length - 1).join('@') || undefined;
36227
+ }
36228
+ if (host.includes('[')) {
36229
+ const closeBracketIndex = host.indexOf(']');
36230
+ if (closeBracketIndex === -1) {
36231
+ return null;
36232
+ }
36233
+ const portPart = host.slice(closeBracketIndex + 1);
36234
+ if (portPart.startsWith(':') && portPart.length > 1) {
36235
+ const parsedPort = Number(portPart.slice(1));
36236
+ if (!Number.isFinite(parsedPort) || parsedPort <= 0) {
36237
+ return null;
36238
+ }
36239
+ port = parsedPort;
36240
+ }
36241
+ host = host.slice(1, closeBracketIndex);
36242
+ }
36243
+ else if (host.includes(':')) {
36244
+ const parts = host.split(/:/g);
36245
+ if (parts.length !== 2 || !parts[0]) {
36246
+ return null;
36247
+ }
36248
+ const parsedPort = Number(parts[1]);
36249
+ if (!Number.isFinite(parsedPort) || parsedPort <= 0) {
36250
+ return null;
36251
+ }
36252
+ host = parts[0];
36253
+ port = parsedPort;
36254
+ }
36255
+ if (!host.trim()) {
36256
+ return null;
36257
+ }
36258
+ return {
36259
+ name: query,
36260
+ type: 'ssh',
36261
+ options: {
36262
+ host,
36263
+ user,
36264
+ port,
36265
+ },
36266
+ };
36267
+ }
36268
+ resolveQuickConnectTarget(query, protocol = 'auto') {
36269
+ const providers = this.getQuickConnectProviders();
36270
+ const providerIds = providers.map(provider => provider.id).sort();
36271
+ const explicitProtocolMatch = query.match(/^([a-z][a-z0-9+.-]*):\/\/(.+)$/i);
36272
+ let normalizedQuery = query.trim();
36273
+ let requestedProtocol = protocol;
36274
+ if (explicitProtocolMatch) {
36275
+ const scheme = explicitProtocolMatch[1].toLowerCase();
36276
+ const body = explicitProtocolMatch[2];
36277
+ if (scheme === 'ssh' || scheme === 'telnet' || scheme === 'socket' || scheme === 'serial') {
36278
+ requestedProtocol = scheme;
36279
+ normalizedQuery = body;
36280
+ }
36281
+ }
36282
+ if (requestedProtocol !== 'auto') {
36283
+ if (requestedProtocol === 'ssh') {
36284
+ return { provider: this.getQuickConnectProvider('ssh'), normalizedQuery, resolvedProtocol: 'ssh' };
36285
+ }
36286
+ const provider = this.getQuickConnectProvider(requestedProtocol);
36287
+ return provider
36288
+ ? { provider, normalizedQuery, resolvedProtocol: requestedProtocol }
36289
+ : {
36290
+ provider: null,
36291
+ normalizedQuery,
36292
+ resolvedProtocol: requestedProtocol,
36293
+ error: `Quick connect protocol \"${requestedProtocol}\" is unavailable`,
36294
+ hint: providerIds.length
36295
+ ? `Available quick-connect providers: ${providerIds.join(', ')}`
36296
+ : 'No quick-connect providers are currently available.'
36297
+ };
36298
+ }
36299
+ const sshProvider = this.getQuickConnectProvider('ssh');
36300
+ const telnetProvider = this.getQuickConnectProvider('telnet');
36301
+ const socketProvider = this.getQuickConnectProvider('socket');
36302
+ const serialProvider = this.getQuickConnectProvider('serial');
36303
+ const looksLikeSerial = /^(COM\d+|\/dev\/(tty|cu)\S+)$/i.test(normalizedQuery);
36304
+ if (looksLikeSerial && serialProvider) {
36305
+ return { provider: serialProvider, normalizedQuery, resolvedProtocol: 'serial' };
36306
+ }
36307
+ const looksLikeSsh = normalizedQuery.includes('@');
36308
+ if (looksLikeSsh) {
36309
+ return { provider: sshProvider, normalizedQuery, resolvedProtocol: 'ssh' };
36310
+ }
36311
+ const ipv6WithPort = normalizedQuery.match(/^\[.+\]:(\d+)$/);
36312
+ const hostWithPort = normalizedQuery.match(/^[^:@]+:(\d+)$/);
36313
+ const portMatch = ipv6WithPort ?? hostWithPort;
36314
+ if (portMatch) {
36315
+ const port = Number(portMatch[1]);
36316
+ if (port === 22) {
36317
+ return { provider: sshProvider, normalizedQuery, resolvedProtocol: 'ssh' };
36318
+ }
36319
+ if (port === 23 && telnetProvider) {
36320
+ return { provider: telnetProvider, normalizedQuery, resolvedProtocol: 'telnet' };
36321
+ }
36322
+ if (socketProvider) {
36323
+ return { provider: socketProvider, normalizedQuery, resolvedProtocol: 'socket' };
36324
+ }
36325
+ if (telnetProvider) {
36326
+ return { provider: telnetProvider, normalizedQuery, resolvedProtocol: 'telnet' };
36327
+ }
36328
+ if (sshProvider) {
36329
+ return { provider: sshProvider, normalizedQuery, resolvedProtocol: 'ssh' };
36330
+ }
36331
+ }
36332
+ if (providers.length === 1) {
36333
+ return { provider: providers[0], normalizedQuery, resolvedProtocol: providers[0].id };
36334
+ }
36335
+ if (sshProvider) {
36336
+ return { provider: sshProvider, normalizedQuery, resolvedProtocol: 'ssh' };
36337
+ }
36338
+ return {
36339
+ provider: null,
36340
+ normalizedQuery,
36341
+ resolvedProtocol: 'auto',
36342
+ error: 'Ambiguous quick connect target',
36343
+ hint: providerIds.length
36344
+ ? `Specify protocol explicitly (ssh://, telnet://, socket://, serial://) or use protocol=. Available providers: ${providerIds.join(', ')}`
36345
+ : 'No quick-connect providers are currently available.'
36346
+ };
36347
+ }
36348
+ async openProfileTabAndBuildResponse(profile, params, sourceLabel) {
36349
+ const timeout = params?.timeout ?? 30000;
36350
+ this.logger.info(`[${sourceLabel}] Opening profile: ${profile.name} (type: ${profile.type})`);
36351
+ const tab = await this.profilesService.openNewTabForProfile(profile);
36352
+ if (!tab) {
36353
+ this.logger.error(`[${sourceLabel}] Failed to open profile: ${profile.name}`);
36354
+ return {
36355
+ content: [{ type: 'text', text: JSON.stringify({ success: false, error: 'Failed to open profile' }) }]
36356
+ };
36357
+ }
36358
+ const topLevelTab = this.app.getParentTab(tab) ?? tab;
36359
+ const tabId = this.getOrCreateTabId(topLevelTab);
36360
+ const tabIndex = this.app.tabs.indexOf(topLevelTab);
36361
+ const isSSH = profile.type === 'ssh' || profile.type?.includes('ssh');
36362
+ const waitForReady = params?.waitForReady ?? isSSH;
36363
+ let sessionId;
36364
+ if (tab instanceof tabby_terminal_1.BaseTerminalTabComponent) {
36365
+ sessionId = this.terminalTools.getOrCreateSessionId(tab);
36366
+ this.logger.debug(`[${sourceLabel}] SessionId assigned: ${sessionId}`);
36367
+ }
36368
+ if (!sessionId) {
36369
+ sessionId = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
36370
+ const r = Math.random() * 16 | 0;
36371
+ const v = c === 'x' ? r : (r & 0x3 | 0x8);
36372
+ return v.toString(16);
36373
+ });
36374
+ this.logger.warn(`[${sourceLabel}] Tab is not BaseTerminalTabComponent, generated fallback sessionId: ${sessionId}`);
36375
+ }
36376
+ if (waitForReady) {
36377
+ const timing = this.config.store.mcp?.timing || {};
36378
+ const sessionPollInterval = timing.sessionPollInterval ?? 200;
36379
+ const sessionStableChecks = timing.sessionStableChecks ?? 5;
36380
+ const startTime = Date.now();
36381
+ let tabReady = false;
36382
+ let sshConnected = false;
36383
+ let lastBufferLength = 0;
36384
+ let stableCount = 0;
36385
+ this.logger.debug(`[${sourceLabel}] Waiting for ready (isSSH=${isSSH}, timeout=${timeout}ms)`);
36386
+ while (Date.now() - startTime < timeout) {
36387
+ const tabAny = tab;
36388
+ const frontendReady = tabAny.frontend !== undefined;
36389
+ const sessionReady = tabAny.sessionReady === true;
36390
+ const sessionOpen = tabAny.session?.open === true;
36391
+ if (isSSH) {
36392
+ const sshSession = tabAny.sshSession;
36393
+ if (sshSession && sshSession.open === true) {
36394
+ sshConnected = true;
36395
+ tabReady = true;
36396
+ this.logger.info(`[${sourceLabel}] SSH session connected: ${profile.name}`);
36397
+ break;
36398
+ }
36399
+ }
36400
+ else {
36401
+ if (sessionOpen || (frontendReady && sessionReady)) {
36402
+ tabReady = true;
36403
+ break;
36404
+ }
36405
+ }
36406
+ let bufferLength = 0;
36407
+ try {
36408
+ const xterm = tabAny.frontend?.xterm;
36409
+ if (xterm?.buffer?.active) {
36410
+ bufferLength = xterm.buffer.active.length;
36411
+ }
36412
+ }
36413
+ catch (e) {
36414
+ // Ignore buffer access errors
36415
+ }
36416
+ if (!isSSH) {
36417
+ if (bufferLength > 0 && bufferLength === lastBufferLength) {
36418
+ stableCount++;
36419
+ if (stableCount >= sessionStableChecks) {
36420
+ tabReady = true;
36421
+ break;
36422
+ }
36423
+ }
36424
+ else {
36425
+ stableCount = 0;
36426
+ lastBufferLength = bufferLength;
36427
+ }
36428
+ }
36429
+ else if (bufferLength !== lastBufferLength) {
36430
+ lastBufferLength = bufferLength;
36431
+ this.logger.debug(`[${sourceLabel}] SSH buffer activity: ${bufferLength} chars`);
36432
+ }
36433
+ await new Promise(resolve => setTimeout(resolve, sessionPollInterval));
36434
+ }
36435
+ const elapsed = Date.now() - startTime;
36436
+ const ready = isSSH ? (tabReady && sshConnected) : tabReady;
36437
+ this.logger.info(`[${sourceLabel}] Profile opened: ${profile.name} (tabReady=${tabReady}, sshConnected=${sshConnected}, ready=${ready}, elapsed=${elapsed}ms)`);
36438
+ return {
36439
+ content: [{
36440
+ type: 'text', text: JSON.stringify({
36441
+ success: true,
36442
+ sessionId,
36443
+ tabId,
36444
+ tabIndex,
36445
+ tabTitle: tab.title,
36446
+ profileName: profile.name,
36447
+ profileType: profile.type,
36448
+ tabReady,
36449
+ sshConnected: isSSH ? sshConnected : undefined,
36450
+ ready,
36451
+ elapsed: `${elapsed}ms`,
36452
+ message: ready
36453
+ ? `Profile ready: ${profile.name}`
36454
+ : tabReady && !sshConnected
36455
+ ? `Tab opened but SSH not connected: ${profile.name}`
36456
+ : `Profile opened but not fully ready: ${profile.name}`,
36457
+ hint: ready
36458
+ ? 'Use sessionId with exec_command, SFTP tools, etc.'
36459
+ : 'Session may not be fully connected. Check sshConnected status.'
36460
+ })
36461
+ }]
36462
+ };
36463
+ }
36464
+ this.logger.info(`[${sourceLabel}] Profile opened (no wait): ${profile.name}`);
36465
+ return {
36466
+ content: [{
36467
+ type: 'text', text: JSON.stringify({
36468
+ success: true,
36469
+ sessionId,
36470
+ tabId,
36471
+ tabIndex,
36472
+ tabTitle: tab.title,
36473
+ profileName: profile.name,
36474
+ profileType: profile.type,
36475
+ tabReady: undefined,
36476
+ sshConnected: undefined,
36477
+ ready: false,
36478
+ message: `Opened profile: ${profile.name}`,
36479
+ note: 'Profile opened without waiting. Use get_session_list to check status.',
36480
+ hint: 'Use sessionId with exec_command, SFTP tools, etc.'
36481
+ })
36482
+ }]
36483
+ };
36484
+ }
35864
36485
  createListTabsTool() {
35865
36486
  return {
35866
36487
  name: 'list_tabs',
@@ -36210,169 +36831,7 @@ NOTE: This opens a NEW tab. For existing connections, use get_session_list + exe
36210
36831
  }]
36211
36832
  };
36212
36833
  }
36213
- this.logger.info(`[open_profile] Opening profile: ${profile.name} (type: ${profile.type})`);
36214
- const tab = await this.profilesService.openNewTabForProfile(profile);
36215
- if (tab) {
36216
- const tabId = this.getOrCreateTabId(tab);
36217
- const tabIndex = this.app.tabs.indexOf(tab);
36218
- const isSSH = profile.type === 'ssh' || profile.type?.includes('ssh');
36219
- // Determine default waitForReady based on profile type
36220
- const waitForReady = params?.waitForReady ?? isSSH;
36221
- // Get sessionId from TerminalToolCategory's registry
36222
- // CRITICAL: Call getOrCreateSessionId DIRECTLY on the tab object
36223
- // DO NOT use findTerminalSessions() as the tab may not yet be in app.tabs
36224
- let sessionId;
36225
- if (tab instanceof tabby_terminal_1.BaseTerminalTabComponent) {
36226
- // Direct call to getOrCreateSessionId ensures the same ID is registered
36227
- sessionId = this.terminalTools.getOrCreateSessionId(tab);
36228
- this.logger.debug(`[open_profile] SessionId assigned: ${sessionId}`);
36229
- }
36230
- // Fallback: generate UUID if not a terminal tab (shouldn't happen)
36231
- if (!sessionId) {
36232
- sessionId = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
36233
- const r = Math.random() * 16 | 0;
36234
- const v = c === 'x' ? r : (r & 0x3 | 0x8);
36235
- return v.toString(16);
36236
- });
36237
- this.logger.warn(`[open_profile] Tab is not BaseTerminalTabComponent, generated fallback sessionId: ${sessionId}`);
36238
- }
36239
- if (waitForReady) {
36240
- // Wait for the terminal session to be fully connected
36241
- const timing = this.config.store.mcp?.timing || {};
36242
- const sessionPollInterval = timing.sessionPollInterval ?? 200;
36243
- const sessionStableChecks = timing.sessionStableChecks ?? 5;
36244
- const startTime = Date.now();
36245
- let tabReady = false;
36246
- let sshConnected = false;
36247
- let lastBufferLength = 0;
36248
- let stableCount = 0;
36249
- this.logger.debug(`[open_profile] Waiting for ready (isSSH=${isSSH}, timeout=${timeout}ms)`);
36250
- while (Date.now() - startTime < timeout) {
36251
- const tabAny = tab;
36252
- // Check 1: Tab/Terminal Ready indicators
36253
- const frontendReady = tabAny.frontend !== undefined;
36254
- const sessionReady = tabAny.sessionReady === true;
36255
- const hasSession = tabAny.session !== undefined;
36256
- const sessionOpen = tabAny.session?.open === true;
36257
- // Check 2: SSH-specific indicators (only for SSH profiles)
36258
- if (isSSH) {
36259
- const sshSession = tabAny.sshSession;
36260
- if (sshSession && sshSession.open === true) {
36261
- sshConnected = true;
36262
- tabReady = true;
36263
- this.logger.info(`[open_profile] SSH session connected: ${profile.name}`);
36264
- break;
36265
- }
36266
- }
36267
- else {
36268
- // For non-SSH, consider ready when session is open
36269
- if (sessionOpen || (frontendReady && sessionReady)) {
36270
- tabReady = true;
36271
- break;
36272
- }
36273
- }
36274
- // Check 3: Buffer stability (fallback indicator)
36275
- // NOTE: For SSH, buffer stability alone is NOT sufficient!
36276
- // SSH may show connection prompts before actually authenticating.
36277
- let bufferLength = 0;
36278
- try {
36279
- const xterm = tabAny.frontend?.xterm;
36280
- if (xterm?.buffer?.active) {
36281
- bufferLength = xterm.buffer.active.length;
36282
- }
36283
- }
36284
- catch (e) {
36285
- // Ignore buffer access errors
36286
- }
36287
- // For SSH: Only use buffer stability as exit AFTER sshConnected
36288
- // For non-SSH: Buffer stability can be used as ready indicator
36289
- if (!isSSH) {
36290
- // Non-SSH: Buffer stability = ready
36291
- if (bufferLength > 0 && bufferLength === lastBufferLength) {
36292
- stableCount++;
36293
- if (stableCount >= sessionStableChecks) {
36294
- tabReady = true;
36295
- break;
36296
- }
36297
- }
36298
- else {
36299
- stableCount = 0;
36300
- lastBufferLength = bufferLength;
36301
- }
36302
- }
36303
- else {
36304
- // SSH: Keep checking sshSession.open in the loop above
36305
- // Buffer stability alone should NOT trigger exit for SSH
36306
- // Just track the buffer for debugging
36307
- if (bufferLength !== lastBufferLength) {
36308
- lastBufferLength = bufferLength;
36309
- this.logger.debug(`[open_profile] SSH buffer activity: ${bufferLength} chars`);
36310
- }
36311
- }
36312
- await new Promise(resolve => setTimeout(resolve, sessionPollInterval));
36313
- }
36314
- const elapsed = Date.now() - startTime;
36315
- // Determine final ready state:
36316
- // - For SSH: ready = tabReady AND sshConnected
36317
- // - For non-SSH: ready = tabReady
36318
- const ready = isSSH ? (tabReady && sshConnected) : tabReady;
36319
- this.logger.info(`[open_profile] Profile opened: ${profile.name} (tabReady=${tabReady}, sshConnected=${sshConnected}, ready=${ready}, elapsed=${elapsed}ms)`);
36320
- return {
36321
- content: [{
36322
- type: 'text', text: JSON.stringify({
36323
- success: true,
36324
- sessionId,
36325
- tabId,
36326
- tabIndex,
36327
- tabTitle: tab.title,
36328
- profileName: profile.name,
36329
- profileType: profile.type,
36330
- // State fields with clear semantics:
36331
- tabReady, // Tab/frontend initialized
36332
- sshConnected: isSSH ? sshConnected : undefined, // SSH connection established (SSH only)
36333
- ready, // OVERALL ready state: can start using this session
36334
- elapsed: `${elapsed}ms`,
36335
- message: ready
36336
- ? `Profile ready: ${profile.name}`
36337
- : tabReady && !sshConnected
36338
- ? `Tab opened but SSH not connected: ${profile.name}`
36339
- : `Profile opened but not fully ready: ${profile.name}`,
36340
- hint: ready
36341
- ? 'Use sessionId with exec_command, SFTP tools, etc.'
36342
- : 'Session may not be fully connected. Check sshConnected status.'
36343
- })
36344
- }]
36345
- };
36346
- }
36347
- // No waiting - return immediately
36348
- this.logger.info(`[open_profile] Profile opened (no wait): ${profile.name}`);
36349
- return {
36350
- content: [{
36351
- type: 'text', text: JSON.stringify({
36352
- success: true,
36353
- sessionId,
36354
- tabId,
36355
- tabIndex,
36356
- tabTitle: tab.title,
36357
- profileName: profile.name,
36358
- profileType: profile.type,
36359
- // State fields (unknown since we didn't wait)
36360
- tabReady: undefined, // Unknown - didn't wait
36361
- sshConnected: undefined, // Unknown - didn't wait
36362
- ready: false, // Not verified as ready
36363
- message: `Opened profile: ${profile.name}`,
36364
- note: 'Profile opened without waiting. Use get_session_list to check status.',
36365
- hint: 'Use sessionId with exec_command, SFTP tools, etc.'
36366
- })
36367
- }]
36368
- };
36369
- }
36370
- else {
36371
- this.logger.error(`[open_profile] Failed to open profile: ${profile.name}`);
36372
- return {
36373
- content: [{ type: 'text', text: JSON.stringify({ success: false, error: 'Failed to open profile' }) }]
36374
- };
36375
- }
36834
+ return await this.openProfileTabAndBuildResponse(profile, params, 'open_profile');
36376
36835
  }
36377
36836
  catch (error) {
36378
36837
  this.logger.error('[open_profile] Error:', error);
@@ -36431,15 +36890,24 @@ Use list_profiles + open_profile for programmatic profile opening instead.`,
36431
36890
  createQuickConnectTool() {
36432
36891
  return {
36433
36892
  name: 'quick_connect',
36434
- description: `Quick SSH connection - creates a NEW tab with temporary profile.
36893
+ description: `Quick connection - creates a NEW tab using the best matching provider.
36435
36894
 
36436
36895
  IMPORTANT: This creates a NEW connection and tab, does NOT reuse existing sessions.
36437
36896
  - For new connections: Use this or open_profile
36438
36897
  - For existing sessions: Use get_session_list to find sessions, then exec_command
36439
-
36440
- Example: quick_connect(query="root@192.168.1.1") or quick_connect(query="user@host:2222")`,
36898
+ - Uses the same tab/session/ready return chain as open_profile
36899
+ - protocol='auto' prefers SSH for user@host style input instead of relying on provider order
36900
+
36901
+ Examples:
36902
+ - quick_connect(query="root@192.168.1.1")
36903
+ - quick_connect(query="user@host:2222")
36904
+ - quick_connect(query="telnet://host:23", protocol="auto")
36905
+ - quick_connect(query="host:9000", protocol="socket")`,
36441
36906
  schema: zod_1.z.object({
36442
- query: zod_1.z.string().describe('SSH string: "user@host" or "user@host:port"')
36907
+ query: zod_1.z.string().describe('Connection target, e.g. user@host, user@host:port, telnet://host:23, socket://host:9000, serial:///dev/ttyUSB0'),
36908
+ protocol: zod_1.z.enum(['auto', 'ssh', 'telnet', 'socket', 'serial']).optional().describe('Protocol selection strategy (default: auto)'),
36909
+ waitForReady: zod_1.z.boolean().optional().describe('Wait for connection readiness (default: true for SSH, false for most others)'),
36910
+ timeout: zod_1.z.number().optional().describe('Timeout in ms when waiting (default: 30000)')
36443
36911
  }),
36444
36912
  handler: async (params) => {
36445
36913
  // Debug: log received params
@@ -36460,33 +36928,41 @@ Example: quick_connect(query="root@192.168.1.1") or quick_connect(query="user@ho
36460
36928
  }]
36461
36929
  };
36462
36930
  }
36463
- // Validate query format (basic check)
36464
- if (!query.includes('@')) {
36465
- return {
36466
- content: [{
36467
- type: 'text',
36468
- text: JSON.stringify({
36469
- success: false,
36470
- error: 'Invalid connection string format',
36471
- hint: 'Use format "user@host" or "user@host:port"',
36472
- received: query
36473
- })
36474
- }]
36475
- };
36476
- }
36477
36931
  try {
36478
- const profile = await this.profilesService.quickConnect(query);
36479
- if (profile) {
36480
- this.logger.info(`Quick connect to: ${query}`);
36932
+ const resolution = this.resolveQuickConnectTarget(query, params?.protocol ?? 'auto');
36933
+ if (!resolution.provider && resolution.resolvedProtocol !== 'ssh') {
36481
36934
  return {
36482
- content: [{ type: 'text', text: JSON.stringify({ success: true, message: `Connected to: ${query}`, profile: profile.name }) }]
36935
+ content: [{
36936
+ type: 'text', text: JSON.stringify({
36937
+ success: false,
36938
+ error: resolution.error || 'Quick connect target could not be resolved',
36939
+ hint: resolution.hint
36940
+ })
36941
+ }]
36483
36942
  };
36484
36943
  }
36485
- else {
36944
+ const profile = resolution.resolvedProtocol === 'ssh'
36945
+ ? this.buildSshQuickConnectProfile(resolution.normalizedQuery)
36946
+ : resolution.provider.quickConnect(resolution.normalizedQuery);
36947
+ if (!profile) {
36486
36948
  return {
36487
- content: [{ type: 'text', text: JSON.stringify({ success: false, error: 'Quick connect failed - no profile returned' }) }]
36949
+ content: [{
36950
+ type: 'text', text: JSON.stringify({
36951
+ success: false,
36952
+ error: `Invalid ${resolution.resolvedProtocol} quick connect target`,
36953
+ hint: resolution.resolvedProtocol === 'ssh'
36954
+ ? 'Use format user@host, user@host:port, ssh://user@host, or ssh://user@host:port'
36955
+ : resolution.resolvedProtocol === 'telnet'
36956
+ ? 'Use format host:port or telnet://host:port'
36957
+ : resolution.resolvedProtocol === 'socket'
36958
+ ? 'Use format host:port or socket://host:port'
36959
+ : 'Use format COM3, /dev/ttyUSB0, or serial:///dev/ttyUSB0'
36960
+ })
36961
+ }]
36488
36962
  };
36489
36963
  }
36964
+ profile.type = profile.type || resolution.resolvedProtocol;
36965
+ return await this.openProfileTabAndBuildResponse(profile, params, 'quick_connect');
36490
36966
  }
36491
36967
  catch (error) {
36492
36968
  this.logger.error('Error with quick connect:', error);
@@ -36649,12 +37125,16 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
36649
37125
  var __metadata = (this && this.__metadata) || function (k, v) {
36650
37126
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
36651
37127
  };
37128
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37129
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37130
+ };
36652
37131
  Object.defineProperty(exports, "__esModule", ({ value: true }));
36653
37132
  exports.TerminalToolCategory = void 0;
36654
37133
  const core_1 = __webpack_require__(9430);
36655
37134
  const tabby_core_1 = __webpack_require__(1368);
36656
37135
  const tabby_terminal_1 = __webpack_require__(4319);
36657
37136
  const addon_serialize_1 = __webpack_require__(4224);
37137
+ const strip_ansi_1 = __importDefault(__webpack_require__(3099));
36658
37138
  const rxjs_1 = __webpack_require__(2607);
36659
37139
  const zod_1 = __webpack_require__(7552);
36660
37140
  const base_tool_category_1 = __webpack_require__(2099);
@@ -36692,6 +37172,7 @@ let TerminalToolCategory = class TerminalToolCategory extends base_tool_category
36692
37172
  this.registerTool(this.createAbortCommandTool());
36693
37173
  this.registerTool(this.createGetCommandStatusTool());
36694
37174
  this.registerTool(this.createFocusPaneTool());
37175
+ this.registerTool(this.createGetSessionEnvironmentTool());
36695
37176
  this.logger.info('Terminal tools initialized');
36696
37177
  }
36697
37178
  /**
@@ -37191,6 +37672,228 @@ Special keys: \\x03 (Ctrl+C), \\x04 (Ctrl+D), \\x1b (Escape), \\r (Enter)`,
37191
37672
  }
37192
37673
  };
37193
37674
  }
37675
+ parseEnvironmentFromBuffer(session, bufferContent, useEnhancedHeuristics) {
37676
+ const normalizedLines = bufferContent
37677
+ .split('\n')
37678
+ .map(line => {
37679
+ const raw = line.trimEnd();
37680
+ const clean = useEnhancedHeuristics
37681
+ ? (0, strip_ansi_1.default)(raw).replace(/\[[0-9;?]*[a-zA-Z]/g, '').trim()
37682
+ : raw.trim();
37683
+ return { raw, clean };
37684
+ })
37685
+ .filter(line => line.raw.length > 0 || line.clean.length > 0);
37686
+ const replMatchers = [
37687
+ { environment: 'python', pattern: /^>>>$/ },
37688
+ { environment: 'ruby', pattern: /^(irb>|irb\(main\):.*)$/ },
37689
+ { environment: 'mysql', pattern: /^mysql>$/ },
37690
+ { environment: 'postgres', pattern: /^(postgres[=#>-]?|\w+=>|\w+=#)$/ },
37691
+ { environment: 'sqlite', pattern: /^sqlite>$/ },
37692
+ { environment: 'mongodb', pattern: /^(mongo>|mongosh>|Enterprise\s.+>)$/ },
37693
+ { environment: 'redis', pattern: /^127\.0\.0\.1:\d+>$/ },
37694
+ { environment: 'node', pattern: /^>$/ },
37695
+ ];
37696
+ let environment = 'unknown';
37697
+ let isShell = false;
37698
+ let promptRaw = '';
37699
+ let promptClean = '';
37700
+ const fallbackLine = normalizedLines.length > 0 ? normalizedLines[normalizedLines.length - 1] : { raw: '', clean: '' };
37701
+ for (let i = normalizedLines.length - 1; i >= 0; i--) {
37702
+ const candidate = normalizedLines[i];
37703
+ if (!candidate.clean) {
37704
+ continue;
37705
+ }
37706
+ const replMatch = replMatchers.find(m => m.pattern.test(candidate.clean));
37707
+ if (replMatch) {
37708
+ environment = replMatch.environment;
37709
+ promptRaw = candidate.raw;
37710
+ promptClean = candidate.clean;
37711
+ break;
37712
+ }
37713
+ if (/[$#%❯➜]\s*$/.test(candidate.clean)) {
37714
+ isShell = true;
37715
+ const detectedShell = this.detectShellType(session);
37716
+ environment = detectedShell === 'sh' ? 'shell' : detectedShell;
37717
+ promptRaw = candidate.raw;
37718
+ promptClean = candidate.clean;
37719
+ break;
37720
+ }
37721
+ }
37722
+ if (!promptRaw) {
37723
+ isShell = true;
37724
+ const detectedShell = this.detectShellType(session);
37725
+ environment = detectedShell === 'sh' ? 'shell' : detectedShell;
37726
+ promptRaw = fallbackLine.raw;
37727
+ promptClean = fallbackLine.clean;
37728
+ }
37729
+ return { environment, isShell, promptRaw, promptClean };
37730
+ }
37731
+ /**
37732
+ * Tool: Get the current environment context of a session
37733
+ */
37734
+ createGetSessionEnvironmentTool() {
37735
+ return {
37736
+ name: 'get_session_environment',
37737
+ description: `Get the environment context of a terminal session (e.g., bash, python, node, database REPL).
37738
+ Use this before sending complex commands to ensure the session is in the expected state.
37739
+ Session targeting: sessionId (recommended) > tabIndex > title > profileName`,
37740
+ schema: zod_1.z.object({
37741
+ sessionId: zod_1.z.string().optional().describe('Stable session ID (recommended)'),
37742
+ tabIndex: zod_1.z.number().optional().describe('Tab index (legacy)'),
37743
+ title: zod_1.z.string().optional().describe('Match by title'),
37744
+ profileName: zod_1.z.string().optional().describe('Match by profile name')
37745
+ }),
37746
+ handler: async (params) => {
37747
+ const environmentDetectionConfig = this.config.store.mcp?.environmentDetection;
37748
+ if (environmentDetectionConfig?.enabled === false) {
37749
+ return {
37750
+ content: [{
37751
+ type: 'text', text: JSON.stringify({
37752
+ success: false,
37753
+ enabled: false,
37754
+ error: 'Environment detection is disabled in Settings → MCP',
37755
+ hint: 'Enable Environment Detection in the MCP settings page before using get_session_environment.'
37756
+ })
37757
+ }]
37758
+ };
37759
+ }
37760
+ const session = this.findSessionByLocator(params);
37761
+ if (!session) {
37762
+ return {
37763
+ content: [{
37764
+ type: 'text', text: JSON.stringify({
37765
+ success: false,
37766
+ error: 'No matching terminal session found',
37767
+ hint: 'Use get_session_list to see available sessions'
37768
+ })
37769
+ }]
37770
+ };
37771
+ }
37772
+ try {
37773
+ this.ensureSessionValid(session);
37774
+ }
37775
+ catch (error) {
37776
+ return {
37777
+ content: [{ type: 'text', text: JSON.stringify({ success: false, error: error.message }) }]
37778
+ };
37779
+ }
37780
+ const useEnhancedHeuristics = environmentDetectionConfig?.useEnhancedHeuristics !== false;
37781
+ const detectionMode = environmentDetectionConfig?.mode ?? 'heuristic';
37782
+ const bufferContent = this.getTerminalBufferText(session);
37783
+ const normalizedLines = bufferContent
37784
+ .split('\n')
37785
+ .map(line => {
37786
+ const raw = line.trimEnd();
37787
+ const clean = useEnhancedHeuristics
37788
+ ? (0, strip_ansi_1.default)(raw).replace(/\[[0-9;?]*[a-zA-Z]/g, '').trim()
37789
+ : raw.trim();
37790
+ return { raw, clean };
37791
+ })
37792
+ .filter(line => line.raw.length > 0 || line.clean.length > 0);
37793
+ const replMatchers = [
37794
+ { environment: 'python', pattern: /^>>>$/ },
37795
+ { environment: 'ruby', pattern: /^(irb>|irb\(main\):.*)$/ },
37796
+ { environment: 'mysql', pattern: /^mysql>$/ },
37797
+ { environment: 'postgres', pattern: /^(postgres[=#>-]?|\w+=>|\w+=#)$/ },
37798
+ { environment: 'sqlite', pattern: /^sqlite>$/ },
37799
+ { environment: 'mongodb', pattern: /^(mongo>|mongosh>|Enterprise\s.+>)$/ },
37800
+ { environment: 'redis', pattern: /^127\.0\.0\.1:\d+>$/ },
37801
+ { environment: 'node', pattern: /^>$/ },
37802
+ ];
37803
+ let environment = 'unknown';
37804
+ let isShell = false;
37805
+ let promptRaw = '';
37806
+ let promptClean = '';
37807
+ const fallbackLine = normalizedLines.length > 0 ? normalizedLines[normalizedLines.length - 1] : { raw: '', clean: '' };
37808
+ for (let i = normalizedLines.length - 1; i >= 0; i--) {
37809
+ const candidate = normalizedLines[i];
37810
+ if (!candidate.clean) {
37811
+ continue;
37812
+ }
37813
+ const replMatch = replMatchers.find(m => m.pattern.test(candidate.clean));
37814
+ if (replMatch) {
37815
+ environment = replMatch.environment;
37816
+ promptRaw = candidate.raw;
37817
+ promptClean = candidate.clean;
37818
+ break;
37819
+ }
37820
+ if (/[$#%❯➜]\s*$/.test(candidate.clean)) {
37821
+ isShell = true;
37822
+ const detectedShell = this.detectShellType(session);
37823
+ environment = detectedShell === 'sh' ? 'shell' : detectedShell;
37824
+ promptRaw = candidate.raw;
37825
+ promptClean = candidate.clean;
37826
+ break;
37827
+ }
37828
+ }
37829
+ if (!promptRaw) {
37830
+ isShell = true;
37831
+ const detectedShell = this.detectShellType(session);
37832
+ environment = detectedShell === 'sh' ? 'shell' : detectedShell;
37833
+ promptRaw = fallbackLine.raw;
37834
+ promptClean = fallbackLine.clean;
37835
+ }
37836
+ const tabAny = session.tab;
37837
+ const profile = tabAny.profile ? {
37838
+ id: tabAny.profile.id,
37839
+ name: tabAny.profile.name,
37840
+ type: tabAny.profile.type
37841
+ } : undefined;
37842
+ if (detectionMode === 'active' && isShell) {
37843
+ const activeEnvironment = await this.detectActiveShellEnvironment(session);
37844
+ if (activeEnvironment) {
37845
+ environment = activeEnvironment.environment;
37846
+ isShell = activeEnvironment.isShell;
37847
+ }
37848
+ }
37849
+ const shell = isShell ? (['bash', 'zsh', 'fish', 'sh', 'shell'].includes(environment) ? environment : this.detectShellType(session)) : undefined;
37850
+ return {
37851
+ content: [{
37852
+ type: 'text', text: JSON.stringify({
37853
+ success: true,
37854
+ sessionId: session.sessionId,
37855
+ environment,
37856
+ shell,
37857
+ isShell,
37858
+ lastPrompt: promptRaw,
37859
+ normalizedPrompt: promptClean || undefined,
37860
+ cwd: tabAny.session?.cwd,
37861
+ pid: tabAny.session?.pty?.pid,
37862
+ profile
37863
+ }, null, 2)
37864
+ }]
37865
+ };
37866
+ }
37867
+ };
37868
+ }
37869
+ async detectActiveShellEnvironment(session) {
37870
+ const tabAny = session.tab;
37871
+ const sessionObj = tabAny.session;
37872
+ if (!sessionObj || sessionObj.open === false) {
37873
+ return null;
37874
+ }
37875
+ const shell = this.detectShellType(session);
37876
+ const command = `printf '__MCP_ENV__:'; if [ -n "$VIRTUAL_ENV" ]; then printf 'python-venv'; elif [ -n "$CONDA_DEFAULT_ENV" ]; then printf 'python-conda'; elif [ -n "$IN_NIX_SHELL" ]; then printf 'nix-shell'; else printf 'shell'; fi; printf ':__MCP_ENV__'`;
37877
+ try {
37878
+ const startMarker = `__MCP_ENV_START_${Date.now()}__`;
37879
+ const endMarker = `__MCP_ENV_END_${Date.now()}__`;
37880
+ const wrappedCommand = this.getWrappedCommand(command, startMarker, endMarker, shell);
37881
+ session.tab.sendInput(wrappedCommand + '\n');
37882
+ const result = await this.waitForCommandOutputViaBuffer(session, startMarker, endMarker, 3000, () => false);
37883
+ const match = result.output.match(/__MCP_ENV__:(.+?):__MCP_ENV__/);
37884
+ if (!match) {
37885
+ return null;
37886
+ }
37887
+ const marker = match[1].trim();
37888
+ if (marker === 'python-venv' || marker === 'python-conda' || marker === 'nix-shell') {
37889
+ return { environment: marker, isShell: false };
37890
+ }
37891
+ return { environment: shell === 'sh' ? 'shell' : shell, isShell: true };
37892
+ }
37893
+ catch {
37894
+ return null;
37895
+ }
37896
+ }
37194
37897
  /**
37195
37898
  * Tool: Get terminal buffer content
37196
37899
  */
@@ -38496,6 +39199,7 @@ module.exports = require("zlib");
38496
39199
  (__unused_webpack_module, exports) {
38497
39200
 
38498
39201
  "use strict";
39202
+ var __webpack_unused_export__;
38499
39203
 
38500
39204
  /**
38501
39205
  * Experimental task capability assertion helpers.
@@ -38503,7 +39207,7 @@ module.exports = require("zlib");
38503
39207
  *
38504
39208
  * @experimental
38505
39209
  */
38506
- Object.defineProperty(exports, "__esModule", ({ value: true }));
39210
+ __webpack_unused_export__ = ({ value: true });
38507
39211
  exports.assertToolsCallTaskCapability = assertToolsCallTaskCapability;
38508
39212
  exports.assertClientRequestTaskCapability = assertClientRequestTaskCapability;
38509
39213
  /**
@@ -38571,12 +39275,13 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
38571
39275
  (__unused_webpack_module, exports) {
38572
39276
 
38573
39277
  "use strict";
39278
+ var __webpack_unused_export__;
38574
39279
 
38575
39280
  /**
38576
39281
  * Experimental task interfaces for MCP SDK.
38577
39282
  * WARNING: These APIs are experimental and may change without notice.
38578
39283
  */
38579
- Object.defineProperty(exports, "__esModule", ({ value: true }));
39284
+ __webpack_unused_export__ = ({ value: true });
38580
39285
  exports.isTerminal = isTerminal;
38581
39286
  /**
38582
39287
  * Checks if a task status represents a terminal state.
@@ -38597,6 +39302,7 @@ function isTerminal(status) {
38597
39302
  (__unused_webpack_module, exports) {
38598
39303
 
38599
39304
  "use strict";
39305
+ var __webpack_unused_export__;
38600
39306
 
38601
39307
  /**
38602
39308
  * Experimental McpServer task features for MCP SDK.
@@ -38604,7 +39310,7 @@ function isTerminal(status) {
38604
39310
  *
38605
39311
  * @experimental
38606
39312
  */
38607
- Object.defineProperty(exports, "__esModule", ({ value: true }));
39313
+ __webpack_unused_export__ = ({ value: true });
38608
39314
  exports.ExperimentalMcpServerTasks = void 0;
38609
39315
  /**
38610
39316
  * Experimental task features for McpServer.
@@ -38640,6 +39346,7 @@ exports.ExperimentalMcpServerTasks = ExperimentalMcpServerTasks;
38640
39346
  (__unused_webpack_module, exports, __webpack_require__) {
38641
39347
 
38642
39348
  "use strict";
39349
+ var __webpack_unused_export__;
38643
39350
 
38644
39351
  /**
38645
39352
  * Experimental server task features for MCP SDK.
@@ -38647,7 +39354,7 @@ exports.ExperimentalMcpServerTasks = ExperimentalMcpServerTasks;
38647
39354
  *
38648
39355
  * @experimental
38649
39356
  */
38650
- Object.defineProperty(exports, "__esModule", ({ value: true }));
39357
+ __webpack_unused_export__ = ({ value: true });
38651
39358
  exports.ExperimentalServerTasks = void 0;
38652
39359
  const types_js_1 = __webpack_require__(1294);
38653
39360
  /**
@@ -38897,20 +39604,21 @@ exports.ExperimentalServerTasks = ExperimentalServerTasks;
38897
39604
  (__unused_webpack_module, exports) {
38898
39605
 
38899
39606
  "use strict";
39607
+ var __webpack_unused_export__;
38900
39608
 
38901
- Object.defineProperty(exports, "__esModule", ({ value: true }));
38902
- exports.McpZodTypeKind = exports.COMPLETABLE_SYMBOL = void 0;
38903
- exports.completable = completable;
39609
+ __webpack_unused_export__ = ({ value: true });
39610
+ __webpack_unused_export__ = exports.MX = void 0;
39611
+ __webpack_unused_export__ = completable;
38904
39612
  exports.isCompletable = isCompletable;
38905
39613
  exports.getCompleter = getCompleter;
38906
- exports.unwrapCompletable = unwrapCompletable;
38907
- exports.COMPLETABLE_SYMBOL = Symbol.for('mcp.completable');
39614
+ __webpack_unused_export__ = unwrapCompletable;
39615
+ exports.MX = Symbol.for('mcp.completable');
38908
39616
  /**
38909
39617
  * Wraps a Zod type to provide autocompletion capabilities. Useful for, e.g., prompt arguments in MCP.
38910
39618
  * Works with both Zod v3 and v4 schemas.
38911
39619
  */
38912
39620
  function completable(schema, complete) {
38913
- Object.defineProperty(schema, exports.COMPLETABLE_SYMBOL, {
39621
+ Object.defineProperty(schema, exports.MX, {
38914
39622
  value: { complete },
38915
39623
  enumerable: false,
38916
39624
  writable: false,
@@ -38922,13 +39630,13 @@ function completable(schema, complete) {
38922
39630
  * Checks if a schema is completable (has completion metadata).
38923
39631
  */
38924
39632
  function isCompletable(schema) {
38925
- return !!schema && typeof schema === 'object' && exports.COMPLETABLE_SYMBOL in schema;
39633
+ return !!schema && typeof schema === 'object' && exports.MX in schema;
38926
39634
  }
38927
39635
  /**
38928
39636
  * Gets the completer callback from a completable schema, if it exists.
38929
39637
  */
38930
39638
  function getCompleter(schema) {
38931
- const meta = schema[exports.COMPLETABLE_SYMBOL];
39639
+ const meta = schema[exports.MX];
38932
39640
  return meta?.complete;
38933
39641
  }
38934
39642
  /**
@@ -38943,7 +39651,7 @@ function unwrapCompletable(schema) {
38943
39651
  var McpZodTypeKind;
38944
39652
  (function (McpZodTypeKind) {
38945
39653
  McpZodTypeKind["Completable"] = "McpCompletable";
38946
- })(McpZodTypeKind || (exports.McpZodTypeKind = McpZodTypeKind = {}));
39654
+ })(McpZodTypeKind || (__webpack_unused_export__ = McpZodTypeKind = {}));
38947
39655
  //# sourceMappingURL=completable.js.map
38948
39656
 
38949
39657
  /***/ },
@@ -38952,8 +39660,9 @@ var McpZodTypeKind;
38952
39660
  (__unused_webpack_module, exports, __webpack_require__) {
38953
39661
 
38954
39662
  "use strict";
39663
+ var __webpack_unused_export__;
38955
39664
 
38956
- Object.defineProperty(exports, "__esModule", ({ value: true }));
39665
+ __webpack_unused_export__ = ({ value: true });
38957
39666
  exports.Server = void 0;
38958
39667
  const protocol_js_1 = __webpack_require__(7533);
38959
39668
  const types_js_1 = __webpack_require__(1294);
@@ -39403,9 +40112,10 @@ exports.Server = Server;
39403
40112
  (__unused_webpack_module, exports, __webpack_require__) {
39404
40113
 
39405
40114
  "use strict";
40115
+ var __webpack_unused_export__;
39406
40116
 
39407
- Object.defineProperty(exports, "__esModule", ({ value: true }));
39408
- exports.ResourceTemplate = exports.McpServer = void 0;
40117
+ __webpack_unused_export__ = ({ value: true });
40118
+ __webpack_unused_export__ = exports.McpServer = void 0;
39409
40119
  const index_js_1 = __webpack_require__(7467);
39410
40120
  const zod_compat_js_1 = __webpack_require__(9029);
39411
40121
  const zod_json_schema_compat_js_1 = __webpack_require__(7472);
@@ -40091,9 +40801,10 @@ class McpServer {
40091
40801
  }
40092
40802
  }
40093
40803
  else if (typeof firstArg === 'object' && firstArg !== null) {
40094
- // Not a ZodRawShapeCompat, so must be annotations in this position
40095
- // Case: tool(name, annotations, cb)
40096
- // Or: tool(name, description, annotations, cb)
40804
+ // ToolAnnotations values are primitives. Nested objects indicate a misplaced schema
40805
+ if (Object.values(firstArg).some(v => typeof v === 'object' && v !== null)) {
40806
+ throw new Error(`Tool ${name} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);
40807
+ }
40097
40808
  annotations = rest.shift();
40098
40809
  }
40099
40810
  }
@@ -40212,7 +40923,7 @@ class ResourceTemplate {
40212
40923
  return this._callbacks.complete?.[variable];
40213
40924
  }
40214
40925
  }
40215
- exports.ResourceTemplate = ResourceTemplate;
40926
+ __webpack_unused_export__ = ResourceTemplate;
40216
40927
  const EMPTY_OBJECT_JSON_SCHEMA = {
40217
40928
  type: 'object',
40218
40929
  properties: {}
@@ -40265,7 +40976,7 @@ function isZodRawShapeCompat(obj) {
40265
40976
  }
40266
40977
  /**
40267
40978
  * Converts a provided Zod schema to a Zod object if it is a ZodRawShapeCompat,
40268
- * otherwise returns the schema as is.
40979
+ * otherwise returns the schema as is. Throws if the value is not a valid Zod schema.
40269
40980
  */
40270
40981
  function getZodSchemaObject(schema) {
40271
40982
  if (!schema) {
@@ -40274,6 +40985,9 @@ function getZodSchemaObject(schema) {
40274
40985
  if (isZodRawShapeCompat(schema)) {
40275
40986
  return (0, zod_compat_js_1.objectFromShape)(schema);
40276
40987
  }
40988
+ if (!isZodSchemaInstance(schema)) {
40989
+ throw new Error('inputSchema must be a Zod schema or raw shape, received an unrecognized object');
40990
+ }
40277
40991
  return schema;
40278
40992
  }
40279
40993
  function promptArgumentsFromSchema(schema) {
@@ -40507,6 +41221,7 @@ exports.SSEServerTransport = SSEServerTransport;
40507
41221
  (__unused_webpack_module, exports, __webpack_require__) {
40508
41222
 
40509
41223
  "use strict";
41224
+ var __webpack_unused_export__;
40510
41225
 
40511
41226
  /**
40512
41227
  * Node.js HTTP Streamable HTTP Server Transport
@@ -40516,7 +41231,7 @@ exports.SSEServerTransport = SSEServerTransport;
40516
41231
  *
40517
41232
  * For web-standard environments (Cloudflare Workers, Deno, Bun), use `WebStandardStreamableHTTPServerTransport` directly.
40518
41233
  */
40519
- Object.defineProperty(exports, "__esModule", ({ value: true }));
41234
+ __webpack_unused_export__ = ({ value: true });
40520
41235
  exports.StreamableHTTPServerTransport = void 0;
40521
41236
  const node_server_1 = __webpack_require__(4019);
40522
41237
  const webStandardStreamableHttp_js_1 = __webpack_require__(3472);
@@ -40679,6 +41394,7 @@ exports.StreamableHTTPServerTransport = StreamableHTTPServerTransport;
40679
41394
  (__unused_webpack_module, exports, __webpack_require__) {
40680
41395
 
40681
41396
  "use strict";
41397
+ var __webpack_unused_export__;
40682
41398
 
40683
41399
  /**
40684
41400
  * Web Standards Streamable HTTP Server Transport
@@ -40688,7 +41404,7 @@ exports.StreamableHTTPServerTransport = StreamableHTTPServerTransport;
40688
41404
  *
40689
41405
  * For Node.js Express/HTTP compatibility, use `StreamableHTTPServerTransport` which wraps this transport.
40690
41406
  */
40691
- Object.defineProperty(exports, "__esModule", ({ value: true }));
41407
+ __webpack_unused_export__ = ({ value: true });
40692
41408
  exports.WebStandardStreamableHTTPServerTransport = void 0;
40693
41409
  const types_js_1 = __webpack_require__(1294);
40694
41410
  /**
@@ -41778,9 +42494,10 @@ function parseWithCompat(schema, data) {
41778
42494
  (__unused_webpack_module, exports, __webpack_require__) {
41779
42495
 
41780
42496
  "use strict";
42497
+ var __webpack_unused_export__;
41781
42498
 
41782
- Object.defineProperty(exports, "__esModule", ({ value: true }));
41783
- exports.Protocol = exports.DEFAULT_REQUEST_TIMEOUT_MSEC = void 0;
42499
+ __webpack_unused_export__ = ({ value: true });
42500
+ exports.Protocol = exports.d = void 0;
41784
42501
  exports.mergeCapabilities = mergeCapabilities;
41785
42502
  const zod_compat_js_1 = __webpack_require__(9029);
41786
42503
  const types_js_1 = __webpack_require__(1294);
@@ -41789,7 +42506,7 @@ const zod_json_schema_compat_js_1 = __webpack_require__(7472);
41789
42506
  /**
41790
42507
  * The default request timeout, in miliseconds.
41791
42508
  */
41792
- exports.DEFAULT_REQUEST_TIMEOUT_MSEC = 60000;
42509
+ exports.d = 60000;
41793
42510
  /**
41794
42511
  * Implements MCP protocol framing on top of a pluggable transport, including
41795
42512
  * features like request/response linking, notifications, and progress.
@@ -42035,6 +42752,10 @@ class Protocol {
42035
42752
  this._progressHandlers.clear();
42036
42753
  this._taskProgressTokens.clear();
42037
42754
  this._pendingDebouncedNotifications.clear();
42755
+ for (const info of this._timeoutInfo.values()) {
42756
+ clearTimeout(info.timeoutId);
42757
+ }
42758
+ this._timeoutInfo.clear();
42038
42759
  // Abort all in-flight request handlers so they stop sending messages
42039
42760
  for (const controller of this._requestHandlerAbortControllers.values()) {
42040
42761
  controller.abort();
@@ -42194,7 +42915,11 @@ class Protocol {
42194
42915
  })
42195
42916
  .catch(error => this._onerror(new Error(`Failed to send response: ${error}`)))
42196
42917
  .finally(() => {
42197
- this._requestHandlerAbortControllers.delete(request.id);
42918
+ // Only delete if the stored controller is still ours; after close()+connect(),
42919
+ // a new connection may have reused the same request ID with a different controller.
42920
+ if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
42921
+ this._requestHandlerAbortControllers.delete(request.id);
42922
+ }
42198
42923
  });
42199
42924
  }
42200
42925
  _onprogress(notification) {
@@ -42485,7 +43210,7 @@ class Protocol {
42485
43210
  options?.signal?.addEventListener('abort', () => {
42486
43211
  cancel(options?.signal?.reason);
42487
43212
  });
42488
- const timeout = options?.timeout ?? exports.DEFAULT_REQUEST_TIMEOUT_MSEC;
43213
+ const timeout = options?.timeout ?? exports.d;
42489
43214
  const timeoutHandler = () => cancel(types_js_1.McpError.fromError(types_js_1.ErrorCode.RequestTimeout, 'Request timed out', { timeout }));
42490
43215
  this._setupTimeout(messageId, timeout, options?.maxTotalTimeout, timeoutHandler, options?.resetTimeoutOnProgress ?? false);
42491
43216
  // Queue request if related to a task
@@ -42889,6 +43614,7 @@ function mergeCapabilities(base, additional) {
42889
43614
  (__unused_webpack_module, exports) {
42890
43615
 
42891
43616
  "use strict";
43617
+ var __webpack_unused_export__;
42892
43618
 
42893
43619
  /**
42894
43620
  * Tool name validation utilities according to SEP: Specify Format for Tool Names
@@ -42899,9 +43625,9 @@ function mergeCapabilities(base, additional) {
42899
43625
  * (0-9), underscore (_), dash (-), and dot (.).
42900
43626
  * Tool names SHOULD NOT contain spaces, commas, or other special characters.
42901
43627
  */
42902
- Object.defineProperty(exports, "__esModule", ({ value: true }));
42903
- exports.validateToolName = validateToolName;
42904
- exports.issueToolNameWarning = issueToolNameWarning;
43628
+ __webpack_unused_export__ = ({ value: true });
43629
+ __webpack_unused_export__ = validateToolName;
43630
+ __webpack_unused_export__ = issueToolNameWarning;
42905
43631
  exports.validateAndWarnToolName = validateAndWarnToolName;
42906
43632
  /**
42907
43633
  * Regular expression for valid tool names according to SEP-986 specification
@@ -42993,9 +43719,10 @@ function validateAndWarnToolName(name) {
42993
43719
  (__unused_webpack_module, exports) {
42994
43720
 
42995
43721
  "use strict";
43722
+ var __webpack_unused_export__;
42996
43723
 
42997
43724
  // Claude-authored implementation of RFC 6570 URI Templates
42998
- Object.defineProperty(exports, "__esModule", ({ value: true }));
43725
+ __webpack_unused_export__ = ({ value: true });
42999
43726
  exports.UriTemplate = void 0;
43000
43727
  const MAX_TEMPLATE_LENGTH = 1000000; // 1MB
43001
43728
  const MAX_VARIABLE_LENGTH = 1000000; // 1MB
@@ -43300,10 +44027,9 @@ exports.CursorSchema = z.string();
43300
44027
  */
43301
44028
  exports.TaskCreationParamsSchema = z.looseObject({
43302
44029
  /**
43303
- * Time in milliseconds to keep task results available after completion.
43304
- * If null, the task has unlimited lifetime until manually cleaned up.
44030
+ * Requested duration in milliseconds to retain task from creation.
43305
44031
  */
43306
- ttl: z.union([z.number(), z.null()]).optional(),
44032
+ ttl: z.number().optional(),
43307
44033
  /**
43308
44034
  * Time in milliseconds to wait between task status requests.
43309
44035
  */
@@ -43731,7 +44457,11 @@ exports.ClientCapabilitiesSchema = z.object({
43731
44457
  /**
43732
44458
  * Present if the client supports task creation.
43733
44459
  */
43734
- tasks: exports.ClientTasksCapabilitySchema.optional()
44460
+ tasks: exports.ClientTasksCapabilitySchema.optional(),
44461
+ /**
44462
+ * Extensions that the client supports. Keys are extension identifiers (vendor-prefix/extension-name).
44463
+ */
44464
+ extensions: z.record(z.string(), AssertObjectSchema).optional()
43735
44465
  });
43736
44466
  exports.InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
43737
44467
  /**
@@ -43806,7 +44536,11 @@ exports.ServerCapabilitiesSchema = z.object({
43806
44536
  /**
43807
44537
  * Present if the server supports task creation.
43808
44538
  */
43809
- tasks: exports.ServerTasksCapabilitySchema.optional()
44539
+ tasks: exports.ServerTasksCapabilitySchema.optional(),
44540
+ /**
44541
+ * Extensions that the server supports. Keys are extension identifiers (vendor-prefix/extension-name).
44542
+ */
44543
+ extensions: z.record(z.string(), AssertObjectSchema).optional()
43810
44544
  });
43811
44545
  /**
43812
44546
  * After receiving an initialize request from the client, the server sends this response.
@@ -44081,6 +44815,12 @@ exports.ResourceSchema = z.object({
44081
44815
  * The MIME type of this resource, if known.
44082
44816
  */
44083
44817
  mimeType: z.optional(z.string()),
44818
+ /**
44819
+ * The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known.
44820
+ *
44821
+ * This can be used by Hosts to display file sizes and estimate context window usage.
44822
+ */
44823
+ size: z.optional(z.number()),
44084
44824
  /**
44085
44825
  * Optional annotations for the client.
44086
44826
  */
@@ -45445,7 +46185,7 @@ exports.AjvJsonSchemaValidator = AjvJsonSchemaValidator;
45445
46185
  "use strict";
45446
46186
 
45447
46187
 
45448
- const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = __webpack_require__(4834)
46188
+ const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = __webpack_require__(4834)
45449
46189
  const { SCHEMES, getSchemeHandler } = __webpack_require__(343)
45450
46190
 
45451
46191
  /**
@@ -45456,7 +46196,7 @@ const { SCHEMES, getSchemeHandler } = __webpack_require__(343)
45456
46196
  */
45457
46197
  function normalize (uri, options) {
45458
46198
  if (typeof uri === 'string') {
45459
- uri = /** @type {T} */ (serialize(parse(uri, options), options))
46199
+ uri = /** @type {T} */ (normalizeString(uri, options))
45460
46200
  } else if (typeof uri === 'object') {
45461
46201
  uri = /** @type {T} */ (parse(serialize(uri, options), options))
45462
46202
  }
@@ -45551,21 +46291,10 @@ function resolveComponent (base, relative, options, skipNormalization) {
45551
46291
  * @returns {boolean}
45552
46292
  */
45553
46293
  function equal (uriA, uriB, options) {
45554
- if (typeof uriA === 'string') {
45555
- uriA = unescape(uriA)
45556
- uriA = serialize(normalizeComponentEncoding(parse(uriA, options), true), { ...options, skipEscape: true })
45557
- } else if (typeof uriA === 'object') {
45558
- uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true })
45559
- }
45560
-
45561
- if (typeof uriB === 'string') {
45562
- uriB = unescape(uriB)
45563
- uriB = serialize(normalizeComponentEncoding(parse(uriB, options), true), { ...options, skipEscape: true })
45564
- } else if (typeof uriB === 'object') {
45565
- uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true })
45566
- }
46294
+ const normalizedA = normalizeComparableURI(uriA, options)
46295
+ const normalizedB = normalizeComparableURI(uriB, options)
45567
46296
 
45568
- return uriA.toLowerCase() === uriB.toLowerCase()
46297
+ return normalizedA !== undefined && normalizedB !== undefined && normalizedA.toLowerCase() === normalizedB.toLowerCase()
45569
46298
  }
45570
46299
 
45571
46300
  /**
@@ -45601,13 +46330,13 @@ function serialize (cmpts, opts) {
45601
46330
 
45602
46331
  if (component.path !== undefined) {
45603
46332
  if (!options.skipEscape) {
45604
- component.path = escape(component.path)
46333
+ component.path = escapePreservingEscapes(component.path)
45605
46334
 
45606
46335
  if (component.scheme !== undefined) {
45607
46336
  component.path = component.path.split('%3A').join(':')
45608
46337
  }
45609
46338
  } else {
45610
- component.path = unescape(component.path)
46339
+ component.path = normalizePercentEncoding(component.path)
45611
46340
  }
45612
46341
  }
45613
46342
 
@@ -45658,12 +46387,29 @@ function serialize (cmpts, opts) {
45658
46387
 
45659
46388
  const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u
45660
46389
 
46390
+ /**
46391
+ * @param {import('./types/index').URIComponent} parsed
46392
+ * @param {RegExpMatchArray} matches
46393
+ * @returns {string|undefined}
46394
+ */
46395
+ function getParseError (parsed, matches) {
46396
+ if (matches[2] !== undefined && parsed.path && parsed.path[0] !== '/') {
46397
+ return 'URI path must start with "/" when authority is present.'
46398
+ }
46399
+
46400
+ if (typeof parsed.port === 'number' && (parsed.port < 0 || parsed.port > 65535)) {
46401
+ return 'URI port is malformed.'
46402
+ }
46403
+
46404
+ return undefined
46405
+ }
46406
+
45661
46407
  /**
45662
46408
  * @param {string} uri
45663
46409
  * @param {import('./types/index').Options} [opts]
45664
- * @returns
46410
+ * @returns {{ parsed: import('./types/index').URIComponent, malformedAuthorityOrPort: boolean }}
45665
46411
  */
45666
- function parse (uri, opts) {
46412
+ function parseWithStatus (uri, opts) {
45667
46413
  const options = Object.assign({}, opts)
45668
46414
  /** @type {import('./types/index').URIComponent} */
45669
46415
  const parsed = {
@@ -45676,6 +46422,8 @@ function parse (uri, opts) {
45676
46422
  fragment: undefined
45677
46423
  }
45678
46424
 
46425
+ let malformedAuthorityOrPort = false
46426
+
45679
46427
  let isIP = false
45680
46428
  if (options.reference === 'suffix') {
45681
46429
  if (options.scheme) {
@@ -45701,6 +46449,13 @@ function parse (uri, opts) {
45701
46449
  if (isNaN(parsed.port)) {
45702
46450
  parsed.port = matches[5]
45703
46451
  }
46452
+
46453
+ const parseError = getParseError(parsed, matches)
46454
+ if (parseError !== undefined) {
46455
+ parsed.error = parsed.error || parseError
46456
+ malformedAuthorityOrPort = true
46457
+ }
46458
+
45704
46459
  if (parsed.host) {
45705
46460
  const ipv4result = isIPv4(parsed.host)
45706
46461
  if (ipv4result === false) {
@@ -45749,14 +46504,18 @@ function parse (uri, opts) {
45749
46504
  parsed.scheme = unescape(parsed.scheme)
45750
46505
  }
45751
46506
  if (parsed.host !== undefined) {
45752
- parsed.host = unescape(parsed.host)
46507
+ parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP)
45753
46508
  }
45754
46509
  }
45755
46510
  if (parsed.path) {
45756
- parsed.path = escape(unescape(parsed.path))
46511
+ parsed.path = normalizePathEncoding(parsed.path)
45757
46512
  }
45758
46513
  if (parsed.fragment) {
45759
- parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment))
46514
+ try {
46515
+ parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment))
46516
+ } catch {
46517
+ parsed.error = parsed.error || 'URI malformed'
46518
+ }
45760
46519
  }
45761
46520
  }
45762
46521
 
@@ -45767,7 +46526,54 @@ function parse (uri, opts) {
45767
46526
  } else {
45768
46527
  parsed.error = parsed.error || 'URI can not be parsed.'
45769
46528
  }
45770
- return parsed
46529
+ return { parsed, malformedAuthorityOrPort }
46530
+ }
46531
+
46532
+ /**
46533
+ * @param {string} uri
46534
+ * @param {import('./types/index').Options} [opts]
46535
+ * @returns
46536
+ */
46537
+ function parse (uri, opts) {
46538
+ return parseWithStatus(uri, opts).parsed
46539
+ }
46540
+
46541
+ /**
46542
+ * @param {string} uri
46543
+ * @param {import('./types/index').Options} [opts]
46544
+ * @returns {string}
46545
+ */
46546
+ function normalizeString (uri, opts) {
46547
+ return normalizeStringWithStatus(uri, opts).normalized
46548
+ }
46549
+
46550
+ /**
46551
+ * @param {string} uri
46552
+ * @param {import('./types/index').Options} [opts]
46553
+ * @returns {{ normalized: string, malformedAuthorityOrPort: boolean }}
46554
+ */
46555
+ function normalizeStringWithStatus (uri, opts) {
46556
+ const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts)
46557
+ return {
46558
+ normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
46559
+ malformedAuthorityOrPort
46560
+ }
46561
+ }
46562
+
46563
+ /**
46564
+ * @param {import ('./types/index').URIComponent|string} uri
46565
+ * @param {import('./types/index').Options} [opts]
46566
+ * @returns {string|undefined}
46567
+ */
46568
+ function normalizeComparableURI (uri, opts) {
46569
+ if (typeof uri === 'string') {
46570
+ const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts)
46571
+ return malformedAuthorityOrPort ? undefined : normalized
46572
+ }
46573
+
46574
+ if (typeof uri === 'object') {
46575
+ return serialize(uri, opts)
46576
+ }
45771
46577
  }
45772
46578
 
45773
46579
  const fastUri = {
@@ -46074,6 +46880,15 @@ const isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\d
46074
46880
  /** @type {(value: string) => boolean} */
46075
46881
  const isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u)
46076
46882
 
46883
+ /** @type {(value: string) => boolean} */
46884
+ const isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu)
46885
+
46886
+ /** @type {(value: string) => boolean} */
46887
+ const isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu)
46888
+
46889
+ /** @type {(value: string) => boolean} */
46890
+ const isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu)
46891
+
46077
46892
  /**
46078
46893
  * @param {Array<string>} input
46079
46894
  * @returns {string}
@@ -46332,31 +47147,126 @@ function removeDotSegments (path) {
46332
47147
  }
46333
47148
 
46334
47149
  /**
46335
- * @param {import('../types/index').URIComponent} component
46336
- * @param {boolean} esc
46337
- * @returns {import('../types/index').URIComponent}
47150
+ * Re-escape RFC 3986 gen-delims that must not appear literally in the host.
47151
+ * After the URI regex parses, these characters cannot be literal in the host
47152
+ * field, so any that appear after decoding came from percent-encoding and
47153
+ * must be restored to prevent authority structure changes.
47154
+ *
47155
+ * @param {string} host
47156
+ * @param {boolean} isIP - true for IPv4/IPv6 hosts (skip colon re-escaping)
47157
+ * @returns {string}
46338
47158
  */
46339
- function normalizeComponentEncoding (component, esc) {
46340
- const func = esc !== true ? escape : unescape
46341
- if (component.scheme !== undefined) {
46342
- component.scheme = func(component.scheme)
46343
- }
46344
- if (component.userinfo !== undefined) {
46345
- component.userinfo = func(component.userinfo)
46346
- }
46347
- if (component.host !== undefined) {
46348
- component.host = func(component.host)
47159
+ const HOST_DELIMS = { '@': '%40', '/': '%2F', '?': '%3F', '#': '%23', ':': '%3A' }
47160
+ const HOST_DELIM_RE = /[@/?#:]/g
47161
+ const HOST_DELIM_NO_COLON_RE = /[@/?#]/g
47162
+
47163
+ function reescapeHostDelimiters (host, isIP) {
47164
+ const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE
47165
+ re.lastIndex = 0
47166
+ return host.replace(re, (ch) => HOST_DELIMS[ch])
47167
+ }
47168
+
47169
+ /**
47170
+ * Normalizes percent escapes and optionally decodes only unreserved ASCII bytes.
47171
+ * Reserved delimiters such as `%2F` and `%2E` stay escaped.
47172
+ *
47173
+ * @param {string} input
47174
+ * @param {boolean} [decodeUnreserved=false]
47175
+ * @returns {string}
47176
+ */
47177
+ function normalizePercentEncoding (input, decodeUnreserved = false) {
47178
+ if (input.indexOf('%') === -1) {
47179
+ return input
46349
47180
  }
46350
- if (component.path !== undefined) {
46351
- component.path = func(component.path)
47181
+
47182
+ let output = ''
47183
+
47184
+ for (let i = 0; i < input.length; i++) {
47185
+ if (input[i] === '%' && i + 2 < input.length) {
47186
+ const hex = input.slice(i + 1, i + 3)
47187
+ if (isHexPair(hex)) {
47188
+ const normalizedHex = hex.toUpperCase()
47189
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16))
47190
+
47191
+ if (decodeUnreserved && isUnreserved(decoded)) {
47192
+ output += decoded
47193
+ } else {
47194
+ output += '%' + normalizedHex
47195
+ }
47196
+
47197
+ i += 2
47198
+ continue
47199
+ }
47200
+ }
47201
+
47202
+ output += input[i]
46352
47203
  }
46353
- if (component.query !== undefined) {
46354
- component.query = func(component.query)
47204
+
47205
+ return output
47206
+ }
47207
+
47208
+ /**
47209
+ * Normalizes path data without turning reserved escapes into live path syntax.
47210
+ * Valid escapes are uppercased, raw unsafe characters are escaped, and only
47211
+ * unreserved bytes that are not `.` are decoded.
47212
+ *
47213
+ * @param {string} input
47214
+ * @returns {string}
47215
+ */
47216
+ function normalizePathEncoding (input) {
47217
+ let output = ''
47218
+
47219
+ for (let i = 0; i < input.length; i++) {
47220
+ if (input[i] === '%' && i + 2 < input.length) {
47221
+ const hex = input.slice(i + 1, i + 3)
47222
+ if (isHexPair(hex)) {
47223
+ const normalizedHex = hex.toUpperCase()
47224
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16))
47225
+
47226
+ if (decoded !== '.' && isUnreserved(decoded)) {
47227
+ output += decoded
47228
+ } else {
47229
+ output += '%' + normalizedHex
47230
+ }
47231
+
47232
+ i += 2
47233
+ continue
47234
+ }
47235
+ }
47236
+
47237
+ if (isPathCharacter(input[i])) {
47238
+ output += input[i]
47239
+ } else {
47240
+ output += escape(input[i])
47241
+ }
46355
47242
  }
46356
- if (component.fragment !== undefined) {
46357
- component.fragment = func(component.fragment)
47243
+
47244
+ return output
47245
+ }
47246
+
47247
+ /**
47248
+ * Escapes a component while preserving existing valid percent escapes.
47249
+ *
47250
+ * @param {string} input
47251
+ * @returns {string}
47252
+ */
47253
+ function escapePreservingEscapes (input) {
47254
+ let output = ''
47255
+
47256
+ for (let i = 0; i < input.length; i++) {
47257
+ if (input[i] === '%' && i + 2 < input.length) {
47258
+ const hex = input.slice(i + 1, i + 3)
47259
+ if (isHexPair(hex)) {
47260
+ output += '%' + hex.toUpperCase()
47261
+ i += 2
47262
+ continue
47263
+ }
47264
+ }
47265
+
47266
+ output += escape(input[i])
46358
47267
  }
46359
- return component
47268
+
47269
+ return output
46360
47270
  }
46361
47271
 
46362
47272
  /**
@@ -46378,7 +47288,7 @@ function recomposeAuthority (component) {
46378
47288
  if (ipV6res.isIPV6 === true) {
46379
47289
  host = `[${ipV6res.escapedHost}]`
46380
47290
  } else {
46381
- host = component.host
47291
+ host = reescapeHostDelimiters(host, false)
46382
47292
  }
46383
47293
  }
46384
47294
  uriTokens.push(host)
@@ -46395,7 +47305,10 @@ function recomposeAuthority (component) {
46395
47305
  module.exports = {
46396
47306
  nonSimpleDomain,
46397
47307
  recomposeAuthority,
46398
- normalizeComponentEncoding,
47308
+ reescapeHostDelimiters,
47309
+ normalizePercentEncoding,
47310
+ normalizePathEncoding,
47311
+ escapePreservingEscapes,
46399
47312
  removeDotSegments,
46400
47313
  isIPv4,
46401
47314
  isUUID,
@@ -48583,8 +49496,9 @@ __exportStar(__webpack_require__(8651), exports);
48583
49496
  (__unused_webpack_module, exports) {
48584
49497
 
48585
49498
  "use strict";
49499
+ var __webpack_unused_export__;
48586
49500
 
48587
- Object.defineProperty(exports, "__esModule", ({ value: true }));
49501
+ __webpack_unused_export__ = ({ value: true });
48588
49502
  exports.errorUtil = void 0;
48589
49503
  var errorUtil;
48590
49504
  (function (errorUtil) {
@@ -67326,6 +68240,58 @@ function json() {
67326
68240
  }
67327
68241
 
67328
68242
 
68243
+ /***/ },
68244
+
68245
+ /***/ 3099
68246
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
68247
+
68248
+ "use strict";
68249
+ // ESM COMPAT FLAG
68250
+ __webpack_require__.r(__webpack_exports__);
68251
+
68252
+ // EXPORTS
68253
+ __webpack_require__.d(__webpack_exports__, {
68254
+ "default": () => (/* binding */ stripAnsi)
68255
+ });
68256
+
68257
+ ;// ./node_modules/ansi-regex/index.js
68258
+ function ansiRegex({onlyFirst = false} = {}) {
68259
+ // Valid string terminator sequences are BEL, ESC\, and 0x9c
68260
+ const ST = '(?:\\u0007|\\u001B\\u005C|\\u009C)';
68261
+
68262
+ // OSC sequences only: ESC ] ... ST (non-greedy until the first ST)
68263
+ const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
68264
+
68265
+ // CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :) then final byte
68266
+ const csi = '[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]';
68267
+
68268
+ const pattern = `${osc}|${csi}`;
68269
+
68270
+ return new RegExp(pattern, onlyFirst ? undefined : 'g');
68271
+ }
68272
+
68273
+ ;// ./node_modules/strip-ansi/index.js
68274
+
68275
+
68276
+ const regex = ansiRegex();
68277
+
68278
+ function stripAnsi(string) {
68279
+ if (typeof string !== 'string') {
68280
+ throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
68281
+ }
68282
+
68283
+ // Fast path: ANSI codes require ESC (7-bit) or CSI (8-bit) introducer
68284
+ if (!string.includes('\u001B') && !string.includes('\u009B')) {
68285
+ return string;
68286
+ }
68287
+
68288
+ // Even though the regex is global, we don't need to reset the `.lastIndex`
68289
+ // because unlike `.exec()` and `.test()`, `.replace()` does it automatically
68290
+ // and doing it manually has a performance penalty.
68291
+ return string.replace(regex, '');
68292
+ }
68293
+
68294
+
67329
68295
  /***/ },
67330
68296
 
67331
68297
  /***/ 3837
@@ -67500,7 +68466,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"100":"Continue","101":"Switching Pro
67500
68466
  (module) {
67501
68467
 
67502
68468
  "use strict";
67503
- module.exports = /*#__PURE__*/JSON.parse('{"name":"tabby-mcp-server","version":"1.4.2","description":"MCP (Model Context Protocol) server plugin for Tabby terminal - Complete terminal control with 34 MCP tools including SFTP file transfer","homepage":"https://github.com/GentlemanHu/Tabby-MCP","repository":{"type":"git","url":"https://github.com/GentlemanHu/Tabby-MCP.git"},"bugs":{"url":"https://github.com/GentlemanHu/Tabby-MCP/issues"},"keywords":["tabby-plugin","mcp","model-context-protocol","terminal","ai","cursor","windsurf","ssh","sftp","sse"],"main":"dist/index.js","typings":"typings/index.d.ts","scripts":{"build":"webpack --progress --color","watch":"webpack --progress --color --watch","install-plugin":"bash scripts/install.sh","uninstall-plugin":"bash scripts/uninstall.sh"},"files":["dist","typings"],"author":"GentlemanHu <justfeelingme@gmail.com>","contributors":["AI Assistant (Claude/Gemini)"],"license":"MIT","peerDependencies":{"@angular/animations":"*","@angular/common":"*","@angular/core":"*","@angular/forms":"*","@ng-bootstrap/ng-bootstrap":"*","rxjs":"*","tabby-core":"*","tabby-settings":"*","tabby-terminal":"*","tabby-ssh":"*"},"peerDependenciesMeta":{"tabby-ssh":{"optional":true},"@angular/animations":{"optional":true},"@angular/common":{"optional":true},"@angular/core":{"optional":true},"@angular/forms":{"optional":true},"@ng-bootstrap/ng-bootstrap":{"optional":true},"rxjs":{"optional":true},"tabby-core":{"optional":true},"tabby-settings":{"optional":true},"tabby-terminal":{"optional":true}},"devDependencies":{"@modelcontextprotocol/sdk":"^1.8.0","@xterm/addon-serialize":"^0.12.0","cors":"^2.8.5","express":"^4.18.2","zod":"^3.22.4","@angular/common":"^17.3.0","@angular/core":"^17.3.0","@angular/forms":"^17.3.0","@angular/animations":"^17.3.0","@angular/platform-browser":"^17.3.0","@ng-bootstrap/ng-bootstrap":"^16.0.0","rxjs":"^7.8.0","tabby-core":"^1.0.163","tabby-settings":"^1.0.163","tabby-ssh":"^1.0.163","tabby-terminal":"^1.0.163","@types/cors":"^2.8.17","@types/express":"^4.17.21","@types/node":"^20.10.0","apply-loader":"^2.0.0","css-loader":"^6.8.1","sass":"^1.69.0","sass-loader":"^13.3.2","strip-ansi":"^7.1.0","style-loader":"^3.3.3","ts-loader":"^9.5.0","typescript":"^5.3.0","webpack":"^5.89.0","webpack-cli":"^5.1.4"}}');
68469
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"tabby-mcp-server","version":"1.6.2","description":"MCP (Model Context Protocol) server plugin for Tabby terminal - Complete terminal control with 34 MCP tools including SFTP file transfer","homepage":"https://github.com/GentlemanHu/Tabby-MCP","repository":{"type":"git","url":"git+https://github.com/GentlemanHu/Tabby-MCP.git"},"bugs":{"url":"https://github.com/GentlemanHu/Tabby-MCP/issues"},"keywords":["tabby-plugin","mcp","model-context-protocol","terminal","ai","cursor","windsurf","ssh","sftp","sse"],"main":"dist/index.js","typings":"typings/index.d.ts","scripts":{"build":"webpack --progress --color","watch":"webpack --progress --color --watch","install-plugin":"bash scripts/install.sh","uninstall-plugin":"bash scripts/uninstall.sh"},"files":["dist","typings"],"author":"GentlemanHu <justfeelingme@gmail.com>","contributors":["AI Assistant (Claude/Gemini)"],"license":"MIT","peerDependencies":{"@angular/animations":"*","@angular/common":"*","@angular/core":"*","@angular/forms":"*","@ng-bootstrap/ng-bootstrap":"*","rxjs":"*","tabby-core":"*","tabby-settings":"*","tabby-terminal":"*","tabby-ssh":"*"},"peerDependenciesMeta":{"tabby-ssh":{"optional":true},"@angular/animations":{"optional":true},"@angular/common":{"optional":true},"@angular/core":{"optional":true},"@angular/forms":{"optional":true},"@ng-bootstrap/ng-bootstrap":{"optional":true},"rxjs":{"optional":true},"tabby-core":{"optional":true},"tabby-settings":{"optional":true},"tabby-terminal":{"optional":true}},"devDependencies":{"@modelcontextprotocol/sdk":"^1.8.0","@xterm/addon-serialize":"^0.12.0","cors":"^2.8.5","express":"^4.18.2","zod":"^3.22.4","@angular/common":"^17.3.0","@angular/core":"^17.3.0","@angular/forms":"^17.3.0","@angular/animations":"^17.3.0","@angular/platform-browser":"^17.3.0","@ng-bootstrap/ng-bootstrap":"^16.0.0","rxjs":"^7.8.0","tabby-core":"^1.0.163","tabby-settings":"^1.0.163","tabby-ssh":"^1.0.163","tabby-terminal":"^1.0.163","@types/cors":"^2.8.17","@types/express":"^4.17.21","@types/node":"^20.10.0","apply-loader":"^2.0.0","css-loader":"^6.8.1","sass":"^1.69.0","sass-loader":"^13.3.2","strip-ansi":"^7.1.0","style-loader":"^3.3.3","ts-loader":"^9.5.0","typescript":"^5.3.0","webpack":"^5.89.0","webpack-cli":"^5.1.4"}}');
67504
68470
 
67505
68471
  /***/ },
67506
68472
 
@@ -67508,7 +68474,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"name":"tabby-mcp-server","version":"
67508
68474
  (module) {
67509
68475
 
67510
68476
  "use strict";
67511
- module.exports = /*#__PURE__*/JSON.parse('{"mcp.settings.title":"MCP Server Settings","mcp.settings.version":"v{version}","mcp.server.status":"Server Status","mcp.server.running":"Running","mcp.server.stopped":"Stopped","mcp.server.connections":"{count} connection(s)","mcp.server.start":"Start Server","mcp.server.stop":"Stop Server","mcp.server.restart":"Restart","mcp.config.port":"Port","mcp.config.port.desc":"MCP server port (default: 3001)","mcp.config.startOnBoot":"Start server on Tabby launch","mcp.logging.title":"Logging","mcp.logging.enable":"Enable logging","mcp.logging.level":"Log Level","mcp.logging.level.debug":"Debug","mcp.logging.level.info":"Info","mcp.logging.level.warn":"Warning","mcp.logging.level.error":"Error","mcp.logging.viewLogs":"View Logs","mcp.logging.exportJson":"Export JSON","mcp.logging.clearLogs":"Clear Logs","mcp.pairProgramming.title":"Pair Programming Mode","mcp.pairProgramming.enable":"Enable Pair Programming Mode","mcp.pairProgramming.enable.desc":"When enabled, AI commands require confirmation before execution","mcp.pairProgramming.showDialog":"Show confirmation dialog","mcp.pairProgramming.autoFocus":"Auto-focus terminal on command execution","mcp.sessionTracking.title":"Session Tracking","mcp.sessionTracking.desc":"Configure how sessions and tabs are identified","mcp.sessionTracking.stableIds":"Use stable UUIDs for session identification","mcp.sessionTracking.stableIds.desc":"Sessions get persistent IDs that don\'t change when tabs are reordered","mcp.sessionTracking.profileInfo":"Include profile info in session list","mcp.sessionTracking.pid":"Include process ID in session info","mcp.sessionTracking.cwd":"Include current working directory in session info","mcp.backgroundExecution.title":"Background Execution","mcp.backgroundExecution.desc":"Control whether MCP operations run in the background without switching focus","mcp.backgroundExecution.enable":"Enable Background Execution Mode","mcp.backgroundExecution.enable.desc":"When enabled, AI commands execute without switching focus to the target terminal. You can continue working on other tabs while AI runs commands in the background.","mcp.backgroundExecution.warning.title":"Background Execution Risks:","mcp.backgroundExecution.warning.visibility":"Limited Visibility: You won\'t see commands executing in real-time","mcp.backgroundExecution.warning.conflicts":"Input Conflicts: If you type in the target terminal while AI is running, input will mix and cause errors","mcp.backgroundExecution.warning.splitPanes":"Split Panes: Commands are sent to the pane specified by sessionId, not the focused pane","mcp.backgroundExecution.warning.dangerous":"Dangerous Commands: AI could run destructive commands (rm -rf, etc.) without you noticing immediately","mcp.backgroundExecution.safety.title":"Recommended Safety Measures:","mcp.backgroundExecution.safety.pairProgramming":"Keep \\"Pair Programming Mode\\" enabled with confirmation dialogs","mcp.backgroundExecution.safety.sessionId":"Use sessionId to target specific terminals to avoid accidental cross-terminal execution","mcp.backgroundExecution.safety.monitor":"Monitor terminal buffers periodically via get_terminal_buffer","mcp.sftp.title":"SFTP Settings","mcp.sftp.desc":"SFTP file transfer support (requires tabby-ssh plugin)","mcp.sftp.enable":"Enable SFTP tools","mcp.sftp.enable.desc":"If tabby-ssh is not installed, SFTP tools will be disabled automatically","mcp.sftp.maxReadSize":"Max Read Size","mcp.sftp.maxReadSize.desc":"Maximum file size for sftp_read_file (default: 1 MB)","mcp.sftp.maxUploadSize":"Max Upload Size","mcp.sftp.maxUploadSize.desc":"Maximum file size for sftp_upload (default: 10 GB)","mcp.sftp.maxDownloadSize":"Max Download Size","mcp.sftp.maxDownloadSize.desc":"Maximum file size for sftp_download (default: 10 GB)","mcp.sftp.timeout":"Timeout (seconds)","mcp.sftp.timeout.desc":"SFTP operation timeout (default: 60 seconds)","mcp.sftp.notes.title":"SFTP Notes:","mcp.sftp.notes.binary":"File transfers are direct binary (no base64 encoding)","mcp.sftp.notes.memory":"Large files may consume significant memory during transfer","mcp.sftp.notes.overwrite":"sftp_write_file can overwrite files without confirmation","mcp.sftp.notes.limit":"If file exceeds size limit, MCP will return an error (no popup)","mcp.experimental.title":"Experimental Features","mcp.experimental.streamCapture.label":"Use Stream Capture (Beta)","mcp.experimental.streamCapture.desc":"Solves output truncation issues for long commands by capturing raw data stream instead of screen buffer. Default is OFF (legacy buffer mode).","mcp.experimental.streamCapture.note":"This mode bypasses the terminal screen buffer limit. It is recommended for executing commands that produce large output (e.g., cat large files).","mcp.timing.title":"Timing Settings","mcp.timing.desc":"Advanced timing configuration for command execution and session detection","mcp.timing.pollInterval":"Poll Interval (ms)","mcp.timing.pollInterval.desc":"How often to check for command output (default: 100)","mcp.timing.initialDelay":"Initial Delay (ms)","mcp.timing.initialDelay.desc":"Delay before polling starts (default: 0)","mcp.timing.sessionStableChecks":"Session Stable Checks","mcp.timing.sessionStableChecks.desc":"Number of stable checks for session ready detection (default: 5)","mcp.timing.sessionPollInterval":"Session Poll Interval (ms)","mcp.timing.sessionPollInterval.desc":"Interval for session ready polling (default: 200)","mcp.connectionInfo.title":"Connection Info","mcp.connectionInfo.streamable":"Streamable HTTP (Recommended):","mcp.connectionInfo.legacySse":"Legacy SSE:","mcp.connectionInfo.healthCheck":"Health Check:","mcp.connectionInfo.addToClient":"Add to your MCP client (e.g., Cursor, VS Code):","mcp.connectionInfo.copyConfig":"Copy Config","mcp.common.saved":"✓ Settings saved","mcp.common.mb":"MB","mcp.common.sec":"sec","mcp.about.title":"About","mcp.about.issues":"Report Issues","mcp.about.credit":"Made with ❤️ by AI and GentlemanHu"}');
68477
+ module.exports = /*#__PURE__*/JSON.parse('{"mcp.settings.title":"MCP Server Settings","mcp.settings.version":"v{version}","mcp.server.status":"Server Status","mcp.server.running":"Running","mcp.server.stopped":"Stopped","mcp.server.connections":"{count} connection(s)","mcp.server.start":"Start Server","mcp.server.stop":"Stop Server","mcp.server.restart":"Restart","mcp.config.port":"Port","mcp.config.port.desc":"MCP server port (default: 3001)","mcp.config.startOnBoot":"Start server on Tabby launch","mcp.logging.title":"Logging","mcp.logging.enable":"Enable logging","mcp.logging.level":"Log Level","mcp.logging.level.debug":"Debug","mcp.logging.level.info":"Info","mcp.logging.level.warn":"Warning","mcp.logging.level.error":"Error","mcp.logging.viewLogs":"View Logs","mcp.logging.exportJson":"Export JSON","mcp.logging.clearLogs":"Clear Logs","mcp.pairProgramming.title":"Pair Programming Mode","mcp.pairProgramming.enable":"Enable Pair Programming Mode","mcp.pairProgramming.enable.desc":"When enabled, AI commands require confirmation before execution","mcp.pairProgramming.showDialog":"Show confirmation dialog","mcp.pairProgramming.autoFocus":"Auto-focus terminal on command execution","mcp.sessionTracking.title":"Session Tracking","mcp.sessionTracking.desc":"Configure how sessions and tabs are identified","mcp.sessionTracking.stableIds":"Use stable UUIDs for session identification","mcp.sessionTracking.stableIds.desc":"Sessions get persistent IDs that don\'t change when tabs are reordered","mcp.sessionTracking.profileInfo":"Include profile info in session list","mcp.sessionTracking.pid":"Include process ID in session info","mcp.sessionTracking.cwd":"Include current working directory in session info","mcp.backgroundExecution.title":"Background Execution","mcp.backgroundExecution.desc":"Control whether MCP operations run in the background without switching focus","mcp.backgroundExecution.enable":"Enable Background Execution Mode","mcp.backgroundExecution.enable.desc":"When enabled, AI commands execute without switching focus to the target terminal. You can continue working on other tabs while AI runs commands in the background.","mcp.backgroundExecution.warning.title":"Background Execution Risks:","mcp.backgroundExecution.warning.visibility":"Limited Visibility: You won\'t see commands executing in real-time","mcp.backgroundExecution.warning.conflicts":"Input Conflicts: If you type in the target terminal while AI is running, input will mix and cause errors","mcp.backgroundExecution.warning.splitPanes":"Split Panes: Commands are sent to the pane specified by sessionId, not the focused pane","mcp.backgroundExecution.warning.dangerous":"Dangerous Commands: AI could run destructive commands (rm -rf, etc.) without you noticing immediately","mcp.backgroundExecution.safety.title":"Recommended Safety Measures:","mcp.backgroundExecution.safety.pairProgramming":"Keep \\"Pair Programming Mode\\" enabled with confirmation dialogs","mcp.backgroundExecution.safety.sessionId":"Use sessionId to target specific terminals to avoid accidental cross-terminal execution","mcp.backgroundExecution.safety.monitor":"Monitor terminal buffers periodically via get_terminal_buffer","mcp.sftp.title":"SFTP Settings","mcp.sftp.desc":"SFTP file transfer support (requires tabby-ssh plugin)","mcp.sftp.enable":"Enable SFTP tools","mcp.sftp.enable.desc":"If tabby-ssh is not installed, SFTP tools will be disabled automatically","mcp.sftp.maxReadSize":"Max Read Size","mcp.sftp.maxReadSize.desc":"Maximum file size for sftp_read_file (default: 1 MB)","mcp.sftp.maxUploadSize":"Max Upload Size","mcp.sftp.maxUploadSize.desc":"Maximum file size for sftp_upload (default: 10 GB)","mcp.sftp.maxDownloadSize":"Max Download Size","mcp.sftp.maxDownloadSize.desc":"Maximum file size for sftp_download (default: 10 GB)","mcp.sftp.timeout":"Timeout (seconds)","mcp.sftp.timeout.desc":"SFTP operation timeout (default: 60 seconds)","mcp.sftp.notes.title":"SFTP Notes:","mcp.sftp.notes.binary":"File transfers are direct binary (no base64 encoding)","mcp.sftp.notes.memory":"Large files may consume significant memory during transfer","mcp.sftp.notes.overwrite":"sftp_write_file can overwrite files without confirmation","mcp.sftp.notes.limit":"If file exceeds size limit, MCP will return an error (no popup)","mcp.environmentDetection.title":"Environment Detection","mcp.environmentDetection.desc":"Heuristically infer the current terminal context (shell, Python, database REPL, etc.) before sending commands.","mcp.environmentDetection.enable":"Enable environment detection","mcp.environmentDetection.enable.desc":"Exposes get_session_environment for agents and scripts. Disabled by default for safety and predictability.","mcp.environmentDetection.enhanced":"Use enhanced heuristics","mcp.environmentDetection.enhanced.desc":"Scan recent prompt lines and normalize ANSI/control sequences for better prompt detection.","mcp.environmentDetection.mode":"Detection mode","mcp.environmentDetection.mode.heuristic":"Heuristic (passive)","mcp.environmentDetection.mode.active":"Active probe (stronger)","mcp.environmentDetection.mode.desc":"Active mode adds low-risk probing for shell sessions to improve accuracy, but it may still be affected by interactive state or shell policies.","mcp.environmentDetection.warning.title":"Environment detection limitations:","mcp.environmentDetection.warning.heuristic":"This feature is heuristic-based and may be inaccurate for custom prompts or uncommon interactive tools.","mcp.environmentDetection.warning.transient":"Transient SSH/status lines may appear before the real prompt and affect interpretation.","mcp.environmentDetection.warning.customPrompt":"Database or REPL detection depends on recognizable prompts; heavily customized prompts can reduce accuracy.","mcp.environmentDetection.warning.verify":"For critical actions, verify with get_terminal_buffer or a manual command before performing destructive operations.","mcp.environmentDetection.restart.confirm":"Environment Detection tool visibility changed. Restart the MCP server now to refresh the available tool list for current clients? Existing MCP connections may need to reconnect.","mcp.environmentDetection.restart.done":"✓ Settings saved and MCP server restarted","mcp.environmentDetection.restart.later":"✓ Settings saved. Existing MCP clients may need to reconnect before the tool list updates.","mcp.experimental.title":"Experimental Features","mcp.experimental.streamCapture.label":"Use Stream Capture (Beta)","mcp.experimental.streamCapture.desc":"Solves output truncation issues for long commands by capturing raw data stream instead of screen buffer. Default is OFF (legacy buffer mode).","mcp.experimental.streamCapture.note":"This mode bypasses the terminal screen buffer limit. It is recommended for executing commands that produce large output (e.g., cat large files).","mcp.timing.title":"Timing Settings","mcp.timing.desc":"Advanced timing configuration for command execution and session detection","mcp.timing.pollInterval":"Poll Interval (ms)","mcp.timing.pollInterval.desc":"How often to check for command output (default: 100)","mcp.timing.initialDelay":"Initial Delay (ms)","mcp.timing.initialDelay.desc":"Delay before polling starts (default: 0)","mcp.timing.sessionStableChecks":"Session Stable Checks","mcp.timing.sessionStableChecks.desc":"Number of stable checks for session ready detection (default: 5)","mcp.timing.sessionPollInterval":"Session Poll Interval (ms)","mcp.timing.sessionPollInterval.desc":"Interval for session ready polling (default: 200)","mcp.connectionInfo.title":"Connection Info","mcp.connectionInfo.streamable":"Streamable HTTP (Recommended):","mcp.connectionInfo.legacySse":"Legacy SSE:","mcp.connectionInfo.healthCheck":"Health Check:","mcp.connectionInfo.addToClient":"Add to your MCP client (e.g., Cursor, VS Code):","mcp.connectionInfo.copyConfig":"Copy Config","mcp.common.saved":"✓ Settings saved","mcp.common.mb":"MB","mcp.common.sec":"sec","mcp.about.title":"About","mcp.about.issues":"Report Issues","mcp.about.credit":"Made with ❤️ by AI and GentlemanHu"}');
67512
68478
 
67513
68479
  /***/ },
67514
68480
 
@@ -67516,7 +68482,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"mcp.settings.title":"MCP Server Sett
67516
68482
  (module) {
67517
68483
 
67518
68484
  "use strict";
67519
- module.exports = /*#__PURE__*/JSON.parse('{"mcp.settings.title":"MCP 服务器设置","mcp.settings.version":"v{version}","mcp.server.status":"服务器状态","mcp.server.running":"运行中","mcp.server.stopped":"已停止","mcp.server.connections":"{count} 个连接","mcp.server.start":"启动服务器","mcp.server.stop":"停止服务器","mcp.server.restart":"重启","mcp.config.port":"端口","mcp.config.port.desc":"MCP 服务器端口(默认:3001)","mcp.config.startOnBoot":"Tabby 启动时自动启动服务器","mcp.logging.title":"日志","mcp.logging.enable":"启用日志","mcp.logging.level":"日志级别","mcp.logging.level.debug":"调试","mcp.logging.level.info":"信息","mcp.logging.level.warn":"警告","mcp.logging.level.error":"错误","mcp.logging.viewLogs":"查看日志","mcp.logging.exportJson":"导出 JSON","mcp.logging.clearLogs":"清空日志","mcp.pairProgramming.title":"结对编程模式","mcp.pairProgramming.enable":"启用结对编程模式","mcp.pairProgramming.enable.desc":"启用后,AI 命令执行前需要确认","mcp.pairProgramming.showDialog":"显示确认对话框","mcp.pairProgramming.autoFocus":"执行命令时自动聚焦终端","mcp.sessionTracking.title":"会话跟踪","mcp.sessionTracking.desc":"配置会话和标签页的识别方式","mcp.sessionTracking.stableIds":"使用稳定的 UUID 识别会话","mcp.sessionTracking.stableIds.desc":"会话获得持久 ID,标签页重新排序时不会改变","mcp.sessionTracking.profileInfo":"在会话列表中包含配置文件信息","mcp.sessionTracking.pid":"在会话信息中包含进程 ID","mcp.sessionTracking.cwd":"在会话信息中包含当前工作目录","mcp.backgroundExecution.title":"后台执行","mcp.backgroundExecution.desc":"控制 MCP 操作是否在后台运行而不切换焦点","mcp.backgroundExecution.enable":"启用后台执行模式","mcp.backgroundExecution.enable.desc":"启用后,AI 命令执行时不会切换到目标终端。你可以继续在其他标签页工作,同时 AI 在后台执行命令。","mcp.backgroundExecution.warning.title":"后台执行风险:","mcp.backgroundExecution.warning.visibility":"可见性受限:你无法实时看到命令执行过程","mcp.backgroundExecution.warning.conflicts":"输入冲突:如果你在目标终端输入时 AI 也在执行命令,输入会混乱导致错误","mcp.backgroundExecution.warning.splitPanes":"分割窗格:命令发送到 sessionId 指定的窗格,而非聚焦的窗格","mcp.backgroundExecution.warning.dangerous":"危险命令:AI 可能在你不注意时执行破坏性命令(rm -rf 等)","mcp.backgroundExecution.safety.title":"建议的安全措施:","mcp.backgroundExecution.safety.pairProgramming":"保持「结对编程模式」开启并启用确认对话框","mcp.backgroundExecution.safety.sessionId":"使用 sessionId 指定目标终端,避免跨终端误操作","mcp.backgroundExecution.safety.monitor":"定期通过 get_terminal_buffer 监控终端缓冲区","mcp.sftp.title":"SFTP 设置","mcp.sftp.desc":"SFTP 文件传输支持(需要 tabby-ssh 插件)","mcp.sftp.enable":"启用 SFTP 工具","mcp.sftp.enable.desc":"如果未安装 tabby-ssh,SFTP 工具将自动禁用","mcp.sftp.maxReadSize":"最大读取大小","mcp.sftp.maxReadSize.desc":"sftp_read_file 的最大文件大小(默认:1 MB)","mcp.sftp.maxUploadSize":"最大上传大小","mcp.sftp.maxUploadSize.desc":"sftp_upload 的最大文件大小(默认:10 GB)","mcp.sftp.maxDownloadSize":"最大下载大小","mcp.sftp.maxDownloadSize.desc":"sftp_download 的最大文件大小(默认:10 GB)","mcp.sftp.timeout":"超时时间(秒)","mcp.sftp.timeout.desc":"SFTP 操作超时(默认:60 秒)","mcp.sftp.notes.title":"SFTP 说明:","mcp.sftp.notes.binary":"文件传输为直接二进制(无 base64 编码)","mcp.sftp.notes.memory":"大文件传输时可能消耗大量内存","mcp.sftp.notes.overwrite":"sftp_write_file 可能在无确认的情况下覆盖文件","mcp.sftp.notes.limit":"如果文件超过大小限制,MCP 将返回错误(无弹窗)","mcp.experimental.title":"实验性功能","mcp.experimental.streamCapture.label":"使用流式捕获 (Beta)","mcp.experimental.streamCapture.desc":"通过直接捕获数据流解决长命令输出截断问题(绕过屏幕缓冲区)。默认为关闭(传统模式)。","mcp.experimental.streamCapture.note":"此模式绕过终端屏幕缓冲区限制。建议用于执行产生大量输出的命令(例如 cat 大文件)。","mcp.timing.title":"时间设置","mcp.timing.desc":"命令执行和会话检测的高级时间配置","mcp.timing.pollInterval":"轮询间隔(毫秒)","mcp.timing.pollInterval.desc":"检查命令输出的频率(默认:100)","mcp.timing.initialDelay":"初始延迟(毫秒)","mcp.timing.initialDelay.desc":"开始轮询前的延迟(默认:0)","mcp.timing.sessionStableChecks":"会话稳定检查次数","mcp.timing.sessionStableChecks.desc":"会话就绪检测的稳定检查次数(默认:5)","mcp.timing.sessionPollInterval":"会话轮询间隔(毫秒)","mcp.timing.sessionPollInterval.desc":"会话就绪轮询的间隔(默认:200)","mcp.connectionInfo.title":"连接信息","mcp.connectionInfo.streamable":"Streamable HTTP(推荐):","mcp.connectionInfo.legacySse":"Legacy SSE:","mcp.connectionInfo.healthCheck":"健康检查:","mcp.connectionInfo.addToClient":"添加到你的 MCP 客户端(如 Cursor、VS Code):","mcp.connectionInfo.copyConfig":"复制配置","mcp.common.saved":"✓ 设置已保存","mcp.common.mb":"MB","mcp.common.sec":"秒"}');
68485
+ module.exports = /*#__PURE__*/JSON.parse('{"mcp.settings.title":"MCP 服务器设置","mcp.settings.version":"v{version}","mcp.server.status":"服务器状态","mcp.server.running":"运行中","mcp.server.stopped":"已停止","mcp.server.connections":"{count} 个连接","mcp.server.start":"启动服务器","mcp.server.stop":"停止服务器","mcp.server.restart":"重启","mcp.config.port":"端口","mcp.config.port.desc":"MCP 服务器端口(默认:3001)","mcp.config.startOnBoot":"Tabby 启动时自动启动服务器","mcp.logging.title":"日志","mcp.logging.enable":"启用日志","mcp.logging.level":"日志级别","mcp.logging.level.debug":"调试","mcp.logging.level.info":"信息","mcp.logging.level.warn":"警告","mcp.logging.level.error":"错误","mcp.logging.viewLogs":"查看日志","mcp.logging.exportJson":"导出 JSON","mcp.logging.clearLogs":"清空日志","mcp.pairProgramming.title":"结对编程模式","mcp.pairProgramming.enable":"启用结对编程模式","mcp.pairProgramming.enable.desc":"启用后,AI 命令执行前需要确认","mcp.pairProgramming.showDialog":"显示确认对话框","mcp.pairProgramming.autoFocus":"执行命令时自动聚焦终端","mcp.sessionTracking.title":"会话跟踪","mcp.sessionTracking.desc":"配置会话和标签页的识别方式","mcp.sessionTracking.stableIds":"使用稳定的 UUID 识别会话","mcp.sessionTracking.stableIds.desc":"会话获得持久 ID,标签页重新排序时不会改变","mcp.sessionTracking.profileInfo":"在会话列表中包含配置文件信息","mcp.sessionTracking.pid":"在会话信息中包含进程 ID","mcp.sessionTracking.cwd":"在会话信息中包含当前工作目录","mcp.backgroundExecution.title":"后台执行","mcp.backgroundExecution.desc":"控制 MCP 操作是否在后台运行而不切换焦点","mcp.backgroundExecution.enable":"启用后台执行模式","mcp.backgroundExecution.enable.desc":"启用后,AI 命令执行时不会切换到目标终端。你可以继续在其他标签页工作,同时 AI 在后台执行命令。","mcp.backgroundExecution.warning.title":"后台执行风险:","mcp.backgroundExecution.warning.visibility":"可见性受限:你无法实时看到命令执行过程","mcp.backgroundExecution.warning.conflicts":"输入冲突:如果你在目标终端输入时 AI 也在执行命令,输入会混乱导致错误","mcp.backgroundExecution.warning.splitPanes":"分割窗格:命令发送到 sessionId 指定的窗格,而非聚焦的窗格","mcp.backgroundExecution.warning.dangerous":"危险命令:AI 可能在你不注意时执行破坏性命令(rm -rf 等)","mcp.backgroundExecution.safety.title":"建议的安全措施:","mcp.backgroundExecution.safety.pairProgramming":"保持「结对编程模式」开启并启用确认对话框","mcp.backgroundExecution.safety.sessionId":"使用 sessionId 指定目标终端,避免跨终端误操作","mcp.backgroundExecution.safety.monitor":"定期通过 get_terminal_buffer 监控终端缓冲区","mcp.sftp.title":"SFTP 设置","mcp.sftp.desc":"SFTP 文件传输支持(需要 tabby-ssh 插件)","mcp.sftp.enable":"启用 SFTP 工具","mcp.sftp.enable.desc":"如果未安装 tabby-ssh,SFTP 工具将自动禁用","mcp.sftp.maxReadSize":"最大读取大小","mcp.sftp.maxReadSize.desc":"sftp_read_file 的最大文件大小(默认:1 MB)","mcp.sftp.maxUploadSize":"最大上传大小","mcp.sftp.maxUploadSize.desc":"sftp_upload 的最大文件大小(默认:10 GB)","mcp.sftp.maxDownloadSize":"最大下载大小","mcp.sftp.maxDownloadSize.desc":"sftp_download 的最大文件大小(默认:10 GB)","mcp.sftp.timeout":"超时时间(秒)","mcp.sftp.timeout.desc":"SFTP 操作超时(默认:60 秒)","mcp.sftp.notes.title":"SFTP 说明:","mcp.sftp.notes.binary":"文件传输为直接二进制(无 base64 编码)","mcp.sftp.notes.memory":"大文件传输时可能消耗大量内存","mcp.sftp.notes.overwrite":"sftp_write_file 可能在无确认的情况下覆盖文件","mcp.sftp.notes.limit":"如果文件超过大小限制,MCP 将返回错误(无弹窗)","mcp.environmentDetection.title":"环境探测","mcp.environmentDetection.desc":"在发送命令前,基于启发式方法推断当前终端上下文(Shell、Python、数据库 REPL 等)。","mcp.environmentDetection.enable":"启用环境探测","mcp.environmentDetection.enable.desc":"向智能体和脚本暴露 get_session_environment。默认关闭,以保证安全和可预测性。","mcp.environmentDetection.enhanced":"使用增强启发式探测","mcp.environmentDetection.enhanced.desc":"扫描最近的提示符行,并规范化 ANSI/控制序列,以提高提示符识别准确率。","mcp.environmentDetection.mode":"探测模式","mcp.environmentDetection.mode.heuristic":"启发式(被动)","mcp.environmentDetection.mode.active":"主动探测(更强)","mcp.environmentDetection.mode.desc":"主动模式会在 shell 会话中增加低风险探针以提高准确率,但仍可能受到交互状态或 shell 策略影响。","mcp.environmentDetection.warning.title":"环境探测限制:","mcp.environmentDetection.warning.heuristic":"该功能基于启发式判断;对于自定义 prompt 或不常见的交互工具,可能不准确。","mcp.environmentDetection.warning.transient":"SSH 登录提示或临时状态行可能出现在真正 prompt 之前,影响判断结果。","mcp.environmentDetection.warning.customPrompt":"数据库或 REPL 的识别依赖可辨认的提示符;高度自定义的 prompt 会降低准确率。","mcp.environmentDetection.warning.verify":"对于关键操作,请先结合 get_terminal_buffer 或手动命令确认,再执行可能有破坏性的动作。","mcp.environmentDetection.restart.confirm":"环境探测工具的可见性已改变。是否现在重启 MCP 服务器,以刷新当前客户端看到的工具列表?现有 MCP 连接可能需要重新连接。","mcp.environmentDetection.restart.done":"✓ 设置已保存,并已重启 MCP 服务器","mcp.environmentDetection.restart.later":"✓ 设置已保存。现有 MCP 客户端可能需要重新连接后才能看到更新后的工具列表。","mcp.experimental.title":"实验性功能","mcp.experimental.streamCapture.label":"使用流式捕获 (Beta)","mcp.experimental.streamCapture.desc":"通过直接捕获数据流解决长命令输出截断问题(绕过屏幕缓冲区)。默认为关闭(传统模式)。","mcp.experimental.streamCapture.note":"此模式绕过终端屏幕缓冲区限制。建议用于执行产生大量输出的命令(例如 cat 大文件)。","mcp.timing.title":"时间设置","mcp.timing.desc":"命令执行和会话检测的高级时间配置","mcp.timing.pollInterval":"轮询间隔(毫秒)","mcp.timing.pollInterval.desc":"检查命令输出的频率(默认:100)","mcp.timing.initialDelay":"初始延迟(毫秒)","mcp.timing.initialDelay.desc":"开始轮询前的延迟(默认:0)","mcp.timing.sessionStableChecks":"会话稳定检查次数","mcp.timing.sessionStableChecks.desc":"会话就绪检测的稳定检查次数(默认:5)","mcp.timing.sessionPollInterval":"会话轮询间隔(毫秒)","mcp.timing.sessionPollInterval.desc":"会话就绪轮询的间隔(默认:200)","mcp.connectionInfo.title":"连接信息","mcp.connectionInfo.streamable":"Streamable HTTP(推荐):","mcp.connectionInfo.legacySse":"Legacy SSE:","mcp.connectionInfo.healthCheck":"健康检查:","mcp.connectionInfo.addToClient":"添加到你的 MCP 客户端(如 Cursor、VS Code):","mcp.connectionInfo.copyConfig":"复制配置","mcp.common.saved":"✓ 设置已保存","mcp.common.mb":"MB","mcp.common.sec":"秒"}');
67520
68486
 
67521
68487
  /***/ }
67522
68488