@helix3/helix-cli 0.1.18-helix3.346 → 0.1.18-helix3.348
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/hostSlots.d.ts +9 -0
- package/dist/browser/hostSlots.js +145 -0
- package/dist/browser/hostSlots.js.map +1 -0
- package/dist/browser/launch.d.ts +5 -4
- package/dist/browser/launch.js +19 -8
- package/dist/browser/launch.js.map +1 -1
- package/dist/browser/nonSystemChrome.d.ts +15 -0
- package/dist/browser/nonSystemChrome.js +79 -0
- package/dist/browser/nonSystemChrome.js.map +1 -0
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/visualQa/browser.d.ts +3 -2
- package/dist/visualQa/browser.js +8 -8
- package/dist/visualQa/browser.js.map +1 -1
- package/dist/visualQa/winChrome.d.ts +3 -0
- package/dist/visualQa/winChrome.js +11 -0
- package/dist/visualQa/winChrome.js.map +1 -1
- package/package.json +1 -1
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_expression.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_jbeam.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_materials.cpython-312.pyc +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function hostBrowserCap(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): number;
|
|
2
|
+
/** Pure-ish: is this slot file's owner gone? `raw` is returned so the caller can confirm the file did not change before reclaiming. */
|
|
3
|
+
export declare function slotIsStale(file: string, alive?: (pid: number) => boolean | 'unknown'): {
|
|
4
|
+
stale: boolean;
|
|
5
|
+
raw: string | null;
|
|
6
|
+
};
|
|
7
|
+
/** Take this process's browser slot (idempotent) and wait while the host is at its cap. Resolves to the slot file, or undefined when uncapped. */
|
|
8
|
+
export declare function acquireHostBrowserSlot(): Promise<string | undefined>;
|
|
9
|
+
export declare function releaseHostBrowserSlot(): void;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.hostBrowserCap = hostBrowserCap;
|
|
7
|
+
exports.slotIsStale = slotIsStale;
|
|
8
|
+
exports.acquireHostBrowserSlot = acquireHostBrowserSlot;
|
|
9
|
+
exports.releaseHostBrowserSlot = releaseHostBrowserSlot;
|
|
10
|
+
// Host-wide cap on concurrent automated browsers. 8-16 headless QA Chromes at once cost ~5 cores and up to 22 GB on the
|
|
11
|
+
// Mac (docs/compute-offload-model.md in the HELIX workspace), and a single `helix item visual-qa` fan-out started four.
|
|
12
|
+
// Every PROCESS that opens a browser takes ONE slot for its whole life (released at exit), so a run that opens several
|
|
13
|
+
// browsers can never deadlock against itself. Slots are files in ~/.cache/helix-headless-slots/ — the same protocol as the
|
|
14
|
+
// workspace's scripts/lib/headless-browser.mjs, so scripts and this CLI share one budget. A slot whose owner pid is dead (or
|
|
15
|
+
// was reused: start time differs) is reclaimed; nothing is ever signalled.
|
|
16
|
+
// HELIX_HEADLESS_MAX=<n> cap (default 4 on macOS; unlimited elsewhere and when CI is set; 0 = off)
|
|
17
|
+
// HELIX_HEADLESS_WAIT_MS=<ms> give up waiting after this long (default 30 min) and throw
|
|
18
|
+
// HELIX_HEADLESS_SLOT_DIR=<dir> override the slot directory (tests)
|
|
19
|
+
const node_child_process_1 = require("node:child_process");
|
|
20
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
21
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
22
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
23
|
+
let held;
|
|
24
|
+
function hostBrowserCap(env = process.env, platform = process.platform) {
|
|
25
|
+
const v = env.HELIX_HEADLESS_MAX;
|
|
26
|
+
if (v !== undefined && v !== '') {
|
|
27
|
+
const n = Number(v);
|
|
28
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
|
|
29
|
+
}
|
|
30
|
+
return platform !== 'darwin' || env.CI ? 0 : 4;
|
|
31
|
+
}
|
|
32
|
+
function startStamp(pid) {
|
|
33
|
+
try {
|
|
34
|
+
return (0, node_child_process_1.execFileSync)('ps', ['-o', 'lstart=', '-p', String(pid)], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Pure-ish: is this slot file's owner gone? `raw` is returned so the caller can confirm the file did not change before reclaiming. */
|
|
41
|
+
function slotIsStale(file, alive = pidAlive) {
|
|
42
|
+
let raw;
|
|
43
|
+
try {
|
|
44
|
+
raw = node_fs_1.default.readFileSync(file, 'utf8');
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return { stale: false, raw: null };
|
|
48
|
+
}
|
|
49
|
+
let owner;
|
|
50
|
+
try {
|
|
51
|
+
owner = JSON.parse(raw);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
owner = null;
|
|
55
|
+
}
|
|
56
|
+
if (!owner || !Number.isInteger(owner.pid)) {
|
|
57
|
+
try {
|
|
58
|
+
return { stale: Date.now() - node_fs_1.default.statSync(file).mtimeMs > 5000, raw };
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return { stale: false, raw };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const state = alive(owner.pid);
|
|
65
|
+
if (state === false)
|
|
66
|
+
return { stale: true, raw };
|
|
67
|
+
if (state === 'unknown')
|
|
68
|
+
return { stale: false, raw };
|
|
69
|
+
const now = startStamp(owner.pid);
|
|
70
|
+
return { stale: !!owner.start && !!now && owner.start !== now, raw };
|
|
71
|
+
}
|
|
72
|
+
function pidAlive(pid) {
|
|
73
|
+
try {
|
|
74
|
+
process.kill(pid, 0);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
return e.code === 'ESRCH' ? false : 'unknown';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Take this process's browser slot (idempotent) and wait while the host is at its cap. Resolves to the slot file, or undefined when uncapped. */
|
|
82
|
+
async function acquireHostBrowserSlot() {
|
|
83
|
+
if (held)
|
|
84
|
+
return held;
|
|
85
|
+
const cap = hostBrowserCap();
|
|
86
|
+
if (!cap)
|
|
87
|
+
return undefined;
|
|
88
|
+
const dir = process.env.HELIX_HEADLESS_SLOT_DIR ?? node_path_1.default.join(node_os_1.default.homedir(), '.cache/helix-headless-slots');
|
|
89
|
+
node_fs_1.default.mkdirSync(dir, { recursive: true });
|
|
90
|
+
const me = JSON.stringify({ pid: process.pid, start: startStamp(process.pid), script: process.argv[1] ?? null, at: new Date().toISOString() });
|
|
91
|
+
const waitMs = Number(process.env.HELIX_HEADLESS_WAIT_MS ?? 30 * 60_000);
|
|
92
|
+
const began = Date.now();
|
|
93
|
+
let lastNote = 0;
|
|
94
|
+
for (;;) {
|
|
95
|
+
const retries = {};
|
|
96
|
+
for (let k = 0; k < cap; k++) {
|
|
97
|
+
const file = node_path_1.default.join(dir, `slot-${k}`);
|
|
98
|
+
try {
|
|
99
|
+
node_fs_1.default.writeFileSync(file, me, { flag: 'wx' });
|
|
100
|
+
held = file;
|
|
101
|
+
process.once('exit', releaseHostBrowserSlot);
|
|
102
|
+
return file;
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
if (e.code !== 'EEXIST')
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
108
|
+
const { stale, raw } = slotIsStale(file);
|
|
109
|
+
retries[k] = (retries[k] ?? 0) + 1;
|
|
110
|
+
if (stale && retries[k] <= 5) {
|
|
111
|
+
const tomb = `${file}.reclaimed-${process.pid}-${Date.now()}`;
|
|
112
|
+
try {
|
|
113
|
+
if (node_fs_1.default.readFileSync(file, 'utf8') === raw)
|
|
114
|
+
node_fs_1.default.renameSync(file, tomb);
|
|
115
|
+
node_fs_1.default.rmSync(tomb, { force: true });
|
|
116
|
+
}
|
|
117
|
+
catch { /* another reclaimer won */ }
|
|
118
|
+
k -= 1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
for (const f of node_fs_1.default.readdirSync(dir))
|
|
122
|
+
if (f.includes('.reclaimed-'))
|
|
123
|
+
node_fs_1.default.rmSync(node_path_1.default.join(dir, f), { force: true });
|
|
124
|
+
if (Date.now() - began > waitMs)
|
|
125
|
+
throw new Error(`No browser slot free after ${Math.round(waitMs / 1000)}s (host cap ${cap} in ${dir}). Other QA runs hold them; wait, or raise HELIX_HEADLESS_MAX.`);
|
|
126
|
+
if (Date.now() - lastNote > 30_000) {
|
|
127
|
+
lastNote = Date.now();
|
|
128
|
+
console.error(`[visual-qa] waiting for a browser slot: host cap is ${cap} concurrent automated browsers (HELIX_HEADLESS_MAX overrides)`);
|
|
129
|
+
}
|
|
130
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function releaseHostBrowserSlot() {
|
|
134
|
+
if (!held)
|
|
135
|
+
return;
|
|
136
|
+
const file = held;
|
|
137
|
+
held = undefined;
|
|
138
|
+
try {
|
|
139
|
+
const owner = JSON.parse(node_fs_1.default.readFileSync(file, 'utf8'));
|
|
140
|
+
if (owner.pid === process.pid)
|
|
141
|
+
node_fs_1.default.rmSync(file, { force: true });
|
|
142
|
+
}
|
|
143
|
+
catch { /* already gone */ }
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=hostSlots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostSlots.js","sourceRoot":"","sources":["../../src/browser/hostSlots.ts"],"names":[],"mappings":"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"}
|
package/dist/browser/launch.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { LaunchOptions } from 'playwright';
|
|
2
2
|
export declare const HEADLESS_GL_ARGS: string[];
|
|
3
3
|
export declare const GPU_GL_ARGS: string[];
|
|
4
|
-
export type BrowserKey = 'bundled' | 'chrome' | 'msedge';
|
|
4
|
+
export type BrowserKey = 'bundled' | 'chromium' | 'chrome' | 'msedge';
|
|
5
5
|
export type BrowserCandidate = {
|
|
6
6
|
key: BrowserKey;
|
|
7
7
|
label: string;
|
|
8
8
|
launchOptions: LaunchOptions;
|
|
9
9
|
};
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
12
|
-
export declare function
|
|
10
|
+
export declare function cachedChromiumCandidate(args: string[], cached?: string | undefined): BrowserCandidate[];
|
|
11
|
+
export declare function browserCandidates(cached?: string): BrowserCandidate[];
|
|
12
|
+
export declare function gpuBrowserCandidates(cached?: string): BrowserCandidate[];
|
|
13
|
+
export declare function selectBrowserCandidates(browser: BrowserKey | undefined, cached?: string): BrowserCandidate[];
|
|
13
14
|
export type LaunchAttempt = {
|
|
14
15
|
key: BrowserKey;
|
|
15
16
|
label: string;
|
package/dist/browser/launch.js
CHANGED
|
@@ -1,37 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GPU_GL_ARGS = exports.HEADLESS_GL_ARGS = void 0;
|
|
4
|
+
exports.cachedChromiumCandidate = cachedChromiumCandidate;
|
|
4
5
|
exports.browserCandidates = browserCandidates;
|
|
5
6
|
exports.gpuBrowserCandidates = gpuBrowserCandidates;
|
|
6
7
|
exports.selectBrowserCandidates = selectBrowserCandidates;
|
|
7
8
|
exports.composeLaunchFailure = composeLaunchFailure;
|
|
8
9
|
exports.composeTimeoutDiagnosisWith = composeTimeoutDiagnosisWith;
|
|
10
|
+
const nonSystemChrome_1 = require("./nonSystemChrome");
|
|
9
11
|
// Software-GL flags: headless Chromium has no real GPU, so WebGL must render via SwiftShader.
|
|
10
12
|
exports.HEADLESS_GL_ARGS = ['--use-angle=swiftshader', '--enable-unsafe-swiftshader'];
|
|
11
13
|
// Real-GPU flags: nothing forces software GL, and the blocklist is ignored so a headless run still gets the
|
|
12
14
|
// hardware backend on the driver/VM combinations Chrome distrusts.
|
|
13
15
|
exports.GPU_GL_ARGS = ['--ignore-gpu-blocklist'];
|
|
16
|
+
// macOS only: a cached Playwright Chromium ("Google Chrome for Testing", its own bundle id) is tried before the user's
|
|
17
|
+
// system Chrome, because an automated headless /Applications/Google Chrome.app registers as the user's own Chrome in
|
|
18
|
+
// LaunchServices and hijacks their Dock icon and Cmd-Q. `cached` is injectable so the chain stays unit-testable.
|
|
19
|
+
function cachedChromiumCandidate(args, cached = process.platform === 'darwin' ? (0, nonSystemChrome_1.findCachedAutomationChromium)() : undefined) {
|
|
20
|
+
return cached ? [{ key: 'chromium', label: 'Playwright Chromium (Chrome for Testing)', launchOptions: { headless: true, args, executablePath: cached } }] : [];
|
|
21
|
+
}
|
|
14
22
|
// Ordered fallback chain for `chromium.launch()`: the pinned bundled build first (most
|
|
15
|
-
// deterministic), then whichever system browser is already
|
|
16
|
-
// without the ~150 MB download on machines that already have Chrome or Edge.
|
|
17
|
-
function browserCandidates() {
|
|
23
|
+
// deterministic), then a cached Playwright Chromium on macOS, then whichever system browser is already
|
|
24
|
+
// installed — so first-run works without the ~150 MB download on machines that already have Chrome or Edge.
|
|
25
|
+
function browserCandidates(cached) {
|
|
18
26
|
return [
|
|
19
27
|
{ key: 'bundled', label: 'bundled Chromium', launchOptions: { headless: true, args: exports.HEADLESS_GL_ARGS } },
|
|
28
|
+
...cachedChromiumCandidate(exports.HEADLESS_GL_ARGS, cached),
|
|
20
29
|
{ key: 'chrome', label: 'system Chrome', launchOptions: { headless: true, args: exports.HEADLESS_GL_ARGS, channel: 'chrome' } },
|
|
21
30
|
{ key: 'msedge', label: 'system Edge', launchOptions: { headless: true, args: exports.HEADLESS_GL_ARGS, channel: 'msedge' } },
|
|
22
31
|
];
|
|
23
32
|
}
|
|
24
|
-
// The GPU chain:
|
|
25
|
-
// hardware GL backend at all — it renders through SwiftShader whatever flags it is handed.
|
|
26
|
-
|
|
33
|
+
// The GPU chain: full browsers only. Playwright's bundled build is the headless SHELL, which carries no
|
|
34
|
+
// hardware GL backend at all — it renders through SwiftShader whatever flags it is handed. On macOS the cached
|
|
35
|
+
// Chrome for Testing (full Chromium, real Metal/WebGPU) leads, so the user's own Chrome is only a last resort.
|
|
36
|
+
function gpuBrowserCandidates(cached) {
|
|
27
37
|
return [
|
|
38
|
+
...cachedChromiumCandidate(exports.GPU_GL_ARGS, cached),
|
|
28
39
|
{ key: 'chrome', label: 'system Chrome', launchOptions: { headless: true, args: exports.GPU_GL_ARGS, channel: 'chrome' } },
|
|
29
40
|
{ key: 'msedge', label: 'system Edge', launchOptions: { headless: true, args: exports.GPU_GL_ARGS, channel: 'msedge' } },
|
|
30
41
|
];
|
|
31
42
|
}
|
|
32
43
|
// Pure so the "forced candidate, no fallback" plan is unit-testable without Playwright.
|
|
33
|
-
function selectBrowserCandidates(browser) {
|
|
34
|
-
return browser ? browserCandidates().filter((c) => c.key === browser) : browserCandidates();
|
|
44
|
+
function selectBrowserCandidates(browser, cached) {
|
|
45
|
+
return browser ? browserCandidates(cached).filter((c) => c.key === browser) : browserCandidates(cached);
|
|
35
46
|
}
|
|
36
47
|
// Pure so the "everything failed" message is unit-testable without Playwright. The install hint only
|
|
37
48
|
// makes sense when the bundled build was among the attempts — forcing a system browser that's simply
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/browser/launch.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/browser/launch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Throws when an executable path or Playwright channel would launch the user's branded Chrome. */
|
|
2
|
+
export declare function assertNotSystemChrome(executablePath?: string, channel?: string, platform?: NodeJS.Platform): void;
|
|
3
|
+
/** Newest Chrome for Testing / Chromium in the Playwright browser cache, regardless of which Playwright installed it. */
|
|
4
|
+
export declare function findCachedAutomationChromium(home?: string, env?: NodeJS.ProcessEnv): string | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* The browser a macOS automated run should use: HELIX_VQA_CHROME, else the Playwright build's own Chromium, else any
|
|
7
|
+
* cached Chrome for Testing. Never the system Chrome. Returns undefined off macOS (callers keep their platform default).
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveAutomationChromium(opts?: {
|
|
10
|
+
override?: string;
|
|
11
|
+
playwrightDefault?: string;
|
|
12
|
+
platform?: NodeJS.Platform;
|
|
13
|
+
home?: string;
|
|
14
|
+
env?: NodeJS.ProcessEnv;
|
|
15
|
+
}): string | undefined;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.assertNotSystemChrome = assertNotSystemChrome;
|
|
7
|
+
exports.findCachedAutomationChromium = findCachedAutomationChromium;
|
|
8
|
+
exports.resolveAutomationChromium = resolveAutomationChromium;
|
|
9
|
+
// On macOS an automated headless /Applications/Google Chrome.app registers with LaunchServices under the
|
|
10
|
+
// user's own bundle id (com.google.Chrome) and can be promoted to the Foreground app: the Dock icon and
|
|
11
|
+
// Cmd-Q then target an invisible headless instance and the user's real Chrome "is active" with no UI and
|
|
12
|
+
// will not quit. Automation therefore runs on a binary with a different bundle id — Playwright's Chromium,
|
|
13
|
+
// which on macOS is "Google Chrome for Testing" (com.google.chrome.for.testing) and, unlike the headless
|
|
14
|
+
// shell, has a real Metal/WebGPU adapter.
|
|
15
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
16
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
17
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
18
|
+
const SYSTEM_CHROME_MARKERS = ['/Applications/Google Chrome.app', '/Google Chrome.app/'];
|
|
19
|
+
/** Throws when an executable path or Playwright channel would launch the user's branded Chrome. */
|
|
20
|
+
function assertNotSystemChrome(executablePath, channel, platform = process.platform) {
|
|
21
|
+
if (platform !== 'darwin')
|
|
22
|
+
return; // the LaunchServices hijack is macOS-only; Linux/Windows hosts keep their own browsers
|
|
23
|
+
if (channel && /^chrome/i.test(channel)) {
|
|
24
|
+
throw new Error(`Refusing Playwright channel '${channel}': it launches the system Google Chrome and hijacks the Dock Chrome. Use Playwright's Chromium (npx playwright install chromium).`);
|
|
25
|
+
}
|
|
26
|
+
if (executablePath && SYSTEM_CHROME_MARKERS.some((m) => executablePath.includes(m))) {
|
|
27
|
+
throw new Error(`Refusing to automate ${executablePath}: never launch /Applications/Google Chrome.app for automation. Use Playwright's Chromium / Chrome for Testing (npx playwright install chromium).`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const CFT_REL = [
|
|
31
|
+
'chrome-mac-arm64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing',
|
|
32
|
+
'chrome-mac-x64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing',
|
|
33
|
+
'chrome-mac/Chromium.app/Contents/MacOS/Chromium',
|
|
34
|
+
];
|
|
35
|
+
/** Newest Chrome for Testing / Chromium in the Playwright browser cache, regardless of which Playwright installed it. */
|
|
36
|
+
function findCachedAutomationChromium(home = node_os_1.default.homedir(), env = process.env) {
|
|
37
|
+
const roots = [env.PLAYWRIGHT_BROWSERS_PATH && env.PLAYWRIGHT_BROWSERS_PATH !== '0' ? env.PLAYWRIGHT_BROWSERS_PATH : undefined, node_path_1.default.join(home, 'Library/Caches/ms-playwright')].filter((r) => !!r);
|
|
38
|
+
for (const root of roots) {
|
|
39
|
+
let dirs = [];
|
|
40
|
+
try {
|
|
41
|
+
dirs = node_fs_1.default.readdirSync(root).filter((n) => /^chromium-\d+$/.test(n));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
dirs.sort((a, b) => Number(b.slice('chromium-'.length)) - Number(a.slice('chromium-'.length)));
|
|
47
|
+
for (const d of dirs)
|
|
48
|
+
for (const rel of CFT_REL) {
|
|
49
|
+
const p = node_path_1.default.join(root, d, rel);
|
|
50
|
+
if (node_fs_1.default.existsSync(p))
|
|
51
|
+
return p;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The browser a macOS automated run should use: HELIX_VQA_CHROME, else the Playwright build's own Chromium, else any
|
|
58
|
+
* cached Chrome for Testing. Never the system Chrome. Returns undefined off macOS (callers keep their platform default).
|
|
59
|
+
*/
|
|
60
|
+
function resolveAutomationChromium(opts = {}) {
|
|
61
|
+
const platform = opts.platform ?? process.platform;
|
|
62
|
+
const env = opts.env ?? process.env;
|
|
63
|
+
const override = opts.override ?? env.HELIX_VQA_CHROME;
|
|
64
|
+
if (override) {
|
|
65
|
+
assertNotSystemChrome(override, undefined, platform);
|
|
66
|
+
return override;
|
|
67
|
+
}
|
|
68
|
+
if (platform !== 'darwin')
|
|
69
|
+
return undefined;
|
|
70
|
+
if (opts.playwrightDefault && node_fs_1.default.existsSync(opts.playwrightDefault)) {
|
|
71
|
+
assertNotSystemChrome(opts.playwrightDefault, undefined, platform);
|
|
72
|
+
return opts.playwrightDefault;
|
|
73
|
+
}
|
|
74
|
+
const cached = findCachedAutomationChromium(opts.home, env);
|
|
75
|
+
if (cached)
|
|
76
|
+
return cached;
|
|
77
|
+
throw new Error('No Playwright Chromium / Chrome for Testing found. Run `npx playwright install chromium` (the system Google Chrome is never used for automation on macOS).');
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=nonSystemChrome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nonSystemChrome.js","sourceRoot":"","sources":["../../src/browser/nonSystemChrome.ts"],"names":[],"mappings":";;;;;AAaA,sDAQC;AASD,oEAYC;AAMD,8DAUC;AA1DD,yGAAyG;AACzG,wGAAwG;AACxG,yGAAyG;AACzG,2GAA2G;AAC3G,yGAAyG;AACzG,0CAA0C;AAC1C,sDAAyB;AACzB,sDAAyB;AACzB,0DAA6B;AAE7B,MAAM,qBAAqB,GAAG,CAAC,iCAAiC,EAAE,qBAAqB,CAAC,CAAC;AAEzF,mGAAmG;AACnG,SAAgB,qBAAqB,CAAC,cAAuB,EAAE,OAAgB,EAAE,WAA4B,OAAO,CAAC,QAAQ;IAC3H,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,CAAC,uFAAuF;IAC1H,IAAI,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,gCAAgC,OAAO,mIAAmI,CAAC,CAAC;IAC9L,CAAC;IACD,IAAI,cAAc,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpF,MAAM,IAAI,KAAK,CAAC,wBAAwB,cAAc,kJAAkJ,CAAC,CAAC;IAC5M,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG;IACd,yFAAyF;IACzF,uFAAuF;IACvF,iDAAiD;CAClD,CAAC;AAEF,yHAAyH;AACzH,SAAgB,4BAA4B,CAAC,OAAe,iBAAE,CAAC,OAAO,EAAE,EAAE,MAAyB,OAAO,CAAC,GAAG;IAC5G,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,wBAAwB,IAAI,GAAG,CAAC,wBAAwB,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC,SAAS,EAAE,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,8BAA8B,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjN,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,GAAa,EAAE,CAAC;QACxB,IAAI,CAAC;YAAC,IAAI,GAAG,iBAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QAChG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/F,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAChD,MAAM,CAAC,GAAG,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;gBAClC,IAAI,iBAAE,CAAC,UAAU,CAAC,CAAC,CAAC;oBAAE,OAAO,CAAC,CAAC;YACjC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAgB,yBAAyB,CAAC,OAA8H,EAAE;IACxK,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,gBAAgB,CAAC;IACvD,IAAI,QAAQ,EAAE,CAAC;QAAC,qBAAqB,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAAC,OAAO,QAAQ,CAAC;IAAC,CAAC;IACxF,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,IAAI,CAAC,iBAAiB,IAAI,iBAAE,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAAC,qBAAqB,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAAC,CAAC;IAC3K,MAAM,MAAM,GAAG,4BAA4B,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC5D,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,IAAI,KAAK,CAAC,4JAA4J,CAAC,CAAC;AAChL,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1767,7 +1767,7 @@ item
|
|
|
1767
1767
|
.option('--host <id...>', 'only fit onto these host/base item ids (add-ons, wearables)')
|
|
1768
1768
|
.option('--package-version <version>', 'render this version of the item\'s pinned package instead of the pin: a version move judged before the pointer moves (vehicles, avatars, add-ons, wearables)')
|
|
1769
1769
|
.option('--vehicle-package <file>', 'with --package-version on a vehicle: the version move\'s vehicle package JSON, served by Try Now after server-side preparation')
|
|
1770
|
-
.option('--chrome <path>', '
|
|
1770
|
+
.option('--chrome <path>', 'Chromium executable (default: Playwright Chromium / Chrome for Testing, headless; the macOS system Chrome is refused)')
|
|
1771
1771
|
.option('--api-url <url>', 'platform API base URL')
|
|
1772
1772
|
.option('--web-url <url>', 'website base URL (default: the site that serves --api-url)')
|
|
1773
1773
|
.option('--json', 'print the outcome as JSON')
|
|
@@ -1778,6 +1778,9 @@ item
|
|
|
1778
1778
|
const flagError = validateCandidateFlags({ packageVersion: opts.packageVersion, vehiclePackageFile: opts.vehiclePackage, submitHosted: !!(opts.hosted || opts.status || opts.hostedWorker) });
|
|
1779
1779
|
if (flagError)
|
|
1780
1780
|
fail(`✖ ${flagError}`);
|
|
1781
|
+
if (process.platform === 'darwin' && !opts.hosted && !opts.status && !opts.hostedWorker && !opts.packageVersion && !opts.json) {
|
|
1782
|
+
console.error('tip: a published version can render on the platform GPU with --hosted (no local Chrome); local renders share this Mac\'s cap of 4 concurrent automated browsers.');
|
|
1783
|
+
}
|
|
1781
1784
|
const vehiclePackage = opts.vehiclePackage ? parseVehiclePackage((0, node_fs_1.readFileSync)(opts.vehiclePackage, 'utf8'), opts.vehiclePackage) : null;
|
|
1782
1785
|
const creds = opts.submit || opts.hosted ? requireAuth() : (0, config_1.loadCredentials)();
|
|
1783
1786
|
const apiBase = opts.apiUrl ?? creds?.apiUrl ?? config_1.DEFAULT_API_URL;
|