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.
- package/assets/chrome/ios-statusbar-comparison-reference.jpg +0 -0
- package/assets/chrome/ios-statusbar-dark-reference.jpg +0 -0
- package/assets/chrome/ios-statusbar-light-reference.jpg +0 -0
- package/assets/cursors/macos.svg +4 -0
- package/assets/cursors/windows.svg +15 -0
- package/assets/devices/ipad-pro-11-m4.json +52 -0
- package/assets/devices/iphone-16-pro.json +53 -0
- package/assets/devices/macbook-air-13.json +45 -0
- package/assets/frames/MacBook Air 13.svg +242 -0
- package/assets/frames/Status bar - iPhone.png +0 -0
- Menu bar- iPad.png +0 -0
- package/assets/frames/iPad Pro M4 11_.png +0 -0
- package/assets/frames/iPhone 16 Pro.png +0 -0
- package/assets/icons/Cellular Connection.svg +3 -0
- package/assets/icons/Union.svg +6 -0
- package/assets/icons/Wifi.svg +3 -0
- package/assets/icons/battery.svg +5 -0
- package/assets/icons/battery_charging.svg +8 -0
- package/assets/skill/OPCODE-REFERENCE.md +607 -0
- package/assets/skill/README.md +39 -0
- package/assets/skill/SKILL.md +453 -468
- package/assets/skill/STUDIO-SKILL.md +476 -0
- package/assets/skill/references/examples.md +104 -0
- package/assets/skill/references/interactive-demo.md +225 -0
- package/assets/skill/references/mock-data.md +178 -0
- package/dist/abort.d.ts +5 -0
- package/dist/abort.js +44 -0
- package/dist/action-verifier.d.ts +29 -0
- package/dist/action-verifier.js +133 -0
- package/dist/agent-action-recovery.d.ts +45 -0
- package/dist/agent-action-recovery.js +370 -0
- package/dist/agent-message-utils.d.ts +21 -0
- package/dist/agent-message-utils.js +77 -0
- package/dist/agent-url-utils.d.ts +30 -0
- package/dist/agent-url-utils.js +138 -0
- package/dist/agent.d.ts +226 -0
- package/dist/agent.js +6666 -0
- package/dist/ak-tree.d.ts +39 -0
- package/dist/ak-tree.js +368 -0
- package/dist/alt-text.d.ts +26 -0
- package/dist/alt-text.js +55 -0
- package/dist/auth-capture.d.ts +17 -0
- package/dist/auth-capture.js +164 -0
- package/dist/benchmark.d.ts +59 -0
- package/dist/benchmark.js +135 -0
- package/dist/billing-operation-logging.d.ts +38 -0
- package/dist/billing-operation-logging.js +248 -0
- package/dist/browser-bar.d.ts +48 -0
- package/dist/browser-bar.js +284 -0
- package/dist/browser-pool.d.ts +7 -0
- package/dist/browser-pool.js +15 -5
- package/dist/browser-utils.d.ts +31 -0
- package/dist/browser-utils.js +97 -0
- package/dist/browser.d.ts +76 -1
- package/dist/browser.js +1657 -39
- package/dist/capture-alt-text.d.ts +12 -0
- package/dist/capture-alt-text.js +52 -0
- package/dist/capture-encryption.d.ts +10 -0
- package/dist/capture-encryption.js +41 -0
- package/dist/capture-language-preflight.d.ts +41 -0
- package/dist/capture-language-preflight.js +300 -0
- package/dist/capture-llm-page-identity.d.ts +15 -0
- package/dist/capture-llm-page-identity.js +128 -0
- package/dist/capture-model-resolution.d.ts +9 -0
- package/dist/capture-model-resolution.js +21 -0
- package/dist/capture-page-identity.d.ts +7 -0
- package/dist/capture-page-identity.js +352 -0
- package/dist/capture-preset-credentials.d.ts +62 -0
- package/dist/capture-preset-credentials.js +184 -0
- package/dist/capture-request-plan.d.ts +58 -0
- package/dist/capture-request-plan.js +264 -0
- package/dist/capture-run-optimizer.d.ts +139 -0
- package/dist/capture-run-optimizer.js +863 -0
- package/dist/capture-selector-memory.d.ts +31 -0
- package/dist/capture-selector-memory.js +345 -0
- package/dist/capture-session-profile-encryption.d.ts +2 -0
- package/dist/capture-session-profile-encryption.js +22 -0
- package/dist/capture-step-timeout.d.ts +10 -0
- package/dist/capture-step-timeout.js +30 -0
- package/dist/capture-strategy.d.ts +36 -0
- package/dist/capture-strategy.js +95 -0
- package/dist/capture-studio-sync.d.ts +23 -0
- package/dist/capture-studio-sync.js +172 -0
- package/dist/capture-surface-contract.d.ts +36 -0
- package/dist/capture-surface-contract.js +299 -0
- package/dist/capture-transition-engine.d.ts +28 -0
- package/dist/capture-transition-engine.js +292 -0
- package/dist/capture-variant-state.d.ts +56 -0
- package/dist/capture-variant-state.js +182 -0
- package/dist/capture-verification.d.ts +35 -0
- package/dist/capture-verification.js +95 -0
- package/dist/capture-viewport-lock.d.ts +48 -0
- package/dist/capture-viewport-lock.js +74 -0
- package/dist/circuit-breaker.d.ts +42 -0
- package/dist/circuit-breaker.js +119 -0
- package/dist/cli-config.d.ts +8 -1
- package/dist/cli-config.js +62 -6
- package/dist/cli-contract.d.ts +15 -0
- package/dist/cli-contract.js +167 -0
- package/dist/cli-runner-local.d.ts +12 -0
- package/dist/cli-runner-local.js +102 -0
- package/dist/cli-runner.d.ts +34 -0
- package/dist/cli-runner.js +433 -0
- package/dist/cli-utils.d.ts +0 -1
- package/dist/cli-utils.js +2 -5
- package/dist/cli.js +1005 -252
- package/dist/clip-orchestrator.d.ts +148 -0
- package/dist/clip-orchestrator.js +957 -0
- package/dist/clip-postprocess.d.ts +42 -0
- package/dist/clip-postprocess.js +201 -0
- package/dist/cookie-dismiss.d.ts +2 -0
- package/dist/cookie-dismiss.js +48 -13
- package/dist/cost-logging.d.ts +35 -0
- package/dist/cost-logging.js +242 -0
- package/dist/cost-resolution-monitor.d.ts +16 -0
- package/dist/cost-resolution-monitor.js +34 -0
- package/dist/credential-templates.d.ts +5 -0
- package/dist/credential-templates.js +60 -0
- package/dist/cursor-overlay-script.d.ts +6 -0
- package/dist/cursor-overlay-script.js +169 -0
- package/dist/dom-css-purger.d.ts +65 -0
- package/dist/dom-css-purger.js +333 -0
- package/dist/dom-font-inliner.d.ts +45 -0
- package/dist/dom-font-inliner.js +148 -0
- package/dist/dom-patch-resolver.d.ts +52 -0
- package/dist/dom-patch-resolver.js +242 -0
- package/dist/dom-serializer.d.ts +82 -0
- package/dist/dom-serializer.js +378 -0
- package/dist/element-capture.d.ts +13 -0
- package/dist/element-capture.js +522 -0
- package/dist/env-validation.d.ts +5 -0
- package/dist/env-validation.js +29 -0
- package/dist/execution-schema.d.ts +4423 -0
- package/dist/execution-schema.js +507 -0
- package/dist/execution-types.d.ts +886 -0
- package/dist/execution-types.js +65 -0
- package/dist/fonts-loader.d.ts +14 -0
- package/dist/fonts-loader.js +55 -0
- package/dist/hybrid-navigator.d.ts +138 -0
- package/dist/hybrid-navigator.js +468 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +17 -0
- package/dist/legacy/agent-action-recovery.d.ts +45 -0
- package/dist/legacy/agent-action-recovery.js +370 -0
- package/dist/legacy/agent-message-utils.d.ts +21 -0
- package/dist/legacy/agent-message-utils.js +77 -0
- package/dist/legacy/agent-url-utils.d.ts +30 -0
- package/dist/legacy/agent-url-utils.js +138 -0
- package/dist/legacy/agent.d.ts +226 -0
- package/dist/legacy/agent.js +6666 -0
- package/dist/legacy/clip-orchestrator.d.ts +148 -0
- package/dist/legacy/clip-orchestrator.js +957 -0
- package/dist/legacy/credential-templates.d.ts +5 -0
- package/dist/legacy/credential-templates.js +60 -0
- package/dist/legacy/hybrid-navigator.d.ts +138 -0
- package/dist/legacy/hybrid-navigator.js +468 -0
- package/dist/legacy/llm-usage.d.ts +17 -0
- package/dist/legacy/llm-usage.js +45 -0
- package/dist/legacy/prompt-cache.d.ts +10 -0
- package/dist/legacy/prompt-cache.js +24 -0
- package/dist/legacy/prompts.d.ts +175 -0
- package/dist/legacy/prompts.js +1038 -0
- package/dist/legacy/tools.d.ts +4 -0
- package/dist/legacy/tools.js +216 -0
- package/dist/legacy/video-agent.d.ts +143 -0
- package/dist/legacy/video-agent.js +4788 -0
- package/dist/legacy/video-observation.d.ts +36 -0
- package/dist/legacy/video-observation.js +192 -0
- package/dist/legacy/video-planner.d.ts +12 -0
- package/dist/legacy/video-planner.js +501 -0
- package/dist/legacy/video-prompts.d.ts +37 -0
- package/dist/legacy/video-prompts.js +569 -0
- package/dist/legacy/video-tools.d.ts +3 -0
- package/dist/legacy/video-tools.js +59 -0
- package/dist/legacy/video-variant-state.d.ts +29 -0
- package/dist/legacy/video-variant-state.js +80 -0
- package/dist/legacy/vision-model.d.ts +17 -0
- package/dist/legacy/vision-model.js +74 -0
- package/dist/llm-healer.d.ts +63 -0
- package/dist/llm-healer.js +166 -0
- package/dist/llm-provider.d.ts +29 -0
- package/dist/llm-provider.js +80 -0
- package/dist/llm-usage.d.ts +17 -0
- package/dist/llm-usage.js +45 -0
- package/dist/logger.d.ts +6 -2
- package/dist/logger.js +15 -1
- package/dist/mockup-html.d.ts +119 -0
- package/dist/mockup-html.js +263 -0
- package/dist/mockup.d.ts +187 -0
- package/dist/mockup.js +869 -0
- package/dist/mouse-animation.d.ts +46 -0
- package/dist/mouse-animation.js +114 -0
- package/dist/opcode-actions.d.ts +42 -0
- package/dist/opcode-actions.js +511 -0
- package/dist/opcode-runner.d.ts +51 -0
- package/dist/opcode-runner.js +770 -0
- package/dist/openrouter-client.d.ts +40 -0
- package/dist/openrouter-client.js +16 -0
- package/dist/overlay-engine.d.ts +24 -0
- package/dist/overlay-engine.js +176 -0
- package/dist/overlay-utils.d.ts +14 -0
- package/dist/overlay-utils.js +13 -0
- package/dist/postcondition.d.ts +16 -0
- package/dist/postcondition.js +269 -0
- package/dist/posthog.d.ts +4 -0
- package/dist/posthog.js +26 -0
- package/dist/program-patcher.d.ts +25 -0
- package/dist/program-patcher.js +44 -0
- package/dist/prompt-cache.d.ts +10 -0
- package/dist/prompt-cache.js +24 -0
- package/dist/prompts.d.ts +175 -0
- package/dist/prompts.js +1038 -0
- package/dist/provider-config.d.ts +12 -0
- package/dist/provider-config.js +15 -0
- package/dist/recovery-chain.d.ts +37 -0
- package/dist/recovery-chain.js +350 -0
- package/dist/remote-browser.d.ts +215 -0
- package/dist/remote-browser.js +360 -0
- package/dist/safari-browser-bar.d.ts +15 -0
- package/dist/safari-browser-bar.js +95 -0
- package/dist/safari-toolbar-asset.d.ts +15 -0
- package/dist/safari-toolbar-asset.js +12 -0
- package/dist/security.d.ts +21 -0
- package/dist/security.js +608 -0
- package/dist/selector-resolver.d.ts +34 -0
- package/dist/selector-resolver.js +181 -0
- package/dist/semantic-resolver.d.ts +35 -0
- package/dist/semantic-resolver.js +161 -0
- package/dist/server-capture-runtime.d.ts +125 -0
- package/dist/server-capture-runtime.js +585 -0
- package/dist/server-credit-usage.d.ts +12 -0
- package/dist/server-credit-usage.js +41 -0
- package/dist/server-posthog.d.ts +2 -0
- package/dist/server-posthog.js +16 -0
- package/dist/server-project-webhooks.d.ts +59 -0
- package/dist/server-project-webhooks.js +123 -0
- package/dist/server-screenshot-watermark.d.ts +7 -0
- package/dist/server-screenshot-watermark.js +60 -0
- package/dist/session-profile.d.ts +86 -0
- package/dist/session-profile.js +1536 -0
- package/dist/sf-pro-fonts.d.ts +4 -0
- package/dist/sf-pro-fonts.js +7 -0
- package/dist/sf-pro-symbols.d.ts +1 -0
- package/dist/sf-pro-symbols.js +55 -0
- package/dist/skill-packaging.d.ts +28 -0
- package/dist/skill-packaging.js +169 -0
- package/dist/smart-wait.d.ts +27 -0
- package/dist/smart-wait.js +81 -0
- package/dist/status-bar-l10n.d.ts +14 -0
- package/dist/status-bar-l10n.js +177 -0
- package/dist/status-bar-render.d.ts +20 -0
- package/dist/status-bar-render.js +410 -0
- package/dist/status-bar.d.ts +53 -0
- package/dist/status-bar.js +620 -0
- package/dist/svg-browser-bar.d.ts +33 -0
- package/dist/svg-browser-bar.js +206 -0
- package/dist/svg-status-bar.d.ts +36 -0
- package/dist/svg-status-bar.js +597 -0
- package/dist/svg-text.d.ts +61 -0
- package/dist/svg-text.js +118 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.js +216 -0
- package/dist/types.d.ts +240 -5
- package/dist/types.js +23 -1
- package/dist/v2/action-verifier.d.ts +29 -0
- package/dist/v2/action-verifier.js +133 -0
- package/dist/v2/alt-text.d.ts +26 -0
- package/dist/v2/alt-text.js +55 -0
- package/dist/v2/benchmark.d.ts +59 -0
- package/dist/v2/benchmark.js +135 -0
- package/dist/v2/capture-strategy.d.ts +30 -0
- package/dist/v2/capture-strategy.js +67 -0
- package/dist/v2/capture-verification.d.ts +35 -0
- package/dist/v2/capture-verification.js +95 -0
- package/dist/v2/circuit-breaker.d.ts +42 -0
- package/dist/v2/circuit-breaker.js +119 -0
- package/dist/v2/cli-runner-local.d.ts +11 -0
- package/dist/v2/cli-runner-local.js +91 -0
- package/dist/v2/cli-runner.d.ts +34 -0
- package/dist/v2/cli-runner.js +300 -0
- package/dist/v2/compiler-prompts.d.ts +27 -0
- package/dist/v2/compiler-prompts.js +123 -0
- package/dist/v2/compiler.d.ts +37 -0
- package/dist/v2/compiler.js +147 -0
- package/dist/v2/explorer.d.ts +41 -0
- package/dist/v2/explorer.js +56 -0
- package/dist/v2/index.d.ts +37 -0
- package/dist/v2/index.js +31 -0
- package/dist/v2/llm-healer.d.ts +62 -0
- package/dist/v2/llm-healer.js +166 -0
- package/dist/v2/llm-provider.d.ts +29 -0
- package/dist/v2/llm-provider.js +80 -0
- package/dist/v2/opcode-runner.d.ts +47 -0
- package/dist/v2/opcode-runner.js +634 -0
- package/dist/v2/overlay-engine.d.ts +24 -0
- package/dist/v2/overlay-engine.js +150 -0
- package/dist/v2/postcondition.d.ts +16 -0
- package/dist/v2/postcondition.js +249 -0
- package/dist/v2/program-patcher.d.ts +25 -0
- package/dist/v2/program-patcher.js +44 -0
- package/dist/v2/recovery-chain.d.ts +30 -0
- package/dist/v2/recovery-chain.js +368 -0
- package/dist/v2/schema.d.ts +2580 -0
- package/dist/v2/schema.js +295 -0
- package/dist/v2/selector-resolver.d.ts +34 -0
- package/dist/v2/selector-resolver.js +181 -0
- package/dist/v2/semantic-resolver.d.ts +35 -0
- package/dist/v2/semantic-resolver.js +161 -0
- package/dist/v2/smart-wait.d.ts +27 -0
- package/dist/v2/smart-wait.js +81 -0
- package/dist/v2/types.d.ts +444 -0
- package/dist/v2/types.js +19 -0
- package/dist/v2/web-playwright-local.d.ts +69 -0
- package/dist/v2/web-playwright-local.js +392 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/video-agent.d.ts +143 -0
- package/dist/video-agent.js +4788 -0
- package/dist/video-observation.d.ts +36 -0
- package/dist/video-observation.js +192 -0
- package/dist/video-planner.d.ts +12 -0
- package/dist/video-planner.js +501 -0
- package/dist/video-prompts.d.ts +37 -0
- package/dist/video-prompts.js +554 -0
- package/dist/video-tools.d.ts +3 -0
- package/dist/video-tools.js +59 -0
- package/dist/video-variant-state.d.ts +29 -0
- package/dist/video-variant-state.js +80 -0
- package/dist/vision-model.d.ts +17 -0
- package/dist/vision-model.js +74 -0
- package/dist/web-playwright-local.d.ts +126 -0
- package/dist/web-playwright-local.js +819 -0
- package/dist/ws-auth.d.ts +20 -0
- package/dist/ws-auth.js +70 -0
- package/dist/ws-broadcast.d.ts +34 -0
- package/dist/ws-broadcast.js +85 -0
- package/dist/ws-connection-limits.d.ts +12 -0
- package/dist/ws-connection-limits.js +44 -0
- package/dist/ws-handler-utils.d.ts +32 -0
- package/dist/ws-handler-utils.js +139 -0
- package/dist/ws-handler.d.ts +10 -0
- package/dist/ws-handler.js +1793 -0
- package/dist/ws-metrics-server.d.ts +9 -0
- package/dist/ws-metrics-server.js +31 -0
- package/dist/ws-server.d.ts +9 -0
- package/dist/ws-server.js +92 -0
- package/package.json +142 -71
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture Agent — Selector Resolver
|
|
3
|
+
*
|
|
4
|
+
* Progressive selector resolution for opcodes that target elements:
|
|
5
|
+
* 1. Primary selector from compiled program
|
|
6
|
+
* 2. AKTree fingerprint match
|
|
7
|
+
* 3. Selector memory candidates (from Supabase)
|
|
8
|
+
* 4. Fuzzy text match on AKTree nodes
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Resolves a selector by trying multiple strategies in order.
|
|
12
|
+
* Returns the first working selector, or null if nothing matches.
|
|
13
|
+
*/
|
|
14
|
+
export async function resolveSelector(adapter, options) {
|
|
15
|
+
const tree = await adapter.getAKTree();
|
|
16
|
+
// 1. Try primary selector
|
|
17
|
+
if (await selectorExists(adapter, options.primary)) {
|
|
18
|
+
return { selector: options.primary, strategy: 'primary', confidence: 'high' };
|
|
19
|
+
}
|
|
20
|
+
// 2. Try alternate selectors
|
|
21
|
+
if (options.alternates) {
|
|
22
|
+
for (const alt of options.alternates) {
|
|
23
|
+
if (await selectorExists(adapter, alt)) {
|
|
24
|
+
return { selector: alt, strategy: 'alternate', confidence: 'high' };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// 3. Try fingerprint match in AKTree
|
|
29
|
+
if (options.fingerprint) {
|
|
30
|
+
const match = findNodeByFingerprint(tree, options.fingerprint);
|
|
31
|
+
if (match) {
|
|
32
|
+
return { selector: match, strategy: 'fingerprint', confidence: 'medium' };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// 4. Try selector memory
|
|
36
|
+
if (options.selectorMemory && options.stepSignature) {
|
|
37
|
+
const candidates = options.selectorMemory[options.stepSignature];
|
|
38
|
+
if (candidates) {
|
|
39
|
+
for (const candidate of candidates) {
|
|
40
|
+
if (await selectorExists(adapter, candidate)) {
|
|
41
|
+
return { selector: candidate, strategy: 'memory', confidence: 'medium' };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// 5. Try fuzzy text match
|
|
47
|
+
if (options.description) {
|
|
48
|
+
const match = findNodeByFuzzyText(tree, options.description);
|
|
49
|
+
if (match) {
|
|
50
|
+
return { selector: match, strategy: 'fuzzy_text', confidence: 'low' };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
56
|
+
async function selectorExists(adapter, selector) {
|
|
57
|
+
try {
|
|
58
|
+
const found = await adapter.waitFor({
|
|
59
|
+
selector,
|
|
60
|
+
state: 'attached',
|
|
61
|
+
timeoutMs: 2000,
|
|
62
|
+
});
|
|
63
|
+
return found;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Finds an AKTree node whose sourceRef/attributes match a fingerprint string.
|
|
71
|
+
* Returns a CSS selector that can be used to interact with the element.
|
|
72
|
+
*/
|
|
73
|
+
function findNodeByFingerprint(tree, fingerprint) {
|
|
74
|
+
const parts = fingerprint.split(':');
|
|
75
|
+
// Fingerprint format: "type:label:context" e.g. "button:submit:login-form"
|
|
76
|
+
const [expectedType, expectedLabel, expectedContext] = parts;
|
|
77
|
+
let bestMatch = null;
|
|
78
|
+
let bestScore = 0;
|
|
79
|
+
function walk(node) {
|
|
80
|
+
if (!node.visible || !node.interactive) {
|
|
81
|
+
node.children.forEach(walk);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
let score = 0;
|
|
85
|
+
// Match type
|
|
86
|
+
if (expectedType && node.type === expectedType)
|
|
87
|
+
score += 3;
|
|
88
|
+
// Match label (fuzzy)
|
|
89
|
+
if (expectedLabel) {
|
|
90
|
+
const nodeLabelLower = node.label.toLowerCase();
|
|
91
|
+
const expectedLabelLower = expectedLabel.toLowerCase();
|
|
92
|
+
if (nodeLabelLower === expectedLabelLower)
|
|
93
|
+
score += 5;
|
|
94
|
+
else if (nodeLabelLower.includes(expectedLabelLower))
|
|
95
|
+
score += 3;
|
|
96
|
+
else if (expectedLabelLower.includes(nodeLabelLower))
|
|
97
|
+
score += 1;
|
|
98
|
+
}
|
|
99
|
+
// Match context (check sourceRef)
|
|
100
|
+
if (expectedContext && node.sourceRef.toLowerCase().includes(expectedContext.toLowerCase())) {
|
|
101
|
+
score += 2;
|
|
102
|
+
}
|
|
103
|
+
if (score > bestScore) {
|
|
104
|
+
bestScore = score;
|
|
105
|
+
bestMatch = node;
|
|
106
|
+
}
|
|
107
|
+
node.children.forEach(walk);
|
|
108
|
+
}
|
|
109
|
+
walk(tree.root);
|
|
110
|
+
if (bestMatch && bestScore >= 4) {
|
|
111
|
+
return buildSelectorFromNode(bestMatch);
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Finds a visible interactive node by fuzzy text matching against the description.
|
|
117
|
+
*/
|
|
118
|
+
function findNodeByFuzzyText(tree, description) {
|
|
119
|
+
const descTokens = tokenize(description);
|
|
120
|
+
if (descTokens.length === 0)
|
|
121
|
+
return null;
|
|
122
|
+
let bestMatch = null;
|
|
123
|
+
let bestOverlap = 0;
|
|
124
|
+
function walk(node) {
|
|
125
|
+
if (!node.visible || !node.interactive) {
|
|
126
|
+
node.children.forEach(walk);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const nodeTokens = tokenize(node.label);
|
|
130
|
+
const overlap = countOverlap(descTokens, nodeTokens);
|
|
131
|
+
if (overlap > bestOverlap) {
|
|
132
|
+
bestOverlap = overlap;
|
|
133
|
+
bestMatch = node;
|
|
134
|
+
}
|
|
135
|
+
node.children.forEach(walk);
|
|
136
|
+
}
|
|
137
|
+
walk(tree.root);
|
|
138
|
+
// Require at least 2 token overlap or >50% match
|
|
139
|
+
if (bestMatch && (bestOverlap >= 2 || bestOverlap / descTokens.length > 0.5)) {
|
|
140
|
+
return buildSelectorFromNode(bestMatch);
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
function buildSelectorFromNode(node) {
|
|
145
|
+
// Try to build the most specific selector from node attributes
|
|
146
|
+
const ref = node.sourceRef;
|
|
147
|
+
// Extract data-testid
|
|
148
|
+
const testIdMatch = ref.match(/data-testid="([^"]+)"/);
|
|
149
|
+
if (testIdMatch)
|
|
150
|
+
return `[data-testid="${testIdMatch[1]}"]`;
|
|
151
|
+
// Extract id
|
|
152
|
+
const idMatch = ref.match(/ id="([^"]+)"/);
|
|
153
|
+
if (idMatch)
|
|
154
|
+
return `#${idMatch[1]}`;
|
|
155
|
+
// Extract tag + role + text
|
|
156
|
+
const tagMatch = ref.match(/^<(\w+)/);
|
|
157
|
+
const tag = tagMatch?.[1] ?? '*';
|
|
158
|
+
const role = node.attributes['role'];
|
|
159
|
+
if (role) {
|
|
160
|
+
return `${tag}[role="${role}"]`;
|
|
161
|
+
}
|
|
162
|
+
// Fallback: use AKNode id as a CSS selector via data attribute
|
|
163
|
+
if (node.id) {
|
|
164
|
+
return `[data-ak-id="${node.id}"]`;
|
|
165
|
+
}
|
|
166
|
+
return `${tag}:has-text("${escapeText(node.label.slice(0, 50))}")`;
|
|
167
|
+
}
|
|
168
|
+
function tokenize(text) {
|
|
169
|
+
return text
|
|
170
|
+
.toLowerCase()
|
|
171
|
+
.split(/[^a-z0-9]+/)
|
|
172
|
+
.filter(t => t.length >= 2);
|
|
173
|
+
}
|
|
174
|
+
function countOverlap(a, b) {
|
|
175
|
+
const setB = new Set(b);
|
|
176
|
+
return a.filter(t => setB.has(t)).length;
|
|
177
|
+
}
|
|
178
|
+
function escapeText(text) {
|
|
179
|
+
return text.replace(/"/g, '\\"').replace(/\n/g, ' ');
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=selector-resolver.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture Agent — Semantic Target Resolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves a SemanticTarget to a concrete Playwright locator.
|
|
5
|
+
* This is the core mechanism that allows opcodes to work WITHOUT CSS selectors.
|
|
6
|
+
*
|
|
7
|
+
* Resolution cascade:
|
|
8
|
+
* 1. CSS selector (if provided, fast path)
|
|
9
|
+
* 2. Playwright semantic locators (getByRole, getByText, getByLabel, getByPlaceholder)
|
|
10
|
+
* 3. Selector alternates
|
|
11
|
+
* 4. Composite: role + name + near (for disambiguation)
|
|
12
|
+
*
|
|
13
|
+
* All resolution happens via Playwright's built-in locator API — no AKTree needed.
|
|
14
|
+
*/
|
|
15
|
+
import type { Page, Locator } from 'playwright';
|
|
16
|
+
import type { SemanticTarget } from './execution-types.js';
|
|
17
|
+
export interface ResolvedTarget {
|
|
18
|
+
locator: Locator;
|
|
19
|
+
method: 'selector' | 'role' | 'text' | 'label' | 'placeholder' | 'alternate' | 'composite';
|
|
20
|
+
}
|
|
21
|
+
export interface ResolveOptions {
|
|
22
|
+
/** Primary CSS selector */
|
|
23
|
+
selector?: string;
|
|
24
|
+
/** Semantic target description */
|
|
25
|
+
target?: SemanticTarget;
|
|
26
|
+
/** Fallback selectors */
|
|
27
|
+
selectorAlternates?: string[];
|
|
28
|
+
/** Timeout for visibility check (ms). Default: 3000 */
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolves an element on the page using the best available method.
|
|
33
|
+
* Returns the first visible locator found, or null if nothing matches.
|
|
34
|
+
*/
|
|
35
|
+
export declare function resolveTarget(page: Page, options: ResolveOptions): Promise<ResolvedTarget | null>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture Agent — Semantic Target Resolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves a SemanticTarget to a concrete Playwright locator.
|
|
5
|
+
* This is the core mechanism that allows opcodes to work WITHOUT CSS selectors.
|
|
6
|
+
*
|
|
7
|
+
* Resolution cascade:
|
|
8
|
+
* 1. CSS selector (if provided, fast path)
|
|
9
|
+
* 2. Playwright semantic locators (getByRole, getByText, getByLabel, getByPlaceholder)
|
|
10
|
+
* 3. Selector alternates
|
|
11
|
+
* 4. Composite: role + name + near (for disambiguation)
|
|
12
|
+
*
|
|
13
|
+
* All resolution happens via Playwright's built-in locator API — no AKTree needed.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Resolves an element on the page using the best available method.
|
|
17
|
+
* Returns the first visible locator found, or null if nothing matches.
|
|
18
|
+
*/
|
|
19
|
+
export async function resolveTarget(page, options) {
|
|
20
|
+
const timeout = options.timeoutMs ?? 3000;
|
|
21
|
+
// 1. Primary CSS selector
|
|
22
|
+
if (options.selector) {
|
|
23
|
+
const locator = page.locator(options.selector).first();
|
|
24
|
+
if (await isVisible(locator, timeout)) {
|
|
25
|
+
return { locator, method: 'selector' };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// 2. Semantic locators from target
|
|
29
|
+
if (options.target) {
|
|
30
|
+
const resolved = await resolveSemanticTarget(page, options.target, timeout);
|
|
31
|
+
if (resolved)
|
|
32
|
+
return resolved;
|
|
33
|
+
}
|
|
34
|
+
// 3. Alternate selectors
|
|
35
|
+
if (options.selectorAlternates) {
|
|
36
|
+
for (const alt of options.selectorAlternates) {
|
|
37
|
+
const locator = page.locator(alt).first();
|
|
38
|
+
if (await isVisible(locator, timeout)) {
|
|
39
|
+
return { locator, method: 'alternate' };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolves a SemanticTarget using Playwright's semantic locator API.
|
|
47
|
+
*/
|
|
48
|
+
async function resolveSemanticTarget(page, target, timeout) {
|
|
49
|
+
const exact = target.exact ?? false;
|
|
50
|
+
// Strategy A: getByRole with name (most precise)
|
|
51
|
+
if (target.role && (target.text || target.label)) {
|
|
52
|
+
const name = target.label || target.text;
|
|
53
|
+
try {
|
|
54
|
+
let locator = page.getByRole(target.role, {
|
|
55
|
+
name: name,
|
|
56
|
+
exact,
|
|
57
|
+
});
|
|
58
|
+
if (target.near) {
|
|
59
|
+
locator = narrowByNear(page, locator, target.near);
|
|
60
|
+
}
|
|
61
|
+
locator = locator.first();
|
|
62
|
+
if (await isVisible(locator, timeout)) {
|
|
63
|
+
return { locator, method: 'role' };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Invalid role or no match
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Strategy B: getByRole without name
|
|
71
|
+
if (target.role && !target.text && !target.label) {
|
|
72
|
+
try {
|
|
73
|
+
let locator = page.getByRole(target.role);
|
|
74
|
+
if (target.near) {
|
|
75
|
+
locator = narrowByNear(page, locator, target.near);
|
|
76
|
+
}
|
|
77
|
+
locator = locator.first();
|
|
78
|
+
if (await isVisible(locator, timeout)) {
|
|
79
|
+
return { locator, method: 'role' };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Invalid role
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Strategy C: getByText
|
|
87
|
+
if (target.text) {
|
|
88
|
+
let locator = page.getByText(target.text, { exact });
|
|
89
|
+
if (target.near) {
|
|
90
|
+
locator = narrowByNear(page, locator, target.near);
|
|
91
|
+
}
|
|
92
|
+
locator = locator.first();
|
|
93
|
+
if (await isVisible(locator, timeout)) {
|
|
94
|
+
return { locator, method: 'text' };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Strategy D: getByLabel
|
|
98
|
+
if (target.label) {
|
|
99
|
+
let locator = page.getByLabel(target.label, { exact });
|
|
100
|
+
if (target.near) {
|
|
101
|
+
locator = narrowByNear(page, locator, target.near);
|
|
102
|
+
}
|
|
103
|
+
locator = locator.first();
|
|
104
|
+
if (await isVisible(locator, timeout)) {
|
|
105
|
+
return { locator, method: 'label' };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Strategy E: getByPlaceholder (for inputs)
|
|
109
|
+
if (target.placeholder) {
|
|
110
|
+
let locator = page.getByPlaceholder(target.placeholder, { exact });
|
|
111
|
+
if (target.near) {
|
|
112
|
+
locator = narrowByNear(page, locator, target.near);
|
|
113
|
+
}
|
|
114
|
+
locator = locator.first();
|
|
115
|
+
if (await isVisible(locator, timeout)) {
|
|
116
|
+
return { locator, method: 'placeholder' };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Strategy F: Composite — try role-based with looser matching
|
|
120
|
+
if (target.role) {
|
|
121
|
+
try {
|
|
122
|
+
const allByRole = page.getByRole(target.role);
|
|
123
|
+
const count = await allByRole.count();
|
|
124
|
+
for (let i = 0; i < Math.min(count, 10); i++) {
|
|
125
|
+
const candidate = allByRole.nth(i);
|
|
126
|
+
if (await isVisible(candidate, 500)) {
|
|
127
|
+
const text = await candidate.textContent().catch(() => null);
|
|
128
|
+
if (text && target.text && text.toLowerCase().includes(target.text.toLowerCase())) {
|
|
129
|
+
return { locator: candidate, method: 'composite' };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// No match
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Narrows a locator to one near a specific text/heading on the page.
|
|
142
|
+
* Uses Playwright's `.filter()` with a parent locator containing the near text.
|
|
143
|
+
*/
|
|
144
|
+
function narrowByNear(page, locator, nearText) {
|
|
145
|
+
// Find a section/container that contains the near text
|
|
146
|
+
const container = page.locator(`section:has-text("${escapeForSelector(nearText)}"), div:has-text("${escapeForSelector(nearText)}"), [role="region"]:has-text("${escapeForSelector(nearText)}")`).first();
|
|
147
|
+
return container.locator(locator);
|
|
148
|
+
}
|
|
149
|
+
async function isVisible(locator, timeout) {
|
|
150
|
+
try {
|
|
151
|
+
await locator.waitFor({ state: 'visible', timeout });
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function escapeForSelector(text) {
|
|
159
|
+
return text.replace(/"/g, '\\"').replace(/\n/g, ' ');
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=semantic-resolver.js.map
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
+
export type BillingPlanId = 'free' | 'maker' | 'team';
|
|
3
|
+
export interface BillingPlanEntitlements {
|
|
4
|
+
creditsPerMonth: number;
|
|
5
|
+
maxProjects: number | null;
|
|
6
|
+
maxPresetsPerProject: number | null;
|
|
7
|
+
allowFullPageCapture: boolean;
|
|
8
|
+
allowElementCapture: boolean;
|
|
9
|
+
retentionDays: number;
|
|
10
|
+
watermarkScreenshots: boolean;
|
|
11
|
+
maxLanguages: number | null;
|
|
12
|
+
maxThemes: number | null;
|
|
13
|
+
apiAccess: boolean;
|
|
14
|
+
captureCompleteWebhook: boolean;
|
|
15
|
+
priorityQueue: boolean;
|
|
16
|
+
maxParallelCaptures: number;
|
|
17
|
+
teamMembers: boolean;
|
|
18
|
+
aiDailyCostLimitUsd: number;
|
|
19
|
+
apiRateLimitRpm: number;
|
|
20
|
+
maxDevLinks: number | null;
|
|
21
|
+
maxCompositions: number | null;
|
|
22
|
+
maxTeamMembersPerProject: number | null;
|
|
23
|
+
}
|
|
24
|
+
export interface BillingPlan {
|
|
25
|
+
id: BillingPlanId;
|
|
26
|
+
nameKey: BillingPlanId;
|
|
27
|
+
descriptionKey: 'forEvaluation' | 'forMakers' | 'forTeams';
|
|
28
|
+
monthlyPriceEur: number;
|
|
29
|
+
yearlyPriceEur: number;
|
|
30
|
+
highlighted?: boolean;
|
|
31
|
+
previewCurrent?: boolean;
|
|
32
|
+
highlights: string[];
|
|
33
|
+
entitlements: BillingPlanEntitlements;
|
|
34
|
+
}
|
|
35
|
+
export interface BillingAccount {
|
|
36
|
+
user_id: string;
|
|
37
|
+
email: string | null;
|
|
38
|
+
admin_override_plan_id: BillingPlanId | null;
|
|
39
|
+
stripe_customer_id: string | null;
|
|
40
|
+
stripe_subscription_id: string | null;
|
|
41
|
+
stripe_plan_id: BillingPlanId | null;
|
|
42
|
+
stripe_subscription_status: string | null;
|
|
43
|
+
stripe_current_period_start: string | null;
|
|
44
|
+
stripe_current_period_end: string | null;
|
|
45
|
+
allow_capture_overages: boolean;
|
|
46
|
+
capture_overage_limit_cents: number | null;
|
|
47
|
+
signup_bonus_credits: number;
|
|
48
|
+
created_at: string;
|
|
49
|
+
}
|
|
50
|
+
export declare class PlanLimitError extends Error {
|
|
51
|
+
status: number;
|
|
52
|
+
code: string;
|
|
53
|
+
constructor(message: string, status?: number, code?: string);
|
|
54
|
+
}
|
|
55
|
+
export declare const SCREENSHOT_CREDIT_COST = 1;
|
|
56
|
+
export declare function getBillingPlan(planId: BillingPlanId): BillingPlan;
|
|
57
|
+
export declare function coerceBillingPlanId(value: unknown): BillingPlanId | null;
|
|
58
|
+
export declare function getBillingAccountForUser(supabase: SupabaseClient, userId: string): Promise<BillingAccount | null>;
|
|
59
|
+
export declare function getProjectOwnerBillingContext(supabase: SupabaseClient, projectId: string): Promise<{
|
|
60
|
+
ownerUserId: string;
|
|
61
|
+
plan: BillingPlan;
|
|
62
|
+
}>;
|
|
63
|
+
export declare function shouldUseStripePlan(status: string | null | undefined): boolean;
|
|
64
|
+
export declare function isYearlySubscription(account: BillingAccount | null): boolean;
|
|
65
|
+
export declare function getStripeOveragePriceIdForPlan(planId: BillingPlanId): string | null;
|
|
66
|
+
export declare function recordStripeMeterEvent(params: {
|
|
67
|
+
customerId: string;
|
|
68
|
+
value: number;
|
|
69
|
+
identifier: string;
|
|
70
|
+
}): Promise<void>;
|
|
71
|
+
export declare function getCaptureConfigLimitViolations(config: {
|
|
72
|
+
langs: string[];
|
|
73
|
+
themes: string[];
|
|
74
|
+
elements?: unknown[];
|
|
75
|
+
}, entitlements: BillingPlanEntitlements): string[];
|
|
76
|
+
export declare function ensureCaptureConfigAllowed(plan: BillingPlan, config: {
|
|
77
|
+
langs: string[];
|
|
78
|
+
themes: string[];
|
|
79
|
+
elements?: unknown[];
|
|
80
|
+
}): void;
|
|
81
|
+
export declare function getLockedResourceIds(supabase: SupabaseClient, ownerUserId: string, plan: BillingPlan): Promise<{
|
|
82
|
+
lockedProjectIds: Set<string>;
|
|
83
|
+
lockedPresetIdsByProject: Map<string, Set<string>>;
|
|
84
|
+
}>;
|
|
85
|
+
export declare function ensureResourceNotLocked(resourceId: string, lockedIds: Set<string>, resourceType?: 'project' | 'preset'): void;
|
|
86
|
+
export declare function getRemainingOverageCredits(params: {
|
|
87
|
+
planId: BillingPlanId;
|
|
88
|
+
quota: number;
|
|
89
|
+
usedCredits: number;
|
|
90
|
+
overageLimitCents: number | null;
|
|
91
|
+
}): number | null;
|
|
92
|
+
export declare function getCaptureOverageState(params: {
|
|
93
|
+
planId: BillingPlanId;
|
|
94
|
+
quota: number;
|
|
95
|
+
usedCredits: number;
|
|
96
|
+
allowOverages: boolean;
|
|
97
|
+
overageLimitCents: number | null;
|
|
98
|
+
hasActiveSubscription: boolean;
|
|
99
|
+
hasOveragePrice: boolean;
|
|
100
|
+
isYearlySubscription: boolean;
|
|
101
|
+
}): {
|
|
102
|
+
eligible: boolean;
|
|
103
|
+
enabled: boolean;
|
|
104
|
+
limitReached: boolean;
|
|
105
|
+
spendCents: number;
|
|
106
|
+
remainingBudgetCents: number | null;
|
|
107
|
+
remainingCredits: number | null;
|
|
108
|
+
};
|
|
109
|
+
export declare function getSignupBonusCredits(account: {
|
|
110
|
+
signup_bonus_credits?: number;
|
|
111
|
+
created_at?: string;
|
|
112
|
+
} | null, billingPeriodStart: string): number;
|
|
113
|
+
export declare function ensureMonthlyCreditsQuota(plan: BillingPlan, usedCredits: number, requestedCredits: number, allowOverage?: boolean, overageLimitCents?: number | null, bonusCredits?: number): void;
|
|
114
|
+
export declare function getOwnerBillingUsage(supabase: SupabaseClient, ownerUserId: string, billingPeriodStartOverride?: string): Promise<{
|
|
115
|
+
billingPeriodStart: string;
|
|
116
|
+
credits: number;
|
|
117
|
+
}>;
|
|
118
|
+
export declare function getIncrementalOverageCount(params: {
|
|
119
|
+
quota: number;
|
|
120
|
+
usedBefore: number;
|
|
121
|
+
completedCount: number;
|
|
122
|
+
}): number;
|
|
123
|
+
export declare function cleanupExpiredCapturesForOwner(supabase: SupabaseClient, ownerUserId: string): Promise<{
|
|
124
|
+
deletedCaptures: number;
|
|
125
|
+
}>;
|