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.
@@ -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 import_promises4 = require("readline/promises");
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 import_node_fs = require("fs");
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
@@ -1821,18 +1818,282 @@ function listLocalChromeProfiles(userDataDir = detectChromePaths().defaultUserDa
1821
1818
  }
1822
1819
  }
1823
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
+
1824
2084
  // src/browser/pool.ts
1825
2085
  var BrowserPool = class {
1826
2086
  browser = null;
1827
2087
  cdpProxy = null;
1828
2088
  launchedProcess = null;
1829
- tempUserDataDir = null;
2089
+ managedUserDataDir = null;
2090
+ persistentProfile = false;
1830
2091
  defaults;
1831
2092
  constructor(defaults = {}) {
1832
2093
  this.defaults = defaults;
1833
2094
  }
1834
2095
  async launch(options = {}) {
1835
- if (this.browser || this.cdpProxy || this.launchedProcess || this.tempUserDataDir) {
2096
+ if (this.browser || this.cdpProxy || this.launchedProcess || this.managedUserDataDir) {
1836
2097
  await this.close();
1837
2098
  }
1838
2099
  const mode = options.mode ?? this.defaults.mode ?? "chromium";
@@ -1882,11 +2143,13 @@ var BrowserPool = class {
1882
2143
  const browser = this.browser;
1883
2144
  const cdpProxy = this.cdpProxy;
1884
2145
  const launchedProcess = this.launchedProcess;
1885
- const tempUserDataDir = this.tempUserDataDir;
2146
+ const managedUserDataDir = this.managedUserDataDir;
2147
+ const persistentProfile = this.persistentProfile;
1886
2148
  this.browser = null;
1887
2149
  this.cdpProxy = null;
1888
2150
  this.launchedProcess = null;
1889
- this.tempUserDataDir = null;
2151
+ this.managedUserDataDir = null;
2152
+ this.persistentProfile = false;
1890
2153
  try {
1891
2154
  if (browser) {
1892
2155
  await browser.close().catch(() => void 0);
@@ -1894,8 +2157,8 @@ var BrowserPool = class {
1894
2157
  } finally {
1895
2158
  cdpProxy?.close();
1896
2159
  await killProcessTree(launchedProcess);
1897
- if (tempUserDataDir) {
1898
- await (0, import_promises.rm)(tempUserDataDir, {
2160
+ if (managedUserDataDir && !persistentProfile) {
2161
+ await (0, import_promises2.rm)(managedUserDataDir, {
1899
2162
  recursive: true,
1900
2163
  force: true
1901
2164
  }).catch(() => void 0);
@@ -1944,10 +2207,11 @@ var BrowserPool = class {
1944
2207
  options.userDataDir ?? chromePaths.defaultUserDataDir
1945
2208
  );
1946
2209
  const profileDirectory = options.profileDirectory ?? "Default";
1947
- const tempUserDataDir = await cloneProfileToTempDir(
2210
+ const persistentProfile = await getOrCreatePersistentProfile(
1948
2211
  sourceUserDataDir,
1949
2212
  profileDirectory
1950
2213
  );
2214
+ await clearPersistentProfileSingletons(persistentProfile.userDataDir);
1951
2215
  const debugPort = await reserveDebugPort();
1952
2216
  const headless = resolveLaunchHeadless(
1953
2217
  "real",
@@ -1955,7 +2219,7 @@ var BrowserPool = class {
1955
2219
  this.defaults.headless
1956
2220
  );
1957
2221
  const launchArgs = buildRealBrowserLaunchArgs({
1958
- userDataDir: tempUserDataDir,
2222
+ userDataDir: persistentProfile.userDataDir,
1959
2223
  profileDirectory,
1960
2224
  debugPort,
1961
2225
  headless
@@ -1975,24 +2239,22 @@ var BrowserPool = class {
1975
2239
  timeout: options.timeout ?? 3e4
1976
2240
  });
1977
2241
  const { context, page } = await createOwnedBrowserContextAndPage(
1978
- browser,
1979
- {
1980
- headless,
1981
- initialUrl: options.initialUrl,
1982
- timeoutMs: options.timeout ?? 3e4
1983
- }
2242
+ browser
1984
2243
  );
2244
+ if (options.initialUrl) {
2245
+ await page.goto(options.initialUrl, {
2246
+ waitUntil: "domcontentloaded",
2247
+ timeout: options.timeout ?? 3e4
2248
+ });
2249
+ }
1985
2250
  this.browser = browser;
1986
2251
  this.launchedProcess = processHandle;
1987
- this.tempUserDataDir = tempUserDataDir;
2252
+ this.managedUserDataDir = persistentProfile.userDataDir;
2253
+ this.persistentProfile = true;
1988
2254
  return { browser, context, page, isExternal: false };
1989
2255
  } catch (error) {
1990
2256
  await browser?.close().catch(() => void 0);
1991
2257
  await killProcessTree(processHandle);
1992
- await (0, import_promises.rm)(tempUserDataDir, {
1993
- recursive: true,
1994
- force: true
1995
- }).catch(() => void 0);
1996
2258
  throw error;
1997
2259
  }
1998
2260
  }
@@ -2015,8 +2277,7 @@ var BrowserPool = class {
2015
2277
  };
2016
2278
  async function pickBrowserContextAndPage(browser) {
2017
2279
  const context = getPrimaryBrowserContext(browser);
2018
- const pages = context.pages();
2019
- const page = pages.find((candidate) => isInspectablePageUrl2(candidate.url())) || pages[0] || await context.newPage();
2280
+ const page = await getAttachedPageOrCreate(context);
2020
2281
  return { context, page };
2021
2282
  }
2022
2283
  function resolveLaunchHeadless(mode, requestedHeadless, defaultHeadless) {
@@ -2028,77 +2289,31 @@ function resolveLaunchHeadless(mode, requestedHeadless, defaultHeadless) {
2028
2289
  }
2029
2290
  return mode === "real";
2030
2291
  }
2031
- async function createOwnedBrowserContextAndPage(browser, options) {
2292
+ async function createOwnedBrowserContextAndPage(browser) {
2032
2293
  const context = getPrimaryBrowserContext(browser);
2033
- const page = await createOwnedBrowserPage(browser, context, options);
2294
+ const page = await getExistingPageOrCreate(context);
2034
2295
  return { context, page };
2035
2296
  }
2036
- async function createOwnedBrowserPage(browser, context, options) {
2037
- const targetUrl = options.initialUrl ?? "about:blank";
2038
- const existingPages = new Set(context.pages());
2039
- const browserSession = await browser.newBrowserCDPSession();
2040
- try {
2041
- const { targetId } = await browserSession.send("Target.createTarget", {
2042
- url: targetUrl,
2043
- newWindow: !options.headless
2044
- });
2045
- await browserSession.send("Target.activateTarget", { targetId }).catch(() => void 0);
2046
- const page = await waitForOwnedBrowserPage(context, {
2047
- existingPages,
2048
- targetUrl,
2049
- timeoutMs: options.timeoutMs
2050
- });
2051
- if (targetUrl !== "about:blank") {
2052
- await page.waitForLoadState("domcontentloaded", {
2053
- timeout: options.timeoutMs
2054
- });
2055
- }
2056
- await closeDisposableStartupTargets(browserSession, targetId);
2057
- return page;
2058
- } finally {
2059
- await browserSession.detach().catch(() => void 0);
2060
- }
2061
- }
2062
- async function closeDisposableStartupTargets(browserSession, preservedTargetId) {
2063
- const response = await browserSession.send("Target.getTargets").catch(() => null);
2064
- if (!response) {
2065
- 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;
2066
2304
  }
2067
- for (const targetInfo of response.targetInfos) {
2068
- if (targetInfo.targetId === preservedTargetId || targetInfo.type !== "page" || !isDisposableStartupPageUrl(targetInfo.url)) {
2069
- continue;
2070
- }
2071
- await browserSession.send("Target.closeTarget", { targetId: targetInfo.targetId }).catch(() => void 0);
2305
+ const attachedPage = pages[0];
2306
+ if (attachedPage) {
2307
+ return attachedPage;
2072
2308
  }
2309
+ return await context.newPage();
2073
2310
  }
2074
- async function waitForOwnedBrowserPage(context, options) {
2075
- const deadline = Date.now() + options.timeoutMs;
2076
- let fallbackPage = null;
2077
- while (Date.now() < deadline) {
2078
- for (const candidate of context.pages()) {
2079
- if (options.existingPages.has(candidate)) {
2080
- continue;
2081
- }
2082
- const url = candidate.url();
2083
- if (!isInspectablePageUrl2(url)) {
2084
- continue;
2085
- }
2086
- fallbackPage ??= candidate;
2087
- if (options.targetUrl === "about:blank") {
2088
- return candidate;
2089
- }
2090
- if (pageLooselyMatchesUrl(url, options.targetUrl)) {
2091
- return candidate;
2092
- }
2093
- }
2094
- await sleep(100);
2095
- }
2096
- if (fallbackPage) {
2097
- return fallbackPage;
2311
+ async function getExistingPageOrCreate(context) {
2312
+ const existingPage = context.pages()[0];
2313
+ if (existingPage) {
2314
+ return existingPage;
2098
2315
  }
2099
- throw new Error(
2100
- `Chrome created a target for ${options.targetUrl}, but Playwright did not expose the page in time.`
2101
- );
2316
+ return await context.newPage();
2102
2317
  }
2103
2318
  function getPrimaryBrowserContext(browser) {
2104
2319
  const contexts = browser.contexts();
@@ -2112,19 +2327,11 @@ function getPrimaryBrowserContext(browser) {
2112
2327
  function isInspectablePageUrl2(url) {
2113
2328
  return url === "about:blank" || url.startsWith("http://") || url.startsWith("https://");
2114
2329
  }
2115
- function isDisposableStartupPageUrl(url) {
2116
- return url === "about:blank" || url === "chrome://newtab/" || url === "chrome://new-tab-page/";
2117
- }
2118
- function pageLooselyMatchesUrl(currentUrl, initialUrl) {
2330
+ function safePageUrl(page) {
2119
2331
  try {
2120
- const current = new URL(currentUrl);
2121
- const requested = new URL(initialUrl);
2122
- if (current.href === requested.href) {
2123
- return true;
2124
- }
2125
- return current.hostname === requested.hostname && current.pathname === requested.pathname;
2332
+ return page.url();
2126
2333
  } catch {
2127
- return currentUrl === initialUrl;
2334
+ return "";
2128
2335
  }
2129
2336
  }
2130
2337
  function normalizeDiscoveryUrl(cdpUrl) {
@@ -2204,38 +2411,12 @@ async function reserveDebugPort() {
2204
2411
  });
2205
2412
  });
2206
2413
  }
2207
- async function cloneProfileToTempDir(userDataDir, profileDirectory) {
2208
- const resolvedUserDataDir = expandHome(userDataDir);
2209
- const tempUserDataDir = await (0, import_promises.mkdtemp)(
2210
- (0, import_node_path.join)((0, import_node_os.tmpdir)(), "opensteer-real-browser-")
2211
- );
2212
- const sourceProfileDir = (0, import_node_path.join)(resolvedUserDataDir, profileDirectory);
2213
- const targetProfileDir = (0, import_node_path.join)(tempUserDataDir, profileDirectory);
2214
- if ((0, import_node_fs.existsSync)(sourceProfileDir)) {
2215
- await (0, import_promises.cp)(sourceProfileDir, targetProfileDir, {
2216
- recursive: true
2217
- });
2218
- } else {
2219
- await (0, import_promises.mkdir)(targetProfileDir, {
2220
- recursive: true
2221
- });
2222
- }
2223
- const localStatePath = (0, import_node_path.join)(resolvedUserDataDir, "Local State");
2224
- if ((0, import_node_fs.existsSync)(localStatePath)) {
2225
- await (0, import_promises.copyFile)(localStatePath, (0, import_node_path.join)(tempUserDataDir, "Local State"));
2226
- }
2227
- return tempUserDataDir;
2228
- }
2229
2414
  function buildRealBrowserLaunchArgs(options) {
2230
2415
  const args = [
2231
2416
  `--user-data-dir=${options.userDataDir}`,
2232
2417
  `--profile-directory=${options.profileDirectory}`,
2233
2418
  `--remote-debugging-port=${options.debugPort}`,
2234
- "--no-first-run",
2235
- "--no-default-browser-check",
2236
- "--disable-background-networking",
2237
- "--disable-sync",
2238
- "--disable-popup-blocking"
2419
+ "--disable-blink-features=AutomationControlled"
2239
2420
  ];
2240
2421
  if (options.headless) {
2241
2422
  args.push("--headless=new");
@@ -7053,7 +7234,7 @@ async function closeTab(context, activePage, index) {
7053
7234
  }
7054
7235
 
7055
7236
  // src/actions/cookies.ts
7056
- var import_promises2 = require("fs/promises");
7237
+ var import_promises3 = require("fs/promises");
7057
7238
  async function getCookies(context, url) {
7058
7239
  return context.cookies(url ? [url] : void 0);
7059
7240
  }
@@ -7065,10 +7246,10 @@ async function clearCookies(context) {
7065
7246
  }
7066
7247
  async function exportCookies(context, filePath, url) {
7067
7248
  const cookies = await context.cookies(url ? [url] : void 0);
7068
- await (0, import_promises2.writeFile)(filePath, JSON.stringify(cookies, null, 2), "utf-8");
7249
+ await (0, import_promises3.writeFile)(filePath, JSON.stringify(cookies, null, 2), "utf-8");
7069
7250
  }
7070
7251
  async function importCookies(context, filePath) {
7071
- const raw = await (0, import_promises2.readFile)(filePath, "utf-8");
7252
+ const raw = await (0, import_promises3.readFile)(filePath, "utf-8");
7072
7253
  const cookies = JSON.parse(raw);
7073
7254
  await context.addCookies(cookies);
7074
7255
  }
@@ -7819,31 +8000,31 @@ function buildVariantDescriptorFromCluster(descriptors) {
7819
8000
  const keyStats = /* @__PURE__ */ new Map();
7820
8001
  for (const descriptor of descriptors) {
7821
8002
  for (const field of descriptor.fields) {
7822
- const stat = keyStats.get(field.path) || {
8003
+ const stat2 = keyStats.get(field.path) || {
7823
8004
  indices: /* @__PURE__ */ new Set(),
7824
8005
  pathNodes: [],
7825
8006
  attributes: [],
7826
8007
  sources: []
7827
8008
  };
7828
- stat.indices.add(descriptor.index);
8009
+ stat2.indices.add(descriptor.index);
7829
8010
  if (isPersistedValueNode(field.node)) {
7830
- stat.pathNodes.push(field.node.$path);
7831
- stat.attributes.push(field.node.attribute);
8011
+ stat2.pathNodes.push(field.node.$path);
8012
+ stat2.attributes.push(field.node.attribute);
7832
8013
  } else if (isPersistedSourceNode(field.node)) {
7833
- stat.sources.push("current_url");
8014
+ stat2.sources.push("current_url");
7834
8015
  }
7835
- keyStats.set(field.path, stat);
8016
+ keyStats.set(field.path, stat2);
7836
8017
  }
7837
8018
  }
7838
8019
  const mergedFields = [];
7839
- for (const [fieldPath, stat] of keyStats) {
7840
- if (stat.indices.size < threshold) continue;
7841
- if (stat.pathNodes.length >= threshold) {
8020
+ for (const [fieldPath, stat2] of keyStats) {
8021
+ if (stat2.indices.size < threshold) continue;
8022
+ if (stat2.pathNodes.length >= threshold) {
7842
8023
  let mergedFieldPath = null;
7843
- if (stat.pathNodes.length === 1) {
7844
- mergedFieldPath = sanitizeElementPath(stat.pathNodes[0]);
8024
+ if (stat2.pathNodes.length === 1) {
8025
+ mergedFieldPath = sanitizeElementPath(stat2.pathNodes[0]);
7845
8026
  } else {
7846
- mergedFieldPath = mergeElementPathsByMajority(stat.pathNodes);
8027
+ mergedFieldPath = mergeElementPathsByMajority(stat2.pathNodes);
7847
8028
  }
7848
8029
  if (!mergedFieldPath) continue;
7849
8030
  if (clusterSize === 1) {
@@ -7856,17 +8037,17 @@ function buildVariantDescriptorFromCluster(descriptors) {
7856
8037
  mergedFieldPath,
7857
8038
  "field"
7858
8039
  );
7859
- const attrThreshold = stat.pathNodes.length === 1 ? 1 : majorityThreshold(stat.pathNodes.length);
8040
+ const attrThreshold = stat2.pathNodes.length === 1 ? 1 : majorityThreshold(stat2.pathNodes.length);
7860
8041
  mergedFields.push({
7861
8042
  path: fieldPath,
7862
8043
  node: createValueNode({
7863
8044
  elementPath: mergedFieldPath,
7864
- attribute: pickModeString(stat.attributes, attrThreshold)
8045
+ attribute: pickModeString(stat2.attributes, attrThreshold)
7865
8046
  })
7866
8047
  });
7867
8048
  continue;
7868
8049
  }
7869
- const dominantSource = pickModeString(stat.sources, threshold);
8050
+ const dominantSource = pickModeString(stat2.sources, threshold);
7870
8051
  if (dominantSource === "current_url") {
7871
8052
  mergedFields.push({
7872
8053
  path: fieldPath,
@@ -8735,7 +8916,96 @@ function stripPositionClauses2(path7) {
8735
8916
  }
8736
8917
 
8737
8918
  // src/cloud/contracts.ts
8919
+ var cloudActionMethods = [
8920
+ "goto",
8921
+ "snapshot",
8922
+ "screenshot",
8923
+ "state",
8924
+ "click",
8925
+ "dblclick",
8926
+ "rightclick",
8927
+ "hover",
8928
+ "input",
8929
+ "select",
8930
+ "scroll",
8931
+ "tabs",
8932
+ "newTab",
8933
+ "switchTab",
8934
+ "closeTab",
8935
+ "getCookies",
8936
+ "setCookie",
8937
+ "clearCookies",
8938
+ "pressKey",
8939
+ "type",
8940
+ "getElementText",
8941
+ "getElementValue",
8942
+ "getElementAttributes",
8943
+ "getElementBoundingBox",
8944
+ "getHtml",
8945
+ "getTitle",
8946
+ "uploadFile",
8947
+ "exportCookies",
8948
+ "importCookies",
8949
+ "waitForText",
8950
+ "extract",
8951
+ "extractFromPlan",
8952
+ "clearCache"
8953
+ ];
8954
+ var cloudErrorCodes = [
8955
+ "CLOUD_AUTH_FAILED",
8956
+ "CLOUD_SESSION_NOT_FOUND",
8957
+ "CLOUD_SESSION_CLOSED",
8958
+ "CLOUD_UNSUPPORTED_METHOD",
8959
+ "CLOUD_INVALID_REQUEST",
8960
+ "CLOUD_MODEL_NOT_ALLOWED",
8961
+ "CLOUD_ACTION_FAILED",
8962
+ "CLOUD_CAPACITY_EXHAUSTED",
8963
+ "CLOUD_RUNTIME_UNAVAILABLE",
8964
+ "CLOUD_RUNTIME_MISMATCH",
8965
+ "CLOUD_SESSION_STALE",
8966
+ "CLOUD_CONTROL_PLANE_ERROR",
8967
+ "CLOUD_CONTRACT_MISMATCH",
8968
+ "CLOUD_PROXY_UNAVAILABLE",
8969
+ "CLOUD_PROXY_REQUIRED",
8970
+ "CLOUD_BILLING_LIMIT_REACHED",
8971
+ "CLOUD_RATE_LIMITED",
8972
+ "CLOUD_BROWSER_PROFILE_NOT_FOUND",
8973
+ "CLOUD_BROWSER_PROFILE_BUSY",
8974
+ "CLOUD_BROWSER_PROFILE_DISABLED",
8975
+ "CLOUD_BROWSER_PROFILE_PROXY_UNAVAILABLE",
8976
+ "CLOUD_BROWSER_PROFILE_SYNC_FAILED",
8977
+ "CLOUD_INTERNAL"
8978
+ ];
8979
+ var cloudSessionStatuses = [
8980
+ "provisioning",
8981
+ "active",
8982
+ "closing",
8983
+ "closed",
8984
+ "failed"
8985
+ ];
8738
8986
  var cloudSessionContractVersion = "v3";
8987
+ var cloudSessionSourceTypes = [
8988
+ "agent-thread",
8989
+ "agent-run",
8990
+ "project-agent-run",
8991
+ "local-cloud",
8992
+ "manual"
8993
+ ];
8994
+ var cloudActionMethodSet = new Set(cloudActionMethods);
8995
+ var cloudErrorCodeSet = new Set(cloudErrorCodes);
8996
+ var cloudSessionSourceTypeSet = new Set(
8997
+ cloudSessionSourceTypes
8998
+ );
8999
+ var cloudSessionStatusSet = new Set(cloudSessionStatuses);
9000
+ function isCloudErrorCode(value) {
9001
+ return typeof value === "string" && cloudErrorCodeSet.has(value);
9002
+ }
9003
+ function isCloudSessionSourceType(value) {
9004
+ return typeof value === "string" && cloudSessionSourceTypeSet.has(value);
9005
+ }
9006
+ function isCloudSessionStatus(value) {
9007
+ return typeof value === "string" && cloudSessionStatusSet.has(value);
9008
+ }
8739
9009
 
8740
9010
  // src/cloud/action-ws-client.ts
8741
9011
  var import_ws2 = __toESM(require("ws"), 1);
@@ -8766,6 +9036,13 @@ function cloudNotLaunchedError() {
8766
9036
  );
8767
9037
  }
8768
9038
 
9039
+ // src/cloud/ws-url.ts
9040
+ function withTokenQuery(wsUrl, token) {
9041
+ const url = new URL(wsUrl);
9042
+ url.searchParams.set("token", token);
9043
+ return url.toString();
9044
+ }
9045
+
8769
9046
  // src/cloud/action-ws-client.ts
8770
9047
  var ActionWsClient = class _ActionWsClient {
8771
9048
  ws;
@@ -8894,11 +9171,6 @@ function rawDataToUtf8(raw) {
8894
9171
  if (Array.isArray(raw)) return Buffer.concat(raw).toString("utf8");
8895
9172
  return raw.toString("utf8");
8896
9173
  }
8897
- function withTokenQuery(wsUrl, token) {
8898
- const url = new URL(wsUrl);
8899
- url.searchParams.set("token", token);
8900
- return url.toString();
8901
- }
8902
9174
 
8903
9175
  // src/cloud/local-cache-sync.ts
8904
9176
  var import_fs4 = __toESM(require("fs"), 1);
@@ -9038,7 +9310,7 @@ function dedupeNewest(entries) {
9038
9310
  var import_playwright2 = require("playwright");
9039
9311
  var CloudCdpClient = class {
9040
9312
  async connect(args) {
9041
- const endpoint = withTokenQuery2(args.wsUrl, args.token);
9313
+ const endpoint = withTokenQuery(args.wsUrl, args.token);
9042
9314
  let browser;
9043
9315
  try {
9044
9316
  browser = await import_playwright2.chromium.connectOverCDP(endpoint);
@@ -9067,7 +9339,7 @@ function selectPreferredContextPage(browser, contexts) {
9067
9339
  let aboutBlankCandidate = null;
9068
9340
  for (const context of contexts) {
9069
9341
  for (const page of context.pages()) {
9070
- const url = safePageUrl(page);
9342
+ const url = safePageUrl2(page);
9071
9343
  if (!isInternalOrEmptyUrl(url)) {
9072
9344
  return { browser, context, page };
9073
9345
  }
@@ -9078,7 +9350,7 @@ function selectPreferredContextPage(browser, contexts) {
9078
9350
  }
9079
9351
  return aboutBlankCandidate;
9080
9352
  }
9081
- function safePageUrl(page) {
9353
+ function safePageUrl2(page) {
9082
9354
  try {
9083
9355
  return page.url();
9084
9356
  } catch {
@@ -9090,11 +9362,6 @@ function isInternalOrEmptyUrl(url) {
9090
9362
  if (url === "about:blank") return true;
9091
9363
  return url.startsWith("chrome://") || url.startsWith("devtools://") || url.startsWith("edge://");
9092
9364
  }
9093
- function withTokenQuery2(wsUrl, token) {
9094
- const url = new URL(wsUrl);
9095
- url.searchParams.set("token", token);
9096
- return url.toString();
9097
- }
9098
9365
 
9099
9366
  // src/utils/strip-trailing-slashes.ts
9100
9367
  function stripTrailingSlashes(value) {
@@ -9131,10 +9398,7 @@ async function parseCloudHttpError(response) {
9131
9398
  return new OpensteerCloudError(code, message, response.status, body?.details);
9132
9399
  }
9133
9400
  function toCloudErrorCode(code) {
9134
- 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" || code === "CLOUD_PROXY_UNAVAILABLE" || code === "CLOUD_PROXY_REQUIRED" || code === "CLOUD_BILLING_LIMIT_REACHED" || code === "CLOUD_RATE_LIMITED" || code === "CLOUD_BROWSER_PROFILE_NOT_FOUND" || code === "CLOUD_BROWSER_PROFILE_BUSY" || code === "CLOUD_BROWSER_PROFILE_DISABLED" || code === "CLOUD_BROWSER_PROFILE_PROXY_UNAVAILABLE" || code === "CLOUD_BROWSER_PROFILE_SYNC_FAILED") {
9135
- return code;
9136
- }
9137
- return "CLOUD_TRANSPORT_ERROR";
9401
+ return isCloudErrorCode(code) ? code : "CLOUD_TRANSPORT_ERROR";
9138
9402
  }
9139
9403
 
9140
9404
  // src/cloud/session-client.ts
@@ -9241,7 +9505,12 @@ function parseCreateResponse(body, status) {
9241
9505
  status,
9242
9506
  "cloudSession"
9243
9507
  ),
9244
- state: requireString(cloudSessionRoot, "state", status, "cloudSession"),
9508
+ state: requireSessionStatus(
9509
+ cloudSessionRoot,
9510
+ "state",
9511
+ status,
9512
+ "cloudSession"
9513
+ ),
9245
9514
  createdAt: requireNumber(cloudSessionRoot, "createdAt", status, "cloudSession"),
9246
9515
  sourceType: requireSourceType(cloudSessionRoot, "sourceType", status, "cloudSession"),
9247
9516
  sourceRef: optionalString(cloudSessionRoot, "sourceRef", status, "cloudSession"),
@@ -9329,7 +9598,7 @@ function optionalNumber(source, field, status, parent) {
9329
9598
  }
9330
9599
  function requireSourceType(source, field, status, parent) {
9331
9600
  const value = source[field];
9332
- if (value === "agent-thread" || value === "agent-run" || value === "local-cloud" || value === "manual") {
9601
+ if (isCloudSessionSourceType(value)) {
9333
9602
  return value;
9334
9603
  }
9335
9604
  throw new OpensteerCloudError(
@@ -9337,13 +9606,30 @@ function requireSourceType(source, field, status, parent) {
9337
9606
  `Invalid cloud session create response: ${formatFieldPath(
9338
9607
  field,
9339
9608
  parent
9340
- )} must be one of "agent-thread", "agent-run", "local-cloud", or "manual".`,
9609
+ )} must be one of ${formatAllowedValues(cloudSessionSourceTypes)}.`,
9610
+ status
9611
+ );
9612
+ }
9613
+ function requireSessionStatus(source, field, status, parent) {
9614
+ const value = source[field];
9615
+ if (isCloudSessionStatus(value)) {
9616
+ return value;
9617
+ }
9618
+ throw new OpensteerCloudError(
9619
+ "CLOUD_CONTRACT_MISMATCH",
9620
+ `Invalid cloud session create response: ${formatFieldPath(
9621
+ field,
9622
+ parent
9623
+ )} must be one of ${formatAllowedValues(cloudSessionStatuses)}.`,
9341
9624
  status
9342
9625
  );
9343
9626
  }
9344
9627
  function formatFieldPath(field, parent) {
9345
9628
  return parent ? `"${parent}.${field}"` : `"${field}"`;
9346
9629
  }
9630
+ function formatAllowedValues(values) {
9631
+ return values.map((value) => `"${value}"`).join(", ");
9632
+ }
9347
9633
  function zeroImportResponse() {
9348
9634
  return {
9349
9635
  imported: 0,
@@ -14498,8 +14784,8 @@ function buildLocalRunId(namespace) {
14498
14784
  // src/browser/chromium-profile.ts
14499
14785
  var import_node_util = require("util");
14500
14786
  var import_node_child_process3 = require("child_process");
14501
- var import_node_crypto = require("crypto");
14502
- var import_promises3 = require("fs/promises");
14787
+ var import_node_crypto2 = require("crypto");
14788
+ var import_promises4 = require("fs/promises");
14503
14789
  var import_node_fs2 = require("fs");
14504
14790
  var import_node_path2 = require("path");
14505
14791
  var import_node_os2 = require("os");
@@ -14724,7 +15010,7 @@ function resolveCookieDbPath(profileDir) {
14724
15010
  return null;
14725
15011
  }
14726
15012
  async function selectProfileDirFromUserDataDir(userDataDir) {
14727
- const entries = await (0, import_promises3.readdir)(userDataDir, {
15013
+ const entries = await (0, import_promises4.readdir)(userDataDir, {
14728
15014
  withFileTypes: true
14729
15015
  }).catch(() => []);
14730
15016
  const candidates = entries.filter((entry) => entry.isDirectory()).map((entry) => (0, import_node_path2.join)(userDataDir, entry.name)).filter((entryPath) => resolveCookieDbPath(entryPath));
@@ -14811,20 +15097,20 @@ function detectChromiumBrand(location) {
14811
15097
  return DEFAULT_CHROMIUM_BRAND;
14812
15098
  }
14813
15099
  async function createSqliteSnapshot(dbPath) {
14814
- const snapshotDir = await (0, import_promises3.mkdtemp)((0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "opensteer-cookie-db-"));
15100
+ const snapshotDir = await (0, import_promises4.mkdtemp)((0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "opensteer-cookie-db-"));
14815
15101
  const snapshotPath = (0, import_node_path2.join)(snapshotDir, "Cookies");
14816
- await (0, import_promises3.copyFile)(dbPath, snapshotPath);
15102
+ await (0, import_promises4.copyFile)(dbPath, snapshotPath);
14817
15103
  for (const suffix of ["-wal", "-shm", "-journal"]) {
14818
15104
  const source = `${dbPath}${suffix}`;
14819
15105
  if (!(0, import_node_fs2.existsSync)(source)) {
14820
15106
  continue;
14821
15107
  }
14822
- await (0, import_promises3.copyFile)(source, `${snapshotPath}${suffix}`);
15108
+ await (0, import_promises4.copyFile)(source, `${snapshotPath}${suffix}`);
14823
15109
  }
14824
15110
  return {
14825
15111
  snapshotPath,
14826
15112
  cleanup: async () => {
14827
- await (0, import_promises3.rm)(snapshotDir, { recursive: true, force: true });
15113
+ await (0, import_promises4.rm)(snapshotDir, { recursive: true, force: true });
14828
15114
  }
14829
15115
  };
14830
15116
  }
@@ -14870,7 +15156,7 @@ function stripDomainHashPrefix(buffer, hostKey) {
14870
15156
  if (buffer.length < 32) {
14871
15157
  return buffer;
14872
15158
  }
14873
- const domainHash = (0, import_node_crypto.createHash)("sha256").update(hostKey, "utf8").digest();
15159
+ const domainHash = (0, import_node_crypto2.createHash)("sha256").update(hostKey, "utf8").digest();
14874
15160
  if (buffer.subarray(0, 32).equals(domainHash)) {
14875
15161
  return buffer.subarray(32);
14876
15162
  }
@@ -14879,7 +15165,7 @@ function stripDomainHashPrefix(buffer, hostKey) {
14879
15165
  function decryptChromiumAes128CbcValue(encryptedValue, key, hostKey) {
14880
15166
  const ciphertext = encryptedValue.length > 3 && encryptedValue[0] === 118 && encryptedValue[1] === 49 && (encryptedValue[2] === 48 || encryptedValue[2] === 49) ? encryptedValue.subarray(3) : encryptedValue;
14881
15167
  const iv = Buffer.alloc(AES_BLOCK_BYTES, " ");
14882
- const decipher = (0, import_node_crypto.createDecipheriv)("aes-128-cbc", key, iv);
15168
+ const decipher = (0, import_node_crypto2.createDecipheriv)("aes-128-cbc", key, iv);
14883
15169
  const plaintext = Buffer.concat([
14884
15170
  decipher.update(ciphertext),
14885
15171
  decipher.final()
@@ -14892,7 +15178,7 @@ function decryptChromiumAes256GcmValue(encryptedValue, key) {
14892
15178
  const nonce = encryptedValue.subarray(3, 15);
14893
15179
  const ciphertext = encryptedValue.subarray(15, encryptedValue.length - 16);
14894
15180
  const authTag = encryptedValue.subarray(encryptedValue.length - 16);
14895
- const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", key, nonce);
15181
+ const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-gcm", key, nonce);
14896
15182
  decipher.setAuthTag(authTag);
14897
15183
  return Buffer.concat([
14898
15184
  decipher.update(ciphertext),
@@ -14929,7 +15215,7 @@ async function buildChromiumDecryptor(location) {
14929
15215
  `Unable to read ${brand.macService} from macOS Keychain.`
14930
15216
  );
14931
15217
  }
14932
- const key = (0, import_node_crypto.pbkdf2Sync)(password, KEY_SALT, MAC_KEY_ITERATIONS, KEY_LENGTH, "sha1");
15218
+ const key = (0, import_node_crypto2.pbkdf2Sync)(password, KEY_SALT, MAC_KEY_ITERATIONS, KEY_LENGTH, "sha1");
14933
15219
  return async (row) => decryptChromiumAes128CbcValue(
14934
15220
  Buffer.from(row.encrypted_value || "", "hex"),
14935
15221
  key,
@@ -14940,7 +15226,7 @@ async function buildChromiumDecryptor(location) {
14940
15226
  const brand = detectChromiumBrand(location);
14941
15227
  const keychainStore = createKeychainStore();
14942
15228
  const password = keychainStore?.get(brand.macService, brand.macAccount) ?? brand.linuxApplications.map((application) => keychainStore?.get(application, application) ?? null).find(Boolean) ?? null;
14943
- const key = (0, import_node_crypto.pbkdf2Sync)(
15229
+ const key = (0, import_node_crypto2.pbkdf2Sync)(
14944
15230
  password || "peanuts",
14945
15231
  KEY_SALT,
14946
15232
  LINUX_KEY_ITERATIONS,
@@ -14960,7 +15246,7 @@ async function buildChromiumDecryptor(location) {
14960
15246
  );
14961
15247
  }
14962
15248
  const localState = JSON.parse(
14963
- await (0, import_promises3.readFile)(location.localStatePath, "utf8")
15249
+ await (0, import_promises4.readFile)(location.localStatePath, "utf8")
14964
15250
  );
14965
15251
  const encryptedKeyBase64 = localState.os_crypt?.encrypted_key;
14966
15252
  if (!encryptedKeyBase64) {
@@ -15054,18 +15340,18 @@ async function loadCookiesFromSqlite(location) {
15054
15340
  }
15055
15341
  }
15056
15342
  async function loadCookiesFromBrowserSnapshot(location, options) {
15057
- const snapshotRootDir = await (0, import_promises3.mkdtemp)((0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "opensteer-profile-"));
15343
+ const snapshotRootDir = await (0, import_promises4.mkdtemp)((0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "opensteer-profile-"));
15058
15344
  const snapshotProfileDir = (0, import_node_path2.join)(
15059
15345
  snapshotRootDir,
15060
15346
  (0, import_node_path2.basename)(location.profileDir)
15061
15347
  );
15062
15348
  let context = null;
15063
15349
  try {
15064
- await (0, import_promises3.cp)(location.profileDir, snapshotProfileDir, {
15350
+ await (0, import_promises4.cp)(location.profileDir, snapshotProfileDir, {
15065
15351
  recursive: true
15066
15352
  });
15067
15353
  if (location.localStatePath) {
15068
- await (0, import_promises3.copyFile)(location.localStatePath, (0, import_node_path2.join)(snapshotRootDir, "Local State"));
15354
+ await (0, import_promises4.copyFile)(location.localStatePath, (0, import_node_path2.join)(snapshotRootDir, "Local State"));
15069
15355
  }
15070
15356
  const brand = detectChromiumBrand(location);
15071
15357
  const args = [`--profile-directory=${(0, import_node_path2.basename)(snapshotProfileDir)}`];
@@ -15078,7 +15364,7 @@ async function loadCookiesFromBrowserSnapshot(location, options) {
15078
15364
  return await context.cookies();
15079
15365
  } finally {
15080
15366
  await context?.close().catch(() => void 0);
15081
- await (0, import_promises3.rm)(snapshotRootDir, { recursive: true, force: true });
15367
+ await (0, import_promises4.rm)(snapshotRootDir, { recursive: true, force: true });
15082
15368
  }
15083
15369
  }
15084
15370
  function isMissingSqliteBinary(error) {
@@ -15321,7 +15607,7 @@ function toResolvedCloudCredential(source, credential) {
15321
15607
  }
15322
15608
 
15323
15609
  // src/auth/machine-credential-store.ts
15324
- var import_node_crypto2 = require("crypto");
15610
+ var import_node_crypto3 = require("crypto");
15325
15611
  var import_node_fs3 = __toESM(require("fs"), 1);
15326
15612
  var import_node_os3 = __toESM(require("os"), 1);
15327
15613
  var import_node_path3 = __toESM(require("path"), 1);
@@ -15469,7 +15755,7 @@ function createMachineCredentialStore(options = {}) {
15469
15755
  }
15470
15756
  function resolveCredentialSlot(authDir, target) {
15471
15757
  const normalizedBaseUrl = normalizeCredentialUrl(target.baseUrl);
15472
- const storageKey = (0, import_node_crypto2.createHash)("sha256").update(normalizedBaseUrl).digest("hex").slice(0, 24);
15758
+ const storageKey = (0, import_node_crypto3.createHash)("sha256").update(normalizedBaseUrl).digest("hex").slice(0, 24);
15473
15759
  return {
15474
15760
  keychainAccount: `${KEYCHAIN_ACCOUNT_PREFIX}${storageKey}`,
15475
15761
  metadataPath: import_node_path3.default.join(authDir, `cli-login.${storageKey}.json`),
@@ -16394,7 +16680,7 @@ function createDefaultDeps() {
16394
16680
  loadLocalProfileCookies: (profileDir, options) => loadCookiesFromLocalProfileDir(profileDir, options),
16395
16681
  isInteractive: () => Boolean(process.stdin.isTTY && process.stdout.isTTY),
16396
16682
  confirm: async (message) => {
16397
- const rl = (0, import_promises4.createInterface)({
16683
+ const rl = (0, import_promises5.createInterface)({
16398
16684
  input: process.stdin,
16399
16685
  output: process.stderr
16400
16686
  });