autokap 1.0.7 → 1.0.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.
- package/assets/cursors/macos.svg +4 -0
- package/assets/cursors/windows.svg +15 -0
- package/assets/skill/OPCODE-REFERENCE.md +607 -0
- package/assets/skill/README.md +39 -0
- package/assets/skill/SKILL.md +453 -468
- package/assets/skill/STUDIO-SKILL.md +476 -0
- package/assets/skill/references/examples.md +104 -0
- package/assets/skill/references/interactive-demo.md +225 -0
- package/assets/skill/references/mock-data.md +178 -0
- package/dist/action-verifier.d.ts +29 -0
- package/dist/action-verifier.js +133 -0
- package/dist/agent-action-recovery.d.ts +45 -0
- package/dist/agent-action-recovery.js +370 -0
- package/dist/agent-message-utils.d.ts +21 -0
- package/dist/agent-message-utils.js +77 -0
- package/dist/agent-url-utils.d.ts +30 -0
- package/dist/agent-url-utils.js +138 -0
- package/dist/agent.d.ts +92 -8
- package/dist/agent.js +2936 -781
- package/dist/ak-tree.d.ts +39 -0
- package/dist/ak-tree.js +368 -0
- package/dist/alt-text.d.ts +26 -0
- package/dist/alt-text.js +55 -0
- package/dist/auth-capture.d.ts +17 -0
- package/dist/auth-capture.js +164 -0
- package/dist/benchmark.d.ts +59 -0
- package/dist/benchmark.js +135 -0
- package/dist/browser-bar.d.ts +14 -6
- package/dist/browser-bar.js +145 -8
- package/dist/browser-pool.d.ts +7 -0
- package/dist/browser-pool.js +15 -5
- package/dist/browser-utils.d.ts +31 -0
- package/dist/browser-utils.js +97 -0
- package/dist/browser.d.ts +51 -1
- package/dist/browser.js +1481 -31
- package/dist/capture-alt-text.js +2 -1
- package/dist/capture-language-preflight.js +14 -0
- package/dist/capture-llm-page-identity.js +22 -10
- package/dist/capture-page-identity.d.ts +5 -7
- package/dist/capture-page-identity.js +211 -78
- package/dist/capture-preset-credentials.d.ts +50 -0
- package/dist/capture-preset-credentials.js +127 -0
- package/dist/capture-request-plan.d.ts +2 -2
- package/dist/capture-request-plan.js +64 -16
- package/dist/capture-run-optimizer.js +48 -33
- package/dist/capture-selector-memory.d.ts +5 -0
- package/dist/capture-selector-memory.js +18 -0
- package/dist/capture-strategy.d.ts +36 -0
- package/dist/capture-strategy.js +95 -0
- package/dist/capture-studio-sync.d.ts +1 -0
- package/dist/capture-studio-sync.js +9 -3
- package/dist/capture-surface-contract.d.ts +36 -0
- package/dist/capture-surface-contract.js +299 -0
- package/dist/capture-transition-engine.d.ts +28 -0
- package/dist/capture-transition-engine.js +292 -0
- package/dist/capture-variant-state.d.ts +2 -0
- package/dist/capture-variant-state.js +26 -0
- package/dist/capture-verification.d.ts +35 -0
- package/dist/capture-verification.js +95 -0
- package/dist/capture-viewport-lock.d.ts +48 -0
- package/dist/capture-viewport-lock.js +74 -0
- package/dist/circuit-breaker.d.ts +42 -0
- package/dist/circuit-breaker.js +119 -0
- package/dist/cli-config.d.ts +8 -1
- package/dist/cli-config.js +62 -6
- package/dist/cli-contract.d.ts +15 -0
- package/dist/cli-contract.js +167 -0
- package/dist/cli-runner-local.d.ts +12 -0
- package/dist/cli-runner-local.js +102 -0
- package/dist/cli-runner.d.ts +34 -0
- package/dist/cli-runner.js +433 -0
- package/dist/cli-utils.d.ts +0 -1
- package/dist/cli-utils.js +2 -5
- package/dist/cli.js +1005 -267
- package/dist/clip-orchestrator.js +9 -2
- package/dist/clip-postprocess.js +25 -16
- package/dist/cookie-dismiss.d.ts +2 -0
- package/dist/cookie-dismiss.js +48 -13
- package/dist/cost-logging.d.ts +8 -0
- package/dist/cost-logging.js +160 -46
- package/dist/cost-resolution-monitor.d.ts +16 -0
- package/dist/cost-resolution-monitor.js +34 -0
- package/dist/credential-templates.js +2 -2
- package/dist/cursor-overlay-script.d.ts +6 -0
- package/dist/cursor-overlay-script.js +169 -0
- package/dist/dom-css-purger.d.ts +65 -0
- package/dist/dom-css-purger.js +333 -0
- package/dist/dom-font-inliner.d.ts +45 -0
- package/dist/dom-font-inliner.js +148 -0
- package/dist/dom-patch-resolver.d.ts +52 -0
- package/dist/dom-patch-resolver.js +242 -0
- package/dist/dom-serializer.d.ts +82 -0
- package/dist/dom-serializer.js +378 -0
- package/dist/element-capture.d.ts +1 -41
- package/dist/element-capture.js +202 -446
- package/dist/env-validation.d.ts +5 -0
- package/dist/env-validation.js +29 -0
- package/dist/execution-schema.d.ts +4423 -0
- package/dist/execution-schema.js +507 -0
- package/dist/execution-types.d.ts +886 -0
- package/dist/execution-types.js +65 -0
- package/dist/fonts-loader.d.ts +14 -0
- package/dist/fonts-loader.js +55 -0
- package/dist/hybrid-navigator.js +12 -12
- package/dist/index.d.ts +9 -6
- package/dist/index.js +10 -4
- package/dist/legacy/agent-action-recovery.d.ts +45 -0
- package/dist/legacy/agent-action-recovery.js +370 -0
- package/dist/legacy/agent-message-utils.d.ts +21 -0
- package/dist/legacy/agent-message-utils.js +77 -0
- package/dist/legacy/agent-url-utils.d.ts +30 -0
- package/dist/legacy/agent-url-utils.js +138 -0
- package/dist/legacy/agent.d.ts +226 -0
- package/dist/legacy/agent.js +6666 -0
- package/dist/legacy/clip-orchestrator.d.ts +148 -0
- package/dist/legacy/clip-orchestrator.js +957 -0
- package/dist/legacy/credential-templates.d.ts +5 -0
- package/dist/legacy/credential-templates.js +60 -0
- package/dist/legacy/hybrid-navigator.d.ts +138 -0
- package/dist/legacy/hybrid-navigator.js +468 -0
- package/dist/legacy/llm-usage.d.ts +17 -0
- package/dist/legacy/llm-usage.js +45 -0
- package/dist/legacy/prompt-cache.d.ts +10 -0
- package/dist/legacy/prompt-cache.js +24 -0
- package/dist/legacy/prompts.d.ts +175 -0
- package/dist/legacy/prompts.js +1038 -0
- package/dist/legacy/tools.d.ts +4 -0
- package/dist/legacy/tools.js +216 -0
- package/dist/legacy/video-agent.d.ts +143 -0
- package/dist/legacy/video-agent.js +4788 -0
- package/dist/legacy/video-observation.d.ts +36 -0
- package/dist/legacy/video-observation.js +192 -0
- package/dist/legacy/video-planner.d.ts +12 -0
- package/dist/legacy/video-planner.js +501 -0
- package/dist/legacy/video-prompts.d.ts +37 -0
- package/dist/legacy/video-prompts.js +569 -0
- package/dist/legacy/video-tools.d.ts +3 -0
- package/dist/legacy/video-tools.js +59 -0
- package/dist/legacy/video-variant-state.d.ts +29 -0
- package/dist/legacy/video-variant-state.js +80 -0
- package/dist/legacy/vision-model.d.ts +17 -0
- package/dist/legacy/vision-model.js +74 -0
- package/dist/llm-healer.d.ts +63 -0
- package/dist/llm-healer.js +166 -0
- package/dist/llm-provider.d.ts +29 -0
- package/dist/llm-provider.js +80 -0
- package/dist/logger.d.ts +6 -2
- package/dist/logger.js +15 -1
- package/dist/mockup-html.js +35 -25
- package/dist/mockup.d.ts +95 -2
- package/dist/mockup.js +427 -166
- package/dist/mouse-animation.d.ts +2 -2
- package/dist/mouse-animation.js +34 -20
- package/dist/opcode-actions.d.ts +42 -0
- package/dist/opcode-actions.js +511 -0
- package/dist/opcode-runner.d.ts +51 -0
- package/dist/opcode-runner.js +770 -0
- package/dist/openrouter-client.d.ts +40 -0
- package/dist/openrouter-client.js +16 -0
- package/dist/overlay-engine.d.ts +24 -0
- package/dist/overlay-engine.js +176 -0
- package/dist/postcondition.d.ts +16 -0
- package/dist/postcondition.js +269 -0
- package/dist/program-patcher.d.ts +25 -0
- package/dist/program-patcher.js +44 -0
- package/dist/prompts.d.ts +13 -5
- package/dist/prompts.js +224 -351
- package/dist/provider-config.d.ts +12 -0
- package/dist/provider-config.js +15 -0
- package/dist/recovery-chain.d.ts +37 -0
- package/dist/recovery-chain.js +350 -0
- package/dist/remote-browser.d.ts +28 -4
- package/dist/remote-browser.js +60 -5
- package/dist/safari-browser-bar.d.ts +15 -0
- package/dist/safari-browser-bar.js +95 -0
- package/dist/safari-toolbar-asset.d.ts +15 -0
- package/dist/safari-toolbar-asset.js +12 -0
- package/dist/security.d.ts +2 -1
- package/dist/security.js +49 -10
- package/dist/selector-resolver.d.ts +34 -0
- package/dist/selector-resolver.js +181 -0
- package/dist/semantic-resolver.d.ts +35 -0
- package/dist/semantic-resolver.js +161 -0
- package/dist/server-capture-runtime.d.ts +5 -3
- package/dist/server-capture-runtime.js +42 -95
- package/dist/server-credit-usage.d.ts +2 -2
- package/dist/server-project-webhooks.d.ts +15 -1
- package/dist/server-project-webhooks.js +34 -8
- package/dist/server-screenshot-watermark.js +27 -5
- package/dist/session-profile.js +164 -1
- package/dist/sf-pro-symbols.d.ts +1 -0
- package/dist/sf-pro-symbols.js +55 -0
- package/dist/skill-packaging.d.ts +28 -0
- package/dist/skill-packaging.js +169 -0
- package/dist/smart-wait.d.ts +27 -0
- package/dist/smart-wait.js +81 -0
- package/dist/status-bar-render.d.ts +20 -0
- package/dist/status-bar-render.js +410 -0
- package/dist/status-bar.d.ts +9 -0
- package/dist/status-bar.js +298 -14
- package/dist/svg-browser-bar.d.ts +33 -0
- package/dist/svg-browser-bar.js +206 -0
- package/dist/svg-status-bar.d.ts +36 -0
- package/dist/svg-status-bar.js +597 -0
- package/dist/svg-text.d.ts +61 -0
- package/dist/svg-text.js +118 -0
- package/dist/tools.js +89 -451
- package/dist/types.d.ts +240 -5
- package/dist/types.js +23 -1
- package/dist/v2/action-verifier.d.ts +29 -0
- package/dist/v2/action-verifier.js +133 -0
- package/dist/v2/alt-text.d.ts +26 -0
- package/dist/v2/alt-text.js +55 -0
- package/dist/v2/benchmark.d.ts +59 -0
- package/dist/v2/benchmark.js +135 -0
- package/dist/v2/capture-strategy.d.ts +30 -0
- package/dist/v2/capture-strategy.js +67 -0
- package/dist/v2/capture-verification.d.ts +35 -0
- package/dist/v2/capture-verification.js +95 -0
- package/dist/v2/circuit-breaker.d.ts +42 -0
- package/dist/v2/circuit-breaker.js +119 -0
- package/dist/v2/cli-runner-local.d.ts +11 -0
- package/dist/v2/cli-runner-local.js +91 -0
- package/dist/v2/cli-runner.d.ts +34 -0
- package/dist/v2/cli-runner.js +300 -0
- package/dist/v2/compiler-prompts.d.ts +27 -0
- package/dist/v2/compiler-prompts.js +123 -0
- package/dist/v2/compiler.d.ts +37 -0
- package/dist/v2/compiler.js +147 -0
- package/dist/v2/explorer.d.ts +41 -0
- package/dist/v2/explorer.js +56 -0
- package/dist/v2/index.d.ts +37 -0
- package/dist/v2/index.js +31 -0
- package/dist/v2/llm-healer.d.ts +62 -0
- package/dist/v2/llm-healer.js +166 -0
- package/dist/v2/llm-provider.d.ts +29 -0
- package/dist/v2/llm-provider.js +80 -0
- package/dist/v2/opcode-runner.d.ts +47 -0
- package/dist/v2/opcode-runner.js +634 -0
- package/dist/v2/overlay-engine.d.ts +24 -0
- package/dist/v2/overlay-engine.js +150 -0
- package/dist/v2/postcondition.d.ts +16 -0
- package/dist/v2/postcondition.js +249 -0
- package/dist/v2/program-patcher.d.ts +25 -0
- package/dist/v2/program-patcher.js +44 -0
- package/dist/v2/recovery-chain.d.ts +30 -0
- package/dist/v2/recovery-chain.js +368 -0
- package/dist/v2/schema.d.ts +2580 -0
- package/dist/v2/schema.js +295 -0
- package/dist/v2/selector-resolver.d.ts +34 -0
- package/dist/v2/selector-resolver.js +181 -0
- package/dist/v2/semantic-resolver.d.ts +35 -0
- package/dist/v2/semantic-resolver.js +161 -0
- package/dist/v2/smart-wait.d.ts +27 -0
- package/dist/v2/smart-wait.js +81 -0
- package/dist/v2/types.d.ts +444 -0
- package/dist/v2/types.js +19 -0
- package/dist/v2/web-playwright-local.d.ts +69 -0
- package/dist/v2/web-playwright-local.js +392 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/video-agent.js +18 -13
- package/dist/video-planner.js +2 -1
- package/dist/video-prompts.js +3 -3
- package/dist/web-playwright-local.d.ts +126 -0
- package/dist/web-playwright-local.js +819 -0
- package/dist/ws-auth.js +4 -1
- package/dist/ws-broadcast.d.ts +34 -0
- package/dist/ws-broadcast.js +85 -0
- package/dist/ws-connection-limits.d.ts +12 -0
- package/dist/ws-connection-limits.js +44 -0
- package/dist/ws-handler-utils.d.ts +32 -0
- package/dist/ws-handler-utils.js +139 -0
- package/dist/ws-handler.js +294 -164
- package/dist/ws-metrics-server.d.ts +9 -0
- package/dist/ws-metrics-server.js +31 -0
- package/dist/ws-server.js +41 -1
- package/package.json +51 -34
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdtemp } from 'node:fs/promises';
|
|
1
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { logger } from './logger.js';
|
|
@@ -891,8 +891,9 @@ async function runClipVariantAttempt(clip, target, lang, theme, navResult, confi
|
|
|
891
891
|
clipOptions,
|
|
892
892
|
parentSignal: config.abortSignal,
|
|
893
893
|
run: async (_signal, _attempt, _phaseContext) => {
|
|
894
|
+
let outputDir = null;
|
|
894
895
|
try {
|
|
895
|
-
|
|
896
|
+
outputDir = await mkdtemp(path.join(os.tmpdir(), `clip-${clip.id}-`));
|
|
896
897
|
const outputScale = config.outputScale ?? 1;
|
|
897
898
|
const postResult = await postProcessClipRecording(recordResult.videoPath, outputDir, `${clip.id}_${variantId.replace(/:/g, '_')}`, {
|
|
898
899
|
...clipOptions,
|
|
@@ -906,6 +907,12 @@ async function runClipVariantAttempt(clip, target, lang, theme, navResult, confi
|
|
|
906
907
|
logger.error(`Post-processing failed for clip "${clip.name}" variant ${variantId}: ${err.message}`);
|
|
907
908
|
return { ok: false, reason: `Post-processing failed: ${err.message}` };
|
|
908
909
|
}
|
|
910
|
+
finally {
|
|
911
|
+
// Clean up temp directory to avoid orphaned files
|
|
912
|
+
if (outputDir) {
|
|
913
|
+
rm(outputDir, { recursive: true, force: true }).catch(() => { });
|
|
914
|
+
}
|
|
915
|
+
}
|
|
909
916
|
},
|
|
910
917
|
});
|
|
911
918
|
if (!postprocessPhase.ok) {
|
package/dist/clip-postprocess.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
|
-
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { rm, stat } from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
const execFileAsync = promisify(execFile);
|
|
@@ -9,24 +9,33 @@ const DEFAULT_GIF_MAX_WIDTH = 800;
|
|
|
9
9
|
const DEFAULT_MAX_DURATION_SEC = 8;
|
|
10
10
|
const DEFAULT_TRIM_START_SEC = 0.3;
|
|
11
11
|
// ── ffmpeg detection ────────────────────────────────────────────────
|
|
12
|
-
|
|
12
|
+
const cachedBinaryPaths = {};
|
|
13
|
+
async function ensureBinaryAvailable(binaryName) {
|
|
14
|
+
const cached = cachedBinaryPaths[binaryName];
|
|
15
|
+
if (cached)
|
|
16
|
+
return cached;
|
|
17
|
+
const resolver = process.platform === 'win32' ? 'where' : 'which';
|
|
18
|
+
const { stdout } = await execFileAsync(resolver, [binaryName]);
|
|
19
|
+
const resolvedPath = stdout
|
|
20
|
+
.split(/\r?\n/)
|
|
21
|
+
.map(line => line.trim())
|
|
22
|
+
.find(Boolean);
|
|
23
|
+
if (!resolvedPath) {
|
|
24
|
+
throw new Error(`${binaryName} not found`);
|
|
25
|
+
}
|
|
26
|
+
cachedBinaryPaths[binaryName] = resolvedPath;
|
|
27
|
+
return resolvedPath;
|
|
28
|
+
}
|
|
13
29
|
/**
|
|
14
30
|
* Resolve the system ffmpeg binary path. Throws if not found.
|
|
15
31
|
*/
|
|
16
32
|
export async function ensureFfmpegAvailable() {
|
|
17
|
-
if (cachedFfmpegPath)
|
|
18
|
-
return cachedFfmpegPath;
|
|
19
33
|
try {
|
|
20
|
-
|
|
21
|
-
const ffmpegPath = stdout.trim();
|
|
22
|
-
if (!ffmpegPath)
|
|
23
|
-
throw new Error('ffmpeg not found');
|
|
24
|
-
cachedFfmpegPath = ffmpegPath;
|
|
25
|
-
return ffmpegPath;
|
|
34
|
+
return await ensureBinaryAvailable('ffmpeg');
|
|
26
35
|
}
|
|
27
36
|
catch {
|
|
28
37
|
throw new Error('ffmpeg is required for clip post-processing but was not found on your system. ' +
|
|
29
|
-
'Install it via: brew install ffmpeg (macOS)
|
|
38
|
+
'Install it via: brew install ffmpeg (macOS), apt install ffmpeg (Linux), or choco install ffmpeg (Windows).');
|
|
30
39
|
}
|
|
31
40
|
}
|
|
32
41
|
// ── Conversion functions ────────────────────────────────────────────
|
|
@@ -61,7 +70,8 @@ export async function convertToGif(webmPath, outputPath, opts = {}) {
|
|
|
61
70
|
finally {
|
|
62
71
|
// Clean up palette file
|
|
63
72
|
try {
|
|
64
|
-
await stat(palettePath)
|
|
73
|
+
await stat(palettePath);
|
|
74
|
+
await rm(palettePath, { force: true });
|
|
65
75
|
}
|
|
66
76
|
catch { /* ignore */ }
|
|
67
77
|
}
|
|
@@ -110,8 +120,7 @@ export async function trimRecording(inputPath, outputPath, startSec = DEFAULT_TR
|
|
|
110
120
|
* Get the duration of a media file in milliseconds.
|
|
111
121
|
*/
|
|
112
122
|
export async function getMediaDurationMs(filePath) {
|
|
113
|
-
const
|
|
114
|
-
const ffprobe = ffmpeg.replace(/ffmpeg$/, 'ffprobe');
|
|
123
|
+
const ffprobe = await ensureBinaryAvailable('ffprobe');
|
|
115
124
|
const { stdout } = await execFileAsync(ffprobe, [
|
|
116
125
|
'-v', 'error',
|
|
117
126
|
'-show_entries', 'format=duration',
|
|
@@ -178,12 +187,12 @@ export async function postProcessClipRecording(webmPath, outputDir, clipId, opti
|
|
|
178
187
|
result.thumbnailPath = thumbnailPath;
|
|
179
188
|
// Clean up intermediate files
|
|
180
189
|
try {
|
|
181
|
-
await
|
|
190
|
+
await rm(trimmedPath, { force: true });
|
|
182
191
|
}
|
|
183
192
|
catch { /* ignore */ }
|
|
184
193
|
if (sourcePath !== trimmedPath) {
|
|
185
194
|
try {
|
|
186
|
-
await
|
|
195
|
+
await rm(sourcePath, { force: true });
|
|
187
196
|
}
|
|
188
197
|
catch { /* ignore */ }
|
|
189
198
|
}
|
package/dist/cookie-dismiss.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Page } from 'playwright';
|
|
2
|
+
export declare function getCaptureHideCSS(): string;
|
|
3
|
+
export declare function ensureCaptureHideStyles(page: Page): Promise<void>;
|
|
2
4
|
export declare function dismissCookiesAndWidgets(page: Page): Promise<{
|
|
3
5
|
dismissed: boolean;
|
|
4
6
|
method: string | null;
|
package/dist/cookie-dismiss.js
CHANGED
|
@@ -82,6 +82,51 @@ const HIDE_SELECTORS = [
|
|
|
82
82
|
'[id*="cookieBanner"]', '[id*="cookieConsent"]',
|
|
83
83
|
'[class*="gdpr"]', '[id*="gdpr"]',
|
|
84
84
|
];
|
|
85
|
+
// Dev-only chrome that should never appear in captures
|
|
86
|
+
const DEV_TOOL_SELECTORS = [
|
|
87
|
+
// Next.js dev indicator / devtools
|
|
88
|
+
'nextjs-portal',
|
|
89
|
+
'#__next-build-watcher',
|
|
90
|
+
'[data-next-badge-root]',
|
|
91
|
+
// Astro dev toolbar
|
|
92
|
+
'astro-dev-toolbar',
|
|
93
|
+
// Vite overlays
|
|
94
|
+
'vite-error-overlay',
|
|
95
|
+
'vite-plugin-checker-error-overlay',
|
|
96
|
+
// Nuxt devtools
|
|
97
|
+
'nuxt-devtools',
|
|
98
|
+
'nuxt-devtools-frame',
|
|
99
|
+
'#nuxt-devtools-anchor',
|
|
100
|
+
'#nuxt-devtools-container',
|
|
101
|
+
];
|
|
102
|
+
const CAPTURE_HIDE_STYLE_ID = 'autokap-capture-hide-style';
|
|
103
|
+
export function getCaptureHideCSS() {
|
|
104
|
+
return [...HIDE_SELECTORS, ...DEV_TOOL_SELECTORS].map(selector => `${selector} { display: none !important; visibility: hidden !important; pointer-events: none !important; }`).join('\n');
|
|
105
|
+
}
|
|
106
|
+
export async function ensureCaptureHideStyles(page) {
|
|
107
|
+
try {
|
|
108
|
+
await page.evaluate(({ styleId, css }) => {
|
|
109
|
+
const parent = document.head ?? document.documentElement;
|
|
110
|
+
if (!parent)
|
|
111
|
+
return;
|
|
112
|
+
let style = document.getElementById(styleId);
|
|
113
|
+
if (!style) {
|
|
114
|
+
style = document.createElement('style');
|
|
115
|
+
style.id = styleId;
|
|
116
|
+
parent.appendChild(style);
|
|
117
|
+
}
|
|
118
|
+
if (style.textContent !== css) {
|
|
119
|
+
style.textContent = css;
|
|
120
|
+
}
|
|
121
|
+
}, {
|
|
122
|
+
styleId: CAPTURE_HIDE_STYLE_ID,
|
|
123
|
+
css: getCaptureHideCSS(),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Page might have navigated away
|
|
128
|
+
}
|
|
129
|
+
}
|
|
85
130
|
export async function dismissCookiesAndWidgets(page) {
|
|
86
131
|
// Strategy 1: Click known CMP buttons
|
|
87
132
|
for (const selector of CMP_SELECTORS) {
|
|
@@ -91,7 +136,7 @@ export async function dismissCookiesAndWidgets(page) {
|
|
|
91
136
|
await button.click({ timeout: 2000 });
|
|
92
137
|
logger.info(`Cookie dismissed via CMP selector: ${selector}`);
|
|
93
138
|
await page.waitForTimeout(500);
|
|
94
|
-
await
|
|
139
|
+
await ensureCaptureHideStyles(page);
|
|
95
140
|
return { dismissed: true, method: `cmp:${selector}` };
|
|
96
141
|
}
|
|
97
142
|
}
|
|
@@ -148,7 +193,7 @@ export async function dismissCookiesAndWidgets(page) {
|
|
|
148
193
|
if (dismissed) {
|
|
149
194
|
logger.info(`Cookie dismissed via text match: "${dismissed}"`);
|
|
150
195
|
await page.waitForTimeout(500);
|
|
151
|
-
await
|
|
196
|
+
await ensureCaptureHideStyles(page);
|
|
152
197
|
return { dismissed: true, method: `text:${dismissed}` };
|
|
153
198
|
}
|
|
154
199
|
}
|
|
@@ -156,17 +201,7 @@ export async function dismissCookiesAndWidgets(page) {
|
|
|
156
201
|
// Text-based search failed
|
|
157
202
|
}
|
|
158
203
|
// Strategy 3: Always inject CSS to hide known overlays and widgets
|
|
159
|
-
await
|
|
204
|
+
await ensureCaptureHideStyles(page);
|
|
160
205
|
return { dismissed: false, method: null };
|
|
161
206
|
}
|
|
162
|
-
async function injectHideCSS(page) {
|
|
163
|
-
try {
|
|
164
|
-
await page.addStyleTag({
|
|
165
|
-
content: HIDE_SELECTORS.map(s => `${s} { display: none !important; visibility: hidden !important; pointer-events: none !important; }`).join('\n'),
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
catch {
|
|
169
|
-
// Page might have navigated away
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
207
|
//# sourceMappingURL=cookie-dismiss.js.map
|
package/dist/cost-logging.d.ts
CHANGED
|
@@ -21,6 +21,14 @@ export declare function updateCostLogCaptureContext(supabase: SupabaseClient, co
|
|
|
21
21
|
viewportWidth?: number | null;
|
|
22
22
|
viewportHeight?: number | null;
|
|
23
23
|
}): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Retry resolution for previously failed cost logs.
|
|
26
|
+
* Designed to be called by a reconciliation cron job.
|
|
27
|
+
*/
|
|
28
|
+
export declare function reconcileUnresolvedCosts(supabase: SupabaseClient, apiKey: string): Promise<{
|
|
29
|
+
retried: number;
|
|
30
|
+
resolved: number;
|
|
31
|
+
}>;
|
|
24
32
|
export declare function resolveAllCosts(supabase: SupabaseClient, entries: Array<{
|
|
25
33
|
costLogId: string;
|
|
26
34
|
generationId: string | null;
|
package/dist/cost-logging.js
CHANGED
|
@@ -1,49 +1,88 @@
|
|
|
1
|
+
function isFiniteInteger(value) {
|
|
2
|
+
return typeof value === 'number' && Number.isInteger(value);
|
|
3
|
+
}
|
|
4
|
+
function normalizeUsageForCostLog(step, index) {
|
|
5
|
+
const normalizedStepNumber = isFiniteInteger(step.stepNumber) && step.stepNumber >= 0
|
|
6
|
+
? step.stepNumber
|
|
7
|
+
: index + 1;
|
|
8
|
+
const normalizedStepType = typeof step.stepType === 'string' && step.stepType.trim().length > 0
|
|
9
|
+
? step.stepType
|
|
10
|
+
: 'agent_iteration';
|
|
11
|
+
const normalizedModelRequested = typeof step.modelRequested === 'string' && step.modelRequested.trim().length > 0
|
|
12
|
+
? step.modelRequested
|
|
13
|
+
: step.modelUsed ?? 'unknown';
|
|
14
|
+
const normalizedImagesInPrompt = typeof step.imagesInPrompt === 'number' && Number.isFinite(step.imagesInPrompt)
|
|
15
|
+
? step.imagesInPrompt
|
|
16
|
+
: 0;
|
|
17
|
+
if (normalizedStepNumber !== step.stepNumber
|
|
18
|
+
|| normalizedStepType !== step.stepType
|
|
19
|
+
|| normalizedModelRequested !== step.modelRequested
|
|
20
|
+
|| normalizedImagesInPrompt !== step.imagesInPrompt) {
|
|
21
|
+
console.warn('Normalizing invalid cost log usage entry:', JSON.stringify({
|
|
22
|
+
stepNumber: step.stepNumber ?? null,
|
|
23
|
+
stepType: step.stepType ?? null,
|
|
24
|
+
modelRequested: step.modelRequested ?? null,
|
|
25
|
+
modelUsed: step.modelUsed ?? null,
|
|
26
|
+
fallbackStepNumber: normalizedStepNumber,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
...step,
|
|
31
|
+
stepNumber: normalizedStepNumber,
|
|
32
|
+
stepType: normalizedStepType,
|
|
33
|
+
modelRequested: normalizedModelRequested,
|
|
34
|
+
imagesInPrompt: normalizedImagesInPrompt,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
1
37
|
export async function insertCostLogs(supabase, ctx, steps) {
|
|
2
38
|
if (steps.length === 0)
|
|
3
39
|
return [];
|
|
4
|
-
const rows = steps.map((
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
const rows = steps.map((rawStep, index) => {
|
|
41
|
+
const step = normalizeUsageForCostLog(rawStep, index);
|
|
42
|
+
return {
|
|
43
|
+
id: crypto.randomUUID(),
|
|
44
|
+
run_id: ctx.runId,
|
|
45
|
+
user_id: ctx.userId,
|
|
46
|
+
project_id: ctx.projectId ?? null,
|
|
47
|
+
preset_id: ctx.presetId ?? null,
|
|
48
|
+
capture_id: ctx.captureId ?? null,
|
|
49
|
+
step_number: step.stepNumber,
|
|
50
|
+
step_type: step.stepType,
|
|
51
|
+
model_requested: step.modelRequested,
|
|
52
|
+
model_used: step.modelUsed,
|
|
53
|
+
generation_id: step.generationId,
|
|
54
|
+
prompt_tokens: step.promptTokens,
|
|
55
|
+
completion_tokens: step.completionTokens,
|
|
56
|
+
total_tokens: step.totalTokens,
|
|
57
|
+
cost_resolved: false,
|
|
58
|
+
images_in_prompt: step.imagesInPrompt,
|
|
59
|
+
lang: ctx.lang ?? null,
|
|
60
|
+
theme: ctx.theme ?? null,
|
|
61
|
+
capture_type: ctx.captureType ?? null,
|
|
62
|
+
element_name: ctx.elementName ?? null,
|
|
63
|
+
target_id: ctx.targetId ?? null,
|
|
64
|
+
viewport_width: ctx.viewportWidth ?? null,
|
|
65
|
+
viewport_height: ctx.viewportHeight ?? null,
|
|
66
|
+
system_prompt_chars: step.systemPromptChars ?? null,
|
|
67
|
+
tool_schema_chars: step.toolSchemaChars ?? null,
|
|
68
|
+
user_payload_chars: step.userPayloadChars ?? null,
|
|
69
|
+
accessibility_chars: step.accessibilityChars ?? null,
|
|
70
|
+
interactive_element_count: step.interactiveElementCount ?? null,
|
|
71
|
+
action_history_count: step.actionHistoryCount ?? null,
|
|
72
|
+
elements_chars: step.elementsChars ?? null,
|
|
73
|
+
session_summary_chars: step.sessionSummaryChars ?? null,
|
|
74
|
+
selector_memory_chars: step.selectorMemoryChars ?? null,
|
|
75
|
+
agent_context_chars: step.agentContextChars ?? null,
|
|
76
|
+
profile_validation_status: step.profileValidationStatus ?? null,
|
|
77
|
+
session_profile_source: step.sessionProfileSource ?? null,
|
|
78
|
+
repair_path_used: step.repairPathUsed ?? null,
|
|
79
|
+
evaluator_used: step.evaluatorUsed ?? false,
|
|
80
|
+
cache_read_tokens: step.cacheReadTokens ?? null,
|
|
81
|
+
cache_write_tokens: step.cacheWriteTokens ?? null,
|
|
82
|
+
session_profile_reused: step.sessionProfileReused ?? false,
|
|
83
|
+
action_replay_used: step.actionReplayUsed ?? false,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
47
86
|
try {
|
|
48
87
|
const { error } = await supabase.from('cost_logs').insert(rows);
|
|
49
88
|
if (error) {
|
|
@@ -79,9 +118,21 @@ export async function updateCostLogCaptureContext(supabase, costLogIds, params)
|
|
|
79
118
|
}
|
|
80
119
|
}
|
|
81
120
|
async function resolveCost(updateClient, generationId, costLogId, apiKey) {
|
|
82
|
-
const delays = [10_000, 20_000, 40_000];
|
|
121
|
+
const delays = [10_000, 20_000, 40_000, 80_000, 160_000];
|
|
83
122
|
for (let attempt = 0; attempt < delays.length; attempt += 1) {
|
|
84
123
|
await new Promise((resolve) => setTimeout(resolve, delays[attempt]));
|
|
124
|
+
// Track resolution attempt (best-effort)
|
|
125
|
+
try {
|
|
126
|
+
await updateClient
|
|
127
|
+
.from('cost_logs')
|
|
128
|
+
.update({
|
|
129
|
+
resolution_attempts: attempt + 1,
|
|
130
|
+
last_resolution_attempt_at: new Date().toISOString(),
|
|
131
|
+
cost_resolution_status: 'pending',
|
|
132
|
+
})
|
|
133
|
+
.eq('id', costLogId);
|
|
134
|
+
}
|
|
135
|
+
catch { /* best-effort tracking */ }
|
|
85
136
|
try {
|
|
86
137
|
const response = await fetch(`https://openrouter.ai/api/v1/generation?id=${generationId}`, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
87
138
|
if (response.status === 404 && attempt < delays.length - 1) {
|
|
@@ -89,13 +140,19 @@ async function resolveCost(updateClient, generationId, costLogId, apiKey) {
|
|
|
89
140
|
}
|
|
90
141
|
if (!response.ok) {
|
|
91
142
|
console.error(`OpenRouter generation lookup failed (${generationId}): HTTP ${response.status}`);
|
|
92
|
-
|
|
143
|
+
if (attempt === delays.length - 1) {
|
|
144
|
+
await markCostResolutionFailed(updateClient, costLogId, `HTTP ${response.status}`);
|
|
145
|
+
}
|
|
146
|
+
continue;
|
|
93
147
|
}
|
|
94
148
|
const generation = await response.json();
|
|
95
149
|
const totalCost = generation.data?.total_cost ?? null;
|
|
96
150
|
if (totalCost == null) {
|
|
97
151
|
console.warn(`OpenRouter returned no total_cost for generation ${generationId}`);
|
|
98
|
-
|
|
152
|
+
if (attempt === delays.length - 1) {
|
|
153
|
+
await markCostResolutionFailed(updateClient, costLogId, 'no total_cost in response');
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
99
156
|
}
|
|
100
157
|
const { error } = await updateClient
|
|
101
158
|
.from('cost_logs')
|
|
@@ -103,6 +160,7 @@ async function resolveCost(updateClient, generationId, costLogId, apiKey) {
|
|
|
103
160
|
cost_usd: totalCost,
|
|
104
161
|
cost_resolved: true,
|
|
105
162
|
resolved_at: new Date().toISOString(),
|
|
163
|
+
cost_resolution_status: 'resolved',
|
|
106
164
|
})
|
|
107
165
|
.eq('id', costLogId);
|
|
108
166
|
if (error) {
|
|
@@ -113,10 +171,66 @@ async function resolveCost(updateClient, generationId, costLogId, apiKey) {
|
|
|
113
171
|
catch (error) {
|
|
114
172
|
if (attempt === delays.length - 1) {
|
|
115
173
|
console.error(`Cost resolution failed for ${generationId}:`, error.message);
|
|
174
|
+
await markCostResolutionFailed(updateClient, costLogId, error.message);
|
|
116
175
|
}
|
|
117
176
|
}
|
|
118
177
|
}
|
|
119
178
|
}
|
|
179
|
+
async function markCostResolutionFailed(updateClient, costLogId, reason) {
|
|
180
|
+
try {
|
|
181
|
+
await updateClient
|
|
182
|
+
.from('cost_logs')
|
|
183
|
+
.update({ cost_resolution_status: 'failed' })
|
|
184
|
+
.eq('id', costLogId);
|
|
185
|
+
console.error(`Cost resolution marked as failed for ${costLogId}: ${reason}`);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// best-effort — don't fail the caller
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Retry resolution for previously failed cost logs.
|
|
193
|
+
* Designed to be called by a reconciliation cron job.
|
|
194
|
+
*/
|
|
195
|
+
export async function reconcileUnresolvedCosts(supabase, apiKey) {
|
|
196
|
+
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
197
|
+
const { data: failedLogs, error } = await supabase
|
|
198
|
+
.from('cost_logs')
|
|
199
|
+
.select('id, generation_id')
|
|
200
|
+
.eq('cost_resolution_status', 'failed')
|
|
201
|
+
.gt('created_at', sevenDaysAgo)
|
|
202
|
+
.not('generation_id', 'is', null)
|
|
203
|
+
.limit(100);
|
|
204
|
+
if (error || !failedLogs?.length) {
|
|
205
|
+
return { retried: 0, resolved: 0 };
|
|
206
|
+
}
|
|
207
|
+
let resolved = 0;
|
|
208
|
+
for (const log of failedLogs) {
|
|
209
|
+
try {
|
|
210
|
+
const response = await fetch(`https://openrouter.ai/api/v1/generation?id=${log.generation_id}`, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
211
|
+
if (!response.ok)
|
|
212
|
+
continue;
|
|
213
|
+
const generation = await response.json();
|
|
214
|
+
const totalCost = generation.data?.total_cost ?? null;
|
|
215
|
+
if (totalCost == null)
|
|
216
|
+
continue;
|
|
217
|
+
await supabase
|
|
218
|
+
.from('cost_logs')
|
|
219
|
+
.update({
|
|
220
|
+
cost_usd: totalCost,
|
|
221
|
+
cost_resolved: true,
|
|
222
|
+
resolved_at: new Date().toISOString(),
|
|
223
|
+
cost_resolution_status: 'resolved',
|
|
224
|
+
})
|
|
225
|
+
.eq('id', log.id);
|
|
226
|
+
resolved += 1;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
// skip this entry, will be retried next run
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return { retried: failedLogs.length, resolved };
|
|
233
|
+
}
|
|
120
234
|
export function resolveAllCosts(supabase, entries, apiKey, serviceClient) {
|
|
121
235
|
const toResolve = entries.filter((entry) => entry.generationId != null);
|
|
122
236
|
if (toResolve.length === 0) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost resolution monitoring — exposes metrics for alerting
|
|
3
|
+
* when the failure rate of OpenRouter cost lookups exceeds thresholds.
|
|
4
|
+
*/
|
|
5
|
+
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
6
|
+
export interface CostResolutionStats {
|
|
7
|
+
/** Number of cost logs with status 'failed' in the last hour. */
|
|
8
|
+
failedLastHour: number;
|
|
9
|
+
/** Total cost logs created in the last hour. */
|
|
10
|
+
totalLastHour: number;
|
|
11
|
+
/** Failure rate as a percentage (0-100). */
|
|
12
|
+
failureRate: number;
|
|
13
|
+
/** Number of cost logs still pending (older than 5 minutes). */
|
|
14
|
+
stalePending: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function getCostResolutionStats(supabase: SupabaseClient): Promise<CostResolutionStats>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost resolution monitoring — exposes metrics for alerting
|
|
3
|
+
* when the failure rate of OpenRouter cost lookups exceeds thresholds.
|
|
4
|
+
*/
|
|
5
|
+
export async function getCostResolutionStats(supabase) {
|
|
6
|
+
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000).toISOString();
|
|
7
|
+
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000).toISOString();
|
|
8
|
+
const [failedResult, totalResult, staleResult] = await Promise.all([
|
|
9
|
+
supabase
|
|
10
|
+
.from('cost_logs')
|
|
11
|
+
.select('*', { count: 'exact', head: true })
|
|
12
|
+
.eq('cost_resolution_status', 'failed')
|
|
13
|
+
.gt('created_at', oneHourAgo),
|
|
14
|
+
supabase
|
|
15
|
+
.from('cost_logs')
|
|
16
|
+
.select('*', { count: 'exact', head: true })
|
|
17
|
+
.gt('created_at', oneHourAgo)
|
|
18
|
+
.not('generation_id', 'is', null),
|
|
19
|
+
supabase
|
|
20
|
+
.from('cost_logs')
|
|
21
|
+
.select('*', { count: 'exact', head: true })
|
|
22
|
+
.eq('cost_resolution_status', 'pending')
|
|
23
|
+
.lt('created_at', fiveMinutesAgo)
|
|
24
|
+
.not('generation_id', 'is', null),
|
|
25
|
+
]);
|
|
26
|
+
const failedLastHour = failedResult.count ?? 0;
|
|
27
|
+
const totalLastHour = totalResult.count ?? 0;
|
|
28
|
+
const stalePending = staleResult.count ?? 0;
|
|
29
|
+
const failureRate = totalLastHour > 0
|
|
30
|
+
? Math.round((failedLastHour / totalLastHour) * 10000) / 100
|
|
31
|
+
: 0;
|
|
32
|
+
return { failedLastHour, totalLastHour, failureRate, stalePending };
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=cost-resolution-monitor.js.map
|
|
@@ -47,9 +47,9 @@ export function resolveActionCredentialArgs(action, args, credentials) {
|
|
|
47
47
|
if (!credentials)
|
|
48
48
|
return args;
|
|
49
49
|
const resolved = { ...args };
|
|
50
|
-
if (action === "type_text" && typeof resolved.text === "string") {
|
|
50
|
+
if ((action === "type_text" || action === "type") && typeof resolved.text === "string") {
|
|
51
51
|
resolved.text = resolveCredentialTemplates(resolved.text, credentials);
|
|
52
|
-
ensureNoCredentialTemplate(
|
|
52
|
+
ensureNoCredentialTemplate(`${action}.text`, resolved.text);
|
|
53
53
|
}
|
|
54
54
|
if (action === "navigate_to" && typeof resolved.url === "string") {
|
|
55
55
|
resolved.url = resolveCredentialTemplates(resolved.url, credentials);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { VideoCursorTheme } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* JavaScript injected via `context.addInitScript()` to show a visible animated
|
|
4
|
+
* cursor in Playwright video recordings (the native OS cursor is invisible).
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildCursorOverlayScript(theme?: VideoCursorTheme): string;
|