opensteer 0.6.6 → 0.6.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/dist/browser-profile-client-CGXc0-P9.d.cts +228 -0
- package/dist/browser-profile-client-DHLzMf-K.d.ts +228 -0
- package/dist/{chunk-H27BERRF.js → chunk-C6AJL5XU.js} +7828 -7641
- package/dist/{chunk-KPPOTU3D.js → chunk-LTREUXLO.js} +140 -12
- package/dist/{chunk-6B6LOYU3.js → chunk-O4HVMKX2.js} +1 -1
- package/dist/{chunk-54KNQTOL.js → chunk-UQYVMJOZ.js} +27 -12
- package/dist/cli/auth.cjs +108 -11
- package/dist/cli/auth.d.cts +1 -1
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +2 -2
- package/dist/cli/profile.cjs +472 -186
- package/dist/cli/profile.d.cts +2 -2
- package/dist/cli/profile.d.ts +2 -2
- package/dist/cli/profile.js +4 -4
- package/dist/cli/server.cjs +453 -167
- package/dist/cli/server.js +2 -2
- package/dist/index.cjs +482 -165
- package/dist/index.d.cts +48 -5
- package/dist/index.d.ts +48 -5
- package/dist/index.js +34 -5
- package/dist/{types-BWItZPl_.d.cts → types-Cr10igF3.d.cts} +1 -1
- package/dist/{types-BWItZPl_.d.ts → types-Cr10igF3.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/browser-profile-client-D6PuRefA.d.cts +0 -168
- package/dist/browser-profile-client-OUHaODro.d.ts +0 -168
package/dist/index.cjs
CHANGED
|
@@ -421,6 +421,7 @@ var init_extractor = __esm({
|
|
|
421
421
|
var index_exports = {};
|
|
422
422
|
__export(index_exports, {
|
|
423
423
|
ActionWsClient: () => ActionWsClient,
|
|
424
|
+
BrowserPool: () => BrowserPool,
|
|
424
425
|
BrowserProfileClient: () => BrowserProfileClient,
|
|
425
426
|
CdpOverlayCursorRenderer: () => CdpOverlayCursorRenderer,
|
|
426
427
|
CloudCdpClient: () => CloudCdpClient,
|
|
@@ -459,10 +460,15 @@ __export(index_exports, {
|
|
|
459
460
|
cleanForFull: () => cleanForFull,
|
|
460
461
|
cleanForScrollable: () => cleanForScrollable,
|
|
461
462
|
clearCookies: () => clearCookies,
|
|
463
|
+
clearPersistentProfileSingletons: () => clearPersistentProfileSingletons,
|
|
462
464
|
cloneElementPath: () => cloneElementPath,
|
|
463
465
|
closeTab: () => closeTab,
|
|
466
|
+
cloudActionMethods: () => cloudActionMethods,
|
|
467
|
+
cloudErrorCodes: () => cloudErrorCodes,
|
|
464
468
|
cloudNotLaunchedError: () => cloudNotLaunchedError,
|
|
465
469
|
cloudSessionContractVersion: () => cloudSessionContractVersion,
|
|
470
|
+
cloudSessionSourceTypes: () => cloudSessionSourceTypes,
|
|
471
|
+
cloudSessionStatuses: () => cloudSessionStatuses,
|
|
466
472
|
cloudUnsupportedMethodError: () => cloudUnsupportedMethodError,
|
|
467
473
|
collectLocalSelectorCacheEntries: () => collectLocalSelectorCacheEntries,
|
|
468
474
|
countArrayItemsWithPath: () => countArrayItemsWithPath,
|
|
@@ -471,6 +477,8 @@ __export(index_exports, {
|
|
|
471
477
|
createExtractCallback: () => createExtractCallback,
|
|
472
478
|
createResolveCallback: () => createResolveCallback,
|
|
473
479
|
createTab: () => createTab,
|
|
480
|
+
detectChromePaths: () => detectChromePaths,
|
|
481
|
+
expandHome: () => expandHome,
|
|
474
482
|
exportCookies: () => exportCookies,
|
|
475
483
|
extractArrayRowsWithPaths: () => extractArrayRowsWithPaths,
|
|
476
484
|
extractArrayWithPaths: () => extractArrayWithPaths,
|
|
@@ -481,9 +489,15 @@ __export(index_exports, {
|
|
|
481
489
|
getElementText: () => getElementText,
|
|
482
490
|
getElementValue: () => getElementValue,
|
|
483
491
|
getModelProvider: () => getModelProvider,
|
|
492
|
+
getOrCreatePersistentProfile: () => getOrCreatePersistentProfile,
|
|
484
493
|
getPageHtml: () => getPageHtml,
|
|
485
494
|
getPageTitle: () => getPageTitle,
|
|
486
495
|
importCookies: () => importCookies,
|
|
496
|
+
isCloudActionMethod: () => isCloudActionMethod,
|
|
497
|
+
isCloudErrorCode: () => isCloudErrorCode,
|
|
498
|
+
isCloudSessionSourceType: () => isCloudSessionSourceType,
|
|
499
|
+
isCloudSessionStatus: () => isCloudSessionStatus,
|
|
500
|
+
listLocalChromeProfiles: () => listLocalChromeProfiles,
|
|
487
501
|
listTabs: () => listTabs,
|
|
488
502
|
markInteractiveElements: () => markInteractiveElements,
|
|
489
503
|
normalizeNamespace: () => normalizeNamespace,
|
|
@@ -516,11 +530,8 @@ var import_crypto = require("crypto");
|
|
|
516
530
|
|
|
517
531
|
// src/browser/pool.ts
|
|
518
532
|
var import_node_child_process = require("child_process");
|
|
519
|
-
var
|
|
520
|
-
var import_promises = require("fs/promises");
|
|
533
|
+
var import_promises2 = require("fs/promises");
|
|
521
534
|
var import_node_net = require("net");
|
|
522
|
-
var import_node_os = require("os");
|
|
523
|
-
var import_node_path = require("path");
|
|
524
535
|
var import_playwright = require("playwright");
|
|
525
536
|
|
|
526
537
|
// src/browser/cdp-proxy.ts
|
|
@@ -1013,18 +1024,282 @@ function listLocalChromeProfiles(userDataDir = detectChromePaths().defaultUserDa
|
|
|
1013
1024
|
}
|
|
1014
1025
|
}
|
|
1015
1026
|
|
|
1027
|
+
// src/browser/persistent-profile.ts
|
|
1028
|
+
var import_node_crypto = require("crypto");
|
|
1029
|
+
var import_node_fs = require("fs");
|
|
1030
|
+
var import_promises = require("fs/promises");
|
|
1031
|
+
var import_node_os = require("os");
|
|
1032
|
+
var import_node_path = require("path");
|
|
1033
|
+
var OPENSTEER_META_FILE = ".opensteer-meta.json";
|
|
1034
|
+
var PROCESS_STARTED_AT_MS = Math.floor(Date.now() - process.uptime() * 1e3);
|
|
1035
|
+
var PROCESS_START_TIME_TOLERANCE_MS = 1e3;
|
|
1036
|
+
var CHROME_SINGLETON_ENTRIES = /* @__PURE__ */ new Set([
|
|
1037
|
+
"SingletonCookie",
|
|
1038
|
+
"SingletonLock",
|
|
1039
|
+
"SingletonSocket",
|
|
1040
|
+
"DevToolsActivePort",
|
|
1041
|
+
"lockfile"
|
|
1042
|
+
]);
|
|
1043
|
+
var COPY_SKIP_ENTRIES = /* @__PURE__ */ new Set([
|
|
1044
|
+
...CHROME_SINGLETON_ENTRIES,
|
|
1045
|
+
OPENSTEER_META_FILE
|
|
1046
|
+
]);
|
|
1047
|
+
var SKIPPED_ROOT_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1048
|
+
"Crash Reports",
|
|
1049
|
+
"Crashpad",
|
|
1050
|
+
"BrowserMetrics",
|
|
1051
|
+
"GrShaderCache",
|
|
1052
|
+
"ShaderCache",
|
|
1053
|
+
"GraphiteDawnCache",
|
|
1054
|
+
"component_crx_cache",
|
|
1055
|
+
"Crowd Deny",
|
|
1056
|
+
"hyphen-data",
|
|
1057
|
+
"OnDeviceHeadSuggestModel",
|
|
1058
|
+
"OptimizationGuidePredictionModels",
|
|
1059
|
+
"Segmentation Platform",
|
|
1060
|
+
"SmartCardDeviceNames",
|
|
1061
|
+
"WidevineCdm",
|
|
1062
|
+
"pnacl"
|
|
1063
|
+
]);
|
|
1064
|
+
async function getOrCreatePersistentProfile(sourceUserDataDir, profileDirectory, profilesRootDir = defaultPersistentProfilesRootDir()) {
|
|
1065
|
+
const resolvedSourceUserDataDir = expandHome(sourceUserDataDir);
|
|
1066
|
+
const targetUserDataDir = (0, import_node_path.join)(
|
|
1067
|
+
expandHome(profilesRootDir),
|
|
1068
|
+
buildPersistentProfileKey(resolvedSourceUserDataDir, profileDirectory)
|
|
1069
|
+
);
|
|
1070
|
+
const sourceProfileDir = (0, import_node_path.join)(resolvedSourceUserDataDir, profileDirectory);
|
|
1071
|
+
const metadata = buildPersistentProfileMetadata(
|
|
1072
|
+
resolvedSourceUserDataDir,
|
|
1073
|
+
profileDirectory
|
|
1074
|
+
);
|
|
1075
|
+
await (0, import_promises.mkdir)((0, import_node_path.dirname)(targetUserDataDir), { recursive: true });
|
|
1076
|
+
await cleanOrphanedTempDirs(
|
|
1077
|
+
(0, import_node_path.dirname)(targetUserDataDir),
|
|
1078
|
+
(0, import_node_path.basename)(targetUserDataDir)
|
|
1079
|
+
);
|
|
1080
|
+
if (!(0, import_node_fs.existsSync)(sourceProfileDir)) {
|
|
1081
|
+
throw new Error(
|
|
1082
|
+
`Chrome profile "${profileDirectory}" was not found in "${resolvedSourceUserDataDir}".`
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
const created = await createPersistentProfileClone(
|
|
1086
|
+
resolvedSourceUserDataDir,
|
|
1087
|
+
sourceProfileDir,
|
|
1088
|
+
targetUserDataDir,
|
|
1089
|
+
profileDirectory,
|
|
1090
|
+
metadata
|
|
1091
|
+
);
|
|
1092
|
+
await ensurePersistentProfileMetadata(targetUserDataDir, metadata);
|
|
1093
|
+
return {
|
|
1094
|
+
created,
|
|
1095
|
+
userDataDir: targetUserDataDir
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
async function clearPersistentProfileSingletons(userDataDir) {
|
|
1099
|
+
await Promise.all(
|
|
1100
|
+
[...CHROME_SINGLETON_ENTRIES].map(
|
|
1101
|
+
(entry) => (0, import_promises.rm)((0, import_node_path.join)(userDataDir, entry), {
|
|
1102
|
+
force: true,
|
|
1103
|
+
recursive: true
|
|
1104
|
+
}).catch(() => void 0)
|
|
1105
|
+
)
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
function buildPersistentProfileKey(sourceUserDataDir, profileDirectory) {
|
|
1109
|
+
const hash = (0, import_node_crypto.createHash)("sha256").update(`${sourceUserDataDir}\0${profileDirectory}`).digest("hex").slice(0, 16);
|
|
1110
|
+
const sourceLabel = sanitizePathSegment((0, import_node_path.basename)(sourceUserDataDir) || "user-data");
|
|
1111
|
+
const profileLabel = sanitizePathSegment(profileDirectory || "Default");
|
|
1112
|
+
return `${sourceLabel}-${profileLabel}-${hash}`;
|
|
1113
|
+
}
|
|
1114
|
+
function defaultPersistentProfilesRootDir() {
|
|
1115
|
+
return (0, import_node_path.join)((0, import_node_os.homedir)(), ".opensteer", "real-browser-profiles");
|
|
1116
|
+
}
|
|
1117
|
+
function sanitizePathSegment(value) {
|
|
1118
|
+
const sanitized = value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/-+/g, "-");
|
|
1119
|
+
return sanitized.replace(/^-|-$/g, "") || "profile";
|
|
1120
|
+
}
|
|
1121
|
+
function isProfileDirectory(userDataDir, entry) {
|
|
1122
|
+
return (0, import_node_fs.existsSync)((0, import_node_path.join)(userDataDir, entry, "Preferences"));
|
|
1123
|
+
}
|
|
1124
|
+
async function copyRootLevelEntries(sourceUserDataDir, targetUserDataDir, targetProfileDirectory) {
|
|
1125
|
+
let entries;
|
|
1126
|
+
try {
|
|
1127
|
+
entries = await (0, import_promises.readdir)(sourceUserDataDir);
|
|
1128
|
+
} catch {
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
const copyTasks = [];
|
|
1132
|
+
for (const entry of entries) {
|
|
1133
|
+
if (COPY_SKIP_ENTRIES.has(entry)) continue;
|
|
1134
|
+
if (entry === targetProfileDirectory) continue;
|
|
1135
|
+
const sourcePath = (0, import_node_path.join)(sourceUserDataDir, entry);
|
|
1136
|
+
const targetPath = (0, import_node_path.join)(targetUserDataDir, entry);
|
|
1137
|
+
if ((0, import_node_fs.existsSync)(targetPath)) continue;
|
|
1138
|
+
let entryStat;
|
|
1139
|
+
try {
|
|
1140
|
+
entryStat = await (0, import_promises.stat)(sourcePath);
|
|
1141
|
+
} catch {
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
if (entryStat.isFile()) {
|
|
1145
|
+
copyTasks.push((0, import_promises.copyFile)(sourcePath, targetPath).catch(() => void 0));
|
|
1146
|
+
} else if (entryStat.isDirectory()) {
|
|
1147
|
+
if (isProfileDirectory(sourceUserDataDir, entry)) continue;
|
|
1148
|
+
if (SKIPPED_ROOT_DIRECTORIES.has(entry)) continue;
|
|
1149
|
+
copyTasks.push(
|
|
1150
|
+
(0, import_promises.cp)(sourcePath, targetPath, { recursive: true }).catch(
|
|
1151
|
+
() => void 0
|
|
1152
|
+
)
|
|
1153
|
+
);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
await Promise.all(copyTasks);
|
|
1157
|
+
}
|
|
1158
|
+
async function writePersistentProfileMetadata(userDataDir, metadata) {
|
|
1159
|
+
await (0, import_promises.writeFile)(
|
|
1160
|
+
(0, import_node_path.join)(userDataDir, OPENSTEER_META_FILE),
|
|
1161
|
+
JSON.stringify(metadata, null, 2)
|
|
1162
|
+
);
|
|
1163
|
+
}
|
|
1164
|
+
function buildPersistentProfileMetadata(sourceUserDataDir, profileDirectory) {
|
|
1165
|
+
return {
|
|
1166
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1167
|
+
profileDirectory,
|
|
1168
|
+
source: sourceUserDataDir
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
async function createPersistentProfileClone(sourceUserDataDir, sourceProfileDir, targetUserDataDir, profileDirectory, metadata) {
|
|
1172
|
+
if ((0, import_node_fs.existsSync)(targetUserDataDir)) {
|
|
1173
|
+
return false;
|
|
1174
|
+
}
|
|
1175
|
+
const tempUserDataDir = await (0, import_promises.mkdtemp)(
|
|
1176
|
+
buildPersistentProfileTempDirPrefix(targetUserDataDir)
|
|
1177
|
+
);
|
|
1178
|
+
let published = false;
|
|
1179
|
+
try {
|
|
1180
|
+
await (0, import_promises.cp)(sourceProfileDir, (0, import_node_path.join)(tempUserDataDir, profileDirectory), {
|
|
1181
|
+
recursive: true
|
|
1182
|
+
});
|
|
1183
|
+
await copyRootLevelEntries(
|
|
1184
|
+
sourceUserDataDir,
|
|
1185
|
+
tempUserDataDir,
|
|
1186
|
+
profileDirectory
|
|
1187
|
+
);
|
|
1188
|
+
await writePersistentProfileMetadata(tempUserDataDir, metadata);
|
|
1189
|
+
try {
|
|
1190
|
+
await (0, import_promises.rename)(tempUserDataDir, targetUserDataDir);
|
|
1191
|
+
} catch (error) {
|
|
1192
|
+
if (wasProfilePublishedByAnotherProcess(error, targetUserDataDir)) {
|
|
1193
|
+
return false;
|
|
1194
|
+
}
|
|
1195
|
+
throw error;
|
|
1196
|
+
}
|
|
1197
|
+
published = true;
|
|
1198
|
+
return true;
|
|
1199
|
+
} finally {
|
|
1200
|
+
if (!published) {
|
|
1201
|
+
await (0, import_promises.rm)(tempUserDataDir, {
|
|
1202
|
+
recursive: true,
|
|
1203
|
+
force: true
|
|
1204
|
+
}).catch(() => void 0);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
async function ensurePersistentProfileMetadata(userDataDir, metadata) {
|
|
1209
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(userDataDir, OPENSTEER_META_FILE))) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
await writePersistentProfileMetadata(userDataDir, metadata);
|
|
1213
|
+
}
|
|
1214
|
+
function wasProfilePublishedByAnotherProcess(error, targetUserDataDir) {
|
|
1215
|
+
const code = typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
1216
|
+
return (0, import_node_fs.existsSync)(targetUserDataDir) && (code === "EEXIST" || code === "ENOTEMPTY" || code === "EPERM");
|
|
1217
|
+
}
|
|
1218
|
+
function buildPersistentProfileTempDirPrefix(targetUserDataDir) {
|
|
1219
|
+
return (0, import_node_path.join)(
|
|
1220
|
+
(0, import_node_path.dirname)(targetUserDataDir),
|
|
1221
|
+
`${(0, import_node_path.basename)(targetUserDataDir)}-tmp-${process.pid}-${PROCESS_STARTED_AT_MS}-`
|
|
1222
|
+
);
|
|
1223
|
+
}
|
|
1224
|
+
async function cleanOrphanedTempDirs(profilesDir, targetBaseName) {
|
|
1225
|
+
let entries;
|
|
1226
|
+
try {
|
|
1227
|
+
entries = await (0, import_promises.readdir)(profilesDir, {
|
|
1228
|
+
encoding: "utf8",
|
|
1229
|
+
withFileTypes: true
|
|
1230
|
+
});
|
|
1231
|
+
} catch {
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
const tempDirPrefix = `${targetBaseName}-tmp-`;
|
|
1235
|
+
await Promise.all(
|
|
1236
|
+
entries.map(async (entry) => {
|
|
1237
|
+
if (!entry.isDirectory() || !entry.name.startsWith(tempDirPrefix)) {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (isTempDirOwnedByLiveProcess(entry.name, tempDirPrefix)) {
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
await (0, import_promises.rm)((0, import_node_path.join)(profilesDir, entry.name), {
|
|
1244
|
+
recursive: true,
|
|
1245
|
+
force: true
|
|
1246
|
+
}).catch(() => void 0);
|
|
1247
|
+
})
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
function isTempDirOwnedByLiveProcess(tempDirName, tempDirPrefix) {
|
|
1251
|
+
const owner = parseTempDirOwner(tempDirName, tempDirPrefix);
|
|
1252
|
+
if (!owner) {
|
|
1253
|
+
return false;
|
|
1254
|
+
}
|
|
1255
|
+
if (owner.pid === process.pid && Math.abs(owner.processStartedAtMs - PROCESS_STARTED_AT_MS) <= PROCESS_START_TIME_TOLERANCE_MS) {
|
|
1256
|
+
return true;
|
|
1257
|
+
}
|
|
1258
|
+
return isProcessRunning(owner.pid);
|
|
1259
|
+
}
|
|
1260
|
+
function parseTempDirOwner(tempDirName, tempDirPrefix) {
|
|
1261
|
+
const remainder = tempDirName.slice(tempDirPrefix.length);
|
|
1262
|
+
const firstDashIndex = remainder.indexOf("-");
|
|
1263
|
+
const secondDashIndex = firstDashIndex === -1 ? -1 : remainder.indexOf("-", firstDashIndex + 1);
|
|
1264
|
+
if (firstDashIndex === -1 || secondDashIndex === -1) {
|
|
1265
|
+
return null;
|
|
1266
|
+
}
|
|
1267
|
+
const pid = Number.parseInt(remainder.slice(0, firstDashIndex), 10);
|
|
1268
|
+
const processStartedAtMs = Number.parseInt(
|
|
1269
|
+
remainder.slice(firstDashIndex + 1, secondDashIndex),
|
|
1270
|
+
10
|
|
1271
|
+
);
|
|
1272
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
1273
|
+
return null;
|
|
1274
|
+
}
|
|
1275
|
+
if (!Number.isInteger(processStartedAtMs) || processStartedAtMs <= 0) {
|
|
1276
|
+
return null;
|
|
1277
|
+
}
|
|
1278
|
+
return { pid, processStartedAtMs };
|
|
1279
|
+
}
|
|
1280
|
+
function isProcessRunning(pid) {
|
|
1281
|
+
try {
|
|
1282
|
+
process.kill(pid, 0);
|
|
1283
|
+
return true;
|
|
1284
|
+
} catch (error) {
|
|
1285
|
+
const code = typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
1286
|
+
return code !== "ESRCH";
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1016
1290
|
// src/browser/pool.ts
|
|
1017
1291
|
var BrowserPool = class {
|
|
1018
1292
|
browser = null;
|
|
1019
1293
|
cdpProxy = null;
|
|
1020
1294
|
launchedProcess = null;
|
|
1021
|
-
|
|
1295
|
+
managedUserDataDir = null;
|
|
1296
|
+
persistentProfile = false;
|
|
1022
1297
|
defaults;
|
|
1023
1298
|
constructor(defaults = {}) {
|
|
1024
1299
|
this.defaults = defaults;
|
|
1025
1300
|
}
|
|
1026
1301
|
async launch(options = {}) {
|
|
1027
|
-
if (this.browser || this.cdpProxy || this.launchedProcess || this.
|
|
1302
|
+
if (this.browser || this.cdpProxy || this.launchedProcess || this.managedUserDataDir) {
|
|
1028
1303
|
await this.close();
|
|
1029
1304
|
}
|
|
1030
1305
|
const mode = options.mode ?? this.defaults.mode ?? "chromium";
|
|
@@ -1074,11 +1349,13 @@ var BrowserPool = class {
|
|
|
1074
1349
|
const browser = this.browser;
|
|
1075
1350
|
const cdpProxy = this.cdpProxy;
|
|
1076
1351
|
const launchedProcess = this.launchedProcess;
|
|
1077
|
-
const
|
|
1352
|
+
const managedUserDataDir = this.managedUserDataDir;
|
|
1353
|
+
const persistentProfile = this.persistentProfile;
|
|
1078
1354
|
this.browser = null;
|
|
1079
1355
|
this.cdpProxy = null;
|
|
1080
1356
|
this.launchedProcess = null;
|
|
1081
|
-
this.
|
|
1357
|
+
this.managedUserDataDir = null;
|
|
1358
|
+
this.persistentProfile = false;
|
|
1082
1359
|
try {
|
|
1083
1360
|
if (browser) {
|
|
1084
1361
|
await browser.close().catch(() => void 0);
|
|
@@ -1086,8 +1363,8 @@ var BrowserPool = class {
|
|
|
1086
1363
|
} finally {
|
|
1087
1364
|
cdpProxy?.close();
|
|
1088
1365
|
await killProcessTree(launchedProcess);
|
|
1089
|
-
if (
|
|
1090
|
-
await (0,
|
|
1366
|
+
if (managedUserDataDir && !persistentProfile) {
|
|
1367
|
+
await (0, import_promises2.rm)(managedUserDataDir, {
|
|
1091
1368
|
recursive: true,
|
|
1092
1369
|
force: true
|
|
1093
1370
|
}).catch(() => void 0);
|
|
@@ -1136,10 +1413,11 @@ var BrowserPool = class {
|
|
|
1136
1413
|
options.userDataDir ?? chromePaths.defaultUserDataDir
|
|
1137
1414
|
);
|
|
1138
1415
|
const profileDirectory = options.profileDirectory ?? "Default";
|
|
1139
|
-
const
|
|
1416
|
+
const persistentProfile = await getOrCreatePersistentProfile(
|
|
1140
1417
|
sourceUserDataDir,
|
|
1141
1418
|
profileDirectory
|
|
1142
1419
|
);
|
|
1420
|
+
await clearPersistentProfileSingletons(persistentProfile.userDataDir);
|
|
1143
1421
|
const debugPort = await reserveDebugPort();
|
|
1144
1422
|
const headless = resolveLaunchHeadless(
|
|
1145
1423
|
"real",
|
|
@@ -1147,7 +1425,7 @@ var BrowserPool = class {
|
|
|
1147
1425
|
this.defaults.headless
|
|
1148
1426
|
);
|
|
1149
1427
|
const launchArgs = buildRealBrowserLaunchArgs({
|
|
1150
|
-
userDataDir:
|
|
1428
|
+
userDataDir: persistentProfile.userDataDir,
|
|
1151
1429
|
profileDirectory,
|
|
1152
1430
|
debugPort,
|
|
1153
1431
|
headless
|
|
@@ -1167,24 +1445,22 @@ var BrowserPool = class {
|
|
|
1167
1445
|
timeout: options.timeout ?? 3e4
|
|
1168
1446
|
});
|
|
1169
1447
|
const { context, page } = await createOwnedBrowserContextAndPage(
|
|
1170
|
-
browser
|
|
1171
|
-
{
|
|
1172
|
-
headless,
|
|
1173
|
-
initialUrl: options.initialUrl,
|
|
1174
|
-
timeoutMs: options.timeout ?? 3e4
|
|
1175
|
-
}
|
|
1448
|
+
browser
|
|
1176
1449
|
);
|
|
1450
|
+
if (options.initialUrl) {
|
|
1451
|
+
await page.goto(options.initialUrl, {
|
|
1452
|
+
waitUntil: "domcontentloaded",
|
|
1453
|
+
timeout: options.timeout ?? 3e4
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1177
1456
|
this.browser = browser;
|
|
1178
1457
|
this.launchedProcess = processHandle;
|
|
1179
|
-
this.
|
|
1458
|
+
this.managedUserDataDir = persistentProfile.userDataDir;
|
|
1459
|
+
this.persistentProfile = true;
|
|
1180
1460
|
return { browser, context, page, isExternal: false };
|
|
1181
1461
|
} catch (error) {
|
|
1182
1462
|
await browser?.close().catch(() => void 0);
|
|
1183
1463
|
await killProcessTree(processHandle);
|
|
1184
|
-
await (0, import_promises.rm)(tempUserDataDir, {
|
|
1185
|
-
recursive: true,
|
|
1186
|
-
force: true
|
|
1187
|
-
}).catch(() => void 0);
|
|
1188
1464
|
throw error;
|
|
1189
1465
|
}
|
|
1190
1466
|
}
|
|
@@ -1207,8 +1483,7 @@ var BrowserPool = class {
|
|
|
1207
1483
|
};
|
|
1208
1484
|
async function pickBrowserContextAndPage(browser) {
|
|
1209
1485
|
const context = getPrimaryBrowserContext(browser);
|
|
1210
|
-
const
|
|
1211
|
-
const page = pages.find((candidate) => isInspectablePageUrl2(candidate.url())) || pages[0] || await context.newPage();
|
|
1486
|
+
const page = await getAttachedPageOrCreate(context);
|
|
1212
1487
|
return { context, page };
|
|
1213
1488
|
}
|
|
1214
1489
|
function resolveLaunchHeadless(mode, requestedHeadless, defaultHeadless) {
|
|
@@ -1220,77 +1495,31 @@ function resolveLaunchHeadless(mode, requestedHeadless, defaultHeadless) {
|
|
|
1220
1495
|
}
|
|
1221
1496
|
return mode === "real";
|
|
1222
1497
|
}
|
|
1223
|
-
async function createOwnedBrowserContextAndPage(browser
|
|
1498
|
+
async function createOwnedBrowserContextAndPage(browser) {
|
|
1224
1499
|
const context = getPrimaryBrowserContext(browser);
|
|
1225
|
-
const page = await
|
|
1500
|
+
const page = await getExistingPageOrCreate(context);
|
|
1226
1501
|
return { context, page };
|
|
1227
1502
|
}
|
|
1228
|
-
async function
|
|
1229
|
-
const
|
|
1230
|
-
const
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
newWindow: !options.headless
|
|
1236
|
-
});
|
|
1237
|
-
await browserSession.send("Target.activateTarget", { targetId }).catch(() => void 0);
|
|
1238
|
-
const page = await waitForOwnedBrowserPage(context, {
|
|
1239
|
-
existingPages,
|
|
1240
|
-
targetUrl,
|
|
1241
|
-
timeoutMs: options.timeoutMs
|
|
1242
|
-
});
|
|
1243
|
-
if (targetUrl !== "about:blank") {
|
|
1244
|
-
await page.waitForLoadState("domcontentloaded", {
|
|
1245
|
-
timeout: options.timeoutMs
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
await closeDisposableStartupTargets(browserSession, targetId);
|
|
1249
|
-
return page;
|
|
1250
|
-
} finally {
|
|
1251
|
-
await browserSession.detach().catch(() => void 0);
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
async function closeDisposableStartupTargets(browserSession, preservedTargetId) {
|
|
1255
|
-
const response = await browserSession.send("Target.getTargets").catch(() => null);
|
|
1256
|
-
if (!response) {
|
|
1257
|
-
return;
|
|
1503
|
+
async function getAttachedPageOrCreate(context) {
|
|
1504
|
+
const pages = context.pages();
|
|
1505
|
+
const inspectablePage = pages.find(
|
|
1506
|
+
(candidate) => isInspectablePageUrl2(safePageUrl(candidate))
|
|
1507
|
+
);
|
|
1508
|
+
if (inspectablePage) {
|
|
1509
|
+
return inspectablePage;
|
|
1258
1510
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
}
|
|
1263
|
-
await browserSession.send("Target.closeTarget", { targetId: targetInfo.targetId }).catch(() => void 0);
|
|
1511
|
+
const attachedPage = pages[0];
|
|
1512
|
+
if (attachedPage) {
|
|
1513
|
+
return attachedPage;
|
|
1264
1514
|
}
|
|
1515
|
+
return await context.newPage();
|
|
1265
1516
|
}
|
|
1266
|
-
async function
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
for (const candidate of context.pages()) {
|
|
1271
|
-
if (options.existingPages.has(candidate)) {
|
|
1272
|
-
continue;
|
|
1273
|
-
}
|
|
1274
|
-
const url = candidate.url();
|
|
1275
|
-
if (!isInspectablePageUrl2(url)) {
|
|
1276
|
-
continue;
|
|
1277
|
-
}
|
|
1278
|
-
fallbackPage ??= candidate;
|
|
1279
|
-
if (options.targetUrl === "about:blank") {
|
|
1280
|
-
return candidate;
|
|
1281
|
-
}
|
|
1282
|
-
if (pageLooselyMatchesUrl(url, options.targetUrl)) {
|
|
1283
|
-
return candidate;
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
await sleep(100);
|
|
1287
|
-
}
|
|
1288
|
-
if (fallbackPage) {
|
|
1289
|
-
return fallbackPage;
|
|
1517
|
+
async function getExistingPageOrCreate(context) {
|
|
1518
|
+
const existingPage = context.pages()[0];
|
|
1519
|
+
if (existingPage) {
|
|
1520
|
+
return existingPage;
|
|
1290
1521
|
}
|
|
1291
|
-
|
|
1292
|
-
`Chrome created a target for ${options.targetUrl}, but Playwright did not expose the page in time.`
|
|
1293
|
-
);
|
|
1522
|
+
return await context.newPage();
|
|
1294
1523
|
}
|
|
1295
1524
|
function getPrimaryBrowserContext(browser) {
|
|
1296
1525
|
const contexts = browser.contexts();
|
|
@@ -1304,19 +1533,11 @@ function getPrimaryBrowserContext(browser) {
|
|
|
1304
1533
|
function isInspectablePageUrl2(url) {
|
|
1305
1534
|
return url === "about:blank" || url.startsWith("http://") || url.startsWith("https://");
|
|
1306
1535
|
}
|
|
1307
|
-
function
|
|
1308
|
-
return url === "about:blank" || url === "chrome://newtab/" || url === "chrome://new-tab-page/";
|
|
1309
|
-
}
|
|
1310
|
-
function pageLooselyMatchesUrl(currentUrl, initialUrl) {
|
|
1536
|
+
function safePageUrl(page) {
|
|
1311
1537
|
try {
|
|
1312
|
-
|
|
1313
|
-
const requested = new URL(initialUrl);
|
|
1314
|
-
if (current.href === requested.href) {
|
|
1315
|
-
return true;
|
|
1316
|
-
}
|
|
1317
|
-
return current.hostname === requested.hostname && current.pathname === requested.pathname;
|
|
1538
|
+
return page.url();
|
|
1318
1539
|
} catch {
|
|
1319
|
-
return
|
|
1540
|
+
return "";
|
|
1320
1541
|
}
|
|
1321
1542
|
}
|
|
1322
1543
|
function normalizeDiscoveryUrl(cdpUrl) {
|
|
@@ -1396,38 +1617,12 @@ async function reserveDebugPort() {
|
|
|
1396
1617
|
});
|
|
1397
1618
|
});
|
|
1398
1619
|
}
|
|
1399
|
-
async function cloneProfileToTempDir(userDataDir, profileDirectory) {
|
|
1400
|
-
const resolvedUserDataDir = expandHome(userDataDir);
|
|
1401
|
-
const tempUserDataDir = await (0, import_promises.mkdtemp)(
|
|
1402
|
-
(0, import_node_path.join)((0, import_node_os.tmpdir)(), "opensteer-real-browser-")
|
|
1403
|
-
);
|
|
1404
|
-
const sourceProfileDir = (0, import_node_path.join)(resolvedUserDataDir, profileDirectory);
|
|
1405
|
-
const targetProfileDir = (0, import_node_path.join)(tempUserDataDir, profileDirectory);
|
|
1406
|
-
if ((0, import_node_fs.existsSync)(sourceProfileDir)) {
|
|
1407
|
-
await (0, import_promises.cp)(sourceProfileDir, targetProfileDir, {
|
|
1408
|
-
recursive: true
|
|
1409
|
-
});
|
|
1410
|
-
} else {
|
|
1411
|
-
await (0, import_promises.mkdir)(targetProfileDir, {
|
|
1412
|
-
recursive: true
|
|
1413
|
-
});
|
|
1414
|
-
}
|
|
1415
|
-
const localStatePath = (0, import_node_path.join)(resolvedUserDataDir, "Local State");
|
|
1416
|
-
if ((0, import_node_fs.existsSync)(localStatePath)) {
|
|
1417
|
-
await (0, import_promises.copyFile)(localStatePath, (0, import_node_path.join)(tempUserDataDir, "Local State"));
|
|
1418
|
-
}
|
|
1419
|
-
return tempUserDataDir;
|
|
1420
|
-
}
|
|
1421
1620
|
function buildRealBrowserLaunchArgs(options) {
|
|
1422
1621
|
const args = [
|
|
1423
1622
|
`--user-data-dir=${options.userDataDir}`,
|
|
1424
1623
|
`--profile-directory=${options.profileDirectory}`,
|
|
1425
1624
|
`--remote-debugging-port=${options.debugPort}`,
|
|
1426
|
-
"--
|
|
1427
|
-
"--no-default-browser-check",
|
|
1428
|
-
"--disable-background-networking",
|
|
1429
|
-
"--disable-sync",
|
|
1430
|
-
"--disable-popup-blocking"
|
|
1625
|
+
"--disable-blink-features=AutomationControlled"
|
|
1431
1626
|
];
|
|
1432
1627
|
if (options.headless) {
|
|
1433
1628
|
args.push("--headless=new");
|
|
@@ -7147,7 +7342,7 @@ async function closeTab(context, activePage, index) {
|
|
|
7147
7342
|
}
|
|
7148
7343
|
|
|
7149
7344
|
// src/actions/cookies.ts
|
|
7150
|
-
var
|
|
7345
|
+
var import_promises3 = require("fs/promises");
|
|
7151
7346
|
async function getCookies(context, url) {
|
|
7152
7347
|
return context.cookies(url ? [url] : void 0);
|
|
7153
7348
|
}
|
|
@@ -7159,10 +7354,10 @@ async function clearCookies(context) {
|
|
|
7159
7354
|
}
|
|
7160
7355
|
async function exportCookies(context, filePath, url) {
|
|
7161
7356
|
const cookies = await context.cookies(url ? [url] : void 0);
|
|
7162
|
-
await (0,
|
|
7357
|
+
await (0, import_promises3.writeFile)(filePath, JSON.stringify(cookies, null, 2), "utf-8");
|
|
7163
7358
|
}
|
|
7164
7359
|
async function importCookies(context, filePath) {
|
|
7165
|
-
const raw = await (0,
|
|
7360
|
+
const raw = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
7166
7361
|
const cookies = JSON.parse(raw);
|
|
7167
7362
|
await context.addCookies(cookies);
|
|
7168
7363
|
}
|
|
@@ -7913,31 +8108,31 @@ function buildVariantDescriptorFromCluster(descriptors) {
|
|
|
7913
8108
|
const keyStats = /* @__PURE__ */ new Map();
|
|
7914
8109
|
for (const descriptor of descriptors) {
|
|
7915
8110
|
for (const field of descriptor.fields) {
|
|
7916
|
-
const
|
|
8111
|
+
const stat2 = keyStats.get(field.path) || {
|
|
7917
8112
|
indices: /* @__PURE__ */ new Set(),
|
|
7918
8113
|
pathNodes: [],
|
|
7919
8114
|
attributes: [],
|
|
7920
8115
|
sources: []
|
|
7921
8116
|
};
|
|
7922
|
-
|
|
8117
|
+
stat2.indices.add(descriptor.index);
|
|
7923
8118
|
if (isPersistedValueNode(field.node)) {
|
|
7924
|
-
|
|
7925
|
-
|
|
8119
|
+
stat2.pathNodes.push(field.node.$path);
|
|
8120
|
+
stat2.attributes.push(field.node.attribute);
|
|
7926
8121
|
} else if (isPersistedSourceNode(field.node)) {
|
|
7927
|
-
|
|
8122
|
+
stat2.sources.push("current_url");
|
|
7928
8123
|
}
|
|
7929
|
-
keyStats.set(field.path,
|
|
8124
|
+
keyStats.set(field.path, stat2);
|
|
7930
8125
|
}
|
|
7931
8126
|
}
|
|
7932
8127
|
const mergedFields = [];
|
|
7933
|
-
for (const [fieldPath,
|
|
7934
|
-
if (
|
|
7935
|
-
if (
|
|
8128
|
+
for (const [fieldPath, stat2] of keyStats) {
|
|
8129
|
+
if (stat2.indices.size < threshold) continue;
|
|
8130
|
+
if (stat2.pathNodes.length >= threshold) {
|
|
7936
8131
|
let mergedFieldPath = null;
|
|
7937
|
-
if (
|
|
7938
|
-
mergedFieldPath = sanitizeElementPath(
|
|
8132
|
+
if (stat2.pathNodes.length === 1) {
|
|
8133
|
+
mergedFieldPath = sanitizeElementPath(stat2.pathNodes[0]);
|
|
7939
8134
|
} else {
|
|
7940
|
-
mergedFieldPath = mergeElementPathsByMajority(
|
|
8135
|
+
mergedFieldPath = mergeElementPathsByMajority(stat2.pathNodes);
|
|
7941
8136
|
}
|
|
7942
8137
|
if (!mergedFieldPath) continue;
|
|
7943
8138
|
if (clusterSize === 1) {
|
|
@@ -7950,17 +8145,17 @@ function buildVariantDescriptorFromCluster(descriptors) {
|
|
|
7950
8145
|
mergedFieldPath,
|
|
7951
8146
|
"field"
|
|
7952
8147
|
);
|
|
7953
|
-
const attrThreshold =
|
|
8148
|
+
const attrThreshold = stat2.pathNodes.length === 1 ? 1 : majorityThreshold(stat2.pathNodes.length);
|
|
7954
8149
|
mergedFields.push({
|
|
7955
8150
|
path: fieldPath,
|
|
7956
8151
|
node: createValueNode({
|
|
7957
8152
|
elementPath: mergedFieldPath,
|
|
7958
|
-
attribute: pickModeString(
|
|
8153
|
+
attribute: pickModeString(stat2.attributes, attrThreshold)
|
|
7959
8154
|
})
|
|
7960
8155
|
});
|
|
7961
8156
|
continue;
|
|
7962
8157
|
}
|
|
7963
|
-
const dominantSource = pickModeString(
|
|
8158
|
+
const dominantSource = pickModeString(stat2.sources, threshold);
|
|
7964
8159
|
if (dominantSource === "current_url") {
|
|
7965
8160
|
mergedFields.push({
|
|
7966
8161
|
path: fieldPath,
|
|
@@ -8829,7 +9024,99 @@ function stripPositionClauses2(path5) {
|
|
|
8829
9024
|
}
|
|
8830
9025
|
|
|
8831
9026
|
// src/cloud/contracts.ts
|
|
9027
|
+
var cloudActionMethods = [
|
|
9028
|
+
"goto",
|
|
9029
|
+
"snapshot",
|
|
9030
|
+
"screenshot",
|
|
9031
|
+
"state",
|
|
9032
|
+
"click",
|
|
9033
|
+
"dblclick",
|
|
9034
|
+
"rightclick",
|
|
9035
|
+
"hover",
|
|
9036
|
+
"input",
|
|
9037
|
+
"select",
|
|
9038
|
+
"scroll",
|
|
9039
|
+
"tabs",
|
|
9040
|
+
"newTab",
|
|
9041
|
+
"switchTab",
|
|
9042
|
+
"closeTab",
|
|
9043
|
+
"getCookies",
|
|
9044
|
+
"setCookie",
|
|
9045
|
+
"clearCookies",
|
|
9046
|
+
"pressKey",
|
|
9047
|
+
"type",
|
|
9048
|
+
"getElementText",
|
|
9049
|
+
"getElementValue",
|
|
9050
|
+
"getElementAttributes",
|
|
9051
|
+
"getElementBoundingBox",
|
|
9052
|
+
"getHtml",
|
|
9053
|
+
"getTitle",
|
|
9054
|
+
"uploadFile",
|
|
9055
|
+
"exportCookies",
|
|
9056
|
+
"importCookies",
|
|
9057
|
+
"waitForText",
|
|
9058
|
+
"extract",
|
|
9059
|
+
"extractFromPlan",
|
|
9060
|
+
"clearCache"
|
|
9061
|
+
];
|
|
9062
|
+
var cloudErrorCodes = [
|
|
9063
|
+
"CLOUD_AUTH_FAILED",
|
|
9064
|
+
"CLOUD_SESSION_NOT_FOUND",
|
|
9065
|
+
"CLOUD_SESSION_CLOSED",
|
|
9066
|
+
"CLOUD_UNSUPPORTED_METHOD",
|
|
9067
|
+
"CLOUD_INVALID_REQUEST",
|
|
9068
|
+
"CLOUD_MODEL_NOT_ALLOWED",
|
|
9069
|
+
"CLOUD_ACTION_FAILED",
|
|
9070
|
+
"CLOUD_CAPACITY_EXHAUSTED",
|
|
9071
|
+
"CLOUD_RUNTIME_UNAVAILABLE",
|
|
9072
|
+
"CLOUD_RUNTIME_MISMATCH",
|
|
9073
|
+
"CLOUD_SESSION_STALE",
|
|
9074
|
+
"CLOUD_CONTROL_PLANE_ERROR",
|
|
9075
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
9076
|
+
"CLOUD_PROXY_UNAVAILABLE",
|
|
9077
|
+
"CLOUD_PROXY_REQUIRED",
|
|
9078
|
+
"CLOUD_BILLING_LIMIT_REACHED",
|
|
9079
|
+
"CLOUD_RATE_LIMITED",
|
|
9080
|
+
"CLOUD_BROWSER_PROFILE_NOT_FOUND",
|
|
9081
|
+
"CLOUD_BROWSER_PROFILE_BUSY",
|
|
9082
|
+
"CLOUD_BROWSER_PROFILE_DISABLED",
|
|
9083
|
+
"CLOUD_BROWSER_PROFILE_PROXY_UNAVAILABLE",
|
|
9084
|
+
"CLOUD_BROWSER_PROFILE_SYNC_FAILED",
|
|
9085
|
+
"CLOUD_INTERNAL"
|
|
9086
|
+
];
|
|
9087
|
+
var cloudSessionStatuses = [
|
|
9088
|
+
"provisioning",
|
|
9089
|
+
"active",
|
|
9090
|
+
"closing",
|
|
9091
|
+
"closed",
|
|
9092
|
+
"failed"
|
|
9093
|
+
];
|
|
8832
9094
|
var cloudSessionContractVersion = "v3";
|
|
9095
|
+
var cloudSessionSourceTypes = [
|
|
9096
|
+
"agent-thread",
|
|
9097
|
+
"agent-run",
|
|
9098
|
+
"project-agent-run",
|
|
9099
|
+
"local-cloud",
|
|
9100
|
+
"manual"
|
|
9101
|
+
];
|
|
9102
|
+
var cloudActionMethodSet = new Set(cloudActionMethods);
|
|
9103
|
+
var cloudErrorCodeSet = new Set(cloudErrorCodes);
|
|
9104
|
+
var cloudSessionSourceTypeSet = new Set(
|
|
9105
|
+
cloudSessionSourceTypes
|
|
9106
|
+
);
|
|
9107
|
+
var cloudSessionStatusSet = new Set(cloudSessionStatuses);
|
|
9108
|
+
function isCloudActionMethod(value) {
|
|
9109
|
+
return typeof value === "string" && cloudActionMethodSet.has(value);
|
|
9110
|
+
}
|
|
9111
|
+
function isCloudErrorCode(value) {
|
|
9112
|
+
return typeof value === "string" && cloudErrorCodeSet.has(value);
|
|
9113
|
+
}
|
|
9114
|
+
function isCloudSessionSourceType(value) {
|
|
9115
|
+
return typeof value === "string" && cloudSessionSourceTypeSet.has(value);
|
|
9116
|
+
}
|
|
9117
|
+
function isCloudSessionStatus(value) {
|
|
9118
|
+
return typeof value === "string" && cloudSessionStatusSet.has(value);
|
|
9119
|
+
}
|
|
8833
9120
|
|
|
8834
9121
|
// src/cloud/action-ws-client.ts
|
|
8835
9122
|
var import_ws2 = __toESM(require("ws"), 1);
|
|
@@ -8860,6 +9147,13 @@ function cloudNotLaunchedError() {
|
|
|
8860
9147
|
);
|
|
8861
9148
|
}
|
|
8862
9149
|
|
|
9150
|
+
// src/cloud/ws-url.ts
|
|
9151
|
+
function withTokenQuery(wsUrl, token) {
|
|
9152
|
+
const url = new URL(wsUrl);
|
|
9153
|
+
url.searchParams.set("token", token);
|
|
9154
|
+
return url.toString();
|
|
9155
|
+
}
|
|
9156
|
+
|
|
8863
9157
|
// src/cloud/action-ws-client.ts
|
|
8864
9158
|
var ActionWsClient = class _ActionWsClient {
|
|
8865
9159
|
ws;
|
|
@@ -8988,11 +9282,6 @@ function rawDataToUtf8(raw) {
|
|
|
8988
9282
|
if (Array.isArray(raw)) return Buffer.concat(raw).toString("utf8");
|
|
8989
9283
|
return raw.toString("utf8");
|
|
8990
9284
|
}
|
|
8991
|
-
function withTokenQuery(wsUrl, token) {
|
|
8992
|
-
const url = new URL(wsUrl);
|
|
8993
|
-
url.searchParams.set("token", token);
|
|
8994
|
-
return url.toString();
|
|
8995
|
-
}
|
|
8996
9285
|
|
|
8997
9286
|
// src/cloud/local-cache-sync.ts
|
|
8998
9287
|
var import_fs4 = __toESM(require("fs"), 1);
|
|
@@ -9132,7 +9421,7 @@ function dedupeNewest(entries) {
|
|
|
9132
9421
|
var import_playwright2 = require("playwright");
|
|
9133
9422
|
var CloudCdpClient = class {
|
|
9134
9423
|
async connect(args) {
|
|
9135
|
-
const endpoint =
|
|
9424
|
+
const endpoint = withTokenQuery(args.wsUrl, args.token);
|
|
9136
9425
|
let browser;
|
|
9137
9426
|
try {
|
|
9138
9427
|
browser = await import_playwright2.chromium.connectOverCDP(endpoint);
|
|
@@ -9161,7 +9450,7 @@ function selectPreferredContextPage(browser, contexts) {
|
|
|
9161
9450
|
let aboutBlankCandidate = null;
|
|
9162
9451
|
for (const context of contexts) {
|
|
9163
9452
|
for (const page of context.pages()) {
|
|
9164
|
-
const url =
|
|
9453
|
+
const url = safePageUrl2(page);
|
|
9165
9454
|
if (!isInternalOrEmptyUrl(url)) {
|
|
9166
9455
|
return { browser, context, page };
|
|
9167
9456
|
}
|
|
@@ -9172,7 +9461,7 @@ function selectPreferredContextPage(browser, contexts) {
|
|
|
9172
9461
|
}
|
|
9173
9462
|
return aboutBlankCandidate;
|
|
9174
9463
|
}
|
|
9175
|
-
function
|
|
9464
|
+
function safePageUrl2(page) {
|
|
9176
9465
|
try {
|
|
9177
9466
|
return page.url();
|
|
9178
9467
|
} catch {
|
|
@@ -9184,11 +9473,6 @@ function isInternalOrEmptyUrl(url) {
|
|
|
9184
9473
|
if (url === "about:blank") return true;
|
|
9185
9474
|
return url.startsWith("chrome://") || url.startsWith("devtools://") || url.startsWith("edge://");
|
|
9186
9475
|
}
|
|
9187
|
-
function withTokenQuery2(wsUrl, token) {
|
|
9188
|
-
const url = new URL(wsUrl);
|
|
9189
|
-
url.searchParams.set("token", token);
|
|
9190
|
-
return url.toString();
|
|
9191
|
-
}
|
|
9192
9476
|
|
|
9193
9477
|
// src/utils/strip-trailing-slashes.ts
|
|
9194
9478
|
function stripTrailingSlashes(value) {
|
|
@@ -9225,10 +9509,7 @@ async function parseCloudHttpError(response) {
|
|
|
9225
9509
|
return new OpensteerCloudError(code, message, response.status, body?.details);
|
|
9226
9510
|
}
|
|
9227
9511
|
function toCloudErrorCode(code) {
|
|
9228
|
-
|
|
9229
|
-
return code;
|
|
9230
|
-
}
|
|
9231
|
-
return "CLOUD_TRANSPORT_ERROR";
|
|
9512
|
+
return isCloudErrorCode(code) ? code : "CLOUD_TRANSPORT_ERROR";
|
|
9232
9513
|
}
|
|
9233
9514
|
|
|
9234
9515
|
// src/cloud/session-client.ts
|
|
@@ -9335,7 +9616,12 @@ function parseCreateResponse(body, status) {
|
|
|
9335
9616
|
status,
|
|
9336
9617
|
"cloudSession"
|
|
9337
9618
|
),
|
|
9338
|
-
state:
|
|
9619
|
+
state: requireSessionStatus(
|
|
9620
|
+
cloudSessionRoot,
|
|
9621
|
+
"state",
|
|
9622
|
+
status,
|
|
9623
|
+
"cloudSession"
|
|
9624
|
+
),
|
|
9339
9625
|
createdAt: requireNumber(cloudSessionRoot, "createdAt", status, "cloudSession"),
|
|
9340
9626
|
sourceType: requireSourceType(cloudSessionRoot, "sourceType", status, "cloudSession"),
|
|
9341
9627
|
sourceRef: optionalString(cloudSessionRoot, "sourceRef", status, "cloudSession"),
|
|
@@ -9423,7 +9709,7 @@ function optionalNumber(source, field, status, parent) {
|
|
|
9423
9709
|
}
|
|
9424
9710
|
function requireSourceType(source, field, status, parent) {
|
|
9425
9711
|
const value = source[field];
|
|
9426
|
-
if (value
|
|
9712
|
+
if (isCloudSessionSourceType(value)) {
|
|
9427
9713
|
return value;
|
|
9428
9714
|
}
|
|
9429
9715
|
throw new OpensteerCloudError(
|
|
@@ -9431,13 +9717,30 @@ function requireSourceType(source, field, status, parent) {
|
|
|
9431
9717
|
`Invalid cloud session create response: ${formatFieldPath(
|
|
9432
9718
|
field,
|
|
9433
9719
|
parent
|
|
9434
|
-
)} must be one of
|
|
9720
|
+
)} must be one of ${formatAllowedValues(cloudSessionSourceTypes)}.`,
|
|
9721
|
+
status
|
|
9722
|
+
);
|
|
9723
|
+
}
|
|
9724
|
+
function requireSessionStatus(source, field, status, parent) {
|
|
9725
|
+
const value = source[field];
|
|
9726
|
+
if (isCloudSessionStatus(value)) {
|
|
9727
|
+
return value;
|
|
9728
|
+
}
|
|
9729
|
+
throw new OpensteerCloudError(
|
|
9730
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
9731
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
9732
|
+
field,
|
|
9733
|
+
parent
|
|
9734
|
+
)} must be one of ${formatAllowedValues(cloudSessionStatuses)}.`,
|
|
9435
9735
|
status
|
|
9436
9736
|
);
|
|
9437
9737
|
}
|
|
9438
9738
|
function formatFieldPath(field, parent) {
|
|
9439
9739
|
return parent ? `"${parent}.${field}"` : `"${field}"`;
|
|
9440
9740
|
}
|
|
9741
|
+
function formatAllowedValues(values) {
|
|
9742
|
+
return values.map((value) => `"${value}"`).join(", ");
|
|
9743
|
+
}
|
|
9441
9744
|
function zeroImportResponse() {
|
|
9442
9745
|
return {
|
|
9443
9746
|
imported: 0,
|
|
@@ -14846,6 +15149,7 @@ function sleep7(ms) {
|
|
|
14846
15149
|
// Annotate the CommonJS export names for ESM import in node:
|
|
14847
15150
|
0 && (module.exports = {
|
|
14848
15151
|
ActionWsClient,
|
|
15152
|
+
BrowserPool,
|
|
14849
15153
|
BrowserProfileClient,
|
|
14850
15154
|
CdpOverlayCursorRenderer,
|
|
14851
15155
|
CloudCdpClient,
|
|
@@ -14884,10 +15188,15 @@ function sleep7(ms) {
|
|
|
14884
15188
|
cleanForFull,
|
|
14885
15189
|
cleanForScrollable,
|
|
14886
15190
|
clearCookies,
|
|
15191
|
+
clearPersistentProfileSingletons,
|
|
14887
15192
|
cloneElementPath,
|
|
14888
15193
|
closeTab,
|
|
15194
|
+
cloudActionMethods,
|
|
15195
|
+
cloudErrorCodes,
|
|
14889
15196
|
cloudNotLaunchedError,
|
|
14890
15197
|
cloudSessionContractVersion,
|
|
15198
|
+
cloudSessionSourceTypes,
|
|
15199
|
+
cloudSessionStatuses,
|
|
14891
15200
|
cloudUnsupportedMethodError,
|
|
14892
15201
|
collectLocalSelectorCacheEntries,
|
|
14893
15202
|
countArrayItemsWithPath,
|
|
@@ -14896,6 +15205,8 @@ function sleep7(ms) {
|
|
|
14896
15205
|
createExtractCallback,
|
|
14897
15206
|
createResolveCallback,
|
|
14898
15207
|
createTab,
|
|
15208
|
+
detectChromePaths,
|
|
15209
|
+
expandHome,
|
|
14899
15210
|
exportCookies,
|
|
14900
15211
|
extractArrayRowsWithPaths,
|
|
14901
15212
|
extractArrayWithPaths,
|
|
@@ -14906,9 +15217,15 @@ function sleep7(ms) {
|
|
|
14906
15217
|
getElementText,
|
|
14907
15218
|
getElementValue,
|
|
14908
15219
|
getModelProvider,
|
|
15220
|
+
getOrCreatePersistentProfile,
|
|
14909
15221
|
getPageHtml,
|
|
14910
15222
|
getPageTitle,
|
|
14911
15223
|
importCookies,
|
|
15224
|
+
isCloudActionMethod,
|
|
15225
|
+
isCloudErrorCode,
|
|
15226
|
+
isCloudSessionSourceType,
|
|
15227
|
+
isCloudSessionStatus,
|
|
15228
|
+
listLocalChromeProfiles,
|
|
14912
15229
|
listTabs,
|
|
14913
15230
|
markInteractiveElements,
|
|
14914
15231
|
normalizeNamespace,
|