@oss-scout/mcp 0.10.2 → 0.12.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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp-server.bundle.cjs +844 -281
- package/dist/tools.js +2 -2
- package/package.json +2 -2
|
@@ -3100,16 +3100,18 @@ var require_data = __commonJS({
|
|
|
3100
3100
|
}
|
|
3101
3101
|
});
|
|
3102
3102
|
|
|
3103
|
-
// ../../node_modules/.pnpm/fast-uri@4.1.
|
|
3103
|
+
// ../../node_modules/.pnpm/fast-uri@4.1.5/node_modules/fast-uri/lib/utils.js
|
|
3104
3104
|
var require_utils = __commonJS({
|
|
3105
|
-
"../../node_modules/.pnpm/fast-uri@4.1.
|
|
3105
|
+
"../../node_modules/.pnpm/fast-uri@4.1.5/node_modules/fast-uri/lib/utils.js"(exports2, module2) {
|
|
3106
3106
|
"use strict";
|
|
3107
3107
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
3108
3108
|
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);
|
|
3109
|
+
var isPort = RegExp.prototype.test.bind(/^\d*$/u);
|
|
3109
3110
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3110
3111
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3111
|
-
var isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
3112
|
-
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[
|
|
3112
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
3113
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
3114
|
+
var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
3113
3115
|
function stringArrayToHexStripped(input) {
|
|
3114
3116
|
let acc = "";
|
|
3115
3117
|
let code = 0;
|
|
@@ -3134,91 +3136,110 @@ var require_utils = __commonJS({
|
|
|
3134
3136
|
}
|
|
3135
3137
|
return acc;
|
|
3136
3138
|
}
|
|
3139
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
3140
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
3141
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
3137
3142
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3143
|
+
var nonSimpleDomainChars = RegExp.prototype.test.bind(/[^\d!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3144
|
+
var numericLastLabel = RegExp.prototype.test.bind(/(?:^|\.)\d+$/u);
|
|
3145
|
+
function nonSimpleMailtoDomain(domain2) {
|
|
3146
|
+
return nonSimpleDomainChars(domain2) || numericLastLabel(domain2);
|
|
3147
|
+
}
|
|
3148
|
+
function isZoneIdentifier(zone) {
|
|
3149
|
+
if (zone.length === 0) return false;
|
|
3150
|
+
for (let i = 0; i < zone.length; i++) {
|
|
3151
|
+
if (isZoneCharacter(zone[i])) continue;
|
|
3152
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
3153
|
+
i += 2;
|
|
3154
|
+
continue;
|
|
3150
3155
|
}
|
|
3151
|
-
|
|
3156
|
+
return false;
|
|
3152
3157
|
}
|
|
3153
3158
|
return true;
|
|
3154
3159
|
}
|
|
3155
|
-
function
|
|
3156
|
-
let
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
let
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
}
|
|
3168
|
-
if (cursor === ":") {
|
|
3169
|
-
if (endipv6Encountered === true) {
|
|
3170
|
-
endIpv6 = true;
|
|
3160
|
+
function compressIPv6ZeroRun(hextets) {
|
|
3161
|
+
let bestStart = -1;
|
|
3162
|
+
let bestLength = 0;
|
|
3163
|
+
let runStart = -1;
|
|
3164
|
+
let runLength = 0;
|
|
3165
|
+
for (let i = 0; i < hextets.length; i++) {
|
|
3166
|
+
if (hextets[i] === "0") {
|
|
3167
|
+
if (runStart === -1) runStart = i;
|
|
3168
|
+
runLength++;
|
|
3169
|
+
if (runLength > bestLength) {
|
|
3170
|
+
bestLength = runLength;
|
|
3171
|
+
bestStart = runStart;
|
|
3171
3172
|
}
|
|
3172
|
-
if (!consume(buffer, address, output)) {
|
|
3173
|
-
break;
|
|
3174
|
-
}
|
|
3175
|
-
if (++tokenCount > 7) {
|
|
3176
|
-
output.error = true;
|
|
3177
|
-
break;
|
|
3178
|
-
}
|
|
3179
|
-
if (i > 0 && input[i - 1] === ":") {
|
|
3180
|
-
endipv6Encountered = true;
|
|
3181
|
-
}
|
|
3182
|
-
address.push(":");
|
|
3183
|
-
continue;
|
|
3184
|
-
} else if (cursor === "%") {
|
|
3185
|
-
if (!consume(buffer, address, output)) {
|
|
3186
|
-
break;
|
|
3187
|
-
}
|
|
3188
|
-
consume = consumeIsZone;
|
|
3189
3173
|
} else {
|
|
3190
|
-
|
|
3174
|
+
runStart = -1;
|
|
3175
|
+
runLength = 0;
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
if (bestLength < 2) return hextets.join(":");
|
|
3179
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
3180
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
3181
|
+
return head + "::" + tail;
|
|
3182
|
+
}
|
|
3183
|
+
function normalizeIPv6Address(input) {
|
|
3184
|
+
const compression = input.indexOf("::");
|
|
3185
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
|
|
3186
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
3187
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
3188
|
+
if (compression !== -1) {
|
|
3189
|
+
if (left.length === 1 && left[0] === "") left.length = 0;
|
|
3190
|
+
if (right.length === 1 && right[0] === "") right.length = 0;
|
|
3191
|
+
}
|
|
3192
|
+
const parts = left.concat(right);
|
|
3193
|
+
let hextetCount = 0;
|
|
3194
|
+
for (let i = 0; i < parts.length; i++) {
|
|
3195
|
+
const part = parts[i];
|
|
3196
|
+
if (part === "") return void 0;
|
|
3197
|
+
if (part.indexOf(".") !== -1) {
|
|
3198
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
|
|
3199
|
+
hextetCount += 2;
|
|
3191
3200
|
continue;
|
|
3192
3201
|
}
|
|
3202
|
+
if (!isHextet(part)) return void 0;
|
|
3203
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
3204
|
+
hextetCount++;
|
|
3193
3205
|
}
|
|
3194
|
-
if (
|
|
3195
|
-
if (
|
|
3196
|
-
|
|
3197
|
-
} else if (endIpv6) {
|
|
3198
|
-
address.push(buffer.join(""));
|
|
3199
|
-
} else {
|
|
3200
|
-
address.push(stringArrayToHexStripped(buffer));
|
|
3201
|
-
}
|
|
3206
|
+
if (compression === -1) {
|
|
3207
|
+
if (hextetCount !== 8) return void 0;
|
|
3208
|
+
return compressIPv6ZeroRun(parts);
|
|
3202
3209
|
}
|
|
3203
|
-
|
|
3204
|
-
|
|
3210
|
+
if (hextetCount >= 8) return void 0;
|
|
3211
|
+
const expanded = parts.slice(0, left.length);
|
|
3212
|
+
for (let i = hextetCount; i < 8; i++) expanded.push("0");
|
|
3213
|
+
for (let i = left.length; i < parts.length; i++) expanded.push(parts[i]);
|
|
3214
|
+
return compressIPv6ZeroRun(expanded);
|
|
3205
3215
|
}
|
|
3206
3216
|
function normalizeIPv6(host) {
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
}
|
|
3210
|
-
|
|
3211
|
-
if (
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3217
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
3218
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
3219
|
+
if (hasBracket && !bracketed) return { host, isIPV6: false, error: true };
|
|
3220
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
3221
|
+
if (bracketed && isIPvFuture(input)) {
|
|
3222
|
+
input = input.toLowerCase();
|
|
3223
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
3224
|
+
}
|
|
3225
|
+
if (findToken(input, ":") < 2) {
|
|
3226
|
+
return { host, isIPV6: false, error: bracketed };
|
|
3227
|
+
}
|
|
3228
|
+
let zoneIdentifier = "";
|
|
3229
|
+
const zoneSeparator = input.indexOf("%");
|
|
3230
|
+
if (zoneSeparator !== -1) {
|
|
3231
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
3232
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
3233
|
+
if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true };
|
|
3234
|
+
input = input.slice(0, zoneSeparator);
|
|
3235
|
+
}
|
|
3236
|
+
const address = normalizeIPv6Address(input);
|
|
3237
|
+
if (address === void 0) return { host, isIPV6: false, error: true };
|
|
3238
|
+
return {
|
|
3239
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
3240
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
3241
|
+
isIPV6: true
|
|
3242
|
+
};
|
|
3222
3243
|
}
|
|
3223
3244
|
function findToken(str, token) {
|
|
3224
3245
|
let ind = 0;
|
|
@@ -3394,6 +3415,45 @@ var require_utils = __commonJS({
|
|
|
3394
3415
|
}
|
|
3395
3416
|
return output;
|
|
3396
3417
|
}
|
|
3418
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
3419
|
+
let output = "";
|
|
3420
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
3421
|
+
for (let i = 0; i < input.length; i++) {
|
|
3422
|
+
const ch = input[i];
|
|
3423
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3424
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3425
|
+
if (isHexPair(hex3)) {
|
|
3426
|
+
output += "%" + hex3.toUpperCase();
|
|
3427
|
+
i += 2;
|
|
3428
|
+
continue;
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
if (ch === "/") {
|
|
3432
|
+
firstSegment = false;
|
|
3433
|
+
}
|
|
3434
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
|
|
3435
|
+
output += ch;
|
|
3436
|
+
} else {
|
|
3437
|
+
const code = input.charCodeAt(i);
|
|
3438
|
+
if (code < 128) {
|
|
3439
|
+
output += BYTE_HEX[code];
|
|
3440
|
+
} else if (code < 55296 || code > 57343) {
|
|
3441
|
+
output += percentEncodeNonAscii(code);
|
|
3442
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3443
|
+
const low = input.charCodeAt(i + 1);
|
|
3444
|
+
if (low >= 56320 && low <= 57343) {
|
|
3445
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3446
|
+
i++;
|
|
3447
|
+
} else {
|
|
3448
|
+
output += percentEncodeNonAscii(65533);
|
|
3449
|
+
}
|
|
3450
|
+
} else {
|
|
3451
|
+
output += percentEncodeNonAscii(65533);
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
return output;
|
|
3456
|
+
}
|
|
3397
3457
|
function normalizeQueryFragmentEncoding(input) {
|
|
3398
3458
|
let output = "";
|
|
3399
3459
|
for (let i = 0; i < input.length; i++) {
|
|
@@ -3435,6 +3495,50 @@ var require_utils = __commonJS({
|
|
|
3435
3495
|
}
|
|
3436
3496
|
return output;
|
|
3437
3497
|
}
|
|
3498
|
+
function encodeComponent(input, isAllowed) {
|
|
3499
|
+
let output = "";
|
|
3500
|
+
for (let i = 0; i < input.length; i++) {
|
|
3501
|
+
const ch = input[i];
|
|
3502
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3503
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3504
|
+
if (isHexPair(hex3)) {
|
|
3505
|
+
output += "%" + hex3.toUpperCase();
|
|
3506
|
+
i += 2;
|
|
3507
|
+
continue;
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
if (isAllowed(ch)) {
|
|
3511
|
+
output += ch;
|
|
3512
|
+
} else {
|
|
3513
|
+
const code = input.charCodeAt(i);
|
|
3514
|
+
if (code < 128) {
|
|
3515
|
+
output += BYTE_HEX[code];
|
|
3516
|
+
} else if (code < 55296 || code > 57343) {
|
|
3517
|
+
output += percentEncodeNonAscii(code);
|
|
3518
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3519
|
+
const low = input.charCodeAt(i + 1);
|
|
3520
|
+
if (low >= 56320 && low <= 57343) {
|
|
3521
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3522
|
+
i++;
|
|
3523
|
+
} else {
|
|
3524
|
+
output += percentEncodeNonAscii(65533);
|
|
3525
|
+
}
|
|
3526
|
+
} else {
|
|
3527
|
+
output += percentEncodeNonAscii(65533);
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
return output;
|
|
3532
|
+
}
|
|
3533
|
+
function encodeUserinfo(input) {
|
|
3534
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
3535
|
+
}
|
|
3536
|
+
function encodeQuery(input) {
|
|
3537
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3538
|
+
}
|
|
3539
|
+
function encodeFragment(input) {
|
|
3540
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3541
|
+
}
|
|
3438
3542
|
function escapePreservingEscapes(input) {
|
|
3439
3543
|
let output = "";
|
|
3440
3544
|
for (let i = 0; i < input.length; i++) {
|
|
@@ -3469,14 +3573,18 @@ var require_utils = __commonJS({
|
|
|
3469
3573
|
function recomposeAuthority(component) {
|
|
3470
3574
|
const uriTokens = [];
|
|
3471
3575
|
if (component.userinfo !== void 0) {
|
|
3472
|
-
uriTokens.push(component.userinfo);
|
|
3576
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
3473
3577
|
uriTokens.push("@");
|
|
3474
3578
|
}
|
|
3475
3579
|
if (component.host !== void 0) {
|
|
3476
|
-
let host =
|
|
3580
|
+
let host = component.host;
|
|
3477
3581
|
if (!isIPv4(host)) {
|
|
3478
|
-
|
|
3479
|
-
if (ipV6res.isIPV6
|
|
3582
|
+
let ipV6res = normalizeIPv6(host);
|
|
3583
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
3584
|
+
host = normalizePercentEncoding(host, true);
|
|
3585
|
+
ipV6res = normalizeIPv6(host);
|
|
3586
|
+
}
|
|
3587
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
3480
3588
|
host = `[${ipV6res.escapedHost}]`;
|
|
3481
3589
|
} else {
|
|
3482
3590
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -3485,18 +3593,29 @@ var require_utils = __commonJS({
|
|
|
3485
3593
|
uriTokens.push(host);
|
|
3486
3594
|
}
|
|
3487
3595
|
if (typeof component.port === "number" || typeof component.port === "string") {
|
|
3596
|
+
const port = String(component.port);
|
|
3597
|
+
if (!isPort(port)) {
|
|
3598
|
+
throw new TypeError("URI port is malformed.");
|
|
3599
|
+
}
|
|
3488
3600
|
uriTokens.push(":");
|
|
3489
|
-
uriTokens.push(
|
|
3601
|
+
uriTokens.push(port);
|
|
3490
3602
|
}
|
|
3491
3603
|
return uriTokens.length ? uriTokens.join("") : void 0;
|
|
3492
3604
|
}
|
|
3493
3605
|
module2.exports = {
|
|
3606
|
+
BYTE_HEX,
|
|
3607
|
+
percentEncodeNonAscii,
|
|
3494
3608
|
nonSimpleDomain,
|
|
3609
|
+
nonSimpleMailtoDomain,
|
|
3495
3610
|
recomposeAuthority,
|
|
3496
3611
|
reescapeHostDelimiters,
|
|
3497
3612
|
normalizePercentEncoding,
|
|
3498
3613
|
normalizePathEncoding,
|
|
3614
|
+
serializePathEncoding,
|
|
3499
3615
|
normalizeQueryFragmentEncoding,
|
|
3616
|
+
encodeUserinfo,
|
|
3617
|
+
encodeQuery,
|
|
3618
|
+
encodeFragment,
|
|
3500
3619
|
escapePreservingEscapes,
|
|
3501
3620
|
removeDotSegments,
|
|
3502
3621
|
isIPv4,
|
|
@@ -3507,12 +3626,12 @@ var require_utils = __commonJS({
|
|
|
3507
3626
|
}
|
|
3508
3627
|
});
|
|
3509
3628
|
|
|
3510
|
-
// ../../node_modules/.pnpm/fast-uri@4.1.
|
|
3629
|
+
// ../../node_modules/.pnpm/fast-uri@4.1.5/node_modules/fast-uri/lib/schemes.js
|
|
3511
3630
|
var require_schemes = __commonJS({
|
|
3512
|
-
"../../node_modules/.pnpm/fast-uri@4.1.
|
|
3631
|
+
"../../node_modules/.pnpm/fast-uri@4.1.5/node_modules/fast-uri/lib/schemes.js"(exports2, module2) {
|
|
3513
3632
|
"use strict";
|
|
3514
|
-
var { isUUID } = require_utils();
|
|
3515
|
-
var URN_REG =
|
|
3633
|
+
var { isUUID, BYTE_HEX, percentEncodeNonAscii, nonSimpleMailtoDomain } = require_utils();
|
|
3634
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
3516
3635
|
var supportedSchemeNames = (
|
|
3517
3636
|
/** @type {const} */
|
|
3518
3637
|
[
|
|
@@ -3521,7 +3640,8 @@ var require_schemes = __commonJS({
|
|
|
3521
3640
|
"ws",
|
|
3522
3641
|
"wss",
|
|
3523
3642
|
"urn",
|
|
3524
|
-
"urn:uuid"
|
|
3643
|
+
"urn:uuid",
|
|
3644
|
+
"mailto"
|
|
3525
3645
|
]
|
|
3526
3646
|
);
|
|
3527
3647
|
function isValidSchemeName(name) {
|
|
@@ -3573,9 +3693,10 @@ var require_schemes = __commonJS({
|
|
|
3573
3693
|
wsComponent.secure = void 0;
|
|
3574
3694
|
}
|
|
3575
3695
|
if (wsComponent.resourceName) {
|
|
3576
|
-
const
|
|
3696
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3697
|
+
const path5 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3577
3698
|
wsComponent.path = path5 && path5 !== "/" ? path5 : void 0;
|
|
3578
|
-
wsComponent.query =
|
|
3699
|
+
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3579
3700
|
wsComponent.resourceName = void 0;
|
|
3580
3701
|
}
|
|
3581
3702
|
wsComponent.fragment = void 0;
|
|
@@ -3587,7 +3708,7 @@ var require_schemes = __commonJS({
|
|
|
3587
3708
|
return urnComponent;
|
|
3588
3709
|
}
|
|
3589
3710
|
const matches = urnComponent.path.match(URN_REG);
|
|
3590
|
-
if (matches) {
|
|
3711
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
3591
3712
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
3592
3713
|
urnComponent.nid = matches[1].toLowerCase();
|
|
3593
3714
|
urnComponent.nss = matches[2];
|
|
@@ -3687,6 +3808,242 @@ var require_schemes = __commonJS({
|
|
|
3687
3808
|
skipNormalize: true
|
|
3688
3809
|
}
|
|
3689
3810
|
);
|
|
3811
|
+
var LOCAL_PART_ALLOWED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*+=";
|
|
3812
|
+
var HFNAME_ALLOWED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*+,;:@";
|
|
3813
|
+
var DTEXT_ALLOWED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*+;:";
|
|
3814
|
+
function allowSet(chars, allowNonAscii = false) {
|
|
3815
|
+
const table = new Uint8Array(128);
|
|
3816
|
+
for (let i = 0; i < chars.length; i++) {
|
|
3817
|
+
table[chars.charCodeAt(i)] = 1;
|
|
3818
|
+
}
|
|
3819
|
+
const escaped = chars.replace(/[\\\]^-]/gu, "\\$&");
|
|
3820
|
+
const cls = allowNonAscii ? `[${escaped}]|[^\\0-\\x7F\\uD800-\\uDFFF]` : `[${escaped}]`;
|
|
3821
|
+
return { all: new RegExp(`^(?:${cls})*$`, "u"), table, allowNonAscii };
|
|
3822
|
+
}
|
|
3823
|
+
var LOCAL_PART = allowSet(LOCAL_PART_ALLOWED);
|
|
3824
|
+
var HFNAME = allowSet(HFNAME_ALLOWED);
|
|
3825
|
+
var DTEXT = allowSet(DTEXT_ALLOWED);
|
|
3826
|
+
var DTEXT_IRI = allowSet(DTEXT_ALLOWED, true);
|
|
3827
|
+
var HEX_PAIR = /^[\da-f]{2}$/iu;
|
|
3828
|
+
var MAILTO_DOMAIN_LITERAL = /^\[[\x21-\x5A\x5E-\x7E]*\]$/u;
|
|
3829
|
+
var MAILTO_DOMAIN_ERROR = "URI mailto has an invalid recipient domain.";
|
|
3830
|
+
var HAS_SURROGATE = /[\uD800-\uDFFF]/u;
|
|
3831
|
+
function decodeHex(str) {
|
|
3832
|
+
if (typeof str !== "string" || str.indexOf("%") === -1) {
|
|
3833
|
+
return str;
|
|
3834
|
+
}
|
|
3835
|
+
try {
|
|
3836
|
+
return decodeURIComponent(str);
|
|
3837
|
+
} catch {
|
|
3838
|
+
return str;
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
function replaceLoneSurrogates(input) {
|
|
3842
|
+
let result = "";
|
|
3843
|
+
for (let i = 0; i < input.length; i++) {
|
|
3844
|
+
const code = input.charCodeAt(i);
|
|
3845
|
+
if (code >= 55296 && code <= 56319 && i + 1 < input.length) {
|
|
3846
|
+
const low = input.charCodeAt(i + 1);
|
|
3847
|
+
if (low >= 56320 && low <= 57343) {
|
|
3848
|
+
result += input[i] + input[i + 1];
|
|
3849
|
+
i++;
|
|
3850
|
+
continue;
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3853
|
+
result += code >= 55296 && code <= 57343 ? "\uFFFD" : input[i];
|
|
3854
|
+
}
|
|
3855
|
+
return result;
|
|
3856
|
+
}
|
|
3857
|
+
function encodeWithAllow(input, set2) {
|
|
3858
|
+
if (set2.all.test(input)) {
|
|
3859
|
+
return input;
|
|
3860
|
+
}
|
|
3861
|
+
const table = set2.table;
|
|
3862
|
+
let result = "";
|
|
3863
|
+
for (let i = 0; i < input.length; i++) {
|
|
3864
|
+
const code = input.charCodeAt(i);
|
|
3865
|
+
if (code < 128) {
|
|
3866
|
+
if (table[code] === 1) {
|
|
3867
|
+
result += input[i];
|
|
3868
|
+
} else if (code === 37 && i + 2 < input.length && HEX_PAIR.test(input.slice(i + 1, i + 3))) {
|
|
3869
|
+
result += "%" + input.slice(i + 1, i + 3).toUpperCase();
|
|
3870
|
+
i += 2;
|
|
3871
|
+
} else {
|
|
3872
|
+
result += BYTE_HEX[code];
|
|
3873
|
+
}
|
|
3874
|
+
continue;
|
|
3875
|
+
}
|
|
3876
|
+
if (code < 55296 || code > 57343) {
|
|
3877
|
+
result += set2.allowNonAscii ? input[i] : percentEncodeNonAscii(code);
|
|
3878
|
+
continue;
|
|
3879
|
+
}
|
|
3880
|
+
if (code <= 56319 && i + 1 < input.length) {
|
|
3881
|
+
const low = input.charCodeAt(i + 1);
|
|
3882
|
+
if (low >= 56320 && low <= 57343) {
|
|
3883
|
+
result += set2.allowNonAscii ? input[i] + input[i + 1] : percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3884
|
+
i++;
|
|
3885
|
+
continue;
|
|
3886
|
+
}
|
|
3887
|
+
}
|
|
3888
|
+
result += set2.allowNonAscii ? "\uFFFD" : percentEncodeNonAscii(65533);
|
|
3889
|
+
}
|
|
3890
|
+
return result;
|
|
3891
|
+
}
|
|
3892
|
+
function mailtoNormalizeDomain(domain2, options, component) {
|
|
3893
|
+
const normalizedDomain = String(domain2).toLowerCase();
|
|
3894
|
+
if (MAILTO_DOMAIN_LITERAL.test(normalizedDomain)) {
|
|
3895
|
+
return normalizedDomain;
|
|
3896
|
+
}
|
|
3897
|
+
if (normalizedDomain !== "" && !nonSimpleMailtoDomain(normalizedDomain)) {
|
|
3898
|
+
return normalizedDomain;
|
|
3899
|
+
}
|
|
3900
|
+
try {
|
|
3901
|
+
const parsedDomain = new URL("http://" + normalizedDomain);
|
|
3902
|
+
if (parsedDomain.username || parsedDomain.password || parsedDomain.port || parsedDomain.pathname !== "/" || parsedDomain.search || parsedDomain.hash || !parsedDomain.hostname) {
|
|
3903
|
+
throw new Error(MAILTO_DOMAIN_ERROR);
|
|
3904
|
+
}
|
|
3905
|
+
return options && options.unicodeSupport ? normalizedDomain : parsedDomain.hostname;
|
|
3906
|
+
} catch {
|
|
3907
|
+
if (component) {
|
|
3908
|
+
component.error = component.error || MAILTO_DOMAIN_ERROR;
|
|
3909
|
+
}
|
|
3910
|
+
return normalizedDomain;
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
function mailtoEncodeDomain(domain2, options) {
|
|
3914
|
+
const set2 = options && options.unicodeSupport ? DTEXT_IRI : DTEXT;
|
|
3915
|
+
if (domain2.length > 1 && domain2[0] === "[" && domain2[domain2.length - 1] === "]") {
|
|
3916
|
+
return "[" + encodeWithAllow(domain2.slice(1, -1), set2) + "]";
|
|
3917
|
+
}
|
|
3918
|
+
return encodeWithAllow(domain2, set2);
|
|
3919
|
+
}
|
|
3920
|
+
function mailtoParse(component, options) {
|
|
3921
|
+
const mailtoComponent = component;
|
|
3922
|
+
let rawPath = mailtoComponent.path;
|
|
3923
|
+
let rawQuery = mailtoComponent.query;
|
|
3924
|
+
if (rawPath && HAS_SURROGATE.test(rawPath)) rawPath = replaceLoneSurrogates(rawPath);
|
|
3925
|
+
if (rawQuery && HAS_SURROGATE.test(rawQuery)) rawQuery = replaceLoneSurrogates(rawQuery);
|
|
3926
|
+
const to = rawPath ? rawPath.indexOf(",") === -1 ? [rawPath] : rawPath.split(",") : [];
|
|
3927
|
+
mailtoComponent.path = void 0;
|
|
3928
|
+
if (rawQuery) {
|
|
3929
|
+
let headers = null;
|
|
3930
|
+
let start = 0;
|
|
3931
|
+
while (start <= rawQuery.length) {
|
|
3932
|
+
let end = rawQuery.indexOf("&", start);
|
|
3933
|
+
if (end === -1) end = rawQuery.length;
|
|
3934
|
+
const token = rawQuery.slice(start, end);
|
|
3935
|
+
start = end + 1;
|
|
3936
|
+
const eqIdx = token.indexOf("=");
|
|
3937
|
+
if (eqIdx !== token.lastIndexOf("=")) {
|
|
3938
|
+
mailtoComponent.error = mailtoComponent.error || "URI mailto has malformed header fields.";
|
|
3939
|
+
continue;
|
|
3940
|
+
}
|
|
3941
|
+
const name = decodeHex(eqIdx === -1 ? token : token.slice(0, eqIdx));
|
|
3942
|
+
const normalizedName = name.toLowerCase();
|
|
3943
|
+
const value = eqIdx === -1 ? "" : token.slice(eqIdx + 1);
|
|
3944
|
+
if (normalizedName === "to") {
|
|
3945
|
+
const addrs = value.split(",");
|
|
3946
|
+
for (let j = 0; j < addrs.length; j++) to.push(addrs[j]);
|
|
3947
|
+
continue;
|
|
3948
|
+
}
|
|
3949
|
+
if (normalizedName === "subject") {
|
|
3950
|
+
mailtoComponent.subject = decodeHex(value);
|
|
3951
|
+
continue;
|
|
3952
|
+
}
|
|
3953
|
+
if (normalizedName === "body") {
|
|
3954
|
+
mailtoComponent.body = decodeHex(value);
|
|
3955
|
+
continue;
|
|
3956
|
+
}
|
|
3957
|
+
if (headers === null) headers = /** @type {Record<string,string>} */
|
|
3958
|
+
/* @__PURE__ */ Object.create(null);
|
|
3959
|
+
headers[name] = decodeHex(value);
|
|
3960
|
+
}
|
|
3961
|
+
if (headers !== null) mailtoComponent.headers = headers;
|
|
3962
|
+
}
|
|
3963
|
+
mailtoComponent.query = void 0;
|
|
3964
|
+
for (let i = 0; i < to.length; i++) {
|
|
3965
|
+
const rawAddr = to[i];
|
|
3966
|
+
const atIdx = rawAddr.lastIndexOf("@");
|
|
3967
|
+
if (atIdx < 0) {
|
|
3968
|
+
mailtoComponent.error = mailtoComponent.error || MAILTO_DOMAIN_ERROR;
|
|
3969
|
+
to[i] = decodeHex(rawAddr);
|
|
3970
|
+
continue;
|
|
3971
|
+
}
|
|
3972
|
+
const local = decodeHex(rawAddr.slice(0, atIdx));
|
|
3973
|
+
const domain2 = mailtoNormalizeDomain(decodeHex(rawAddr.slice(atIdx + 1)), options, mailtoComponent);
|
|
3974
|
+
to[i] = local + "@" + domain2;
|
|
3975
|
+
}
|
|
3976
|
+
if (to.length) mailtoComponent.to = to;
|
|
3977
|
+
return mailtoComponent;
|
|
3978
|
+
}
|
|
3979
|
+
function mailtoEncodeHeaderName(name) {
|
|
3980
|
+
return encodeWithAllow(name.replace(/%/gu, "%25"), HFNAME);
|
|
3981
|
+
}
|
|
3982
|
+
function mailtoSerialize(component, options) {
|
|
3983
|
+
const mailtoComponent = component;
|
|
3984
|
+
const to = Array.isArray(mailtoComponent.to) ? mailtoComponent.to.slice() : [];
|
|
3985
|
+
const sourceHeaders = mailtoComponent.headers && typeof mailtoComponent.headers === "object" ? Object.assign(/* @__PURE__ */ Object.create(null), mailtoComponent.headers) : /* @__PURE__ */ Object.create(null);
|
|
3986
|
+
const headers = /* @__PURE__ */ Object.create(null);
|
|
3987
|
+
for (const name in sourceHeaders) {
|
|
3988
|
+
const normalizedName = name.toLowerCase();
|
|
3989
|
+
if (normalizedName === "to") {
|
|
3990
|
+
const addrs = String(sourceHeaders[name]).split(",");
|
|
3991
|
+
for (let i = 0; i < addrs.length; i++) to.push(addrs[i]);
|
|
3992
|
+
} else if (normalizedName === "subject" || normalizedName === "body") {
|
|
3993
|
+
headers[normalizedName] = sourceHeaders[name];
|
|
3994
|
+
} else {
|
|
3995
|
+
headers[name] = sourceHeaders[name];
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
if (mailtoComponent.subject !== void 0) headers.subject = mailtoComponent.subject;
|
|
3999
|
+
if (mailtoComponent.body !== void 0) headers.body = mailtoComponent.body;
|
|
4000
|
+
mailtoComponent.headers = headers;
|
|
4001
|
+
if (to.length) {
|
|
4002
|
+
for (let i = 0; i < to.length; i++) {
|
|
4003
|
+
const addr = String(to[i]);
|
|
4004
|
+
const atIdx = addr.lastIndexOf("@");
|
|
4005
|
+
const rawLocal = atIdx >= 0 ? addr.slice(0, atIdx) : addr;
|
|
4006
|
+
const rawDomain = atIdx >= 0 ? addr.slice(atIdx + 1) : "";
|
|
4007
|
+
const local = encodeWithAllow(rawLocal, LOCAL_PART);
|
|
4008
|
+
const decodedDomain = decodeHex(rawDomain);
|
|
4009
|
+
const normalizedDomain = mailtoNormalizeDomain(decodedDomain, options);
|
|
4010
|
+
to[i] = local + "@" + mailtoEncodeDomain(normalizedDomain, options);
|
|
4011
|
+
}
|
|
4012
|
+
mailtoComponent.path = to.join(",");
|
|
4013
|
+
options.skipEscape = true;
|
|
4014
|
+
} else {
|
|
4015
|
+
mailtoComponent.path = void 0;
|
|
4016
|
+
}
|
|
4017
|
+
let query = "";
|
|
4018
|
+
let count = 0;
|
|
4019
|
+
for (const name in headers) {
|
|
4020
|
+
if (count++ !== 0) query += "&";
|
|
4021
|
+
query += mailtoEncodeHeaderName(name) + "=" + encodeWithAllow(String(headers[name]), HFNAME);
|
|
4022
|
+
}
|
|
4023
|
+
if (count !== 0) {
|
|
4024
|
+
mailtoComponent.query = query;
|
|
4025
|
+
} else {
|
|
4026
|
+
mailtoComponent.headers = void 0;
|
|
4027
|
+
}
|
|
4028
|
+
return mailtoComponent;
|
|
4029
|
+
}
|
|
4030
|
+
var mailto = (
|
|
4031
|
+
/** @type {SchemeHandler} */
|
|
4032
|
+
{
|
|
4033
|
+
scheme: "mailto",
|
|
4034
|
+
parse: mailtoParse,
|
|
4035
|
+
serialize: mailtoSerialize,
|
|
4036
|
+
domainHost: false,
|
|
4037
|
+
unicodeSupport: true,
|
|
4038
|
+
// `mailtoParse` re-derives every component from the raw path/query via
|
|
4039
|
+
// `decodeHex`, which subsumes the generic normalizers, so running them first
|
|
4040
|
+
// is wasted work (~28% of parsing a URI with header fields).
|
|
4041
|
+
skipNormalize: true,
|
|
4042
|
+
// A recipient list has no dot segments to remove, and `removeDotSegments`
|
|
4043
|
+
// would rewrite a "./"-prefixed local part.
|
|
4044
|
+
absolutePath: true
|
|
4045
|
+
}
|
|
4046
|
+
);
|
|
3690
4047
|
var SCHEMES = (
|
|
3691
4048
|
/** @type {Record<SchemeName, SchemeHandler>} */
|
|
3692
4049
|
{
|
|
@@ -3695,7 +4052,8 @@ var require_schemes = __commonJS({
|
|
|
3695
4052
|
ws,
|
|
3696
4053
|
wss,
|
|
3697
4054
|
urn,
|
|
3698
|
-
"urn:uuid": urnuuid
|
|
4055
|
+
"urn:uuid": urnuuid,
|
|
4056
|
+
mailto
|
|
3699
4057
|
}
|
|
3700
4058
|
);
|
|
3701
4059
|
Object.setPrototypeOf(SCHEMES, null);
|
|
@@ -3717,12 +4075,21 @@ var require_schemes = __commonJS({
|
|
|
3717
4075
|
}
|
|
3718
4076
|
});
|
|
3719
4077
|
|
|
3720
|
-
// ../../node_modules/.pnpm/fast-uri@4.1.
|
|
4078
|
+
// ../../node_modules/.pnpm/fast-uri@4.1.5/node_modules/fast-uri/index.js
|
|
3721
4079
|
var require_fast_uri = __commonJS({
|
|
3722
|
-
"../../node_modules/.pnpm/fast-uri@4.1.
|
|
4080
|
+
"../../node_modules/.pnpm/fast-uri@4.1.5/node_modules/fast-uri/index.js"(exports2, module2) {
|
|
3723
4081
|
"use strict";
|
|
3724
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, normalizeQueryFragmentEncoding,
|
|
4082
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3725
4083
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
4084
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
4085
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
4086
|
+
function decodeValidScheme(scheme) {
|
|
4087
|
+
const decodedScheme = unescape(String(scheme));
|
|
4088
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
4089
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
4090
|
+
}
|
|
4091
|
+
return decodedScheme;
|
|
4092
|
+
}
|
|
3726
4093
|
function normalize(uri, options) {
|
|
3727
4094
|
if (typeof uri === "string") {
|
|
3728
4095
|
uri = /** @type {T} */
|
|
@@ -3735,12 +4102,34 @@ var require_fast_uri = __commonJS({
|
|
|
3735
4102
|
}
|
|
3736
4103
|
function resolve(baseURI, relativeURI, options) {
|
|
3737
4104
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3738
|
-
const {
|
|
3739
|
-
|
|
3740
|
-
|
|
4105
|
+
const {
|
|
4106
|
+
parsed: baseParsed,
|
|
4107
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
4108
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
4109
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
4110
|
+
malformedHost: baseMalformedHost,
|
|
4111
|
+
malformedScheme: baseMalformedScheme
|
|
4112
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
4113
|
+
const {
|
|
4114
|
+
parsed: relativeParsed,
|
|
4115
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
4116
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
4117
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
4118
|
+
malformedHost: relativeMalformedHost,
|
|
4119
|
+
malformedScheme: relativeMalformedScheme
|
|
4120
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
4121
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
3741
4122
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3742
4123
|
}
|
|
3743
4124
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
4125
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
4126
|
+
const resolvedHost = resolved.host;
|
|
4127
|
+
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
4128
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
4129
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !new RegExp("\\P{ASCII}", "u").test(resolvedHost);
|
|
4130
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
4131
|
+
throw new Error(resolved.error);
|
|
4132
|
+
}
|
|
3744
4133
|
schemelessOptions.skipEscape = true;
|
|
3745
4134
|
return serialize(resolved, schemelessOptions);
|
|
3746
4135
|
}
|
|
@@ -3800,7 +4189,7 @@ var require_fast_uri = __commonJS({
|
|
|
3800
4189
|
function equal(uriA, uriB, options) {
|
|
3801
4190
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3802
4191
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3803
|
-
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA
|
|
4192
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
3804
4193
|
}
|
|
3805
4194
|
function serialize(cmpts, opts) {
|
|
3806
4195
|
const component = {
|
|
@@ -3817,23 +4206,30 @@ var require_fast_uri = __commonJS({
|
|
|
3817
4206
|
reference: cmpts.reference,
|
|
3818
4207
|
resourceName: cmpts.resourceName,
|
|
3819
4208
|
secure: cmpts.secure,
|
|
4209
|
+
to: cmpts.to,
|
|
4210
|
+
subject: cmpts.subject,
|
|
4211
|
+
body: cmpts.body,
|
|
4212
|
+
headers: cmpts.headers,
|
|
3820
4213
|
error: ""
|
|
3821
4214
|
};
|
|
3822
4215
|
const options = Object.assign({}, opts);
|
|
3823
4216
|
const uriTokens = [];
|
|
4217
|
+
if (component.scheme) {
|
|
4218
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
4219
|
+
}
|
|
3824
4220
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3825
4221
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
4222
|
+
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
4223
|
+
const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
|
|
3826
4224
|
if (component.path !== void 0) {
|
|
3827
4225
|
if (!options.skipEscape) {
|
|
3828
|
-
component.path =
|
|
3829
|
-
if (component.scheme !== void 0) {
|
|
3830
|
-
component.path = component.path.split("%3A").join(":");
|
|
3831
|
-
}
|
|
4226
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
3832
4227
|
} else {
|
|
3833
4228
|
component.path = normalizePercentEncoding(component.path);
|
|
3834
4229
|
}
|
|
3835
4230
|
}
|
|
3836
4231
|
if (options.reference !== "suffix" && component.scheme) {
|
|
4232
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3837
4233
|
uriTokens.push(component.scheme, ":");
|
|
3838
4234
|
}
|
|
3839
4235
|
const authority = recomposeAuthority(component);
|
|
@@ -3851,16 +4247,19 @@ var require_fast_uri = __commonJS({
|
|
|
3851
4247
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3852
4248
|
s = removeDotSegments(s);
|
|
3853
4249
|
}
|
|
4250
|
+
if (pathNoScheme) {
|
|
4251
|
+
s = serializePathEncoding(s, true);
|
|
4252
|
+
}
|
|
3854
4253
|
if (authority === void 0 && s[0] === "/" && s[1] === "/") {
|
|
3855
4254
|
s = "/%2F" + s.slice(2);
|
|
3856
4255
|
}
|
|
3857
4256
|
uriTokens.push(s);
|
|
3858
4257
|
}
|
|
3859
4258
|
if (component.query !== void 0) {
|
|
3860
|
-
uriTokens.push("?", component.query);
|
|
4259
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
3861
4260
|
}
|
|
3862
4261
|
if (component.fragment !== void 0) {
|
|
3863
|
-
uriTokens.push("#", component.fragment);
|
|
4262
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
3864
4263
|
}
|
|
3865
4264
|
return uriTokens.join("");
|
|
3866
4265
|
}
|
|
@@ -3876,6 +4275,36 @@ var require_fast_uri = __commonJS({
|
|
|
3876
4275
|
}
|
|
3877
4276
|
return void 0;
|
|
3878
4277
|
}
|
|
4278
|
+
function hasMalformedPercentEncoding(component) {
|
|
4279
|
+
if (component === void 0) return false;
|
|
4280
|
+
let percent = component.indexOf("%");
|
|
4281
|
+
while (percent !== -1) {
|
|
4282
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
4283
|
+
return true;
|
|
4284
|
+
}
|
|
4285
|
+
percent = component.indexOf("%", percent + 3);
|
|
4286
|
+
}
|
|
4287
|
+
return false;
|
|
4288
|
+
}
|
|
4289
|
+
function isIPLiteral(host) {
|
|
4290
|
+
return host[0] === "[" && host[host.length - 1] === "]";
|
|
4291
|
+
}
|
|
4292
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
4293
|
+
const host = matches[4];
|
|
4294
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
4295
|
+
}
|
|
4296
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
4297
|
+
const bracketedIPLiteral = parsed.host && parsed.host[0] === "[" && parsed.host[parsed.host.length - 1] === "]";
|
|
4298
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && !bracketedIPLiteral && nonSimpleDomain(parsed.host)) {
|
|
4299
|
+
try {
|
|
4300
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
4301
|
+
} catch (e) {
|
|
4302
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
4303
|
+
return true;
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
return false;
|
|
4307
|
+
}
|
|
3879
4308
|
function parseWithStatus(uri, opts) {
|
|
3880
4309
|
const options = Object.assign({}, opts);
|
|
3881
4310
|
const parsed = {
|
|
@@ -3888,6 +4317,11 @@ var require_fast_uri = __commonJS({
|
|
|
3888
4317
|
fragment: void 0
|
|
3889
4318
|
};
|
|
3890
4319
|
let malformedAuthorityOrPort = false;
|
|
4320
|
+
let malformedPercentEncoding = false;
|
|
4321
|
+
let malformedSchemeSpecific = false;
|
|
4322
|
+
let malformedHost = false;
|
|
4323
|
+
let malformedIPLiteral = false;
|
|
4324
|
+
let malformedScheme = false;
|
|
3891
4325
|
let isIP = false;
|
|
3892
4326
|
if (options.reference === "suffix") {
|
|
3893
4327
|
if (options.scheme) {
|
|
@@ -3917,13 +4351,26 @@ var require_fast_uri = __commonJS({
|
|
|
3917
4351
|
}
|
|
3918
4352
|
const matches = uri.match(URI_PARSE);
|
|
3919
4353
|
if (matches) {
|
|
3920
|
-
parsed.scheme = matches[1]
|
|
4354
|
+
parsed.scheme = matches[1];
|
|
3921
4355
|
parsed.userinfo = matches[3];
|
|
3922
4356
|
parsed.host = matches[4];
|
|
3923
4357
|
parsed.port = parseInt(matches[5], 10);
|
|
3924
4358
|
parsed.path = matches[6] || "";
|
|
3925
4359
|
parsed.query = matches[7];
|
|
3926
4360
|
parsed.fragment = matches[8];
|
|
4361
|
+
if (parsed.scheme !== void 0) {
|
|
4362
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
4363
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
4364
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
4365
|
+
} else {
|
|
4366
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
4367
|
+
malformedScheme = true;
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
4371
|
+
if (malformedPercentEncoding) {
|
|
4372
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
4373
|
+
}
|
|
3927
4374
|
if (isNaN(parsed.port)) {
|
|
3928
4375
|
parsed.port = matches[5];
|
|
3929
4376
|
}
|
|
@@ -3935,9 +4382,16 @@ var require_fast_uri = __commonJS({
|
|
|
3935
4382
|
if (parsed.host) {
|
|
3936
4383
|
const ipv4result = isIPv4(parsed.host);
|
|
3937
4384
|
if (ipv4result === false) {
|
|
4385
|
+
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
4386
|
+
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
3938
4387
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
3939
|
-
|
|
3940
|
-
|
|
4388
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4389
|
+
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
4390
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4391
|
+
if (malformedIPLiteral) {
|
|
4392
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
4393
|
+
malformedAuthorityOrPort = true;
|
|
4394
|
+
}
|
|
3941
4395
|
} else {
|
|
3942
4396
|
isIP = true;
|
|
3943
4397
|
}
|
|
@@ -3955,24 +4409,17 @@ var require_fast_uri = __commonJS({
|
|
|
3955
4409
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
3956
4410
|
}
|
|
3957
4411
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
3958
|
-
if (!
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
4412
|
+
if (!malformedIPLiteral) {
|
|
4413
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
4414
|
+
}
|
|
4415
|
+
if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
|
|
4416
|
+
let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4417
|
+
if (!isIP) {
|
|
4418
|
+
host = normalizePercentEncoding(host.toLowerCase());
|
|
3965
4419
|
}
|
|
4420
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
3966
4421
|
}
|
|
3967
4422
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
3968
|
-
if (uri.indexOf("%") !== -1) {
|
|
3969
|
-
if (parsed.scheme !== void 0) {
|
|
3970
|
-
parsed.scheme = unescape(parsed.scheme);
|
|
3971
|
-
}
|
|
3972
|
-
if (parsed.host !== void 0) {
|
|
3973
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
3974
|
-
}
|
|
3975
|
-
}
|
|
3976
4423
|
if (parsed.path) {
|
|
3977
4424
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3978
4425
|
}
|
|
@@ -3985,11 +4432,14 @@ var require_fast_uri = __commonJS({
|
|
|
3985
4432
|
}
|
|
3986
4433
|
if (schemeHandler && schemeHandler.parse) {
|
|
3987
4434
|
schemeHandler.parse(parsed, options);
|
|
4435
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
|
|
4436
|
+
malformedSchemeSpecific = true;
|
|
4437
|
+
}
|
|
3988
4438
|
}
|
|
3989
4439
|
} else {
|
|
3990
4440
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3991
4441
|
}
|
|
3992
|
-
return { parsed, malformedAuthorityOrPort };
|
|
4442
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
3993
4443
|
}
|
|
3994
4444
|
function parse4(uri, opts) {
|
|
3995
4445
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -3998,20 +4448,28 @@ var require_fast_uri = __commonJS({
|
|
|
3998
4448
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3999
4449
|
}
|
|
4000
4450
|
function normalizeStringWithStatus(uri, opts) {
|
|
4001
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
4451
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
4002
4452
|
return {
|
|
4003
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
4004
|
-
malformedAuthorityOrPort
|
|
4453
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
4454
|
+
malformedAuthorityOrPort,
|
|
4455
|
+
malformedPercentEncoding,
|
|
4456
|
+
malformedSchemeSpecific,
|
|
4457
|
+
malformedHost,
|
|
4458
|
+
malformedScheme
|
|
4005
4459
|
};
|
|
4006
4460
|
}
|
|
4007
4461
|
function normalizeComparableURI(uri, opts) {
|
|
4008
|
-
if (typeof uri
|
|
4009
|
-
|
|
4010
|
-
return malformedAuthorityOrPort ? void 0 : normalized;
|
|
4462
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
4463
|
+
return void 0;
|
|
4011
4464
|
}
|
|
4012
|
-
|
|
4013
|
-
|
|
4465
|
+
let value;
|
|
4466
|
+
try {
|
|
4467
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
4468
|
+
} catch {
|
|
4469
|
+
return void 0;
|
|
4014
4470
|
}
|
|
4471
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
4472
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
|
|
4015
4473
|
}
|
|
4016
4474
|
var fastUri = {
|
|
4017
4475
|
SCHEMES,
|
|
@@ -36075,6 +36533,7 @@ var IssueScopeSchema = external_exports3.enum([
|
|
|
36075
36533
|
]);
|
|
36076
36534
|
var SearchStrategySchema = external_exports3.enum([
|
|
36077
36535
|
"merged",
|
|
36536
|
+
"orgs",
|
|
36078
36537
|
"starred",
|
|
36079
36538
|
"broad",
|
|
36080
36539
|
"maintained",
|
|
@@ -36082,6 +36541,7 @@ var SearchStrategySchema = external_exports3.enum([
|
|
|
36082
36541
|
]);
|
|
36083
36542
|
var CONCRETE_STRATEGIES = [
|
|
36084
36543
|
"merged",
|
|
36544
|
+
"orgs",
|
|
36085
36545
|
"starred",
|
|
36086
36546
|
"broad",
|
|
36087
36547
|
"maintained"
|
|
@@ -36181,7 +36641,9 @@ var SkippedIssueSchema = external_exports3.looseObject({
|
|
|
36181
36641
|
repo: external_exports3.string(),
|
|
36182
36642
|
number: external_exports3.number(),
|
|
36183
36643
|
title: external_exports3.string(),
|
|
36184
|
-
skippedAt: external_exports3.string()
|
|
36644
|
+
skippedAt: external_exports3.string(),
|
|
36645
|
+
/** Why it was skipped: the vetter's reasons, or absent for a manual skip (#343). */
|
|
36646
|
+
reason: external_exports3.string().optional()
|
|
36185
36647
|
});
|
|
36186
36648
|
var HorizonSchema = external_exports3.enum(["quick-win", "bigger-bet"]);
|
|
36187
36649
|
var SavedCandidateSchema = external_exports3.looseObject({
|
|
@@ -36215,13 +36677,20 @@ var ScoutPreferencesSchema = external_exports3.looseObject({
|
|
|
36215
36677
|
scope: external_exports3.array(IssueScopeSchema).optional(),
|
|
36216
36678
|
excludeRepos: external_exports3.array(external_exports3.string()).default([]),
|
|
36217
36679
|
excludeOrgs: external_exports3.array(external_exports3.string()).default([]),
|
|
36680
|
+
// Orgs whose repos the "orgs" search phase targets with org: qualifiers.
|
|
36681
|
+
// Empty (the default) disables the phase even when the strategy is enabled.
|
|
36682
|
+
preferredOrgs: external_exports3.array(external_exports3.string()).default([]),
|
|
36218
36683
|
aiPolicyBlocklist: external_exports3.array(external_exports3.string()).default(["matplotlib/matplotlib"]),
|
|
36219
36684
|
projectCategories: external_exports3.array(ProjectCategorySchema).default([]),
|
|
36220
36685
|
minStars: external_exports3.number().default(50),
|
|
36221
36686
|
maxIssueAgeDays: external_exports3.number().default(90),
|
|
36222
36687
|
includeDocIssues: external_exports3.boolean().default(true),
|
|
36223
36688
|
minRepoScoreThreshold: external_exports3.number().default(4),
|
|
36224
|
-
|
|
36689
|
+
// Fixed pause before a search moves on to the next strategy. Defaults to
|
|
36690
|
+
// 0 (#334): SearchBudgetTracker already paces every search call against
|
|
36691
|
+
// the 30/min window and the pre-flight quota, so the old 30s pin only
|
|
36692
|
+
// added wall clock. Retained as a knob for hosts that want spacing.
|
|
36693
|
+
interPhaseDelayMs: external_exports3.number().min(0).max(12e4).default(0),
|
|
36225
36694
|
persistence: PersistenceModeSchema.default("local"),
|
|
36226
36695
|
defaultStrategy: external_exports3.array(SearchStrategySchema).optional(),
|
|
36227
36696
|
/**
|
|
@@ -36315,11 +36784,30 @@ var ScoutStateSchema = external_exports3.looseObject({
|
|
|
36315
36784
|
* variant leads each run. `languageOffset` advances (no modulo; the
|
|
36316
36785
|
* consumer wraps at use time so a shrinking language list never needs
|
|
36317
36786
|
* clamping here).
|
|
36787
|
+
*
|
|
36788
|
+
* `phase0Offset`, `starredOffset` and `maintainedOffset` do the same for the
|
|
36789
|
+
* repo lists those phases cap per run (#324, #333): each run searches the
|
|
36790
|
+
* next window of the list instead of always the first N, so every
|
|
36791
|
+
* contributed/starred repo gets searched within a few runs.
|
|
36792
|
+
*
|
|
36793
|
+
* `strategyOffset` is the round-robin cursor (#336): a position in
|
|
36794
|
+
* CONCRETE_STRATEGIES. A search runs the first usable strategy from there,
|
|
36795
|
+
* and the cursor moves to just after the strategy that led.
|
|
36318
36796
|
*/
|
|
36319
36797
|
searchRotation: external_exports3.looseObject({
|
|
36320
36798
|
languageOffset: external_exports3.number().int().min(0).default(0),
|
|
36799
|
+
phase0Offset: external_exports3.number().int().min(0).default(0),
|
|
36800
|
+
starredOffset: external_exports3.number().int().min(0).default(0),
|
|
36801
|
+
maintainedOffset: external_exports3.number().int().min(0).default(0),
|
|
36802
|
+
strategyOffset: external_exports3.number().int().min(0).default(0),
|
|
36321
36803
|
lastRotatedAt: external_exports3.string().optional()
|
|
36322
|
-
}).default(() => ({
|
|
36804
|
+
}).default(() => ({
|
|
36805
|
+
languageOffset: 0,
|
|
36806
|
+
phase0Offset: 0,
|
|
36807
|
+
starredOffset: 0,
|
|
36808
|
+
maintainedOffset: 0,
|
|
36809
|
+
strategyOffset: 0
|
|
36810
|
+
}))
|
|
36323
36811
|
});
|
|
36324
36812
|
function parseScoutState(raw) {
|
|
36325
36813
|
return ScoutStateSchema.parse(raw);
|
|
@@ -36341,6 +36829,18 @@ function isDocOnlyIssue(item) {
|
|
|
36341
36829
|
return false;
|
|
36342
36830
|
return nonEmptyLabels.every((n) => DOC_ONLY_LABELS.has(n));
|
|
36343
36831
|
}
|
|
36832
|
+
var NON_ACTIONABLE_LABELS = /* @__PURE__ */ new Set(["question", "discussion", "support"]);
|
|
36833
|
+
function isNonActionableIssue(item) {
|
|
36834
|
+
const labelNames = (item.labels ?? []).map((l) => (typeof l === "string" ? l : l.name || "").toLowerCase());
|
|
36835
|
+
if (labelNames.some((n) => NON_ACTIONABLE_LABELS.has(n)))
|
|
36836
|
+
return true;
|
|
36837
|
+
const title = (item.title ?? "").trim();
|
|
36838
|
+
if (title.endsWith("?"))
|
|
36839
|
+
return true;
|
|
36840
|
+
if (/^(how|why|what|when|where|which|who|is|are|does|do|can|could|should|would|will|has|have)\b/i.test(title))
|
|
36841
|
+
return true;
|
|
36842
|
+
return title.split(/\s+/).filter(Boolean).length < 3;
|
|
36843
|
+
}
|
|
36344
36844
|
var BEGINNER_LABELS = /* @__PURE__ */ new Set([
|
|
36345
36845
|
"good first issue",
|
|
36346
36846
|
"hacktoberfest",
|
|
@@ -37049,16 +37549,10 @@ async function checkNotClaimed(octokit, owner, repo, issueNumber, commentCount)
|
|
|
37049
37549
|
function analyzeRequirements(body) {
|
|
37050
37550
|
if (!body || body.length < 50)
|
|
37051
37551
|
return false;
|
|
37052
|
-
const hasSteps =
|
|
37053
|
-
const
|
|
37054
|
-
const
|
|
37055
|
-
|
|
37056
|
-
hasSteps,
|
|
37057
|
-
hasCodeBlock,
|
|
37058
|
-
hasExpectedBehavior,
|
|
37059
|
-
body.length > 200
|
|
37060
|
-
];
|
|
37061
|
-
return indicators.filter(Boolean).length >= 2;
|
|
37552
|
+
const hasSteps = /(^|\n)\s*\d+[.)]\s/.test(body) || /steps?\s+to\s+reproduce|\brepro(duction)?\b/i.test(body);
|
|
37553
|
+
const hasExpectedVsActual = /\b(expected|should)\b/i.test(body) && /\b(actual(ly)?|instead|but|currently|observed|got)\b/i.test(body);
|
|
37554
|
+
const hasCodeRef = /```|`[^`\n]+`/.test(body) || /\b[\w/.-]+\.(ts|tsx|js|jsx|mjs|cjs|py|rb|go|rs|java|kt|swift|c|cc|cpp|h|hpp|cs|php|sh|vue|svelte)\b/.test(body) || /^\s+at\s+\S+\s+\(/m.test(body);
|
|
37555
|
+
return hasCodeRef || hasSteps && hasExpectedVsActual;
|
|
37062
37556
|
}
|
|
37063
37557
|
|
|
37064
37558
|
// ../core/dist/core/probe-repo-file.js
|
|
@@ -38168,8 +38662,8 @@ var IssueVetter = class {
|
|
|
38168
38662
|
|
|
38169
38663
|
// ../core/dist/core/search-phases.js
|
|
38170
38664
|
var MODULE11 = "search-phases";
|
|
38171
|
-
var GITHUB_MAX_BOOLEAN_OPS = 5;
|
|
38172
38665
|
var INTER_QUERY_DELAY_MS = 2e3;
|
|
38666
|
+
var KNOWN_REPO_PER_REPO_CAP = 2;
|
|
38173
38667
|
var GRAPHQL_INTER_QUERY_DELAY_MS = 500;
|
|
38174
38668
|
var graphqlSearchQueryCount = 0;
|
|
38175
38669
|
function getGraphQLSearchQueryCount() {
|
|
@@ -38178,29 +38672,10 @@ function getGraphQLSearchQueryCount() {
|
|
|
38178
38672
|
function resetGraphQLSearchQueryCount() {
|
|
38179
38673
|
graphqlSearchQueryCount = 0;
|
|
38180
38674
|
}
|
|
38181
|
-
function chunkLabels(labels, reservedOps = 0) {
|
|
38182
|
-
const maxPerChunk = GITHUB_MAX_BOOLEAN_OPS - reservedOps + 1;
|
|
38183
|
-
if (maxPerChunk < 1) {
|
|
38184
|
-
if (labels.length > 0) {
|
|
38185
|
-
warn(MODULE11, `Label filtering disabled: ${reservedOps} repo/org ORs exceed GitHub's ${GITHUB_MAX_BOOLEAN_OPS} operator limit. All ${labels.length} label(s) dropped from query.`);
|
|
38186
|
-
}
|
|
38187
|
-
return [[]];
|
|
38188
|
-
}
|
|
38189
|
-
if (labels.length <= maxPerChunk)
|
|
38190
|
-
return [labels];
|
|
38191
|
-
const chunks = [];
|
|
38192
|
-
for (let i = 0; i < labels.length; i += maxPerChunk) {
|
|
38193
|
-
chunks.push(labels.slice(i, i + maxPerChunk));
|
|
38194
|
-
}
|
|
38195
|
-
debug(MODULE11, `Split ${labels.length} labels into ${chunks.length} chunks (${reservedOps} ops reserved, max ${maxPerChunk} per chunk)`);
|
|
38196
|
-
return chunks;
|
|
38197
|
-
}
|
|
38198
38675
|
function buildLabelQuery(labels) {
|
|
38199
38676
|
if (labels.length === 0)
|
|
38200
38677
|
return "";
|
|
38201
|
-
|
|
38202
|
-
return `label:"${labels[0]}"`;
|
|
38203
|
-
return `(${labels.map((l) => `label:"${l}"`).join(" OR ")})`;
|
|
38678
|
+
return `label:${labels.map((l) => JSON.stringify(l)).join(",")}`;
|
|
38204
38679
|
}
|
|
38205
38680
|
function buildEffectiveLabels(scopes, customLabels) {
|
|
38206
38681
|
const labels = /* @__PURE__ */ new Set();
|
|
@@ -38364,9 +38839,9 @@ async function fetchIssuesFromKnownRepos(octokit, vetter, repos, labels, maxResu
|
|
|
38364
38839
|
if (mapped.length > 0) {
|
|
38365
38840
|
const filtered = filterFn(mapped);
|
|
38366
38841
|
if (filtered.length > 0) {
|
|
38367
|
-
const remainingNeeded = maxResults - candidates.length;
|
|
38842
|
+
const remainingNeeded = Math.min(KNOWN_REPO_PER_REPO_CAP, maxResults - candidates.length);
|
|
38368
38843
|
const { candidates: vetted, rateLimitHit: vetRateLimitHit } = await vetter.vetIssuesParallel(filtered.slice(0, remainingNeeded * 2).map((item) => item.html_url), remainingNeeded, priority);
|
|
38369
|
-
candidates.push(...vetted);
|
|
38844
|
+
candidates.push(...vetted.slice(0, remainingNeeded));
|
|
38370
38845
|
if (vetRateLimitHit)
|
|
38371
38846
|
rateLimitFailures++;
|
|
38372
38847
|
}
|
|
@@ -38388,28 +38863,14 @@ async function fetchIssuesFromKnownRepos(octokit, vetter, repos, labels, maxResu
|
|
|
38388
38863
|
}
|
|
38389
38864
|
return { candidates, allReposFailed, rateLimitHit };
|
|
38390
38865
|
}
|
|
38391
|
-
async function searchWithChunkedLabels(octokit, labels,
|
|
38392
|
-
const
|
|
38393
|
-
|
|
38394
|
-
|
|
38395
|
-
|
|
38396
|
-
|
|
38397
|
-
|
|
38398
|
-
|
|
38399
|
-
const data = await searchIssuesGraphQLFirst(octokit, {
|
|
38400
|
-
q: query,
|
|
38401
|
-
sort: "created",
|
|
38402
|
-
order: "desc",
|
|
38403
|
-
per_page: perPage
|
|
38404
|
-
}, tracker);
|
|
38405
|
-
for (const item of data.items) {
|
|
38406
|
-
if (!seenUrls.has(item.html_url)) {
|
|
38407
|
-
seenUrls.add(item.html_url);
|
|
38408
|
-
allItems.push(item);
|
|
38409
|
-
}
|
|
38410
|
-
}
|
|
38411
|
-
}
|
|
38412
|
-
return allItems;
|
|
38866
|
+
async function searchWithChunkedLabels(octokit, labels, _reservedOps, buildQuery, perPage, tracker = getSearchBudgetTracker()) {
|
|
38867
|
+
const data = await searchIssuesGraphQLFirst(octokit, {
|
|
38868
|
+
q: buildQuery(buildLabelQuery(labels)),
|
|
38869
|
+
sort: "created",
|
|
38870
|
+
order: "desc",
|
|
38871
|
+
per_page: perPage
|
|
38872
|
+
}, tracker);
|
|
38873
|
+
return data.items;
|
|
38413
38874
|
}
|
|
38414
38875
|
function buildLanguageVariants(languages, isAnyLanguage, hasLabels) {
|
|
38415
38876
|
if (isAnyLanguage || languages.length === 0)
|
|
@@ -38420,7 +38881,7 @@ function buildLanguageVariants(languages, isAnyLanguage, hasLabels) {
|
|
|
38420
38881
|
return [languages.map((l) => `language:${l}`).join(" ")];
|
|
38421
38882
|
return languages.map((l) => `language:${l}`);
|
|
38422
38883
|
}
|
|
38423
|
-
async function searchAcrossLanguagesAndLabels(octokit, languages, isAnyLanguage, labels, buildBaseQuery, perPage, tracker = getSearchBudgetTracker(), startOffset = 0) {
|
|
38884
|
+
async function searchAcrossLanguagesAndLabels(octokit, languages, isAnyLanguage, labels, buildBaseQuery, perPage, tracker = getSearchBudgetTracker(), startOffset = 0, reservedOps = 0) {
|
|
38424
38885
|
const variants = buildLanguageVariants(languages, isAnyLanguage, labels.length > 0);
|
|
38425
38886
|
const k = variants.length > 0 ? startOffset % variants.length : 0;
|
|
38426
38887
|
const langVariants = [...variants.slice(k), ...variants.slice(0, k)];
|
|
@@ -38429,7 +38890,7 @@ async function searchAcrossLanguagesAndLabels(octokit, languages, isAnyLanguage,
|
|
|
38429
38890
|
for (let i = 0; i < langVariants.length; i++) {
|
|
38430
38891
|
if (i > 0)
|
|
38431
38892
|
await sleep(GRAPHQL_INTER_QUERY_DELAY_MS);
|
|
38432
|
-
const items = await searchWithChunkedLabels(octokit, labels,
|
|
38893
|
+
const items = await searchWithChunkedLabels(octokit, labels, reservedOps, (labelQ) => `${buildBaseQuery(langVariants[i])} ${labelQ}`.replace(/ +/g, " ").trim(), perPage, tracker);
|
|
38433
38894
|
for (const item of items) {
|
|
38434
38895
|
if (!seenUrls.has(item.html_url)) {
|
|
38435
38896
|
seenUrls.add(item.html_url);
|
|
@@ -38565,6 +39026,15 @@ var CRITICAL_BUDGET_THRESHOLD = 10;
|
|
|
38565
39026
|
var PHASE0_PER_PAGE = 30;
|
|
38566
39027
|
var CONTRIBUTED_REPO_MAX_AGE_DAYS = 365;
|
|
38567
39028
|
var PHASE0_MAX_SHARE = 0.5;
|
|
39029
|
+
var PHASE0_REPOS_PER_RUN = 10;
|
|
39030
|
+
var STARRED_REPOS_PER_RUN = 10;
|
|
39031
|
+
var MAINTAINED_REPOS_PER_RUN = 15;
|
|
39032
|
+
function rotatingWindow(items, size, offset) {
|
|
39033
|
+
if (items.length <= size)
|
|
39034
|
+
return [...items];
|
|
39035
|
+
const start = offset * size % items.length;
|
|
39036
|
+
return Array.from({ length: size }, (_, i) => items[(start + i) % items.length]);
|
|
39037
|
+
}
|
|
38568
39038
|
function buildIssueFilter(config2) {
|
|
38569
39039
|
return (items) => {
|
|
38570
39040
|
return items.filter((item) => {
|
|
@@ -38593,6 +39063,8 @@ function buildIssueFilter(config2) {
|
|
|
38593
39063
|
return false;
|
|
38594
39064
|
if (!config2.includeDocIssues && isDocOnlyIssue(item))
|
|
38595
39065
|
return false;
|
|
39066
|
+
if (isNonActionableIssue(item))
|
|
39067
|
+
return false;
|
|
38596
39068
|
return true;
|
|
38597
39069
|
});
|
|
38598
39070
|
};
|
|
@@ -38607,10 +39079,39 @@ async function runPhase0(octokit, vetter, repos, maxResults, filterIssues) {
|
|
|
38607
39079
|
rateLimitHit
|
|
38608
39080
|
};
|
|
38609
39081
|
}
|
|
39082
|
+
var MAX_QUERY_ORGS = 8;
|
|
39083
|
+
async function runPhaseOrgs(octokit, vetter, orgs, languages, isAnyLanguage, labels, maxResults, minStars, phase0RepoSet, starredRepoSet, filterIssues, tracker) {
|
|
39084
|
+
info(MODULE12, `Orgs phase: searching ${orgs.length} preferred org(s)...`);
|
|
39085
|
+
const queryOrgs = orgs.slice(0, MAX_QUERY_ORGS);
|
|
39086
|
+
if (orgs.length > MAX_QUERY_ORGS) {
|
|
39087
|
+
warn(MODULE12, `Orgs phase: capping query at ${MAX_QUERY_ORGS} org(s); dropping ${orgs.slice(MAX_QUERY_ORGS).join(", ")}`);
|
|
39088
|
+
}
|
|
39089
|
+
const orgQuery = queryOrgs.map((o) => `org:${o}`).join(" ");
|
|
39090
|
+
try {
|
|
39091
|
+
const allItems = await searchAcrossLanguagesAndLabels(octokit, languages, isAnyLanguage, labels, (langQ) => `is:issue is:open ${langQ} no:assignee ${orgQuery}`.replace(/ +/g, " ").trim(), maxResults * 3, tracker, 0, queryOrgs.length);
|
|
39092
|
+
const { candidates, allVetFailed, rateLimitHit } = await filterVetAndScore(vetter, allItems, filterIssues, [phase0RepoSet, starredRepoSet], maxResults, minStars, "Orgs phase");
|
|
39093
|
+
info(MODULE12, `Found ${candidates.length} candidates from preferred orgs`);
|
|
39094
|
+
return {
|
|
39095
|
+
candidates,
|
|
39096
|
+
error: allVetFailed ? "all vetting failed" : null,
|
|
39097
|
+
rateLimitHit
|
|
39098
|
+
};
|
|
39099
|
+
} catch (error48) {
|
|
39100
|
+
if (getHttpStatusCode(error48) === 401)
|
|
39101
|
+
throw error48;
|
|
39102
|
+
const errMsg = errorMessage(error48);
|
|
39103
|
+
warn(MODULE12, `Error in preferred-orgs search: ${errMsg}`);
|
|
39104
|
+
return {
|
|
39105
|
+
candidates: [],
|
|
39106
|
+
error: errMsg,
|
|
39107
|
+
rateLimitHit: isRateLimitError(error48)
|
|
39108
|
+
};
|
|
39109
|
+
}
|
|
39110
|
+
}
|
|
38610
39111
|
async function runPhase1(octokit, vetter, repos, labels, maxResults, filterIssues) {
|
|
38611
39112
|
info(MODULE12, `Phase 1: Searching issues in ${repos.length} starred repos...`);
|
|
38612
39113
|
const phase1Labels = labels.slice(0, 3);
|
|
38613
|
-
const reposToSearch = repos.slice(0,
|
|
39114
|
+
const reposToSearch = repos.slice(0, STARRED_REPOS_PER_RUN);
|
|
38614
39115
|
const { candidates, allReposFailed, rateLimitHit } = await fetchIssuesFromKnownRepos(octokit, vetter, reposToSearch, phase1Labels, maxResults, "starred", filterIssues);
|
|
38615
39116
|
info(MODULE12, `Found ${candidates.length} candidates from starred repos`);
|
|
38616
39117
|
return {
|
|
@@ -38681,13 +39182,13 @@ async function runPhase2(octokit, vetter, scopes, labels, configLabels, language
|
|
|
38681
39182
|
rateLimitHit
|
|
38682
39183
|
};
|
|
38683
39184
|
}
|
|
38684
|
-
async function runPhase3(octokit, vetter, langQuery, minStars, projectCategories, maxResults, phase0RepoSet, starredRepoSet, starredRepos, existingCandidates, filterIssues, tracker) {
|
|
39185
|
+
async function runPhase3(octokit, vetter, langQuery, minStars, projectCategories, maxResults, phase0RepoSet, starredRepoSet, starredRepos, existingCandidates, filterIssues, tracker, rotationOffset = 0) {
|
|
38685
39186
|
info(MODULE12, "Phase 3: Searching actively maintained repos...");
|
|
38686
39187
|
const seenRepos = new Set(existingCandidates.map((c) => c.issue.repo));
|
|
38687
|
-
const eligibleStarred = starredRepos.filter((r) => !phase0RepoSet.has(r) && !seenRepos.has(r));
|
|
39188
|
+
const eligibleStarred = rotatingWindow(starredRepos, MAINTAINED_REPOS_PER_RUN, rotationOffset).filter((r) => !phase0RepoSet.has(r) && !seenRepos.has(r));
|
|
38688
39189
|
if (eligibleStarred.length > 0) {
|
|
38689
39190
|
info(MODULE12, `Phase 3: Checking ${eligibleStarred.length} starred repos via REST API...`);
|
|
38690
|
-
const restItems = await fetchIssuesFromMaintainedRepos(octokit, eligibleStarred
|
|
39191
|
+
const restItems = await fetchIssuesFromMaintainedRepos(octokit, eligibleStarred, minStars, maxResults);
|
|
38691
39192
|
if (restItems.length > 0) {
|
|
38692
39193
|
try {
|
|
38693
39194
|
const { candidates, allVetFailed, rateLimitHit: vetRateLimitHit } = await filterVetAndScore(vetter, restItems, filterIssues, [phase0RepoSet, seenRepos], maxResults, minStars, "Phase 3 (REST)");
|
|
@@ -38805,7 +39306,7 @@ var IssueDiscovery = class {
|
|
|
38805
39306
|
const labels = options.labels || (scopes ? buildEffectiveLabels(scopes, config2.labels) : config2.labels);
|
|
38806
39307
|
const maxResults = options.maxResults || 10;
|
|
38807
39308
|
const minStars = config2.minStars ?? 50;
|
|
38808
|
-
const interPhaseDelay = options.interPhaseDelayMs ?? config2.interPhaseDelayMs ??
|
|
39309
|
+
const interPhaseDelay = options.interPhaseDelayMs ?? config2.interPhaseDelayMs ?? 0;
|
|
38809
39310
|
const ALL_STRATEGIES = CONCRETE_STRATEGIES;
|
|
38810
39311
|
const pickStrategies = (...candidates) => candidates.find((c) => c && c.length > 0) ?? ["all"];
|
|
38811
39312
|
const rawStrategies = pickStrategies(options.strategies, config2.defaultStrategy);
|
|
@@ -38885,78 +39386,114 @@ var IssueDiscovery = class {
|
|
|
38885
39386
|
...baseFilterConfig,
|
|
38886
39387
|
maxAgeDays: CONTRIBUTED_REPO_MAX_AGE_DAYS
|
|
38887
39388
|
});
|
|
38888
|
-
const
|
|
38889
|
-
const phase0Repos = [];
|
|
38890
|
-
for (const repo of [...mergedPRRepos, ...openPRRepos]) {
|
|
38891
|
-
if (seenPhase0.has(repo))
|
|
38892
|
-
continue;
|
|
38893
|
-
seenPhase0.add(repo);
|
|
38894
|
-
phase0Repos.push(repo);
|
|
38895
|
-
if (phase0Repos.length >= 10)
|
|
38896
|
-
break;
|
|
38897
|
-
}
|
|
39389
|
+
const repoRotation = options.repoRotationOffsets ?? {};
|
|
39390
|
+
const phase0Repos = rotatingWindow([.../* @__PURE__ */ new Set([...mergedPRRepos, ...openPRRepos])], PHASE0_REPOS_PER_RUN, repoRotation.merged ?? 0);
|
|
38898
39391
|
const phase0RepoSet = new Set(phase0Repos);
|
|
38899
|
-
const
|
|
38900
|
-
|
|
38901
|
-
|
|
38902
|
-
|
|
38903
|
-
|
|
38904
|
-
|
|
38905
|
-
|
|
38906
|
-
|
|
38907
|
-
|
|
38908
|
-
}
|
|
38909
|
-
|
|
38910
|
-
|
|
38911
|
-
|
|
38912
|
-
|
|
38913
|
-
|
|
38914
|
-
|
|
38915
|
-
|
|
38916
|
-
|
|
38917
|
-
|
|
38918
|
-
|
|
38919
|
-
|
|
38920
|
-
|
|
38921
|
-
|
|
38922
|
-
|
|
38923
|
-
|
|
38924
|
-
|
|
38925
|
-
if (viableBeforeBroad >= maxResults && enabledStrategies.has("broad")) {
|
|
38926
|
-
info(MODULE12, `Skipping broad search: ${viableBeforeBroad} viable candidate(s) already meet maxResults (${maxResults})`);
|
|
38927
|
-
} else if (enabledStrategies.has("broad")) {
|
|
38928
|
-
const newRepoCandidateCount = allCandidates.filter((c) => c.recommendation !== "skip" && !phase0RepoSet.has(c.issue.repo) && !starredRepoSet.has(c.issue.repo)).length;
|
|
38929
|
-
if (skipThreshold > 0 && newRepoCandidateCount >= skipThreshold) {
|
|
38930
|
-
info(MODULE12, `Skipping broad search: already found ${newRepoCandidateCount} viable candidate(s) from new repos (threshold: ${skipThreshold})`);
|
|
38931
|
-
} else {
|
|
38932
|
-
await applyInterPhaseDelay();
|
|
38933
|
-
if (allCandidates.length > 0 && broadDelay > 0) {
|
|
38934
|
-
info(MODULE12, `Waiting ${(broadDelay / 1e3).toFixed(0)}s for rate limit cooldown before broad search...`);
|
|
38935
|
-
await sleep(broadDelay);
|
|
38936
|
-
} else if (allCandidates.length === 0) {
|
|
38937
|
-
info(MODULE12, `Skipping broad phase delay: no results from previous phases, proceeding immediately`);
|
|
38938
|
-
}
|
|
38939
|
-
const remaining = maxResults - viableBeforeBroad;
|
|
38940
|
-
const result = await runPhase2(this.octokit, this.vetter, scopes, labels, config2.labels, languages, isAnyLanguage, remaining, minStars, phase0RepoSet, starredRepoSet, allCandidates, filterIssues, tracker, options.languageRotationOffset ?? 0);
|
|
38941
|
-
recordPhaseResult("2", result);
|
|
39392
|
+
const preferredOrgs = config2.preferredOrgs ?? [];
|
|
39393
|
+
const starredToSearch = rotatingWindow(starredRepos, STARRED_REPOS_PER_RUN, repoRotation.starred ?? 0).filter((r) => !phase0RepoSet.has(r));
|
|
39394
|
+
const canRun = {
|
|
39395
|
+
all: false,
|
|
39396
|
+
merged: phase0Repos.length > 0,
|
|
39397
|
+
orgs: preferredOrgs.length > 0,
|
|
39398
|
+
starred: starredToSearch.length > 0 && searchBudget >= CRITICAL_BUDGET_THRESHOLD,
|
|
39399
|
+
broad: true,
|
|
39400
|
+
maintained: true
|
|
39401
|
+
};
|
|
39402
|
+
const broadDelay = options.broadPhaseDelayMs ?? config2.broadPhaseDelayMs ?? 0;
|
|
39403
|
+
const runStrategy = {
|
|
39404
|
+
merged: async (wanted) => {
|
|
39405
|
+
recordPhaseResult("0", await runPhase0(this.octokit, this.vetter, phase0Repos, wanted, filterIssuesPhase0));
|
|
39406
|
+
strategiesUsed.push("merged");
|
|
39407
|
+
},
|
|
39408
|
+
orgs: async (wanted) => {
|
|
39409
|
+
recordPhaseResult("orgs", await runPhaseOrgs(this.octokit, this.vetter, preferredOrgs, languages, isAnyLanguage, labels, wanted, minStars, phase0RepoSet, starredRepoSet, filterIssues, tracker));
|
|
39410
|
+
strategiesUsed.push("orgs");
|
|
39411
|
+
},
|
|
39412
|
+
starred: async (wanted) => {
|
|
39413
|
+
recordPhaseResult("1", await runPhase1(this.octokit, this.vetter, starredToSearch, labels, wanted, filterIssues));
|
|
39414
|
+
strategiesUsed.push("starred");
|
|
39415
|
+
},
|
|
39416
|
+
broad: async (wanted) => {
|
|
39417
|
+
recordPhaseResult("2", await runPhase2(this.octokit, this.vetter, scopes, labels, config2.labels, languages, isAnyLanguage, wanted, minStars, phase0RepoSet, starredRepoSet, allCandidates, filterIssues, tracker, options.languageRotationOffset ?? 0));
|
|
38942
39418
|
strategiesUsed.push("broad");
|
|
39419
|
+
},
|
|
39420
|
+
maintained: async (wanted) => {
|
|
39421
|
+
recordPhaseResult("3", await runPhase3(this.octokit, this.vetter, langQuery, minStars, config2.projectCategories ?? [], wanted, phase0RepoSet, starredRepoSet, starredRepos, allCandidates, filterIssues, tracker, repoRotation.maintained ?? 0));
|
|
39422
|
+
strategiesUsed.push("maintained");
|
|
39423
|
+
}
|
|
39424
|
+
};
|
|
39425
|
+
let starredSkippedForBudget = searchBudget < CRITICAL_BUDGET_THRESHOLD;
|
|
39426
|
+
if (options.strategyRotationOffset !== void 0) {
|
|
39427
|
+
const cursor = options.strategyRotationOffset;
|
|
39428
|
+
const n = CONCRETE_STRATEGIES.length;
|
|
39429
|
+
const order = CONCRETE_STRATEGIES.map((_, i) => CONCRETE_STRATEGIES[(cursor + i) % n]).filter((s) => enabledStrategies.has(s));
|
|
39430
|
+
starredSkippedForBudget = false;
|
|
39431
|
+
for (const strategy of order) {
|
|
39432
|
+
if (!canRun[strategy]) {
|
|
39433
|
+
if (strategy === "starred" && starredToSearch.length > 0) {
|
|
39434
|
+
starredSkippedForBudget = true;
|
|
39435
|
+
}
|
|
39436
|
+
continue;
|
|
39437
|
+
}
|
|
39438
|
+
if (strategiesUsed.length > 0)
|
|
39439
|
+
await applyInterPhaseDelay();
|
|
39440
|
+
info(MODULE12, `Round-robin: running the ${strategy} strategy`);
|
|
39441
|
+
await runStrategy[strategy](maxResults - viableCandidateCount());
|
|
39442
|
+
if (viableCandidateCount() > 0)
|
|
39443
|
+
break;
|
|
39444
|
+
}
|
|
39445
|
+
} else {
|
|
39446
|
+
const orgsPhaseEnabled = canRun.orgs && enabledStrategies.has("orgs");
|
|
39447
|
+
const otherStrategiesCanRun = orgsPhaseEnabled || starredRepos.length > 0 && enabledStrategies.has("starred") || enabledStrategies.has("broad") || enabledStrategies.has("maintained");
|
|
39448
|
+
if (canRun.merged && enabledStrategies.has("merged")) {
|
|
39449
|
+
const phase0Cap = otherStrategiesCanRun ? Math.max(1, Math.ceil(maxResults * PHASE0_MAX_SHARE)) : maxResults;
|
|
39450
|
+
await runStrategy.merged(Math.min(maxResults - allCandidates.length, phase0Cap));
|
|
39451
|
+
}
|
|
39452
|
+
if (allCandidates.length < maxResults && orgsPhaseEnabled) {
|
|
39453
|
+
await applyInterPhaseDelay();
|
|
39454
|
+
await runStrategy.orgs(maxResults - allCandidates.length);
|
|
39455
|
+
}
|
|
39456
|
+
if (allCandidates.length < maxResults && starredRepos.length > 0 && searchBudget >= CRITICAL_BUDGET_THRESHOLD && enabledStrategies.has("starred")) {
|
|
39457
|
+
await applyInterPhaseDelay();
|
|
39458
|
+
if (starredToSearch.length > 0) {
|
|
39459
|
+
await runStrategy.starred(maxResults - allCandidates.length);
|
|
39460
|
+
}
|
|
39461
|
+
}
|
|
39462
|
+
const configuredSkipThreshold = config2.skipBroadWhenSufficientResults ?? 8;
|
|
39463
|
+
const skipThreshold = configuredSkipThreshold > 0 ? Math.min(configuredSkipThreshold, maxResults - 1) : 0;
|
|
39464
|
+
const viableBeforeBroad = viableCandidateCount();
|
|
39465
|
+
if (viableBeforeBroad >= maxResults && enabledStrategies.has("broad")) {
|
|
39466
|
+
info(MODULE12, `Skipping broad search: ${viableBeforeBroad} viable candidate(s) already meet maxResults (${maxResults})`);
|
|
39467
|
+
} else if (enabledStrategies.has("broad")) {
|
|
39468
|
+
const preferredOrgSet = new Set(preferredOrgs.map((o) => o.toLowerCase()));
|
|
39469
|
+
const newRepoCandidateCount = allCandidates.filter((c) => c.recommendation !== "skip" && !phase0RepoSet.has(c.issue.repo) && !starredRepoSet.has(c.issue.repo) && !preferredOrgSet.has(c.issue.repo.split("/")[0]?.toLowerCase() ?? "")).length;
|
|
39470
|
+
if (skipThreshold > 0 && newRepoCandidateCount >= skipThreshold) {
|
|
39471
|
+
info(MODULE12, `Skipping broad search: already found ${newRepoCandidateCount} viable candidate(s) from new repos (threshold: ${skipThreshold})`);
|
|
39472
|
+
} else {
|
|
39473
|
+
await applyInterPhaseDelay();
|
|
39474
|
+
if (allCandidates.length > 0 && broadDelay > 0) {
|
|
39475
|
+
info(MODULE12, `Waiting ${(broadDelay / 1e3).toFixed(0)}s for rate limit cooldown before broad search...`);
|
|
39476
|
+
await sleep(broadDelay);
|
|
39477
|
+
} else if (allCandidates.length === 0) {
|
|
39478
|
+
info(MODULE12, `Skipping broad phase delay: no results from previous phases, proceeding immediately`);
|
|
39479
|
+
}
|
|
39480
|
+
await runStrategy.broad(maxResults - viableBeforeBroad);
|
|
39481
|
+
}
|
|
39482
|
+
}
|
|
39483
|
+
const viableBeforeMaintained = viableCandidateCount();
|
|
39484
|
+
if (viableBeforeMaintained >= maxResults && enabledStrategies.has("maintained")) {
|
|
39485
|
+
info(MODULE12, `Skipping maintained search: ${viableBeforeMaintained} viable candidate(s) already meet maxResults (${maxResults})`);
|
|
39486
|
+
} else if (enabledStrategies.has("maintained")) {
|
|
39487
|
+
await applyInterPhaseDelay();
|
|
39488
|
+
await runStrategy.maintained(maxResults - viableBeforeMaintained);
|
|
38943
39489
|
}
|
|
38944
39490
|
}
|
|
38945
|
-
const
|
|
38946
|
-
|
|
38947
|
-
info(MODULE12, `Skipping maintained search: ${viableBeforeMaintained} viable candidate(s) already meet maxResults (${maxResults})`);
|
|
38948
|
-
} else if (enabledStrategies.has("maintained")) {
|
|
38949
|
-
await applyInterPhaseDelay();
|
|
38950
|
-
const remaining = maxResults - viableBeforeMaintained;
|
|
38951
|
-
const result = await runPhase3(this.octokit, this.vetter, langQuery, minStars, config2.projectCategories ?? [], remaining, phase0RepoSet, starredRepoSet, starredRepos, allCandidates, filterIssues, tracker);
|
|
38952
|
-
recordPhaseResult("3", result);
|
|
38953
|
-
strategiesUsed.push("maintained");
|
|
38954
|
-
}
|
|
38955
|
-
const phasesSkippedForBudget = searchBudget < CRITICAL_BUDGET_THRESHOLD;
|
|
38956
|
-
const budgetNote = phasesSkippedForBudget ? preflightFailed ? " The starred-repo phase was skipped as a precaution because the rate-limit check failed (quota unknown); broad and maintained phases still ran on GraphQL." : ` The starred-repo phase was skipped due to critically low API quota (${searchBudget} remaining); broad and maintained phases still ran on GraphQL.` : "";
|
|
39491
|
+
const phasesSkippedForBudget = starredSkippedForBudget;
|
|
39492
|
+
const budgetNote = phasesSkippedForBudget ? preflightFailed ? " The starred-repo phase was skipped as a precaution because the rate-limit check failed (quota unknown); the other strategies don't use that quota." : ` The starred-repo phase was skipped due to critically low API quota (${searchBudget} remaining); the other strategies don't use that quota.` : "";
|
|
38957
39493
|
if (allCandidates.length === 0) {
|
|
38958
39494
|
const errorDetails = [
|
|
38959
39495
|
phaseErrors["0"] ? `Phase 0 (merged-PR repos): ${phaseErrors["0"]}` : null,
|
|
39496
|
+
phaseErrors["orgs"] ? `Orgs phase (preferred orgs): ${phaseErrors["orgs"]}` : null,
|
|
38960
39497
|
phaseErrors["1"] ? `Phase 1 (starred repos): ${phaseErrors["1"]}` : null,
|
|
38961
39498
|
phaseErrors["2"] ? `Phase 2 (general): ${phaseErrors["2"]}` : null,
|
|
38962
39499
|
phaseErrors["3"] ? `Phase 3 (maintained repos): ${phaseErrors["3"]}` : null
|
|
@@ -39315,8 +39852,8 @@ var NO_BROAD_RESULTS_MESSAGE = "No open feature opportunities matched your filte
|
|
|
39315
39852
|
var DEFAULT_BROAD_MAX_TO_VET = 30;
|
|
39316
39853
|
function buildBroadFeatureSearchQuery(opts) {
|
|
39317
39854
|
const parts = ["is:issue", "is:open", "no:assignee"];
|
|
39318
|
-
const labelClause = FEATURE_LABELS.map((l) =>
|
|
39319
|
-
parts.push(
|
|
39855
|
+
const labelClause = `label:${FEATURE_LABELS.map((l) => JSON.stringify(l)).join(",")}`;
|
|
39856
|
+
parts.push(labelClause);
|
|
39320
39857
|
for (const excl of FEATURE_EXCLUSION_LABELS) {
|
|
39321
39858
|
parts.push(`-label:"${excl}"`);
|
|
39322
39859
|
}
|
|
@@ -39962,11 +40499,10 @@ var OssScout = class {
|
|
|
39962
40499
|
}
|
|
39963
40500
|
/**
|
|
39964
40501
|
* Multi-strategy issue search. Returns scored, sorted candidates.
|
|
39965
|
-
*
|
|
40502
|
+
* Skipped issues are excluded; the skip list is permanent (#343).
|
|
39966
40503
|
*/
|
|
39967
40504
|
async search(options) {
|
|
39968
40505
|
this.evictStaleCacheEntries();
|
|
39969
|
-
this.cullExpiredSkips();
|
|
39970
40506
|
const skippedUrls = new Set((this.state.skippedIssues ?? []).map((s) => s.url));
|
|
39971
40507
|
if (options?.excludeRecentlySurfaced ?? true) {
|
|
39972
40508
|
const ttlDays = options?.recentlySurfacedTtlDays ?? 7;
|
|
@@ -40003,15 +40539,21 @@ var OssScout = class {
|
|
|
40003
40539
|
diversityRatio,
|
|
40004
40540
|
interPhaseDelayMs: options?.interPhaseDelayMs,
|
|
40005
40541
|
broadPhaseDelayMs: options?.broadPhaseDelayMs,
|
|
40006
|
-
languageRotationOffset: rotation.languageOffset
|
|
40542
|
+
languageRotationOffset: rotation.languageOffset,
|
|
40543
|
+
repoRotationOffsets: {
|
|
40544
|
+
merged: rotation.phase0Offset ?? 0,
|
|
40545
|
+
starred: rotation.starredOffset ?? 0,
|
|
40546
|
+
maintained: rotation.maintainedOffset ?? 0
|
|
40547
|
+
},
|
|
40548
|
+
strategyRotationOffset: rotation.strategyOffset ?? 0
|
|
40007
40549
|
}));
|
|
40008
40550
|
} catch (err) {
|
|
40009
40551
|
if (err instanceof ValidationError) {
|
|
40010
|
-
this.
|
|
40552
|
+
this.advanceRotation(rotation, err.strategiesUsed ?? []);
|
|
40011
40553
|
}
|
|
40012
40554
|
throw err;
|
|
40013
40555
|
}
|
|
40014
|
-
this.
|
|
40556
|
+
this.advanceRotation(rotation, strategiesUsed);
|
|
40015
40557
|
for (const c of candidates) {
|
|
40016
40558
|
this.updateRepoSignalsFromHealth(c.projectHealth);
|
|
40017
40559
|
}
|
|
@@ -40026,18 +40568,26 @@ var OssScout = class {
|
|
|
40026
40568
|
};
|
|
40027
40569
|
}
|
|
40028
40570
|
/**
|
|
40029
|
-
* Advance the
|
|
40030
|
-
*
|
|
40031
|
-
*
|
|
40032
|
-
*
|
|
40033
|
-
*
|
|
40571
|
+
* Advance the rotation cursor of each phase that actually ran: the language
|
|
40572
|
+
* cursor for broad (#249 follow-up), the repo-window cursors for
|
|
40573
|
+
* merged/starred/maintained (#324, #333). Called on both the success path
|
|
40574
|
+
* and the zero-candidate ValidationError path — a phase that ran and found
|
|
40575
|
+
* nothing must still rotate, or the same barren slice would lead every
|
|
40576
|
+
* subsequent run. Skipped/gated phases don't burn a rotation slot. The
|
|
40577
|
+
* round-robin strategy cursor (#336) moves to just after the strategy that
|
|
40578
|
+
* led (the first one used), so the next search starts with the next one.
|
|
40034
40579
|
*/
|
|
40035
|
-
|
|
40036
|
-
|
|
40580
|
+
advanceRotation(rotation, strategiesUsed) {
|
|
40581
|
+
const ran = (strategy) => strategiesUsed.includes(strategy) ? 1 : 0;
|
|
40582
|
+
if (strategiesUsed.length === 0)
|
|
40037
40583
|
return;
|
|
40038
40584
|
this.state.searchRotation = {
|
|
40039
40585
|
...rotation,
|
|
40040
|
-
languageOffset: rotation.languageOffset +
|
|
40586
|
+
languageOffset: rotation.languageOffset + ran("broad"),
|
|
40587
|
+
phase0Offset: (rotation.phase0Offset ?? 0) + ran("merged"),
|
|
40588
|
+
starredOffset: (rotation.starredOffset ?? 0) + ran("starred"),
|
|
40589
|
+
maintainedOffset: (rotation.maintainedOffset ?? 0) + ran("maintained"),
|
|
40590
|
+
strategyOffset: CONCRETE_STRATEGIES.indexOf(strategiesUsed[0]) + 1,
|
|
40041
40591
|
lastRotatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
40042
40592
|
};
|
|
40043
40593
|
this.dirty = true;
|
|
@@ -40453,6 +41003,16 @@ var OssScout = class {
|
|
|
40453
41003
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
40454
41004
|
const existing = new Map((this.state.savedResults ?? []).map((r) => [r.issueUrl, r]));
|
|
40455
41005
|
for (const c of candidates) {
|
|
41006
|
+
if (c.recommendation === "skip") {
|
|
41007
|
+
existing.delete(c.issue.url);
|
|
41008
|
+
this.skipIssue(c.issue.url, {
|
|
41009
|
+
repo: c.issue.repo,
|
|
41010
|
+
number: c.issue.number,
|
|
41011
|
+
title: c.issue.title,
|
|
41012
|
+
reason: c.reasonsToSkip.join("; ") || "vetter: skip"
|
|
41013
|
+
});
|
|
41014
|
+
continue;
|
|
41015
|
+
}
|
|
40456
41016
|
const prev = existing.get(c.issue.url);
|
|
40457
41017
|
existing.set(c.issue.url, {
|
|
40458
41018
|
issueUrl: c.issue.url,
|
|
@@ -40503,7 +41063,7 @@ var OssScout = class {
|
|
|
40503
41063
|
}
|
|
40504
41064
|
// ── Skip List ───────────────────────────────────────────────────────
|
|
40505
41065
|
/**
|
|
40506
|
-
* Skip an issue — excludes it from future searches
|
|
41066
|
+
* Skip an issue — excludes it from future searches permanently (#343).
|
|
40507
41067
|
*/
|
|
40508
41068
|
skipIssue(url2, metadata) {
|
|
40509
41069
|
const existing = this.state.skippedIssues ?? [];
|
|
@@ -40516,7 +41076,8 @@ var OssScout = class {
|
|
|
40516
41076
|
repo: metadata?.repo ?? "",
|
|
40517
41077
|
number: metadata?.number ?? 0,
|
|
40518
41078
|
title: metadata?.title ?? "",
|
|
40519
|
-
skippedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41079
|
+
skippedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41080
|
+
...metadata?.reason ? { reason: metadata.reason } : {}
|
|
40520
41081
|
}
|
|
40521
41082
|
];
|
|
40522
41083
|
if (this.state.savedResults) {
|
|
@@ -40549,7 +41110,8 @@ var OssScout = class {
|
|
|
40549
41110
|
this.dirty = true;
|
|
40550
41111
|
}
|
|
40551
41112
|
/**
|
|
40552
|
-
* Remove skipped issues older than maxDays (default 90).
|
|
41113
|
+
* Remove skipped issues older than maxDays (default 90). Not called by
|
|
41114
|
+
* search since #343 (skips are permanent); available for an explicit prune.
|
|
40553
41115
|
* @returns The number of expired entries that were removed.
|
|
40554
41116
|
*/
|
|
40555
41117
|
cullExpiredSkips(maxDays = 90) {
|
|
@@ -40647,6 +41209,7 @@ var FIELD_CONFIGS = {
|
|
|
40647
41209
|
scope: { type: "enum-array", validValues: IssueScopeSchema.options },
|
|
40648
41210
|
excludeRepos: { type: "array" },
|
|
40649
41211
|
excludeOrgs: { type: "array" },
|
|
41212
|
+
preferredOrgs: { type: "array" },
|
|
40650
41213
|
aiPolicyBlocklist: { type: "array" },
|
|
40651
41214
|
projectCategories: {
|
|
40652
41215
|
type: "enum-array",
|
|
@@ -40810,7 +41373,7 @@ function registerTools(server, scout) {
|
|
|
40810
41373
|
{
|
|
40811
41374
|
maxResults: external_exports3.number().int().min(1).max(100).optional().describe("Maximum number of results to return (1-100, default 10)"),
|
|
40812
41375
|
strategies: external_exports3.string().optional().describe(
|
|
40813
|
-
"Comma-separated search strategies: merged, starred, broad, maintained, all"
|
|
41376
|
+
"Comma-separated search strategies: merged, orgs, starred, broad, maintained, all"
|
|
40814
41377
|
),
|
|
40815
41378
|
preferLanguages: external_exports3.array(external_exports3.string()).optional().describe(
|
|
40816
41379
|
"Soft-boost ranking for candidates whose repo language matches one of these (case-insensitive). Personalization tier between recommendation and viabilityScore (#1244). Not a filter; only reorders."
|
|
@@ -40979,7 +41542,7 @@ function registerTools(server, scout) {
|
|
|
40979
41542
|
);
|
|
40980
41543
|
server.tool(
|
|
40981
41544
|
"skip",
|
|
40982
|
-
"Skip, unskip, list, or clear skipped issues. Skipped issues are excluded from future searches
|
|
41545
|
+
"Skip, unskip, list, or clear skipped issues. Skipped issues are excluded from future searches permanently.",
|
|
40983
41546
|
{
|
|
40984
41547
|
action: external_exports3.enum(["add", "remove", "list", "clear"]).default("add").describe("Action to perform (default: add)"),
|
|
40985
41548
|
issueUrl: external_exports3.string().optional().describe("GitHub issue URL (required for add/remove actions)")
|
|
@@ -41157,7 +41720,7 @@ function registerResources(server, scout) {
|
|
|
41157
41720
|
// src/index.ts
|
|
41158
41721
|
var SERVER_INFO = {
|
|
41159
41722
|
name: "oss-scout-mcp",
|
|
41160
|
-
version: "0.
|
|
41723
|
+
version: "0.12.0"
|
|
41161
41724
|
// x-release-please-version
|
|
41162
41725
|
};
|
|
41163
41726
|
function createServer(scout) {
|