opensteer 0.8.6 → 0.8.7

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
@@ -1461,13 +1461,9 @@ var networkRecordSchema = objectSchema(
1461
1461
  ]
1462
1462
  }
1463
1463
  );
1464
- var networkQuerySourceSchema = enumSchema(["live", "saved"], {
1465
- title: "NetworkQuerySource"
1466
- });
1467
1464
  var networkQueryRecordSchema = objectSchema(
1468
1465
  {
1469
1466
  recordId: stringSchema({ minLength: 1 }),
1470
- source: networkQuerySourceSchema,
1471
1467
  actionId: stringSchema({ minLength: 1 }),
1472
1468
  tags: arraySchema(stringSchema({ minLength: 1 }), {
1473
1469
  uniqueItems: true
@@ -1477,7 +1473,7 @@ var networkQueryRecordSchema = objectSchema(
1477
1473
  },
1478
1474
  {
1479
1475
  title: "NetworkQueryRecord",
1480
- required: ["recordId", "source", "record"]
1476
+ required: ["recordId", "record"]
1481
1477
  }
1482
1478
  );
1483
1479
  arraySchema(headerEntrySchema, {
@@ -2173,9 +2169,6 @@ var opensteerRecipeRecordSchema = objectSchema(
2173
2169
  var opensteerAuthRecipeRecordSchema = opensteerRecipeRecordSchema;
2174
2170
  var opensteerNetworkQueryInputSchema = objectSchema(
2175
2171
  {
2176
- source: enumSchema(["live", "saved"], {
2177
- title: "OpensteerNetworkQuerySource"
2178
- }),
2179
2172
  pageRef: pageRefSchema,
2180
2173
  recordId: stringSchema({ minLength: 1 }),
2181
2174
  requestId: stringSchema({ minLength: 1 }),
@@ -2203,7 +2196,7 @@ var opensteerNetworkQueryOutputSchema = objectSchema(
2203
2196
  required: ["records"]
2204
2197
  }
2205
2198
  );
2206
- var opensteerNetworkSaveInputSchema = objectSchema(
2199
+ var opensteerNetworkTagInputSchema = objectSchema(
2207
2200
  {
2208
2201
  pageRef: pageRefSchema,
2209
2202
  recordId: stringSchema({ minLength: 1 }),
@@ -2218,17 +2211,17 @@ var opensteerNetworkSaveInputSchema = objectSchema(
2218
2211
  resourceType: networkResourceTypeSchema
2219
2212
  },
2220
2213
  {
2221
- title: "OpensteerNetworkSaveInput",
2214
+ title: "OpensteerNetworkTagInput",
2222
2215
  required: ["tag"]
2223
2216
  }
2224
2217
  );
2225
- var opensteerNetworkSaveOutputSchema = objectSchema(
2218
+ var opensteerNetworkTagOutputSchema = objectSchema(
2226
2219
  {
2227
- savedCount: integerSchema({ minimum: 0 })
2220
+ taggedCount: integerSchema({ minimum: 0 })
2228
2221
  },
2229
2222
  {
2230
- title: "OpensteerNetworkSaveOutput",
2231
- required: ["savedCount"]
2223
+ title: "OpensteerNetworkTagOutput",
2224
+ required: ["taggedCount"]
2232
2225
  }
2233
2226
  );
2234
2227
  var opensteerNetworkClearInputSchema = objectSchema(
@@ -5703,7 +5696,7 @@ var opensteerSemanticOperationNames = [
5703
5696
  "dom.scroll",
5704
5697
  "dom.extract",
5705
5698
  "network.query",
5706
- "network.save",
5699
+ "network.tag",
5707
5700
  "network.clear",
5708
5701
  "network.minimize",
5709
5702
  "network.diff",
@@ -5764,7 +5757,7 @@ var opensteerPackageRunnableSemanticOperationNames = /* @__PURE__ */ new Set([
5764
5757
  "dom.scroll",
5765
5758
  "dom.extract",
5766
5759
  "network.query",
5767
- "network.save",
5760
+ "network.tag",
5768
5761
  "network.clear",
5769
5762
  "network.minimize",
5770
5763
  "network.diff",
@@ -6674,18 +6667,17 @@ var opensteerSemanticOperationSpecificationsBase = [
6674
6667
  }),
6675
6668
  defineSemanticOperationSpec({
6676
6669
  name: "network.query",
6677
- description: "Query live or saved network records for reverse engineering workflows.",
6670
+ description: "Query persisted network records for reverse engineering workflows.",
6678
6671
  inputSchema: opensteerNetworkQueryInputSchema,
6679
6672
  outputSchema: opensteerNetworkQueryOutputSchema,
6680
- requiredCapabilities: [],
6681
- resolveRequiredCapabilities: (input) => input.source === "saved" ? [] : input.includeBodies === true ? ["inspect.network", "inspect.networkBodies"] : ["inspect.network"]
6673
+ requiredCapabilities: []
6682
6674
  }),
6683
6675
  defineSemanticOperationSpec({
6684
- name: "network.save",
6685
- description: "Persist filtered live network records into the saved network registry under a tag.",
6686
- inputSchema: opensteerNetworkSaveInputSchema,
6687
- outputSchema: opensteerNetworkSaveOutputSchema,
6688
- requiredCapabilities: ["inspect.network"]
6676
+ name: "network.tag",
6677
+ description: "Apply a tag to persisted network records matching the provided filters.",
6678
+ inputSchema: opensteerNetworkTagInputSchema,
6679
+ outputSchema: opensteerNetworkTagOutputSchema,
6680
+ requiredCapabilities: []
6689
6681
  }),
6690
6682
  defineSemanticOperationSpec({
6691
6683
  name: "network.clear",
@@ -7577,7 +7569,7 @@ var SqliteSavedNetworkStore = class {
7577
7569
  async initialize() {
7578
7570
  await this.ensureDatabaseDirectory();
7579
7571
  }
7580
- async save(records, tag) {
7572
+ async save(records, options) {
7581
7573
  const database = await this.requireDatabase();
7582
7574
  const readExisting = database.prepare(`
7583
7575
  SELECT record_id
@@ -7586,123 +7578,7 @@ var SqliteSavedNetworkStore = class {
7586
7578
  AND page_ref_key = @page_ref_key
7587
7579
  AND request_id = @request_id
7588
7580
  `);
7589
- const upsertRecord = database.prepare(`
7590
- INSERT INTO saved_network_records (
7591
- record_id,
7592
- request_id,
7593
- session_ref,
7594
- page_ref,
7595
- page_ref_key,
7596
- frame_ref,
7597
- document_ref,
7598
- action_id,
7599
- method,
7600
- method_lc,
7601
- url,
7602
- url_lc,
7603
- hostname,
7604
- hostname_lc,
7605
- path,
7606
- path_lc,
7607
- status,
7608
- status_text,
7609
- resource_type,
7610
- navigation_request,
7611
- request_headers_json,
7612
- response_headers_json,
7613
- request_body_json,
7614
- response_body_json,
7615
- initiator_json,
7616
- timing_json,
7617
- transfer_json,
7618
- source_json,
7619
- capture_state,
7620
- request_body_state,
7621
- response_body_state,
7622
- request_body_skip_reason,
7623
- response_body_skip_reason,
7624
- request_body_error,
7625
- response_body_error,
7626
- redirect_from_request_id,
7627
- redirect_to_request_id,
7628
- saved_at
7629
- ) VALUES (
7630
- @record_id,
7631
- @request_id,
7632
- @session_ref,
7633
- @page_ref,
7634
- @page_ref_key,
7635
- @frame_ref,
7636
- @document_ref,
7637
- @action_id,
7638
- @method,
7639
- @method_lc,
7640
- @url,
7641
- @url_lc,
7642
- @hostname,
7643
- @hostname_lc,
7644
- @path,
7645
- @path_lc,
7646
- @status,
7647
- @status_text,
7648
- @resource_type,
7649
- @navigation_request,
7650
- @request_headers_json,
7651
- @response_headers_json,
7652
- @request_body_json,
7653
- @response_body_json,
7654
- @initiator_json,
7655
- @timing_json,
7656
- @transfer_json,
7657
- @source_json,
7658
- @capture_state,
7659
- @request_body_state,
7660
- @response_body_state,
7661
- @request_body_skip_reason,
7662
- @response_body_skip_reason,
7663
- @request_body_error,
7664
- @response_body_error,
7665
- @redirect_from_request_id,
7666
- @redirect_to_request_id,
7667
- @saved_at
7668
- )
7669
- ON CONFLICT(record_id) DO UPDATE SET
7670
- page_ref = excluded.page_ref,
7671
- page_ref_key = excluded.page_ref_key,
7672
- frame_ref = excluded.frame_ref,
7673
- document_ref = excluded.document_ref,
7674
- action_id = excluded.action_id,
7675
- method = excluded.method,
7676
- method_lc = excluded.method_lc,
7677
- url = excluded.url,
7678
- url_lc = excluded.url_lc,
7679
- hostname = excluded.hostname,
7680
- hostname_lc = excluded.hostname_lc,
7681
- path = excluded.path,
7682
- path_lc = excluded.path_lc,
7683
- status = excluded.status,
7684
- status_text = excluded.status_text,
7685
- resource_type = excluded.resource_type,
7686
- navigation_request = excluded.navigation_request,
7687
- request_headers_json = excluded.request_headers_json,
7688
- response_headers_json = excluded.response_headers_json,
7689
- request_body_json = excluded.request_body_json,
7690
- response_body_json = excluded.response_body_json,
7691
- initiator_json = excluded.initiator_json,
7692
- timing_json = excluded.timing_json,
7693
- transfer_json = excluded.transfer_json,
7694
- source_json = excluded.source_json,
7695
- capture_state = excluded.capture_state,
7696
- request_body_state = excluded.request_body_state,
7697
- response_body_state = excluded.response_body_state,
7698
- request_body_skip_reason = excluded.request_body_skip_reason,
7699
- response_body_skip_reason = excluded.response_body_skip_reason,
7700
- request_body_error = excluded.request_body_error,
7701
- response_body_error = excluded.response_body_error,
7702
- redirect_from_request_id = excluded.redirect_from_request_id,
7703
- redirect_to_request_id = excluded.redirect_to_request_id,
7704
- saved_at = excluded.saved_at
7705
- `);
7581
+ const upsertRecord = database.prepare(buildSavedNetworkUpsertSql(options.bodyWriteMode));
7706
7582
  const insertTag = database.prepare(`
7707
7583
  INSERT OR IGNORE INTO saved_network_tags (record_id, tag)
7708
7584
  VALUES (@record_id, @tag)
@@ -7758,10 +7634,14 @@ var SqliteSavedNetworkStore = class {
7758
7634
  redirect_to_request_id: entry.record.redirectToRequestId ?? null,
7759
7635
  saved_at: entry.savedAt ?? Date.now()
7760
7636
  });
7761
- if (tag !== void 0) {
7637
+ const tags = new Set(entry.tags ?? []);
7638
+ if (options.tag !== void 0) {
7639
+ tags.add(options.tag);
7640
+ }
7641
+ for (const currentTag of tags) {
7762
7642
  const result = insertTag.run({
7763
7643
  record_id: recordId,
7764
- tag
7644
+ tag: currentTag
7765
7645
  });
7766
7646
  savedCount += result.changes ?? 0;
7767
7647
  }
@@ -7769,6 +7649,39 @@ var SqliteSavedNetworkStore = class {
7769
7649
  return savedCount;
7770
7650
  });
7771
7651
  }
7652
+ async tagByFilter(filter, tag) {
7653
+ const database = await this.requireDatabase();
7654
+ const { whereSql, parameters } = buildSavedNetworkWhere(filter);
7655
+ const selectRecords = database.prepare(
7656
+ `
7657
+ SELECT r.record_id
7658
+ FROM saved_network_records r
7659
+ ${whereSql}
7660
+ `
7661
+ );
7662
+ const insertTag = database.prepare(`
7663
+ INSERT OR IGNORE INTO saved_network_tags (record_id, tag)
7664
+ VALUES (@record_id, @tag)
7665
+ `);
7666
+ return withSqliteTransaction(database, () => {
7667
+ let taggedCount = 0;
7668
+ const rows = selectRecords.all(
7669
+ ...parameters
7670
+ );
7671
+ for (const row of rows) {
7672
+ const recordId = row.record_id;
7673
+ if (typeof recordId !== "string") {
7674
+ continue;
7675
+ }
7676
+ const result = insertTag.run({
7677
+ record_id: recordId,
7678
+ tag
7679
+ });
7680
+ taggedCount += result.changes ?? 0;
7681
+ }
7682
+ return taggedCount;
7683
+ });
7684
+ }
7772
7685
  async query(input = {}) {
7773
7686
  const database = await this.requireDatabase();
7774
7687
  const limit = Math.max(1, Math.min(input.limit ?? 50, 200));
@@ -7971,6 +7884,10 @@ var SqliteSavedNetworkStore = class {
7971
7884
  function buildSavedNetworkWhere(input) {
7972
7885
  const clauses = [];
7973
7886
  const parameters = [];
7887
+ if (input.pageRef !== void 0) {
7888
+ clauses.push("r.page_ref_key = ?");
7889
+ parameters.push(input.pageRef);
7890
+ }
7974
7891
  if (input.recordId !== void 0) {
7975
7892
  clauses.push("r.record_id = ?");
7976
7893
  parameters.push(input.recordId);
@@ -8023,6 +7940,127 @@ function buildSavedNetworkWhere(input) {
8023
7940
  parameters
8024
7941
  };
8025
7942
  }
7943
+ function buildSavedNetworkUpsertSql(bodyWriteMode) {
7944
+ const bodyUpdateSql = bodyWriteMode === "authoritative" ? `
7945
+ request_body_json = excluded.request_body_json,
7946
+ response_body_json = excluded.response_body_json,
7947
+ request_body_state = excluded.request_body_state,
7948
+ response_body_state = excluded.response_body_state,
7949
+ request_body_skip_reason = excluded.request_body_skip_reason,
7950
+ response_body_skip_reason = excluded.response_body_skip_reason,
7951
+ request_body_error = excluded.request_body_error,
7952
+ response_body_error = excluded.response_body_error,
7953
+ ` : "";
7954
+ return `
7955
+ INSERT INTO saved_network_records (
7956
+ record_id,
7957
+ request_id,
7958
+ session_ref,
7959
+ page_ref,
7960
+ page_ref_key,
7961
+ frame_ref,
7962
+ document_ref,
7963
+ action_id,
7964
+ method,
7965
+ method_lc,
7966
+ url,
7967
+ url_lc,
7968
+ hostname,
7969
+ hostname_lc,
7970
+ path,
7971
+ path_lc,
7972
+ status,
7973
+ status_text,
7974
+ resource_type,
7975
+ navigation_request,
7976
+ request_headers_json,
7977
+ response_headers_json,
7978
+ request_body_json,
7979
+ response_body_json,
7980
+ initiator_json,
7981
+ timing_json,
7982
+ transfer_json,
7983
+ source_json,
7984
+ capture_state,
7985
+ request_body_state,
7986
+ response_body_state,
7987
+ request_body_skip_reason,
7988
+ response_body_skip_reason,
7989
+ request_body_error,
7990
+ response_body_error,
7991
+ redirect_from_request_id,
7992
+ redirect_to_request_id,
7993
+ saved_at
7994
+ ) VALUES (
7995
+ @record_id,
7996
+ @request_id,
7997
+ @session_ref,
7998
+ @page_ref,
7999
+ @page_ref_key,
8000
+ @frame_ref,
8001
+ @document_ref,
8002
+ @action_id,
8003
+ @method,
8004
+ @method_lc,
8005
+ @url,
8006
+ @url_lc,
8007
+ @hostname,
8008
+ @hostname_lc,
8009
+ @path,
8010
+ @path_lc,
8011
+ @status,
8012
+ @status_text,
8013
+ @resource_type,
8014
+ @navigation_request,
8015
+ @request_headers_json,
8016
+ @response_headers_json,
8017
+ @request_body_json,
8018
+ @response_body_json,
8019
+ @initiator_json,
8020
+ @timing_json,
8021
+ @transfer_json,
8022
+ @source_json,
8023
+ @capture_state,
8024
+ @request_body_state,
8025
+ @response_body_state,
8026
+ @request_body_skip_reason,
8027
+ @response_body_skip_reason,
8028
+ @request_body_error,
8029
+ @response_body_error,
8030
+ @redirect_from_request_id,
8031
+ @redirect_to_request_id,
8032
+ @saved_at
8033
+ )
8034
+ ON CONFLICT(record_id) DO UPDATE SET
8035
+ page_ref = excluded.page_ref,
8036
+ page_ref_key = excluded.page_ref_key,
8037
+ frame_ref = excluded.frame_ref,
8038
+ document_ref = excluded.document_ref,
8039
+ action_id = excluded.action_id,
8040
+ method = excluded.method,
8041
+ method_lc = excluded.method_lc,
8042
+ url = excluded.url,
8043
+ url_lc = excluded.url_lc,
8044
+ hostname = excluded.hostname,
8045
+ hostname_lc = excluded.hostname_lc,
8046
+ path = excluded.path,
8047
+ path_lc = excluded.path_lc,
8048
+ status = excluded.status,
8049
+ status_text = excluded.status_text,
8050
+ resource_type = excluded.resource_type,
8051
+ navigation_request = excluded.navigation_request,
8052
+ request_headers_json = excluded.request_headers_json,
8053
+ response_headers_json = excluded.response_headers_json,
8054
+ ${bodyUpdateSql} initiator_json = excluded.initiator_json,
8055
+ timing_json = excluded.timing_json,
8056
+ transfer_json = excluded.transfer_json,
8057
+ source_json = excluded.source_json,
8058
+ capture_state = excluded.capture_state,
8059
+ redirect_from_request_id = excluded.redirect_from_request_id,
8060
+ redirect_to_request_id = excluded.redirect_to_request_id,
8061
+ saved_at = MIN(saved_network_records.saved_at, excluded.saved_at)
8062
+ `;
8063
+ }
8026
8064
  function inflateSavedNetworkRow(row, includeBodies) {
8027
8065
  const requestBody = includeBodies && row.request_body_json !== null ? JSON.parse(row.request_body_json) : void 0;
8028
8066
  const responseBody = includeBodies && row.response_body_json !== null ? JSON.parse(row.response_body_json) : void 0;
@@ -8093,7 +8131,6 @@ function inflateSavedNetworkRow(row, includeBodies) {
8093
8131
  }
8094
8132
  return {
8095
8133
  recordId: row.record_id,
8096
- source: "saved",
8097
8134
  ...row.action_id === null ? {} : { actionId: row.action_id },
8098
8135
  ...row.tags === null || row.tags.length === 0 ? {} : { tags: row.tags.split(TAG_DELIMITER).filter((tag) => tag.length > 0) },
8099
8136
  savedAt: row.saved_at,
@@ -8440,7 +8477,7 @@ var DEFAULT_TIMEOUTS = {
8440
8477
  "dom.scroll": 1e4,
8441
8478
  "dom.extract": 15e3,
8442
8479
  "network.query": 15e3,
8443
- "network.save": 15e3,
8480
+ "network.tag": 15e3,
8444
8481
  "network.clear": 1e4,
8445
8482
  "scripts.capture": 15e3,
8446
8483
  "request.raw": 3e4,
@@ -10232,6 +10269,19 @@ var MemoryDomDescriptorStore = class {
10232
10269
  }
10233
10270
  };
10234
10271
 
10272
+ // ../runtime-core/src/action-boundary.ts
10273
+ async function captureActionBoundarySnapshot(engine, pageRef) {
10274
+ const frames = await engine.listFrames({ pageRef });
10275
+ const mainFrame = frames.find((frame) => frame.isMainFrame);
10276
+ if (!mainFrame) {
10277
+ throw new Error(`page ${pageRef} does not expose a main frame`);
10278
+ }
10279
+ return {
10280
+ pageRef,
10281
+ documentRef: mainFrame.documentRef
10282
+ };
10283
+ }
10284
+
10235
10285
  // ../runtime-core/src/runtimes/dom/executor.ts
10236
10286
  var MAX_DOM_ACTION_ATTEMPTS = 3;
10237
10287
  var DEFAULT_SCROLL_OPTIONS = {
@@ -10361,6 +10411,7 @@ var DomActionExecutor = class {
10361
10411
  })
10362
10412
  );
10363
10413
  let finalResolved = resolved;
10414
+ let finalSnapshot;
10364
10415
  if (input.pressEnter) {
10365
10416
  await this.settle(resolved.pageRef, "dom.input", timeout);
10366
10417
  const enterSession = this.options.createResolutionSession();
@@ -10376,6 +10427,9 @@ var DomActionExecutor = class {
10376
10427
  () => bridge.inspectActionTarget(enterResolved.locator)
10377
10428
  );
10378
10429
  this.assertKeyboardActionable("dom.input", enterResolved, inspectionBeforeEnter);
10430
+ finalSnapshot = await timeout.runStep(
10431
+ () => captureActionBoundarySnapshot(this.options.engine, enterResolved.pageRef)
10432
+ );
10379
10433
  await timeout.runStep(
10380
10434
  () => bridge.pressKey(enterResolved.locator, {
10381
10435
  key: "Enter"
@@ -10383,7 +10437,7 @@ var DomActionExecutor = class {
10383
10437
  );
10384
10438
  finalResolved = enterResolved;
10385
10439
  }
10386
- await this.settle(finalResolved.pageRef, "dom.input", timeout);
10440
+ await this.settle(finalResolved.pageRef, "dom.input", timeout, finalSnapshot);
10387
10441
  return finalResolved;
10388
10442
  } catch (error) {
10389
10443
  lastError = error;
@@ -10456,8 +10510,16 @@ var DomActionExecutor = class {
10456
10510
  );
10457
10511
  }
10458
10512
  }
10513
+ const actionBoundarySnapshot = await timeout.runStep(
10514
+ () => captureActionBoundarySnapshot(this.options.engine, pointerTarget.resolved.pageRef)
10515
+ );
10459
10516
  const outcome = await dispatch(pointerTarget, point, timeout);
10460
- await this.settle(pointerTarget.resolved.pageRef, input.operation, timeout);
10517
+ await this.settle(
10518
+ pointerTarget.resolved.pageRef,
10519
+ input.operation,
10520
+ timeout,
10521
+ actionBoundarySnapshot
10522
+ );
10461
10523
  return outcome;
10462
10524
  } catch (error) {
10463
10525
  lastError = error;
@@ -10475,16 +10537,17 @@ var DomActionExecutor = class {
10475
10537
  }
10476
10538
  return runWithPolicyTimeout(this.options.policy.timeout, { operation }, execute);
10477
10539
  }
10478
- async settle(pageRef, operation, timeout) {
10540
+ async settle(pageRef, operation, timeout, snapshot) {
10479
10541
  const bridge = this.requireBridge();
10480
10542
  await timeout.runStep(
10481
10543
  () => bridge.finalizeDomAction(pageRef, {
10482
10544
  operation,
10545
+ ...snapshot === void 0 ? {} : { snapshot },
10483
10546
  signal: timeout.signal,
10484
10547
  remainingMs: () => timeout.remainingMs(),
10485
- policySettle: (targetPageRef) => settleWithPolicy(this.options.policy.settle, {
10548
+ policySettle: (targetPageRef, trigger) => settleWithPolicy(this.options.policy.settle, {
10486
10549
  operation,
10487
- trigger: "dom-action",
10550
+ trigger,
10488
10551
  engine: this.options.engine,
10489
10552
  pageRef: targetPageRef,
10490
10553
  signal: timeout.signal,
@@ -16052,16 +16115,20 @@ var DefaultComputerUseRuntime = class {
16052
16115
  const preActionDisplay = createComputerDisplayTransform(preActionNativeViewport);
16053
16116
  const nativeAction = toNativeComputerAction(input.input.action, preActionDisplay);
16054
16117
  const screenshot = normalizeScreenshotOptions(input.input.screenshot);
16118
+ const snapshot = await input.timeout.runStep(
16119
+ () => captureActionBoundarySnapshot(this.options.engine, input.pageRef)
16120
+ );
16055
16121
  const executed = await input.timeout.runStep(
16056
16122
  () => bridge.execute({
16057
16123
  pageRef: input.pageRef,
16124
+ snapshot,
16058
16125
  action: nativeAction,
16059
16126
  screenshot,
16060
16127
  signal: input.timeout.signal,
16061
16128
  remainingMs: () => input.timeout.remainingMs(),
16062
- policySettle: async (pageRef) => settleWithPolicy(this.options.policy.settle, {
16129
+ policySettle: async (pageRef, trigger) => settleWithPolicy(this.options.policy.settle, {
16063
16130
  operation: "computer.execute",
16064
- trigger: "dom-action",
16131
+ trigger,
16065
16132
  engine: this.options.engine,
16066
16133
  pageRef,
16067
16134
  signal: input.timeout.signal,
@@ -16181,8 +16248,8 @@ async function dispatchSemanticOperation(runtime, operation, input, options = {}
16181
16248
  input,
16182
16249
  options
16183
16250
  );
16184
- case "network.save":
16185
- return runtime.saveNetwork(
16251
+ case "network.tag":
16252
+ return runtime.tagNetwork(
16186
16253
  input,
16187
16254
  options
16188
16255
  );
@@ -17056,9 +17123,9 @@ function inferRequestPlanFromNetworkRecord(record, input, options = {}) {
17056
17123
  key: input.key,
17057
17124
  version: input.version,
17058
17125
  provenance: {
17059
- source: record.source === "saved" ? "saved-network-record" : "live-network-record",
17126
+ source: record.savedAt === void 0 ? "network-record" : "saved-network-record",
17060
17127
  sourceId: record.recordId,
17061
- ...record.source === "saved" ? record.savedAt === void 0 ? {} : { capturedAt: record.savedAt } : options.observedAt === void 0 ? {} : { capturedAt: options.observedAt }
17128
+ ...record.savedAt === void 0 ? options.observedAt === void 0 ? {} : { capturedAt: options.observedAt } : { capturedAt: record.savedAt }
17062
17129
  },
17063
17130
  payload,
17064
17131
  ...record.tags === void 0 || record.tags.length === 0 ? {} : { tags: record.tags }
@@ -17438,51 +17505,55 @@ function resolveBodyEncoding(charset) {
17438
17505
  return "utf8";
17439
17506
  }
17440
17507
  }
17441
- var NetworkJournal = class {
17508
+ var NetworkHistory = class {
17442
17509
  metadataByRequestId = /* @__PURE__ */ new Map();
17443
17510
  requestIdByRecordId = /* @__PURE__ */ new Map();
17444
17511
  requestIdsByActionId = /* @__PURE__ */ new Map();
17445
17512
  requestIdsByTag = /* @__PURE__ */ new Map();
17446
- sync(records, options = {}) {
17513
+ tombstonedRequestIds = /* @__PURE__ */ new Set();
17514
+ materialize(records, options = {}) {
17447
17515
  const observedAt = Date.now();
17448
- return records.map((record) => this.materializeLiveRecord(record, observedAt, options));
17449
- }
17450
- materializeLiveRecord(record, observedAt, options = {}) {
17451
- let metadata = this.metadataByRequestId.get(record.requestId);
17452
- if (!metadata) {
17453
- metadata = {
17454
- recordId: `record:${crypto.randomUUID()}`,
17455
- observedAt,
17456
- ...record.pageRef === void 0 ? {} : { pageRef: record.pageRef },
17457
- tags: /* @__PURE__ */ new Set()
17458
- };
17459
- this.metadataByRequestId.set(record.requestId, metadata);
17460
- this.requestIdByRecordId.set(metadata.recordId, record.requestId);
17461
- } else if (metadata.pageRef === void 0 && record.pageRef !== void 0) {
17462
- metadata.pageRef = record.pageRef;
17516
+ const materialized = [];
17517
+ for (const record of records) {
17518
+ const entry = this.materializeRecord(record, observedAt, options);
17519
+ if (entry !== void 0) {
17520
+ materialized.push(entry);
17521
+ }
17463
17522
  }
17464
- return {
17465
- recordId: metadata.recordId,
17466
- source: "live",
17467
- ...metadata.actionId === void 0 ? {} : { actionId: metadata.actionId },
17468
- ...metadata.tags.size === 0 ? {} : { tags: [...metadata.tags].sort() },
17469
- record: toProtocolNetworkRecord(record, {
17470
- redactSecretHeaders: options.redactSecretHeaders ?? true
17471
- })
17472
- };
17523
+ return materialized;
17473
17524
  }
17474
- diffNewRequestIds(records, baselineRequestIds) {
17475
- const observedAt = Date.now();
17476
- const all = records.map(
17477
- (record) => this.materializeLiveRecord(record, observedAt, {
17478
- redactSecretHeaders: true
17479
- })
17480
- );
17481
- const delta = all.filter((entry) => !baselineRequestIds.has(entry.record.requestId));
17482
- return {
17483
- all,
17484
- delta
17485
- };
17525
+ async persist(records, store, options) {
17526
+ const observedAt = options.observedAt ?? Date.now();
17527
+ const metadataToSave = /* @__PURE__ */ new Set();
17528
+ const persisted = [];
17529
+ for (const record of records) {
17530
+ const entry = this.materializeRecord(record, observedAt, {
17531
+ ...options.redactSecretHeaders === void 0 ? {} : { redactSecretHeaders: options.redactSecretHeaders }
17532
+ });
17533
+ if (entry === void 0) {
17534
+ continue;
17535
+ }
17536
+ const requestId = entry.record.requestId;
17537
+ const metadata = this.metadataByRequestId.get(requestId);
17538
+ if (metadata === void 0) {
17539
+ continue;
17540
+ }
17541
+ const savedAt = metadata.savedAt ?? observedAt;
17542
+ metadataToSave.add(metadata);
17543
+ persisted.push({
17544
+ ...entry,
17545
+ savedAt
17546
+ });
17547
+ }
17548
+ if (persisted.length > 0) {
17549
+ await store.save(persisted, {
17550
+ bodyWriteMode: options.bodyWriteMode
17551
+ });
17552
+ for (const metadata of metadataToSave) {
17553
+ metadata.savedAt ??= observedAt;
17554
+ }
17555
+ }
17556
+ return persisted;
17486
17557
  }
17487
17558
  assignActionId(records, actionId) {
17488
17559
  for (const record of records) {
@@ -17523,11 +17594,73 @@ var NetworkJournal = class {
17523
17594
  getPageRefForRequestId(requestId) {
17524
17595
  return this.metadataByRequestId.get(requestId)?.pageRef;
17525
17596
  }
17597
+ getKnownRequestIds() {
17598
+ return new Set(this.metadataByRequestId.keys());
17599
+ }
17600
+ clearTag(tag) {
17601
+ const requestIds = [...this.requestIdsByTag.get(tag) ?? []];
17602
+ this.requestIdsByTag.delete(tag);
17603
+ for (const requestId of requestIds) {
17604
+ const metadata = this.metadataByRequestId.get(requestId);
17605
+ if (!metadata) {
17606
+ continue;
17607
+ }
17608
+ metadata.tags.delete(tag);
17609
+ if (metadata.tags.size === 0) {
17610
+ this.tombstoneRequestIds([requestId]);
17611
+ }
17612
+ }
17613
+ }
17614
+ tombstoneRequestIds(requestIds) {
17615
+ for (const requestId of requestIds) {
17616
+ this.tombstonedRequestIds.add(requestId);
17617
+ const metadata = this.metadataByRequestId.get(requestId);
17618
+ if (!metadata) {
17619
+ continue;
17620
+ }
17621
+ this.metadataByRequestId.delete(requestId);
17622
+ this.requestIdByRecordId.delete(metadata.recordId);
17623
+ if (metadata.actionId !== void 0) {
17624
+ this.requestIdsByActionId.get(metadata.actionId)?.delete(requestId);
17625
+ }
17626
+ for (const tag of metadata.tags) {
17627
+ this.requestIdsByTag.get(tag)?.delete(requestId);
17628
+ }
17629
+ }
17630
+ }
17526
17631
  clear() {
17527
17632
  this.metadataByRequestId.clear();
17528
17633
  this.requestIdByRecordId.clear();
17529
17634
  this.requestIdsByActionId.clear();
17530
17635
  this.requestIdsByTag.clear();
17636
+ this.tombstonedRequestIds.clear();
17637
+ }
17638
+ materializeRecord(record, observedAt, options) {
17639
+ if (this.tombstonedRequestIds.has(record.requestId)) {
17640
+ return void 0;
17641
+ }
17642
+ let metadata = this.metadataByRequestId.get(record.requestId);
17643
+ if (!metadata) {
17644
+ metadata = {
17645
+ recordId: `record:${crypto.randomUUID()}`,
17646
+ observedAt,
17647
+ ...record.pageRef === void 0 ? {} : { pageRef: record.pageRef },
17648
+ tags: /* @__PURE__ */ new Set()
17649
+ };
17650
+ this.metadataByRequestId.set(record.requestId, metadata);
17651
+ this.requestIdByRecordId.set(metadata.recordId, record.requestId);
17652
+ } else if (metadata.pageRef === void 0 && record.pageRef !== void 0) {
17653
+ metadata.pageRef = record.pageRef;
17654
+ }
17655
+ return {
17656
+ recordId: metadata.recordId,
17657
+ ...metadata.actionId === void 0 ? {} : { actionId: metadata.actionId },
17658
+ ...metadata.tags.size === 0 ? {} : { tags: [...metadata.tags].sort() },
17659
+ ...metadata.savedAt === void 0 ? {} : { savedAt: metadata.savedAt },
17660
+ record: toProtocolNetworkRecord(record, {
17661
+ redactSecretHeaders: options.redactSecretHeaders ?? true
17662
+ })
17663
+ };
17531
17664
  }
17532
17665
  addIndexedRequestId(index, key, requestId) {
17533
17666
  const requestIds = index.get(key) ?? /* @__PURE__ */ new Set();
@@ -22355,12 +22488,11 @@ var OpensteerSessionRuntime = class {
22355
22488
  engine;
22356
22489
  dom;
22357
22490
  computer;
22358
- networkJournal = new NetworkJournal();
22491
+ networkHistory = new NetworkHistory();
22359
22492
  extractionDescriptors;
22360
22493
  sessionRef;
22361
22494
  pageRef;
22362
22495
  runId;
22363
- backgroundNetworkPersistence = /* @__PURE__ */ new Set();
22364
22496
  cookieJars = /* @__PURE__ */ new Map();
22365
22497
  recipeCache = /* @__PURE__ */ new Map();
22366
22498
  ownsEngine = false;
@@ -22790,19 +22922,28 @@ var OpensteerSessionRuntime = class {
22790
22922
  const output = await this.runWithOperationTimeout(
22791
22923
  "page.evaluate",
22792
22924
  async (timeout) => {
22793
- const remainingMs = timeout.remainingMs();
22794
- const evaluated = await timeout.runStep(
22795
- () => this.requireEngine().evaluatePage({
22925
+ const baselineRequestIds = await this.beginMutationCapture(timeout);
22926
+ try {
22927
+ const remainingMs = timeout.remainingMs();
22928
+ const evaluated = await timeout.runStep(
22929
+ () => this.requireEngine().evaluatePage({
22930
+ pageRef,
22931
+ script: input.script,
22932
+ ...input.args === void 0 ? {} : { args: input.args },
22933
+ ...remainingMs === void 0 ? {} : { timeoutMs: remainingMs }
22934
+ })
22935
+ );
22936
+ await this.completeMutationCapture(timeout, baselineRequestIds, void 0);
22937
+ return {
22796
22938
  pageRef,
22797
- script: input.script,
22798
- ...input.args === void 0 ? {} : { args: input.args },
22799
- ...remainingMs === void 0 ? {} : { timeoutMs: remainingMs }
22800
- })
22801
- );
22802
- return {
22803
- pageRef,
22804
- value: toJsonValueOrNull(evaluated.data)
22805
- };
22939
+ value: toJsonValueOrNull(evaluated.data)
22940
+ };
22941
+ } catch (error) {
22942
+ await this.completeMutationCapture(timeout, baselineRequestIds, void 0).catch(
22943
+ () => void 0
22944
+ );
22945
+ throw error;
22946
+ }
22806
22947
  },
22807
22948
  options
22808
22949
  );
@@ -23166,38 +23307,19 @@ var OpensteerSessionRuntime = class {
23166
23307
  }
23167
23308
  async queryNetwork(input = {}, options = {}) {
23168
23309
  assertValidSemanticOperationInput("network.query", input);
23169
- if (input.source !== "saved") {
23170
- await this.ensurePageRef();
23171
- }
23172
23310
  const root = await this.ensureRoot();
23173
23311
  const startedAt = Date.now();
23174
23312
  try {
23175
23313
  const output = await this.runWithOperationTimeout(
23176
23314
  "network.query",
23177
23315
  async (timeout) => {
23178
- if (input.source === "saved") {
23179
- await timeout.runStep(() => this.flushBackgroundNetworkPersistence());
23180
- return {
23181
- records: await timeout.runStep(
23182
- () => root.registry.savedNetwork.query({
23183
- ...input.recordId === void 0 ? {} : { recordId: input.recordId },
23184
- ...input.requestId === void 0 ? {} : { requestId: input.requestId },
23185
- ...input.actionId === void 0 ? {} : { actionId: input.actionId },
23186
- ...input.tag === void 0 ? {} : { tag: input.tag },
23187
- ...input.url === void 0 ? {} : { url: input.url },
23188
- ...input.hostname === void 0 ? {} : { hostname: input.hostname },
23189
- ...input.path === void 0 ? {} : { path: input.path },
23190
- ...input.method === void 0 ? {} : { method: input.method },
23191
- ...input.status === void 0 ? {} : { status: input.status },
23192
- ...input.resourceType === void 0 ? {} : { resourceType: input.resourceType },
23193
- ...input.includeBodies === void 0 ? {} : { includeBodies: input.includeBodies },
23194
- ...input.limit === void 0 ? {} : { limit: input.limit }
23195
- })
23196
- )
23197
- };
23198
- }
23316
+ await this.syncPersistedNetworkSelection(timeout, input, {
23317
+ includeBodies: input.includeBodies ?? false
23318
+ });
23199
23319
  return {
23200
- records: await this.queryLiveNetwork(input, timeout)
23320
+ records: await timeout.runStep(
23321
+ () => root.registry.savedNetwork.query(this.toSavedNetworkQueryInput(input))
23322
+ )
23201
23323
  };
23202
23324
  },
23203
23325
  options
@@ -23208,7 +23330,6 @@ var OpensteerSessionRuntime = class {
23208
23330
  completedAt: Date.now(),
23209
23331
  outcome: "ok",
23210
23332
  data: {
23211
- source: input.source ?? "live",
23212
23333
  includeBodies: input.includeBodies ?? false,
23213
23334
  limit: input.limit ?? 50,
23214
23335
  count: output.records.length
@@ -23234,56 +23355,42 @@ var OpensteerSessionRuntime = class {
23234
23355
  throw error;
23235
23356
  }
23236
23357
  }
23237
- async saveNetwork(input, options = {}) {
23238
- assertValidSemanticOperationInput("network.save", input);
23239
- await this.ensurePageRef();
23358
+ async tagNetwork(input, options = {}) {
23359
+ assertValidSemanticOperationInput("network.tag", input);
23240
23360
  const root = await this.ensureRoot();
23361
+ const filter = this.toQueryInputFromTagInput(input);
23362
+ const savedFilter = this.toSavedNetworkQueryInput(filter);
23241
23363
  const startedAt = Date.now();
23242
23364
  try {
23243
23365
  const output = await this.runWithOperationTimeout(
23244
- "network.save",
23366
+ "network.tag",
23245
23367
  async (timeout) => {
23246
- const records = await this.queryLiveNetwork(
23247
- {
23248
- includeBodies: true,
23249
- source: "live",
23250
- ...input.pageRef === void 0 ? {} : { pageRef: input.pageRef },
23251
- ...input.recordId === void 0 ? {} : { recordId: input.recordId },
23252
- ...input.requestId === void 0 ? {} : { requestId: input.requestId },
23253
- ...input.actionId === void 0 ? {} : { actionId: input.actionId },
23254
- ...input.url === void 0 ? {} : { url: input.url },
23255
- ...input.hostname === void 0 ? {} : { hostname: input.hostname },
23256
- ...input.path === void 0 ? {} : { path: input.path },
23257
- ...input.method === void 0 ? {} : { method: input.method },
23258
- ...input.status === void 0 ? {} : { status: input.status },
23259
- ...input.resourceType === void 0 ? {} : { resourceType: input.resourceType }
23260
- },
23261
- timeout,
23262
- { ignoreLimit: true, redactSecretHeaders: false }
23263
- );
23264
- this.networkJournal.addTag(records, input.tag);
23368
+ const records = await this.syncPersistedNetworkSelection(timeout, filter, {
23369
+ includeBodies: false
23370
+ });
23371
+ this.networkHistory.addTag(records, input.tag);
23265
23372
  return {
23266
- savedCount: await timeout.runStep(
23267
- () => root.registry.savedNetwork.save(records, input.tag)
23373
+ taggedCount: await timeout.runStep(
23374
+ () => root.registry.savedNetwork.tagByFilter(savedFilter, input.tag)
23268
23375
  )
23269
23376
  };
23270
23377
  },
23271
23378
  options
23272
23379
  );
23273
23380
  await this.appendTrace({
23274
- operation: "network.save",
23381
+ operation: "network.tag",
23275
23382
  startedAt,
23276
23383
  completedAt: Date.now(),
23277
23384
  outcome: "ok",
23278
23385
  data: {
23279
23386
  tag: input.tag,
23280
- savedCount: output.savedCount
23387
+ taggedCount: output.taggedCount
23281
23388
  }
23282
23389
  });
23283
23390
  return output;
23284
23391
  } catch (error) {
23285
23392
  await this.appendTrace({
23286
- operation: "network.save",
23393
+ operation: "network.tag",
23287
23394
  startedAt,
23288
23395
  completedAt: Date.now(),
23289
23396
  outcome: "error",
@@ -23300,7 +23407,19 @@ var OpensteerSessionRuntime = class {
23300
23407
  const output = await this.runWithOperationTimeout(
23301
23408
  "network.clear",
23302
23409
  async (timeout) => {
23303
- await timeout.runStep(() => this.flushBackgroundNetworkPersistence());
23410
+ if (this.sessionRef !== void 0) {
23411
+ const liveRequestIds = await this.readLiveRequestIds(timeout, {
23412
+ includeCurrentPageOnly: false
23413
+ });
23414
+ if (input.tag === void 0) {
23415
+ this.networkHistory.tombstoneRequestIds(liveRequestIds);
23416
+ }
23417
+ }
23418
+ if (input.tag === void 0) {
23419
+ this.networkHistory.tombstoneRequestIds(this.networkHistory.getKnownRequestIds());
23420
+ } else {
23421
+ this.networkHistory.clearTag(input.tag);
23422
+ }
23304
23423
  return {
23305
23424
  clearedCount: await timeout.runStep(() => root.registry.savedNetwork.clear(input))
23306
23425
  };
@@ -24017,7 +24136,6 @@ var OpensteerSessionRuntime = class {
24017
24136
  });
24018
24137
  const networkRecords = await this.queryLiveNetwork(
24019
24138
  {
24020
- source: "live",
24021
24139
  pageRef,
24022
24140
  ...input.network?.url === void 0 ? {} : { url: input.network.url },
24023
24141
  ...input.network?.hostname === void 0 ? {} : { hostname: input.network.hostname },
@@ -24033,7 +24151,7 @@ var OpensteerSessionRuntime = class {
24033
24151
  );
24034
24152
  const persistedNetwork = filterReverseObservationWindow(
24035
24153
  networkRecords.filter(isReverseRelevantNetworkRecord),
24036
- this.networkJournal,
24154
+ this.networkHistory,
24037
24155
  input.captureWindowMs
24038
24156
  );
24039
24157
  const fallbackSavedNetwork = persistedNetwork.length === 0 ? (await root.registry.savedNetwork.query({
@@ -24048,7 +24166,10 @@ var OpensteerSessionRuntime = class {
24048
24166
  const observationId = `observation:${crypto.randomUUID()}`;
24049
24167
  const networkTag = `reverse-case:${caseRecord.id}:${observationId}`;
24050
24168
  if (observationNetwork.length > 0) {
24051
- await root.registry.savedNetwork.save(observationNetwork, networkTag);
24169
+ await root.registry.savedNetwork.save(observationNetwork, {
24170
+ tag: networkTag,
24171
+ bodyWriteMode: input.network?.includeBodies === false ? "metadata-only" : "authoritative"
24172
+ });
24052
24173
  }
24053
24174
  const scriptArtifactIds = input.includeScripts === false ? [] : (await this.captureScriptsInternal(
24054
24175
  pageRef,
@@ -24144,7 +24265,7 @@ var OpensteerSessionRuntime = class {
24144
24265
  includeBodies: true,
24145
24266
  redactSecretHeaders: false
24146
24267
  }),
24147
- observedAt: this.networkJournal.getObservedAt(recordId)
24268
+ observedAt: this.networkHistory.getObservedAt(recordId)
24148
24269
  }))
24149
24270
  );
24150
24271
  const clusteredRecords = observationRecords.map((entry) => {
@@ -25084,7 +25205,10 @@ var OpensteerSessionRuntime = class {
25084
25205
  timeout.signal
25085
25206
  )).filter((record) => !baselineRequestIds.has(record.record.requestId));
25086
25207
  if (deltaRecords.length > 0) {
25087
- await root.registry.savedNetwork.save(deltaRecords, `interaction:${pageRef}`);
25208
+ await root.registry.savedNetwork.save(deltaRecords, {
25209
+ tag: `interaction:${pageRef}`,
25210
+ bodyWriteMode: "authoritative"
25211
+ });
25088
25212
  }
25089
25213
  const trace = await root.registry.interactionTraces.write({
25090
25214
  key: input.key ?? buildInteractionTraceKey(pageInfo.url),
@@ -25427,7 +25551,7 @@ var OpensteerSessionRuntime = class {
25427
25551
  includeBodies: true
25428
25552
  });
25429
25553
  const inferred = inferRequestPlanFromNetworkRecord(source, input, {
25430
- ...this.networkJournal.getObservedAt(source.recordId) === void 0 ? {} : { observedAt: this.networkJournal.getObservedAt(source.recordId) }
25554
+ ...this.networkHistory.getObservedAt(source.recordId) === void 0 ? {} : { observedAt: this.networkHistory.getObservedAt(source.recordId) }
25431
25555
  });
25432
25556
  return timeout.runStep(
25433
25557
  () => root.registry.requestPlans.write({
@@ -26239,7 +26363,7 @@ var OpensteerSessionRuntime = class {
26239
26363
  await this.runWithOperationTimeout(
26240
26364
  "session.close",
26241
26365
  async (timeout) => {
26242
- await timeout.runStep(() => this.flushBackgroundNetworkPersistence());
26366
+ await timeout.runStep(() => this.flushPersistedNetworkHistory());
26243
26367
  if (engine === void 0) {
26244
26368
  return;
26245
26369
  }
@@ -26308,10 +26432,7 @@ var OpensteerSessionRuntime = class {
26308
26432
  }
26309
26433
  async disconnect() {
26310
26434
  try {
26311
- await this.flushBackgroundNetworkPersistence();
26312
- if (this.sessionRef !== void 0 && this.pageRef !== void 0) {
26313
- await this.saveNetwork({ tag: "auto" }).catch(() => void 0);
26314
- }
26435
+ await this.flushPersistedNetworkHistory();
26315
26436
  } finally {
26316
26437
  await this.resetRuntimeState({
26317
26438
  disposeEngine: true
@@ -26403,7 +26524,10 @@ var OpensteerSessionRuntime = class {
26403
26524
  };
26404
26525
  }
26405
26526
  if (target.kind === "element") {
26406
- const elementTarget = { kind: "selector", selector: `[c="${String(target.element)}"]` };
26527
+ const elementTarget = {
26528
+ kind: "selector",
26529
+ selector: `[c="${String(target.element)}"]`
26530
+ };
26407
26531
  const resolved2 = await timeout.runStep(
26408
26532
  () => this.requireDom().resolveTarget({
26409
26533
  pageRef,
@@ -26466,11 +26590,11 @@ var OpensteerSessionRuntime = class {
26466
26590
  };
26467
26591
  }
26468
26592
  async queryLiveNetwork(input, timeout, options = {}) {
26469
- const requestIds = resolveLiveQueryRequestIds(input, this.networkJournal);
26593
+ const requestIds = resolveLiveQueryRequestIds(input, this.networkHistory);
26470
26594
  if (requestIds !== void 0 && requestIds.length === 0) {
26471
26595
  return [];
26472
26596
  }
26473
- const pageRef = resolveLiveQueryPageRef(input, this.pageRef, requestIds, this.networkJournal);
26597
+ const pageRef = resolveLiveQueryPageRef(input, this.pageRef, requestIds, this.networkHistory);
26474
26598
  const includeCurrentPageOnly = pageRef === void 0 && input.recordId === void 0;
26475
26599
  const metadataRecords = await timeout.runStep(
26476
26600
  () => this.readLiveNetworkRecords(
@@ -26497,7 +26621,7 @@ var OpensteerSessionRuntime = class {
26497
26621
  ...input.status === void 0 ? {} : { status: input.status },
26498
26622
  ...input.resourceType === void 0 ? {} : { resourceType: input.resourceType }
26499
26623
  });
26500
- const sorted = sortLiveNetworkRecords(filtered, this.networkJournal);
26624
+ const sorted = sortLiveNetworkRecords(filtered, this.networkHistory);
26501
26625
  const limit = options.ignoreLimit ? sorted.length : Math.max(1, Math.min(input.limit ?? 50, 200));
26502
26626
  const limited = sorted.slice(0, limit);
26503
26627
  if (!(input.includeBodies ?? false) || limited.length === 0) {
@@ -26713,21 +26837,40 @@ var OpensteerSessionRuntime = class {
26713
26837
  if (delta.length === 0) {
26714
26838
  return;
26715
26839
  }
26716
- this.networkJournal.assignActionId(delta, `action:${crypto.randomUUID()}`);
26717
- if (networkTag === void 0) {
26718
- return;
26840
+ this.networkHistory.assignActionId(delta, `action:${crypto.randomUUID()}`);
26841
+ if (networkTag !== void 0) {
26842
+ this.networkHistory.addTag(delta, networkTag);
26719
26843
  }
26720
- this.networkJournal.addTag(delta, networkTag);
26721
- this.scheduleBackgroundNetworkSaveByRequestIds(
26844
+ await this.persistLiveRequestIds(
26722
26845
  delta.map((record) => record.record.requestId),
26723
- networkTag
26846
+ timeout,
26847
+ {
26848
+ includeCurrentPageOnly: true
26849
+ }
26724
26850
  );
26725
26851
  }
26726
26852
  async resolveNetworkRecordByRecordId(recordId, timeout, options) {
26727
26853
  const root = await this.ensureRoot();
26854
+ await this.syncPersistedNetworkSelection(
26855
+ timeout,
26856
+ {
26857
+ recordId,
26858
+ includeBodies: options.includeBodies
26859
+ },
26860
+ {
26861
+ includeBodies: options.includeBodies
26862
+ }
26863
+ );
26864
+ const saved = await timeout.runStep(
26865
+ () => root.registry.savedNetwork.getByRecordId(recordId, {
26866
+ includeBodies: options.includeBodies
26867
+ })
26868
+ );
26869
+ if (saved) {
26870
+ return saved;
26871
+ }
26728
26872
  const live = await this.queryLiveNetwork(
26729
26873
  {
26730
- source: "live",
26731
26874
  recordId,
26732
26875
  includeBodies: options.includeBodies,
26733
26876
  limit: 1
@@ -26738,24 +26881,15 @@ var OpensteerSessionRuntime = class {
26738
26881
  ...options.redactSecretHeaders === void 0 ? {} : { redactSecretHeaders: options.redactSecretHeaders }
26739
26882
  }
26740
26883
  );
26741
- if (live.length > 0) {
26884
+ if (live[0] !== void 0) {
26742
26885
  return live[0];
26743
26886
  }
26744
- await timeout.runStep(() => this.flushBackgroundNetworkPersistence());
26745
- const saved = await timeout.runStep(
26746
- () => root.registry.savedNetwork.getByRecordId(recordId, {
26747
- includeBodies: options.includeBodies
26748
- })
26749
- );
26750
- if (!saved) {
26751
- throw new OpensteerProtocolError("not-found", `network record ${recordId} was not found`, {
26752
- details: {
26753
- recordId,
26754
- kind: "network-record"
26755
- }
26756
- });
26757
- }
26758
- return saved;
26887
+ throw new OpensteerProtocolError("not-found", `network record ${recordId} was not found`, {
26888
+ details: {
26889
+ recordId,
26890
+ kind: "network-record"
26891
+ }
26892
+ });
26759
26893
  }
26760
26894
  resolveCurrentStateSource() {
26761
26895
  const ownership = this.sessionInfoBase.provider?.ownership;
@@ -26995,7 +27129,6 @@ var OpensteerSessionRuntime = class {
26995
27129
  timeout.throwIfAborted();
26996
27130
  const records = await this.queryLiveNetwork(
26997
27131
  {
26998
- source: "live",
26999
27132
  pageRef,
27000
27133
  url,
27001
27134
  method,
@@ -27026,7 +27159,6 @@ var OpensteerSessionRuntime = class {
27026
27159
  timeout.throwIfAborted();
27027
27160
  const records = await this.queryLiveNetwork(
27028
27161
  {
27029
- source: "live",
27030
27162
  pageRef,
27031
27163
  ...filter.url === void 0 ? {} : { url: filter.url },
27032
27164
  ...filter.host === void 0 ? {} : { hostname: filter.host },
@@ -27092,12 +27224,12 @@ var OpensteerSessionRuntime = class {
27092
27224
  };
27093
27225
  }
27094
27226
  }
27095
- async readLiveNetworkRecords(input, signal) {
27227
+ async readBrowserNetworkRecords(input, signal) {
27096
27228
  const sessionRef = this.sessionRef;
27097
27229
  if (!sessionRef) {
27098
27230
  throw new Error("Opensteer session is not initialized");
27099
27231
  }
27100
- const records = await this.requireEngine().getNetworkRecords({
27232
+ return this.requireEngine().getNetworkRecords({
27101
27233
  sessionRef,
27102
27234
  ...input.includeCurrentPageOnly === false || input.pageRef !== void 0 ? input.pageRef === void 0 ? {} : { pageRef: input.pageRef } : this.pageRef === void 0 ? {} : { pageRef: this.pageRef },
27103
27235
  ...input.requestIds === void 0 ? {} : { requestIds: input.requestIds },
@@ -27110,10 +27242,102 @@ var OpensteerSessionRuntime = class {
27110
27242
  includeBodies: input.includeBodies,
27111
27243
  signal
27112
27244
  });
27113
- return this.networkJournal.sync(records, {
27245
+ }
27246
+ async readLiveNetworkRecords(input, signal) {
27247
+ const records = await this.readBrowserNetworkRecords(input, signal);
27248
+ return this.networkHistory.materialize(records, {
27114
27249
  redactSecretHeaders: input.redactSecretHeaders ?? true
27115
27250
  });
27116
27251
  }
27252
+ async persistLiveRequestIds(requestIds, timeout, options) {
27253
+ if (requestIds.length === 0) {
27254
+ return [];
27255
+ }
27256
+ const root = await this.ensureRoot();
27257
+ const browserRecords = await timeout.runStep(
27258
+ () => this.readBrowserNetworkRecords(
27259
+ {
27260
+ includeBodies: true,
27261
+ includeCurrentPageOnly: options.includeCurrentPageOnly,
27262
+ ...options.pageRef === void 0 ? {} : { pageRef: options.pageRef },
27263
+ requestIds
27264
+ },
27265
+ timeout.signal
27266
+ )
27267
+ );
27268
+ return timeout.runStep(
27269
+ () => this.networkHistory.persist(browserRecords, root.registry.savedNetwork, {
27270
+ bodyWriteMode: "authoritative",
27271
+ redactSecretHeaders: false
27272
+ })
27273
+ );
27274
+ }
27275
+ async syncPersistedNetworkSelection(timeout, input, options) {
27276
+ if (this.sessionRef === void 0) {
27277
+ return [];
27278
+ }
27279
+ const requestIds = resolveLiveQueryRequestIds(input, this.networkHistory);
27280
+ if (requestIds !== void 0 && requestIds.length === 0) {
27281
+ return [];
27282
+ }
27283
+ const pageRef = resolveLiveQueryPageRef(input, this.pageRef, requestIds, this.networkHistory);
27284
+ const includeCurrentPageOnly = pageRef === void 0 && input.recordId === void 0;
27285
+ const browserRecords = await timeout.runStep(
27286
+ () => this.readBrowserNetworkRecords(
27287
+ {
27288
+ ...pageRef === void 0 ? {} : { pageRef },
27289
+ ...requestIds === void 0 ? {} : { requestIds },
27290
+ ...input.url === void 0 ? {} : { url: input.url },
27291
+ ...input.hostname === void 0 ? {} : { hostname: input.hostname },
27292
+ ...input.path === void 0 ? {} : { path: input.path },
27293
+ ...input.method === void 0 ? {} : { method: input.method },
27294
+ ...input.status === void 0 ? {} : { status: input.status },
27295
+ ...input.resourceType === void 0 ? {} : { resourceType: input.resourceType },
27296
+ includeBodies: options.includeBodies,
27297
+ includeCurrentPageOnly
27298
+ },
27299
+ timeout.signal
27300
+ )
27301
+ );
27302
+ const root = await this.ensureRoot();
27303
+ return timeout.runStep(
27304
+ () => this.networkHistory.persist(browserRecords, root.registry.savedNetwork, {
27305
+ bodyWriteMode: options.includeBodies ? "authoritative" : "metadata-only",
27306
+ redactSecretHeaders: false
27307
+ })
27308
+ );
27309
+ }
27310
+ toSavedNetworkQueryInput(input) {
27311
+ return {
27312
+ ...input.pageRef === void 0 ? {} : { pageRef: input.pageRef },
27313
+ ...input.recordId === void 0 ? {} : { recordId: input.recordId },
27314
+ ...input.requestId === void 0 ? {} : { requestId: input.requestId },
27315
+ ...input.actionId === void 0 ? {} : { actionId: input.actionId },
27316
+ ...input.tag === void 0 ? {} : { tag: input.tag },
27317
+ ...input.url === void 0 ? {} : { url: input.url },
27318
+ ...input.hostname === void 0 ? {} : { hostname: input.hostname },
27319
+ ...input.path === void 0 ? {} : { path: input.path },
27320
+ ...input.method === void 0 ? {} : { method: input.method },
27321
+ ...input.status === void 0 ? {} : { status: input.status },
27322
+ ...input.resourceType === void 0 ? {} : { resourceType: input.resourceType },
27323
+ ...input.includeBodies === void 0 ? {} : { includeBodies: input.includeBodies },
27324
+ ...input.limit === void 0 ? {} : { limit: input.limit }
27325
+ };
27326
+ }
27327
+ toQueryInputFromTagInput(input) {
27328
+ return {
27329
+ ...input.pageRef === void 0 ? {} : { pageRef: input.pageRef },
27330
+ ...input.recordId === void 0 ? {} : { recordId: input.recordId },
27331
+ ...input.requestId === void 0 ? {} : { requestId: input.requestId },
27332
+ ...input.actionId === void 0 ? {} : { actionId: input.actionId },
27333
+ ...input.url === void 0 ? {} : { url: input.url },
27334
+ ...input.hostname === void 0 ? {} : { hostname: input.hostname },
27335
+ ...input.path === void 0 ? {} : { path: input.path },
27336
+ ...input.method === void 0 ? {} : { method: input.method },
27337
+ ...input.status === void 0 ? {} : { status: input.status },
27338
+ ...input.resourceType === void 0 ? {} : { resourceType: input.resourceType }
27339
+ };
27340
+ }
27117
27341
  async readLiveRequestIds(timeout, options) {
27118
27342
  const records = await timeout.runStep(
27119
27343
  () => this.readLiveNetworkRecords(
@@ -27137,7 +27361,17 @@ var OpensteerSessionRuntime = class {
27137
27361
  )
27138
27362
  );
27139
27363
  const delta = records.filter((record) => !baselineRequestIds.has(record.record.requestId));
27140
- return sortLiveNetworkRecords(delta, this.networkJournal)[0]?.recordId;
27364
+ if (delta.length === 0) {
27365
+ return void 0;
27366
+ }
27367
+ await this.persistLiveRequestIds(
27368
+ delta.map((record) => record.record.requestId),
27369
+ timeout,
27370
+ {
27371
+ includeCurrentPageOnly: options.includeCurrentPageOnly
27372
+ }
27373
+ );
27374
+ return sortLiveNetworkRecords(delta, this.networkHistory)[0]?.recordId;
27141
27375
  }
27142
27376
  async executeTransportRequestWithJournal(request, timeout, sessionRef) {
27143
27377
  const baselineRequestIds = await this.readLiveRequestIds(timeout, {
@@ -27421,7 +27655,6 @@ var OpensteerSessionRuntime = class {
27421
27655
  const syntheticSessionRef = binding?.sessionRef ?? createSessionRef(`${transportLabel}-${this.workspace}`);
27422
27656
  const record = {
27423
27657
  recordId,
27424
- source: "saved",
27425
27658
  savedAt: now,
27426
27659
  record: {
27427
27660
  kind: "http",
@@ -27443,7 +27676,10 @@ var OpensteerSessionRuntime = class {
27443
27676
  ...response.body === void 0 ? {} : { responseBody: toProtocolBodyPayload(response.body) }
27444
27677
  }
27445
27678
  };
27446
- await root.registry.savedNetwork.save([record], tag);
27679
+ await root.registry.savedNetwork.save([record], {
27680
+ bodyWriteMode: "authoritative",
27681
+ ...tag === void 0 ? {} : { tag }
27682
+ });
27447
27683
  return recordId;
27448
27684
  }
27449
27685
  async executeResolvedRequestPlan(plan, input, timeout, binding) {
@@ -27816,7 +28052,6 @@ var OpensteerSessionRuntime = class {
27816
28052
  const record = await pollUntilResult(timeout, async () => {
27817
28053
  const matches = await this.queryLiveNetwork(
27818
28054
  {
27819
- source: "live",
27820
28055
  ...step.url === void 0 ? {} : { url: interpolateTemplate(step.url, variables) },
27821
28056
  ...step.hostname === void 0 ? {} : { hostname: interpolateTemplate(step.hostname, variables) },
27822
28057
  ...step.path === void 0 ? {} : { path: interpolateTemplate(step.path, variables) },
@@ -28274,37 +28509,7 @@ var OpensteerSessionRuntime = class {
28274
28509
  const pageUrl = step.pageUrl === void 0 ? void 0 : interpolateTemplate(step.pageUrl, variables);
28275
28510
  return snapshot.sessionStorage?.filter((entry) => entry.origin === origin).find((entry) => pageUrl === void 0 || entry.origin === new URL(pageUrl).origin)?.entries.find((entry) => entry.key === key)?.value;
28276
28511
  }
28277
- scheduleBackgroundNetworkSaveByRequestIds(requestIds, tag) {
28278
- const task = (async () => {
28279
- const root = await this.ensureRoot();
28280
- const requestIdSet = new Set(requestIds);
28281
- const records = await this.readLiveNetworkRecords(
28282
- {
28283
- includeBodies: true,
28284
- includeCurrentPageOnly: false,
28285
- ...this.pageRef === void 0 ? {} : { pageRef: this.pageRef },
28286
- requestIds,
28287
- redactSecretHeaders: false
28288
- },
28289
- new AbortController().signal
28290
- );
28291
- const filtered = records.filter((record) => requestIdSet.has(record.record.requestId));
28292
- if (filtered.length === 0) {
28293
- return;
28294
- }
28295
- await root.registry.savedNetwork.save(filtered, tag);
28296
- })();
28297
- this.backgroundNetworkPersistence.add(task);
28298
- task.finally(() => {
28299
- this.backgroundNetworkPersistence.delete(task);
28300
- });
28301
- void task.catch(() => void 0);
28302
- }
28303
- async flushBackgroundNetworkPersistence() {
28304
- if (this.backgroundNetworkPersistence.size === 0) {
28305
- return;
28306
- }
28307
- await Promise.all([...this.backgroundNetworkPersistence]);
28512
+ async flushPersistedNetworkHistory() {
28308
28513
  }
28309
28514
  toDomTargetRef(target) {
28310
28515
  if (target.kind === "description") {
@@ -28339,7 +28544,9 @@ var OpensteerSessionRuntime = class {
28339
28544
  ...workspace.registry,
28340
28545
  ...overrides.requestPlans === void 0 ? {} : { requestPlans: overrides.requestPlans },
28341
28546
  ...overrides.authRecipes === void 0 ? {} : { authRecipes: overrides.authRecipes },
28342
- ...overrides.recipes === void 0 ? {} : { recipes: overrides.recipes }
28547
+ ...overrides.recipes === void 0 ? {} : { recipes: overrides.recipes },
28548
+ ...overrides.reverseCases === void 0 ? {} : { reverseCases: overrides.reverseCases },
28549
+ ...overrides.reversePackages === void 0 ? {} : { reversePackages: overrides.reversePackages }
28343
28550
  }
28344
28551
  };
28345
28552
  } else {
@@ -28596,8 +28803,7 @@ var OpensteerSessionRuntime = class {
28596
28803
  }
28597
28804
  async resetRuntimeState(options) {
28598
28805
  const engine = this.engine;
28599
- this.networkJournal.clear();
28600
- this.backgroundNetworkPersistence.clear();
28806
+ this.networkHistory.clear();
28601
28807
  this.sessionRef = void 0;
28602
28808
  this.pageRef = void 0;
28603
28809
  this.runId = void 0;
@@ -28673,10 +28879,10 @@ function buildEngineNetworkRecordFilters(input) {
28673
28879
  ...input.resourceType === void 0 ? {} : { resourceType: input.resourceType }
28674
28880
  };
28675
28881
  }
28676
- function resolveLiveQueryRequestIds(input, journal) {
28882
+ function resolveLiveQueryRequestIds(input, history) {
28677
28883
  const requestIdCandidates = [];
28678
28884
  if (input.recordId !== void 0) {
28679
- const requestId = journal.getRequestId(input.recordId);
28885
+ const requestId = history.getRequestId(input.recordId);
28680
28886
  if (requestId === void 0) {
28681
28887
  return [];
28682
28888
  }
@@ -28686,24 +28892,24 @@ function resolveLiveQueryRequestIds(input, journal) {
28686
28892
  requestIdCandidates.push(/* @__PURE__ */ new Set([input.requestId]));
28687
28893
  }
28688
28894
  if (input.actionId !== void 0) {
28689
- requestIdCandidates.push(journal.getRequestIdsForActionId(input.actionId));
28895
+ requestIdCandidates.push(history.getRequestIdsForActionId(input.actionId));
28690
28896
  }
28691
28897
  if (input.tag !== void 0) {
28692
- requestIdCandidates.push(journal.getRequestIdsForTag(input.tag));
28898
+ requestIdCandidates.push(history.getRequestIdsForTag(input.tag));
28693
28899
  }
28694
28900
  if (requestIdCandidates.length === 0) {
28695
28901
  return void 0;
28696
28902
  }
28697
28903
  return intersectRequestIdSets(requestIdCandidates);
28698
28904
  }
28699
- function resolveLiveQueryPageRef(input, currentPageRef, requestIds, journal) {
28905
+ function resolveLiveQueryPageRef(input, currentPageRef, requestIds, history) {
28700
28906
  const requestedPageRef = selectLiveQueryPageRef(input, currentPageRef);
28701
28907
  if (requestedPageRef !== void 0 || requestIds === void 0) {
28702
28908
  return requestedPageRef;
28703
28909
  }
28704
28910
  const pageRefs = /* @__PURE__ */ new Set();
28705
28911
  for (const requestId of requestIds) {
28706
- const pageRef = journal.getPageRefForRequestId(requestId);
28912
+ const pageRef = history.getPageRefForRequestId(requestId);
28707
28913
  if (pageRef === void 0) {
28708
28914
  continue;
28709
28915
  }
@@ -28745,10 +28951,10 @@ function filterNetworkQueryRecords(records, input) {
28745
28951
  return true;
28746
28952
  });
28747
28953
  }
28748
- function sortLiveNetworkRecords(records, journal) {
28954
+ function sortLiveNetworkRecords(records, history) {
28749
28955
  return [...records].sort((left, right) => {
28750
- const leftObservedAt = journal.getObservedAt(left.recordId) ?? 0;
28751
- const rightObservedAt = journal.getObservedAt(right.recordId) ?? 0;
28956
+ const leftObservedAt = history.getObservedAt(left.recordId) ?? 0;
28957
+ const rightObservedAt = history.getObservedAt(right.recordId) ?? 0;
28752
28958
  if (leftObservedAt !== rightObservedAt) {
28753
28959
  return rightObservedAt - leftObservedAt;
28754
28960
  }
@@ -28955,7 +29161,7 @@ function buildMinimizedRequestPlan(input) {
28955
29161
  provenance: {
28956
29162
  source: "network-minimize",
28957
29163
  sourceId: input.record.recordId,
28958
- ...input.record.source === "saved" && input.record.savedAt !== void 0 ? { capturedAt: input.record.savedAt } : {}
29164
+ ...input.record.savedAt === void 0 ? {} : { capturedAt: input.record.savedAt }
28959
29165
  },
28960
29166
  payload: normalizeRequestPlanPayload({
28961
29167
  transport: {
@@ -29174,12 +29380,12 @@ function originFromUrl(url) {
29174
29380
  return void 0;
29175
29381
  }
29176
29382
  }
29177
- function filterReverseObservationWindow(records, journal, captureWindowMs) {
29383
+ function filterReverseObservationWindow(records, history, captureWindowMs) {
29178
29384
  if (captureWindowMs === void 0) {
29179
29385
  return records;
29180
29386
  }
29181
29387
  const observedAfter = Date.now() - captureWindowMs;
29182
- return records.filter((record) => (journal.getObservedAt(record.recordId) ?? 0) >= observedAfter);
29388
+ return records.filter((record) => (history.getObservedAt(record.recordId) ?? 0) >= observedAfter);
29183
29389
  }
29184
29390
  function isReverseRelevantNetworkRecord(record) {
29185
29391
  return record.record.resourceType === "document" || record.record.resourceType === "fetch" || record.record.resourceType === "xhr" || record.record.resourceType === "websocket" || record.record.resourceType === "event-stream";
@@ -31186,6 +31392,7 @@ var OpensteerRuntime = class extends OpensteerSessionRuntime {
31186
31392
  ...options.policy === void 0 ? {} : { policy: options.policy },
31187
31393
  ...options.descriptorStore === void 0 ? {} : { descriptorStore: options.descriptorStore },
31188
31394
  ...options.extractionDescriptorStore === void 0 ? {} : { extractionDescriptorStore: options.extractionDescriptorStore },
31395
+ ...options.registryOverrides === void 0 ? {} : { registryOverrides: options.registryOverrides },
31189
31396
  cleanupRootOnClose
31190
31397
  })
31191
31398
  );
@@ -31214,6 +31421,7 @@ var OpensteerSessionRuntime2 = class extends OpensteerSessionRuntime {
31214
31421
  ...options.policy === void 0 ? {} : { policy: options.policy },
31215
31422
  ...options.descriptorStore === void 0 ? {} : { descriptorStore: options.descriptorStore },
31216
31423
  ...options.extractionDescriptorStore === void 0 ? {} : { extractionDescriptorStore: options.extractionDescriptorStore },
31424
+ ...options.registryOverrides === void 0 ? {} : { registryOverrides: options.registryOverrides },
31217
31425
  cleanupRootOnClose
31218
31426
  })
31219
31427
  );
@@ -31238,6 +31446,7 @@ function buildSharedRuntimeOptions(input) {
31238
31446
  ...input.policy === void 0 ? {} : { policy: input.policy },
31239
31447
  ...input.descriptorStore === void 0 ? {} : { descriptorStore: input.descriptorStore },
31240
31448
  ...input.extractionDescriptorStore === void 0 ? {} : { extractionDescriptorStore: input.extractionDescriptorStore },
31449
+ ...input.registryOverrides === void 0 ? {} : { registryOverrides: input.registryOverrides },
31241
31450
  cleanupRootOnClose: input.cleanupRootOnClose,
31242
31451
  sessionInfo: {
31243
31452
  provider: {
@@ -31978,6 +32187,20 @@ var OpensteerCloudClient = class {
31978
32187
  });
31979
32188
  return await response.json();
31980
32189
  }
32190
+ async importReverseCases(entries) {
32191
+ const response = await this.request("/registry/reverse-cases/import", {
32192
+ method: "POST",
32193
+ body: { entries }
32194
+ });
32195
+ return await response.json();
32196
+ }
32197
+ async importReversePackages(entries) {
32198
+ const response = await this.request("/registry/reverse-packages/import", {
32199
+ method: "POST",
32200
+ body: { entries }
32201
+ });
32202
+ return await response.json();
32203
+ }
31981
32204
  buildAuthorizationHeader() {
31982
32205
  return `Bearer ${this.config.apiKey}`;
31983
32206
  }
@@ -32493,11 +32716,13 @@ function asRecord(value) {
32493
32716
  var REGISTRY_SYNC_MAX_PAYLOAD_BYTES = 15e5;
32494
32717
  var REGISTRY_SYNC_MAX_ENTRIES_PER_BATCH = 100;
32495
32718
  async function syncLocalRegistryToCloud(client, workspace, store) {
32496
- const [descriptors, requestPlans, recipes, authRecipes] = await Promise.all([
32719
+ const [descriptors, requestPlans, recipes, authRecipes, reverseCases, reversePackages] = await Promise.all([
32497
32720
  store.registry.descriptors.list(),
32498
32721
  store.registry.requestPlans.list(),
32499
32722
  store.registry.recipes.list(),
32500
- store.registry.authRecipes.list()
32723
+ store.registry.authRecipes.list(),
32724
+ store.registry.reverseCases.list(),
32725
+ store.registry.reversePackages.list()
32501
32726
  ]);
32502
32727
  const descriptorEntries = descriptors.map((record) => toDescriptorImportEntry(workspace, record));
32503
32728
  await Promise.all([
@@ -32513,6 +32738,14 @@ async function syncLocalRegistryToCloud(client, workspace, store) {
32513
32738
  importInBatches(
32514
32739
  authRecipes.map((record) => toRegistryImportEntry(workspace, record)),
32515
32740
  (entries) => client.importAuthRecipes(entries)
32741
+ ),
32742
+ importInBatches(
32743
+ reverseCases.map((record) => toRegistryImportEntry(workspace, record)),
32744
+ (entries) => client.importReverseCases(entries)
32745
+ ),
32746
+ importInBatches(
32747
+ reversePackages.map((record) => toRegistryImportEntry(workspace, record)),
32748
+ (entries) => client.importReversePackages(entries)
32516
32749
  )
32517
32750
  ]);
32518
32751
  }
@@ -32722,9 +32955,9 @@ var CloudSessionProxy = class {
32722
32955
  await this.ensureSession();
32723
32956
  return this.requireClient().invoke("network.query", input);
32724
32957
  }
32725
- async saveNetwork(input) {
32958
+ async tagNetwork(input) {
32726
32959
  await this.ensureSession();
32727
- return this.requireClient().invoke("network.save", input);
32960
+ return this.requireClient().invoke("network.tag", input);
32728
32961
  }
32729
32962
  async minimizeNetwork(input) {
32730
32963
  await this.ensureSession();
@@ -33208,13 +33441,20 @@ var Opensteer = class {
33208
33441
  const { timeoutMs, pollIntervalMs, ...query } = input;
33209
33442
  const timeoutAt = Date.now() + (timeoutMs ?? 3e4);
33210
33443
  const pollInterval = pollIntervalMs ?? 100;
33444
+ const baseline = new Set(
33445
+ (await this.runtime.queryNetwork({
33446
+ ...query,
33447
+ limit: 200
33448
+ })).records.map((record) => record.recordId)
33449
+ );
33211
33450
  while (true) {
33212
33451
  const { records } = await this.runtime.queryNetwork({
33213
33452
  ...query,
33214
- limit: 1
33453
+ limit: 200
33215
33454
  });
33216
- if (records[0] !== void 0) {
33217
- return records[0];
33455
+ const next = records.find((record) => !baseline.has(record.recordId));
33456
+ if (next !== void 0) {
33457
+ return next;
33218
33458
  }
33219
33459
  if (Date.now() >= timeoutAt) {
33220
33460
  throw new Error("waitForNetwork timed out");
@@ -33255,8 +33495,8 @@ var Opensteer = class {
33255
33495
  async snapshot(input = {}) {
33256
33496
  return this.runtime.snapshot(typeof input === "string" ? { mode: input } : input);
33257
33497
  }
33258
- async saveNetwork(input) {
33259
- return this.runtime.saveNetwork(input);
33498
+ async tagNetwork(input) {
33499
+ return this.runtime.tagNetwork(input);
33260
33500
  }
33261
33501
  async minimizeNetwork(input) {
33262
33502
  return this.runtime.minimizeNetwork(input);