opensteer 0.9.3 → 0.9.5

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.
Files changed (38) hide show
  1. package/README.md +158 -165
  2. package/dist/{chunk-UM2Q4JD2.js → chunk-7D45QUZ3.js} +5 -7
  3. package/dist/chunk-7D45QUZ3.js.map +1 -0
  4. package/dist/{chunk-GREXSYNC.js → chunk-7LQL5YUR.js} +578 -224
  5. package/dist/chunk-7LQL5YUR.js.map +1 -0
  6. package/dist/{chunk-2TIVULZY.js → chunk-GSCQQKZZ.js} +53 -9
  7. package/dist/chunk-GSCQQKZZ.js.map +1 -0
  8. package/dist/{chunk-BMPUL66S.js → chunk-T5P2QGZ3.js} +58 -53
  9. package/dist/chunk-T5P2QGZ3.js.map +1 -0
  10. package/dist/{chunk-FIMNKEG5.js → chunk-ZRF7WMS3.js} +4 -4
  11. package/dist/{chunk-FIMNKEG5.js.map → chunk-ZRF7WMS3.js.map} +1 -1
  12. package/dist/cli/bin.cjs +707 -278
  13. package/dist/cli/bin.cjs.map +1 -1
  14. package/dist/cli/bin.js +30 -34
  15. package/dist/cli/bin.js.map +1 -1
  16. package/dist/index.cjs +733 -473
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +25 -460
  19. package/dist/index.d.ts +25 -460
  20. package/dist/index.js +4 -5
  21. package/dist/local-view/serve-entry.cjs +106 -57
  22. package/dist/local-view/serve-entry.cjs.map +1 -1
  23. package/dist/local-view/serve-entry.js +2 -2
  24. package/dist/opensteer-T2JENADR.js +6 -0
  25. package/dist/{opensteer-IBDPRIEX.js.map → opensteer-T2JENADR.js.map} +1 -1
  26. package/dist/{session-control-IFE3IPS3.js → session-control-M3JD7ZKA.js} +4 -4
  27. package/dist/{session-control-IFE3IPS3.js.map → session-control-M3JD7ZKA.js.map} +1 -1
  28. package/package.json +6 -6
  29. package/skills/opensteer/SKILL.md +134 -95
  30. package/skills/recorder/SKILL.md +43 -48
  31. package/dist/chunk-2TIVULZY.js.map +0 -1
  32. package/dist/chunk-BMPUL66S.js.map +0 -1
  33. package/dist/chunk-GREXSYNC.js.map +0 -1
  34. package/dist/chunk-KCINASQC.js +0 -3
  35. package/dist/chunk-KCINASQC.js.map +0 -1
  36. package/dist/chunk-UM2Q4JD2.js.map +0 -1
  37. package/dist/opensteer-IBDPRIEX.js +0 -6
  38. package/skills/recorder/references/recorder-reference.md +0 -71
package/dist/index.cjs CHANGED
@@ -4039,6 +4039,20 @@ var opensteerBrowserContextOptionsSchema = objectSchema(
4039
4039
  {
4040
4040
  title: "OpensteerStealthProfileInput"
4041
4041
  }
4042
+ ),
4043
+ humanize: oneOfSchema(
4044
+ [
4045
+ { type: "boolean" },
4046
+ objectSchema(
4047
+ {
4048
+ mouse: { type: "boolean" },
4049
+ keyboard: { type: "boolean" },
4050
+ scroll: { type: "boolean" }
4051
+ },
4052
+ { title: "OpensteerHumanizeOptions" }
4053
+ )
4054
+ ],
4055
+ { title: "OpensteerHumanize" }
4042
4056
  )
4043
4057
  },
4044
4058
  {
@@ -4431,10 +4445,10 @@ var opensteerDomScrollInputSchema = objectSchema(
4431
4445
  required: ["target", "direction", "amount"]
4432
4446
  }
4433
4447
  );
