autokap 1.0.6 → 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.
Files changed (347) hide show
  1. package/assets/chrome/ios-statusbar-comparison-reference.jpg +0 -0
  2. package/assets/chrome/ios-statusbar-dark-reference.jpg +0 -0
  3. package/assets/chrome/ios-statusbar-light-reference.jpg +0 -0
  4. package/assets/cursors/macos.svg +4 -0
  5. package/assets/cursors/windows.svg +15 -0
  6. package/assets/devices/ipad-pro-11-m4.json +52 -0
  7. package/assets/devices/iphone-16-pro.json +53 -0
  8. package/assets/devices/macbook-air-13.json +45 -0
  9. package/assets/frames/MacBook Air 13.svg +242 -0
  10. package/assets/frames/Status bar - iPhone.png +0 -0
  11. Menu bar- iPad.png +0 -0
  12. package/assets/frames/iPad Pro M4 11_.png +0 -0
  13. package/assets/frames/iPhone 16 Pro.png +0 -0
  14. package/assets/icons/Cellular Connection.svg +3 -0
  15. package/assets/icons/Union.svg +6 -0
  16. package/assets/icons/Wifi.svg +3 -0
  17. package/assets/icons/battery.svg +5 -0
  18. package/assets/icons/battery_charging.svg +8 -0
  19. package/assets/skill/OPCODE-REFERENCE.md +607 -0
  20. package/assets/skill/README.md +39 -0
  21. package/assets/skill/SKILL.md +453 -468
  22. package/assets/skill/STUDIO-SKILL.md +476 -0
  23. package/assets/skill/references/examples.md +104 -0
  24. package/assets/skill/references/interactive-demo.md +225 -0
  25. package/assets/skill/references/mock-data.md +178 -0
  26. package/dist/abort.d.ts +5 -0
  27. package/dist/abort.js +44 -0
  28. package/dist/action-verifier.d.ts +29 -0
  29. package/dist/action-verifier.js +133 -0
  30. package/dist/agent-action-recovery.d.ts +45 -0
  31. package/dist/agent-action-recovery.js +370 -0
  32. package/dist/agent-message-utils.d.ts +21 -0
  33. package/dist/agent-message-utils.js +77 -0
  34. package/dist/agent-url-utils.d.ts +30 -0
  35. package/dist/agent-url-utils.js +138 -0
  36. package/dist/agent.d.ts +226 -0
  37. package/dist/agent.js +6666 -0
  38. package/dist/ak-tree.d.ts +39 -0
  39. package/dist/ak-tree.js +368 -0
  40. package/dist/alt-text.d.ts +26 -0
  41. package/dist/alt-text.js +55 -0
  42. package/dist/auth-capture.d.ts +17 -0
  43. package/dist/auth-capture.js +164 -0
  44. package/dist/benchmark.d.ts +59 -0
  45. package/dist/benchmark.js +135 -0
  46. package/dist/billing-operation-logging.d.ts +38 -0
  47. package/dist/billing-operation-logging.js +248 -0
  48. package/dist/browser-bar.d.ts +48 -0
  49. package/dist/browser-bar.js +284 -0
  50. package/dist/browser-pool.d.ts +7 -0
  51. package/dist/browser-pool.js +15 -5
  52. package/dist/browser-utils.d.ts +31 -0
  53. package/dist/browser-utils.js +97 -0
  54. package/dist/browser.d.ts +76 -1
  55. package/dist/browser.js +1657 -39
  56. package/dist/capture-alt-text.d.ts +12 -0
  57. package/dist/capture-alt-text.js +52 -0
  58. package/dist/capture-encryption.d.ts +10 -0
  59. package/dist/capture-encryption.js +41 -0
  60. package/dist/capture-language-preflight.d.ts +41 -0
  61. package/dist/capture-language-preflight.js +300 -0
  62. package/dist/capture-llm-page-identity.d.ts +15 -0
  63. package/dist/capture-llm-page-identity.js +128 -0
  64. package/dist/capture-model-resolution.d.ts +9 -0
  65. package/dist/capture-model-resolution.js +21 -0
  66. package/dist/capture-page-identity.d.ts +7 -0
  67. package/dist/capture-page-identity.js +352 -0
  68. package/dist/capture-preset-credentials.d.ts +62 -0
  69. package/dist/capture-preset-credentials.js +184 -0
  70. package/dist/capture-request-plan.d.ts +58 -0
  71. package/dist/capture-request-plan.js +264 -0
  72. package/dist/capture-run-optimizer.d.ts +139 -0
  73. package/dist/capture-run-optimizer.js +863 -0
  74. package/dist/capture-selector-memory.d.ts +31 -0
  75. package/dist/capture-selector-memory.js +345 -0
  76. package/dist/capture-session-profile-encryption.d.ts +2 -0
  77. package/dist/capture-session-profile-encryption.js +22 -0
  78. package/dist/capture-step-timeout.d.ts +10 -0
  79. package/dist/capture-step-timeout.js +30 -0
  80. package/dist/capture-strategy.d.ts +36 -0
  81. package/dist/capture-strategy.js +95 -0
  82. package/dist/capture-studio-sync.d.ts +23 -0
  83. package/dist/capture-studio-sync.js +172 -0
  84. package/dist/capture-surface-contract.d.ts +36 -0
  85. package/dist/capture-surface-contract.js +299 -0
  86. package/dist/capture-transition-engine.d.ts +28 -0
  87. package/dist/capture-transition-engine.js +292 -0
  88. package/dist/capture-variant-state.d.ts +56 -0
  89. package/dist/capture-variant-state.js +182 -0
  90. package/dist/capture-verification.d.ts +35 -0
  91. package/dist/capture-verification.js +95 -0
  92. package/dist/capture-viewport-lock.d.ts +48 -0
  93. package/dist/capture-viewport-lock.js +74 -0
  94. package/dist/circuit-breaker.d.ts +42 -0
  95. package/dist/circuit-breaker.js +119 -0
  96. package/dist/cli-config.d.ts +8 -1
  97. package/dist/cli-config.js +62 -6
  98. package/dist/cli-contract.d.ts +15 -0
  99. package/dist/cli-contract.js +167 -0
  100. package/dist/cli-runner-local.d.ts +12 -0
  101. package/dist/cli-runner-local.js +102 -0
  102. package/dist/cli-runner.d.ts +34 -0
  103. package/dist/cli-runner.js +433 -0
  104. package/dist/cli-utils.d.ts +0 -1
  105. package/dist/cli-utils.js +2 -5
  106. package/dist/cli.js +1005 -252
  107. package/dist/clip-orchestrator.d.ts +148 -0
  108. package/dist/clip-orchestrator.js +957 -0
  109. package/dist/clip-postprocess.d.ts +42 -0
  110. package/dist/clip-postprocess.js +201 -0
  111. package/dist/cookie-dismiss.d.ts +2 -0
  112. package/dist/cookie-dismiss.js +48 -13
  113. package/dist/cost-logging.d.ts +35 -0
  114. package/dist/cost-logging.js +242 -0
  115. package/dist/cost-resolution-monitor.d.ts +16 -0
  116. package/dist/cost-resolution-monitor.js +34 -0
  117. package/dist/credential-templates.d.ts +5 -0
  118. package/dist/credential-templates.js +60 -0
  119. package/dist/cursor-overlay-script.d.ts +6 -0
  120. package/dist/cursor-overlay-script.js +169 -0
  121. package/dist/dom-css-purger.d.ts +65 -0
  122. package/dist/dom-css-purger.js +333 -0
  123. package/dist/dom-font-inliner.d.ts +45 -0
  124. package/dist/dom-font-inliner.js +148 -0
  125. package/dist/dom-patch-resolver.d.ts +52 -0
  126. package/dist/dom-patch-resolver.js +242 -0
  127. package/dist/dom-serializer.d.ts +82 -0
  128. package/dist/dom-serializer.js +378 -0
  129. package/dist/element-capture.d.ts +13 -0
  130. package/dist/element-capture.js +522 -0
  131. package/dist/env-validation.d.ts +5 -0
  132. package/dist/env-validation.js +29 -0
  133. package/dist/execution-schema.d.ts +4423 -0
  134. package/dist/execution-schema.js +507 -0
  135. package/dist/execution-types.d.ts +886 -0
  136. package/dist/execution-types.js +65 -0
  137. package/dist/fonts-loader.d.ts +14 -0
  138. package/dist/fonts-loader.js +55 -0
  139. package/dist/hybrid-navigator.d.ts +138 -0
  140. package/dist/hybrid-navigator.js +468 -0
  141. package/dist/index.d.ts +18 -0
  142. package/dist/index.js +17 -0
  143. package/dist/legacy/agent-action-recovery.d.ts +45 -0
  144. package/dist/legacy/agent-action-recovery.js +370 -0
  145. package/dist/legacy/agent-message-utils.d.ts +21 -0
  146. package/dist/legacy/agent-message-utils.js +77 -0
  147. package/dist/legacy/agent-url-utils.d.ts +30 -0
  148. package/dist/legacy/agent-url-utils.js +138 -0
  149. package/dist/legacy/agent.d.ts +226 -0
  150. package/dist/legacy/agent.js +6666 -0
  151. package/dist/legacy/clip-orchestrator.d.ts +148 -0
  152. package/dist/legacy/clip-orchestrator.js +957 -0
  153. package/dist/legacy/credential-templates.d.ts +5 -0
  154. package/dist/legacy/credential-templates.js +60 -0
  155. package/dist/legacy/hybrid-navigator.d.ts +138 -0
  156. package/dist/legacy/hybrid-navigator.js +468 -0
  157. package/dist/legacy/llm-usage.d.ts +17 -0
  158. package/dist/legacy/llm-usage.js +45 -0
  159. package/dist/legacy/prompt-cache.d.ts +10 -0
  160. package/dist/legacy/prompt-cache.js +24 -0
  161. package/dist/legacy/prompts.d.ts +175 -0
  162. package/dist/legacy/prompts.js +1038 -0
  163. package/dist/legacy/tools.d.ts +4 -0
  164. package/dist/legacy/tools.js +216 -0
  165. package/dist/legacy/video-agent.d.ts +143 -0
  166. package/dist/legacy/video-agent.js +4788 -0
  167. package/dist/legacy/video-observation.d.ts +36 -0
  168. package/dist/legacy/video-observation.js +192 -0
  169. package/dist/legacy/video-planner.d.ts +12 -0
  170. package/dist/legacy/video-planner.js +501 -0
  171. package/dist/legacy/video-prompts.d.ts +37 -0
  172. package/dist/legacy/video-prompts.js +569 -0
  173. package/dist/legacy/video-tools.d.ts +3 -0
  174. package/dist/legacy/video-tools.js +59 -0
  175. package/dist/legacy/video-variant-state.d.ts +29 -0
  176. package/dist/legacy/video-variant-state.js +80 -0
  177. package/dist/legacy/vision-model.d.ts +17 -0
  178. package/dist/legacy/vision-model.js +74 -0
  179. package/dist/llm-healer.d.ts +63 -0
  180. package/dist/llm-healer.js +166 -0
  181. package/dist/llm-provider.d.ts +29 -0
  182. package/dist/llm-provider.js +80 -0
  183. package/dist/llm-usage.d.ts +17 -0
  184. package/dist/llm-usage.js +45 -0
  185. package/dist/logger.d.ts +6 -2
  186. package/dist/logger.js +15 -1
  187. package/dist/mockup-html.d.ts +119 -0
  188. package/dist/mockup-html.js +263 -0
  189. package/dist/mockup.d.ts +187 -0
  190. package/dist/mockup.js +869 -0
  191. package/dist/mouse-animation.d.ts +46 -0
  192. package/dist/mouse-animation.js +114 -0
  193. package/dist/opcode-actions.d.ts +42 -0
  194. package/dist/opcode-actions.js +511 -0
  195. package/dist/opcode-runner.d.ts +51 -0
  196. package/dist/opcode-runner.js +770 -0
  197. package/dist/openrouter-client.d.ts +40 -0
  198. package/dist/openrouter-client.js +16 -0
  199. package/dist/overlay-engine.d.ts +24 -0
  200. package/dist/overlay-engine.js +176 -0
  201. package/dist/overlay-utils.d.ts +14 -0
  202. package/dist/overlay-utils.js +13 -0
  203. package/dist/postcondition.d.ts +16 -0
  204. package/dist/postcondition.js +269 -0
  205. package/dist/posthog.d.ts +4 -0
  206. package/dist/posthog.js +26 -0
  207. package/dist/program-patcher.d.ts +25 -0
  208. package/dist/program-patcher.js +44 -0
  209. package/dist/prompt-cache.d.ts +10 -0
  210. package/dist/prompt-cache.js +24 -0
  211. package/dist/prompts.d.ts +175 -0
  212. package/dist/prompts.js +1038 -0
  213. package/dist/provider-config.d.ts +12 -0
  214. package/dist/provider-config.js +15 -0
  215. package/dist/recovery-chain.d.ts +37 -0
  216. package/dist/recovery-chain.js +350 -0
  217. package/dist/remote-browser.d.ts +215 -0
  218. package/dist/remote-browser.js +360 -0
  219. package/dist/safari-browser-bar.d.ts +15 -0
  220. package/dist/safari-browser-bar.js +95 -0
  221. package/dist/safari-toolbar-asset.d.ts +15 -0
  222. package/dist/safari-toolbar-asset.js +12 -0
  223. package/dist/security.d.ts +21 -0
  224. package/dist/security.js +608 -0
  225. package/dist/selector-resolver.d.ts +34 -0
  226. package/dist/selector-resolver.js +181 -0
  227. package/dist/semantic-resolver.d.ts +35 -0
  228. package/dist/semantic-resolver.js +161 -0
  229. package/dist/server-capture-runtime.d.ts +125 -0
  230. package/dist/server-capture-runtime.js +585 -0
  231. package/dist/server-credit-usage.d.ts +12 -0
  232. package/dist/server-credit-usage.js +41 -0
  233. package/dist/server-posthog.d.ts +2 -0
  234. package/dist/server-posthog.js +16 -0
  235. package/dist/server-project-webhooks.d.ts +59 -0
  236. package/dist/server-project-webhooks.js +123 -0
  237. package/dist/server-screenshot-watermark.d.ts +7 -0
  238. package/dist/server-screenshot-watermark.js +60 -0
  239. package/dist/session-profile.d.ts +86 -0
  240. package/dist/session-profile.js +1536 -0
  241. package/dist/sf-pro-fonts.d.ts +4 -0
  242. package/dist/sf-pro-fonts.js +7 -0
  243. package/dist/sf-pro-symbols.d.ts +1 -0
  244. package/dist/sf-pro-symbols.js +55 -0
  245. package/dist/skill-packaging.d.ts +28 -0
  246. package/dist/skill-packaging.js +169 -0
  247. package/dist/smart-wait.d.ts +27 -0
  248. package/dist/smart-wait.js +81 -0
  249. package/dist/status-bar-l10n.d.ts +14 -0
  250. package/dist/status-bar-l10n.js +177 -0
  251. package/dist/status-bar-render.d.ts +20 -0
  252. package/dist/status-bar-render.js +410 -0
  253. package/dist/status-bar.d.ts +53 -0
  254. package/dist/status-bar.js +620 -0
  255. package/dist/svg-browser-bar.d.ts +33 -0
  256. package/dist/svg-browser-bar.js +206 -0
  257. package/dist/svg-status-bar.d.ts +36 -0
  258. package/dist/svg-status-bar.js +597 -0
  259. package/dist/svg-text.d.ts +61 -0
  260. package/dist/svg-text.js +118 -0
  261. package/dist/tools.d.ts +4 -0
  262. package/dist/tools.js +216 -0
  263. package/dist/types.d.ts +240 -5
  264. package/dist/types.js +23 -1
  265. package/dist/v2/action-verifier.d.ts +29 -0
  266. package/dist/v2/action-verifier.js +133 -0
  267. package/dist/v2/alt-text.d.ts +26 -0
  268. package/dist/v2/alt-text.js +55 -0
  269. package/dist/v2/benchmark.d.ts +59 -0
  270. package/dist/v2/benchmark.js +135 -0
  271. package/dist/v2/capture-strategy.d.ts +30 -0
  272. package/dist/v2/capture-strategy.js +67 -0
  273. package/dist/v2/capture-verification.d.ts +35 -0
  274. package/dist/v2/capture-verification.js +95 -0
  275. package/dist/v2/circuit-breaker.d.ts +42 -0
  276. package/dist/v2/circuit-breaker.js +119 -0
  277. package/dist/v2/cli-runner-local.d.ts +11 -0
  278. package/dist/v2/cli-runner-local.js +91 -0
  279. package/dist/v2/cli-runner.d.ts +34 -0
  280. package/dist/v2/cli-runner.js +300 -0
  281. package/dist/v2/compiler-prompts.d.ts +27 -0
  282. package/dist/v2/compiler-prompts.js +123 -0
  283. package/dist/v2/compiler.d.ts +37 -0
  284. package/dist/v2/compiler.js +147 -0
  285. package/dist/v2/explorer.d.ts +41 -0
  286. package/dist/v2/explorer.js +56 -0
  287. package/dist/v2/index.d.ts +37 -0
  288. package/dist/v2/index.js +31 -0
  289. package/dist/v2/llm-healer.d.ts +62 -0
  290. package/dist/v2/llm-healer.js +166 -0
  291. package/dist/v2/llm-provider.d.ts +29 -0
  292. package/dist/v2/llm-provider.js +80 -0
  293. package/dist/v2/opcode-runner.d.ts +47 -0
  294. package/dist/v2/opcode-runner.js +634 -0
  295. package/dist/v2/overlay-engine.d.ts +24 -0
  296. package/dist/v2/overlay-engine.js +150 -0
  297. package/dist/v2/postcondition.d.ts +16 -0
  298. package/dist/v2/postcondition.js +249 -0
  299. package/dist/v2/program-patcher.d.ts +25 -0
  300. package/dist/v2/program-patcher.js +44 -0
  301. package/dist/v2/recovery-chain.d.ts +30 -0
  302. package/dist/v2/recovery-chain.js +368 -0
  303. package/dist/v2/schema.d.ts +2580 -0
  304. package/dist/v2/schema.js +295 -0
  305. package/dist/v2/selector-resolver.d.ts +34 -0
  306. package/dist/v2/selector-resolver.js +181 -0
  307. package/dist/v2/semantic-resolver.d.ts +35 -0
  308. package/dist/v2/semantic-resolver.js +161 -0
  309. package/dist/v2/smart-wait.d.ts +27 -0
  310. package/dist/v2/smart-wait.js +81 -0
  311. package/dist/v2/types.d.ts +444 -0
  312. package/dist/v2/types.js +19 -0
  313. package/dist/v2/web-playwright-local.d.ts +69 -0
  314. package/dist/v2/web-playwright-local.js +392 -0
  315. package/dist/version.d.ts +1 -0
  316. package/dist/version.js +5 -0
  317. package/dist/video-agent.d.ts +143 -0
  318. package/dist/video-agent.js +4788 -0
  319. package/dist/video-observation.d.ts +36 -0
  320. package/dist/video-observation.js +192 -0
  321. package/dist/video-planner.d.ts +12 -0
  322. package/dist/video-planner.js +501 -0
  323. package/dist/video-prompts.d.ts +37 -0
  324. package/dist/video-prompts.js +554 -0
  325. package/dist/video-tools.d.ts +3 -0
  326. package/dist/video-tools.js +59 -0
  327. package/dist/video-variant-state.d.ts +29 -0
  328. package/dist/video-variant-state.js +80 -0
  329. package/dist/vision-model.d.ts +17 -0
  330. package/dist/vision-model.js +74 -0
  331. package/dist/web-playwright-local.d.ts +126 -0
  332. package/dist/web-playwright-local.js +819 -0
  333. package/dist/ws-auth.d.ts +20 -0
  334. package/dist/ws-auth.js +70 -0
  335. package/dist/ws-broadcast.d.ts +34 -0
  336. package/dist/ws-broadcast.js +85 -0
  337. package/dist/ws-connection-limits.d.ts +12 -0
  338. package/dist/ws-connection-limits.js +44 -0
  339. package/dist/ws-handler-utils.d.ts +32 -0
  340. package/dist/ws-handler-utils.js +139 -0
  341. package/dist/ws-handler.d.ts +10 -0
  342. package/dist/ws-handler.js +1793 -0
  343. package/dist/ws-metrics-server.d.ts +9 -0
  344. package/dist/ws-metrics-server.js +31 -0
  345. package/dist/ws-server.d.ts +9 -0
  346. package/dist/ws-server.js +92 -0
  347. package/package.json +142 -71
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Capture Agent — Benchmark Harness
3
+ *
4
+ * Runs the same preset repeatedly, comparing:
5
+ * - Total LLM cost
6
+ * - Total wall-clock time
7
+ * - Success rate
8
+ * - Recovery rate (how often healing was needed)
9
+ *
10
+ * Useful for tracking determinism, recovery rate, and runtime cost over time.
11
+ */
12
+ import type { ExecutionProgram, RunResult } from './execution-types.js';
13
+ export interface BenchmarkPreset {
14
+ name: string;
15
+ presetId: string;
16
+ program: ExecutionProgram;
17
+ /** Expected behavior description for manual verification */
18
+ expectedBehavior: string;
19
+ /** Difficulty tier */
20
+ tier: 'simple' | 'multi_step' | 'auth_required' | 'clip' | 'video';
21
+ }
22
+ export interface BenchmarkRunResult {
23
+ presetName: string;
24
+ tier: string;
25
+ success: boolean;
26
+ totalDurationMs: number;
27
+ llmCostEur: number;
28
+ llmCallCount: number;
29
+ totalOpcodes: number;
30
+ recoveredOpcodes: number;
31
+ failedOpcodes: number;
32
+ healerInvocations: number;
33
+ circuitBreakerTrips: number;
34
+ variantCount: number;
35
+ successfulVariants: number;
36
+ error?: string;
37
+ }
38
+ export interface BenchmarkSummary {
39
+ totalPresets: number;
40
+ successCount: number;
41
+ failCount: number;
42
+ successRate: number;
43
+ averageDurationMs: number;
44
+ averageLlmCostEur: number;
45
+ totalLlmCostEur: number;
46
+ deterministicRate: number;
47
+ recoveryRate: number;
48
+ results: BenchmarkRunResult[];
49
+ byTier: Record<string, {
50
+ total: number;
51
+ success: number;
52
+ rate: number;
53
+ }>;
54
+ }
55
+ export type RunFn = (program: ExecutionProgram) => Promise<RunResult>;
56
+ export declare function runBenchmark(presets: BenchmarkPreset[], runCapture: RunFn, options?: {
57
+ runs?: number;
58
+ }): Promise<BenchmarkSummary>;
59
+ export declare function formatBenchmarkSummary(summary: BenchmarkSummary): string;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Capture Agent — Benchmark Harness
3
+ *
4
+ * Runs the same preset repeatedly, comparing:
5
+ * - Total LLM cost
6
+ * - Total wall-clock time
7
+ * - Success rate
8
+ * - Recovery rate (how often healing was needed)
9
+ *
10
+ * Useful for tracking determinism, recovery rate, and runtime cost over time.
11
+ */
12
+ import { logger } from './logger.js';
13
+ export async function runBenchmark(presets, runCapture, options) {
14
+ const runsPerPreset = options?.runs ?? 1;
15
+ const results = [];
16
+ for (const preset of presets) {
17
+ logger.info(`[Benchmark] Running "${preset.name}" (${preset.tier}) — ${runsPerPreset} run(s)`);
18
+ for (let run = 0; run < runsPerPreset; run++) {
19
+ try {
20
+ const runResult = await runCapture(preset.program);
21
+ results.push({
22
+ presetName: preset.name,
23
+ tier: preset.tier,
24
+ success: runResult.success,
25
+ totalDurationMs: runResult.totalDurationMs,
26
+ llmCostEur: runResult.telemetry.llmCostEur,
27
+ llmCallCount: runResult.telemetry.llmCallCount,
28
+ totalOpcodes: runResult.telemetry.totalOpcodes,
29
+ recoveredOpcodes: runResult.telemetry.recoveredOpcodes,
30
+ failedOpcodes: runResult.telemetry.failedOpcodes,
31
+ healerInvocations: runResult.telemetry.healerInvocations,
32
+ circuitBreakerTrips: runResult.telemetry.circuitBreakerTrips,
33
+ variantCount: runResult.variantResults.length,
34
+ successfulVariants: runResult.variantResults.filter(v => v.success).length,
35
+ error: runResult.error,
36
+ });
37
+ }
38
+ catch (err) {
39
+ results.push({
40
+ presetName: preset.name,
41
+ tier: preset.tier,
42
+ success: false,
43
+ totalDurationMs: 0,
44
+ llmCostEur: 0,
45
+ llmCallCount: 0,
46
+ totalOpcodes: 0,
47
+ recoveredOpcodes: 0,
48
+ failedOpcodes: 0,
49
+ healerInvocations: 0,
50
+ circuitBreakerTrips: 0,
51
+ variantCount: 0,
52
+ successfulVariants: 0,
53
+ error: err instanceof Error ? err.message : String(err),
54
+ });
55
+ }
56
+ }
57
+ }
58
+ return computeSummary(results);
59
+ }
60
+ // ── Summary computation ─────────────────────────────────────────────
61
+ function computeSummary(results) {
62
+ const total = results.length;
63
+ const successCount = results.filter(r => r.success).length;
64
+ const failCount = total - successCount;
65
+ const totalDuration = results.reduce((sum, r) => sum + r.totalDurationMs, 0);
66
+ const totalLlmCost = results.reduce((sum, r) => sum + r.llmCostEur, 0);
67
+ const totalOpcodes = results.reduce((sum, r) => sum + r.totalOpcodes, 0);
68
+ const totalRecovered = results.reduce((sum, r) => sum + r.recoveredOpcodes, 0);
69
+ const deterministicRuns = results.filter(r => r.llmCallCount === 0 && r.success).length;
70
+ // By tier
71
+ const byTier = {};
72
+ for (const result of results) {
73
+ if (!byTier[result.tier])
74
+ byTier[result.tier] = { total: 0, success: 0, rate: 0 };
75
+ byTier[result.tier].total++;
76
+ if (result.success)
77
+ byTier[result.tier].success++;
78
+ }
79
+ for (const tier of Object.values(byTier)) {
80
+ tier.rate = tier.total > 0 ? tier.success / tier.total : 0;
81
+ }
82
+ return {
83
+ totalPresets: total,
84
+ successCount,
85
+ failCount,
86
+ successRate: total > 0 ? successCount / total : 0,
87
+ averageDurationMs: total > 0 ? totalDuration / total : 0,
88
+ averageLlmCostEur: total > 0 ? totalLlmCost / total : 0,
89
+ totalLlmCostEur: totalLlmCost,
90
+ deterministicRate: total > 0 ? deterministicRuns / total : 0,
91
+ recoveryRate: totalOpcodes > 0 ? totalRecovered / totalOpcodes : 0,
92
+ results,
93
+ byTier,
94
+ };
95
+ }
96
+ // ── Pretty printer ──────────────────────────────────────────────────
97
+ export function formatBenchmarkSummary(summary) {
98
+ const lines = [];
99
+ lines.push('═══════════════════════════════════════════════════');
100
+ lines.push(' Capture Benchmark Summary');
101
+ lines.push('═══════════════════════════════════════════════════');
102
+ lines.push(` Total presets: ${summary.totalPresets}`);
103
+ lines.push(` Success: ${summary.successCount}/${summary.totalPresets} (${(summary.successRate * 100).toFixed(1)}%)`);
104
+ lines.push(` Deterministic rate: ${(summary.deterministicRate * 100).toFixed(1)}% (no LLM needed)`);
105
+ lines.push(` Recovery rate: ${(summary.recoveryRate * 100).toFixed(1)}% of opcodes`);
106
+ lines.push(` Avg duration: ${(summary.averageDurationMs / 1000).toFixed(1)}s`);
107
+ lines.push(` Avg LLM cost: ${summary.averageLlmCostEur.toFixed(4)} EUR`);
108
+ lines.push(` Total LLM cost: ${summary.totalLlmCostEur.toFixed(4)} EUR`);
109
+ lines.push('───────────────────────────────────────────────────');
110
+ for (const [tier, stats] of Object.entries(summary.byTier)) {
111
+ lines.push(` ${tier.padEnd(18)} ${stats.success}/${stats.total} (${(stats.rate * 100).toFixed(0)}%)`);
112
+ }
113
+ lines.push('───────────────────────────────────────────────────');
114
+ for (const result of summary.results) {
115
+ const status = result.success ? 'OK' : 'FAIL';
116
+ const duration = `${(result.totalDurationMs / 1000).toFixed(1)}s`;
117
+ const cost = result.llmCostEur > 0 ? `${result.llmCostEur.toFixed(4)}EUR` : 'free';
118
+ lines.push(` [${status}] ${result.presetName.padEnd(30)} ${duration.padStart(6)} ${cost.padStart(10)}${result.error ? ` — ${result.error.slice(0, 50)}` : ''}`);
119
+ }
120
+ lines.push('═══════════════════════════════════════════════════');
121
+ // Health check
122
+ const simpleStats = summary.byTier['simple'];
123
+ const multiStats = summary.byTier['multi_step'];
124
+ const simpleOk = !simpleStats || simpleStats.rate >= 0.95;
125
+ const multiOk = !multiStats || multiStats.rate >= 0.80;
126
+ const costOk = summary.averageLlmCostEur < 0.05;
127
+ lines.push('');
128
+ lines.push(' Health Checklist:');
129
+ lines.push(` ${simpleOk ? '[x]' : '[ ]'} Simple scenarios > 95% (${simpleStats ? (simpleStats.rate * 100).toFixed(0) : 'N/A'}%)`);
130
+ lines.push(` ${multiOk ? '[x]' : '[ ]'} Multi-step > 80% (${multiStats ? (multiStats.rate * 100).toFixed(0) : 'N/A'}%)`);
131
+ lines.push(` ${costOk ? '[x]' : '[ ]'} Avg cost < 0.05 EUR (${summary.averageLlmCostEur.toFixed(4)} EUR)`);
132
+ lines.push('');
133
+ return lines.join('\n');
134
+ }
135
+ //# sourceMappingURL=benchmark.js.map
@@ -0,0 +1,38 @@
1
+ import type { SupabaseClient } from '@supabase/supabase-js';
2
+ import type { StepUsage } from './types.js';
3
+ export type BillingOperationType = 'screenshot' | 'clip' | 'video';
4
+ type BillingOperationOutcome = 'succeeded' | 'failed' | 'cancelled';
5
+ interface BillingOperationContext {
6
+ runId: string;
7
+ userId: string;
8
+ projectId?: string | null;
9
+ presetId?: string | null;
10
+ captureId?: string | null;
11
+ videoId?: string | null;
12
+ clipRecordId?: string | null;
13
+ operationType: BillingOperationType;
14
+ captureType?: 'fullpage' | 'element' | 'video' | null;
15
+ lang?: string | null;
16
+ theme?: 'light' | 'dark' | string | null;
17
+ elementName?: string;
18
+ targetId?: string;
19
+ viewportWidth?: number | null;
20
+ viewportHeight?: number | null;
21
+ deviceFrame?: string | null;
22
+ }
23
+ interface BillingOperationParams {
24
+ outcome: BillingOperationOutcome;
25
+ outcomeReason?: string | null;
26
+ billable: boolean;
27
+ creditsCharged: number;
28
+ costLogIds: string[];
29
+ usage: StepUsage[];
30
+ metadata?: Record<string, unknown>;
31
+ }
32
+ export declare function insertBillingOperationLog(supabase: SupabaseClient, ctx: BillingOperationContext, params: BillingOperationParams): Promise<string | null>;
33
+ export declare function insertScreenshotOperationLog(supabase: SupabaseClient, ctx: Omit<BillingOperationContext, 'operationType'>, params: BillingOperationParams): Promise<string | null>;
34
+ export declare function insertClipOperationLog(supabase: SupabaseClient, ctx: Omit<BillingOperationContext, 'operationType'>, params: BillingOperationParams): Promise<string | null>;
35
+ export declare function insertVideoOperationLog(supabase: SupabaseClient, ctx: Omit<BillingOperationContext, 'operationType'>, params: BillingOperationParams): Promise<string | null>;
36
+ export declare function cancelScreenshotOperationLogsForCapture(supabase: SupabaseClient, captureId: string, reason: string): Promise<void>;
37
+ export declare function reconcilePendingBillingOperationCosts(supabase: SupabaseClient, operationIds?: string[]): Promise<void>;
38
+ export {};
@@ -0,0 +1,248 @@
1
+ function uniqNonEmpty(values) {
2
+ return Array.from(new Set(values
3
+ .map((value) => value?.trim())
4
+ .filter((value) => !!value)));
5
+ }
6
+ function summarizeUsage(usage) {
7
+ return {
8
+ llmCallCount: usage.length,
9
+ promptTokens: usage.reduce((sum, step) => sum + (step.promptTokens ?? 0), 0),
10
+ completionTokens: usage.reduce((sum, step) => sum + (step.completionTokens ?? 0), 0),
11
+ totalTokens: usage.reduce((sum, step) => sum + (step.totalTokens ?? 0), 0),
12
+ cacheReadTokens: usage.reduce((sum, step) => sum + (step.cacheReadTokens ?? 0), 0),
13
+ cacheWriteTokens: usage.reduce((sum, step) => sum + (step.cacheWriteTokens ?? 0), 0),
14
+ imagesInPrompt: usage.reduce((sum, step) => sum + (step.imagesInPrompt ?? 0), 0),
15
+ modelRequested: uniqNonEmpty(usage.map((step) => step.modelRequested)).join(', ') || null,
16
+ modelUsed: uniqNonEmpty(usage.map((step) => step.modelUsed)).join(', ') || null,
17
+ generationIds: uniqNonEmpty(usage.map((step) => step.generationId)),
18
+ };
19
+ }
20
+ async function resolveCostLogs(supabase, costLogIds) {
21
+ if (costLogIds.length === 0) {
22
+ return {
23
+ costUsd: 0,
24
+ costSource: 'no_llm',
25
+ costResolved: true,
26
+ costResolutionStatus: 'resolved',
27
+ costResolutionError: null,
28
+ resolvedAt: new Date().toISOString(),
29
+ };
30
+ }
31
+ const { data, error } = await supabase
32
+ .from('cost_logs')
33
+ .select('id, generation_id, cost_resolved, cost_usd')
34
+ .in('id', costLogIds);
35
+ if (error) {
36
+ return {
37
+ costUsd: null,
38
+ costSource: 'cost_logs_lookup_failed',
39
+ costResolved: false,
40
+ costResolutionStatus: 'unresolvable',
41
+ costResolutionError: error.message,
42
+ resolvedAt: null,
43
+ };
44
+ }
45
+ const rows = data ?? [];
46
+ if (rows.length !== costLogIds.length) {
47
+ return {
48
+ costUsd: null,
49
+ costSource: 'missing_cost_logs',
50
+ costResolved: false,
51
+ costResolutionStatus: 'unresolvable',
52
+ costResolutionError: `Expected ${costLogIds.length} cost log rows, found ${rows.length}.`,
53
+ resolvedAt: null,
54
+ };
55
+ }
56
+ if (rows.some((row) => !row.cost_resolved || row.cost_usd == null)) {
57
+ if (rows.some((row) => !row.cost_resolved && row.cost_usd == null && row.generation_id == null)) {
58
+ return {
59
+ costUsd: null,
60
+ costSource: 'missing_generation_id',
61
+ costResolved: false,
62
+ costResolutionStatus: 'unresolvable',
63
+ costResolutionError: 'At least one referenced cost log is missing a generation_id, so OpenRouter cannot return the real cost.',
64
+ resolvedAt: null,
65
+ };
66
+ }
67
+ return {
68
+ costUsd: null,
69
+ costSource: 'aggregated_cost_logs_pending',
70
+ costResolved: false,
71
+ costResolutionStatus: 'pending',
72
+ costResolutionError: null,
73
+ resolvedAt: null,
74
+ };
75
+ }
76
+ const costUsd = rows.reduce((sum, row) => sum + Number(row.cost_usd ?? 0), 0);
77
+ return {
78
+ costUsd,
79
+ costSource: 'aggregated_cost_logs',
80
+ costResolved: true,
81
+ costResolutionStatus: 'resolved',
82
+ costResolutionError: null,
83
+ resolvedAt: new Date().toISOString(),
84
+ };
85
+ }
86
+ function deriveInitialCostResolution(usage, costLogIds) {
87
+ if (usage.length === 0) {
88
+ return {
89
+ costUsd: 0,
90
+ costSource: 'no_llm',
91
+ costResolved: true,
92
+ costResolutionStatus: 'resolved',
93
+ costResolutionError: null,
94
+ resolvedAt: new Date().toISOString(),
95
+ };
96
+ }
97
+ if (costLogIds.length !== usage.length) {
98
+ return {
99
+ costUsd: null,
100
+ costSource: 'missing_cost_logs',
101
+ costResolved: false,
102
+ costResolutionStatus: 'unresolvable',
103
+ costResolutionError: `Expected ${usage.length} cost log ids, received ${costLogIds.length}.`,
104
+ resolvedAt: null,
105
+ };
106
+ }
107
+ const missingGenerationCount = usage.filter((step) => !step.generationId?.trim()).length;
108
+ if (missingGenerationCount > 0) {
109
+ return {
110
+ costUsd: null,
111
+ costSource: 'missing_generation_id',
112
+ costResolved: false,
113
+ costResolutionStatus: 'unresolvable',
114
+ costResolutionError: `Expected generation ids for all usage steps, but ${missingGenerationCount} step(s) are missing them.`,
115
+ resolvedAt: null,
116
+ };
117
+ }
118
+ return null;
119
+ }
120
+ export async function insertBillingOperationLog(supabase, ctx, params) {
121
+ const usageSummary = summarizeUsage(params.usage);
122
+ const forcedResolution = deriveInitialCostResolution(params.usage, params.costLogIds);
123
+ const costResolution = forcedResolution ?? await resolveCostLogs(supabase, params.costLogIds);
124
+ const id = crypto.randomUUID();
125
+ const { error } = await supabase.from('billing_operation_logs').insert({
126
+ id,
127
+ run_id: ctx.runId,
128
+ user_id: ctx.userId,
129
+ project_id: ctx.projectId ?? null,
130
+ preset_id: ctx.presetId ?? null,
131
+ capture_id: ctx.captureId ?? null,
132
+ video_id: ctx.videoId ?? null,
133
+ clip_record_id: ctx.clipRecordId ?? null,
134
+ operation_type: ctx.operationType,
135
+ operation_outcome: params.outcome,
136
+ outcome_reason: params.outcomeReason ?? null,
137
+ billable: params.billable,
138
+ credits_charged: params.creditsCharged,
139
+ cost_usd: costResolution.costUsd,
140
+ cost_resolved: costResolution.costResolved,
141
+ cost_resolution_status: costResolution.costResolutionStatus,
142
+ cost_source: costResolution.costSource,
143
+ cost_resolution_error: costResolution.costResolutionError,
144
+ resolved_at: costResolution.resolvedAt,
145
+ cost_log_ids: params.costLogIds,
146
+ llm_call_count: usageSummary.llmCallCount,
147
+ prompt_tokens: usageSummary.promptTokens,
148
+ completion_tokens: usageSummary.completionTokens,
149
+ total_tokens: usageSummary.totalTokens,
150
+ cache_read_tokens: usageSummary.cacheReadTokens,
151
+ cache_write_tokens: usageSummary.cacheWriteTokens,
152
+ images_in_prompt: usageSummary.imagesInPrompt,
153
+ model_requested: usageSummary.modelRequested,
154
+ model_used: usageSummary.modelUsed,
155
+ capture_type: ctx.captureType ?? null,
156
+ target_id: ctx.targetId ?? null,
157
+ element_name: ctx.elementName ?? null,
158
+ lang: ctx.lang ?? null,
159
+ theme: ctx.theme ?? null,
160
+ viewport_width: ctx.viewportWidth ?? null,
161
+ viewport_height: ctx.viewportHeight ?? null,
162
+ device_frame: ctx.deviceFrame ?? null,
163
+ metadata: {
164
+ ...(params.metadata ?? {}),
165
+ generationIds: usageSummary.generationIds,
166
+ },
167
+ });
168
+ if (error) {
169
+ console.error('Failed to insert billing operation log:', error.message);
170
+ return null;
171
+ }
172
+ return id;
173
+ }
174
+ export async function insertScreenshotOperationLog(supabase, ctx, params) {
175
+ return insertBillingOperationLog(supabase, { ...ctx, operationType: 'screenshot' }, params);
176
+ }
177
+ export async function insertClipOperationLog(supabase, ctx, params) {
178
+ return insertBillingOperationLog(supabase, { ...ctx, operationType: 'clip' }, params);
179
+ }
180
+ export async function insertVideoOperationLog(supabase, ctx, params) {
181
+ return insertBillingOperationLog(supabase, { ...ctx, operationType: 'video' }, params);
182
+ }
183
+ export async function cancelScreenshotOperationLogsForCapture(supabase, captureId, reason) {
184
+ try {
185
+ const { error } = await supabase
186
+ .from('billing_operation_logs')
187
+ .update({
188
+ operation_outcome: 'cancelled',
189
+ outcome_reason: reason,
190
+ billable: false,
191
+ credits_charged: 0,
192
+ })
193
+ .eq('capture_id', captureId)
194
+ .eq('operation_type', 'screenshot');
195
+ if (error) {
196
+ console.error('Failed to cancel screenshot billing operation logs:', error.message);
197
+ }
198
+ }
199
+ catch (error) {
200
+ console.error('Failed to cancel screenshot billing operation logs:', error.message);
201
+ }
202
+ }
203
+ export async function reconcilePendingBillingOperationCosts(supabase, operationIds) {
204
+ try {
205
+ let query = supabase
206
+ .from('billing_operation_logs')
207
+ .select('id, cost_log_ids')
208
+ .eq('cost_resolution_status', 'pending');
209
+ if (operationIds?.length) {
210
+ query = query.in('id', operationIds);
211
+ }
212
+ else {
213
+ query = query.limit(100);
214
+ }
215
+ const { data, error } = await query;
216
+ if (error) {
217
+ console.error('Failed to load pending billing operations:', error.message);
218
+ return;
219
+ }
220
+ for (const row of data ?? []) {
221
+ const costLogIds = Array.isArray(row.cost_log_ids)
222
+ ? row.cost_log_ids.filter((value) => typeof value === 'string')
223
+ : [];
224
+ const resolution = await resolveCostLogs(supabase, costLogIds);
225
+ if (!resolution.costResolved && resolution.costResolutionStatus === 'pending') {
226
+ continue;
227
+ }
228
+ const { error: updateError } = await supabase
229
+ .from('billing_operation_logs')
230
+ .update({
231
+ cost_usd: resolution.costUsd,
232
+ cost_resolved: resolution.costResolved,
233
+ cost_resolution_status: resolution.costResolutionStatus,
234
+ cost_source: resolution.costSource,
235
+ cost_resolution_error: resolution.costResolutionError,
236
+ resolved_at: resolution.resolvedAt,
237
+ })
238
+ .eq('id', row.id);
239
+ if (updateError) {
240
+ console.error(`Failed to reconcile billing operation log ${row.id}:`, updateError.message);
241
+ }
242
+ }
243
+ }
244
+ catch (error) {
245
+ console.error('Failed to reconcile pending billing operation costs:', error.message);
246
+ }
247
+ }
248
+ //# sourceMappingURL=billing-operation-logging.js.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Browser bar — dispatches between coded browser chrome styles (Chrome, Safari, …).
3
+ *
4
+ * Chrome: pixel-perfect from toolbar4.svg (ref 2160×129, two-row layout).
5
+ * Safari: ref 1500×52, single-row toolbar with SF Pro Symbols icons.
6
+ *
7
+ * Dynamic content (page title, URL, favicon) overlaid as HTML.
8
+ * SF Pro embedded fonts for cross-OS rendering.
9
+ */
10
+ export type BrowserBarStyle = 'chrome' | 'safari';
11
+ export interface BrowserBarConfig {
12
+ url?: string;
13
+ pageTitle?: string;
14
+ tabIconUrl?: string;
15
+ colorScheme?: 'light' | 'dark';
16
+ /** Which coded browser chrome to draw. Defaults to 'chrome' when unset. */
17
+ style?: BrowserBarStyle;
18
+ }
19
+ export interface BrowserBarZoneRect {
20
+ x: number;
21
+ y: number;
22
+ width: number;
23
+ height: number;
24
+ fontSize?: number;
25
+ fontWeight?: number | string;
26
+ textAlign?: 'left' | 'center' | 'right';
27
+ }
28
+ export interface BrowserBarZones {
29
+ favicon?: BrowserBarZoneRect;
30
+ pageTitle?: BrowserBarZoneRect;
31
+ url?: BrowserBarZoneRect;
32
+ }
33
+ export interface BrowserBarRenderOptions {
34
+ config: BrowserBarConfig;
35
+ width: number;
36
+ height: number;
37
+ scale: number;
38
+ pixelScale?: number;
39
+ }
40
+ export declare function generateBrowserBarHtml(options: BrowserBarRenderOptions): string;
41
+ export declare function generateBrowserBarSvg(options: BrowserBarRenderOptions): string;
42
+ export declare function generateChromeBrowserBarHtml(options: BrowserBarRenderOptions): string;
43
+ /**
44
+ * Generate a self-contained SVG string for the Chrome browser bar.
45
+ * Used by the sharp compositing pipeline (no Playwright).
46
+ * Returns an SVG at the target width×height with embedded fonts.
47
+ */
48
+ export declare function generateChromeBrowserBarSvg(options: BrowserBarRenderOptions): string;