@opensteer/runtime-core 0.1.0 → 0.1.1

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.cjs CHANGED
@@ -42,7 +42,7 @@ var vm__default = /*#__PURE__*/_interopDefault(vm);
42
42
 
43
43
  // package.json
44
44
  var package_default = {
45
- version: "0.1.0"};
45
+ version: "0.1.1"};
46
46
 
47
47
  // src/version.ts
48
48
  var OPENSTEER_RUNTIME_CORE_VERSION = package_default.version;
@@ -1325,12 +1325,6 @@ var opensteerRegistryProvenanceSchema = objectSchema(
1325
1325
  required: ["source"]
1326
1326
  }
1327
1327
  );
1328
- var opensteerRequestPlanLifecycleSchema = enumSchema(
1329
- ["draft", "active", "deprecated", "retired"],
1330
- {
1331
- title: "OpensteerRequestPlanLifecycle"
1332
- }
1333
- );
1334
1328
  var opensteerRequestPlanFreshnessSchema = objectSchema(
1335
1329
  {
1336
1330
  lastValidatedAt: integerSchema({ minimum: 0 }),
@@ -1353,23 +1347,12 @@ var opensteerRequestPlanRecordSchema = objectSchema(
1353
1347
  uniqueItems: true
1354
1348
  }),
1355
1349
  provenance: opensteerRegistryProvenanceSchema,
1356
- lifecycle: opensteerRequestPlanLifecycleSchema,
1357
1350
  freshness: opensteerRequestPlanFreshnessSchema,
1358
1351
  payload: opensteerRequestPlanPayloadSchema
1359
1352
  },
1360
1353
  {
1361
1354
  title: "OpensteerRequestPlanRecord",
1362
- required: [
1363
- "id",
1364
- "key",
1365
- "version",
1366
- "createdAt",
1367
- "updatedAt",
1368
- "contentHash",
1369
- "tags",
1370
- "lifecycle",
1371
- "payload"
1372
- ]
1355
+ required: ["id", "key", "version", "createdAt", "updatedAt", "contentHash", "tags", "payload"]
1373
1356
  }
1374
1357
  );
1375
1358
  var jsonValueSchema = defineSchema({
@@ -1812,7 +1795,6 @@ var opensteerWriteRequestPlanInputSchema = objectSchema(
1812
1795
  uniqueItems: true
1813
1796
  }),
1814
1797
  provenance: opensteerRegistryProvenanceSchema,
1815
- lifecycle: opensteerRequestPlanLifecycleSchema,
1816
1798
  freshness: opensteerRequestPlanFreshnessSchema,
1817
1799
  payload: opensteerRequestPlanPayloadSchema
1818
1800
  },
@@ -2053,7 +2035,7 @@ var opensteerInferRequestPlanInputSchema = objectSchema(
2053
2035
  recordId: stringSchema({ minLength: 1 }),
2054
2036
  key: stringSchema({ minLength: 1 }),
2055
2037
  version: stringSchema({ minLength: 1 }),
2056
- lifecycle: opensteerRequestPlanLifecycleSchema
2038
+ transport: transportKindSchema
2057
2039
  },
2058
2040
  {
2059
2041
  title: "OpensteerInferRequestPlanInput",
@@ -7118,8 +7100,74 @@ var defaultSnapshotSettleObserver = {
7118
7100
  }
7119
7101
  };
7120
7102
  Object.freeze(defaultSnapshotSettleObserver);
7103
+ var DOM_ACTION_VISUAL_STABILITY_PROFILES = {
7104
+ "dom.click": { settleMs: 750, scope: "visible-frames", timeoutMs: 7e3 },
7105
+ "dom.input": { settleMs: 750, scope: "visible-frames", timeoutMs: 7e3 },
7106
+ "dom.scroll": { settleMs: 600, scope: "visible-frames", timeoutMs: 7e3 },
7107
+ "dom.hover": { settleMs: 200, scope: "main-frame", timeoutMs: 2500 }
7108
+ };
7109
+ var DEFAULT_DOM_ACTION_VISUAL_STABILITY_PROFILE = {
7110
+ settleMs: 750,
7111
+ scope: "visible-frames",
7112
+ timeoutMs: 7e3
7113
+ };
7114
+ var NAVIGATION_VISUAL_STABILITY_PROFILE = {
7115
+ settleMs: 750,
7116
+ scope: "visible-frames",
7117
+ timeoutMs: 7e3
7118
+ };
7119
+ var defaultDomActionSettleObserver = {
7120
+ async settle(input) {
7121
+ if (input.trigger !== "dom-action") {
7122
+ return false;
7123
+ }
7124
+ const profile = DOM_ACTION_VISUAL_STABILITY_PROFILES[input.operation] ?? DEFAULT_DOM_ACTION_VISUAL_STABILITY_PROFILE;
7125
+ const effectiveTimeout = input.remainingMs === void 0 ? profile.timeoutMs : Math.min(profile.timeoutMs, input.remainingMs);
7126
+ if (effectiveTimeout <= 0) {
7127
+ return false;
7128
+ }
7129
+ try {
7130
+ await input.engine.waitForVisualStability({
7131
+ pageRef: input.pageRef,
7132
+ timeoutMs: effectiveTimeout,
7133
+ settleMs: profile.settleMs,
7134
+ scope: profile.scope
7135
+ });
7136
+ return true;
7137
+ } catch {
7138
+ return false;
7139
+ }
7140
+ }
7141
+ };
7142
+ Object.freeze(defaultDomActionSettleObserver);
7143
+ var defaultNavigationSettleObserver = {
7144
+ async settle(input) {
7145
+ if (input.trigger !== "navigation") {
7146
+ return false;
7147
+ }
7148
+ const profile = NAVIGATION_VISUAL_STABILITY_PROFILE;
7149
+ const effectiveTimeout = input.remainingMs === void 0 ? profile.timeoutMs : Math.min(profile.timeoutMs, input.remainingMs);
7150
+ if (effectiveTimeout <= 0) {
7151
+ return false;
7152
+ }
7153
+ try {
7154
+ await input.engine.waitForVisualStability({
7155
+ pageRef: input.pageRef,
7156
+ timeoutMs: effectiveTimeout,
7157
+ settleMs: profile.settleMs,
7158
+ scope: profile.scope
7159
+ });
7160
+ return true;
7161
+ } catch {
7162
+ return false;
7163
+ }
7164
+ }
7165
+ };
7166
+ Object.freeze(defaultNavigationSettleObserver);
7121
7167
  var DEFAULT_SETTLE_OBSERVERS = Object.freeze([
7122
- defaultSnapshotSettleObserver
7168
+ defaultSnapshotSettleObserver,
7169
+ defaultDomActionSettleObserver,
7170
+ defaultNavigationSettleObserver
7123
7171
  ]);
