@kaitranntt/ccs 7.79.1-dev.18 → 7.79.1-dev.19
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.
|
@@ -1209,7 +1209,18 @@ function getTools() {
|
|
|
1209
1209
|
},
|
|
1210
1210
|
event: {
|
|
1211
1211
|
type: 'object',
|
|
1212
|
-
description:
|
|
1212
|
+
description:
|
|
1213
|
+
'Required event selector. request events require urlIncludes; download events require urlIncludes or suggestedFilenameIncludes. URLs in returned details are redacted.',
|
|
1214
|
+
properties: {
|
|
1215
|
+
kind: { type: 'string', enum: ['dialog', 'navigation', 'request', 'download'] },
|
|
1216
|
+
dialogType: { type: 'string' },
|
|
1217
|
+
messageIncludes: { type: 'string' },
|
|
1218
|
+
urlIncludes: { type: 'string' },
|
|
1219
|
+
method: { type: 'string' },
|
|
1220
|
+
suggestedFilenameIncludes: { type: 'string' },
|
|
1221
|
+
},
|
|
1222
|
+
required: ['kind'],
|
|
1223
|
+
additionalProperties: false,
|
|
1213
1224
|
},
|
|
1214
1225
|
},
|
|
1215
1226
|
required: ['event'],
|
|
@@ -3348,24 +3359,80 @@ function parseEventCondition(value) {
|
|
|
3348
3359
|
};
|
|
3349
3360
|
}
|
|
3350
3361
|
if (value.kind === 'request') {
|
|
3362
|
+
const urlIncludes = value.urlIncludes ? String(value.urlIncludes) : undefined;
|
|
3363
|
+
if (!urlIncludes) {
|
|
3364
|
+
throw new Error('request events require urlIncludes to limit network metadata exposure');
|
|
3365
|
+
}
|
|
3351
3366
|
return {
|
|
3352
3367
|
kind: 'request',
|
|
3353
|
-
urlIncludes
|
|
3368
|
+
urlIncludes,
|
|
3354
3369
|
method: value.method ? String(value.method) : undefined,
|
|
3355
3370
|
};
|
|
3356
3371
|
}
|
|
3357
3372
|
if (value.kind === 'download') {
|
|
3373
|
+
const urlIncludes = value.urlIncludes ? String(value.urlIncludes) : undefined;
|
|
3374
|
+
const suggestedFilenameIncludes = value.suggestedFilenameIncludes
|
|
3375
|
+
? String(value.suggestedFilenameIncludes)
|
|
3376
|
+
: undefined;
|
|
3377
|
+
if (!urlIncludes && !suggestedFilenameIncludes) {
|
|
3378
|
+
throw new Error(
|
|
3379
|
+
'download events require urlIncludes or suggestedFilenameIncludes to limit metadata exposure'
|
|
3380
|
+
);
|
|
3381
|
+
}
|
|
3358
3382
|
return {
|
|
3359
3383
|
kind: 'download',
|
|
3360
|
-
urlIncludes
|
|
3361
|
-
suggestedFilenameIncludes
|
|
3362
|
-
? String(value.suggestedFilenameIncludes)
|
|
3363
|
-
: undefined,
|
|
3384
|
+
urlIncludes,
|
|
3385
|
+
suggestedFilenameIncludes,
|
|
3364
3386
|
};
|
|
3365
3387
|
}
|
|
3366
3388
|
throw new Error(`unknown event kind: ${String(value.kind || '')}`);
|
|
3367
3389
|
}
|
|
3368
3390
|
|
|
3391
|
+
function redactUrlForModel(value, options = {}) {
|
|
3392
|
+
const rawUrl = String(value || '');
|
|
3393
|
+
if (!rawUrl) {
|
|
3394
|
+
return '';
|
|
3395
|
+
}
|
|
3396
|
+
try {
|
|
3397
|
+
const url = new URL(rawUrl);
|
|
3398
|
+
if (options.originOnly) {
|
|
3399
|
+
return url.origin;
|
|
3400
|
+
}
|
|
3401
|
+
url.username = '';
|
|
3402
|
+
url.password = '';
|
|
3403
|
+
url.search = '';
|
|
3404
|
+
url.hash = '';
|
|
3405
|
+
return url.toString();
|
|
3406
|
+
} catch {
|
|
3407
|
+
return '[redacted-url]';
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
|
|
3411
|
+
function redactObservedEvent(event, observed) {
|
|
3412
|
+
if (!observed || typeof observed !== 'object') {
|
|
3413
|
+
return observed;
|
|
3414
|
+
}
|
|
3415
|
+
if (event.kind === 'request') {
|
|
3416
|
+
return {
|
|
3417
|
+
url: redactUrlForModel(observed.url, { originOnly: true }),
|
|
3418
|
+
method: observed.method || '',
|
|
3419
|
+
};
|
|
3420
|
+
}
|
|
3421
|
+
if (event.kind === 'download') {
|
|
3422
|
+
return {
|
|
3423
|
+
url: redactUrlForModel(observed.url, { originOnly: true }),
|
|
3424
|
+
suggestedFilename: observed.suggestedFilename || '',
|
|
3425
|
+
};
|
|
3426
|
+
}
|
|
3427
|
+
if (event.kind === 'navigation' && Object.prototype.hasOwnProperty.call(observed, 'url')) {
|
|
3428
|
+
return {
|
|
3429
|
+
...observed,
|
|
3430
|
+
url: redactUrlForModel(observed.url, { originOnly: true }),
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
return observed;
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3369
3436
|
function matchesObservedEvent(event, observed) {
|
|
3370
3437
|
if (event.kind === 'dialog') {
|
|
3371
3438
|
return (
|
|
@@ -4819,7 +4886,8 @@ async function handleWaitForEvent(toolArgs) {
|
|
|
4819
4886
|
);
|
|
4820
4887
|
const event = parseEventCondition(toolArgs.event);
|
|
4821
4888
|
const observed = await waitForMatchingEvent({ page, pageIndex, timeoutMs, event });
|
|
4822
|
-
|
|
4889
|
+
const safeObserved = redactObservedEvent(event, observed);
|
|
4890
|
+
return `pageIndex: ${pageIndex}\nevent: ${event.kind}\nstatus: observed\ndetail: ${JSON.stringify(safeObserved)}`;
|
|
4823
4891
|
}
|
|
4824
4892
|
|
|
4825
4893
|
function findInterceptRuleIndex(ruleId) {
|