opensteer 0.4.8 → 0.4.10
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/bin/opensteer.mjs +0 -1
- package/dist/{chunk-GQ7HNCM2.js → chunk-C3NM6XZH.js} +77 -37
- package/dist/cli/server.cjs +77 -37
- package/dist/cli/server.js +1 -1
- package/dist/index.cjs +77 -37
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/bin/opensteer.mjs
CHANGED
|
@@ -781,7 +781,6 @@ Environment:
|
|
|
781
781
|
OPENSTEER_MODE Runtime routing: "local" (default) or "cloud"
|
|
782
782
|
OPENSTEER_API_KEY Required when cloud mode is selected
|
|
783
783
|
OPENSTEER_BASE_URL Override cloud control-plane base URL
|
|
784
|
-
OPENSTEER_APP_URL Cloud app base URL for emitting browser session links (default: https://opensteer.com)
|
|
785
784
|
OPENSTEER_REMOTE_ANNOUNCE Cloud session announcement policy: always (default), off, tty
|
|
786
785
|
`)
|
|
787
786
|
}
|
|
@@ -38,6 +38,7 @@ function sanitizeNamespaceSegment(segment) {
|
|
|
38
38
|
var DEFAULT_TIMEOUT = 3e4;
|
|
39
39
|
var DEFAULT_SETTLE_MS = 750;
|
|
40
40
|
var FRAME_EVALUATE_GRACE_MS = 200;
|
|
41
|
+
var TRANSIENT_CONTEXT_RETRY_DELAY_MS = 25;
|
|
41
42
|
var STEALTH_WORLD_NAME = "__opensteer_wait__";
|
|
42
43
|
var StealthWaitUnavailableError = class extends Error {
|
|
43
44
|
constructor(cause) {
|
|
@@ -341,7 +342,12 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
|
|
|
341
342
|
const frameRecords = await this.getFrameRecords();
|
|
342
343
|
const mainFrame = frameRecords[0];
|
|
343
344
|
if (!mainFrame) return;
|
|
344
|
-
await this.waitForFrameVisualStability(
|
|
345
|
+
await this.waitForFrameVisualStability(
|
|
346
|
+
mainFrame.frameId,
|
|
347
|
+
timeout,
|
|
348
|
+
settleMs,
|
|
349
|
+
true
|
|
350
|
+
);
|
|
345
351
|
}
|
|
346
352
|
async collectVisibleFrameIds() {
|
|
347
353
|
const frameRecords = await this.getFrameRecords();
|
|
@@ -370,19 +376,44 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
|
|
|
370
376
|
}
|
|
371
377
|
return visibleFrameIds;
|
|
372
378
|
}
|
|
373
|
-
async waitForFrameVisualStability(frameId, timeout, settleMs) {
|
|
379
|
+
async waitForFrameVisualStability(frameId, timeout, settleMs, retryTransientContextErrors = true) {
|
|
374
380
|
if (timeout <= 0) return;
|
|
375
381
|
const script = buildStabilityScript(timeout, settleMs);
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
+
if (!retryTransientContextErrors) {
|
|
383
|
+
let contextId = await this.ensureFrameContextId(frameId);
|
|
384
|
+
try {
|
|
385
|
+
await this.evaluateWithGuard(contextId, script, timeout);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
if (!isMissingExecutionContextError(error)) {
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
this.contextsByFrame.delete(frameId);
|
|
391
|
+
contextId = await this.ensureFrameContextId(frameId);
|
|
392
|
+
await this.evaluateWithGuard(contextId, script, timeout);
|
|
393
|
+
}
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const deadline = Date.now() + timeout;
|
|
397
|
+
while (true) {
|
|
398
|
+
const remaining = Math.max(0, deadline - Date.now());
|
|
399
|
+
if (remaining === 0) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const contextId = await this.ensureFrameContextId(frameId);
|
|
403
|
+
try {
|
|
404
|
+
await this.evaluateWithGuard(contextId, script, remaining);
|
|
405
|
+
return;
|
|
406
|
+
} catch (error) {
|
|
407
|
+
if (!isTransientExecutionContextError(error)) {
|
|
408
|
+
throw error;
|
|
409
|
+
}
|
|
410
|
+
this.contextsByFrame.delete(frameId);
|
|
411
|
+
const retryDelay = Math.min(
|
|
412
|
+
TRANSIENT_CONTEXT_RETRY_DELAY_MS,
|
|
413
|
+
Math.max(0, deadline - Date.now())
|
|
414
|
+
);
|
|
415
|
+
await sleep(retryDelay);
|
|
382
416
|
}
|
|
383
|
-
this.contextsByFrame.delete(frameId);
|
|
384
|
-
contextId = await this.ensureFrameContextId(frameId);
|
|
385
|
-
await this.evaluateWithGuard(contextId, script, timeout);
|
|
386
417
|
}
|
|
387
418
|
}
|
|
388
419
|
async initialize() {
|
|
@@ -502,7 +533,8 @@ async function waitForVisualStabilityAcrossFrames(page, options = {}) {
|
|
|
502
533
|
await runtime.waitForFrameVisualStability(
|
|
503
534
|
frameId,
|
|
504
535
|
remaining,
|
|
505
|
-
settleMs
|
|
536
|
+
settleMs,
|
|
537
|
+
false
|
|
506
538
|
);
|
|
507
539
|
} catch (error) {
|
|
508
540
|
if (isIgnorableFrameError(error)) return;
|
|
@@ -540,6 +572,11 @@ function sameFrameIds(before, after) {
|
|
|
540
572
|
function formatCdpException(details) {
|
|
541
573
|
return details.exception?.description || details.text || "CDP runtime evaluation failed.";
|
|
542
574
|
}
|
|
575
|
+
function isTransientExecutionContextError(error) {
|
|
576
|
+
if (!(error instanceof Error)) return false;
|
|
577
|
+
const message = error.message;
|
|
578
|
+
return message.includes("Execution context was destroyed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
|
|
579
|
+
}
|
|
543
580
|
function isMissingExecutionContextError(error) {
|
|
544
581
|
if (!(error instanceof Error)) return false;
|
|
545
582
|
const message = error.message;
|
|
@@ -548,7 +585,7 @@ function isMissingExecutionContextError(error) {
|
|
|
548
585
|
function isIgnorableFrameError(error) {
|
|
549
586
|
if (!(error instanceof Error)) return false;
|
|
550
587
|
const message = error.message;
|
|
551
|
-
return message.includes("Frame was detached") || message.includes("
|
|
588
|
+
return message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || isTransientExecutionContextError(error) || message.includes("No frame for given id found");
|
|
552
589
|
}
|
|
553
590
|
function sleep(ms) {
|
|
554
591
|
return new Promise((resolve) => {
|
|
@@ -6177,6 +6214,11 @@ function resolveOpensteerApiKey(env) {
|
|
|
6177
6214
|
if (!value) return void 0;
|
|
6178
6215
|
return value;
|
|
6179
6216
|
}
|
|
6217
|
+
function resolveOpensteerBaseUrl(env) {
|
|
6218
|
+
const value = env.OPENSTEER_BASE_URL?.trim();
|
|
6219
|
+
if (!value) return void 0;
|
|
6220
|
+
return value;
|
|
6221
|
+
}
|
|
6180
6222
|
function resolveOpensteerAuthScheme(env) {
|
|
6181
6223
|
return parseAuthScheme(env.OPENSTEER_AUTH_SCHEME, "OPENSTEER_AUTH_SCHEME");
|
|
6182
6224
|
}
|
|
@@ -6255,6 +6297,7 @@ function resolveConfig(input = {}) {
|
|
|
6255
6297
|
const mergedWithEnv = mergeDeep(mergedWithFile, envConfig);
|
|
6256
6298
|
const resolved = mergeDeep(mergedWithEnv, input);
|
|
6257
6299
|
const envApiKey = resolveOpensteerApiKey(env);
|
|
6300
|
+
const envBaseUrl = resolveOpensteerBaseUrl(env);
|
|
6258
6301
|
const envAuthScheme = resolveOpensteerAuthScheme(env);
|
|
6259
6302
|
const envCloudAnnounce = parseCloudAnnounce(
|
|
6260
6303
|
env.OPENSTEER_REMOTE_ANNOUNCE,
|
|
@@ -6272,6 +6315,9 @@ function resolveConfig(input = {}) {
|
|
|
6272
6315
|
const inputHasCloudApiKey = Boolean(
|
|
6273
6316
|
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "apiKey")
|
|
6274
6317
|
);
|
|
6318
|
+
const inputHasCloudBaseUrl = Boolean(
|
|
6319
|
+
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "baseUrl")
|
|
6320
|
+
);
|
|
6275
6321
|
const cloudSelection = resolveCloudSelection({
|
|
6276
6322
|
cloud: resolved.cloud
|
|
6277
6323
|
}, env);
|
|
@@ -6291,6 +6337,12 @@ function resolveConfig(input = {}) {
|
|
|
6291
6337
|
apiKey: envApiKey
|
|
6292
6338
|
};
|
|
6293
6339
|
}
|
|
6340
|
+
if (envBaseUrl && cloudSelection.cloud && !inputHasCloudBaseUrl) {
|
|
6341
|
+
resolved.cloud = {
|
|
6342
|
+
...normalizeCloudOptions(resolved.cloud) ?? {},
|
|
6343
|
+
baseUrl: envBaseUrl
|
|
6344
|
+
};
|
|
6345
|
+
}
|
|
6294
6346
|
return resolved;
|
|
6295
6347
|
}
|
|
6296
6348
|
function resolveNamespace(config, rootDir) {
|
|
@@ -7685,12 +7737,16 @@ function clonePersistedExtractNode(node) {
|
|
|
7685
7737
|
|
|
7686
7738
|
// src/cloud/runtime.ts
|
|
7687
7739
|
var DEFAULT_CLOUD_BASE_URL = "https://remote.opensteer.com";
|
|
7688
|
-
|
|
7689
|
-
|
|
7740
|
+
function createCloudRuntimeState(key, baseUrl = resolveCloudBaseUrl(), authScheme = "api-key") {
|
|
7741
|
+
const normalizedBaseUrl = normalizeCloudBaseUrl(baseUrl);
|
|
7690
7742
|
return {
|
|
7691
|
-
sessionClient: new CloudSessionClient(
|
|
7743
|
+
sessionClient: new CloudSessionClient(
|
|
7744
|
+
normalizedBaseUrl,
|
|
7745
|
+
key,
|
|
7746
|
+
authScheme
|
|
7747
|
+
),
|
|
7692
7748
|
cdpClient: new CloudCdpClient(),
|
|
7693
|
-
|
|
7749
|
+
baseUrl: normalizedBaseUrl,
|
|
7694
7750
|
actionClient: null,
|
|
7695
7751
|
sessionId: null,
|
|
7696
7752
|
localRunId: null,
|
|
@@ -7700,15 +7756,9 @@ function createCloudRuntimeState(key, baseUrl = resolveCloudBaseUrl(), authSchem
|
|
|
7700
7756
|
function resolveCloudBaseUrl() {
|
|
7701
7757
|
const value = process.env.OPENSTEER_BASE_URL?.trim();
|
|
7702
7758
|
if (!value) return DEFAULT_CLOUD_BASE_URL;
|
|
7703
|
-
return value
|
|
7759
|
+
return normalizeCloudBaseUrl(value);
|
|
7704
7760
|
}
|
|
7705
|
-
function
|
|
7706
|
-
const value = process.env.OPENSTEER_APP_URL?.trim();
|
|
7707
|
-
if (!value) return DEFAULT_CLOUD_APP_URL;
|
|
7708
|
-
return normalizeCloudAppUrl(value);
|
|
7709
|
-
}
|
|
7710
|
-
function normalizeCloudAppUrl(value) {
|
|
7711
|
-
if (!value) return null;
|
|
7761
|
+
function normalizeCloudBaseUrl(value) {
|
|
7712
7762
|
return value.replace(/\/+$/, "");
|
|
7713
7763
|
}
|
|
7714
7764
|
function readCloudActionDescription(payload) {
|
|
@@ -7766,8 +7816,7 @@ var Opensteer = class _Opensteer {
|
|
|
7766
7816
|
this.cloud = createCloudRuntimeState(
|
|
7767
7817
|
apiKey,
|
|
7768
7818
|
cloudConfig?.baseUrl,
|
|
7769
|
-
cloudConfig?.authScheme
|
|
7770
|
-
cloudConfig?.appUrl
|
|
7819
|
+
cloudConfig?.authScheme
|
|
7771
7820
|
);
|
|
7772
7821
|
} else {
|
|
7773
7822
|
this.cloud = null;
|
|
@@ -7959,10 +8008,7 @@ var Opensteer = class _Opensteer {
|
|
|
7959
8008
|
this.snapshotCache = null;
|
|
7960
8009
|
this.cloud.actionClient = actionClient;
|
|
7961
8010
|
this.cloud.sessionId = sessionId;
|
|
7962
|
-
this.cloud.cloudSessionUrl =
|
|
7963
|
-
this.cloud.appUrl,
|
|
7964
|
-
session2.cloudSession.sessionId
|
|
7965
|
-
);
|
|
8011
|
+
this.cloud.cloudSessionUrl = session2.cloudSessionUrl;
|
|
7966
8012
|
this.announceCloudSession({
|
|
7967
8013
|
sessionId: session2.sessionId,
|
|
7968
8014
|
workspaceId: session2.cloudSession.workspaceId,
|
|
@@ -10019,12 +10065,6 @@ function buildLocalRunId(namespace) {
|
|
|
10019
10065
|
const normalized = namespace.trim() || "default";
|
|
10020
10066
|
return `${normalized}-${Date.now().toString(36)}-${randomUUID2().slice(0, 8)}`;
|
|
10021
10067
|
}
|
|
10022
|
-
function buildCloudSessionUrl(appUrl, sessionId) {
|
|
10023
|
-
if (!appUrl) {
|
|
10024
|
-
return null;
|
|
10025
|
-
}
|
|
10026
|
-
return `${appUrl}/browser/${encodeURIComponent(sessionId)}`;
|
|
10027
|
-
}
|
|
10028
10068
|
|
|
10029
10069
|
export {
|
|
10030
10070
|
normalizeNamespace,
|
package/dist/cli/server.cjs
CHANGED
|
@@ -1036,6 +1036,11 @@ function resolveOpensteerApiKey(env) {
|
|
|
1036
1036
|
if (!value) return void 0;
|
|
1037
1037
|
return value;
|
|
1038
1038
|
}
|
|
1039
|
+
function resolveOpensteerBaseUrl(env) {
|
|
1040
|
+
const value = env.OPENSTEER_BASE_URL?.trim();
|
|
1041
|
+
if (!value) return void 0;
|
|
1042
|
+
return value;
|
|
1043
|
+
}
|
|
1039
1044
|
function resolveOpensteerAuthScheme(env) {
|
|
1040
1045
|
return parseAuthScheme(env.OPENSTEER_AUTH_SCHEME, "OPENSTEER_AUTH_SCHEME");
|
|
1041
1046
|
}
|
|
@@ -1114,6 +1119,7 @@ function resolveConfig(input = {}) {
|
|
|
1114
1119
|
const mergedWithEnv = mergeDeep(mergedWithFile, envConfig);
|
|
1115
1120
|
const resolved = mergeDeep(mergedWithEnv, input);
|
|
1116
1121
|
const envApiKey = resolveOpensteerApiKey(env);
|
|
1122
|
+
const envBaseUrl = resolveOpensteerBaseUrl(env);
|
|
1117
1123
|
const envAuthScheme = resolveOpensteerAuthScheme(env);
|
|
1118
1124
|
const envCloudAnnounce = parseCloudAnnounce(
|
|
1119
1125
|
env.OPENSTEER_REMOTE_ANNOUNCE,
|
|
@@ -1131,6 +1137,9 @@ function resolveConfig(input = {}) {
|
|
|
1131
1137
|
const inputHasCloudApiKey = Boolean(
|
|
1132
1138
|
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "apiKey")
|
|
1133
1139
|
);
|
|
1140
|
+
const inputHasCloudBaseUrl = Boolean(
|
|
1141
|
+
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "baseUrl")
|
|
1142
|
+
);
|
|
1134
1143
|
const cloudSelection = resolveCloudSelection({
|
|
1135
1144
|
cloud: resolved.cloud
|
|
1136
1145
|
}, env);
|
|
@@ -1150,6 +1159,12 @@ function resolveConfig(input = {}) {
|
|
|
1150
1159
|
apiKey: envApiKey
|
|
1151
1160
|
};
|
|
1152
1161
|
}
|
|
1162
|
+
if (envBaseUrl && cloudSelection.cloud && !inputHasCloudBaseUrl) {
|
|
1163
|
+
resolved.cloud = {
|
|
1164
|
+
...normalizeCloudOptions(resolved.cloud) ?? {},
|
|
1165
|
+
baseUrl: envBaseUrl
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1153
1168
|
return resolved;
|
|
1154
1169
|
}
|
|
1155
1170
|
function resolveNamespace(config, rootDir) {
|
|
@@ -1190,6 +1205,7 @@ function getCallerFilePath() {
|
|
|
1190
1205
|
var DEFAULT_TIMEOUT = 3e4;
|
|
1191
1206
|
var DEFAULT_SETTLE_MS = 750;
|
|
1192
1207
|
var FRAME_EVALUATE_GRACE_MS = 200;
|
|
1208
|
+
var TRANSIENT_CONTEXT_RETRY_DELAY_MS = 25;
|
|
1193
1209
|
var STEALTH_WORLD_NAME = "__opensteer_wait__";
|
|
1194
1210
|
var StealthWaitUnavailableError = class extends Error {
|
|
1195
1211
|
constructor(cause) {
|
|
@@ -1493,7 +1509,12 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
|
|
|
1493
1509
|
const frameRecords = await this.getFrameRecords();
|
|
1494
1510
|
const mainFrame = frameRecords[0];
|
|
1495
1511
|
if (!mainFrame) return;
|
|
1496
|
-
await this.waitForFrameVisualStability(
|
|
1512
|
+
await this.waitForFrameVisualStability(
|
|
1513
|
+
mainFrame.frameId,
|
|
1514
|
+
timeout,
|
|
1515
|
+
settleMs,
|
|
1516
|
+
true
|
|
1517
|
+
);
|
|
1497
1518
|
}
|
|
1498
1519
|
async collectVisibleFrameIds() {
|
|
1499
1520
|
const frameRecords = await this.getFrameRecords();
|
|
@@ -1522,19 +1543,44 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
|
|
|
1522
1543
|
}
|
|
1523
1544
|
return visibleFrameIds;
|
|
1524
1545
|
}
|
|
1525
|
-
async waitForFrameVisualStability(frameId, timeout, settleMs) {
|
|
1546
|
+
async waitForFrameVisualStability(frameId, timeout, settleMs, retryTransientContextErrors = true) {
|
|
1526
1547
|
if (timeout <= 0) return;
|
|
1527
1548
|
const script = buildStabilityScript(timeout, settleMs);
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1549
|
+
if (!retryTransientContextErrors) {
|
|
1550
|
+
let contextId = await this.ensureFrameContextId(frameId);
|
|
1551
|
+
try {
|
|
1552
|
+
await this.evaluateWithGuard(contextId, script, timeout);
|
|
1553
|
+
} catch (error) {
|
|
1554
|
+
if (!isMissingExecutionContextError(error)) {
|
|
1555
|
+
throw error;
|
|
1556
|
+
}
|
|
1557
|
+
this.contextsByFrame.delete(frameId);
|
|
1558
|
+
contextId = await this.ensureFrameContextId(frameId);
|
|
1559
|
+
await this.evaluateWithGuard(contextId, script, timeout);
|
|
1560
|
+
}
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
const deadline = Date.now() + timeout;
|
|
1564
|
+
while (true) {
|
|
1565
|
+
const remaining = Math.max(0, deadline - Date.now());
|
|
1566
|
+
if (remaining === 0) {
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
const contextId = await this.ensureFrameContextId(frameId);
|
|
1570
|
+
try {
|
|
1571
|
+
await this.evaluateWithGuard(contextId, script, remaining);
|
|
1572
|
+
return;
|
|
1573
|
+
} catch (error) {
|
|
1574
|
+
if (!isTransientExecutionContextError(error)) {
|
|
1575
|
+
throw error;
|
|
1576
|
+
}
|
|
1577
|
+
this.contextsByFrame.delete(frameId);
|
|
1578
|
+
const retryDelay = Math.min(
|
|
1579
|
+
TRANSIENT_CONTEXT_RETRY_DELAY_MS,
|
|
1580
|
+
Math.max(0, deadline - Date.now())
|
|
1581
|
+
);
|
|
1582
|
+
await sleep(retryDelay);
|
|
1534
1583
|
}
|
|
1535
|
-
this.contextsByFrame.delete(frameId);
|
|
1536
|
-
contextId = await this.ensureFrameContextId(frameId);
|
|
1537
|
-
await this.evaluateWithGuard(contextId, script, timeout);
|
|
1538
1584
|
}
|
|
1539
1585
|
}
|
|
1540
1586
|
async initialize() {
|
|
@@ -1654,7 +1700,8 @@ async function waitForVisualStabilityAcrossFrames(page, options = {}) {
|
|
|
1654
1700
|
await runtime.waitForFrameVisualStability(
|
|
1655
1701
|
frameId,
|
|
1656
1702
|
remaining,
|
|
1657
|
-
settleMs
|
|
1703
|
+
settleMs,
|
|
1704
|
+
false
|
|
1658
1705
|
);
|
|
1659
1706
|
} catch (error) {
|
|
1660
1707
|
if (isIgnorableFrameError(error)) return;
|
|
@@ -1692,6 +1739,11 @@ function sameFrameIds(before, after) {
|
|
|
1692
1739
|
function formatCdpException(details) {
|
|
1693
1740
|
return details.exception?.description || details.text || "CDP runtime evaluation failed.";
|
|
1694
1741
|
}
|
|
1742
|
+
function isTransientExecutionContextError(error) {
|
|
1743
|
+
if (!(error instanceof Error)) return false;
|
|
1744
|
+
const message = error.message;
|
|
1745
|
+
return message.includes("Execution context was destroyed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
|
|
1746
|
+
}
|
|
1695
1747
|
function isMissingExecutionContextError(error) {
|
|
1696
1748
|
if (!(error instanceof Error)) return false;
|
|
1697
1749
|
const message = error.message;
|
|
@@ -1700,7 +1752,7 @@ function isMissingExecutionContextError(error) {
|
|
|
1700
1752
|
function isIgnorableFrameError(error) {
|
|
1701
1753
|
if (!(error instanceof Error)) return false;
|
|
1702
1754
|
const message = error.message;
|
|
1703
|
-
return message.includes("Frame was detached") || message.includes("
|
|
1755
|
+
return message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || isTransientExecutionContextError(error) || message.includes("No frame for given id found");
|
|
1704
1756
|
}
|
|
1705
1757
|
function sleep(ms) {
|
|
1706
1758
|
return new Promise((resolve) => {
|
|
@@ -8019,12 +8071,16 @@ function toCloudErrorCode(code) {
|
|
|
8019
8071
|
|
|
8020
8072
|
// src/cloud/runtime.ts
|
|
8021
8073
|
var DEFAULT_CLOUD_BASE_URL = "https://remote.opensteer.com";
|
|
8022
|
-
|
|
8023
|
-
|
|
8074
|
+
function createCloudRuntimeState(key, baseUrl = resolveCloudBaseUrl(), authScheme = "api-key") {
|
|
8075
|
+
const normalizedBaseUrl = normalizeCloudBaseUrl(baseUrl);
|
|
8024
8076
|
return {
|
|
8025
|
-
sessionClient: new CloudSessionClient(
|
|
8077
|
+
sessionClient: new CloudSessionClient(
|
|
8078
|
+
normalizedBaseUrl,
|
|
8079
|
+
key,
|
|
8080
|
+
authScheme
|
|
8081
|
+
),
|
|
8026
8082
|
cdpClient: new CloudCdpClient(),
|
|
8027
|
-
|
|
8083
|
+
baseUrl: normalizedBaseUrl,
|
|
8028
8084
|
actionClient: null,
|
|
8029
8085
|
sessionId: null,
|
|
8030
8086
|
localRunId: null,
|
|
@@ -8034,15 +8090,9 @@ function createCloudRuntimeState(key, baseUrl = resolveCloudBaseUrl(), authSchem
|
|
|
8034
8090
|
function resolveCloudBaseUrl() {
|
|
8035
8091
|
const value = process.env.OPENSTEER_BASE_URL?.trim();
|
|
8036
8092
|
if (!value) return DEFAULT_CLOUD_BASE_URL;
|
|
8037
|
-
return value
|
|
8093
|
+
return normalizeCloudBaseUrl(value);
|
|
8038
8094
|
}
|
|
8039
|
-
function
|
|
8040
|
-
const value = process.env.OPENSTEER_APP_URL?.trim();
|
|
8041
|
-
if (!value) return DEFAULT_CLOUD_APP_URL;
|
|
8042
|
-
return normalizeCloudAppUrl(value);
|
|
8043
|
-
}
|
|
8044
|
-
function normalizeCloudAppUrl(value) {
|
|
8045
|
-
if (!value) return null;
|
|
8095
|
+
function normalizeCloudBaseUrl(value) {
|
|
8046
8096
|
return value.replace(/\/+$/, "");
|
|
8047
8097
|
}
|
|
8048
8098
|
function readCloudActionDescription(payload) {
|
|
@@ -8100,8 +8150,7 @@ var Opensteer = class _Opensteer {
|
|
|
8100
8150
|
this.cloud = createCloudRuntimeState(
|
|
8101
8151
|
apiKey,
|
|
8102
8152
|
cloudConfig?.baseUrl,
|
|
8103
|
-
cloudConfig?.authScheme
|
|
8104
|
-
cloudConfig?.appUrl
|
|
8153
|
+
cloudConfig?.authScheme
|
|
8105
8154
|
);
|
|
8106
8155
|
} else {
|
|
8107
8156
|
this.cloud = null;
|
|
@@ -8293,10 +8342,7 @@ var Opensteer = class _Opensteer {
|
|
|
8293
8342
|
this.snapshotCache = null;
|
|
8294
8343
|
this.cloud.actionClient = actionClient;
|
|
8295
8344
|
this.cloud.sessionId = sessionId;
|
|
8296
|
-
this.cloud.cloudSessionUrl =
|
|
8297
|
-
this.cloud.appUrl,
|
|
8298
|
-
session3.cloudSession.sessionId
|
|
8299
|
-
);
|
|
8345
|
+
this.cloud.cloudSessionUrl = session3.cloudSessionUrl;
|
|
8300
8346
|
this.announceCloudSession({
|
|
8301
8347
|
sessionId: session3.sessionId,
|
|
8302
8348
|
workspaceId: session3.cloudSession.workspaceId,
|
|
@@ -10353,12 +10399,6 @@ function buildLocalRunId(namespace) {
|
|
|
10353
10399
|
const normalized = namespace.trim() || "default";
|
|
10354
10400
|
return `${normalized}-${Date.now().toString(36)}-${(0, import_crypto2.randomUUID)().slice(0, 8)}`;
|
|
10355
10401
|
}
|
|
10356
|
-
function buildCloudSessionUrl(appUrl, sessionId) {
|
|
10357
|
-
if (!appUrl) {
|
|
10358
|
-
return null;
|
|
10359
|
-
}
|
|
10360
|
-
return `${appUrl}/browser/${encodeURIComponent(sessionId)}`;
|
|
10361
|
-
}
|
|
10362
10402
|
|
|
10363
10403
|
// src/cli/paths.ts
|
|
10364
10404
|
var import_os2 = require("os");
|
package/dist/cli/server.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1111,6 +1111,11 @@ function resolveOpensteerApiKey(env) {
|
|
|
1111
1111
|
if (!value) return void 0;
|
|
1112
1112
|
return value;
|
|
1113
1113
|
}
|
|
1114
|
+
function resolveOpensteerBaseUrl(env) {
|
|
1115
|
+
const value = env.OPENSTEER_BASE_URL?.trim();
|
|
1116
|
+
if (!value) return void 0;
|
|
1117
|
+
return value;
|
|
1118
|
+
}
|
|
1114
1119
|
function resolveOpensteerAuthScheme(env) {
|
|
1115
1120
|
return parseAuthScheme(env.OPENSTEER_AUTH_SCHEME, "OPENSTEER_AUTH_SCHEME");
|
|
1116
1121
|
}
|
|
@@ -1189,6 +1194,7 @@ function resolveConfig(input = {}) {
|
|
|
1189
1194
|
const mergedWithEnv = mergeDeep(mergedWithFile, envConfig);
|
|
1190
1195
|
const resolved = mergeDeep(mergedWithEnv, input);
|
|
1191
1196
|
const envApiKey = resolveOpensteerApiKey(env);
|
|
1197
|
+
const envBaseUrl = resolveOpensteerBaseUrl(env);
|
|
1192
1198
|
const envAuthScheme = resolveOpensteerAuthScheme(env);
|
|
1193
1199
|
const envCloudAnnounce = parseCloudAnnounce(
|
|
1194
1200
|
env.OPENSTEER_REMOTE_ANNOUNCE,
|
|
@@ -1206,6 +1212,9 @@ function resolveConfig(input = {}) {
|
|
|
1206
1212
|
const inputHasCloudApiKey = Boolean(
|
|
1207
1213
|
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "apiKey")
|
|
1208
1214
|
);
|
|
1215
|
+
const inputHasCloudBaseUrl = Boolean(
|
|
1216
|
+
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "baseUrl")
|
|
1217
|
+
);
|
|
1209
1218
|
const cloudSelection = resolveCloudSelection({
|
|
1210
1219
|
cloud: resolved.cloud
|
|
1211
1220
|
}, env);
|
|
@@ -1225,6 +1234,12 @@ function resolveConfig(input = {}) {
|
|
|
1225
1234
|
apiKey: envApiKey
|
|
1226
1235
|
};
|
|
1227
1236
|
}
|
|
1237
|
+
if (envBaseUrl && cloudSelection.cloud && !inputHasCloudBaseUrl) {
|
|
1238
|
+
resolved.cloud = {
|
|
1239
|
+
...normalizeCloudOptions(resolved.cloud) ?? {},
|
|
1240
|
+
baseUrl: envBaseUrl
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1228
1243
|
return resolved;
|
|
1229
1244
|
}
|
|
1230
1245
|
function resolveNamespace(config, rootDir) {
|
|
@@ -1265,6 +1280,7 @@ function getCallerFilePath() {
|
|
|
1265
1280
|
var DEFAULT_TIMEOUT = 3e4;
|
|
1266
1281
|
var DEFAULT_SETTLE_MS = 750;
|
|
1267
1282
|
var FRAME_EVALUATE_GRACE_MS = 200;
|
|
1283
|
+
var TRANSIENT_CONTEXT_RETRY_DELAY_MS = 25;
|
|
1268
1284
|
var STEALTH_WORLD_NAME = "__opensteer_wait__";
|
|
1269
1285
|
var StealthWaitUnavailableError = class extends Error {
|
|
1270
1286
|
constructor(cause) {
|
|
@@ -1568,7 +1584,12 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
|
|
|
1568
1584
|
const frameRecords = await this.getFrameRecords();
|
|
1569
1585
|
const mainFrame = frameRecords[0];
|
|
1570
1586
|
if (!mainFrame) return;
|
|
1571
|
-
await this.waitForFrameVisualStability(
|
|
1587
|
+
await this.waitForFrameVisualStability(
|
|
1588
|
+
mainFrame.frameId,
|
|
1589
|
+
timeout,
|
|
1590
|
+
settleMs,
|
|
1591
|
+
true
|
|
1592
|
+
);
|
|
1572
1593
|
}
|
|
1573
1594
|
async collectVisibleFrameIds() {
|
|
1574
1595
|
const frameRecords = await this.getFrameRecords();
|
|
@@ -1597,19 +1618,44 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
|
|
|
1597
1618
|
}
|
|
1598
1619
|
return visibleFrameIds;
|
|
1599
1620
|
}
|
|
1600
|
-
async waitForFrameVisualStability(frameId, timeout, settleMs) {
|
|
1621
|
+
async waitForFrameVisualStability(frameId, timeout, settleMs, retryTransientContextErrors = true) {
|
|
1601
1622
|
if (timeout <= 0) return;
|
|
1602
1623
|
const script = buildStabilityScript(timeout, settleMs);
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1624
|
+
if (!retryTransientContextErrors) {
|
|
1625
|
+
let contextId = await this.ensureFrameContextId(frameId);
|
|
1626
|
+
try {
|
|
1627
|
+
await this.evaluateWithGuard(contextId, script, timeout);
|
|
1628
|
+
} catch (error) {
|
|
1629
|
+
if (!isMissingExecutionContextError(error)) {
|
|
1630
|
+
throw error;
|
|
1631
|
+
}
|
|
1632
|
+
this.contextsByFrame.delete(frameId);
|
|
1633
|
+
contextId = await this.ensureFrameContextId(frameId);
|
|
1634
|
+
await this.evaluateWithGuard(contextId, script, timeout);
|
|
1635
|
+
}
|
|
1636
|
+
return;
|
|
1637
|
+
}
|
|
1638
|
+
const deadline = Date.now() + timeout;
|
|
1639
|
+
while (true) {
|
|
1640
|
+
const remaining = Math.max(0, deadline - Date.now());
|
|
1641
|
+
if (remaining === 0) {
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
const contextId = await this.ensureFrameContextId(frameId);
|
|
1645
|
+
try {
|
|
1646
|
+
await this.evaluateWithGuard(contextId, script, remaining);
|
|
1647
|
+
return;
|
|
1648
|
+
} catch (error) {
|
|
1649
|
+
if (!isTransientExecutionContextError(error)) {
|
|
1650
|
+
throw error;
|
|
1651
|
+
}
|
|
1652
|
+
this.contextsByFrame.delete(frameId);
|
|
1653
|
+
const retryDelay = Math.min(
|
|
1654
|
+
TRANSIENT_CONTEXT_RETRY_DELAY_MS,
|
|
1655
|
+
Math.max(0, deadline - Date.now())
|
|
1656
|
+
);
|
|
1657
|
+
await sleep(retryDelay);
|
|
1609
1658
|
}
|
|
1610
|
-
this.contextsByFrame.delete(frameId);
|
|
1611
|
-
contextId = await this.ensureFrameContextId(frameId);
|
|
1612
|
-
await this.evaluateWithGuard(contextId, script, timeout);
|
|
1613
1659
|
}
|
|
1614
1660
|
}
|
|
1615
1661
|
async initialize() {
|
|
@@ -1729,7 +1775,8 @@ async function waitForVisualStabilityAcrossFrames(page, options = {}) {
|
|
|
1729
1775
|
await runtime.waitForFrameVisualStability(
|
|
1730
1776
|
frameId,
|
|
1731
1777
|
remaining,
|
|
1732
|
-
settleMs
|
|
1778
|
+
settleMs,
|
|
1779
|
+
false
|
|
1733
1780
|
);
|
|
1734
1781
|
} catch (error) {
|
|
1735
1782
|
if (isIgnorableFrameError(error)) return;
|
|
@@ -1767,6 +1814,11 @@ function sameFrameIds(before, after) {
|
|
|
1767
1814
|
function formatCdpException(details) {
|
|
1768
1815
|
return details.exception?.description || details.text || "CDP runtime evaluation failed.";
|
|
1769
1816
|
}
|
|
1817
|
+
function isTransientExecutionContextError(error) {
|
|
1818
|
+
if (!(error instanceof Error)) return false;
|
|
1819
|
+
const message = error.message;
|
|
1820
|
+
return message.includes("Execution context was destroyed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
|
|
1821
|
+
}
|
|
1770
1822
|
function isMissingExecutionContextError(error) {
|
|
1771
1823
|
if (!(error instanceof Error)) return false;
|
|
1772
1824
|
const message = error.message;
|
|
@@ -1775,7 +1827,7 @@ function isMissingExecutionContextError(error) {
|
|
|
1775
1827
|
function isIgnorableFrameError(error) {
|
|
1776
1828
|
if (!(error instanceof Error)) return false;
|
|
1777
1829
|
const message = error.message;
|
|
1778
|
-
return message.includes("Frame was detached") || message.includes("
|
|
1830
|
+
return message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || isTransientExecutionContextError(error) || message.includes("No frame for given id found");
|
|
1779
1831
|
}
|
|
1780
1832
|
function sleep(ms) {
|
|
1781
1833
|
return new Promise((resolve) => {
|
|
@@ -8104,12 +8156,16 @@ function toCloudErrorCode(code) {
|
|
|
8104
8156
|
|
|
8105
8157
|
// src/cloud/runtime.ts
|
|
8106
8158
|
var DEFAULT_CLOUD_BASE_URL = "https://remote.opensteer.com";
|
|
8107
|
-
|
|
8108
|
-
|
|
8159
|
+
function createCloudRuntimeState(key, baseUrl = resolveCloudBaseUrl(), authScheme = "api-key") {
|
|
8160
|
+
const normalizedBaseUrl = normalizeCloudBaseUrl(baseUrl);
|
|
8109
8161
|
return {
|
|
8110
|
-
sessionClient: new CloudSessionClient(
|
|
8162
|
+
sessionClient: new CloudSessionClient(
|
|
8163
|
+
normalizedBaseUrl,
|
|
8164
|
+
key,
|
|
8165
|
+
authScheme
|
|
8166
|
+
),
|
|
8111
8167
|
cdpClient: new CloudCdpClient(),
|
|
8112
|
-
|
|
8168
|
+
baseUrl: normalizedBaseUrl,
|
|
8113
8169
|
actionClient: null,
|
|
8114
8170
|
sessionId: null,
|
|
8115
8171
|
localRunId: null,
|
|
@@ -8119,15 +8175,9 @@ function createCloudRuntimeState(key, baseUrl = resolveCloudBaseUrl(), authSchem
|
|
|
8119
8175
|
function resolveCloudBaseUrl() {
|
|
8120
8176
|
const value = process.env.OPENSTEER_BASE_URL?.trim();
|
|
8121
8177
|
if (!value) return DEFAULT_CLOUD_BASE_URL;
|
|
8122
|
-
return value
|
|
8178
|
+
return normalizeCloudBaseUrl(value);
|
|
8123
8179
|
}
|
|
8124
|
-
function
|
|
8125
|
-
const value = process.env.OPENSTEER_APP_URL?.trim();
|
|
8126
|
-
if (!value) return DEFAULT_CLOUD_APP_URL;
|
|
8127
|
-
return normalizeCloudAppUrl(value);
|
|
8128
|
-
}
|
|
8129
|
-
function normalizeCloudAppUrl(value) {
|
|
8130
|
-
if (!value) return null;
|
|
8180
|
+
function normalizeCloudBaseUrl(value) {
|
|
8131
8181
|
return value.replace(/\/+$/, "");
|
|
8132
8182
|
}
|
|
8133
8183
|
function readCloudActionDescription(payload) {
|
|
@@ -8185,8 +8235,7 @@ var Opensteer = class _Opensteer {
|
|
|
8185
8235
|
this.cloud = createCloudRuntimeState(
|
|
8186
8236
|
apiKey,
|
|
8187
8237
|
cloudConfig?.baseUrl,
|
|
8188
|
-
cloudConfig?.authScheme
|
|
8189
|
-
cloudConfig?.appUrl
|
|
8238
|
+
cloudConfig?.authScheme
|
|
8190
8239
|
);
|
|
8191
8240
|
} else {
|
|
8192
8241
|
this.cloud = null;
|
|
@@ -8378,10 +8427,7 @@ var Opensteer = class _Opensteer {
|
|
|
8378
8427
|
this.snapshotCache = null;
|
|
8379
8428
|
this.cloud.actionClient = actionClient;
|
|
8380
8429
|
this.cloud.sessionId = sessionId;
|
|
8381
|
-
this.cloud.cloudSessionUrl =
|
|
8382
|
-
this.cloud.appUrl,
|
|
8383
|
-
session2.cloudSession.sessionId
|
|
8384
|
-
);
|
|
8430
|
+
this.cloud.cloudSessionUrl = session2.cloudSessionUrl;
|
|
8385
8431
|
this.announceCloudSession({
|
|
8386
8432
|
sessionId: session2.sessionId,
|
|
8387
8433
|
workspaceId: session2.cloudSession.workspaceId,
|
|
@@ -10438,12 +10484,6 @@ function buildLocalRunId(namespace) {
|
|
|
10438
10484
|
const normalized = namespace.trim() || "default";
|
|
10439
10485
|
return `${normalized}-${Date.now().toString(36)}-${(0, import_crypto2.randomUUID)().slice(0, 8)}`;
|
|
10440
10486
|
}
|
|
10441
|
-
function buildCloudSessionUrl(appUrl, sessionId) {
|
|
10442
|
-
if (!appUrl) {
|
|
10443
|
-
return null;
|
|
10444
|
-
}
|
|
10445
|
-
return `${appUrl}/browser/${encodeURIComponent(sessionId)}`;
|
|
10446
|
-
}
|
|
10447
10487
|
|
|
10448
10488
|
// src/ai/index.ts
|
|
10449
10489
|
init_resolver();
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED