@chrischall/tripadvisor-mcp 0.3.5 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +640 -187
- package/dist/tools/location.js +27 -14
- package/dist/tools/search.js +12 -17
- package/dist/tools/web.js +10 -2
- package/dist/version.js +1 -1
- package/dist/view.js +45 -0
- package/package.json +3 -3
- package/server.json +2 -2
package/dist/bundle.js
CHANGED
|
@@ -3116,9 +3116,28 @@ var require_utils = __commonJS({
|
|
|
3116
3116
|
"use strict";
|
|
3117
3117
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
3118
3118
|
var 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);
|
|
3119
|
+
var isPort = RegExp.prototype.test.bind(/^\d*$/u);
|
|
3119
3120
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3120
3121
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3121
|
-
var isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
3122
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
3123
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
3124
|
+
var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
3125
|
+
var BYTE_HEX = new Array(256);
|
|
3126
|
+
{
|
|
3127
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
3128
|
+
for (let i = 0; i < 256; i++) {
|
|
3129
|
+
BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
function percentEncodeNonAscii(cp) {
|
|
3133
|
+
if (cp < 2048) {
|
|
3134
|
+
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
3135
|
+
}
|
|
3136
|
+
if (cp < 65536) {
|
|
3137
|
+
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3138
|
+
}
|
|
3139
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3140
|
+
}
|
|
3122
3141
|
function stringArrayToHexStripped(input) {
|
|
3123
3142
|
let acc = "";
|
|
3124
3143
|
let code = 0;
|
|
@@ -3143,91 +3162,105 @@ var require_utils = __commonJS({
|
|
|
3143
3162
|
}
|
|
3144
3163
|
return acc;
|
|
3145
3164
|
}
|
|
3165
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
3166
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
3167
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
3146
3168
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3147
|
-
function
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
if (hex3 !== "") {
|
|
3155
|
-
address.push(hex3);
|
|
3156
|
-
} else {
|
|
3157
|
-
output.error = true;
|
|
3158
|
-
return false;
|
|
3169
|
+
function isZoneIdentifier(zone) {
|
|
3170
|
+
if (zone.length === 0) return false;
|
|
3171
|
+
for (let i = 0; i < zone.length; i++) {
|
|
3172
|
+
if (isZoneCharacter(zone[i])) continue;
|
|
3173
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
3174
|
+
i += 2;
|
|
3175
|
+
continue;
|
|
3159
3176
|
}
|
|
3160
|
-
|
|
3177
|
+
return false;
|
|
3161
3178
|
}
|
|
3162
3179
|
return true;
|
|
3163
3180
|
}
|
|
3164
|
-
function
|
|
3165
|
-
let
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
let
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
}
|
|
3177
|
-
if (cursor === ":") {
|
|
3178
|
-
if (endipv6Encountered === true) {
|
|
3179
|
-
endIpv6 = true;
|
|
3180
|
-
}
|
|
3181
|
-
if (!consume(buffer, address, output)) {
|
|
3182
|
-
break;
|
|
3183
|
-
}
|
|
3184
|
-
if (++tokenCount > 7) {
|
|
3185
|
-
output.error = true;
|
|
3186
|
-
break;
|
|
3181
|
+
function compressIPv6ZeroRun(hextets) {
|
|
3182
|
+
let bestStart = -1;
|
|
3183
|
+
let bestLength = 0;
|
|
3184
|
+
let runStart = -1;
|
|
3185
|
+
let runLength = 0;
|
|
3186
|
+
for (let i = 0; i < hextets.length; i++) {
|
|
3187
|
+
if (hextets[i] === "0") {
|
|
3188
|
+
if (runStart === -1) runStart = i;
|
|
3189
|
+
runLength++;
|
|
3190
|
+
if (runLength > bestLength) {
|
|
3191
|
+
bestLength = runLength;
|
|
3192
|
+
bestStart = runStart;
|
|
3187
3193
|
}
|
|
3188
|
-
if (i > 0 && input[i - 1] === ":") {
|
|
3189
|
-
endipv6Encountered = true;
|
|
3190
|
-
}
|
|
3191
|
-
address.push(":");
|
|
3192
|
-
continue;
|
|
3193
|
-
} else if (cursor === "%") {
|
|
3194
|
-
if (!consume(buffer, address, output)) {
|
|
3195
|
-
break;
|
|
3196
|
-
}
|
|
3197
|
-
consume = consumeIsZone;
|
|
3198
3194
|
} else {
|
|
3199
|
-
|
|
3195
|
+
runStart = -1;
|
|
3196
|
+
runLength = 0;
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
if (bestLength < 2) return hextets.join(":");
|
|
3200
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
3201
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
3202
|
+
return head + "::" + tail;
|
|
3203
|
+
}
|
|
3204
|
+
function normalizeIPv6Address(input) {
|
|
3205
|
+
const compression = input.indexOf("::");
|
|
3206
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
|
|
3207
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
3208
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
3209
|
+
if (compression !== -1) {
|
|
3210
|
+
if (left.length === 1 && left[0] === "") left.length = 0;
|
|
3211
|
+
if (right.length === 1 && right[0] === "") right.length = 0;
|
|
3212
|
+
}
|
|
3213
|
+
const parts = left.concat(right);
|
|
3214
|
+
let hextetCount = 0;
|
|
3215
|
+
for (let i = 0; i < parts.length; i++) {
|
|
3216
|
+
const part = parts[i];
|
|
3217
|
+
if (part === "") return void 0;
|
|
3218
|
+
if (part.indexOf(".") !== -1) {
|
|
3219
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
|
|
3220
|
+
hextetCount += 2;
|
|
3200
3221
|
continue;
|
|
3201
3222
|
}
|
|
3223
|
+
if (!isHextet(part)) return void 0;
|
|
3224
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
3225
|
+
hextetCount++;
|
|
3202
3226
|
}
|
|
3203
|
-
if (
|
|
3204
|
-
if (
|
|
3205
|
-
|
|
3206
|
-
} else if (endIpv6) {
|
|
3207
|
-
address.push(buffer.join(""));
|
|
3208
|
-
} else {
|
|
3209
|
-
address.push(stringArrayToHexStripped(buffer));
|
|
3210
|
-
}
|
|
3227
|
+
if (compression === -1) {
|
|
3228
|
+
if (hextetCount !== 8) return void 0;
|
|
3229
|
+
return compressIPv6ZeroRun(parts);
|
|
3211
3230
|
}
|
|
3212
|
-
|
|
3213
|
-
|
|
3231
|
+
if (hextetCount >= 8) return void 0;
|
|
3232
|
+
const expanded = parts.slice(0, left.length);
|
|
3233
|
+
for (let i = hextetCount; i < 8; i++) expanded.push("0");
|
|
3234
|
+
for (let i = left.length; i < parts.length; i++) expanded.push(parts[i]);
|
|
3235
|
+
return compressIPv6ZeroRun(expanded);
|
|
3214
3236
|
}
|
|
3215
3237
|
function normalizeIPv6(host) {
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
}
|
|
3219
|
-
|
|
3220
|
-
if (
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3238
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
3239
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
3240
|
+
if (hasBracket && !bracketed) return { host, isIPV6: false, error: true };
|
|
3241
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
3242
|
+
if (bracketed && isIPvFuture(input)) {
|
|
3243
|
+
input = input.toLowerCase();
|
|
3244
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
3245
|
+
}
|
|
3246
|
+
if (findToken(input, ":") < 2) {
|
|
3247
|
+
return { host, isIPV6: false, error: bracketed };
|
|
3248
|
+
}
|
|
3249
|
+
let zoneIdentifier = "";
|
|
3250
|
+
const zoneSeparator = input.indexOf("%");
|
|
3251
|
+
if (zoneSeparator !== -1) {
|
|
3252
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
3253
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
3254
|
+
if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true };
|
|
3255
|
+
input = input.slice(0, zoneSeparator);
|
|
3256
|
+
}
|
|
3257
|
+
const address = normalizeIPv6Address(input);
|
|
3258
|
+
if (address === void 0) return { host, isIPV6: false, error: true };
|
|
3259
|
+
return {
|
|
3260
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
3261
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
3262
|
+
isIPV6: true
|
|
3263
|
+
};
|
|
3231
3264
|
}
|
|
3232
3265
|
function findToken(str2, token) {
|
|
3233
3266
|
let ind = 0;
|
|
@@ -3314,8 +3347,8 @@ var require_utils = __commonJS({
|
|
|
3314
3347
|
var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
|
|
3315
3348
|
var HOST_DELIM_RE = /[@/?#:]/g;
|
|
3316
3349
|
var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
|
|
3317
|
-
function reescapeHostDelimiters(host,
|
|
3318
|
-
const re =
|
|
3350
|
+
function reescapeHostDelimiters(host, isIP2) {
|
|
3351
|
+
const re = isIP2 ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
|
|
3319
3352
|
re.lastIndex = 0;
|
|
3320
3353
|
return host.replace(re, (ch) => HOST_DELIMS[ch]);
|
|
3321
3354
|
}
|
|
@@ -3346,7 +3379,8 @@ var require_utils = __commonJS({
|
|
|
3346
3379
|
function normalizePathEncoding(input) {
|
|
3347
3380
|
let output = "";
|
|
3348
3381
|
for (let i = 0; i < input.length; i++) {
|
|
3349
|
-
|
|
3382
|
+
const ch = input[i];
|
|
3383
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3350
3384
|
const hex3 = input.slice(i + 1, i + 3);
|
|
3351
3385
|
if (isHexPair(hex3)) {
|
|
3352
3386
|
const normalizedHex = hex3.toUpperCase();
|
|
@@ -3360,10 +3394,152 @@ var require_utils = __commonJS({
|
|
|
3360
3394
|
continue;
|
|
3361
3395
|
}
|
|
3362
3396
|
}
|
|
3363
|
-
if (isPathCharacter(
|
|
3364
|
-
output +=
|
|
3397
|
+
if (isPathCharacter(ch)) {
|
|
3398
|
+
output += ch;
|
|
3399
|
+
} else {
|
|
3400
|
+
const code = input.charCodeAt(i);
|
|
3401
|
+
if (code < 128) {
|
|
3402
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3403
|
+
} else if (code < 55296 || code > 57343) {
|
|
3404
|
+
output += percentEncodeNonAscii(code);
|
|
3405
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3406
|
+
const low = input.charCodeAt(i + 1);
|
|
3407
|
+
if (low >= 56320 && low <= 57343) {
|
|
3408
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3409
|
+
i++;
|
|
3410
|
+
} else {
|
|
3411
|
+
output += percentEncodeNonAscii(65533);
|
|
3412
|
+
}
|
|
3413
|
+
} else {
|
|
3414
|
+
output += percentEncodeNonAscii(65533);
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3418
|
+
return output;
|
|
3419
|
+
}
|
|
3420
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
3421
|
+
let output = "";
|
|
3422
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
3423
|
+
for (let i = 0; i < input.length; i++) {
|
|
3424
|
+
const ch = input[i];
|
|
3425
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3426
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3427
|
+
if (isHexPair(hex3)) {
|
|
3428
|
+
output += "%" + hex3.toUpperCase();
|
|
3429
|
+
i += 2;
|
|
3430
|
+
continue;
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
if (ch === "/") {
|
|
3434
|
+
firstSegment = false;
|
|
3435
|
+
}
|
|
3436
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
|
|
3437
|
+
output += ch;
|
|
3438
|
+
} else {
|
|
3439
|
+
const code = input.charCodeAt(i);
|
|
3440
|
+
if (code < 128) {
|
|
3441
|
+
output += BYTE_HEX[code];
|
|
3442
|
+
} else if (code < 55296 || code > 57343) {
|
|
3443
|
+
output += percentEncodeNonAscii(code);
|
|
3444
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3445
|
+
const low = input.charCodeAt(i + 1);
|
|
3446
|
+
if (low >= 56320 && low <= 57343) {
|
|
3447
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3448
|
+
i++;
|
|
3449
|
+
} else {
|
|
3450
|
+
output += percentEncodeNonAscii(65533);
|
|
3451
|
+
}
|
|
3452
|
+
} else {
|
|
3453
|
+
output += percentEncodeNonAscii(65533);
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
return output;
|
|
3458
|
+
}
|
|
3459
|
+
function encodeComponent(input, isAllowed) {
|
|
3460
|
+
let output = "";
|
|
3461
|
+
for (let i = 0; i < input.length; i++) {
|
|
3462
|
+
const ch = input[i];
|
|
3463
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3464
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3465
|
+
if (isHexPair(hex3)) {
|
|
3466
|
+
output += "%" + hex3.toUpperCase();
|
|
3467
|
+
i += 2;
|
|
3468
|
+
continue;
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
if (isAllowed(ch)) {
|
|
3472
|
+
output += ch;
|
|
3473
|
+
} else {
|
|
3474
|
+
const code = input.charCodeAt(i);
|
|
3475
|
+
if (code < 128) {
|
|
3476
|
+
output += BYTE_HEX[code];
|
|
3477
|
+
} else if (code < 55296 || code > 57343) {
|
|
3478
|
+
output += percentEncodeNonAscii(code);
|
|
3479
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3480
|
+
const low = input.charCodeAt(i + 1);
|
|
3481
|
+
if (low >= 56320 && low <= 57343) {
|
|
3482
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3483
|
+
i++;
|
|
3484
|
+
} else {
|
|
3485
|
+
output += percentEncodeNonAscii(65533);
|
|
3486
|
+
}
|
|
3487
|
+
} else {
|
|
3488
|
+
output += percentEncodeNonAscii(65533);
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
return output;
|
|
3493
|
+
}
|
|
3494
|
+
function encodeUserinfo(input) {
|
|
3495
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
3496
|
+
}
|
|
3497
|
+
function encodeQuery(input) {
|
|
3498
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3499
|
+
}
|
|
3500
|
+
function encodeFragment(input) {
|
|
3501
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3502
|
+
}
|
|
3503
|
+
function isEscapeSafe(cp) {
|
|
3504
|
+
return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
|
|
3505
|
+
}
|
|
3506
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
3507
|
+
let output = "";
|
|
3508
|
+
for (let i = 0; i < input.length; i++) {
|
|
3509
|
+
const ch = input[i];
|
|
3510
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3511
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3512
|
+
if (isHexPair(hex3)) {
|
|
3513
|
+
const normalizedHex = hex3.toUpperCase();
|
|
3514
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3515
|
+
if (isUnreserved(decoded)) {
|
|
3516
|
+
output += decoded;
|
|
3517
|
+
} else {
|
|
3518
|
+
output += "%" + normalizedHex;
|
|
3519
|
+
}
|
|
3520
|
+
i += 2;
|
|
3521
|
+
continue;
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
3525
|
+
output += ch;
|
|
3365
3526
|
} else {
|
|
3366
|
-
|
|
3527
|
+
const code = input.charCodeAt(i);
|
|
3528
|
+
if (code < 128) {
|
|
3529
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3530
|
+
} else if (code < 55296 || code > 57343) {
|
|
3531
|
+
output += percentEncodeNonAscii(code);
|
|
3532
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3533
|
+
const low = input.charCodeAt(i + 1);
|
|
3534
|
+
if (low >= 56320 && low <= 57343) {
|
|
3535
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3536
|
+
i++;
|
|
3537
|
+
} else {
|
|
3538
|
+
output += percentEncodeNonAscii(65533);
|
|
3539
|
+
}
|
|
3540
|
+
} else {
|
|
3541
|
+
output += percentEncodeNonAscii(65533);
|
|
3542
|
+
}
|
|
3367
3543
|
}
|
|
3368
3544
|
}
|
|
3369
3545
|
return output;
|
|
@@ -3386,14 +3562,18 @@ var require_utils = __commonJS({
|
|
|
3386
3562
|
function recomposeAuthority(component) {
|
|
3387
3563
|
const uriTokens = [];
|
|
3388
3564
|
if (component.userinfo !== void 0) {
|
|
3389
|
-
uriTokens.push(component.userinfo);
|
|
3565
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
3390
3566
|
uriTokens.push("@");
|
|
3391
3567
|
}
|
|
3392
3568
|
if (component.host !== void 0) {
|
|
3393
|
-
let host =
|
|
3569
|
+
let host = component.host;
|
|
3394
3570
|
if (!isIPv4(host)) {
|
|
3395
|
-
|
|
3396
|
-
if (ipV6res.isIPV6
|
|
3571
|
+
let ipV6res = normalizeIPv6(host);
|
|
3572
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
3573
|
+
host = normalizePercentEncoding(host, true);
|
|
3574
|
+
ipV6res = normalizeIPv6(host);
|
|
3575
|
+
}
|
|
3576
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
3397
3577
|
host = `[${ipV6res.escapedHost}]`;
|
|
3398
3578
|
} else {
|
|
3399
3579
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -3402,8 +3582,12 @@ var require_utils = __commonJS({
|
|
|
3402
3582
|
uriTokens.push(host);
|
|
3403
3583
|
}
|
|
3404
3584
|
if (typeof component.port === "number" || typeof component.port === "string") {
|
|
3585
|
+
const port = String(component.port);
|
|
3586
|
+
if (!isPort(port)) {
|
|
3587
|
+
throw new TypeError("URI port is malformed.");
|
|
3588
|
+
}
|
|
3405
3589
|
uriTokens.push(":");
|
|
3406
|
-
uriTokens.push(
|
|
3590
|
+
uriTokens.push(port);
|
|
3407
3591
|
}
|
|
3408
3592
|
return uriTokens.length ? uriTokens.join("") : void 0;
|
|
3409
3593
|
}
|
|
@@ -3413,6 +3597,11 @@ var require_utils = __commonJS({
|
|
|
3413
3597
|
reescapeHostDelimiters,
|
|
3414
3598
|
normalizePercentEncoding,
|
|
3415
3599
|
normalizePathEncoding,
|
|
3600
|
+
serializePathEncoding,
|
|
3601
|
+
normalizeQueryFragmentEncoding,
|
|
3602
|
+
encodeUserinfo,
|
|
3603
|
+
encodeQuery,
|
|
3604
|
+
encodeFragment,
|
|
3416
3605
|
escapePreservingEscapes,
|
|
3417
3606
|
removeDotSegments,
|
|
3418
3607
|
isIPv4,
|
|
@@ -3428,7 +3617,7 @@ var require_schemes = __commonJS({
|
|
|
3428
3617
|
"node_modules/fast-uri/lib/schemes.js"(exports, module) {
|
|
3429
3618
|
"use strict";
|
|
3430
3619
|
var { isUUID } = require_utils();
|
|
3431
|
-
var URN_REG =
|
|
3620
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
3432
3621
|
var supportedSchemeNames = (
|
|
3433
3622
|
/** @type {const} */
|
|
3434
3623
|
[
|
|
@@ -3489,9 +3678,10 @@ var require_schemes = __commonJS({
|
|
|
3489
3678
|
wsComponent.secure = void 0;
|
|
3490
3679
|
}
|
|
3491
3680
|
if (wsComponent.resourceName) {
|
|
3492
|
-
const
|
|
3681
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3682
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3493
3683
|
wsComponent.path = path && path !== "/" ? path : void 0;
|
|
3494
|
-
wsComponent.query =
|
|
3684
|
+
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3495
3685
|
wsComponent.resourceName = void 0;
|
|
3496
3686
|
}
|
|
3497
3687
|
wsComponent.fragment = void 0;
|
|
@@ -3503,7 +3693,7 @@ var require_schemes = __commonJS({
|
|
|
3503
3693
|
return urnComponent;
|
|
3504
3694
|
}
|
|
3505
3695
|
const matches = urnComponent.path.match(URN_REG);
|
|
3506
|
-
if (matches) {
|
|
3696
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
3507
3697
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
3508
3698
|
urnComponent.nid = matches[1].toLowerCase();
|
|
3509
3699
|
urnComponent.nss = matches[2];
|
|
@@ -3637,8 +3827,17 @@ var require_schemes = __commonJS({
|
|
|
3637
3827
|
var require_fast_uri = __commonJS({
|
|
3638
3828
|
"node_modules/fast-uri/index.js"(exports, module) {
|
|
3639
3829
|
"use strict";
|
|
3640
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3830
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3641
3831
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3832
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
3833
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
3834
|
+
function decodeValidScheme(scheme) {
|
|
3835
|
+
const decodedScheme = unescape(String(scheme));
|
|
3836
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
3837
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
3838
|
+
}
|
|
3839
|
+
return decodedScheme;
|
|
3840
|
+
}
|
|
3642
3841
|
function normalize(uri, options) {
|
|
3643
3842
|
if (typeof uri === "string") {
|
|
3644
3843
|
uri = /** @type {T} */
|
|
@@ -3651,12 +3850,34 @@ var require_fast_uri = __commonJS({
|
|
|
3651
3850
|
}
|
|
3652
3851
|
function resolve(baseURI, relativeURI, options) {
|
|
3653
3852
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3654
|
-
const {
|
|
3655
|
-
|
|
3656
|
-
|
|
3853
|
+
const {
|
|
3854
|
+
parsed: baseParsed,
|
|
3855
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
3856
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
3857
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
3858
|
+
malformedHost: baseMalformedHost,
|
|
3859
|
+
malformedScheme: baseMalformedScheme
|
|
3860
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
3861
|
+
const {
|
|
3862
|
+
parsed: relativeParsed,
|
|
3863
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
3864
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
3865
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
3866
|
+
malformedHost: relativeMalformedHost,
|
|
3867
|
+
malformedScheme: relativeMalformedScheme
|
|
3868
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
3869
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
3657
3870
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3658
3871
|
}
|
|
3659
3872
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3873
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
3874
|
+
const resolvedHost = resolved.host;
|
|
3875
|
+
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
3876
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
3877
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
|
|
3878
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
3879
|
+
throw new Error(resolved.error);
|
|
3880
|
+
}
|
|
3660
3881
|
schemelessOptions.skipEscape = true;
|
|
3661
3882
|
return serialize(resolved, schemelessOptions);
|
|
3662
3883
|
}
|
|
@@ -3716,7 +3937,7 @@ var require_fast_uri = __commonJS({
|
|
|
3716
3937
|
function equal(uriA, uriB, options) {
|
|
3717
3938
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3718
3939
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3719
|
-
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA
|
|
3940
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
3720
3941
|
}
|
|
3721
3942
|
function serialize(cmpts, opts) {
|
|
3722
3943
|
const component = {
|
|
@@ -3737,19 +3958,22 @@ var require_fast_uri = __commonJS({
|
|
|
3737
3958
|
};
|
|
3738
3959
|
const options = Object.assign({}, opts);
|
|
3739
3960
|
const uriTokens = [];
|
|
3961
|
+
if (component.scheme) {
|
|
3962
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3963
|
+
}
|
|
3740
3964
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3741
3965
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
3966
|
+
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
3967
|
+
const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
|
|
3742
3968
|
if (component.path !== void 0) {
|
|
3743
3969
|
if (!options.skipEscape) {
|
|
3744
|
-
component.path =
|
|
3745
|
-
if (component.scheme !== void 0) {
|
|
3746
|
-
component.path = component.path.split("%3A").join(":");
|
|
3747
|
-
}
|
|
3970
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
3748
3971
|
} else {
|
|
3749
3972
|
component.path = normalizePercentEncoding(component.path);
|
|
3750
3973
|
}
|
|
3751
3974
|
}
|
|
3752
3975
|
if (options.reference !== "suffix" && component.scheme) {
|
|
3976
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3753
3977
|
uriTokens.push(component.scheme, ":");
|
|
3754
3978
|
}
|
|
3755
3979
|
const authority = recomposeAuthority(component);
|
|
@@ -3767,16 +3991,19 @@ var require_fast_uri = __commonJS({
|
|
|
3767
3991
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3768
3992
|
s = removeDotSegments(s);
|
|
3769
3993
|
}
|
|
3994
|
+
if (pathNoScheme) {
|
|
3995
|
+
s = serializePathEncoding(s, true);
|
|
3996
|
+
}
|
|
3770
3997
|
if (authority === void 0 && s[0] === "/" && s[1] === "/") {
|
|
3771
3998
|
s = "/%2F" + s.slice(2);
|
|
3772
3999
|
}
|
|
3773
4000
|
uriTokens.push(s);
|
|
3774
4001
|
}
|
|
3775
4002
|
if (component.query !== void 0) {
|
|
3776
|
-
uriTokens.push("?", component.query);
|
|
4003
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
3777
4004
|
}
|
|
3778
4005
|
if (component.fragment !== void 0) {
|
|
3779
|
-
uriTokens.push("#", component.fragment);
|
|
4006
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
3780
4007
|
}
|
|
3781
4008
|
return uriTokens.join("");
|
|
3782
4009
|
}
|
|
@@ -3792,6 +4019,35 @@ var require_fast_uri = __commonJS({
|
|
|
3792
4019
|
}
|
|
3793
4020
|
return void 0;
|
|
3794
4021
|
}
|
|
4022
|
+
function hasMalformedPercentEncoding(component) {
|
|
4023
|
+
if (component === void 0) return false;
|
|
4024
|
+
let percent = component.indexOf("%");
|
|
4025
|
+
while (percent !== -1) {
|
|
4026
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
4027
|
+
return true;
|
|
4028
|
+
}
|
|
4029
|
+
percent = component.indexOf("%", percent + 3);
|
|
4030
|
+
}
|
|
4031
|
+
return false;
|
|
4032
|
+
}
|
|
4033
|
+
function isIPLiteral(host) {
|
|
4034
|
+
return host[0] === "[" && host[host.length - 1] === "]";
|
|
4035
|
+
}
|
|
4036
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
4037
|
+
const host = matches[4];
|
|
4038
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
4039
|
+
}
|
|
4040
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP2) {
|
|
4041
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP2 === false && nonSimpleDomain(parsed.host)) {
|
|
4042
|
+
try {
|
|
4043
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
4044
|
+
} catch (e) {
|
|
4045
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
4046
|
+
return true;
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
return false;
|
|
4050
|
+
}
|
|
3795
4051
|
function parseWithStatus(uri, opts) {
|
|
3796
4052
|
const options = Object.assign({}, opts);
|
|
3797
4053
|
const parsed = {
|
|
@@ -3804,7 +4060,12 @@ var require_fast_uri = __commonJS({
|
|
|
3804
4060
|
fragment: void 0
|
|
3805
4061
|
};
|
|
3806
4062
|
let malformedAuthorityOrPort = false;
|
|
3807
|
-
let
|
|
4063
|
+
let malformedPercentEncoding = false;
|
|
4064
|
+
let malformedSchemeSpecific = false;
|
|
4065
|
+
let malformedHost = false;
|
|
4066
|
+
let malformedIPLiteral = false;
|
|
4067
|
+
let malformedScheme = false;
|
|
4068
|
+
let isIP2 = false;
|
|
3808
4069
|
if (options.reference === "suffix") {
|
|
3809
4070
|
if (options.scheme) {
|
|
3810
4071
|
uri = options.scheme + ":" + uri;
|
|
@@ -3840,6 +4101,19 @@ var require_fast_uri = __commonJS({
|
|
|
3840
4101
|
parsed.path = matches[6] || "";
|
|
3841
4102
|
parsed.query = matches[7];
|
|
3842
4103
|
parsed.fragment = matches[8];
|
|
4104
|
+
if (parsed.scheme !== void 0) {
|
|
4105
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
4106
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
4107
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
4108
|
+
} else {
|
|
4109
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
4110
|
+
malformedScheme = true;
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
4113
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
4114
|
+
if (malformedPercentEncoding) {
|
|
4115
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
4116
|
+
}
|
|
3843
4117
|
if (isNaN(parsed.port)) {
|
|
3844
4118
|
parsed.port = matches[5];
|
|
3845
4119
|
}
|
|
@@ -3851,11 +4125,18 @@ var require_fast_uri = __commonJS({
|
|
|
3851
4125
|
if (parsed.host) {
|
|
3852
4126
|
const ipv4result = isIPv4(parsed.host);
|
|
3853
4127
|
if (ipv4result === false) {
|
|
4128
|
+
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
4129
|
+
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
3854
4130
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
3855
|
-
|
|
3856
|
-
|
|
4131
|
+
isIP2 = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4132
|
+
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
4133
|
+
parsed.host = isIP2 ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4134
|
+
if (malformedIPLiteral) {
|
|
4135
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
4136
|
+
malformedAuthorityOrPort = true;
|
|
4137
|
+
}
|
|
3857
4138
|
} else {
|
|
3858
|
-
|
|
4139
|
+
isIP2 = true;
|
|
3859
4140
|
}
|
|
3860
4141
|
}
|
|
3861
4142
|
if (parsed.scheme === void 0 && parsed.userinfo === void 0 && parsed.host === void 0 && parsed.port === void 0 && parsed.query === void 0 && !parsed.path) {
|
|
@@ -3871,42 +4152,36 @@ var require_fast_uri = __commonJS({
|
|
|
3871
4152
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
3872
4153
|
}
|
|
3873
4154
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
3874
|
-
if (!
|
|
3875
|
-
|
|
3876
|
-
try {
|
|
3877
|
-
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3878
|
-
} catch (e) {
|
|
3879
|
-
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3880
|
-
}
|
|
3881
|
-
}
|
|
4155
|
+
if (!malformedIPLiteral) {
|
|
4156
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP2);
|
|
3882
4157
|
}
|
|
3883
4158
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
3884
4159
|
if (uri.indexOf("%") !== -1) {
|
|
3885
|
-
if (parsed.
|
|
3886
|
-
parsed.
|
|
3887
|
-
|
|
3888
|
-
if (parsed.host !== void 0) {
|
|
3889
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
4160
|
+
if (parsed.host !== void 0 && !malformedIPLiteral) {
|
|
4161
|
+
const host = isIP2 ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4162
|
+
parsed.host = reescapeHostDelimiters(host, isIP2);
|
|
3890
4163
|
}
|
|
3891
4164
|
}
|
|
3892
4165
|
if (parsed.path) {
|
|
3893
4166
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3894
4167
|
}
|
|
4168
|
+
if (parsed.query) {
|
|
4169
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
4170
|
+
}
|
|
3895
4171
|
if (parsed.fragment) {
|
|
3896
|
-
|
|
3897
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3898
|
-
} catch {
|
|
3899
|
-
parsed.error = parsed.error || "URI malformed";
|
|
3900
|
-
}
|
|
4172
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
3901
4173
|
}
|
|
3902
4174
|
}
|
|
3903
4175
|
if (schemeHandler && schemeHandler.parse) {
|
|
3904
4176
|
schemeHandler.parse(parsed, options);
|
|
4177
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
|
|
4178
|
+
malformedSchemeSpecific = true;
|
|
4179
|
+
}
|
|
3905
4180
|
}
|
|
3906
4181
|
} else {
|
|
3907
4182
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3908
4183
|
}
|
|
3909
|
-
return { parsed, malformedAuthorityOrPort };
|
|
4184
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
3910
4185
|
}
|
|
3911
4186
|
function parse3(uri, opts) {
|
|
3912
4187
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -3915,20 +4190,28 @@ var require_fast_uri = __commonJS({
|
|
|
3915
4190
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3916
4191
|
}
|
|
3917
4192
|
function normalizeStringWithStatus(uri, opts) {
|
|
3918
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
4193
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
3919
4194
|
return {
|
|
3920
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
3921
|
-
malformedAuthorityOrPort
|
|
4195
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
4196
|
+
malformedAuthorityOrPort,
|
|
4197
|
+
malformedPercentEncoding,
|
|
4198
|
+
malformedSchemeSpecific,
|
|
4199
|
+
malformedHost,
|
|
4200
|
+
malformedScheme
|
|
3922
4201
|
};
|
|
3923
4202
|
}
|
|
3924
4203
|
function normalizeComparableURI(uri, opts) {
|
|
3925
|
-
if (typeof uri
|
|
3926
|
-
|
|
3927
|
-
return malformedAuthorityOrPort ? void 0 : normalized;
|
|
4204
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
4205
|
+
return void 0;
|
|
3928
4206
|
}
|
|
3929
|
-
|
|
3930
|
-
|
|
4207
|
+
let value;
|
|
4208
|
+
try {
|
|
4209
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
4210
|
+
} catch {
|
|
4211
|
+
return void 0;
|
|
3931
4212
|
}
|
|
4213
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
4214
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
|
|
3932
4215
|
}
|
|
3933
4216
|
var fastUri = {
|
|
3934
4217
|
SCHEMES,
|
|
@@ -7199,7 +7482,7 @@ var require_permessage_deflate = __commonJS({
|
|
|
7199
7482
|
acceptAsServer(offers) {
|
|
7200
7483
|
const opts = this._options;
|
|
7201
7484
|
const accepted = offers.find((params) => {
|
|
7202
|
-
if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) {
|
|
7485
|
+
if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && (typeof params.client_max_window_bits === "number" ? opts.clientMaxWindowBits > params.client_max_window_bits : !params.client_max_window_bits)) {
|
|
7203
7486
|
return false;
|
|
7204
7487
|
}
|
|
7205
7488
|
return true;
|
|
@@ -34730,12 +35013,82 @@ function messageOf(err) {
|
|
|
34730
35013
|
return String(err);
|
|
34731
35014
|
}
|
|
34732
35015
|
|
|
34733
|
-
// node_modules/@chrischall/mcp-utils/dist/response/
|
|
34734
|
-
|
|
34735
|
-
|
|
34736
|
-
|
|
34737
|
-
|
|
35016
|
+
// node_modules/@chrischall/mcp-utils/dist/response/view.js
|
|
35017
|
+
var VIEWS = ["compact", "full", "raw"];
|
|
35018
|
+
var DEFAULT_VIEW = "compact";
|
|
35019
|
+
var BLURB = {
|
|
35020
|
+
compact: '"compact" (default) drops fields the response already carries elsewhere',
|
|
35021
|
+
full: '"full" returns every field this server understands',
|
|
35022
|
+
raw: '"raw" returns the upstream payload unprojected'
|
|
35023
|
+
};
|
|
35024
|
+
function viewParam(honoured, opts = {}) {
|
|
35025
|
+
if (honoured.length < 2) {
|
|
35026
|
+
throw new Error("viewParam needs at least two rungs: a parameter offering one value decides nothing");
|
|
35027
|
+
}
|
|
35028
|
+
if (!honoured.includes("compact")) {
|
|
35029
|
+
throw new Error('viewParam must offer "compact": a tool with no cheap rung has nothing to default to');
|
|
35030
|
+
}
|
|
35031
|
+
const ordered = VIEWS.filter((v) => honoured.includes(v));
|
|
35032
|
+
const sentence = `Response shape: ${ordered.map((v) => BLURB[v]).join("; ")}.`;
|
|
35033
|
+
return external_exports.enum(Object.fromEntries(ordered.map((v) => [v, v]))).optional().describe(opts.note ? `${sentence} ${opts.note}` : sentence);
|
|
35034
|
+
}
|
|
35035
|
+
function resolveView(value, honoured) {
|
|
35036
|
+
return value !== void 0 && honoured.includes(value) ? value : DEFAULT_VIEW;
|
|
35037
|
+
}
|
|
35038
|
+
function minifiedResult(data) {
|
|
35039
|
+
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
35040
|
+
}
|
|
35041
|
+
|
|
35042
|
+
// node_modules/@chrischall/mcp-utils/dist/response/media.js
|
|
35043
|
+
var MEDIA_NOUN = "(?:avatar|picture|photo|thumbnail|thumb|image|icon|banner|profile_pic(?:ture)?|logo)";
|
|
35044
|
+
var MEDIA_QUALIFIER = "(?:primary|secondary|main|default|cover|hero|profile|master|rendered|small|medium|large|full|original|tall)";
|
|
35045
|
+
var MEDIA_KEY = new RegExp(`^(?:(?:${MEDIA_QUALIFIER}|${MEDIA_NOUN})[_-]?)?${MEDIA_NOUN}s?(?:[_-]?(?:link|uri|url|src)s?)?$`, "i");
|
|
35046
|
+
var MEDIA_URL = /^https?:\/\/[^\s]+?\.(png|jpe?g|gif|webp|svg|avif|bmp|ico)([?#]|$)/i;
|
|
35047
|
+
function stripMediaUrls(value, opts = {}) {
|
|
35048
|
+
const keep = normalizeRules(opts.keep ?? []);
|
|
35049
|
+
const drop = normalizeRules(opts.drop ?? []);
|
|
35050
|
+
return walk(value, keep, drop);
|
|
35051
|
+
}
|
|
35052
|
+
function normalizeRules(rules) {
|
|
35053
|
+
return rules.map((rule) => typeof rule === "string" ? rule.toLowerCase() : new RegExp(rule.source, rule.flags));
|
|
35054
|
+
}
|
|
35055
|
+
function matchesRule(key, rules) {
|
|
35056
|
+
const lower = key.toLowerCase();
|
|
35057
|
+
for (const rule of rules) {
|
|
35058
|
+
if (typeof rule === "string") {
|
|
35059
|
+
if (rule === lower)
|
|
35060
|
+
return true;
|
|
35061
|
+
continue;
|
|
35062
|
+
}
|
|
35063
|
+
rule.lastIndex = 0;
|
|
35064
|
+
if (rule.test(key))
|
|
35065
|
+
return true;
|
|
35066
|
+
}
|
|
35067
|
+
return false;
|
|
35068
|
+
}
|
|
35069
|
+
function walk(value, keep, drop) {
|
|
35070
|
+
if (Array.isArray(value))
|
|
35071
|
+
return value.map((v) => walk(v, keep, drop));
|
|
35072
|
+
if (value === null || typeof value !== "object")
|
|
35073
|
+
return value;
|
|
35074
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
|
|
35075
|
+
return value;
|
|
35076
|
+
const out = {};
|
|
35077
|
+
for (const [key, v] of Object.entries(value)) {
|
|
35078
|
+
if (matchesRule(key, keep)) {
|
|
35079
|
+
out[key] = v;
|
|
35080
|
+
continue;
|
|
35081
|
+
}
|
|
35082
|
+
if (MEDIA_KEY.test(key) || matchesRule(key, drop))
|
|
35083
|
+
continue;
|
|
35084
|
+
if (typeof v === "string" && MEDIA_URL.test(v))
|
|
35085
|
+
continue;
|
|
35086
|
+
out[key] = walk(v, keep, drop);
|
|
35087
|
+
}
|
|
35088
|
+
return out;
|
|
34738
35089
|
}
|
|
35090
|
+
|
|
35091
|
+
// node_modules/@chrischall/mcp-utils/dist/response/index.js
|
|
34739
35092
|
function errorResult(message) {
|
|
34740
35093
|
return {
|
|
34741
35094
|
content: [{ type: "text", text: redactSecrets(message) }],
|
|
@@ -35006,7 +35359,7 @@ var pageSchema = {
|
|
|
35006
35359
|
};
|
|
35007
35360
|
|
|
35008
35361
|
// src/version.ts
|
|
35009
|
-
var VERSION = "0.
|
|
35362
|
+
var VERSION = "0.5.0";
|
|
35010
35363
|
|
|
35011
35364
|
// src/client.ts
|
|
35012
35365
|
import { dirname, join } from "node:path";
|
|
@@ -35167,15 +35520,25 @@ function compactLocationList(raw) {
|
|
|
35167
35520
|
return { data: rows.map((r) => compactLocation(r)) };
|
|
35168
35521
|
}
|
|
35169
35522
|
|
|
35523
|
+
// src/view.ts
|
|
35524
|
+
var TA_VIEWS = ["compact", "full"];
|
|
35525
|
+
var NOTE = `compact returns the slim projection where one exists and strips image URLs elsewhere; "full" returns TripAdvisor's whole records.`;
|
|
35526
|
+
var viewArg = () => viewParam(TA_VIEWS, { note: NOTE });
|
|
35527
|
+
function viewResponse(view, data, projector) {
|
|
35528
|
+
const rung = resolveView(view, TA_VIEWS);
|
|
35529
|
+
if (rung !== "compact") return minifiedResult(data);
|
|
35530
|
+
if (projector === "list") return minifiedResult(compactList(data));
|
|
35531
|
+
if (projector === "locationList") return minifiedResult(compactLocationList(data));
|
|
35532
|
+
return minifiedResult(stripMediaUrls(data));
|
|
35533
|
+
}
|
|
35534
|
+
|
|
35170
35535
|
// src/tools/search.ts
|
|
35171
|
-
var
|
|
35172
|
-
compact: external_exports.boolean().optional().describe("Return a slim summary per result (id, name, category, city, rating, review_count, url) instead of full records")
|
|
35173
|
-
};
|
|
35536
|
+
var viewParamShared = { view: viewArg() };
|
|
35174
35537
|
function registerSearchTools(server) {
|
|
35175
35538
|
server.registerTool(
|
|
35176
35539
|
"ta_search_locations",
|
|
35177
35540
|
{
|
|
35178
|
-
description:
|
|
35541
|
+
description: 'Search TripAdvisor locations (restaurants, attractions, hotels) by name. Returns matches with a location id for the detail tools, plus pagination. Returns slim summaries by default; pass view:"full" for the whole records.',
|
|
35179
35542
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
35180
35543
|
inputSchema: {
|
|
35181
35544
|
query: external_exports.string().min(1).max(500).describe("Text to search location names for"),
|
|
@@ -35185,21 +35548,21 @@ function registerSearchTools(server) {
|
|
|
35185
35548
|
postal_code: external_exports.string().optional().describe("Postal/ZIP code (takes precedence over geo_name)"),
|
|
35186
35549
|
locale: LocaleList,
|
|
35187
35550
|
...pageParams,
|
|
35188
|
-
...
|
|
35551
|
+
...viewParamShared
|
|
35189
35552
|
}
|
|
35190
35553
|
},
|
|
35191
|
-
async ({ query, category, country_code, geo_name, postal_code, locale, page, size,
|
|
35554
|
+
async ({ query, category, country_code, geo_name, postal_code, locale, page, size, view }) => {
|
|
35192
35555
|
const data = await client.get(
|
|
35193
35556
|
`/locations/search${qs({ query, category, country_code, geo_name, postal_code, locale, page, size })}`,
|
|
35194
35557
|
{ cache: "dynamic" }
|
|
35195
35558
|
);
|
|
35196
|
-
return
|
|
35559
|
+
return viewResponse(view, data, "list");
|
|
35197
35560
|
}
|
|
35198
35561
|
);
|
|
35199
35562
|
server.registerTool(
|
|
35200
35563
|
"ta_search_nearby",
|
|
35201
35564
|
{
|
|
35202
|
-
description:
|
|
35565
|
+
description: 'Find TripAdvisor locations near a point within a radius, or inside a bounding box. Center by lat+lon+radius, by a reference location_id+radius, or by a sw/ne bounding box. Returns matches with distance and a location id. Returns slim summaries by default; pass view:"full" for the whole records.',
|
|
35203
35566
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
35204
35567
|
inputSchema: {
|
|
35205
35568
|
// Center — supply exactly one of: lat+lon, location_id, or the sw/ne box.
|
|
@@ -35218,11 +35581,11 @@ function registerSearchTools(server) {
|
|
|
35218
35581
|
sort: external_exports.enum(["distance", "rating"]).optional().describe("Sort order (default distance)"),
|
|
35219
35582
|
locale: LocaleList,
|
|
35220
35583
|
...pageParams,
|
|
35221
|
-
...
|
|
35584
|
+
...viewParamShared
|
|
35222
35585
|
}
|
|
35223
35586
|
},
|
|
35224
35587
|
async (args) => {
|
|
35225
|
-
const { lat, lon, location_id, radius, sw_lat, sw_lon, ne_lat, ne_lon,
|
|
35588
|
+
const { lat, lon, location_id, radius, sw_lat, sw_lon, ne_lat, ne_lon, view, ...rest } = args;
|
|
35226
35589
|
const boxParts = [sw_lat, sw_lon, ne_lat, ne_lon];
|
|
35227
35590
|
const boxGiven = boxParts.filter((v) => v !== void 0).length;
|
|
35228
35591
|
if (boxGiven > 0 && boxGiven < 4) {
|
|
@@ -35253,7 +35616,7 @@ function registerSearchTools(server) {
|
|
|
35253
35616
|
`/locations/nearby${qs({ lat, lon, location_id, radius, sw_lat, sw_lon, ne_lat, ne_lon, ...rest })}`,
|
|
35254
35617
|
{ cache: "dynamic" }
|
|
35255
35618
|
);
|
|
35256
|
-
return
|
|
35619
|
+
return viewResponse(view, data, "list");
|
|
35257
35620
|
}
|
|
35258
35621
|
);
|
|
35259
35622
|
}
|
|
@@ -35263,17 +35626,17 @@ function registerLocationTools(server) {
|
|
|
35263
35626
|
server.registerTool(
|
|
35264
35627
|
"ta_get_locations",
|
|
35265
35628
|
{
|
|
35266
|
-
description:
|
|
35629
|
+
description: 'Get details for MULTIPLE locations in one call (batch). Pass an array of location ids \u2014 cheaper than repeated ta_get_location_details. Unknown or unlicensed ids are silently omitted. Returns slim summaries by default; pass view:"full" for the whole records.',
|
|
35267
35630
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
35268
35631
|
inputSchema: {
|
|
35269
35632
|
ids: external_exports.array(LocationId).min(1).max(50).describe("Location IDs to fetch (1\u201350)"),
|
|
35270
35633
|
locale: LocaleList,
|
|
35271
|
-
|
|
35634
|
+
view: viewArg()
|
|
35272
35635
|
}
|
|
35273
35636
|
},
|
|
35274
|
-
async ({ ids, locale,
|
|
35637
|
+
async ({ ids, locale, view }) => {
|
|
35275
35638
|
const data = await client.get(`/locations${qs({ id: ids, locale })}`, { cache: "static" });
|
|
35276
|
-
return
|
|
35639
|
+
return viewResponse(view, data, "locationList");
|
|
35277
35640
|
}
|
|
35278
35641
|
);
|
|
35279
35642
|
server.registerTool(
|
|
@@ -35288,7 +35651,7 @@ function registerLocationTools(server) {
|
|
|
35288
35651
|
},
|
|
35289
35652
|
async ({ locationId, locale }) => {
|
|
35290
35653
|
const data = await client.get(`/locations/${locationId}${qs({ locale })}`, { cache: "static" });
|
|
35291
|
-
return
|
|
35654
|
+
return minifiedResult(data);
|
|
35292
35655
|
}
|
|
35293
35656
|
);
|
|
35294
35657
|
server.registerTool(
|
|
@@ -35306,25 +35669,26 @@ function registerLocationTools(server) {
|
|
|
35306
35669
|
const data = await client.get(`/locations/${locationId}/photos${qs({ locale, page, size })}`, {
|
|
35307
35670
|
cache: "static"
|
|
35308
35671
|
});
|
|
35309
|
-
return
|
|
35672
|
+
return minifiedResult(data);
|
|
35310
35673
|
}
|
|
35311
35674
|
);
|
|
35312
35675
|
server.registerTool(
|
|
35313
35676
|
"ta_get_location_reviews",
|
|
35314
35677
|
{
|
|
35315
|
-
description:
|
|
35678
|
+
description: `Get traveler reviews for a TripAdvisor location, with pagination. Reviewer avatars and other image URLs are dropped by default; pass view:"full" for TripAdvisor's whole records.`,
|
|
35316
35679
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
35317
35680
|
inputSchema: {
|
|
35318
35681
|
locationId: LocationId,
|
|
35319
35682
|
locale: LocaleList,
|
|
35320
|
-
...pageParams
|
|
35683
|
+
...pageParams,
|
|
35684
|
+
view: viewArg()
|
|
35321
35685
|
}
|
|
35322
35686
|
},
|
|
35323
|
-
async ({ locationId, locale, page, size }) => {
|
|
35687
|
+
async ({ locationId, locale, page, size, view }) => {
|
|
35324
35688
|
const data = await client.get(`/locations/${locationId}/reviews${qs({ locale, page, size })}`, {
|
|
35325
35689
|
cache: "static"
|
|
35326
35690
|
});
|
|
35327
|
-
return
|
|
35691
|
+
return viewResponse(view, data);
|
|
35328
35692
|
}
|
|
35329
35693
|
);
|
|
35330
35694
|
}
|
|
@@ -37366,6 +37730,7 @@ function classifyBridgeError(err) {
|
|
|
37366
37730
|
}
|
|
37367
37731
|
|
|
37368
37732
|
// node_modules/@fetchproxy/server/dist/ws-server.js
|
|
37733
|
+
import { isIP } from "node:net";
|
|
37369
37734
|
function envWsPort() {
|
|
37370
37735
|
const raw = process.env.FETCHPROXY_WS_PORT;
|
|
37371
37736
|
if (raw === void 0 || raw.trim() === "")
|
|
@@ -37377,6 +37742,15 @@ function envWsPort() {
|
|
|
37377
37742
|
return void 0;
|
|
37378
37743
|
return port;
|
|
37379
37744
|
}
|
|
37745
|
+
function envWsHost() {
|
|
37746
|
+
const raw = process.env.FETCHPROXY_WS_HOST;
|
|
37747
|
+
if (raw === void 0)
|
|
37748
|
+
return void 0;
|
|
37749
|
+
const host = raw.trim();
|
|
37750
|
+
if (host === "" || isIP(host) === 0)
|
|
37751
|
+
return void 0;
|
|
37752
|
+
return host;
|
|
37753
|
+
}
|
|
37380
37754
|
var FetchproxyProtocolError = class extends Error {
|
|
37381
37755
|
constructor(message) {
|
|
37382
37756
|
super(message);
|
|
@@ -37625,7 +37999,7 @@ var FetchproxyServer = class {
|
|
|
37625
37999
|
}
|
|
37626
38000
|
this.opts = {
|
|
37627
38001
|
port: opts.port ?? envWsPort() ?? 37149,
|
|
37628
|
-
host: opts.host ?? "127.0.0.1",
|
|
38002
|
+
host: opts.host ?? envWsHost() ?? "127.0.0.1",
|
|
37629
38003
|
serverName: opts.serverName,
|
|
37630
38004
|
version: opts.version,
|
|
37631
38005
|
domains: [...opts.domains],
|
|
@@ -37911,6 +38285,7 @@ var FetchproxyServer = class {
|
|
|
37911
38285
|
return {
|
|
37912
38286
|
role: this.role,
|
|
37913
38287
|
port: this.opts.port,
|
|
38288
|
+
host: this.opts.host,
|
|
37914
38289
|
serverVersion: this.opts.version,
|
|
37915
38290
|
fetchTimeoutMs: this.opts.fetchTimeoutMs ?? 0,
|
|
37916
38291
|
bridgeReviveDelayMs: this.opts.bridgeReviveDelayMs ?? 0,
|
|
@@ -39343,6 +39718,13 @@ function createFetchproxyTransport(opts) {
|
|
|
39343
39718
|
return transport;
|
|
39344
39719
|
}
|
|
39345
39720
|
function bridgeErrorInfo(err) {
|
|
39721
|
+
if (err instanceof FetchproxySessionNotReadyError) {
|
|
39722
|
+
return {
|
|
39723
|
+
type: "session_not_ready",
|
|
39724
|
+
message: truncateErrorMessage(messageOf(err).replace(err.hint, "").trim()),
|
|
39725
|
+
hint: err.hint
|
|
39726
|
+
};
|
|
39727
|
+
}
|
|
39346
39728
|
const kind = classifyBridgeError(err);
|
|
39347
39729
|
const message = truncateErrorMessage(messageOf(err));
|
|
39348
39730
|
switch (kind) {
|
|
@@ -39375,15 +39757,32 @@ function bridgeErrorInfo(err) {
|
|
|
39375
39757
|
}
|
|
39376
39758
|
function healthcheckHint(args) {
|
|
39377
39759
|
const { hostLabel, prefix, probePath, port } = args;
|
|
39760
|
+
const portNote = port === null ? "" : ` (port ${port})`;
|
|
39378
39761
|
if (args.ok) {
|
|
39762
|
+
if (args.direct) {
|
|
39763
|
+
return `Direct fetch round-tripped ${probePath} successfully \u2014 the browser bridge wasn't used for this probe. If real tools still fail, the problem is on the ${hostLabel} side (a bot wall answering some calls but not this one, a field that moved, \u2026), not the transport.`;
|
|
39764
|
+
}
|
|
39379
39765
|
return `Bridge round-tripped ${probePath} successfully. If real tools still fail, the problem is downstream of fetchproxy (${hostLabel} redirecting on login, a bot-wall / behavioral challenge, etc.) \u2014 not the bridge.`;
|
|
39380
39766
|
}
|
|
39767
|
+
if (args.errorKind === "session_not_ready") {
|
|
39768
|
+
const s = args.session;
|
|
39769
|
+
if (s?.pairCode) {
|
|
39770
|
+
return `The Transporter extension is waiting for you to approve pair code ${s.pairCode} for ${prefix}-mcp. Open the extension popup, approve it, then retry.`;
|
|
39771
|
+
}
|
|
39772
|
+
if (s?.state === "extension_disconnected") {
|
|
39773
|
+
return `No Transporter extension is attached to this bridge${portNote}. Open Chrome with the extension installed and a ${hostLabel} tab, then retry.`;
|
|
39774
|
+
}
|
|
39775
|
+
return `The Transporter extension is attached but never confirmed a session for ${prefix}-mcp \u2014 its hello got no answer within the session-ready timeout. Reload the extension (chrome://extensions) or reopen the ${hostLabel} tab, then retry. On a hosted bridge this is also what a relay that dialled the child before it bound its port${portNote} looks like.`;
|
|
39776
|
+
}
|
|
39381
39777
|
if (args.errorKind === "bridge_down") {
|
|
39382
39778
|
const base = `The fetchproxy browser extension's service worker is not responding. Chrome evicts extension service workers after ~30s idle by default \u2014 this looks like that case. Wake it by clicking the fetchproxy extension icon (or opening any ${hostLabel} tab and reloading), then retry. If it keeps happening, reload the extension from chrome://extensions.`;
|
|
39383
39779
|
return args.bridgeHint ? `${args.bridgeHint} ${base}` : base;
|
|
39384
39780
|
}
|
|
39781
|
+
if (args.direct) {
|
|
39782
|
+
return `The probe ran over the direct fetch \u2014 the browser bridge wasn't used for this probe \u2014 and failed; see error.message. If ${hostLabel} is answering with a bot wall, pin the bridge (the consumer's transport env var) or leave the default fallback to switch on the next challenge.`;
|
|
39783
|
+
}
|
|
39385
39784
|
if (args.role === null) {
|
|
39386
|
-
return `The bridge never bound a role. listen() may have failed silently on startup. Check stderr from ${prefix}-mcp for an error during start, and confirm port ${port} isn't blocked.`;
|
|
39785
|
+
return `The bridge never bound a role. listen() may have failed silently on startup. Check stderr from ${prefix}-mcp for an error during start, and confirm ${port === null ? "the bridge port" : `port ${port}`} isn't blocked.`;
|
|
39387
39786
|
}
|
|
39388
39787
|
if (args.errorKind === "timeout") {
|
|
39389
39788
|
return `Bridge is alive (role=${args.role}), but the request didn't get a response in time. Either (a) the fetchproxy browser extension isn't connected to this MCP yet \u2014 open the extension popup and check for a green dot next to "${prefix}-mcp", or (b) the signed-in ${hostLabel} tab is sleeping / closed. Open ${hostLabel} in your browser, then retry.`;
|
|
@@ -39393,12 +39792,32 @@ function healthcheckHint(args) {
|
|
|
39393
39792
|
}
|
|
39394
39793
|
return `Unexpected error \u2014 see the error.message field for details.`;
|
|
39395
39794
|
}
|
|
39795
|
+
function projectBridgeStatus(health) {
|
|
39796
|
+
const session = health.session;
|
|
39797
|
+
return {
|
|
39798
|
+
role: health.role,
|
|
39799
|
+
port: health.port,
|
|
39800
|
+
server_version: health.serverVersion,
|
|
39801
|
+
fetch_timeout_ms: health.fetchTimeoutMs,
|
|
39802
|
+
last_success_at: health.lastSuccessAt,
|
|
39803
|
+
last_failure_at: health.lastFailureAt,
|
|
39804
|
+
last_failure_reason: health.lastFailureReason,
|
|
39805
|
+
consecutive_failures: health.consecutiveFailures,
|
|
39806
|
+
last_extension_message_at: health.lastExtensionMessageAt,
|
|
39807
|
+
...session ? {
|
|
39808
|
+
session_state: session.state,
|
|
39809
|
+
pending_pair_code: session.pairCode,
|
|
39810
|
+
extension_connected: session.extensionConnected
|
|
39811
|
+
} : {}
|
|
39812
|
+
};
|
|
39813
|
+
}
|
|
39396
39814
|
function registerBridgeHealthcheckTool(args) {
|
|
39397
|
-
const { server, prefix, probePath, hostLabel,
|
|
39815
|
+
const { server, prefix, probePath, hostLabel, probeFn, classifyThrown, hints, path } = args;
|
|
39398
39816
|
const probeUrl = `https://${hostLabel}${probePath}`;
|
|
39817
|
+
const resolveTransport = () => typeof args.transport === "function" ? args.transport() : args.transport;
|
|
39399
39818
|
server.registerTool(`${prefix}_healthcheck`, {
|
|
39400
39819
|
title: "Verify the fetchproxy bridge end-to-end",
|
|
39401
|
-
description: `Round-trips a small public ${hostLabel} URL (${probePath}) through the fetchproxy bridge and returns diagnostics: the bridge's role (host/peer/null), port, version, the elapsed round-trip time, and a plain-English hint distinguishing 'bridge never came up' from 'extension not connected' from 'real ${hostLabel}-side problem'. Call this when a real tool fails and you want to know which hop broke. Read-only, no auth required.`,
|
|
39820
|
+
description: `Round-trips a small public ${hostLabel} URL (${probePath}) through the fetchproxy bridge and returns diagnostics: the bridge's role (host/peer/null), port, version, the extension link (linked / pair pending / not attached / never answered), the elapsed round-trip time, and a plain-English hint distinguishing 'bridge never came up' from 'extension not connected' from 'real ${hostLabel}-side problem'. Call this when a real tool fails and you want to know which hop broke. Read-only, no auth required.`,
|
|
39402
39821
|
annotations: {
|
|
39403
39822
|
title: "Verify the fetchproxy bridge end-to-end",
|
|
39404
39823
|
readOnlyHint: true,
|
|
@@ -39409,29 +39828,60 @@ function registerBridgeHealthcheckTool(args) {
|
|
|
39409
39828
|
}, async () => {
|
|
39410
39829
|
let probeBody = "";
|
|
39411
39830
|
let thrown;
|
|
39412
|
-
const
|
|
39831
|
+
const wrappedProbe = async (p) => {
|
|
39413
39832
|
try {
|
|
39414
|
-
probeBody = await probeFn(
|
|
39833
|
+
probeBody = await probeFn(p);
|
|
39415
39834
|
return probeBody;
|
|
39416
39835
|
} catch (e) {
|
|
39417
39836
|
thrown = e;
|
|
39418
39837
|
throw e;
|
|
39419
39838
|
}
|
|
39420
|
-
}
|
|
39421
|
-
|
|
39422
|
-
|
|
39423
|
-
|
|
39424
|
-
|
|
39425
|
-
|
|
39426
|
-
|
|
39427
|
-
|
|
39839
|
+
};
|
|
39840
|
+
let ok;
|
|
39841
|
+
let elapsedMs;
|
|
39842
|
+
let bridge;
|
|
39843
|
+
let rawError;
|
|
39844
|
+
let pathNow;
|
|
39845
|
+
if (path) {
|
|
39846
|
+
const start = Date.now();
|
|
39847
|
+
try {
|
|
39848
|
+
await wrappedProbe(probePath);
|
|
39849
|
+
ok = true;
|
|
39850
|
+
} catch (e) {
|
|
39851
|
+
ok = false;
|
|
39852
|
+
rawError = { kind: classifyBridgeError(e), message: truncateErrorMessage(messageOf(e)) };
|
|
39853
|
+
}
|
|
39854
|
+
elapsedMs = Date.now() - start;
|
|
39855
|
+
pathNow = path();
|
|
39856
|
+
const transport = resolveTransport();
|
|
39857
|
+
bridge = transport ? projectBridgeStatus(transport.status()) : void 0;
|
|
39858
|
+
} else {
|
|
39859
|
+
const transport = resolveTransport();
|
|
39860
|
+
if (!transport) {
|
|
39861
|
+
throw new Error("registerBridgeHealthcheckTool: transport() returned nothing and no `path` was supplied \u2014 a bridge-only healthcheck needs its bridge.");
|
|
39862
|
+
}
|
|
39863
|
+
const probeResult = await transport.runProbe(wrappedProbe, probePath);
|
|
39864
|
+
ok = probeResult.ok;
|
|
39865
|
+
elapsedMs = probeResult.elapsed_ms;
|
|
39866
|
+
bridge = {
|
|
39867
|
+
...probeResult.bridge,
|
|
39868
|
+
last_extension_message_at: transport.status().lastExtensionMessageAt
|
|
39869
|
+
};
|
|
39870
|
+
rawError = probeResult.error;
|
|
39871
|
+
}
|
|
39872
|
+
const probe = ok ? { url: probeUrl, elapsed_ms: elapsedMs, status: 200, body_length: probeBody.length } : { url: probeUrl, elapsed_ms: elapsedMs };
|
|
39428
39873
|
let error51;
|
|
39429
39874
|
let bridgeHint;
|
|
39430
39875
|
let customHint;
|
|
39431
39876
|
let customDetail;
|
|
39432
|
-
if (
|
|
39433
|
-
let kind =
|
|
39434
|
-
|
|
39877
|
+
if (rawError) {
|
|
39878
|
+
let kind = rawError.kind === "other" ? "unknown" : rawError.kind;
|
|
39879
|
+
if (thrown instanceof FetchproxySessionNotReadyError) {
|
|
39880
|
+
kind = "session_not_ready";
|
|
39881
|
+
bridgeHint = thrown.hint;
|
|
39882
|
+
} else if (thrown instanceof FetchproxyBridgeDownError) {
|
|
39883
|
+
bridgeHint = thrown.hint;
|
|
39884
|
+
}
|
|
39435
39885
|
if (thrown !== void 0 && classifyThrown) {
|
|
39436
39886
|
const custom2 = classifyThrown(thrown);
|
|
39437
39887
|
if (custom2) {
|
|
@@ -39442,30 +39892,33 @@ function registerBridgeHealthcheckTool(args) {
|
|
|
39442
39892
|
}
|
|
39443
39893
|
error51 = {
|
|
39444
39894
|
kind,
|
|
39445
|
-
message:
|
|
39895
|
+
message: rawError.message,
|
|
39446
39896
|
...bridgeHint !== void 0 ? { bridge_hint: bridgeHint } : {},
|
|
39447
39897
|
...customDetail !== void 0 ? { detail: customDetail } : {}
|
|
39448
39898
|
};
|
|
39449
39899
|
}
|
|
39450
|
-
const
|
|
39451
|
-
const arm = ok ? "ok" : error51?.kind === "bridge_down" ? "bridge_down" :
|
|
39900
|
+
const direct = pathNow ? pathNow.transport === "direct" : bridge === void 0;
|
|
39901
|
+
const arm = ok ? "ok" : error51?.kind === "session_not_ready" ? "session_not_ready" : error51?.kind === "bridge_down" ? "bridge_down" : direct ? "direct" : bridge === void 0 || bridge.role === null ? "no_role" : error51?.kind === "timeout" ? "timeout" : error51?.kind === "protocol" || error51?.kind === "http" ? "protocol" : "unknown";
|
|
39452
39902
|
const defaultHint = healthcheckHint({
|
|
39453
39903
|
ok,
|
|
39454
|
-
role:
|
|
39455
|
-
//
|
|
39456
|
-
port:
|
|
39904
|
+
role: bridge?.role ?? null,
|
|
39905
|
+
// The real configured port from bridgeHealth(), never a literal 37149.
|
|
39906
|
+
port: bridge?.port ?? null,
|
|
39457
39907
|
hostLabel,
|
|
39458
39908
|
prefix,
|
|
39459
39909
|
probePath,
|
|
39460
39910
|
errorKind: error51?.kind,
|
|
39461
|
-
bridgeHint: error51?.kind === "bridge_down" ? bridgeHint : void 0
|
|
39911
|
+
bridgeHint: error51?.kind === "bridge_down" ? bridgeHint : void 0,
|
|
39912
|
+
session: {
|
|
39913
|
+
...bridge?.session_state !== void 0 ? { state: bridge.session_state } : {},
|
|
39914
|
+
pairCode: bridge?.pending_pair_code ?? (thrown instanceof FetchproxySessionNotReadyError ? thrown.pairCode : null)
|
|
39915
|
+
},
|
|
39916
|
+
direct
|
|
39462
39917
|
});
|
|
39463
39918
|
const result = {
|
|
39464
39919
|
ok,
|
|
39465
|
-
bridge: {
|
|
39466
|
-
|
|
39467
|
-
last_extension_message_at: lastExtensionMessageAt
|
|
39468
|
-
},
|
|
39920
|
+
...bridge ? { bridge } : {},
|
|
39921
|
+
...pathNow ? { transport: pathNow } : {},
|
|
39469
39922
|
probe,
|
|
39470
39923
|
...error51 ? { error: error51 } : {},
|
|
39471
39924
|
// Precedence: classifyThrown's hint > per-arm override > default ladder.
|
|
@@ -39696,7 +40149,7 @@ function registerWebTools(server) {
|
|
|
39696
40149
|
hint: "The page may be a bot-challenge shell or the id may be wrong \u2014 run ta_web_healthcheck and confirm a signed-in www.tripadvisor.com tab is open, then retry."
|
|
39697
40150
|
});
|
|
39698
40151
|
}
|
|
39699
|
-
return
|
|
40152
|
+
return minifiedResult({ location_id: locationId, ...detail });
|
|
39700
40153
|
}
|
|
39701
40154
|
);
|
|
39702
40155
|
}
|