@hasna/browser 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7451,6 +7451,261 @@ function inferUseCase(label) {
7451
7451
  };
7452
7452
  return map[label.toLowerCase()] ?? "spa_navigate" /* SPA_NAVIGATE */;
7453
7453
  }
7454
+ // src/lib/network.ts
7455
+ function enableNetworkLogging(page, sessionId) {
7456
+ const requestStart = new Map;
7457
+ const onRequest = (req) => {
7458
+ requestStart.set(req.url(), Date.now());
7459
+ };
7460
+ const onResponse = (res) => {
7461
+ const start = requestStart.get(res.url()) ?? Date.now();
7462
+ const duration = Date.now() - start;
7463
+ const req = res.request();
7464
+ try {
7465
+ logRequest({
7466
+ session_id: sessionId,
7467
+ method: req.method(),
7468
+ url: res.url(),
7469
+ status_code: res.status(),
7470
+ request_headers: JSON.stringify(req.headers()),
7471
+ response_headers: JSON.stringify(res.headers()),
7472
+ body_size: res.headers()["content-length"] != null ? parseInt(res.headers()["content-length"]) : undefined,
7473
+ duration_ms: duration,
7474
+ resource_type: req.resourceType()
7475
+ });
7476
+ } catch {}
7477
+ };
7478
+ page.on("request", onRequest);
7479
+ page.on("response", onResponse);
7480
+ return () => {
7481
+ page.off("request", onRequest);
7482
+ page.off("response", onResponse);
7483
+ };
7484
+ }
7485
+ async function addInterceptRule(page, rule) {
7486
+ await page.route(rule.pattern, async (route) => {
7487
+ if (rule.action === "block") {
7488
+ await route.abort();
7489
+ } else if (rule.action === "modify" && rule.response) {
7490
+ await route.fulfill({
7491
+ status: rule.response.status,
7492
+ body: rule.response.body,
7493
+ headers: rule.response.headers
7494
+ });
7495
+ } else {
7496
+ await route.continue();
7497
+ }
7498
+ });
7499
+ }
7500
+ async function clearInterceptRules(page) {
7501
+ await page.unrouteAll();
7502
+ }
7503
+ function startHAR(page) {
7504
+ const entries = [];
7505
+ const requestStart = new Map;
7506
+ const onRequest = (req) => {
7507
+ requestStart.set(req.url() + req.method(), {
7508
+ time: Date.now(),
7509
+ method: req.method(),
7510
+ headers: req.headers(),
7511
+ postData: req.postData() ?? undefined
7512
+ });
7513
+ };
7514
+ const onResponse = async (res) => {
7515
+ const key = res.url() + res.request().method();
7516
+ const start = requestStart.get(key);
7517
+ if (!start)
7518
+ return;
7519
+ const duration = Date.now() - start.time;
7520
+ const entry = {
7521
+ startedDateTime: new Date(start.time).toISOString(),
7522
+ time: duration,
7523
+ request: {
7524
+ method: start.method,
7525
+ url: res.url(),
7526
+ headers: Object.entries(start.headers).map(([name, value]) => ({ name, value })),
7527
+ postData: start.postData ? { text: start.postData } : undefined
7528
+ },
7529
+ response: {
7530
+ status: res.status(),
7531
+ statusText: res.statusText(),
7532
+ headers: Object.entries(res.headers()).map(([name, value]) => ({ name, value })),
7533
+ content: {
7534
+ size: parseInt(res.headers()["content-length"] ?? "0") || 0,
7535
+ mimeType: res.headers()["content-type"] ?? "application/octet-stream"
7536
+ }
7537
+ },
7538
+ timings: { send: 0, wait: duration, receive: 0 }
7539
+ };
7540
+ entries.push(entry);
7541
+ requestStart.delete(key);
7542
+ };
7543
+ page.on("request", onRequest);
7544
+ page.on("response", onResponse);
7545
+ return {
7546
+ entries,
7547
+ stop: () => {
7548
+ page.off("request", onRequest);
7549
+ page.off("response", onResponse);
7550
+ return {
7551
+ log: {
7552
+ version: "1.2",
7553
+ creator: { name: "@hasna/browser", version: "0.0.1" },
7554
+ entries
7555
+ }
7556
+ };
7557
+ }
7558
+ };
7559
+ }
7560
+
7561
+ // src/lib/console.ts
7562
+ function enableConsoleCapture(page, sessionId) {
7563
+ const onConsole = (msg) => {
7564
+ const levelMap = {
7565
+ log: "log",
7566
+ warn: "warn",
7567
+ error: "error",
7568
+ debug: "debug",
7569
+ info: "info",
7570
+ warning: "warn"
7571
+ };
7572
+ const level = levelMap[msg.type()] ?? "log";
7573
+ const location = msg.location();
7574
+ try {
7575
+ logConsoleMessage({
7576
+ session_id: sessionId,
7577
+ level,
7578
+ message: msg.text(),
7579
+ source: location.url || undefined,
7580
+ line_number: location.lineNumber || undefined
7581
+ });
7582
+ } catch {}
7583
+ };
7584
+ page.on("console", onConsole);
7585
+ return () => page.off("console", onConsole);
7586
+ }
7587
+ async function capturePageErrors(page, sessionId) {
7588
+ const onError = (err) => {
7589
+ try {
7590
+ logConsoleMessage({
7591
+ session_id: sessionId,
7592
+ level: "error",
7593
+ message: `[Page Error] ${err.message}`,
7594
+ source: err.stack?.split(`
7595
+ `)[1]?.trim()
7596
+ });
7597
+ } catch {}
7598
+ };
7599
+ page.on("pageerror", onError);
7600
+ return () => page.off("pageerror", onError);
7601
+ }
7602
+
7603
+ // src/lib/stealth.ts
7604
+ var REALISTIC_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36";
7605
+ var STEALTH_SCRIPT = `
7606
+ // \u2500\u2500 1. Remove navigator.webdriver flag \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
7607
+ Object.defineProperty(navigator, 'webdriver', {
7608
+ get: () => false,
7609
+ configurable: true,
7610
+ });
7611
+
7612
+ // \u2500\u2500 2. Override navigator.plugins to show typical Chrome plugins \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
7613
+ Object.defineProperty(navigator, 'plugins', {
7614
+ get: () => {
7615
+ const plugins = [
7616
+ { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format', length: 1 },
7617
+ { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '', length: 1 },
7618
+ { name: 'Native Client', filename: 'internal-nacl-plugin', description: '', length: 2 },
7619
+ ];
7620
+ // Mimic PluginArray interface
7621
+ const pluginArray = Object.create(PluginArray.prototype);
7622
+ plugins.forEach((p, i) => {
7623
+ const plugin = Object.create(Plugin.prototype);
7624
+ Object.defineProperties(plugin, {
7625
+ name: { value: p.name, enumerable: true },
7626
+ filename: { value: p.filename, enumerable: true },
7627
+ description: { value: p.description, enumerable: true },
7628
+ length: { value: p.length, enumerable: true },
7629
+ });
7630
+ pluginArray[i] = plugin;
7631
+ });
7632
+ Object.defineProperty(pluginArray, 'length', { value: plugins.length });
7633
+ pluginArray.item = (i) => pluginArray[i] || null;
7634
+ pluginArray.namedItem = (name) => plugins.find(p => p.name === name) ? pluginArray[plugins.findIndex(p => p.name === name)] : null;
7635
+ pluginArray.refresh = () => {};
7636
+ return pluginArray;
7637
+ },
7638
+ configurable: true,
7639
+ });
7640
+
7641
+ // \u2500\u2500 3. Override navigator.languages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
7642
+ Object.defineProperty(navigator, 'languages', {
7643
+ get: () => ['en-US', 'en'],
7644
+ configurable: true,
7645
+ });
7646
+
7647
+ // \u2500\u2500 4. Override chrome.runtime to appear like real Chrome \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
7648
+ if (!window.chrome) {
7649
+ window.chrome = {};
7650
+ }
7651
+ if (!window.chrome.runtime) {
7652
+ window.chrome.runtime = {
7653
+ connect: function() { return { onMessage: { addListener: function() {} }, postMessage: function() {} }; },
7654
+ sendMessage: function() {},
7655
+ onMessage: { addListener: function() {}, removeListener: function() {} },
7656
+ id: undefined,
7657
+ };
7658
+ }
7659
+ `;
7660
+ async function applyStealthPatches(page) {
7661
+ await page.context().addInitScript(STEALTH_SCRIPT);
7662
+ await page.context().setExtraHTTPHeaders({
7663
+ "User-Agent": REALISTIC_USER_AGENT
7664
+ });
7665
+ }
7666
+
7667
+ // src/lib/dialogs.ts
7668
+ var pendingDialogs = new Map;
7669
+ var AUTO_DISMISS_MS = 5000;
7670
+ function setupDialogHandler(page, sessionId) {
7671
+ const onDialog = (dialog) => {
7672
+ const info = {
7673
+ type: dialog.type(),
7674
+ message: dialog.message(),
7675
+ default_value: dialog.defaultValue(),
7676
+ timestamp: new Date().toISOString()
7677
+ };
7678
+ const autoTimer = setTimeout(() => {
7679
+ try {
7680
+ dialog.dismiss().catch(() => {});
7681
+ } catch {}
7682
+ const list = pendingDialogs.get(sessionId);
7683
+ if (list) {
7684
+ const idx = list.findIndex((p) => p.dialog === dialog);
7685
+ if (idx >= 0)
7686
+ list.splice(idx, 1);
7687
+ if (list.length === 0)
7688
+ pendingDialogs.delete(sessionId);
7689
+ }
7690
+ }, AUTO_DISMISS_MS);
7691
+ const pending = { dialog, info, autoTimer };
7692
+ if (!pendingDialogs.has(sessionId)) {
7693
+ pendingDialogs.set(sessionId, []);
7694
+ }
7695
+ pendingDialogs.get(sessionId).push(pending);
7696
+ };
7697
+ page.on("dialog", onDialog);
7698
+ return () => {
7699
+ page.off("dialog", onDialog);
7700
+ const list = pendingDialogs.get(sessionId);
7701
+ if (list) {
7702
+ for (const p of list)
7703
+ clearTimeout(p.autoTimer);
7704
+ pendingDialogs.delete(sessionId);
7705
+ }
7706
+ };
7707
+ }
7708
+
7454
7709
  // src/lib/session.ts
