autokap 1.0.7 → 1.0.10

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 (301) hide show
  1. package/assets/cursors/macos.svg +4 -0
  2. package/assets/cursors/windows.svg +15 -0
  3. package/assets/skill/OPCODE-REFERENCE.md +635 -0
  4. package/assets/skill/README.md +39 -0
  5. package/assets/skill/SKILL.md +454 -468
  6. package/assets/skill/STUDIO-SKILL.md +476 -0
  7. package/assets/skill/references/examples.md +104 -0
  8. package/assets/skill/references/interactive-demo.md +225 -0
  9. package/assets/skill/references/mock-data.md +178 -0
  10. package/dist/action-verifier.d.ts +29 -0
  11. package/dist/action-verifier.js +133 -0
  12. package/dist/agent-action-recovery.d.ts +45 -0
  13. package/dist/agent-action-recovery.js +370 -0
  14. package/dist/agent-message-utils.d.ts +21 -0
  15. package/dist/agent-message-utils.js +77 -0
  16. package/dist/agent-url-utils.d.ts +30 -0
  17. package/dist/agent-url-utils.js +138 -0
  18. package/dist/agent.d.ts +92 -8
  19. package/dist/agent.js +2936 -781
  20. package/dist/ak-tree.d.ts +39 -0
  21. package/dist/ak-tree.js +368 -0
  22. package/dist/alt-text.d.ts +26 -0
  23. package/dist/alt-text.js +55 -0
  24. package/dist/auth-capture.d.ts +17 -0
  25. package/dist/auth-capture.js +197 -0
  26. package/dist/benchmark.d.ts +59 -0
  27. package/dist/benchmark.js +135 -0
  28. package/dist/billing-operation-logging.d.ts +3 -1
  29. package/dist/billing-operation-logging.js +4 -0
  30. package/dist/browser-bar.d.ts +14 -6
  31. package/dist/browser-bar.js +145 -8
  32. package/dist/browser-pool.d.ts +7 -0
  33. package/dist/browser-pool.js +15 -5
  34. package/dist/browser-utils.d.ts +31 -0
  35. package/dist/browser-utils.js +97 -0
  36. package/dist/browser.d.ts +61 -11
  37. package/dist/browser.js +1513 -59
  38. package/dist/capture-alt-text.js +2 -1
  39. package/dist/capture-encryption.d.ts +3 -1
  40. package/dist/capture-encryption.js +21 -6
  41. package/dist/capture-language-preflight.js +14 -0
  42. package/dist/capture-llm-page-identity.js +22 -10
  43. package/dist/capture-page-identity.d.ts +5 -7
  44. package/dist/capture-page-identity.js +211 -78
  45. package/dist/capture-preset-credentials.d.ts +50 -0
  46. package/dist/capture-preset-credentials.js +127 -0
  47. package/dist/capture-request-plan.d.ts +2 -2
  48. package/dist/capture-request-plan.js +64 -16
  49. package/dist/capture-run-optimizer.js +48 -33
  50. package/dist/capture-selector-memory.d.ts +5 -0
  51. package/dist/capture-selector-memory.js +18 -0
  52. package/dist/capture-strategy.d.ts +36 -0
  53. package/dist/capture-strategy.js +96 -0
  54. package/dist/capture-studio-sync.d.ts +1 -0
  55. package/dist/capture-studio-sync.js +9 -3
  56. package/dist/capture-surface-contract.d.ts +36 -0
  57. package/dist/capture-surface-contract.js +299 -0
  58. package/dist/capture-transition-engine.d.ts +28 -0
  59. package/dist/capture-transition-engine.js +292 -0
  60. package/dist/capture-variant-state.d.ts +2 -0
  61. package/dist/capture-variant-state.js +26 -0
  62. package/dist/capture-verification.d.ts +35 -0
  63. package/dist/capture-verification.js +95 -0
  64. package/dist/capture-viewport-lock.d.ts +48 -0
  65. package/dist/capture-viewport-lock.js +74 -0
  66. package/dist/circuit-breaker.d.ts +42 -0
  67. package/dist/circuit-breaker.js +119 -0
  68. package/dist/cli-config.d.ts +9 -1
  69. package/dist/cli-config.js +112 -7
  70. package/dist/cli-contract.d.ts +19 -0
  71. package/dist/cli-contract.js +173 -0
  72. package/dist/cli-runner-local.d.ts +12 -0
  73. package/dist/cli-runner-local.js +115 -0
  74. package/dist/cli-runner.d.ts +34 -0
  75. package/dist/cli-runner.js +580 -0
  76. package/dist/cli-utils.d.ts +0 -1
  77. package/dist/cli-utils.js +2 -5
  78. package/dist/cli.js +1011 -267
  79. package/dist/clip-begin-frame-recorder.d.ts +44 -0
  80. package/dist/clip-begin-frame-recorder.js +250 -0
  81. package/dist/clip-capture-backend.d.ts +25 -0
  82. package/dist/clip-capture-backend.js +189 -0
  83. package/dist/clip-capture-loop.d.ts +61 -0
  84. package/dist/clip-capture-loop.js +111 -0
  85. package/dist/clip-frame-recorder.d.ts +63 -0
  86. package/dist/clip-frame-recorder.js +305 -0
  87. package/dist/clip-orchestrator.js +9 -2
  88. package/dist/clip-postprocess.d.ts +31 -2
  89. package/dist/clip-postprocess.js +194 -68
  90. package/dist/clip-runtime.d.ts +18 -0
  91. package/dist/clip-runtime.js +67 -0
  92. package/dist/clip-scale.d.ts +10 -0
  93. package/dist/clip-scale.js +21 -0
  94. package/dist/clip-screencast-recorder.d.ts +42 -0
  95. package/dist/clip-screencast-recorder.js +242 -0
  96. package/dist/clip-sidecar.d.ts +54 -0
  97. package/dist/clip-sidecar.js +208 -0
  98. package/dist/cookie-dismiss.d.ts +2 -0
  99. package/dist/cookie-dismiss.js +48 -13
  100. package/dist/cost-logging.d.ts +8 -0
  101. package/dist/cost-logging.js +160 -46
  102. package/dist/cost-resolution-monitor.d.ts +16 -0
  103. package/dist/cost-resolution-monitor.js +34 -0
  104. package/dist/credential-templates.js +2 -2
  105. package/dist/cursor-overlay-script.d.ts +6 -0
  106. package/dist/cursor-overlay-script.js +169 -0
  107. package/dist/dom-css-purger.d.ts +65 -0
  108. package/dist/dom-css-purger.js +333 -0
  109. package/dist/dom-font-inliner.d.ts +45 -0
  110. package/dist/dom-font-inliner.js +148 -0
  111. package/dist/dom-patch-resolver.d.ts +52 -0
  112. package/dist/dom-patch-resolver.js +242 -0
  113. package/dist/dom-serializer.d.ts +82 -0
  114. package/dist/dom-serializer.js +378 -0
  115. package/dist/element-capture.d.ts +1 -41
  116. package/dist/element-capture.js +202 -446
  117. package/dist/env-validation.d.ts +5 -0
  118. package/dist/env-validation.js +63 -0
  119. package/dist/execution-schema.d.ts +4753 -0
  120. package/dist/execution-schema.js +563 -0
  121. package/dist/execution-types.d.ts +936 -0
  122. package/dist/execution-types.js +66 -0
  123. package/dist/fonts-loader.d.ts +14 -0
  124. package/dist/fonts-loader.js +55 -0
  125. package/dist/hybrid-navigator.js +12 -12
  126. package/dist/index.d.ts +11 -6
  127. package/dist/index.js +11 -4
  128. package/dist/legacy/agent-action-recovery.d.ts +45 -0
  129. package/dist/legacy/agent-action-recovery.js +370 -0
  130. package/dist/legacy/agent-message-utils.d.ts +21 -0
  131. package/dist/legacy/agent-message-utils.js +77 -0
  132. package/dist/legacy/agent-url-utils.d.ts +30 -0
  133. package/dist/legacy/agent-url-utils.js +138 -0
  134. package/dist/legacy/agent.d.ts +226 -0
  135. package/dist/legacy/agent.js +6666 -0
  136. package/dist/legacy/clip-orchestrator.d.ts +148 -0
  137. package/dist/legacy/clip-orchestrator.js +957 -0
  138. package/dist/legacy/credential-templates.d.ts +5 -0
  139. package/dist/legacy/credential-templates.js +60 -0
  140. package/dist/legacy/hybrid-navigator.d.ts +138 -0
  141. package/dist/legacy/hybrid-navigator.js +468 -0
  142. package/dist/legacy/llm-usage.d.ts +17 -0
  143. package/dist/legacy/llm-usage.js +45 -0
  144. package/dist/legacy/prompt-cache.d.ts +10 -0
  145. package/dist/legacy/prompt-cache.js +24 -0
  146. package/dist/legacy/prompts.d.ts +175 -0
  147. package/dist/legacy/prompts.js +1038 -0
  148. package/dist/legacy/tools.d.ts +4 -0
  149. package/dist/legacy/tools.js +216 -0
  150. package/dist/legacy/video-agent.d.ts +143 -0
  151. package/dist/legacy/video-agent.js +4788 -0
  152. package/dist/legacy/video-observation.d.ts +36 -0
  153. package/dist/legacy/video-observation.js +192 -0
  154. package/dist/legacy/video-planner.d.ts +12 -0
  155. package/dist/legacy/video-planner.js +501 -0
  156. package/dist/legacy/video-prompts.d.ts +37 -0
  157. package/dist/legacy/video-prompts.js +569 -0
  158. package/dist/legacy/video-tools.d.ts +3 -0
  159. package/dist/legacy/video-tools.js +59 -0
  160. package/dist/legacy/video-variant-state.d.ts +29 -0
  161. package/dist/legacy/video-variant-state.js +80 -0
  162. package/dist/legacy/vision-model.d.ts +17 -0
  163. package/dist/legacy/vision-model.js +74 -0
  164. package/dist/llm-healer.d.ts +55 -0
  165. package/dist/llm-healer.js +213 -0
  166. package/dist/llm-provider.d.ts +29 -0
  167. package/dist/llm-provider.js +83 -0
  168. package/dist/logger.d.ts +6 -2
  169. package/dist/logger.js +15 -1
  170. package/dist/mockup-html.js +35 -25
  171. package/dist/mockup.d.ts +95 -2
  172. package/dist/mockup.js +427 -166
  173. package/dist/mouse-animation.d.ts +2 -2
  174. package/dist/mouse-animation.js +34 -20
  175. package/dist/opcode-actions.d.ts +42 -0
  176. package/dist/opcode-actions.js +524 -0
  177. package/dist/opcode-runner.d.ts +51 -0
  178. package/dist/opcode-runner.js +779 -0
  179. package/dist/openrouter-client.d.ts +40 -0
  180. package/dist/openrouter-client.js +16 -0
  181. package/dist/overlay-engine.d.ts +24 -0
  182. package/dist/overlay-engine.js +176 -0
  183. package/dist/postcondition.d.ts +16 -0
  184. package/dist/postcondition.js +269 -0
  185. package/dist/program-patcher.d.ts +25 -0
  186. package/dist/program-patcher.js +44 -0
  187. package/dist/program-signing.d.ts +1094 -0
  188. package/dist/program-signing.js +140 -0
  189. package/dist/prompts.d.ts +13 -5
  190. package/dist/prompts.js +224 -351
  191. package/dist/provider-config.d.ts +17 -0
  192. package/dist/provider-config.js +42 -0
  193. package/dist/recovery-chain.d.ts +37 -0
  194. package/dist/recovery-chain.js +374 -0
  195. package/dist/remote-browser.d.ts +28 -4
  196. package/dist/remote-browser.js +60 -5
  197. package/dist/safari-browser-bar.d.ts +15 -0
  198. package/dist/safari-browser-bar.js +95 -0
  199. package/dist/safari-toolbar-asset.d.ts +15 -0
  200. package/dist/safari-toolbar-asset.js +12 -0
  201. package/dist/security.d.ts +2 -1
  202. package/dist/security.js +49 -10
  203. package/dist/selector-resolver.d.ts +34 -0
  204. package/dist/selector-resolver.js +181 -0
  205. package/dist/semantic-resolver.d.ts +35 -0
  206. package/dist/semantic-resolver.js +161 -0
  207. package/dist/server-capture-runtime.d.ts +5 -3
  208. package/dist/server-capture-runtime.js +42 -95
  209. package/dist/server-credit-usage.d.ts +2 -2
  210. package/dist/server-project-webhooks.d.ts +15 -1
  211. package/dist/server-project-webhooks.js +34 -8
  212. package/dist/server-screenshot-watermark.js +27 -5
  213. package/dist/session-profile.js +164 -1
  214. package/dist/sf-pro-symbols.d.ts +1 -0
  215. package/dist/sf-pro-symbols.js +55 -0
  216. package/dist/skill-packaging.d.ts +28 -0
  217. package/dist/skill-packaging.js +169 -0
  218. package/dist/smart-wait.d.ts +27 -0
  219. package/dist/smart-wait.js +81 -0
  220. package/dist/status-bar-render.d.ts +20 -0
  221. package/dist/status-bar-render.js +410 -0
  222. package/dist/status-bar.d.ts +9 -0
  223. package/dist/status-bar.js +298 -14
  224. package/dist/svg-browser-bar.d.ts +33 -0
  225. package/dist/svg-browser-bar.js +206 -0
  226. package/dist/svg-status-bar.d.ts +36 -0
  227. package/dist/svg-status-bar.js +597 -0
  228. package/dist/svg-text.d.ts +61 -0
  229. package/dist/svg-text.js +118 -0
  230. package/dist/tools.js +89 -451
  231. package/dist/types.d.ts +248 -7
  232. package/dist/types.js +23 -1
  233. package/dist/v2/action-verifier.d.ts +29 -0
  234. package/dist/v2/action-verifier.js +133 -0
  235. package/dist/v2/alt-text.d.ts +26 -0
  236. package/dist/v2/alt-text.js +55 -0
  237. package/dist/v2/benchmark.d.ts +59 -0
  238. package/dist/v2/benchmark.js +135 -0
  239. package/dist/v2/capture-strategy.d.ts +30 -0
  240. package/dist/v2/capture-strategy.js +67 -0
  241. package/dist/v2/capture-verification.d.ts +35 -0
  242. package/dist/v2/capture-verification.js +95 -0
  243. package/dist/v2/circuit-breaker.d.ts +42 -0
  244. package/dist/v2/circuit-breaker.js +119 -0
  245. package/dist/v2/cli-runner-local.d.ts +11 -0
  246. package/dist/v2/cli-runner-local.js +91 -0
  247. package/dist/v2/cli-runner.d.ts +34 -0
  248. package/dist/v2/cli-runner.js +300 -0
  249. package/dist/v2/compiler-prompts.d.ts +27 -0
  250. package/dist/v2/compiler-prompts.js +123 -0
  251. package/dist/v2/compiler.d.ts +37 -0
  252. package/dist/v2/compiler.js +147 -0
  253. package/dist/v2/explorer.d.ts +41 -0
  254. package/dist/v2/explorer.js +56 -0
  255. package/dist/v2/index.d.ts +37 -0
  256. package/dist/v2/index.js +31 -0
  257. package/dist/v2/llm-healer.d.ts +62 -0
  258. package/dist/v2/llm-healer.js +166 -0
  259. package/dist/v2/llm-provider.d.ts +29 -0
  260. package/dist/v2/llm-provider.js +80 -0
  261. package/dist/v2/opcode-runner.d.ts +47 -0
  262. package/dist/v2/opcode-runner.js +634 -0
  263. package/dist/v2/overlay-engine.d.ts +24 -0
  264. package/dist/v2/overlay-engine.js +150 -0
  265. package/dist/v2/postcondition.d.ts +16 -0
  266. package/dist/v2/postcondition.js +249 -0
  267. package/dist/v2/program-patcher.d.ts +25 -0
  268. package/dist/v2/program-patcher.js +44 -0
  269. package/dist/v2/recovery-chain.d.ts +30 -0
  270. package/dist/v2/recovery-chain.js +368 -0
  271. package/dist/v2/schema.d.ts +2580 -0
  272. package/dist/v2/schema.js +295 -0
  273. package/dist/v2/selector-resolver.d.ts +34 -0
  274. package/dist/v2/selector-resolver.js +181 -0
  275. package/dist/v2/semantic-resolver.d.ts +35 -0
  276. package/dist/v2/semantic-resolver.js +161 -0
  277. package/dist/v2/smart-wait.d.ts +27 -0
  278. package/dist/v2/smart-wait.js +81 -0
  279. package/dist/v2/types.d.ts +444 -0
  280. package/dist/v2/types.js +19 -0
  281. package/dist/v2/web-playwright-local.d.ts +69 -0
  282. package/dist/v2/web-playwright-local.js +392 -0
  283. package/dist/version.d.ts +1 -0
  284. package/dist/version.js +5 -0
  285. package/dist/video-agent.js +18 -13
  286. package/dist/video-planner.js +2 -1
  287. package/dist/video-prompts.js +3 -3
  288. package/dist/web-playwright-local.d.ts +156 -0
  289. package/dist/web-playwright-local.js +989 -0
  290. package/dist/ws-auth.js +4 -1
  291. package/dist/ws-broadcast.d.ts +34 -0
  292. package/dist/ws-broadcast.js +85 -0
  293. package/dist/ws-connection-limits.d.ts +12 -0
  294. package/dist/ws-connection-limits.js +44 -0
  295. package/dist/ws-handler-utils.d.ts +32 -0
  296. package/dist/ws-handler-utils.js +139 -0
  297. package/dist/ws-handler.js +294 -164
  298. package/dist/ws-metrics-server.d.ts +9 -0
  299. package/dist/ws-metrics-server.js +31 -0
  300. package/dist/ws-server.js +41 -1
  301. package/package.json +62 -35
