@wenathlan/extension 1.1.48 → 1.1.50
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/README.md +7 -5
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1341 -5
- package/dist/index.js.map +4 -4
- package/dist/memory.d.ts +79 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/policy.d.ts +45 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/protocol.d.ts +98 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/sessions.d.ts +79 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/types.d.ts +297 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/workflow.d.ts +148 -0
- package/dist/workflow.d.ts.map +1 -0
- package/extension/dist/background.js +2025 -48
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/manifest.json +1 -1
- package/extension/dist/pagebridge.js +2 -2
- package/extension/dist/pagebridge.js.map +2 -2
- package/extension/dist/popup.html +1 -1
- package/extension/dist/popup.js +56 -2
- package/extension/dist/popup.js.map +2 -2
- package/extension/dist/sidepanel.html +1 -1
- package/extension/dist/sidepanel.js +392 -2
- package/extension/dist/sidepanel.js.map +3 -3
- package/extension/dist/style.css +2 -0
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1331,6 +1331,212 @@ function expireprofilerecords(input) {
|
|
|
1331
1331
|
};
|
|
1332
1332
|
}
|
|
1333
1333
|
|
|
1334
|
+
// sessions.ts
|
|
1335
|
+
var sessionkinds = ["persiststate", "capturesession", "restoresession", "namedsessions", "diffsessions", "searchsessions", "exportsessions", "importsessions"];
|
|
1336
|
+
var sessionfileversion = 1;
|
|
1337
|
+
var snapshotsections = ["tabs", "scroll", "forms", "storage", "cookies"];
|
|
1338
|
+
var searchfields = ["urls", "titles", "names", "text"];
|
|
1339
|
+
function checksumtext(payload) {
|
|
1340
|
+
let hash = 2166136261;
|
|
1341
|
+
for (let index = 0; index < payload.length; index += 1) {
|
|
1342
|
+
hash ^= payload.charCodeAt(index);
|
|
1343
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
1344
|
+
}
|
|
1345
|
+
return hash.toString(16).padStart(8, "0");
|
|
1346
|
+
}
|
|
1347
|
+
function taskstatechecksum(runid, stepcursor, outputs) {
|
|
1348
|
+
return checksumtext(`${runid}:${stepcursor}:${outputs.length}:${outputs.map((output) => `${output.stepid}:${output.ok}:${output.summary.length}`).join("|")}`);
|
|
1349
|
+
}
|
|
1350
|
+
function taskstateof(input) {
|
|
1351
|
+
return { runid: input.runid, stepcursor: input.stepcursor, outputs: input.outputs, checkpointat: input.checkpointat, checksum: taskstatechecksum(input.runid, input.stepcursor, input.outputs) };
|
|
1352
|
+
}
|
|
1353
|
+
function taskstatevalid(state) {
|
|
1354
|
+
if (!state || typeof state.runid !== "string" || !state.runid.trim()) return false;
|
|
1355
|
+
if (typeof state.stepcursor !== "number" || !Number.isInteger(state.stepcursor) || state.stepcursor < 0) return false;
|
|
1356
|
+
if (typeof state.checkpointat !== "number" || !Number.isFinite(state.checkpointat)) return false;
|
|
1357
|
+
if (!Array.isArray(state.outputs)) return false;
|
|
1358
|
+
return state.checksum === taskstatechecksum(state.runid, state.stepcursor, state.outputs);
|
|
1359
|
+
}
|
|
1360
|
+
function sessiontabof(value) {
|
|
1361
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1362
|
+
const candidate = value;
|
|
1363
|
+
if (typeof candidate.url !== "string" || !candidate.url.trim()) return void 0;
|
|
1364
|
+
if (typeof candidate.title !== "string") return void 0;
|
|
1365
|
+
if (typeof candidate.index !== "number" || !Number.isInteger(candidate.index) || candidate.index < 0) return void 0;
|
|
1366
|
+
const scrollx = typeof candidate.scrollx === "number" && Number.isFinite(candidate.scrollx) ? candidate.scrollx : 0;
|
|
1367
|
+
const scrolly = typeof candidate.scrolly === "number" && Number.isFinite(candidate.scrolly) ? candidate.scrolly : 0;
|
|
1368
|
+
const forms = Array.isArray(candidate.forms) ? candidate.forms.flatMap((entry) => {
|
|
1369
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
|
|
1370
|
+
const form = entry;
|
|
1371
|
+
if (typeof form.selector !== "string" || !form.selector.trim()) return [];
|
|
1372
|
+
return [{ selector: form.selector, value: typeof form.value === "string" ? form.value : "" }];
|
|
1373
|
+
}) : [];
|
|
1374
|
+
return { url: candidate.url, title: candidate.title, index: candidate.index, scrollx, scrolly, forms };
|
|
1375
|
+
}
|
|
1376
|
+
function autointervalof(value) {
|
|
1377
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1378
|
+
const candidate = value;
|
|
1379
|
+
if (typeof candidate.period !== "number" || !Number.isFinite(candidate.period) || candidate.period <= 0) return void 0;
|
|
1380
|
+
if (typeof candidate.maxsnapshots !== "number" || !Number.isInteger(candidate.maxsnapshots) || candidate.maxsnapshots < 1) return void 0;
|
|
1381
|
+
if (typeof candidate.expiry !== "number" || !Number.isFinite(candidate.expiry) || candidate.expiry < 0) return void 0;
|
|
1382
|
+
return { period: candidate.period, maxsnapshots: candidate.maxsnapshots, expiry: candidate.expiry };
|
|
1383
|
+
}
|
|
1384
|
+
function snapshotplanof(value) {
|
|
1385
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1386
|
+
const candidate = value;
|
|
1387
|
+
if (candidate.scope !== "tab" && candidate.scope !== "run" && candidate.scope !== "all") return void 0;
|
|
1388
|
+
const sections = Array.isArray(candidate.sections) ? candidate.sections.flatMap((section) => typeof section === "string" && snapshotsections.includes(section) ? [section] : []) : [];
|
|
1389
|
+
if (sections.length === 0) return void 0;
|
|
1390
|
+
if (typeof candidate.captures !== "boolean") return void 0;
|
|
1391
|
+
const auto = candidate.auto === void 0 ? void 0 : autointervalof(candidate.auto);
|
|
1392
|
+
if (candidate.auto !== void 0 && auto === void 0) return void 0;
|
|
1393
|
+
return { scope: candidate.scope, sections, captures: candidate.captures, ...auto !== void 0 ? { auto } : {} };
|
|
1394
|
+
}
|
|
1395
|
+
function restoreplanof(value) {
|
|
1396
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1397
|
+
const candidate = value;
|
|
1398
|
+
if (candidate.tabpolicy !== "reopen" && candidate.tabpolicy !== "skip") return void 0;
|
|
1399
|
+
if (candidate.formpolicy !== "restore" && candidate.formpolicy !== "skip") return void 0;
|
|
1400
|
+
if (candidate.capturepolicy !== "link" && candidate.capturepolicy !== "skip") return void 0;
|
|
1401
|
+
return { tabpolicy: candidate.tabpolicy, formpolicy: candidate.formpolicy, capturepolicy: candidate.capturepolicy };
|
|
1402
|
+
}
|
|
1403
|
+
function searchqueryof(value) {
|
|
1404
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1405
|
+
const candidate = value;
|
|
1406
|
+
const terms = Array.isArray(candidate.terms) ? candidate.terms.flatMap((term) => typeof term === "string" && term.trim() ? [term.trim()] : []) : [];
|
|
1407
|
+
if (terms.length === 0) return void 0;
|
|
1408
|
+
const fields = Array.isArray(candidate.fields) ? candidate.fields.flatMap((field) => typeof field === "string" && searchfields.includes(field) ? [field] : []) : [...searchfields];
|
|
1409
|
+
if (fields.length === 0) return void 0;
|
|
1410
|
+
const from = typeof candidate.from === "number" && Number.isFinite(candidate.from) ? candidate.from : void 0;
|
|
1411
|
+
const to = typeof candidate.to === "number" && Number.isFinite(candidate.to) ? candidate.to : void 0;
|
|
1412
|
+
if (from !== void 0 && to !== void 0 && from > to) return void 0;
|
|
1413
|
+
return { terms, fields, ...from !== void 0 ? { from } : {}, ...to !== void 0 ? { to } : {} };
|
|
1414
|
+
}
|
|
1415
|
+
function sessionfolderof(value) {
|
|
1416
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1417
|
+
const candidate = value;
|
|
1418
|
+
if (typeof candidate.name !== "string" || !candidate.name.trim()) return void 0;
|
|
1419
|
+
const parent = typeof candidate.parent === "string" && candidate.parent.trim() ? candidate.parent : void 0;
|
|
1420
|
+
const tags = Array.isArray(candidate.tags) ? candidate.tags.flatMap((tag) => typeof tag === "string" && tag.trim() ? [tag] : []) : [];
|
|
1421
|
+
return { name: candidate.name, ...parent !== void 0 ? { parent } : {}, tags };
|
|
1422
|
+
}
|
|
1423
|
+
function newsessionrecord(input) {
|
|
1424
|
+
return { id: input.id, name: input.name, createdat: input.createdat, tabs: input.tabs, captures: input.captures, storage: input.storage, cookies: input.cookies, ...input.folder !== void 0 ? { folder: input.folder } : {}, tags: input.tags ?? [], ...input.auto === true ? { auto: true } : {} };
|
|
1425
|
+
}
|
|
1426
|
+
function diffsessionrecords(left, right) {
|
|
1427
|
+
const changes = [];
|
|
1428
|
+
const leftbyindex = new Map(left.tabs.map((tab) => [tab.index, tab]));
|
|
1429
|
+
const rightbyindex = new Map(right.tabs.map((tab) => [tab.index, tab]));
|
|
1430
|
+
for (const tab of right.tabs) {
|
|
1431
|
+
const prior = leftbyindex.get(tab.index);
|
|
1432
|
+
if (!prior) {
|
|
1433
|
+
changes.push({ class: "added", subject: "tab", detail: `Tab ${tab.index} added: ${tab.url}` });
|
|
1434
|
+
continue;
|
|
1435
|
+
}
|
|
1436
|
+
if (prior.url !== tab.url) changes.push({ class: "changed", subject: "url", detail: `Tab ${tab.index} moved from ${prior.url} to ${tab.url}` });
|
|
1437
|
+
if (prior.title !== tab.title) changes.push({ class: "changed", subject: "tab", detail: `Tab ${tab.index} title changed from "${prior.title}" to "${tab.title}"` });
|
|
1438
|
+
const priorforms = new Map(prior.forms.map((form) => [form.selector, form.value]));
|
|
1439
|
+
for (const form of tab.forms) {
|
|
1440
|
+
const before = priorforms.get(form.selector);
|
|
1441
|
+
if (before === void 0) {
|
|
1442
|
+
changes.push({ class: "added", subject: "form", detail: `Form field ${form.selector} of tab ${tab.index} added with a value` });
|
|
1443
|
+
continue;
|
|
1444
|
+
}
|
|
1445
|
+
if (before !== form.value) changes.push({ class: "changed", subject: "form", detail: `Form field ${form.selector} of tab ${tab.index} changed its captured value` });
|
|
1446
|
+
}
|
|
1447
|
+
for (const form of prior.forms) if (!tab.forms.some((entry) => entry.selector === form.selector)) changes.push({ class: "removed", subject: "form", detail: `Form field ${form.selector} of tab ${tab.index} removed` });
|
|
1448
|
+
}
|
|
1449
|
+
for (const tab of left.tabs) if (!rightbyindex.has(tab.index)) changes.push({ class: "removed", subject: "tab", detail: `Tab ${tab.index} removed: ${tab.url}` });
|
|
1450
|
+
const leftstorage = new Map(left.storage.map((entry) => [entry.origin, entry]));
|
|
1451
|
+
for (const entry of right.storage) {
|
|
1452
|
+
const prior = leftstorage.get(entry.origin);
|
|
1453
|
+
if (!prior) {
|
|
1454
|
+
changes.push({ class: "added", subject: "storage", detail: `Local storage of ${entry.origin} captured with ${entry.keys.length} keys` });
|
|
1455
|
+
continue;
|
|
1456
|
+
}
|
|
1457
|
+
if (prior.keys.join("|") !== entry.keys.join("|") || prior.values.join("|") !== entry.values.join("|")) changes.push({ class: "changed", subject: "storage", detail: `Local storage of ${entry.origin} changed its captured keys or values` });
|
|
1458
|
+
}
|
|
1459
|
+
for (const entry of left.storage) if (!right.storage.some((candidate) => candidate.origin === entry.origin)) changes.push({ class: "removed", subject: "storage", detail: `Local storage of ${entry.origin} left the capture` });
|
|
1460
|
+
return changes;
|
|
1461
|
+
}
|
|
1462
|
+
function newsessiondiff(input) {
|
|
1463
|
+
return { id: input.id, leftid: input.left.id, rightid: input.right.id, changes: diffsessionrecords(input.left, input.right), at: input.at };
|
|
1464
|
+
}
|
|
1465
|
+
function searchsessionrecords(query, records) {
|
|
1466
|
+
const matches = [];
|
|
1467
|
+
for (const record2 of records) {
|
|
1468
|
+
if (query.from !== void 0 && record2.createdat < query.from) continue;
|
|
1469
|
+
if (query.to !== void 0 && record2.createdat > query.to) continue;
|
|
1470
|
+
const haystacks = [
|
|
1471
|
+
{ field: "urls", text: record2.tabs.map((tab) => tab.url).join(" ") },
|
|
1472
|
+
{ field: "titles", text: record2.tabs.map((tab) => tab.title).join(" ") },
|
|
1473
|
+
{ field: "names", text: [record2.name, record2.folder ?? "", ...record2.tags].join(" ") },
|
|
1474
|
+
{ field: "text", text: record2.tabs.flatMap((tab) => tab.forms.map((form) => form.value)).join(" ") }
|
|
1475
|
+
];
|
|
1476
|
+
for (const haystack of haystacks) {
|
|
1477
|
+
if (!query.fields.includes(haystack.field)) continue;
|
|
1478
|
+
const lower = haystack.text.toLowerCase();
|
|
1479
|
+
for (const term of query.terms) {
|
|
1480
|
+
const at = lower.indexOf(term.toLowerCase());
|
|
1481
|
+
if (at < 0) continue;
|
|
1482
|
+
const start = Math.max(0, at - 30);
|
|
1483
|
+
matches.push({ sessionid: record2.id, field: haystack.field, term, at: record2.createdat, excerpt: haystack.text.slice(start, start + 80).trim() });
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
return matches;
|
|
1488
|
+
}
|
|
1489
|
+
function exportsessionfile(records, now) {
|
|
1490
|
+
const recordids = records.map((record2) => record2.id);
|
|
1491
|
+
const payload = JSON.stringify(records);
|
|
1492
|
+
return { formatversion: sessionfileversion, records, recordids, bytesize: payload.length, checksum: checksumtext(`${sessionfileversion}:${recordids.join(",")}:${payload.length}`), exportedat: now };
|
|
1493
|
+
}
|
|
1494
|
+
function importsessionfile(value) {
|
|
1495
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1496
|
+
const candidate = value;
|
|
1497
|
+
if (candidate.formatversion !== sessionfileversion) return void 0;
|
|
1498
|
+
const records = Array.isArray(candidate.records) ? candidate.records.flatMap((record2) => sessionrecordvalid(record2) ? [record2] : []) : [];
|
|
1499
|
+
if (records.length === 0) return void 0;
|
|
1500
|
+
if (!Array.isArray(candidate.recordids) || candidate.recordids.length !== records.length || !candidate.recordids.every((id, index) => id === records[index]?.id)) return void 0;
|
|
1501
|
+
const bytesize = typeof candidate.bytesize === "number" && Number.isFinite(candidate.bytesize) ? candidate.bytesize : -1;
|
|
1502
|
+
if (bytesize < 0) return void 0;
|
|
1503
|
+
const checksum = typeof candidate.checksum === "string" ? candidate.checksum : "";
|
|
1504
|
+
if (checksum !== checksumtext(`${sessionfileversion}:${candidate.recordids.join(",")}:${bytesize}`)) return void 0;
|
|
1505
|
+
return { formatversion: sessionfileversion, records, recordids: candidate.recordids, bytesize, checksum, exportedat: typeof candidate.exportedat === "number" && Number.isFinite(candidate.exportedat) ? candidate.exportedat : 0 };
|
|
1506
|
+
}
|
|
1507
|
+
function sessionrecordvalid(value) {
|
|
1508
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1509
|
+
const candidate = value;
|
|
1510
|
+
if (typeof candidate.id !== "string" || !candidate.id.trim()) return false;
|
|
1511
|
+
if (typeof candidate.name !== "string" || !candidate.name.trim()) return false;
|
|
1512
|
+
if (typeof candidate.createdat !== "number" || !Number.isFinite(candidate.createdat)) return false;
|
|
1513
|
+
if (!Array.isArray(candidate.tabs) || !candidate.tabs.every((tab) => sessiontabof(tab) !== void 0)) return false;
|
|
1514
|
+
if (!Array.isArray(candidate.captures) || !candidate.captures.every((id) => typeof id === "string")) return false;
|
|
1515
|
+
if (!Array.isArray(candidate.tags) || !candidate.tags.every((tag) => typeof tag === "string")) return false;
|
|
1516
|
+
return true;
|
|
1517
|
+
}
|
|
1518
|
+
function expiresessions(records, retention, now) {
|
|
1519
|
+
if (retention === void 0 || !Number.isFinite(retention)) return records;
|
|
1520
|
+
return records.map((record2) => {
|
|
1521
|
+
if (record2.sectionsexpired || now - record2.createdat < retention) return record2;
|
|
1522
|
+
return { id: record2.id, name: record2.name, createdat: record2.createdat, tabs: [], captures: record2.captures, storage: [], cookies: [], ...record2.folder !== void 0 ? { folder: record2.folder } : {}, tags: record2.tags, ...record2.auto === true ? { auto: true } : {}, ...record2.restoredat !== void 0 ? { restoredat: record2.restoredat } : {}, sectionsexpired: true };
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
function filteredsessions(records, filter) {
|
|
1526
|
+
return records.filter((record2) => {
|
|
1527
|
+
if (filter.name !== void 0 && !record2.name.toLowerCase().includes(filter.name.toLowerCase())) return false;
|
|
1528
|
+
if (filter.folder !== void 0 && record2.folder !== filter.folder) return false;
|
|
1529
|
+
if (filter.from !== void 0 && record2.createdat < filter.from) return false;
|
|
1530
|
+
if (filter.to !== void 0 && record2.createdat > filter.to) return false;
|
|
1531
|
+
return true;
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
function crashinterrupted(state, plansteps, now) {
|
|
1535
|
+
if (!state) return void 0;
|
|
1536
|
+
if (state.stepcursor >= plansteps) return state;
|
|
1537
|
+
return { ...state, interrupted: true, crashat: state.crashat ?? now };
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1334
1540
|
// memory.ts
|
|
1335
1541
|
var sessionmemory = class {
|
|
1336
1542
|
constructor(adapter) {
|
|
@@ -2778,6 +2984,170 @@ var sessionmemory = class {
|
|
|
2778
2984
|
async getlocationconsents() {
|
|
2779
2985
|
return await this.adapter.get("locationconsents") ?? [];
|
|
2780
2986
|
}
|
|
2987
|
+
/** Returns the persisted task state checkpoint of one run so the run resumes after a service worker restart. */
|
|
2988
|
+
async gettaskstate(runid) {
|
|
2989
|
+
return this.adapter.get(`taskstate${runid}`);
|
|
2990
|
+
}
|
|
2991
|
+
/** Persists one task state checkpoint per run with its corruption checksum. */
|
|
2992
|
+
async settaskstate(state) {
|
|
2993
|
+
return this.adapter.set(`taskstate${state.runid}`, state);
|
|
2994
|
+
}
|
|
2995
|
+
/** Returns the session event history with timestamps, newest first. */
|
|
2996
|
+
async getsessionevents() {
|
|
2997
|
+
return await this.adapter.get("sessionevents") ?? [];
|
|
2998
|
+
}
|
|
2999
|
+
/** Records one session event of the run with its timestamp and detail. */
|
|
3000
|
+
async addsessionevent(event) {
|
|
3001
|
+
const records = await this.getsessionevents();
|
|
3002
|
+
await this.adapter.set("sessionevents", [event, ...records]);
|
|
3003
|
+
}
|
|
3004
|
+
/** Returns every saved session record with its sections, newest first. */
|
|
3005
|
+
async getsessionrecords() {
|
|
3006
|
+
return await this.adapter.get("sessionrecords") ?? [];
|
|
3007
|
+
}
|
|
3008
|
+
/** Adds one saved session record to the library. */
|
|
3009
|
+
async addsessionrecord(record2) {
|
|
3010
|
+
const records = await this.getsessionrecords();
|
|
3011
|
+
await this.adapter.set("sessionrecords", [record2, ...records]);
|
|
3012
|
+
}
|
|
3013
|
+
/** Replaces one saved session record by its id after a filing or restore touches it. */
|
|
3014
|
+
async updatesessionrecord(record2) {
|
|
3015
|
+
const records = await this.getsessionrecords();
|
|
3016
|
+
await this.adapter.set("sessionrecords", records.map((item) => item.id === record2.id ? record2 : item));
|
|
3017
|
+
}
|
|
3018
|
+
/** Lists saved sessions filtered by name substring, folder and time window; the filter stays a user choice with no result cap. */
|
|
3019
|
+
async listsessions(filter) {
|
|
3020
|
+
return filteredsessions(await this.getsessionrecords(), filter);
|
|
3021
|
+
}
|
|
3022
|
+
/** Returns one saved session with every section; an expired record carries its metadata only. */
|
|
3023
|
+
async getsessionrecord(id) {
|
|
3024
|
+
return (await this.getsessionrecords()).find((record2) => record2.id === id);
|
|
3025
|
+
}
|
|
3026
|
+
/** Runs the reviewed search query across every stored session and returns the matches with their session ids and time windows. */
|
|
3027
|
+
async searchmemory(query) {
|
|
3028
|
+
return searchsessionrecords(query, await this.getsessionrecords());
|
|
3029
|
+
}
|
|
3030
|
+
/** Returns the folder tree of the session library. */
|
|
3031
|
+
async getsessionfolders() {
|
|
3032
|
+
return await this.adapter.get("sessionfolders") ?? [];
|
|
3033
|
+
}
|
|
3034
|
+
/** Replaces the folder tree after a reviewed filing adds or moves one folder. */
|
|
3035
|
+
async setsessionfolders(folders) {
|
|
3036
|
+
return this.adapter.set("sessionfolders", folders);
|
|
3037
|
+
}
|
|
3038
|
+
/** Returns every stored session diff result, newest first. */
|
|
3039
|
+
async getsessiondiffs() {
|
|
3040
|
+
return await this.adapter.get("sessiondiffs") ?? [];
|
|
3041
|
+
}
|
|
3042
|
+
/** Stores one session diff result for later review. */
|
|
3043
|
+
async addsessiondiff(diff) {
|
|
3044
|
+
const records = await this.getsessiondiffs();
|
|
3045
|
+
await this.adapter.set("sessiondiffs", [diff, ...records]);
|
|
3046
|
+
}
|
|
3047
|
+
/** Returns the persisted auto snapshot state with the reviewed interval, the last snapshot time and the snapshot count. */
|
|
3048
|
+
async getautosnapshot() {
|
|
3049
|
+
return await this.adapter.get("autosnapshot") ?? void 0;
|
|
3050
|
+
}
|
|
3051
|
+
/** Stores the auto snapshot state of the reviewed interval. */
|
|
3052
|
+
async setautosnapshot(state) {
|
|
3053
|
+
return this.adapter.set("autosnapshot", state);
|
|
3054
|
+
}
|
|
3055
|
+
/** Clears the auto snapshot interval so on demand captures stay the only source of records. */
|
|
3056
|
+
async clearautosnapshot() {
|
|
3057
|
+
return this.adapter.set("autosnapshot", null);
|
|
3058
|
+
}
|
|
3059
|
+
/** Expires the heavy sections of saved sessions after the reviewed retention window while the record metadata survives. */
|
|
3060
|
+
async applysessionexpiry(retention, now) {
|
|
3061
|
+
const records = expiresessions(await this.getsessionrecords(), retention, now);
|
|
3062
|
+
await this.adapter.set("sessionrecords", records);
|
|
3063
|
+
return records;
|
|
3064
|
+
}
|
|
3065
|
+
/** Returns the crash marker of a run interrupted by a browser restart. */
|
|
3066
|
+
async getcrashflag() {
|
|
3067
|
+
return await this.adapter.get("crashed") ?? false;
|
|
3068
|
+
}
|
|
3069
|
+
/** Sets the crash marker so the sessions view offers the crash restore inside the consent model. */
|
|
3070
|
+
async setcrashflag(value) {
|
|
3071
|
+
return this.adapter.set("crashed", value);
|
|
3072
|
+
}
|
|
3073
|
+
/** Stores one composed workflow record version with its timestamp; re-composing the same version replaces it while older versions survive for the audit trail. */
|
|
3074
|
+
async addworkflowrecord(record2) {
|
|
3075
|
+
const records = await this.getworkflowrecordversions();
|
|
3076
|
+
const remaining = records.filter((entry) => !(entry.id === record2.id && entry.version === record2.version));
|
|
3077
|
+
await this.adapter.set("workflowrecords", [record2, ...remaining]);
|
|
3078
|
+
}
|
|
3079
|
+
/** Returns every stored workflow record version, newest first. */
|
|
3080
|
+
async getworkflowrecordversions() {
|
|
3081
|
+
return await this.adapter.get("workflowrecords") ?? [];
|
|
3082
|
+
}
|
|
3083
|
+
/** Returns the latest stored version of one workflow record. */
|
|
3084
|
+
async getworkflowrecord(id) {
|
|
3085
|
+
return (await this.getworkflowrecordversions()).find((entry) => entry.id === id);
|
|
3086
|
+
}
|
|
3087
|
+
/** Lists the saved workflow records, the latest version of each, newest first. */
|
|
3088
|
+
async listworkflows() {
|
|
3089
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3090
|
+
const latest = [];
|
|
3091
|
+
for (const entry of await this.getworkflowrecordversions()) {
|
|
3092
|
+
if (seen.has(entry.id)) continue;
|
|
3093
|
+
seen.add(entry.id);
|
|
3094
|
+
latest.push(entry);
|
|
3095
|
+
}
|
|
3096
|
+
return latest;
|
|
3097
|
+
}
|
|
3098
|
+
/** Stores one workflow run with its state transition; a run replace keeps the full runlog of the same id. */
|
|
3099
|
+
async setworkflowrun(run) {
|
|
3100
|
+
const runs = await this.listworkflowruns();
|
|
3101
|
+
const remaining = runs.filter((entry) => entry.id !== run.id);
|
|
3102
|
+
await this.adapter.set("workflowruns", [run, ...remaining]);
|
|
3103
|
+
}
|
|
3104
|
+
/** Returns every stored workflow run, newest first. */
|
|
3105
|
+
async listworkflowruns() {
|
|
3106
|
+
return await this.adapter.get("workflowruns") ?? [];
|
|
3107
|
+
}
|
|
3108
|
+
/** Returns one run with its full step outcome list so the panel shows the timeline after and during a run. */
|
|
3109
|
+
async getrun(id) {
|
|
3110
|
+
const run = (await this.listworkflowruns()).find((entry) => entry.id === id);
|
|
3111
|
+
if (!run) return void 0;
|
|
3112
|
+
return { run, log: await this.getrunlog(id) };
|
|
3113
|
+
}
|
|
3114
|
+
/** Records one runlog entry of a run; the runlog retention window is a user setting and an absent window keeps every entry. */
|
|
3115
|
+
async addrunlogentry(runid, entry) {
|
|
3116
|
+
const entries = await this.getrunlog(runid);
|
|
3117
|
+
const combined = [...entries, entry];
|
|
3118
|
+
const retention = (await this.getsettings())?.runlogretention;
|
|
3119
|
+
await this.adapter.set(`runlog${runid}`, retention === void 0 ? combined : combined.slice(-retention));
|
|
3120
|
+
}
|
|
3121
|
+
/** Returns the runlog of one run, oldest first. */
|
|
3122
|
+
async getrunlog(runid) {
|
|
3123
|
+
return await this.adapter.get(`runlog${runid}`) ?? [];
|
|
3124
|
+
}
|
|
3125
|
+
/** Stores the variable values per scope of one run for inspection after the run. */
|
|
3126
|
+
async setrunscopes(runid, scopes) {
|
|
3127
|
+
return this.adapter.set(`runscopes${runid}`, scopes);
|
|
3128
|
+
}
|
|
3129
|
+
/** Returns the variable scopes of one run, oldest first. */
|
|
3130
|
+
async getrunscopes(runid) {
|
|
3131
|
+
return await this.adapter.get(`runscopes${runid}`) ?? [];
|
|
3132
|
+
}
|
|
3133
|
+
/** Records one provenance entry of a run: an expression result or a regex capture with its name, value and time. */
|
|
3134
|
+
async addworkflowprovenance(runid, entry) {
|
|
3135
|
+
const entries = await this.getworkflowprovenance(runid);
|
|
3136
|
+
await this.adapter.set(`workflowprovenance${runid}`, [...entries, entry]);
|
|
3137
|
+
}
|
|
3138
|
+
/** Returns every provenance entry of one run, oldest first. */
|
|
3139
|
+
async getworkflowprovenance(runid) {
|
|
3140
|
+
return await this.adapter.get(`workflowprovenance${runid}`) ?? [];
|
|
3141
|
+
}
|
|
3142
|
+
/** Stores one shareable step template under its unique name. */
|
|
3143
|
+
async addsteptemplate(template) {
|
|
3144
|
+
const templates = (await this.getsteptemplates()).filter((entry) => entry.name !== template.name);
|
|
3145
|
+
await this.adapter.set("steptemplates", [template, ...templates]);
|
|
3146
|
+
}
|
|
3147
|
+
/** Returns every stored step template, newest first. */
|
|
3148
|
+
async getsteptemplates() {
|
|
3149
|
+
return await this.adapter.get("steptemplates") ?? [];
|
|
3150
|
+
}
|
|
2781
3151
|
};
|
|
2782
3152
|
function mediakindof(record2) {
|
|
2783
3153
|
if ("pages" in record2) return "pdf";
|
|
@@ -3314,6 +3684,511 @@ function extractvalues(body, paths) {
|
|
|
3314
3684
|
return fields.map((field) => ({ path: field.path, ...field.value !== void 0 ? { value: field.value } : {}, ...field.missing ? { missing: true } : {} }));
|
|
3315
3685
|
}
|
|
3316
3686
|
|
|
3687
|
+
// workflow.ts
|
|
3688
|
+
var workflowkinds = ["composeworkflow", "savetemplate", "runworkflow", "dryrun", "delay", "waitelement", "compute", "extractvars"];
|
|
3689
|
+
function workflowstepof(value) {
|
|
3690
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3691
|
+
const candidate = value;
|
|
3692
|
+
if (typeof candidate.id !== "string" || !candidate.id.trim()) return void 0;
|
|
3693
|
+
if (typeof candidate.kind !== "string" || !/^[a-z]+$/.test(candidate.kind)) return void 0;
|
|
3694
|
+
if (typeof candidate.label !== "string" || !candidate.label.trim()) return void 0;
|
|
3695
|
+
if (candidate.target !== void 0 && (typeof candidate.target !== "string" || !candidate.target)) return void 0;
|
|
3696
|
+
if (candidate.value !== void 0 && typeof candidate.value !== "string") return void 0;
|
|
3697
|
+
if (candidate.options !== void 0 && typeof candidate.options !== "string") return void 0;
|
|
3698
|
+
const bindings = Array.isArray(candidate.bindings) ? candidate.bindings.flatMap((binding) => bindingof(binding) !== void 0 ? [bindingof(binding)] : []) : void 0;
|
|
3699
|
+
if (candidate.bindings !== void 0 && bindings === void 0) return void 0;
|
|
3700
|
+
if (Array.isArray(candidate.bindings) && bindings !== void 0 && bindings.length !== candidate.bindings.length) return void 0;
|
|
3701
|
+
const expression = candidate.expression === void 0 ? void 0 : expressionof(candidate.expression);
|
|
3702
|
+
if (candidate.expression !== void 0 && expression === void 0) return void 0;
|
|
3703
|
+
const extract = candidate.extract === void 0 ? void 0 : regexruleof(candidate.extract);
|
|
3704
|
+
if (candidate.extract !== void 0 && extract === void 0) return void 0;
|
|
3705
|
+
return { id: candidate.id, kind: candidate.kind, label: candidate.label, ...candidate.target !== void 0 ? { target: candidate.target } : {}, ...candidate.value !== void 0 ? { value: candidate.value } : {}, ...candidate.options !== void 0 ? { options: candidate.options } : {}, ...bindings !== void 0 && bindings.length > 0 ? { bindings } : {}, ...expression !== void 0 ? { expression } : {}, ...extract !== void 0 ? { extract } : {} };
|
|
3706
|
+
}
|
|
3707
|
+
function blockinvocationof(value) {
|
|
3708
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3709
|
+
const candidate = value;
|
|
3710
|
+
if (typeof candidate.block !== "string" || !candidate.block.trim()) return void 0;
|
|
3711
|
+
if (typeof candidate.label !== "string" || !candidate.label.trim()) return void 0;
|
|
3712
|
+
return { block: candidate.block, label: candidate.label };
|
|
3713
|
+
}
|
|
3714
|
+
function workflowblockof(value) {
|
|
3715
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3716
|
+
const candidate = value;
|
|
3717
|
+
if (typeof candidate.name !== "string" || !/^[a-z][a-z0-9]*$/.test(candidate.name)) return void 0;
|
|
3718
|
+
if (typeof candidate.label !== "string" || !candidate.label.trim()) return void 0;
|
|
3719
|
+
if (!Array.isArray(candidate.steps)) return void 0;
|
|
3720
|
+
const steps = [];
|
|
3721
|
+
for (const entry of candidate.steps) {
|
|
3722
|
+
const step = workflowstepof(entry);
|
|
3723
|
+
if (step) {
|
|
3724
|
+
steps.push(step);
|
|
3725
|
+
continue;
|
|
3726
|
+
}
|
|
3727
|
+
const invocation = blockinvocationof(entry);
|
|
3728
|
+
if (invocation) {
|
|
3729
|
+
steps.push(invocation);
|
|
3730
|
+
continue;
|
|
3731
|
+
}
|
|
3732
|
+
return void 0;
|
|
3733
|
+
}
|
|
3734
|
+
return { name: candidate.name, label: candidate.label, steps };
|
|
3735
|
+
}
|
|
3736
|
+
function steptemplateof(value) {
|
|
3737
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3738
|
+
const candidate = value;
|
|
3739
|
+
if (typeof candidate.id !== "string" || !candidate.id.trim()) return void 0;
|
|
3740
|
+
if (typeof candidate.name !== "string" || !candidate.name.trim()) return void 0;
|
|
3741
|
+
if (typeof candidate.origin !== "string" || !candidate.origin.trim()) return void 0;
|
|
3742
|
+
const step = workflowstepof(candidate.step);
|
|
3743
|
+
if (!step) return void 0;
|
|
3744
|
+
if (typeof candidate.sharedat !== "number" || !Number.isFinite(candidate.sharedat)) return void 0;
|
|
3745
|
+
return { id: candidate.id, name: candidate.name, origin: candidate.origin, step, sharedat: candidate.sharedat };
|
|
3746
|
+
}
|
|
3747
|
+
function bindingof(value) {
|
|
3748
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3749
|
+
const candidate = value;
|
|
3750
|
+
if (typeof candidate.variable !== "string" || !/^[a-z][a-z0-9]*$/.test(candidate.variable)) return void 0;
|
|
3751
|
+
if (!variablekinds.includes(candidate.kind)) return void 0;
|
|
3752
|
+
if (typeof candidate.stepid !== "string" || !candidate.stepid.trim()) return void 0;
|
|
3753
|
+
if (candidate.path !== void 0 && (typeof candidate.path !== "string" || !candidate.path.trim())) return void 0;
|
|
3754
|
+
return { variable: candidate.variable, kind: candidate.kind, stepid: candidate.stepid, ...candidate.path !== void 0 ? { path: candidate.path } : {} };
|
|
3755
|
+
}
|
|
3756
|
+
var variablekinds = ["string", "number", "boolean", "list", "element"];
|
|
3757
|
+
var expressionoperators = ["add", "subtract", "multiply", "divide", "modulo", "equal", "notequal", "less", "greater", "lessequal", "greaterequal", "and", "or", "not", "concat", "contains", "length"];
|
|
3758
|
+
function expressionof(value) {
|
|
3759
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3760
|
+
const candidate = value;
|
|
3761
|
+
const left = operandof(candidate.left);
|
|
3762
|
+
if (!left) return void 0;
|
|
3763
|
+
const right = candidate.right === void 0 ? void 0 : operandof(candidate.right);
|
|
3764
|
+
if (candidate.right !== void 0 && right === void 0) return void 0;
|
|
3765
|
+
if (typeof candidate.operator !== "string" || !expressionoperators.includes(candidate.operator)) return void 0;
|
|
3766
|
+
if (typeof candidate.result !== "string" || !/^[a-z][a-z0-9]*$/.test(candidate.result)) return void 0;
|
|
3767
|
+
if (!variablekinds.includes(candidate.resultkind)) return void 0;
|
|
3768
|
+
return { left, ...right !== void 0 ? { right } : {}, operator: candidate.operator, result: candidate.result, resultkind: candidate.resultkind };
|
|
3769
|
+
}
|
|
3770
|
+
function operandof(value) {
|
|
3771
|
+
if (value === void 0) return void 0;
|
|
3772
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return { literal: value };
|
|
3773
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3774
|
+
const candidate = value;
|
|
3775
|
+
if (typeof candidate.ref === "string" && /^[a-z][a-z0-9]*$/.test(candidate.ref)) return { ref: candidate.ref };
|
|
3776
|
+
if (typeof candidate.literal === "string" || typeof candidate.literal === "number" || typeof candidate.literal === "boolean") return { literal: candidate.literal };
|
|
3777
|
+
return void 0;
|
|
3778
|
+
}
|
|
3779
|
+
function regexruleof(value) {
|
|
3780
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3781
|
+
const candidate = value;
|
|
3782
|
+
if (typeof candidate.pattern !== "string" || !candidate.pattern.trim()) return void 0;
|
|
3783
|
+
if (typeof candidate.flags !== "string" || !/^[dgimsuvy]*$/.test(candidate.flags)) return void 0;
|
|
3784
|
+
const groups = Array.isArray(candidate.groups) ? candidate.groups.flatMap((group) => typeof group === "string" && /^[a-z][a-z0-9]*$/.test(group) ? [group] : []) : [];
|
|
3785
|
+
if (candidate.groups !== void 0 && groups.length !== candidate.groups.length) return void 0;
|
|
3786
|
+
return { pattern: candidate.pattern, flags: candidate.flags, groups };
|
|
3787
|
+
}
|
|
3788
|
+
function expandblocks(steps, blocks) {
|
|
3789
|
+
const byname = new Map(blocks.map((block) => [block.name, block]));
|
|
3790
|
+
const expanded = [];
|
|
3791
|
+
const visit = (entries, path, inside) => {
|
|
3792
|
+
for (const entry of entries) {
|
|
3793
|
+
if ("kind" in entry && "label" in entry && !("block" in entry)) {
|
|
3794
|
+
expanded.push(inside === void 0 ? entry : { ...entry, block: inside });
|
|
3795
|
+
continue;
|
|
3796
|
+
}
|
|
3797
|
+
const invocation = blockinvocationof(entry);
|
|
3798
|
+
if (!invocation) throw new Error("The step list entry is neither a reviewed step nor a block invocation.");
|
|
3799
|
+
if (path.includes(invocation.block)) throw new Error(`The block ${invocation.block} recurs inside itself and cannot expand.`);
|
|
3800
|
+
const block = byname.get(invocation.block);
|
|
3801
|
+
if (!block) throw new Error(`The block ${invocation.block} is not defined in the workflow.`);
|
|
3802
|
+
visit(block.steps, [...path, invocation.block], invocation.block);
|
|
3803
|
+
}
|
|
3804
|
+
};
|
|
3805
|
+
visit(steps, [], void 0);
|
|
3806
|
+
if (expanded.length === 0) throw new Error("A workflow needs at least one executable step after block expansion.");
|
|
3807
|
+
return expanded;
|
|
3808
|
+
}
|
|
3809
|
+
function composeworkflow(input) {
|
|
3810
|
+
if (typeof input.name !== "string" || !input.name.trim()) throw new Error("The workflow name must be a non-empty string.");
|
|
3811
|
+
if (typeof input.version !== "number" || !Number.isInteger(input.version) || input.version < 1) throw new Error("The workflow version must be a positive integer.");
|
|
3812
|
+
if (!Array.isArray(input.origins) || input.origins.length === 0) throw new Error("A workflow needs at least one granted HTTPS origin.");
|
|
3813
|
+
const origins = input.origins.map((origin) => {
|
|
3814
|
+
try {
|
|
3815
|
+
return new URL(origin).origin;
|
|
3816
|
+
} catch {
|
|
3817
|
+
throw new Error(`The workflow origin ${origin} is not a valid url.`);
|
|
3818
|
+
}
|
|
3819
|
+
});
|
|
3820
|
+
if (origins.some((origin) => !origin.startsWith("https://"))) throw new Error("Workflow origins must use HTTPS.");
|
|
3821
|
+
const blocks = input.blocks ?? [];
|
|
3822
|
+
if (blocks.some((block, index) => blocks.findIndex((other) => other.name === block.name) !== index)) throw new Error("Workflow block names must stay unique.");
|
|
3823
|
+
for (const entry of input.steps) {
|
|
3824
|
+
if ("kind" in entry && "label" in entry && !("block" in entry)) {
|
|
3825
|
+
if (input.kindallowed && !input.kindallowed(entry.kind)) throw new Error(`The workflow step kind ${entry.kind} is not a reviewed action kind.`);
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
3828
|
+
for (const block of blocks) for (const entry of block.steps) {
|
|
3829
|
+
if ("kind" in entry && "label" in entry && !("block" in entry) && input.kindallowed && !input.kindallowed(entry.kind)) throw new Error(`The workflow step kind ${entry.kind} inside block ${block.name} is not a reviewed action kind.`);
|
|
3830
|
+
}
|
|
3831
|
+
const steps = expandblocks(input.steps, blocks);
|
|
3832
|
+
for (const step of steps) {
|
|
3833
|
+
if (input.kindallowed && !input.kindallowed(step.kind)) throw new Error(`The workflow step kind ${step.kind} is not a reviewed action kind.`);
|
|
3834
|
+
if (step.bindings) for (const binding of step.bindings) {
|
|
3835
|
+
if (!steps.some((other) => other.id === binding.stepid)) throw new Error(`The binding of ${binding.variable} references the unknown step ${binding.stepid}.`);
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
const riskof = input.riskof ?? (() => "sensitive");
|
|
3839
|
+
const risk = steps.some((step) => riskof(step.kind) === "sensitive") ? "sensitive" : steps.some((step) => riskof(step.kind) === "interaction") ? "interaction" : "read";
|
|
3840
|
+
const record2 = { id: input.id ?? crypto.randomUUID(), name: input.name, version: input.version, origins: [...new Set(origins)], steps, blocks, risk, createdat: input.now };
|
|
3841
|
+
return deepfreeze(record2);
|
|
3842
|
+
}
|
|
3843
|
+
function deepfreeze(record2) {
|
|
3844
|
+
for (const step of record2.steps) Object.freeze(step);
|
|
3845
|
+
for (const block of record2.blocks) for (const entry of block.steps) if ("kind" in entry && "label" in entry && !("block" in entry)) Object.freeze(entry);
|
|
3846
|
+
Object.freeze(record2.blocks);
|
|
3847
|
+
Object.freeze(record2.steps);
|
|
3848
|
+
return Object.freeze(record2);
|
|
3849
|
+
}
|
|
3850
|
+
function validateworkflow(record2, options) {
|
|
3851
|
+
if (record2.steps.length === 0) return { allowed: false, reason: "A workflow needs at least one reviewed step." };
|
|
3852
|
+
const defined = new Set(options?.inputs ?? []);
|
|
3853
|
+
const byid = new Map(record2.steps.map((step, index) => [step.id, { step, index }]));
|
|
3854
|
+
for (let index = 0; index < record2.steps.length; index += 1) {
|
|
3855
|
+
const step = record2.steps[index];
|
|
3856
|
+
if (options?.kindallowed && !options.kindallowed(step.kind)) return { allowed: false, reason: `The workflow step kind ${step.kind} is not a reviewed action kind.` };
|
|
3857
|
+
if (step.bindings) for (const binding of step.bindings) {
|
|
3858
|
+
const source = byid.get(binding.stepid);
|
|
3859
|
+
if (!source) return { allowed: false, reason: `The binding of ${binding.variable} references the unknown step ${binding.stepid}.` };
|
|
3860
|
+
if (source.index >= index) return { allowed: false, reason: `The binding of ${binding.variable} must link an earlier step than ${step.id}.` };
|
|
3861
|
+
defined.add(binding.variable);
|
|
3862
|
+
}
|
|
3863
|
+
if (step.expression) {
|
|
3864
|
+
for (const operand of [step.expression.left, step.expression.right]) {
|
|
3865
|
+
if (operand?.ref && !defined.has(operand.ref)) return { allowed: false, reason: `The expression of step ${step.id} references the undefined variable ${operand.ref}.` };
|
|
3866
|
+
}
|
|
3867
|
+
defined.add(step.expression.result);
|
|
3868
|
+
}
|
|
3869
|
+
if (step.extract) for (const group of step.extract.groups) defined.add(group);
|
|
3870
|
+
}
|
|
3871
|
+
return { allowed: true };
|
|
3872
|
+
}
|
|
3873
|
+
function pushscope(scopes, name, parent) {
|
|
3874
|
+
return [...scopes, { name, variables: [], ...parent !== void 0 ? { parent } : {} }];
|
|
3875
|
+
}
|
|
3876
|
+
function popscope(scopes) {
|
|
3877
|
+
if (scopes.length === 0) return scopes;
|
|
3878
|
+
return scopes.slice(0, -1);
|
|
3879
|
+
}
|
|
3880
|
+
function resolvevariable(scopes, name) {
|
|
3881
|
+
for (let index = scopes.length - 1; index >= 0; index -= 1) {
|
|
3882
|
+
const scope = scopes[index];
|
|
3883
|
+
const found = scope.variables.find((variable) => variable.name === name);
|
|
3884
|
+
if (found) return found;
|
|
3885
|
+
if (scope.parent === void 0) continue;
|
|
3886
|
+
const parentindex = scopes.findIndex((candidate) => candidate.name === scope.parent);
|
|
3887
|
+
if (parentindex >= 0 && parentindex < index) {
|
|
3888
|
+
const inherited = resolvevariable([scopes[parentindex]], name);
|
|
3889
|
+
if (inherited) return inherited;
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
return void 0;
|
|
3893
|
+
}
|
|
3894
|
+
function setvariable(scopes, name, kind, value, now) {
|
|
3895
|
+
if (scopes.length === 0) scopes = [{ name: "root", variables: [] }];
|
|
3896
|
+
const target = scopes[scopes.length - 1];
|
|
3897
|
+
const variables = [...target.variables.filter((variable) => variable.name !== name), { name, kind, value, setat: now }];
|
|
3898
|
+
return [...scopes.slice(0, -1), { ...target, variables }];
|
|
3899
|
+
}
|
|
3900
|
+
function coercevariable(value, kind) {
|
|
3901
|
+
if (kind === "number") {
|
|
3902
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : NaN;
|
|
3903
|
+
if (!Number.isFinite(parsed)) throw new Error("The bound value is not a finite number.");
|
|
3904
|
+
return parsed;
|
|
3905
|
+
}
|
|
3906
|
+
if (kind === "boolean") {
|
|
3907
|
+
if (typeof value === "boolean") return value;
|
|
3908
|
+
if (value === "true") return true;
|
|
3909
|
+
if (value === "false") return false;
|
|
3910
|
+
throw new Error("The bound value is not a boolean.");
|
|
3911
|
+
}
|
|
3912
|
+
if (kind === "list") {
|
|
3913
|
+
if (Array.isArray(value)) return value.map((item) => String(item));
|
|
3914
|
+
if (typeof value === "string") return value.length === 0 ? [] : value.split(",");
|
|
3915
|
+
throw new Error("The bound value is not a list.");
|
|
3916
|
+
}
|
|
3917
|
+
if (kind === "element") {
|
|
3918
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
3919
|
+
throw new Error("The bound value is not an element reference.");
|
|
3920
|
+
}
|
|
3921
|
+
if (typeof value === "string") return value;
|
|
3922
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
3923
|
+
throw new Error("The bound value is not a string.");
|
|
3924
|
+
}
|
|
3925
|
+
function outcomedetail(outcome, path) {
|
|
3926
|
+
if (!path) return outcome.summary;
|
|
3927
|
+
let current = outcome.details ?? {};
|
|
3928
|
+
for (const segment of path.split(".")) {
|
|
3929
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) return void 0;
|
|
3930
|
+
current = current[segment];
|
|
3931
|
+
}
|
|
3932
|
+
return current;
|
|
3933
|
+
}
|
|
3934
|
+
function bindvariables(scopes, bindings, outputs, now) {
|
|
3935
|
+
let current = scopes;
|
|
3936
|
+
const produced = [];
|
|
3937
|
+
for (const binding of bindings) {
|
|
3938
|
+
const outcome = outputs[binding.stepid];
|
|
3939
|
+
if (!outcome) continue;
|
|
3940
|
+
const raw = outcomedetail(outcome, binding.path);
|
|
3941
|
+
if (raw === void 0) throw new Error(`The binding of ${binding.variable} found no value at ${binding.path ?? "the summary"} of step ${binding.stepid}.`);
|
|
3942
|
+
current = setvariable(current, binding.variable, binding.kind, coercevariable(raw, binding.kind), now);
|
|
3943
|
+
produced.push(binding.variable);
|
|
3944
|
+
}
|
|
3945
|
+
return { scopes: current, produced };
|
|
3946
|
+
}
|
|
3947
|
+
function operandvalue(operand, scopes) {
|
|
3948
|
+
if (operand.ref !== void 0) {
|
|
3949
|
+
const resolved = resolvevariable(scopes, operand.ref);
|
|
3950
|
+
if (!resolved) throw new Error(`The expression references the undefined variable ${operand.ref}.`);
|
|
3951
|
+
return resolved.value;
|
|
3952
|
+
}
|
|
3953
|
+
if (operand.literal === void 0) throw new Error("The expression operand needs a variable reference or a literal.");
|
|
3954
|
+
return operand.literal;
|
|
3955
|
+
}
|
|
3956
|
+
function expressioneval(expression, scopes) {
|
|
3957
|
+
const left = operandvalue(expression.left, scopes);
|
|
3958
|
+
const right = expression.right === void 0 ? void 0 : operandvalue(expression.right, scopes);
|
|
3959
|
+
const operand = (value) => {
|
|
3960
|
+
if (Array.isArray(value)) throw new Error("The expression operand is a list and needs the contains or length operator.");
|
|
3961
|
+
if (value === void 0) throw new Error("The expression operand is missing.");
|
|
3962
|
+
return value;
|
|
3963
|
+
};
|
|
3964
|
+
const numbervalue = (value) => {
|
|
3965
|
+
const primitive = operand(value);
|
|
3966
|
+
if (typeof primitive === "number") return primitive;
|
|
3967
|
+
if (typeof primitive === "string" && primitive.trim() !== "") {
|
|
3968
|
+
const parsed = Number(primitive);
|
|
3969
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
3970
|
+
}
|
|
3971
|
+
throw new Error("The arithmetic operand is not a number.");
|
|
3972
|
+
};
|
|
3973
|
+
const booleanvalue = (value) => {
|
|
3974
|
+
const primitive = operand(value);
|
|
3975
|
+
if (typeof primitive === "boolean") return primitive;
|
|
3976
|
+
throw new Error("The logic operand is not a boolean.");
|
|
3977
|
+
};
|
|
3978
|
+
const stringvalue = (value) => {
|
|
3979
|
+
const primitive = operand(value);
|
|
3980
|
+
if (typeof primitive === "string") return primitive;
|
|
3981
|
+
if (typeof primitive === "number" || typeof primitive === "boolean") return String(primitive);
|
|
3982
|
+
throw new Error("The text operand is not a string.");
|
|
3983
|
+
};
|
|
3984
|
+
switch (expression.operator) {
|
|
3985
|
+
case "add":
|
|
3986
|
+
return numbervalue(left) + numbervalue(right);
|
|
3987
|
+
case "subtract":
|
|
3988
|
+
return numbervalue(left) - numbervalue(right);
|
|
3989
|
+
case "multiply":
|
|
3990
|
+
return numbervalue(left) * numbervalue(right);
|
|
3991
|
+
case "divide": {
|
|
3992
|
+
const divisor = numbervalue(right);
|
|
3993
|
+
if (divisor === 0) throw new Error("The expression divides by zero.");
|
|
3994
|
+
return numbervalue(left) / divisor;
|
|
3995
|
+
}
|
|
3996
|
+
case "modulo": {
|
|
3997
|
+
const divisor = numbervalue(right);
|
|
3998
|
+
if (divisor === 0) throw new Error("The expression divides by zero.");
|
|
3999
|
+
return numbervalue(left) % divisor;
|
|
4000
|
+
}
|
|
4001
|
+
case "equal":
|
|
4002
|
+
return left === right;
|
|
4003
|
+
case "notequal":
|
|
4004
|
+
return left !== right;
|
|
4005
|
+
case "less":
|
|
4006
|
+
return numbervalue(left) < numbervalue(right);
|
|
4007
|
+
case "greater":
|
|
4008
|
+
return numbervalue(left) > numbervalue(right);
|
|
4009
|
+
case "lessequal":
|
|
4010
|
+
return numbervalue(left) <= numbervalue(right);
|
|
4011
|
+
case "greaterequal":
|
|
4012
|
+
return numbervalue(left) >= numbervalue(right);
|
|
4013
|
+
case "and":
|
|
4014
|
+
return booleanvalue(left) && booleanvalue(right);
|
|
4015
|
+
case "or":
|
|
4016
|
+
return booleanvalue(left) || booleanvalue(right);
|
|
4017
|
+
case "not":
|
|
4018
|
+
return !booleanvalue(left);
|
|
4019
|
+
case "concat":
|
|
4020
|
+
return `${stringvalue(left)}${stringvalue(right)}`;
|
|
4021
|
+
case "contains": {
|
|
4022
|
+
if (Array.isArray(left)) return left.includes(stringvalue(right));
|
|
4023
|
+
return stringvalue(left).includes(stringvalue(right));
|
|
4024
|
+
}
|
|
4025
|
+
case "length": {
|
|
4026
|
+
if (Array.isArray(left)) return left.length;
|
|
4027
|
+
return stringvalue(left).length;
|
|
4028
|
+
}
|
|
4029
|
+
default:
|
|
4030
|
+
throw new Error("The reviewed expression operator is unknown.");
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
4033
|
+
function regexextract(rule, text2, now) {
|
|
4034
|
+
const pattern = new RegExp(rule.pattern, rule.flags);
|
|
4035
|
+
const match = pattern.exec(text2);
|
|
4036
|
+
if (!match) return { matched: false, variables: [] };
|
|
4037
|
+
const variables = [];
|
|
4038
|
+
for (const group of rule.groups) {
|
|
4039
|
+
const value = match.groups?.[group];
|
|
4040
|
+
variables.push({ name: group, kind: "string", value: typeof value === "string" ? value : "", setat: now });
|
|
4041
|
+
}
|
|
4042
|
+
return { matched: true, variables };
|
|
4043
|
+
}
|
|
4044
|
+
function waitelementplan(wait) {
|
|
4045
|
+
if (wait.timeout <= 0 || wait.poll <= 0) return { probes: 1, lastwait: 0 };
|
|
4046
|
+
const probes = Math.floor(wait.timeout / wait.poll) + 1;
|
|
4047
|
+
return { probes, lastwait: wait.timeout % wait.poll };
|
|
4048
|
+
}
|
|
4049
|
+
function delayjitter(delay, seed) {
|
|
4050
|
+
if (delay.jitter <= 0) return Math.max(0, delay.base);
|
|
4051
|
+
const sample = seededrandom(seed);
|
|
4052
|
+
return Math.max(0, delay.base - delay.jitter / 2 + sample * delay.jitter);
|
|
4053
|
+
}
|
|
4054
|
+
function seededrandom(seed) {
|
|
4055
|
+
let state = seed >>> 0;
|
|
4056
|
+
state ^= state >>> 16;
|
|
4057
|
+
state = Math.imul(state, 2246822507);
|
|
4058
|
+
state ^= state >>> 13;
|
|
4059
|
+
state = Math.imul(state, 3266489909);
|
|
4060
|
+
state ^= state >>> 16;
|
|
4061
|
+
state = state >>> 0 || 1;
|
|
4062
|
+
state ^= state << 13;
|
|
4063
|
+
state >>>= 0;
|
|
4064
|
+
state ^= state >> 17;
|
|
4065
|
+
state ^= state << 5;
|
|
4066
|
+
state >>>= 0;
|
|
4067
|
+
return state / 4294967296;
|
|
4068
|
+
}
|
|
4069
|
+
function newworkflowrun(input) {
|
|
4070
|
+
return { id: input.id ?? crypto.randomUUID(), workflowid: input.workflowid, state: "pending", cursor: 0, startedat: input.now, ...input.dryrun === true ? { dryrun: true } : {} };
|
|
4071
|
+
}
|
|
4072
|
+
function pauserun(run, now) {
|
|
4073
|
+
if (run.state !== "running") throw new Error("Only a running workflow can pause.");
|
|
4074
|
+
return { ...run, state: "paused", pausedat: now };
|
|
4075
|
+
}
|
|
4076
|
+
function cancelrun(run, reason, now) {
|
|
4077
|
+
if (run.state === "done" || run.state === "cancelled") return run;
|
|
4078
|
+
return { ...run, state: "cancelled", cancelreason: reason, endedat: now };
|
|
4079
|
+
}
|
|
4080
|
+
function interpolate(text2, scopes) {
|
|
4081
|
+
const consumed = [];
|
|
4082
|
+
const resolved = text2.replace(/\$\{([a-z][a-z0-9]*)\}/g, (_whole, name) => {
|
|
4083
|
+
const variable = resolvevariable(scopes, name);
|
|
4084
|
+
if (!variable) throw new Error(`The step references the undefined variable ${name}.`);
|
|
4085
|
+
consumed.push(name);
|
|
4086
|
+
return Array.isArray(variable.value) ? variable.value.join(",") : String(variable.value);
|
|
4087
|
+
});
|
|
4088
|
+
return { text: resolved, consumed };
|
|
4089
|
+
}
|
|
4090
|
+
function runlogof(step, state, startedat, duration, summary, extra) {
|
|
4091
|
+
return { stepid: step.id, label: step.label, state, startedat, duration, summary, ...extra.block !== void 0 ? { block: extra.block } : {}, ...extra.consumed !== void 0 && extra.consumed.length > 0 ? { consumed: extra.consumed } : {}, ...extra.produced !== void 0 && extra.produced.length > 0 ? { produced: extra.produced } : {}, ...extra.checkpoint === true ? { checkpoint: true } : {}, ...extra.details !== void 0 ? { details: extra.details } : {} };
|
|
4092
|
+
}
|
|
4093
|
+
async function runstep(input) {
|
|
4094
|
+
const startedat = input.now;
|
|
4095
|
+
let scopes = input.scopes;
|
|
4096
|
+
const consumed = [];
|
|
4097
|
+
if (input.step.bindings) {
|
|
4098
|
+
const bound = bindvariables(scopes, input.step.bindings.filter((binding) => input.outputs[binding.stepid] !== void 0), input.outputs, input.now);
|
|
4099
|
+
scopes = bound.scopes;
|
|
4100
|
+
}
|
|
4101
|
+
let produced = [];
|
|
4102
|
+
try {
|
|
4103
|
+
if (input.step.expression) {
|
|
4104
|
+
const value2 = expressioneval(input.step.expression, scopes);
|
|
4105
|
+
scopes = setvariable(scopes, input.step.expression.result, input.step.expression.resultkind, coercevariable(value2, input.step.expression.resultkind), input.now);
|
|
4106
|
+
produced = [...produced, input.step.expression.result];
|
|
4107
|
+
}
|
|
4108
|
+
let stepvalue = input.step.value;
|
|
4109
|
+
if (input.step.extract) {
|
|
4110
|
+
const text2 = stepvalue ?? "";
|
|
4111
|
+
const interpolated = interpolate(text2, scopes);
|
|
4112
|
+
consumed.push(...interpolated.consumed);
|
|
4113
|
+
const extraction = regexextract(input.step.extract, interpolated.text, input.now);
|
|
4114
|
+
if (extraction.matched) {
|
|
4115
|
+
for (const variable of extraction.variables) scopes = setvariable(scopes, variable.name, "string", variable.value, input.now);
|
|
4116
|
+
produced = [...produced, ...extraction.variables.map((variable) => variable.name)];
|
|
4117
|
+
}
|
|
4118
|
+
stepvalue = interpolated.text;
|
|
4119
|
+
}
|
|
4120
|
+
const target = input.step.target !== void 0 ? interpolate(input.step.target, scopes) : void 0;
|
|
4121
|
+
if (target) consumed.push(...target.consumed);
|
|
4122
|
+
const value = stepvalue !== void 0 ? interpolate(stepvalue, scopes) : void 0;
|
|
4123
|
+
if (value) consumed.push(...value.consumed);
|
|
4124
|
+
const options = input.step.options !== void 0 ? interpolate(input.step.options, scopes) : void 0;
|
|
4125
|
+
if (options) consumed.push(...options.consumed);
|
|
4126
|
+
const dispatchable = { ...input.step, ...target !== void 0 ? { target: target.text } : {}, ...value !== void 0 ? { value: value.text } : {}, ...options !== void 0 ? { options: options.text } : {} };
|
|
4127
|
+
const output = await input.execute(dispatchable, { scopes, ...input.block !== void 0 ? { block: input.block } : {} });
|
|
4128
|
+
if (input.step.bindings) {
|
|
4129
|
+
const bound = bindvariables(scopes, input.step.bindings, { ...input.outputs, [input.step.id]: { stepid: input.step.id, ok: output.ok, summary: output.summary, ...output.details !== void 0 ? { details: output.details } : {}, at: input.now } }, input.now);
|
|
4130
|
+
scopes = bound.scopes;
|
|
4131
|
+
produced = [.../* @__PURE__ */ new Set([...produced, ...bound.produced])];
|
|
4132
|
+
}
|
|
4133
|
+
const duration = Date.now() - startedat;
|
|
4134
|
+
return { scopes, log: runlogof(input.step, output.ok ? "done" : "failed", startedat, duration, output.summary, { ...input.block !== void 0 ? { block: input.block } : {}, ...consumed.length > 0 ? { consumed } : {}, ...produced.length > 0 ? { produced } : {}, ...output.details !== void 0 ? { details: output.details } : {}, ...output.ok ? { checkpoint: true } : {} }), output };
|
|
4135
|
+
} catch (error) {
|
|
4136
|
+
const duration = Date.now() - startedat;
|
|
4137
|
+
const summary = error instanceof Error ? error.message : String(error);
|
|
4138
|
+
return { scopes, log: runlogof(input.step, "failed", startedat, duration, summary, { ...input.block !== void 0 ? { block: input.block } : {}, ...consumed.length > 0 ? { consumed } : {} }), output: { ok: false, summary } };
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
async function runworkflow(input) {
|
|
4142
|
+
if (input.gates && !input.gates.sessionactive) throw new Error("The workflow refuses to run outside an approved session.");
|
|
4143
|
+
if (input.gates && !input.gates.planapproved) throw new Error("The workflow refuses to run without the approved plan review.");
|
|
4144
|
+
if (input.gates) for (const origin of input.record.origins) {
|
|
4145
|
+
if (!input.gates.origingranted(origin)) throw new Error(`The workflow origin ${origin} falls outside the session grants.`);
|
|
4146
|
+
}
|
|
4147
|
+
if (input.run.state === "done" || input.run.state === "failed" || input.run.state === "cancelled") throw new Error(`The workflow run is already ${input.run.state}.`);
|
|
4148
|
+
const { pausedat, ...resumed } = input.run;
|
|
4149
|
+
void pausedat;
|
|
4150
|
+
let run = input.run.state === "paused" ? { ...resumed, state: "running" } : { ...input.run, state: "running" };
|
|
4151
|
+
let scopes = input.scopes ?? [{ name: "root", variables: [] }];
|
|
4152
|
+
const log = [...input.log ?? []];
|
|
4153
|
+
const outputs = { ...input.outputs ?? {} };
|
|
4154
|
+
let activeblock;
|
|
4155
|
+
for (let index = run.cursor; index < input.record.steps.length; index += 1) {
|
|
4156
|
+
const step = input.record.steps[index];
|
|
4157
|
+
if (step.block !== void 0 && step.block !== activeblock) {
|
|
4158
|
+
scopes = pushscope(scopes, step.block, scopes[scopes.length - 1].name);
|
|
4159
|
+
activeblock = step.block;
|
|
4160
|
+
} else if (step.block === void 0 && activeblock !== void 0) {
|
|
4161
|
+
while (scopes.length > 1) scopes = popscope(scopes);
|
|
4162
|
+
activeblock = void 0;
|
|
4163
|
+
}
|
|
4164
|
+
const executed = await runstep({ step, scopes, outputs, execute: input.execute, now: Date.now(), ...step.block !== void 0 ? { block: step.block } : {} });
|
|
4165
|
+
scopes = executed.scopes;
|
|
4166
|
+
log.push(executed.log);
|
|
4167
|
+
outputs[step.id] = { stepid: step.id, ok: executed.output.ok, summary: executed.output.summary, ...executed.output.details !== void 0 ? { details: executed.output.details } : {}, at: Date.now() };
|
|
4168
|
+
if (!executed.output.ok) {
|
|
4169
|
+
run = { ...run, state: "failed", endedat: Date.now(), failreason: executed.output.summary };
|
|
4170
|
+
return { run, scopes, log, outputs };
|
|
4171
|
+
}
|
|
4172
|
+
run = { ...run, cursor: index + 1 };
|
|
4173
|
+
if (input.oncheckpoint) await input.oncheckpoint({ run, scopes, log });
|
|
4174
|
+
}
|
|
4175
|
+
run = { ...run, state: "done", endedat: Date.now() };
|
|
4176
|
+
return { run, scopes, log, outputs };
|
|
4177
|
+
}
|
|
4178
|
+
function dryrunworkflow(input) {
|
|
4179
|
+
const run = { ...input.run, state: "running", ...input.run.dryrun === true ? { dryrun: true } : { dryrun: true } };
|
|
4180
|
+
let scopes = input.scopes ?? [{ name: "root", variables: [] }];
|
|
4181
|
+
const log = [...input.log ?? []];
|
|
4182
|
+
for (let index = run.cursor; index < input.record.steps.length; index += 1) {
|
|
4183
|
+
const step = input.record.steps[index];
|
|
4184
|
+
const summary = input.projection(step);
|
|
4185
|
+
const entry = summary === void 0 ? runlogof(step, "refused", input.now, 0, `The ${step.kind} step has no read only projection and the dry run refuses it.`, { ...step.block !== void 0 ? { block: step.block } : {} }) : runlogof(step, "done", input.now, 0, summary, { ...step.block !== void 0 ? { block: step.block } : {} });
|
|
4186
|
+
log.push(entry);
|
|
4187
|
+
scopes = setvariable(scopes, `${step.id}outcome`, "boolean", entry.state === "done", input.now);
|
|
4188
|
+
}
|
|
4189
|
+
return { run: { ...run, state: "done", cursor: input.record.steps.length, endedat: input.now }, scopes, log };
|
|
4190
|
+
}
|
|
4191
|
+
|
|
3317
4192
|
// runtimeline.ts
|
|
3318
4193
|
var timelinekinds = ["watchconsole", "watcherrors", "watchtasks"];
|
|
3319
4194
|
var loglevels = ["error", "warn", "info", "log", "debug", "trace"];
|
|
@@ -3724,9 +4599,9 @@ function polldecision(input) {
|
|
|
3724
4599
|
}
|
|
3725
4600
|
|
|
3726
4601
|
// policy.ts
|
|
3727
|
-
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps", "emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission"]);
|
|
4602
|
+
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps", "emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "restoresession", "exportsessions", "importsessions", "runworkflow"]);
|
|
3728
4603
|
var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction", "capturebodies", "setbreakpoint", "stepcode", "watchexpr"]);
|
|
3729
|
-
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies", "watchconsole", "watcherrors", "watchtasks", "watchcdp", "measureflow", "trackmemory", "watchshifts", "traceload", "annotatetrace", "replaytrace", "blackboxscripts"]);
|
|
4604
|
+
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies", "watchconsole", "watcherrors", "watchtasks", "watchcdp", "measureflow", "trackmemory", "watchshifts", "traceload", "annotatetrace", "replaytrace", "blackboxscripts", "persiststate", "capturesession", "namedsessions", "diffsessions", "searchsessions", "composeworkflow", "savetemplate", "dryrun", "delay", "waitelement", "compute", "extractvars"]);
|
|
3730
4605
|
var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
|
|
3731
4606
|
var watchactions = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "watchtab"]);
|
|
3732
4607
|
var targetactions = /* @__PURE__ */ new Set(["inspect", "focus", "click", "type", "scroll", "select", "hover", "clickdeep", "rightclick", "doubleclick", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "highlight", "setattribute", "removeattribute", "waitfor", "shiftclick", "typetime", "appendtext", "setvalue", "typeedit", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "expanddetails", "verifyvisible", "verifyenabled", "pierceshadow", "deriveselector", "fingerprintsection", "submitform", "retryform", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "scrapetable", "paginateextract", "shotelement", "captureframe", "shotcanvas"]);
|
|
@@ -3746,6 +4621,8 @@ var debugactions = /* @__PURE__ */ new Set(["watchconsole", "watcherrors", "watc
|
|
|
3746
4621
|
var cdpactions = /* @__PURE__ */ new Set(["attachcdp", "detachcdp", "cdpcmd", "watchcdp", "setbreakpoint", "stepcode", "watchexpr", "overridescript"]);
|
|
3747
4622
|
var profileractions = /* @__PURE__ */ new Set(["measureflow", "heapshot", "trackmemory", "profilecpu", "watchshifts", "traceload", "annotatetrace", "replaytrace", "capturesourcemaps"]);
|
|
3748
4623
|
var emulationactions = /* @__PURE__ */ new Set(["emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "blackboxscripts"]);
|
|
4624
|
+
var sessionactions = /* @__PURE__ */ new Set(["persiststate", "capturesession", "restoresession", "namedsessions", "diffsessions", "searchsessions", "exportsessions", "importsessions"]);
|
|
4625
|
+
var workflowactions = /* @__PURE__ */ new Set(["composeworkflow", "savetemplate", "runworkflow", "dryrun", "delay", "waitelement", "compute", "extractvars"]);
|
|
3749
4626
|
var credentialheaders = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2", "set-cookie", "api-key", "x-api-key", "x-auth-token", "x-session-token", "proxy-authorization"]);
|
|
3750
4627
|
var fieldkinds = ["text", "email", "phone", "date", "number", "select", "check", "radio", "file", "password", "card", "code"];
|
|
3751
4628
|
var layoutmutationactions = /* @__PURE__ */ new Set(["grouptabs", "colorgroup", "collapsegroup", "savelayout", "restorelayout"]);
|
|
@@ -3761,6 +4638,12 @@ function hostpattern(origin) {
|
|
|
3761
4638
|
if (parsed.protocol !== "https:") throw new Error("Only HTTPS origins can be granted.");
|
|
3762
4639
|
return `${parsed.origin}/*`;
|
|
3763
4640
|
}
|
|
4641
|
+
function issessionkind(kind) {
|
|
4642
|
+
return sessionactions.has(kind);
|
|
4643
|
+
}
|
|
4644
|
+
function isworkflowkind(kind) {
|
|
4645
|
+
return workflowactions.has(kind);
|
|
4646
|
+
}
|
|
3764
4647
|
function iswatchkind(kind) {
|
|
3765
4648
|
return watchactions.has(kind);
|
|
3766
4649
|
}
|
|
@@ -5135,6 +6018,253 @@ function permissionnamevalid(name) {
|
|
|
5135
6018
|
if (!browserpermissions.includes(name)) return { allowed: false, reason: `The permission ${name} stays outside the reviewed browser permission set: ${browserpermissions.join(", ")}.` };
|
|
5136
6019
|
return { allowed: true };
|
|
5137
6020
|
}
|
|
6021
|
+
function validatesessiongrammar(step, options) {
|
|
6022
|
+
const kind = step.kind;
|
|
6023
|
+
if (kind === "persiststate") {
|
|
6024
|
+
if (options.resume !== void 0 && typeof options.resume !== "boolean") return { allowed: false, reason: "The reviewed resume flag must be a boolean." };
|
|
6025
|
+
return { allowed: true };
|
|
6026
|
+
}
|
|
6027
|
+
if (kind === "capturesession") {
|
|
6028
|
+
const plan = snapshotplanof(options.snapshot);
|
|
6029
|
+
if (!plan) return { allowed: false, reason: "The session capture needs a reviewed snapshot plan with its scope, a non-empty section list of the reviewed grammar (tabs, scroll, forms, storage, cookies) and the capture link flag." };
|
|
6030
|
+
if (plan.auto !== void 0) {
|
|
6031
|
+
const interval = autointervalof(options.snapshot.auto);
|
|
6032
|
+
if (interval === void 0) return { allowed: false, reason: "The reviewed auto snapshot interval needs a positive period, a positive maximum snapshot count and a zero or positive expiry window with no code ceiling." };
|
|
6033
|
+
}
|
|
6034
|
+
return { allowed: true };
|
|
6035
|
+
}
|
|
6036
|
+
if (kind === "restoresession") {
|
|
6037
|
+
if (typeof options.sessionid !== "string" || !options.sessionid.trim()) return { allowed: false, reason: "The session restore needs the reviewed session id of the saved record." };
|
|
6038
|
+
if (restoreplanof(options.restore) === void 0) return { allowed: false, reason: "The session restore needs a reviewed restore plan with its tab, form and capture policies." };
|
|
6039
|
+
if (options.reviewed !== true) return { allowed: false, reason: "Every session restore needs the explicit restore review with its tabs, form state and captures listed before it reopens anything." };
|
|
6040
|
+
return { allowed: true };
|
|
6041
|
+
}
|
|
6042
|
+
if (kind === "namedsessions") {
|
|
6043
|
+
if (typeof options.sessionid !== "string" || !options.sessionid.trim()) return { allowed: false, reason: "The session filing needs the reviewed session id of the saved record." };
|
|
6044
|
+
if (typeof options.name !== "string" || !options.name.trim()) return { allowed: false, reason: "The session filing needs a reviewed non-empty session name." };
|
|
6045
|
+
if (options.folder !== void 0 && (typeof options.folder !== "string" || !options.folder.trim())) return { allowed: false, reason: "The reviewed folder name must be a non-empty string." };
|
|
6046
|
+
if (options.tags !== void 0 && (!Array.isArray(options.tags) || !options.tags.every((tag) => typeof tag === "string" && tag.trim()))) return { allowed: false, reason: "The reviewed tag list must be a list of non-empty strings." };
|
|
6047
|
+
return { allowed: true };
|
|
6048
|
+
}
|
|
6049
|
+
if (kind === "diffsessions") {
|
|
6050
|
+
if (typeof options.left !== "string" || !options.left.trim() || typeof options.right !== "string" || !options.right.trim()) return { allowed: false, reason: "The session diff needs the reviewed ids of both saved sessions." };
|
|
6051
|
+
return { allowed: true };
|
|
6052
|
+
}
|
|
6053
|
+
if (kind === "searchsessions") {
|
|
6054
|
+
if (searchqueryof(options.query) === void 0) return { allowed: false, reason: "The session search needs a reviewed query with a non-empty term list, fields of the reviewed grammar (urls, titles, names, text) and an optional time window." };
|
|
6055
|
+
return { allowed: true };
|
|
6056
|
+
}
|
|
6057
|
+
if (kind === "exportsessions") {
|
|
6058
|
+
if (options.reviewed !== true) return { allowed: false, reason: "Session exports need the explicit export review before any session file leaves the device." };
|
|
6059
|
+
if (options.ids !== void 0 && (!Array.isArray(options.ids) || options.ids.length === 0 || !options.ids.every((id) => typeof id === "string" && id.trim()))) return { allowed: false, reason: "The reviewed export id list must be a non-empty list of saved session ids." };
|
|
6060
|
+
return { allowed: true };
|
|
6061
|
+
}
|
|
6062
|
+
if (kind === "importsessions") {
|
|
6063
|
+
if (options.reviewed !== true) return { allowed: false, reason: "Session imports need the explicit full record review before any record joins the library." };
|
|
6064
|
+
if (importsessionfile(options.file) === void 0) return { allowed: false, reason: "The session import needs a reviewed file of the known format version with an intact checksum." };
|
|
6065
|
+
return { allowed: true };
|
|
6066
|
+
}
|
|
6067
|
+
return { allowed: true };
|
|
6068
|
+
}
|
|
6069
|
+
function restorereviewgranted(step) {
|
|
6070
|
+
let options = {};
|
|
6071
|
+
try {
|
|
6072
|
+
options = parseoptions(step);
|
|
6073
|
+
} catch {
|
|
6074
|
+
options = {};
|
|
6075
|
+
}
|
|
6076
|
+
if (restoreplanof(options.restore) === void 0) return { allowed: false, reason: "Every session restore needs a reviewed restore plan with its tab, form and capture policies." };
|
|
6077
|
+
if (options.reviewed !== true) return { allowed: false, reason: "The session restore needs the explicit restore review of its tabs, form state and captures before it reopens anything." };
|
|
6078
|
+
return { allowed: true };
|
|
6079
|
+
}
|
|
6080
|
+
function sessionrestoregate(input) {
|
|
6081
|
+
const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: "run the session memory step" });
|
|
6082
|
+
if (!gate.allowed) return gate;
|
|
6083
|
+
if (!input.plan || input.plan.state !== "approved") return { allowed: false, reason: "Session memory steps need an approved plan before they run." };
|
|
6084
|
+
if (input.step.kind === "restoresession") return restorereviewgranted(input.step);
|
|
6085
|
+
return { allowed: true };
|
|
6086
|
+
}
|
|
6087
|
+
function restoreoriginsgranted(urls, grants) {
|
|
6088
|
+
const covered = new Set(grants);
|
|
6089
|
+
const skippedorigins = [];
|
|
6090
|
+
for (const url of urls) {
|
|
6091
|
+
let origin = "";
|
|
6092
|
+
try {
|
|
6093
|
+
origin = new URL(url).origin;
|
|
6094
|
+
} catch {
|
|
6095
|
+
origin = "";
|
|
6096
|
+
}
|
|
6097
|
+
if (!origin || !covered.has(origin)) skippedorigins.push(origin || url);
|
|
6098
|
+
}
|
|
6099
|
+
return { allowed: skippedorigins.length === 0, skippedorigins: [...new Set(skippedorigins)] };
|
|
6100
|
+
}
|
|
6101
|
+
function sessionnameunique(name, records, recordid) {
|
|
6102
|
+
if (records.some((record2) => record2.name === name && record2.id !== recordid)) return { allowed: false, reason: `The session name ${name} already exists in the library; review a unique name.` };
|
|
6103
|
+
return { allowed: true };
|
|
6104
|
+
}
|
|
6105
|
+
function sessionfolderunique(name, folders) {
|
|
6106
|
+
if (folders.some((folder) => folder.name === name)) return { allowed: false, reason: `The folder name ${name} already exists in the library; review a unique folder name.` };
|
|
6107
|
+
return { allowed: true };
|
|
6108
|
+
}
|
|
6109
|
+
function snapshotretentionwindow(settings) {
|
|
6110
|
+
return settings?.sessionretention;
|
|
6111
|
+
}
|
|
6112
|
+
function validateworkflowgrammar(step, options) {
|
|
6113
|
+
const kind = step.kind;
|
|
6114
|
+
if (kind === "composeworkflow") {
|
|
6115
|
+
const payload = options.workflow;
|
|
6116
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return { allowed: false, reason: "The workflow composition needs the reviewed workflow payload with its name, version, origins, steps and blocks." };
|
|
6117
|
+
const candidate = payload;
|
|
6118
|
+
if (typeof candidate.name !== "string" || !candidate.name.trim()) return { allowed: false, reason: "The workflow composition needs a reviewed non-empty name." };
|
|
6119
|
+
if (typeof candidate.version !== "number" || !Number.isInteger(candidate.version) || candidate.version < 1) return { allowed: false, reason: "The workflow version must be a positive integer." };
|
|
6120
|
+
if (!Array.isArray(candidate.origins) || candidate.origins.length === 0 || !candidate.origins.every((origin) => typeof origin === "string" && origin.startsWith("https://"))) return { allowed: false, reason: "The workflow needs at least one granted HTTPS origin so every step stays inside the grants." };
|
|
6121
|
+
if (!Array.isArray(candidate.steps) || candidate.steps.length === 0 || !candidate.steps.every((entry) => workflowstepof(entry) !== void 0 || entry && typeof entry === "object" && typeof entry.block === "string")) return { allowed: false, reason: "The workflow needs a non-empty reviewed step list of the workflow step grammar or block invocations." };
|
|
6122
|
+
const blocks = Array.isArray(candidate.blocks) ? candidate.blocks.flatMap((block) => {
|
|
6123
|
+
const parsed = workflowblockof(block);
|
|
6124
|
+
return parsed !== void 0 ? [parsed] : [];
|
|
6125
|
+
}) : [];
|
|
6126
|
+
if (Array.isArray(candidate.blocks) && blocks.length !== candidate.blocks.length) return { allowed: false, reason: "The reviewed block list must carry unique lowercase names, labels and valid child steps." };
|
|
6127
|
+
try {
|
|
6128
|
+
const record2 = composeworkflow({ name: candidate.name, version: candidate.version, origins: candidate.origins, steps: candidate.steps.map((entry) => "block" in entry ? { block: entry.block, label: typeof entry.label === "string" ? entry.label : entry.block } : workflowstepof(entry)), blocks, now: 0, kindallowed: (candidatekind) => {
|
|
6129
|
+
try {
|
|
6130
|
+
actionrisk(candidatekind);
|
|
6131
|
+
return true;
|
|
6132
|
+
} catch {
|
|
6133
|
+
return false;
|
|
6134
|
+
}
|
|
6135
|
+
}, riskof: (candidatekind) => actionrisk(candidatekind) });
|
|
6136
|
+
const inputs = Array.isArray(candidate.inputs) ? candidate.inputs.flatMap((name) => typeof name === "string" ? [name] : []) : void 0;
|
|
6137
|
+
const checked = validateworkflow(record2, { kindallowed: (workflowkind) => {
|
|
6138
|
+
try {
|
|
6139
|
+
actionrisk(workflowkind);
|
|
6140
|
+
return true;
|
|
6141
|
+
} catch {
|
|
6142
|
+
return false;
|
|
6143
|
+
}
|
|
6144
|
+
}, ...inputs !== void 0 ? { inputs } : {} });
|
|
6145
|
+
if (!checked.allowed) return checked;
|
|
6146
|
+
} catch (error) {
|
|
6147
|
+
return { allowed: false, reason: error instanceof Error ? error.message : "The workflow payload failed its composition validation." };
|
|
6148
|
+
}
|
|
6149
|
+
return { allowed: true };
|
|
6150
|
+
}
|
|
6151
|
+
if (kind === "savetemplate") {
|
|
6152
|
+
const payload = options.template && typeof options.template === "object" && !Array.isArray(options.template) ? options.template : {};
|
|
6153
|
+
const template = steptemplateof({ id: "templatereview", origin: "https://example.com", sharedat: 0, ...payload });
|
|
6154
|
+
if (!template) return { allowed: false, reason: "The step template needs a reviewed name and a valid workflow step it shares across workflows." };
|
|
6155
|
+
return { allowed: true };
|
|
6156
|
+
}
|
|
6157
|
+
if (kind === "runworkflow") {
|
|
6158
|
+
if (typeof options.workflowid !== "string" || !options.workflowid.trim()) return { allowed: false, reason: "The workflow run needs the reviewed id of the composed workflow." };
|
|
6159
|
+
if (options.reviewed !== true) return { allowed: false, reason: "Every real workflow run needs the explicit run review with its expanded step list shown before the first step executes." };
|
|
6160
|
+
if (options.variables !== void 0 && (!options.variables || typeof options.variables !== "object" || Array.isArray(options.variables) || !Object.values(options.variables).every((value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean"))) return { allowed: false, reason: "The reviewed run variables must be an object of string, number or boolean values." };
|
|
6161
|
+
return { allowed: true };
|
|
6162
|
+
}
|
|
6163
|
+
if (kind === "dryrun") {
|
|
6164
|
+
if (typeof options.workflowid !== "string" || !options.workflowid.trim()) return { allowed: false, reason: "The dry run needs the reviewed id of the composed workflow." };
|
|
6165
|
+
return { allowed: true };
|
|
6166
|
+
}
|
|
6167
|
+
if (kind === "delay") {
|
|
6168
|
+
const delay = options.delay;
|
|
6169
|
+
if (!delay || typeof delay !== "object" || Array.isArray(delay)) return { allowed: false, reason: "The delay needs a reviewed base and jitter window in options." };
|
|
6170
|
+
const reviewed = delay;
|
|
6171
|
+
if (typeof reviewed.base !== "number" || !Number.isFinite(reviewed.base) || reviewed.base < 0) return { allowed: false, reason: "The reviewed delay base must be zero or a positive number of milliseconds." };
|
|
6172
|
+
if (typeof reviewed.jitter !== "number" || !Number.isFinite(reviewed.jitter) || reviewed.jitter < 0) return { allowed: false, reason: "The reviewed delay jitter window must be zero or a positive number of milliseconds with no code ceiling." };
|
|
6173
|
+
return { allowed: true };
|
|
6174
|
+
}
|
|
6175
|
+
if (kind === "waitelement") {
|
|
6176
|
+
const wait = options.wait;
|
|
6177
|
+
if (!wait || typeof wait !== "object" || Array.isArray(wait)) return { allowed: false, reason: "The element wait needs a reviewed selector, timeout and poll interval in options." };
|
|
6178
|
+
const reviewed = wait;
|
|
6179
|
+
if (typeof reviewed.selector !== "string" || !reviewed.selector.trim()) return { allowed: false, reason: "The element wait needs a reviewed non-empty selector." };
|
|
6180
|
+
if (typeof reviewed.timeout !== "number" || !Number.isFinite(reviewed.timeout) || reviewed.timeout < 0) return { allowed: false, reason: "The reviewed element wait timeout must be zero or a positive number of milliseconds with no code ceiling." };
|
|
6181
|
+
if (typeof reviewed.poll !== "number" || !Number.isFinite(reviewed.poll) || reviewed.poll < 0) return { allowed: false, reason: "The reviewed element wait poll interval must be zero or a positive number of milliseconds with no code ceiling." };
|
|
6182
|
+
return { allowed: true };
|
|
6183
|
+
}
|
|
6184
|
+
if (kind === "compute") {
|
|
6185
|
+
const expression = expressionof(options.expression);
|
|
6186
|
+
if (!expression) return { allowed: false, reason: `The expression step needs a reviewed expression with operands, an operator of the reviewed set (${expressionoperators.join(", ")}) and a result variable of a reviewed kind.` };
|
|
6187
|
+
const operatorcheck = validatexpressionoperators(expression);
|
|
6188
|
+
if (!operatorcheck.allowed) return operatorcheck;
|
|
6189
|
+
return { allowed: true };
|
|
6190
|
+
}
|
|
6191
|
+
if (kind === "extractvars") {
|
|
6192
|
+
const rule = regexruleof(options.rule);
|
|
6193
|
+
if (!rule) return { allowed: false, reason: "The variable extraction needs a reviewed regex rule with its pattern, flags and named capture groups." };
|
|
6194
|
+
const shapecheck = validateregexrule(rule.pattern);
|
|
6195
|
+
if (!shapecheck.allowed) return shapecheck;
|
|
6196
|
+
if (typeof options.text !== "string") return { allowed: false, reason: "The variable extraction needs the reviewed text the regex rule applies to." };
|
|
6197
|
+
return { allowed: true };
|
|
6198
|
+
}
|
|
6199
|
+
return { allowed: true };
|
|
6200
|
+
}
|
|
6201
|
+
function validateregexrule(pattern) {
|
|
6202
|
+
try {
|
|
6203
|
+
new RegExp(pattern);
|
|
6204
|
+
} catch {
|
|
6205
|
+
return { allowed: false, reason: "The reviewed regex pattern does not compile." };
|
|
6206
|
+
}
|
|
6207
|
+
const nestedquantifier = /\((?:[^()\\]|\\.)*[+*}]\)[+*{]/.test(pattern) || /\(\)[+*{]/.test(pattern);
|
|
6208
|
+
if (nestedquantifier) return { allowed: false, reason: "The reviewed regex pattern nests an unbounded quantifier inside a quantified group and is refused because adversarial text could explode the backtracking." };
|
|
6209
|
+
const unboundedrepeat = /\{\d+,\}/.test(pattern);
|
|
6210
|
+
if (unboundedrepeat && /\([^)]*\{\d+,\}[^)]*\)[+*{]/.test(pattern)) return { allowed: false, reason: "The reviewed regex pattern repeats an unbounded group and is refused because adversarial text could explode the backtracking." };
|
|
6211
|
+
return { allowed: true };
|
|
6212
|
+
}
|
|
6213
|
+
function validatexpressionoperators(expression) {
|
|
6214
|
+
const numeric = /* @__PURE__ */ new Set(["add", "subtract", "multiply", "divide", "modulo"]);
|
|
6215
|
+
const logic = /* @__PURE__ */ new Set(["and", "or", "not"]);
|
|
6216
|
+
const comparison = /* @__PURE__ */ new Set(["less", "greater", "lessequal", "greaterequal"]);
|
|
6217
|
+
const text2 = /* @__PURE__ */ new Set(["concat", "contains"]);
|
|
6218
|
+
const operator = expression.operator;
|
|
6219
|
+
if (numeric.has(operator)) {
|
|
6220
|
+
for (const operand of [expression.left, expression.right]) {
|
|
6221
|
+
if (operand === void 0) continue;
|
|
6222
|
+
if (operand.literal !== void 0 && typeof operand.literal === "boolean") return { allowed: false, reason: `The ${operator} operator needs numeric operands; boolean literals are refused.` };
|
|
6223
|
+
}
|
|
6224
|
+
if (expression.resultkind !== "number" && expression.resultkind !== "string") return { allowed: false, reason: `The ${operator} operator needs a number result kind.` };
|
|
6225
|
+
}
|
|
6226
|
+
if (logic.has(operator)) {
|
|
6227
|
+
for (const operand of [expression.left, expression.right]) {
|
|
6228
|
+
if (operand === void 0) continue;
|
|
6229
|
+
if (operand.literal !== void 0 && typeof operand.literal !== "boolean") return { allowed: false, reason: `The ${operator} operator needs boolean operands; non boolean literals are refused.` };
|
|
6230
|
+
}
|
|
6231
|
+
if (expression.resultkind !== "boolean") return { allowed: false, reason: `The ${operator} operator needs a boolean result kind.` };
|
|
6232
|
+
if (operator === "not" && expression.right !== void 0) return { allowed: false, reason: "The not operator takes one operand only." };
|
|
6233
|
+
}
|
|
6234
|
+
if (comparison.has(operator) && expression.resultkind !== "boolean") return { allowed: false, reason: `The ${operator} operator needs a boolean result kind.` };
|
|
6235
|
+
if (text2.has(operator) && expression.resultkind !== "boolean" && expression.resultkind !== "string") return { allowed: false, reason: `The ${operator} operator needs a string or boolean result kind.` };
|
|
6236
|
+
if (operator === "contains" && expression.resultkind !== "boolean") return { allowed: false, reason: "The contains operator needs a boolean result kind." };
|
|
6237
|
+
if (operator === "length") {
|
|
6238
|
+
if (expression.right !== void 0) return { allowed: false, reason: "The length operator takes one operand only." };
|
|
6239
|
+
if (expression.resultkind !== "number") return { allowed: false, reason: "The length operator needs a number result kind." };
|
|
6240
|
+
}
|
|
6241
|
+
if ((operator === "equal" || operator === "notequal") && !(/* @__PURE__ */ new Set(["boolean", "string", "number"])).has(expression.resultkind)) return { allowed: false, reason: "The equality operator needs a primitive result kind." };
|
|
6242
|
+
return { allowed: true };
|
|
6243
|
+
}
|
|
6244
|
+
function workflowgate(input) {
|
|
6245
|
+
const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: "run the workflow step" });
|
|
6246
|
+
if (!gate.allowed) return gate;
|
|
6247
|
+
if (!input.plan || input.plan.state !== "approved") return { allowed: false, reason: "Workflow steps need the approved plan review before they run." };
|
|
6248
|
+
if (input.step.kind === "runworkflow") {
|
|
6249
|
+
let runoptions = {};
|
|
6250
|
+
try {
|
|
6251
|
+
runoptions = parseoptions(input.step);
|
|
6252
|
+
} catch {
|
|
6253
|
+
runoptions = {};
|
|
6254
|
+
}
|
|
6255
|
+
if (runoptions.reviewed !== true) return { allowed: false, reason: "Every real workflow run needs the explicit run review with its expanded step list shown before the first step executes." };
|
|
6256
|
+
}
|
|
6257
|
+
return { allowed: true };
|
|
6258
|
+
}
|
|
6259
|
+
function dryrunprojection(step) {
|
|
6260
|
+
const risk = resolvedrisk({ id: step.id, kind: step.kind, summary: step.label, risk: "read", ...step.target !== void 0 ? { target: step.target } : {}, ...step.value !== void 0 ? { value: step.value } : {}, ...step.options !== void 0 ? { options: step.options } : {} });
|
|
6261
|
+
if (risk !== "read") return void 0;
|
|
6262
|
+
if (step.kind === "delay") return `The delay step would sleep its reviewed base inside the jitter window.`;
|
|
6263
|
+
if (step.kind === "waitelement") return `The element wait step would poll ${step.target ?? "the reviewed selector"} until appearance or the reviewed timeout.`;
|
|
6264
|
+
if (step.kind === "compute") return `The compute step would evaluate its reviewed expression into the result variable.`;
|
|
6265
|
+
if (step.kind === "extractvars") return `The variable extraction step would apply its reviewed regex rule and store the named captures.`;
|
|
6266
|
+
return `The ${step.kind} step would run read only and mutate nothing.`;
|
|
6267
|
+
}
|
|
5138
6268
|
function permissionstatevalid(state) {
|
|
5139
6269
|
if (!permissionstates.includes(state)) return { allowed: false, reason: `The reviewed permission state must be one of ${permissionstates.join(", ")}.` };
|
|
5140
6270
|
return { allowed: true };
|
|
@@ -5700,6 +6830,14 @@ function validatestep(step, origin) {
|
|
|
5700
6830
|
const emulationcheck = validateemulationgrammar(step, options);
|
|
5701
6831
|
if (!emulationcheck.allowed) return emulationcheck;
|
|
5702
6832
|
}
|
|
6833
|
+
if (issessionkind(step.kind)) {
|
|
6834
|
+
const sessioncheck = validatesessiongrammar(step, options);
|
|
6835
|
+
if (!sessioncheck.allowed) return sessioncheck;
|
|
6836
|
+
}
|
|
6837
|
+
if (isworkflowkind(step.kind)) {
|
|
6838
|
+
const workflowcheck = validateworkflowgrammar(step, options);
|
|
6839
|
+
if (!workflowcheck.allowed) return workflowcheck;
|
|
6840
|
+
}
|
|
5703
6841
|
if (step.kind === "tabcreate") {
|
|
5704
6842
|
if (options.background !== void 0 && typeof options.background !== "boolean") return { allowed: false, reason: "The reviewed background flag must be a boolean." };
|
|
5705
6843
|
if (options.window !== void 0 && (typeof options.window !== "number" || !Number.isInteger(options.window) || options.window < 0)) return { allowed: false, reason: "The reviewed target window id must be a non-negative integer." };
|
|
@@ -5873,6 +7011,27 @@ function canexecute(input) {
|
|
|
5873
7011
|
const emugatecheck = emugate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });
|
|
5874
7012
|
if (!emugatecheck.allowed) return emugatecheck;
|
|
5875
7013
|
}
|
|
7014
|
+
if (issessionkind(input.step.kind)) {
|
|
7015
|
+
const sessiongatecheck = sessionrestoregate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });
|
|
7016
|
+
if (!sessiongatecheck.allowed) return sessiongatecheck;
|
|
7017
|
+
if (input.step.kind === "restoresession") {
|
|
7018
|
+
let restoreoptions = {};
|
|
7019
|
+
try {
|
|
7020
|
+
restoreoptions = parseoptions(input.step);
|
|
7021
|
+
} catch {
|
|
7022
|
+
restoreoptions = {};
|
|
7023
|
+
}
|
|
7024
|
+
for (const url of Array.isArray(restoreoptions.origins) ? restoreoptions.origins : []) {
|
|
7025
|
+
if (typeof url !== "string" || !url) continue;
|
|
7026
|
+
const origingate = origincheck(input.session, url);
|
|
7027
|
+
if (!origingate.allowed) return { allowed: false, reason: `The session restore reopens ${url} outside the session origin grants; review the restore record or grant the origin.` };
|
|
7028
|
+
}
|
|
7029
|
+
}
|
|
7030
|
+
}
|
|
7031
|
+
if (isworkflowkind(input.step.kind)) {
|
|
7032
|
+
const workflowgatecheck = workflowgate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });
|
|
7033
|
+
if (!workflowgatecheck.allowed) return workflowgatecheck;
|
|
7034
|
+
}
|
|
5876
7035
|
if (iscontrolkind(input.step.kind)) {
|
|
5877
7036
|
const controlgate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: "control the network" });
|
|
5878
7037
|
if (!controlgate.allowed) return controlgate;
|
|
@@ -5956,7 +7115,7 @@ function canexecute(input) {
|
|
|
5956
7115
|
}
|
|
5957
7116
|
|
|
5958
7117
|
// version.ts
|
|
5959
|
-
var packageversion = "1.1.
|
|
7118
|
+
var packageversion = "1.1.50";
|
|
5960
7119
|
|
|
5961
7120
|
// types.ts
|
|
5962
7121
|
var protocolversion = packageversion;
|
|
@@ -6150,6 +7309,51 @@ function parseproposal(value, origin, grants) {
|
|
|
6150
7309
|
}
|
|
6151
7310
|
if (step.kind === "overridepermission" && permissiongrantof(emulationoptions.permission) === void 0) throw new Error("Permission overrides of unknown permission names are refused.");
|
|
6152
7311
|
}
|
|
7312
|
+
if (issessionkind(step.kind)) {
|
|
7313
|
+
let sessionoptions = {};
|
|
7314
|
+
try {
|
|
7315
|
+
sessionoptions = parseoptions(step);
|
|
7316
|
+
} catch {
|
|
7317
|
+
sessionoptions = {};
|
|
7318
|
+
}
|
|
7319
|
+
if (step.kind === "restoresession") {
|
|
7320
|
+
for (const url of Array.isArray(sessionoptions.origins) ? sessionoptions.origins : []) {
|
|
7321
|
+
if (typeof url !== "string" || !url) continue;
|
|
7322
|
+
const granted = covered.some((pattern) => {
|
|
7323
|
+
try {
|
|
7324
|
+
return new URL(url).origin === new URL(pattern).origin;
|
|
7325
|
+
} catch {
|
|
7326
|
+
return false;
|
|
7327
|
+
}
|
|
7328
|
+
});
|
|
7329
|
+
if (!granted) throw new Error(`The session restore reopens ${url} outside the grants.`);
|
|
7330
|
+
}
|
|
7331
|
+
}
|
|
7332
|
+
if (step.kind === "importsessions" && importsessionfile(sessionoptions.file) === void 0) throw new Error("Session import files of unknown format versions are refused.");
|
|
7333
|
+
}
|
|
7334
|
+
if (isworkflowkind(step.kind)) {
|
|
7335
|
+
let workflowoptions = {};
|
|
7336
|
+
try {
|
|
7337
|
+
workflowoptions = parseoptions(step);
|
|
7338
|
+
} catch {
|
|
7339
|
+
workflowoptions = {};
|
|
7340
|
+
}
|
|
7341
|
+
if (step.kind === "composeworkflow") {
|
|
7342
|
+
const payload = workflowoptions.workflow && typeof workflowoptions.workflow === "object" && !Array.isArray(workflowoptions.workflow) ? workflowoptions.workflow : void 0;
|
|
7343
|
+
const origins = payload && Array.isArray(payload.origins) ? payload.origins.filter((originvalue) => typeof originvalue === "string") : [];
|
|
7344
|
+
for (const workfloworigin of origins) {
|
|
7345
|
+
const granted = covered.some((pattern) => {
|
|
7346
|
+
try {
|
|
7347
|
+
return new URL(workfloworigin).origin === new URL(pattern).origin;
|
|
7348
|
+
} catch {
|
|
7349
|
+
return false;
|
|
7350
|
+
}
|
|
7351
|
+
});
|
|
7352
|
+
if (!granted) throw new Error(`The workflow origin ${workfloworigin} stays outside the grants.`);
|
|
7353
|
+
}
|
|
7354
|
+
}
|
|
7355
|
+
if (step.kind === "runworkflow" && workflowoptions.reviewed !== true) throw new Error("Workflow runs without the explicit run review of the expanded step list are refused.");
|
|
7356
|
+
}
|
|
6153
7357
|
const evaluation = validatestep(step, origin);
|
|
6154
7358
|
if (!evaluation.allowed) throw new Error(evaluation.reason);
|
|
6155
7359
|
const target = outboundtarget(step);
|
|
@@ -6209,6 +7413,70 @@ function parseproposal(value, origin, grants) {
|
|
|
6209
7413
|
};
|
|
6210
7414
|
return { version: protocolversion, plan };
|
|
6211
7415
|
}
|
|
7416
|
+
function parseworkflowproposal(value, origin, grants, dryrun) {
|
|
7417
|
+
const root = record(value);
|
|
7418
|
+
if (root.version !== protocolversion) throw new Error("Unsupported protocol version.");
|
|
7419
|
+
const covered = grants !== void 0 && grants.length > 0 ? grants : [origin];
|
|
7420
|
+
const candidate = record(root.workflow);
|
|
7421
|
+
const name = text(candidate.name, "workflow name");
|
|
7422
|
+
const version = typeof candidate.version === "number" && Number.isInteger(candidate.version) && candidate.version >= 1 ? candidate.version : void 0;
|
|
7423
|
+
if (version === void 0) throw new Error("The workflow version must be a positive integer.");
|
|
7424
|
+
const origins = Array.isArray(candidate.origins) ? candidate.origins : [];
|
|
7425
|
+
if (origins.length === 0 || !origins.every((workfloworigin) => typeof workfloworigin === "string" && workfloworigin.startsWith("https://"))) throw new Error("The workflow needs at least one granted HTTPS origin.");
|
|
7426
|
+
for (const workfloworigin of origins) {
|
|
7427
|
+
const granted = covered.some((pattern) => {
|
|
7428
|
+
try {
|
|
7429
|
+
return new URL(workfloworigin).origin === new URL(pattern).origin;
|
|
7430
|
+
} catch {
|
|
7431
|
+
return false;
|
|
7432
|
+
}
|
|
7433
|
+
});
|
|
7434
|
+
if (!granted) throw new Error(`The workflow origin ${workfloworigin} stays outside the grants.`);
|
|
7435
|
+
}
|
|
7436
|
+
const steps = Array.isArray(candidate.steps) ? candidate.steps : [];
|
|
7437
|
+
if (steps.length === 0) throw new Error("A workflow proposal needs at least one step or block invocation.");
|
|
7438
|
+
const blocks = Array.isArray(candidate.blocks) ? candidate.blocks.flatMap((block) => workflowblockof(block) !== void 0 ? [workflowblockof(block)] : []) : [];
|
|
7439
|
+
if (Array.isArray(candidate.blocks) && blocks.length !== candidate.blocks.length) throw new Error("The reviewed block list must carry unique lowercase names, labels and valid child steps.");
|
|
7440
|
+
const composed = composeworkflow({
|
|
7441
|
+
name,
|
|
7442
|
+
version,
|
|
7443
|
+
origins,
|
|
7444
|
+
steps: steps.map((entry) => {
|
|
7445
|
+
const step = workflowstepof(entry);
|
|
7446
|
+
if (step) return step;
|
|
7447
|
+
const invocation = blockinvocationof(entry);
|
|
7448
|
+
if (invocation) return invocation;
|
|
7449
|
+
throw new Error("Every workflow entry must be a reviewed step or a block invocation.");
|
|
7450
|
+
}),
|
|
7451
|
+
blocks,
|
|
7452
|
+
now: Date.now(),
|
|
7453
|
+
kindallowed: (kind) => {
|
|
7454
|
+
try {
|
|
7455
|
+
actionrisk(kind);
|
|
7456
|
+
return true;
|
|
7457
|
+
} catch {
|
|
7458
|
+
return false;
|
|
7459
|
+
}
|
|
7460
|
+
},
|
|
7461
|
+
riskof: (kind) => actionrisk(kind)
|
|
7462
|
+
});
|
|
7463
|
+
const inputs = Array.isArray(candidate.inputs) ? candidate.inputs.flatMap((inputname) => typeof inputname === "string" ? [inputname] : []) : void 0;
|
|
7464
|
+
const checked = validateworkflow(composed, { kindallowed: (kind) => {
|
|
7465
|
+
try {
|
|
7466
|
+
actionrisk(kind);
|
|
7467
|
+
return true;
|
|
7468
|
+
} catch {
|
|
7469
|
+
return false;
|
|
7470
|
+
}
|
|
7471
|
+
}, ...inputs !== void 0 ? { inputs } : {} });
|
|
7472
|
+
if (!checked.allowed) throw new Error(checked.reason ?? "The workflow proposal failed its validation.");
|
|
7473
|
+
return { version: protocolversion, workflow: composed, ...dryrun === true ? { dryrun: true } : {} };
|
|
7474
|
+
}
|
|
7475
|
+
function workflowoutcome(input) {
|
|
7476
|
+
const selected = input.stepid !== void 0 ? input.entries.filter((entry) => entry.stepid === input.stepid) : input.entries;
|
|
7477
|
+
const steps = selected.map((entry) => ({ stepid: entry.stepid, label: entry.label, state: entry.state, duration: entry.duration, summary: entry.summary, ...entry.block !== void 0 ? { block: entry.block } : {}, ...entry.produced !== void 0 ? { produced: entry.produced } : {}, ...entry.consumed !== void 0 ? { consumed: entry.consumed } : {}, ...entry.checkpoint === true ? { checkpoint: true } : {} }));
|
|
7478
|
+
return { version: protocolversion, runid: input.run.id, workflowid: input.run.workflowid, state: input.run.state, ...input.run.dryrun === true ? { dryrun: true } : {}, steps };
|
|
7479
|
+
}
|
|
6212
7480
|
function stepof(kind, candidate, index) {
|
|
6213
7481
|
return { id: typeof candidate.id === "string" ? candidate.id : `candidate${index + 1}`, kind, summary: typeof candidate.summary === "string" ? candidate.summary : "", risk: "read", ...typeof candidate.options === "string" ? { options: candidate.options } : {} };
|
|
6214
7482
|
}
|
|
@@ -6224,7 +7492,7 @@ function requestbody(input) {
|
|
|
6224
7492
|
return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
|
|
6225
7493
|
}
|
|
6226
7494
|
function outcomeresponse(input) {
|
|
6227
|
-
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {}, ...input.timeline ? { timeline: input.timeline } : {}, ...input.cdp ? { cdp: input.cdp } : {}, ...input.profile ? { profile: input.profile } : {}, ...input.emulation ? { emulation: input.emulation } : {} });
|
|
7495
|
+
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {}, ...input.timeline ? { timeline: input.timeline } : {}, ...input.cdp ? { cdp: input.cdp } : {}, ...input.profile ? { profile: input.profile } : {}, ...input.emulation ? { emulation: input.emulation } : {}, ...input.session ? { session: input.session } : {}, ...input.workflow ? { workflow: { runid: input.workflow.runid, state: input.workflow.state, ...input.workflow.dryrun === true ? { dryrun: true } : {}, produced: input.workflow.produced, consumed: input.workflow.consumed } } : {} });
|
|
6228
7496
|
}
|
|
6229
7497
|
function mapresponse(input) {
|
|
6230
7498
|
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, map: input.map });
|
|
@@ -6370,6 +7638,12 @@ function emulationreport(input) {
|
|
|
6370
7638
|
});
|
|
6371
7639
|
return { version: protocolversion, ...input.state !== void 0 ? { state: input.state } : {}, layers: input.state?.layers ?? [], devices: input.devices, networks: input.networks, locations: input.locations, agents: input.agents, blackbox: input.blackbox, permissions: input.permissions, consents };
|
|
6372
7640
|
}
|
|
7641
|
+
function sessionreport(input) {
|
|
7642
|
+
return { version: protocolversion, records: input.records, events: input.events, folders: input.folders, diffs: input.diffs, ...input.auto !== void 0 ? { auto: input.auto } : {}, ...input.crashed === true ? { crashed: true } : {} };
|
|
7643
|
+
}
|
|
7644
|
+
function workflowreport(input) {
|
|
7645
|
+
return { version: protocolversion, workflows: input.workflows, runs: input.runs, templates: input.templates, log: input.log ?? [], scopes: input.scopes ?? [], provenance: input.provenance ?? [] };
|
|
7646
|
+
}
|
|
6373
7647
|
export {
|
|
6374
7648
|
activelayers,
|
|
6375
7649
|
agentgrammarvalid,
|
|
@@ -6391,12 +7665,15 @@ export {
|
|
|
6391
7665
|
authconsentgranted,
|
|
6392
7666
|
authorizeurl,
|
|
6393
7667
|
authreport,
|
|
7668
|
+
autointervalof,
|
|
7669
|
+
bindvariables,
|
|
6394
7670
|
blackboxedurls,
|
|
6395
7671
|
blackboxmatches,
|
|
6396
7672
|
blackboxruleof,
|
|
6397
7673
|
blendrows,
|
|
6398
7674
|
blockgate,
|
|
6399
7675
|
blockingduration,
|
|
7676
|
+
blockinvocationof,
|
|
6400
7677
|
blockruleof,
|
|
6401
7678
|
bodyfilterof,
|
|
6402
7679
|
bodymatches,
|
|
@@ -6411,6 +7688,7 @@ export {
|
|
|
6411
7688
|
callgraphql,
|
|
6412
7689
|
callrest,
|
|
6413
7690
|
callsreport,
|
|
7691
|
+
cancelrun,
|
|
6414
7692
|
canexecute,
|
|
6415
7693
|
capturebody,
|
|
6416
7694
|
capturecode,
|
|
@@ -6436,6 +7714,7 @@ export {
|
|
|
6436
7714
|
channelorigin,
|
|
6437
7715
|
closechannel,
|
|
6438
7716
|
collectmessages,
|
|
7717
|
+
composeworkflow,
|
|
6439
7718
|
consolecapture,
|
|
6440
7719
|
consoleconsentcovers,
|
|
6441
7720
|
consolediff,
|
|
@@ -6449,6 +7728,7 @@ export {
|
|
|
6449
7728
|
cookierecordof,
|
|
6450
7729
|
correlationid,
|
|
6451
7730
|
cpusnap,
|
|
7731
|
+
crashinterrupted,
|
|
6452
7732
|
croprect,
|
|
6453
7733
|
crossesviewport,
|
|
6454
7734
|
cursorfrom,
|
|
@@ -6457,12 +7737,16 @@ export {
|
|
|
6457
7737
|
debuggerconsentcovers,
|
|
6458
7738
|
debugwaitbudgetallowed,
|
|
6459
7739
|
dedupeimages,
|
|
7740
|
+
delayjitter,
|
|
6460
7741
|
actionrisk as deriveactionrisk,
|
|
6461
7742
|
detachcdpsession,
|
|
6462
7743
|
devicepresetof,
|
|
6463
7744
|
diffresponse,
|
|
6464
7745
|
diffreviewgrade,
|
|
7746
|
+
diffsessionrecords,
|
|
6465
7747
|
downloadreport,
|
|
7748
|
+
dryrunprojection,
|
|
7749
|
+
dryrunworkflow,
|
|
6466
7750
|
emugate,
|
|
6467
7751
|
emulationkinds,
|
|
6468
7752
|
emulationreport,
|
|
@@ -6473,15 +7757,22 @@ export {
|
|
|
6473
7757
|
errorreportresponse,
|
|
6474
7758
|
eventresponse,
|
|
6475
7759
|
exchangesreport,
|
|
7760
|
+
expandblocks,
|
|
6476
7761
|
expirelayers,
|
|
6477
7762
|
expireprofilerecords,
|
|
7763
|
+
expiresessions,
|
|
6478
7764
|
exportpresetlibrary,
|
|
7765
|
+
exportsessionfile,
|
|
7766
|
+
expressioneval,
|
|
7767
|
+
expressionof,
|
|
7768
|
+
expressionoperators,
|
|
6479
7769
|
extractionreport,
|
|
6480
7770
|
extractvalues,
|
|
6481
7771
|
failureclass,
|
|
6482
7772
|
familyofkind,
|
|
6483
7773
|
fetchoptionsof,
|
|
6484
7774
|
fetchrequestof,
|
|
7775
|
+
filteredsessions,
|
|
6485
7776
|
filterentries,
|
|
6486
7777
|
filterexchanges,
|
|
6487
7778
|
finishrecording,
|
|
@@ -6509,6 +7800,7 @@ export {
|
|
|
6509
7800
|
imagematches,
|
|
6510
7801
|
imagenames,
|
|
6511
7802
|
importpresetlibrary,
|
|
7803
|
+
importsessionfile,
|
|
6512
7804
|
iscdpkind,
|
|
6513
7805
|
iscontrolkind,
|
|
6514
7806
|
isdebugkind,
|
|
@@ -6516,8 +7808,10 @@ export {
|
|
|
6516
7808
|
isformkind,
|
|
6517
7809
|
isnetwatchkind,
|
|
6518
7810
|
isprofilekind,
|
|
7811
|
+
issessionkind,
|
|
6519
7812
|
issocketkind,
|
|
6520
7813
|
iswatchkind,
|
|
7814
|
+
isworkflowkind,
|
|
6521
7815
|
jsonpathrulesof,
|
|
6522
7816
|
lapseframes,
|
|
6523
7817
|
lapseplanof,
|
|
@@ -6556,6 +7850,9 @@ export {
|
|
|
6556
7850
|
newlayer,
|
|
6557
7851
|
newmockspec,
|
|
6558
7852
|
newrecording,
|
|
7853
|
+
newsessiondiff,
|
|
7854
|
+
newsessionrecord,
|
|
7855
|
+
newworkflowrun,
|
|
6559
7856
|
normalizeendpoint,
|
|
6560
7857
|
oauthflowof,
|
|
6561
7858
|
observationmodeof,
|
|
@@ -6570,9 +7867,11 @@ export {
|
|
|
6570
7867
|
parseproposal,
|
|
6571
7868
|
parsessetext,
|
|
6572
7869
|
parsetokens,
|
|
7870
|
+
parseworkflowproposal,
|
|
6573
7871
|
passwordconsentgranted,
|
|
6574
7872
|
patternorigin,
|
|
6575
7873
|
pauseretentionwindow,
|
|
7874
|
+
pauserun,
|
|
6576
7875
|
payloadshapeof,
|
|
6577
7876
|
payloadvalid,
|
|
6578
7877
|
payloadwithdefaults,
|
|
@@ -6589,6 +7888,7 @@ export {
|
|
|
6589
7888
|
pollcursorof,
|
|
6590
7889
|
polldecision,
|
|
6591
7890
|
pollurl,
|
|
7891
|
+
popscope,
|
|
6592
7892
|
privatemime,
|
|
6593
7893
|
profilegrantgranted,
|
|
6594
7894
|
profilereport,
|
|
@@ -6599,6 +7899,7 @@ export {
|
|
|
6599
7899
|
proxygate,
|
|
6600
7900
|
proxyrouteof,
|
|
6601
7901
|
publishmessage,
|
|
7902
|
+
pushscope,
|
|
6602
7903
|
quarantinereport,
|
|
6603
7904
|
randomid,
|
|
6604
7905
|
rankapis,
|
|
@@ -6613,6 +7914,8 @@ export {
|
|
|
6613
7914
|
recordwatchvalue,
|
|
6614
7915
|
redactconsoletext,
|
|
6615
7916
|
redactedcookies,
|
|
7917
|
+
regexextract,
|
|
7918
|
+
regexruleof,
|
|
6616
7919
|
regionsteps,
|
|
6617
7920
|
rejectioncapture,
|
|
6618
7921
|
replaytrace,
|
|
@@ -6620,7 +7923,11 @@ export {
|
|
|
6620
7923
|
requestbody,
|
|
6621
7924
|
resolutionverdict,
|
|
6622
7925
|
resolvedrisk,
|
|
7926
|
+
resolvevariable,
|
|
6623
7927
|
resourcefacts,
|
|
7928
|
+
restoreoriginsgranted,
|
|
7929
|
+
restoreplanof,
|
|
7930
|
+
restorereviewgranted,
|
|
6624
7931
|
retryafterof,
|
|
6625
7932
|
revertalllayers,
|
|
6626
7933
|
revertlayer,
|
|
@@ -6630,18 +7937,34 @@ export {
|
|
|
6630
7937
|
rewritesourcelocation,
|
|
6631
7938
|
rotatelogs,
|
|
6632
7939
|
rotationruleof,
|
|
7940
|
+
runstep,
|
|
7941
|
+
runworkflow,
|
|
6633
7942
|
safetyresponse,
|
|
6634
7943
|
scaledrect,
|
|
6635
7944
|
seamweights,
|
|
7945
|
+
searchfields,
|
|
7946
|
+
searchqueryof,
|
|
7947
|
+
searchsessionrecords,
|
|
6636
7948
|
selectorresponse,
|
|
6637
7949
|
sendcdpcommand,
|
|
6638
7950
|
sendfetch,
|
|
6639
7951
|
sequenceintegrity,
|
|
6640
7952
|
serializearg,
|
|
6641
7953
|
serializecdpcommand,
|
|
7954
|
+
sessionfileversion,
|
|
7955
|
+
sessionfolderof,
|
|
7956
|
+
sessionfolderunique,
|
|
7957
|
+
sessionkinds,
|
|
6642
7958
|
sessionmemory,
|
|
7959
|
+
sessionnameunique,
|
|
7960
|
+
sessionreport,
|
|
7961
|
+
sessionrestoregate,
|
|
7962
|
+
sessiontabof,
|
|
6643
7963
|
shiftentryof,
|
|
6644
7964
|
signalsreport,
|
|
7965
|
+
snapshotplanof,
|
|
7966
|
+
snapshotretentionwindow,
|
|
7967
|
+
snapshotsections,
|
|
6645
7968
|
socketgate,
|
|
6646
7969
|
socketkinds,
|
|
6647
7970
|
sourcemapconsentcovers,
|
|
@@ -6653,6 +7976,7 @@ export {
|
|
|
6653
7976
|
stackgate,
|
|
6654
7977
|
statusclassof,
|
|
6655
7978
|
stepmodeof,
|
|
7979
|
+
steptemplateof,
|
|
6656
7980
|
stepwindows,
|
|
6657
7981
|
streamsummaries,
|
|
6658
7982
|
streamwindowof,
|
|
@@ -6660,6 +7984,9 @@ export {
|
|
|
6660
7984
|
subscriptionoptionsof,
|
|
6661
7985
|
tabreportresponse,
|
|
6662
7986
|
targetgate,
|
|
7987
|
+
taskstatechecksum,
|
|
7988
|
+
taskstateof,
|
|
7989
|
+
taskstatevalid,
|
|
6663
7990
|
teardowncdpsession,
|
|
6664
7991
|
teardownplanof,
|
|
6665
7992
|
templateurl,
|
|
@@ -6683,13 +8010,22 @@ export {
|
|
|
6683
8010
|
validatebreakpointcondition,
|
|
6684
8011
|
validatefieldmatch,
|
|
6685
8012
|
validateformrecord,
|
|
8013
|
+
validateregexrule,
|
|
6686
8014
|
validatestep,
|
|
6687
8015
|
validatetargetref,
|
|
6688
8016
|
validatevaluegen,
|
|
8017
|
+
validateworkflow,
|
|
8018
|
+
waitelementplan,
|
|
6689
8019
|
watchcdpevents,
|
|
6690
8020
|
watcherdetached,
|
|
6691
8021
|
watchexpressionof,
|
|
6692
8022
|
watchgate,
|
|
6693
|
-
wizardreport
|
|
8023
|
+
wizardreport,
|
|
8024
|
+
workflowblockof,
|
|
8025
|
+
workflowgate,
|
|
8026
|
+
workflowkinds,
|
|
8027
|
+
workflowoutcome,
|
|
8028
|
+
workflowreport,
|
|
8029
|
+
workflowstepof
|
|
6694
8030
|
};
|
|
6695
8031
|
//# sourceMappingURL=index.js.map
|