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.
- package/README.md +2 -2
- package/dist/{chunk-R33BXCMQ.js → chunk-BPGXP3RF.js} +245 -21
- package/dist/chunk-BPGXP3RF.js.map +1 -0
- package/dist/{chunk-PJXN7HED.js → chunk-EXXRLPLI.js} +46 -35
- package/dist/chunk-EXXRLPLI.js.map +1 -0
- package/dist/{chunk-U4BUCIZ4.js → chunk-GKYBP3KD.js} +4 -4
- package/dist/chunk-GKYBP3KD.js.map +1 -0
- package/dist/{chunk-3OHKIPBD.js → chunk-LFWP5RXF.js} +189 -53
- package/dist/chunk-LFWP5RXF.js.map +1 -0
- package/dist/{chunk-52UNH5UW.js → chunk-SOJEWKSW.js} +5 -5
- package/dist/{chunk-52UNH5UW.js.map → chunk-SOJEWKSW.js.map} +1 -1
- package/dist/cli/bin.cjs +570 -119
- package/dist/cli/bin.cjs.map +1 -1
- package/dist/cli/bin.js +106 -28
- package/dist/cli/bin.js.map +1 -1
- package/dist/index.cjs +211 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +4 -4
- package/dist/local-view/serve-entry.cjs +288 -50
- package/dist/local-view/serve-entry.cjs.map +1 -1
- package/dist/local-view/serve-entry.js +2 -2
- package/dist/opensteer-XLPY343Y.js +6 -0
- package/dist/{opensteer-CY2QUJEG.js.map → opensteer-XLPY343Y.js.map} +1 -1
- package/dist/{session-control-FIP6ZJLH.js → session-control-FVKKD45R.js} +4 -4
- package/dist/{session-control-FIP6ZJLH.js.map → session-control-FVKKD45R.js.map} +1 -1
- package/package.json +7 -7
- package/skills/recorder/SKILL.md +2 -2
- package/dist/chunk-3OHKIPBD.js.map +0 -1
- package/dist/chunk-PJXN7HED.js.map +0 -1
- package/dist/chunk-R33BXCMQ.js.map +0 -1
- package/dist/chunk-U4BUCIZ4.js.map +0 -1
- package/dist/opensteer-CY2QUJEG.js +0 -6
package/dist/cli/bin.cjs
CHANGED
|
@@ -2940,6 +2940,9 @@ var init_metadata2 = __esm({
|
|
|
2940
2940
|
{
|
|
2941
2941
|
pageRef: pageRefSchema,
|
|
2942
2942
|
sessionRef: sessionRefSchema,
|
|
2943
|
+
targetId: stringSchema({
|
|
2944
|
+
description: "Underlying browser target identifier when available."
|
|
2945
|
+
}),
|
|
2943
2946
|
openerPageRef: pageRefSchema,
|
|
2944
2947
|
url: stringSchema({
|
|
2945
2948
|
description: "Current main-frame URL."
|
|
@@ -9143,6 +9146,9 @@ var init_observations = __esm({
|
|
|
9143
9146
|
this.store = store;
|
|
9144
9147
|
this.sessionId = sessionId;
|
|
9145
9148
|
}
|
|
9149
|
+
configure(input) {
|
|
9150
|
+
return this.store.configureSession(this.sessionId, input);
|
|
9151
|
+
}
|
|
9146
9152
|
append(input) {
|
|
9147
9153
|
return this.store.appendEvent(this.sessionId, input);
|
|
9148
9154
|
}
|
|
@@ -9173,40 +9179,14 @@ var init_observations = __esm({
|
|
|
9173
9179
|
const sessionId = normalizeNonEmptyString("sessionId", input.sessionId);
|
|
9174
9180
|
const openedAt = normalizeTimestamp("openedAt", input.openedAt ?? Date.now());
|
|
9175
9181
|
const config = normalizeObservabilityConfig(input.config);
|
|
9176
|
-
|
|
9177
|
-
this.redactors.set(sessionId, redactor);
|
|
9178
|
-
const redactedLabels = redactor.redactLabels(config.labels);
|
|
9179
|
-
const redactedTraceContext = redactor.redactTraceContext(config.traceContext);
|
|
9180
|
-
await withFilesystemLock(this.sessionLockPath(sessionId), async () => {
|
|
9181
|
-
const existing = await this.reconcileSessionManifest(sessionId);
|
|
9182
|
-
if (existing === void 0) {
|
|
9183
|
-
await ensureDirectory(this.sessionEventsDirectory(sessionId));
|
|
9184
|
-
await ensureDirectory(this.sessionArtifactsDirectory(sessionId));
|
|
9185
|
-
const session = {
|
|
9186
|
-
sessionId,
|
|
9187
|
-
profile: config.profile,
|
|
9188
|
-
...redactedLabels === void 0 ? {} : { labels: redactedLabels },
|
|
9189
|
-
...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
|
|
9190
|
-
openedAt,
|
|
9191
|
-
updatedAt: openedAt,
|
|
9192
|
-
currentSequence: 0,
|
|
9193
|
-
eventCount: 0,
|
|
9194
|
-
artifactCount: 0
|
|
9195
|
-
};
|
|
9196
|
-
await writeJsonFileExclusive(this.sessionManifestPath(sessionId), session);
|
|
9197
|
-
return;
|
|
9198
|
-
}
|
|
9199
|
-
const patched = {
|
|
9200
|
-
...existing,
|
|
9201
|
-
profile: config.profile,
|
|
9202
|
-
...redactedLabels === void 0 ? {} : { labels: redactedLabels },
|
|
9203
|
-
...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
|
|
9204
|
-
updatedAt: Math.max(existing.updatedAt, openedAt)
|
|
9205
|
-
};
|
|
9206
|
-
await writeJsonFileAtomic(this.sessionManifestPath(sessionId), patched);
|
|
9207
|
-
});
|
|
9182
|
+
await this.applySessionConfiguration(sessionId, config, openedAt);
|
|
9208
9183
|
return new FilesystemSessionSink(this, sessionId);
|
|
9209
9184
|
}
|
|
9185
|
+
async configureSession(sessionId, input) {
|
|
9186
|
+
const updatedAt = normalizeTimestamp("updatedAt", input.updatedAt ?? Date.now());
|
|
9187
|
+
const config = normalizeObservabilityConfig(input.config);
|
|
9188
|
+
await this.applySessionConfiguration(sessionId, config, updatedAt);
|
|
9189
|
+
}
|
|
9210
9190
|
async getSession(sessionId) {
|
|
9211
9191
|
const manifestPath = this.sessionManifestPath(sessionId);
|
|
9212
9192
|
if (!await pathExists(manifestPath)) {
|
|
@@ -9427,6 +9407,40 @@ var init_observations = __esm({
|
|
|
9427
9407
|
sessionLockPath(sessionId) {
|
|
9428
9408
|
return path10__default.default.join(this.sessionDirectory(sessionId), ".lock");
|
|
9429
9409
|
}
|
|
9410
|
+
async applySessionConfiguration(sessionId, config, timestamp) {
|
|
9411
|
+
const redactor = createObservationRedactor(config);
|
|
9412
|
+
this.redactors.set(sessionId, redactor);
|
|
9413
|
+
const redactedLabels = redactor.redactLabels(config.labels);
|
|
9414
|
+
const redactedTraceContext = redactor.redactTraceContext(config.traceContext);
|
|
9415
|
+
await withFilesystemLock(this.sessionLockPath(sessionId), async () => {
|
|
9416
|
+
const existing = await this.reconcileSessionManifest(sessionId);
|
|
9417
|
+
if (existing === void 0) {
|
|
9418
|
+
await ensureDirectory(this.sessionEventsDirectory(sessionId));
|
|
9419
|
+
await ensureDirectory(this.sessionArtifactsDirectory(sessionId));
|
|
9420
|
+
const session = {
|
|
9421
|
+
sessionId,
|
|
9422
|
+
profile: config.profile,
|
|
9423
|
+
...redactedLabels === void 0 ? {} : { labels: redactedLabels },
|
|
9424
|
+
...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
|
|
9425
|
+
openedAt: timestamp,
|
|
9426
|
+
updatedAt: timestamp,
|
|
9427
|
+
currentSequence: 0,
|
|
9428
|
+
eventCount: 0,
|
|
9429
|
+
artifactCount: 0
|
|
9430
|
+
};
|
|
9431
|
+
await writeJsonFileExclusive(this.sessionManifestPath(sessionId), session);
|
|
9432
|
+
return;
|
|
9433
|
+
}
|
|
9434
|
+
const patched = {
|
|
9435
|
+
...existing,
|
|
9436
|
+
profile: config.profile,
|
|
9437
|
+
...redactedLabels === void 0 ? {} : { labels: redactedLabels },
|
|
9438
|
+
...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
|
|
9439
|
+
updatedAt: Math.max(existing.updatedAt, timestamp)
|
|
9440
|
+
};
|
|
9441
|
+
await writeJsonFileAtomic(this.sessionManifestPath(sessionId), patched);
|
|
9442
|
+
});
|
|
9443
|
+
}
|
|
9430
9444
|
async reconcileSessionManifest(sessionId) {
|
|
9431
9445
|
const session = await this.getSession(sessionId);
|
|
9432
9446
|
if (session === void 0) {
|
|
@@ -9863,10 +9877,10 @@ async function isAttachedLocalBrowserSessionReachable(record) {
|
|
|
9863
9877
|
}
|
|
9864
9878
|
}
|
|
9865
9879
|
function isPersistedCloudSessionRecord(value) {
|
|
9866
|
-
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);
|
|
9880
|
+
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);
|
|
9867
9881
|
}
|
|
9868
9882
|
function isPersistedLocalBrowserSessionRecord(value) {
|
|
9869
|
-
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;
|
|
9883
|
+
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;
|
|
9870
9884
|
}
|
|
9871
9885
|
var OPENSTEER_LIVE_SESSION_LAYOUT, OPENSTEER_LIVE_SESSION_VERSION;
|
|
9872
9886
|
var init_live_session = __esm({
|
|
@@ -12145,11 +12159,11 @@ function delay2(ms) {
|
|
|
12145
12159
|
function wrapCloudFetchError(error, input) {
|
|
12146
12160
|
if (!(error instanceof Error)) {
|
|
12147
12161
|
return new Error(
|
|
12148
|
-
`Failed to reach Opensteer cloud endpoint ${input.method} ${input.url}. Check
|
|
12162
|
+
`Failed to reach Opensteer cloud endpoint ${input.method} ${input.url}. Check the configured Opensteer cloud base URL and network reachability from this environment.`
|
|
12149
12163
|
);
|
|
12150
12164
|
}
|
|
12151
12165
|
const wrapped = new Error(
|
|
12152
|
-
`Failed to reach Opensteer cloud endpoint ${input.method} ${input.url}. Check
|
|
12166
|
+
`Failed to reach Opensteer cloud endpoint ${input.method} ${input.url}. Check the configured Opensteer cloud base URL and network reachability from this environment.`,
|
|
12153
12167
|
{
|
|
12154
12168
|
cause: error
|
|
12155
12169
|
}
|
|
@@ -12424,34 +12438,40 @@ function resolveCloudConfig(input = {}) {
|
|
|
12424
12438
|
return void 0;
|
|
12425
12439
|
}
|
|
12426
12440
|
const cloudProvider = input.provider?.mode === "cloud" ? input.provider : void 0;
|
|
12427
|
-
const apiKey = cloudProvider?.apiKey ?? input.environment?.OPENSTEER_API_KEY;
|
|
12428
|
-
if (
|
|
12441
|
+
const apiKey = normalizeOptionalCloudConfigValue(cloudProvider?.apiKey) ?? normalizeOptionalCloudConfigValue(input.environment?.OPENSTEER_API_KEY);
|
|
12442
|
+
if (apiKey === void 0) {
|
|
12429
12443
|
throw new Error("provider=cloud requires OPENSTEER_API_KEY or provider.apiKey.");
|
|
12430
12444
|
}
|
|
12431
|
-
const baseUrl = cloudProvider?.baseUrl ?? input.environment?.OPENSTEER_BASE_URL;
|
|
12432
|
-
|
|
12433
|
-
throw new Error("provider=cloud requires OPENSTEER_BASE_URL or provider.baseUrl.");
|
|
12434
|
-
}
|
|
12435
|
-
const appBaseUrl = cloudProvider?.appBaseUrl ?? input.environment?.OPENSTEER_CLOUD_APP_BASE_URL;
|
|
12445
|
+
const baseUrl = normalizeOptionalCloudConfigValue(cloudProvider?.baseUrl) ?? normalizeOptionalCloudConfigValue(input.environment?.OPENSTEER_BASE_URL) ?? DEFAULT_OPENSTEER_CLOUD_BASE_URL;
|
|
12446
|
+
const appBaseUrl = normalizeOptionalCloudConfigValue(cloudProvider?.appBaseUrl) ?? normalizeOptionalCloudConfigValue(input.environment?.OPENSTEER_CLOUD_APP_BASE_URL);
|
|
12436
12447
|
return {
|
|
12437
|
-
apiKey
|
|
12438
|
-
baseUrl
|
|
12439
|
-
...appBaseUrl === void 0
|
|
12448
|
+
apiKey,
|
|
12449
|
+
baseUrl,
|
|
12450
|
+
...appBaseUrl === void 0 ? {} : { appBaseUrl },
|
|
12440
12451
|
...cloudProvider?.browserProfile === void 0 ? {} : { browserProfile: cloudProvider.browserProfile }
|
|
12441
12452
|
};
|
|
12442
12453
|
}
|
|
12443
12454
|
function requireCloudAppBaseUrl(cloudConfig) {
|
|
12444
|
-
const appBaseUrl = cloudConfig.appBaseUrl;
|
|
12445
|
-
if (
|
|
12455
|
+
const appBaseUrl = normalizeOptionalCloudConfigValue(cloudConfig.appBaseUrl);
|
|
12456
|
+
if (appBaseUrl === void 0) {
|
|
12446
12457
|
throw new Error(
|
|
12447
12458
|
'record with provider=cloud requires OPENSTEER_CLOUD_APP_BASE_URL or "--cloud-app-base-url".'
|
|
12448
12459
|
);
|
|
12449
12460
|
}
|
|
12450
|
-
return appBaseUrl
|
|
12461
|
+
return appBaseUrl;
|
|
12462
|
+
}
|
|
12463
|
+
function normalizeOptionalCloudConfigValue(value) {
|
|
12464
|
+
if (typeof value !== "string") {
|
|
12465
|
+
return void 0;
|
|
12466
|
+
}
|
|
12467
|
+
const normalized = value.trim().replace(/\/+$/, "");
|
|
12468
|
+
return normalized.length === 0 ? void 0 : normalized;
|
|
12451
12469
|
}
|
|
12470
|
+
var DEFAULT_OPENSTEER_CLOUD_BASE_URL;
|
|
12452
12471
|
var init_config2 = __esm({
|
|
12453
12472
|
"src/cloud/config.ts"() {
|
|
12454
12473
|
init_config();
|
|
12474
|
+
DEFAULT_OPENSTEER_CLOUD_BASE_URL = "https://api.opensteer.com";
|
|
12455
12475
|
}
|
|
12456
12476
|
});
|
|
12457
12477
|
|
|
@@ -12461,7 +12481,7 @@ var init_package = __esm({
|
|
|
12461
12481
|
"../runtime-core/package.json"() {
|
|
12462
12482
|
package_default2 = {
|
|
12463
12483
|
name: "@opensteer/runtime-core",
|
|
12464
|
-
version: "0.2.
|
|
12484
|
+
version: "0.2.7",
|
|
12465
12485
|
description: "Shared semantic runtime for Opensteer local and cloud execution.",
|
|
12466
12486
|
license: "MIT",
|
|
12467
12487
|
type: "module",
|
|
@@ -13332,7 +13352,9 @@ function resolveExtractedValueInContext(normalizedValue, options) {
|
|
|
13332
13352
|
function stripPositionClauses(nodes) {
|
|
13333
13353
|
return (nodes || []).map((node) => ({
|
|
13334
13354
|
...node,
|
|
13335
|
-
match: (node.match || []).filter(
|
|
13355
|
+
match: (node.match || []).filter(
|
|
13356
|
+
(clause) => clause.kind !== "position" && clause.kind !== "text"
|
|
13357
|
+
)
|
|
13336
13358
|
}));
|
|
13337
13359
|
}
|
|
13338
13360
|
function dedupeSelectors(selectors) {
|
|
@@ -15641,7 +15663,9 @@ var init_runtime = __esm({
|
|
|
15641
15663
|
`Unable to resolve structural anchor "${buildPathSelectorHint(anchor)}" in the current session`
|
|
15642
15664
|
);
|
|
15643
15665
|
}
|
|
15644
|
-
const replayPath = await this.tryBuildPathFromNode(context.snapshot, target.node, {
|
|
15666
|
+
const replayPath = await this.tryBuildPathFromNode(context.snapshot, target.node, {
|
|
15667
|
+
enableTextMatch: true
|
|
15668
|
+
});
|
|
15645
15669
|
return this.createResolvedTarget(source, context.snapshot, target.node, anchor, {
|
|
15646
15670
|
...persist === void 0 ? {} : { persist },
|
|
15647
15671
|
...replayPath === void 0 ? {} : { replayPath }
|
|
@@ -23269,7 +23293,10 @@ var init_runtime3 = __esm({
|
|
|
23269
23293
|
sessionRef;
|
|
23270
23294
|
pageRef;
|
|
23271
23295
|
runId;
|
|
23272
|
-
|
|
23296
|
+
observationSessions = /* @__PURE__ */ new Map();
|
|
23297
|
+
openingObservationSessions = /* @__PURE__ */ new Map();
|
|
23298
|
+
openedObservationSessions = /* @__PURE__ */ new Set();
|
|
23299
|
+
observationSessionStorage = new async_hooks.AsyncLocalStorage();
|
|
23273
23300
|
operationEventStorage = new async_hooks.AsyncLocalStorage();
|
|
23274
23301
|
pendingOperationEventCaptures = [];
|
|
23275
23302
|
ownsEngine = false;
|
|
@@ -23321,18 +23348,26 @@ var init_runtime3 = __esm({
|
|
|
23321
23348
|
}
|
|
23322
23349
|
async setObservabilityConfig(input) {
|
|
23323
23350
|
this.observationConfig = normalizeObservabilityConfig(input);
|
|
23324
|
-
|
|
23325
|
-
if (observationSessionId === void 0) {
|
|
23326
|
-
return this.observationConfig;
|
|
23327
|
-
}
|
|
23328
|
-
const sink = this.injectedObservationSink ?? (await this.ensureRoot()).observations;
|
|
23329
|
-
this.observations = await sink.openSession({
|
|
23330
|
-
sessionId: observationSessionId,
|
|
23331
|
-
openedAt: Date.now(),
|
|
23332
|
-
config: this.observationConfig
|
|
23333
|
-
});
|
|
23351
|
+
await this.ensureConfiguredObservationSession();
|
|
23334
23352
|
return this.observationConfig;
|
|
23335
23353
|
}
|
|
23354
|
+
async withObservationSessionId(sessionId, task) {
|
|
23355
|
+
return await this.observationSessionStorage.run(
|
|
23356
|
+
{
|
|
23357
|
+
mode: "session",
|
|
23358
|
+
sessionId: normalizeNonEmptyString("sessionId", sessionId)
|
|
23359
|
+
},
|
|
23360
|
+
task
|
|
23361
|
+
);
|
|
23362
|
+
}
|
|
23363
|
+
async withoutObservationSession(task) {
|
|
23364
|
+
return await this.observationSessionStorage.run(
|
|
23365
|
+
{
|
|
23366
|
+
mode: "disabled"
|
|
23367
|
+
},
|
|
23368
|
+
task
|
|
23369
|
+
);
|
|
23370
|
+
}
|
|
23336
23371
|
async open(input = {}, options = {}) {
|
|
23337
23372
|
assertValidSemanticOperationInput("session.open", input);
|
|
23338
23373
|
if (input.workspace !== void 0 && normalizeNamespace2(input.workspace) !== this.workspace) {
|
|
@@ -26776,7 +26811,7 @@ var init_runtime3 = __esm({
|
|
|
26776
26811
|
}
|
|
26777
26812
|
async resetRuntimeState(options) {
|
|
26778
26813
|
const engine = this.engine;
|
|
26779
|
-
const
|
|
26814
|
+
const observationSessions = [...this.openedObservationSessions];
|
|
26780
26815
|
this.networkHistory.clear();
|
|
26781
26816
|
this.sessionRef = void 0;
|
|
26782
26817
|
this.pageRef = void 0;
|
|
@@ -26785,9 +26820,15 @@ var init_runtime3 = __esm({
|
|
|
26785
26820
|
this.computer = void 0;
|
|
26786
26821
|
this.extractionDescriptors = void 0;
|
|
26787
26822
|
this.engine = void 0;
|
|
26788
|
-
this.
|
|
26823
|
+
this.observationSessions.clear();
|
|
26824
|
+
this.openingObservationSessions.clear();
|
|
26825
|
+
this.openedObservationSessions.clear();
|
|
26789
26826
|
this.pendingOperationEventCaptures.length = 0;
|
|
26790
|
-
await
|
|
26827
|
+
await Promise.allSettled(
|
|
26828
|
+
observationSessions.map(
|
|
26829
|
+
(observationSession) => observationSession.close("runtime_reset").catch(() => void 0)
|
|
26830
|
+
)
|
|
26831
|
+
);
|
|
26791
26832
|
if (options.disposeEngine && this.ownsEngine && engine?.dispose) {
|
|
26792
26833
|
await engine.dispose();
|
|
26793
26834
|
}
|
|
@@ -26797,23 +26838,64 @@ var init_runtime3 = __esm({
|
|
|
26797
26838
|
if (this.observationConfig.profile === "off") {
|
|
26798
26839
|
return void 0;
|
|
26799
26840
|
}
|
|
26800
|
-
|
|
26801
|
-
|
|
26841
|
+
const observationSessionId = this.resolveObservationSessionId();
|
|
26842
|
+
if (observationSessionId === void 0) {
|
|
26843
|
+
return void 0;
|
|
26844
|
+
}
|
|
26845
|
+
const existingObservationSession = this.observationSessions.get(observationSessionId);
|
|
26846
|
+
if (existingObservationSession !== void 0) {
|
|
26847
|
+
return existingObservationSession;
|
|
26848
|
+
}
|
|
26849
|
+
const openingObservationSession = this.openingObservationSessions.get(observationSessionId);
|
|
26850
|
+
if (openingObservationSession !== void 0) {
|
|
26851
|
+
return await openingObservationSession;
|
|
26852
|
+
}
|
|
26853
|
+
const openObservationSessionTask = this.openObservationSession(observationSessionId).finally(
|
|
26854
|
+
() => {
|
|
26855
|
+
this.openingObservationSessions.delete(observationSessionId);
|
|
26856
|
+
}
|
|
26857
|
+
);
|
|
26858
|
+
this.openingObservationSessions.set(observationSessionId, openObservationSessionTask);
|
|
26859
|
+
return await openObservationSessionTask;
|
|
26860
|
+
}
|
|
26861
|
+
async ensureConfiguredObservationSession() {
|
|
26862
|
+
if (this.observationConfig.profile === "off") {
|
|
26863
|
+
return void 0;
|
|
26802
26864
|
}
|
|
26803
26865
|
const observationSessionId = this.resolveObservationSessionId();
|
|
26804
26866
|
if (observationSessionId === void 0) {
|
|
26805
26867
|
return void 0;
|
|
26806
26868
|
}
|
|
26869
|
+
const hadObservationSession = this.observationSessions.has(observationSessionId) || this.openingObservationSessions.has(observationSessionId);
|
|
26870
|
+
const observationSession = await this.ensureObservationSession();
|
|
26871
|
+
if (observationSession !== void 0 && hadObservationSession) {
|
|
26872
|
+
await observationSession.configure?.({
|
|
26873
|
+
config: this.observationConfig,
|
|
26874
|
+
updatedAt: Date.now()
|
|
26875
|
+
});
|
|
26876
|
+
}
|
|
26877
|
+
return observationSession;
|
|
26878
|
+
}
|
|
26879
|
+
resolveObservationSessionId() {
|
|
26880
|
+
const scopedSession = this.observationSessionStorage.getStore();
|
|
26881
|
+
if (scopedSession?.mode === "session") {
|
|
26882
|
+
return scopedSession.sessionId;
|
|
26883
|
+
}
|
|
26884
|
+
if (scopedSession?.mode === "disabled") {
|
|
26885
|
+
return void 0;
|
|
26886
|
+
}
|
|
26887
|
+
return this.observationSessionId ?? this.sessionRef;
|
|
26888
|
+
}
|
|
26889
|
+
async openObservationSession(sessionId) {
|
|
26807
26890
|
const sink = this.injectedObservationSink ?? (await this.ensureRoot()).observations;
|
|
26808
|
-
|
|
26809
|
-
sessionId
|
|
26891
|
+
const observationSession = await sink.openSession({
|
|
26892
|
+
sessionId,
|
|
26810
26893
|
openedAt: Date.now(),
|
|
26811
26894
|
config: this.observationConfig
|
|
26812
26895
|
});
|
|
26813
|
-
|
|
26814
|
-
|
|
26815
|
-
|
|
26816
|
-
return this.observationSessionId ?? this.sessionRef;
|
|
26896
|
+
this.observationSessions.set(sessionId, observationSession);
|
|
26897
|
+
this.openedObservationSessions.add(observationSession);
|
|
26898
|
+
return observationSession;
|
|
26817
26899
|
}
|
|
26818
26900
|
runWithOperationTimeout(operation, callback, options = {}) {
|
|
26819
26901
|
const timeoutPolicy = options.timeoutMs === void 0 ? this.policy.timeout : {
|
|
@@ -28981,26 +29063,35 @@ function renderOpensteerBootstrap(replayTarget) {
|
|
|
28981
29063
|
`const opensteer = new Opensteer({`,
|
|
28982
29064
|
` provider: {`,
|
|
28983
29065
|
` mode: "cloud",`,
|
|
28984
|
-
` baseUrl: requireEnv(${JSON.stringify(replayTarget.baseUrlEnvVar ?? "OPENSTEER_BASE_URL")}),`,
|
|
28985
29066
|
` apiKey: requireEnv(${JSON.stringify(replayTarget.apiKeyEnvVar ?? "OPENSTEER_API_KEY")}),`,
|
|
29067
|
+
...renderCloudBaseUrl(replayTarget),
|
|
28986
29068
|
...renderCloudBrowserProfile(replayTarget),
|
|
28987
29069
|
` },`,
|
|
28988
29070
|
`});`
|
|
28989
29071
|
];
|
|
28990
29072
|
}
|
|
28991
29073
|
function renderRequireEnvHelper(replayTarget) {
|
|
28992
|
-
const baseUrlEnvVar = replayTarget.baseUrlEnvVar ?? "OPENSTEER_BASE_URL";
|
|
28993
29074
|
const apiKeyEnvVar = replayTarget.apiKeyEnvVar ?? "OPENSTEER_API_KEY";
|
|
29075
|
+
const requiredEnvVars = [
|
|
29076
|
+
...replayTarget.baseUrlEnvVar === void 0 ? [] : [replayTarget.baseUrlEnvVar],
|
|
29077
|
+
apiKeyEnvVar
|
|
29078
|
+
];
|
|
28994
29079
|
return [
|
|
28995
29080
|
`function requireEnv(name: string): string {`,
|
|
28996
29081
|
` const value = process.env[name];`,
|
|
28997
29082
|
` if (typeof value === "string" && value.trim().length > 0) {`,
|
|
28998
29083
|
` return value;`,
|
|
28999
29084
|
` }`,
|
|
29000
|
-
` throw new Error(\`Missing environment variable \${name}. Set ${
|
|
29085
|
+
` throw new Error(\`Missing environment variable \${name}. Set ${requiredEnvVars.join(" and ")} before replaying this recording.\`);`,
|
|
29001
29086
|
`}`
|
|
29002
29087
|
].join("\n");
|
|
29003
29088
|
}
|
|
29089
|
+
function renderCloudBaseUrl(replayTarget) {
|
|
29090
|
+
if (replayTarget.baseUrlEnvVar === void 0) {
|
|
29091
|
+
return [];
|
|
29092
|
+
}
|
|
29093
|
+
return [` baseUrl: requireEnv(${JSON.stringify(replayTarget.baseUrlEnvVar)}),`];
|
|
29094
|
+
}
|
|
29004
29095
|
function renderCloudBrowserProfile(replayTarget) {
|
|
29005
29096
|
if (replayTarget.browserProfileId === void 0) {
|
|
29006
29097
|
return [];
|
|
@@ -30263,6 +30354,41 @@ var init_session_proxy = __esm({
|
|
|
30263
30354
|
};
|
|
30264
30355
|
}
|
|
30265
30356
|
});
|
|
30357
|
+
async function persistLocalActivePageHint(runtime, rootPath) {
|
|
30358
|
+
try {
|
|
30359
|
+
await syncPersistedLocalActivePageHint(runtime, rootPath);
|
|
30360
|
+
} catch {
|
|
30361
|
+
}
|
|
30362
|
+
}
|
|
30363
|
+
async function syncPersistedLocalActivePageHint(runtime, rootPath) {
|
|
30364
|
+
const record = await readPersistedLocalBrowserSessionRecord(rootPath);
|
|
30365
|
+
if (!record) {
|
|
30366
|
+
return;
|
|
30367
|
+
}
|
|
30368
|
+
const sessionInfo = await runtime.info();
|
|
30369
|
+
const activePageRef = sessionInfo.activePageRef;
|
|
30370
|
+
let activePageUrl;
|
|
30371
|
+
let activePageTitle;
|
|
30372
|
+
if (activePageRef !== void 0) {
|
|
30373
|
+
const pages = await runtime.listPages();
|
|
30374
|
+
const activePage = pages.pages.find((page) => page.pageRef === activePageRef);
|
|
30375
|
+
activePageUrl = activePage?.url;
|
|
30376
|
+
activePageTitle = activePage?.title;
|
|
30377
|
+
}
|
|
30378
|
+
const {
|
|
30379
|
+
activePageRef: _previousActivePageRef,
|
|
30380
|
+
activePageUrl: _previousActivePageUrl,
|
|
30381
|
+
activePageTitle: _previousActivePageTitle,
|
|
30382
|
+
...restRecord
|
|
30383
|
+
} = record;
|
|
30384
|
+
await writePersistedSessionRecord(rootPath, {
|
|
30385
|
+
...restRecord,
|
|
30386
|
+
updatedAt: Date.now(),
|
|
30387
|
+
...activePageRef === void 0 ? {} : { activePageRef },
|
|
30388
|
+
...activePageUrl === void 0 ? {} : { activePageUrl },
|
|
30389
|
+
...activePageTitle === void 0 ? {} : { activePageTitle }
|
|
30390
|
+
});
|
|
30391
|
+
}
|
|
30266
30392
|
function buildSharedRuntimeOptions(input) {
|
|
30267
30393
|
const ownership = resolveOwnership(input.browser);
|
|
30268
30394
|
const engineFactory = input.engineFactory ?? ((factoryOptions) => new OpensteerBrowserManager({
|
|
@@ -30309,14 +30435,37 @@ function normalizeWorkspace2(workspace) {
|
|
|
30309
30435
|
function resolveOwnership(browser) {
|
|
30310
30436
|
return typeof browser === "object" && browser.mode === "attach" ? "attached" : "owned";
|
|
30311
30437
|
}
|
|
30312
|
-
var OpensteerRuntime;
|
|
30438
|
+
var LocalActivePageHintRuntime, OpensteerRuntime;
|
|
30313
30439
|
var init_runtime4 = __esm({
|
|
30314
30440
|
"src/sdk/runtime.ts"() {
|
|
30315
30441
|
init_src3();
|
|
30316
30442
|
init_browser_manager();
|
|
30317
30443
|
init_engine_selection2();
|
|
30444
|
+
init_live_session();
|
|
30318
30445
|
init_root2();
|
|
30319
|
-
|
|
30446
|
+
LocalActivePageHintRuntime = class extends OpensteerSessionRuntime {
|
|
30447
|
+
async completeWithLocalActivePageHint(operation) {
|
|
30448
|
+
const output = await operation();
|
|
30449
|
+
await persistLocalActivePageHint(this, this.rootPath);
|
|
30450
|
+
return output;
|
|
30451
|
+
}
|
|
30452
|
+
async open(input = {}, options = {}) {
|
|
30453
|
+
return this.completeWithLocalActivePageHint(() => super.open(input, options));
|
|
30454
|
+
}
|
|
30455
|
+
async newPage(input = {}, options = {}) {
|
|
30456
|
+
return this.completeWithLocalActivePageHint(() => super.newPage(input, options));
|
|
30457
|
+
}
|
|
30458
|
+
async activatePage(input, options = {}) {
|
|
30459
|
+
return this.completeWithLocalActivePageHint(() => super.activatePage(input, options));
|
|
30460
|
+
}
|
|
30461
|
+
async closePage(input = {}, options = {}) {
|
|
30462
|
+
return this.completeWithLocalActivePageHint(() => super.closePage(input, options));
|
|
30463
|
+
}
|
|
30464
|
+
async goto(input, options = {}) {
|
|
30465
|
+
return this.completeWithLocalActivePageHint(() => super.goto(input, options));
|
|
30466
|
+
}
|
|
30467
|
+
};
|
|
30468
|
+
OpensteerRuntime = class extends LocalActivePageHintRuntime {
|
|
30320
30469
|
constructor(options = {}) {
|
|
30321
30470
|
const publicWorkspace = normalizeWorkspace2(options.workspace);
|
|
30322
30471
|
const rootPath = options.rootPath ?? (publicWorkspace === void 0 ? path10__default.default.resolve(options.rootDir ?? process.cwd(), ".opensteer", "temporary", crypto.randomUUID()) : resolveFilesystemWorkspacePath({
|
|
@@ -31038,7 +31187,7 @@ var init_opensteer = __esm({
|
|
|
31038
31187
|
|
|
31039
31188
|
// package.json
|
|
31040
31189
|
var package_default = {
|
|
31041
|
-
version: "0.9.
|
|
31190
|
+
version: "0.9.8"};
|
|
31042
31191
|
|
|
31043
31192
|
// src/cli/bin.ts
|
|
31044
31193
|
init_browser_manager();
|
|
@@ -31693,14 +31842,22 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31693
31842
|
return parsed.rest[0] === void 0 ? {} : { mode: parsed.rest[0] };
|
|
31694
31843
|
case "page.evaluate":
|
|
31695
31844
|
if (parsed.rest[0] === void 0) {
|
|
31696
|
-
throw new CliError(
|
|
31845
|
+
throw new CliError(
|
|
31846
|
+
"missing_arguments",
|
|
31847
|
+
"evaluate requires a script.",
|
|
31848
|
+
CLI_USAGE_HINTS[operation]
|
|
31849
|
+
);
|
|
31697
31850
|
}
|
|
31698
31851
|
return {
|
|
31699
31852
|
script: joinRest(parsed.rest, 0)
|
|
31700
31853
|
};
|
|
31701
31854
|
case "page.add-init-script":
|
|
31702
31855
|
if (parsed.rest[0] === void 0) {
|
|
31703
|
-
throw new CliError(
|
|
31856
|
+
throw new CliError(
|
|
31857
|
+
"missing_arguments",
|
|
31858
|
+
"init-script requires a script.",
|
|
31859
|
+
CLI_USAGE_HINTS[operation]
|
|
31860
|
+
);
|
|
31704
31861
|
}
|
|
31705
31862
|
return {
|
|
31706
31863
|
script: joinRest(parsed.rest, 0)
|
|
@@ -31716,7 +31873,11 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31716
31873
|
return buildElementTargetInput(parsed, "hover");
|
|
31717
31874
|
case "dom.input": {
|
|
31718
31875
|
if (parsed.rest[1] === void 0) {
|
|
31719
|
-
throw new CliError(
|
|
31876
|
+
throw new CliError(
|
|
31877
|
+
"missing_arguments",
|
|
31878
|
+
"input requires an element number and text.",
|
|
31879
|
+
CLI_USAGE_HINTS[operation]
|
|
31880
|
+
);
|
|
31720
31881
|
}
|
|
31721
31882
|
const pressEnter = readOptionalBoolean(parsed.rawOptions, "press-enter");
|
|
31722
31883
|
return {
|
|
@@ -31747,7 +31908,11 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31747
31908
|
}
|
|
31748
31909
|
case "dom.extract": {
|
|
31749
31910
|
if (parsed.rest[0] === void 0) {
|
|
31750
|
-
throw new CliError(
|
|
31911
|
+
throw new CliError(
|
|
31912
|
+
"missing_arguments",
|
|
31913
|
+
"extract requires a template.",
|
|
31914
|
+
CLI_USAGE_HINTS[operation]
|
|
31915
|
+
);
|
|
31751
31916
|
}
|
|
31752
31917
|
const persist = readPersistKey(parsed, "extract");
|
|
31753
31918
|
return {
|
|
@@ -31783,7 +31948,11 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31783
31948
|
}
|
|
31784
31949
|
case "network.detail": {
|
|
31785
31950
|
if (parsed.rest[0] === void 0) {
|
|
31786
|
-
throw new CliError(
|
|
31951
|
+
throw new CliError(
|
|
31952
|
+
"missing_arguments",
|
|
31953
|
+
"network detail requires a record id.",
|
|
31954
|
+
CLI_USAGE_HINTS[operation]
|
|
31955
|
+
);
|
|
31787
31956
|
}
|
|
31788
31957
|
const probeFlag = readOptionalBoolean(parsed.rawOptions, "probe");
|
|
31789
31958
|
return {
|
|
@@ -31794,7 +31963,11 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31794
31963
|
case "session.fetch": {
|
|
31795
31964
|
const url = parsed.rest[0];
|
|
31796
31965
|
if (url === void 0) {
|
|
31797
|
-
throw new CliError(
|
|
31966
|
+
throw new CliError(
|
|
31967
|
+
"missing_arguments",
|
|
31968
|
+
"fetch requires a URL.",
|
|
31969
|
+
CLI_USAGE_HINTS[operation]
|
|
31970
|
+
);
|
|
31798
31971
|
}
|
|
31799
31972
|
const bodyJson = readJsonValue(parsed.rawOptions, "body");
|
|
31800
31973
|
const bodyText = readSingle(parsed.rawOptions, "body-text");
|
|
@@ -31833,7 +32006,11 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31833
32006
|
const siteKey = readSingle(parsed.rawOptions, "site-key");
|
|
31834
32007
|
const pageUrl = readSingle(parsed.rawOptions, "page-url");
|
|
31835
32008
|
if (provider === void 0 || apiKey === void 0) {
|
|
31836
|
-
throw new CliError(
|
|
32009
|
+
throw new CliError(
|
|
32010
|
+
"missing_arguments",
|
|
32011
|
+
'captcha solve requires "--provider" and "--api-key".',
|
|
32012
|
+
CLI_USAGE_HINTS[operation]
|
|
32013
|
+
);
|
|
31837
32014
|
}
|
|
31838
32015
|
return {
|
|
31839
32016
|
provider: readCaptchaProvider(provider),
|
|
@@ -31863,7 +32040,11 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31863
32040
|
case "scripts.beautify":
|
|
31864
32041
|
case "scripts.deobfuscate": {
|
|
31865
32042
|
if (parsed.rest[0] === void 0) {
|
|
31866
|
-
throw new CliError(
|
|
32043
|
+
throw new CliError(
|
|
32044
|
+
"missing_arguments",
|
|
32045
|
+
`${parsed.command.join(" ")} requires an artifact id.`,
|
|
32046
|
+
CLI_USAGE_HINTS[operation]
|
|
32047
|
+
);
|
|
31867
32048
|
}
|
|
31868
32049
|
const persist = readOptionalBoolean(parsed.rawOptions, "persist");
|
|
31869
32050
|
return {
|
|
@@ -31873,7 +32054,11 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31873
32054
|
}
|
|
31874
32055
|
case "scripts.sandbox":
|
|
31875
32056
|
if (parsed.rest[0] === void 0) {
|
|
31876
|
-
throw new CliError(
|
|
32057
|
+
throw new CliError(
|
|
32058
|
+
"missing_arguments",
|
|
32059
|
+
"scripts sandbox requires an artifact id.",
|
|
32060
|
+
CLI_USAGE_HINTS[operation]
|
|
32061
|
+
);
|
|
31877
32062
|
}
|
|
31878
32063
|
{
|
|
31879
32064
|
const fidelity = readSingle(parsed.rawOptions, "fidelity");
|
|
@@ -31922,14 +32107,22 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31922
32107
|
case "interaction.get":
|
|
31923
32108
|
case "interaction.replay":
|
|
31924
32109
|
if (parsed.rest[0] === void 0) {
|
|
31925
|
-
throw new CliError(
|
|
32110
|
+
throw new CliError(
|
|
32111
|
+
"missing_arguments",
|
|
32112
|
+
`${parsed.command.join(" ")} requires a trace id.`,
|
|
32113
|
+
CLI_USAGE_HINTS[operation]
|
|
32114
|
+
);
|
|
31926
32115
|
}
|
|
31927
32116
|
return {
|
|
31928
32117
|
traceId: parsed.rest[0]
|
|
31929
32118
|
};
|
|
31930
32119
|
case "interaction.diff":
|
|
31931
32120
|
if (parsed.rest[0] === void 0 || parsed.rest[1] === void 0) {
|
|
31932
|
-
throw new CliError(
|
|
32121
|
+
throw new CliError(
|
|
32122
|
+
"missing_arguments",
|
|
32123
|
+
"interaction diff requires two trace ids.",
|
|
32124
|
+
CLI_USAGE_HINTS[operation]
|
|
32125
|
+
);
|
|
31933
32126
|
}
|
|
31934
32127
|
return {
|
|
31935
32128
|
leftTraceId: parsed.rest[0],
|
|
@@ -31937,7 +32130,11 @@ async function buildOperationInput(operation, parsed, runtime) {
|
|
|
31937
32130
|
};
|
|
31938
32131
|
case "artifact.read":
|
|
31939
32132
|
if (parsed.rest[0] === void 0) {
|
|
31940
|
-
throw new CliError(
|
|
32133
|
+
throw new CliError(
|
|
32134
|
+
"missing_arguments",
|
|
32135
|
+
"artifact read requires an artifact id.",
|
|
32136
|
+
CLI_USAGE_HINTS[operation]
|
|
32137
|
+
);
|
|
31941
32138
|
}
|
|
31942
32139
|
return {
|
|
31943
32140
|
artifactId: parsed.rest[0]
|
|
@@ -32075,7 +32272,10 @@ function buildComputerExecuteInput(parsed) {
|
|
|
32075
32272
|
}
|
|
32076
32273
|
};
|
|
32077
32274
|
default:
|
|
32078
|
-
throw new CliError(
|
|
32275
|
+
throw new CliError(
|
|
32276
|
+
"unknown_command",
|
|
32277
|
+
`Unknown computer command: ${parsed.command.join(" ")}`
|
|
32278
|
+
);
|
|
32079
32279
|
}
|
|
32080
32280
|
}
|
|
32081
32281
|
async function resolvePageRefByIndex(runtime, index) {
|
|
@@ -32105,7 +32305,10 @@ function readRequiredNumber(value, message) {
|
|
|
32105
32305
|
}
|
|
32106
32306
|
function readSingleDirection(value) {
|
|
32107
32307
|
if (value === void 0 || !SCROLL_DIRECTIONS.has(value)) {
|
|
32108
|
-
throw new CliError(
|
|
32308
|
+
throw new CliError(
|
|
32309
|
+
"missing_arguments",
|
|
32310
|
+
"scroll requires a direction: up, down, left, or right."
|
|
32311
|
+
);
|
|
32109
32312
|
}
|
|
32110
32313
|
return value;
|
|
32111
32314
|
}
|
|
@@ -32132,13 +32335,19 @@ function readCaptchaProvider(value) {
|
|
|
32132
32335
|
}
|
|
32133
32336
|
function readCaptchaType(value) {
|
|
32134
32337
|
if (value === void 0 || !CAPTCHA_TYPES.has(value)) {
|
|
32135
|
-
throw new CliError(
|
|
32338
|
+
throw new CliError(
|
|
32339
|
+
"invalid_value",
|
|
32340
|
+
'Expected "--type" to be one of: recaptcha-v2, hcaptcha, turnstile.'
|
|
32341
|
+
);
|
|
32136
32342
|
}
|
|
32137
32343
|
return value;
|
|
32138
32344
|
}
|
|
32139
32345
|
function readSandboxFidelity(value) {
|
|
32140
32346
|
if (value === void 0 || !SANDBOX_FIDELITIES.has(value)) {
|
|
32141
|
-
throw new CliError(
|
|
32347
|
+
throw new CliError(
|
|
32348
|
+
"invalid_value",
|
|
32349
|
+
'Expected "--fidelity" to be one of: minimal, standard, full.'
|
|
32350
|
+
);
|
|
32142
32351
|
}
|
|
32143
32352
|
return value;
|
|
32144
32353
|
}
|
|
@@ -32161,7 +32370,10 @@ function readKeyModifiers(value) {
|
|
|
32161
32370
|
}
|
|
32162
32371
|
for (const modifier of modifiers) {
|
|
32163
32372
|
if (!KEY_MODIFIERS.has(modifier)) {
|
|
32164
|
-
throw new CliError(
|
|
32373
|
+
throw new CliError(
|
|
32374
|
+
"invalid_value",
|
|
32375
|
+
'Expected "--modifiers" to contain only: Shift, Control, Alt, Meta.'
|
|
32376
|
+
);
|
|
32165
32377
|
}
|
|
32166
32378
|
}
|
|
32167
32379
|
return [...new Set(modifiers)];
|
|
@@ -33743,6 +33955,172 @@ init_process_owner();
|
|
|
33743
33955
|
init_service_state();
|
|
33744
33956
|
init_service_state();
|
|
33745
33957
|
|
|
33958
|
+
// src/local-view/browser-target-order.ts
|
|
33959
|
+
async function readPageTargetId(page) {
|
|
33960
|
+
const cdp = await page.context().newCDPSession(page);
|
|
33961
|
+
try {
|
|
33962
|
+
const result = await cdp.send("Target.getTargetInfo");
|
|
33963
|
+
const targetId = result?.targetInfo?.targetId;
|
|
33964
|
+
return typeof targetId === "string" && targetId.length > 0 ? targetId : null;
|
|
33965
|
+
} finally {
|
|
33966
|
+
await cdp.detach().catch(() => void 0);
|
|
33967
|
+
}
|
|
33968
|
+
}
|
|
33969
|
+
async function readBrowserPageTargetOrder(browserContext) {
|
|
33970
|
+
const browser = browserContext.browser();
|
|
33971
|
+
if (!browser || !hasBrowserCdpSession(browser)) {
|
|
33972
|
+
return [];
|
|
33973
|
+
}
|
|
33974
|
+
const cdp = await browser.newBrowserCDPSession();
|
|
33975
|
+
try {
|
|
33976
|
+
const result = await cdp.send("Target.getTargets");
|
|
33977
|
+
return normalizeBrowserPageTargetOrder(result?.targetInfos ?? []);
|
|
33978
|
+
} catch {
|
|
33979
|
+
return [];
|
|
33980
|
+
} finally {
|
|
33981
|
+
await cdp.detach().catch(() => void 0);
|
|
33982
|
+
}
|
|
33983
|
+
}
|
|
33984
|
+
async function orderPagesByBrowserTargetOrder(browserContext, pages) {
|
|
33985
|
+
if (pages.length < 2) {
|
|
33986
|
+
return pages;
|
|
33987
|
+
}
|
|
33988
|
+
const orderedTargetIds = await readBrowserPageTargetOrder(browserContext);
|
|
33989
|
+
if (orderedTargetIds.length === 0) {
|
|
33990
|
+
return pages;
|
|
33991
|
+
}
|
|
33992
|
+
const rankByTargetId = new Map(orderedTargetIds.map((targetId, index) => [targetId, index]));
|
|
33993
|
+
const targetIds = await Promise.all(
|
|
33994
|
+
pages.map((page) => readPageTargetId(page).catch(() => null))
|
|
33995
|
+
);
|
|
33996
|
+
return pages.map((page, index) => {
|
|
33997
|
+
const targetId = targetIds[index] ?? void 0;
|
|
33998
|
+
return {
|
|
33999
|
+
page,
|
|
34000
|
+
index,
|
|
34001
|
+
rank: targetId === void 0 ? void 0 : rankByTargetId.get(targetId)
|
|
34002
|
+
};
|
|
34003
|
+
}).sort((left, right) => {
|
|
34004
|
+
if (left.rank !== void 0 && right.rank !== void 0) {
|
|
34005
|
+
return left.rank - right.rank;
|
|
34006
|
+
}
|
|
34007
|
+
if (left.rank !== void 0) {
|
|
34008
|
+
return -1;
|
|
34009
|
+
}
|
|
34010
|
+
if (right.rank !== void 0) {
|
|
34011
|
+
return 1;
|
|
34012
|
+
}
|
|
34013
|
+
return left.index - right.index;
|
|
34014
|
+
}).map((entry) => entry.page);
|
|
34015
|
+
}
|
|
34016
|
+
function hasBrowserCdpSession(browser) {
|
|
34017
|
+
return typeof browser.newBrowserCDPSession === "function";
|
|
34018
|
+
}
|
|
34019
|
+
function normalizeBrowserPageTargetOrder(targetInfos) {
|
|
34020
|
+
const reversedPageInfos = [];
|
|
34021
|
+
for (const targetInfo of targetInfos) {
|
|
34022
|
+
if (targetInfo.type !== "page") {
|
|
34023
|
+
continue;
|
|
34024
|
+
}
|
|
34025
|
+
const targetId = typeof targetInfo.targetId === "string" && targetInfo.targetId.length > 0 ? targetInfo.targetId : void 0;
|
|
34026
|
+
if (targetId === void 0) {
|
|
34027
|
+
continue;
|
|
34028
|
+
}
|
|
34029
|
+
reversedPageInfos.push({
|
|
34030
|
+
targetId,
|
|
34031
|
+
openerId: typeof targetInfo.openerId === "string" && targetInfo.openerId.length > 0 ? targetInfo.openerId : void 0
|
|
34032
|
+
});
|
|
34033
|
+
}
|
|
34034
|
+
reversedPageInfos.reverse();
|
|
34035
|
+
const rawTargetInfoById = new Map(
|
|
34036
|
+
reversedPageInfos.map((targetInfo) => [targetInfo.targetId, targetInfo])
|
|
34037
|
+
);
|
|
34038
|
+
const targetInfoById = new Map(
|
|
34039
|
+
reversedPageInfos.map(
|
|
34040
|
+
(targetInfo) => [
|
|
34041
|
+
targetInfo.targetId,
|
|
34042
|
+
{
|
|
34043
|
+
...targetInfo,
|
|
34044
|
+
openerId: resolveAcyclicOpenerId(targetInfo.targetId, rawTargetInfoById)
|
|
34045
|
+
}
|
|
34046
|
+
]
|
|
34047
|
+
)
|
|
34048
|
+
);
|
|
34049
|
+
const orderedTargetIds = [];
|
|
34050
|
+
const placed = /* @__PURE__ */ new Set();
|
|
34051
|
+
const placeTarget = (targetId) => {
|
|
34052
|
+
if (placed.has(targetId)) {
|
|
34053
|
+
return;
|
|
34054
|
+
}
|
|
34055
|
+
const targetInfo = targetInfoById.get(targetId);
|
|
34056
|
+
if (!targetInfo) {
|
|
34057
|
+
return;
|
|
34058
|
+
}
|
|
34059
|
+
const openerId = targetInfo.openerId;
|
|
34060
|
+
if (openerId === void 0) {
|
|
34061
|
+
orderedTargetIds.push(targetId);
|
|
34062
|
+
placed.add(targetId);
|
|
34063
|
+
return;
|
|
34064
|
+
}
|
|
34065
|
+
placeTarget(openerId);
|
|
34066
|
+
const openerIndex = orderedTargetIds.indexOf(openerId);
|
|
34067
|
+
const insertionIndex = openerIndex === -1 ? orderedTargetIds.length : findPopupInsertionIndex(orderedTargetIds, openerIndex, openerId, targetInfoById);
|
|
34068
|
+
orderedTargetIds.splice(insertionIndex, 0, targetId);
|
|
34069
|
+
placed.add(targetId);
|
|
34070
|
+
};
|
|
34071
|
+
for (const targetInfo of reversedPageInfos) {
|
|
34072
|
+
placeTarget(targetInfo.targetId);
|
|
34073
|
+
}
|
|
34074
|
+
return orderedTargetIds;
|
|
34075
|
+
}
|
|
34076
|
+
function resolveAcyclicOpenerId(targetId, targetInfoById) {
|
|
34077
|
+
const openerId = targetInfoById.get(targetId)?.openerId;
|
|
34078
|
+
if (openerId === void 0 || !targetInfoById.has(openerId)) {
|
|
34079
|
+
return void 0;
|
|
34080
|
+
}
|
|
34081
|
+
const visitedTargetIds = /* @__PURE__ */ new Set([targetId]);
|
|
34082
|
+
let currentTargetId = openerId;
|
|
34083
|
+
while (currentTargetId !== void 0) {
|
|
34084
|
+
if (visitedTargetIds.has(currentTargetId)) {
|
|
34085
|
+
return void 0;
|
|
34086
|
+
}
|
|
34087
|
+
visitedTargetIds.add(currentTargetId);
|
|
34088
|
+
currentTargetId = targetInfoById.get(currentTargetId)?.openerId;
|
|
34089
|
+
}
|
|
34090
|
+
return openerId;
|
|
34091
|
+
}
|
|
34092
|
+
function findPopupInsertionIndex(orderedTargetIds, openerIndex, openerTargetId, targetInfoById) {
|
|
34093
|
+
let index = openerIndex + 1;
|
|
34094
|
+
while (index < orderedTargetIds.length) {
|
|
34095
|
+
const candidateTargetId = orderedTargetIds[index];
|
|
34096
|
+
if (!candidateTargetId || !isDescendantTarget(candidateTargetId, openerTargetId, targetInfoById)) {
|
|
34097
|
+
break;
|
|
34098
|
+
}
|
|
34099
|
+
index += 1;
|
|
34100
|
+
}
|
|
34101
|
+
return index;
|
|
34102
|
+
}
|
|
34103
|
+
function isDescendantTarget(targetId, ancestorTargetId, targetInfoById) {
|
|
34104
|
+
const visitedTargetIds = /* @__PURE__ */ new Set();
|
|
34105
|
+
let currentTargetId = targetId;
|
|
34106
|
+
while (currentTargetId !== void 0) {
|
|
34107
|
+
if (visitedTargetIds.has(currentTargetId)) {
|
|
34108
|
+
return false;
|
|
34109
|
+
}
|
|
34110
|
+
visitedTargetIds.add(currentTargetId);
|
|
34111
|
+
const currentTargetInfo = targetInfoById.get(currentTargetId);
|
|
34112
|
+
const openerId = currentTargetInfo?.openerId;
|
|
34113
|
+
if (openerId === void 0) {
|
|
34114
|
+
return false;
|
|
34115
|
+
}
|
|
34116
|
+
if (openerId === ancestorTargetId) {
|
|
34117
|
+
return true;
|
|
34118
|
+
}
|
|
34119
|
+
currentTargetId = openerId;
|
|
34120
|
+
}
|
|
34121
|
+
return false;
|
|
34122
|
+
}
|
|
34123
|
+
|
|
33746
34124
|
// src/local-view/tab-state-tracker.ts
|
|
33747
34125
|
var ACTIVATION_INTENT_DISCOVERY_GRACE_MS = 2e3;
|
|
33748
34126
|
var TabStateTracker = class {
|
|
@@ -33758,6 +34136,7 @@ var TabStateTracker = class {
|
|
|
33758
34136
|
boundContextCleanup = null;
|
|
33759
34137
|
constructor(deps) {
|
|
33760
34138
|
this.deps = deps;
|
|
34139
|
+
this.lastActivePage = deps.initialActivePage ?? null;
|
|
33761
34140
|
}
|
|
33762
34141
|
start() {
|
|
33763
34142
|
if (this.running) {
|
|
@@ -33882,7 +34261,7 @@ var TabStateTracker = class {
|
|
|
33882
34261
|
this.updatePolling(pages.length);
|
|
33883
34262
|
const preferredActivePage = this.lastActivePage ?? pages[0] ?? null;
|
|
33884
34263
|
const pageStates = await Promise.all(
|
|
33885
|
-
pages.map(async (page,
|
|
34264
|
+
pages.map(async (page, originalIndex) => {
|
|
33886
34265
|
const metadata = await this.readPageMetadata(page, {
|
|
33887
34266
|
refresh: args.refreshMetadata
|
|
33888
34267
|
});
|
|
@@ -33892,7 +34271,7 @@ var TabStateTracker = class {
|
|
|
33892
34271
|
};
|
|
33893
34272
|
return {
|
|
33894
34273
|
page,
|
|
33895
|
-
|
|
34274
|
+
originalIndex,
|
|
33896
34275
|
targetId: metadata.targetId,
|
|
33897
34276
|
url: page.url(),
|
|
33898
34277
|
title: metadata.title,
|
|
@@ -33901,17 +34280,18 @@ var TabStateTracker = class {
|
|
|
33901
34280
|
};
|
|
33902
34281
|
})
|
|
33903
34282
|
);
|
|
34283
|
+
const orderedPageStates = await this.orderPageStates(pageStates);
|
|
33904
34284
|
const activePage = this.pickActivePage(
|
|
33905
|
-
|
|
34285
|
+
orderedPageStates,
|
|
33906
34286
|
this.lastActivePage,
|
|
33907
34287
|
preferredActivePage,
|
|
33908
|
-
this.resolveIntentPage(
|
|
34288
|
+
this.resolveIntentPage(orderedPageStates)
|
|
33909
34289
|
);
|
|
33910
34290
|
if (activePage && activePage !== this.lastActivePage) {
|
|
33911
34291
|
this.lastActivePage = activePage;
|
|
33912
34292
|
this.deps.onActivePageChanged(activePage);
|
|
33913
34293
|
}
|
|
33914
|
-
const tabs =
|
|
34294
|
+
const tabs = orderedPageStates.map((state) => ({
|
|
33915
34295
|
index: state.index,
|
|
33916
34296
|
...state.targetId === void 0 ? {} : { targetId: state.targetId },
|
|
33917
34297
|
url: state.url,
|
|
@@ -33961,18 +34341,11 @@ var TabStateTracker = class {
|
|
|
33961
34341
|
if (cached) {
|
|
33962
34342
|
return cached;
|
|
33963
34343
|
}
|
|
33964
|
-
const
|
|
33965
|
-
|
|
33966
|
-
|
|
33967
|
-
const targetId = result?.targetInfo?.targetId;
|
|
33968
|
-
if (typeof targetId === "string" && targetId.length > 0) {
|
|
33969
|
-
this.targetIdByPage.set(page, targetId);
|
|
33970
|
-
return targetId;
|
|
33971
|
-
}
|
|
33972
|
-
return null;
|
|
33973
|
-
} finally {
|
|
33974
|
-
await cdp.detach().catch(() => void 0);
|
|
34344
|
+
const targetId = await readPageTargetId(page);
|
|
34345
|
+
if (targetId) {
|
|
34346
|
+
this.targetIdByPage.set(page, targetId);
|
|
33975
34347
|
}
|
|
34348
|
+
return targetId;
|
|
33976
34349
|
}
|
|
33977
34350
|
async readFocusState(page) {
|
|
33978
34351
|
try {
|
|
@@ -34040,6 +34413,33 @@ var TabStateTracker = class {
|
|
|
34040
34413
|
this.deps.runtimeState.clearPageActivationIntent(this.deps.sessionId, intent.targetId);
|
|
34041
34414
|
return { page: matched.page };
|
|
34042
34415
|
}
|
|
34416
|
+
async orderPageStates(pageStates) {
|
|
34417
|
+
if (pageStates.length < 2) {
|
|
34418
|
+
return pageStates.map(({ originalIndex: _originalIndex, ...state }, index) => ({
|
|
34419
|
+
...state,
|
|
34420
|
+
index
|
|
34421
|
+
}));
|
|
34422
|
+
}
|
|
34423
|
+
const orderedTargetIds = await readBrowserPageTargetOrder(this.deps.browserContext);
|
|
34424
|
+
const rankByTargetId = new Map(orderedTargetIds.map((targetId, index) => [targetId, index]));
|
|
34425
|
+
return [...pageStates].sort((left, right) => {
|
|
34426
|
+
const leftRank = left.targetId === void 0 ? void 0 : rankByTargetId.get(left.targetId);
|
|
34427
|
+
const rightRank = right.targetId === void 0 ? void 0 : rankByTargetId.get(right.targetId);
|
|
34428
|
+
if (leftRank !== void 0 && rightRank !== void 0) {
|
|
34429
|
+
return leftRank - rightRank;
|
|
34430
|
+
}
|
|
34431
|
+
if (leftRank !== void 0) {
|
|
34432
|
+
return -1;
|
|
34433
|
+
}
|
|
34434
|
+
if (rightRank !== void 0) {
|
|
34435
|
+
return 1;
|
|
34436
|
+
}
|
|
34437
|
+
return left.originalIndex - right.originalIndex;
|
|
34438
|
+
}).map(({ originalIndex: _originalIndex, ...state }, index) => ({
|
|
34439
|
+
...state,
|
|
34440
|
+
index
|
|
34441
|
+
}));
|
|
34442
|
+
}
|
|
34043
34443
|
};
|
|
34044
34444
|
|
|
34045
34445
|
// src/local-view/view-stream-capture-policy.ts
|
|
@@ -34403,6 +34803,7 @@ var SessionViewStreamProducer = class {
|
|
|
34403
34803
|
sessionId: this.deps.sessionId,
|
|
34404
34804
|
pollMs: TAB_STATE_POLL_MS,
|
|
34405
34805
|
runtimeState: this.deps.runtimeState,
|
|
34806
|
+
initialActivePage: session.page,
|
|
34406
34807
|
onActivePageChanged: (page) => {
|
|
34407
34808
|
this.activePage = page;
|
|
34408
34809
|
void this.queueBindToPage(page).catch(() => void 0);
|
|
@@ -34501,7 +34902,20 @@ var SessionViewStreamProducer = class {
|
|
|
34501
34902
|
if (!context) {
|
|
34502
34903
|
throw new Error("Connected browser did not expose a Chromium browser context.");
|
|
34503
34904
|
}
|
|
34504
|
-
const
|
|
34905
|
+
const existingPages = context.pages();
|
|
34906
|
+
if (existingPages.length === 0) {
|
|
34907
|
+
const page2 = await context.newPage();
|
|
34908
|
+
return {
|
|
34909
|
+
browser,
|
|
34910
|
+
context,
|
|
34911
|
+
page: page2
|
|
34912
|
+
};
|
|
34913
|
+
}
|
|
34914
|
+
const orderedPages = await orderPagesByBrowserTargetOrder(context, existingPages);
|
|
34915
|
+
const page = await resolvePersistedActivePage(orderedPages, {
|
|
34916
|
+
...resolved.record.activePageUrl === void 0 ? {} : { activePageUrl: resolved.record.activePageUrl },
|
|
34917
|
+
...resolved.record.activePageTitle === void 0 ? {} : { activePageTitle: resolved.record.activePageTitle }
|
|
34918
|
+
}) ?? orderedPages[0];
|
|
34505
34919
|
return {
|
|
34506
34920
|
browser,
|
|
34507
34921
|
context,
|
|
@@ -34846,6 +35260,28 @@ async function disconnectPlaywrightChromiumBrowser2(browser) {
|
|
|
34846
35260
|
const { disconnectPlaywrightChromiumBrowser: disconnect } = await import('@opensteer/engine-playwright');
|
|
34847
35261
|
await disconnect(browser);
|
|
34848
35262
|
}
|
|
35263
|
+
async function resolvePersistedActivePage(pages, input) {
|
|
35264
|
+
if (pages.length === 0) {
|
|
35265
|
+
return null;
|
|
35266
|
+
}
|
|
35267
|
+
if (input.activePageUrl === void 0 && input.activePageTitle === void 0) {
|
|
35268
|
+
return null;
|
|
35269
|
+
}
|
|
35270
|
+
const matchesByUrl = input.activePageUrl === void 0 ? pages : pages.filter((page) => page.url() === input.activePageUrl);
|
|
35271
|
+
if (matchesByUrl.length === 0) {
|
|
35272
|
+
return null;
|
|
35273
|
+
}
|
|
35274
|
+
if (input.activePageTitle === void 0) {
|
|
35275
|
+
return matchesByUrl[0] ?? null;
|
|
35276
|
+
}
|
|
35277
|
+
for (const page of matchesByUrl) {
|
|
35278
|
+
const title = await page.title().catch(() => "");
|
|
35279
|
+
if (title === input.activePageTitle) {
|
|
35280
|
+
return page;
|
|
35281
|
+
}
|
|
35282
|
+
}
|
|
35283
|
+
return matchesByUrl[0] ?? null;
|
|
35284
|
+
}
|
|
34849
35285
|
|
|
34850
35286
|
// src/local-view/server.ts
|
|
34851
35287
|
var DEFAULT_MAX_FPS = 12;
|
|
@@ -35326,7 +35762,10 @@ async function main() {
|
|
|
35326
35762
|
throw new CliError("unknown_command", `Unknown command: ${parsed.command.join(" ")}`);
|
|
35327
35763
|
}
|
|
35328
35764
|
if (parsed.options.workspace === void 0) {
|
|
35329
|
-
throw new CliError(
|
|
35765
|
+
throw new CliError(
|
|
35766
|
+
"missing_workspace",
|
|
35767
|
+
'Stateful commands require "--workspace <id>" or OPENSTEER_WORKSPACE.'
|
|
35768
|
+
);
|
|
35330
35769
|
}
|
|
35331
35770
|
const { engineName, provider, runtimeProvider } = resolveCliRuntimeSelection(parsed);
|
|
35332
35771
|
if (operation === "session.close") {
|
|
@@ -35373,7 +35812,10 @@ async function main() {
|
|
|
35373
35812
|
}
|
|
35374
35813
|
async function handleExecCommand(parsed) {
|
|
35375
35814
|
if (parsed.options.workspace === void 0) {
|
|
35376
|
-
throw new CliError(
|
|
35815
|
+
throw new CliError(
|
|
35816
|
+
"missing_workspace",
|
|
35817
|
+
'exec requires "--workspace <id>" or OPENSTEER_WORKSPACE.'
|
|
35818
|
+
);
|
|
35377
35819
|
}
|
|
35378
35820
|
const expression = parsed.rest.join(" ");
|
|
35379
35821
|
if (!expression) {
|
|
@@ -35516,7 +35958,10 @@ async function handleCloseCommand(parsed, engineName, providerMode, runtimeProvi
|
|
|
35516
35958
|
}
|
|
35517
35959
|
async function handleRecordCommandEntry(parsed) {
|
|
35518
35960
|
if (parsed.options.workspace === void 0) {
|
|
35519
|
-
throw new CliError(
|
|
35961
|
+
throw new CliError(
|
|
35962
|
+
"missing_workspace",
|
|
35963
|
+
'record requires "--workspace <id>" or OPENSTEER_WORKSPACE.'
|
|
35964
|
+
);
|
|
35520
35965
|
}
|
|
35521
35966
|
const url = parsed.options.url ?? parsed.rest[0];
|
|
35522
35967
|
if (url === void 0) {
|
|
@@ -35556,7 +36001,10 @@ async function handleRecordCommandEntry(parsed) {
|
|
|
35556
36001
|
return;
|
|
35557
36002
|
}
|
|
35558
36003
|
if (parsed.options.launch?.headless === true) {
|
|
35559
|
-
throw new CliError(
|
|
36004
|
+
throw new CliError(
|
|
36005
|
+
"config_conflict",
|
|
36006
|
+
'record requires a headed browser. Remove "--headless true".'
|
|
36007
|
+
);
|
|
35560
36008
|
}
|
|
35561
36009
|
if (typeof recordBrowser === "object") {
|
|
35562
36010
|
throw new CliError("config_conflict", 'record does not support browser.mode="attach".');
|
|
@@ -35628,7 +36076,10 @@ function resolveCliBootstrapAction(argv) {
|
|
|
35628
36076
|
}
|
|
35629
36077
|
function buildCliBrowserProfile(parsed) {
|
|
35630
36078
|
if (parsed.options.cloudProfileReuseIfActive === true && parsed.options.cloudProfileId === void 0) {
|
|
35631
|
-
throw new CliError(
|
|
36079
|
+
throw new CliError(
|
|
36080
|
+
"invalid_option",
|
|
36081
|
+
'"--cloud-profile-reuse-if-active" requires "--cloud-profile-id <id>".'
|
|
36082
|
+
);
|
|
35632
36083
|
}
|
|
35633
36084
|
return parsed.options.cloudProfileId === void 0 ? void 0 : {
|
|
35634
36085
|
profileId: parsed.options.cloudProfileId,
|