@impractical-ai/motion 0.1.13 → 0.1.14
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/{api-4YQKINQI.js → api-VLQHOCLI.js} +6 -2
- package/dist/{chunk-PTYSKJ2Y.js → chunk-7SNCVSTA.js} +4 -4
- package/dist/{chunk-ZCTJTQB7.js → chunk-L5ERED5A.js} +79 -10
- package/dist/{chunk-GAHKKLF3.js → chunk-O3BUN66P.js} +45 -14
- package/dist/{commands-NWJK7ANI.js → commands-3PIMUGYP.js} +12 -5
- package/dist/index.js +5 -5
- package/dist/{stdio-PLWZDKDA.js → stdio-M2YRHGFJ.js} +773 -237
- package/package.json +3 -3
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
DEVICE_START_BODY,
|
|
4
|
+
fetchWorkspaces,
|
|
5
|
+
grantScope,
|
|
6
|
+
openBrowser,
|
|
7
|
+
workspaceLabel
|
|
8
|
+
} from "./chunk-L5ERED5A.js";
|
|
5
9
|
import {
|
|
6
10
|
ApiError,
|
|
7
11
|
admitMcpCall,
|
|
8
12
|
invoke,
|
|
9
13
|
invokeAt,
|
|
10
14
|
loadConfig,
|
|
15
|
+
requireConfig,
|
|
11
16
|
saveConfig,
|
|
17
|
+
studioQuery,
|
|
12
18
|
validateApiResponse,
|
|
13
19
|
withAdmissionReceipt
|
|
14
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-O3BUN66P.js";
|
|
15
21
|
import {
|
|
16
22
|
BUILD_COMMIT,
|
|
17
23
|
PACKAGE_VERSION,
|
|
18
24
|
PRODUCTION_APP_URL,
|
|
19
25
|
PRODUCTION_SUPABASE_URL
|
|
20
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-7SNCVSTA.js";
|
|
21
27
|
import {
|
|
22
28
|
__commonJS,
|
|
23
29
|
__export,
|
|
@@ -3100,9 +3106,28 @@ var require_utils = __commonJS({
|
|
|
3100
3106
|
"use strict";
|
|
3101
3107
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
3102
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);
|
|
3103
3110
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3104
3111
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3105
|
-
var isPathCharacter = 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);
|
|
3115
|
+
var BYTE_HEX = new Array(256);
|
|
3116
|
+
{
|
|
3117
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
3118
|
+
for (let i = 0; i < 256; i++) {
|
|
3119
|
+
BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
function percentEncodeNonAscii(cp) {
|
|
3123
|
+
if (cp < 2048) {
|
|
3124
|
+
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
3125
|
+
}
|
|
3126
|
+
if (cp < 65536) {
|
|
3127
|
+
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3128
|
+
}
|
|
3129
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3130
|
+
}
|
|
3106
3131
|
function stringArrayToHexStripped(input) {
|
|
3107
3132
|
let acc = "";
|
|
3108
3133
|
let code = 0;
|
|
@@ -3127,91 +3152,105 @@ var require_utils = __commonJS({
|
|
|
3127
3152
|
}
|
|
3128
3153
|
return acc;
|
|
3129
3154
|
}
|
|
3155
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
3156
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
3157
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
3130
3158
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3131
|
-
function
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
if (hex3 !== "") {
|
|
3139
|
-
address.push(hex3);
|
|
3140
|
-
} else {
|
|
3141
|
-
output.error = true;
|
|
3142
|
-
return false;
|
|
3159
|
+
function isZoneIdentifier(zone) {
|
|
3160
|
+
if (zone.length === 0) return false;
|
|
3161
|
+
for (let i = 0; i < zone.length; i++) {
|
|
3162
|
+
if (isZoneCharacter(zone[i])) continue;
|
|
3163
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
3164
|
+
i += 2;
|
|
3165
|
+
continue;
|
|
3143
3166
|
}
|
|
3144
|
-
|
|
3167
|
+
return false;
|
|
3145
3168
|
}
|
|
3146
3169
|
return true;
|
|
3147
3170
|
}
|
|
3148
|
-
function
|
|
3149
|
-
let
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
let
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
}
|
|
3161
|
-
if (cursor === ":") {
|
|
3162
|
-
if (endipv6Encountered === true) {
|
|
3163
|
-
endIpv6 = true;
|
|
3164
|
-
}
|
|
3165
|
-
if (!consume(buffer, address, output)) {
|
|
3166
|
-
break;
|
|
3167
|
-
}
|
|
3168
|
-
if (++tokenCount > 7) {
|
|
3169
|
-
output.error = true;
|
|
3170
|
-
break;
|
|
3171
|
-
}
|
|
3172
|
-
if (i > 0 && input[i - 1] === ":") {
|
|
3173
|
-
endipv6Encountered = true;
|
|
3174
|
-
}
|
|
3175
|
-
address.push(":");
|
|
3176
|
-
continue;
|
|
3177
|
-
} else if (cursor === "%") {
|
|
3178
|
-
if (!consume(buffer, address, output)) {
|
|
3179
|
-
break;
|
|
3171
|
+
function compressIPv6ZeroRun(hextets) {
|
|
3172
|
+
let bestStart = -1;
|
|
3173
|
+
let bestLength = 0;
|
|
3174
|
+
let runStart = -1;
|
|
3175
|
+
let runLength = 0;
|
|
3176
|
+
for (let i = 0; i < hextets.length; i++) {
|
|
3177
|
+
if (hextets[i] === "0") {
|
|
3178
|
+
if (runStart === -1) runStart = i;
|
|
3179
|
+
runLength++;
|
|
3180
|
+
if (runLength > bestLength) {
|
|
3181
|
+
bestLength = runLength;
|
|
3182
|
+
bestStart = runStart;
|
|
3180
3183
|
}
|
|
3181
|
-
consume = consumeIsZone;
|
|
3182
3184
|
} else {
|
|
3183
|
-
|
|
3185
|
+
runStart = -1;
|
|
3186
|
+
runLength = 0;
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
if (bestLength < 2) return hextets.join(":");
|
|
3190
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
3191
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
3192
|
+
return head + "::" + tail;
|
|
3193
|
+
}
|
|
3194
|
+
function normalizeIPv6Address(input) {
|
|
3195
|
+
const compression = input.indexOf("::");
|
|
3196
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
|
|
3197
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
3198
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
3199
|
+
if (compression !== -1) {
|
|
3200
|
+
if (left.length === 1 && left[0] === "") left.length = 0;
|
|
3201
|
+
if (right.length === 1 && right[0] === "") right.length = 0;
|
|
3202
|
+
}
|
|
3203
|
+
const parts = left.concat(right);
|
|
3204
|
+
let hextetCount = 0;
|
|
3205
|
+
for (let i = 0; i < parts.length; i++) {
|
|
3206
|
+
const part = parts[i];
|
|
3207
|
+
if (part === "") return void 0;
|
|
3208
|
+
if (part.indexOf(".") !== -1) {
|
|
3209
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
|
|
3210
|
+
hextetCount += 2;
|
|
3184
3211
|
continue;
|
|
3185
3212
|
}
|
|
3213
|
+
if (!isHextet(part)) return void 0;
|
|
3214
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
3215
|
+
hextetCount++;
|
|
3186
3216
|
}
|
|
3187
|
-
if (
|
|
3188
|
-
if (
|
|
3189
|
-
|
|
3190
|
-
} else if (endIpv6) {
|
|
3191
|
-
address.push(buffer.join(""));
|
|
3192
|
-
} else {
|
|
3193
|
-
address.push(stringArrayToHexStripped(buffer));
|
|
3194
|
-
}
|
|
3217
|
+
if (compression === -1) {
|
|
3218
|
+
if (hextetCount !== 8) return void 0;
|
|
3219
|
+
return compressIPv6ZeroRun(parts);
|
|
3195
3220
|
}
|
|
3196
|
-
|
|
3197
|
-
|
|
3221
|
+
if (hextetCount >= 8) return void 0;
|
|
3222
|
+
const expanded = parts.slice(0, left.length);
|
|
3223
|
+
for (let i = hextetCount; i < 8; i++) expanded.push("0");
|
|
3224
|
+
for (let i = left.length; i < parts.length; i++) expanded.push(parts[i]);
|
|
3225
|
+
return compressIPv6ZeroRun(expanded);
|
|
3198
3226
|
}
|
|
3199
3227
|
function normalizeIPv6(host) {
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
}
|
|
3203
|
-
|
|
3204
|
-
if (
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3228
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
3229
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
3230
|
+
if (hasBracket && !bracketed) return { host, isIPV6: false, error: true };
|
|
3231
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
3232
|
+
if (bracketed && isIPvFuture(input)) {
|
|
3233
|
+
input = input.toLowerCase();
|
|
3234
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
3235
|
+
}
|
|
3236
|
+
if (findToken(input, ":") < 2) {
|
|
3237
|
+
return { host, isIPV6: false, error: bracketed };
|
|
3238
|
+
}
|
|
3239
|
+
let zoneIdentifier = "";
|
|
3240
|
+
const zoneSeparator = input.indexOf("%");
|
|
3241
|
+
if (zoneSeparator !== -1) {
|
|
3242
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
3243
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
3244
|
+
if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true };
|
|
3245
|
+
input = input.slice(0, zoneSeparator);
|
|
3246
|
+
}
|
|
3247
|
+
const address = normalizeIPv6Address(input);
|
|
3248
|
+
if (address === void 0) return { host, isIPV6: false, error: true };
|
|
3249
|
+
return {
|
|
3250
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
3251
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
3252
|
+
isIPV6: true
|
|
3253
|
+
};
|
|
3215
3254
|
}
|
|
3216
3255
|
function findToken(str, token) {
|
|
3217
3256
|
let ind = 0;
|
|
@@ -3330,7 +3369,8 @@ var require_utils = __commonJS({
|
|
|
3330
3369
|
function normalizePathEncoding(input) {
|
|
3331
3370
|
let output = "";
|
|
3332
3371
|
for (let i = 0; i < input.length; i++) {
|
|
3333
|
-
|
|
3372
|
+
const ch = input[i];
|
|
3373
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3334
3374
|
const hex3 = input.slice(i + 1, i + 3);
|
|
3335
3375
|
if (isHexPair(hex3)) {
|
|
3336
3376
|
const normalizedHex = hex3.toUpperCase();
|
|
@@ -3344,10 +3384,152 @@ var require_utils = __commonJS({
|
|
|
3344
3384
|
continue;
|
|
3345
3385
|
}
|
|
3346
3386
|
}
|
|
3347
|
-
if (isPathCharacter(
|
|
3348
|
-
output +=
|
|
3387
|
+
if (isPathCharacter(ch)) {
|
|
3388
|
+
output += ch;
|
|
3389
|
+
} else {
|
|
3390
|
+
const code = input.charCodeAt(i);
|
|
3391
|
+
if (code < 128) {
|
|
3392
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3393
|
+
} else if (code < 55296 || code > 57343) {
|
|
3394
|
+
output += percentEncodeNonAscii(code);
|
|
3395
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3396
|
+
const low = input.charCodeAt(i + 1);
|
|
3397
|
+
if (low >= 56320 && low <= 57343) {
|
|
3398
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3399
|
+
i++;
|
|
3400
|
+
} else {
|
|
3401
|
+
output += percentEncodeNonAscii(65533);
|
|
3402
|
+
}
|
|
3403
|
+
} else {
|
|
3404
|
+
output += percentEncodeNonAscii(65533);
|
|
3405
|
+
}
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
return output;
|
|
3409
|
+
}
|
|
3410
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
3411
|
+
let output = "";
|
|
3412
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
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 (ch === "/") {
|
|
3424
|
+
firstSegment = false;
|
|
3425
|
+
}
|
|
3426
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
|
|
3427
|
+
output += ch;
|
|
3428
|
+
} else {
|
|
3429
|
+
const code = input.charCodeAt(i);
|
|
3430
|
+
if (code < 128) {
|
|
3431
|
+
output += BYTE_HEX[code];
|
|
3432
|
+
} else if (code < 55296 || code > 57343) {
|
|
3433
|
+
output += percentEncodeNonAscii(code);
|
|
3434
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3435
|
+
const low = input.charCodeAt(i + 1);
|
|
3436
|
+
if (low >= 56320 && low <= 57343) {
|
|
3437
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3438
|
+
i++;
|
|
3439
|
+
} else {
|
|
3440
|
+
output += percentEncodeNonAscii(65533);
|
|
3441
|
+
}
|
|
3442
|
+
} else {
|
|
3443
|
+
output += percentEncodeNonAscii(65533);
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
return output;
|
|
3448
|
+
}
|
|
3449
|
+
function encodeComponent(input, isAllowed) {
|
|
3450
|
+
let output = "";
|
|
3451
|
+
for (let i = 0; i < input.length; i++) {
|
|
3452
|
+
const ch = input[i];
|
|
3453
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3454
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3455
|
+
if (isHexPair(hex3)) {
|
|
3456
|
+
output += "%" + hex3.toUpperCase();
|
|
3457
|
+
i += 2;
|
|
3458
|
+
continue;
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
if (isAllowed(ch)) {
|
|
3462
|
+
output += ch;
|
|
3463
|
+
} else {
|
|
3464
|
+
const code = input.charCodeAt(i);
|
|
3465
|
+
if (code < 128) {
|
|
3466
|
+
output += BYTE_HEX[code];
|
|
3467
|
+
} else if (code < 55296 || code > 57343) {
|
|
3468
|
+
output += percentEncodeNonAscii(code);
|
|
3469
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3470
|
+
const low = input.charCodeAt(i + 1);
|
|
3471
|
+
if (low >= 56320 && low <= 57343) {
|
|
3472
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3473
|
+
i++;
|
|
3474
|
+
} else {
|
|
3475
|
+
output += percentEncodeNonAscii(65533);
|
|
3476
|
+
}
|
|
3477
|
+
} else {
|
|
3478
|
+
output += percentEncodeNonAscii(65533);
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
return output;
|
|
3483
|
+
}
|
|
3484
|
+
function encodeUserinfo(input) {
|
|
3485
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
3486
|
+
}
|
|
3487
|
+
function encodeQuery(input) {
|
|
3488
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3489
|
+
}
|
|
3490
|
+
function encodeFragment(input) {
|
|
3491
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3492
|
+
}
|
|
3493
|
+
function isEscapeSafe(cp) {
|
|
3494
|
+
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;
|
|
3495
|
+
}
|
|
3496
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
3497
|
+
let output = "";
|
|
3498
|
+
for (let i = 0; i < input.length; i++) {
|
|
3499
|
+
const ch = input[i];
|
|
3500
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3501
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3502
|
+
if (isHexPair(hex3)) {
|
|
3503
|
+
const normalizedHex = hex3.toUpperCase();
|
|
3504
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3505
|
+
if (isUnreserved(decoded)) {
|
|
3506
|
+
output += decoded;
|
|
3507
|
+
} else {
|
|
3508
|
+
output += "%" + normalizedHex;
|
|
3509
|
+
}
|
|
3510
|
+
i += 2;
|
|
3511
|
+
continue;
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
3515
|
+
output += ch;
|
|
3349
3516
|
} else {
|
|
3350
|
-
|
|
3517
|
+
const code = input.charCodeAt(i);
|
|
3518
|
+
if (code < 128) {
|
|
3519
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3520
|
+
} else if (code < 55296 || code > 57343) {
|
|
3521
|
+
output += percentEncodeNonAscii(code);
|
|
3522
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3523
|
+
const low = input.charCodeAt(i + 1);
|
|
3524
|
+
if (low >= 56320 && low <= 57343) {
|
|
3525
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3526
|
+
i++;
|
|
3527
|
+
} else {
|
|
3528
|
+
output += percentEncodeNonAscii(65533);
|
|
3529
|
+
}
|
|
3530
|
+
} else {
|
|
3531
|
+
output += percentEncodeNonAscii(65533);
|
|
3532
|
+
}
|
|
3351
3533
|
}
|
|
3352
3534
|
}
|
|
3353
3535
|
return output;
|
|
@@ -3370,14 +3552,18 @@ var require_utils = __commonJS({
|
|
|
3370
3552
|
function recomposeAuthority(component) {
|
|
3371
3553
|
const uriTokens = [];
|
|
3372
3554
|
if (component.userinfo !== void 0) {
|
|
3373
|
-
uriTokens.push(component.userinfo);
|
|
3555
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
3374
3556
|
uriTokens.push("@");
|
|
3375
3557
|
}
|
|
3376
3558
|
if (component.host !== void 0) {
|
|
3377
|
-
let host =
|
|
3559
|
+
let host = component.host;
|
|
3378
3560
|
if (!isIPv4(host)) {
|
|
3379
|
-
|
|
3380
|
-
if (ipV6res.isIPV6
|
|
3561
|
+
let ipV6res = normalizeIPv6(host);
|
|
3562
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
3563
|
+
host = normalizePercentEncoding(host, true);
|
|
3564
|
+
ipV6res = normalizeIPv6(host);
|
|
3565
|
+
}
|
|
3566
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
3381
3567
|
host = `[${ipV6res.escapedHost}]`;
|
|
3382
3568
|
} else {
|
|
3383
3569
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -3386,8 +3572,12 @@ var require_utils = __commonJS({
|
|
|
3386
3572
|
uriTokens.push(host);
|
|
3387
3573
|
}
|
|
3388
3574
|
if (typeof component.port === "number" || typeof component.port === "string") {
|
|
3575
|
+
const port = String(component.port);
|
|
3576
|
+
if (!isPort(port)) {
|
|
3577
|
+
throw new TypeError("URI port is malformed.");
|
|
3578
|
+
}
|
|
3389
3579
|
uriTokens.push(":");
|
|
3390
|
-
uriTokens.push(
|
|
3580
|
+
uriTokens.push(port);
|
|
3391
3581
|
}
|
|
3392
3582
|
return uriTokens.length ? uriTokens.join("") : void 0;
|
|
3393
3583
|
}
|
|
@@ -3397,6 +3587,11 @@ var require_utils = __commonJS({
|
|
|
3397
3587
|
reescapeHostDelimiters,
|
|
3398
3588
|
normalizePercentEncoding,
|
|
3399
3589
|
normalizePathEncoding,
|
|
3590
|
+
serializePathEncoding,
|
|
3591
|
+
normalizeQueryFragmentEncoding,
|
|
3592
|
+
encodeUserinfo,
|
|
3593
|
+
encodeQuery,
|
|
3594
|
+
encodeFragment,
|
|
3400
3595
|
escapePreservingEscapes,
|
|
3401
3596
|
removeDotSegments,
|
|
3402
3597
|
isIPv4,
|
|
@@ -3412,7 +3607,7 @@ var require_schemes = __commonJS({
|
|
|
3412
3607
|
"node_modules/fast-uri/lib/schemes.js"(exports, module) {
|
|
3413
3608
|
"use strict";
|
|
3414
3609
|
var { isUUID } = require_utils();
|
|
3415
|
-
var URN_REG =
|
|
3610
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
3416
3611
|
var supportedSchemeNames = (
|
|
3417
3612
|
/** @type {const} */
|
|
3418
3613
|
[
|
|
@@ -3473,9 +3668,10 @@ var require_schemes = __commonJS({
|
|
|
3473
3668
|
wsComponent.secure = void 0;
|
|
3474
3669
|
}
|
|
3475
3670
|
if (wsComponent.resourceName) {
|
|
3476
|
-
const
|
|
3671
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3672
|
+
const path7 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3477
3673
|
wsComponent.path = path7 && path7 !== "/" ? path7 : void 0;
|
|
3478
|
-
wsComponent.query =
|
|
3674
|
+
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3479
3675
|
wsComponent.resourceName = void 0;
|
|
3480
3676
|
}
|
|
3481
3677
|
wsComponent.fragment = void 0;
|
|
@@ -3487,7 +3683,7 @@ var require_schemes = __commonJS({
|
|
|
3487
3683
|
return urnComponent;
|
|
3488
3684
|
}
|
|
3489
3685
|
const matches = urnComponent.path.match(URN_REG);
|
|
3490
|
-
if (matches) {
|
|
3686
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
3491
3687
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
3492
3688
|
urnComponent.nid = matches[1].toLowerCase();
|
|
3493
3689
|
urnComponent.nss = matches[2];
|
|
@@ -3621,8 +3817,17 @@ var require_schemes = __commonJS({
|
|
|
3621
3817
|
var require_fast_uri = __commonJS({
|
|
3622
3818
|
"node_modules/fast-uri/index.js"(exports, module) {
|
|
3623
3819
|
"use strict";
|
|
3624
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3820
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3625
3821
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3822
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
3823
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
3824
|
+
function decodeValidScheme(scheme) {
|
|
3825
|
+
const decodedScheme = unescape(String(scheme));
|
|
3826
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
3827
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
3828
|
+
}
|
|
3829
|
+
return decodedScheme;
|
|
3830
|
+
}
|
|
3626
3831
|
function normalize2(uri, options) {
|
|
3627
3832
|
if (typeof uri === "string") {
|
|
3628
3833
|
uri = /** @type {T} */
|
|
@@ -3635,12 +3840,34 @@ var require_fast_uri = __commonJS({
|
|
|
3635
3840
|
}
|
|
3636
3841
|
function resolve(baseURI, relativeURI, options) {
|
|
3637
3842
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3638
|
-
const {
|
|
3639
|
-
|
|
3640
|
-
|
|
3843
|
+
const {
|
|
3844
|
+
parsed: baseParsed,
|
|
3845
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
3846
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
3847
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
3848
|
+
malformedHost: baseMalformedHost,
|
|
3849
|
+
malformedScheme: baseMalformedScheme
|
|
3850
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
3851
|
+
const {
|
|
3852
|
+
parsed: relativeParsed,
|
|
3853
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
3854
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
3855
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
3856
|
+
malformedHost: relativeMalformedHost,
|
|
3857
|
+
malformedScheme: relativeMalformedScheme
|
|
3858
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
3859
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
3641
3860
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3642
3861
|
}
|
|
3643
3862
|
const resolved2 = resolveComponent2(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3863
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved2.scheme);
|
|
3864
|
+
const resolvedHost = resolved2.host;
|
|
3865
|
+
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
3866
|
+
canonicalizeHost(resolved2, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
3867
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !new RegExp("\\P{ASCII}", "u").test(resolvedHost);
|
|
3868
|
+
if (resolved2.error && !encodedASCIIHost) {
|
|
3869
|
+
throw new Error(resolved2.error);
|
|
3870
|
+
}
|
|
3644
3871
|
schemelessOptions.skipEscape = true;
|
|
3645
3872
|
return serialize(resolved2, schemelessOptions);
|
|
3646
3873
|
}
|
|
@@ -3700,7 +3927,7 @@ var require_fast_uri = __commonJS({
|
|
|
3700
3927
|
function equal(uriA, uriB, options) {
|
|
3701
3928
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3702
3929
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3703
|
-
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA
|
|
3930
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
3704
3931
|
}
|
|
3705
3932
|
function serialize(cmpts, opts) {
|
|
3706
3933
|
const component = {
|
|
@@ -3721,19 +3948,22 @@ var require_fast_uri = __commonJS({
|
|
|
3721
3948
|
};
|
|
3722
3949
|
const options = Object.assign({}, opts);
|
|
3723
3950
|
const uriTokens = [];
|
|
3951
|
+
if (component.scheme) {
|
|
3952
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3953
|
+
}
|
|
3724
3954
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3725
3955
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
3956
|
+
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
3957
|
+
const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
|
|
3726
3958
|
if (component.path !== void 0) {
|
|
3727
3959
|
if (!options.skipEscape) {
|
|
3728
|
-
component.path =
|
|
3729
|
-
if (component.scheme !== void 0) {
|
|
3730
|
-
component.path = component.path.split("%3A").join(":");
|
|
3731
|
-
}
|
|
3960
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
3732
3961
|
} else {
|
|
3733
3962
|
component.path = normalizePercentEncoding(component.path);
|
|
3734
3963
|
}
|
|
3735
3964
|
}
|
|
3736
3965
|
if (options.reference !== "suffix" && component.scheme) {
|
|
3966
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3737
3967
|
uriTokens.push(component.scheme, ":");
|
|
3738
3968
|
}
|
|
3739
3969
|
const authority = recomposeAuthority(component);
|
|
@@ -3751,16 +3981,19 @@ var require_fast_uri = __commonJS({
|
|
|
3751
3981
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3752
3982
|
s = removeDotSegments(s);
|
|
3753
3983
|
}
|
|
3984
|
+
if (pathNoScheme) {
|
|
3985
|
+
s = serializePathEncoding(s, true);
|
|
3986
|
+
}
|
|
3754
3987
|
if (authority === void 0 && s[0] === "/" && s[1] === "/") {
|
|
3755
3988
|
s = "/%2F" + s.slice(2);
|
|
3756
3989
|
}
|
|
3757
3990
|
uriTokens.push(s);
|
|
3758
3991
|
}
|
|
3759
3992
|
if (component.query !== void 0) {
|
|
3760
|
-
uriTokens.push("?", component.query);
|
|
3993
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
3761
3994
|
}
|
|
3762
3995
|
if (component.fragment !== void 0) {
|
|
3763
|
-
uriTokens.push("#", component.fragment);
|
|
3996
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
3764
3997
|
}
|
|
3765
3998
|
return uriTokens.join("");
|
|
3766
3999
|
}
|
|
@@ -3776,6 +4009,35 @@ var require_fast_uri = __commonJS({
|
|
|
3776
4009
|
}
|
|
3777
4010
|
return void 0;
|
|
3778
4011
|
}
|
|
4012
|
+
function hasMalformedPercentEncoding(component) {
|
|
4013
|
+
if (component === void 0) return false;
|
|
4014
|
+
let percent = component.indexOf("%");
|
|
4015
|
+
while (percent !== -1) {
|
|
4016
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
4017
|
+
return true;
|
|
4018
|
+
}
|
|
4019
|
+
percent = component.indexOf("%", percent + 3);
|
|
4020
|
+
}
|
|
4021
|
+
return false;
|
|
4022
|
+
}
|
|
4023
|
+
function isIPLiteral(host) {
|
|
4024
|
+
return host[0] === "[" && host[host.length - 1] === "]";
|
|
4025
|
+
}
|
|
4026
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
4027
|
+
const host = matches[4];
|
|
4028
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
4029
|
+
}
|
|
4030
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
4031
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
4032
|
+
try {
|
|
4033
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
4034
|
+
} catch (e) {
|
|
4035
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
4036
|
+
return true;
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
return false;
|
|
4040
|
+
}
|
|
3779
4041
|
function parseWithStatus(uri, opts) {
|
|
3780
4042
|
const options = Object.assign({}, opts);
|
|
3781
4043
|
const parsed = {
|
|
@@ -3788,6 +4050,11 @@ var require_fast_uri = __commonJS({
|
|
|
3788
4050
|
fragment: void 0
|
|
3789
4051
|
};
|
|
3790
4052
|
let malformedAuthorityOrPort = false;
|
|
4053
|
+
let malformedPercentEncoding = false;
|
|
4054
|
+
let malformedSchemeSpecific = false;
|
|
4055
|
+
let malformedHost = false;
|
|
4056
|
+
let malformedIPLiteral = false;
|
|
4057
|
+
let malformedScheme = false;
|
|
3791
4058
|
let isIP = false;
|
|
3792
4059
|
if (options.reference === "suffix") {
|
|
3793
4060
|
if (options.scheme) {
|
|
@@ -3824,6 +4091,19 @@ var require_fast_uri = __commonJS({
|
|
|
3824
4091
|
parsed.path = matches[6] || "";
|
|
3825
4092
|
parsed.query = matches[7];
|
|
3826
4093
|
parsed.fragment = matches[8];
|
|
4094
|
+
if (parsed.scheme !== void 0) {
|
|
4095
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
4096
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
4097
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
4098
|
+
} else {
|
|
4099
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
4100
|
+
malformedScheme = true;
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
4104
|
+
if (malformedPercentEncoding) {
|
|
4105
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
4106
|
+
}
|
|
3827
4107
|
if (isNaN(parsed.port)) {
|
|
3828
4108
|
parsed.port = matches[5];
|
|
3829
4109
|
}
|
|
@@ -3835,9 +4115,16 @@ var require_fast_uri = __commonJS({
|
|
|
3835
4115
|
if (parsed.host) {
|
|
3836
4116
|
const ipv4result = isIPv4(parsed.host);
|
|
3837
4117
|
if (ipv4result === false) {
|
|
4118
|
+
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
4119
|
+
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
3838
4120
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
3839
|
-
|
|
3840
|
-
|
|
4121
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4122
|
+
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
4123
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4124
|
+
if (malformedIPLiteral) {
|
|
4125
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
4126
|
+
malformedAuthorityOrPort = true;
|
|
4127
|
+
}
|
|
3841
4128
|
} else {
|
|
3842
4129
|
isIP = true;
|
|
3843
4130
|
}
|
|
@@ -3855,42 +4142,37 @@ var require_fast_uri = __commonJS({
|
|
|
3855
4142
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
3856
4143
|
}
|
|
3857
4144
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
3858
|
-
if (!
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
4145
|
+
if (!malformedIPLiteral) {
|
|
4146
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
4147
|
+
}
|
|
4148
|
+
if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
|
|
4149
|
+
let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4150
|
+
if (!isIP) {
|
|
4151
|
+
host = normalizePercentEncoding(host.toLowerCase());
|
|
3865
4152
|
}
|
|
4153
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
3866
4154
|
}
|
|
3867
4155
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
3868
|
-
if (uri.indexOf("%") !== -1) {
|
|
3869
|
-
if (parsed.scheme !== void 0) {
|
|
3870
|
-
parsed.scheme = unescape(parsed.scheme);
|
|
3871
|
-
}
|
|
3872
|
-
if (parsed.host !== void 0) {
|
|
3873
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
3874
|
-
}
|
|
3875
|
-
}
|
|
3876
4156
|
if (parsed.path) {
|
|
3877
4157
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3878
4158
|
}
|
|
4159
|
+
if (parsed.query) {
|
|
4160
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
4161
|
+
}
|
|
3879
4162
|
if (parsed.fragment) {
|
|
3880
|
-
|
|
3881
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3882
|
-
} catch {
|
|
3883
|
-
parsed.error = parsed.error || "URI malformed";
|
|
3884
|
-
}
|
|
4163
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
3885
4164
|
}
|
|
3886
4165
|
}
|
|
3887
4166
|
if (schemeHandler && schemeHandler.parse) {
|
|
3888
4167
|
schemeHandler.parse(parsed, options);
|
|
4168
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
|
|
4169
|
+
malformedSchemeSpecific = true;
|
|
4170
|
+
}
|
|
3889
4171
|
}
|
|
3890
4172
|
} else {
|
|
3891
4173
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3892
4174
|
}
|
|
3893
|
-
return { parsed, malformedAuthorityOrPort };
|
|
4175
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
3894
4176
|
}
|
|
3895
4177
|
function parse4(uri, opts) {
|
|
3896
4178
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -3899,20 +4181,28 @@ var require_fast_uri = __commonJS({
|
|
|
3899
4181
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3900
4182
|
}
|
|
3901
4183
|
function normalizeStringWithStatus(uri, opts) {
|
|
3902
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
4184
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
3903
4185
|
return {
|
|
3904
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
3905
|
-
malformedAuthorityOrPort
|
|
4186
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
4187
|
+
malformedAuthorityOrPort,
|
|
4188
|
+
malformedPercentEncoding,
|
|
4189
|
+
malformedSchemeSpecific,
|
|
4190
|
+
malformedHost,
|
|
4191
|
+
malformedScheme
|
|
3906
4192
|
};
|
|
3907
4193
|
}
|
|
3908
4194
|
function normalizeComparableURI(uri, opts) {
|
|
3909
|
-
if (typeof uri
|
|
3910
|
-
|
|
3911
|
-
return malformedAuthorityOrPort ? void 0 : normalized;
|
|
4195
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
4196
|
+
return void 0;
|
|
3912
4197
|
}
|
|
3913
|
-
|
|
3914
|
-
|
|
4198
|
+
let value;
|
|
4199
|
+
try {
|
|
4200
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
4201
|
+
} catch {
|
|
4202
|
+
return void 0;
|
|
3915
4203
|
}
|
|
4204
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
4205
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
|
|
3916
4206
|
}
|
|
3917
4207
|
var fastUri = {
|
|
3918
4208
|
SCHEMES,
|
|
@@ -4332,7 +4622,7 @@ var require_core = __commonJS({
|
|
|
4332
4622
|
errorsText(errors = this.errors, { separator = ", ", dataVar = "data" } = {}) {
|
|
4333
4623
|
if (!errors || errors.length === 0)
|
|
4334
4624
|
return "No errors";
|
|
4335
|
-
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((
|
|
4625
|
+
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
|
|
4336
4626
|
}
|
|
4337
4627
|
$dataMetaSchema(metaSchema, keywordsJsonPointers) {
|
|
4338
4628
|
const rules = this.RULES.all;
|
|
@@ -46823,8 +47113,8 @@ function ko_default() {
|
|
|
46823
47113
|
}
|
|
46824
47114
|
|
|
46825
47115
|
// node_modules/zod/v4/locales/lt.js
|
|
46826
|
-
var capitalizeFirstCharacter = (
|
|
46827
|
-
return
|
|
47116
|
+
var capitalizeFirstCharacter = (text2) => {
|
|
47117
|
+
return text2.charAt(0).toUpperCase() + text2.slice(1);
|
|
46828
47118
|
};
|
|
46829
47119
|
function getUnitTypeFromNumber(number4) {
|
|
46830
47120
|
const abs = Math.abs(number4);
|
|
@@ -57051,6 +57341,9 @@ var Protocol = class {
|
|
|
57051
57341
|
this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
|
|
57052
57342
|
const handleTaskResult = async () => {
|
|
57053
57343
|
const taskId = request.params.taskId;
|
|
57344
|
+
if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
|
|
57345
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
57346
|
+
}
|
|
57054
57347
|
if (this._taskMessageQueue) {
|
|
57055
57348
|
let queuedMessage;
|
|
57056
57349
|
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
@@ -57081,12 +57374,12 @@ var Protocol = class {
|
|
|
57081
57374
|
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
57082
57375
|
}
|
|
57083
57376
|
if (!isTerminal(task.status)) {
|
|
57084
|
-
await this._waitForTaskUpdate(taskId, extra.signal);
|
|
57377
|
+
await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
|
|
57085
57378
|
return await handleTaskResult();
|
|
57086
57379
|
}
|
|
57087
57380
|
if (isTerminal(task.status)) {
|
|
57088
57381
|
const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
|
|
57089
|
-
this._clearTaskQueue(taskId);
|
|
57382
|
+
this._clearTaskQueue(taskId, extra.sessionId);
|
|
57090
57383
|
return {
|
|
57091
57384
|
...result,
|
|
57092
57385
|
_meta: {
|
|
@@ -57123,7 +57416,7 @@ var Protocol = class {
|
|
|
57123
57416
|
throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
|
|
57124
57417
|
}
|
|
57125
57418
|
await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
|
|
57126
|
-
this._clearTaskQueue(request.params.taskId);
|
|
57419
|
+
this._clearTaskQueue(request.params.taskId, extra.sessionId);
|
|
57127
57420
|
const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
57128
57421
|
if (!cancelledTask) {
|
|
57129
57422
|
throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
|
|
@@ -57251,6 +57544,19 @@ var Protocol = class {
|
|
|
57251
57544
|
const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
|
|
57252
57545
|
const capturedTransport = this._transport;
|
|
57253
57546
|
const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
|
|
57547
|
+
const sessionId = capturedTransport?.sessionId;
|
|
57548
|
+
const store = this._taskStore;
|
|
57549
|
+
let relatedTaskFound = true;
|
|
57550
|
+
let relatedTaskLookup;
|
|
57551
|
+
if (relatedTaskId && store && this._taskMessageQueue && sessionId !== void 0) {
|
|
57552
|
+
relatedTaskFound = false;
|
|
57553
|
+
relatedTaskLookup = (async () => {
|
|
57554
|
+
if (!await store.getTask(relatedTaskId, sessionId)) {
|
|
57555
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
|
|
57556
|
+
}
|
|
57557
|
+
relatedTaskFound = true;
|
|
57558
|
+
})();
|
|
57559
|
+
}
|
|
57254
57560
|
if (handler === void 0) {
|
|
57255
57561
|
const errorResponse = {
|
|
57256
57562
|
jsonrpc: "2.0",
|
|
@@ -57260,7 +57566,10 @@ var Protocol = class {
|
|
|
57260
57566
|
message: "Method not found"
|
|
57261
57567
|
}
|
|
57262
57568
|
};
|
|
57263
|
-
if (relatedTaskId &&
|
|
57569
|
+
if (relatedTaskId && relatedTaskLookup) {
|
|
57570
|
+
const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
|
|
57571
|
+
relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error51) => this._onerror(new Error(`Failed to send an error response: ${error51}`)));
|
|
57572
|
+
} else if (relatedTaskId && this._taskMessageQueue) {
|
|
57264
57573
|
this._enqueueTaskMessage(relatedTaskId, {
|
|
57265
57574
|
type: "error",
|
|
57266
57575
|
message: errorResponse,
|
|
@@ -57311,7 +57620,10 @@ var Protocol = class {
|
|
|
57311
57620
|
closeSSEStream: extra?.closeSSEStream,
|
|
57312
57621
|
closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
|
|
57313
57622
|
};
|
|
57314
|
-
Promise.resolve().then(() => {
|
|
57623
|
+
(relatedTaskLookup ?? Promise.resolve()).then(() => {
|
|
57624
|
+
if (relatedTaskLookup && abortController.signal.aborted) {
|
|
57625
|
+
throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
|
|
57626
|
+
}
|
|
57315
57627
|
if (taskCreationParams) {
|
|
57316
57628
|
this.assertTaskHandlerCapability(request.method);
|
|
57317
57629
|
}
|
|
@@ -57346,7 +57658,7 @@ var Protocol = class {
|
|
|
57346
57658
|
...error51["data"] !== void 0 && { data: error51["data"] }
|
|
57347
57659
|
}
|
|
57348
57660
|
};
|
|
57349
|
-
if (relatedTaskId && this._taskMessageQueue) {
|
|
57661
|
+
if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
|
|
57350
57662
|
await this._enqueueTaskMessage(relatedTaskId, {
|
|
57351
57663
|
type: "error",
|
|
57352
57664
|
message: errorResponse,
|
|
@@ -57826,7 +58138,7 @@ var Protocol = class {
|
|
|
57826
58138
|
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
57827
58139
|
}
|
|
57828
58140
|
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
57829
|
-
await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
|
|
58141
|
+
await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
|
|
57830
58142
|
}
|
|
57831
58143
|
/**
|
|
57832
58144
|
* Clears the message queue for a task and rejects any pending request resolvers.
|
|
@@ -57855,12 +58167,13 @@ var Protocol = class {
|
|
|
57855
58167
|
* Uses polling to check for updates at the task's configured poll interval.
|
|
57856
58168
|
* @param taskId The task ID to wait for
|
|
57857
58169
|
* @param signal Abort signal to cancel the wait
|
|
58170
|
+
* @param sessionId Session of the request that waits, passed to the task store
|
|
57858
58171
|
* @returns Promise that resolves when an update occurs or rejects if aborted
|
|
57859
58172
|
*/
|
|
57860
|
-
async _waitForTaskUpdate(taskId, signal) {
|
|
58173
|
+
async _waitForTaskUpdate(taskId, signal, sessionId) {
|
|
57861
58174
|
let interval = this._options?.defaultTaskPollInterval ?? 1e3;
|
|
57862
58175
|
try {
|
|
57863
|
-
const task = await this._taskStore?.getTask(taskId);
|
|
58176
|
+
const task = await this._taskStore?.getTask(taskId, sessionId);
|
|
57864
58177
|
if (task?.pollInterval) {
|
|
57865
58178
|
interval = task.pollInterval;
|
|
57866
58179
|
}
|
|
@@ -58739,6 +59052,42 @@ var ExperimentalMcpServerTasks = class {
|
|
|
58739
59052
|
};
|
|
58740
59053
|
|
|
58741
59054
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
59055
|
+
function toolInputElementCount(value, max) {
|
|
59056
|
+
let count = 0;
|
|
59057
|
+
const stack = [value];
|
|
59058
|
+
while (stack.length > 0) {
|
|
59059
|
+
const node = stack.pop();
|
|
59060
|
+
if (node === null || typeof node !== "object")
|
|
59061
|
+
continue;
|
|
59062
|
+
if (Array.isArray(node)) {
|
|
59063
|
+
for (const child of node) {
|
|
59064
|
+
if (++count > max)
|
|
59065
|
+
return count;
|
|
59066
|
+
if (child !== null && typeof child === "object")
|
|
59067
|
+
stack.push(child);
|
|
59068
|
+
}
|
|
59069
|
+
} else {
|
|
59070
|
+
for (const key in node) {
|
|
59071
|
+
if (!Object.prototype.hasOwnProperty.call(node, key))
|
|
59072
|
+
continue;
|
|
59073
|
+
if (++count > max)
|
|
59074
|
+
return count;
|
|
59075
|
+
const child = node[key];
|
|
59076
|
+
if (child !== null && typeof child === "object")
|
|
59077
|
+
stack.push(child);
|
|
59078
|
+
}
|
|
59079
|
+
}
|
|
59080
|
+
}
|
|
59081
|
+
return count;
|
|
59082
|
+
}
|
|
59083
|
+
function resolveMaxToolInputElements(value) {
|
|
59084
|
+
if (value === void 0 || value === Infinity)
|
|
59085
|
+
return void 0;
|
|
59086
|
+
if (typeof value !== "number" || Number.isNaN(value) || value < 1) {
|
|
59087
|
+
throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
|
|
59088
|
+
}
|
|
59089
|
+
return value;
|
|
59090
|
+
}
|
|
58742
59091
|
var McpServer = class {
|
|
58743
59092
|
constructor(serverInfo, options) {
|
|
58744
59093
|
this._registeredResources = {};
|
|
@@ -58750,6 +59099,7 @@ var McpServer = class {
|
|
|
58750
59099
|
this._resourceHandlersInitialized = false;
|
|
58751
59100
|
this._promptHandlersInitialized = false;
|
|
58752
59101
|
this.server = new Server(serverInfo, options);
|
|
59102
|
+
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
58753
59103
|
}
|
|
58754
59104
|
/**
|
|
58755
59105
|
* Access experimental features.
|
|
@@ -58880,12 +59230,15 @@ var McpServer = class {
|
|
|
58880
59230
|
* Validates tool input arguments against the tool's input schema.
|
|
58881
59231
|
*/
|
|
58882
59232
|
async validateToolInput(tool, args, toolName) {
|
|
59233
|
+
if (this._maxToolInputElements !== void 0 && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) {
|
|
59234
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
|
|
59235
|
+
}
|
|
58883
59236
|
if (!tool.inputSchema) {
|
|
58884
59237
|
return void 0;
|
|
58885
59238
|
}
|
|
58886
59239
|
const inputObj = normalizeObjectSchema(tool.inputSchema);
|
|
58887
59240
|
const schemaToParse = inputObj ?? tool.inputSchema;
|
|
58888
|
-
const parseResult = await safeParseAsync2(schemaToParse, args);
|
|
59241
|
+
const parseResult = await safeParseAsync2(schemaToParse, args ?? {});
|
|
58889
59242
|
if (!parseResult.success) {
|
|
58890
59243
|
const error51 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
58891
59244
|
const errorMessage = getParseErrorMessage(error51);
|
|
@@ -59123,7 +59476,7 @@ var McpServer = class {
|
|
|
59123
59476
|
}
|
|
59124
59477
|
if (prompt.argsSchema) {
|
|
59125
59478
|
const argsObj = normalizeObjectSchema(prompt.argsSchema);
|
|
59126
|
-
const parseResult = await safeParseAsync2(argsObj, request.params.arguments);
|
|
59479
|
+
const parseResult = await safeParseAsync2(argsObj, request.params.arguments ?? {});
|
|
59127
59480
|
if (!parseResult.success) {
|
|
59128
59481
|
const error51 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
59129
59482
|
const errorMessage = getParseErrorMessage(error51);
|
|
@@ -59637,6 +59990,79 @@ var StdioServerTransport = class {
|
|
|
59637
59990
|
}
|
|
59638
59991
|
};
|
|
59639
59992
|
|
|
59993
|
+
// src/mcp/workspaces.ts
|
|
59994
|
+
var fail = (text2) => ({ text: text2, isError: true });
|
|
59995
|
+
var LEGACY_KEY_NOTE = "This connection uses an older key bound to a single workspace. Call `connect` once (the user approves in the browser) to replace it with one key that reaches every workspace they belong to.";
|
|
59996
|
+
var TARGETED_TOOLS = /* @__PURE__ */ new Set(["create_video", "brand_extract", "brand_get", "motion_profile"]);
|
|
59997
|
+
var WORKSPACE_ACTING_TOOLS = /* @__PURE__ */ new Set([
|
|
59998
|
+
"create_video",
|
|
59999
|
+
"write_draft_files",
|
|
60000
|
+
"edit_draft_file",
|
|
60001
|
+
"export_video",
|
|
60002
|
+
"brand_extract",
|
|
60003
|
+
"install_kits",
|
|
60004
|
+
"install_font",
|
|
60005
|
+
"install_components",
|
|
60006
|
+
"motion_profile"
|
|
60007
|
+
]);
|
|
60008
|
+
var CREATING_TOOLS = /* @__PURE__ */ new Set(["create_video", "brand_extract"]);
|
|
60009
|
+
var text = (value) => typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
60010
|
+
function admissionTarget(toolName, args, envWorkspace) {
|
|
60011
|
+
const projectId = text(args.projectId);
|
|
60012
|
+
const draftId = text(args.draftId);
|
|
60013
|
+
const jobIds = Array.isArray(args.jobIds) ? args.jobIds.filter((id) => typeof id === "string").slice(0, 50) : void 0;
|
|
60014
|
+
const addressed = Boolean(projectId || draftId || jobIds?.length);
|
|
60015
|
+
const workspace = text(args.workspace) ?? (addressed ? void 0 : envWorkspace);
|
|
60016
|
+
const targeted = TARGETED_TOOLS.has(toolName) || Boolean(text(args.brandSlug));
|
|
60017
|
+
return {
|
|
60018
|
+
...workspace ? { workspace } : {},
|
|
60019
|
+
...projectId ? { projectId } : {},
|
|
60020
|
+
...draftId ? { draftId } : {},
|
|
60021
|
+
...jobIds?.length ? { jobIds } : {},
|
|
60022
|
+
...!workspace && !addressed && !targeted ? { all: true } : {}
|
|
60023
|
+
};
|
|
60024
|
+
}
|
|
60025
|
+
function workspaceNote(toolName, workspace) {
|
|
60026
|
+
const label = workspaceLabel(workspace);
|
|
60027
|
+
const why = workspace.because ? ` (${workspace.because})` : "";
|
|
60028
|
+
return CREATING_TOOLS.has(toolName) ? `Created in ${label}${why}.` : `Workspace: ${label}${why}`;
|
|
60029
|
+
}
|
|
60030
|
+
function describeRow(workspace, lastOpen) {
|
|
60031
|
+
const usage = workspace.usage;
|
|
60032
|
+
return `- ${workspaceLabel(workspace)}${workspace.id === lastOpen ? " [open in the web app]" : ""} \u2014 role: ${workspace.role || "unknown"}` + (workspace.plan ? `, plan: ${workspace.plan}` : "") + (usage?.summary ? `, ${usage.summary}` : "");
|
|
60033
|
+
}
|
|
60034
|
+
var listWorkspacesTool = {
|
|
60035
|
+
name: "list_workspaces",
|
|
60036
|
+
title: "List the workspaces this connection can use",
|
|
60037
|
+
description: "List every Impractical workspace the connected user belongs to (id, name, slug, role, plan) and which one is open in the web app. Pass a workspace id, slug or name as `workspace` to create_video / brand_extract to choose where new work goes. Does not use quota.",
|
|
60038
|
+
inputSchema: {},
|
|
60039
|
+
local: true,
|
|
60040
|
+
handler: async (_args, ctx) => {
|
|
60041
|
+
const listing = await fetchWorkspaces(ctx.invoke);
|
|
60042
|
+
if (!listing.supported) {
|
|
60043
|
+
return {
|
|
60044
|
+
text: "This Impractical server does not support workspace listing yet; this connection keeps using its one workspace. account_status shows which."
|
|
60045
|
+
};
|
|
60046
|
+
}
|
|
60047
|
+
if (listing.keyScope !== "user") {
|
|
60048
|
+
const only = listing.workspaces[0];
|
|
60049
|
+
return {
|
|
60050
|
+
text: (only ? `Connected workspace: ${describeRow(only, null).slice(2)}
|
|
60051
|
+
|
|
60052
|
+
` : "") + LEGACY_KEY_NOTE
|
|
60053
|
+
};
|
|
60054
|
+
}
|
|
60055
|
+
if (!listing.workspaces.length) {
|
|
60056
|
+
return fail("The connected user is not an active member of any workspace.");
|
|
60057
|
+
}
|
|
60058
|
+
const open = listing.workspaces.find((workspace) => workspace.id === listing.lastOpenWorkspaceId);
|
|
60059
|
+
return {
|
|
60060
|
+
text: "Workspaces:\n" + listing.workspaces.map((workspace) => describeRow(workspace, listing.lastOpenWorkspaceId)).join("\n") + "\n\nLists span all of these. Tools given a project/draft id act in its workspace. New work goes to `workspace` if passed, else " + (open ? `${workspaceLabel(open)}, the one open in the web app.` : listing.workspaces.length === 1 ? "the only workspace." : "the workspace open in the web app \u2014 none is recorded, so pass `workspace` explicitly.")
|
|
60061
|
+
};
|
|
60062
|
+
}
|
|
60063
|
+
};
|
|
60064
|
+
var WORKSPACE_TOOLS = [listWorkspacesTool];
|
|
60065
|
+
|
|
59640
60066
|
// src/mcp/contract-mode.ts
|
|
59641
60067
|
var CONTRACT_ENV = "IMPRACTICAL_CONTRACT";
|
|
59642
60068
|
function b20Semantics(env = process.env) {
|
|
@@ -60511,8 +60937,8 @@ var collectFocusProbe = (input) => {
|
|
|
60511
60937
|
if (!parent) break;
|
|
60512
60938
|
for (const sibling of Array.from(parent.children)) {
|
|
60513
60939
|
if (sibling === level) continue;
|
|
60514
|
-
const
|
|
60515
|
-
if (
|
|
60940
|
+
const text2 = textOf(sibling);
|
|
60941
|
+
if (text2 && siblingTexts.length < 16) siblingTexts.push(text2);
|
|
60516
60942
|
}
|
|
60517
60943
|
level = parent;
|
|
60518
60944
|
}
|
|
@@ -60539,11 +60965,11 @@ var NARRATIVE_ENTITY_STOPLIST = new Set(
|
|
|
60539
60965
|
"the a an and or but nor to for with without your our their his her its my you we they it this that these those here there now new all one every each more most best better first last next meet introducing get set go from in on at by of no not just say hello welcome today tomorrow how what when where why who which try free start build ship launch power fast easy simple ai app team plan pro data live real time work works make made let us see watch look".split(/\s+/)
|
|
60540
60966
|
);
|
|
60541
60967
|
var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
60542
|
-
var containsEntity = (
|
|
60968
|
+
var containsEntity = (text2, entity) => new RegExp(`(?:^|[^A-Za-z0-9])${escapeRegExp(entity)}(?:[^A-Za-z0-9]|$)`, "i").test(text2);
|
|
60543
60969
|
function extractEntityTokens(copy) {
|
|
60544
60970
|
const out = [];
|
|
60545
|
-
for (const
|
|
60546
|
-
for (const match of
|
|
60971
|
+
for (const text2 of copy) {
|
|
60972
|
+
for (const match of text2.matchAll(/\b[A-Z][a-zA-Z0-9'&-]*(?:\s+[A-Z][a-zA-Z0-9'&-]*){0,2}\b/g)) {
|
|
60547
60973
|
const words = match[0].trim().split(/\s+/);
|
|
60548
60974
|
while (words.length && NARRATIVE_ENTITY_STOPLIST.has(words[0].toLowerCase())) words.shift();
|
|
60549
60975
|
while (words.length && NARRATIVE_ENTITY_STOPLIST.has(words[words.length - 1].toLowerCase()))
|
|
@@ -60565,7 +60991,7 @@ function narrativeCameraFindings(probes) {
|
|
|
60565
60991
|
const key = entity.toLowerCase();
|
|
60566
60992
|
if (flagged.has(key)) continue;
|
|
60567
60993
|
if (containsEntity(probe.focusedText, entity)) continue;
|
|
60568
|
-
const sibling = probe.siblingTexts.find((
|
|
60994
|
+
const sibling = probe.siblingTexts.find((text2) => containsEntity(text2, entity));
|
|
60569
60995
|
if (!sibling) continue;
|
|
60570
60996
|
flagged.add(key);
|
|
60571
60997
|
out.push(
|
|
@@ -60803,8 +61229,8 @@ var collectPoseGeometry = (input) => {
|
|
|
60803
61229
|
for (const node of Array.from(el2.childNodes)) {
|
|
60804
61230
|
if (node.nodeType === Node.TEXT_NODE) direct += node.textContent ?? "";
|
|
60805
61231
|
}
|
|
60806
|
-
const
|
|
60807
|
-
if (
|
|
61232
|
+
const text2 = direct.trim();
|
|
61233
|
+
if (text2.length < 3) continue;
|
|
60808
61234
|
const r = el2.getBoundingClientRect();
|
|
60809
61235
|
if (r.width < 2 || r.height < 8) continue;
|
|
60810
61236
|
const frac = clippedVisibleFraction(r, el2);
|
|
@@ -60814,7 +61240,7 @@ var collectPoseGeometry = (input) => {
|
|
|
60814
61240
|
edgeTexts.push({
|
|
60815
61241
|
textId: tagOf(el2, "data-motion-textid"),
|
|
60816
61242
|
selector: describe3(el2),
|
|
60817
|
-
text:
|
|
61243
|
+
text: text2.slice(0, 60),
|
|
60818
61244
|
opacity,
|
|
60819
61245
|
visibleFraction: frac,
|
|
60820
61246
|
screenHeight: r.height
|
|
@@ -61204,8 +61630,8 @@ var PLATE_EXPOSED_MIN = 0.25;
|
|
|
61204
61630
|
var PLATE_PERSISTENCE_MIN = 0.75;
|
|
61205
61631
|
function parseShotBeats(raw) {
|
|
61206
61632
|
if (!raw) return [];
|
|
61207
|
-
const
|
|
61208
|
-
const parsed = JSON.parse(
|
|
61633
|
+
const text2 = raw.replace(/^\[shotlist\.json[^\n]*\]\s*\n/, "");
|
|
61634
|
+
const parsed = JSON.parse(text2);
|
|
61209
61635
|
return (parsed.beats ?? []).map((b, i) => ({
|
|
61210
61636
|
index: i + 1,
|
|
61211
61637
|
start: Number(b.start ?? 0),
|
|
@@ -62333,8 +62759,8 @@ function collectCallerValues(ast) {
|
|
|
62333
62759
|
const inner = t3.isJSXExpressionContainer(v) ? v.expression : v;
|
|
62334
62760
|
if (t3.isJSXEmptyExpression(inner) || t3.isBooleanLiteral(inner) || t3.isNullLiteral(inner)) continue;
|
|
62335
62761
|
if (t3.isIdentifier(inner) && inner.name === "undefined") continue;
|
|
62336
|
-
const
|
|
62337
|
-
props.set(attr.name.name, [...props.get(attr.name.name) ?? [],
|
|
62762
|
+
const text2 = t3.isStringLiteral(inner) ? inner.value : t3.isTemplateLiteral(inner) ? inner.quasis.map((q) => q.value.cooked ?? "").join("\u2026") : "";
|
|
62763
|
+
props.set(attr.name.name, [...props.get(attr.name.name) ?? [], text2]);
|
|
62338
62764
|
}
|
|
62339
62765
|
byComponent.set(el2.name.name, props);
|
|
62340
62766
|
});
|
|
@@ -63008,8 +63434,8 @@ function serializeMarkSet(set2) {
|
|
|
63008
63434
|
if (w.overflow) notes.push(`content overflows its box (${w.overflow})`);
|
|
63009
63435
|
if (!w.visible) notes.push("not visible");
|
|
63010
63436
|
if (w.src) notes.push(`src ${w.src}`);
|
|
63011
|
-
const
|
|
63012
|
-
lines.push(`${w.mark} | ${w.type} | ${
|
|
63437
|
+
const text2 = w.text ? JSON.stringify(w.text) : "\u2014";
|
|
63438
|
+
lines.push(`${w.mark} | ${w.type} | ${text2} | ${Math.round(w.rect.x)},${Math.round(w.rect.y)},${Math.round(w.rect.w)},${Math.round(w.rect.h)} | ${w.click ? "yes" : "no"} | ${notes.join("; ") || "\u2014"}`);
|
|
63013
63439
|
}
|
|
63014
63440
|
return lines.join("\n");
|
|
63015
63441
|
}
|
|
@@ -64290,7 +64716,7 @@ async function runReviewModules(input) {
|
|
|
64290
64716
|
// frame-sized, so geometry cannot tell the target from its wrapper or its children.
|
|
64291
64717
|
// The author wrote the intent down — world.camera.zoomTo(detailCard, …).
|
|
64292
64718
|
subjectAt: async (t4) => describeShot(shotAt(shots, t4)),
|
|
64293
|
-
log: (name2,
|
|
64719
|
+
log: (name2, text2) => writeFileSync5(path4.join(frameDir, name2), text2),
|
|
64294
64720
|
// One red box around the element the action names — Set-of-Mark scoped to a single
|
|
64295
64721
|
// element, so the eye is pointed without the 26-mark noise that hurt the earlier test.
|
|
64296
64722
|
annotate: async (jpg, action) => {
|
|
@@ -64384,7 +64810,7 @@ async function runReviewModules(input) {
|
|
|
64384
64810
|
duration: duration3,
|
|
64385
64811
|
ask: (prompt, images2) => runner(family2)(prompt, images2, { timeoutMs: 3e5 }),
|
|
64386
64812
|
variant: reviewWalkVariant(),
|
|
64387
|
-
log: (name2,
|
|
64813
|
+
log: (name2, text2) => writeFileSync5(path4.join(frameDir, name2), text2)
|
|
64388
64814
|
});
|
|
64389
64815
|
for (const f of res.findings) failures.push(`ACTION ${f.index} ${f.start.toFixed(2)}\u2013${f.end.toFixed(2)}s: ${f.label} \u2014 ${f.claim.slice(0, 90)} \u2014 ${f.evidence.slice(0, 160)}`);
|
|
64390
64816
|
}
|
|
@@ -64493,10 +64919,10 @@ async function runReviewModules(input) {
|
|
|
64493
64919
|
);
|
|
64494
64920
|
}
|
|
64495
64921
|
if (ledger) {
|
|
64496
|
-
const
|
|
64497
|
-
if (
|
|
64922
|
+
const text2 = describeLedger(ledger);
|
|
64923
|
+
if (text2.trim()) {
|
|
64498
64924
|
lines.push(" ISSUE LEDGER \u2014 the same defect seen at several actions is ONE issue; support counts how many saw it:");
|
|
64499
|
-
for (const l of
|
|
64925
|
+
for (const l of text2.split("\n")) lines.push(" " + l);
|
|
64500
64926
|
}
|
|
64501
64927
|
}
|
|
64502
64928
|
if (!failures.length) lines.push(" all beats clean \u2014 every module ran and every action was checked; export is not held by the review modules");
|
|
@@ -65014,8 +65440,8 @@ function pushAdvisoryEnabled(env = process.env) {
|
|
|
65014
65440
|
}
|
|
65015
65441
|
var lineOf = (content, index) => content.slice(0, index).split("\n").length;
|
|
65016
65442
|
var scannable = (path7) => !path7.startsWith("kit/") && !path7.endsWith(".json") && !path7.endsWith(".md") && /\.(tsx?|jsx?|css|html)$/.test(path7);
|
|
65017
|
-
var clip = (
|
|
65018
|
-
const flat =
|
|
65443
|
+
var clip = (text2, max = 90) => {
|
|
65444
|
+
const flat = text2.replace(/\s+/g, " ").trim();
|
|
65019
65445
|
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
65020
65446
|
};
|
|
65021
65447
|
var CLASSNAME_RE = /className\s*=\s*(?:"([^"]*)"|'([^']*)'|\{`([^`]*)`\})/g;
|
|
@@ -65910,7 +66336,7 @@ async function sampleTextBlocks(page, minFontPx) {
|
|
|
65910
66336
|
const viewportHeight = window.innerHeight;
|
|
65911
66337
|
const margin = 0.02 * Math.min(viewportWidth, viewportHeight);
|
|
65912
66338
|
const shown = (style) => style.visibility !== "hidden" && style.display !== "none" && !(parseFloat(style.opacity) < 0.05);
|
|
65913
|
-
const describe3 = (el2,
|
|
66339
|
+
const describe3 = (el2, text2) => {
|
|
65914
66340
|
const style = getComputedStyle(el2);
|
|
65915
66341
|
const fontSize = parseFloat(style.fontSize);
|
|
65916
66342
|
if (!Number.isFinite(fontSize)) return null;
|
|
@@ -65929,7 +66355,7 @@ async function sampleTextBlocks(page, minFontPx) {
|
|
|
65929
66355
|
}
|
|
65930
66356
|
}
|
|
65931
66357
|
return {
|
|
65932
|
-
text:
|
|
66358
|
+
text: text2.slice(0, 40),
|
|
65933
66359
|
fontSize,
|
|
65934
66360
|
x: rect.x,
|
|
65935
66361
|
y: rect.y,
|
|
@@ -65961,8 +66387,8 @@ async function sampleTextBlocks(page, minFontPx) {
|
|
|
65961
66387
|
}
|
|
65962
66388
|
for (const [root, slot] of slotOf) {
|
|
65963
66389
|
if (!liveRoots.has(root)) continue;
|
|
65964
|
-
const
|
|
65965
|
-
out[slot] = describe3(root,
|
|
66390
|
+
const text2 = (root.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
66391
|
+
out[slot] = describe3(root, text2);
|
|
65966
66392
|
}
|
|
65967
66393
|
return out.filter((block) => block !== null);
|
|
65968
66394
|
},
|
|
@@ -65982,7 +66408,7 @@ var WITNESS_SCALE_FRACTION = 0.04;
|
|
|
65982
66408
|
var MIN_WITNESS_SECONDS = 0.9;
|
|
65983
66409
|
var STATEMENT_HOLD_SECONDS = 1.2;
|
|
65984
66410
|
var RIDING_DIFF_THRESHOLD = 0.05;
|
|
65985
|
-
var normalize = (
|
|
66411
|
+
var normalize = (text2) => text2.trim().replace(/\s+/g, " ");
|
|
65986
66412
|
var settledBetween = (a, b, frameDiagonal) => Math.hypot(a.x + a.width / 2 - (b.x + b.width / 2), a.y + a.height / 2 - (b.y + b.height / 2)) < frameDiagonal * 0.01;
|
|
65987
66413
|
var ICON_GLYPHS = /^[\s\u2190-\u21FF\u27F0-\u27FF\u2794-\u27BF\u2713\u2714\u2705\u2717\u2718\u2716\u274C\u25B6\u25C0\u25B2\u25BC\u2605\u2606\u2B50]+$|^\s*(->|=>|<-|<=|\[x\]|\[ \])\s*$/;
|
|
65988
66414
|
function analyzeTextContract(input) {
|
|
@@ -66061,12 +66487,12 @@ function analyzeTextContract(input) {
|
|
|
66061
66487
|
);
|
|
66062
66488
|
const firstLocked = lockedLines?.length ? normalize(lockedLines[0]) : null;
|
|
66063
66489
|
for (const [index, block] of openers.entries()) {
|
|
66064
|
-
const
|
|
66065
|
-
const isDeclaredOpening = firstLocked ? firstLocked.startsWith(
|
|
66490
|
+
const text2 = normalize(block.text);
|
|
66491
|
+
const isDeclaredOpening = firstLocked ? firstLocked.startsWith(text2) || text2.startsWith(firstLocked) : index === 0 && openers.length === 1;
|
|
66066
66492
|
if (!isDeclaredOpening && (firstLocked || openers.length > 1)) {
|
|
66067
66493
|
findings.push({
|
|
66068
66494
|
kind: "frame0-leak",
|
|
66069
|
-
detail: `"${
|
|
66495
|
+
detail: `"${text2.slice(0, 30)}" is visible at frame 0 but is not the film's opening \u2014 a later element is leaking its initial state. Hide it statically (App.tsx or gsap.set in setup); a from() tween does not hide anything on a cold seek.`
|
|
66070
66496
|
});
|
|
66071
66497
|
}
|
|
66072
66498
|
}
|
|
@@ -66104,13 +66530,13 @@ function analyzeTextContract(input) {
|
|
|
66104
66530
|
const glyphSeen = /* @__PURE__ */ new Set();
|
|
66105
66531
|
for (const sample of samples) {
|
|
66106
66532
|
for (const block of sample.blocks) {
|
|
66107
|
-
const
|
|
66108
|
-
if (!
|
|
66109
|
-
if (!ICON_GLYPHS.test(
|
|
66110
|
-
glyphSeen.add(
|
|
66533
|
+
const text2 = block.text.trim();
|
|
66534
|
+
if (!text2 || block.fontSize < CANDIDATE_MIN_PX) continue;
|
|
66535
|
+
if (!ICON_GLYPHS.test(text2) || glyphSeen.has(text2)) continue;
|
|
66536
|
+
glyphSeen.add(text2);
|
|
66111
66537
|
findings.push({
|
|
66112
66538
|
kind: "glyph-icon",
|
|
66113
|
-
detail: `"${
|
|
66539
|
+
detail: `"${text2}" is a text glyph doing an icon's job. Use the real icon from lucide-react (import { ArrowRight, Check } from 'lucide-react') \u2014 a glyph inherits the text font, so it sits on the baseline at the wrong weight and optical size, and it cannot take a stroke width or animate as its own element.`
|
|
66114
66540
|
});
|
|
66115
66541
|
}
|
|
66116
66542
|
}
|
|
@@ -70158,11 +70584,11 @@ async function openPreview(ctx, draftId) {
|
|
|
70158
70584
|
const consoleTail = [];
|
|
70159
70585
|
page.on("pageerror", (err) => pageErrors.push((err.stack || err.message || String(err)).slice(0, 900)));
|
|
70160
70586
|
page.on("console", (msg) => {
|
|
70161
|
-
const
|
|
70162
|
-
if (/music\.json|connect-src/.test(
|
|
70163
|
-
consoleTail.push(`console.${msg.type()}: ${
|
|
70587
|
+
const text2 = msg.text();
|
|
70588
|
+
if (/music\.json|connect-src/.test(text2)) return;
|
|
70589
|
+
consoleTail.push(`console.${msg.type()}: ${text2.slice(0, 300)}`);
|
|
70164
70590
|
if (consoleTail.length > 30) consoleTail.shift();
|
|
70165
|
-
if (msg.type() === "error") pageErrors.push("console.error: " +
|
|
70591
|
+
if (msg.type() === "error") pageErrors.push("console.error: " + text2.slice(0, 600));
|
|
70166
70592
|
});
|
|
70167
70593
|
await page.goto(PREVIEW_URL, { waitUntil: "load", timeout: 6e4 });
|
|
70168
70594
|
try {
|
|
@@ -70477,6 +70903,9 @@ var motionContextTool = {
|
|
|
70477
70903
|
title: "Study the motion library",
|
|
70478
70904
|
description: `Retrieve the current versioned house skills, relevant templates, selected production reference sources, the catalog of house kits this draft can install, and rendered style frames for this brief. CALL THIS after engine_types and before create_video. The production library is fetched live; local development may explicitly override its guidance with ${LOCAL_MOTION_LIBRARY_ENV}.`,
|
|
70479
70905
|
inputSchema: {
|
|
70906
|
+
workspace: external_exports.string().min(1).max(200).optional().describe(
|
|
70907
|
+
"Workspace holding brandSlug (id, slug or name). Default: the one open in the web app, or the only one."
|
|
70908
|
+
),
|
|
70480
70909
|
brief: external_exports.string().min(1).describe("What the video should communicate and how it should feel."),
|
|
70481
70910
|
styleId: external_exports.string().optional().describe("Optional style id from a previous motion_context result."),
|
|
70482
70911
|
templateId: external_exports.string().optional().describe("Optional template id to study in detail."),
|
|
@@ -70721,37 +71150,37 @@ function cameraLint(files) {
|
|
|
70721
71150
|
lines.forEach((raw, i) => {
|
|
70722
71151
|
if (ALLOW.test(raw)) return;
|
|
70723
71152
|
const line = i + 1;
|
|
70724
|
-
const
|
|
71153
|
+
const text2 = raw.trim().slice(0, 140);
|
|
70725
71154
|
if (path7.endsWith("App.tsx") || path7.endsWith(".tsx")) {
|
|
70726
71155
|
if (APP_STAGE_TRANSFORM.test(raw))
|
|
70727
|
-
out.push({ path: path7, line, text, severity: "note", why: "the stage element carries its own transform \u2014 that is a hand-rolled camera", fix: "remove it; the World Camera moves the stage" });
|
|
71156
|
+
out.push({ path: path7, line, text: text2, severity: "note", why: "the stage element carries its own transform \u2014 that is a hand-rolled camera", fix: "remove it; the World Camera moves the stage" });
|
|
70728
71157
|
return;
|
|
70729
71158
|
}
|
|
70730
71159
|
let m;
|
|
70731
71160
|
if (RETURN_TIMELINE.test(raw)) {
|
|
70732
|
-
out.push({ path: path7, line, text, severity: "note", why: "the direction returns the timeline \u2014 the stage awaits that value, and a GSAP timeline is a thenable that resolves only when the film COMPLETES; a paused film never does, so the preview never becomes ready", fix: "return nothing from direction (delete this line); the engine already owns ctx.tl" });
|
|
71161
|
+
out.push({ path: path7, line, text: text2, severity: "note", why: "the direction returns the timeline \u2014 the stage awaits that value, and a GSAP timeline is a thenable that resolves only when the film COMPLETES; a paused film never does, so the preview never becomes ready", fix: "return nothing from direction (delete this line); the engine already owns ctx.tl" });
|
|
70733
71162
|
return;
|
|
70734
71163
|
}
|
|
70735
71164
|
if (m = LEGACY.exec(raw)) {
|
|
70736
71165
|
const verb = m[1];
|
|
70737
71166
|
const fix = verb === "set" || verb === "full" ? "world.camera.cutTo(subject) (or world.camera.moveTo for a glide)" : verb === "move" ? "film.at(t).do(world.camera.moveTo(subject)) \u2014 name the subject, the verb centres and frames it" : verb === "crop" || verb === "focus" ? "world.camera.zoomTo(subject) (or focusOn)" : "world.camera.moveTo / zoomTo / cutTo / whipTo";
|
|
70738
|
-
out.push({ path: path7, line, text, severity: "note", why: `legacy camera API (camera.${verb})`, fix });
|
|
71167
|
+
out.push({ path: path7, line, text: text2, severity: "note", why: `legacy camera API (camera.${verb})`, fix });
|
|
70739
71168
|
return;
|
|
70740
71169
|
}
|
|
70741
71170
|
if (!b20Semantics() && HAND_TIMED_BOUNDARY.test(raw)) {
|
|
70742
|
-
out.push({ path: path7, line, text, severity: "note", why: "a scene boundary scheduled by hand (film.at(<number>) with an exit/strike/transition)", fix: "film.cut(previous.exit(...), next.enter(...), world.camera.moveTo(...)) \u2014 the sequencer advances on the previous plan's end horizon; typed times are for in-scene cues only" });
|
|
71171
|
+
out.push({ path: path7, line, text: text2, severity: "note", why: "a scene boundary scheduled by hand (film.at(<number>) with an exit/strike/transition)", fix: "film.cut(previous.exit(...), next.enter(...), world.camera.moveTo(...)) \u2014 the sequencer advances on the previous plan's end horizon; typed times are for in-scene cues only" });
|
|
70743
71172
|
return;
|
|
70744
71173
|
}
|
|
70745
71174
|
if (STAGE_TWEEN.test(raw)) {
|
|
70746
|
-
out.push({ path: path7, line, text, severity: "note", why: "a tween on the stage element is a hand-rolled camera move", fix: "world.camera.moveTo / zoomTo on the subject instead" });
|
|
71175
|
+
out.push({ path: path7, line, text: text2, severity: "note", why: "a tween on the stage element is a hand-rolled camera move", fix: "world.camera.moveTo / zoomTo on the subject instead" });
|
|
70747
71176
|
return;
|
|
70748
71177
|
}
|
|
70749
71178
|
if (m = SCENE_ROOT.exec(raw)) {
|
|
70750
71179
|
const vars = m[1];
|
|
70751
71180
|
if (SCALE_IN.test(vars))
|
|
70752
|
-
out.push({ path: path7, line, text, severity: "note", why: "scaling a scene root is a zoom in disguise", fix: "world.camera.zoomTo(the component the story is about)" });
|
|
71181
|
+
out.push({ path: path7, line, text: text2, severity: "note", why: "scaling a scene root is a zoom in disguise", fix: "world.camera.zoomTo(the component the story is about)" });
|
|
70753
71182
|
else if (TRANSLATE_IN.test(vars))
|
|
70754
|
-
out.push({ path: path7, line, text, severity: "note", why: "translating a scene root by hand", fix: "use the engine's exit families or world.strike / world.transition for a scene change" });
|
|
71183
|
+
out.push({ path: path7, line, text: text2, severity: "note", why: "translating a scene root by hand", fix: "use the engine's exit families or world.strike / world.transition for a scene change" });
|
|
70755
71184
|
}
|
|
70756
71185
|
});
|
|
70757
71186
|
}
|
|
@@ -70773,6 +71202,8 @@ var UNMETERED_MCP_TOOLS = /* @__PURE__ */ new Set([
|
|
|
70773
71202
|
"whoami",
|
|
70774
71203
|
"upgrade",
|
|
70775
71204
|
"studio_link",
|
|
71205
|
+
// Lists the user's workspaces (multi-workspace keys); read-only.
|
|
71206
|
+
"list_workspaces",
|
|
70776
71207
|
// This tool has a packaged local fallback and is explicitly required before
|
|
70777
71208
|
// authentication-dependent work. Admission must not block that fallback.
|
|
70778
71209
|
"engine_types"
|
|
@@ -70789,8 +71220,9 @@ var createSessionState = () => ({
|
|
|
70789
71220
|
shotListByDraft: /* @__PURE__ */ new Map(),
|
|
70790
71221
|
measuredByDraft: /* @__PURE__ */ new Map()
|
|
70791
71222
|
});
|
|
71223
|
+
var WORKSPACE_ARG = external_exports.string().min(1).max(200).optional();
|
|
70792
71224
|
var json2 = (value) => ({ text: JSON.stringify(value, null, 2) });
|
|
70793
|
-
var
|
|
71225
|
+
var fail2 = (text2) => ({ text: text2, isError: true });
|
|
70794
71226
|
var nap = (ctx, ms) => ctx.sleep ? ctx.sleep(ms) : new Promise((resolve) => setTimeout(resolve, ms));
|
|
70795
71227
|
var TERMINAL = /* @__PURE__ */ new Set(["completed", "failed", "canceled"]);
|
|
70796
71228
|
var POLL_ERROR_LIMIT = 5;
|
|
@@ -70888,16 +71320,20 @@ async function measuredBlock(ctx, rows) {
|
|
|
70888
71320
|
return parts.length ? "\n\n" + parts.join("\n") : "";
|
|
70889
71321
|
}
|
|
70890
71322
|
var getDraft = (ctx, draftId) => ctx.invoke("get-draft", { draftId });
|
|
70891
|
-
var studioLink = (ctx, projectId, slug) => {
|
|
71323
|
+
var studioLink = (ctx, projectId, slug, workspace = ctx.callWorkspaceId) => {
|
|
70892
71324
|
const base = (ctx.appUrl ?? "https://motion.impractical.ai").replace(/\/$/, "");
|
|
70893
|
-
return `${base}/projects/${projectId}/studio${slug
|
|
71325
|
+
return `${base}/projects/${projectId}/studio${studioQuery(slug, workspace)}`;
|
|
71326
|
+
};
|
|
71327
|
+
var resolvedStudioLink = async (ctx, projectId, slug) => {
|
|
71328
|
+
const workspace = ctx.callWorkspaceId ?? await ctx.projectWorkspace?.(projectId).catch(() => null) ?? null;
|
|
71329
|
+
return studioLink(ctx, projectId, slug, workspace);
|
|
70894
71330
|
};
|
|
70895
71331
|
async function saveDraft(ctx, draftId, apply) {
|
|
70896
71332
|
let conflicts = 0;
|
|
70897
71333
|
while (true) {
|
|
70898
71334
|
const draft = await getDraft(ctx, draftId);
|
|
70899
71335
|
if (draft.lockedByJobId) {
|
|
70900
|
-
return
|
|
71336
|
+
return fail2(
|
|
70901
71337
|
`Draft ${draftId} is locked by job ${draft.lockedByJobId}. Wait for it with job_status({ jobIds: ["${draft.lockedByJobId}"], wait: true }), then retry.`
|
|
70902
71338
|
);
|
|
70903
71339
|
}
|
|
@@ -70916,7 +71352,7 @@ async function saveDraft(ctx, draftId, apply) {
|
|
|
70916
71352
|
const atelierFindings = atelierEnabled() ? await atelierSourceFindings(String(merged["direction.ts"] ?? ""), String(merged["App.tsx"] ?? ""), ctx) : [];
|
|
70917
71353
|
const preflightError = await preflightDraft(merged);
|
|
70918
71354
|
if (preflightError) {
|
|
70919
|
-
return
|
|
71355
|
+
return fail2(
|
|
70920
71356
|
"Local build preflight failed \u2014 nothing was sent to the cloud, fix and save again:\n" + preflightError
|
|
70921
71357
|
);
|
|
70922
71358
|
}
|
|
@@ -70967,7 +71403,7 @@ async function saveDraft(ctx, draftId, apply) {
|
|
|
70967
71403
|
continue;
|
|
70968
71404
|
}
|
|
70969
71405
|
if (status === 409) {
|
|
70970
|
-
return
|
|
71406
|
+
return fail2(
|
|
70971
71407
|
`Save rejected (409): ${message}. The draft changed underneath this edit \u2014 re-read the file and re-apply your change on top of the new content.`
|
|
70972
71408
|
);
|
|
70973
71409
|
}
|
|
@@ -71037,9 +71473,24 @@ function reviewModulesFailure(capture, session, draftId) {
|
|
|
71037
71473
|
var accountStatus = {
|
|
71038
71474
|
name: "account_status",
|
|
71039
71475
|
title: "Show account, plan, and MCP usage",
|
|
71040
|
-
description: "Show the connected workspace
|
|
71476
|
+
description: "Show the connected workspace(s) with role, plan, weekly MCP usage, reset time, seats, and billing state. Run this once at the start of a session to confirm the connection works.",
|
|
71041
71477
|
inputSchema: {},
|
|
71042
|
-
handler: async (_args, ctx) =>
|
|
71478
|
+
handler: async (_args, ctx) => {
|
|
71479
|
+
const listing = await fetchWorkspaces(ctx.invoke);
|
|
71480
|
+
if (listing.supported && listing.keyScope === "user") {
|
|
71481
|
+
const open = listing.workspaces.find((w) => w.id === listing.lastOpenWorkspaceId);
|
|
71482
|
+
return json2({
|
|
71483
|
+
keyScope: "user",
|
|
71484
|
+
workspaces: listing.workspaces,
|
|
71485
|
+
openInWebApp: open ? workspaceLabel(open) : null,
|
|
71486
|
+
howWorkspacesWork: "This connection reaches every workspace listed. Lists span all of them; tools given a project/draft id act in its workspace; new work goes to `workspace` if passed, else the workspace open in the web app, else the only one."
|
|
71487
|
+
});
|
|
71488
|
+
}
|
|
71489
|
+
const snapshot = await ctx.invoke("workspace-bootstrap");
|
|
71490
|
+
return json2(
|
|
71491
|
+
listing.supported ? { ...snapshot, workspaceAccess: LEGACY_KEY_NOTE } : snapshot
|
|
71492
|
+
);
|
|
71493
|
+
}
|
|
71043
71494
|
};
|
|
71044
71495
|
var whoami = {
|
|
71045
71496
|
...accountStatus,
|
|
@@ -71088,8 +71539,11 @@ var upgradeTool = {
|
|
|
71088
71539
|
var listProjects = {
|
|
71089
71540
|
name: "list_projects",
|
|
71090
71541
|
title: "List video projects",
|
|
71091
|
-
description: "List video projects
|
|
71542
|
+
description: "List video projects, newest first \u2014 across every workspace the user belongs to (each project tagged with its workspace), or one workspace with `workspace`. Large lists: pass limit/offset to page instead of relying on a truncated dump, and nameFilter to search. The tool pages through the server list internally, so totals describe the whole listing (up to 2,000 projects in total).",
|
|
71092
71543
|
inputSchema: {
|
|
71544
|
+
workspace: WORKSPACE_ARG.describe(
|
|
71545
|
+
"Only this workspace (id, slug or name). Default: every workspace you belong to."
|
|
71546
|
+
),
|
|
71093
71547
|
limit: external_exports.number().int().min(1).max(200).optional().describe("Return at most this many projects (default: all)."),
|
|
71094
71548
|
offset: external_exports.number().int().min(0).optional().describe("Skip this many projects, for paging."),
|
|
71095
71549
|
nameFilter: external_exports.string().optional().describe("Case-insensitive substring match on the project name/slug.")
|
|
@@ -71100,7 +71554,9 @@ var listProjects = {
|
|
|
71100
71554
|
for (let pageCount = 0; serverOffset !== null && pageCount < 20; pageCount++) {
|
|
71101
71555
|
const result = await ctx.invoke("list-projects", {
|
|
71102
71556
|
offset: serverOffset,
|
|
71103
|
-
limit: 100
|
|
71557
|
+
limit: 100,
|
|
71558
|
+
// Spans every workspace for a multi-workspace key; ignored otherwise.
|
|
71559
|
+
...args.workspace ? {} : { allWorkspaces: true }
|
|
71104
71560
|
});
|
|
71105
71561
|
const rows = result.projects ?? [];
|
|
71106
71562
|
fetched.push(...rows);
|
|
@@ -71125,7 +71581,7 @@ var listProjects = {
|
|
|
71125
71581
|
offset,
|
|
71126
71582
|
returned: projects.length,
|
|
71127
71583
|
hasMore: offset + projects.length < matched,
|
|
71128
|
-
...truncated ? { note: "
|
|
71584
|
+
...truncated ? { note: "More than 2,000 projects; totals reflect the newest 2,000." } : {},
|
|
71129
71585
|
projects
|
|
71130
71586
|
});
|
|
71131
71587
|
}
|
|
@@ -71142,6 +71598,9 @@ var createVideo = {
|
|
|
71142
71598
|
title: "Create a video project",
|
|
71143
71599
|
description: "Create a new video project and an empty draft for you to direct. This does NOT run Impractical's own director \u2014 it scaffolds App.tsx, direction.ts and brand.json and hands them to you. Read the `impractical://engine.d.ts` resource, then write the scene yourself with edit_draft_file / write_draft_files.",
|
|
71144
71600
|
inputSchema: {
|
|
71601
|
+
workspace: WORKSPACE_ARG.describe(
|
|
71602
|
+
'Workspace to create the video in (id, slug or name \u2014 e.g. when the user says "a video for Rox"). Default: the one open in the web app, else the only one; with several and none open, the call fails listing them. The result says where it landed and why.'
|
|
71603
|
+
),
|
|
71145
71604
|
valueProp: external_exports.string().min(1).describe("One or two sentences on what ships and why it matters."),
|
|
71146
71605
|
name: external_exports.string().optional().describe("Human-readable project name. Defaults to the slug."),
|
|
71147
71606
|
slug: external_exports.string().optional().describe(
|
|
@@ -71167,24 +71626,24 @@ var createVideo = {
|
|
|
71167
71626
|
},
|
|
71168
71627
|
handler: async (args, ctx) => {
|
|
71169
71628
|
if (ctx.qualityLoop && !args.creativeContract) {
|
|
71170
|
-
return
|
|
71629
|
+
return fail2(
|
|
71171
71630
|
"The local quality loop requires creativeContract before scaffolding. Name the audience, singleIdea, visualProof, referenceStrategy, productSource, opening, proof, and payoff. This is a planning gate only; it does not change the scene schema."
|
|
71172
71631
|
);
|
|
71173
71632
|
}
|
|
71174
71633
|
if (ctx.phasedFlow) {
|
|
71175
71634
|
const gate = phasedGateFailure({ concept: args.concept, content: args.content });
|
|
71176
|
-
if (gate) return
|
|
71635
|
+
if (gate) return fail2(gate);
|
|
71177
71636
|
if (shotListEnabled()) {
|
|
71178
71637
|
const shotGap = shotListGateFailure(args.concept);
|
|
71179
|
-
if (shotGap) return
|
|
71638
|
+
if (shotGap) return fail2(shotGap);
|
|
71180
71639
|
}
|
|
71181
71640
|
const refDir = refInjectDir();
|
|
71182
71641
|
if (refDir) {
|
|
71183
71642
|
const refGap = refInjectGateFailure(args.concept, refDir);
|
|
71184
|
-
if (refGap) return
|
|
71643
|
+
if (refGap) return fail2(refGap);
|
|
71185
71644
|
}
|
|
71186
71645
|
if (!ctx.qualityLoopState?.referenceLedger) {
|
|
71187
|
-
return
|
|
71646
|
+
return fail2(
|
|
71188
71647
|
"The phased flow requires gather_references BEFORE create_video: record the real references this film is designed against (or an honest noneFound after exhausting the ladder: local code -> product site -> screenshots -> component-class images)."
|
|
71189
71648
|
);
|
|
71190
71649
|
}
|
|
@@ -71290,7 +71749,7 @@ var readDraftFile = {
|
|
|
71290
71749
|
const path7 = String(args.path);
|
|
71291
71750
|
const content = draft.files[path7];
|
|
71292
71751
|
if (content === void 0) {
|
|
71293
|
-
return
|
|
71752
|
+
return fail2(
|
|
71294
71753
|
`No file "${path7}" in draft ${args.draftId}. Available: ${Object.keys(draft.files).sort().join(", ")}`
|
|
71295
71754
|
);
|
|
71296
71755
|
}
|
|
@@ -71365,7 +71824,7 @@ var editDraftFile = {
|
|
|
71365
71824
|
return { files: { [path7]: next }, deletedPaths: [] };
|
|
71366
71825
|
}
|
|
71367
71826
|
);
|
|
71368
|
-
return problem ?
|
|
71827
|
+
return problem ? fail2(problem) : output;
|
|
71369
71828
|
}
|
|
71370
71829
|
};
|
|
71371
71830
|
var jobStatus = {
|
|
@@ -71474,7 +71933,7 @@ var exportVideo = {
|
|
|
71474
71933
|
gateReform,
|
|
71475
71934
|
capture: ctx.qualityLoopState?.finalMotionReviewByDraft.get(String(args.draftId))
|
|
71476
71935
|
}) ?? driftMotionFailure(ctx.qualityLoopState?.finalMotionReviewByDraft.get(String(args.draftId)));
|
|
71477
|
-
if (failure) return
|
|
71936
|
+
if (failure) return fail2(`Quality gate blocked export: ${failure}`);
|
|
71478
71937
|
}
|
|
71479
71938
|
const started = await ctx.invoke("start-export", { draftId: args.draftId });
|
|
71480
71939
|
return json2({
|
|
@@ -71490,15 +71949,25 @@ var exportVideo = {
|
|
|
71490
71949
|
var brandList = {
|
|
71491
71950
|
name: "brand_list",
|
|
71492
71951
|
title: "List brand kits",
|
|
71493
|
-
description: "List
|
|
71494
|
-
inputSchema: {
|
|
71495
|
-
|
|
71952
|
+
description: "List saved brand kits \u2014 across every workspace the user belongs to (each tagged with its workspace), or one workspace with `workspace`.",
|
|
71953
|
+
inputSchema: {
|
|
71954
|
+
workspace: WORKSPACE_ARG.describe("Only this workspace. Default: all of them.")
|
|
71955
|
+
},
|
|
71956
|
+
handler: async (args, ctx) => json2(await ctx.invoke("brand-kits", {
|
|
71957
|
+
action: "list",
|
|
71958
|
+
...args.workspace ? {} : { allWorkspaces: true }
|
|
71959
|
+
}))
|
|
71496
71960
|
};
|
|
71497
71961
|
var brandGet = {
|
|
71498
71962
|
name: "brand_get",
|
|
71499
71963
|
title: "Get a brand kit",
|
|
71500
71964
|
description: "Get one brand kit \u2014 its colors, fonts and logo. Treat these as law when directing.",
|
|
71501
|
-
inputSchema: {
|
|
71965
|
+
inputSchema: {
|
|
71966
|
+
slug: external_exports.string().describe("Brand kit slug."),
|
|
71967
|
+
workspace: WORKSPACE_ARG.describe(
|
|
71968
|
+
"Workspace holding the kit (brand_list shows it). Default: the one open in the web app, or the only one."
|
|
71969
|
+
)
|
|
71970
|
+
},
|
|
71502
71971
|
handler: async (args, ctx) => json2(await ctx.invoke("brand-kits", { action: "get", slug: args.slug }))
|
|
71503
71972
|
};
|
|
71504
71973
|
var brandExtract = {
|
|
@@ -71506,6 +71975,9 @@ var brandExtract = {
|
|
|
71506
71975
|
title: "Extract a brand kit from a URL",
|
|
71507
71976
|
description: "Start extracting a brand kit (colors, fonts, logo) from a website and return the run id immediately. To observe an existing run, call this tool with jobId instead of url; that status mode never starts another extraction.",
|
|
71508
71977
|
inputSchema: {
|
|
71978
|
+
workspace: WORKSPACE_ARG.describe(
|
|
71979
|
+
"Workspace to save the kit in (id, slug or name). Default: the one open in the web app, else the only one; with several and none open, the call fails listing them. Pass the same value when continuing by jobId."
|
|
71980
|
+
),
|
|
71509
71981
|
url: external_exports.string().optional().describe("The brand website URL. Omit when continuing by jobId."),
|
|
71510
71982
|
jobId: external_exports.string().optional().describe("Run id returned by a previous brand_extract call."),
|
|
71511
71983
|
reextract: external_exports.boolean().optional().describe("Re-extract even if a kit already exists."),
|
|
@@ -71517,8 +71989,8 @@ var brandExtract = {
|
|
|
71517
71989
|
handler: async (args, ctx, progress) => {
|
|
71518
71990
|
const url2 = typeof args.url === "string" ? args.url : "";
|
|
71519
71991
|
const jobId = typeof args.jobId === "string" ? args.jobId : "";
|
|
71520
|
-
if (url2 && jobId) return
|
|
71521
|
-
if (!url2 && !jobId) return
|
|
71992
|
+
if (url2 && jobId) return fail2("Pass either url to start or jobId to continue, not both.");
|
|
71993
|
+
if (!url2 && !jobId) return fail2("Pass url to start an extraction, or jobId to continue one.");
|
|
71522
71994
|
if (url2) {
|
|
71523
71995
|
const started = await ctx.invoke("brand-extraction", {
|
|
71524
71996
|
action: "start",
|
|
@@ -71538,7 +72010,7 @@ var brandExtract = {
|
|
|
71538
72010
|
if (!args.wait) {
|
|
71539
72011
|
const status = await readStatus();
|
|
71540
72012
|
if (status.status === "error" || status.status === "failed" || status.error) {
|
|
71541
|
-
return
|
|
72013
|
+
return fail2(`Brand extraction failed${status.error ? `: ${status.error}` : ""}`);
|
|
71542
72014
|
}
|
|
71543
72015
|
return json2({ jobId, ...status });
|
|
71544
72016
|
}
|
|
@@ -71560,7 +72032,7 @@ var brandExtract = {
|
|
|
71560
72032
|
return json2({ jobId, ...status });
|
|
71561
72033
|
}
|
|
71562
72034
|
if (status.status === "error" || status.status === "failed" || status.error) {
|
|
71563
|
-
return
|
|
72035
|
+
return fail2(`Brand extraction failed${status.error ? `: ${status.error}` : ""}`);
|
|
71564
72036
|
}
|
|
71565
72037
|
} catch (error51) {
|
|
71566
72038
|
lastError = error51 instanceof Error ? error51.message : String(error51);
|
|
@@ -71588,6 +72060,9 @@ var motionProfile = {
|
|
|
71588
72060
|
title: "Manage the personal motion profile",
|
|
71589
72061
|
description: "Inspect and manage the user's learned motion preferences. Call with action 'get' to see the effective profile before directing. Use 'remember' ONLY when the user explicitly asks to remember a preference; use 'propose' to submit an inferred preference as a pending proposal for the user to confirm \u2014 never confirm an inferred preference yourself. 'confirm'/'reject' decide a pending proposal after asking the user; 'forget', 'pause', 'resume' and 'reset' manage stored preferences on the user's behalf.",
|
|
71590
72062
|
inputSchema: {
|
|
72063
|
+
workspace: WORKSPACE_ARG.describe(
|
|
72064
|
+
"Workspace whose profile layers to use. Default: the draft's workspace when draftId is given, else the one open in the web app, else the only one."
|
|
72065
|
+
),
|
|
71591
72066
|
action: external_exports.enum(["get", "remember", "propose", "confirm", "reject", "forget", "pause", "resume", "reset"]).describe("The profile command to run."),
|
|
71592
72067
|
rule: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe(
|
|
71593
72068
|
"Structured preference for remember/propose, e.g. {kind:'trait',trait:'pacing',value:'fast'}, {kind:'library',itemType:'style',itemId:'optical',stance:'prefer'}, {kind:'freeform',text:'...'}, {kind:'duration',max:15}, or {kind:'example',draftId:'...'}."
|
|
@@ -71599,7 +72074,10 @@ var motionProfile = {
|
|
|
71599
72074
|
contentType: external_exports.string().optional().describe("Content type this preference applies to."),
|
|
71600
72075
|
draftId: external_exports.string().optional().describe("Draft that motivated a proposal.")
|
|
71601
72076
|
},
|
|
71602
|
-
handler: async (args, ctx) =>
|
|
72077
|
+
handler: async (args, ctx) => {
|
|
72078
|
+
const { workspace: _workspace, ...body } = args;
|
|
72079
|
+
return json2(await ctx.invoke("motion-profile", body));
|
|
72080
|
+
}
|
|
71603
72081
|
};
|
|
71604
72082
|
var studioLinkTool = {
|
|
71605
72083
|
name: "studio_link",
|
|
@@ -71610,7 +72088,7 @@ var studioLinkTool = {
|
|
|
71610
72088
|
slug: external_exports.string().optional().describe("Draft slug to open directly.")
|
|
71611
72089
|
},
|
|
71612
72090
|
handler: async (args, ctx) => ({
|
|
71613
|
-
text:
|
|
72091
|
+
text: await resolvedStudioLink(ctx, String(args.projectId), args.slug)
|
|
71614
72092
|
})
|
|
71615
72093
|
};
|
|
71616
72094
|
var REMOTE_SAFE_TOOLS = [
|
|
@@ -71759,10 +72237,10 @@ function kitCatalog(sources, {
|
|
|
71759
72237
|
if (header.length) break;
|
|
71760
72238
|
continue;
|
|
71761
72239
|
}
|
|
71762
|
-
const
|
|
71763
|
-
if (!
|
|
71764
|
-
if (!header.length) standsAlone = KIT_TITLE_BAR.test(raw) || /[.!?]$/.test(
|
|
71765
|
-
header.push(
|
|
72240
|
+
const text2 = line.replace(/^\/\/\s*/, "").replace(/[─]+/g, "").trim();
|
|
72241
|
+
if (!text2) continue;
|
|
72242
|
+
if (!header.length) standsAlone = KIT_TITLE_BAR.test(raw) || /[.!?]$/.test(text2);
|
|
72243
|
+
header.push(text2);
|
|
71766
72244
|
if (header.length >= (headerMode === "title" && standsAlone ? 1 : 2)) break;
|
|
71767
72245
|
}
|
|
71768
72246
|
const exports = [...file2.content.matchAll(/^export (?:const|function) (\w+)/gm)].map((m) => m[1]).filter((n) => !n.startsWith("_")).filter(
|
|
@@ -72298,7 +72776,7 @@ var openStudioTool = {
|
|
|
72298
72776
|
slug: external_exports.string().optional().describe("Draft slug to open directly.")
|
|
72299
72777
|
},
|
|
72300
72778
|
handler: async (args, ctx) => {
|
|
72301
|
-
const url2 =
|
|
72779
|
+
const url2 = await resolvedStudioLink(ctx, String(args.projectId), args.slug);
|
|
72302
72780
|
const needle = `/projects/${String(args.projectId)}`;
|
|
72303
72781
|
try {
|
|
72304
72782
|
const existing = await findOpenStudioTab(needle);
|
|
@@ -72320,9 +72798,11 @@ var openStudioTool = {
|
|
|
72320
72798
|
// src/mcp/connect.ts
|
|
72321
72799
|
var CONNECT_WAIT_SECONDS = 300;
|
|
72322
72800
|
async function connectWorkspace(input, deps) {
|
|
72323
|
-
const grant = await deps.request(
|
|
72324
|
-
|
|
72325
|
-
|
|
72801
|
+
const grant = await deps.request(
|
|
72802
|
+
deps.supabaseUrl,
|
|
72803
|
+
"cli-device-auth",
|
|
72804
|
+
DEVICE_START_BODY
|
|
72805
|
+
);
|
|
72326
72806
|
const browserOpened = deps.open(grant.verificationUri);
|
|
72327
72807
|
const expiry = Date.parse(grant.expiresAt);
|
|
72328
72808
|
const deadline = Math.min(
|
|
@@ -72347,7 +72827,12 @@ async function connectWorkspace(input, deps) {
|
|
|
72347
72827
|
supabaseUrl: deps.supabaseUrl,
|
|
72348
72828
|
appUrl: deps.appUrl
|
|
72349
72829
|
});
|
|
72350
|
-
return {
|
|
72830
|
+
return {
|
|
72831
|
+
status: "connected",
|
|
72832
|
+
userCode: grant.userCode,
|
|
72833
|
+
browserOpened,
|
|
72834
|
+
keyScope: grantScope(poll)
|
|
72835
|
+
};
|
|
72351
72836
|
}
|
|
72352
72837
|
await deps.sleep(intervalMs);
|
|
72353
72838
|
}
|
|
@@ -72361,7 +72846,7 @@ async function connectWorkspace(input, deps) {
|
|
|
72361
72846
|
var connectTool = {
|
|
72362
72847
|
name: "connect",
|
|
72363
72848
|
title: "Connect this workspace",
|
|
72364
|
-
description: "Authenticate Impractical Motion for this machine. Opens the user's browser to approve the connection, waits for them to confirm, and stores the credential locally. TELL THE USER YOU ARE ABOUT TO OPEN THEIR BROWSER BEFORE CALLING THIS \u2014 the call blocks until they approve. Use it whenever a tool reports that the workspace is not connected.",
|
|
72849
|
+
description: "Authenticate Impractical Motion for this machine. Opens the user's browser to approve the connection, waits for them to confirm, and stores the credential locally. TELL THE USER YOU ARE ABOUT TO OPEN THEIR BROWSER BEFORE CALLING THIS \u2014 the call blocks until they approve. Use it whenever a tool reports that the workspace is not connected. The key it stores reaches every workspace the user belongs to; calling it again also upgrades an older single-workspace connection.",
|
|
72365
72850
|
inputSchema: {
|
|
72366
72851
|
waitSeconds: external_exports.number().optional().describe(`How long to wait for browser approval. Default ${CONNECT_WAIT_SECONDS}.`)
|
|
72367
72852
|
},
|
|
@@ -72392,6 +72877,13 @@ var connectTool = {
|
|
|
72392
72877
|
};
|
|
72393
72878
|
}
|
|
72394
72879
|
try {
|
|
72880
|
+
if (result.keyScope === "user") {
|
|
72881
|
+
const listing = await fetchWorkspaces(ctx.invoke);
|
|
72882
|
+
const open = listing.workspaces.find((w) => w.id === listing.lastOpenWorkspaceId);
|
|
72883
|
+
return {
|
|
72884
|
+
text: `Connected. This key reaches all ${listing.workspaces.length} of the user's workspaces: ` + listing.workspaces.map(workspaceLabel).join(", ") + ". Lists span all of them; tools that address a project or draft act in its workspace; new videos go to the workspace named with `workspace`, else " + (open ? `the one open in the web app (now ${workspaceLabel(open)})` : "the one open in the web app") + (listing.workspaces.length === 1 ? " \u2014 here the only one." : ".")
|
|
72885
|
+
};
|
|
72886
|
+
}
|
|
72395
72887
|
const snapshot = await ctx.invoke(
|
|
72396
72888
|
"workspace-bootstrap"
|
|
72397
72889
|
);
|
|
@@ -72448,6 +72940,7 @@ var engineTypesTool = {
|
|
|
72448
72940
|
};
|
|
72449
72941
|
var TOOLS = [
|
|
72450
72942
|
connectTool,
|
|
72943
|
+
...WORKSPACE_TOOLS,
|
|
72451
72944
|
upgradeTool,
|
|
72452
72945
|
...REMOTE_SAFE_TOOLS,
|
|
72453
72946
|
getFramesTool,
|
|
@@ -72565,12 +73058,23 @@ function register(server, tool, ctx) {
|
|
|
72565
73058
|
async (args, extra) => {
|
|
72566
73059
|
try {
|
|
72567
73060
|
const admissionName = tool.admitAs ?? tool.name;
|
|
72568
|
-
const admission = ctx.admit && !UNMETERED_MCP_TOOLS.has(admissionName) ? await ctx.admit(
|
|
72569
|
-
|
|
72570
|
-
|
|
73061
|
+
const admission = ctx.admit && !UNMETERED_MCP_TOOLS.has(admissionName) ? await ctx.admit(
|
|
73062
|
+
admissionName,
|
|
73063
|
+
admissionTarget(tool.name, args ?? {}, ctx.defaultWorkspace)
|
|
73064
|
+
) : null;
|
|
73065
|
+
const admitted = admission?.keyScope === "user" ? admission.workspace ?? null : null;
|
|
73066
|
+
const linkWorkspace = admission?.workspace?.id && admission.workspace.reason !== "any" ? admission.workspace.id : void 0;
|
|
73067
|
+
const callCtx = linkWorkspace ? { ...ctx, callWorkspaceId: linkWorkspace } : ctx;
|
|
73068
|
+
const execute = () => tool.handler(args ?? {}, callCtx, toolProgress(extra));
|
|
73069
|
+
const output = admission?.receipt && ctx.withAdmission ? await ctx.withAdmission(admission.receipt, execute, admitted?.id) : await execute();
|
|
72571
73070
|
if (admission?.warning) output.text += `
|
|
72572
73071
|
|
|
72573
73072
|
${formatUsageNotice(admission.warning)}`;
|
|
73073
|
+
if (admitted && !output.isError && WORKSPACE_ACTING_TOOLS.has(tool.name)) {
|
|
73074
|
+
output.text += `
|
|
73075
|
+
|
|
73076
|
+
${workspaceNote(tool.name, admitted)}`;
|
|
73077
|
+
}
|
|
72574
73078
|
return toContent(output);
|
|
72575
73079
|
} catch (error51) {
|
|
72576
73080
|
const status = error51.status;
|
|
@@ -72588,7 +73092,11 @@ ${formatUsageNotice(admission.warning)}`;
|
|
|
72588
73092
|
isError: true
|
|
72589
73093
|
});
|
|
72590
73094
|
}
|
|
72591
|
-
const hint = status === 401 || isNotConnected(message) ? "\n\nCall the `connect` tool to authenticate this workspace." : status ===
|
|
73095
|
+
const hint = status === 401 || isNotConnected(message) ? "\n\nCall the `connect` tool to authenticate this workspace." : status === 409 && details?.error === "workspace_selection_required" ? `
|
|
73096
|
+
|
|
73097
|
+
The user belongs to several workspaces${workspaceChoices(details)} and none was named or open in the web app. Ask which one, then retry with \`workspace\`.` : status === 403 && details?.error === "workspace_access_denied" ? `
|
|
73098
|
+
|
|
73099
|
+
That workspace is not available to this user${workspaceChoices(details)}. Call list_workspaces and retry with one of them.` : status === 402 ? "\n\nThe workspace needs an active subscription or trial." : "";
|
|
72592
73100
|
return toContent({ text: `${tool.name} failed: ${message}${hint}`, isError: true });
|
|
72593
73101
|
}
|
|
72594
73102
|
}
|
|
@@ -72678,6 +73186,31 @@ function createServer(ctx) {
|
|
|
72678
73186
|
registerEngineResource(server);
|
|
72679
73187
|
return server;
|
|
72680
73188
|
}
|
|
73189
|
+
function workspaceChoices(details) {
|
|
73190
|
+
const list = Array.isArray(details?.workspaces) ? details.workspaces : [];
|
|
73191
|
+
const names = list.filter((row) => typeof row === "object" && row !== null && typeof row.id === "string" && /^[A-Za-z0-9_-]{1,100}$/.test(row.id)).slice(0, 20).map(
|
|
73192
|
+
(row) => typeof row.name === "string" && row.name.length <= 100 ? `${row.name.replace(/[\u0000-\u001f]/g, "")} \u2014 ${row.id}` : row.id
|
|
73193
|
+
);
|
|
73194
|
+
return names.length ? ` (${names.join(", ")})` : "";
|
|
73195
|
+
}
|
|
73196
|
+
function createProjectWorkspaceLookup(request = (body) => {
|
|
73197
|
+
const { apiKey, supabaseUrl } = requireConfig();
|
|
73198
|
+
return invokeAt(supabaseUrl, "workspace-bootstrap", body, apiKey);
|
|
73199
|
+
}) {
|
|
73200
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
73201
|
+
return async (projectId) => {
|
|
73202
|
+
if (cache2.has(projectId)) return cache2.get(projectId) ?? null;
|
|
73203
|
+
let id = null;
|
|
73204
|
+
try {
|
|
73205
|
+
const result = await request({ action: "project_workspace", projectId });
|
|
73206
|
+
id = typeof result?.workspace?.id === "string" ? result.workspace.id : null;
|
|
73207
|
+
} catch {
|
|
73208
|
+
id = null;
|
|
73209
|
+
}
|
|
73210
|
+
cache2.set(projectId, id);
|
|
73211
|
+
return id;
|
|
73212
|
+
};
|
|
73213
|
+
}
|
|
72681
73214
|
async function runStdioServer() {
|
|
72682
73215
|
const config2 = loadConfig();
|
|
72683
73216
|
if (!config2.apiKey) {
|
|
@@ -72699,7 +73232,9 @@ async function runStdioServer() {
|
|
|
72699
73232
|
phasedFlow: phasedFlowEnabled(),
|
|
72700
73233
|
// stdio runs on the user's machine, so completed preview builds can be
|
|
72701
73234
|
// measured in the local browser and answered with what the frame became.
|
|
72702
|
-
measurePreview: measureStage
|
|
73235
|
+
measurePreview: measureStage,
|
|
73236
|
+
defaultWorkspace: config2.workspace,
|
|
73237
|
+
projectWorkspace: createProjectWorkspaceLookup()
|
|
72703
73238
|
});
|
|
72704
73239
|
await server.connect(new StdioServerTransport());
|
|
72705
73240
|
const served = TOOLS.length + 2 + createComponentTools().length + (motionLabEnabled() ? 1 : 0) + (phasedFlowEnabled() ? 1 : 0);
|
|
@@ -72709,6 +73244,7 @@ async function runStdioServer() {
|
|
|
72709
73244
|
export {
|
|
72710
73245
|
ENGINE_DTS_URI,
|
|
72711
73246
|
buildServerInstructions,
|
|
73247
|
+
createProjectWorkspaceLookup,
|
|
72712
73248
|
createServer,
|
|
72713
73249
|
runStdioServer
|
|
72714
73250
|
};
|