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,172 @@
1
+ function isRecord(value) {
2
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
3
+ }
4
+ function getNullableString(value) {
5
+ return typeof value === 'string' && value.trim().length > 0 ? value : null;
6
+ }
7
+ function mergeStudioMockupConfig(existingConfig, deviceFrame, orientation, browserBar, rawScreenshotUrl) {
8
+ const normalizedBrowserBar = browserBar && Object.keys(browserBar).length > 0
9
+ ? {
10
+ ...(browserBar.url ? { url: browserBar.url } : {}),
11
+ ...(browserBar.pageTitle ? { pageTitle: browserBar.pageTitle } : {}),
12
+ ...(browserBar.tabIconUrl ? { tabIconUrl: browserBar.tabIconUrl } : {}),
13
+ }
14
+ : null;
15
+ const normalizedFrame = deviceFrame ?? null;
16
+ const normalizedOrientation = orientation === 'portrait' || orientation === 'landscape'
17
+ ? orientation
18
+ : null;
19
+ const normalizedRawUrl = rawScreenshotUrl ?? null;
20
+ const base = isRecord(existingConfig) ? { ...existingConfig } : {};
21
+ if (normalizedFrame) {
22
+ base.deviceFrame = normalizedFrame;
23
+ }
24
+ else {
25
+ delete base.deviceFrame;
26
+ }
27
+ if (normalizedOrientation) {
28
+ base.orientation = normalizedOrientation;
29
+ }
30
+ if (normalizedRawUrl) {
31
+ base.rawScreenshotUrl = normalizedRawUrl;
32
+ }
33
+ else {
34
+ delete base.rawScreenshotUrl;
35
+ }
36
+ if (normalizedBrowserBar) {
37
+ base.browserBar = normalizedBrowserBar;
38
+ }
39
+ else {
40
+ delete base.browserBar;
41
+ }
42
+ return Object.keys(base).length > 0 ? base : null;
43
+ }
44
+ export async function syncStudioVariantAfterCapture(params) {
45
+ const { supabase, projectId, presetId, targetId = null, lang, theme, elementName, captureId, screenshotUrl, rawScreenshotUrl = null, deviceFrame = null, orientation = null, browserBar, matchTargetId = true, } = params;
46
+ if (!projectId || !presetId || !screenshotUrl) {
47
+ return;
48
+ }
49
+ let linkSelect = supabase
50
+ .from('screenshot_links')
51
+ .select('id, latest_capture:captures!latest_capture_id(screenshot_url, raw_screenshot_url)')
52
+ .eq('preset_id', presetId)
53
+ .eq('lang', lang)
54
+ .eq('theme', theme);
55
+ if (matchTargetId && targetId) {
56
+ linkSelect = linkSelect.eq('target_id', targetId);
57
+ }
58
+ if (elementName !== null) {
59
+ linkSelect = linkSelect.eq('element_name', elementName);
60
+ }
61
+ else {
62
+ linkSelect = linkSelect.is('element_name', null);
63
+ }
64
+ const { data: existingLinks, error: linkSelectError } = await linkSelect;
65
+ if (linkSelectError) {
66
+ console.error('[capture] failed to load screenshot links for studio sync:', linkSelectError.message);
67
+ return;
68
+ }
69
+ let linkUpdate = supabase
70
+ .from('screenshot_links')
71
+ .update({ latest_capture_id: captureId })
72
+ .eq('preset_id', presetId)
73
+ .eq('lang', lang)
74
+ .eq('theme', theme);
75
+ if (matchTargetId && targetId) {
76
+ linkUpdate = linkUpdate.eq('target_id', targetId);
77
+ }
78
+ if (elementName !== null) {
79
+ linkUpdate = linkUpdate.eq('element_name', elementName);
80
+ }
81
+ else {
82
+ linkUpdate = linkUpdate.is('element_name', null);
83
+ }
84
+ const { error: linkUpdateError } = await linkUpdate;
85
+ if (linkUpdateError) {
86
+ console.error('[capture] failed to update screenshot links:', linkUpdateError.message);
87
+ return;
88
+ }
89
+ const previousUrls = new Set();
90
+ for (const link of existingLinks ?? []) {
91
+ const latestCapture = isRecord(link.latest_capture) ? link.latest_capture : null;
92
+ const previousScreenshotUrl = getNullableString(latestCapture?.screenshot_url);
93
+ const previousRawScreenshotUrl = getNullableString(latestCapture?.raw_screenshot_url);
94
+ if (previousScreenshotUrl)
95
+ previousUrls.add(previousScreenshotUrl);
96
+ if (previousRawScreenshotUrl)
97
+ previousUrls.add(previousRawScreenshotUrl);
98
+ }
99
+ const { data: compositions, error: compositionsError } = await supabase
100
+ .from('compositions')
101
+ .select('id, pages')
102
+ .eq('project_id', projectId);
103
+ if (compositionsError) {
104
+ console.error('[capture] failed to load compositions for studio sync:', compositionsError.message);
105
+ return;
106
+ }
107
+ for (const composition of compositions ?? []) {
108
+ const pages = Array.isArray(composition.pages) ? composition.pages : [];
109
+ let changed = false;
110
+ const nextPages = pages.map((page) => {
111
+ if (!isRecord(page) || !isRecord(page.screenshot)) {
112
+ return page;
113
+ }
114
+ const screenshot = page.screenshot;
115
+ if (getNullableString(screenshot.presetId) !== presetId) {
116
+ return page;
117
+ }
118
+ const currentTargetId = getNullableString(screenshot.targetId);
119
+ const currentLang = getNullableString(screenshot.lang);
120
+ const currentTheme = getNullableString(screenshot.theme);
121
+ const currentElementName = getNullableString(screenshot.elementName);
122
+ const currentScreenshotUrl = getNullableString(screenshot.screenshotUrl);
123
+ const currentRawScreenshotUrl = getNullableString(screenshot.rawScreenshotUrl);
124
+ const targetMatches = !matchTargetId || !targetId || currentTargetId === targetId;
125
+ const exactMatch = targetMatches
126
+ && currentLang === lang
127
+ && currentTheme === theme
128
+ && currentElementName === elementName;
129
+ const legacyMatch = (!currentTargetId || !currentLang || !currentTheme)
130
+ && (currentElementName === null || currentElementName === elementName)
131
+ && ((currentScreenshotUrl !== null && previousUrls.has(currentScreenshotUrl))
132
+ || (currentRawScreenshotUrl !== null && previousUrls.has(currentRawScreenshotUrl)));
133
+ if (!exactMatch && !legacyMatch) {
134
+ return page;
135
+ }
136
+ const nextMockupConfig = mergeStudioMockupConfig(screenshot.mockupConfig, deviceFrame, orientation, browserBar, rawScreenshotUrl);
137
+ const nextScreenshot = {
138
+ ...screenshot,
139
+ presetId,
140
+ captureId,
141
+ targetId: targetId ?? currentTargetId,
142
+ lang,
143
+ theme,
144
+ elementName,
145
+ screenshotUrl,
146
+ rawScreenshotUrl,
147
+ };
148
+ if (nextMockupConfig) {
149
+ nextScreenshot.mockupConfig = nextMockupConfig;
150
+ }
151
+ if (JSON.stringify(nextScreenshot) === JSON.stringify(screenshot)) {
152
+ return page;
153
+ }
154
+ changed = true;
155
+ return {
156
+ ...page,
157
+ screenshot: nextScreenshot,
158
+ };
159
+ });
160
+ if (!changed) {
161
+ continue;
162
+ }
163
+ const { error: compositionUpdateError } = await supabase
164
+ .from('compositions')
165
+ .update({ pages: nextPages })
166
+ .eq('id', composition.id);
167
+ if (compositionUpdateError) {
168
+ console.error(`[capture] failed to sync composition ${composition.id} with latest capture:`, compositionUpdateError.message);
169
+ }
170
+ }
171
+ }
172
+ //# sourceMappingURL=capture-studio-sync.js.map
@@ -0,0 +1,36 @@
1
+ import type { BrowserObservation } from "./browser.js";
2
+ import type { CapturePageContract, CapturePageIdentity, VideoPageSignals } from "./types.js";
3
+ export interface ObservedSurfaceEvidence {
4
+ currentUrl: string;
5
+ routeText: string;
6
+ mainText: string;
7
+ chromeText: string;
8
+ overlayText: string;
9
+ dialogText: string;
10
+ strongTargetTokens: string[];
11
+ mainTokenMatches: string[];
12
+ chromeTokenMatches: string[];
13
+ overlayTokenMatches: string[];
14
+ dialogTokenMatches: string[];
15
+ routeTokenMatches: string[];
16
+ hasMainSurface: boolean;
17
+ hasOverlaySurface: boolean;
18
+ hasConfigurationSurface: boolean;
19
+ }
20
+ export declare function buildObservedSurfaceEvidence(params: {
21
+ currentUrl?: string | null;
22
+ observation: BrowserObservation;
23
+ pageSignals?: VideoPageSignals | null;
24
+ pageIdentity?: CapturePageIdentity | null;
25
+ }): ObservedSurfaceEvidence;
26
+ export declare function evaluateSurfaceContract(params: {
27
+ contract: CapturePageContract;
28
+ currentUrl?: string | null;
29
+ observation: BrowserObservation;
30
+ pageSignals?: VideoPageSignals | null;
31
+ pageIdentity?: CapturePageIdentity | null;
32
+ }): {
33
+ matched: boolean;
34
+ reason?: string;
35
+ evidence: ObservedSurfaceEvidence;
36
+ };
@@ -0,0 +1,299 @@
1
+ const WEAK_TARGET_TOKENS = new Set([
2
+ "page",
3
+ "pages",
4
+ "screen",
5
+ "view",
6
+ "views",
7
+ "section",
8
+ "content",
9
+ "main",
10
+ "current",
11
+ "currently",
12
+ "open",
13
+ "opened",
14
+ "screenshot",
15
+ "screenshots",
16
+ "state",
17
+ "target",
18
+ "ready",
19
+ "modal",
20
+ "dialog",
21
+ "popup",
22
+ "overlay",
23
+ "drawer",
24
+ "panel",
25
+ "route",
26
+ "routes",
27
+ "editor",
28
+ "form",
29
+ "configuration",
30
+ "config",
31
+ "selection",
32
+ "select",
33
+ "choose",
34
+ "picker",
35
+ "workflow",
36
+ "step",
37
+ "steps",
38
+ "app",
39
+ "site",
40
+ "web",
41
+ ]);
42
+ function normalizeText(value) {
43
+ return (value ?? "")
44
+ .normalize("NFD")
45
+ .replace(/[\u0300-\u036f]/g, " ")
46
+ .toLowerCase()
47
+ .replace(/[^a-z0-9]+/g, " ")
48
+ .trim();
49
+ }
50
+ function joinText(values) {
51
+ return values
52
+ .map((value) => normalizeText(value))
53
+ .filter(Boolean)
54
+ .join(" ");
55
+ }
56
+ function tokenize(value) {
57
+ return normalizeText(value)
58
+ .split(/\s+/g)
59
+ .map((part) => part.trim())
60
+ .filter((part) => part.length >= 3);
61
+ }
62
+ function unique(values) {
63
+ const seen = new Set();
64
+ const out = [];
65
+ for (const value of values) {
66
+ if (seen.has(value))
67
+ continue;
68
+ seen.add(value);
69
+ out.push(value);
70
+ }
71
+ return out;
72
+ }
73
+ function buildStrongTargetTokens(pageIdentity) {
74
+ return unique((pageIdentity?.subjectTokens ?? [])
75
+ .map((token) => normalizeText(token))
76
+ .filter((token) => token.length >= 4 && !WEAK_TARGET_TOKENS.has(token)));
77
+ }
78
+ function countTokenMatches(tokens, haystack) {
79
+ if (tokens.length === 0 || !haystack)
80
+ return [];
81
+ const haystackTokens = new Set(tokenize(haystack));
82
+ return tokens.filter((token) => haystackTokens.has(token));
83
+ }
84
+ function requiredTokenEvidenceCount(tokenCount) {
85
+ return tokenCount <= 1 ? 1 : 2;
86
+ }
87
+ function hasSufficientSurfaceEvidence(params) {
88
+ if (params.totalTokenCount <= 0)
89
+ return false;
90
+ const minimum = requiredTokenEvidenceCount(params.totalTokenCount);
91
+ if (params.matchedCount >= minimum)
92
+ return true;
93
+ if (minimum >= 2 && params.matchedCount >= 1 && params.routeMatchedCount >= 1) {
94
+ return true;
95
+ }
96
+ return false;
97
+ }
98
+ function hasMeaningfulMainSurface(observation, pageSignals) {
99
+ return !!(normalizeText(observation.primarySurface)
100
+ || normalizeText(observation.configurationSurface)
101
+ || normalizeText(pageSignals?.title ?? observation.title)
102
+ || (pageSignals?.headings.length ?? 0) > 0
103
+ || normalizeText(pageSignals?.visibleText));
104
+ }
105
+ export function buildObservedSurfaceEvidence(params) {
106
+ const currentUrl = normalizeText(params.currentUrl ?? params.observation.url ?? "");
107
+ const routeText = joinText([
108
+ currentUrl,
109
+ params.pageSignals?.canonicalUrl ?? "",
110
+ ]);
111
+ const mainText = joinText([
112
+ params.pageSignals?.title ?? params.observation.title,
113
+ ...(params.pageSignals?.headings ?? []),
114
+ ...(params.pageSignals?.breadcrumbLabels ?? []),
115
+ params.observation.primarySurface,
116
+ params.observation.configurationSurface,
117
+ params.pageSignals?.visibleText ?? "",
118
+ params.observation.textSample,
119
+ ]);
120
+ const chromeText = joinText([
121
+ ...(params.pageSignals?.navLabels ?? []),
122
+ params.observation.navigationSurface,
123
+ ]);
124
+ const overlayText = joinText([
125
+ params.observation.overlaySurface,
126
+ ]);
127
+ const dialogText = joinText([
128
+ params.observation.overlaySurface,
129
+ params.observation.configurationSurface,
130
+ params.pageSignals?.title ?? params.observation.title,
131
+ ...(params.pageSignals?.headings ?? []),
132
+ ]);
133
+ const strongTargetTokens = buildStrongTargetTokens(params.pageIdentity ?? null);
134
+ return {
135
+ currentUrl,
136
+ routeText,
137
+ mainText,
138
+ chromeText,
139
+ overlayText,
140
+ dialogText,
141
+ strongTargetTokens,
142
+ mainTokenMatches: countTokenMatches(strongTargetTokens, mainText),
143
+ chromeTokenMatches: countTokenMatches(strongTargetTokens, chromeText),
144
+ overlayTokenMatches: countTokenMatches(strongTargetTokens, overlayText),
145
+ dialogTokenMatches: countTokenMatches(strongTargetTokens, dialogText),
146
+ routeTokenMatches: countTokenMatches(strongTargetTokens, routeText),
147
+ hasMainSurface: hasMeaningfulMainSurface(params.observation, params.pageSignals ?? null),
148
+ hasOverlaySurface: overlayText.length > 0,
149
+ hasConfigurationSurface: normalizeText(params.observation.configurationSurface).length > 0,
150
+ };
151
+ }
152
+ function resolveExpectedSurfaceLabel(contract) {
153
+ switch (contract.expectedSurfaceKind) {
154
+ case "dialog_configuration":
155
+ case "dialog_selection":
156
+ return "dialog/modal capture target";
157
+ case "editor_route":
158
+ case "detail_route":
159
+ return "requested page state";
160
+ default:
161
+ return "requested capture target";
162
+ }
163
+ }
164
+ function formatSurfaceReason(params) {
165
+ const expectedTokens = params.evidence.strongTargetTokens.slice(0, 5).join(", ");
166
+ const observedSurfaces = [
167
+ params.observation.overlaySurface ? `overlay="${params.observation.overlaySurface.slice(0, 80)}"` : "",
168
+ params.observation.configurationSurface ? `configuration="${params.observation.configurationSurface.slice(0, 80)}"` : "",
169
+ params.observation.primarySurface ? `main="${params.observation.primarySurface.slice(0, 80)}"` : "",
170
+ ]
171
+ .filter(Boolean)
172
+ .join("; ");
173
+ const details = [
174
+ params.pageIdentity?.summary ? `identity=${params.pageIdentity.summary}` : "",
175
+ expectedTokens ? `expected_tokens=${expectedTokens}` : "",
176
+ `dialogs=${params.observation.dialogCount}`,
177
+ observedSurfaces,
178
+ ]
179
+ .filter(Boolean)
180
+ .join("; ");
181
+ return details ? `${params.base} [${details}]` : params.base;
182
+ }
183
+ export function evaluateSurfaceContract(params) {
184
+ const evidence = buildObservedSurfaceEvidence(params);
185
+ const expectedLabel = resolveExpectedSurfaceLabel(params.contract);
186
+ const targetSeenInMain = hasSufficientSurfaceEvidence({
187
+ matchedCount: evidence.mainTokenMatches.length,
188
+ routeMatchedCount: evidence.routeTokenMatches.length,
189
+ totalTokenCount: evidence.strongTargetTokens.length,
190
+ });
191
+ const targetSeenInOverlay = hasSufficientSurfaceEvidence({
192
+ matchedCount: evidence.overlayTokenMatches.length,
193
+ routeMatchedCount: evidence.routeTokenMatches.length,
194
+ totalTokenCount: evidence.strongTargetTokens.length,
195
+ });
196
+ const targetSeenInRoute = evidence.routeTokenMatches.length >= requiredTokenEvidenceCount(evidence.strongTargetTokens.length);
197
+ const targetSeenOnlyInChrome = evidence.chromeTokenMatches.length > 0
198
+ && !targetSeenInMain
199
+ && !targetSeenInOverlay
200
+ && !targetSeenInRoute;
201
+ const structuralDialogVisible = params.contract.dialogPolicy === "must_be_open"
202
+ && params.observation.dialogCount > 0
203
+ && (evidence.hasOverlaySurface || evidence.hasConfigurationSurface || evidence.dialogText.length > 0);
204
+ const dialogCueMatches = unique([
205
+ ...evidence.overlayTokenMatches,
206
+ ...evidence.dialogTokenMatches,
207
+ ...evidence.mainTokenMatches,
208
+ ]);
209
+ if (params.contract.dialogPolicy === "must_be_open" && params.observation.dialogCount === 0) {
210
+ return {
211
+ matched: false,
212
+ reason: formatSurfaceReason({
213
+ base: `Expected a ${expectedLabel}, but no dialog is currently open.`,
214
+ evidence,
215
+ observation: params.observation,
216
+ pageIdentity: params.pageIdentity ?? null,
217
+ }),
218
+ evidence,
219
+ };
220
+ }
221
+ if (params.contract.dialogPolicy === "must_be_closed" && params.observation.dialogCount > 0) {
222
+ return {
223
+ matched: false,
224
+ reason: formatSurfaceReason({
225
+ base: `Expected the ${expectedLabel}, but a dialog/modal is still open on top of the page.`,
226
+ evidence,
227
+ observation: params.observation,
228
+ pageIdentity: params.pageIdentity ?? null,
229
+ }),
230
+ evidence,
231
+ };
232
+ }
233
+ if (evidence.strongTargetTokens.length > 0) {
234
+ const hasTargetEvidence = targetSeenInMain
235
+ || targetSeenInOverlay
236
+ || targetSeenInRoute;
237
+ if (hasTargetEvidence) {
238
+ return { matched: true, evidence };
239
+ }
240
+ if (structuralDialogVisible && dialogCueMatches.length >= 1) {
241
+ return { matched: true, evidence };
242
+ }
243
+ if (targetSeenOnlyInChrome) {
244
+ return {
245
+ matched: false,
246
+ reason: formatSurfaceReason({
247
+ base: `Expected the ${expectedLabel}, but matching cues appear only in the navigation/chrome, not in the main page content.`,
248
+ evidence,
249
+ observation: params.observation,
250
+ pageIdentity: params.pageIdentity ?? null,
251
+ }),
252
+ evidence,
253
+ };
254
+ }
255
+ return {
256
+ matched: false,
257
+ reason: formatSurfaceReason({
258
+ base: structuralDialogVisible
259
+ ? `Expected the ${expectedLabel}, but the visible dialog still lacks enough target-specific cues.`
260
+ : `Expected the ${expectedLabel}, but the main page content does not yet show the requested target.`,
261
+ evidence,
262
+ observation: params.observation,
263
+ pageIdentity: params.pageIdentity ?? null,
264
+ }),
265
+ evidence,
266
+ };
267
+ }
268
+ if (structuralDialogVisible && evidence.hasConfigurationSurface) {
269
+ return { matched: true, evidence };
270
+ }
271
+ if ((params.contract.expectedSurfaceKind === "dialog_configuration" || params.contract.expectedSurfaceKind === "dialog_selection")
272
+ && !evidence.hasOverlaySurface
273
+ && !evidence.hasConfigurationSurface) {
274
+ return {
275
+ matched: false,
276
+ reason: formatSurfaceReason({
277
+ base: `Expected a ${expectedLabel}, but the open dialog does not expose enough visible content yet.`,
278
+ evidence,
279
+ observation: params.observation,
280
+ pageIdentity: params.pageIdentity ?? null,
281
+ }),
282
+ evidence,
283
+ };
284
+ }
285
+ if (!evidence.hasMainSurface && params.contract.dialogPolicy !== "must_be_open") {
286
+ return {
287
+ matched: false,
288
+ reason: formatSurfaceReason({
289
+ base: `Expected the ${expectedLabel}, but the current page surface is too weakly identified.`,
290
+ evidence,
291
+ observation: params.observation,
292
+ pageIdentity: params.pageIdentity ?? null,
293
+ }),
294
+ evidence,
295
+ };
296
+ }
297
+ return { matched: true, evidence };
298
+ }
299
+ //# sourceMappingURL=capture-surface-contract.js.map
@@ -0,0 +1,28 @@
1
+ import type { BrowserObservation } from "./browser.js";
2
+ import type { CaptureBaselineResult, CaptureHandoffContext, CapturePageContract, CapturePageIdentity, CaptureTransitionDecision, ValidatedSessionProfile, VideoPageSignals } from "./types.js";
3
+ export declare function deriveCapturePageContract(params: {
4
+ pageIdentity?: CapturePageIdentity | null;
5
+ }): CapturePageContract;
6
+ export declare function buildCaptureCheckpointEvidence(params: {
7
+ currentUrl?: string | null;
8
+ targetUrl: string;
9
+ pageIdentity?: CapturePageIdentity | null;
10
+ observation: BrowserObservation;
11
+ pageSignals?: VideoPageSignals | null;
12
+ profile?: ValidatedSessionProfile;
13
+ requestedLang?: string;
14
+ requestedTheme?: "light" | "dark";
15
+ }): CaptureTransitionDecision;
16
+ export declare function decideCaptureTransition(params: {
17
+ pageIndex: number;
18
+ currentUrl?: string | null;
19
+ targetUrl: string;
20
+ resumeUrl?: string | null;
21
+ pageIdentity?: CapturePageIdentity | null;
22
+ observation: BrowserObservation | null;
23
+ pageSignals?: VideoPageSignals | null;
24
+ profile?: ValidatedSessionProfile;
25
+ handoffContext?: CaptureHandoffContext;
26
+ requestedLang?: string;
27
+ requestedTheme?: "light" | "dark";
28
+ }): CaptureBaselineResult;