7455
7710
  var handles = new Map;
7456
7711
  async function createSession2(opts = {}) {
@@ -7477,13 +7732,33 @@ async function createSession2(opts = {}) {
7477
7732
  engine: resolvedEngine,
7478
7733
  projectId: opts.projectId,
7479
7734
  agentId: opts.agentId,
7480
- startUrl: opts.startUrl
7735
+ startUrl: opts.startUrl,
7736
+ name: opts.name ?? (opts.startUrl ? new URL(opts.startUrl).hostname : undefined)
7481
7737
  });
7482
- handles.set(session.id, { browser, page, engine: resolvedEngine });
7738
+ if (opts.stealth) {
7739
+ try {
7740
+ await applyStealthPatches(page);
7741
+ } catch {}
7742
+ }
7743
+ const cleanups = [];
7744
+ if (opts.captureNetwork !== false) {
7745
+ try {
7746
+ cleanups.push(enableNetworkLogging(page, session.id));
7747
+ } catch {}
7748
+ }
7749
+ if (opts.captureConsole !== false) {
7750
+ try {
7751
+ cleanups.push(enableConsoleCapture(page, session.id));
7752
+ } catch {}
7753
+ }
7754
+ try {
7755
+ cleanups.push(setupDialogHandler(page, session.id));
7756
+ } catch {}
7757
+ handles.set(session.id, { browser, page, engine: resolvedEngine, cleanups, tokenBudget: { total: 0, used: 0 } });
7483
7758
  if (opts.startUrl) {
7484
7759
  try {
7485
7760
  await page.goto(opts.startUrl, { waitUntil: "domcontentloaded" });
7486
- } catch (err) {}
7761
+ } catch {}
7487
7762
  }
