@wenathlan/extension 1.1.37 → 1.1.38

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.
@@ -1,7 +1,7 @@
1
1
  // policy.ts
2
- 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"]);
2
+ 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"]);
3
3
  var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction"]);
4
- 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"]);
4
+ 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"]);
5
5
  var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
6
6
 
7
7
  // extension/tabscommand.ts
@@ -28,6 +28,19 @@ function cardmask(value) {
28
28
  return "\u2022".repeat(trimmed.length);
29
29
  }
30
30
 
31
+ // extension/datacommand.ts
32
+ function sortrows(rows, key, direction) {
33
+ const sign = direction === "desc" ? -1 : 1;
34
+ return [...rows].sort((left, right) => {
35
+ const a = left[key] ?? "";
36
+ const b = right[key] ?? "";
37
+ const numeric = Number(a);
38
+ const numericb = Number(b);
39
+ if (Number.isFinite(numeric) && Number.isFinite(numericb) && a.trim() !== "" && b.trim() !== "") return (numeric - numericb) * sign;
40
+ return a.localeCompare(b) * sign;
41
+ });
42
+ }
43
+
31
44
  // extension/sidepanel.ts
32
45
  var objective = document.querySelector("#objective");
33
46
  var localbutton = document.querySelector("#localplan");
@@ -48,6 +61,7 @@ var trailroot = document.querySelector("#trail");
48
61
  var navigationroot = document.querySelector("#navigation");
49
62
  var tabswindowsroot = document.querySelector("#tabswindows");
50
63
  var formsroot = document.querySelector("#forms");
64
+ var datasetsroot = document.querySelector("#datasets");
51
65
  var statusnode = document.querySelector("#status");
52
66
  var progressnode = document.querySelector("#planprogress");
53
67
  var capabilitiestext = document.querySelector("#capabilitiestext");
@@ -150,6 +164,19 @@ function quietdetail(step, outcomes) {
150
164
  node.textContent = `network quiet: ${samples.length} sample${samples.length === 1 ? "" : "s"} \xB7 quiet for ${Math.round(last?.quietfor ?? 0)} ms \xB7 idle threshold ${idle} ms \xB7 ${latest.ok ? "quiet reached" : "still busy"}`;
151
165
  return node;
152
166
  }
