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.
- package/assets/cursors/macos.svg +4 -0
- package/assets/cursors/windows.svg +15 -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/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 +92 -8
- package/dist/agent.js +2936 -781
- 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/browser-bar.d.ts +14 -6
- package/dist/browser-bar.js +145 -8
- 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 +51 -1
- package/dist/browser.js +1481 -31
- package/dist/capture-alt-text.js +2 -1
- package/dist/capture-language-preflight.js +14 -0
- package/dist/capture-llm-page-identity.js +22 -10
- package/dist/capture-page-identity.d.ts +5 -7
- package/dist/capture-page-identity.js +211 -78
- package/dist/capture-preset-credentials.d.ts +50 -0
- package/dist/capture-preset-credentials.js +127 -0
- package/dist/capture-request-plan.d.ts +2 -2
- package/dist/capture-request-plan.js +64 -16
- package/dist/capture-run-optimizer.js +48 -33
- package/dist/capture-selector-memory.d.ts +5 -0
- package/dist/capture-selector-memory.js +18 -0
- package/dist/capture-strategy.d.ts +36 -0
- package/dist/capture-strategy.js +95 -0
- package/dist/capture-studio-sync.d.ts +1 -0
- package/dist/capture-studio-sync.js +9 -3
- 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 +2 -0
- package/dist/capture-variant-state.js +26 -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 -267
- package/dist/clip-orchestrator.js +9 -2
- package/dist/clip-postprocess.js +25 -16
- package/dist/cookie-dismiss.d.ts +2 -0
- package/dist/cookie-dismiss.js +48 -13
- package/dist/cost-logging.d.ts +8 -0
- package/dist/cost-logging.js +160 -46
- package/dist/cost-resolution-monitor.d.ts +16 -0
- package/dist/cost-resolution-monitor.js +34 -0
- package/dist/credential-templates.js +2 -2
- 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 +1 -41
- package/dist/element-capture.js +202 -446
- 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.js +12 -12
- package/dist/index.d.ts +9 -6
- package/dist/index.js +10 -4
- 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/logger.d.ts +6 -2
- package/dist/logger.js +15 -1
- package/dist/mockup-html.js +35 -25
- package/dist/mockup.d.ts +95 -2
- package/dist/mockup.js +427 -166
- package/dist/mouse-animation.d.ts +2 -2
- package/dist/mouse-animation.js +34 -20
- 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/postcondition.d.ts +16 -0
- package/dist/postcondition.js +269 -0
- package/dist/program-patcher.d.ts +25 -0
- package/dist/program-patcher.js +44 -0
- package/dist/prompts.d.ts +13 -5
- package/dist/prompts.js +224 -351
- 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 +28 -4
- package/dist/remote-browser.js +60 -5
- 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 +2 -1
- package/dist/security.js +49 -10
- 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 +5 -3
- package/dist/server-capture-runtime.js +42 -95
- package/dist/server-credit-usage.d.ts +2 -2
- package/dist/server-project-webhooks.d.ts +15 -1
- package/dist/server-project-webhooks.js +34 -8
- package/dist/server-screenshot-watermark.js +27 -5
- package/dist/session-profile.js +164 -1
- 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-render.d.ts +20 -0
- package/dist/status-bar-render.js +410 -0
- package/dist/status-bar.d.ts +9 -0
- package/dist/status-bar.js +298 -14
- 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.js +89 -451
- 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.js +18 -13
- package/dist/video-planner.js +2 -1
- package/dist/video-prompts.js +3 -3
- package/dist/web-playwright-local.d.ts +126 -0
- package/dist/web-playwright-local.js +819 -0
- package/dist/ws-auth.js +4 -1
- 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.js +294 -164
- package/dist/ws-metrics-server.d.ts +9 -0
- package/dist/ws-metrics-server.js +31 -0
- package/dist/ws-server.js +41 -1
- package/package.json +51 -34
|
@@ -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,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture Agent — Smart Wait
|
|
3
|
+
*
|
|
4
|
+
* Detects if the page is still loading before capture.
|
|
5
|
+
* Uses Playwright-native checks (no LLM) to wait for:
|
|
6
|
+
* - Network idle
|
|
7
|
+
* - No visible spinners/skeletons
|
|
8
|
+
* - DOM stability
|
|
9
|
+
*/
|
|
10
|
+
import type { RuntimeAdapter } from './types.js';
|
|
11
|
+
export interface SmartWaitResult {
|
|
12
|
+
/** Whether the page appears stable */
|
|
13
|
+
stable: boolean;
|
|
14
|
+
/** What we waited for */
|
|
15
|
+
waitedFor: string[];
|
|
16
|
+
/** Total time spent waiting (ms) */
|
|
17
|
+
waitedMs: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Waits for the page to be visually stable before capture.
|
|
21
|
+
* Checks for common loading patterns and waits for them to resolve.
|
|
22
|
+
*
|
|
23
|
+
* This runs BEFORE CAPTURE_SCREENSHOT — deterministic, no LLM.
|
|
24
|
+
*/
|
|
25
|
+
export declare function smartWaitForStability(adapter: RuntimeAdapter, options?: {
|
|
26
|
+
maxWaitMs?: number;
|
|
27
|
+
}): Promise<SmartWaitResult>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture Agent — Smart Wait
|
|
3
|
+
*
|
|
4
|
+
* Detects if the page is still loading before capture.
|
|
5
|
+
* Uses Playwright-native checks (no LLM) to wait for:
|
|
6
|
+
* - Network idle
|
|
7
|
+
* - No visible spinners/skeletons
|
|
8
|
+
* - DOM stability
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Waits for the page to be visually stable before capture.
|
|
12
|
+
* Checks for common loading patterns and waits for them to resolve.
|
|
13
|
+
*
|
|
14
|
+
* This runs BEFORE CAPTURE_SCREENSHOT — deterministic, no LLM.
|
|
15
|
+
*/
|
|
16
|
+
export async function smartWaitForStability(adapter, options) {
|
|
17
|
+
const maxWait = options?.maxWaitMs ?? 10000;
|
|
18
|
+
const startTime = Date.now();
|
|
19
|
+
const waitedFor = [];
|
|
20
|
+
// 1. Wait for no visible spinners/skeletons
|
|
21
|
+
const spinnerSelectors = [
|
|
22
|
+
'[class*="spinner"]',
|
|
23
|
+
'[class*="loading"]',
|
|
24
|
+
'[class*="skeleton"]',
|
|
25
|
+
'[class*="shimmer"]',
|
|
26
|
+
'[role="progressbar"]',
|
|
27
|
+
'[aria-busy="true"]',
|
|
28
|
+
'.animate-spin',
|
|
29
|
+
'.animate-pulse',
|
|
30
|
+
];
|
|
31
|
+
for (const selector of spinnerSelectors) {
|
|
32
|
+
const elapsed = Date.now() - startTime;
|
|
33
|
+
if (elapsed >= maxWait)
|
|
34
|
+
break;
|
|
35
|
+
try {
|
|
36
|
+
// Check if spinner exists and is visible
|
|
37
|
+
const visible = await adapter.waitFor({
|
|
38
|
+
selector,
|
|
39
|
+
state: 'visible',
|
|
40
|
+
timeoutMs: 200, // Quick check
|
|
41
|
+
});
|
|
42
|
+
if (visible) {
|
|
43
|
+
// Spinner found — wait for it to disappear
|
|
44
|
+
waitedFor.push(selector);
|
|
45
|
+
const remaining = maxWait - (Date.now() - startTime);
|
|
46
|
+
if (remaining > 0) {
|
|
47
|
+
// Poll until spinner disappears
|
|
48
|
+
const deadline = Date.now() + Math.min(remaining, 5000);
|
|
49
|
+
while (Date.now() < deadline) {
|
|
50
|
+
const stillVisible = await adapter.waitFor({
|
|
51
|
+
selector,
|
|
52
|
+
state: 'visible',
|
|
53
|
+
timeoutMs: 300,
|
|
54
|
+
});
|
|
55
|
+
if (!stillVisible)
|
|
56
|
+
break;
|
|
57
|
+
await sleep(300);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Selector check failed — skip
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// 2. Brief stability pause (let animations settle)
|
|
67
|
+
const elapsed = Date.now() - startTime;
|
|
68
|
+
if (elapsed < maxWait) {
|
|
69
|
+
await sleep(Math.min(500, maxWait - elapsed));
|
|
70
|
+
waitedFor.push('stability-pause');
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
stable: true,
|
|
74
|
+
waitedFor,
|
|
75
|
+
waitedMs: Date.now() - startTime,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function sleep(ms) {
|
|
79
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=smart-wait.js.map
|