@@ -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((step) => ({
5
- id: crypto.randomUUID(),
6
- run_id: ctx.runId,
7
- user_id: ctx.userId,
8
- project_id: ctx.projectId ?? null,
9
- preset_id: ctx.presetId ?? null,
10
- capture_id: ctx.captureId ?? null,
11
- step_number: step.stepNumber,
12
- step_type: step.stepType,
13
- model_requested: step.modelRequested,
14
- model_used: step.modelUsed,
15
- generation_id: step.generationId,
16
- prompt_tokens: step.promptTokens,
17
- completion_tokens: step.completionTokens,
18
- total_tokens: step.totalTokens,
19
- cost_resolved: false,
20
- images_in_prompt: step.imagesInPrompt,
21
- lang: ctx.lang ?? null,
22
- theme: ctx.theme ?? null,
23
- capture_type: ctx.captureType ?? null,
24
- element_name: ctx.elementName ?? null,
25
- target_id: ctx.targetId ?? null,
26
- viewport_width: ctx.viewportWidth ?? null,
27
- viewport_height: ctx.viewportHeight ?? null,
28
- system_prompt_chars: step.systemPromptChars ?? null,
29
- tool_schema_chars: step.toolSchemaChars ?? null,
30
- user_payload_chars: step.userPayloadChars ?? null,
31
- accessibility_chars: step.accessibilityChars ?? null,
32
- interactive_element_count: step.interactiveElementCount ?? null,
33
- action_history_count: step.actionHistoryCount ?? null,
34
- elements_chars: step.elementsChars ?? null,
35
- session_summary_chars: step.sessionSummaryChars ?? null,
36
- selector_memory_chars: step.selectorMemoryChars ?? null,
37
- agent_context_chars: step.agentContextChars ?? null,
38
- profile_validation_status: step.profileValidationStatus ?? null,
39
- session_profile_source: step.sessionProfileSource ?? null,
40
- repair_path_used: step.repairPathUsed ?? null,
41
- evaluator_used: step.evaluatorUsed ?? false,
42
- cache_read_tokens: step.cacheReadTokens ?? null,
43
- cache_write_tokens: step.cacheWriteTokens ?? null,
44
- session_profile_reused: step.sessionProfileReused ?? false,
45
- action_replay_used: step.actionReplayUsed ?? false,
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
- return;
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
- return;
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("type_text.text", resolved.text);
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;
@@ -0,0 +1,169 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ // SVG files are the single source of truth — edit web/public/cursors/*.svg directly.
5
+ function loadCursorSvg(name) {
6
+ const currentDir = path.dirname(fileURLToPath(import.meta.url));
7
+ const candidatePaths = [
8
+ // From dist/ → ../web/public/cursors/
9
+ path.resolve(currentDir, '../web/public/cursors', `${name}.svg`),
10
+ // From package/dist/ → ../../web/public/cursors/
11
+ path.resolve(currentDir, '../../web/public/cursors', `${name}.svg`),
12
+ // Bundled alongside dist in package/assets/cursors/
13
+ path.resolve(currentDir, '../assets/cursors', `${name}.svg`),
14
+ // Fallback: same directory
15
+ path.resolve(currentDir, './web/public/cursors', `${name}.svg`),
16
+ ];
17
+ for (const candidatePath of candidatePaths) {
18
+ if (fs.existsSync(candidatePath)) {
19
+ return fs.readFileSync(candidatePath, 'utf-8').trim();
20
+ }
21
+ }
22
+ throw new Error(`Cursor asset "${name}.svg" not found. Looked in: ${candidatePaths.join(', ')}`);
23
+ }
24
+ const CURSOR_THEME_SVGS = {};
25
+ function getCursorThemeSvg(theme) {
26
+ if (!CURSOR_THEME_SVGS[theme]) {
27
+ CURSOR_THEME_SVGS[theme] = loadCursorSvg(theme);
28
+ }
29
+ return CURSOR_THEME_SVGS[theme];
30
+ }
31
+ /**
32
+ * JavaScript injected via `context.addInitScript()` to show a visible animated
33
+ * cursor in Playwright video recordings (the native OS cursor is invisible).
34
+ */
35
+ export function buildCursorOverlayScript(theme = 'minimal') {
36
+ const cursorSvg = theme === 'minimal' ? null : getCursorThemeSvg(theme);
37
+ return `
38
+ (function() {
39
+ function injectCursor() {
40
+ if (document.getElementById('__ak_cursor__')) return;
41
+ const cursorTheme = ${JSON.stringify(theme)};
42
+ const cursorSvg = ${JSON.stringify(cursorSvg)};
43
+
44
+ const style = document.createElement('style');
45
+ style.textContent = [
46
+ '*, *::before, *::after { cursor: none !important; }',
47
+ '#__ak_cursor__ { mix-blend-mode: normal; }',
48
+ '#__ak_cursor__ svg { width: 100%; height: 100%; display: block; overflow: visible; }',
49
+ '#__ak_cursor__[data-theme="macos"], #__ak_cursor__[data-theme="windows"] { width: 28px !important; height: 28px !important; background: transparent !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; }',
50
+ '#__ak_cursor__.__ak_pressed { transform: translate(-50%, -50%) scale(0.72) !important; box-shadow: 0 0 0 8px rgba(37, 99, 235, 0.18), 0 4px 18px rgba(0,0,0,0.28) !important; background: rgba(255,255,255,0.98) !important; border-color: rgba(30,41,59,0.92) !important; }',
51
+ '#__ak_cursor__[data-theme="macos"].__ak_pressed, #__ak_cursor__[data-theme="windows"].__ak_pressed { background: transparent !important; border-color: transparent !important; box-shadow: none !important; filter: drop-shadow(0 0 0 rgba(37, 99, 235, 0)) drop-shadow(0 0 0 rgba(37, 99, 235, 0)) !important; }',
52
+ '#__ak_cursor__[data-theme="macos"].__ak_pressed svg, #__ak_cursor__[data-theme="windows"].__ak_pressed svg { filter: drop-shadow(0 0 0.5px rgba(255,255,255,0.9)) drop-shadow(0 0 10px rgba(37, 99, 235, 0.45)); }',
53
+ '#__ak_cursor_click_pulse__ { position: fixed; width: 20px; height: 20px; border-radius: 9999px; pointer-events: none; z-index: 2147483646; border: 3px solid rgba(37, 99, 235, 0.75); box-shadow: 0 0 0 1px rgba(255,255,255,0.45) inset; transform: translate(-50%, -50%) scale(0.55); opacity: 0; }',
54
+ '#__ak_cursor_click_pulse__.__ak_active { animation: __ak_cursor_pulse__ 340ms cubic-bezier(0.16, 1, 0.3, 1) forwards; }',
55
+ '@keyframes __ak_cursor_pulse__ { 0% { opacity: 0.95; transform: translate(-50%, -50%) scale(0.55); } 100% { opacity: 0; transform: translate(-50%, -50%) scale(2.6); } }',
56
+ ].join('\\n');
57
+ document.head.appendChild(style);
58
+
59
+ const cursor = document.createElement('div');
60
+ cursor.id = '__ak_cursor__';
61
+ cursor.dataset.theme = cursorTheme;
62
+ cursor.style.cssText = [
63
+ 'position: fixed',
64
+ 'top: -100px',
65
+ 'left: -100px',
66
+ 'width: 20px',
67
+ 'height: 20px',
68
+ 'background: rgba(255, 255, 255, 0.95)',
69
+ 'border: 2.5px solid rgba(0, 0, 0, 0.8)',
70
+ 'border-radius: 50%',
71
+ 'pointer-events: none',
72
+ 'z-index: 2147483647',
73
+ 'transform: translate(-50%, -50%)',
74
+ 'box-shadow: 0 2px 8px rgba(0,0,0,0.4)',
75
+ 'transition: transform 0.09s ease, box-shadow 0.12s ease, background 0.12s ease, border-color 0.12s ease',
76
+ 'will-change: left, top',
77
+ ].join(';');
78
+ if (cursorSvg) cursor.innerHTML = cursorSvg;
79
+
80
+ const pulse = document.createElement('div');
81
+ pulse.id = '__ak_cursor_click_pulse__';
82
+
83
+ document.body.appendChild(cursor);
84
+ document.body.appendChild(pulse);
85
+
86
+ let pulseResetTimer = null;
87
+
88
+ function setCursorPosition(x, y) {
89
+ cursor.style.left = x + 'px';
90
+ cursor.style.top = y + 'px';
91
+ pulse.style.left = x + 'px';
92
+ pulse.style.top = y + 'px';
93
+ }
94
+
95
+ function triggerPulse() {
96
+ pulse.classList.remove('__ak_active');
97
+ void pulse.offsetWidth;
98
+ pulse.classList.add('__ak_active');
99
+ if (pulseResetTimer) clearTimeout(pulseResetTimer);
100
+ pulseResetTimer = setTimeout(function() {
101
+ pulse.classList.remove('__ak_active');
102
+ }, 380);
103
+ }
104
+
105
+ // CDP mouse events (page.mouse.move) don't fire DOM mousemove events in
106
+ // Playwright video recording. Expose global helpers so the runner can
107
+ // position the cursor directly via page.evaluate().
108
+ window.__akMoveCursor = function(x, y) { setCursorPosition(x, y); };
109
+ window.__akPressCursor = function() { cursor.classList.add('__ak_pressed'); };
110
+ window.__akReleaseCursor = function() { cursor.classList.remove('__ak_pressed'); };
111
+ window.__akClickPulse = function(x, y) {
112
+ setCursorPosition(x, y);
113
+ triggerPulse();
114
+ };
115
+
116
+ // Keep DOM event listeners as fallback for real mouse events (headed mode)
117
+ document.addEventListener('mousemove', function(e) {
118
+ setCursorPosition(e.clientX, e.clientY);
119
+ }, { passive: true });
120
+
121
+ window.addEventListener('mousedown', function(e) {
122
+ setCursorPosition(e.clientX, e.clientY);
123
+ cursor.classList.add('__ak_pressed');
124
+ triggerPulse();
125
+ }, true);
126
+ window.addEventListener('mouseup', function(e) {
127
+ setCursorPosition(e.clientX, e.clientY);
128
+ cursor.classList.remove('__ak_pressed');
129
+ }, true);
130
+ window.addEventListener('click', function(e) {
131
+ setCursorPosition(e.clientX, e.clientY);
132
+ triggerPulse();
133
+ }, true);
134
+ }
135
+
136
+ // Inject immediately and re-inject if a framework (React, Next.js, etc.)
137
+ // replaces the body during hydration and removes our cursor element.
138
+ function ensureCursor() {
139
+ if (!document.getElementById('__ak_cursor__')) {
140
+ if (document.body) injectCursor();
141
+ }
142
+ }
143
+
144
+ if (document.readyState === 'loading') {
145
+ document.addEventListener('DOMContentLoaded', ensureCursor);
146
+ } else {
147
+ ensureCursor();
148
+ }
149
+
150
+ // Re-inject when frameworks replace body content during hydration.
151
+ var observer = new MutationObserver(function() {
152
+ if (document.body && !document.getElementById('__ak_cursor__')) {
153
+ injectCursor();
154
+ }
155
+ });
156
+ function startObserving() {
157
+ if (document.body) {
158
+ observer.observe(document.body, { childList: true });
159
+ } else {
160
+ document.addEventListener('DOMContentLoaded', function() {
161
+ observer.observe(document.body, { childList: true });
162
+ });
163
+ }
164
+ }
165
+ startObserving();
166
+ })();
167
+ `;
168
+ }
169
+ //# sourceMappingURL=cursor-overlay-script.js.map
@@ -0,0 +1,65 @@
1
+ /**
2
+ * DOM CSS Purger — AUT-121 Interactive Demos, Phase 3
3
+ *
4
+ * Walks captured HTML, collects every tag/class/id present in the DOM, then
5
+ * walks each inline `<style>` block and drops CSS rules whose selectors
6
+ * never match any element. Designed to shrink captured DOMs by 60-80% per
7
+ * the Linear estimate.
8
+ *
9
+ * Conservative on purpose — better to keep a few unused bytes than break a
10
+ * captured layout. Specifically, the purger PRESERVES:
11
+ * - All at-rules: @media, @supports, @keyframes, @font-face, @import,
12
+ * @charset, @namespace, @page (passed through unchanged for the rules
13
+ * inside @media/@supports, recursively pruned)
14
+ * - Selectors that only contain pseudo-classes (`:hover`, `:focus`, etc.)
15
+ * since they may match elements only in interactive states
16
+ * - Universal selector `*`
17
+ * - Attribute selectors (parsed but not validated against the DOM —
18
+ * `[data-state]` would require a DOM walk to verify, kept for safety)
19
+ *
20
+ * For Phase 3 minimum viable, only inline `<style>` blocks are purged.
21
+ * External `<link rel="stylesheet">` files would require server-side
22
+ * fetching of the asset bytes — that's left to a follow-up.
23
+ *
24
+ * No regex CSS parser is perfect, but the trade-off is:
25
+ * - dependency-free (we already pay for parse5 in dom-serializer)
26
+ * - small footprint (~150 LOC)
27
+ * - good enough for the 95% of CSS that captures produce
28
+ *
29
+ * Worst case: a malformed CSS block is left untouched.
30
+ */
31
+ export interface PurgeStats {
32
+ /** Number of `<style>` blocks processed */
33
+ blocks: number;
34
+ /** Bytes of CSS before purging */
35
+ preBytes: number;
36
+ /** Bytes of CSS after purging */
37
+ postBytes: number;
38
+ /** Number of rules removed */
39
+ rulesRemoved: number;
40
+ }
41
+ export interface PurgeResult {
42
+ html: string;
43
+ stats: PurgeStats;
44
+ }
45
+ /**
46
+ * Walk an HTML document, find every `<style>` block, and purge each one
47
+ * against the set of tags/classes/ids actually present in the document.
48
+ */
49
+ export declare function purgeInlineStyleBlocks(html: string): PurgeResult;
50
+ interface DomPresence {
51
+ tags: Set<string>;
52
+ classes: Set<string>;
53
+ ids: Set<string>;
54
+ }
55
+ interface PurgedCss {
56
+ css: string;
57
+ removed: number;
58
+ }
59
+ /**
60
+ * Tokenize CSS into a flat sequence of `at-rule` / `rule` blocks and walk
61
+ * each rule to decide whether to keep it. At-rules are preserved verbatim
62
+ * — `@media`/`@supports` bodies are recursively purged.
63
+ */
64
+ export declare function purgeCss(input: string, presence: DomPresence): PurgedCss;
65
+ export {};