75 lines
2.8 KiB
TypeScript
75 lines
2.8 KiB
TypeScript
import { existsSync, mkdirSync, readdirSync, symlinkSync } from 'node:fs';
|
|
import { homedir } from 'node:os';
|
|
import path from 'node:path';
|
|
import { getOpenClawConfigDir } from './paths';
|
|
|
|
const PLAYWRIGHT_BROWSERS_DIR = 'ms-playwright';
|
|
const PLAYWRIGHT_LOCKS_DIR = 'locks';
|
|
const PLAYWRIGHT_COMPLETE_MARKER = 'INSTALLATION_COMPLETE';
|
|
|
|
function resolveDefaultPlaywrightBrowsersPath(): string | null {
|
|
if (process.platform === 'darwin') {
|
|
return path.join(homedir(), 'Library', 'Caches', 'ms-playwright');
|
|
}
|
|
if (process.platform === 'win32') {
|
|
const localAppData = process.env.LOCALAPPDATA?.trim();
|
|
return localAppData ? path.join(localAppData, 'ms-playwright') : null;
|
|
}
|
|
return path.join(homedir(), '.cache', 'ms-playwright');
|
|
}
|
|
|
|
export function resolveYinianPlaywrightBrowsersPath(): string {
|
|
return path.join(getOpenClawConfigDir(), 'runtime', PLAYWRIGHT_BROWSERS_DIR);
|
|
}
|
|
|
|
export function resolveYinianPlaywrightInstallLockPath(): string {
|
|
return path.join(getOpenClawConfigDir(), 'runtime', PLAYWRIGHT_LOCKS_DIR, 'playwright-chromium-install.lock');
|
|
}
|
|
|
|
function mirrorCompletedDefaultBrowsers(targetRoot: string): void {
|
|
const defaultRoot = resolveDefaultPlaywrightBrowsersPath();
|
|
if (!defaultRoot || defaultRoot === targetRoot || !existsSync(defaultRoot)) return;
|
|
|
|
let entries;
|
|
try {
|
|
entries = readdirSync(defaultRoot, { withFileTypes: true });
|
|
} catch {
|
|
return;
|
|
}
|
|
|
|
for (const entry of entries) {
|
|
if (!entry.isDirectory() || !entry.name.startsWith('chromium')) continue;
|
|
|
|
const sourceDir = path.join(defaultRoot, entry.name);
|
|
if (!existsSync(path.join(sourceDir, PLAYWRIGHT_COMPLETE_MARKER))) continue;
|
|
|
|
const targetDir = path.join(targetRoot, entry.name);
|
|
if (existsSync(targetDir)) continue;
|
|
|
|
try {
|
|
symlinkSync(sourceDir, targetDir, process.platform === 'win32' ? 'junction' : 'dir');
|
|
} catch {
|
|
// Best effort. A missing browser remains a warning-level diagnostic.
|
|
}
|
|
}
|
|
}
|
|
|
|
export function ensureYinianPlaywrightRuntimeDirs(): void {
|
|
const browsersPath = resolveYinianPlaywrightBrowsersPath();
|
|
mkdirSync(browsersPath, { recursive: true });
|
|
mkdirSync(path.dirname(resolveYinianPlaywrightInstallLockPath()), { recursive: true });
|
|
mirrorCompletedDefaultBrowsers(browsersPath);
|
|
}
|
|
|
|
export function buildPlaywrightRuntimeEnv(
|
|
baseEnv: Record<string, string | undefined> = process.env as Record<string, string | undefined>,
|
|
): Record<string, string> {
|
|
const explicitBrowsersPath = baseEnv.PLAYWRIGHT_BROWSERS_PATH?.trim();
|
|
return {
|
|
PLAYWRIGHT_BROWSERS_PATH: explicitBrowsersPath || resolveYinianPlaywrightBrowsersPath(),
|
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: baseEnv.PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD ?? '1',
|
|
YINIAN_PLAYWRIGHT_INSTALL_LOCK_PATH: baseEnv.YINIAN_PLAYWRIGHT_INSTALL_LOCK_PATH
|
|
?? resolveYinianPlaywrightInstallLockPath(),
|
|
};
|
|
}
|