opensteer 0.9.7 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +2 -2
  2. package/dist/{chunk-R33BXCMQ.js → chunk-BPGXP3RF.js} +245 -21
  3. package/dist/chunk-BPGXP3RF.js.map +1 -0
  4. package/dist/{chunk-PJXN7HED.js → chunk-EXXRLPLI.js} +46 -35
  5. package/dist/chunk-EXXRLPLI.js.map +1 -0
  6. package/dist/{chunk-U4BUCIZ4.js → chunk-GKYBP3KD.js} +4 -4
  7. package/dist/chunk-GKYBP3KD.js.map +1 -0
  8. package/dist/{chunk-3OHKIPBD.js → chunk-LFWP5RXF.js} +189 -53
  9. package/dist/chunk-LFWP5RXF.js.map +1 -0
  10. package/dist/{chunk-52UNH5UW.js → chunk-SOJEWKSW.js} +5 -5
  11. package/dist/{chunk-52UNH5UW.js.map → chunk-SOJEWKSW.js.map} +1 -1
  12. package/dist/cli/bin.cjs +570 -119
  13. package/dist/cli/bin.cjs.map +1 -1
  14. package/dist/cli/bin.js +106 -28
  15. package/dist/cli/bin.js.map +1 -1
  16. package/dist/index.cjs +211 -72
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +10 -1
  19. package/dist/index.d.ts +10 -1
  20. package/dist/index.js +4 -4
  21. package/dist/local-view/serve-entry.cjs +288 -50
  22. package/dist/local-view/serve-entry.cjs.map +1 -1
  23. package/dist/local-view/serve-entry.js +2 -2
  24. package/dist/opensteer-XLPY343Y.js +6 -0
  25. package/dist/{opensteer-CY2QUJEG.js.map → opensteer-XLPY343Y.js.map} +1 -1
  26. package/dist/{session-control-FIP6ZJLH.js → session-control-FVKKD45R.js} +4 -4
  27. package/dist/{session-control-FIP6ZJLH.js.map → session-control-FVKKD45R.js.map} +1 -1
  28. package/package.json +7 -7
  29. package/skills/recorder/SKILL.md +2 -2
  30. package/dist/chunk-3OHKIPBD.js.map +0 -1
  31. package/dist/chunk-PJXN7HED.js.map +0 -1
  32. package/dist/chunk-R33BXCMQ.js.map +0 -1
  33. package/dist/chunk-U4BUCIZ4.js.map +0 -1
  34. package/dist/opensteer-CY2QUJEG.js +0 -6
