opensteer 0.4.6 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -3
- package/README.md +4 -4
- package/bin/opensteer.mjs +5 -3
- package/dist/{chunk-MGZ3QEYT.js → chunk-PIJI7FBH.js} +469 -220
- package/dist/cli/server.cjs +465 -216
- package/dist/cli/server.js +3 -2
- package/dist/index.cjs +475 -225
- package/dist/index.d.cts +64 -41
- package/dist/index.d.ts +64 -41
- package/dist/index.js +13 -11
- package/package.json +73 -80
package/dist/cli/server.cjs
CHANGED
|
@@ -752,7 +752,7 @@ var BrowserPool = class {
|
|
|
752
752
|
const context = contexts[0];
|
|
753
753
|
const pages = context.pages();
|
|
754
754
|
const page = pages.length > 0 ? pages[0] : await context.newPage();
|
|
755
|
-
return { browser, context, page,
|
|
755
|
+
return { browser, context, page, isExternal: true };
|
|
756
756
|
} catch (error) {
|
|
757
757
|
if (browser) {
|
|
758
758
|
await browser.close().catch(() => void 0);
|
|
@@ -787,7 +787,7 @@ var BrowserPool = class {
|
|
|
787
787
|
context = await browser.newContext(options.context || {});
|
|
788
788
|
page = await context.newPage();
|
|
789
789
|
}
|
|
790
|
-
return { browser, context, page,
|
|
790
|
+
return { browser, context, page, isExternal: false };
|
|
791
791
|
}
|
|
792
792
|
async launchSandbox(options) {
|
|
793
793
|
const browser = await import_playwright.chromium.launch({
|
|
@@ -798,7 +798,7 @@ var BrowserPool = class {
|
|
|
798
798
|
const context = await browser.newContext(options.context || {});
|
|
799
799
|
const page = await context.newPage();
|
|
800
800
|
this.browser = browser;
|
|
801
|
-
return { browser, context, page,
|
|
801
|
+
return { browser, context, page, isExternal: false };
|
|
802
802
|
}
|
|
803
803
|
};
|
|
804
804
|
|
|
@@ -869,28 +869,27 @@ function assertNoLegacyAiConfig(source, config) {
|
|
|
869
869
|
);
|
|
870
870
|
}
|
|
871
871
|
}
|
|
872
|
-
function
|
|
872
|
+
function assertNoLegacyRuntimeConfig(source, config) {
|
|
873
873
|
if (!config || typeof config !== "object") return;
|
|
874
874
|
const configRecord = config;
|
|
875
875
|
if (hasOwn(configRecord, "runtime")) {
|
|
876
876
|
throw new Error(
|
|
877
|
-
`Legacy "runtime" config is no longer supported in ${source}. Use top-level "
|
|
877
|
+
`Legacy "runtime" config is no longer supported in ${source}. Use top-level "cloud" instead.`
|
|
878
878
|
);
|
|
879
879
|
}
|
|
880
|
-
if (hasOwn(configRecord, "
|
|
880
|
+
if (hasOwn(configRecord, "mode")) {
|
|
881
881
|
throw new Error(
|
|
882
|
-
`Top-level "
|
|
882
|
+
`Top-level "mode" config is no longer supported in ${source}. Use "cloud: true" to enable cloud mode.`
|
|
883
883
|
);
|
|
884
884
|
}
|
|
885
|
-
|
|
886
|
-
if (typeof remoteValue === "boolean") {
|
|
885
|
+
if (hasOwn(configRecord, "remote")) {
|
|
887
886
|
throw new Error(
|
|
888
|
-
`
|
|
887
|
+
`Top-level "remote" config is no longer supported in ${source}. Use "cloud" options instead.`
|
|
889
888
|
);
|
|
890
889
|
}
|
|
891
|
-
if (
|
|
890
|
+
if (hasOwn(configRecord, "apiKey")) {
|
|
892
891
|
throw new Error(
|
|
893
|
-
`
|
|
892
|
+
`Top-level "apiKey" config is not supported in ${source}. Use "cloud.apiKey" instead.`
|
|
894
893
|
);
|
|
895
894
|
}
|
|
896
895
|
}
|
|
@@ -936,20 +935,20 @@ function parseNumber(value) {
|
|
|
936
935
|
if (!Number.isFinite(parsed)) return void 0;
|
|
937
936
|
return parsed;
|
|
938
937
|
}
|
|
939
|
-
function
|
|
938
|
+
function parseRuntimeMode(value, source) {
|
|
940
939
|
if (value == null) return void 0;
|
|
941
940
|
if (typeof value !== "string") {
|
|
942
941
|
throw new Error(
|
|
943
|
-
`Invalid ${source} value "${String(value)}". Use "local" or "
|
|
942
|
+
`Invalid ${source} value "${String(value)}". Use "local" or "cloud".`
|
|
944
943
|
);
|
|
945
944
|
}
|
|
946
945
|
const normalized = value.trim().toLowerCase();
|
|
947
946
|
if (!normalized) return void 0;
|
|
948
|
-
if (normalized === "local" || normalized === "
|
|
947
|
+
if (normalized === "local" || normalized === "cloud") {
|
|
949
948
|
return normalized;
|
|
950
949
|
}
|
|
951
950
|
throw new Error(
|
|
952
|
-
`Invalid ${source} value "${value}". Use "local" or "
|
|
951
|
+
`Invalid ${source} value "${value}". Use "local" or "cloud".`
|
|
953
952
|
);
|
|
954
953
|
}
|
|
955
954
|
function parseAuthScheme(value, source) {
|
|
@@ -968,6 +967,22 @@ function parseAuthScheme(value, source) {
|
|
|
968
967
|
`Invalid ${source} value "${value}". Use "api-key" or "bearer".`
|
|
969
968
|
);
|
|
970
969
|
}
|
|
970
|
+
function parseCloudAnnounce(value, source) {
|
|
971
|
+
if (value == null) return void 0;
|
|
972
|
+
if (typeof value !== "string") {
|
|
973
|
+
throw new Error(
|
|
974
|
+
`Invalid ${source} value "${String(value)}". Use "always", "off", or "tty".`
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
const normalized = value.trim().toLowerCase();
|
|
978
|
+
if (!normalized) return void 0;
|
|
979
|
+
if (normalized === "always" || normalized === "off" || normalized === "tty") {
|
|
980
|
+
return normalized;
|
|
981
|
+
}
|
|
982
|
+
throw new Error(
|
|
983
|
+
`Invalid ${source} value "${value}". Use "always", "off", or "tty".`
|
|
984
|
+
);
|
|
985
|
+
}
|
|
971
986
|
function resolveOpensteerApiKey() {
|
|
972
987
|
const value = process.env.OPENSTEER_API_KEY?.trim();
|
|
973
988
|
if (!value) return void 0;
|
|
@@ -979,29 +994,40 @@ function resolveOpensteerAuthScheme() {
|
|
|
979
994
|
"OPENSTEER_AUTH_SCHEME"
|
|
980
995
|
);
|
|
981
996
|
}
|
|
982
|
-
function
|
|
997
|
+
function normalizeCloudOptions(value) {
|
|
983
998
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
984
999
|
return void 0;
|
|
985
1000
|
}
|
|
986
1001
|
return value;
|
|
987
1002
|
}
|
|
988
|
-
function
|
|
989
|
-
|
|
990
|
-
if (
|
|
1003
|
+
function parseCloudEnabled(value, source) {
|
|
1004
|
+
if (value == null) return void 0;
|
|
1005
|
+
if (typeof value === "boolean") return value;
|
|
1006
|
+
if (typeof value === "object" && !Array.isArray(value)) return true;
|
|
1007
|
+
throw new Error(
|
|
1008
|
+
`Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
function resolveCloudSelection(config) {
|
|
1012
|
+
const configCloud = parseCloudEnabled(config.cloud, "cloud");
|
|
1013
|
+
if (configCloud !== void 0) {
|
|
991
1014
|
return {
|
|
992
|
-
|
|
993
|
-
source: "config.
|
|
1015
|
+
cloud: configCloud,
|
|
1016
|
+
source: "config.cloud"
|
|
994
1017
|
};
|
|
995
1018
|
}
|
|
996
|
-
const envMode =
|
|
1019
|
+
const envMode = parseRuntimeMode(
|
|
1020
|
+
process.env.OPENSTEER_MODE,
|
|
1021
|
+
"OPENSTEER_MODE"
|
|
1022
|
+
);
|
|
997
1023
|
if (envMode) {
|
|
998
1024
|
return {
|
|
999
|
-
|
|
1025
|
+
cloud: envMode === "cloud",
|
|
1000
1026
|
source: "env.OPENSTEER_MODE"
|
|
1001
1027
|
};
|
|
1002
1028
|
}
|
|
1003
1029
|
return {
|
|
1004
|
-
|
|
1030
|
+
cloud: false,
|
|
1005
1031
|
source: "default"
|
|
1006
1032
|
};
|
|
1007
1033
|
}
|
|
@@ -1017,11 +1043,11 @@ function resolveConfig(input = {}) {
|
|
|
1017
1043
|
);
|
|
1018
1044
|
}
|
|
1019
1045
|
assertNoLegacyAiConfig("Opensteer constructor config", input);
|
|
1020
|
-
|
|
1046
|
+
assertNoLegacyRuntimeConfig("Opensteer constructor config", input);
|
|
1021
1047
|
const rootDir = input.storage?.rootDir ?? DEFAULT_CONFIG.storage.rootDir ?? process.cwd();
|
|
1022
1048
|
const fileConfig = loadConfigFile(rootDir);
|
|
1023
1049
|
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
1024
|
-
|
|
1050
|
+
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
1025
1051
|
const envConfig = {
|
|
1026
1052
|
browser: {
|
|
1027
1053
|
headless: parseBool(process.env.OPENSTEER_HEADLESS),
|
|
@@ -1039,28 +1065,38 @@ function resolveConfig(input = {}) {
|
|
|
1039
1065
|
const resolved = mergeDeep(mergedWithEnv, input);
|
|
1040
1066
|
const envApiKey = resolveOpensteerApiKey();
|
|
1041
1067
|
const envAuthScheme = resolveOpensteerAuthScheme();
|
|
1042
|
-
const
|
|
1068
|
+
const envCloudAnnounce = parseCloudAnnounce(
|
|
1069
|
+
process.env.OPENSTEER_REMOTE_ANNOUNCE,
|
|
1070
|
+
"OPENSTEER_REMOTE_ANNOUNCE"
|
|
1071
|
+
);
|
|
1072
|
+
const inputCloudOptions = normalizeCloudOptions(input.cloud);
|
|
1043
1073
|
const inputAuthScheme = parseAuthScheme(
|
|
1044
|
-
|
|
1045
|
-
"
|
|
1074
|
+
inputCloudOptions?.authScheme,
|
|
1075
|
+
"cloud.authScheme"
|
|
1046
1076
|
);
|
|
1047
|
-
const
|
|
1048
|
-
|
|
1077
|
+
const inputCloudAnnounce = parseCloudAnnounce(
|
|
1078
|
+
inputCloudOptions?.announce,
|
|
1079
|
+
"cloud.announce"
|
|
1049
1080
|
);
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1081
|
+
const inputHasCloudApiKey = Boolean(
|
|
1082
|
+
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "apiKey")
|
|
1083
|
+
);
|
|
1084
|
+
const cloudSelection = resolveCloudSelection({
|
|
1085
|
+
cloud: resolved.cloud
|
|
1052
1086
|
});
|
|
1053
|
-
if (
|
|
1054
|
-
const
|
|
1055
|
-
const authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1087
|
+
if (cloudSelection.cloud) {
|
|
1088
|
+
const resolvedCloud = normalizeCloudOptions(resolved.cloud) ?? {};
|
|
1089
|
+
const authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
|
|
1090
|
+
const announce = inputCloudAnnounce ?? envCloudAnnounce ?? parseCloudAnnounce(resolvedCloud.announce, "cloud.announce") ?? "always";
|
|
1091
|
+
resolved.cloud = {
|
|
1092
|
+
...resolvedCloud,
|
|
1093
|
+
authScheme,
|
|
1094
|
+
announce
|
|
1059
1095
|
};
|
|
1060
1096
|
}
|
|
1061
|
-
if (envApiKey &&
|
|
1062
|
-
resolved.
|
|
1063
|
-
...
|
|
1097
|
+
if (envApiKey && cloudSelection.cloud && !inputHasCloudApiKey) {
|
|
1098
|
+
resolved.cloud = {
|
|
1099
|
+
...normalizeCloudOptions(resolved.cloud) ?? {},
|
|
1064
1100
|
apiKey: envApiKey
|
|
1065
1101
|
};
|
|
1066
1102
|
}
|
|
@@ -7357,36 +7393,39 @@ function clonePersistedExtractNode(node) {
|
|
|
7357
7393
|
return JSON.parse(JSON.stringify(node));
|
|
7358
7394
|
}
|
|
7359
7395
|
|
|
7360
|
-
// src/
|
|
7396
|
+
// src/cloud/contracts.ts
|
|
7397
|
+
var cloudSessionContractVersion = "v3";
|
|
7398
|
+
|
|
7399
|
+
// src/cloud/action-ws-client.ts
|
|
7361
7400
|
var import_ws2 = __toESM(require("ws"), 1);
|
|
7362
7401
|
|
|
7363
|
-
// src/
|
|
7364
|
-
var
|
|
7402
|
+
// src/cloud/errors.ts
|
|
7403
|
+
var OpensteerCloudError = class extends Error {
|
|
7365
7404
|
code;
|
|
7366
7405
|
status;
|
|
7367
7406
|
details;
|
|
7368
7407
|
constructor(code, message, status, details) {
|
|
7369
7408
|
super(message);
|
|
7370
|
-
this.name = "
|
|
7409
|
+
this.name = "OpensteerCloudError";
|
|
7371
7410
|
this.code = code;
|
|
7372
7411
|
this.status = status;
|
|
7373
7412
|
this.details = details;
|
|
7374
7413
|
}
|
|
7375
7414
|
};
|
|
7376
|
-
function
|
|
7377
|
-
return new
|
|
7378
|
-
"
|
|
7379
|
-
message || `${method} is not supported in
|
|
7415
|
+
function cloudUnsupportedMethodError(method, message) {
|
|
7416
|
+
return new OpensteerCloudError(
|
|
7417
|
+
"CLOUD_UNSUPPORTED_METHOD",
|
|
7418
|
+
message || `${method} is not supported in cloud mode.`
|
|
7380
7419
|
);
|
|
7381
7420
|
}
|
|
7382
|
-
function
|
|
7383
|
-
return new
|
|
7384
|
-
"
|
|
7385
|
-
"
|
|
7421
|
+
function cloudNotLaunchedError() {
|
|
7422
|
+
return new OpensteerCloudError(
|
|
7423
|
+
"CLOUD_SESSION_NOT_FOUND",
|
|
7424
|
+
"Cloud session is not connected. Call launch() first."
|
|
7386
7425
|
);
|
|
7387
7426
|
}
|
|
7388
7427
|
|
|
7389
|
-
// src/
|
|
7428
|
+
// src/cloud/action-ws-client.ts
|
|
7390
7429
|
var ActionWsClient = class _ActionWsClient {
|
|
7391
7430
|
ws;
|
|
7392
7431
|
sessionId;
|
|
@@ -7403,18 +7442,18 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
7403
7442
|
});
|
|
7404
7443
|
ws.on("error", (error) => {
|
|
7405
7444
|
this.rejectAll(
|
|
7406
|
-
new
|
|
7407
|
-
"
|
|
7408
|
-
`
|
|
7445
|
+
new OpensteerCloudError(
|
|
7446
|
+
"CLOUD_TRANSPORT_ERROR",
|
|
7447
|
+
`Cloud action websocket error: ${error.message}`
|
|
7409
7448
|
)
|
|
7410
7449
|
);
|
|
7411
7450
|
});
|
|
7412
7451
|
ws.on("close", () => {
|
|
7413
7452
|
this.closed = true;
|
|
7414
7453
|
this.rejectAll(
|
|
7415
|
-
new
|
|
7416
|
-
"
|
|
7417
|
-
"
|
|
7454
|
+
new OpensteerCloudError(
|
|
7455
|
+
"CLOUD_SESSION_CLOSED",
|
|
7456
|
+
"Cloud action websocket closed."
|
|
7418
7457
|
)
|
|
7419
7458
|
);
|
|
7420
7459
|
});
|
|
@@ -7426,8 +7465,8 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
7426
7465
|
ws.once("open", () => resolve());
|
|
7427
7466
|
ws.once("error", (error) => {
|
|
7428
7467
|
reject(
|
|
7429
|
-
new
|
|
7430
|
-
"
|
|
7468
|
+
new OpensteerCloudError(
|
|
7469
|
+
"CLOUD_TRANSPORT_ERROR",
|
|
7431
7470
|
`Failed to connect action websocket: ${error.message}`
|
|
7432
7471
|
)
|
|
7433
7472
|
);
|
|
@@ -7437,9 +7476,9 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
7437
7476
|
}
|
|
7438
7477
|
async request(method, args) {
|
|
7439
7478
|
if (this.closed || this.ws.readyState !== import_ws2.default.OPEN) {
|
|
7440
|
-
throw new
|
|
7441
|
-
"
|
|
7442
|
-
"
|
|
7479
|
+
throw new OpensteerCloudError(
|
|
7480
|
+
"CLOUD_SESSION_CLOSED",
|
|
7481
|
+
"Cloud action websocket is closed."
|
|
7443
7482
|
);
|
|
7444
7483
|
}
|
|
7445
7484
|
const id = this.nextRequestId;
|
|
@@ -7458,8 +7497,8 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
7458
7497
|
this.ws.send(JSON.stringify(payload));
|
|
7459
7498
|
} catch (error) {
|
|
7460
7499
|
this.pending.delete(id);
|
|
7461
|
-
const message = error instanceof Error ? error.message : "Failed to send
|
|
7462
|
-
throw new
|
|
7500
|
+
const message = error instanceof Error ? error.message : "Failed to send cloud action request.";
|
|
7501
|
+
throw new OpensteerCloudError("CLOUD_TRANSPORT_ERROR", message);
|
|
7463
7502
|
}
|
|
7464
7503
|
return await resultPromise;
|
|
7465
7504
|
}
|
|
@@ -7477,9 +7516,9 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
7477
7516
|
parsed = JSON.parse(rawDataToUtf8(raw));
|
|
7478
7517
|
} catch {
|
|
7479
7518
|
this.rejectAll(
|
|
7480
|
-
new
|
|
7481
|
-
"
|
|
7482
|
-
"Invalid
|
|
7519
|
+
new OpensteerCloudError(
|
|
7520
|
+
"CLOUD_TRANSPORT_ERROR",
|
|
7521
|
+
"Invalid cloud action response payload."
|
|
7483
7522
|
)
|
|
7484
7523
|
);
|
|
7485
7524
|
return;
|
|
@@ -7492,7 +7531,7 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
7492
7531
|
return;
|
|
7493
7532
|
}
|
|
7494
7533
|
pending.reject(
|
|
7495
|
-
new
|
|
7534
|
+
new OpensteerCloudError(
|
|
7496
7535
|
parsed.code,
|
|
7497
7536
|
parsed.error,
|
|
7498
7537
|
void 0,
|
|
@@ -7520,7 +7559,7 @@ function withTokenQuery(wsUrl, token) {
|
|
|
7520
7559
|
return url.toString();
|
|
7521
7560
|
}
|
|
7522
7561
|
|
|
7523
|
-
// src/
|
|
7562
|
+
// src/cloud/local-cache-sync.ts
|
|
7524
7563
|
var import_fs3 = __toESM(require("fs"), 1);
|
|
7525
7564
|
var import_path5 = __toESM(require("path"), 1);
|
|
7526
7565
|
function collectLocalSelectorCacheEntries(storage) {
|
|
@@ -7644,24 +7683,24 @@ function dedupeNewest(entries) {
|
|
|
7644
7683
|
return [...byKey.values()];
|
|
7645
7684
|
}
|
|
7646
7685
|
|
|
7647
|
-
// src/
|
|
7686
|
+
// src/cloud/cdp-client.ts
|
|
7648
7687
|
var import_playwright2 = require("playwright");
|
|
7649
|
-
var
|
|
7688
|
+
var CloudCdpClient = class {
|
|
7650
7689
|
async connect(args) {
|
|
7651
7690
|
const endpoint = withTokenQuery2(args.wsUrl, args.token);
|
|
7652
7691
|
let browser;
|
|
7653
7692
|
try {
|
|
7654
7693
|
browser = await import_playwright2.chromium.connectOverCDP(endpoint);
|
|
7655
7694
|
} catch (error) {
|
|
7656
|
-
const message = error instanceof Error ? error.message : "Failed to connect to
|
|
7657
|
-
throw new
|
|
7695
|
+
const message = error instanceof Error ? error.message : "Failed to connect to cloud CDP endpoint.";
|
|
7696
|
+
throw new OpensteerCloudError("CLOUD_TRANSPORT_ERROR", message);
|
|
7658
7697
|
}
|
|
7659
7698
|
const context = browser.contexts()[0];
|
|
7660
7699
|
if (!context) {
|
|
7661
7700
|
await browser.close();
|
|
7662
|
-
throw new
|
|
7663
|
-
"
|
|
7664
|
-
"
|
|
7701
|
+
throw new OpensteerCloudError(
|
|
7702
|
+
"CLOUD_INTERNAL",
|
|
7703
|
+
"Cloud browser returned no context."
|
|
7665
7704
|
);
|
|
7666
7705
|
}
|
|
7667
7706
|
const page = context.pages()[0] || await context.newPage();
|
|
@@ -7674,9 +7713,9 @@ function withTokenQuery2(wsUrl, token) {
|
|
|
7674
7713
|
return url.toString();
|
|
7675
7714
|
}
|
|
7676
7715
|
|
|
7677
|
-
// src/
|
|
7716
|
+
// src/cloud/session-client.ts
|
|
7678
7717
|
var CACHE_IMPORT_BATCH_SIZE = 200;
|
|
7679
|
-
var
|
|
7718
|
+
var CloudSessionClient = class {
|
|
7680
7719
|
baseUrl;
|
|
7681
7720
|
key;
|
|
7682
7721
|
authScheme;
|
|
@@ -7697,7 +7736,17 @@ var RemoteSessionClient = class {
|
|
|
7697
7736
|
if (!response.ok) {
|
|
7698
7737
|
throw await parseHttpError(response);
|
|
7699
7738
|
}
|
|
7700
|
-
|
|
7739
|
+
let body;
|
|
7740
|
+
try {
|
|
7741
|
+
body = await response.json();
|
|
7742
|
+
} catch {
|
|
7743
|
+
throw new OpensteerCloudError(
|
|
7744
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
7745
|
+
"Invalid cloud session create response: expected a JSON object.",
|
|
7746
|
+
response.status
|
|
7747
|
+
);
|
|
7748
|
+
}
|
|
7749
|
+
return parseCreateResponse(body, response.status);
|
|
7701
7750
|
}
|
|
7702
7751
|
async close(sessionId) {
|
|
7703
7752
|
const response = await fetch(`${this.baseUrl}/sessions/${sessionId}`, {
|
|
@@ -7756,6 +7805,134 @@ var RemoteSessionClient = class {
|
|
|
7756
7805
|
function normalizeBaseUrl(baseUrl) {
|
|
7757
7806
|
return baseUrl.replace(/\/+$/, "");
|
|
7758
7807
|
}
|
|
7808
|
+
function parseCreateResponse(body, status) {
|
|
7809
|
+
const root = requireObject(
|
|
7810
|
+
body,
|
|
7811
|
+
"Invalid cloud session create response: expected a JSON object.",
|
|
7812
|
+
status
|
|
7813
|
+
);
|
|
7814
|
+
const sessionId = requireString(root, "sessionId", status);
|
|
7815
|
+
const actionWsUrl = requireString(root, "actionWsUrl", status);
|
|
7816
|
+
const cdpWsUrl = requireString(root, "cdpWsUrl", status);
|
|
7817
|
+
const actionToken = requireString(root, "actionToken", status);
|
|
7818
|
+
const cdpToken = requireString(root, "cdpToken", status);
|
|
7819
|
+
const cloudSessionUrl = requireString(root, "cloudSessionUrl", status);
|
|
7820
|
+
const cloudSessionRoot = requireObject(
|
|
7821
|
+
root.cloudSession,
|
|
7822
|
+
"Invalid cloud session create response: cloudSession must be an object.",
|
|
7823
|
+
status
|
|
7824
|
+
);
|
|
7825
|
+
const cloudSession = {
|
|
7826
|
+
sessionId: requireString(cloudSessionRoot, "sessionId", status, "cloudSession"),
|
|
7827
|
+
workspaceId: requireString(
|
|
7828
|
+
cloudSessionRoot,
|
|
7829
|
+
"workspaceId",
|
|
7830
|
+
status,
|
|
7831
|
+
"cloudSession"
|
|
7832
|
+
),
|
|
7833
|
+
state: requireString(cloudSessionRoot, "state", status, "cloudSession"),
|
|
7834
|
+
createdAt: requireNumber(cloudSessionRoot, "createdAt", status, "cloudSession"),
|
|
7835
|
+
sourceType: requireSourceType(cloudSessionRoot, "sourceType", status, "cloudSession"),
|
|
7836
|
+
sourceRef: optionalString(cloudSessionRoot, "sourceRef", status, "cloudSession"),
|
|
7837
|
+
label: optionalString(cloudSessionRoot, "label", status, "cloudSession")
|
|
7838
|
+
};
|
|
7839
|
+
const expiresAt = optionalNumber(root, "expiresAt", status);
|
|
7840
|
+
return {
|
|
7841
|
+
sessionId,
|
|
7842
|
+
actionWsUrl,
|
|
7843
|
+
cdpWsUrl,
|
|
7844
|
+
actionToken,
|
|
7845
|
+
cdpToken,
|
|
7846
|
+
expiresAt,
|
|
7847
|
+
cloudSessionUrl,
|
|
7848
|
+
cloudSession
|
|
7849
|
+
};
|
|
7850
|
+
}
|
|
7851
|
+
function requireObject(value, message, status) {
|
|
7852
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
7853
|
+
throw new OpensteerCloudError("CLOUD_CONTRACT_MISMATCH", message, status);
|
|
7854
|
+
}
|
|
7855
|
+
return value;
|
|
7856
|
+
}
|
|
7857
|
+
function requireString(source, field, status, parent) {
|
|
7858
|
+
const value = source[field];
|
|
7859
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
7860
|
+
throw new OpensteerCloudError(
|
|
7861
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
7862
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
7863
|
+
field,
|
|
7864
|
+
parent
|
|
7865
|
+
)} must be a non-empty string.`,
|
|
7866
|
+
status
|
|
7867
|
+
);
|
|
7868
|
+
}
|
|
7869
|
+
return value;
|
|
7870
|
+
}
|
|
7871
|
+
function requireNumber(source, field, status, parent) {
|
|
7872
|
+
const value = source[field];
|
|
7873
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
7874
|
+
throw new OpensteerCloudError(
|
|
7875
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
7876
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
7877
|
+
field,
|
|
7878
|
+
parent
|
|
7879
|
+
)} must be a finite number.`,
|
|
7880
|
+
status
|
|
7881
|
+
);
|
|
7882
|
+
}
|
|
7883
|
+
return value;
|
|
7884
|
+
}
|
|
7885
|
+
function optionalString(source, field, status, parent) {
|
|
7886
|
+
const value = source[field];
|
|
7887
|
+
if (value == null) {
|
|
7888
|
+
return void 0;
|
|
7889
|
+
}
|
|
7890
|
+
if (typeof value !== "string") {
|
|
7891
|
+
throw new OpensteerCloudError(
|
|
7892
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
7893
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
7894
|
+
field,
|
|
7895
|
+
parent
|
|
7896
|
+
)} must be a string when present.`,
|
|
7897
|
+
status
|
|
7898
|
+
);
|
|
7899
|
+
}
|
|
7900
|
+
return value;
|
|
7901
|
+
}
|
|
7902
|
+
function optionalNumber(source, field, status, parent) {
|
|
7903
|
+
const value = source[field];
|
|
7904
|
+
if (value == null) {
|
|
7905
|
+
return void 0;
|
|
7906
|
+
}
|
|
7907
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
7908
|
+
throw new OpensteerCloudError(
|
|
7909
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
7910
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
7911
|
+
field,
|
|
7912
|
+
parent
|
|
7913
|
+
)} must be a finite number when present.`,
|
|
7914
|
+
status
|
|
7915
|
+
);
|
|
7916
|
+
}
|
|
7917
|
+
return value;
|
|
7918
|
+
}
|
|
7919
|
+
function requireSourceType(source, field, status, parent) {
|
|
7920
|
+
const value = source[field];
|
|
7921
|
+
if (value === "agent-thread" || value === "agent-run" || value === "local-cloud" || value === "manual") {
|
|
7922
|
+
return value;
|
|
7923
|
+
}
|
|
7924
|
+
throw new OpensteerCloudError(
|
|
7925
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
7926
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
7927
|
+
field,
|
|
7928
|
+
parent
|
|
7929
|
+
)} must be one of "agent-thread", "agent-run", "local-cloud", or "manual".`,
|
|
7930
|
+
status
|
|
7931
|
+
);
|
|
7932
|
+
}
|
|
7933
|
+
function formatFieldPath(field, parent) {
|
|
7934
|
+
return parent ? `"${parent}.${field}"` : `"${field}"`;
|
|
7935
|
+
}
|
|
7759
7936
|
function zeroImportResponse() {
|
|
7760
7937
|
return {
|
|
7761
7938
|
imported: 0,
|
|
@@ -7779,33 +7956,46 @@ async function parseHttpError(response) {
|
|
|
7779
7956
|
} catch {
|
|
7780
7957
|
body = null;
|
|
7781
7958
|
}
|
|
7782
|
-
const code = typeof body?.code === "string" ?
|
|
7783
|
-
const message = typeof body?.error === "string" ? body.error : `
|
|
7784
|
-
return new
|
|
7959
|
+
const code = typeof body?.code === "string" ? toCloudErrorCode(body.code) : "CLOUD_TRANSPORT_ERROR";
|
|
7960
|
+
const message = typeof body?.error === "string" ? body.error : `Cloud request failed with status ${response.status}.`;
|
|
7961
|
+
return new OpensteerCloudError(code, message, response.status, body?.details);
|
|
7785
7962
|
}
|
|
7786
|
-
function
|
|
7787
|
-
if (code === "
|
|
7963
|
+
function toCloudErrorCode(code) {
|
|
7964
|
+
if (code === "CLOUD_AUTH_FAILED" || code === "CLOUD_SESSION_NOT_FOUND" || code === "CLOUD_SESSION_CLOSED" || code === "CLOUD_UNSUPPORTED_METHOD" || code === "CLOUD_INVALID_REQUEST" || code === "CLOUD_MODEL_NOT_ALLOWED" || code === "CLOUD_ACTION_FAILED" || code === "CLOUD_INTERNAL" || code === "CLOUD_CAPACITY_EXHAUSTED" || code === "CLOUD_RUNTIME_UNAVAILABLE" || code === "CLOUD_RUNTIME_MISMATCH" || code === "CLOUD_SESSION_STALE" || code === "CLOUD_CONTRACT_MISMATCH" || code === "CLOUD_CONTROL_PLANE_ERROR") {
|
|
7788
7965
|
return code;
|
|
7789
7966
|
}
|
|
7790
|
-
return "
|
|
7967
|
+
return "CLOUD_TRANSPORT_ERROR";
|
|
7791
7968
|
}
|
|
7792
7969
|
|
|
7793
|
-
// src/
|
|
7794
|
-
var
|
|
7795
|
-
|
|
7970
|
+
// src/cloud/runtime.ts
|
|
7971
|
+
var DEFAULT_CLOUD_BASE_URL = "https://remote.opensteer.com";
|
|
7972
|
+
var DEFAULT_CLOUD_APP_URL = "https://opensteer.com";
|
|
7973
|
+
function createCloudRuntimeState(key, baseUrl = resolveCloudBaseUrl(), authScheme = "api-key", appUrl = resolveCloudAppUrl()) {
|
|
7796
7974
|
return {
|
|
7797
|
-
sessionClient: new
|
|
7798
|
-
cdpClient: new
|
|
7975
|
+
sessionClient: new CloudSessionClient(baseUrl, key, authScheme),
|
|
7976
|
+
cdpClient: new CloudCdpClient(),
|
|
7977
|
+
appUrl: normalizeCloudAppUrl(appUrl),
|
|
7799
7978
|
actionClient: null,
|
|
7800
|
-
sessionId: null
|
|
7979
|
+
sessionId: null,
|
|
7980
|
+
localRunId: null,
|
|
7981
|
+
cloudSessionUrl: null
|
|
7801
7982
|
};
|
|
7802
7983
|
}
|
|
7803
|
-
function
|
|
7984
|
+
function resolveCloudBaseUrl() {
|
|
7804
7985
|
const value = process.env.OPENSTEER_BASE_URL?.trim();
|
|
7805
|
-
if (!value) return
|
|
7986
|
+
if (!value) return DEFAULT_CLOUD_BASE_URL;
|
|
7806
7987
|
return value.replace(/\/+$/, "");
|
|
7807
7988
|
}
|
|
7808
|
-
function
|
|
7989
|
+
function resolveCloudAppUrl() {
|
|
7990
|
+
const value = process.env.OPENSTEER_APP_URL?.trim();
|
|
7991
|
+
if (!value) return DEFAULT_CLOUD_APP_URL;
|
|
7992
|
+
return normalizeCloudAppUrl(value);
|
|
7993
|
+
}
|
|
7994
|
+
function normalizeCloudAppUrl(value) {
|
|
7995
|
+
if (!value) return null;
|
|
7996
|
+
return value.replace(/\/+$/, "");
|
|
7997
|
+
}
|
|
7998
|
+
function readCloudActionDescription(payload) {
|
|
7809
7999
|
const description = payload.description;
|
|
7810
8000
|
if (typeof description !== "string") return void 0;
|
|
7811
8001
|
const normalized = description.trim();
|
|
@@ -7813,7 +8003,7 @@ function readRemoteActionDescription(payload) {
|
|
|
7813
8003
|
}
|
|
7814
8004
|
|
|
7815
8005
|
// src/opensteer.ts
|
|
7816
|
-
var
|
|
8006
|
+
var CLOUD_INTERACTION_METHODS = /* @__PURE__ */ new Set([
|
|
7817
8007
|
"click",
|
|
7818
8008
|
"dblclick",
|
|
7819
8009
|
"rightclick",
|
|
@@ -7830,7 +8020,7 @@ var Opensteer = class _Opensteer {
|
|
|
7830
8020
|
namespace;
|
|
7831
8021
|
storage;
|
|
7832
8022
|
pool;
|
|
7833
|
-
|
|
8023
|
+
cloud;
|
|
7834
8024
|
browser = null;
|
|
7835
8025
|
pageRef = null;
|
|
7836
8026
|
contextRef = null;
|
|
@@ -7838,8 +8028,8 @@ var Opensteer = class _Opensteer {
|
|
|
7838
8028
|
snapshotCache = null;
|
|
7839
8029
|
constructor(config = {}) {
|
|
7840
8030
|
const resolved = resolveConfig(config);
|
|
7841
|
-
const
|
|
7842
|
-
|
|
8031
|
+
const cloudSelection = resolveCloudSelection({
|
|
8032
|
+
cloud: resolved.cloud
|
|
7843
8033
|
});
|
|
7844
8034
|
const model = resolved.model;
|
|
7845
8035
|
this.config = resolved;
|
|
@@ -7849,21 +8039,22 @@ var Opensteer = class _Opensteer {
|
|
|
7849
8039
|
this.namespace = resolveNamespace(resolved, rootDir);
|
|
7850
8040
|
this.storage = new LocalSelectorStorage(rootDir, this.namespace);
|
|
7851
8041
|
this.pool = new BrowserPool(resolved.browser || {});
|
|
7852
|
-
if (
|
|
7853
|
-
const
|
|
7854
|
-
const apiKey =
|
|
8042
|
+
if (cloudSelection.cloud) {
|
|
8043
|
+
const cloudConfig = resolved.cloud && typeof resolved.cloud === "object" ? resolved.cloud : void 0;
|
|
8044
|
+
const apiKey = cloudConfig?.apiKey?.trim();
|
|
7855
8045
|
if (!apiKey) {
|
|
7856
8046
|
throw new Error(
|
|
7857
|
-
"
|
|
8047
|
+
"Cloud mode requires a non-empty API key via cloud.apiKey or OPENSTEER_API_KEY."
|
|
7858
8048
|
);
|
|
7859
8049
|
}
|
|
7860
|
-
this.
|
|
8050
|
+
this.cloud = createCloudRuntimeState(
|
|
7861
8051
|
apiKey,
|
|
7862
|
-
|
|
7863
|
-
|
|
8052
|
+
cloudConfig?.baseUrl,
|
|
8053
|
+
cloudConfig?.authScheme,
|
|
8054
|
+
cloudConfig?.appUrl
|
|
7864
8055
|
);
|
|
7865
8056
|
} else {
|
|
7866
|
-
this.
|
|
8057
|
+
this.cloud = null;
|
|
7867
8058
|
}
|
|
7868
8059
|
}
|
|
7869
8060
|
createLazyResolveCallback(model) {
|
|
@@ -7901,32 +8092,32 @@ var Opensteer = class _Opensteer {
|
|
|
7901
8092
|
};
|
|
7902
8093
|
return extract;
|
|
7903
8094
|
}
|
|
7904
|
-
async
|
|
7905
|
-
const result = await this.
|
|
8095
|
+
async invokeCloudActionAndResetCache(method, args) {
|
|
8096
|
+
const result = await this.invokeCloudAction(method, args);
|
|
7906
8097
|
this.snapshotCache = null;
|
|
7907
8098
|
return result;
|
|
7908
8099
|
}
|
|
7909
|
-
async
|
|
7910
|
-
const actionClient = this.
|
|
7911
|
-
const sessionId = this.
|
|
8100
|
+
async invokeCloudAction(method, args) {
|
|
8101
|
+
const actionClient = this.cloud?.actionClient;
|
|
8102
|
+
const sessionId = this.cloud?.sessionId;
|
|
7912
8103
|
if (!actionClient || !sessionId) {
|
|
7913
|
-
throw
|
|
8104
|
+
throw cloudNotLaunchedError();
|
|
7914
8105
|
}
|
|
7915
8106
|
const payload = args && typeof args === "object" ? args : {};
|
|
7916
8107
|
try {
|
|
7917
8108
|
return await actionClient.request(method, payload);
|
|
7918
8109
|
} catch (err) {
|
|
7919
|
-
if (err instanceof
|
|
8110
|
+
if (err instanceof OpensteerCloudError && err.code === "CLOUD_ACTION_FAILED" && CLOUD_INTERACTION_METHODS.has(method)) {
|
|
7920
8111
|
const detailsRecord = err.details && typeof err.details === "object" ? err.details : null;
|
|
7921
|
-
const
|
|
8112
|
+
const cloudFailure = normalizeActionFailure(
|
|
7922
8113
|
detailsRecord?.actionFailure
|
|
7923
8114
|
);
|
|
7924
|
-
const failure =
|
|
8115
|
+
const failure = cloudFailure || classifyActionFailure({
|
|
7925
8116
|
action: method,
|
|
7926
8117
|
error: err,
|
|
7927
8118
|
fallbackMessage: defaultActionFailureMessage(method)
|
|
7928
8119
|
});
|
|
7929
|
-
const description =
|
|
8120
|
+
const description = readCloudActionDescription(payload);
|
|
7930
8121
|
throw this.buildActionError(
|
|
7931
8122
|
method,
|
|
7932
8123
|
description,
|
|
@@ -7967,8 +8158,36 @@ var Opensteer = class _Opensteer {
|
|
|
7967
8158
|
}
|
|
7968
8159
|
return this.contextRef;
|
|
7969
8160
|
}
|
|
7970
|
-
|
|
7971
|
-
return this.
|
|
8161
|
+
getCloudSessionId() {
|
|
8162
|
+
return this.cloud?.sessionId ?? null;
|
|
8163
|
+
}
|
|
8164
|
+
getCloudSessionUrl() {
|
|
8165
|
+
return this.cloud?.cloudSessionUrl ?? null;
|
|
8166
|
+
}
|
|
8167
|
+
announceCloudSession(args) {
|
|
8168
|
+
if (!this.shouldAnnounceCloudSession()) {
|
|
8169
|
+
return;
|
|
8170
|
+
}
|
|
8171
|
+
const fields = [
|
|
8172
|
+
`sessionId=${args.sessionId}`,
|
|
8173
|
+
`workspaceId=${args.workspaceId}`
|
|
8174
|
+
];
|
|
8175
|
+
if (args.cloudSessionUrl) {
|
|
8176
|
+
fields.push(`url=${args.cloudSessionUrl}`);
|
|
8177
|
+
}
|
|
8178
|
+
process.stderr.write(`[opensteer] cloud session ready ${fields.join(" ")}
|
|
8179
|
+
`);
|
|
8180
|
+
}
|
|
8181
|
+
shouldAnnounceCloudSession() {
|
|
8182
|
+
const cloudConfig = this.config.cloud && typeof this.config.cloud === "object" ? this.config.cloud : null;
|
|
8183
|
+
const announce = cloudConfig?.announce ?? "always";
|
|
8184
|
+
if (announce === "off") {
|
|
8185
|
+
return false;
|
|
8186
|
+
}
|
|
8187
|
+
if (announce === "tty") {
|
|
8188
|
+
return Boolean(process.stderr.isTTY);
|
|
8189
|
+
}
|
|
8190
|
+
return true;
|
|
7972
8191
|
}
|
|
7973
8192
|
async launch(options = {}) {
|
|
7974
8193
|
if (this.pageRef && !this.ownsBrowser) {
|
|
@@ -7979,22 +8198,29 @@ var Opensteer = class _Opensteer {
|
|
|
7979
8198
|
if (this.pageRef && this.ownsBrowser) {
|
|
7980
8199
|
return;
|
|
7981
8200
|
}
|
|
7982
|
-
if (this.
|
|
8201
|
+
if (this.cloud) {
|
|
7983
8202
|
let actionClient = null;
|
|
7984
8203
|
let browser = null;
|
|
7985
8204
|
let sessionId = null;
|
|
8205
|
+
let localRunId = null;
|
|
7986
8206
|
try {
|
|
7987
8207
|
try {
|
|
7988
|
-
await this.
|
|
8208
|
+
await this.syncLocalSelectorCacheToCloud();
|
|
7989
8209
|
} catch (error) {
|
|
7990
8210
|
if (this.config.debug) {
|
|
7991
8211
|
const message = error instanceof Error ? error.message : String(error);
|
|
7992
8212
|
console.warn(
|
|
7993
|
-
`[opensteer]
|
|
8213
|
+
`[opensteer] cloud selector cache sync failed: ${message}`
|
|
7994
8214
|
);
|
|
7995
8215
|
}
|
|
7996
8216
|
}
|
|
7997
|
-
|
|
8217
|
+
localRunId = this.cloud.localRunId || buildLocalRunId(this.namespace);
|
|
8218
|
+
this.cloud.localRunId = localRunId;
|
|
8219
|
+
const session3 = await this.cloud.sessionClient.create({
|
|
8220
|
+
cloudSessionContractVersion,
|
|
8221
|
+
sourceType: "local-cloud",
|
|
8222
|
+
clientSessionHint: this.namespace,
|
|
8223
|
+
localRunId,
|
|
7998
8224
|
name: this.namespace,
|
|
7999
8225
|
model: this.config.model,
|
|
8000
8226
|
launchContext: options.context || void 0
|
|
@@ -8005,7 +8231,7 @@ var Opensteer = class _Opensteer {
|
|
|
8005
8231
|
token: session3.actionToken,
|
|
8006
8232
|
sessionId: session3.sessionId
|
|
8007
8233
|
});
|
|
8008
|
-
const cdpConnection = await this.
|
|
8234
|
+
const cdpConnection = await this.cloud.cdpClient.connect({
|
|
8009
8235
|
wsUrl: session3.cdpWsUrl,
|
|
8010
8236
|
token: session3.cdpToken
|
|
8011
8237
|
});
|
|
@@ -8015,8 +8241,17 @@ var Opensteer = class _Opensteer {
|
|
|
8015
8241
|
this.pageRef = cdpConnection.page;
|
|
8016
8242
|
this.ownsBrowser = true;
|
|
8017
8243
|
this.snapshotCache = null;
|
|
8018
|
-
this.
|
|
8019
|
-
this.
|
|
8244
|
+
this.cloud.actionClient = actionClient;
|
|
8245
|
+
this.cloud.sessionId = sessionId;
|
|
8246
|
+
this.cloud.cloudSessionUrl = buildCloudSessionUrl(
|
|
8247
|
+
this.cloud.appUrl,
|
|
8248
|
+
session3.cloudSession.sessionId
|
|
8249
|
+
);
|
|
8250
|
+
this.announceCloudSession({
|
|
8251
|
+
sessionId: session3.sessionId,
|
|
8252
|
+
workspaceId: session3.cloudSession.workspaceId,
|
|
8253
|
+
cloudSessionUrl: this.cloud.cloudSessionUrl
|
|
8254
|
+
});
|
|
8020
8255
|
return;
|
|
8021
8256
|
} catch (error) {
|
|
8022
8257
|
if (actionClient) {
|
|
@@ -8026,8 +8261,9 @@ var Opensteer = class _Opensteer {
|
|
|
8026
8261
|
await browser.close().catch(() => void 0);
|
|
8027
8262
|
}
|
|
8028
8263
|
if (sessionId) {
|
|
8029
|
-
await this.
|
|
8264
|
+
await this.cloud.sessionClient.close(sessionId).catch(() => void 0);
|
|
8030
8265
|
}
|
|
8266
|
+
this.cloud.cloudSessionUrl = null;
|
|
8031
8267
|
throw error;
|
|
8032
8268
|
}
|
|
8033
8269
|
}
|
|
@@ -8045,13 +8281,13 @@ var Opensteer = class _Opensteer {
|
|
|
8045
8281
|
}
|
|
8046
8282
|
static from(page, config = {}) {
|
|
8047
8283
|
const resolvedConfig = resolveConfig(config);
|
|
8048
|
-
const
|
|
8049
|
-
|
|
8284
|
+
const cloudSelection = resolveCloudSelection({
|
|
8285
|
+
cloud: resolvedConfig.cloud
|
|
8050
8286
|
});
|
|
8051
|
-
if (
|
|
8052
|
-
throw
|
|
8287
|
+
if (cloudSelection.cloud) {
|
|
8288
|
+
throw cloudUnsupportedMethodError(
|
|
8053
8289
|
"Opensteer.from(page)",
|
|
8054
|
-
"Opensteer.from(page) is not supported in
|
|
8290
|
+
"Opensteer.from(page) is not supported in cloud mode."
|
|
8055
8291
|
);
|
|
8056
8292
|
}
|
|
8057
8293
|
const instance2 = new _Opensteer(config);
|
|
@@ -8064,12 +8300,14 @@ var Opensteer = class _Opensteer {
|
|
|
8064
8300
|
}
|
|
8065
8301
|
async close() {
|
|
8066
8302
|
this.snapshotCache = null;
|
|
8067
|
-
if (this.
|
|
8068
|
-
const actionClient = this.
|
|
8069
|
-
const sessionId = this.
|
|
8303
|
+
if (this.cloud) {
|
|
8304
|
+
const actionClient = this.cloud.actionClient;
|
|
8305
|
+
const sessionId = this.cloud.sessionId;
|
|
8070
8306
|
const browser = this.browser;
|
|
8071
|
-
this.
|
|
8072
|
-
this.
|
|
8307
|
+
this.cloud.actionClient = null;
|
|
8308
|
+
this.cloud.sessionId = null;
|
|
8309
|
+
this.cloud.localRunId = null;
|
|
8310
|
+
this.cloud.cloudSessionUrl = null;
|
|
8073
8311
|
this.browser = null;
|
|
8074
8312
|
this.pageRef = null;
|
|
8075
8313
|
this.contextRef = null;
|
|
@@ -8081,7 +8319,7 @@ var Opensteer = class _Opensteer {
|
|
|
8081
8319
|
await browser.close().catch(() => void 0);
|
|
8082
8320
|
}
|
|
8083
8321
|
if (sessionId) {
|
|
8084
|
-
await this.
|
|
8322
|
+
await this.cloud.sessionClient.close(sessionId).catch(() => void 0);
|
|
8085
8323
|
}
|
|
8086
8324
|
return;
|
|
8087
8325
|
}
|
|
@@ -8093,17 +8331,17 @@ var Opensteer = class _Opensteer {
|
|
|
8093
8331
|
this.contextRef = null;
|
|
8094
8332
|
this.ownsBrowser = false;
|
|
8095
8333
|
}
|
|
8096
|
-
async
|
|
8097
|
-
if (!this.
|
|
8334
|
+
async syncLocalSelectorCacheToCloud() {
|
|
8335
|
+
if (!this.cloud) return;
|
|
8098
8336
|
const entries = collectLocalSelectorCacheEntries(this.storage);
|
|
8099
8337
|
if (!entries.length) return;
|
|
8100
|
-
await this.
|
|
8338
|
+
await this.cloud.sessionClient.importSelectorCache({
|
|
8101
8339
|
entries
|
|
8102
8340
|
});
|
|
8103
8341
|
}
|
|
8104
8342
|
async goto(url, options) {
|
|
8105
|
-
if (this.
|
|
8106
|
-
await this.
|
|
8343
|
+
if (this.cloud) {
|
|
8344
|
+
await this.invokeCloudActionAndResetCache("goto", { url, options });
|
|
8107
8345
|
return;
|
|
8108
8346
|
}
|
|
8109
8347
|
const { waitUntil = "domcontentloaded", ...rest } = options ?? {};
|
|
@@ -8112,8 +8350,8 @@ var Opensteer = class _Opensteer {
|
|
|
8112
8350
|
this.snapshotCache = null;
|
|
8113
8351
|
}
|
|
8114
8352
|
async snapshot(options = {}) {
|
|
8115
|
-
if (this.
|
|
8116
|
-
return await this.
|
|
8353
|
+
if (this.cloud) {
|
|
8354
|
+
return await this.invokeCloudActionAndResetCache("snapshot", {
|
|
8117
8355
|
options
|
|
8118
8356
|
});
|
|
8119
8357
|
}
|
|
@@ -8122,8 +8360,8 @@ var Opensteer = class _Opensteer {
|
|
|
8122
8360
|
return prepared.cleanedHtml;
|
|
8123
8361
|
}
|
|
8124
8362
|
async state() {
|
|
8125
|
-
if (this.
|
|
8126
|
-
return await this.
|
|
8363
|
+
if (this.cloud) {
|
|
8364
|
+
return await this.invokeCloudAction("state", {});
|
|
8127
8365
|
}
|
|
8128
8366
|
const html = await this.snapshot({ mode: "action" });
|
|
8129
8367
|
return {
|
|
@@ -8133,8 +8371,8 @@ var Opensteer = class _Opensteer {
|
|
|
8133
8371
|
};
|
|
8134
8372
|
}
|
|
8135
8373
|
async screenshot(options = {}) {
|
|
8136
|
-
if (this.
|
|
8137
|
-
const b64 = await this.
|
|
8374
|
+
if (this.cloud) {
|
|
8375
|
+
const b64 = await this.invokeCloudAction(
|
|
8138
8376
|
"screenshot",
|
|
8139
8377
|
options
|
|
8140
8378
|
);
|
|
@@ -8148,8 +8386,8 @@ var Opensteer = class _Opensteer {
|
|
|
8148
8386
|
});
|
|
8149
8387
|
}
|
|
8150
8388
|
async click(options) {
|
|
8151
|
-
if (this.
|
|
8152
|
-
return await this.
|
|
8389
|
+
if (this.cloud) {
|
|
8390
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8153
8391
|
"click",
|
|
8154
8392
|
options
|
|
8155
8393
|
);
|
|
@@ -8161,8 +8399,8 @@ var Opensteer = class _Opensteer {
|
|
|
8161
8399
|
});
|
|
8162
8400
|
}
|
|
8163
8401
|
async dblclick(options) {
|
|
8164
|
-
if (this.
|
|
8165
|
-
return await this.
|
|
8402
|
+
if (this.cloud) {
|
|
8403
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8166
8404
|
"dblclick",
|
|
8167
8405
|
options
|
|
8168
8406
|
);
|
|
@@ -8174,8 +8412,8 @@ var Opensteer = class _Opensteer {
|
|
|
8174
8412
|
});
|
|
8175
8413
|
}
|
|
8176
8414
|
async rightclick(options) {
|
|
8177
|
-
if (this.
|
|
8178
|
-
return await this.
|
|
8415
|
+
if (this.cloud) {
|
|
8416
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8179
8417
|
"rightclick",
|
|
8180
8418
|
options
|
|
8181
8419
|
);
|
|
@@ -8187,8 +8425,8 @@ var Opensteer = class _Opensteer {
|
|
|
8187
8425
|
});
|
|
8188
8426
|
}
|
|
8189
8427
|
async hover(options) {
|
|
8190
|
-
if (this.
|
|
8191
|
-
return await this.
|
|
8428
|
+
if (this.cloud) {
|
|
8429
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8192
8430
|
"hover",
|
|
8193
8431
|
options
|
|
8194
8432
|
);
|
|
@@ -8286,8 +8524,8 @@ var Opensteer = class _Opensteer {
|
|
|
8286
8524
|
);
|
|
8287
8525
|
}
|
|
8288
8526
|
async input(options) {
|
|
8289
|
-
if (this.
|
|
8290
|
-
return await this.
|
|
8527
|
+
if (this.cloud) {
|
|
8528
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8291
8529
|
"input",
|
|
8292
8530
|
options
|
|
8293
8531
|
);
|
|
@@ -8389,8 +8627,8 @@ var Opensteer = class _Opensteer {
|
|
|
8389
8627
|
);
|
|
8390
8628
|
}
|
|
8391
8629
|
async select(options) {
|
|
8392
|
-
if (this.
|
|
8393
|
-
return await this.
|
|
8630
|
+
if (this.cloud) {
|
|
8631
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8394
8632
|
"select",
|
|
8395
8633
|
options
|
|
8396
8634
|
);
|
|
@@ -8499,8 +8737,8 @@ var Opensteer = class _Opensteer {
|
|
|
8499
8737
|
);
|
|
8500
8738
|
}
|
|
8501
8739
|
async scroll(options = {}) {
|
|
8502
|
-
if (this.
|
|
8503
|
-
return await this.
|
|
8740
|
+
if (this.cloud) {
|
|
8741
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8504
8742
|
"scroll",
|
|
8505
8743
|
options
|
|
8506
8744
|
);
|
|
@@ -8601,14 +8839,14 @@ var Opensteer = class _Opensteer {
|
|
|
8601
8839
|
}
|
|
8602
8840
|
// --- Tab Management ---
|
|
8603
8841
|
async tabs() {
|
|
8604
|
-
if (this.
|
|
8605
|
-
return await this.
|
|
8842
|
+
if (this.cloud) {
|
|
8843
|
+
return await this.invokeCloudAction("tabs", {});
|
|
8606
8844
|
}
|
|
8607
8845
|
return listTabs(this.context, this.page);
|
|
8608
8846
|
}
|
|
8609
8847
|
async newTab(url) {
|
|
8610
|
-
if (this.
|
|
8611
|
-
return await this.
|
|
8848
|
+
if (this.cloud) {
|
|
8849
|
+
return await this.invokeCloudActionAndResetCache("newTab", {
|
|
8612
8850
|
url
|
|
8613
8851
|
});
|
|
8614
8852
|
}
|
|
@@ -8618,8 +8856,8 @@ var Opensteer = class _Opensteer {
|
|
|
8618
8856
|
return info;
|
|
8619
8857
|
}
|
|
8620
8858
|
async switchTab(index) {
|
|
8621
|
-
if (this.
|
|
8622
|
-
await this.
|
|
8859
|
+
if (this.cloud) {
|
|
8860
|
+
await this.invokeCloudActionAndResetCache("switchTab", { index });
|
|
8623
8861
|
return;
|
|
8624
8862
|
}
|
|
8625
8863
|
const page = await switchTab(this.context, index);
|
|
@@ -8627,8 +8865,8 @@ var Opensteer = class _Opensteer {
|
|
|
8627
8865
|
this.snapshotCache = null;
|
|
8628
8866
|
}
|
|
8629
8867
|
async closeTab(index) {
|
|
8630
|
-
if (this.
|
|
8631
|
-
await this.
|
|
8868
|
+
if (this.cloud) {
|
|
8869
|
+
await this.invokeCloudActionAndResetCache("closeTab", { index });
|
|
8632
8870
|
return;
|
|
8633
8871
|
}
|
|
8634
8872
|
const newPage = await closeTab(this.context, this.page, index);
|
|
@@ -8639,8 +8877,8 @@ var Opensteer = class _Opensteer {
|
|
|
8639
8877
|
}
|
|
8640
8878
|
// --- Cookie Management ---
|
|
8641
8879
|
async getCookies(url) {
|
|
8642
|
-
if (this.
|
|
8643
|
-
return await this.
|
|
8880
|
+
if (this.cloud) {
|
|
8881
|
+
return await this.invokeCloudAction(
|
|
8644
8882
|
"getCookies",
|
|
8645
8883
|
{ url }
|
|
8646
8884
|
);
|
|
@@ -8648,41 +8886,41 @@ var Opensteer = class _Opensteer {
|
|
|
8648
8886
|
return getCookies(this.context, url);
|
|
8649
8887
|
}
|
|
8650
8888
|
async setCookie(cookie) {
|
|
8651
|
-
if (this.
|
|
8652
|
-
await this.
|
|
8889
|
+
if (this.cloud) {
|
|
8890
|
+
await this.invokeCloudAction("setCookie", cookie);
|
|
8653
8891
|
return;
|
|
8654
8892
|
}
|
|
8655
8893
|
return setCookie(this.context, cookie);
|
|
8656
8894
|
}
|
|
8657
8895
|
async clearCookies() {
|
|
8658
|
-
if (this.
|
|
8659
|
-
await this.
|
|
8896
|
+
if (this.cloud) {
|
|
8897
|
+
await this.invokeCloudAction("clearCookies", {});
|
|
8660
8898
|
return;
|
|
8661
8899
|
}
|
|
8662
8900
|
return clearCookies(this.context);
|
|
8663
8901
|
}
|
|
8664
8902
|
async exportCookies(filePath, url) {
|
|
8665
|
-
if (this.
|
|
8666
|
-
throw
|
|
8903
|
+
if (this.cloud) {
|
|
8904
|
+
throw cloudUnsupportedMethodError(
|
|
8667
8905
|
"exportCookies",
|
|
8668
|
-
"exportCookies() is not supported in
|
|
8906
|
+
"exportCookies() is not supported in cloud mode because it depends on local filesystem paths."
|
|
8669
8907
|
);
|
|
8670
8908
|
}
|
|
8671
8909
|
return exportCookies(this.context, filePath, url);
|
|
8672
8910
|
}
|
|
8673
8911
|
async importCookies(filePath) {
|
|
8674
|
-
if (this.
|
|
8675
|
-
throw
|
|
8912
|
+
if (this.cloud) {
|
|
8913
|
+
throw cloudUnsupportedMethodError(
|
|
8676
8914
|
"importCookies",
|
|
8677
|
-
"importCookies() is not supported in
|
|
8915
|
+
"importCookies() is not supported in cloud mode because it depends on local filesystem paths."
|
|
8678
8916
|
);
|
|
8679
8917
|
}
|
|
8680
8918
|
return importCookies(this.context, filePath);
|
|
8681
8919
|
}
|
|
8682
8920
|
// --- Keyboard Input ---
|
|
8683
8921
|
async pressKey(key) {
|
|
8684
|
-
if (this.
|
|
8685
|
-
await this.
|
|
8922
|
+
if (this.cloud) {
|
|
8923
|
+
await this.invokeCloudActionAndResetCache("pressKey", { key });
|
|
8686
8924
|
return;
|
|
8687
8925
|
}
|
|
8688
8926
|
await this.runWithPostActionWait("pressKey", void 0, async () => {
|
|
@@ -8691,8 +8929,8 @@ var Opensteer = class _Opensteer {
|
|
|
8691
8929
|
this.snapshotCache = null;
|
|
8692
8930
|
}
|
|
8693
8931
|
async type(text) {
|
|
8694
|
-
if (this.
|
|
8695
|
-
await this.
|
|
8932
|
+
if (this.cloud) {
|
|
8933
|
+
await this.invokeCloudActionAndResetCache("type", { text });
|
|
8696
8934
|
return;
|
|
8697
8935
|
}
|
|
8698
8936
|
await this.runWithPostActionWait("type", void 0, async () => {
|
|
@@ -8702,8 +8940,8 @@ var Opensteer = class _Opensteer {
|
|
|
8702
8940
|
}
|
|
8703
8941
|
// --- Element Info ---
|
|
8704
8942
|
async getElementText(options) {
|
|
8705
|
-
if (this.
|
|
8706
|
-
return await this.
|
|
8943
|
+
if (this.cloud) {
|
|
8944
|
+
return await this.invokeCloudAction("getElementText", options);
|
|
8707
8945
|
}
|
|
8708
8946
|
return this.executeElementInfoAction(
|
|
8709
8947
|
"getElementText",
|
|
@@ -8716,8 +8954,8 @@ var Opensteer = class _Opensteer {
|
|
|
8716
8954
|
);
|
|
8717
8955
|
}
|
|
8718
8956
|
async getElementValue(options) {
|
|
8719
|
-
if (this.
|
|
8720
|
-
return await this.
|
|
8957
|
+
if (this.cloud) {
|
|
8958
|
+
return await this.invokeCloudAction(
|
|
8721
8959
|
"getElementValue",
|
|
8722
8960
|
options
|
|
8723
8961
|
);
|
|
@@ -8732,8 +8970,8 @@ var Opensteer = class _Opensteer {
|
|
|
8732
8970
|
);
|
|
8733
8971
|
}
|
|
8734
8972
|
async getElementAttributes(options) {
|
|
8735
|
-
if (this.
|
|
8736
|
-
return await this.
|
|
8973
|
+
if (this.cloud) {
|
|
8974
|
+
return await this.invokeCloudAction(
|
|
8737
8975
|
"getElementAttributes",
|
|
8738
8976
|
options
|
|
8739
8977
|
);
|
|
@@ -8754,8 +8992,8 @@ var Opensteer = class _Opensteer {
|
|
|
8754
8992
|
);
|
|
8755
8993
|
}
|
|
8756
8994
|
async getElementBoundingBox(options) {
|
|
8757
|
-
if (this.
|
|
8758
|
-
return await this.
|
|
8995
|
+
if (this.cloud) {
|
|
8996
|
+
return await this.invokeCloudAction(
|
|
8759
8997
|
"getElementBoundingBox",
|
|
8760
8998
|
options
|
|
8761
8999
|
);
|
|
@@ -8770,14 +9008,14 @@ var Opensteer = class _Opensteer {
|
|
|
8770
9008
|
);
|
|
8771
9009
|
}
|
|
8772
9010
|
async getHtml(selector) {
|
|
8773
|
-
if (this.
|
|
8774
|
-
return await this.
|
|
9011
|
+
if (this.cloud) {
|
|
9012
|
+
return await this.invokeCloudAction("getHtml", { selector });
|
|
8775
9013
|
}
|
|
8776
9014
|
return getPageHtml(this.page, selector);
|
|
8777
9015
|
}
|
|
8778
9016
|
async getTitle() {
|
|
8779
|
-
if (this.
|
|
8780
|
-
return await this.
|
|
9017
|
+
if (this.cloud) {
|
|
9018
|
+
return await this.invokeCloudAction("getTitle", {});
|
|
8781
9019
|
}
|
|
8782
9020
|
return getPageTitle(this.page);
|
|
8783
9021
|
}
|
|
@@ -8815,10 +9053,10 @@ var Opensteer = class _Opensteer {
|
|
|
8815
9053
|
}
|
|
8816
9054
|
// --- File Upload ---
|
|
8817
9055
|
async uploadFile(options) {
|
|
8818
|
-
if (this.
|
|
8819
|
-
throw
|
|
9056
|
+
if (this.cloud) {
|
|
9057
|
+
throw cloudUnsupportedMethodError(
|
|
8820
9058
|
"uploadFile",
|
|
8821
|
-
"uploadFile() is not supported in
|
|
9059
|
+
"uploadFile() is not supported in cloud mode because file paths must be accessible on the cloud runtime."
|
|
8822
9060
|
);
|
|
8823
9061
|
}
|
|
8824
9062
|
const storageKey = this.resolveStorageKey(options.description);
|
|
@@ -8920,15 +9158,15 @@ var Opensteer = class _Opensteer {
|
|
|
8920
9158
|
}
|
|
8921
9159
|
// --- Wait for Text ---
|
|
8922
9160
|
async waitForText(text, options) {
|
|
8923
|
-
if (this.
|
|
8924
|
-
await this.
|
|
9161
|
+
if (this.cloud) {
|
|
9162
|
+
await this.invokeCloudAction("waitForText", { text, options });
|
|
8925
9163
|
return;
|
|
8926
9164
|
}
|
|
8927
9165
|
await this.page.getByText(text).first().waitFor({ timeout: options?.timeout ?? 3e4 });
|
|
8928
9166
|
}
|
|
8929
9167
|
async extract(options) {
|
|
8930
|
-
if (this.
|
|
8931
|
-
return await this.
|
|
9168
|
+
if (this.cloud) {
|
|
9169
|
+
return await this.invokeCloudAction("extract", options);
|
|
8932
9170
|
}
|
|
8933
9171
|
const storageKey = this.resolveStorageKey(options.description);
|
|
8934
9172
|
const schemaHash = options.schema ? computeSchemaHash(options.schema) : null;
|
|
@@ -8980,8 +9218,8 @@ var Opensteer = class _Opensteer {
|
|
|
8980
9218
|
return inflateDataPathObject(data);
|
|
8981
9219
|
}
|
|
8982
9220
|
async extractFromPlan(options) {
|
|
8983
|
-
if (this.
|
|
8984
|
-
return await this.
|
|
9221
|
+
if (this.cloud) {
|
|
9222
|
+
return await this.invokeCloudAction(
|
|
8985
9223
|
"extractFromPlan",
|
|
8986
9224
|
options
|
|
8987
9225
|
);
|
|
@@ -9030,10 +9268,10 @@ var Opensteer = class _Opensteer {
|
|
|
9030
9268
|
return this.storage;
|
|
9031
9269
|
}
|
|
9032
9270
|
clearCache() {
|
|
9033
|
-
if (this.
|
|
9271
|
+
if (this.cloud) {
|
|
9034
9272
|
this.snapshotCache = null;
|
|
9035
|
-
if (!this.
|
|
9036
|
-
void this.
|
|
9273
|
+
if (!this.cloud.actionClient) return;
|
|
9274
|
+
void this.invokeCloudAction("clearCache", {});
|
|
9037
9275
|
return;
|
|
9038
9276
|
}
|
|
9039
9277
|
this.storage.clearNamespace();
|
|
@@ -10061,6 +10299,16 @@ function getScrollDelta2(options) {
|
|
|
10061
10299
|
return { x: 0, y: absoluteAmount };
|
|
10062
10300
|
}
|
|
10063
10301
|
}
|
|
10302
|
+
function buildLocalRunId(namespace) {
|
|
10303
|
+
const normalized = namespace.trim() || "default";
|
|
10304
|
+
return `${normalized}-${Date.now().toString(36)}-${(0, import_crypto2.randomUUID)().slice(0, 8)}`;
|
|
10305
|
+
}
|
|
10306
|
+
function buildCloudSessionUrl(appUrl, sessionId) {
|
|
10307
|
+
if (!appUrl) {
|
|
10308
|
+
return null;
|
|
10309
|
+
}
|
|
10310
|
+
return `${appUrl}/browser/${encodeURIComponent(sessionId)}`;
|
|
10311
|
+
}
|
|
10064
10312
|
|
|
10065
10313
|
// src/cli/paths.ts
|
|
10066
10314
|
var import_os2 = require("os");
|
|
@@ -10462,7 +10710,8 @@ async function handleRequest(request, socket) {
|
|
|
10462
10710
|
url: instance.page.url(),
|
|
10463
10711
|
session,
|
|
10464
10712
|
name: activeNamespace,
|
|
10465
|
-
|
|
10713
|
+
cloudSessionId: instance.getCloudSessionId() ?? void 0,
|
|
10714
|
+
cloudSessionUrl: instance.getCloudSessionUrl() ?? void 0
|
|
10466
10715
|
}
|
|
10467
10716
|
});
|
|
10468
10717
|
} catch (err) {
|