autokap 1.9.9 → 2.0.0
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-pool.d.ts +17 -0
- package/dist/browser-pool.js +78 -1
- package/dist/browser.js +7 -5
- package/dist/cli-runner.js +9 -1
- package/dist/execution-schema.d.ts +382 -182
- package/dist/execution-schema.js +40 -13
- package/dist/execution-types.d.ts +64 -33
- package/dist/llm-healer.js +28 -16
- package/dist/opcode-actions.js +139 -42
- package/dist/opcode-runner.js +27 -14
- package/dist/program-signing.d.ts +47 -7
- package/dist/recovery-chain.js +51 -12
- package/dist/selector-resolver.d.ts +19 -4
- package/dist/selector-resolver.js +39 -3
- package/dist/semantic-resolver.d.ts +8 -0
- package/dist/semantic-resolver.js +0 -0
- package/dist/video-narration-schema.d.ts +47 -7
- package/dist/wait-contract.js +4 -1
- package/dist/web-playwright-local.d.ts +12 -0
- package/dist/web-playwright-local.js +53 -0
- package/package.json +1 -1
package/dist/browser-pool.d.ts
CHANGED
|
@@ -2,6 +2,23 @@ import { type BrowserContext } from 'playwright';
|
|
|
2
2
|
import type { BrowserStorageState } from './types.js';
|
|
3
3
|
/** Chromium flags for server-side headless operation (used by pool and standalone launches). */
|
|
4
4
|
export declare const CHROMIUM_ARGS: string[];
|
|
5
|
+
/**
|
|
6
|
+
* Cloud Run NVIDIA L4 GPU launch flags for HEADLESS screenshot capture. Returns
|
|
7
|
+
* null off Cloud Run (Vercel/local have no GPU → keep software rasterization).
|
|
8
|
+
*
|
|
9
|
+
* The clip path (Browser.forClipCapture) proves the L4 binds via ANGLE/Vulkan on
|
|
10
|
+
* this image; screenshots don't need Xvfb (no ffmpeg x11grab), so we use Chromium
|
|
11
|
+
* NEW headless (`--headless=new` — the OLD `--headless` has no GPU) and strip
|
|
12
|
+
* Playwright's default `--headless` so the two don't clash. Verify the binding
|
|
13
|
+
* with the `[gpu-check]` log below: "NVIDIA"/"ANGLE (NVIDIA…)" = hardware,
|
|
14
|
+
* "SwiftShader"/"llvmpipe" = it fell back to software (then we'd need Xvfb).
|
|
15
|
+
* The GPU accelerates page render/composite (the win for animated/blur-heavy
|
|
16
|
+
* pages); the final PNG encode stays CPU-bound.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveCloudGpuLaunch(): {
|
|
19
|
+
args: string[];
|
|
20
|
+
ignoreDefaultArgs: string[];
|
|
21
|
+
} | null;
|
|
5
22
|
declare class BrowserPool {
|
|
6
23
|
private browser;
|
|
7
24
|
private launchPromise;
|
package/dist/browser-pool.js
CHANGED
|
@@ -54,6 +54,66 @@ const MAX_CAPTURES_BEFORE_RESTART = 100;
|
|
|
54
54
|
* for recovery instead of eating the whole variant. See usage in acquireContext.
|
|
55
55
|
*/
|
|
56
56
|
const POOL_CONTEXT_ACTION_TIMEOUT_MS = 25000;
|
|
57
|
+
/**
|
|
58
|
+
* Cloud Run NVIDIA L4 GPU launch flags for HEADLESS screenshot capture. Returns
|
|
59
|
+
* null off Cloud Run (Vercel/local have no GPU → keep software rasterization).
|
|
60
|
+
*
|
|
61
|
+
* The clip path (Browser.forClipCapture) proves the L4 binds via ANGLE/Vulkan on
|
|
62
|
+
* this image; screenshots don't need Xvfb (no ffmpeg x11grab), so we use Chromium
|
|
63
|
+
* NEW headless (`--headless=new` — the OLD `--headless` has no GPU) and strip
|
|
64
|
+
* Playwright's default `--headless` so the two don't clash. Verify the binding
|
|
65
|
+
* with the `[gpu-check]` log below: "NVIDIA"/"ANGLE (NVIDIA…)" = hardware,
|
|
66
|
+
* "SwiftShader"/"llvmpipe" = it fell back to software (then we'd need Xvfb).
|
|
67
|
+
* The GPU accelerates page render/composite (the win for animated/blur-heavy
|
|
68
|
+
* pages); the final PNG encode stays CPU-bound.
|
|
69
|
+
*/
|
|
70
|
+
export function resolveCloudGpuLaunch() {
|
|
71
|
+
const isCloudRunner = process.env.AUTOKAP_CLOUD_RUNNER === '1';
|
|
72
|
+
if (process.platform !== 'linux' || !isCloudRunner)
|
|
73
|
+
return null;
|
|
74
|
+
return {
|
|
75
|
+
args: [
|
|
76
|
+
'--headless=new',
|
|
77
|
+
'--use-gl=angle',
|
|
78
|
+
'--use-angle=vulkan',
|
|
79
|
+
'--enable-features=Vulkan',
|
|
80
|
+
'--ignore-gpu-blocklist',
|
|
81
|
+
'--enable-gpu-rasterization',
|
|
82
|
+
'--enable-zero-copy',
|
|
83
|
+
],
|
|
84
|
+
ignoreDefaultArgs: ['--headless'],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Log the active WebGL renderer once per pooled browser launch so a Cloud Run
|
|
88
|
+
* deploy can confirm the L4 bound (NVIDIA) vs a silent SwiftShader fallback. */
|
|
89
|
+
async function logPoolGpuRenderer(browser) {
|
|
90
|
+
try {
|
|
91
|
+
const context = await browser.newContext();
|
|
92
|
+
try {
|
|
93
|
+
const page = await context.newPage();
|
|
94
|
+
const info = await page.evaluate(() => {
|
|
95
|
+
const canvas = document.createElement('canvas');
|
|
96
|
+
const gl = (canvas.getContext('webgl2') || canvas.getContext('webgl'));
|
|
97
|
+
if (!gl)
|
|
98
|
+
return { error: 'no webgl context' };
|
|
99
|
+
const ext = gl.getExtension('WEBGL_debug_renderer_info');
|
|
100
|
+
if (!ext)
|
|
101
|
+
return { error: 'no debug_renderer_info extension' };
|
|
102
|
+
return {
|
|
103
|
+
vendor: gl.getParameter(ext.UNMASKED_VENDOR_WEBGL),
|
|
104
|
+
renderer: gl.getParameter(ext.UNMASKED_RENDERER_WEBGL),
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
console.info('[gpu-check] pool WebGL renderer:', JSON.stringify(info));
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
await context.close();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
console.warn('[gpu-check] pool WebGL query failed:', err.message);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
57
117
|
function normalizeDeviceScaleFactor(value) {
|
|
58
118
|
if (!Number.isFinite(value))
|
|
59
119
|
return 2;
|
|
@@ -134,7 +194,24 @@ class BrowserPool {
|
|
|
134
194
|
await this.launchPromise;
|
|
135
195
|
}
|
|
136
196
|
async launchBrowser() {
|
|
137
|
-
|
|
197
|
+
const gpu = resolveCloudGpuLaunch();
|
|
198
|
+
if (gpu) {
|
|
199
|
+
// Cloud Run L4: drop the software-only flags and enable Vulkan/ANGLE GPU
|
|
200
|
+
// rasterization for headless screenshot capture, mirroring the clip path.
|
|
201
|
+
const args = [
|
|
202
|
+
...CHROMIUM_ARGS.filter((a) => a !== '--disable-gpu' && a !== '--disable-gpu-sandbox'),
|
|
203
|
+
...gpu.args,
|
|
204
|
+
];
|
|
205
|
+
this.browser = await chromium.launch({
|
|
206
|
+
headless: true,
|
|
207
|
+
ignoreDefaultArgs: gpu.ignoreDefaultArgs,
|
|
208
|
+
args,
|
|
209
|
+
});
|
|
210
|
+
await logPoolGpuRenderer(this.browser);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
this.browser = await chromium.launch({ headless: true, args: CHROMIUM_ARGS });
|
|
214
|
+
}
|
|
138
215
|
this.captureCount = 0;
|
|
139
216
|
this.browser.on('disconnected', () => {
|
|
140
217
|
// Browser crashed — active contexts are now dead, they'll throw naturally
|
package/dist/browser.js
CHANGED
|
@@ -222,12 +222,14 @@ async function seedCloudChromiumPreferences(userDataDir) {
|
|
|
222
222
|
*/
|
|
223
223
|
const CONTEXT_ACTION_TIMEOUT_MS = 25000;
|
|
224
224
|
/**
|
|
225
|
-
* Explicit
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
225
|
+
* Explicit backstop for the heavy screenshot primitives. Sits just under the 45s
|
|
226
|
+
* global screenshot deadline and ABOVE the runner's reserved action budget
|
|
227
|
+
* (~global − recovery reserve), so the runner's per-attempt bound is the real
|
|
228
|
+
* control and this only catches a screenshot that has genuinely wedged. Must not
|
|
229
|
+
* be smaller than a legitimate slow high-res capture, or it would pre-empt the
|
|
230
|
+
* runner and fail captures that would have completed.
|
|
229
231
|
*/
|
|
230
|
-
const SCREENSHOT_PRIMITIVE_TIMEOUT_MS =
|
|
232
|
+
const SCREENSHOT_PRIMITIVE_TIMEOUT_MS = 40000;
|
|
231
233
|
/** Apply our engine-wide Playwright defaults to a freshly created context. */
|
|
232
234
|
function applyContextDefaults(context) {
|
|
233
235
|
context.setDefaultTimeout(CONTEXT_ACTION_TIMEOUT_MS);
|
package/dist/cli-runner.js
CHANGED
|
@@ -209,7 +209,15 @@ export async function runCapture(options) {
|
|
|
209
209
|
// serialize variants (CPU/RAM bound on the encoder side). Only 'screenshot'
|
|
210
210
|
// honors the requested concurrency.
|
|
211
211
|
const isRecordable = program.mediaMode === 'clip' || program.mediaMode === 'video';
|
|
212
|
-
|
|
212
|
+
// AUTOKAP_MAX_PARALLEL_CAPTURES lets the RUNTIME (e.g. the Cloud Run container)
|
|
213
|
+
// clamp per-run variant concurrency below what the server compiled, decoupled
|
|
214
|
+
// from billing/queue limits. Fewer concurrent captures = more CPU/GPU per
|
|
215
|
+
// capture on a shared L4 container. Unset/invalid → honor the compiled value.
|
|
216
|
+
const runtimeConcurrencyCap = Number.parseInt(process.env.AUTOKAP_MAX_PARALLEL_CAPTURES ?? '', 10);
|
|
217
|
+
const requestedConcurrency = Number.isFinite(runtimeConcurrencyCap) && runtimeConcurrencyCap > 0
|
|
218
|
+
? Math.min(program.maxParallelCaptures ?? runtimeConcurrencyCap, runtimeConcurrencyCap)
|
|
219
|
+
: program.maxParallelCaptures;
|
|
220
|
+
const maxParallelVariants = isRecordable ? 1 : requestedConcurrency;
|
|
213
221
|
// AUT-149: collect structured logs + progress events for export on failure.
|
|
214
222
|
const logCollector = new LogCollector();
|
|
215
223
|
logCollector.start();
|