package/dist/index.cjs CHANGED
@@ -1323,6 +1323,9 @@ var pageInfoSchema = objectSchema(
1323
1323
  {
1324
1324
  pageRef: pageRefSchema,
1325
1325
  sessionRef: sessionRefSchema,
1326
+ targetId: stringSchema({
1327
+ description: "Underlying browser target identifier when available."
1328
+ }),
1326
1329
  openerPageRef: pageRefSchema,
1327
1330
  url: stringSchema({
1328
1331
  description: "Current main-frame URL."
@@ -6203,6 +6206,9 @@ var FilesystemSessionSink = class {
6203
6206
  this.store = store;
6204
6207
  this.sessionId = sessionId;
6205
6208
  }
6209
+ configure(input) {
6210
+ return this.store.configureSession(this.sessionId, input);
6211
+ }
6206
6212
  append(input) {
6207
6213
  return this.store.appendEvent(this.sessionId, input);
6208
6214
  }
@@ -6233,40 +6239,14 @@ var FilesystemObservationStoreImpl = class {
6233
6239
  const sessionId = normalizeNonEmptyString("sessionId", input.sessionId);
6234
6240
  const openedAt = normalizeTimestamp("openedAt", input.openedAt ?? Date.now());
6235
6241
  const config = normalizeObservabilityConfig(input.config);
6236
- const redactor = createObservationRedactor(config);
6237
- this.redactors.set(sessionId, redactor);
6238
- const redactedLabels = redactor.redactLabels(config.labels);
6239
- const redactedTraceContext = redactor.redactTraceContext(config.traceContext);
6240
- await withFilesystemLock(this.sessionLockPath(sessionId), async () => {
6241
- const existing = await this.reconcileSessionManifest(sessionId);
6242
- if (existing === void 0) {
6243
- await ensureDirectory(this.sessionEventsDirectory(sessionId));
6244
- await ensureDirectory(this.sessionArtifactsDirectory(sessionId));
6245
- const session = {
6246
- sessionId,
6247
- profile: config.profile,
6248
- ...redactedLabels === void 0 ? {} : { labels: redactedLabels },
6249
- ...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
6250
- openedAt,
6251
- updatedAt: openedAt,
6252
- currentSequence: 0,
6253
- eventCount: 0,
6254
- artifactCount: 0
6255
- };
6256
- await writeJsonFileExclusive(this.sessionManifestPath(sessionId), session);
6257
- return;
6258
- }
6259
- const patched = {
6260
- ...existing,
6261
- profile: config.profile,
6262
- ...redactedLabels === void 0 ? {} : { labels: redactedLabels },
6263
- ...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
6264
- updatedAt: Math.max(existing.updatedAt, openedAt)
6265
- };
6266
- await writeJsonFileAtomic(this.sessionManifestPath(sessionId), patched);
6267
- });
6242
+ await this.applySessionConfiguration(sessionId, config, openedAt);
6268
6243
  return new FilesystemSessionSink(this, sessionId);
6269
6244
  }
6245
+ async configureSession(sessionId, input) {
6246
+ const updatedAt = normalizeTimestamp("updatedAt", input.updatedAt ?? Date.now());
6247
+ const config = normalizeObservabilityConfig(input.config);
6248
+ await this.applySessionConfiguration(sessionId, config, updatedAt);
6249
+ }
6270
6250
  async getSession(sessionId) {
6271
6251
  const manifestPath = this.sessionManifestPath(sessionId);
6272
6252
  if (!await pathExists(manifestPath)) {
@@ -6487,6 +6467,40 @@ var FilesystemObservationStoreImpl = class {
6487
6467
  sessionLockPath(sessionId) {
6488
6468
  return path10__default.default.join(this.sessionDirectory(sessionId), ".lock");
6489
6469
  }
6470
+ async applySessionConfiguration(sessionId, config, timestamp) {
6471
+ const redactor = createObservationRedactor(config);
6472
+ this.redactors.set(sessionId, redactor);
6473
+ const redactedLabels = redactor.redactLabels(config.labels);
6474
+ const redactedTraceContext = redactor.redactTraceContext(config.traceContext);
6475
+ await withFilesystemLock(this.sessionLockPath(sessionId), async () => {
6476
+ const existing = await this.reconcileSessionManifest(sessionId);
6477
+ if (existing === void 0) {
6478
+ await ensureDirectory(this.sessionEventsDirectory(sessionId));
6479
+ await ensureDirectory(this.sessionArtifactsDirectory(sessionId));
6480
+ const session = {
6481
+ sessionId,
6482
+ profile: config.profile,
6483
+ ...redactedLabels === void 0 ? {} : { labels: redactedLabels },
6484
+ ...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
6485
+ openedAt: timestamp,
6486
+ updatedAt: timestamp,
6487
+ currentSequence: 0,
6488
+ eventCount: 0,
6489
+ artifactCount: 0
6490
+ };
6491
+ await writeJsonFileExclusive(this.sessionManifestPath(sessionId), session);
6492
+ return;
6493
+ }
6494
+ const patched = {
6495
+ ...existing,
6496
+ profile: config.profile,
6497
+ ...redactedLabels === void 0 ? {} : { labels: redactedLabels },
6498
+ ...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
6499
+ updatedAt: Math.max(existing.updatedAt, timestamp)
6500
+ };
6501
+ await writeJsonFileAtomic(this.sessionManifestPath(sessionId), patched);
6502
+ });
6503
+ }
6490
6504
  async reconcileSessionManifest(sessionId) {
6491
6505
  const session = await this.getSession(sessionId);
6492
6506
  if (session === void 0) {
@@ -7546,7 +7560,9 @@ function resolveExtractedValueInContext(normalizedValue, options) {
7546
7560
  function stripPositionClauses(nodes) {
7547
7561
  return (nodes || []).map((node) => ({
7548
7562
  ...node,
7549
- match: (node.match || []).filter((clause) => clause.kind !== "position" && clause.kind !== "text")
7563
+ match: (node.match || []).filter(
7564
+ (clause) => clause.kind !== "position" && clause.kind !== "text"
7565
+ )
7550
7566
  }));
7551
7567
  }
7552
7568
  function dedupeSelectors(selectors) {
@@ -9818,7 +9834,9 @@ var DefaultDomRuntime = class {
9818
9834
  `Unable to resolve structural anchor "${buildPathSelectorHint(anchor)}" in the current session`
9819
9835
  );
9820
9836
  }
9821
- const replayPath = await this.tryBuildPathFromNode(context.snapshot, target.node, { enableTextMatch: true });
9837
+ const replayPath = await this.tryBuildPathFromNode(context.snapshot, target.node, {
9838
+ enableTextMatch: true
9839
+ });
9822
9840
  return this.createResolvedTarget(source, context.snapshot, target.node, anchor, {
9823
9841
  ...persist === void 0 ? {} : { persist },
9824
9842
  ...replayPath === void 0 ? {} : { replayPath }
@@ -13505,10 +13523,10 @@ async function isAttachedLocalBrowserSessionReachable(record) {
13505
13523
  }
13506
13524
  }
13507
13525
  function isPersistedCloudSessionRecord(value) {
13508
- return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "cloud" && typeof value.sessionId === "string" && value.sessionId.length > 0 && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt);
13526
+ return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "cloud" && typeof value.sessionId === "string" && value.sessionId.length > 0 && (value.activePageUrl === void 0 || typeof value.activePageUrl === "string") && (value.activePageTitle === void 0 || typeof value.activePageTitle === "string") && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt);
13509
13527
  }
13510
13528
  function isPersistedLocalBrowserSessionRecord(value) {
13511
- return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "local" && (value.engine === "playwright" || value.engine === "abp") && (value.ownership === void 0 || value.ownership === "owned" || value.ownership === "attached") && typeof value.pid === "number" && Number.isFinite(value.pid) && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) && typeof value.userDataDir === "string" && value.userDataDir.length > 0;
13529
+ return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "local" && (value.engine === "playwright" || value.engine === "abp") && (value.ownership === void 0 || value.ownership === "owned" || value.ownership === "attached") && (value.activePageUrl === void 0 || typeof value.activePageUrl === "string") && (value.activePageTitle === void 0 || typeof value.activePageTitle === "string") && typeof value.pid === "number" && Number.isFinite(value.pid) && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) && typeof value.userDataDir === "string" && value.userDataDir.length > 0;
13512
13530
  }
13513
13531
  function resolveOpensteerStateDir() {
13514
13532
  const explicit = process.env.OPENSTEER_HOME?.trim();
@@ -15946,11 +15964,11 @@ function delay2(ms) {
15946
15964
  function wrapCloudFetchError(error, input) {
15947
15965
  if (!(error instanceof Error)) {
15948
15966
  return new Error(
15949
- `Failed to reach Opensteer cloud endpoint ${input.method} ${input.url}. Check OPENSTEER_BASE_URL and network reachability from this environment.`
15967
+ `Failed to reach Opensteer cloud endpoint ${input.method} ${input.url}. Check the configured Opensteer cloud base URL and network reachability from this environment.`
15950
15968
  );
15951
15969
  }
15952
15970
  const wrapped = new Error(
15953
- `Failed to reach Opensteer cloud endpoint ${input.method} ${input.url}. Check OPENSTEER_BASE_URL and network reachability from this environment.`,
15971
+ `Failed to reach Opensteer cloud endpoint ${input.method} ${input.url}. Check the configured Opensteer cloud base URL and network reachability from this environment.`,
15954
15972
  {
15955
15973
  cause: error
15956
15974
  }
@@ -15990,6 +16008,7 @@ function asCloudErrorPayload(value) {
15990
16008
  }
15991
16009
 
15992
16010
  // src/cloud/config.ts
16011
+ var DEFAULT_OPENSTEER_CLOUD_BASE_URL = "https://api.opensteer.com";
15993
16012
  function resolveCloudConfig(input = {}) {
15994
16013
  const provider = resolveOpensteerProvider({
15995
16014
  ...input.provider === void 0 ? {} : { provider: input.provider },
@@ -15999,26 +16018,30 @@ function resolveCloudConfig(input = {}) {
15999
16018
  return void 0;
16000
16019
  }
16001
16020
  const cloudProvider = input.provider?.mode === "cloud" ? input.provider : void 0;
16002
- const apiKey = cloudProvider?.apiKey ?? input.environment?.OPENSTEER_API_KEY;
16003
- if (!apiKey || apiKey.trim().length === 0) {
16021
+ const apiKey = normalizeOptionalCloudConfigValue(cloudProvider?.apiKey) ?? normalizeOptionalCloudConfigValue(input.environment?.OPENSTEER_API_KEY);
16022
+ if (apiKey === void 0) {
16004
16023
  throw new Error("provider=cloud requires OPENSTEER_API_KEY or provider.apiKey.");
16005
16024
  }
16006
- const baseUrl = cloudProvider?.baseUrl ?? input.environment?.OPENSTEER_BASE_URL;
16007
- if (!baseUrl || baseUrl.trim().length === 0) {
16008
- throw new Error("provider=cloud requires OPENSTEER_BASE_URL or provider.baseUrl.");
16009
- }
16010
- const appBaseUrl = cloudProvider?.appBaseUrl ?? input.environment?.OPENSTEER_CLOUD_APP_BASE_URL;
16025
+ const baseUrl = normalizeOptionalCloudConfigValue(cloudProvider?.baseUrl) ?? normalizeOptionalCloudConfigValue(input.environment?.OPENSTEER_BASE_URL) ?? DEFAULT_OPENSTEER_CLOUD_BASE_URL;
16026
+ const appBaseUrl = normalizeOptionalCloudConfigValue(cloudProvider?.appBaseUrl) ?? normalizeOptionalCloudConfigValue(input.environment?.OPENSTEER_CLOUD_APP_BASE_URL);
16011
16027
  return {
16012
- apiKey: apiKey.trim(),
16013
- baseUrl: baseUrl.trim().replace(/\/+$/, ""),
16014
- ...appBaseUrl === void 0 || appBaseUrl.trim().length === 0 ? {} : { appBaseUrl: appBaseUrl.trim().replace(/\/+$/, "") },
16028
+ apiKey,
16029
+ baseUrl,
16030
+ ...appBaseUrl === void 0 ? {} : { appBaseUrl },
16015
16031
  ...cloudProvider?.browserProfile === void 0 ? {} : { browserProfile: cloudProvider.browserProfile }
16016
16032
  };
16017
16033
  }
16034
+ function normalizeOptionalCloudConfigValue(value) {
16035
+ if (typeof value !== "string") {
16036
+ return void 0;
16037
+ }
16038
+ const normalized = value.trim().replace(/\/+$/, "");
16039
+ return normalized.length === 0 ? void 0 : normalized;
16040
+ }
16018
16041
 
16019
16042
  // ../runtime-core/package.json
16020
16043
  var package_default = {
16021
- version: "0.2.6"};
16044
+ version: "0.2.7"};
16022
16045
 
16023
16046
  // ../runtime-core/src/version.ts
16024
16047
  var OPENSTEER_RUNTIME_CORE_VERSION = package_default.version;
@@ -20089,7 +20112,10 @@ var OpensteerSessionRuntime = class {
20089
20112
  sessionRef;
20090
20113
  pageRef;
20091
20114
  runId;
20092
- observations;
20115
+ observationSessions = /* @__PURE__ */ new Map();
20116
+ openingObservationSessions = /* @__PURE__ */ new Map();
20117
+ openedObservationSessions = /* @__PURE__ */ new Set();
20118
+ observationSessionStorage = new async_hooks.AsyncLocalStorage();
20093
20119
  operationEventStorage = new async_hooks.AsyncLocalStorage();
20094
20120
  pendingOperationEventCaptures = [];
20095
20121
  ownsEngine = false;
@@ -20141,18 +20167,26 @@ var OpensteerSessionRuntime = class {
20141
20167
  }
20142
20168
  async setObservabilityConfig(input) {
20143
20169
  this.observationConfig = normalizeObservabilityConfig(input);
20144
- const observationSessionId = this.resolveObservationSessionId();
20145
- if (observationSessionId === void 0) {
20146
- return this.observationConfig;
20147
- }
20148
- const sink = this.injectedObservationSink ?? (await this.ensureRoot()).observations;
20149
- this.observations = await sink.openSession({
20150
- sessionId: observationSessionId,
20151
- openedAt: Date.now(),
20152
- config: this.observationConfig
20153
- });
20170
+ await this.ensureConfiguredObservationSession();
20154
20171
  return this.observationConfig;
20155
20172
  }
20173
+ async withObservationSessionId(sessionId, task) {
20174
+ return await this.observationSessionStorage.run(
20175
+ {
20176
+ mode: "session",
20177
+ sessionId: normalizeNonEmptyString("sessionId", sessionId)
20178
+ },
20179
+ task
20180
+ );
20181
+ }
20182
+ async withoutObservationSession(task) {
20183
+ return await this.observationSessionStorage.run(
20184
+ {
20185
+ mode: "disabled"
20186
+ },
20187
+ task
20188
+ );
20189
+ }
20156
20190
  async open(input = {}, options = {}) {
20157
20191
  assertValidSemanticOperationInput("session.open", input);
20158
20192
  if (input.workspace !== void 0 && normalizeNamespace2(input.workspace) !== this.workspace) {
@@ -23596,7 +23630,7 @@ var OpensteerSessionRuntime = class {
23596
23630
  }
23597
23631
  async resetRuntimeState(options) {
23598
23632
  const engine = this.engine;
23599
- const observations = this.observations;
23633
+ const observationSessions = [...this.openedObservationSessions];
23600
23634
  this.networkHistory.clear();
23601
23635
  this.sessionRef = void 0;
23602
23636
  this.pageRef = void 0;
@@ -23605,9 +23639,15 @@ var OpensteerSessionRuntime = class {
23605
23639
  this.computer = void 0;
23606
23640
  this.extractionDescriptors = void 0;
23607
23641
  this.engine = void 0;
23608
- this.observations = void 0;
23642
+ this.observationSessions.clear();
23643
+ this.openingObservationSessions.clear();
23644
+ this.openedObservationSessions.clear();
23609
23645
  this.pendingOperationEventCaptures.length = 0;
23610
- await observations?.close("runtime_reset").catch(() => void 0);
23646
+ await Promise.allSettled(
23647
+ observationSessions.map(
23648
+ (observationSession) => observationSession.close("runtime_reset").catch(() => void 0)
23649
+ )
23650
+ );
23611
23651
  if (options.disposeEngine && this.ownsEngine && engine?.dispose) {
23612
23652
  await engine.dispose();
23613
23653
  }
@@ -23617,23 +23657,64 @@ var OpensteerSessionRuntime = class {
23617
23657
  if (this.observationConfig.profile === "off") {
23618
23658
  return void 0;
23619
23659
  }
23620
- if (this.observations !== void 0) {
23621
- return this.observations;
23660
+ const observationSessionId = this.resolveObservationSessionId();
23661
+ if (observationSessionId === void 0) {
23662
+ return void 0;
23663
+ }
23664
+ const existingObservationSession = this.observationSessions.get(observationSessionId);
23665
+ if (existingObservationSession !== void 0) {
23666
+ return existingObservationSession;
23667
+ }
23668
+ const openingObservationSession = this.openingObservationSessions.get(observationSessionId);
23669
+ if (openingObservationSession !== void 0) {
23670
+ return await openingObservationSession;
23671
+ }
23672
+ const openObservationSessionTask = this.openObservationSession(observationSessionId).finally(
23673
+ () => {
23674
+ this.openingObservationSessions.delete(observationSessionId);
23675
+ }
23676
+ );
23677
+ this.openingObservationSessions.set(observationSessionId, openObservationSessionTask);
23678
+ return await openObservationSessionTask;
23679
+ }
23680
+ async ensureConfiguredObservationSession() {
23681
+ if (this.observationConfig.profile === "off") {
23682
+ return void 0;
23622
23683
  }
23623
23684
  const observationSessionId = this.resolveObservationSessionId();
23624
23685
  if (observationSessionId === void 0) {
23625
23686
  return void 0;
23626
23687
  }
23688
+ const hadObservationSession = this.observationSessions.has(observationSessionId) || this.openingObservationSessions.has(observationSessionId);
23689
+ const observationSession = await this.ensureObservationSession();
23690
+ if (observationSession !== void 0 && hadObservationSession) {
23691
+ await observationSession.configure?.({
23692
+ config: this.observationConfig,
23693
+ updatedAt: Date.now()
23694
+ });
23695
+ }
23696
+ return observationSession;
23697
+ }
23698
+ resolveObservationSessionId() {
23699
+ const scopedSession = this.observationSessionStorage.getStore();
23700
+ if (scopedSession?.mode === "session") {
23701
+ return scopedSession.sessionId;
23702
+ }
23703
+ if (scopedSession?.mode === "disabled") {
23704
+ return void 0;
23705
+ }
23706
+ return this.observationSessionId ?? this.sessionRef;
23707
+ }
23708
+ async openObservationSession(sessionId) {
23627
23709
  const sink = this.injectedObservationSink ?? (await this.ensureRoot()).observations;
23628
- this.observations = await sink.openSession({
23629
- sessionId: observationSessionId,
23710
+ const observationSession = await sink.openSession({
23711
+ sessionId,
23630
23712
  openedAt: Date.now(),
23631
23713
  config: this.observationConfig
23632
23714
  });
23633
- return this.observations;
23634
- }
23635
- resolveObservationSessionId() {
23636
- return this.observationSessionId ?? this.sessionRef;
23715
+ this.observationSessions.set(sessionId, observationSession);
23716
+ this.openedObservationSessions.add(observationSession);
23717
+ return observationSession;
23637
23718
  }
23638
23719
  runWithOperationTimeout(operation, callback, options = {}) {
23639
23720
  const timeoutPolicy = options.timeoutMs === void 0 ? this.policy.timeout : {
@@ -26309,7 +26390,29 @@ function isLoopbackBaseUrl(baseUrl) {
26309
26390
  }
26310
26391
  return url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1" || url.hostname === "[::1]";
26311
26392
  }
26312
- var OpensteerRuntime = class extends OpensteerSessionRuntime {
26393
+ var LocalActivePageHintRuntime = class extends OpensteerSessionRuntime {
26394
+ async completeWithLocalActivePageHint(operation) {
26395
+ const output = await operation();
26396
+ await persistLocalActivePageHint(this, this.rootPath);
26397
+ return output;
26398
+ }
26399
+ async open(input = {}, options = {}) {
26400
+ return this.completeWithLocalActivePageHint(() => super.open(input, options));
26401
+ }
26402
+ async newPage(input = {}, options = {}) {
26403
+ return this.completeWithLocalActivePageHint(() => super.newPage(input, options));
26404
+ }
26405
+ async activatePage(input, options = {}) {
26406
+ return this.completeWithLocalActivePageHint(() => super.activatePage(input, options));
26407
+ }
26408
+ async closePage(input = {}, options = {}) {
26409
+ return this.completeWithLocalActivePageHint(() => super.closePage(input, options));
26410
+ }
26411
+ async goto(input, options = {}) {
26412
+ return this.completeWithLocalActivePageHint(() => super.goto(input, options));
26413
+ }
26414
+ };
26415
+ var OpensteerRuntime = class extends LocalActivePageHintRuntime {
26313
26416
  constructor(options = {}) {
26314
26417
  const publicWorkspace = normalizeWorkspace2(options.workspace);
26315
26418
  const rootPath = options.rootPath ?? (publicWorkspace === void 0 ? path10__default.default.resolve(options.rootDir ?? process.cwd(), ".opensteer", "temporary", crypto.randomUUID()) : resolveFilesystemWorkspacePath({
@@ -26347,6 +26450,41 @@ var OpensteerRuntime = class extends OpensteerSessionRuntime {
26347
26450
  );
26348
26451
  }
26349
26452
  };
26453
+ async function persistLocalActivePageHint(runtime, rootPath) {
26454
+ try {
26455
+ await syncPersistedLocalActivePageHint(runtime, rootPath);
26456
+ } catch {
26457
+ }
26458
+ }
26459
+ async function syncPersistedLocalActivePageHint(runtime, rootPath) {
26460
+ const record = await readPersistedLocalBrowserSessionRecord(rootPath);
26461
+ if (!record) {
26462
+ return;
26463
+ }
26464
+ const sessionInfo = await runtime.info();
26465
+ const activePageRef = sessionInfo.activePageRef;
26466
+ let activePageUrl;
26467
+ let activePageTitle;
26468
+ if (activePageRef !== void 0) {
26469
+ const pages = await runtime.listPages();
26470
+ const activePage = pages.pages.find((page) => page.pageRef === activePageRef);
26471
+ activePageUrl = activePage?.url;
26472
+ activePageTitle = activePage?.title;
26473
+ }
26474
+ const {
26475
+ activePageRef: _previousActivePageRef,
26476
+ activePageUrl: _previousActivePageUrl,
26477
+ activePageTitle: _previousActivePageTitle,
26478
+ ...restRecord
26479
+ } = record;
26480
+ await writePersistedSessionRecord(rootPath, {
26481
+ ...restRecord,
26482
+ updatedAt: Date.now(),
26483
+ ...activePageRef === void 0 ? {} : { activePageRef },
26484
+ ...activePageUrl === void 0 ? {} : { activePageUrl },
26485
+ ...activePageTitle === void 0 ? {} : { activePageTitle }
26486
+ });
26487
+ }
26350
26488
  function buildSharedRuntimeOptions(input) {
26351
26489
  const ownership = resolveOwnership(input.browser);
26352
26490
  const engineFactory = input.engineFactory ?? ((factoryOptions) => new OpensteerBrowserManager({
@@ -26847,6 +26985,7 @@ function delay3(ms) {
26847
26985
  return new Promise((resolve4) => setTimeout(resolve4, ms));
26848
26986
  }
26849
26987
 
26988
+ exports.DEFAULT_OPENSTEER_CLOUD_BASE_URL = DEFAULT_OPENSTEER_CLOUD_BASE_URL;
26850
26989
  exports.DEFAULT_OPENSTEER_ENGINE = DEFAULT_OPENSTEER_ENGINE;
26851
26990
  exports.DEFERRED_MATCH_ATTR_KEYS = DEFERRED_MATCH_ATTR_KEYS;
26852
26991
  exports.ElementPathError = ElementPathError;