opensteer 0.6.5 → 0.6.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/dist/{browser-profile-client-OUHaODro.d.ts → browser-profile-client-AGTsLQxT.d.ts} +1 -1
- package/dist/{browser-profile-client-D6PuRefA.d.cts → browser-profile-client-Biu6DyT6.d.cts} +1 -1
- package/dist/{chunk-G6V2DJRN.js → chunk-ACRSRDRN.js} +7916 -7644
- package/dist/cli/auth.d.cts +1 -1
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/profile.cjs +432 -173
- package/dist/cli/profile.d.cts +2 -2
- package/dist/cli/profile.d.ts +2 -2
- package/dist/cli/profile.js +1 -1
- package/dist/cli/server.cjs +413 -154
- package/dist/cli/server.js +1 -1
- package/dist/index.cjs +423 -152
- package/dist/index.d.cts +48 -5
- package/dist/index.d.ts +48 -5
- package/dist/index.js +15 -2
- package/dist/{types-BWItZPl_.d.ts → types-Cr10igF3.d.cts} +1 -1
- package/dist/{types-BWItZPl_.d.cts → types-Cr10igF3.d.ts} +1 -1
- package/package.json +1 -1
- package/skills/electron/SKILL.md +6 -4
- package/skills/electron/references/opensteer-electron-recipes.md +5 -3
- package/skills/electron/references/opensteer-electron-workflow.md +2 -2
- package/skills/opensteer/SKILL.md +17 -3
- package/skills/opensteer/references/cli-reference.md +4 -1
package/dist/cli/profile.cjs
CHANGED
|
@@ -425,7 +425,7 @@ __export(profile_exports, {
|
|
|
425
425
|
});
|
|
426
426
|
module.exports = __toCommonJS(profile_exports);
|
|
427
427
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
428
|
-
var
|
|
428
|
+
var import_promises5 = require("readline/promises");
|
|
429
429
|
|
|
430
430
|
// src/config.ts
|
|
431
431
|
var import_fs = __toESM(require("fs"), 1);
|
|
@@ -1324,11 +1324,8 @@ var import_crypto = require("crypto");
|
|
|
1324
1324
|
|
|
1325
1325
|
// src/browser/pool.ts
|
|
1326
1326
|
var import_node_child_process = require("child_process");
|
|
1327
|
-
var
|
|
1328
|
-
var import_promises = require("fs/promises");
|
|
1327
|
+
var import_promises2 = require("fs/promises");
|
|
1329
1328
|
var import_node_net = require("net");
|
|
1330
|
-
var import_node_os = require("os");
|
|
1331
|
-
var import_node_path = require("path");
|
|
1332
1329
|
var import_playwright = require("playwright");
|
|
1333
1330
|
|
|
1334
1331
|
// src/browser/cdp-proxy.ts
|
|
@@ -1336,6 +1333,8 @@ var import_ws = __toESM(require("ws"), 1);
|
|
|
1336
1333
|
var CDP_DISCOVERY_TIMEOUT_MS = 3e3;
|
|
1337
1334
|
var LOCAL_PROXY_HOST = "127.0.0.1";
|
|
1338
1335
|
var INTERNAL_COMMAND_ID_START = 1e9;
|
|
1336
|
+
var CREATE_BLANK_TARGET_COMMAND_ID = 1;
|
|
1337
|
+
var CREATE_BLANK_TARGET_TIMEOUT_MS = 5e3;
|
|
1339
1338
|
async function discoverTargets(cdpUrl) {
|
|
1340
1339
|
const baseUrl = resolveHttpDiscoveryBase(cdpUrl);
|
|
1341
1340
|
const [targetsPayload, versionPayload] = await Promise.all([
|
|
@@ -1347,6 +1346,81 @@ async function discoverTargets(cdpUrl) {
|
|
|
1347
1346
|
targets: readPageTargets(targetsPayload)
|
|
1348
1347
|
};
|
|
1349
1348
|
}
|
|
1349
|
+
function createBlankTarget(browserWsUrl) {
|
|
1350
|
+
return new Promise((resolve, reject) => {
|
|
1351
|
+
const ws = new import_ws.default(browserWsUrl);
|
|
1352
|
+
let settled = false;
|
|
1353
|
+
function settle(handler) {
|
|
1354
|
+
if (settled) {
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
settled = true;
|
|
1358
|
+
clearTimeout(timeout);
|
|
1359
|
+
ws.close();
|
|
1360
|
+
handler();
|
|
1361
|
+
}
|
|
1362
|
+
const timeout = setTimeout(() => {
|
|
1363
|
+
settle(
|
|
1364
|
+
() => reject(new Error("Timed out creating a blank tab via CDP."))
|
|
1365
|
+
);
|
|
1366
|
+
}, CREATE_BLANK_TARGET_TIMEOUT_MS);
|
|
1367
|
+
ws.once("open", () => {
|
|
1368
|
+
ws.send(
|
|
1369
|
+
JSON.stringify({
|
|
1370
|
+
id: CREATE_BLANK_TARGET_COMMAND_ID,
|
|
1371
|
+
method: "Target.createTarget",
|
|
1372
|
+
params: { url: "about:blank" }
|
|
1373
|
+
})
|
|
1374
|
+
);
|
|
1375
|
+
});
|
|
1376
|
+
ws.on("message", (data, isBinary) => {
|
|
1377
|
+
if (isBinary) {
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
const message = parseMessage(data);
|
|
1381
|
+
if (!message || asNumber(message.id) !== CREATE_BLANK_TARGET_COMMAND_ID) {
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
const cdpError = asObject(message.error);
|
|
1385
|
+
if (cdpError) {
|
|
1386
|
+
settle(
|
|
1387
|
+
() => reject(
|
|
1388
|
+
new Error(
|
|
1389
|
+
`Target.createTarget failed: ${asString(cdpError.message) ?? JSON.stringify(cdpError)}`
|
|
1390
|
+
)
|
|
1391
|
+
)
|
|
1392
|
+
);
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
const targetId = asString(asObject(message.result)?.targetId);
|
|
1396
|
+
if (targetId) {
|
|
1397
|
+
settle(() => resolve(targetId));
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
settle(
|
|
1401
|
+
() => reject(
|
|
1402
|
+
new Error(
|
|
1403
|
+
"Target.createTarget succeeded but no targetId was returned."
|
|
1404
|
+
)
|
|
1405
|
+
)
|
|
1406
|
+
);
|
|
1407
|
+
});
|
|
1408
|
+
ws.once("error", (err) => {
|
|
1409
|
+
settle(
|
|
1410
|
+
() => reject(new Error(`Failed to create blank tab: ${errorMessage(err)}`))
|
|
1411
|
+
);
|
|
1412
|
+
});
|
|
1413
|
+
ws.once("close", () => {
|
|
1414
|
+
settle(
|
|
1415
|
+
() => reject(
|
|
1416
|
+
new Error(
|
|
1417
|
+
"CDP browser websocket closed before blank tab creation completed."
|
|
1418
|
+
)
|
|
1419
|
+
)
|
|
1420
|
+
);
|
|
1421
|
+
});
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1350
1424
|
var CDPProxy = class {
|
|
1351
1425
|
constructor(browserWsUrl, targetId) {
|
|
1352
1426
|
this.browserWsUrl = browserWsUrl;
|
|
@@ -1744,18 +1818,282 @@ function listLocalChromeProfiles(userDataDir = detectChromePaths().defaultUserDa
|
|
|
1744
1818
|
}
|
|
1745
1819
|
}
|
|
1746
1820
|
|
|
1821
|
+
// src/browser/persistent-profile.ts
|
|
1822
|
+
var import_node_crypto = require("crypto");
|
|
1823
|
+
var import_node_fs = require("fs");
|
|
1824
|
+
var import_promises = require("fs/promises");
|
|
1825
|
+
var import_node_os = require("os");
|
|
1826
|
+
var import_node_path = require("path");
|
|
1827
|
+
var OPENSTEER_META_FILE = ".opensteer-meta.json";
|
|
1828
|
+
var PROCESS_STARTED_AT_MS = Math.floor(Date.now() - process.uptime() * 1e3);
|
|
1829
|
+
var PROCESS_START_TIME_TOLERANCE_MS = 1e3;
|
|
1830
|
+
var CHROME_SINGLETON_ENTRIES = /* @__PURE__ */ new Set([
|
|
1831
|
+
"SingletonCookie",
|
|
1832
|
+
"SingletonLock",
|
|
1833
|
+
"SingletonSocket",
|
|
1834
|
+
"DevToolsActivePort",
|
|
1835
|
+
"lockfile"
|
|
1836
|
+
]);
|
|
1837
|
+
var COPY_SKIP_ENTRIES = /* @__PURE__ */ new Set([
|
|
1838
|
+
...CHROME_SINGLETON_ENTRIES,
|
|
1839
|
+
OPENSTEER_META_FILE
|
|
1840
|
+
]);
|
|
1841
|
+
var SKIPPED_ROOT_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1842
|
+
"Crash Reports",
|
|
1843
|
+
"Crashpad",
|
|
1844
|
+
"BrowserMetrics",
|
|
1845
|
+
"GrShaderCache",
|
|
1846
|
+
"ShaderCache",
|
|
1847
|
+
"GraphiteDawnCache",
|
|
1848
|
+
"component_crx_cache",
|
|
1849
|
+
"Crowd Deny",
|
|
1850
|
+
"hyphen-data",
|
|
1851
|
+
"OnDeviceHeadSuggestModel",
|
|
1852
|
+
"OptimizationGuidePredictionModels",
|
|
1853
|
+
"Segmentation Platform",
|
|
1854
|
+
"SmartCardDeviceNames",
|
|
1855
|
+
"WidevineCdm",
|
|
1856
|
+
"pnacl"
|
|
1857
|
+
]);
|
|
1858
|
+
async function getOrCreatePersistentProfile(sourceUserDataDir, profileDirectory, profilesRootDir = defaultPersistentProfilesRootDir()) {
|
|
1859
|
+
const resolvedSourceUserDataDir = expandHome(sourceUserDataDir);
|
|
1860
|
+
const targetUserDataDir = (0, import_node_path.join)(
|
|
1861
|
+
expandHome(profilesRootDir),
|
|
1862
|
+
buildPersistentProfileKey(resolvedSourceUserDataDir, profileDirectory)
|
|
1863
|
+
);
|
|
1864
|
+
const sourceProfileDir = (0, import_node_path.join)(resolvedSourceUserDataDir, profileDirectory);
|
|
1865
|
+
const metadata = buildPersistentProfileMetadata(
|
|
1866
|
+
resolvedSourceUserDataDir,
|
|
1867
|
+
profileDirectory
|
|
1868
|
+
);
|
|
1869
|
+
await (0, import_promises.mkdir)((0, import_node_path.dirname)(targetUserDataDir), { recursive: true });
|
|
1870
|
+
await cleanOrphanedTempDirs(
|
|
1871
|
+
(0, import_node_path.dirname)(targetUserDataDir),
|
|
1872
|
+
(0, import_node_path.basename)(targetUserDataDir)
|
|
1873
|
+
);
|
|
1874
|
+
if (!(0, import_node_fs.existsSync)(sourceProfileDir)) {
|
|
1875
|
+
throw new Error(
|
|
1876
|
+
`Chrome profile "${profileDirectory}" was not found in "${resolvedSourceUserDataDir}".`
|
|
1877
|
+
);
|
|
1878
|
+
}
|
|
1879
|
+
const created = await createPersistentProfileClone(
|
|
1880
|
+
resolvedSourceUserDataDir,
|
|
1881
|
+
sourceProfileDir,
|
|
1882
|
+
targetUserDataDir,
|
|
1883
|
+
profileDirectory,
|
|
1884
|
+
metadata
|
|
1885
|
+
);
|
|
1886
|
+
await ensurePersistentProfileMetadata(targetUserDataDir, metadata);
|
|
1887
|
+
return {
|
|
1888
|
+
created,
|
|
1889
|
+
userDataDir: targetUserDataDir
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1892
|
+
async function clearPersistentProfileSingletons(userDataDir) {
|
|
1893
|
+
await Promise.all(
|
|
1894
|
+
[...CHROME_SINGLETON_ENTRIES].map(
|
|
1895
|
+
(entry) => (0, import_promises.rm)((0, import_node_path.join)(userDataDir, entry), {
|
|
1896
|
+
force: true,
|
|
1897
|
+
recursive: true
|
|
1898
|
+
}).catch(() => void 0)
|
|
1899
|
+
)
|
|
1900
|
+
);
|
|
1901
|
+
}
|
|
1902
|
+
function buildPersistentProfileKey(sourceUserDataDir, profileDirectory) {
|
|
1903
|
+
const hash = (0, import_node_crypto.createHash)("sha256").update(`${sourceUserDataDir}\0${profileDirectory}`).digest("hex").slice(0, 16);
|
|
1904
|
+
const sourceLabel = sanitizePathSegment((0, import_node_path.basename)(sourceUserDataDir) || "user-data");
|
|
1905
|
+
const profileLabel = sanitizePathSegment(profileDirectory || "Default");
|
|
1906
|
+
return `${sourceLabel}-${profileLabel}-${hash}`;
|
|
1907
|
+
}
|
|
1908
|
+
function defaultPersistentProfilesRootDir() {
|
|
1909
|
+
return (0, import_node_path.join)((0, import_node_os.homedir)(), ".opensteer", "real-browser-profiles");
|
|
1910
|
+
}
|
|
1911
|
+
function sanitizePathSegment(value) {
|
|
1912
|
+
const sanitized = value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/-+/g, "-");
|
|
1913
|
+
return sanitized.replace(/^-|-$/g, "") || "profile";
|
|
1914
|
+
}
|
|
1915
|
+
function isProfileDirectory(userDataDir, entry) {
|
|
1916
|
+
return (0, import_node_fs.existsSync)((0, import_node_path.join)(userDataDir, entry, "Preferences"));
|
|
1917
|
+
}
|
|
1918
|
+
async function copyRootLevelEntries(sourceUserDataDir, targetUserDataDir, targetProfileDirectory) {
|
|
1919
|
+
let entries;
|
|
1920
|
+
try {
|
|
1921
|
+
entries = await (0, import_promises.readdir)(sourceUserDataDir);
|
|
1922
|
+
} catch {
|
|
1923
|
+
return;
|
|
1924
|
+
}
|
|
1925
|
+
const copyTasks = [];
|
|
1926
|
+
for (const entry of entries) {
|
|
1927
|
+
if (COPY_SKIP_ENTRIES.has(entry)) continue;
|
|
1928
|
+
if (entry === targetProfileDirectory) continue;
|
|
1929
|
+
const sourcePath = (0, import_node_path.join)(sourceUserDataDir, entry);
|
|
1930
|
+
const targetPath = (0, import_node_path.join)(targetUserDataDir, entry);
|
|
1931
|
+
if ((0, import_node_fs.existsSync)(targetPath)) continue;
|
|
1932
|
+
let entryStat;
|
|
1933
|
+
try {
|
|
1934
|
+
entryStat = await (0, import_promises.stat)(sourcePath);
|
|
1935
|
+
} catch {
|
|
1936
|
+
continue;
|
|
1937
|
+
}
|
|
1938
|
+
if (entryStat.isFile()) {
|
|
1939
|
+
copyTasks.push((0, import_promises.copyFile)(sourcePath, targetPath).catch(() => void 0));
|
|
1940
|
+
} else if (entryStat.isDirectory()) {
|
|
1941
|
+
if (isProfileDirectory(sourceUserDataDir, entry)) continue;
|
|
1942
|
+
if (SKIPPED_ROOT_DIRECTORIES.has(entry)) continue;
|
|
1943
|
+
copyTasks.push(
|
|
1944
|
+
(0, import_promises.cp)(sourcePath, targetPath, { recursive: true }).catch(
|
|
1945
|
+
() => void 0
|
|
1946
|
+
)
|
|
1947
|
+
);
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
await Promise.all(copyTasks);
|
|
1951
|
+
}
|
|
1952
|
+
async function writePersistentProfileMetadata(userDataDir, metadata) {
|
|
1953
|
+
await (0, import_promises.writeFile)(
|
|
1954
|
+
(0, import_node_path.join)(userDataDir, OPENSTEER_META_FILE),
|
|
1955
|
+
JSON.stringify(metadata, null, 2)
|
|
1956
|
+
);
|
|
1957
|
+
}
|
|
1958
|
+
function buildPersistentProfileMetadata(sourceUserDataDir, profileDirectory) {
|
|
1959
|
+
return {
|
|
1960
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1961
|
+
profileDirectory,
|
|
1962
|
+
source: sourceUserDataDir
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
async function createPersistentProfileClone(sourceUserDataDir, sourceProfileDir, targetUserDataDir, profileDirectory, metadata) {
|
|
1966
|
+
if ((0, import_node_fs.existsSync)(targetUserDataDir)) {
|
|
1967
|
+
return false;
|
|
1968
|
+
}
|
|
1969
|
+
const tempUserDataDir = await (0, import_promises.mkdtemp)(
|
|
1970
|
+
buildPersistentProfileTempDirPrefix(targetUserDataDir)
|
|
1971
|
+
);
|
|
1972
|
+
let published = false;
|
|
1973
|
+
try {
|
|
1974
|
+
await (0, import_promises.cp)(sourceProfileDir, (0, import_node_path.join)(tempUserDataDir, profileDirectory), {
|
|
1975
|
+
recursive: true
|
|
1976
|
+
});
|
|
1977
|
+
await copyRootLevelEntries(
|
|
1978
|
+
sourceUserDataDir,
|
|
1979
|
+
tempUserDataDir,
|
|
1980
|
+
profileDirectory
|
|
1981
|
+
);
|
|
1982
|
+
await writePersistentProfileMetadata(tempUserDataDir, metadata);
|
|
1983
|
+
try {
|
|
1984
|
+
await (0, import_promises.rename)(tempUserDataDir, targetUserDataDir);
|
|
1985
|
+
} catch (error) {
|
|
1986
|
+
if (wasProfilePublishedByAnotherProcess(error, targetUserDataDir)) {
|
|
1987
|
+
return false;
|
|
1988
|
+
}
|
|
1989
|
+
throw error;
|
|
1990
|
+
}
|
|
1991
|
+
published = true;
|
|
1992
|
+
return true;
|
|
1993
|
+
} finally {
|
|
1994
|
+
if (!published) {
|
|
1995
|
+
await (0, import_promises.rm)(tempUserDataDir, {
|
|
1996
|
+
recursive: true,
|
|
1997
|
+
force: true
|
|
1998
|
+
}).catch(() => void 0);
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
async function ensurePersistentProfileMetadata(userDataDir, metadata) {
|
|
2003
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(userDataDir, OPENSTEER_META_FILE))) {
|
|
2004
|
+
return;
|
|
2005
|
+
}
|
|
2006
|
+
await writePersistentProfileMetadata(userDataDir, metadata);
|
|
2007
|
+
}
|
|
2008
|
+
function wasProfilePublishedByAnotherProcess(error, targetUserDataDir) {
|
|
2009
|
+
const code = typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
2010
|
+
return (0, import_node_fs.existsSync)(targetUserDataDir) && (code === "EEXIST" || code === "ENOTEMPTY" || code === "EPERM");
|
|
2011
|
+
}
|
|
2012
|
+
function buildPersistentProfileTempDirPrefix(targetUserDataDir) {
|
|
2013
|
+
return (0, import_node_path.join)(
|
|
2014
|
+
(0, import_node_path.dirname)(targetUserDataDir),
|
|
2015
|
+
`${(0, import_node_path.basename)(targetUserDataDir)}-tmp-${process.pid}-${PROCESS_STARTED_AT_MS}-`
|
|
2016
|
+
);
|
|
2017
|
+
}
|
|
2018
|
+
async function cleanOrphanedTempDirs(profilesDir, targetBaseName) {
|
|
2019
|
+
let entries;
|
|
2020
|
+
try {
|
|
2021
|
+
entries = await (0, import_promises.readdir)(profilesDir, {
|
|
2022
|
+
encoding: "utf8",
|
|
2023
|
+
withFileTypes: true
|
|
2024
|
+
});
|
|
2025
|
+
} catch {
|
|
2026
|
+
return;
|
|
2027
|
+
}
|
|
2028
|
+
const tempDirPrefix = `${targetBaseName}-tmp-`;
|
|
2029
|
+
await Promise.all(
|
|
2030
|
+
entries.map(async (entry) => {
|
|
2031
|
+
if (!entry.isDirectory() || !entry.name.startsWith(tempDirPrefix)) {
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
if (isTempDirOwnedByLiveProcess(entry.name, tempDirPrefix)) {
|
|
2035
|
+
return;
|
|
2036
|
+
}
|
|
2037
|
+
await (0, import_promises.rm)((0, import_node_path.join)(profilesDir, entry.name), {
|
|
2038
|
+
recursive: true,
|
|
2039
|
+
force: true
|
|
2040
|
+
}).catch(() => void 0);
|
|
2041
|
+
})
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
2044
|
+
function isTempDirOwnedByLiveProcess(tempDirName, tempDirPrefix) {
|
|
2045
|
+
const owner = parseTempDirOwner(tempDirName, tempDirPrefix);
|
|
2046
|
+
if (!owner) {
|
|
2047
|
+
return false;
|
|
2048
|
+
}
|
|
2049
|
+
if (owner.pid === process.pid && Math.abs(owner.processStartedAtMs - PROCESS_STARTED_AT_MS) <= PROCESS_START_TIME_TOLERANCE_MS) {
|
|
2050
|
+
return true;
|
|
2051
|
+
}
|
|
2052
|
+
return isProcessRunning(owner.pid);
|
|
2053
|
+
}
|
|
2054
|
+
function parseTempDirOwner(tempDirName, tempDirPrefix) {
|
|
2055
|
+
const remainder = tempDirName.slice(tempDirPrefix.length);
|
|
2056
|
+
const firstDashIndex = remainder.indexOf("-");
|
|
2057
|
+
const secondDashIndex = firstDashIndex === -1 ? -1 : remainder.indexOf("-", firstDashIndex + 1);
|
|
2058
|
+
if (firstDashIndex === -1 || secondDashIndex === -1) {
|
|
2059
|
+
return null;
|
|
2060
|
+
}
|
|
2061
|
+
const pid = Number.parseInt(remainder.slice(0, firstDashIndex), 10);
|
|
2062
|
+
const processStartedAtMs = Number.parseInt(
|
|
2063
|
+
remainder.slice(firstDashIndex + 1, secondDashIndex),
|
|
2064
|
+
10
|
|
2065
|
+
);
|
|
2066
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
2067
|
+
return null;
|
|
2068
|
+
}
|
|
2069
|
+
if (!Number.isInteger(processStartedAtMs) || processStartedAtMs <= 0) {
|
|
2070
|
+
return null;
|
|
2071
|
+
}
|
|
2072
|
+
return { pid, processStartedAtMs };
|
|
2073
|
+
}
|
|
2074
|
+
function isProcessRunning(pid) {
|
|
2075
|
+
try {
|
|
2076
|
+
process.kill(pid, 0);
|
|
2077
|
+
return true;
|
|
2078
|
+
} catch (error) {
|
|
2079
|
+
const code = typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
2080
|
+
return code !== "ESRCH";
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
|
|
1747
2084
|
// src/browser/pool.ts
|
|
1748
2085
|
var BrowserPool = class {
|
|
1749
2086
|
browser = null;
|
|
1750
2087
|
cdpProxy = null;
|
|
1751
2088
|
launchedProcess = null;
|
|
1752
|
-
|
|
2089
|
+
managedUserDataDir = null;
|
|
2090
|
+
persistentProfile = false;
|
|
1753
2091
|
defaults;
|
|
1754
2092
|
constructor(defaults = {}) {
|
|
1755
2093
|
this.defaults = defaults;
|
|
1756
2094
|
}
|
|
1757
2095
|
async launch(options = {}) {
|
|
1758
|
-
if (this.browser || this.cdpProxy || this.launchedProcess || this.
|
|
2096
|
+
if (this.browser || this.cdpProxy || this.launchedProcess || this.managedUserDataDir) {
|
|
1759
2097
|
await this.close();
|
|
1760
2098
|
}
|
|
1761
2099
|
const mode = options.mode ?? this.defaults.mode ?? "chromium";
|
|
@@ -1805,11 +2143,13 @@ var BrowserPool = class {
|
|
|
1805
2143
|
const browser = this.browser;
|
|
1806
2144
|
const cdpProxy = this.cdpProxy;
|
|
1807
2145
|
const launchedProcess = this.launchedProcess;
|
|
1808
|
-
const
|
|
2146
|
+
const managedUserDataDir = this.managedUserDataDir;
|
|
2147
|
+
const persistentProfile = this.persistentProfile;
|
|
1809
2148
|
this.browser = null;
|
|
1810
2149
|
this.cdpProxy = null;
|
|
1811
2150
|
this.launchedProcess = null;
|
|
1812
|
-
this.
|
|
2151
|
+
this.managedUserDataDir = null;
|
|
2152
|
+
this.persistentProfile = false;
|
|
1813
2153
|
try {
|
|
1814
2154
|
if (browser) {
|
|
1815
2155
|
await browser.close().catch(() => void 0);
|
|
@@ -1817,8 +2157,8 @@ var BrowserPool = class {
|
|
|
1817
2157
|
} finally {
|
|
1818
2158
|
cdpProxy?.close();
|
|
1819
2159
|
await killProcessTree(launchedProcess);
|
|
1820
|
-
if (
|
|
1821
|
-
await (0,
|
|
2160
|
+
if (managedUserDataDir && !persistentProfile) {
|
|
2161
|
+
await (0, import_promises2.rm)(managedUserDataDir, {
|
|
1822
2162
|
recursive: true,
|
|
1823
2163
|
force: true
|
|
1824
2164
|
}).catch(() => void 0);
|
|
@@ -1830,12 +2170,13 @@ var BrowserPool = class {
|
|
|
1830
2170
|
let cdpProxy = null;
|
|
1831
2171
|
try {
|
|
1832
2172
|
const { browserWsUrl, targets } = await discoverTargets(cdpUrl);
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
2173
|
+
let targetId;
|
|
2174
|
+
if (targets.length > 0) {
|
|
2175
|
+
targetId = targets[0].id;
|
|
2176
|
+
} else {
|
|
2177
|
+
targetId = await createBlankTarget(browserWsUrl);
|
|
1837
2178
|
}
|
|
1838
|
-
cdpProxy = new CDPProxy(browserWsUrl,
|
|
2179
|
+
cdpProxy = new CDPProxy(browserWsUrl, targetId);
|
|
1839
2180
|
const proxyWsUrl = await cdpProxy.start();
|
|
1840
2181
|
browser = await import_playwright.chromium.connectOverCDP(proxyWsUrl, {
|
|
1841
2182
|
timeout: timeout ?? 3e4
|
|
@@ -1866,10 +2207,11 @@ var BrowserPool = class {
|
|
|
1866
2207
|
options.userDataDir ?? chromePaths.defaultUserDataDir
|
|
1867
2208
|
);
|
|
1868
2209
|
const profileDirectory = options.profileDirectory ?? "Default";
|
|
1869
|
-
const
|
|
2210
|
+
const persistentProfile = await getOrCreatePersistentProfile(
|
|
1870
2211
|
sourceUserDataDir,
|
|
1871
2212
|
profileDirectory
|
|
1872
2213
|
);
|
|
2214
|
+
await clearPersistentProfileSingletons(persistentProfile.userDataDir);
|
|
1873
2215
|
const debugPort = await reserveDebugPort();
|
|
1874
2216
|
const headless = resolveLaunchHeadless(
|
|
1875
2217
|
"real",
|
|
@@ -1877,7 +2219,7 @@ var BrowserPool = class {
|
|
|
1877
2219
|
this.defaults.headless
|
|
1878
2220
|
);
|
|
1879
2221
|
const launchArgs = buildRealBrowserLaunchArgs({
|
|
1880
|
-
userDataDir:
|
|
2222
|
+
userDataDir: persistentProfile.userDataDir,
|
|
1881
2223
|
profileDirectory,
|
|
1882
2224
|
debugPort,
|
|
1883
2225
|
headless
|
|
@@ -1897,24 +2239,22 @@ var BrowserPool = class {
|
|
|
1897
2239
|
timeout: options.timeout ?? 3e4
|
|
1898
2240
|
});
|
|
1899
2241
|
const { context, page } = await createOwnedBrowserContextAndPage(
|
|
1900
|
-
browser
|
|
1901
|
-
{
|
|
1902
|
-
headless,
|
|
1903
|
-
initialUrl: options.initialUrl,
|
|
1904
|
-
timeoutMs: options.timeout ?? 3e4
|
|
1905
|
-
}
|
|
2242
|
+
browser
|
|
1906
2243
|
);
|
|
2244
|
+
if (options.initialUrl) {
|
|
2245
|
+
await page.goto(options.initialUrl, {
|
|
2246
|
+
waitUntil: "domcontentloaded",
|
|
2247
|
+
timeout: options.timeout ?? 3e4
|
|
2248
|
+
});
|
|
2249
|
+
}
|
|
1907
2250
|
this.browser = browser;
|
|
1908
2251
|
this.launchedProcess = processHandle;
|
|
1909
|
-
this.
|
|
2252
|
+
this.managedUserDataDir = persistentProfile.userDataDir;
|
|
2253
|
+
this.persistentProfile = true;
|
|
1910
2254
|
return { browser, context, page, isExternal: false };
|
|
1911
2255
|
} catch (error) {
|
|
1912
2256
|
await browser?.close().catch(() => void 0);
|
|
1913
2257
|
await killProcessTree(processHandle);
|
|
1914
|
-
await (0, import_promises.rm)(tempUserDataDir, {
|
|
1915
|
-
recursive: true,
|
|
1916
|
-
force: true
|
|
1917
|
-
}).catch(() => void 0);
|
|
1918
2258
|
throw error;
|
|
1919
2259
|
}
|
|
1920
2260
|
}
|
|
@@ -1937,8 +2277,7 @@ var BrowserPool = class {
|
|
|
1937
2277
|
};
|
|
1938
2278
|
async function pickBrowserContextAndPage(browser) {
|
|
1939
2279
|
const context = getPrimaryBrowserContext(browser);
|
|
1940
|
-
const
|
|
1941
|
-
const page = pages.find((candidate) => isInspectablePageUrl2(candidate.url())) || pages[0] || await context.newPage();
|
|
2280
|
+
const page = await getAttachedPageOrCreate(context);
|
|
1942
2281
|
return { context, page };
|
|
1943
2282
|
}
|
|
1944
2283
|
function resolveLaunchHeadless(mode, requestedHeadless, defaultHeadless) {
|
|
@@ -1950,77 +2289,31 @@ function resolveLaunchHeadless(mode, requestedHeadless, defaultHeadless) {
|
|
|
1950
2289
|
}
|
|
1951
2290
|
return mode === "real";
|
|
1952
2291
|
}
|
|
1953
|
-
async function createOwnedBrowserContextAndPage(browser
|
|
2292
|
+
async function createOwnedBrowserContextAndPage(browser) {
|
|
1954
2293
|
const context = getPrimaryBrowserContext(browser);
|
|
1955
|
-
const page = await
|
|
2294
|
+
const page = await getExistingPageOrCreate(context);
|
|
1956
2295
|
return { context, page };
|
|
1957
2296
|
}
|
|
1958
|
-
async function
|
|
1959
|
-
const
|
|
1960
|
-
const
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
newWindow: !options.headless
|
|
1966
|
-
});
|
|
1967
|
-
await browserSession.send("Target.activateTarget", { targetId }).catch(() => void 0);
|
|
1968
|
-
const page = await waitForOwnedBrowserPage(context, {
|
|
1969
|
-
existingPages,
|
|
1970
|
-
targetUrl,
|
|
1971
|
-
timeoutMs: options.timeoutMs
|
|
1972
|
-
});
|
|
1973
|
-
if (targetUrl !== "about:blank") {
|
|
1974
|
-
await page.waitForLoadState("domcontentloaded", {
|
|
1975
|
-
timeout: options.timeoutMs
|
|
1976
|
-
});
|
|
1977
|
-
}
|
|
1978
|
-
await closeDisposableStartupTargets(browserSession, targetId);
|
|
1979
|
-
return page;
|
|
1980
|
-
} finally {
|
|
1981
|
-
await browserSession.detach().catch(() => void 0);
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1984
|
-
async function closeDisposableStartupTargets(browserSession, preservedTargetId) {
|
|
1985
|
-
const response = await browserSession.send("Target.getTargets").catch(() => null);
|
|
1986
|
-
if (!response) {
|
|
1987
|
-
return;
|
|
2297
|
+
async function getAttachedPageOrCreate(context) {
|
|
2298
|
+
const pages = context.pages();
|
|
2299
|
+
const inspectablePage = pages.find(
|
|
2300
|
+
(candidate) => isInspectablePageUrl2(safePageUrl(candidate))
|
|
2301
|
+
);
|
|
2302
|
+
if (inspectablePage) {
|
|
2303
|
+
return inspectablePage;
|
|
1988
2304
|
}
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
}
|
|
1993
|
-
await browserSession.send("Target.closeTarget", { targetId: targetInfo.targetId }).catch(() => void 0);
|
|
2305
|
+
const attachedPage = pages[0];
|
|
2306
|
+
if (attachedPage) {
|
|
2307
|
+
return attachedPage;
|
|
1994
2308
|
}
|
|
2309
|
+
return await context.newPage();
|
|
1995
2310
|
}
|
|
1996
|
-
async function
|
|
1997
|
-
const
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
for (const candidate of context.pages()) {
|
|
2001
|
-
if (options.existingPages.has(candidate)) {
|
|
2002
|
-
continue;
|
|
2003
|
-
}
|
|
2004
|
-
const url = candidate.url();
|
|
2005
|
-
if (!isInspectablePageUrl2(url)) {
|
|
2006
|
-
continue;
|
|
2007
|
-
}
|
|
2008
|
-
fallbackPage ??= candidate;
|
|
2009
|
-
if (options.targetUrl === "about:blank") {
|
|
2010
|
-
return candidate;
|
|
2011
|
-
}
|
|
2012
|
-
if (pageLooselyMatchesUrl(url, options.targetUrl)) {
|
|
2013
|
-
return candidate;
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
await sleep(100);
|
|
2017
|
-
}
|
|
2018
|
-
if (fallbackPage) {
|
|
2019
|
-
return fallbackPage;
|
|
2311
|
+
async function getExistingPageOrCreate(context) {
|
|
2312
|
+
const existingPage = context.pages()[0];
|
|
2313
|
+
if (existingPage) {
|
|
2314
|
+
return existingPage;
|
|
2020
2315
|
}
|
|
2021
|
-
|
|
2022
|
-
`Chrome created a target for ${options.targetUrl}, but Playwright did not expose the page in time.`
|
|
2023
|
-
);
|
|
2316
|
+
return await context.newPage();
|
|
2024
2317
|
}
|
|
2025
2318
|
function getPrimaryBrowserContext(browser) {
|
|
2026
2319
|
const contexts = browser.contexts();
|
|
@@ -2034,19 +2327,11 @@ function getPrimaryBrowserContext(browser) {
|
|
|
2034
2327
|
function isInspectablePageUrl2(url) {
|
|
2035
2328
|
return url === "about:blank" || url.startsWith("http://") || url.startsWith("https://");
|
|
2036
2329
|
}
|
|
2037
|
-
function
|
|
2038
|
-
return url === "about:blank" || url === "chrome://newtab/" || url === "chrome://new-tab-page/";
|
|
2039
|
-
}
|
|
2040
|
-
function pageLooselyMatchesUrl(currentUrl, initialUrl) {
|
|
2330
|
+
function safePageUrl(page) {
|
|
2041
2331
|
try {
|
|
2042
|
-
|
|
2043
|
-
const requested = new URL(initialUrl);
|
|
2044
|
-
if (current.href === requested.href) {
|
|
2045
|
-
return true;
|
|
2046
|
-
}
|
|
2047
|
-
return current.hostname === requested.hostname && current.pathname === requested.pathname;
|
|
2332
|
+
return page.url();
|
|
2048
2333
|
} catch {
|
|
2049
|
-
return
|
|
2334
|
+
return "";
|
|
2050
2335
|
}
|
|
2051
2336
|
}
|
|
2052
2337
|
function normalizeDiscoveryUrl(cdpUrl) {
|
|
@@ -2126,38 +2411,12 @@ async function reserveDebugPort() {
|
|
|
2126
2411
|
});
|
|
2127
2412
|
});
|
|
2128
2413
|
}
|
|
2129
|
-
async function cloneProfileToTempDir(userDataDir, profileDirectory) {
|
|
2130
|
-
const resolvedUserDataDir = expandHome(userDataDir);
|
|
2131
|
-
const tempUserDataDir = await (0, import_promises.mkdtemp)(
|
|
2132
|
-
(0, import_node_path.join)((0, import_node_os.tmpdir)(), "opensteer-real-browser-")
|
|
2133
|
-
);
|
|
2134
|
-
const sourceProfileDir = (0, import_node_path.join)(resolvedUserDataDir, profileDirectory);
|
|
2135
|
-
const targetProfileDir = (0, import_node_path.join)(tempUserDataDir, profileDirectory);
|
|
2136
|
-
if ((0, import_node_fs.existsSync)(sourceProfileDir)) {
|
|
2137
|
-
await (0, import_promises.cp)(sourceProfileDir, targetProfileDir, {
|
|
2138
|
-
recursive: true
|
|
2139
|
-
});
|
|
2140
|
-
} else {
|
|
2141
|
-
await (0, import_promises.mkdir)(targetProfileDir, {
|
|
2142
|
-
recursive: true
|
|
2143
|
-
});
|
|
2144
|
-
}
|
|
2145
|
-
const localStatePath = (0, import_node_path.join)(resolvedUserDataDir, "Local State");
|
|
2146
|
-
if ((0, import_node_fs.existsSync)(localStatePath)) {
|
|
2147
|
-
await (0, import_promises.copyFile)(localStatePath, (0, import_node_path.join)(tempUserDataDir, "Local State"));
|
|
2148
|
-
}
|
|
2149
|
-
return tempUserDataDir;
|
|
2150
|
-
}
|
|
2151
2414
|
function buildRealBrowserLaunchArgs(options) {
|
|
2152
2415
|
const args = [
|
|
2153
2416
|
`--user-data-dir=${options.userDataDir}`,
|
|
2154
2417
|
`--profile-directory=${options.profileDirectory}`,
|
|
2155
2418
|
`--remote-debugging-port=${options.debugPort}`,
|
|
2156
|
-
"--
|
|
2157
|
-
"--no-default-browser-check",
|
|
2158
|
-
"--disable-background-networking",
|
|
2159
|
-
"--disable-sync",
|
|
2160
|
-
"--disable-popup-blocking"
|
|
2419
|
+
"--disable-blink-features=AutomationControlled"
|
|
2161
2420
|
];
|
|
2162
2421
|
if (options.headless) {
|
|
2163
2422
|
args.push("--headless=new");
|
|
@@ -6975,7 +7234,7 @@ async function closeTab(context, activePage, index) {
|
|
|
6975
7234
|
}
|
|
6976
7235
|
|
|
6977
7236
|
// src/actions/cookies.ts
|
|
6978
|
-
var
|
|
7237
|
+
var import_promises3 = require("fs/promises");
|
|
6979
7238
|
async function getCookies(context, url) {
|
|
6980
7239
|
return context.cookies(url ? [url] : void 0);
|
|
6981
7240
|
}
|
|
@@ -6987,10 +7246,10 @@ async function clearCookies(context) {
|
|
|
6987
7246
|
}
|
|
6988
7247
|
async function exportCookies(context, filePath, url) {
|
|
6989
7248
|
const cookies = await context.cookies(url ? [url] : void 0);
|
|
6990
|
-
await (0,
|
|
7249
|
+
await (0, import_promises3.writeFile)(filePath, JSON.stringify(cookies, null, 2), "utf-8");
|
|
6991
7250
|
}
|
|
6992
7251
|
async function importCookies(context, filePath) {
|
|
6993
|
-
const raw = await (0,
|
|
7252
|
+
const raw = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
6994
7253
|
const cookies = JSON.parse(raw);
|
|
6995
7254
|
await context.addCookies(cookies);
|
|
6996
7255
|
}
|
|
@@ -7741,31 +8000,31 @@ function buildVariantDescriptorFromCluster(descriptors) {
|
|
|
7741
8000
|
const keyStats = /* @__PURE__ */ new Map();
|
|
7742
8001
|
for (const descriptor of descriptors) {
|
|
7743
8002
|
for (const field of descriptor.fields) {
|
|
7744
|
-
const
|
|
8003
|
+
const stat2 = keyStats.get(field.path) || {
|
|
7745
8004
|
indices: /* @__PURE__ */ new Set(),
|
|
7746
8005
|
pathNodes: [],
|
|
7747
8006
|
attributes: [],
|
|
7748
8007
|
sources: []
|
|
7749
8008
|
};
|
|
7750
|
-
|
|
8009
|
+
stat2.indices.add(descriptor.index);
|
|
7751
8010
|
if (isPersistedValueNode(field.node)) {
|
|
7752
|
-
|
|
7753
|
-
|
|
8011
|
+
stat2.pathNodes.push(field.node.$path);
|
|
8012
|
+
stat2.attributes.push(field.node.attribute);
|
|
7754
8013
|
} else if (isPersistedSourceNode(field.node)) {
|
|
7755
|
-
|
|
8014
|
+
stat2.sources.push("current_url");
|
|
7756
8015
|
}
|
|
7757
|
-
keyStats.set(field.path,
|
|
8016
|
+
keyStats.set(field.path, stat2);
|
|
7758
8017
|
}
|
|
7759
8018
|
}
|
|
7760
8019
|
const mergedFields = [];
|
|
7761
|
-
for (const [fieldPath,
|
|
7762
|
-
if (
|
|
7763
|
-
if (
|
|
8020
|
+
for (const [fieldPath, stat2] of keyStats) {
|
|
8021
|
+
if (stat2.indices.size < threshold) continue;
|
|
8022
|
+
if (stat2.pathNodes.length >= threshold) {
|
|
7764
8023
|
let mergedFieldPath = null;
|
|
7765
|
-
if (
|
|
7766
|
-
mergedFieldPath = sanitizeElementPath(
|
|
8024
|
+
if (stat2.pathNodes.length === 1) {
|
|
8025
|
+
mergedFieldPath = sanitizeElementPath(stat2.pathNodes[0]);
|
|
7767
8026
|
} else {
|
|
7768
|
-
mergedFieldPath = mergeElementPathsByMajority(
|
|
8027
|
+
mergedFieldPath = mergeElementPathsByMajority(stat2.pathNodes);
|
|
7769
8028
|
}
|
|
7770
8029
|
if (!mergedFieldPath) continue;
|
|
7771
8030
|
if (clusterSize === 1) {
|
|
@@ -7778,17 +8037,17 @@ function buildVariantDescriptorFromCluster(descriptors) {
|
|
|
7778
8037
|
mergedFieldPath,
|
|
7779
8038
|
"field"
|
|
7780
8039
|
);
|
|
7781
|
-
const attrThreshold =
|
|
8040
|
+
const attrThreshold = stat2.pathNodes.length === 1 ? 1 : majorityThreshold(stat2.pathNodes.length);
|
|
7782
8041
|
mergedFields.push({
|
|
7783
8042
|
path: fieldPath,
|
|
7784
8043
|
node: createValueNode({
|
|
7785
8044
|
elementPath: mergedFieldPath,
|
|
7786
|
-
attribute: pickModeString(
|
|
8045
|
+
attribute: pickModeString(stat2.attributes, attrThreshold)
|
|
7787
8046
|
})
|
|
7788
8047
|
});
|
|
7789
8048
|
continue;
|
|
7790
8049
|
}
|
|
7791
|
-
const dominantSource = pickModeString(
|
|
8050
|
+
const dominantSource = pickModeString(stat2.sources, threshold);
|
|
7792
8051
|
if (dominantSource === "current_url") {
|
|
7793
8052
|
mergedFields.push({
|
|
7794
8053
|
path: fieldPath,
|
|
@@ -8989,7 +9248,7 @@ function selectPreferredContextPage(browser, contexts) {
|
|
|
8989
9248
|
let aboutBlankCandidate = null;
|
|
8990
9249
|
for (const context of contexts) {
|
|
8991
9250
|
for (const page of context.pages()) {
|
|
8992
|
-
const url =
|
|
9251
|
+
const url = safePageUrl2(page);
|
|
8993
9252
|
if (!isInternalOrEmptyUrl(url)) {
|
|
8994
9253
|
return { browser, context, page };
|
|
8995
9254
|
}
|
|
@@ -9000,7 +9259,7 @@ function selectPreferredContextPage(browser, contexts) {
|
|
|
9000
9259
|
}
|
|
9001
9260
|
return aboutBlankCandidate;
|
|
9002
9261
|
}
|
|
9003
|
-
function
|
|
9262
|
+
function safePageUrl2(page) {
|
|
9004
9263
|
try {
|
|
9005
9264
|
return page.url();
|
|
9006
9265
|
} catch {
|
|
@@ -14420,8 +14679,8 @@ function buildLocalRunId(namespace) {
|
|
|
14420
14679
|
// src/browser/chromium-profile.ts
|
|
14421
14680
|
var import_node_util = require("util");
|
|
14422
14681
|
var import_node_child_process3 = require("child_process");
|
|
14423
|
-
var
|
|
14424
|
-
var
|
|
14682
|
+
var import_node_crypto2 = require("crypto");
|
|
14683
|
+
var import_promises4 = require("fs/promises");
|
|
14425
14684
|
var import_node_fs2 = require("fs");
|
|
14426
14685
|
var import_node_path2 = require("path");
|
|
14427
14686
|
var import_node_os2 = require("os");
|
|
@@ -14646,7 +14905,7 @@ function resolveCookieDbPath(profileDir) {
|
|
|
14646
14905
|
return null;
|
|
14647
14906
|
}
|
|
14648
14907
|
async function selectProfileDirFromUserDataDir(userDataDir) {
|
|
14649
|
-
const entries = await (0,
|
|
14908
|
+
const entries = await (0, import_promises4.readdir)(userDataDir, {
|
|
14650
14909
|
withFileTypes: true
|
|
14651
14910
|
}).catch(() => []);
|
|
14652
14911
|
const candidates = entries.filter((entry) => entry.isDirectory()).map((entry) => (0, import_node_path2.join)(userDataDir, entry.name)).filter((entryPath) => resolveCookieDbPath(entryPath));
|
|
@@ -14733,20 +14992,20 @@ function detectChromiumBrand(location) {
|
|
|
14733
14992
|
return DEFAULT_CHROMIUM_BRAND;
|
|
14734
14993
|
}
|
|
14735
14994
|
async function createSqliteSnapshot(dbPath) {
|
|
14736
|
-
const snapshotDir = await (0,
|
|
14995
|
+
const snapshotDir = await (0, import_promises4.mkdtemp)((0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "opensteer-cookie-db-"));
|
|
14737
14996
|
const snapshotPath = (0, import_node_path2.join)(snapshotDir, "Cookies");
|
|
14738
|
-
await (0,
|
|
14997
|
+
await (0, import_promises4.copyFile)(dbPath, snapshotPath);
|
|
14739
14998
|
for (const suffix of ["-wal", "-shm", "-journal"]) {
|
|
14740
14999
|
const source = `${dbPath}${suffix}`;
|
|
14741
15000
|
if (!(0, import_node_fs2.existsSync)(source)) {
|
|
14742
15001
|
continue;
|
|
14743
15002
|
}
|
|
14744
|
-
await (0,
|
|
15003
|
+
await (0, import_promises4.copyFile)(source, `${snapshotPath}${suffix}`);
|
|
14745
15004
|
}
|
|
14746
15005
|
return {
|
|
14747
15006
|
snapshotPath,
|
|
14748
15007
|
cleanup: async () => {
|
|
14749
|
-
await (0,
|
|
15008
|
+
await (0, import_promises4.rm)(snapshotDir, { recursive: true, force: true });
|
|
14750
15009
|
}
|
|
14751
15010
|
};
|
|
14752
15011
|
}
|
|
@@ -14792,7 +15051,7 @@ function stripDomainHashPrefix(buffer, hostKey) {
|
|
|
14792
15051
|
if (buffer.length < 32) {
|
|
14793
15052
|
return buffer;
|
|
14794
15053
|
}
|
|
14795
|
-
const domainHash = (0,
|
|
15054
|
+
const domainHash = (0, import_node_crypto2.createHash)("sha256").update(hostKey, "utf8").digest();
|
|
14796
15055
|
if (buffer.subarray(0, 32).equals(domainHash)) {
|
|
14797
15056
|
return buffer.subarray(32);
|
|
14798
15057
|
}
|
|
@@ -14801,7 +15060,7 @@ function stripDomainHashPrefix(buffer, hostKey) {
|
|
|
14801
15060
|
function decryptChromiumAes128CbcValue(encryptedValue, key, hostKey) {
|
|
14802
15061
|
const ciphertext = encryptedValue.length > 3 && encryptedValue[0] === 118 && encryptedValue[1] === 49 && (encryptedValue[2] === 48 || encryptedValue[2] === 49) ? encryptedValue.subarray(3) : encryptedValue;
|
|
14803
15062
|
const iv = Buffer.alloc(AES_BLOCK_BYTES, " ");
|
|
14804
|
-
const decipher = (0,
|
|
15063
|
+
const decipher = (0, import_node_crypto2.createDecipheriv)("aes-128-cbc", key, iv);
|
|
14805
15064
|
const plaintext = Buffer.concat([
|
|
14806
15065
|
decipher.update(ciphertext),
|
|
14807
15066
|
decipher.final()
|
|
@@ -14814,7 +15073,7 @@ function decryptChromiumAes256GcmValue(encryptedValue, key) {
|
|
|
14814
15073
|
const nonce = encryptedValue.subarray(3, 15);
|
|
14815
15074
|
const ciphertext = encryptedValue.subarray(15, encryptedValue.length - 16);
|
|
14816
15075
|
const authTag = encryptedValue.subarray(encryptedValue.length - 16);
|
|
14817
|
-
const decipher = (0,
|
|
15076
|
+
const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-gcm", key, nonce);
|
|
14818
15077
|
decipher.setAuthTag(authTag);
|
|
14819
15078
|
return Buffer.concat([
|
|
14820
15079
|
decipher.update(ciphertext),
|
|
@@ -14851,7 +15110,7 @@ async function buildChromiumDecryptor(location) {
|
|
|
14851
15110
|
`Unable to read ${brand.macService} from macOS Keychain.`
|
|
14852
15111
|
);
|
|
14853
15112
|
}
|
|
14854
|
-
const key = (0,
|
|
15113
|
+
const key = (0, import_node_crypto2.pbkdf2Sync)(password, KEY_SALT, MAC_KEY_ITERATIONS, KEY_LENGTH, "sha1");
|
|
14855
15114
|
return async (row) => decryptChromiumAes128CbcValue(
|
|
14856
15115
|
Buffer.from(row.encrypted_value || "", "hex"),
|
|
14857
15116
|
key,
|
|
@@ -14862,7 +15121,7 @@ async function buildChromiumDecryptor(location) {
|
|
|
14862
15121
|
const brand = detectChromiumBrand(location);
|
|
14863
15122
|
const keychainStore = createKeychainStore();
|
|
14864
15123
|
const password = keychainStore?.get(brand.macService, brand.macAccount) ?? brand.linuxApplications.map((application) => keychainStore?.get(application, application) ?? null).find(Boolean) ?? null;
|
|
14865
|
-
const key = (0,
|
|
15124
|
+
const key = (0, import_node_crypto2.pbkdf2Sync)(
|
|
14866
15125
|
password || "peanuts",
|
|
14867
15126
|
KEY_SALT,
|
|
14868
15127
|
LINUX_KEY_ITERATIONS,
|
|
@@ -14882,7 +15141,7 @@ async function buildChromiumDecryptor(location) {
|
|
|
14882
15141
|
);
|
|
14883
15142
|
}
|
|
14884
15143
|
const localState = JSON.parse(
|
|
14885
|
-
await (0,
|
|
15144
|
+
await (0, import_promises4.readFile)(location.localStatePath, "utf8")
|
|
14886
15145
|
);
|
|
14887
15146
|
const encryptedKeyBase64 = localState.os_crypt?.encrypted_key;
|
|
14888
15147
|
if (!encryptedKeyBase64) {
|
|
@@ -14976,18 +15235,18 @@ async function loadCookiesFromSqlite(location) {
|
|
|
14976
15235
|
}
|
|
14977
15236
|
}
|
|
14978
15237
|
async function loadCookiesFromBrowserSnapshot(location, options) {
|
|
14979
|
-
const snapshotRootDir = await (0,
|
|
15238
|
+
const snapshotRootDir = await (0, import_promises4.mkdtemp)((0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "opensteer-profile-"));
|
|
14980
15239
|
const snapshotProfileDir = (0, import_node_path2.join)(
|
|
14981
15240
|
snapshotRootDir,
|
|
14982
15241
|
(0, import_node_path2.basename)(location.profileDir)
|
|
14983
15242
|
);
|
|
14984
15243
|
let context = null;
|
|
14985
15244
|
try {
|
|
14986
|
-
await (0,
|
|
15245
|
+
await (0, import_promises4.cp)(location.profileDir, snapshotProfileDir, {
|
|
14987
15246
|
recursive: true
|
|
14988
15247
|
});
|
|
14989
15248
|
if (location.localStatePath) {
|
|
14990
|
-
await (0,
|
|
15249
|
+
await (0, import_promises4.copyFile)(location.localStatePath, (0, import_node_path2.join)(snapshotRootDir, "Local State"));
|
|
14991
15250
|
}
|
|
14992
15251
|
const brand = detectChromiumBrand(location);
|
|
14993
15252
|
const args = [`--profile-directory=${(0, import_node_path2.basename)(snapshotProfileDir)}`];
|
|
@@ -15000,7 +15259,7 @@ async function loadCookiesFromBrowserSnapshot(location, options) {
|
|
|
15000
15259
|
return await context.cookies();
|
|
15001
15260
|
} finally {
|
|
15002
15261
|
await context?.close().catch(() => void 0);
|
|
15003
|
-
await (0,
|
|
15262
|
+
await (0, import_promises4.rm)(snapshotRootDir, { recursive: true, force: true });
|
|
15004
15263
|
}
|
|
15005
15264
|
}
|
|
15006
15265
|
function isMissingSqliteBinary(error) {
|
|
@@ -15243,7 +15502,7 @@ function toResolvedCloudCredential(source, credential) {
|
|
|
15243
15502
|
}
|
|
15244
15503
|
|
|
15245
15504
|
// src/auth/machine-credential-store.ts
|
|
15246
|
-
var
|
|
15505
|
+
var import_node_crypto3 = require("crypto");
|
|
15247
15506
|
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
15248
15507
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
15249
15508
|
var import_node_path3 = __toESM(require("path"), 1);
|
|
@@ -15391,7 +15650,7 @@ function createMachineCredentialStore(options = {}) {
|
|
|
15391
15650
|
}
|
|
15392
15651
|
function resolveCredentialSlot(authDir, target) {
|
|
15393
15652
|
const normalizedBaseUrl = normalizeCredentialUrl(target.baseUrl);
|
|
15394
|
-
const storageKey = (0,
|
|
15653
|
+
const storageKey = (0, import_node_crypto3.createHash)("sha256").update(normalizedBaseUrl).digest("hex").slice(0, 24);
|
|
15395
15654
|
return {
|
|
15396
15655
|
keychainAccount: `${KEYCHAIN_ACCOUNT_PREFIX}${storageKey}`,
|
|
15397
15656
|
metadataPath: import_node_path3.default.join(authDir, `cli-login.${storageKey}.json`),
|
|
@@ -16316,7 +16575,7 @@ function createDefaultDeps() {
|
|
|
16316
16575
|
loadLocalProfileCookies: (profileDir, options) => loadCookiesFromLocalProfileDir(profileDir, options),
|
|
16317
16576
|
isInteractive: () => Boolean(process.stdin.isTTY && process.stdout.isTTY),
|
|
16318
16577
|
confirm: async (message) => {
|
|
16319
|
-
const rl = (0,
|
|
16578
|
+
const rl = (0, import_promises5.createInterface)({
|
|
16320
16579
|
input: process.stdin,
|
|
16321
16580
|
output: process.stderr
|
|
16322
16581
|
});
|