@ifrankwang/openspec-agents 0.128.0 → 0.131.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/.mcp-server/cli.mjs +583 -155
- package/README.md +1 -1
- package/assets/agents/openspec-developer.md +1 -1
- package/assets/agents/openspec-reviewer.md +2 -1
- package/assets/workflows/task-simple.yaml +11 -10
- package/assets/workflows/task.yaml +1 -1
- package/dsh/cordis.patch.yml +3 -2
- package/package.json +1 -1
- package/src/core/git.ts +90 -1
- package/src/core/tools/gate.ts +5 -0
- package/src/core/tools/lifecycle.ts +63 -22
- package/src/core/tools/schemas.ts +5 -1
- package/src/core/tools/submit.ts +26 -8
- package/src/core/views.ts +21 -0
- package/src/core/workflow/status.ts +41 -13
package/.mcp-server/cli.mjs
CHANGED
|
@@ -3053,7 +3053,25 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3053
3053
|
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);
|
|
3054
3054
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3055
3055
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3056
|
-
var isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
3056
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
3057
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
3058
|
+
var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
3059
|
+
var BYTE_HEX = new Array(256);
|
|
3060
|
+
{
|
|
3061
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
3062
|
+
for (let i = 0;i < 256; i++) {
|
|
3063
|
+
BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
function percentEncodeNonAscii(cp) {
|
|
3067
|
+
if (cp < 2048) {
|
|
3068
|
+
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
3069
|
+
}
|
|
3070
|
+
if (cp < 65536) {
|
|
3071
|
+
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3072
|
+
}
|
|
3073
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3074
|
+
}
|
|
3057
3075
|
function stringArrayToHexStripped(input) {
|
|
3058
3076
|
let acc = "";
|
|
3059
3077
|
let code = 0;
|
|
@@ -3078,91 +3096,122 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3078
3096
|
}
|
|
3079
3097
|
return acc;
|
|
3080
3098
|
}
|
|
3099
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
3100
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
3101
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
3081
3102
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3082
|
-
function
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
} else {
|
|
3092
|
-
output.error = true;
|
|
3093
|
-
return false;
|
|
3103
|
+
function isZoneIdentifier(zone) {
|
|
3104
|
+
if (zone.length === 0)
|
|
3105
|
+
return false;
|
|
3106
|
+
for (let i = 0;i < zone.length; i++) {
|
|
3107
|
+
if (isZoneCharacter(zone[i]))
|
|
3108
|
+
continue;
|
|
3109
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
3110
|
+
i += 2;
|
|
3111
|
+
continue;
|
|
3094
3112
|
}
|
|
3095
|
-
|
|
3113
|
+
return false;
|
|
3096
3114
|
}
|
|
3097
3115
|
return true;
|
|
3098
3116
|
}
|
|
3099
|
-
function
|
|
3100
|
-
let
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
let
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
if (cursor === ":") {
|
|
3113
|
-
if (endipv6Encountered === true) {
|
|
3114
|
-
endIpv6 = true;
|
|
3115
|
-
}
|
|
3116
|
-
if (!consume(buffer, address, output)) {
|
|
3117
|
-
break;
|
|
3118
|
-
}
|
|
3119
|
-
if (++tokenCount > 7) {
|
|
3120
|
-
output.error = true;
|
|
3121
|
-
break;
|
|
3122
|
-
}
|
|
3123
|
-
if (i > 0 && input[i - 1] === ":") {
|
|
3124
|
-
endipv6Encountered = true;
|
|
3117
|
+
function compressIPv6ZeroRun(hextets) {
|
|
3118
|
+
let bestStart = -1;
|
|
3119
|
+
let bestLength = 0;
|
|
3120
|
+
let runStart = -1;
|
|
3121
|
+
let runLength = 0;
|
|
3122
|
+
for (let i = 0;i < hextets.length; i++) {
|
|
3123
|
+
if (hextets[i] === "0") {
|
|
3124
|
+
if (runStart === -1)
|
|
3125
|
+
runStart = i;
|
|
3126
|
+
runLength++;
|
|
3127
|
+
if (runLength > bestLength) {
|
|
3128
|
+
bestLength = runLength;
|
|
3129
|
+
bestStart = runStart;
|
|
3125
3130
|
}
|
|
3126
|
-
address.push(":");
|
|
3127
|
-
continue;
|
|
3128
|
-
} else if (cursor === "%") {
|
|
3129
|
-
if (!consume(buffer, address, output)) {
|
|
3130
|
-
break;
|
|
3131
|
-
}
|
|
3132
|
-
consume = consumeIsZone;
|
|
3133
3131
|
} else {
|
|
3134
|
-
|
|
3135
|
-
|
|
3132
|
+
runStart = -1;
|
|
3133
|
+
runLength = 0;
|
|
3136
3134
|
}
|
|
3137
3135
|
}
|
|
3138
|
-
if (
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3136
|
+
if (bestLength < 2)
|
|
3137
|
+
return hextets.join(":");
|
|
3138
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
3139
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
3140
|
+
return head + "::" + tail;
|
|
3141
|
+
}
|
|
3142
|
+
function normalizeIPv6Address(input) {
|
|
3143
|
+
const compression = input.indexOf("::");
|
|
3144
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1)
|
|
3145
|
+
return;
|
|
3146
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
3147
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
3148
|
+
if (compression !== -1) {
|
|
3149
|
+
if (left.length === 1 && left[0] === "")
|
|
3150
|
+
left.length = 0;
|
|
3151
|
+
if (right.length === 1 && right[0] === "")
|
|
3152
|
+
right.length = 0;
|
|
3153
|
+
}
|
|
3154
|
+
const parts = left.concat(right);
|
|
3155
|
+
let hextetCount = 0;
|
|
3156
|
+
for (let i = 0;i < parts.length; i++) {
|
|
3157
|
+
const part = parts[i];
|
|
3158
|
+
if (part === "")
|
|
3159
|
+
return;
|
|
3160
|
+
if (part.indexOf(".") !== -1) {
|
|
3161
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part))
|
|
3162
|
+
return;
|
|
3163
|
+
hextetCount += 2;
|
|
3164
|
+
continue;
|
|
3145
3165
|
}
|
|
3166
|
+
if (!isHextet(part))
|
|
3167
|
+
return;
|
|
3168
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
3169
|
+
hextetCount++;
|
|
3146
3170
|
}
|
|
3147
|
-
|
|
3148
|
-
|
|
3171
|
+
if (compression === -1) {
|
|
3172
|
+
if (hextetCount !== 8)
|
|
3173
|
+
return;
|
|
3174
|
+
return compressIPv6ZeroRun(parts);
|
|
3175
|
+
}
|
|
3176
|
+
if (hextetCount >= 8)
|
|
3177
|
+
return;
|
|
3178
|
+
const expanded = parts.slice(0, left.length);
|
|
3179
|
+
for (let i = hextetCount;i < 8; i++)
|
|
3180
|
+
expanded.push("0");
|
|
3181
|
+
for (let i = left.length;i < parts.length; i++)
|
|
3182
|
+
expanded.push(parts[i]);
|
|
3183
|
+
return compressIPv6ZeroRun(expanded);
|
|
3149
3184
|
}
|
|
3150
3185
|
function normalizeIPv6(host) {
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
}
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3186
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
3187
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
3188
|
+
if (hasBracket && !bracketed)
|
|
3189
|
+
return { host, isIPV6: false, error: true };
|
|
3190
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
3191
|
+
if (bracketed && isIPvFuture(input)) {
|
|
3192
|
+
input = input.toLowerCase();
|
|
3193
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
3194
|
+
}
|
|
3195
|
+
if (findToken(input, ":") < 2) {
|
|
3196
|
+
return { host, isIPV6: false, error: bracketed };
|
|
3197
|
+
}
|
|
3198
|
+
let zoneIdentifier = "";
|
|
3199
|
+
const zoneSeparator = input.indexOf("%");
|
|
3200
|
+
if (zoneSeparator !== -1) {
|
|
3201
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
3202
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
3203
|
+
if (!isZoneIdentifier(zoneIdentifier))
|
|
3204
|
+
return { host, isIPV6: false, error: true };
|
|
3205
|
+
input = input.slice(0, zoneSeparator);
|
|
3206
|
+
}
|
|
3207
|
+
const address = normalizeIPv6Address(input);
|
|
3208
|
+
if (address === undefined)
|
|
3209
|
+
return { host, isIPV6: false, error: true };
|
|
3210
|
+
return {
|
|
3211
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
3212
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
3213
|
+
isIPV6: true
|
|
3214
|
+
};
|
|
3166
3215
|
}
|
|
3167
3216
|
function findToken(str, token) {
|
|
3168
3217
|
let ind = 0;
|
|
@@ -3282,7 +3331,8 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3282
3331
|
function normalizePathEncoding(input) {
|
|
3283
3332
|
let output = "";
|
|
3284
3333
|
for (let i = 0;i < input.length; i++) {
|
|
3285
|
-
|
|
3334
|
+
const ch = input[i];
|
|
3335
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3286
3336
|
const hex3 = input.slice(i + 1, i + 3);
|
|
3287
3337
|
if (isHexPair(hex3)) {
|
|
3288
3338
|
const normalizedHex = hex3.toUpperCase();
|
|
@@ -3296,10 +3346,152 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3296
3346
|
continue;
|
|
3297
3347
|
}
|
|
3298
3348
|
}
|
|
3299
|
-
if (isPathCharacter(
|
|
3300
|
-
output +=
|
|
3349
|
+
if (isPathCharacter(ch)) {
|
|
3350
|
+
output += ch;
|
|
3351
|
+
} else {
|
|
3352
|
+
const code = input.charCodeAt(i);
|
|
3353
|
+
if (code < 128) {
|
|
3354
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3355
|
+
} else if (code < 55296 || code > 57343) {
|
|
3356
|
+
output += percentEncodeNonAscii(code);
|
|
3357
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3358
|
+
const low = input.charCodeAt(i + 1);
|
|
3359
|
+
if (low >= 56320 && low <= 57343) {
|
|
3360
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3361
|
+
i++;
|
|
3362
|
+
} else {
|
|
3363
|
+
output += percentEncodeNonAscii(65533);
|
|
3364
|
+
}
|
|
3365
|
+
} else {
|
|
3366
|
+
output += percentEncodeNonAscii(65533);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
return output;
|
|
3371
|
+
}
|
|
3372
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
3373
|
+
let output = "";
|
|
3374
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
3375
|
+
for (let i = 0;i < input.length; i++) {
|
|
3376
|
+
const ch = input[i];
|
|
3377
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3378
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3379
|
+
if (isHexPair(hex3)) {
|
|
3380
|
+
output += "%" + hex3.toUpperCase();
|
|
3381
|
+
i += 2;
|
|
3382
|
+
continue;
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
if (ch === "/") {
|
|
3386
|
+
firstSegment = false;
|
|
3387
|
+
}
|
|
3388
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
|
|
3389
|
+
output += ch;
|
|
3390
|
+
} else {
|
|
3391
|
+
const code = input.charCodeAt(i);
|
|
3392
|
+
if (code < 128) {
|
|
3393
|
+
output += BYTE_HEX[code];
|
|
3394
|
+
} else if (code < 55296 || code > 57343) {
|
|
3395
|
+
output += percentEncodeNonAscii(code);
|
|
3396
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3397
|
+
const low = input.charCodeAt(i + 1);
|
|
3398
|
+
if (low >= 56320 && low <= 57343) {
|
|
3399
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3400
|
+
i++;
|
|
3401
|
+
} else {
|
|
3402
|
+
output += percentEncodeNonAscii(65533);
|
|
3403
|
+
}
|
|
3404
|
+
} else {
|
|
3405
|
+
output += percentEncodeNonAscii(65533);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
return output;
|
|
3410
|
+
}
|
|
3411
|
+
function encodeComponent(input, isAllowed) {
|
|
3412
|
+
let output = "";
|
|
3413
|
+
for (let i = 0;i < input.length; i++) {
|
|
3414
|
+
const ch = input[i];
|
|
3415
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3416
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3417
|
+
if (isHexPair(hex3)) {
|
|
3418
|
+
output += "%" + hex3.toUpperCase();
|
|
3419
|
+
i += 2;
|
|
3420
|
+
continue;
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
if (isAllowed(ch)) {
|
|
3424
|
+
output += ch;
|
|
3301
3425
|
} else {
|
|
3302
|
-
|
|
3426
|
+
const code = input.charCodeAt(i);
|
|
3427
|
+
if (code < 128) {
|
|
3428
|
+
output += BYTE_HEX[code];
|
|
3429
|
+
} else if (code < 55296 || code > 57343) {
|
|
3430
|
+
output += percentEncodeNonAscii(code);
|
|
3431
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3432
|
+
const low = input.charCodeAt(i + 1);
|
|
3433
|
+
if (low >= 56320 && low <= 57343) {
|
|
3434
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3435
|
+
i++;
|
|
3436
|
+
} else {
|
|
3437
|
+
output += percentEncodeNonAscii(65533);
|
|
3438
|
+
}
|
|
3439
|
+
} else {
|
|
3440
|
+
output += percentEncodeNonAscii(65533);
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
return output;
|
|
3445
|
+
}
|
|
3446
|
+
function encodeUserinfo(input) {
|
|
3447
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
3448
|
+
}
|
|
3449
|
+
function encodeQuery(input) {
|
|
3450
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3451
|
+
}
|
|
3452
|
+
function encodeFragment(input) {
|
|
3453
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3454
|
+
}
|
|
3455
|
+
function isEscapeSafe(cp) {
|
|
3456
|
+
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;
|
|
3457
|
+
}
|
|
3458
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
3459
|
+
let output = "";
|
|
3460
|
+
for (let i = 0;i < input.length; i++) {
|
|
3461
|
+
const ch = input[i];
|
|
3462
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3463
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3464
|
+
if (isHexPair(hex3)) {
|
|
3465
|
+
const normalizedHex = hex3.toUpperCase();
|
|
3466
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3467
|
+
if (isUnreserved(decoded)) {
|
|
3468
|
+
output += decoded;
|
|
3469
|
+
} else {
|
|
3470
|
+
output += "%" + normalizedHex;
|
|
3471
|
+
}
|
|
3472
|
+
i += 2;
|
|
3473
|
+
continue;
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
3477
|
+
output += ch;
|
|
3478
|
+
} else {
|
|
3479
|
+
const code = input.charCodeAt(i);
|
|
3480
|
+
if (code < 128) {
|
|
3481
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3482
|
+
} else if (code < 55296 || code > 57343) {
|
|
3483
|
+
output += percentEncodeNonAscii(code);
|
|
3484
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3485
|
+
const low = input.charCodeAt(i + 1);
|
|
3486
|
+
if (low >= 56320 && low <= 57343) {
|
|
3487
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3488
|
+
i++;
|
|
3489
|
+
} else {
|
|
3490
|
+
output += percentEncodeNonAscii(65533);
|
|
3491
|
+
}
|
|
3492
|
+
} else {
|
|
3493
|
+
output += percentEncodeNonAscii(65533);
|
|
3494
|
+
}
|
|
3303
3495
|
}
|
|
3304
3496
|
}
|
|
3305
3497
|
return output;
|
|
@@ -3322,14 +3514,18 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3322
3514
|
function recomposeAuthority(component) {
|
|
3323
3515
|
const uriTokens = [];
|
|
3324
3516
|
if (component.userinfo !== undefined) {
|
|
3325
|
-
uriTokens.push(component.userinfo);
|
|
3517
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
3326
3518
|
uriTokens.push("@");
|
|
3327
3519
|
}
|
|
3328
3520
|
if (component.host !== undefined) {
|
|
3329
|
-
let host =
|
|
3521
|
+
let host = component.host;
|
|
3330
3522
|
if (!isIPv4(host)) {
|
|
3331
|
-
|
|
3332
|
-
if (ipV6res.isIPV6
|
|
3523
|
+
let ipV6res = normalizeIPv6(host);
|
|
3524
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
3525
|
+
host = normalizePercentEncoding(host, true);
|
|
3526
|
+
ipV6res = normalizeIPv6(host);
|
|
3527
|
+
}
|
|
3528
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
3333
3529
|
host = `[${ipV6res.escapedHost}]`;
|
|
3334
3530
|
} else {
|
|
3335
3531
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -3349,6 +3545,11 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3349
3545
|
reescapeHostDelimiters,
|
|
3350
3546
|
normalizePercentEncoding,
|
|
3351
3547
|
normalizePathEncoding,
|
|
3548
|
+
serializePathEncoding,
|
|
3549
|
+
normalizeQueryFragmentEncoding,
|
|
3550
|
+
encodeUserinfo,
|
|
3551
|
+
encodeQuery,
|
|
3552
|
+
encodeFragment,
|
|
3352
3553
|
escapePreservingEscapes,
|
|
3353
3554
|
removeDotSegments,
|
|
3354
3555
|
isIPv4,
|
|
@@ -3361,7 +3562,7 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3361
3562
|
// node_modules/fast-uri/lib/schemes.js
|
|
3362
3563
|
var require_schemes = __commonJS(function(exports, module) {
|
|
3363
3564
|
var { isUUID } = require_utils();
|
|
3364
|
-
var URN_REG =
|
|
3565
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
3365
3566
|
var supportedSchemeNames = [
|
|
3366
3567
|
"http",
|
|
3367
3568
|
"https",
|
|
@@ -3416,9 +3617,10 @@ var require_schemes = __commonJS(function(exports, module) {
|
|
|
3416
3617
|
wsComponent.secure = undefined;
|
|
3417
3618
|
}
|
|
3418
3619
|
if (wsComponent.resourceName) {
|
|
3419
|
-
const
|
|
3620
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3621
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3420
3622
|
wsComponent.path = path && path !== "/" ? path : undefined;
|
|
3421
|
-
wsComponent.query =
|
|
3623
|
+
wsComponent.query = queryIndex === -1 ? undefined : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3422
3624
|
wsComponent.resourceName = undefined;
|
|
3423
3625
|
}
|
|
3424
3626
|
wsComponent.fragment = undefined;
|
|
@@ -3430,7 +3632,7 @@ var require_schemes = __commonJS(function(exports, module) {
|
|
|
3430
3632
|
return urnComponent;
|
|
3431
3633
|
}
|
|
3432
3634
|
const matches = urnComponent.path.match(URN_REG);
|
|
3433
|
-
if (matches) {
|
|
3635
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
3434
3636
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
3435
3637
|
urnComponent.nid = matches[1].toLowerCase();
|
|
3436
3638
|
urnComponent.nss = matches[2];
|
|
@@ -3534,8 +3736,17 @@ var require_schemes = __commonJS(function(exports, module) {
|
|
|
3534
3736
|
|
|
3535
3737
|
// node_modules/fast-uri/index.js
|
|
3536
3738
|
var require_fast_uri = __commonJS(function(exports, module) {
|
|
3537
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3739
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3538
3740
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3741
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
3742
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
3743
|
+
function decodeValidScheme(scheme) {
|
|
3744
|
+
const decodedScheme = unescape(String(scheme));
|
|
3745
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
3746
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
3747
|
+
}
|
|
3748
|
+
return decodedScheme;
|
|
3749
|
+
}
|
|
3539
3750
|
function normalize(uri, options) {
|
|
3540
3751
|
if (typeof uri === "string") {
|
|
3541
3752
|
uri = normalizeString(uri, options);
|
|
@@ -3546,12 +3757,34 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3546
3757
|
}
|
|
3547
3758
|
function resolve(baseURI, relativeURI, options) {
|
|
3548
3759
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3549
|
-
const {
|
|
3550
|
-
|
|
3551
|
-
|
|
3760
|
+
const {
|
|
3761
|
+
parsed: baseParsed,
|
|
3762
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
3763
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
3764
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
3765
|
+
malformedHost: baseMalformedHost,
|
|
3766
|
+
malformedScheme: baseMalformedScheme
|
|
3767
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
3768
|
+
const {
|
|
3769
|
+
parsed: relativeParsed,
|
|
3770
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
3771
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
3772
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
3773
|
+
malformedHost: relativeMalformedHost,
|
|
3774
|
+
malformedScheme: relativeMalformedScheme
|
|
3775
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
3776
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
3552
3777
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3553
3778
|
}
|
|
3554
3779
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3780
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
3781
|
+
const resolvedHost = resolved.host;
|
|
3782
|
+
const resolvedHostIsIP = resolvedHost !== undefined && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
3783
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
3784
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
|
|
3785
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
3786
|
+
throw new Error(resolved.error);
|
|
3787
|
+
}
|
|
3555
3788
|
schemelessOptions.skipEscape = true;
|
|
3556
3789
|
return serialize(resolved, schemelessOptions);
|
|
3557
3790
|
}
|
|
@@ -3611,7 +3844,7 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3611
3844
|
function equal(uriA, uriB, options) {
|
|
3612
3845
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3613
3846
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3614
|
-
return normalizedA !== undefined && normalizedB !== undefined && normalizedA
|
|
3847
|
+
return normalizedA !== undefined && normalizedB !== undefined && normalizedA === normalizedB;
|
|
3615
3848
|
}
|
|
3616
3849
|
function serialize(cmpts, opts) {
|
|
3617
3850
|
const component = {
|
|
@@ -3632,20 +3865,23 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3632
3865
|
};
|
|
3633
3866
|
const options = Object.assign({}, opts);
|
|
3634
3867
|
const uriTokens = [];
|
|
3868
|
+
if (component.scheme) {
|
|
3869
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3870
|
+
}
|
|
3635
3871
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3636
3872
|
if (schemeHandler && schemeHandler.serialize)
|
|
3637
3873
|
schemeHandler.serialize(component, options);
|
|
3874
|
+
const hasAuthority = component.userinfo !== undefined || component.host !== undefined || component.port !== undefined;
|
|
3875
|
+
const pathNoScheme = !options.skipEscape && component.scheme === undefined && !hasAuthority;
|
|
3638
3876
|
if (component.path !== undefined) {
|
|
3639
3877
|
if (!options.skipEscape) {
|
|
3640
|
-
component.path =
|
|
3641
|
-
if (component.scheme !== undefined) {
|
|
3642
|
-
component.path = component.path.split("%3A").join(":");
|
|
3643
|
-
}
|
|
3878
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
3644
3879
|
} else {
|
|
3645
3880
|
component.path = normalizePercentEncoding(component.path);
|
|
3646
3881
|
}
|
|
3647
3882
|
}
|
|
3648
3883
|
if (options.reference !== "suffix" && component.scheme) {
|
|
3884
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3649
3885
|
uriTokens.push(component.scheme, ":");
|
|
3650
3886
|
}
|
|
3651
3887
|
const authority = recomposeAuthority(component);
|
|
@@ -3663,16 +3899,19 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3663
3899
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3664
3900
|
s = removeDotSegments(s);
|
|
3665
3901
|
}
|
|
3902
|
+
if (pathNoScheme) {
|
|
3903
|
+
s = serializePathEncoding(s, true);
|
|
3904
|
+
}
|
|
3666
3905
|
if (authority === undefined && s[0] === "/" && s[1] === "/") {
|
|
3667
3906
|
s = "/%2F" + s.slice(2);
|
|
3668
3907
|
}
|
|
3669
3908
|
uriTokens.push(s);
|
|
3670
3909
|
}
|
|
3671
3910
|
if (component.query !== undefined) {
|
|
3672
|
-
uriTokens.push("?", component.query);
|
|
3911
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
3673
3912
|
}
|
|
3674
3913
|
if (component.fragment !== undefined) {
|
|
3675
|
-
uriTokens.push("#", component.fragment);
|
|
3914
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
3676
3915
|
}
|
|
3677
3916
|
return uriTokens.join("");
|
|
3678
3917
|
}
|
|
@@ -3688,6 +3927,33 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3688
3927
|
}
|
|
3689
3928
|
return;
|
|
3690
3929
|
}
|
|
3930
|
+
function hasMalformedPercentEncoding(component) {
|
|
3931
|
+
if (component === undefined)
|
|
3932
|
+
return false;
|
|
3933
|
+
let percent = component.indexOf("%");
|
|
3934
|
+
while (percent !== -1) {
|
|
3935
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
3936
|
+
return true;
|
|
3937
|
+
}
|
|
3938
|
+
percent = component.indexOf("%", percent + 3);
|
|
3939
|
+
}
|
|
3940
|
+
return false;
|
|
3941
|
+
}
|
|
3942
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
3943
|
+
const host = matches[4];
|
|
3944
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== undefined && !(host[0] === "[" && host[host.length - 1] === "]") && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
3945
|
+
}
|
|
3946
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
3947
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && parsed.host[0] !== "[" && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
3948
|
+
try {
|
|
3949
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3950
|
+
} catch (e) {
|
|
3951
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3952
|
+
return true;
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
return false;
|
|
3956
|
+
}
|
|
3691
3957
|
function parseWithStatus(uri, opts) {
|
|
3692
3958
|
const options = Object.assign({}, opts);
|
|
3693
3959
|
const parsed = {
|
|
@@ -3700,6 +3966,11 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3700
3966
|
fragment: undefined
|
|
3701
3967
|
};
|
|
3702
3968
|
let malformedAuthorityOrPort = false;
|
|
3969
|
+
let malformedPercentEncoding = false;
|
|
3970
|
+
let malformedSchemeSpecific = false;
|
|
3971
|
+
let malformedHost = false;
|
|
3972
|
+
let malformedIPLiteral = false;
|
|
3973
|
+
let malformedScheme = false;
|
|
3703
3974
|
let isIP = false;
|
|
3704
3975
|
if (options.reference === "suffix") {
|
|
3705
3976
|
if (options.scheme) {
|
|
@@ -3736,6 +4007,19 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3736
4007
|
parsed.path = matches[6] || "";
|
|
3737
4008
|
parsed.query = matches[7];
|
|
3738
4009
|
parsed.fragment = matches[8];
|
|
4010
|
+
if (parsed.scheme !== undefined) {
|
|
4011
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
4012
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
4013
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
4014
|
+
} else {
|
|
4015
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
4016
|
+
malformedScheme = true;
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
4020
|
+
if (malformedPercentEncoding) {
|
|
4021
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
4022
|
+
}
|
|
3739
4023
|
if (isNaN(parsed.port)) {
|
|
3740
4024
|
parsed.port = matches[5];
|
|
3741
4025
|
}
|
|
@@ -3747,9 +4031,15 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3747
4031
|
if (parsed.host) {
|
|
3748
4032
|
const ipv4result = isIPv4(parsed.host);
|
|
3749
4033
|
if (ipv4result === false) {
|
|
4034
|
+
const bracketedIPLiteral = parsed.host[0] === "[" && parsed.host[parsed.host.length - 1] === "]";
|
|
3750
4035
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
3751
|
-
|
|
3752
|
-
|
|
4036
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4037
|
+
malformedIPLiteral = bracketedIPLiteral && ipv6result.error === true;
|
|
4038
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4039
|
+
if (malformedIPLiteral) {
|
|
4040
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
4041
|
+
malformedAuthorityOrPort = true;
|
|
4042
|
+
}
|
|
3753
4043
|
} else {
|
|
3754
4044
|
isIP = true;
|
|
3755
4045
|
}
|
|
@@ -3767,42 +4057,34 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3767
4057
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
3768
4058
|
}
|
|
3769
4059
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
3770
|
-
|
|
3771
|
-
if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
3772
|
-
try {
|
|
3773
|
-
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3774
|
-
} catch (e) {
|
|
3775
|
-
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3776
|
-
}
|
|
3777
|
-
}
|
|
3778
|
-
}
|
|
4060
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
3779
4061
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
3780
4062
|
if (uri.indexOf("%") !== -1) {
|
|
3781
|
-
if (parsed.
|
|
3782
|
-
parsed.
|
|
3783
|
-
|
|
3784
|
-
if (parsed.host !== undefined) {
|
|
3785
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
4063
|
+
if (parsed.host !== undefined && !malformedIPLiteral) {
|
|
4064
|
+
const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4065
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
3786
4066
|
}
|
|
3787
4067
|
}
|
|
3788
4068
|
if (parsed.path) {
|
|
3789
4069
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3790
4070
|
}
|
|
4071
|
+
if (parsed.query) {
|
|
4072
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
4073
|
+
}
|
|
3791
4074
|
if (parsed.fragment) {
|
|
3792
|
-
|
|
3793
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3794
|
-
} catch {
|
|
3795
|
-
parsed.error = parsed.error || "URI malformed";
|
|
3796
|
-
}
|
|
4075
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
3797
4076
|
}
|
|
3798
4077
|
}
|
|
3799
4078
|
if (schemeHandler && schemeHandler.parse) {
|
|
3800
4079
|
schemeHandler.parse(parsed, options);
|
|
4080
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === undefined) {
|
|
4081
|
+
malformedSchemeSpecific = true;
|
|
4082
|
+
}
|
|
3801
4083
|
}
|
|
3802
4084
|
} else {
|
|
3803
4085
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3804
4086
|
}
|
|
3805
|
-
return { parsed, malformedAuthorityOrPort };
|
|
4087
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
3806
4088
|
}
|
|
3807
4089
|
function parse6(uri, opts) {
|
|
3808
4090
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -3811,20 +4093,28 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3811
4093
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3812
4094
|
}
|
|
3813
4095
|
function normalizeStringWithStatus(uri, opts) {
|
|
3814
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
4096
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
3815
4097
|
return {
|
|
3816
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
3817
|
-
malformedAuthorityOrPort
|
|
4098
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
4099
|
+
malformedAuthorityOrPort,
|
|
4100
|
+
malformedPercentEncoding,
|
|
4101
|
+
malformedSchemeSpecific,
|
|
4102
|
+
malformedHost,
|
|
4103
|
+
malformedScheme
|
|
3818
4104
|
};
|
|
3819
4105
|
}
|
|
3820
4106
|
function normalizeComparableURI(uri, opts) {
|
|
3821
|
-
if (typeof uri
|
|
3822
|
-
|
|
3823
|
-
return malformedAuthorityOrPort ? undefined : normalized;
|
|
4107
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
4108
|
+
return;
|
|
3824
4109
|
}
|
|
3825
|
-
|
|
3826
|
-
|
|
4110
|
+
let value;
|
|
4111
|
+
try {
|
|
4112
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
4113
|
+
} catch {
|
|
4114
|
+
return;
|
|
3827
4115
|
}
|
|
4116
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
4117
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? undefined : normalized;
|
|
3828
4118
|
}
|
|
3829
4119
|
var fastUri = {
|
|
3830
4120
|
SCHEMES,
|
|
@@ -29396,6 +29686,7 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
29396
29686
|
|
|
29397
29687
|
// src/core/tools/lifecycle.ts
|
|
29398
29688
|
import path6 from "path";
|
|
29689
|
+
import { rmdir } from "node:fs/promises";
|
|
29399
29690
|
|
|
29400
29691
|
// src/core/types.ts
|
|
29401
29692
|
var CODE_DIMENSIONS = ["style", "architecture", "performance", "security", "maintainability"];
|
|
@@ -29452,7 +29743,15 @@ function reviewLayerFromMetadata(child) {
|
|
|
29452
29743
|
// src/core/git.ts
|
|
29453
29744
|
import path from "path";
|
|
29454
29745
|
import { execFile } from "node:child_process";
|
|
29455
|
-
import { readFile, writeFile, stat } from "node:fs/promises";
|
|
29746
|
+
import { readFile, writeFile, stat, rm } from "node:fs/promises";
|
|
29747
|
+
async function pathExists(p) {
|
|
29748
|
+
try {
|
|
29749
|
+
await stat(p);
|
|
29750
|
+
return true;
|
|
29751
|
+
} catch {
|
|
29752
|
+
return false;
|
|
29753
|
+
}
|
|
29754
|
+
}
|
|
29456
29755
|
function execGit(args) {
|
|
29457
29756
|
return new Promise((resolve) => {
|
|
29458
29757
|
const child = execFile("git", args, { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 }, (err, stdout, stderr) => {
|
|
@@ -29485,6 +29784,55 @@ async function runGit(worktree, args) {
|
|
|
29485
29784
|
async function runGitChecked(worktree, args) {
|
|
29486
29785
|
return gitRunner.runChecked(worktree, args);
|
|
29487
29786
|
}
|
|
29787
|
+
async function removeTaskGroupWorktree(repoRoot, wtPath, opts = {}) {
|
|
29788
|
+
const result = { dirResolved: false, dirResolvedByFallback: false, pruned: false, branchDeleted: null, errors: [] };
|
|
29789
|
+
if (!await pathExists(wtPath)) {
|
|
29790
|
+
const pruneRes = await runGitChecked(repoRoot, ["worktree", "prune"]);
|
|
29791
|
+
if (pruneRes.success)
|
|
29792
|
+
result.pruned = true;
|
|
29793
|
+
else
|
|
29794
|
+
result.errors.push(`worktree prune 失败:${pruneRes.stderr}`);
|
|
29795
|
+
result.dirResolved = true;
|
|
29796
|
+
} else {
|
|
29797
|
+
const rmRes = await runGitChecked(repoRoot, ["worktree", "remove", wtPath, "--force"]);
|
|
29798
|
+
if (!rmRes.success)
|
|
29799
|
+
result.errors.push(`git worktree remove 失败:${rmRes.stderr}`);
|
|
29800
|
+
if (await pathExists(wtPath)) {
|
|
29801
|
+
try {
|
|
29802
|
+
await rm(wtPath, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
29803
|
+
} catch (e) {
|
|
29804
|
+
result.errors.push(`文件系统兜底删除 "${wtPath}" 失败:${e instanceof Error ? e.message : String(e)}`);
|
|
29805
|
+
}
|
|
29806
|
+
const pruneRes = await runGitChecked(repoRoot, ["worktree", "prune"]);
|
|
29807
|
+
if (pruneRes.success)
|
|
29808
|
+
result.pruned = true;
|
|
29809
|
+
else
|
|
29810
|
+
result.errors.push(`worktree prune 失败:${pruneRes.stderr}`);
|
|
29811
|
+
if (!await pathExists(wtPath)) {
|
|
29812
|
+
result.dirResolved = true;
|
|
29813
|
+
result.dirResolvedByFallback = true;
|
|
29814
|
+
}
|
|
29815
|
+
} else {
|
|
29816
|
+
result.dirResolved = true;
|
|
29817
|
+
}
|
|
29818
|
+
}
|
|
29819
|
+
if (!result.dirResolved) {
|
|
29820
|
+
if (opts.branchName) {
|
|
29821
|
+
result.errors.push(`目录 "${wtPath}" 未能删除,跳过分支 "${opts.branchName}" 的删除以保留排查线索`);
|
|
29822
|
+
}
|
|
29823
|
+
return result;
|
|
29824
|
+
}
|
|
29825
|
+
if (opts.branchName) {
|
|
29826
|
+
const branchRes = await runGitChecked(repoRoot, ["branch", "-D", opts.branchName]);
|
|
29827
|
+
if (branchRes.success)
|
|
29828
|
+
result.branchDeleted = true;
|
|
29829
|
+
else {
|
|
29830
|
+
result.branchDeleted = false;
|
|
29831
|
+
result.errors.push(`删除分支 "${opts.branchName}" 失败:${branchRes.stderr}`);
|
|
29832
|
+
}
|
|
29833
|
+
}
|
|
29834
|
+
return result;
|
|
29835
|
+
}
|
|
29488
29836
|
async function getCurrentHead(worktree) {
|
|
29489
29837
|
return runGit(worktree, ["rev-parse", "HEAD"]);
|
|
29490
29838
|
}
|
|
@@ -32405,16 +32753,21 @@ function requireLoader() {
|
|
|
32405
32753
|
state.result += _result;
|
|
32406
32754
|
}
|
|
32407
32755
|
}
|
|
32756
|
+
function chargeMergeWork(state) {
|
|
32757
|
+
state.totalMergeKeys++;
|
|
32758
|
+
if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) {
|
|
32759
|
+
throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
|
|
32760
|
+
}
|
|
32761
|
+
}
|
|
32408
32762
|
function mergeMappings(state, destination, source, overridableKeys) {
|
|
32409
32763
|
if (!common2.isObject(source)) {
|
|
32410
32764
|
throwError(state, "cannot merge mappings; the provided source object is unacceptable");
|
|
32411
32765
|
}
|
|
32766
|
+
chargeMergeWork(state);
|
|
32412
32767
|
const sourceKeys = Object.keys(source);
|
|
32413
32768
|
for (let index = 0, quantity = sourceKeys.length;index < quantity; index += 1) {
|
|
32414
32769
|
const key = sourceKeys[index];
|
|
32415
|
-
|
|
32416
|
-
throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
|
|
32417
|
-
}
|
|
32770
|
+
chargeMergeWork(state);
|
|
32418
32771
|
if (!_hasOwnProperty.call(destination, key)) {
|
|
32419
32772
|
setProperty(destination, key, source[key]);
|
|
32420
32773
|
overridableKeys[key] = true;
|
|
@@ -32442,6 +32795,9 @@ function requireLoader() {
|
|
|
32442
32795
|
}
|
|
32443
32796
|
if (keyTag === "tag:yaml.org,2002:merge") {
|
|
32444
32797
|
if (Array.isArray(valueNode)) {
|
|
32798
|
+
if (valueNode.length > 100) {
|
|
32799
|
+
throwError(state, "abnormal merge sequence size");
|
|
32800
|
+
}
|
|
32445
32801
|
for (let index = 0, quantity = valueNode.length;index < quantity; index += 1) {
|
|
32446
32802
|
mergeMappings(state, _result, valueNode[index], overridableKeys);
|
|
32447
32803
|
}
|
|
@@ -34660,6 +35016,20 @@ function renderAgentSummaries(agentSummaries, agentName) {
|
|
|
34660
35016
|
lines.push("");
|
|
34661
35017
|
return lines;
|
|
34662
35018
|
}
|
|
35019
|
+
function renderDevSelfCheckDeclaration(metadata) {
|
|
35020
|
+
const selfCheck = typeof metadata["self_check_results"] === "string" ? metadata["self_check_results"].trim() : "";
|
|
35021
|
+
const testResults = typeof metadata["test_results"] === "string" ? metadata["test_results"].trim() : "";
|
|
35022
|
+
if (selfCheck === "" && testResults === "")
|
|
35023
|
+
return [];
|
|
35024
|
+
const lines = ["## 开发者自检申报", ""];
|
|
35025
|
+
if (selfCheck !== "") {
|
|
35026
|
+
lines.push("**自检申报(self_check_results)**:", "", selfCheck, "");
|
|
35027
|
+
}
|
|
35028
|
+
if (testResults !== "") {
|
|
35029
|
+
lines.push("**接口测试结果(test_results)**:", "", testResults, "");
|
|
35030
|
+
}
|
|
35031
|
+
return lines;
|
|
35032
|
+
}
|
|
34663
35033
|
var INTERPOLATION_ALLOWED_KEYS = new Set([
|
|
34664
35034
|
"worktree_path",
|
|
34665
35035
|
"change_id",
|
|
@@ -35192,7 +35562,13 @@ function renderAgentWorking(item, rec, step, common2, ctxAgent, state, tg, toolC
|
|
|
35192
35562
|
lines.push(...renderStepSemantics(step, common2, stepCtx));
|
|
35193
35563
|
lines.push(...renderWorktreeSection(state, tg, { showNamespace: true, showPort: true }));
|
|
35194
35564
|
if (step?.id === "verify_tool" && agentToReviewLayer(ctxAgent) === "tool" && toolChanges?.hasNonDocChange) {
|
|
35195
|
-
lines.push(...renderToolChangesEvidence(item, tg, toolChanges));
|
|
35565
|
+
lines.push(...renderToolChangesEvidence(item, tg, toolChanges, "tool_review"));
|
|
35566
|
+
}
|
|
35567
|
+
if (step?.id === "quality_review" && toolChanges) {
|
|
35568
|
+
lines.push(...renderToolChangesEvidence(item, tg, toolChanges, "merged_review"));
|
|
35569
|
+
}
|
|
35570
|
+
if (step?.id === "quality_review") {
|
|
35571
|
+
lines.push(...renderDevSelfCheckDeclaration(item.metadata));
|
|
35196
35572
|
}
|
|
35197
35573
|
lines.push(...renderAgentSummaries(readAgentSummaries(item), ctxAgent));
|
|
35198
35574
|
lines.push(...renderStepContext(item, step, ctxAgent, state, exemptionCtx));
|
|
@@ -35400,15 +35776,20 @@ function renderToolChildren(item, ctxAgent, exemptionCtx) {
|
|
|
35400
35776
|
lines.push(...renderChildrenSection("Issue (待裁定是否可豁免)", pending, exemptionCtx));
|
|
35401
35777
|
return lines;
|
|
35402
35778
|
}
|
|
35403
|
-
|
|
35779
|
+
var EVIDENCE_KIND_LABELS = {
|
|
35780
|
+
tool_review: { title: "自上次工具检查", lastCheck: "上次工具检查" },
|
|
35781
|
+
merged_review: { title: "自上次合并审查", lastCheck: "上次合并审查" }
|
|
35782
|
+
};
|
|
35783
|
+
function renderToolChangesEvidence(item, tg, toolChanges, kind) {
|
|
35784
|
+
const label = EVIDENCE_KIND_LABELS[kind];
|
|
35404
35785
|
const checkpoint = typeof item.metadata["_tool_review_checkpoint"] === "string" ? item.metadata["_tool_review_checkpoint"] : undefined;
|
|
35405
35786
|
const baseRef = tg.baseRef ?? undefined;
|
|
35406
35787
|
const rangeRef = checkpoint ?? baseRef;
|
|
35407
|
-
const lines = [
|
|
35788
|
+
const lines = [`## 本次变更证据(${label.title})`, ""];
|
|
35408
35789
|
if (checkpoint) {
|
|
35409
|
-
lines.push(`- **口径**:
|
|
35790
|
+
lines.push(`- **口径**: 本次为「${label.title}(${checkpoint}..HEAD)」的增量区间(含已提交与未提交的非 openspec 变更);` + `与上方「变更范围」(${baseRef ?? "(无)"}..HEAD 整个 change 累计口径)不同`, "");
|
|
35410
35791
|
} else if (baseRef) {
|
|
35411
|
-
lines.push(`- **口径**: 本次区间以基线(${baseRef}..HEAD
|
|
35792
|
+
lines.push(`- **口径**: 本次区间以基线(${baseRef}..HEAD)兜底,与上方「变更范围」一致(首次进入,无${label.lastCheck}记录;` + "含已提交与未提交的非 openspec 变更)", "");
|
|
35412
35793
|
} else {
|
|
35413
35794
|
lines.push("- **口径**: 无检查点且无基线基准,无法界定已提交变更区间;本次变更仅按检出文件与未提交变更提示", "");
|
|
35414
35795
|
}
|
|
@@ -36014,13 +36395,15 @@ async function setWorktreeExecute(params, ctx) {
|
|
|
36014
36395
|
await bindWorktreeRefs(item, existingPath, branch, state.baseBranch);
|
|
36015
36396
|
reused = true;
|
|
36016
36397
|
} else {
|
|
36017
|
-
const
|
|
36018
|
-
if (!
|
|
36019
|
-
|
|
36020
|
-
|
|
36021
|
-
|
|
36022
|
-
|
|
36023
|
-
|
|
36398
|
+
const cleanup = await removeTaskGroupWorktree(repoRoot, existingPath, { branchName: branch });
|
|
36399
|
+
if (!cleanup.dirResolved || cleanup.branchDeleted === false) {
|
|
36400
|
+
const problems = [];
|
|
36401
|
+
if (!cleanup.dirResolved)
|
|
36402
|
+
problems.push(`无法清理已有 worktree "${existingPath}"`);
|
|
36403
|
+
if (cleanup.branchDeleted === false)
|
|
36404
|
+
problems.push(`无法清理已有分支 "${branch}"`);
|
|
36405
|
+
throw new Error(`${problems.join(";")}:${cleanup.errors.join(";") || "原因未知"}
|
|
36406
|
+
请手动处理后重试。`);
|
|
36024
36407
|
}
|
|
36025
36408
|
}
|
|
36026
36409
|
}
|
|
@@ -36071,7 +36454,8 @@ async function statusExecute(params, ctx) {
|
|
|
36071
36454
|
const tg = findTaskGroup(state, state.taskGroupId);
|
|
36072
36455
|
const mainPollution = ctx.orchestrator ? await detectMainRepoPollution(ctx.worktree) : null;
|
|
36073
36456
|
let toolChanges;
|
|
36074
|
-
|
|
36457
|
+
const changesEvidenceStep = rec.status === "recommend" && rec.agents.includes(agent) && (agentToReviewLayer(agent) === "tool" && rec.stepId === "verify_tool" || agent === "openspec-reviewer" && rec.stepId === "quality_review");
|
|
36458
|
+
if (changesEvidenceStep) {
|
|
36075
36459
|
const wtPath = typeof item.metadata["worktree_path"] === "string" ? item.metadata["worktree_path"] : undefined;
|
|
36076
36460
|
if (wtPath) {
|
|
36077
36461
|
const checkpoint = typeof item.metadata["_tool_review_checkpoint"] === "string" ? item.metadata["_tool_review_checkpoint"] : undefined;
|
|
@@ -36083,6 +36467,19 @@ async function statusExecute(params, ctx) {
|
|
|
36083
36467
|
const exemptionItems = (await readExemptions(ctx.worktree)).items;
|
|
36084
36468
|
return renderWorkflowStatusView(item, workflow, rec, { agent, orchestrator: ctx.orchestrator, identityDeclared: ctx.identityDeclared }, { state, tg, mainPollution, toolChanges, exemptedHits, exemptionItems });
|
|
36085
36469
|
}
|
|
36470
|
+
async function sweepEmptyWorktreeParents(repoRoot, removedDir, changeId) {
|
|
36471
|
+
const repoRootAbs = path6.resolve(repoRoot);
|
|
36472
|
+
const groupLevelDir = path6.join(repoRootAbs, ".worktree", changeId);
|
|
36473
|
+
const worktreeLevelDir = path6.join(repoRootAbs, ".worktree");
|
|
36474
|
+
if (path6.dirname(path6.resolve(removedDir)) === groupLevelDir) {
|
|
36475
|
+
try {
|
|
36476
|
+
await rmdir(groupLevelDir);
|
|
36477
|
+
} catch {}
|
|
36478
|
+
}
|
|
36479
|
+
try {
|
|
36480
|
+
await rmdir(worktreeLevelDir);
|
|
36481
|
+
} catch {}
|
|
36482
|
+
}
|
|
36086
36483
|
async function completeTaskGroupExecute(params, ctx) {
|
|
36087
36484
|
assertOrchestrator(ctx, "opx_orch_complete_task_group");
|
|
36088
36485
|
const state = await readStateByWorktree(ctx.worktree, params.change_id);
|
|
@@ -36137,17 +36534,42 @@ async function completeTaskGroupExecute(params, ctx) {
|
|
|
36137
36534
|
`);
|
|
36138
36535
|
}
|
|
36139
36536
|
}
|
|
36140
|
-
|
|
36141
|
-
|
|
36142
|
-
|
|
36143
|
-
|
|
36144
|
-
|
|
36537
|
+
let cleanupNote = "";
|
|
36538
|
+
let cleanupResidualWarning = "";
|
|
36539
|
+
if (worktreePath) {
|
|
36540
|
+
const cleanup = await removeTaskGroupWorktree(ctx.worktree, worktreePath, { branchName });
|
|
36541
|
+
if (cleanup.dirResolved) {
|
|
36542
|
+
await sweepEmptyWorktreeParents(ctx.worktree, worktreePath, params.change_id);
|
|
36543
|
+
const successNotes = [];
|
|
36544
|
+
if (cleanup.dirResolvedByFallback) {
|
|
36545
|
+
successNotes.push("- **cleanup**: git worktree remove 未直接移除目录,已按文件系统兜底删除并 prune 管理记录。");
|
|
36546
|
+
}
|
|
36547
|
+
if (cleanup.errors.length > 0) {
|
|
36548
|
+
successNotes.push(`- **cleanup 部分告警**: ${cleanup.errors.join(";")}`);
|
|
36549
|
+
}
|
|
36550
|
+
cleanupNote = successNotes.join(`
|
|
36551
|
+
`);
|
|
36552
|
+
} else {
|
|
36553
|
+
item.metadata["cleanup_residual"] = { worktree_path: worktreePath, errors: cleanup.errors };
|
|
36554
|
+
cleanupResidualWarning = [
|
|
36555
|
+
"",
|
|
36556
|
+
"## ⚠️ worktree 清理残留(不影响收尾)",
|
|
36557
|
+
`- **残留路径**: \`${worktreePath}\``,
|
|
36558
|
+
"- **原因**:",
|
|
36559
|
+
...cleanup.errors.map((e) => ` - ${e}`),
|
|
36560
|
+
`- **处理**: 请人工执行 \`rm -rf '${worktreePath}' && git worktree prune\` 清理残留目录与 git 管理记录。`,
|
|
36561
|
+
branchName ? `- **分支**: 分支 "${branchName}" 未删除。` : ""
|
|
36562
|
+
].filter(Boolean).join(`
|
|
36563
|
+
`);
|
|
36564
|
+
}
|
|
36145
36565
|
}
|
|
36146
36566
|
item.metadata["completed_at"] = new Date().toISOString();
|
|
36147
36567
|
await writeState(ctx.worktree, state);
|
|
36148
36568
|
const doneMessage = `任务组已完成并合并到 "${mergeTarget}"。`;
|
|
36149
|
-
|
|
36150
|
-
|
|
36569
|
+
const notes = [cleanupNote, checkboxWarning, cleanupResidualWarning].filter(Boolean);
|
|
36570
|
+
return notes.length > 0 ? `${doneMessage}
|
|
36571
|
+
${notes.join(`
|
|
36572
|
+
`)}` : doneMessage;
|
|
36151
36573
|
}
|
|
36152
36574
|
async function setUnattendedExecute(params, ctx) {
|
|
36153
36575
|
assertOrchestrator(ctx, "opx_orch_set_unattended");
|
|
@@ -36350,6 +36772,9 @@ function handleImplementParams(item, params) {
|
|
|
36350
36772
|
if (params.self_check_results) {
|
|
36351
36773
|
item.metadata["self_check_results"] = params.self_check_results;
|
|
36352
36774
|
}
|
|
36775
|
+
if (params.test_results) {
|
|
36776
|
+
item.metadata["test_results"] = params.test_results;
|
|
36777
|
+
}
|
|
36353
36778
|
}
|
|
36354
36779
|
function mergeBoundaryInto(item, expansion) {
|
|
36355
36780
|
const boundary = item.metadata["execution_boundary"];
|
|
@@ -36401,7 +36826,7 @@ function handleReviewParams(item, params, newChildren, stepId, opts) {
|
|
|
36401
36826
|
}
|
|
36402
36827
|
mergeBoundaryInto(item, params.boundary_expansion);
|
|
36403
36828
|
}
|
|
36404
|
-
if (params.test_results)
|
|
36829
|
+
if (params.test_results && stepId !== "quality_review")
|
|
36405
36830
|
item.metadata["test_results"] = params.test_results;
|
|
36406
36831
|
if (params.validation_steps) {
|
|
36407
36832
|
assertStructuredSkipReasons(params.validation_steps);
|
|
@@ -36411,7 +36836,7 @@ function handleReviewParams(item, params, newChildren, stepId, opts) {
|
|
|
36411
36836
|
const uncovered = uncoveredMustDo(opts.capabilityTags, params.validation_steps);
|
|
36412
36837
|
if (uncovered.length > 0) {
|
|
36413
36838
|
throw new Error(`提交的验证步骤未覆盖质量门 skill 必做清单,缺少以下必做项:${uncovered.join("、")}。
|
|
36414
|
-
` + `请按已加载质量门类 skill 的必做清单逐项执行并逐项申报结果(completed=true);` + `确实无法执行的必做项须以结构化 skip_reason 申报降级理由` + `(格式:${SKIP_REASON_FORMAT})。`);
|
|
36839
|
+
` + `请按已加载质量门类 skill 的必做清单逐项执行并逐项申报结果(completed=true);` + `确实无法执行的必做项须以结构化 skip_reason 申报降级理由` + `(格式:${SKIP_REASON_FORMAT})。` + `低成本必做项必须实跑后申报;核验申报仅限 workflow 指令白名单限定的高成本必做项。`);
|
|
36415
36840
|
}
|
|
36416
36841
|
}
|
|
36417
36842
|
if (params.verified_tasks?.length || params.failed_tasks?.length) {
|
|
@@ -36636,7 +37061,7 @@ async function agentSubmitExecute(params, ctx) {
|
|
|
36636
37061
|
baseRef
|
|
36637
37062
|
});
|
|
36638
37063
|
}
|
|
36639
|
-
if (params.step_id === "verify_tool" && agentToReviewLayer(ctx.agent) === "tool") {
|
|
37064
|
+
if (params.step_id === "verify_tool" && agentToReviewLayer(ctx.agent) === "tool" || params.step_id === "quality_review" && ctx.agent === "openspec-reviewer") {
|
|
36640
37065
|
const head = await getCurrentHead(wtPath);
|
|
36641
37066
|
if (head)
|
|
36642
37067
|
item.metadata["_tool_review_checkpoint"] = head;
|
|
@@ -37043,7 +37468,10 @@ var agentSubmitSchema = {
|
|
|
37043
37468
|
description: "implement step:已完成的 task id(覆盖门禁:全部 open/rejected task 必须被覆盖)",
|
|
37044
37469
|
items: { type: "string" }
|
|
37045
37470
|
},
|
|
37046
|
-
test_results: {
|
|
37471
|
+
test_results: {
|
|
37472
|
+
type: "string",
|
|
37473
|
+
description: "implement / verify_tool step:测试运行结果摘要(implement 为接口测试执行结果——附执行顺序与覆盖接口清单;verify_tool 为 UT 运行结果摘要);quality_review(simple 合并审查)下由开发者在 implement 申报,审查者提交时不生效"
|
|
37474
|
+
},
|
|
37047
37475
|
validation_steps: {
|
|
37048
37476
|
type: "array",
|
|
37049
37477
|
description: "review step:验证步骤执行摘要",
|
|
@@ -37185,7 +37613,7 @@ async function ensureDefaultUnattended(args, ctx) {
|
|
|
37185
37613
|
}
|
|
37186
37614
|
} catch {}
|
|
37187
37615
|
}
|
|
37188
|
-
var PKG_VERSION = "0.
|
|
37616
|
+
var PKG_VERSION = "0.131.0";
|
|
37189
37617
|
function buildMcpServer(worktree, opts = {}) {
|
|
37190
37618
|
const mcp = new McpServer({ name: "openspec-agents", version: PKG_VERSION });
|
|
37191
37619
|
for (const [name, spec] of Object.entries(TOOL_SPECS)) {
|