167
+ function loopdetail(step, progress) {
168
+ if (step.kind !== "looprows") return null;
169
+ const iterations = (progress?.outcomes ?? []).filter((outcome) => outcome.stepid === step.id && outcome.details?.iteration !== void 0);
170
+ if (iterations.length === 0) return null;
171
+ const node = document.createElement("p");
172
+ node.className = "timeline";
173
+ const latest = iterations[iterations.length - 1];
174
+ if (!latest) return null;
175
+ const variables = latest.details?.variables;
176
+ const shown = variables ? Object.entries(variables).slice(0, 4).map(([key, value]) => `${key}=${value}`).join(", ") : "";
177
+ node.textContent = `loop timeline: ${iterations.length} iteration${iterations.length === 1 ? "" : "s"} \xB7 ${String(latest.details?.variable ?? "row")} variables ${shown}`;
178
+ return node;
179
+ }
153
180
  function navlistdetail(step, progress, outcomes) {
154
181
  if (step.kind !== "navlist") return null;
155
182
  const entries = (progress?.outcomes ?? []).filter((outcome) => outcome.stepid === step.id && outcome.details?.naventry !== void 0).map((outcome) => outcome.details?.naventry);
@@ -208,6 +235,8 @@ function stepitem(plan, step, completed, outcomes, retries, progress) {
208
235
  if (timeline) item.append(timeline);
209
236
  const navlist = navlistdetail(step, progress, outcomes);
210
237
  if (navlist) item.append(navlist);
238
+ const loopvars = loopdetail(step, progress);
239
+ if (loopvars) item.append(loopvars);
211
240
  const redirects = redirectdetail(step, outcomes);
212
241
  if (redirects) item.append(redirects);
213
242
  const preview = renderpreview(step);
@@ -965,6 +994,147 @@ function renderforms(context) {
965
994
  }
966
995
  formsroot.append(codecard);
967
996
  }
997
+ function renderdatasets(context) {
998
+ if (!datasetsroot) return;
999
+ datasetsroot.replaceChildren();
1000
+ const outcomes = context.outcomes ?? [];
1001
+ const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();
1002
+ const extractsessions = context.extractsessions ?? [];
1003
+ for (const extract of extractsessions.slice(0, 4)) {
1004
+ const card = document.createElement("p");
1005
+ const interrupted2 = extract.done !== true;
1006
+ card.textContent = `extraction ${extract.name}: ${extract.pages.length} page${extract.pages.length === 1 ? "" : "s"} visited \xB7 ${extract.rows} row${extract.rows === 1 ? "" : "s"} collected \xB7 cursor ${extract.cursor} of ${extract.planned}${extract.done ? " \xB7 complete" : " \xB7 interrupted"}`;
1007
+ datasetsroot.append(card);
1008
+ }
1009
+ const interrupted = extractsessions.find((extract) => extract.done !== true);
1010
+ if (interrupted && active) {
1011
+ const prompt = document.createElement("div");
1012
+ prompt.className = "bannercard";
1013
+ prompt.textContent = `Extraction ${interrupted.name} was interrupted at cursor ${interrupted.cursor}; run its resumeextract reviewed step to continue from the stored cursor.`;
1014
+ datasetsroot.append(prompt);
1015
+ }
1016
+ const streams = context.streams ?? [];
1017
+ if (streams.length > 0) {
1018
+ const stream = streams[0];
1019
+ const card = document.createElement("p");
1020
+ card.textContent = `stream state: ${stream.name} chunk ${stream.chunk} of ${stream.chunks} \xB7 ${stream.written} row${stream.written === 1 ? "" : "s"} written${stream.done ? " \xB7 complete" : " \xB7 resumable"}`;
1021
+ datasetsroot.append(card);
1022
+ }
1023
+ const rules = (context.taskrules ?? [])[0];
1024
+ if (rules && rules.transforms.length > 0) {
1025
+ const transforms = document.createElement("p");
1026
+ transforms.textContent = `transform rules: ${rules.transforms.map((rule) => `${rule.sources.join("+")} \u2192 ${rule.target} (${rule.expression})`).join(" \xB7 ")}`;
1027
+ datasetsroot.append(transforms);
1028
+ }
1029
+ if (rules && rules.dedupekeys.length > 0) {
1030
+ const keys = document.createElement("p");
1031
+ keys.textContent = `dedupe keys: ${rules.dedupekeys.join(", ")}`;
1032
+ datasetsroot.append(keys);
1033
+ }
1034
+ const dedupeoutcome = [...outcomes].reverse().find((outcome) => outcome.details?.dedupe !== void 0);
1035
+ if (dedupeoutcome) {
1036
+ const dedupe = dedupeoutcome.details?.dedupe;
1037
+ const card = document.createElement("p");
1038
+ card.textContent = `last dedupe: removed ${dedupe.removed} duplicate row${dedupe.removed === 1 ? "" : "s"}, kept ${dedupe.kept} by ${dedupe.keys.join(", ")}`;
1039
+ datasetsroot.append(card);
1040
+ }
1041
+ for (const datasetvalue of (context.datasets ?? []).slice(0, 4)) {
1042
+ const card = document.createElement("div");
1043
+ card.className = "panel";
1044
+ const head = document.createElement("p");
1045
+ head.textContent = `dataset ${datasetvalue.name}: ${datasetvalue.rows.length} row${datasetvalue.rows.length === 1 ? "" : "s"} \xB7 ${datasetvalue.columns.length} column${datasetvalue.columns.length === 1 ? "" : "s"}${(context.imports ?? []).some((item) => item.id === datasetvalue.id) ? " \xB7 imported csv" : ""}`;
1046
+ card.append(head);
1047
+ const grid = document.createElement("table");
1048
+ const headerrow = document.createElement("tr");
1049
+ for (const column of datasetvalue.columns.slice(0, 6)) {
1050
+ const cell = document.createElement("th");
1051
+ cell.textContent = `${column.label || column.key} ${column.kind === "number" ? "#" : ""}`;
1052
+ cell.addEventListener("click", () => {
1053
+ const body2 = grid.querySelector("tbody");
1054
+ if (!body2) return;
1055
+ const sorted = sortrows(datasetvalue.rows.slice(0, 5), column.key, cell.dataset.sorted === "asc" ? "desc" : "asc");
1056
+ cell.dataset.sorted = cell.dataset.sorted === "asc" ? "desc" : "asc";
1057
+ body2.replaceChildren(...sorted.map((row) => {
1058
+ const line = document.createElement("tr");
1059
+ for (const columnspec of datasetvalue.columns.slice(0, 6)) {
1060
+ const value = document.createElement("td");
1061
+ value.textContent = row[columnspec.key] ?? "";
1062
+ line.append(value);
1063
+ }
1064
+ return line;
1065
+ }));
1066
+ });
1067
+ headerrow.append(cell);
1068
+ }
1069
+ grid.append(headerrow);
1070
+ const body = document.createElement("tbody");
1071
+ for (const row of datasetvalue.rows.slice(0, 5)) {
1072
+ const line = document.createElement("tr");
1073
+ for (const column of datasetvalue.columns.slice(0, 6)) {
1074
+ const cell = document.createElement("td");
1075
+ cell.textContent = row[column.key] ?? "";
1076
+ line.append(cell);
1077
+ }
1078
+ body.append(line);
1079
+ }
1080
+ grid.append(body);
1081
+ card.append(grid);
1082
+ if (active) {
1083
+ const actions = document.createElement("p");
1084
+ for (const format of ["csv", "json", "excel"]) {
1085
+ actions.append(" ", button(`Export ${format}`, async () => {
1086
+ const artifact = await request({ kind: "exportdataset", datasetid: datasetvalue.id, format });
1087
+ status(`Exported ${datasetvalue.name} to ${artifact.name} with checksum ${artifact.checksum}.`);
1088
+ await refresh();
1089
+ }));
1090
+ }
1091
+ card.append(actions);
1092
+ }
1093
+ datasetsroot.append(card);
1094
+ }
1095
+ const provenances = context.provenances ?? [];
1096
+ if (provenances.length > 0) {
1097
+ const list = document.createElement("ul");
1098
+ for (const record of provenances.slice(0, 6)) {
1099
+ const item = document.createElement("li");
1100
+ item.textContent = `${record.name}: rows ${record.rowstart}\u2013${record.rowend} \xB7 checksum ${record.checksum} \xB7 source ${record.url}`;
1101
+ list.append(item);
1102
+ }
1103
+ datasetsroot.append(list);
1104
+ }
1105
+ const sheetendpoints = context.sheetendpoints ?? [];
1106
+ if (sheetendpoints.length > 0) {
1107
+ const sheets = document.createElement("p");
1108
+ sheets.textContent = `sheet endpoints: ${sheetendpoints.map((config) => `${config.origin} ${config.granted ? "granted" : "not granted"}`).join(" \xB7 ")}`;
1109
+ datasetsroot.append(sheets);
1110
+ }
1111
+ if (active) {
1112
+ const importer = document.createElement("div");
1113
+ importer.className = "panel";
1114
+ const csvinput = document.createElement("textarea");
1115
+ csvinput.rows = 3;
1116
+ csvinput.placeholder = "Paste reviewed csv content for a fill loop (header line first).";
1117
+ const nameinput = document.createElement("input");
1118
+ nameinput.placeholder = "dataset name (optional)";
1119
+ const mappinginput = document.createElement("input");
1120
+ mappinginput.placeholder = "column mapping json (optional, csv header \u2192 target)";
1121
+ importer.append(csvinput, nameinput, mappinginput, " ", button("Import csv", async () => {
1122
+ let mapping = {};
1123
+ if (mappinginput.value.trim()) {
1124
+ try {
1125
+ mapping = JSON.parse(mappinginput.value);
1126
+ } catch {
1127
+ status("The column mapping must be a json object.", true);
1128
+ return;
1129
+ }
1130
+ }
1131
+ const imported = await request({ kind: "importcsv", csv: csvinput.value, name: nameinput.value, mapping });
1132
+ status(`Imported ${imported.rows} rows as dataset ${imported.name} for fill loops.`);
1133
+ await refresh();
1134
+ }));
1135
+ datasetsroot.append(importer);
1136
+ }
1137
+ }
968
1138
  function rendercapabilities(report) {
969
1139
  if (!capabilitiestext) return;
970
1140
  if (!report) {
@@ -1012,6 +1182,7 @@ async function refresh() {
1012
1182
  rendernavigation(context);
1013
1183
  rendertabswindows(context);
1014
1184
  renderforms(context);
1185
+ renderdatasets(context);
1015
1186
  renderaudit(context.audit);
1016
1187
  rendercapabilities(context.capabilities);
1017
1188
  if (context.session?.pausedat) status("Session paused. Reviewed actions are blocked until resume.");