4434
- var opensteerExtractSchemaSchema = objectSchema(
4448
+ var opensteerExtractTemplateSchema = objectSchema(
4435
4449
  {},
4436
4450
  {
4437
- title: "OpensteerExtractSchema",
4451
+ title: "OpensteerExtractTemplate",
4438
4452
  additionalProperties: true
4439
4453
  }
4440
4454
  );
@@ -4442,13 +4456,13 @@ var opensteerDomExtractInputSchema = defineSchema({
4442
4456
  ...objectSchema(
4443
4457
  {
4444
4458
  persist: stringSchema(),
4445
- schema: opensteerExtractSchemaSchema
4459
+ template: opensteerExtractTemplateSchema
4446
4460
  },
4447
4461
  {
4448
4462
  title: "OpensteerDomExtractInput"
4449
4463
  }
4450
4464
  ),
4451
- anyOf: [defineSchema({ required: ["persist"] }), defineSchema({ required: ["schema"] })]
4465
+ anyOf: [defineSchema({ required: ["persist"] }), defineSchema({ required: ["template"] })]
4452
4466
  });
4453
4467
  var jsonValueSchema2 = recordSchema({}, { title: "JsonValueRecord" });
4454
4468
  var opensteerDomExtractOutputSchema = objectSchema(
@@ -6898,6 +6912,7 @@ var defaultNavigationSettleObserver = {
6898
6912
  return false;
6899
6913
  }
6900
6914
  try {
6915
+ const startedAt = Date.now();
6901
6916
  await input.engine.waitForPostLoadQuiet({
6902
6917
  pageRef: input.pageRef,
6903
6918
  timeoutMs: effectiveTimeout,
@@ -6905,9 +6920,13 @@ var defaultNavigationSettleObserver = {
6905
6920
  captureWindowMs: Math.min(NAVIGATION_POST_LOAD_CAPTURE_WINDOW_MS, effectiveTimeout),
6906
6921
  signal: input.signal
6907
6922
  });
6923
+ const visualTimeout = Math.max(0, effectiveTimeout - (Date.now() - startedAt));
6924
+ if (visualTimeout <= 0) {
6925
+ return true;
6926
+ }
6908
6927
  await input.engine.waitForVisualStability({
6909
6928
  pageRef: input.pageRef,
6910
- timeoutMs: effectiveTimeout,
6929
+ timeoutMs: visualTimeout,
6911
6930
  settleMs: profile.settleMs,
6912
6931
  scope: profile.scope
6913
6932
  });
@@ -11186,9 +11205,9 @@ function isPersistedObjectNode(node) {
11186
11205
  }
11187
11206
 
11188
11207
  // ../runtime-core/src/sdk/extraction.ts
11189
- function assertValidOpensteerExtractionSchemaRoot(schema) {
11190
- if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
11191
- throw new Error("Invalid extraction schema: expected a JSON object at the top level.");
11208
+ function assertValidOpensteerExtractionTemplateRoot(template) {
11209
+ if (!template || typeof template !== "object" || Array.isArray(template)) {
11210
+ throw new Error("Invalid extraction template: expected a JSON object at the top level.");
11192
11211
  }
11193
11212
  }
11194
11213
  function isPersistedOpensteerExtractionValueNode2(value) {
@@ -11210,12 +11229,12 @@ function isPersistedOpensteerExtractionArrayNode2(value) {
11210
11229
  return "$array" in value;
11211
11230
  }
11212
11231
  async function compileOpensteerExtractionFieldTargets(options) {
11213
- assertValidOpensteerExtractionSchemaRoot(options.schema);
11232
+ assertValidOpensteerExtractionTemplateRoot(options.template);
11214
11233
  const fields = [];
11215
- await collectFieldTargetsFromSchemaObject({
11234
+ await collectFieldTargetsFromTemplateObject({
11216
11235
  dom: options.dom,
11217
11236
  pageRef: options.pageRef,
11218
- value: options.schema,
11237
+ value: options.template,
11219
11238
  path: "",
11220
11239
  fields,
11221
11240
  insideArray: false
@@ -11267,13 +11286,13 @@ function createOpensteerExtractionDescriptorStore(options) {
11267
11286
  }
11268
11287
  return new MemoryOpensteerExtractionDescriptorStore(namespace);
11269
11288
  }
11270
- async function collectFieldTargetsFromSchemaObject(options) {
11289
+ async function collectFieldTargetsFromTemplateObject(options) {
11271
11290
  for (const [key, childValue] of Object.entries(options.value)) {
11272
11291
  const normalizedKey = normalizeKey(key);
11273
11292
  if (!normalizedKey) {
11274
11293
  continue;
11275
11294
  }
11276
- await collectFieldTargetsFromSchemaValue({
11295
+ await collectFieldTargetsFromTemplateValue({
11277
11296
  dom: options.dom,
11278
11297
  pageRef: options.pageRef,
11279
11298
  value: childValue,
@@ -11283,8 +11302,8 @@ async function collectFieldTargetsFromSchemaObject(options) {
11283
11302
  });
11284
11303
  }
11285
11304
  }
11286
- async function collectFieldTargetsFromSchemaValue(options) {
11287
- const normalizedField = normalizeSchemaField(options.value);
11305
+ async function collectFieldTargetsFromTemplateValue(options) {
11306
+ const normalizedField = normalizeTemplateField(options.value);
11288
11307
  if (normalizedField !== null) {
11289
11308
  options.fields.push(
11290
11309
  await compileFieldTarget({
@@ -11299,12 +11318,12 @@ async function collectFieldTargetsFromSchemaValue(options) {
11299
11318
  if (Array.isArray(options.value)) {
11300
11319
  if (options.insideArray) {
11301
11320
  throw new Error(
11302
- `Nested arrays are not supported in extraction schema at "${labelForPath(options.path)}".`
11321
+ `Nested arrays are not supported in extraction template at "${labelForPath(options.path)}".`
11303
11322
  );
11304
11323
  }
11305
11324
  if (options.value.length === 0) {
11306
11325
  throw new Error(
11307
- `Extraction array "${labelForPath(options.path)}" must include at least one representative item.`
11326
+ `Extraction array "${labelForPath(options.path)}" must include at least one representative template item.`
11308
11327
  );
11309
11328
  }
11310
11329
  for (let index = 0; index < options.value.length; index += 1) {
@@ -11315,7 +11334,7 @@ async function collectFieldTargetsFromSchemaValue(options) {
11315
11334
  );
11316
11335
  }
11317
11336
  const fieldCountBeforeItem = options.fields.length;
11318
- await collectFieldTargetsFromSchemaObject({
11337
+ await collectFieldTargetsFromTemplateObject({
11319
11338
  dom: options.dom,
11320
11339
  pageRef: options.pageRef,
11321
11340
  value: itemValue,
@@ -11326,7 +11345,7 @@ async function collectFieldTargetsFromSchemaValue(options) {
11326
11345
  const itemFields = options.fields.slice(fieldCountBeforeItem);
11327
11346
  if (!itemFields.some((field) => !("source" in field))) {
11328
11347
  throw new Error(
11329
- `Extraction array "${labelForPath(options.path)}" item ${String(index)} must include at least one element- or selector-backed field.`
11348
+ `Extraction array "${labelForPath(options.path)}" item ${String(index)} must include at least one element number or selector field.`
11330
11349
  );
11331
11350
  }
11332
11351
  }
@@ -11334,10 +11353,10 @@ async function collectFieldTargetsFromSchemaValue(options) {
11334
11353
  }
11335
11354
  if (!options.value || typeof options.value !== "object") {
11336
11355
  throw new Error(
11337
- `Invalid extraction schema value at "${labelForPath(options.path)}": expected an object, array, or field descriptor.`
11356
+ `Invalid extraction template value at "${labelForPath(options.path)}": expected an object, array, or field descriptor.`
11338
11357
  );
11339
11358
  }
11340
- await collectFieldTargetsFromSchemaObject({
11359
+ await collectFieldTargetsFromTemplateObject({
11341
11360
  dom: options.dom,
11342
11361
  pageRef: options.pageRef,
11343
11362
  value: options.value,
@@ -11369,7 +11388,7 @@ async function compileFieldTarget(options) {
11369
11388
  path: await resolveSelectorFieldPath({
11370
11389
  dom: options.dom,
11371
11390
  pageRef: options.pageRef,
11372
- selector: `[c="${String(options.field.element)}"]`
11391
+ selector: `[c="${String(options.field.c)}"]`
11373
11392
  }),
11374
11393
  ...options.field.attribute === void 0 ? {} : { attribute: options.field.attribute }
11375
11394
  };
@@ -11670,24 +11689,29 @@ function countNonNullLeaves(value) {
11670
11689
  }
11671
11690
  return Object.values(value).reduce((sum, item) => sum + countNonNullLeaves(item), 0);
11672
11691
  }
11673
- function normalizeSchemaField(value) {
11692
+ function normalizeTemplateField(value) {
11693
+ if (typeof value === "number") {
11694
+ return {
11695
+ c: normalizeExtractionCounter(value)
11696
+ };
11697
+ }
11674
11698
  if (!value || typeof value !== "object" || Array.isArray(value)) {
11675
11699
  return null;
11676
11700
  }
11677
11701
  const raw = value;
11678
- const hasElement = raw.element !== void 0;
11702
+ const hasCounter = raw.c !== void 0 || raw.element !== void 0;
11679
11703
  const hasSelector = raw.selector !== void 0;
11680
11704
  const hasSource = raw.source !== void 0;
11681
- const targetCount = Number(hasElement) + Number(hasSelector) + Number(hasSource);
11705
+ const targetCount = Number(hasCounter) + Number(hasSelector) + Number(hasSource);
11682
11706
  if (targetCount === 0) {
11683
11707
  return null;
11684
11708
  }
11685
11709
  if (targetCount !== 1) {
11686
11710
  throw new Error(
11687
- "Extraction field descriptors must specify exactly one of element, selector, or source."
11711
+ "Extraction field descriptors must specify exactly one of c/element, selector, or source."
11688
11712
  );
11689
11713
  }
11690
- const attribute = raw.attribute === void 0 ? void 0 : normalizeNonEmptyString2("attribute", raw.attribute);
11714
+ const attribute = raw.attr !== void 0 ? normalizeNonEmptyString2("attr", raw.attr) : raw.attribute === void 0 ? void 0 : normalizeNonEmptyString2("attribute", raw.attribute);
11691
11715
  if (hasSource) {
11692
11716
  if (raw.source !== "current_url") {
11693
11717
  throw new Error(`Unsupported extraction source "${String(raw.source)}".`);
@@ -11702,17 +11726,20 @@ function normalizeSchemaField(value) {
11702
11726
  ...attribute === void 0 ? {} : { attribute }
11703
11727
  };
11704
11728
  }
11705
- const element = Number(raw.element);
11706
- if (!Number.isInteger(element) || element < 1) {
11707
- throw new Error(
11708
- `Extraction field element must be a positive integer, received ${String(raw.element)}.`
11709
- );
11710
- }
11711
11729
  return {
11712
- element,
11730
+ c: normalizeExtractionCounter(raw.c ?? raw.element),
11713
11731
  ...attribute === void 0 ? {} : { attribute }
11714
11732
  };
11715
11733
  }
11734
+ function normalizeExtractionCounter(value) {
11735
+ const counter = Number(value);
11736
+ if (!Number.isInteger(counter) || counter < 1) {
11737
+ throw new Error(
11738
+ `Extraction element number must be a positive integer, received ${String(value)}.`
11739
+ );
11740
+ }
11741
+ return counter;
11742
+ }
11716
11743
  function normalizeNamespace(namespace) {
11717
11744
  const normalized = String(namespace ?? "default").trim();
11718
11745
  return normalized.length === 0 ? "default" : normalized;
@@ -11743,7 +11770,7 @@ function parseExtractionDescriptorRecord(record) {
11743
11770
  kind: "dom-extraction",
11744
11771
  persist: raw.persist,
11745
11772
  root,
11746
- ...typeof raw.schemaHash === "string" ? { schemaHash: raw.schemaHash } : {},
11773
+ ...typeof raw.templateHash === "string" ? { templateHash: raw.templateHash } : typeof raw.schemaHash === "string" ? { templateHash: raw.schemaHash } : {},
11747
11774
  ...typeof raw.sourceUrl === "string" ? { sourceUrl: raw.sourceUrl } : {}
11748
11775
  }
11749
11776
  };
@@ -11829,7 +11856,7 @@ var FilesystemOpensteerExtractionDescriptorStore = class {
11829
11856
  kind: "dom-extraction",
11830
11857
  persist: input.persist,
11831
11858
  root: input.root,
11832
- ...input.schemaHash === void 0 ? {} : { schemaHash: input.schemaHash },
11859
+ ...input.templateHash === void 0 ? {} : { templateHash: input.templateHash },
11833
11860
  ...input.sourceUrl === void 0 ? {} : { sourceUrl: input.sourceUrl }
11834
11861
  };
11835
11862
  const key = persistKey(this.namespace, input.persist);
@@ -11878,7 +11905,7 @@ var MemoryOpensteerExtractionDescriptorStore = class {
11878
11905
  kind: "dom-extraction",
11879
11906
  persist: input.persist,
11880
11907
  root: input.root,
11881
- ...input.schemaHash === void 0 ? {} : { schemaHash: input.schemaHash },
11908
+ ...input.templateHash === void 0 ? {} : { templateHash: input.templateHash },
11882
11909
  ...input.sourceUrl === void 0 ? {} : { sourceUrl: input.sourceUrl }
11883
11910
  };
11884
11911
  const key = persistKey(this.namespace, input.persist);
@@ -12180,32 +12207,33 @@ var BROWSER_BRANDS = [
12180
12207
  }
12181
12208
  },
12182
12209
  {
12183
- id: "chromium",
12184
- displayName: "Chromium",
12210
+ id: "edge",
12211
+ displayName: "Microsoft Edge",
12185
12212
  darwin: {
12186
- executableCandidates: ["/Applications/Chromium.app/Contents/MacOS/Chromium"],
12187
- userDataDir: "~/Library/Application Support/Chromium",
12188
- bundleId: "org.chromium.Chromium",
12189
- processNames: ["/Applications/Chromium.app/Contents/MacOS/Chromium"]
12213
+ executableCandidates: ["/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"],
12214
+ userDataDir: "~/Library/Application Support/Microsoft Edge",
12215
+ bundleId: "com.microsoft.edgemac",
12216
+ processNames: ["/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"]
12190
12217
  },
12191
12218
  win32: {
12192
12219
  executableCandidates: [
12193
- path10.join(WINDOWS_PROGRAM_FILES, "Chromium", "Application", "chrome.exe"),
12194
- path10.join(WINDOWS_PROGRAM_FILES_X86, "Chromium", "Application", "chrome.exe"),
12195
- path10.join("~", "AppData", "Local", "Chromium", "Application", "chrome.exe")
12220
+ path10.join(WINDOWS_PROGRAM_FILES, "Microsoft", "Edge", "Application", "msedge.exe"),
12221
+ path10.join(WINDOWS_PROGRAM_FILES_X86, "Microsoft", "Edge", "Application", "msedge.exe"),
12222
+ path10.join("~", "AppData", "Local", "Microsoft", "Edge", "Application", "msedge.exe")
12196
12223
  ],
12197
- userDataDir: "~/AppData/Local/Chromium/User Data",
12198
- processNames: ["/chromium/application/chrome.exe"]
12224
+ userDataDir: "~/AppData/Local/Microsoft/Edge/User Data",
12225
+ processNames: ["/microsoft/edge/application/msedge.exe"]
12199
12226
  },
12200
12227
  linux: {
12201
12228
  executableCandidates: [
12202
- "/usr/bin/chromium",
12203
- "/usr/bin/chromium-browser",
12204
- resolveBinaryFromPath("chromium"),
12205
- resolveBinaryFromPath("chromium-browser")
12229
+ "/usr/bin/microsoft-edge",
12230
+ "/usr/bin/microsoft-edge-stable",
12231
+ "/opt/microsoft/msedge/msedge",
12232
+ resolveBinaryFromPath("microsoft-edge"),
12233
+ resolveBinaryFromPath("microsoft-edge-stable")
12206
12234
  ],
12207
- userDataDir: "~/.config/chromium",
12208
- processNames: ["/chromium", "/chromium-browser"]
12235
+ userDataDir: "~/.config/microsoft-edge",
12236
+ processNames: ["/microsoft-edge", "/microsoft-edge-stable", "/opt/microsoft/msedge/msedge"]
12209
12237
  }
12210
12238
  },
12211
12239
  {
@@ -12242,36 +12270,6 @@ var BROWSER_BRANDS = [
12242
12270
  processNames: ["/brave-browser", "/opt/brave.com/brave/brave-browser"]
12243
12271
  }
12244
12272
  },
12245
- {
12246
- id: "edge",
12247
- displayName: "Microsoft Edge",
12248
- darwin: {
12249
- executableCandidates: ["/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"],
12250
- userDataDir: "~/Library/Application Support/Microsoft Edge",
12251
- bundleId: "com.microsoft.edgemac",
12252
- processNames: ["/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"]
12253
- },
12254
- win32: {
12255
- executableCandidates: [
12256
- path10.join(WINDOWS_PROGRAM_FILES, "Microsoft", "Edge", "Application", "msedge.exe"),
12257
- path10.join(WINDOWS_PROGRAM_FILES_X86, "Microsoft", "Edge", "Application", "msedge.exe"),
12258
- path10.join("~", "AppData", "Local", "Microsoft", "Edge", "Application", "msedge.exe")
12259
- ],
12260
- userDataDir: "~/AppData/Local/Microsoft/Edge/User Data",
12261
- processNames: ["/microsoft/edge/application/msedge.exe"]
12262
- },
12263
- linux: {
12264
- executableCandidates: [
12265
- "/usr/bin/microsoft-edge",
12266
- "/usr/bin/microsoft-edge-stable",
12267
- "/opt/microsoft/msedge/msedge",
12268
- resolveBinaryFromPath("microsoft-edge"),
12269
- resolveBinaryFromPath("microsoft-edge-stable")
12270
- ],
12271
- userDataDir: "~/.config/microsoft-edge",
12272
- processNames: ["/microsoft-edge", "/microsoft-edge-stable", "/opt/microsoft/msedge/msedge"]
12273
- }
12274
- },
12275
12273
  {
12276
12274
  id: "vivaldi",
12277
12275
  displayName: "Vivaldi",
@@ -12310,6 +12308,35 @@ var BROWSER_BRANDS = [
12310
12308
  userDataDir: "~/Library/Application Support/net.imput.helium",
12311
12309
  processNames: ["/Applications/Helium.app/Contents/MacOS/Helium"]
12312
12310
  }
12311
+ },
12312
+ {
12313
+ id: "chromium",
12314
+ displayName: "Chromium",
12315
+ darwin: {
12316
+ executableCandidates: ["/Applications/Chromium.app/Contents/MacOS/Chromium"],
12317
+ userDataDir: "~/Library/Application Support/Chromium",
12318
+ bundleId: "org.chromium.Chromium",
12319
+ processNames: ["/Applications/Chromium.app/Contents/MacOS/Chromium"]
12320
+ },
12321
+ win32: {
12322
+ executableCandidates: [
12323
+ path10.join(WINDOWS_PROGRAM_FILES, "Chromium", "Application", "chrome.exe"),
12324
+ path10.join(WINDOWS_PROGRAM_FILES_X86, "Chromium", "Application", "chrome.exe"),
12325
+ path10.join("~", "AppData", "Local", "Chromium", "Application", "chrome.exe")
12326
+ ],
12327
+ userDataDir: "~/AppData/Local/Chromium/User Data",
12328
+ processNames: ["/chromium/application/chrome.exe"]
12329
+ },
12330
+ linux: {
12331
+ executableCandidates: [
12332
+ "/usr/bin/chromium",
12333
+ "/usr/bin/chromium-browser",
12334
+ resolveBinaryFromPath("chromium"),
12335
+ resolveBinaryFromPath("chromium-browser")
12336
+ ],
12337
+ userDataDir: "~/.config/chromium",
12338
+ processNames: ["/chromium", "/chromium-browser"]
12339
+ }
12313
12340
  }
12314
12341
  ];
12315
12342
  function getBrowserBrand(id) {
@@ -12392,10 +12419,15 @@ function resolveChromeExecutablePath(executablePath) {
12392
12419
  }
12393
12420
  return resolvedPath;
12394
12421
  }
12395
- for (const installation of detectLocalChromeInstallations()) {
12396
- if (installation.executablePath) {
12397
- return installation.executablePath;
12398
- }
12422
+ const chromeInstallation = detectLocalChromeInstallations().find(
12423
+ (installation) => installation.brand === "chrome" && installation.executablePath !== null
12424
+ );
12425
+ if (chromeInstallation?.executablePath) {
12426
+ return chromeInstallation.executablePath;
12427
+ }
12428
+ const brandedInstallation = detectInstalledBrowserBrands()[0];
12429
+ if (brandedInstallation) {
12430
+ return brandedInstallation.executablePath;
12399
12431
  }
12400
12432
  throw new Error(
12401
12433
  "Could not find a Chrome or Chromium executable. Pass browser.executablePath or --executable-path."
@@ -12833,10 +12865,11 @@ async function copyRootLevelEntries(input) {
12833
12865
  if (!entryStat.isDirectory()) {
12834
12866
  continue;
12835
12867
  }
12836
- if (SKIPPED_ROOT_DIRECTORIES.has(entry) || isProfileDirectory(input.sourceUserDataDir, entry)) {
12868
+ if (SKIPPED_ROOT_DIRECTORIES.has(entry)) {
12837
12869
  continue;
12838
12870
  }
12839
- if (input.copyMode === "session") {
12871
+ const profileDirectory = isProfileDirectory(input.sourceUserDataDir, entry);
12872
+ if (input.copyMode === "session" && !profileDirectory) {
12840
12873
  continue;
12841
12874
  }
12842
12875
  await promises.cp(sourcePath, targetPath, {
@@ -13934,9 +13967,13 @@ var OpensteerBrowserManager = class {
13934
13967
  this.workspace = normalizeWorkspace(options.workspace);
13935
13968
  this.mode = resolveBrowserMode(this.workspace, options.browser);
13936
13969
  this.browserOptions = isAttachBrowserOptions(options.browser) ? options.browser : void 0;
13937
- this.launchOptions = options.launch;
13938
- this.contextOptions = normalizeBrowserContextOptions(options.context);
13970
+ this.launchOptions = resolveLaunchOptions(options.launch, options.environment ?? process.env);
13939
13971
  this.engineName = options.engineName ?? DEFAULT_OPENSTEER_ENGINE;
13972
+ this.contextOptions = normalizeBrowserContextOptions(
13973
+ options.context,
13974
+ options.environment ?? process.env,
13975
+ this.engineName
13976
+ );
13940
13977
  assertSupportedEngineOptions({
13941
13978
  engineName: this.engineName,
13942
13979
  ...options.browser === void 0 ? {} : { browser: options.browser },
@@ -14448,6 +14485,26 @@ function normalizeWorkspace(workspace) {
14448
14485
  const normalized = workspace?.trim();
14449
14486
  return normalized === void 0 || normalized.length === 0 ? void 0 : normalized;
14450
14487
  }
14488
+ function resolveLaunchOptions(launch, environment) {
14489
+ if (launch?.executablePath !== void 0) {
14490
+ return launch;
14491
+ }
14492
+ const executablePath = normalizeConfiguredExecutablePath(environment.OPENSTEER_EXECUTABLE_PATH);
14493
+ if (executablePath === void 0) {
14494
+ return launch;
14495
+ }
14496
+ return {
14497
+ ...launch ?? {},
14498
+ executablePath
14499
+ };
14500
+ }
14501
+ function normalizeConfiguredExecutablePath(value) {
14502
+ if (value === void 0) {
14503
+ return void 0;
14504
+ }
14505
+ const trimmed = value.trim();
14506
+ return trimmed.length === 0 ? void 0 : trimmed;
14507
+ }
14451
14508
  function toPersistedLocalBrowserSessionRecord(workspace, live) {
14452
14509
  return {
14453
14510
  layout: "opensteer-session",
@@ -14543,7 +14600,7 @@ async function launchOwnedBrowser(input) {
14543
14600
  }
14544
14601
  function buildChromeArgs(userDataDir, launch, viewport, requestedRemoteDebuggingPort) {
14545
14602
  const isHeadless = launch?.headless ?? true;
14546
- const args = [
14603
+ const args = isHeadless ? [
14547
14604
  ...requestedRemoteDebuggingPort === void 0 ? ["--remote-debugging-port=0"] : [],
14548
14605
  "--no-first-run",
14549
14606
  "--no-default-browser-check",
@@ -14562,6 +14619,12 @@ function buildChromeArgs(userDataDir, launch, viewport, requestedRemoteDebugging
14562
14619
  "--password-store=basic",
14563
14620
  "--use-mock-keychain",
14564
14621
  `--user-data-dir=${userDataDir}`
14622
+ ] : [
14623
+ ...requestedRemoteDebuggingPort === void 0 ? ["--remote-debugging-port=0"] : [],
14624
+ "--no-first-run",
14625
+ "--no-default-browser-check",
14626
+ "--disable-blink-features=AutomationControlled",
14627
+ `--user-data-dir=${userDataDir}`
14565
14628
  ];
14566
14629
  if (isHeadless) {
14567
14630
  args.push("--headless=new");
@@ -14785,23 +14848,36 @@ function isMissingPackageError(error, packageName) {
14785
14848
  }
14786
14849
  return error.message.includes(`Cannot find package '${packageName}'`) || error.message.includes(`Cannot find module '${packageName}'`) || error.message.includes(`Cannot find module "${packageName}"`);
14787
14850
  }
14788
- function normalizeBrowserContextOptions(context) {
14851
+ function normalizeBrowserContextOptions(context, environment, engineName = DEFAULT_OPENSTEER_ENGINE) {
14789
14852
  const stealthProfile = resolveStealthProfile(context?.stealthProfile);
14790
14853
  const locale = context?.locale ?? stealthProfile?.locale;
14791
14854
  const timezoneId = context?.timezoneId ?? stealthProfile?.timezoneId;
14792
14855
  const userAgent = context?.userAgent ?? stealthProfile?.userAgent;
14856
+ const humanize = engineName === "abp" && context?.humanize === void 0 ? void 0 : resolveHumanizeOption(context?.humanize, environment);
14793
14857
  return {
14794
14858
  ...context ?? {},
14795
14859
  ...stealthProfile === void 0 ? {} : { stealthProfile },
14796
14860
  ...locale === void 0 ? {} : { locale },
14797
14861
  ...timezoneId === void 0 ? {} : { timezoneId },
14798
14862
  ...userAgent === void 0 ? {} : { userAgent },
14863
+ ...humanize === void 0 ? {} : { humanize },
14799
14864
  viewport: context?.viewport ?? stealthProfile?.viewport ?? {
14800
14865
  width: 1440,
14801
14866
  height: 900
14802
14867
  }
14803
14868
  };
14804
14869
  }
14870
+ function resolveHumanizeOption(explicit, environment) {
14871
+ if (explicit !== void 0) {
14872
+ return explicit;
14873
+ }
14874
+ const envValue = environment?.OPENSTEER_HUMANIZE;
14875
+ if (envValue !== void 0) {
14876
+ const normalized = envValue.trim().toLowerCase();
14877
+ return normalized !== "false" && normalized !== "0";
14878
+ }
14879
+ return void 0;
14880
+ }
14805
14881
  function toEngineBrowserContextOptions(context) {
14806
14882
  const { stealthProfile: _stealthProfile, ...engineContext } = context;
14807
14883
  return engineContext;
@@ -15628,7 +15704,7 @@ function resolveCloudConfig(input = {}) {
15628
15704
 
15629
15705
  // ../runtime-core/package.json
15630
15706
  var package_default = {
15631
- version: "0.2.3"};
15707
+ version: "0.2.4"};
15632
15708
 
15633
15709
  // ../runtime-core/src/version.ts
15634
15710
  var OPENSTEER_RUNTIME_CORE_VERSION = package_default.version;
@@ -16674,10 +16750,19 @@ var VOID_TAGS = /* @__PURE__ */ new Set([
16674
16750
  // ../runtime-core/src/sdk/snapshot/cleaner.ts
16675
16751
  var STRIP_TAGS = /* @__PURE__ */ new Set(["script", "style", "noscript", "meta", "link", "template"]);
16676
16752
  var TEXT_ATTR_MAX = 150;
16677
- var URL_ATTR_MAX = 500;
16678
- var URL_ATTRS = /* @__PURE__ */ new Set(["href", "src", "srcset"]);
16753
+ var SRCSET_ATTR_MAX = 160;
16754
+ var MIDDLE_TRUNCATED_URL_ATTRS = /* @__PURE__ */ new Set(["href", "src"]);
16679
16755
  var TEXT_ATTRS = /* @__PURE__ */ new Set(["alt", "title", "aria-label", "placeholder", "value"]);
16680
- var TRUNCATION_SUFFIX = " [truncated]";
16756
+ var TRUNCATION_SUFFIX = "...";
16757
+ var MIDDLE_TRUNCATION_MARKER = "...";
16758
+ var MIDDLE_TRUNCATION_HEAD_MAX = 40;
16759
+ var MIDDLE_TRUNCATION_TAIL_MAX = 20;
16760
+ var SRCSET_CANDIDATE_HEAD_MAX = 36;
16761
+ var SRCSET_CANDIDATE_TAIL_MAX = 12;
16762
+ var SRCSET_COMPACT_CANDIDATE_HEAD_MAX = 20;
16763
+ var SRCSET_COMPACT_CANDIDATE_TAIL_MAX = 8;
16764
+ var SRCSET_FALLBACK_HEAD_MAX = 56;
16765
+ var SRCSET_FALLBACK_TAIL_MAX = 20;
16681
16766
  var NOISE_SELECTORS = [
16682
16767
  `[${OPENSTEER_HIDDEN_ATTR}]`,
16683
16768
  "[hidden]",
@@ -16740,104 +16825,375 @@ function truncateValue(value, max) {
16740
16825
  }
16741
16826
  return `${head}${TRUNCATION_SUFFIX}`;
16742
16827
  }
16828
+ function takeValueWithinSerializedLengthFromEnd(value, max) {
16829
+ let serializedLength = 0;
16830
+ const chars = [];
16831
+ for (let index = value.length - 1; index >= 0; index -= 1) {
16832
+ const char = value[index];
16833
+ let nextLength = 1;
16834
+ if (char === "&") {
16835
+ nextLength = 5;
16836
+ } else if (char === "<" || char === ">") {
16837
+ nextLength = 4;
16838
+ } else if (char === '"') {
16839
+ nextLength = 6;
16840
+ }
16841
+ if (serializedLength + nextLength > max) {
16842
+ break;
16843
+ }
16844
+ chars.push(char);
16845
+ serializedLength += nextLength;
16846
+ }
16847
+ return chars.reverse().join("");
16848
+ }
16849
+ function truncateValueInMiddle(value, headMax, tailMax, marker = MIDDLE_TRUNCATION_MARKER) {
16850
+ const markerLength = getSerializedLength(marker);
16851
+ const max = headMax + markerLength + tailMax;
16852
+ if (getSerializedLength(value) <= max) {
16853
+ return value;
16854
+ }
16855
+ const head = takeValueWithinSerializedLength(value, headMax).replace(/\s+$/u, "");
16856
+ const tail = takeValueWithinSerializedLengthFromEnd(value, tailMax).replace(/^\s+/u, "");
16857
+ if (head.length === 0) {
16858
+ return tail.length === 0 ? marker : `${marker}${tail}`;
16859
+ }
16860
+ if (tail.length === 0) {
16861
+ return `${head}${marker}`;
16862
+ }
16863
+ return `${head}${marker}${tail}`;
16864
+ }
16743
16865
  function getAttrLimit(attr) {
16744
- if (URL_ATTRS.has(attr)) {
16745
- return URL_ATTR_MAX;
16866
+ if (attr === "srcset") {
16867
+ return SRCSET_ATTR_MAX;
16746
16868
  }
16747
16869
  if (TEXT_ATTRS.has(attr)) {
16748
16870
  return TEXT_ATTR_MAX;
16749
16871
  }
16750
16872
  return void 0;
16751
16873
  }
16874
+ function shouldBoundAttr(attr) {
16875
+ return MIDDLE_TRUNCATED_URL_ATTRS.has(attr) || getAttrLimit(attr) !== void 0;
16876
+ }
16752
16877
  function setBoundedAttr(el, attr, value) {
16878
+ if (MIDDLE_TRUNCATED_URL_ATTRS.has(attr)) {
16879
+ el.attr(
16880
+ attr,
16881
+ truncateValueInMiddle(value, MIDDLE_TRUNCATION_HEAD_MAX, MIDDLE_TRUNCATION_TAIL_MAX)
16882
+ );
16883
+ return;
16884
+ }
16753
16885
  const limit = getAttrLimit(attr);
16886
+ if (attr === "srcset" && limit !== void 0) {
16887
+ el.attr(attr, truncateSrcsetValue(value, limit));
16888
+ return;
16889
+ }
16754
16890
  el.attr(attr, limit === void 0 ? value : truncateValue(value, limit));
16755
16891
  }
16756
- function removeNoise($) {
16757
- for (const tag of STRIP_TAGS) {
16758
- $(tag).remove();
16892
+ function truncateSrcsetValue(value, max) {
16893
+ if (getSerializedLength(value) <= max) {
16894
+ return value;
16759
16895
  }
16760
- $(NOISE_SELECTORS.join(", ")).remove();
16761
- }
16762
- function removeComments($) {
16763
- $("*").contents().each(function removeComment() {
16764
- if (this.type === "comment") {
16765
- $(this).remove();
16766
- }
16767
- });
16768
- }
16769
- function markInlineSelfHiddenFallback($) {
16770
- $(
16771
- "[style*='visibility: hidden'], [style*='visibility:hidden'], [style*='visibility: collapse'], [style*='visibility:collapse']"
16772
- ).each(function markInlineVisibilityHidden() {
16773
- const el = $(this);
16774
- if (el.attr(OPENSTEER_HIDDEN_ATTR) === void 0) {
16775
- el.attr(OPENSTEER_SELF_HIDDEN_ATTR, "1");
16896
+ const candidates = parseSrcsetCandidates2(value);
16897
+ if (candidates.length === 0) {
16898
+ return truncateValueInMiddle(value, SRCSET_FALLBACK_HEAD_MAX, SRCSET_FALLBACK_TAIL_MAX);
16899
+ }
16900
+ for (const [headMax, tailMax, includeBest] of [
16901
+ [SRCSET_CANDIDATE_HEAD_MAX, SRCSET_CANDIDATE_TAIL_MAX, true],
16902
+ [SRCSET_COMPACT_CANDIDATE_HEAD_MAX, SRCSET_COMPACT_CANDIDATE_TAIL_MAX, true],
16903
+ [SRCSET_COMPACT_CANDIDATE_HEAD_MAX, SRCSET_COMPACT_CANDIDATE_TAIL_MAX, false]
16904
+ ]) {
16905
+ const compact = buildTruncatedSrcsetValue(candidates, headMax, tailMax, includeBest);
16906
+ if (getSerializedLength(compact) <= max) {
16907
+ return compact;
16776
16908
  }
16777
- });
16909
+ }
16910
+ return truncateValueInMiddle(value, SRCSET_FALLBACK_HEAD_MAX, SRCSET_FALLBACK_TAIL_MAX);
16778
16911
  }
16779
- function pruneSelfHiddenNodes($) {
16780
- const nodes = [];
16781
- $(`[${OPENSTEER_SELF_HIDDEN_ATTR}]`).each(function collectSelfHiddenNodes() {
16782
- nodes.push($(this));
16783
- });
16784
- nodes.sort((left, right) => right.parents().length - left.parents().length);
16785
- for (const el of nodes) {
16786
- if (!el[0]) {
16787
- continue;
16788
- }
16789
- el.contents().each(function removeSelfHiddenText() {
16790
- if (this.type === "text") {
16791
- $(this).remove();
16792
- }
16793
- });
16794
- if (el.children().length === 0) {
16795
- el.remove();
16912
+ function buildTruncatedSrcsetValue(candidates, headMax, tailMax, includeBest) {
16913
+ const kept = getPreferredSrcsetCandidateIndices(candidates, includeBest);
16914
+ const parts = [];
16915
+ let previousIndex;
16916
+ for (const candidateIndex of kept) {
16917
+ if (previousIndex !== void 0 && candidateIndex - previousIndex > 1) {
16918
+ parts.push(MIDDLE_TRUNCATION_MARKER);
16796
16919
  }
16920
+ parts.push(formatSrcsetCandidate(candidates[candidateIndex], headMax, tailMax));
16921
+ previousIndex = candidateIndex;
16797
16922
  }
16923
+ return parts.join(", ");
16798
16924
  }
16799
- function hasDirectText($, el) {
16800
- return el.contents().filter(function hasDirectNodeText() {
16801
- return this.type === "text" && $(this).text().trim() !== "";
16802
- }).length > 0;
16803
- }
16804
- function hasTextDeep(el) {
16805
- return el.text().trim().length > 0;
16806
- }
16807
- function hasActionLabel(attrs) {
16808
- return typeof attrs["aria-label"] === "string" && attrs["aria-label"].trim() !== "" || typeof attrs["aria-labelledby"] === "string" && attrs["aria-labelledby"].trim() !== "" || typeof attrs["aria-describedby"] === "string" && attrs["aria-describedby"].trim() !== "" || typeof attrs.title === "string" && attrs.title.trim() !== "" || typeof attrs.placeholder === "string" && attrs.placeholder.trim() !== "" || typeof attrs.value === "string" && attrs.value.trim() !== "";
16925
+ function getPreferredSrcsetCandidateIndices(candidates, includeBest) {
16926
+ if (candidates.length === 0) {
16927
+ return [];
16928
+ }
16929
+ const kept = /* @__PURE__ */ new Set([0, candidates.length - 1]);
16930
+ if (includeBest) {
16931
+ kept.add(pickBestSrcsetCandidateIndex(candidates));
16932
+ }
16933
+ return [...kept].filter((index) => index >= 0 && index < candidates.length).sort((a, b) => a - b);
16809
16934
  }
16810
- function unwrapActionNode($, el) {
16811
- if (hasTextDeep(el)) {
16812
- if (el.prev().length > 0) {
16813
- el.before(" ");
16935
+ function pickBestSrcsetCandidateIndex(candidates) {
16936
+ let bestWidthIndex = -1;
16937
+ let bestWidth = -1;
16938
+ let bestDensityIndex = -1;
16939
+ let bestDensity = -1;
16940
+ for (let index = 0; index < candidates.length; index += 1) {
16941
+ const candidate = candidates[index];
16942
+ if (typeof candidate.width === "number" && Number.isFinite(candidate.width) && candidate.width > bestWidth) {
16943
+ bestWidth = candidate.width;
16944
+ bestWidthIndex = index;
16814
16945
  }
16815
- if (el.next().length > 0) {
16816
- el.after(" ");
16946
+ if (typeof candidate.density === "number" && Number.isFinite(candidate.density) && candidate.density > bestDensity) {
16947
+ bestDensity = candidate.density;
16948
+ bestDensityIndex = index;
16817
16949
  }
16818
16950
  }
16819
- el.replaceWith(el.contents());
16951
+ if (bestWidthIndex >= 0) {
16952
+ return bestWidthIndex;
16953
+ }
16954
+ if (bestDensityIndex >= 0) {
16955
+ return bestDensityIndex;
16956
+ }
16957
+ return candidates.length - 1;
16820
16958
  }
16821
- function stripToAttrs(el, keep) {
16822
- const attrs = el.attr() || {};
16823
- for (const attr of Object.keys(attrs)) {
16824
- if (!keep.has(attr)) {
16825
- el.removeAttr(attr);
16826
- continue;
16959
+ function formatSrcsetCandidate(candidate, headMax, tailMax) {
16960
+ const url = truncateValueInMiddle(candidate.url, headMax, tailMax);
16961
+ return candidate.descriptorText ? `${url} ${candidate.descriptorText}` : url;
16962
+ }
16963
+ function parseSrcsetCandidates2(raw) {
16964
+ const text = raw.trim();
16965
+ if (!text) {
16966
+ return [];
16967
+ }
16968
+ const out = [];
16969
+ let index = 0;
16970
+ while (index < text.length) {
16971
+ index = skipSrcsetSeparators(text, index);
16972
+ if (index >= text.length) {
16973
+ break;
16827
16974
  }
16828
- const value = el.attr(attr);
16829
- if (typeof value !== "string") {
16975
+ const urlToken = readSrcsetUrlToken(text, index);
16976
+ index = urlToken.nextIndex;
16977
+ const url = urlToken.value.trim();
16978
+ if (!url) {
16830
16979
  continue;
16831
16980
  }
16832
- if (getAttrLimit(attr) !== void 0) {
16833
- setBoundedAttr(el, attr, value);
16981
+ index = skipSrcsetWhitespace(text, index);
16982
+ const descriptors = [];
16983
+ while (index < text.length && text[index] !== ",") {
16984
+ const descriptorToken = readSrcsetDescriptorToken(text, index);
16985
+ if (!descriptorToken.value) {
16986
+ index = descriptorToken.nextIndex;
16987
+ continue;
16988
+ }
16989
+ descriptors.push(descriptorToken.value);
16990
+ index = descriptorToken.nextIndex;
16991
+ index = skipSrcsetWhitespace(text, index);
16834
16992
  }
16835
- }
16836
- }
16837
- function restoreBoundedAttr(el, attr, value) {
16838
- if (typeof value !== "string") {
16839
- return;
16840
- }
16993
+ if (index < text.length && text[index] === ",") {
16994
+ index += 1;
16995
+ }
16996
+ let width = null;
16997
+ let density = null;
16998
+ for (const descriptor of descriptors) {
16999
+ const token = descriptor.trim().toLowerCase();
17000
+ if (!token) {
17001
+ continue;
17002
+ }
17003
+ const widthMatch = token.match(/^(\d+)w$/);
17004
+ if (widthMatch) {
17005
+ const parsed = Number.parseInt(widthMatch[1], 10);
17006
+ if (Number.isFinite(parsed)) {
17007
+ width = parsed;
17008
+ }
17009
+ continue;
17010
+ }
17011
+ const densityMatch = token.match(/^(\d*\.?\d+)x$/);
17012
+ if (densityMatch) {
17013
+ const parsed = Number.parseFloat(densityMatch[1]);
17014
+ if (Number.isFinite(parsed)) {
17015
+ density = parsed;
17016
+ }
17017
+ }
17018
+ }
17019
+ out.push({
17020
+ url,
17021
+ descriptorText: descriptors.join(" "),
17022
+ width,
17023
+ density
17024
+ });
17025
+ }
17026
+ return out;
17027
+ }
17028
+ function skipSrcsetWhitespace(value, index) {
17029
+ let cursor = index;
17030
+ while (cursor < value.length && /\s/u.test(value[cursor])) {
17031
+ cursor += 1;
17032
+ }
17033
+ return cursor;
17034
+ }
17035
+ function skipSrcsetSeparators(value, index) {
17036
+ let cursor = skipSrcsetWhitespace(value, index);
17037
+ while (cursor < value.length && value[cursor] === ",") {
17038
+ cursor += 1;
17039
+ cursor = skipSrcsetWhitespace(value, cursor);
17040
+ }
17041
+ return cursor;
17042
+ }
17043
+ function readSrcsetUrlToken(value, index) {
17044
+ let cursor = index;
17045
+ let out = "";
17046
+ const isDataUrl = value.slice(index, index + 5).toLowerCase().startsWith("data:");
17047
+ while (cursor < value.length) {
17048
+ const char = value[cursor];
17049
+ if (/\s/u.test(char)) {
17050
+ break;
17051
+ }
17052
+ if (char === "," && !isDataUrl) {
17053
+ break;
17054
+ }
17055
+ out += char;
17056
+ cursor += 1;
17057
+ }
17058
+ if (isDataUrl && out.endsWith(",") && cursor < value.length) {
17059
+ out = out.slice(0, -1);
17060
+ }
17061
+ return {
17062
+ value: out,
17063
+ nextIndex: cursor
17064
+ };
17065
+ }
17066
+ function readSrcsetDescriptorToken(value, index) {
17067
+ let cursor = skipSrcsetWhitespace(value, index);
17068
+ let out = "";
17069
+ while (cursor < value.length) {
17070
+ const char = value[cursor];
17071
+ if (char === "," || /\s/u.test(char)) {
17072
+ break;
17073
+ }
17074
+ out += char;
17075
+ cursor += 1;
17076
+ }
17077
+ return {
17078
+ value: out.trim(),
17079
+ nextIndex: cursor
17080
+ };
17081
+ }
17082
+ function removeNoise($) {
17083
+ for (const tag of STRIP_TAGS) {
17084
+ $(tag).remove();
17085
+ }
17086
+ $(NOISE_SELECTORS.join(", ")).remove();
17087
+ }
17088
+ function removeComments($) {
17089
+ $("*").contents().each(function removeComment() {
17090
+ if (this.type === "comment") {
17091
+ $(this).remove();
17092
+ }
17093
+ });
17094
+ }
17095
+ function markInlineSelfHiddenFallback($) {
17096
+ $(
17097
+ "[style*='visibility: hidden'], [style*='visibility:hidden'], [style*='visibility: collapse'], [style*='visibility:collapse']"
17098
+ ).each(function markInlineVisibilityHidden() {
17099
+ const el = $(this);
17100
+ if (el.attr(OPENSTEER_HIDDEN_ATTR) === void 0) {
17101
+ el.attr(OPENSTEER_SELF_HIDDEN_ATTR, "1");
17102
+ }
17103
+ });
17104
+ }
17105
+ function pruneSelfHiddenNodes($) {
17106
+ for (const node of getElementsInReverseDocumentOrder($)) {
17107
+ if (node.attribs?.[OPENSTEER_SELF_HIDDEN_ATTR] === void 0) {
17108
+ continue;
17109
+ }
17110
+ const el = $(node);
17111
+ el.contents().each(function removeSelfHiddenText() {
17112
+ if (this.type === "text") {
17113
+ $(this).remove();
17114
+ }
17115
+ });
17116
+ if (!hasElementChildren(node)) {
17117
+ el.remove();
17118
+ }
17119
+ }
17120
+ }
17121
+ function getChildNodes(node) {
17122
+ return node?.children ?? [];
17123
+ }
17124
+ function isElementLikeNode(node) {
17125
+ return node?.type === "tag" || node?.type === "script" || node?.type === "style";
17126
+ }
17127
+ function hasDirectText(node) {
17128
+ if (!node) {
17129
+ return false;
17130
+ }
17131
+ for (const child of getChildNodes(node)) {
17132
+ if (child.type === "text" && (child.data || "").trim() !== "") {
17133
+ return true;
17134
+ }
17135
+ }
17136
+ return false;
17137
+ }
17138
+ function hasElementChildren(node) {
17139
+ if (!node) {
17140
+ return false;
17141
+ }
17142
+ for (const child of getChildNodes(node)) {
17143
+ if (isElementLikeNode(child)) {
17144
+ return true;
17145
+ }
17146
+ }
17147
+ return false;
17148
+ }
17149
+ function hasTextDeepNode(node) {
17150
+ if (!node) {
17151
+ return false;
17152
+ }
17153
+ if (node.type === "text") {
17154
+ return (node.data || "").trim() !== "";
17155
+ }
17156
+ for (const child of getChildNodes(node)) {
17157
+ if (hasTextDeepNode(child)) {
17158
+ return true;
17159
+ }
17160
+ }
17161
+ return false;
17162
+ }
17163
+ function hasActionLabel(attrs) {
17164
+ return typeof attrs["aria-label"] === "string" && attrs["aria-label"].trim() !== "" || typeof attrs["aria-labelledby"] === "string" && attrs["aria-labelledby"].trim() !== "" || typeof attrs["aria-describedby"] === "string" && attrs["aria-describedby"].trim() !== "" || typeof attrs.title === "string" && attrs.title.trim() !== "" || typeof attrs.placeholder === "string" && attrs.placeholder.trim() !== "" || typeof attrs.value === "string" && attrs.value.trim() !== "";
17165
+ }
17166
+ function unwrapActionNode($, el) {
17167
+ if (hasTextDeepNode(el[0])) {
17168
+ if (el.prev().length > 0) {
17169
+ el.before(" ");
17170
+ }
17171
+ if (el.next().length > 0) {
17172
+ el.after(" ");
17173
+ }
17174
+ }
17175
+ el.replaceWith(el.contents());
17176
+ }
17177
+ function stripToAttrs(el, keep) {
17178
+ const attrs = el.attr() || {};
17179
+ for (const attr of Object.keys(attrs)) {
17180
+ if (!keep.has(attr)) {
17181
+ el.removeAttr(attr);
17182
+ continue;
17183
+ }
17184
+ const value = el.attr(attr);
17185
+ if (typeof value !== "string") {
17186
+ continue;
17187
+ }
17188
+ if (shouldBoundAttr(attr)) {
17189
+ setBoundedAttr(el, attr, value);
17190
+ }
17191
+ }
17192
+ }
17193
+ function restoreBoundedAttr(el, attr, value) {
17194
+ if (typeof value !== "string") {
17195
+ return;
17196
+ }
16841
17197
  const trimmed = value.trim();
16842
17198
  if (trimmed === "") {
16843
17199
  return;
@@ -16847,6 +17203,9 @@ function restoreBoundedAttr(el, attr, value) {
16847
17203
  function deduplicateImages(html) {
16848
17204
  const seen = /* @__PURE__ */ new Set();
16849
17205
  return html.replace(/<img\b([^>]*)>/gi, (full, attrContent) => {
17206
+ if (/\bc\s*=/.test(attrContent)) {
17207
+ return full;
17208
+ }
16850
17209
  const srcMatch = attrContent.match(/\bsrc\s*=\s*(["']?)(.*?)\1/);
16851
17210
  const srcsetMatch = attrContent.match(/\bsrcset\s*=\s*(["'])(.*?)\1/);
16852
17211
  let src = null;
@@ -16865,59 +17224,155 @@ function deduplicateImages(html) {
16865
17224
  return full;
16866
17225
  });
16867
17226
  }
16868
- function isPreservedImageElement($, el) {
16869
- const tag = (el[0]?.tagName || "").toLowerCase();
17227
+ function hasAttribute2(node, attr) {
17228
+ return node?.attribs?.[attr] !== void 0;
17229
+ }
17230
+ function hasPictureAncestor(node) {
17231
+ let current = node?.parent;
17232
+ while (current) {
17233
+ if (isElementLikeNode(current) && (current.tagName || "").toLowerCase() === "picture") {
17234
+ return true;
17235
+ }
17236
+ current = current.parent;
17237
+ }
17238
+ return false;
17239
+ }
17240
+ function pictureHasPreservedDescendant(node) {
17241
+ if (!node) {
17242
+ return false;
17243
+ }
17244
+ for (const child of getChildNodes(node)) {
17245
+ if (!isElementLikeNode(child)) {
17246
+ continue;
17247
+ }
17248
+ const tag = (child.tagName || "").toLowerCase();
17249
+ if (tag === "img") {
17250
+ return true;
17251
+ }
17252
+ if (tag === "source" && typeof child.attribs?.src === "string" && child.attribs.src.trim() !== "") {
17253
+ return true;
17254
+ }
17255
+ if (tag === "source" && typeof child.attribs?.srcset === "string" && child.attribs.srcset.trim() !== "") {
17256
+ return true;
17257
+ }
17258
+ if (pictureHasPreservedDescendant(child)) {
17259
+ return true;
17260
+ }
17261
+ }
17262
+ return false;
17263
+ }
17264
+ function isPreservedImageElement(node) {
17265
+ const tag = (node?.tagName || "").toLowerCase();
16870
17266
  if (tag === "img") {
16871
17267
  return true;
16872
17268
  }
16873
17269
  if (tag === "picture") {
16874
- const hasImg = el.find("img").length > 0;
16875
- const hasSource = el.find("source[src], source[srcset]").length > 0;
16876
- return hasImg || hasSource;
17270
+ return pictureHasPreservedDescendant(node);
16877
17271
  }
16878
17272
  if (tag === "source") {
16879
- const inPicture = el.parents("picture").length > 0;
16880
- const hasSrc = el.attr("src") != null && el.attr("src").trim() !== "" || el.attr("srcset") != null && el.attr("srcset").trim() !== "";
17273
+ const inPicture = hasPictureAncestor(node);
17274
+ const hasSrc = typeof node?.attribs?.src === "string" && node.attribs.src.trim() !== "" || typeof node?.attribs?.srcset === "string" && node.attribs.srcset.trim() !== "";
16881
17275
  return inPicture && hasSrc;
16882
17276
  }
16883
17277
  return false;
16884
17278
  }
17279
+ function getElementsInReverseDocumentOrder($) {
17280
+ return $.root().find("*").toArray().reverse().filter((node) => node.type === "tag");
17281
+ }
17282
+ function getNodeDepth(node) {
17283
+ let depth = 0;
17284
+ let current = node.parent;
17285
+ while (current) {
17286
+ depth++;
17287
+ current = current.parent;
17288
+ }
17289
+ return depth;
17290
+ }
17291
+ function getElementsByDepthDescending($) {
17292
+ const elements = $.root().find("*").toArray().filter((node) => node.type === "tag");
17293
+ const depths = /* @__PURE__ */ new Map();
17294
+ for (const el of elements) {
17295
+ depths.set(el, getNodeDepth(el));
17296
+ }
17297
+ return elements.sort((a, b) => (depths.get(b) ?? 0) - (depths.get(a) ?? 0));
17298
+ }
16885
17299
  function flattenExtractionTree($) {
16886
- const flatten = (root) => {
16887
- root.find("*").each(function flattenNode() {
16888
- const el = $(this);
16889
- const node = el[0];
16890
- if (!node) {
16891
- return;
16892
- }
16893
- const tag = (node.tagName || "").toLowerCase();
16894
- if (ROOT_TAGS.has(tag) || isBoundaryTag(tag)) {
16895
- return;
16896
- }
16897
- if (isPreservedImageElement($, el)) {
16898
- return;
16899
- }
16900
- if (tag === "a") {
16901
- el.children().each(function flattenAnchorChild() {
16902
- flatten($(this));
16903
- });
16904
- return;
16905
- }
16906
- const hasText = hasDirectText($, el);
16907
- if (hasText) {
16908
- return;
16909
- }
16910
- if (el.children().length === 0) {
16911
- el.remove();
16912
- return;
17300
+ for (const node of getElementsInReverseDocumentOrder($)) {
17301
+ const el = $(node);
17302
+ const tag = (node.tagName || "").toLowerCase();
17303
+ if (ROOT_TAGS.has(tag) || isBoundaryTag(tag) || isPreservedImageElement(node)) {
17304
+ continue;
17305
+ }
17306
+ if (tag === "a" || hasDirectText(node)) {
17307
+ continue;
17308
+ }
17309
+ if (!hasElementChildren(node)) {
17310
+ el.remove();
17311
+ continue;
17312
+ }
17313
+ el.replaceWith(el.contents());
17314
+ }
17315
+ }
17316
+ function hasMarkedAncestor(el, attr) {
17317
+ let current = el[0]?.parent;
17318
+ while (current) {
17319
+ if (!isElementLikeNode(current)) {
17320
+ return false;
17321
+ }
17322
+ if (current.attribs?.[attr] !== void 0) {
17323
+ return true;
17324
+ }
17325
+ current = current.parent;
17326
+ }
17327
+ return false;
17328
+ }
17329
+ function isIndicatorImage(node) {
17330
+ return (node?.tagName || "").toLowerCase() === "img" && (hasAttribute2(node, "alt") || hasAttribute2(node, "src") || hasAttribute2(node, "srcset"));
17331
+ }
17332
+ function isIndicatorPictureSource(node) {
17333
+ return (node?.tagName || "").toLowerCase() === "source" && hasPictureAncestor(node) && (hasAttribute2(node, "src") || hasAttribute2(node, "srcset"));
17334
+ }
17335
+ function isSemanticIndicator(node) {
17336
+ const tag = (node?.tagName || "").toLowerCase();
17337
+ if (tag === "svg") {
17338
+ return true;
17339
+ }
17340
+ return hasAttribute2(node, "aria-label") || hasAttribute2(node, "title") || hasAttribute2(node, "data-icon") || node?.attribs?.role === "img";
17341
+ }
17342
+ function findIndicatorDescendant(root) {
17343
+ if (!root) {
17344
+ return void 0;
17345
+ }
17346
+ let firstImage;
17347
+ let firstSource;
17348
+ let firstSemantic;
17349
+ const visit = (node) => {
17350
+ if (!isElementLikeNode(node)) {
17351
+ return false;
17352
+ }
17353
+ if (isIndicatorImage(node)) {
17354
+ firstImage = node;
17355
+ return true;
17356
+ }
17357
+ if (firstSource === void 0 && isIndicatorPictureSource(node)) {
17358
+ firstSource = node;
17359
+ }
17360
+ if (firstSemantic === void 0 && isSemanticIndicator(node)) {
17361
+ firstSemantic = node;
17362
+ }
17363
+ for (const child of getChildNodes(node)) {
17364
+ if (visit(child)) {
17365
+ return true;
16913
17366
  }
16914
- el.children().each(function flattenChild() {
16915
- flatten($(this));
16916
- });
16917
- el.replaceWith(el.contents());
16918
- });
17367
+ }
17368
+ return false;
16919
17369
  };
16920
- flatten($.root());
17370
+ for (const child of getChildNodes(root)) {
17371
+ if (visit(child)) {
17372
+ return firstImage;
17373
+ }
17374
+ }
17375
+ return firstImage ?? firstSource ?? firstSemantic;
16921
17376
  }
16922
17377
  function serializeForExtraction($, root) {
16923
17378
  const lines = [];
@@ -16986,7 +17441,7 @@ function serializeForExtraction($, root) {
16986
17441
  lines.push(`${" ".repeat(depth)}</${tagName}>`);
16987
17442
  }
16988
17443
  traverse(root, 0);
16989
- return lines.join("\n");
17444
+ return lines.map((l) => l.trim()).filter((l) => l.length > 0).join("");
16990
17445
  }
16991
17446
  function isClickable($, el, context) {
16992
17447
  if (context.hasPreMarked) {
@@ -17078,7 +17533,11 @@ function cleanForExtraction(html) {
17078
17533
  }
17079
17534
  });
17080
17535
  flattenExtractionTree($clean);
17081
- return deduplicateImages(serializeForExtraction($clean, $clean.root()[0]));
17536
+ const root = $clean.root()[0];
17537
+ if (root === void 0) {
17538
+ return "";
17539
+ }
17540
+ return deduplicateImages(serializeForExtraction($clean, root));
17082
17541
  }
17083
17542
  function cleanForAction(html) {
17084
17543
  if (!html.trim()) {
@@ -17104,22 +17563,12 @@ function cleanForAction(html) {
17104
17563
  $(`[${clickableMark}]`).each(function markIndicators() {
17105
17564
  const el = $(this);
17106
17565
  const wrapperAttrs = el.attr() || {};
17107
- if (hasTextDeep(el) || hasActionLabel(wrapperAttrs)) {
17566
+ if (hasTextDeepNode(el[0]) || hasActionLabel(wrapperAttrs)) {
17108
17567
  return;
17109
17568
  }
17110
- const imageIndicator = el.find("img[alt], img[src], img[srcset]").first();
17111
- if (imageIndicator.length) {
17112
- imageIndicator.attr(indicatorMark, "1");
17113
- return;
17114
- }
17115
- const pictureSourceIndicator = el.find("picture source[src], picture source[srcset]").first();
17116
- if (pictureSourceIndicator.length) {
17117
- pictureSourceIndicator.attr(indicatorMark, "1");
17118
- return;
17119
- }
17120
- const semanticIndicator = el.find('[aria-label], [title], [data-icon], [role="img"], svg').first();
17121
- if (semanticIndicator.length) {
17122
- semanticIndicator.attr(indicatorMark, "1");
17569
+ const indicatorNode = findIndicatorDescendant(el[0]);
17570
+ if (indicatorNode !== void 0) {
17571
+ $(indicatorNode).attr(indicatorMark, "1");
17123
17572
  }
17124
17573
  });
17125
17574
  $(`[${clickableMark}]`).each(function removeEmptyClickable() {
@@ -17129,7 +17578,7 @@ function cleanForAction(html) {
17129
17578
  if (NATIVE_INTERACTIVE_TAGS.has(tag) || tag === "a") {
17130
17579
  return;
17131
17580
  }
17132
- if (el.children().length > 0 || hasDirectText($, el)) {
17581
+ if (hasElementChildren(node) || hasDirectText(node)) {
17133
17582
  return;
17134
17583
  }
17135
17584
  const wrapperAttrs = el.attr() || {};
@@ -17155,46 +17604,31 @@ function cleanForAction(html) {
17155
17604
  current = ancestor.parent();
17156
17605
  }
17157
17606
  });
17158
- let changed = true;
17159
- while (changed) {
17160
- changed = false;
17161
- const nodes = [];
17162
- $("*").each(function collectNodes() {
17163
- nodes.push($(this));
17164
- });
17165
- nodes.sort((left, right) => right.parents().length - left.parents().length);
17166
- for (const el of nodes) {
17167
- const node = el[0];
17168
- if (!node) {
17169
- continue;
17170
- }
17171
- const tag = (node.tagName || "").toLowerCase();
17172
- if (ROOT_TAGS.has(tag) || isBoundaryTag(tag)) {
17173
- continue;
17174
- }
17175
- if (el.attr(clickableMark) !== void 0 || el.attr(indicatorMark) !== void 0) {
17176
- continue;
17177
- }
17178
- const insideClickable = el.parents(`[${clickableMark}]`).length > 0;
17179
- const preserveBranch = el.attr(branchMark) !== void 0;
17180
- const hasContent = el.children().length > 0 || hasDirectText($, el);
17181
- if (insideClickable || preserveBranch) {
17182
- if (!hasContent) {
17183
- el.remove();
17184
- } else {
17185
- unwrapActionNode($, el);
17186
- }
17187
- changed = true;
17188
- continue;
17189
- }
17607
+ for (const node of getElementsByDepthDescending($)) {
17608
+ const el = $(node);
17609
+ const tag = (node.tagName || "").toLowerCase();
17610
+ if (ROOT_TAGS.has(tag) || isBoundaryTag(tag)) {
17611
+ continue;
17612
+ }
17613
+ if (el.attr(clickableMark) !== void 0 || el.attr(indicatorMark) !== void 0) {
17614
+ continue;
17615
+ }
17616
+ const insideClickable = hasMarkedAncestor(el, clickableMark);
17617
+ const preserveBranch = el.attr(branchMark) !== void 0;
17618
+ const hasContent = hasElementChildren(node) || hasDirectText(node);
17619
+ if (insideClickable || preserveBranch) {
17190
17620
  if (!hasContent) {
17191
17621
  el.remove();
17192
- changed = true;
17193
- continue;
17622
+ } else {
17623
+ unwrapActionNode($, el);
17194
17624
  }
17195
- unwrapActionNode($, el);
17196
- changed = true;
17625
+ continue;
17626
+ }
17627
+ if (!hasContent) {
17628
+ el.remove();
17629
+ continue;
17197
17630
  }
17631
+ unwrapActionNode($, el);
17198
17632
  }
17199
17633
  $.root().find("*").contents().each(function normalizeActionTextNodes() {
17200
17634
  if (this.type !== "text") {
@@ -17274,21 +17708,7 @@ function cleanForAction(html) {
17274
17708
  OPENSTEER_SPARSE_COUNTER_ATTR
17275
17709
  ]);
17276
17710
  if (clickable) {
17277
- for (const attr of [
17278
- "href",
17279
- "role",
17280
- "type",
17281
- "title",
17282
- "placeholder",
17283
- "value",
17284
- "aria-label",
17285
- "aria-labelledby",
17286
- "aria-describedby",
17287
- "aria-expanded",
17288
- "aria-pressed",
17289
- "aria-selected",
17290
- "aria-haspopup"
17291
- ]) {
17711
+ for (const attr of ["href", "role", "type", "title", "placeholder", "value", "aria-label"]) {
17292
17712
  keep.add(attr);
17293
17713
  }
17294
17714
  }
@@ -17908,9 +18328,9 @@ function renderNode(snapshot, node, nodesById, snapshotsByDocumentRef, snapshotI
17908
18328
  const snapshotAttributes = normalizeNodeAttributes(node.attributes);
17909
18329
  const authoredAttributes = stripInternalSnapshotAttributes(snapshotAttributes);
17910
18330
  const attributes = [...authoredAttributes];
17911
- const subtreeHidden = hasAttribute2(snapshotAttributes, OPENSTEER_HIDDEN_ATTR) || isLikelySubtreeHidden(node);
17912
- const selfHidden = !subtreeHidden && (hasAttribute2(snapshotAttributes, OPENSTEER_SELF_HIDDEN_ATTR) || isLikelySelfHidden(node, nodesById));
17913
- const interactive = !subtreeHidden && !selfHidden && (hasAttribute2(snapshotAttributes, OPENSTEER_INTERACTIVE_ATTR) || isLikelyInteractive(tagName, node, authoredAttributes));
18331
+ const subtreeHidden = hasAttribute3(snapshotAttributes, OPENSTEER_HIDDEN_ATTR) || isLikelySubtreeHidden(node);
18332
+ const selfHidden = !subtreeHidden && (hasAttribute3(snapshotAttributes, OPENSTEER_SELF_HIDDEN_ATTR) || isLikelySelfHidden(node, nodesById));
18333
+ const interactive = !subtreeHidden && !selfHidden && (hasAttribute3(snapshotAttributes, OPENSTEER_INTERACTIVE_ATTR) || isLikelyInteractive(tagName, node, authoredAttributes));
17914
18334
  if (interactive) {
17915
18335
  attributes.push({ name: OPENSTEER_INTERACTIVE_ATTR, value: "1" });
17916
18336
  }
@@ -18228,7 +18648,7 @@ function parseOpacity(value) {
18228
18648
  const parsed = Number.parseFloat(value);
18229
18649
  return Number.isFinite(parsed) ? parsed : Number.NaN;
18230
18650
  }
18231
- function hasAttribute2(attributes, name) {
18651
+ function hasAttribute3(attributes, name) {
18232
18652
  const normalizedName = name.toLowerCase();
18233
18653
  return attributes.some((attribute) => attribute.name.toLowerCase() === normalizedName);
18234
18654
  }
@@ -19444,6 +19864,7 @@ function diffInteractionTraces(left, right) {
19444
19864
  // ../runtime-core/src/sdk/runtime.ts
19445
19865
  var MUTATION_CAPTURE_FINALIZE_TIMEOUT_MS = 5e3;
19446
19866
  var PERSISTED_NETWORK_FLUSH_TIMEOUT_MS = 5e3;
19867
+ var PERSISTED_NETWORK_SETTLE_POLL_MS = 25;
19447
19868
  var PENDING_OPERATION_EVENT_CAPTURE_LIMIT = 64;
19448
19869
  var PENDING_OPERATION_EVENT_CAPTURE_SKEW_MS = 1e3;
19449
19870
  var REPLAY_PROBE_MIN_ATTEMPT_TIMEOUT_MS = 3e3;
@@ -20188,12 +20609,12 @@ var OpensteerSessionRuntime = class {
20188
20609
  async (timeout) => {
20189
20610
  let descriptor2;
20190
20611
  let data;
20191
- if (input.schema !== void 0) {
20192
- assertValidOpensteerExtractionSchemaRoot(input.schema);
20612
+ if (input.template !== void 0) {
20613
+ assertValidOpensteerExtractionTemplateRoot(input.template);
20193
20614
  const fieldTargets = await timeout.runStep(
20194
20615
  () => compileOpensteerExtractionFieldTargets({
20195
20616
  pageRef,
20196
- schema: input.schema,
20617
+ template: input.template,
20197
20618
  dom: this.requireDom()
20198
20619
  })
20199
20620
  );
@@ -20225,7 +20646,7 @@ var OpensteerSessionRuntime = class {
20225
20646
  () => descriptors.write({
20226
20647
  persist,
20227
20648
  root: payload,
20228
- schemaHash: canonicalJsonString(input.schema),
20649
+ templateHash: canonicalJsonString(input.template),
20229
20650
  sourceUrl: pageInfo.url
20230
20651
  })
20231
20652
  );
@@ -20285,7 +20706,7 @@ var OpensteerSessionRuntime = class {
20285
20706
  artifacts,
20286
20707
  data: {
20287
20708
  ...input.persist === void 0 ? {} : { persist: input.persist },
20288
- ...descriptor?.payload.schemaHash === void 0 ? {} : { schemaHash: descriptor.payload.schemaHash },
20709
+ ...descriptor?.payload.templateHash === void 0 ? {} : { templateHash: descriptor.payload.templateHash },
20289
20710
  data: output.data
20290
20711
  },
20291
20712
  context: buildRuntimeTraceContext({
@@ -22218,15 +22639,22 @@ var OpensteerSessionRuntime = class {
22218
22639
  return [];
22219
22640
  }
22220
22641
  const root = await this.ensureRoot();
22221
- const browserRecords = await this.readBrowserNetworkRecords(
22222
- {
22223
- includeBodies: true,
22224
- includeCurrentPageOnly: options.includeCurrentPageOnly,
22225
- ...options.pageRef === void 0 ? {} : { pageRef: options.pageRef },
22226
- requestIds
22227
- },
22228
- signal
22229
- );
22642
+ let browserRecords = [];
22643
+ for (; ; ) {
22644
+ browserRecords = await this.readBrowserNetworkRecords(
22645
+ {
22646
+ includeBodies: true,
22647
+ includeCurrentPageOnly: options.includeCurrentPageOnly,
22648
+ ...options.pageRef === void 0 ? {} : { pageRef: options.pageRef },
22649
+ requestIds
22650
+ },
22651
+ signal
22652
+ );
22653
+ if (browserRecords.length === requestIds.length && browserRecords.every((record) => record.captureState !== "pending")) {
22654
+ break;
22655
+ }
22656
+ await delayWithSignal(PERSISTED_NETWORK_SETTLE_POLL_MS, signal);
22657
+ }
22230
22658
  return this.networkHistory.persist(browserRecords, root.registry.savedNetwork, {
22231
22659
  bodyWriteMode: "authoritative",
22232
22660
  redactSecretHeaders: false
@@ -24588,142 +25016,6 @@ function screenshotMediaType(format2) {
24588
25016
  return "image/webp";
24589
25017
  }
24590
25018
  }
24591
-
24592
- // ../runtime-core/src/sdk/semantic-dispatch.ts
24593
- async function dispatchSemanticOperation(runtime, operation, input, options = {}) {
24594
- switch (operation) {
24595
- case "session.open":
24596
- return runtime.open(input, options);
24597
- case "page.list":
24598
- return runtime.listPages(
24599
- input,
24600
- options
24601
- );
24602
- case "page.new":
24603
- return runtime.newPage(input, options);
24604
- case "page.activate":
24605
- return runtime.activatePage(
24606
- input,
24607
- options
24608
- );
24609
- case "page.close":
24610
- return runtime.closePage(
24611
- input,
24612
- options
24613
- );
24614
- case "page.goto":
24615
- return runtime.goto(input, options);
24616
- case "page.evaluate":
24617
- return runtime.evaluate(
24618
- input,
24619
- options
24620
- );
24621
- case "page.add-init-script":
24622
- return runtime.addInitScript(
24623
- input,
24624
- options
24625
- );
24626
- case "page.snapshot":
24627
- return runtime.snapshot(
24628
- input,
24629
- options
24630
- );
24631
- case "dom.click":
24632
- return runtime.click(input, options);
24633
- case "dom.hover":
24634
- return runtime.hover(input, options);
24635
- case "dom.input":
24636
- return runtime.input(input, options);
24637
- case "dom.scroll":
24638
- return runtime.scroll(input, options);
24639
- case "dom.extract":
24640
- return runtime.extract(input, options);
24641
- case "network.query":
24642
- return runtime.queryNetwork(
24643
- input,
24644
- options
24645
- );
24646
- case "network.detail":
24647
- return runtime.getNetworkDetail(
24648
- input,
24649
- options
24650
- );
24651
- case "interaction.capture":
24652
- return runtime.captureInteraction(
24653
- input,
24654
- options
24655
- );
24656
- case "interaction.get":
24657
- return runtime.getInteraction(
24658
- input,
24659
- options
24660
- );
24661
- case "interaction.diff":
24662
- return runtime.diffInteraction(
24663
- input,
24664
- options
24665
- );
24666
- case "interaction.replay":
24667
- return runtime.replayInteraction(
24668
- input,
24669
- options
24670
- );
24671
- case "artifact.read":
24672
- return runtime.readArtifact(
24673
- input,
24674
- options
24675
- );
24676
- case "session.cookies":
24677
- return runtime.getCookies(
24678
- input,
24679
- options
24680
- );
24681
- case "session.storage":
24682
- return runtime.getStorageSnapshot(
24683
- input,
24684
- options
24685
- );
24686
- case "session.state":
24687
- return runtime.getBrowserState(
24688
- input,
24689
- options
24690
- );
24691
- case "session.fetch":
24692
- return runtime.fetch(input, options);
24693
- case "scripts.capture":
24694
- return runtime.captureScripts(
24695
- input,
24696
- options
24697
- );
24698
- case "scripts.beautify":
24699
- return runtime.beautifyScript(
24700
- input,
24701
- options
24702
- );
24703
- case "scripts.deobfuscate":
24704
- return runtime.deobfuscateScript(
24705
- input,
24706
- options
24707
- );
24708
- case "scripts.sandbox":
24709
- return runtime.sandboxScript(
24710
- input,
24711
- options
24712
- );
24713
- case "captcha.solve":
24714
- return runtime.solveCaptcha(
24715
- input,
24716
- options
24717
- );
24718
- case "computer.execute":
24719
- return runtime.computerExecute(
24720
- input,
24721
- options
24722
- );
24723
- case "session.close":
24724
- return runtime.close(options);
24725
- }
24726
- }
24727
25019
  var OpensteerSemanticRestError = class extends Error {
24728
25020
  opensteerError;
24729
25021
  statusCode;
@@ -25706,39 +25998,10 @@ var OpensteerRuntime = class extends OpensteerSessionRuntime {
25706
25998
  super(
25707
25999
  buildSharedRuntimeOptions({
25708
26000
  name: publicWorkspace ?? "default",
26001
+ ...options.rootDir === void 0 ? {} : { rootDir: options.rootDir },
25709
26002
  rootPath,
25710
26003
  ...publicWorkspace === void 0 ? {} : { workspaceName: publicWorkspace },
25711
- ...options.browser === void 0 ? {} : { browser: options.browser },
25712
- ...options.launch === void 0 ? {} : { launch: options.launch },
25713
- ...options.context === void 0 ? {} : { context: options.context },
25714
- engineName,
25715
- ...options.engine === void 0 ? {} : { engine: options.engine },
25716
- ...options.engineFactory === void 0 ? {} : { engineFactory: options.engineFactory },
25717
- ...options.policy === void 0 ? {} : { policy: options.policy },
25718
- ...options.descriptorStore === void 0 ? {} : { descriptorStore: options.descriptorStore },
25719
- ...options.extractionDescriptorStore === void 0 ? {} : { extractionDescriptorStore: options.extractionDescriptorStore },
25720
- cleanupRootOnClose,
25721
- ...options.observability === void 0 ? {} : { observability: options.observability },
25722
- ...options.observationSessionId === void 0 ? {} : { observationSessionId: options.observationSessionId },
25723
- ...options.observationSink === void 0 ? {} : { observationSink: options.observationSink }
25724
- })
25725
- );
25726
- }
25727
- };
25728
- var OpensteerSessionRuntime2 = class extends OpensteerSessionRuntime {
25729
- constructor(options) {
25730
- const rootPath = options.rootPath ?? path10__default.default.resolve(options.rootDir ?? process.cwd());
25731
- const cleanupRootOnClose = options.cleanupRootOnClose ?? false;
25732
- const engineName = options.engineName ?? DEFAULT_OPENSTEER_ENGINE;
25733
- assertSupportedEngineOptions({
25734
- engineName,
25735
- ...options.browser === void 0 ? {} : { browser: options.browser },
25736
- ...options.context === void 0 ? {} : { context: options.context }
25737
- });
25738
- super(
25739
- buildSharedRuntimeOptions({
25740
- name: options.name,
25741
- rootPath,
26004
+ ...options.environment === void 0 ? {} : { environment: options.environment },
25742
26005
  ...options.browser === void 0 ? {} : { browser: options.browser },
25743
26006
  ...options.launch === void 0 ? {} : { launch: options.launch },
25744
26007
  ...options.context === void 0 ? {} : { context: options.context },
@@ -25759,9 +26022,11 @@ var OpensteerSessionRuntime2 = class extends OpensteerSessionRuntime {
25759
26022
  function buildSharedRuntimeOptions(input) {
25760
26023
  const ownership = resolveOwnership(input.browser);
25761
26024
  const engineFactory = input.engineFactory ?? ((factoryOptions) => new OpensteerBrowserManager({
26025
+ ...input.rootDir === void 0 ? {} : { rootDir: input.rootDir },
25762
26026
  rootPath: input.rootPath,
25763
26027
  ...input.workspaceName === void 0 ? {} : { workspace: input.workspaceName },
25764
26028
  engineName: input.engineName,
26029
+ ...input.environment === void 0 ? {} : { environment: input.environment },
25765
26030
  ...(factoryOptions.browser ?? input.browser) === void 0 ? {} : { browser: factoryOptions.browser ?? input.browser },
25766
26031
  ...(factoryOptions.launch ?? input.launch) === void 0 ? {} : { launch: factoryOptions.launch ?? input.launch },
25767
26032
  ...(factoryOptions.context ?? input.context) === void 0 ? {} : { context: factoryOptions.context ?? input.context }
@@ -25822,9 +26087,10 @@ function resolveOpensteerRuntimeConfig(input = {}) {
25822
26087
  function createOpensteerSemanticRuntime(input = {}) {
25823
26088
  const runtimeOptions = input.runtimeOptions ?? {};
25824
26089
  const engine = input.engine ?? runtimeOptions.engineName ?? DEFAULT_OPENSTEER_ENGINE;
26090
+ const environment = input.environment ?? process.env;
25825
26091
  const config = resolveOpensteerRuntimeConfig({
25826
26092
  ...input.provider === void 0 ? {} : { provider: input.provider },
25827
- ...input.environment === void 0 ? {} : { environment: input.environment }
26093
+ environment
25828
26094
  });
25829
26095
  assertProviderSupportsEngine(config.provider.mode, engine);
25830
26096
  if (config.provider.mode === "cloud") {
@@ -25839,7 +26105,8 @@ function createOpensteerSemanticRuntime(input = {}) {
25839
26105
  }
25840
26106
  return new OpensteerRuntime({
25841
26107
  ...runtimeOptions,
25842
- engineName: engine
26108
+ engineName: engine,
26109
+ environment
25843
26110
  });
25844
26111
  }
25845
26112
 
@@ -25894,6 +26161,7 @@ var Opensteer = class {
25894
26161
  ...runtimeOptions.rootPath === void 0 ? {} : { rootPath: runtimeOptions.rootPath },
25895
26162
  ...runtimeOptions.workspace === void 0 ? {} : { workspace: runtimeOptions.workspace },
25896
26163
  ...engineName === void 0 ? {} : { engineName },
26164
+ environment,
25897
26165
  ...runtimeOptions.browser === void 0 ? {} : { browser: runtimeOptions.browser },
25898
26166
  ...runtimeOptions.launch === void 0 ? {} : { launch: runtimeOptions.launch },
25899
26167
  ...runtimeOptions.context === void 0 ? {} : { context: runtimeOptions.context }
@@ -26018,9 +26286,6 @@ var Opensteer = class {
26018
26286
  await delay3(pollIntervalMs);
26019
26287
  }
26020
26288
  }
26021
- async snapshot(mode = "action") {
26022
- return (await this.runtime.snapshot({ mode })).html;
26023
- }
26024
26289
  async cookies(domain) {
26025
26290
  return new SessionCookieJar(
26026
26291
  await this.runtime.getCookies(domain === void 0 ? {} : { domain })
@@ -26171,7 +26436,6 @@ function delay3(ms) {
26171
26436
  return new Promise((resolve4) => setTimeout(resolve4, ms));
26172
26437
  }
26173
26438
 
26174
- exports.CloudSessionProxy = CloudSessionProxy;
26175
26439
  exports.DEFAULT_OPENSTEER_ENGINE = DEFAULT_OPENSTEER_ENGINE;
26176
26440
  exports.DEFERRED_MATCH_ATTR_KEYS = DEFERRED_MATCH_ATTR_KEYS;
26177
26441
  exports.ElementPathError = ElementPathError;
@@ -26184,8 +26448,6 @@ exports.Opensteer = Opensteer;
26184
26448
  exports.OpensteerAttachAmbiguousError = OpensteerAttachAmbiguousError;
26185
26449
  exports.OpensteerBrowserManager = OpensteerBrowserManager;
26186
26450
  exports.OpensteerCloudClient = OpensteerCloudClient;
26187
- exports.OpensteerRuntime = OpensteerRuntime;
26188
- exports.OpensteerSessionRuntime = OpensteerSessionRuntime2;
26189
26451
  exports.STABLE_PRIMARY_ATTR_KEYS = STABLE_PRIMARY_ATTR_KEYS;
26190
26452
  exports.assertProviderSupportsEngine = assertProviderSupportsEngine;
26191
26453
  exports.buildArrayFieldPathCandidates = buildArrayFieldPathCandidates;
@@ -26205,7 +26467,6 @@ exports.createDomRuntime = createDomRuntime;
26205
26467
  exports.createFilesystemOpensteerWorkspace = createFilesystemOpensteerWorkspace;
26206
26468
  exports.createObservationStore = createObservationStore;
26207
26469
  exports.createOpensteerExtractionDescriptorStore = createOpensteerExtractionDescriptorStore;
26208
- exports.createOpensteerSemanticRuntime = createOpensteerSemanticRuntime;
26209
26470
  exports.defaultFallbackPolicy = defaultFallbackPolicy;
26210
26471
  exports.defaultPolicy = defaultPolicy;
26211
26472
  exports.defaultRetryPolicy = defaultRetryPolicy;
@@ -26213,7 +26474,6 @@ exports.defaultSettlePolicy = defaultSettlePolicy;
26213
26474
  exports.defaultTimeoutPolicy = defaultTimeoutPolicy;
26214
26475
  exports.delayWithSignal = delayWithSignal;
26215
26476
  exports.discoverLocalCdpBrowsers = discoverLocalCdpBrowsers;
26216
- exports.dispatchSemanticOperation = dispatchSemanticOperation;
26217
26477
  exports.hashDomDescriptorPersist = hashDomDescriptorPersist;
26218
26478
  exports.inspectCdpEndpoint = inspectCdpEndpoint;
26219
26479
  exports.isCurrentUrlField = isCurrentUrlField;