7488
7763
  return { session, page };
7489
7764
  }
@@ -7491,6 +7766,12 @@ function getSessionPage(sessionId) {
7491
7766
  const handle = handles.get(sessionId);
7492
7767
  if (!handle)
7493
7768
  throw new SessionNotFoundError(sessionId);
7769
+ try {
7770
+ handle.page.url();
7771
+ } catch {
7772
+ handles.delete(sessionId);
7773
+ throw new SessionNotFoundError(sessionId);
7774
+ }
7494
7775
  return handle.page;
7495
7776
  }
7496
7777
  function getSessionBrowser(sessionId) {
@@ -7508,9 +7789,20 @@ function getSessionEngine(sessionId) {
7508
7789
  function hasActiveHandle(sessionId) {
7509
7790
  return handles.has(sessionId);
7510
7791
  }
7792
+ function setSessionPage(sessionId, page) {
7793
+ const handle = handles.get(sessionId);
7794
+ if (!handle)
7795
+ throw new SessionNotFoundError(sessionId);
7796
+ handle.page = page;
7797
+ }
7511
7798
  async function closeSession2(sessionId) {
7512
7799
  const handle = handles.get(sessionId);
7513
7800
  if (handle) {
7801
+ for (const cleanup of handle.cleanups) {
7802
+ try {
7803
+ cleanup();
7804
+ } catch {}
7805
+ }
7514
7806
  try {
7515
7807
  await handle.page.context().close();
7516
7808
  } catch {}
@@ -7538,6 +7830,23 @@ function getSessionByName2(name) {
7538
7830
  function renameSession2(id, name) {
7539
7831
  return renameSession(id, name);
7540
7832
  }
7833
+ function getTokenBudget(sessionId) {
7834
+ const handle = handles.get(sessionId);
7835
+ return handle ? handle.tokenBudget : null;
7836
+ }
7837
+ // src/lib/snapshot.ts
7838
+ var lastSnapshots = new Map;
7839
+ var sessionRefMaps = new Map;
7840
+ function getRefLocator(page, sessionId, ref) {
7841
+ const refMap = sessionRefMaps.get(sessionId);
7842
+ if (!refMap)
7843
+ throw new Error(`No snapshot taken for session ${sessionId}. Call browser_snapshot first.`);
7844
+ const entry = refMap.get(ref);
7845
+ if (!entry)
7846
+ throw new Error(`Ref ${ref} not found. Available refs: ${[...refMap.keys()].slice(0, 20).join(", ")}`);
7847
+ return page.getByRole(entry.role, { name: entry.name }).first();
7848
+ }
7849
+
7541
7850
  // src/lib/actions.ts
7542
7851
  async function click(page, selector, opts) {
7543
7852
  try {
@@ -7780,6 +8089,73 @@ function stopWatch(watchId) {
7780
8089
  activeWatches.delete(watchId);
7781
8090
  }
7782
8091
  }
8092
+ async function clickRef(page, sessionId, ref, opts) {
8093
+ try {
8094
+ const locator = getRefLocator(page, sessionId, ref);
8095
+ await locator.click({ timeout: opts?.timeout ?? 1e4 });
8096
+ } catch (err) {
8097
+ if (err instanceof Error && err.message.includes("Ref "))
8098
+ throw new ElementNotFoundError(ref);
8099
+ if (err instanceof Error && err.message.includes("No snapshot"))
8100
+ throw new BrowserError(err.message, "NO_SNAPSHOT");
8101
+ throw new BrowserError(`clickRef ${ref} failed: ${err instanceof Error ? err.message : String(err)}`, "CLICK_REF_FAILED");
8102
+ }
8103
+ }
8104
+ async function typeRef(page, sessionId, ref, text, opts) {
8105
+ try {
8106
+ const locator = getRefLocator(page, sessionId, ref);
8107
+ if (opts?.clear)
8108
+ await locator.fill("", { timeout: opts.timeout ?? 1e4 });
8109
+ await locator.pressSequentially(text, { delay: opts?.delay, timeout: opts?.timeout ?? 1e4 });
8110
+ } catch (err) {
8111
+ if (err instanceof Error && err.message.includes("Ref "))
8112
+ throw new ElementNotFoundError(ref);
8113
+ throw new BrowserError(`typeRef ${ref} failed: ${err instanceof Error ? err.message : String(err)}`, "TYPE_REF_FAILED");
8114
+ }
8115
+ }
8116
+ async function fillRef(page, sessionId, ref, value, timeout = 1e4) {
8117
+ try {
8118
+ const locator = getRefLocator(page, sessionId, ref);
8119
+ await locator.fill(value, { timeout });
8120
+ } catch (err) {
8121
+ if (err instanceof Error && err.message.includes("Ref "))
8122
+ throw new ElementNotFoundError(ref);
8123
+ throw new BrowserError(`fillRef ${ref} failed: ${err instanceof Error ? err.message : String(err)}`, "FILL_REF_FAILED");
8124
+ }
8125
+ }
8126
+ async function selectRef(page, sessionId, ref, value, timeout = 1e4) {
8127
+ try {
8128
+ const locator = getRefLocator(page, sessionId, ref);
8129
+ return await locator.selectOption(value, { timeout });
8130
+ } catch (err) {
8131
+ if (err instanceof Error && err.message.includes("Ref "))
8132
+ throw new ElementNotFoundError(ref);
8133
+ throw new BrowserError(`selectRef ${ref} failed: ${err instanceof Error ? err.message : String(err)}`, "SELECT_REF_FAILED");
8134
+ }
8135
+ }
8136
+ async function checkRef(page, sessionId, ref, checked, timeout = 1e4) {
8137
+ try {
8138
+ const locator = getRefLocator(page, sessionId, ref);
8139
+ if (checked)
8140
+ await locator.check({ timeout });
8141
+ else
8142
+ await locator.uncheck({ timeout });
8143
+ } catch (err) {
8144
+ if (err instanceof Error && err.message.includes("Ref "))
8145
+ throw new ElementNotFoundError(ref);
8146
+ throw new BrowserError(`checkRef ${ref} failed: ${err instanceof Error ? err.message : String(err)}`, "CHECK_REF_FAILED");
8147
+ }
8148
+ }
8149
+ async function hoverRef(page, sessionId, ref, timeout = 1e4) {
8150
+ try {
8151
+ const locator = getRefLocator(page, sessionId, ref);
8152
+ await locator.hover({ timeout });
8153
+ } catch (err) {
8154
+ if (err instanceof Error && err.message.includes("Ref "))
8155
+ throw new ElementNotFoundError(ref);
8156
+ throw new BrowserError(`hoverRef ${ref} failed: ${err instanceof Error ? err.message : String(err)}`, "HOVER_REF_FAILED");
8157
+ }
8158
+ }
7783
8159
  // src/lib/extractor.ts
7784
8160
  async function getText(page, selector) {
7785
8161
  if (selector) {
@@ -7934,112 +8310,6 @@ async function getPageInfo(page) {
7934
8310
  viewport
7935
8311
  };
7936
8312
  }
7937
- // src/lib/network.ts
7938
- function enableNetworkLogging(page, sessionId) {
7939
- const requestStart = new Map;
7940
- const onRequest = (req) => {
7941
- requestStart.set(req.url(), Date.now());
7942
- };
7943
- const onResponse = (res) => {
7944
- const start = requestStart.get(res.url()) ?? Date.now();
7945
- const duration = Date.now() - start;
7946
- const req = res.request();
7947
- try {
7948
- logRequest({
7949
- session_id: sessionId,
7950
- method: req.method(),
7951
- url: res.url(),
7952
- status_code: res.status(),
7953
- request_headers: JSON.stringify(req.headers()),
7954
- response_headers: JSON.stringify(res.headers()),
7955
- body_size: res.headers()["content-length"] != null ? parseInt(res.headers()["content-length"]) : undefined,
7956
- duration_ms: duration,
7957
- resource_type: req.resourceType()
7958
- });
7959
- } catch {}
7960
- };
7961
- page.on("request", onRequest);
7962
- page.on("response", onResponse);
7963
- return () => {
7964
- page.off("request", onRequest);
7965
- page.off("response", onResponse);
7966
- };
7967
- }
7968
- async function addInterceptRule(page, rule) {
7969
- await page.route(rule.pattern, async (route) => {
7970
- if (rule.action === "block") {
7971
- await route.abort();
7972
- } else if (rule.action === "modify" && rule.response) {
7973
- await route.fulfill({
7974
- status: rule.response.status,
7975
- body: rule.response.body,
7976
- headers: rule.response.headers
7977
- });
7978
- } else {
7979
- await route.continue();
7980
- }
7981
- });
7982
- }
7983
- async function clearInterceptRules(page) {
7984
- await page.unrouteAll();
7985
- }
7986
- function startHAR(page) {
7987
- const entries = [];
7988
- const requestStart = new Map;
7989
- const onRequest = (req) => {
7990
- requestStart.set(req.url() + req.method(), {
7991
- time: Date.now(),
7992
- method: req.method(),
7993
- headers: req.headers(),
7994
- postData: req.postData() ?? undefined
7995
- });
7996
- };
7997
- const onResponse = async (res) => {
7998
- const key = res.url() + res.request().method();
7999
- const start = requestStart.get(key);
8000
- if (!start)
8001
- return;
8002
- const duration = Date.now() - start.time;
8003
- const entry = {
8004
- startedDateTime: new Date(start.time).toISOString(),
8005
- time: duration,
8006
- request: {
8007
- method: start.method,
8008
- url: res.url(),
8009
- headers: Object.entries(start.headers).map(([name, value]) => ({ name, value })),
8010
- postData: start.postData ? { text: start.postData } : undefined
8011
- },
8012
- response: {
8013
- status: res.status(),
8014
- statusText: res.statusText(),
8015
- headers: Object.entries(res.headers()).map(([name, value]) => ({ name, value })),
8016
- content: {
8017
- size: parseInt(res.headers()["content-length"] ?? "0") || 0,
8018
- mimeType: res.headers()["content-type"] ?? "application/octet-stream"
8019
- }
8020
- },
8021
- timings: { send: 0, wait: duration, receive: 0 }
8022
- };
8023
- entries.push(entry);
8024
- requestStart.delete(key);
8025
- };
8026
- page.on("request", onRequest);
8027
- page.on("response", onResponse);
8028
- return {
8029
- entries,
8030
- stop: () => {
8031
- page.off("request", onRequest);
8032
- page.off("response", onResponse);
8033
- return {
8034
- log: {
8035
- version: "1.2",
8036
- creator: { name: "@hasna/browser", version: "0.0.1" },
8037
- entries
8038
- }
8039
- };
8040
- }
8041
- };
8042
- }
8043
8313
  // src/lib/performance.ts
8044
8314
  async function getPerformanceMetrics(page) {
8045
8315
  const navTiming = await page.evaluate(() => {
@@ -8127,47 +8397,6 @@ async function startCoverage(page) {
8127
8397
  }
8128
8398
  };
8129
8399
  }
8130
- // src/lib/console.ts
8131
- function enableConsoleCapture(page, sessionId) {
8132
- const onConsole = (msg) => {
8133
- const levelMap = {
8134
- log: "log",
8135
- warn: "warn",
8136
- error: "error",
8137
- debug: "debug",
8138
- info: "info",
8139
- warning: "warn"
8140
- };
8141
- const level = levelMap[msg.type()] ?? "log";
8142
- const location = msg.location();
8143
- try {
8144
- logConsoleMessage({
8145
- session_id: sessionId,
8146
- level,
8147
- message: msg.text(),
8148
- source: location.url || undefined,
8149
- line_number: location.lineNumber || undefined
8150
- });
8151
- } catch {}
8152
- };
8153
- page.on("console", onConsole);
8154
- return () => page.off("console", onConsole);
8155
- }
8156
- async function capturePageErrors(page, sessionId) {
8157
- const onError = (err) => {
8158
- try {
8159
- logConsoleMessage({
8160
- session_id: sessionId,
8161
- level: "error",
8162
- message: `[Page Error] ${err.message}`,
8163
- source: err.stack?.split(`
8164
- `)[1]?.trim()
8165
- });
8166
- } catch {}
8167
- };
8168
- page.on("pageerror", onError);
8169
- return () => page.off("pageerror", onError);
8170
- }
8171
8400
  // src/lib/screenshot.ts
8172
8401
  var import_sharp = __toESM(require_lib(), 1);
8173
8402
  import { join as join2 } from "path";
@@ -8673,6 +8902,7 @@ export {
8673
8902
  updateRecording,
8674
8903
  updateProject,
8675
8904
  updateAgent,
8905
+ typeRef,
8676
8906
  type,
8677
8907
  takeScreenshot,
8678
8908
  stopWatch,
@@ -8682,8 +8912,10 @@ export {
8682
8912
  startHAR,
8683
8913
  startCoverage,
8684
8914
  setSessionStorage,
8915
+ setSessionPage,
8685
8916
  setLocalStorage,
8686
8917
  setCookie,
8918
+ selectRef,
8687
8919
  selectOption,
8688
8920
  selectEngine,
8689
8921
  scrollTo,
@@ -8712,6 +8944,7 @@ export {
8712
8944
  isEngineAvailable,
8713
8945
  isAgentStale,
8714
8946
  inferUseCase,
8947
+ hoverRef,
8715
8948
  hover,
8716
8949
  heartbeat2 as heartbeat,
8717
8950
  hasActiveHandle,
@@ -8719,6 +8952,7 @@ export {
8719
8952
  goBack,
8720
8953
  getWatchChanges,
8721
8954
  getUrl,
8955
+ getTokenBudget,
8722
8956
  getTitle,
8723
8957
  getTimingEntries,
8724
8958
  getText,
@@ -8758,6 +8992,7 @@ export {
8758
8992
  getActiveAgents,
8759
8993
  generatePDF,
8760
8994
  findElements,
8995
+ fillRef,
8761
8996
  fillForm,
8762
8997
  fill,
8763
8998
  extractTable,
@@ -8795,6 +9030,7 @@ export {
8795
9030
  closeBrowser,
8796
9031
  closeAllSessions,
8797
9032
  clickText,
9033
+ clickRef,
8798
9034
  click,
8799
9035
  clearSessionStorage,
8800
9036
  clearNetworkLog,
@@ -8804,6 +9040,7 @@ export {
8804
9040
  clearConsoleLog,
8805
9041
  cleanStaleAgents,
8806
9042
  cleanOldHeartbeats,
9043
+ checkRef,
8807
9044
  checkBox,
8808
9045
  capturePageErrors,
8809
9046
  attachPageListeners,
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=actions-ref.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions-ref.test.d.ts","sourceRoot":"","sources":["../../src/lib/actions-ref.test.ts"],"names":[],"mappings":""}
@@ -58,4 +58,16 @@ export declare function watchPage(page: Page, opts?: {
58
58
  }): WatchHandle;
59
59
  export declare function getWatchChanges(watchId: string): string[];
60
60
  export declare function stopWatch(watchId: string): void;
61
+ export declare function clickRef(page: Page, sessionId: string, ref: string, opts?: {
62
+ timeout?: number;
63
+ }): Promise<void>;
64
+ export declare function typeRef(page: Page, sessionId: string, ref: string, text: string, opts?: {
65
+ delay?: number;
66
+ clear?: boolean;
67
+ timeout?: number;
68
+ }): Promise<void>;
69
+ export declare function fillRef(page: Page, sessionId: string, ref: string, value: string, timeout?: number): Promise<void>;
70
+ export declare function selectRef(page: Page, sessionId: string, ref: string, value: string, timeout?: number): Promise<string[]>;
71
+ export declare function checkRef(page: Page, sessionId: string, ref: string, checked: boolean, timeout?: number): Promise<void>;
72
+ export declare function hoverRef(page: Page, sessionId: string, ref: string, timeout?: number): Promise<void>;
61
73
  //# sourceMappingURL=actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/lib/actions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/lib/actions.ts"],"names":[],"mappings":"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"}