7124
7172
  var defaultTimeoutPolicy = {
7125
7173
  resolveTimeoutMs(input) {
@@ -7370,9 +7418,7 @@ var FilesystemRegistryStore = class {
7370
7418
  if (input.version !== void 0) {
7371
7419
  return this.resolveIndexedRecord(key, normalizeNonEmptyString("version", input.version));
7372
7420
  }
7373
- const matches = (await this.readAllRecords()).filter(
7374
- (record) => this.isActive(record) && record.key === key
7375
- );
7421
+ const matches = (await this.readAllRecords()).filter((record) => record.key === key);
7376
7422
  matches.sort(compareByCreatedAtAndId);
7377
7423
  return matches[0];
7378
7424
  }
@@ -7495,8 +7541,10 @@ var FilesystemDescriptorRegistry = class extends FilesystemRegistryStore {
7495
7541
  };
7496
7542
  return this.writeRecord(record);
7497
7543
  }
7498
- isActive(_record) {
7499
- return true;
7544
+ async list(input = {}) {
7545
+ const key = input.key === void 0 ? void 0 : normalizeNonEmptyString("key", input.key);
7546
+ const records = await this.readAllRecords();
7547
+ return key === void 0 ? records : records.filter((record) => record.key === key);
7500
7548
  }
7501
7549
  };
7502
7550
  var FilesystemRequestPlanRegistry = class extends FilesystemRegistryStore {
@@ -7526,7 +7574,6 @@ var FilesystemRequestPlanRegistry = class extends FilesystemRegistryStore {
7526
7574
  tags: normalizeTags(input.tags),
7527
7575
  ...provenance === void 0 ? {} : { provenance },
7528
7576
  payload,
7529
- lifecycle: input.lifecycle ?? "active",
7530
7577
  ...freshness === void 0 ? {} : { freshness }
7531
7578
  };
7532
7579
  return this.writeRecord(record);
@@ -7536,7 +7583,7 @@ var FilesystemRequestPlanRegistry = class extends FilesystemRegistryStore {
7536
7583
  const records = await this.readAllRecords();
7537
7584
  return key === void 0 ? records : records.filter((record) => record.key === key);
7538
7585
  }
7539
- async updateMetadata(input) {
7586
+ async updateFreshness(input) {
7540
7587
  const id = normalizeNonEmptyString("id", input.id);
7541
7588
  return withFilesystemLock(this.writeLockPath(), async () => {
7542
7589
  const existing = await this.getById(id);
@@ -7554,16 +7601,12 @@ var FilesystemRequestPlanRegistry = class extends FilesystemRegistryStore {
7554
7601
  const nextRecord = {
7555
7602
  ...existing,
7556
7603
  updatedAt: nextUpdatedAt,
7557
- lifecycle: input.lifecycle ?? existing.lifecycle,
7558
7604
  ...nextFreshness === void 0 ? {} : { freshness: nextFreshness }
7559
7605
  };
7560
7606
  await writeJsonFileAtomic(this.recordPath(id), nextRecord);
7561
7607
  return nextRecord;
7562
7608
  });
7563
7609
  }
7564
- isActive(record) {
7565
- return record.lifecycle === "active";
7566
- }
7567
7610
  };
7568
7611
  var FilesystemAuthRecipeRegistry = class extends FilesystemRegistryStore {
7569
7612
  constructor(rootPath) {
@@ -7599,9 +7642,6 @@ var FilesystemAuthRecipeRegistry = class extends FilesystemRegistryStore {
7599
7642
  const records = await this.readAllRecords();
7600
7643
  return key === void 0 ? records : records.filter((record) => record.key === key);
7601
7644
  }
7602
- isActive(_record) {
7603
- return true;
7604
- }
7605
7645
  };
7606
7646
  var FilesystemRecipeRegistry = class extends FilesystemRegistryStore {
7607
7647
  constructor(rootPath) {
@@ -7637,9 +7677,6 @@ var FilesystemRecipeRegistry = class extends FilesystemRegistryStore {
7637
7677
  const records = await this.readAllRecords();
7638
7678
  return key === void 0 ? records : records.filter((record) => record.key === key);
7639
7679
  }
7640
- isActive(_record) {
7641
- return true;
7642
- }
7643
7680
  };
7644
7681
  var FilesystemInteractionTraceRegistry = class extends FilesystemRegistryStore {
7645
7682
  constructor(rootPath) {
@@ -7675,9 +7712,6 @@ var FilesystemInteractionTraceRegistry = class extends FilesystemRegistryStore {
7675
7712
  const records = await this.readAllRecords();
7676
7713
  return key === void 0 ? records : records.filter((record) => record.key === key);
7677
7714
  }
7678
- isActive(_record) {
7679
- return true;
7680
- }
7681
7715
  };
7682
7716
  var FilesystemReverseCaseRegistry = class extends FilesystemRegistryStore {
7683
7717
  constructor(rootPath) {
@@ -7741,9 +7775,6 @@ var FilesystemReverseCaseRegistry = class extends FilesystemRegistryStore {
7741
7775
  return nextRecord;
7742
7776
  });
7743
7777
  }
7744
- isActive(_record) {
7745
- return true;
7746
- }
7747
7778
  };
7748
7779
  var FilesystemReversePackageRegistry = class extends FilesystemRegistryStore {
7749
7780
  constructor(rootPath) {
@@ -7779,9 +7810,6 @@ var FilesystemReversePackageRegistry = class extends FilesystemRegistryStore {
7779
7810
  const records = await this.readAllRecords();
7780
7811
  return key === void 0 ? records : records.filter((record) => record.key === key);
7781
7812
  }
7782
- isActive(_record) {
7783
- return true;
7784
- }
7785
7813
  };
7786
7814
  var FilesystemReverseReportRegistry = class extends FilesystemRegistryStore {
7787
7815
  constructor(rootPath) {
@@ -7817,9 +7845,6 @@ var FilesystemReverseReportRegistry = class extends FilesystemRegistryStore {
7817
7845
  const records = await this.readAllRecords();
7818
7846
  return key === void 0 ? records : records.filter((record) => record.key === key);
7819
7847
  }
7820
- isActive(_record) {
7821
- return true;
7822
- }
7823
7848
  };
7824
7849
  function createDescriptorRegistry(rootPath) {
7825
7850
  return new FilesystemDescriptorRegistry(rootPath);
@@ -7847,101 +7872,20 @@ function createReverseReportRegistry(rootPath) {
7847
7872
  }
7848
7873
  var TAG_DELIMITER = "";
7849
7874
  var NODE_SQLITE_SPECIFIER = `node:${"sqlite"}`;
7875
+ var SAVED_NETWORK_SQLITE_SUPPORT_ERROR = "Saved-network operations require Node's built-in SQLite support. Use a Node runtime with node:sqlite enabled.";
7850
7876
  var SqliteSavedNetworkStore = class {
7851
7877
  databasePath;
7852
7878
  database;
7879
+ directoryInitialization;
7880
+ databaseInitialization;
7853
7881
  constructor(rootPath) {
7854
7882
  this.databasePath = path6__default.default.join(rootPath, "registry", "saved-network.sqlite");
7855
7883
  }
7856
7884
  async initialize() {
7857
- await ensureDirectory(path6__default.default.dirname(this.databasePath));
7858
- const { DatabaseSync } = await import(NODE_SQLITE_SPECIFIER);
7859
- const database = new DatabaseSync(this.databasePath);
7860
- database.exec("PRAGMA journal_mode = WAL");
7861
- database.exec("PRAGMA foreign_keys = ON");
7862
- database.exec(`
7863
- CREATE TABLE IF NOT EXISTS saved_network_records (
7864
- record_id TEXT PRIMARY KEY,
7865
- request_id TEXT NOT NULL,
7866
- session_ref TEXT NOT NULL,
7867
- page_ref TEXT,
7868
- page_ref_key TEXT NOT NULL,
7869
- frame_ref TEXT,
7870
- document_ref TEXT,
7871
- action_id TEXT,
7872
- method TEXT NOT NULL,
7873
- method_lc TEXT NOT NULL,
7874
- url TEXT NOT NULL,
7875
- url_lc TEXT NOT NULL,
7876
- hostname TEXT NOT NULL,
7877
- hostname_lc TEXT NOT NULL,
7878
- path TEXT NOT NULL,
7879
- path_lc TEXT NOT NULL,
7880
- status INTEGER,
7881
- status_text TEXT,
7882
- resource_type TEXT NOT NULL,
7883
- navigation_request INTEGER NOT NULL,
7884
- request_headers_json TEXT NOT NULL,
7885
- response_headers_json TEXT NOT NULL,
7886
- request_body_json TEXT,
7887
- response_body_json TEXT,
7888
- initiator_json TEXT,
7889
- timing_json TEXT,
7890
- transfer_json TEXT,
7891
- source_json TEXT,
7892
- capture_state TEXT NOT NULL,
7893
- request_body_state TEXT NOT NULL,
7894
- response_body_state TEXT NOT NULL,
7895
- request_body_skip_reason TEXT,
7896
- response_body_skip_reason TEXT,
7897
- request_body_error TEXT,
7898
- response_body_error TEXT,
7899
- redirect_from_request_id TEXT,
7900
- redirect_to_request_id TEXT,
7901
- saved_at INTEGER NOT NULL
7902
- );
7903
-
7904
- CREATE UNIQUE INDEX IF NOT EXISTS saved_network_records_scope_request
7905
- ON saved_network_records (session_ref, page_ref_key, request_id);
7906
-
7907
- CREATE INDEX IF NOT EXISTS saved_network_records_saved_at
7908
- ON saved_network_records (saved_at DESC);
7909
-
7910
- CREATE TABLE IF NOT EXISTS saved_network_tags (
7911
- record_id TEXT NOT NULL REFERENCES saved_network_records(record_id) ON DELETE CASCADE,
7912
- tag TEXT NOT NULL,
7913
- PRIMARY KEY (record_id, tag)
7914
- );
7915
-
7916
- CREATE INDEX IF NOT EXISTS saved_network_tags_tag
7917
- ON saved_network_tags (tag);
7918
- `);
7919
- this.ensureColumn(
7920
- database,
7921
- "saved_network_records",
7922
- "capture_state",
7923
- "TEXT NOT NULL DEFAULT 'complete'"
7924
- );
7925
- this.ensureColumn(
7926
- database,
7927
- "saved_network_records",
7928
- "request_body_state",
7929
- "TEXT NOT NULL DEFAULT 'skipped'"
7930
- );
7931
- this.ensureColumn(
7932
- database,
7933
- "saved_network_records",
7934
- "response_body_state",
7935
- "TEXT NOT NULL DEFAULT 'skipped'"
7936
- );
7937
- this.ensureColumn(database, "saved_network_records", "request_body_skip_reason", "TEXT");
7938
- this.ensureColumn(database, "saved_network_records", "response_body_skip_reason", "TEXT");
7939
- this.ensureColumn(database, "saved_network_records", "request_body_error", "TEXT");
7940
- this.ensureColumn(database, "saved_network_records", "response_body_error", "TEXT");
7941
- this.database = database;
7885
+ await this.ensureDatabaseDirectory();
7942
7886
  }
7943
7887
  async save(records, tag) {
7944
- const database = this.requireDatabase();
7888
+ const database = await this.requireDatabase();
7945
7889
  const readExisting = database.prepare(`
7946
7890
  SELECT record_id
7947
7891
  FROM saved_network_records
@@ -8133,7 +8077,7 @@ var SqliteSavedNetworkStore = class {
8133
8077
  });
8134
8078
  }
8135
8079
  async query(input = {}) {
8136
- const database = this.requireDatabase();
8080
+ const database = await this.requireDatabase();
8137
8081
  const limit = Math.max(1, Math.min(input.limit ?? 50, 200));
8138
8082
  const { whereSql, parameters } = buildSavedNetworkWhere(input);
8139
8083
  const rows = database.prepare(
@@ -8164,7 +8108,7 @@ var SqliteSavedNetworkStore = class {
8164
8108
  return record;
8165
8109
  }
8166
8110
  async clear(input = {}) {
8167
- const database = this.requireDatabase();
8111
+ const database = await this.requireDatabase();
8168
8112
  const countAll = database.prepare(`
8169
8113
  SELECT COUNT(*) AS cleared
8170
8114
  FROM saved_network_records
@@ -8201,11 +8145,127 @@ var SqliteSavedNetworkStore = class {
8201
8145
  return cleared;
8202
8146
  });
8203
8147
  }
8204
- requireDatabase() {
8205
- if (!this.database) {
8206
- throw new Error("saved network store is not initialized");
8148
+ async requireDatabase() {
8149
+ if (this.database) {
8150
+ return this.database;
8151
+ }
8152
+ this.databaseInitialization ??= this.openDatabase();
8153
+ try {
8154
+ return await this.databaseInitialization;
8155
+ } catch (error) {
8156
+ this.databaseInitialization = void 0;
8157
+ throw error;
8158
+ }
8159
+ }
8160
+ async openDatabase() {
8161
+ await this.ensureDatabaseDirectory();
8162
+ let DatabaseSync;
8163
+ try {
8164
+ ({ DatabaseSync } = await import(NODE_SQLITE_SPECIFIER));
8165
+ } catch (error) {
8166
+ throw normalizeSqliteImportError(error);
8207
8167
  }
8208
- return this.database;
8168
+ const database = new DatabaseSync(this.databasePath);
8169
+ try {
8170
+ this.configureDatabase(database);
8171
+ this.database = database;
8172
+ return database;
8173
+ } catch (error) {
8174
+ closeSqliteDatabase(database);
8175
+ throw error;
8176
+ }
8177
+ }
8178
+ async ensureDatabaseDirectory() {
8179
+ this.directoryInitialization ??= ensureDirectory(path6__default.default.dirname(this.databasePath)).catch(
8180
+ (error) => {
8181
+ this.directoryInitialization = void 0;
8182
+ throw error;
8183
+ }
8184
+ );
8185
+ await this.directoryInitialization;
8186
+ }
8187
+ configureDatabase(database) {
8188
+ database.exec("PRAGMA journal_mode = WAL");
8189
+ database.exec("PRAGMA foreign_keys = ON");
8190
+ database.exec(`
8191
+ CREATE TABLE IF NOT EXISTS saved_network_records (
8192
+ record_id TEXT PRIMARY KEY,
8193
+ request_id TEXT NOT NULL,
8194
+ session_ref TEXT NOT NULL,
8195
+ page_ref TEXT,
8196
+ page_ref_key TEXT NOT NULL,
8197
+ frame_ref TEXT,
8198
+ document_ref TEXT,
8199
+ action_id TEXT,
8200
+ method TEXT NOT NULL,
8201
+ method_lc TEXT NOT NULL,
8202
+ url TEXT NOT NULL,
8203
+ url_lc TEXT NOT NULL,
8204
+ hostname TEXT NOT NULL,
8205
+ hostname_lc TEXT NOT NULL,
8206
+ path TEXT NOT NULL,
8207
+ path_lc TEXT NOT NULL,
8208
+ status INTEGER,
8209
+ status_text TEXT,
8210
+ resource_type TEXT NOT NULL,
8211
+ navigation_request INTEGER NOT NULL,
8212
+ request_headers_json TEXT NOT NULL,
8213
+ response_headers_json TEXT NOT NULL,
8214
+ request_body_json TEXT,
8215
+ response_body_json TEXT,
8216
+ initiator_json TEXT,
8217
+ timing_json TEXT,
8218
+ transfer_json TEXT,
8219
+ source_json TEXT,
8220
+ capture_state TEXT NOT NULL,
8221
+ request_body_state TEXT NOT NULL,
8222
+ response_body_state TEXT NOT NULL,
8223
+ request_body_skip_reason TEXT,
8224
+ response_body_skip_reason TEXT,
8225
+ request_body_error TEXT,
8226
+ response_body_error TEXT,
8227
+ redirect_from_request_id TEXT,
8228
+ redirect_to_request_id TEXT,
8229
+ saved_at INTEGER NOT NULL
8230
+ );
8231
+
8232
+ CREATE UNIQUE INDEX IF NOT EXISTS saved_network_records_scope_request
8233
+ ON saved_network_records (session_ref, page_ref_key, request_id);
8234
+
8235
+ CREATE INDEX IF NOT EXISTS saved_network_records_saved_at
8236
+ ON saved_network_records (saved_at DESC);
8237
+
8238
+ CREATE TABLE IF NOT EXISTS saved_network_tags (
8239
+ record_id TEXT NOT NULL REFERENCES saved_network_records(record_id) ON DELETE CASCADE,
8240
+ tag TEXT NOT NULL,
8241
+ PRIMARY KEY (record_id, tag)
8242
+ );
8243
+
8244
+ CREATE INDEX IF NOT EXISTS saved_network_tags_tag
8245
+ ON saved_network_tags (tag);
8246
+ `);
8247
+ this.ensureColumn(
8248
+ database,
8249
+ "saved_network_records",
8250
+ "capture_state",
8251
+ "TEXT NOT NULL DEFAULT 'complete'"
8252
+ );
8253
+ this.ensureColumn(
8254
+ database,
8255
+ "saved_network_records",
8256
+ "request_body_state",
8257
+ "TEXT NOT NULL DEFAULT 'skipped'"
8258
+ );
8259
+ this.ensureColumn(
8260
+ database,
8261
+ "saved_network_records",
8262
+ "response_body_state",
8263
+ "TEXT NOT NULL DEFAULT 'skipped'"
8264
+ );
8265
+ this.ensureColumn(database, "saved_network_records", "request_body_skip_reason", "TEXT");
8266
+ this.ensureColumn(database, "saved_network_records", "response_body_skip_reason", "TEXT");
8267
+ this.ensureColumn(database, "saved_network_records", "request_body_error", "TEXT");
8268
+ this.ensureColumn(database, "saved_network_records", "response_body_error", "TEXT");
8209
8269
  }
8210
8270
  ensureColumn(database, table, column, definition) {
8211
8271
  const rows = database.prepare(`PRAGMA table_info(${table})`).all();
@@ -8350,6 +8410,20 @@ function inflateSavedNetworkRow(row, includeBodies) {
8350
8410
  function stringifyOptional(value) {
8351
8411
  return value === void 0 ? null : JSON.stringify(value);
8352
8412
  }
8413
+ function normalizeSqliteImportError(error) {
8414
+ if (error instanceof Error && error.code === "ERR_UNKNOWN_BUILTIN_MODULE" && error.message.includes(NODE_SQLITE_SPECIFIER)) {
8415
+ return new Error(SAVED_NETWORK_SQLITE_SUPPORT_ERROR, {
8416
+ cause: error
8417
+ });
8418
+ }
8419
+ return error instanceof Error ? error : new Error(String(error));
8420
+ }
8421
+ function closeSqliteDatabase(database) {
8422
+ try {
8423
+ database.close();
8424
+ } catch {
8425
+ }
8426
+ }
8353
8427
  function withSqliteTransaction(database, task) {
8354
8428
  database.exec("BEGIN IMMEDIATE");
8355
8429
  try {
@@ -8559,8 +8633,8 @@ async function createFilesystemOpensteerWorkspace(options) {
8559
8633
  const browserManifestPath = path6__default.default.join(browserPath, "manifest.json");
8560
8634
  const browserUserDataDir = path6__default.default.join(browserPath, "user-data");
8561
8635
  const livePath = path6__default.default.join(options.rootPath, "live");
8562
- const liveSessionPath = path6__default.default.join(livePath, "session.json");
8563
- const liveBrowserPath = path6__default.default.join(livePath, "browser.json");
8636
+ const liveLocalPath = path6__default.default.join(livePath, "local.json");
8637
+ const liveCloudPath = path6__default.default.join(livePath, "cloud.json");
8564
8638
  const artifactsPath = path6__default.default.join(options.rootPath, "artifacts");
8565
8639
  const tracesPath = path6__default.default.join(options.rootPath, "traces");
8566
8640
  const registryPath = path6__default.default.join(options.rootPath, "registry");
@@ -8635,8 +8709,8 @@ async function createFilesystemOpensteerWorkspace(options) {
8635
8709
  browserManifestPath,
8636
8710
  browserUserDataDir,
8637
8711
  livePath,
8638
- liveSessionPath,
8639
- liveBrowserPath,
8712
+ liveLocalPath,
8713
+ liveCloudPath,
8640
8714
  artifactsPath,
8641
8715
  tracesPath,
8642
8716
  registryPath,
@@ -8660,6 +8734,16 @@ async function createFilesystemOpensteerWorkspace(options) {
8660
8734
  };
8661
8735
  }
8662
8736
 
8737
+ // src/runtimes/dom/errors.ts
8738
+ var ElementPathError = class extends Error {
8739
+ code;
8740
+ constructor(code, message) {
8741
+ super(message);
8742
+ this.name = "ElementPathError";
8743
+ this.code = code;
8744
+ }
8745
+ };
8746
+
8663
8747
  // src/runtimes/dom/match-policy.ts
8664
8748
  var ATTRIBUTE_DENY_KEYS = /* @__PURE__ */ new Set([
8665
8749
  "style",
@@ -9220,16 +9304,6 @@ function readDescriptorToken(value, index) {
9220
9304
  nextIndex: cursor
9221
9305
  };
9222
9306
  }
9223
-
9224
- // src/runtimes/dom/errors.ts
9225
- var ElementPathError = class extends Error {
9226
- code;
9227
- constructor(code, message) {
9228
- super(message);
9229
- this.name = "ElementPathError";
9230
- this.code = code;
9231
- }
9232
- };
9233
9307
  var selectorAdapter = {
9234
9308
  isTag(node) {
9235
9309
  return node.kind === "element" && node.source.nodeType === 1;
@@ -9984,24 +10058,31 @@ function collectChildrenInScope(index, node, scopeHostNodeRef) {
9984
10058
  function getShadowScopeNodeRef(index, node) {
9985
10059
  return findContainingShadowHostNode(index, node)?.nodeRef;
9986
10060
  }
10061
+
10062
+ // src/runtimes/dom/descriptors.ts
9987
10063
  function createDomDescriptorStore(options) {
9988
- const namespace = normalizeNamespace(options.namespace);
10064
+ const namespace = normalizeDomDescriptorNamespace(options.namespace);
9989
10065
  if (options.root) {
9990
10066
  return new FilesystemDomDescriptorStore(options.root.registry.descriptors, namespace);
9991
10067
  }
9992
10068
  return new MemoryDomDescriptorStore(namespace);
9993
10069
  }
9994
- function descriptionKey(namespace, method, description) {
9995
- return `dom:${namespace}:${method}:${sha256Hex2(description.trim())}`;
10070
+ function hashDomDescriptorDescription(description) {
10071
+ return sha256Hex2(description.trim());
9996
10072
  }
9997
- function normalizeNamespace(namespace) {
10073
+ function buildDomDescriptorKey(options) {
10074
+ return `dom:${normalizeDomDescriptorNamespace(options.namespace)}:${options.method}:${hashDomDescriptorDescription(
10075
+ options.description
10076
+ )}`;
10077
+ }
10078
+ function normalizeDomDescriptorNamespace(namespace) {
9998
10079
  const normalized = String(namespace || "default").trim();
9999
10080
  return normalized.length === 0 ? "default" : normalized;
10000
10081
  }
10001
10082
  function sha256Hex2(value) {
10002
10083
  return crypto.createHash("sha256").update(value).digest("hex");
10003
10084
  }
10004
- function buildPayload(input) {
10085
+ function buildDomDescriptorPayload(input) {
10005
10086
  return {
10006
10087
  kind: "dom-target",
10007
10088
  method: input.method,
@@ -10010,6 +10091,9 @@ function buildPayload(input) {
10010
10091
  ...input.sourceUrl === void 0 ? {} : { sourceUrl: input.sourceUrl }
10011
10092
  };
10012
10093
  }
10094
+ function buildDomDescriptorVersion(payload) {
10095
+ return sha256Hex2(canonicalJsonString(payload));
10096
+ }
10013
10097
  function parseDomDescriptorRecord(record) {
10014
10098
  const payload = record.payload;
10015
10099
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
@@ -10051,7 +10135,11 @@ var FilesystemDomDescriptorStore = class {
10051
10135
  }
10052
10136
  async read(input) {
10053
10137
  const record = await this.registry.resolve({
10054
- key: descriptionKey(this.namespace, input.method, input.description)
10138
+ key: buildDomDescriptorKey({
10139
+ namespace: this.namespace,
10140
+ method: input.method,
10141
+ description: input.description
10142
+ })
10055
10143
  });
10056
10144
  if (!record) {
10057
10145
  return void 0;
@@ -10059,9 +10147,13 @@ var FilesystemDomDescriptorStore = class {
10059
10147
  return parseDomDescriptorRecord(record);
10060
10148
  }
10061
10149
  async write(input) {
10062
- const payload = buildPayload(input);
10063
- const key = descriptionKey(this.namespace, input.method, input.description);
10064
- const version = sha256Hex2(canonicalJsonString(payload));
10150
+ const payload = buildDomDescriptorPayload(input);
10151
+ const key = buildDomDescriptorKey({
10152
+ namespace: this.namespace,
10153
+ method: input.method,
10154
+ description: input.description
10155
+ });
10156
+ const version = buildDomDescriptorVersion(payload);
10065
10157
  const existing = await this.registry.resolve({ key, version });
10066
10158
  if (existing) {
10067
10159
  const parsed2 = parseDomDescriptorRecord(existing);
@@ -10099,12 +10191,22 @@ var MemoryDomDescriptorStore = class {
10099
10191
  latestByKey = /* @__PURE__ */ new Map();
10100
10192
  recordsByKey = /* @__PURE__ */ new Map();
10101
10193
  async read(input) {
10102
- return this.latestByKey.get(descriptionKey(this.namespace, input.method, input.description));
10194
+ return this.latestByKey.get(
10195
+ buildDomDescriptorKey({
10196
+ namespace: this.namespace,
10197
+ method: input.method,
10198
+ description: input.description
10199
+ })
10200
+ );
10103
10201
  }
10104
10202
  async write(input) {
10105
- const payload = buildPayload(input);
10106
- const key = descriptionKey(this.namespace, input.method, input.description);
10107
- const version = sha256Hex2(canonicalJsonString(payload));
10203
+ const payload = buildDomDescriptorPayload(input);
10204
+ const key = buildDomDescriptorKey({
10205
+ namespace: this.namespace,
10206
+ method: input.method,
10207
+ description: input.description
10208
+ });
10209
+ const version = buildDomDescriptorVersion(payload);
10108
10210
  const existing = this.recordsByKey.get(key)?.get(version);
10109
10211
  if (existing) {
10110
10212
  return existing;
@@ -10747,7 +10849,7 @@ var DefaultDomRuntime = class {
10747
10849
  bridge;
10748
10850
  constructor(options) {
10749
10851
  this.engine = options.engine;
10750
- this.descriptors = createDomDescriptorStore({
10852
+ this.descriptors = options.descriptorStore ?? createDomDescriptorStore({
10751
10853
  ...options.root === void 0 ? {} : { root: options.root },
10752
10854
  ...options.namespace === void 0 ? {} : { namespace: options.namespace }
10753
10855
  });
@@ -12635,7 +12737,7 @@ function inferRequestPlanFromNetworkRecord(record, input, options = {}) {
12635
12737
  const body = inferRequestPlanBody(record.record.requestBody, requestContentType);
12636
12738
  const payload = normalizeRequestPlanPayload({
12637
12739
  transport: {
12638
- kind: "context-http"
12740
+ kind: input.transport ?? "context-http"
12639
12741
  },
12640
12742
  endpoint: {
12641
12743
  method: record.record.method,
@@ -12655,7 +12757,6 @@ function inferRequestPlanFromNetworkRecord(record, input, options = {}) {
12655
12757
  return {
12656
12758
  key: input.key,
12657
12759
  version: input.version,
12658
- lifecycle: input.lifecycle ?? "draft",
12659
12760
  provenance: {
12660
12761
  source: record.source === "saved" ? "saved-network-record" : "live-network-record",
12661
12762
  sourceId: record.recordId,
@@ -16927,7 +17028,6 @@ async function compileOpensteerExtractionFieldTargets(options) {
16927
17028
  await collectFieldTargetsFromSchemaObject({
16928
17029
  dom: options.dom,
16929
17030
  pageRef: options.pageRef,
16930
- latestSnapshotCounters: options.latestSnapshotCounters,
16931
17031
  value: options.schema,
16932
17032
  path: "",
16933
17033
  fields,
@@ -16945,22 +17045,11 @@ async function extractOpensteerExtractionFieldTargets(options) {
16945
17045
  source: "current_url"
16946
17046
  };
16947
17047
  }
16948
- if ("path" in field) {
16949
- return {
16950
- key: field.key,
16951
- target: {
16952
- kind: "path",
16953
- path: field.path
16954
- },
16955
- ...field.attribute === void 0 ? {} : { attribute: field.attribute }
16956
- };
16957
- }
16958
17048
  return {
16959
17049
  key: field.key,
16960
17050
  target: {
16961
- kind: "live",
16962
- locator: field.locator,
16963
- anchor: field.anchor
17051
+ kind: "path",
17052
+ path: field.path
16964
17053
  },
16965
17054
  ...field.attribute === void 0 ? {} : { attribute: field.attribute }
16966
17055
  };
@@ -16969,8 +17058,6 @@ async function extractOpensteerExtractionFieldTargets(options) {
16969
17058
  }
16970
17059
  async function compilePersistedOpensteerExtractionPayloadFromFieldTargets(options) {
16971
17060
  const fields = await resolvePersistableFieldTargets({
16972
- pageRef: options.pageRef,
16973
- dom: options.dom,
16974
17061
  fieldTargets: options.fieldTargets
16975
17062
  });
16976
17063
  const payload = buildPersistedOpensteerExtractionPayload(fields);
@@ -16984,7 +17071,7 @@ async function replayOpensteerExtractionPayload(options) {
16984
17071
  return extractPersistedObjectNode(options.pageRef, options.dom, options.payload);
16985
17072
  }
16986
17073
  function createOpensteerExtractionDescriptorStore(options) {
16987
- const namespace = normalizeNamespace2(options.namespace);
17074
+ const namespace = normalizeNamespace(options.namespace);
16988
17075
  if (options.root) {
16989
17076
  return new FilesystemOpensteerExtractionDescriptorStore(
16990
17077
  options.root.registry.descriptors,
@@ -17002,7 +17089,6 @@ async function collectFieldTargetsFromSchemaObject(options) {
17002
17089
  await collectFieldTargetsFromSchemaValue({
17003
17090
  dom: options.dom,
17004
17091
  pageRef: options.pageRef,
17005
- latestSnapshotCounters: options.latestSnapshotCounters,
17006
17092
  value: childValue,
17007
17093
  path: joinDataPath(options.path, normalizedKey),
17008
17094
  fields: options.fields,
@@ -17017,7 +17103,6 @@ async function collectFieldTargetsFromSchemaValue(options) {
17017
17103
  await compileFieldTarget({
17018
17104
  dom: options.dom,
17019
17105
  pageRef: options.pageRef,
17020
- latestSnapshotCounters: options.latestSnapshotCounters,
17021
17106
  field: normalizedField,
17022
17107
  path: options.path
17023
17108
  })
@@ -17046,7 +17131,6 @@ async function collectFieldTargetsFromSchemaValue(options) {
17046
17131
  await collectFieldTargetsFromSchemaObject({
17047
17132
  dom: options.dom,
17048
17133
  pageRef: options.pageRef,
17049
- latestSnapshotCounters: options.latestSnapshotCounters,
17050
17134
  value: itemValue,
17051
17135
  path: appendDataPathIndex(options.path, index),
17052
17136
  fields: options.fields,
@@ -17069,7 +17153,6 @@ async function collectFieldTargetsFromSchemaValue(options) {
17069
17153
  await collectFieldTargetsFromSchemaObject({
17070
17154
  dom: options.dom,
17071
17155
  pageRef: options.pageRef,
17072
- latestSnapshotCounters: options.latestSnapshotCounters,
17073
17156
  value: options.value,
17074
17157
  path: options.path,
17075
17158
  fields: options.fields,
@@ -17096,10 +17179,10 @@ async function compileFieldTarget(options) {
17096
17179
  }
17097
17180
  return {
17098
17181
  key: options.path,
17099
- ...await resolveLiveFieldTarget({
17100
- latestSnapshotCounters: options.latestSnapshotCounters,
17101
- field: options.field,
17102
- path: options.path
17182
+ path: await resolveSelectorFieldPath({
17183
+ dom: options.dom,
17184
+ pageRef: options.pageRef,
17185
+ selector: `[c="${String(options.field.element)}"]`
17103
17186
  }),
17104
17187
  ...options.field.attribute === void 0 ? {} : { attribute: options.field.attribute }
17105
17188
  };
@@ -17117,24 +17200,6 @@ async function resolveSelectorFieldPath(options) {
17117
17200
  locator: resolved.locator
17118
17201
  });
17119
17202
  }
17120
- async function resolveLiveFieldTarget(options) {
17121
- const counters = options.latestSnapshotCounters;
17122
- if (counters === void 0) {
17123
- throw new Error(
17124
- `Extraction schema field "${labelForPath(options.path)}" uses element ${String(options.field.element)} but no snapshot is available.`
17125
- );
17126
- }
17127
- const counter = counters.get(options.field.element);
17128
- if (!counter) {
17129
- throw new Error(
17130
- `Extraction schema field "${labelForPath(options.path)}" references missing counter ${String(options.field.element)}.`
17131
- );
17132
- }
17133
- return {
17134
- locator: counter.locator,
17135
- anchor: counter.anchor
17136
- };
17137
- }
17138
17203
  async function resolvePersistableFieldTargets(options) {
17139
17204
  const fields = [];
17140
17205
  for (const field of options.fieldTargets) {
@@ -17145,29 +17210,9 @@ async function resolvePersistableFieldTargets(options) {
17145
17210
  });
17146
17211
  continue;
17147
17212
  }
17148
- if ("path" in field) {
17149
- fields.push({
17150
- key: field.key,
17151
- path: sanitizeElementPath(field.path),
17152
- ...field.attribute === void 0 ? {} : { attribute: field.attribute }
17153
- });
17154
- continue;
17155
- }
17156
- const resolved = await options.dom.resolveTarget({
17157
- pageRef: options.pageRef,
17158
- method: "extract",
17159
- target: {
17160
- kind: "live",
17161
- locator: field.locator,
17162
- anchor: field.anchor
17163
- }
17164
- });
17165
- const path9 = resolved.replayPath ?? await options.dom.buildPath({
17166
- locator: resolved.locator
17167
- });
17168
17213
  fields.push({
17169
17214
  key: field.key,
17170
- path: sanitizeElementPath(path9),
17215
+ path: sanitizeElementPath(field.path),
17171
17216
  ...field.attribute === void 0 ? {} : { attribute: field.attribute }
17172
17217
  });
17173
17218
  }
@@ -17481,11 +17526,11 @@ function normalizeSchemaField(value) {
17481
17526
  ...attribute === void 0 ? {} : { attribute }
17482
17527
  };
17483
17528
  }
17484
- function normalizeNamespace2(namespace) {
17529
+ function normalizeNamespace(namespace) {
17485
17530
  const normalized = String(namespace ?? "default").trim();
17486
17531
  return normalized.length === 0 ? "default" : normalized;
17487
17532
  }
17488
- function descriptionKey2(namespace, description) {
17533
+ function descriptionKey(namespace, description) {
17489
17534
  return `extract:${namespace}:${sha256Hex3(description.trim())}`;
17490
17535
  }
17491
17536
  function parseExtractionDescriptorRecord(record) {
@@ -17588,7 +17633,7 @@ var FilesystemOpensteerExtractionDescriptorStore = class {
17588
17633
  }
17589
17634
  async read(input) {
17590
17635
  const record = await this.registry.resolve({
17591
- key: descriptionKey2(this.namespace, input.description)
17636
+ key: descriptionKey(this.namespace, input.description)
17592
17637
  });
17593
17638
  return record === void 0 ? void 0 : parseExtractionDescriptorRecord(record);
17594
17639
  }
@@ -17600,7 +17645,7 @@ var FilesystemOpensteerExtractionDescriptorStore = class {
17600
17645
  ...input.schemaHash === void 0 ? {} : { schemaHash: input.schemaHash },
17601
17646
  ...input.sourceUrl === void 0 ? {} : { sourceUrl: input.sourceUrl }
17602
17647
  };
17603
- const key = descriptionKey2(this.namespace, input.description);
17648
+ const key = descriptionKey(this.namespace, input.description);
17604
17649
  const version = sha256Hex3(canonicalJsonString(payload));
17605
17650
  const existing = await this.registry.resolve({ key, version });
17606
17651
  if (existing) {
@@ -17639,7 +17684,7 @@ var MemoryOpensteerExtractionDescriptorStore = class {
17639
17684
  latestByKey = /* @__PURE__ */ new Map();
17640
17685
  recordsByKey = /* @__PURE__ */ new Map();
17641
17686
  async read(input) {
17642
- return this.latestByKey.get(descriptionKey2(this.namespace, input.description));
17687
+ return this.latestByKey.get(descriptionKey(this.namespace, input.description));
17643
17688
  }
17644
17689
  async write(input) {
17645
17690
  const payload = {
@@ -17649,7 +17694,7 @@ var MemoryOpensteerExtractionDescriptorStore = class {
17649
17694
  ...input.schemaHash === void 0 ? {} : { schemaHash: input.schemaHash },
17650
17695
  ...input.sourceUrl === void 0 ? {} : { sourceUrl: input.sourceUrl }
17651
17696
  };
17652
- const key = descriptionKey2(this.namespace, input.description);
17697
+ const key = descriptionKey(this.namespace, input.description);
17653
17698
  const version = sha256Hex3(canonicalJsonString(payload));
17654
17699
  const existing = this.recordsByKey.get(key)?.get(version);
17655
17700
  if (existing) {
@@ -17693,6 +17738,7 @@ var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
17693
17738
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
17694
17739
  var OPENSTEER_SCROLLABLE_ATTR = "data-opensteer-scrollable";
17695
17740
  var OPENSTEER_NODE_ID_ATTR = "data-os-node-id";
17741
+ var OPENSTEER_SPARSE_COUNTER_ATTR = "data-os-c";
17696
17742
  var OPENSTEER_BOUNDARY_ATTR = "data-os-boundary";
17697
17743
  var OPENSTEER_UNAVAILABLE_ATTR = "data-os-unavailable";
17698
17744
  var OPENSTEER_IFRAME_BOUNDARY_TAG = "os-iframe-root";
@@ -18197,7 +18243,82 @@ var VOID_TAGS2 = /* @__PURE__ */ new Set([
18197
18243
  ]);
18198
18244
 
18199
18245
  // src/sdk/snapshot/compiler.ts
18246
+ async function assignSparseCountersToLiveDom(engine, pageRef) {
18247
+ try {
18248
+ await engine.evaluatePage({
18249
+ pageRef,
18250
+ script: `(() => {
18251
+ let counter = 1;
18252
+ const walk = (root) => {
18253
+ for (const child of root.children) {
18254
+ child.setAttribute('data-os-c', String(counter++));
18255
+ walk(child);
18256
+ if (child.shadowRoot) walk(child.shadowRoot);
18257
+ }
18258
+ };
18259
+ walk(document);
18260
+ })()`
18261
+ });
18262
+ return true;
18263
+ } catch {
18264
+ return false;
18265
+ }
18266
+ }
18267
+ async function syncDenseCountersToLiveDom(engine, pageRef, sparseToDirectMapping) {
18268
+ const mappingObj = Object.fromEntries(sparseToDirectMapping);
18269
+ await engine.evaluatePage({
18270
+ pageRef,
18271
+ script: `((mapping) => {
18272
+ const walk = (root) => {
18273
+ for (const child of root.children) {
18274
+ child.removeAttribute('c');
18275
+ const sparse = child.getAttribute('data-os-c');
18276
+ if (sparse !== null) {
18277
+ const dense = mapping[sparse];
18278
+ if (dense !== undefined) {
18279
+ child.setAttribute('c', String(dense));
18280
+ }
18281
+ child.removeAttribute('data-os-c');
18282
+ }
18283
+ walk(child);
18284
+ if (child.shadowRoot) walk(child.shadowRoot);
18285
+ }
18286
+ };
18287
+ walk(document);
18288
+ })`,
18289
+ args: [mappingObj]
18290
+ });
18291
+ }
18292
+ function renumberCountersDensely(cleanedHtml, counterRecords) {
18293
+ const $ = cheerio__namespace.load(cleanedHtml, { xmlMode: false });
18294
+ const newRecords = /* @__PURE__ */ new Map();
18295
+ const sparseToDirectMapping = /* @__PURE__ */ new Map();
18296
+ let nextDense = 1;
18297
+ $("[c]").each(function renumberElement() {
18298
+ const el = $(this);
18299
+ const oldC = Number.parseInt(String(el.attr("c") || ""), 10);
18300
+ if (!Number.isFinite(oldC)) {
18301
+ return;
18302
+ }
18303
+ const record = counterRecords.get(oldC);
18304
+ if (!record) {
18305
+ return;
18306
+ }
18307
+ const denseC = nextDense++;
18308
+ el.attr("c", String(denseC));
18309
+ newRecords.set(denseC, { ...record, element: denseC });
18310
+ if (record.sparseCounter !== void 0) {
18311
+ sparseToDirectMapping.set(record.sparseCounter, denseC);
18312
+ }
18313
+ });
18314
+ return {
18315
+ html: $.html(),
18316
+ counterRecords: newRecords,
18317
+ sparseToDirectMapping
18318
+ };
18319
+ }
18200
18320
  async function compileOpensteerSnapshot(options) {
18321
+ const liveCountersEnabled = await assignSparseCountersToLiveDom(options.engine, options.pageRef);
18201
18322
  const pageInfo = await options.engine.getPageInfo({ pageRef: options.pageRef });
18202
18323
  const mainSnapshot = await getMainDocumentSnapshot(options.engine, options.pageRef);
18203
18324
  const snapshotsByDocumentRef = await collectDocumentSnapshots(options.engine, mainSnapshot);
@@ -18216,13 +18337,23 @@ async function compileOpensteerSnapshot(options) {
18216
18337
  const compiledHtml = assignCounters(rawHtml, renderedNodes);
18217
18338
  const cleanedHtml = options.mode === "extraction" ? cleanForExtraction(compiledHtml.html) : cleanForAction(compiledHtml.html);
18218
18339
  const filtered = retainVisibleCounterRecords(cleanedHtml, compiledHtml.counterRecords);
18340
+ const dense = renumberCountersDensely(cleanedHtml, filtered);
18341
+ if (liveCountersEnabled && dense.sparseToDirectMapping.size > 0) {
18342
+ try {
18343
+ await syncDenseCountersToLiveDom(
18344
+ options.engine,
18345
+ options.pageRef,
18346
+ dense.sparseToDirectMapping
18347
+ );
18348
+ } catch {
18349
+ }
18350
+ }
18219
18351
  return {
18220
18352
  url: pageInfo.url,
18221
18353
  title: pageInfo.title,
18222
18354
  mode: options.mode,
18223
- html: cleanedHtml,
18224
- counters: [...filtered.values()].map(toPublicCounterRecord),
18225
- counterRecords: filtered
18355
+ html: dense.html,
18356
+ counters: [...dense.counterRecords.values()].map(toPublicCounterRecord)
18226
18357
  };
18227
18358
  }
18228
18359
  async function getMainDocumentSnapshot(engine, pageRef) {
@@ -18451,6 +18582,9 @@ function assignCounters(rawHtml, renderedNodes) {
18451
18582
  if (!rendered) {
18452
18583
  return;
18453
18584
  }
18585
+ const rawSparseCounter = el.attr(OPENSTEER_SPARSE_COUNTER_ATTR);
18586
+ el.removeAttr(OPENSTEER_SPARSE_COUNTER_ATTR);
18587
+ const sparseCounter = rawSparseCounter ? Number.parseInt(rawSparseCounter, 10) : void 0;
18454
18588
  const counter = nextCounter++;
18455
18589
  el.attr("c", String(counter));
18456
18590
  counterRecords.set(counter, {
@@ -18468,7 +18602,8 @@ function assignCounters(rawHtml, renderedNodes) {
18468
18602
  shadowDepth: rendered.shadowDepth,
18469
18603
  interactive: rendered.interactive,
18470
18604
  locator: rendered.locator,
18471
- anchor: rendered.anchor
18605
+ anchor: rendered.anchor,
18606
+ ...sparseCounter !== void 0 && Number.isFinite(sparseCounter) ? { sparseCounter } : {}
18472
18607
  });
18473
18608
  });
18474
18609
  return {
@@ -19836,6 +19971,9 @@ var OpensteerSessionRuntime = class {
19836
19971
  injectedEngine;
19837
19972
  engineFactory;
19838
19973
  policy;
19974
+ injectedDescriptorStore;
19975
+ injectedExtractionDescriptorStore;
19976
+ registryOverrides;
19839
19977
  cleanupRootOnClose;
19840
19978
  sessionInfoBase;
19841
19979
  root;
@@ -19847,19 +19985,21 @@ var OpensteerSessionRuntime = class {
19847
19985
  sessionRef;
19848
19986
  pageRef;
19849
19987
  runId;
19850
- latestSnapshot;
19851
19988
  backgroundNetworkPersistence = /* @__PURE__ */ new Set();
19852
19989
  cookieJars = /* @__PURE__ */ new Map();
19853
19990
  recipeCache = /* @__PURE__ */ new Map();
19854
19991
  ownsEngine = false;
19855
19992
  constructor(options) {
19856
- this.workspace = normalizeNamespace3(options.name);
19993
+ this.workspace = normalizeNamespace2(options.name);
19857
19994
  this.workspaceName = options.workspaceName?.trim() === void 0 || options.workspaceName?.trim().length === 0 ? void 0 : options.workspaceName.trim();
19858
19995
  this.root = options.workspace;
19859
19996
  this.rootPath = options.workspace?.rootPath ?? options.rootPath ?? path6__default.default.resolve(process.cwd(), ".opensteer", "temporary", crypto.randomUUID());
19860
19997
  this.injectedEngine = options.engine;
19861
19998
  this.engineFactory = options.engineFactory;
19862
19999
  this.policy = options.policy ?? defaultPolicy();
20000
+ this.injectedDescriptorStore = options.descriptorStore;
20001
+ this.injectedExtractionDescriptorStore = options.extractionDescriptorStore;
20002
+ this.registryOverrides = options.registryOverrides;
19863
20003
  this.cleanupRootOnClose = options.cleanupRootOnClose ?? options.workspace === void 0;
19864
20004
  this.sessionInfoBase = options.sessionInfo ?? {};
19865
20005
  if (this.injectedEngine === void 0 && this.engineFactory === void 0) {
@@ -19870,7 +20010,7 @@ var OpensteerSessionRuntime = class {
19870
20010
  const base = this.sessionInfoBase;
19871
20011
  return {
19872
20012
  provider: base.provider ?? {
19873
- kind: "local",
20013
+ mode: "local",
19874
20014
  ownership: "owned",
19875
20015
  engine: "playwright"
19876
20016
  },
@@ -19895,7 +20035,7 @@ var OpensteerSessionRuntime = class {
19895
20035
  }
19896
20036
  async open(input = {}, options = {}) {
19897
20037
  assertValidSemanticOperationInput("session.open", input);
19898
- if (input.workspace !== void 0 && normalizeNamespace3(input.workspace) !== this.workspace) {
20038
+ if (input.workspace !== void 0 && normalizeNamespace2(input.workspace) !== this.workspace) {
19899
20039
  throw new Error(
19900
20040
  `session.open requested workspace "${input.workspace}" but runtime is bound to "${this.workspace}"`
19901
20041
  );
@@ -19937,7 +20077,6 @@ var OpensteerSessionRuntime = class {
19937
20077
  timeout.throwIfAborted();
19938
20078
  this.sessionRef = sessionRef;
19939
20079
  this.pageRef = createdPage.data.pageRef;
19940
- this.latestSnapshot = void 0;
19941
20080
  await timeout.runStep(() => this.ensureSemantics());
19942
20081
  let frameRef2 = createdPage.frameRef;
19943
20082
  if (input.url !== void 0) {
@@ -20060,7 +20199,6 @@ var OpensteerSessionRuntime = class {
20060
20199
  })
20061
20200
  );
20062
20201
  this.pageRef = created.data.pageRef;
20063
- this.latestSnapshot = void 0;
20064
20202
  return this.readSessionState();
20065
20203
  },
20066
20204
  options
@@ -20103,7 +20241,6 @@ var OpensteerSessionRuntime = class {
20103
20241
  () => this.requireEngine().activatePage({ pageRef: input.pageRef })
20104
20242
  );
20105
20243
  this.pageRef = input.pageRef;
20106
- this.latestSnapshot = void 0;
20107
20244
  return this.readSessionState();
20108
20245
  },
20109
20246
  options
@@ -20167,7 +20304,6 @@ var OpensteerSessionRuntime = class {
20167
20304
  );
20168
20305
  }
20169
20306
  this.pageRef = activePageRef;
20170
- this.latestSnapshot = void 0;
20171
20307
  return {
20172
20308
  closedPageRef: targetPageRef,
20173
20309
  ...activePageRef === void 0 ? {} : { activePageRef },
@@ -20226,7 +20362,6 @@ var OpensteerSessionRuntime = class {
20226
20362
  timeout
20227
20363
  );
20228
20364
  timeout.throwIfAborted();
20229
- this.latestSnapshot = void 0;
20230
20365
  await this.completeMutationCapture(timeout, baselineRequestIds, input.networkTag);
20231
20366
  return {
20232
20367
  navigation: navigation2,
@@ -20396,7 +20531,6 @@ var OpensteerSessionRuntime = class {
20396
20531
  })
20397
20532
  );
20398
20533
  timeout.throwIfAborted();
20399
- this.latestSnapshot = compiled;
20400
20534
  const artifacts2 = await this.captureSnapshotArtifacts(
20401
20535
  pageRef,
20402
20536
  {
@@ -20546,8 +20680,7 @@ var OpensteerSessionRuntime = class {
20546
20680
  () => compileOpensteerExtractionFieldTargets({
20547
20681
  pageRef,
20548
20682
  schema: input.schema,
20549
- dom: this.requireDom(),
20550
- ...this.latestSnapshot?.counterRecords === void 0 ? {} : { latestSnapshotCounters: this.latestSnapshot.counterRecords }
20683
+ dom: this.requireDom()
20551
20684
  })
20552
20685
  );
20553
20686
  data = toCanonicalJsonValue(
@@ -22311,8 +22444,7 @@ var OpensteerSessionRuntime = class {
22311
22444
  const inferred = inferRequestPlanFromNetworkRecord(record, {
22312
22445
  recordId: candidate.recordId,
22313
22446
  key: input.key,
22314
- version: input.version,
22315
- lifecycle: "draft"
22447
+ version: input.version
22316
22448
  });
22317
22449
  const defaultHeaders = inferred.payload.endpoint.defaultHeaders === void 0 ? void 0 : stripManagedRequestHeaders(
22318
22450
  inferred.payload.endpoint.defaultHeaders,
@@ -22940,8 +23072,7 @@ var OpensteerSessionRuntime = class {
22940
23072
  recordId: input.recordId,
22941
23073
  id: record.id,
22942
23074
  key: record.key,
22943
- version: record.version,
22944
- lifecycle: record.lifecycle
23075
+ version: record.version
22945
23076
  }
22946
23077
  });
22947
23078
  return record;
@@ -22982,8 +23113,7 @@ var OpensteerSessionRuntime = class {
22982
23113
  data: {
22983
23114
  id: record.id,
22984
23115
  key: record.key,
22985
- version: record.version,
22986
- lifecycle: record.lifecycle
23116
+ version: record.version
22987
23117
  }
22988
23118
  });
22989
23119
  return record;
@@ -23029,8 +23159,7 @@ var OpensteerSessionRuntime = class {
23029
23159
  data: {
23030
23160
  id: record.id,
23031
23161
  key: record.key,
23032
- version: record.version,
23033
- lifecycle: record.lifecycle
23162
+ version: record.version
23034
23163
  }
23035
23164
  });
23036
23165
  return record;
@@ -23670,7 +23799,6 @@ var OpensteerSessionRuntime = class {
23670
23799
  });
23671
23800
  timeout.throwIfAborted();
23672
23801
  this.pageRef = output2.pageRef;
23673
- this.latestSnapshot = void 0;
23674
23802
  await this.completeMutationCapture(timeout, baselineRequestIds, input.networkTag);
23675
23803
  const artifacts2 = await this.persistComputerArtifacts(output2, timeout);
23676
23804
  return {
@@ -23900,19 +24028,12 @@ var OpensteerSessionRuntime = class {
23900
24028
  };
23901
24029
  }
23902
24030
  if (target.kind === "element") {
23903
- const counter = this.latestSnapshot?.counterRecords.get(target.element);
23904
- if (!counter) {
23905
- throw new Error(`no counter ${String(target.element)} is available in the latest snapshot`);
23906
- }
24031
+ const elementTarget = { kind: "selector", selector: `[c="${String(target.element)}"]` };
23907
24032
  const resolved2 = await timeout.runStep(
23908
24033
  () => this.requireDom().resolveTarget({
23909
24034
  pageRef,
23910
24035
  method,
23911
- target: {
23912
- kind: "live",
23913
- locator: counter.locator,
23914
- anchor: counter.anchor
23915
- }
24036
+ target: elementTarget
23916
24037
  })
23917
24038
  );
23918
24039
  const stablePath2 = resolved2.replayPath ?? await timeout.runStep(
@@ -25155,7 +25276,7 @@ var OpensteerSessionRuntime = class {
25155
25276
  }
25156
25277
  async touchRequestPlanFreshness(plan) {
25157
25278
  const freshness = touchFreshness(plan.freshness);
25158
- await this.requireRoot().registry.requestPlans.updateMetadata({
25279
+ await this.requireRoot().registry.requestPlans.updateFreshness({
25159
25280
  id: plan.id,
25160
25281
  ...freshness === void 0 ? {} : { freshness }
25161
25282
  });
@@ -25823,22 +25944,33 @@ var OpensteerSessionRuntime = class {
25823
25944
  selector: target.selector
25824
25945
  };
25825
25946
  }
25826
- const counter = this.latestSnapshot?.counterRecords.get(target.element);
25827
- if (!counter) {
25828
- throw new Error(`no counter ${String(target.element)} is available in the latest snapshot`);
25829
- }
25830
25947
  return {
25831
- kind: "live",
25832
- locator: counter.locator,
25833
- anchor: counter.anchor
25948
+ kind: "selector",
25949
+ selector: `[c="${String(target.element)}"]`
25834
25950
  };
25835
25951
  }
25836
25952
  async ensureRoot() {
25837
- this.root ??= await createFilesystemOpensteerWorkspace({
25838
- rootPath: this.rootPath,
25839
- ...this.workspaceName === void 0 ? {} : { workspace: this.workspaceName },
25840
- scope: this.workspaceName === void 0 ? "temporary" : "workspace"
25841
- });
25953
+ if (!this.root) {
25954
+ const workspace = await createFilesystemOpensteerWorkspace({
25955
+ rootPath: this.rootPath,
25956
+ ...this.workspaceName === void 0 ? {} : { workspace: this.workspaceName },
25957
+ scope: this.workspaceName === void 0 ? "temporary" : "workspace"
25958
+ });
25959
+ if (this.registryOverrides) {
25960
+ const overrides = this.registryOverrides;
25961
+ this.root = {
25962
+ ...workspace,
25963
+ registry: {
25964
+ ...workspace.registry,
25965
+ ...overrides.requestPlans === void 0 ? {} : { requestPlans: overrides.requestPlans },
25966
+ ...overrides.authRecipes === void 0 ? {} : { authRecipes: overrides.authRecipes },
25967
+ ...overrides.recipes === void 0 ? {} : { recipes: overrides.recipes }
25968
+ }
25969
+ };
25970
+ } else {
25971
+ this.root = workspace;
25972
+ }
25973
+ }
25842
25974
  return this.root;
25843
25975
  }
25844
25976
  async ensureEngine(overrides = {}) {
@@ -25864,6 +25996,7 @@ var OpensteerSessionRuntime = class {
25864
25996
  engine,
25865
25997
  root,
25866
25998
  namespace: this.workspace,
25999
+ ...this.injectedDescriptorStore === void 0 ? {} : { descriptorStore: this.injectedDescriptorStore },
25867
26000
  policy: this.policy
25868
26001
  });
25869
26002
  this.computer = createComputerUseRuntime({
@@ -25871,7 +26004,7 @@ var OpensteerSessionRuntime = class {
25871
26004
  dom: this.dom,
25872
26005
  policy: this.policy
25873
26006
  });
25874
- this.extractionDescriptors = createOpensteerExtractionDescriptorStore({
26007
+ this.extractionDescriptors = this.injectedExtractionDescriptorStore ?? createOpensteerExtractionDescriptorStore({
25875
26008
  root,
25876
26009
  namespace: this.workspace
25877
26010
  });
@@ -26092,7 +26225,6 @@ var OpensteerSessionRuntime = class {
26092
26225
  this.backgroundNetworkPersistence.clear();
26093
26226
  this.sessionRef = void 0;
26094
26227
  this.pageRef = void 0;
26095
- this.latestSnapshot = void 0;
26096
26228
  this.runId = void 0;
26097
26229
  this.dom = void 0;
26098
26230
  this.computer = void 0;
@@ -26450,7 +26582,6 @@ function buildMinimizedRequestPlan(input) {
26450
26582
  sourceId: input.record.recordId,
26451
26583
  ...input.record.source === "saved" && input.record.savedAt !== void 0 ? { capturedAt: input.record.savedAt } : {}
26452
26584
  },
26453
- lifecycle: "draft",
26454
26585
  payload: normalizeRequestPlanPayload({
26455
26586
  transport: {
26456
26587
  kind: input.transport
@@ -28605,7 +28736,7 @@ function directionToDelta(direction, amount) {
28605
28736
  return { x: amount, y: 0 };
28606
28737
  }
28607
28738
  }
28608
- function normalizeNamespace3(value) {
28739
+ function normalizeNamespace2(value) {
28609
28740
  const normalized = String(value ?? "default").trim();
28610
28741
  return normalized.length === 0 ? "default" : normalized;
28611
28742
  }
@@ -28655,9 +28786,18 @@ exports.OPENSTEER_FILESYSTEM_WORKSPACE_LAYOUT = OPENSTEER_FILESYSTEM_WORKSPACE_L
28655
28786
  exports.OPENSTEER_FILESYSTEM_WORKSPACE_VERSION = OPENSTEER_FILESYSTEM_WORKSPACE_VERSION;
28656
28787
  exports.OPENSTEER_RUNTIME_CORE_VERSION = OPENSTEER_RUNTIME_CORE_VERSION;
28657
28788
  exports.OpensteerSessionRuntime = OpensteerSessionRuntime;
28789
+ exports.buildDomDescriptorKey = buildDomDescriptorKey;
28790
+ exports.buildDomDescriptorPayload = buildDomDescriptorPayload;
28791
+ exports.buildDomDescriptorVersion = buildDomDescriptorVersion;
28792
+ exports.createDomDescriptorStore = createDomDescriptorStore;
28658
28793
  exports.createFilesystemOpensteerWorkspace = createFilesystemOpensteerWorkspace;
28794
+ exports.createOpensteerExtractionDescriptorStore = createOpensteerExtractionDescriptorStore;
28659
28795
  exports.dispatchSemanticOperation = dispatchSemanticOperation;
28796
+ exports.hashDomDescriptorDescription = hashDomDescriptorDescription;
28660
28797
  exports.normalizeWorkspaceId = normalizeWorkspaceId;
28798
+ exports.parseDomDescriptorRecord = parseDomDescriptorRecord;
28799
+ exports.parseExtractionDescriptorRecord = parseExtractionDescriptorRecord;
28661
28800
  exports.resolveFilesystemWorkspacePath = resolveFilesystemWorkspacePath;
28801
+ exports.sanitizeReplayElementPath = sanitizeReplayElementPath;
28662
28802
  //# sourceMappingURL=index.cjs.map
28663
28803
  //# sourceMappingURL=index.cjs.map