autokap 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) 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 +607 -0
  4. package/assets/skill/README.md +39 -0
  5. package/assets/skill/SKILL.md +453 -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 +164 -0
  26. package/dist/benchmark.d.ts +59 -0
  27. package/dist/benchmark.js +135 -0
  28. package/dist/browser-bar.d.ts +14 -6
  29. package/dist/browser-bar.js +145 -8
  30. package/dist/browser-pool.d.ts +7 -0
  31. package/dist/browser-pool.js +15 -5
  32. package/dist/browser-utils.d.ts +31 -0
  33. package/dist/browser-utils.js +97 -0
  34. package/dist/browser.d.ts +51 -1
  35. package/dist/browser.js +1481 -31
  36. package/dist/capture-alt-text.js +2 -1
  37. package/dist/capture-language-preflight.js +14 -0
  38. package/dist/capture-llm-page-identity.js +22 -10
  39. package/dist/capture-page-identity.d.ts +5 -7
  40. package/dist/capture-page-identity.js +211 -78
  41. package/dist/capture-preset-credentials.d.ts +50 -0
  42. package/dist/capture-preset-credentials.js +127 -0
  43. package/dist/capture-request-plan.d.ts +2 -2
  44. package/dist/capture-request-plan.js +64 -16
  45. package/dist/capture-run-optimizer.js +48 -33
  46. package/dist/capture-selector-memory.d.ts +5 -0
  47. package/dist/capture-selector-memory.js +18 -0
  48. package/dist/capture-strategy.d.ts +36 -0
  49. package/dist/capture-strategy.js +95 -0
  50. package/dist/capture-studio-sync.d.ts +1 -0
  51. package/dist/capture-studio-sync.js +9 -3
  52. package/dist/capture-surface-contract.d.ts +36 -0
  53. package/dist/capture-surface-contract.js +299 -0
  54. package/dist/capture-transition-engine.d.ts +28 -0
  55. package/dist/capture-transition-engine.js +292 -0
  56. package/dist/capture-variant-state.d.ts +2 -0
  57. package/dist/capture-variant-state.js +26 -0
  58. package/dist/capture-verification.d.ts +35 -0
  59. package/dist/capture-verification.js +95 -0
  60. package/dist/capture-viewport-lock.d.ts +48 -0
  61. package/dist/capture-viewport-lock.js +74 -0
  62. package/dist/circuit-breaker.d.ts +42 -0
  63. package/dist/circuit-breaker.js +119 -0
  64. package/dist/cli-config.d.ts +8 -1
  65. package/dist/cli-config.js +62 -6
  66. package/dist/cli-contract.d.ts +15 -0
  67. package/dist/cli-contract.js +167 -0
  68. package/dist/cli-runner-local.d.ts +12 -0
  69. package/dist/cli-runner-local.js +102 -0
  70. package/dist/cli-runner.d.ts +34 -0
  71. package/dist/cli-runner.js +433 -0
  72. package/dist/cli-utils.d.ts +0 -1
  73. package/dist/cli-utils.js +2 -5
  74. package/dist/cli.js +1005 -267
  75. package/dist/clip-orchestrator.js +9 -2
  76. package/dist/clip-postprocess.js +25 -16
  77. package/dist/cookie-dismiss.d.ts +2 -0
  78. package/dist/cookie-dismiss.js +48 -13
  79. package/dist/cost-logging.d.ts +8 -0
  80. package/dist/cost-logging.js +160 -46
  81. package/dist/cost-resolution-monitor.d.ts +16 -0
  82. package/dist/cost-resolution-monitor.js +34 -0
  83. package/dist/credential-templates.js +2 -2
  84. package/dist/cursor-overlay-script.d.ts +6 -0
  85. package/dist/cursor-overlay-script.js +169 -0
  86. package/dist/dom-css-purger.d.ts +65 -0
  87. package/dist/dom-css-purger.js +333 -0
  88. package/dist/dom-font-inliner.d.ts +45 -0
  89. package/dist/dom-font-inliner.js +148 -0
  90. package/dist/dom-patch-resolver.d.ts +52 -0
  91. package/dist/dom-patch-resolver.js +242 -0
  92. package/dist/dom-serializer.d.ts +82 -0
  93. package/dist/dom-serializer.js +378 -0
  94. package/dist/element-capture.d.ts +1 -41
  95. package/dist/element-capture.js +202 -446
  96. package/dist/env-validation.d.ts +5 -0
  97. package/dist/env-validation.js +29 -0
  98. package/dist/execution-schema.d.ts +4423 -0
  99. package/dist/execution-schema.js +507 -0
  100. package/dist/execution-types.d.ts +886 -0
  101. package/dist/execution-types.js +65 -0
  102. package/dist/fonts-loader.d.ts +14 -0
  103. package/dist/fonts-loader.js +55 -0
  104. package/dist/hybrid-navigator.js +12 -12
  105. package/dist/index.d.ts +9 -6
  106. package/dist/index.js +10 -4
  107. package/dist/legacy/agent-action-recovery.d.ts +45 -0
  108. package/dist/legacy/agent-action-recovery.js +370 -0
  109. package/dist/legacy/agent-message-utils.d.ts +21 -0
  110. package/dist/legacy/agent-message-utils.js +77 -0
  111. package/dist/legacy/agent-url-utils.d.ts +30 -0
  112. package/dist/legacy/agent-url-utils.js +138 -0
  113. package/dist/legacy/agent.d.ts +226 -0
  114. package/dist/legacy/agent.js +6666 -0
  115. package/dist/legacy/clip-orchestrator.d.ts +148 -0
  116. package/dist/legacy/clip-orchestrator.js +957 -0
  117. package/dist/legacy/credential-templates.d.ts +5 -0
  118. package/dist/legacy/credential-templates.js +60 -0
  119. package/dist/legacy/hybrid-navigator.d.ts +138 -0
  120. package/dist/legacy/hybrid-navigator.js +468 -0
  121. package/dist/legacy/llm-usage.d.ts +17 -0
  122. package/dist/legacy/llm-usage.js +45 -0
  123. package/dist/legacy/prompt-cache.d.ts +10 -0
  124. package/dist/legacy/prompt-cache.js +24 -0
  125. package/dist/legacy/prompts.d.ts +175 -0
  126. package/dist/legacy/prompts.js +1038 -0
  127. package/dist/legacy/tools.d.ts +4 -0
  128. package/dist/legacy/tools.js +216 -0
  129. package/dist/legacy/video-agent.d.ts +143 -0
  130. package/dist/legacy/video-agent.js +4788 -0
  131. package/dist/legacy/video-observation.d.ts +36 -0
  132. package/dist/legacy/video-observation.js +192 -0
  133. package/dist/legacy/video-planner.d.ts +12 -0
  134. package/dist/legacy/video-planner.js +501 -0
  135. package/dist/legacy/video-prompts.d.ts +37 -0
  136. package/dist/legacy/video-prompts.js +569 -0
  137. package/dist/legacy/video-tools.d.ts +3 -0
  138. package/dist/legacy/video-tools.js +59 -0
  139. package/dist/legacy/video-variant-state.d.ts +29 -0
  140. package/dist/legacy/video-variant-state.js +80 -0
  141. package/dist/legacy/vision-model.d.ts +17 -0
  142. package/dist/legacy/vision-model.js +74 -0
  143. package/dist/llm-healer.d.ts +63 -0
  144. package/dist/llm-healer.js +166 -0
  145. package/dist/llm-provider.d.ts +29 -0
  146. package/dist/llm-provider.js +80 -0
  147. package/dist/logger.d.ts +6 -2
  148. package/dist/logger.js +15 -1
  149. package/dist/mockup-html.js +35 -25
  150. package/dist/mockup.d.ts +95 -2
  151. package/dist/mockup.js +427 -166
  152. package/dist/mouse-animation.d.ts +2 -2
  153. package/dist/mouse-animation.js +34 -20
  154. package/dist/opcode-actions.d.ts +42 -0
  155. package/dist/opcode-actions.js +511 -0
  156. package/dist/opcode-runner.d.ts +51 -0
  157. package/dist/opcode-runner.js +770 -0
  158. package/dist/openrouter-client.d.ts +40 -0
  159. package/dist/openrouter-client.js +16 -0
  160. package/dist/overlay-engine.d.ts +24 -0
  161. package/dist/overlay-engine.js +176 -0
  162. package/dist/postcondition.d.ts +16 -0
  163. package/dist/postcondition.js +269 -0
  164. package/dist/program-patcher.d.ts +25 -0
  165. package/dist/program-patcher.js +44 -0
  166. package/dist/prompts.d.ts +13 -5
  167. package/dist/prompts.js +224 -351
  168. package/dist/provider-config.d.ts +12 -0
  169. package/dist/provider-config.js +15 -0
  170. package/dist/recovery-chain.d.ts +37 -0
  171. package/dist/recovery-chain.js +350 -0
  172. package/dist/remote-browser.d.ts +28 -4
  173. package/dist/remote-browser.js +60 -5
  174. package/dist/safari-browser-bar.d.ts +15 -0
  175. package/dist/safari-browser-bar.js +95 -0
  176. package/dist/safari-toolbar-asset.d.ts +15 -0
  177. package/dist/safari-toolbar-asset.js +12 -0
  178. package/dist/security.d.ts +2 -1
  179. package/dist/security.js +49 -10
  180. package/dist/selector-resolver.d.ts +34 -0
  181. package/dist/selector-resolver.js +181 -0
  182. package/dist/semantic-resolver.d.ts +35 -0
  183. package/dist/semantic-resolver.js +161 -0
  184. package/dist/server-capture-runtime.d.ts +5 -3
  185. package/dist/server-capture-runtime.js +42 -95
  186. package/dist/server-credit-usage.d.ts +2 -2
  187. package/dist/server-project-webhooks.d.ts +15 -1
  188. package/dist/server-project-webhooks.js +34 -8
  189. package/dist/server-screenshot-watermark.js +27 -5
  190. package/dist/session-profile.js +164 -1
  191. package/dist/sf-pro-symbols.d.ts +1 -0
  192. package/dist/sf-pro-symbols.js +55 -0
  193. package/dist/skill-packaging.d.ts +28 -0
  194. package/dist/skill-packaging.js +169 -0
  195. package/dist/smart-wait.d.ts +27 -0
  196. package/dist/smart-wait.js +81 -0
  197. package/dist/status-bar-render.d.ts +20 -0
  198. package/dist/status-bar-render.js +410 -0
  199. package/dist/status-bar.d.ts +9 -0
  200. package/dist/status-bar.js +298 -14
  201. package/dist/svg-browser-bar.d.ts +33 -0
  202. package/dist/svg-browser-bar.js +206 -0
  203. package/dist/svg-status-bar.d.ts +36 -0
  204. package/dist/svg-status-bar.js +597 -0
  205. package/dist/svg-text.d.ts +61 -0
  206. package/dist/svg-text.js +118 -0
  207. package/dist/tools.js +89 -451
  208. package/dist/types.d.ts +240 -5
  209. package/dist/types.js +23 -1
  210. package/dist/v2/action-verifier.d.ts +29 -0
  211. package/dist/v2/action-verifier.js +133 -0
  212. package/dist/v2/alt-text.d.ts +26 -0
  213. package/dist/v2/alt-text.js +55 -0
  214. package/dist/v2/benchmark.d.ts +59 -0
  215. package/dist/v2/benchmark.js +135 -0
  216. package/dist/v2/capture-strategy.d.ts +30 -0
  217. package/dist/v2/capture-strategy.js +67 -0
  218. package/dist/v2/capture-verification.d.ts +35 -0
  219. package/dist/v2/capture-verification.js +95 -0
  220. package/dist/v2/circuit-breaker.d.ts +42 -0
  221. package/dist/v2/circuit-breaker.js +119 -0
  222. package/dist/v2/cli-runner-local.d.ts +11 -0
  223. package/dist/v2/cli-runner-local.js +91 -0
  224. package/dist/v2/cli-runner.d.ts +34 -0
  225. package/dist/v2/cli-runner.js +300 -0
  226. package/dist/v2/compiler-prompts.d.ts +27 -0
  227. package/dist/v2/compiler-prompts.js +123 -0
  228. package/dist/v2/compiler.d.ts +37 -0
  229. package/dist/v2/compiler.js +147 -0
  230. package/dist/v2/explorer.d.ts +41 -0
  231. package/dist/v2/explorer.js +56 -0
  232. package/dist/v2/index.d.ts +37 -0
  233. package/dist/v2/index.js +31 -0
  234. package/dist/v2/llm-healer.d.ts +62 -0
  235. package/dist/v2/llm-healer.js +166 -0
  236. package/dist/v2/llm-provider.d.ts +29 -0
  237. package/dist/v2/llm-provider.js +80 -0
  238. package/dist/v2/opcode-runner.d.ts +47 -0
  239. package/dist/v2/opcode-runner.js +634 -0
  240. package/dist/v2/overlay-engine.d.ts +24 -0
  241. package/dist/v2/overlay-engine.js +150 -0
  242. package/dist/v2/postcondition.d.ts +16 -0
  243. package/dist/v2/postcondition.js +249 -0
  244. package/dist/v2/program-patcher.d.ts +25 -0
  245. package/dist/v2/program-patcher.js +44 -0
  246. package/dist/v2/recovery-chain.d.ts +30 -0
  247. package/dist/v2/recovery-chain.js +368 -0
  248. package/dist/v2/schema.d.ts +2580 -0
  249. package/dist/v2/schema.js +295 -0
  250. package/dist/v2/selector-resolver.d.ts +34 -0
  251. package/dist/v2/selector-resolver.js +181 -0
  252. package/dist/v2/semantic-resolver.d.ts +35 -0
  253. package/dist/v2/semantic-resolver.js +161 -0
  254. package/dist/v2/smart-wait.d.ts +27 -0
  255. package/dist/v2/smart-wait.js +81 -0
  256. package/dist/v2/types.d.ts +444 -0
  257. package/dist/v2/types.js +19 -0
  258. package/dist/v2/web-playwright-local.d.ts +69 -0
  259. package/dist/v2/web-playwright-local.js +392 -0
  260. package/dist/version.d.ts +1 -0
  261. package/dist/version.js +5 -0
  262. package/dist/video-agent.js +18 -13
  263. package/dist/video-planner.js +2 -1
  264. package/dist/video-prompts.js +3 -3
  265. package/dist/web-playwright-local.d.ts +126 -0
  266. package/dist/web-playwright-local.js +819 -0
  267. package/dist/ws-auth.js +4 -1
  268. package/dist/ws-broadcast.d.ts +34 -0
  269. package/dist/ws-broadcast.js +85 -0
  270. package/dist/ws-connection-limits.d.ts +12 -0
  271. package/dist/ws-connection-limits.js +44 -0
  272. package/dist/ws-handler-utils.d.ts +32 -0
  273. package/dist/ws-handler-utils.js +139 -0
  274. package/dist/ws-handler.js +294 -164
  275. package/dist/ws-metrics-server.d.ts +9 -0
  276. package/dist/ws-metrics-server.js +31 -0
  277. package/dist/ws-server.js +41 -1
  278. package/package.json +51 -34
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Capture Agent — Overlay Engine
3
+ *
4
+ * Consolidated deterministic overlay handling.
5
+ * Wraps and extends the existing cookie-dismiss module with
6
+ * additional patterns for newsletter popups, chat widgets, and age gates.
7
+ *
8
+ * This module is used by the DISMISS_OVERLAYS opcode.
9
+ */
10
+ /**
11
+ * Multi-pass overlay dismissal.
12
+ * 1. Delegate to the adapter's built-in dismissOverlays (cookie-dismiss.ts)
13
+ * 2. Check AKTree for remaining blocking overlays
14
+ * 3. Try additional heuristics for newsletter/chat/age gate
15
+ * 4. Final AKTree check
16
+ */
17
+ export async function dismissAllOverlays(adapter) {
18
+ const methods = [];
19
+ let totalFound = 0;
20
+ // Pass 1: Built-in cookie/widget dismissal
21
+ const cookieResult = await adapter.dismissOverlays();
22
+ if (cookieResult.dismissed) {
23
+ methods.push(cookieResult.method ?? 'cookie-dismiss');
24
+ }
25
+ // Check remaining overlays
26
+ let tree = await adapter.getAKTree();
27
+ const blocking = tree.overlays.filter(o => o.blocksInteraction);
28
+ totalFound = tree.overlays.length;
29
+ if (blocking.length === 0) {
30
+ return { dismissed: methods.length > 0, methods, overlaysFound: totalFound, overlaysRemaining: 0 };
31
+ }
32
+ // Pass 2: Try Escape key to dismiss modals/popups
33
+ try {
34
+ await adapter.pressKey('Escape');
35
+ await sleep(300);
36
+ tree = await adapter.getAKTree();
37
+ const remaining = tree.overlays.filter(o => o.blocksInteraction);
38
+ if (remaining.length < blocking.length) {
39
+ methods.push('escape-key');
40
+ }
41
+ if (remaining.length === 0) {
42
+ return { dismissed: true, methods, overlaysFound: totalFound, overlaysRemaining: 0 };
43
+ }
44
+ }
45
+ catch {
46
+ // Non-fatal
47
+ }
48
+ // Pass 3: Try clicking common close patterns in AKTree
49
+ const closePatterns = [
50
+ 'close', 'dismiss', 'fermer', 'schließen', 'cerrar', 'chiudi',
51
+ 'no thanks', 'non merci', 'maybe later', 'not now', 'skip',
52
+ ];
53
+ for (const overlay of tree.overlays) {
54
+ if (!overlay.blocksInteraction)
55
+ continue;
56
+ // Look for close buttons within the overlay's subtree
57
+ const closeNode = findCloseButton(tree, overlay.nodeId, closePatterns);
58
+ if (closeNode) {
59
+ try {
60
+ // Build selector from the close node's sourceRef
61
+ const selector = buildSelectorFromSourceRef(closeNode.sourceRef);
62
+ if (selector) {
63
+ await adapter.click(selector);
64
+ methods.push(`close-button:${selector}`);
65
+ await sleep(300);
66
+ }
67
+ }
68
+ catch {
69
+ // Continue to next overlay
70
+ }
71
+ }
72
+ }
73
+ // Final check
74
+ tree = await adapter.getAKTree();
75
+ const finalBlocking = tree.overlays.filter(o => o.blocksInteraction);
76
+ return {
77
+ dismissed: methods.length > 0,
78
+ methods,
79
+ overlaysFound: totalFound,
80
+ overlaysRemaining: finalBlocking.length,
81
+ };
82
+ }
83
+ function findCloseButton(tree, overlayNodeId, patterns) {
84
+ // Find the overlay node first
85
+ const overlayNode = findNodeById(tree.root, overlayNodeId);
86
+ if (!overlayNode)
87
+ return null;
88
+ // Search for interactive close-like buttons within this subtree
89
+ let best = null;
90
+ function walk(node) {
91
+ if (node.visible && node.interactive) {
92
+ const label = node.label.toLowerCase();
93
+ const ref = node.sourceRef.toLowerCase();
94
+ const combined = label + ' ' + ref;
95
+ for (const pattern of patterns) {
96
+ if (combined.includes(pattern)) {
97
+ // Prefer buttons over links, and shorter labels over longer ones
98
+ if (!best || (node.type === 'button' && best.type !== 'button') || node.label.length < best.label.length) {
99
+ best = node;
100
+ }
101
+ break;
102
+ }
103
+ }
104
+ // Also match aria-label="close" or title="close" in sourceRef
105
+ if (ref.includes('aria-label="close"') || ref.includes('title="close"') || ref.includes('class="close"')) {
106
+ if (!best)
107
+ best = node;
108
+ }
109
+ }
110
+ node.children.forEach(walk);
111
+ }
112
+ walk(overlayNode);
113
+ return best;
114
+ }
115
+ function findNodeById(node, id) {
116
+ if (node.id === id)
117
+ return node;
118
+ for (const child of node.children) {
119
+ const found = findNodeById(child, id);
120
+ if (found)
121
+ return found;
122
+ }
123
+ return null;
124
+ }
125
+ function buildSelectorFromSourceRef(sourceRef) {
126
+ // Extract data-testid
127
+ const testIdMatch = sourceRef.match(/data-testid="([^"]+)"/);
128
+ if (testIdMatch)
129
+ return `[data-testid="${testIdMatch[1]}"]`;
130
+ // Extract id
131
+ const idMatch = sourceRef.match(/ id="([^"]+)"/);
132
+ if (idMatch)
133
+ return `#${idMatch[1]}`;
134
+ // Extract aria-label
135
+ const ariaMatch = sourceRef.match(/aria-label="([^"]+)"/);
136
+ if (ariaMatch)
137
+ return `[aria-label="${ariaMatch[1]}"]`;
138
+ // Extract class-based close button
139
+ const classMatch = sourceRef.match(/class="([^"]*close[^"]*)"/);
140
+ if (classMatch) {
141
+ const tagMatch = sourceRef.match(/^<(\w+)/);
142
+ const tag = tagMatch?.[1] ?? 'button';
143
+ return `${tag}.${classMatch[1].split(/\s+/).find(c => c.includes('close'))}`;
144
+ }
145
+ return null;
146
+ }
147
+ function sleep(ms) {
148
+ return new Promise(resolve => setTimeout(resolve, ms));
149
+ }
150
+ //# sourceMappingURL=overlay-engine.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Capture Agent — Postcondition Evaluator
3
+ *
4
+ * Deterministic evaluation of postconditions after each opcode.
5
+ * No LLM calls — purely structural checks against AKTree, URL, and screenshots.
6
+ */
7
+ import type { RuntimeAdapter, PostconditionSpec } from './types.js';
8
+ /**
9
+ * Evaluates whether a postcondition holds.
10
+ * Retries internally up to postcondition.waitMs (polling).
11
+ * Returns true if the condition is satisfied, false otherwise.
12
+ */
13
+ export declare function evaluatePostcondition(adapter: RuntimeAdapter, spec: PostconditionSpec): Promise<{
14
+ passed: boolean;
15
+ reason: string;
16
+ }>;
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Capture Agent — Postcondition Evaluator
3
+ *
4
+ * Deterministic evaluation of postconditions after each opcode.
5
+ * No LLM calls — purely structural checks against AKTree, URL, and screenshots.
6
+ */
7
+ import { serializeAKTree } from '../ak-tree.js';
8
+ /**
9
+ * Evaluates whether a postcondition holds.
10
+ * Retries internally up to postcondition.waitMs (polling).
11
+ * Returns true if the condition is satisfied, false otherwise.
12
+ */
13
+ export async function evaluatePostcondition(adapter, spec) {
14
+ const maxWait = spec.waitMs ?? 5000;
15
+ const pollInterval = 500;
16
+ const deadline = Date.now() + maxWait;
17
+ // 'always' postcondition always passes immediately
18
+ if (spec.type === 'always') {
19
+ return { passed: true, reason: 'always passes' };
20
+ }
21
+ while (Date.now() < deadline) {
22
+ const result = await checkOnce(adapter, spec);
23
+ if (result.passed)
24
+ return result;
25
+ const remaining = deadline - Date.now();
26
+ if (remaining <= 0)
27
+ break;
28
+ await sleep(Math.min(pollInterval, remaining));
29
+ }
30
+ // Final check after timeout
31
+ return checkOnce(adapter, spec);
32
+ }
33
+ async function checkOnce(adapter, spec) {
34
+ switch (spec.type) {
35
+ case 'route_matches':
36
+ return checkRouteMatches(adapter, spec.pattern);
37
+ case 'element_visible':
38
+ return checkElementVisible(adapter, spec.selector);
39
+ case 'element_absent':
40
+ return checkElementAbsent(adapter, spec.selector);
41
+ case 'text_contains':
42
+ return checkTextContains(adapter, spec.selector, spec.text);
43
+ case 'overlay_dismissed':
44
+ return checkOverlayDismissed(adapter);
45
+ case 'screenshot_stable':
46
+ return checkScreenshotStable(adapter, spec.threshold ?? 0.01);
47
+ case 'any_change':
48
+ // 'any_change' is a soft postcondition — we just assume the action did something.
49
+ // The action-verifier handles real change detection via AKTree diff.
50
+ return { passed: true, reason: 'any_change always passes (action verifier handles real detection)' };
51
+ case 'always':
52
+ return { passed: true, reason: 'always passes' };
53
+ default:
54
+ return { passed: false, reason: `unknown postcondition type: ${spec.type}` };
55
+ }
56
+ }
57
+ // ── Individual checks ───────────────────────────────────────────────
58
+ async function checkRouteMatches(adapter, pattern) {
59
+ const url = await adapter.getCurrentUrl();
60
+ try {
61
+ const { pathname, search } = new URL(url);
62
+ const fullPath = pathname + search;
63
+ // Support glob-like patterns: * matches anything, ** matches path segments
64
+ const regexStr = pattern
65
+ .replace(/\*\*/g, '.*')
66
+ .replace(/\*/g, '[^/]*')
67
+ .replace(/\?/g, '[^/]');
68
+ const regex = new RegExp(`^${regexStr}$`);
69
+ if (regex.test(fullPath) || regex.test(pathname)) {
70
+ return { passed: true, reason: `URL "${fullPath}" matches pattern "${pattern}"` };
71
+ }
72
+ return { passed: false, reason: `URL "${fullPath}" does not match pattern "${pattern}"` };
73
+ }
74
+ catch {
75
+ return { passed: false, reason: `invalid URL "${url}" or pattern "${pattern}"` };
76
+ }
77
+ }
78
+ async function checkElementVisible(adapter, selector) {
79
+ // Primary check: use Playwright waitFor (fast, reliable)
80
+ try {
81
+ const found = await adapter.waitFor({ selector, state: 'visible', timeoutMs: 2000 });
82
+ if (found) {
83
+ return { passed: true, reason: `element "${selector}" is visible (Playwright)` };
84
+ }
85
+ }
86
+ catch {
87
+ // Fall through to AKTree check
88
+ }
89
+ // Fallback: check AKTree
90
+ try {
91
+ const tree = await adapter.getAKTree();
92
+ if (hasVisibleNodeWithSelector(tree, selector)) {
93
+ return { passed: true, reason: `element "${selector}" is visible in AKTree` };
94
+ }
95
+ const serialized = serializeAKTree(tree);
96
+ if (serialized.includes(selector.replace(/[[\]"]/g, ''))) {
97
+ return { passed: true, reason: `element pattern "${selector}" found in serialized AKTree` };
98
+ }
99
+ return { passed: false, reason: `element "${selector}" not visible` };
100
+ }
101
+ catch {
102
+ return { passed: false, reason: `element "${selector}" not verifiable (AKTree unavailable)` };
103
+ }
104
+ }
105
+ async function checkElementAbsent(adapter, selector) {
106
+ // Use Playwright: if waitFor fails (element not found), it's absent = good
107
+ try {
108
+ const found = await adapter.waitFor({ selector, state: 'visible', timeoutMs: 1000 });
109
+ if (found) {
110
+ return { passed: false, reason: `element "${selector}" is still visible` };
111
+ }
112
+ return { passed: true, reason: `element "${selector}" is absent` };
113
+ }
114
+ catch {
115
+ return { passed: true, reason: `element "${selector}" is absent` };
116
+ }
117
+ }
118
+ async function checkTextContains(adapter, selector, expectedText) {
119
+ try {
120
+ const tree = await adapter.getAKTree();
121
+ const node = findNodeBySelector(tree, selector);
122
+ if (!node) {
123
+ return { passed: false, reason: `element "${selector}" not found for text check` };
124
+ }
125
+ const nodeText = (node.label || '') + (node.value || '');
126
+ if (nodeText.includes(expectedText)) {
127
+ return { passed: true, reason: `element "${selector}" contains "${expectedText}"` };
128
+ }
129
+ return { passed: false, reason: `element "${selector}" text "${nodeText}" does not contain "${expectedText}"` };
130
+ }
131
+ catch (err) {
132
+ return { passed: false, reason: `error checking text: ${err}` };
133
+ }
134
+ }
135
+ async function checkOverlayDismissed(adapter) {
136
+ try {
137
+ const tree = await adapter.getAKTree();
138
+ // Check if any overlays are reported in the tree
139
+ if (tree.overlays.length === 0) {
140
+ return { passed: true, reason: 'no overlays detected' };
141
+ }
142
+ // Check if remaining overlays are blocking
143
+ const blocking = tree.overlays.filter(o => o.blocksInteraction);
144
+ if (blocking.length === 0) {
145
+ return { passed: true, reason: 'overlays present but none blocking interaction' };
146
+ }
147
+ return { passed: false, reason: `${blocking.length} blocking overlay(s) still present` };
148
+ }
149
+ catch {
150
+ // If AKTree is unavailable (e.g. page.evaluate failure), assume overlays are dismissed.
151
+ // The overlay dismissal itself ran; we just can't verify via AKTree.
152
+ return { passed: true, reason: 'overlay check skipped (AKTree unavailable), assuming dismissed' };
153
+ }
154
+ }
155
+ let lastScreenshotHash = null;
156
+ async function checkScreenshotStable(adapter, threshold) {
157
+ try {
158
+ const screenshot = await adapter.takeScreenshot();
159
+ const currentHash = simpleHash(screenshot);
160
+ if (lastScreenshotHash === null) {
161
+ lastScreenshotHash = currentHash;
162
+ // Wait and take another screenshot
163
+ await sleep(500);
164
+ const screenshot2 = await adapter.takeScreenshot();
165
+ const hash2 = simpleHash(screenshot2);
166
+ lastScreenshotHash = null;
167
+ if (currentHash === hash2) {
168
+ return { passed: true, reason: 'consecutive screenshots are identical' };
169
+ }
170
+ return { passed: false, reason: 'consecutive screenshots differ (page still changing)' };
171
+ }
172
+ // Compare with previous
173
+ if (currentHash === lastScreenshotHash) {
174
+ lastScreenshotHash = null;
175
+ return { passed: true, reason: 'screenshot matches previous' };
176
+ }
177
+ lastScreenshotHash = currentHash;
178
+ return { passed: false, reason: 'screenshot changed from previous check' };
179
+ }
180
+ catch (err) {
181
+ lastScreenshotHash = null;
182
+ return { passed: false, reason: `error checking screenshot stability: ${err}` };
183
+ }
184
+ }
185
+ // ── Helpers ─────────────────────────────────────────────────────────
186
+ function hasVisibleNodeWithSelector(tree, selector) {
187
+ // Walk the AKTree looking for a visible node whose sourceRef matches the selector
188
+ function walk(node) {
189
+ if (node.visible && node.sourceRef && matchesSelectorHeuristic(node.sourceRef, selector)) {
190
+ return true;
191
+ }
192
+ return node.children.some(walk);
193
+ }
194
+ return walk(tree.root);
195
+ }
196
+ function findNodeBySelector(tree, selector) {
197
+ function walk(node) {
198
+ if (node.sourceRef && matchesSelectorHeuristic(node.sourceRef, selector)) {
199
+ return node;
200
+ }
201
+ for (const child of node.children) {
202
+ const found = walk(child);
203
+ if (found)
204
+ return found;
205
+ }
206
+ return null;
207
+ }
208
+ return walk(tree.root);
209
+ }
210
+ /**
211
+ * Heuristic match between an AKTree sourceRef and a CSS-like selector.
212
+ * Not a full CSS selector engine — handles common patterns:
213
+ * - Tag name: "h1", "button"
214
+ * - ID: "#my-id"
215
+ * - data-testid: [data-testid="x"]
216
+ * - Class: ".my-class"
217
+ */
218
+ function matchesSelectorHeuristic(sourceRef, selector) {
219
+ const lower = sourceRef.toLowerCase();
220
+ const selectorLower = selector.toLowerCase();
221
+ // data-testid match
222
+ const testIdMatch = selector.match(/\[data-testid=["'](.+?)["']\]/);
223
+ if (testIdMatch) {
224
+ return lower.includes(`data-testid="${testIdMatch[1]}"`);
225
+ }
226
+ // ID match
227
+ if (selector.startsWith('#')) {
228
+ return lower.includes(`id="${selector.slice(1)}"`) || lower.includes(`#${selector.slice(1)}`);
229
+ }
230
+ // Tag name match
231
+ if (/^[a-z][a-z0-9]*$/i.test(selector)) {
232
+ return lower.startsWith(`<${selectorLower}`) || lower.includes(`<${selectorLower} `);
233
+ }
234
+ // Fallback: contains
235
+ return lower.includes(selectorLower);
236
+ }
237
+ function simpleHash(buffer) {
238
+ // Fast non-crypto hash for screenshot comparison
239
+ let hash = 0;
240
+ const step = Math.max(1, Math.floor(buffer.length / 10000));
241
+ for (let i = 0; i < buffer.length; i += step) {
242
+ hash = ((hash << 5) - hash + buffer[i]) | 0;
243
+ }
244
+ return hash.toString(36);
245
+ }
246
+ function sleep(ms) {
247
+ return new Promise(resolve => setTimeout(resolve, ms));
248
+ }
249
+ //# sourceMappingURL=postcondition.js.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Capture Agent — Program Patcher
3
+ *
4
+ * Applies healer patches to compiled programs.
5
+ * Patches are applied in-memory during the run, and propagated to
6
+ * the server ONLY after a fully successful run.
7
+ */
8
+ import type { ExecutionProgram, HealerPatch } from './types.js';
9
+ /**
10
+ * Applies a healer patch to a program in-place.
11
+ * The original opcode at the given index is replaced by the healer's output.
12
+ * If the healer produced multiple opcodes, subsequent steps are shifted.
13
+ *
14
+ * Returns the modified program (same reference, mutated).
15
+ */
16
+ export declare function applyPatch(program: ExecutionProgram, patch: HealerPatch): ExecutionProgram;
17
+ /**
18
+ * Applies all patches from a successful run to a program.
19
+ * Patches are applied in reverse index order to avoid shifting issues.
20
+ */
21
+ export declare function applyAllPatches(program: ExecutionProgram, patches: HealerPatch[]): ExecutionProgram;
22
+ /**
23
+ * Creates a deep clone of a program for safe patching.
24
+ */
25
+ export declare function cloneProgram(program: ExecutionProgram): ExecutionProgram;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Capture Agent — Program Patcher
3
+ *
4
+ * Applies healer patches to compiled programs.
5
+ * Patches are applied in-memory during the run, and propagated to
6
+ * the server ONLY after a fully successful run.
7
+ */
8
+ /**
9
+ * Applies a healer patch to a program in-place.
10
+ * The original opcode at the given index is replaced by the healer's output.
11
+ * If the healer produced multiple opcodes, subsequent steps are shifted.
12
+ *
13
+ * Returns the modified program (same reference, mutated).
14
+ */
15
+ export function applyPatch(program, patch) {
16
+ const { opcodeIndex, replacementOpcodes } = patch;
17
+ if (opcodeIndex < 0 || opcodeIndex >= program.steps.length) {
18
+ throw new Error(`patch index ${opcodeIndex} out of bounds (program has ${program.steps.length} steps)`);
19
+ }
20
+ // Replace the failed opcode with the replacement(s)
21
+ program.steps.splice(opcodeIndex, 1, ...replacementOpcodes);
22
+ // Bump version
23
+ program.programVersion++;
24
+ return program;
25
+ }
26
+ /**
27
+ * Applies all patches from a successful run to a program.
28
+ * Patches are applied in reverse index order to avoid shifting issues.
29
+ */
30
+ export function applyAllPatches(program, patches) {
31
+ // Sort patches by index descending to apply from end to start
32
+ const sorted = [...patches].sort((a, b) => b.opcodeIndex - a.opcodeIndex);
33
+ for (const patch of sorted) {
34
+ applyPatch(program, patch);
35
+ }
36
+ return program;
37
+ }
38
+ /**
39
+ * Creates a deep clone of a program for safe patching.
40
+ */
41
+ export function cloneProgram(program) {
42
+ return JSON.parse(JSON.stringify(program));
43
+ }
44
+ //# sourceMappingURL=program-patcher.js.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Capture Agent — Recovery Chain
3
+ *
4
+ * Ordered recovery strategies when a deterministic opcode fails:
5
+ * 1. Deterministic retry (same opcode, fresh observation)
6
+ * 2. Selector memory lookup (known-good selectors from Supabase)
7
+ * 3. Alternative interaction (keyboard, JS dispatch, coordinates)
8
+ * 4. Targeted reload (reload page and retry)
9
+ * 5. LLM Healer (last resort)
10
+ */
11
+ import type { ExecutionOpcode, RuntimeAdapter } from './types.js';
12
+ import type { RecoveryChain as IRecoveryChain, RecoveryAttemptResult, RecoveryAttemptOptions } from './opcode-runner.js';
13
+ import { type HealerLLMProvider } from './llm-healer.js';
14
+ export interface RecoveryChainOptions {
15
+ /** Selector memory: stepSignature -> known-good selectors */
16
+ selectorMemory?: Record<string, string[]>;
17
+ /** LLM provider for the healer (optional, disables healer if not provided) */
18
+ llmProvider?: HealerLLMProvider;
19
+ /** Max healer invocations per run. Default: 3 */
20
+ maxHealerInvocations?: number;
21
+ /** Full program steps for healer context */
22
+ programSteps?: ExecutionOpcode[];
23
+ }
24
+ export declare class RecoveryChainImpl implements IRecoveryChain {
25
+ private healer;
26
+ private selectorMemory;
27
+ private programSteps;
28
+ constructor(options?: RecoveryChainOptions);
29
+ attempt(failedOpcode: ExecutionOpcode, opcodeIndex: number, adapter: RuntimeAdapter, options?: RecoveryAttemptOptions): Promise<RecoveryAttemptResult>;
30
+ }