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
package/dist/capture-alt-text.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { zdrParam } from './provider-config.js';
|
|
1
2
|
export async function generateAltText(params) {
|
|
2
3
|
const { url, prompt, lang, theme, targetLabel, elementName, model, apiKey } = params;
|
|
3
4
|
const contextParts = [
|
|
@@ -29,7 +30,7 @@ Describe what the screenshot represents based on the context provided.`;
|
|
|
29
30
|
{ role: 'system', content: systemPrompt },
|
|
30
31
|
{ role: 'user', content: contextParts.join('\n') },
|
|
31
32
|
],
|
|
32
|
-
provider: {
|
|
33
|
+
provider: { ...zdrParam() },
|
|
33
34
|
}),
|
|
34
35
|
signal: AbortSignal.timeout(5_000),
|
|
35
36
|
});
|
|
@@ -271,6 +271,20 @@ export async function ensureScreenshotVariantLanguage(params) {
|
|
|
271
271
|
rebasedToStartUrl,
|
|
272
272
|
};
|
|
273
273
|
}
|
|
274
|
+
// Trust the agent when it succeeded (verification passed) but metadata signals
|
|
275
|
+
// still disagree. This handles SPAs and sites that don't update <html lang> or
|
|
276
|
+
// locale controls after client-side navigation (e.g., /en/ with lang="fr-FR").
|
|
277
|
+
if (preflightAgentResult?.success) {
|
|
278
|
+
params.onLog?.(`Language guard: metadata signals still disagree but variant preflight agent succeeded — trusting agent assessment. ${summarizeVariantObservation(observation)}.`);
|
|
279
|
+
return {
|
|
280
|
+
ok: true,
|
|
281
|
+
resolvedBy: "language_preflight_agent",
|
|
282
|
+
observation,
|
|
283
|
+
usage,
|
|
284
|
+
selectorUpdates,
|
|
285
|
+
rebasedToStartUrl,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
274
288
|
const reason = buildFailureReason(requestedLang, params.requestedTheme, observation);
|
|
275
289
|
params.onLog?.(`Language guard: blocking variant before main workflow. ${reason}`);
|
|
276
290
|
return {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { inferCapturePageIdentity } from "./capture-page-identity.js";
|
|
1
|
+
import { buildCapturePageIdentitySummary, inferCapturePageIdentity, normalizeCaptureIdentityTokens, } from "./capture-page-identity.js";
|
|
2
|
+
import { zdrParam } from "./provider-config.js";
|
|
2
3
|
/**
|
|
3
4
|
* Use a cheap LLM call to classify all pages in a capture run.
|
|
4
5
|
* Falls back to regex heuristics if the LLM call fails.
|
|
@@ -19,25 +20,26 @@ IMPORTANT: The "pageId" is a user-defined identifier — it is NOT a technical d
|
|
|
19
20
|
|
|
20
21
|
For each page, determine:
|
|
21
22
|
- "kind": one of "gallery", "modal_selection", "modal_configuration", "editor_route", "detail_route", "unknown"
|
|
22
|
-
- "gallery": a grid/
|
|
23
|
+
- "gallery": a non-modal overview/list/grid/collection page
|
|
23
24
|
- "modal_selection": the prompt explicitly describes opening a dialog/modal/popup to pick or select something
|
|
24
|
-
- "modal_configuration": the prompt explicitly describes opening a dialog/modal/popup to configure
|
|
25
|
-
- "editor_route": a dedicated full-page
|
|
26
|
-
- "detail_route": a
|
|
25
|
+
- "modal_configuration": the prompt explicitly describes opening a dialog/modal/popup to configure or edit something
|
|
26
|
+
- "editor_route": a dedicated full-page destination with its own route
|
|
27
|
+
- "detail_route": a non-modal detail/content state that is not just a generic overview
|
|
27
28
|
- "unknown": none of the above
|
|
28
29
|
- "dialogTarget": true ONLY if the prompt explicitly says to open an actual DOM dialog, modal, or popup overlay. Set to FALSE for: sidebar panels, drawers, slide-over panels, full pages, dropdown menus, popovers, or any UI that is part of the main page layout. When in doubt, set to false.
|
|
29
30
|
- "dedicatedRoute": true if the capture target has its own URL route (not just a modal on top of another page)
|
|
31
|
+
- "subjectTokens": 2-6 short semantic tokens that describe the FINAL visible capture target. Exclude navigation verbs and chrome words such as: click, open, wait, sidebar, header, page, route, menu, button, first, current.
|
|
30
32
|
|
|
31
|
-
Respond with a JSON array of objects: [{ "pageId": "...", "kind": "...", "dialogTarget": true/false, "dedicatedRoute": true/false }]
|
|
33
|
+
Respond with a JSON array of objects: [{ "pageId": "...", "kind": "...", "dialogTarget": true/false, "dedicatedRoute": true/false, "subjectTokens": ["...", "..."] }]
|
|
32
34
|
Output ONLY valid JSON, nothing else.`;
|
|
33
35
|
try {
|
|
34
|
-
const providerBody = { provider: { ...providerPrefs?.[model],
|
|
36
|
+
const providerBody = { provider: { ...providerPrefs?.[model], ...zdrParam() } };
|
|
35
37
|
const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
|
|
36
38
|
method: "POST",
|
|
37
39
|
headers: {
|
|
38
40
|
Authorization: `Bearer ${apiKey}`,
|
|
39
41
|
"Content-Type": "application/json",
|
|
40
|
-
"HTTP-Referer": "https://
|
|
42
|
+
"HTTP-Referer": "https://github.com/screenshot-agent",
|
|
41
43
|
"X-Title": "Screenshot Agent",
|
|
42
44
|
},
|
|
43
45
|
body: JSON.stringify({
|
|
@@ -51,7 +53,7 @@ Output ONLY valid JSON, nothing else.`;
|
|
|
51
53
|
],
|
|
52
54
|
...providerBody,
|
|
53
55
|
}),
|
|
54
|
-
signal: AbortSignal.timeout(
|
|
56
|
+
signal: AbortSignal.timeout(30_000),
|
|
55
57
|
});
|
|
56
58
|
if (!res.ok) {
|
|
57
59
|
console.warn(`[llm-page-identity] LLM call failed: HTTP ${res.status}`);
|
|
@@ -98,12 +100,22 @@ Output ONLY valid JSON, nothing else.`;
|
|
|
98
100
|
"gallery", "modal_selection", "modal_configuration", "editor_route", "detail_route", "unknown",
|
|
99
101
|
];
|
|
100
102
|
const kind = validKinds.includes(cls.kind) ? cls.kind : result[pageId].kind;
|
|
103
|
+
const subjectTokens = normalizeCaptureIdentityTokens(cls.subjectTokens ?? []);
|
|
101
104
|
result[pageId] = {
|
|
102
105
|
...result[pageId],
|
|
103
106
|
kind,
|
|
107
|
+
subjectTokens: subjectTokens.length > 0 ? subjectTokens : result[pageId].subjectTokens,
|
|
104
108
|
dialogTarget: typeof cls.dialogTarget === "boolean" ? cls.dialogTarget : result[pageId].dialogTarget,
|
|
105
109
|
dedicatedRoute: typeof cls.dedicatedRoute === "boolean" ? cls.dedicatedRoute : result[pageId].dedicatedRoute,
|
|
106
|
-
summary:
|
|
110
|
+
summary: buildCapturePageIdentitySummary(kind, subjectTokens.length > 0 ? subjectTokens : result[pageId].subjectTokens, (() => {
|
|
111
|
+
try {
|
|
112
|
+
const pageRun = pageRuns.find((pr) => (pr.pageId ?? "main") === pageId);
|
|
113
|
+
return new URL(pageRun?.url ?? "").pathname.toLowerCase();
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return "/";
|
|
117
|
+
}
|
|
118
|
+
})()),
|
|
107
119
|
};
|
|
108
120
|
}
|
|
109
121
|
return { identities: result, usage };
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import type { CapturePageIdentity } from "./types.js";
|
|
1
|
+
import type { CapturePageIdentity, CapturePageIdentityKind } from "./types.js";
|
|
2
2
|
import type { ScreenshotPageRunInput } from "./capture-run-optimizer.js";
|
|
3
|
+
export declare function normalizeCaptureIdentityTokens(values: Array<string | null | undefined>, options?: {
|
|
4
|
+
stopWords?: ReadonlySet<string>;
|
|
5
|
+
}): string[];
|
|
6
|
+
export declare function buildCapturePageIdentitySummary(kind: CapturePageIdentityKind, tokens: string[], urlPath: string): string;
|
|
3
7
|
export declare function inferCapturePageIdentity(pageRun: ScreenshotPageRunInput): CapturePageIdentity;
|
|
4
|
-
export interface VariantPageDefinitionIssue {
|
|
5
|
-
pageId: string;
|
|
6
|
-
duplicateOfPageId: string;
|
|
7
|
-
reason: string;
|
|
8
|
-
}
|
|
9
|
-
export declare function findVariantPageDefinitionIssues(pageRuns: ScreenshotPageRunInput[]): VariantPageDefinitionIssue[];
|
|
@@ -62,14 +62,136 @@ const TOKEN_STOP_WORDS = new Set([
|
|
|
62
62
|
"interface",
|
|
63
63
|
"etape",
|
|
64
64
|
"étape",
|
|
65
|
+
"click",
|
|
66
|
+
"clicked",
|
|
67
|
+
"clicking",
|
|
68
|
+
"tap",
|
|
69
|
+
"tapped",
|
|
70
|
+
"press",
|
|
71
|
+
"pressed",
|
|
72
|
+
"navigate",
|
|
73
|
+
"navigation",
|
|
74
|
+
"go",
|
|
75
|
+
"goto",
|
|
76
|
+
"open",
|
|
77
|
+
"opening",
|
|
78
|
+
"wait",
|
|
79
|
+
"waiting",
|
|
80
|
+
"load",
|
|
81
|
+
"loaded",
|
|
82
|
+
"loading",
|
|
83
|
+
"select",
|
|
84
|
+
"selected",
|
|
85
|
+
"choose",
|
|
86
|
+
"chosen",
|
|
87
|
+
"pick",
|
|
88
|
+
"picked",
|
|
89
|
+
"launch",
|
|
90
|
+
"launched",
|
|
91
|
+
"continue",
|
|
92
|
+
"continuing",
|
|
93
|
+
"stop",
|
|
94
|
+
"stopping",
|
|
95
|
+
"first",
|
|
96
|
+
"second",
|
|
97
|
+
"third",
|
|
98
|
+
"next",
|
|
99
|
+
"previous",
|
|
100
|
+
"left",
|
|
101
|
+
"right",
|
|
102
|
+
"top",
|
|
103
|
+
"bottom",
|
|
104
|
+
"header",
|
|
105
|
+
"footer",
|
|
106
|
+
"sidebar",
|
|
107
|
+
"toolbar",
|
|
108
|
+
"menu",
|
|
109
|
+
"menus",
|
|
110
|
+
"button",
|
|
111
|
+
"buttons",
|
|
112
|
+
"link",
|
|
113
|
+
"links",
|
|
114
|
+
"new",
|
|
115
|
+
"exact",
|
|
116
|
+
"exactly",
|
|
117
|
+
"fully",
|
|
118
|
+
"ensure",
|
|
119
|
+
"make",
|
|
120
|
+
"sure",
|
|
121
|
+
"should",
|
|
122
|
+
"must",
|
|
123
|
+
"still",
|
|
124
|
+
"just",
|
|
125
|
+
"true",
|
|
126
|
+
"real",
|
|
127
|
+
"launching",
|
|
128
|
+
"lance",
|
|
129
|
+
"lancer",
|
|
130
|
+
"ouvrir",
|
|
131
|
+
"ouvrez",
|
|
132
|
+
"navigue",
|
|
133
|
+
"naviguer",
|
|
134
|
+
"clique",
|
|
135
|
+
"cliquez",
|
|
136
|
+
"attend",
|
|
137
|
+
"attendre",
|
|
138
|
+
"charge",
|
|
139
|
+
"charger",
|
|
140
|
+
"selectionne",
|
|
141
|
+
"sélectionne",
|
|
142
|
+
"selectionner",
|
|
143
|
+
"sélectionner",
|
|
144
|
+
"choisir",
|
|
145
|
+
"choisis",
|
|
146
|
+
"premier",
|
|
147
|
+
"premiere",
|
|
148
|
+
"première",
|
|
149
|
+
"gauche",
|
|
150
|
+
"droite",
|
|
151
|
+
"haut",
|
|
152
|
+
"bas",
|
|
153
|
+
"menu",
|
|
154
|
+
"sidebar",
|
|
155
|
+
"header",
|
|
156
|
+
"bouton",
|
|
157
|
+
"boutons",
|
|
158
|
+
"nouveau",
|
|
159
|
+
"nouvelle",
|
|
160
|
+
"exacte",
|
|
161
|
+
"exactement",
|
|
162
|
+
"entierement",
|
|
163
|
+
"entièrement",
|
|
164
|
+
"assure",
|
|
165
|
+
"assurez",
|
|
166
|
+
"doit",
|
|
167
|
+
"encore",
|
|
168
|
+
"arrete",
|
|
169
|
+
"arrête",
|
|
170
|
+
"arreter",
|
|
171
|
+
"arrêter",
|
|
172
|
+
]);
|
|
173
|
+
const PAGE_ID_STOP_WORDS = new Set([
|
|
174
|
+
...TOKEN_STOP_WORDS,
|
|
175
|
+
"form",
|
|
176
|
+
"editor",
|
|
177
|
+
"edit",
|
|
178
|
+
"modal",
|
|
179
|
+
"dialog",
|
|
180
|
+
"route",
|
|
181
|
+
"screen",
|
|
182
|
+
"detail",
|
|
183
|
+
"details",
|
|
184
|
+
"config",
|
|
185
|
+
"configuration",
|
|
186
|
+
"preview",
|
|
65
187
|
]);
|
|
66
|
-
const
|
|
188
|
+
const COLLECTION_RE = /\b(gallery|grid|list|overview|results?|catalog|library|feed|table|items?|cards?)\b/i;
|
|
67
189
|
const MODAL_RE = /\b(modal|dialog|popup|drawer|overlay)\b/i;
|
|
68
|
-
const
|
|
69
|
-
const CONFIGURATION_RE = /\b(edit|editor|editing|config|configuration|configure|settings|details|detail|instructions|textarea|form|modifier|modification|
|
|
70
|
-
const
|
|
190
|
+
const SELECTION_RE = /\b(select|selection|choose|pick|picker|library|options?|templates?)\b/i;
|
|
191
|
+
const CONFIGURATION_RE = /\b(edit|editor|editing|config|configuration|configure|settings|details|detail|instructions|textarea|form|modifier|modification|edition|customi[sz]e|compose)\b/i;
|
|
192
|
+
const FOCUSED_DETAIL_RE = /\b(first|selected|opened|individual|single|preview|inspect|expanded|zoom(?:ed)?|detail view|item details?)\b/i;
|
|
193
|
+
const STRONG_ROUTE_PROMPT_RE = /\b(route|dedicated page|full page|editor page|edit page|detail page|screen|view|section)\b/i;
|
|
71
194
|
const PASSIVE_STATE_RE = /\b(currently open|already open|currently displayed|already displayed|without launching|ne la lance pas|sans la lancer|deja ouverte|ouverte actuellement)\b/i;
|
|
72
|
-
const DISTINCT_TRANSITION_RE = /\b(save|saved|submitted|created|results|preview|confirmation|pricing|homepage|hero|scratch|blank|empty|different|another|autre|resultat|apercu|confirmation|vide)\b/i;
|
|
73
195
|
function uniqueInOrder(values) {
|
|
74
196
|
const seen = new Set();
|
|
75
197
|
const out = [];
|
|
@@ -90,6 +212,23 @@ function tokenize(value) {
|
|
|
90
212
|
.map((part) => part.trim())
|
|
91
213
|
.filter((part) => part.length >= 3 && !TOKEN_STOP_WORDS.has(part));
|
|
92
214
|
}
|
|
215
|
+
export function normalizeCaptureIdentityTokens(values, options = {}) {
|
|
216
|
+
const stopWords = options.stopWords ?? TOKEN_STOP_WORDS;
|
|
217
|
+
const tokens = [];
|
|
218
|
+
for (const value of values) {
|
|
219
|
+
if (!value)
|
|
220
|
+
continue;
|
|
221
|
+
const parts = value
|
|
222
|
+
.toLowerCase()
|
|
223
|
+
.normalize("NFD")
|
|
224
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
225
|
+
.split(/[^a-z0-9]+/g)
|
|
226
|
+
.map((part) => part.trim())
|
|
227
|
+
.filter((part) => part.length >= 3 && !stopWords.has(part));
|
|
228
|
+
tokens.push(...parts);
|
|
229
|
+
}
|
|
230
|
+
return uniqueInOrder(tokens);
|
|
231
|
+
}
|
|
93
232
|
function normalizeUrlPath(rawUrl) {
|
|
94
233
|
try {
|
|
95
234
|
return new URL(rawUrl).pathname.toLowerCase();
|
|
@@ -98,7 +237,7 @@ function normalizeUrlPath(rawUrl) {
|
|
|
98
237
|
return rawUrl.toLowerCase();
|
|
99
238
|
}
|
|
100
239
|
}
|
|
101
|
-
function
|
|
240
|
+
export function buildCapturePageIdentitySummary(kind, tokens, urlPath) {
|
|
102
241
|
const tokenSummary = tokens.slice(0, 4).join(",");
|
|
103
242
|
const pathSummary = urlPath.replace(/\/+/g, "/").slice(0, 80) || "/";
|
|
104
243
|
return `${kind}:${tokenSummary || "none"}@${pathSummary}`;
|
|
@@ -109,6 +248,38 @@ function normalizeForMatching(value) {
|
|
|
109
248
|
.replace(/[\u0300-\u036f]/g, "")
|
|
110
249
|
.toLowerCase();
|
|
111
250
|
}
|
|
251
|
+
function extractPromptSurfaceHints(rawPrompt) {
|
|
252
|
+
const patterns = [
|
|
253
|
+
/select ([^.]+?),?\s+and capture/i,
|
|
254
|
+
/select ([^.]+?) and stop/i,
|
|
255
|
+
/capture the currently open ([^.]+)/i,
|
|
256
|
+
/capture the ([^.]+?) with [^.]+ visible/i,
|
|
257
|
+
/the page should show ([^.]+)/i,
|
|
258
|
+
/the detail view should show ([^.]+)/i,
|
|
259
|
+
/the page must show ([^.]+)/i,
|
|
260
|
+
/stop (?:only )?when ([^.]+)/i,
|
|
261
|
+
/with ([^.]+?) visible/i,
|
|
262
|
+
/show the full ([^.]+)/i,
|
|
263
|
+
];
|
|
264
|
+
const hints = [];
|
|
265
|
+
for (const pattern of patterns) {
|
|
266
|
+
const match = rawPrompt.match(pattern);
|
|
267
|
+
if (match?.[1]) {
|
|
268
|
+
hints.push(match[1]);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const quoted = Array.from(rawPrompt.matchAll(/["“]([^"”]+)["”]/g), (match) => match[1]);
|
|
272
|
+
hints.push(...quoted);
|
|
273
|
+
return uniqueInOrder(hints.filter(Boolean));
|
|
274
|
+
}
|
|
275
|
+
function extractPathMeaningfulTokens(urlPath) {
|
|
276
|
+
const segments = urlPath
|
|
277
|
+
.split("/")
|
|
278
|
+
.map((segment) => segment.trim())
|
|
279
|
+
.filter(Boolean)
|
|
280
|
+
.filter((segment) => !/^\d+$/.test(segment) && !/^[a-f0-9]{8,}$/i.test(segment));
|
|
281
|
+
return normalizeCaptureIdentityTokens(segments, { stopWords: TOKEN_STOP_WORDS });
|
|
282
|
+
}
|
|
112
283
|
export function inferCapturePageIdentity(pageRun) {
|
|
113
284
|
const rawPrompt = pageRun.prompt.trim();
|
|
114
285
|
const prompt = normalizeForMatching(rawPrompt);
|
|
@@ -118,102 +289,64 @@ export function inferCapturePageIdentity(pageRun) {
|
|
|
118
289
|
// For dialog/modal detection, only use the prompt and URL — page IDs are user-defined
|
|
119
290
|
// identifiers that often contain "modal" or "dialog" as naming convention, not as DOM intent.
|
|
120
291
|
const promptAndUrl = normalizeForMatching(`${rawPrompt} ${urlPath}`);
|
|
121
|
-
const
|
|
122
|
-
const
|
|
292
|
+
const pathSegments = urlPath.split("/").filter(Boolean);
|
|
293
|
+
const hasSpecificPath = pathSegments.length >= 2
|
|
294
|
+
|| pathSegments.some((segment) => /[0-9]/.test(segment) || segment.length >= 12);
|
|
295
|
+
const mentionsCollection = COLLECTION_RE.test(context);
|
|
123
296
|
const mentionsModal = MODAL_RE.test(promptAndUrl);
|
|
124
|
-
const
|
|
297
|
+
const mentionsSelection = SELECTION_RE.test(promptAndUrl);
|
|
125
298
|
const mentionsConfiguration = CONFIGURATION_RE.test(context);
|
|
299
|
+
const mentionsFocusedDetail = FOCUSED_DETAIL_RE.test(prompt);
|
|
126
300
|
const passiveState = PASSIVE_STATE_RE.test(prompt);
|
|
127
|
-
const mentionsDedicatedRoute =
|
|
301
|
+
const mentionsDedicatedRoute = !mentionsModal
|
|
302
|
+
&& !passiveState
|
|
303
|
+
&& (STRONG_ROUTE_PROMPT_RE.test(prompt)
|
|
304
|
+
|| (hasSpecificPath && mentionsConfiguration));
|
|
128
305
|
let kind = "unknown";
|
|
129
|
-
if (
|
|
306
|
+
if (mentionsModal && mentionsSelection && !mentionsConfiguration) {
|
|
307
|
+
kind = "modal_selection";
|
|
308
|
+
}
|
|
309
|
+
else if (mentionsModal && (mentionsConfiguration || passiveState)) {
|
|
310
|
+
kind = "modal_configuration";
|
|
311
|
+
}
|
|
312
|
+
else if (mentionsCollection && mentionsFocusedDetail && !mentionsModal) {
|
|
313
|
+
kind = "detail_route";
|
|
314
|
+
}
|
|
315
|
+
else if (mentionsCollection && !mentionsConfiguration && !mentionsModal && !mentionsSelection) {
|
|
130
316
|
kind = "gallery";
|
|
131
317
|
}
|
|
132
318
|
else if (mentionsConfiguration && mentionsDedicatedRoute && !mentionsModal) {
|
|
133
319
|
kind = "editor_route";
|
|
134
320
|
}
|
|
135
|
-
else if (mentionsConfiguration && (mentionsModal ||
|
|
321
|
+
else if (mentionsConfiguration && (mentionsModal || mentionsSelection || passiveState)) {
|
|
136
322
|
kind = "modal_configuration";
|
|
137
323
|
}
|
|
138
|
-
else if (mentionsModal ||
|
|
324
|
+
else if (mentionsModal || mentionsSelection) {
|
|
139
325
|
kind = "modal_selection";
|
|
140
326
|
}
|
|
141
327
|
else if (mentionsConfiguration) {
|
|
142
328
|
kind = "detail_route";
|
|
143
329
|
}
|
|
144
|
-
else if (
|
|
330
|
+
else if (mentionsCollection) {
|
|
145
331
|
kind = "gallery";
|
|
146
332
|
}
|
|
333
|
+
const promptSurfaceHints = extractPromptSurfaceHints(rawPrompt);
|
|
334
|
+
const promptSubjectTokens = normalizeCaptureIdentityTokens(promptSurfaceHints.length > 0 ? promptSurfaceHints : [rawPrompt]);
|
|
335
|
+
const pathSubjectTokens = extractPathMeaningfulTokens(urlPath);
|
|
336
|
+
const pageIdSubjectTokens = normalizeCaptureIdentityTokens([pageId], {
|
|
337
|
+
stopWords: PAGE_ID_STOP_WORDS,
|
|
338
|
+
});
|
|
147
339
|
const subjectTokens = uniqueInOrder([
|
|
148
|
-
...
|
|
149
|
-
...
|
|
150
|
-
...
|
|
340
|
+
...promptSubjectTokens,
|
|
341
|
+
...pathSubjectTokens,
|
|
342
|
+
...pageIdSubjectTokens,
|
|
151
343
|
]).slice(0, 10);
|
|
152
344
|
return {
|
|
153
345
|
kind,
|
|
154
|
-
summary:
|
|
346
|
+
summary: buildCapturePageIdentitySummary(kind, subjectTokens, urlPath),
|
|
155
347
|
subjectTokens,
|
|
156
348
|
dialogTarget: kind === "modal_selection" || kind === "modal_configuration",
|
|
157
|
-
dedicatedRoute: kind === "editor_route" || (kind === "detail_route" &&
|
|
349
|
+
dedicatedRoute: kind === "editor_route" || (kind === "detail_route" && hasSpecificPath),
|
|
158
350
|
};
|
|
159
351
|
}
|
|
160
|
-
function countTokenOverlap(left, right) {
|
|
161
|
-
if (left.length === 0 || right.length === 0)
|
|
162
|
-
return 0;
|
|
163
|
-
const rightSet = new Set(right);
|
|
164
|
-
return left.filter((token) => rightSet.has(token)).length;
|
|
165
|
-
}
|
|
166
|
-
function urlsPointToSameState(leftUrl, rightUrl) {
|
|
167
|
-
try {
|
|
168
|
-
const left = new URL(leftUrl);
|
|
169
|
-
const right = new URL(rightUrl);
|
|
170
|
-
return left.origin === right.origin && left.pathname === right.pathname;
|
|
171
|
-
}
|
|
172
|
-
catch {
|
|
173
|
-
return leftUrl === rightUrl;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
function promptDeclaresDistinctTransition(prompt) {
|
|
177
|
-
return DISTINCT_TRANSITION_RE.test(normalizeForMatching(prompt));
|
|
178
|
-
}
|
|
179
|
-
export function findVariantPageDefinitionIssues(pageRuns) {
|
|
180
|
-
const issues = [];
|
|
181
|
-
for (let index = 1; index < pageRuns.length; index += 1) {
|
|
182
|
-
const previous = pageRuns[index - 1];
|
|
183
|
-
const current = pageRuns[index];
|
|
184
|
-
const previousIdentity = inferCapturePageIdentity(previous);
|
|
185
|
-
const currentIdentity = inferCapturePageIdentity(current);
|
|
186
|
-
const sameUrl = urlsPointToSameState(previous.url, current.url);
|
|
187
|
-
const overlap = countTokenOverlap(previousIdentity.subjectTokens, currentIdentity.subjectTokens);
|
|
188
|
-
const sameKind = previousIdentity.kind === currentIdentity.kind;
|
|
189
|
-
const passiveState = PASSIVE_STATE_RE.test(normalizeForMatching(current.prompt));
|
|
190
|
-
const lacksDistinctTransition = !promptDeclaresDistinctTransition(current.prompt);
|
|
191
|
-
if (sameUrl
|
|
192
|
-
&& sameKind
|
|
193
|
-
&& previousIdentity.kind !== "unknown"
|
|
194
|
-
&& currentIdentity.kind !== "unknown"
|
|
195
|
-
&& (overlap >= 2 || passiveState)
|
|
196
|
-
&& lacksDistinctTransition) {
|
|
197
|
-
issues.push({
|
|
198
|
-
pageId: current.pageId ?? "main",
|
|
199
|
-
duplicateOfPageId: previous.pageId ?? "main",
|
|
200
|
-
reason: `Named capture "${current.pageId ?? "main"}" is ambiguous with "${previous.pageId ?? "main"}": both target the same ${currentIdentity.kind.replace(/_/g, " ")} state at ${current.url}. ` +
|
|
201
|
-
"Rewrite one prompt to describe a materially different state, or add a URL override for the later page.",
|
|
202
|
-
});
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
if (currentIdentity.dedicatedRoute
|
|
206
|
-
&& previousIdentity.dialogTarget
|
|
207
|
-
&& sameUrl
|
|
208
|
-
&& !promptDeclaresDistinctTransition(current.prompt)) {
|
|
209
|
-
issues.push({
|
|
210
|
-
pageId: current.pageId ?? "main",
|
|
211
|
-
duplicateOfPageId: previous.pageId ?? "main",
|
|
212
|
-
reason: `Named capture "${current.pageId ?? "main"}" expects a dedicated editor/detail route, but it reuses the same URL/state as "${previous.pageId ?? "main"}" without any explicit navigation step. ` +
|
|
213
|
-
"Add a distinct URL override or rewrite the prompt so the target route is unambiguous.",
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return issues;
|
|
218
|
-
}
|
|
219
352
|
//# sourceMappingURL=capture-page-identity.js.map
|
|
@@ -4,9 +4,59 @@ export interface StoredPresetCredentials {
|
|
|
4
4
|
email?: string;
|
|
5
5
|
password?: string;
|
|
6
6
|
}
|
|
7
|
+
export interface StoredPresetAuthCookie {
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
domain: string;
|
|
11
|
+
path?: string;
|
|
12
|
+
}
|
|
13
|
+
export type StoredPresetAuthCookies = StoredPresetAuthCookie[];
|
|
14
|
+
export interface StoredPresetAuthCookiesMeta {
|
|
15
|
+
count: number;
|
|
16
|
+
domains: string[];
|
|
17
|
+
}
|
|
7
18
|
export declare function normalizePresetCredentials(credentials?: Partial<StoredPresetCredentials> | null): StoredPresetCredentials | undefined;
|
|
8
19
|
export declare function hasStoredCredentials(raw: unknown): boolean;
|
|
9
20
|
export declare function encryptPresetCredentials(credentials: StoredPresetCredentials): EncryptedEnvelope;
|
|
10
21
|
export declare function decryptPresetCredentials(value: unknown): StoredPresetCredentials | undefined;
|
|
22
|
+
export declare function normalizePresetAuthCookies(value: unknown): StoredPresetAuthCookies | undefined;
|
|
23
|
+
export declare function encryptPresetAuthCookies(cookies: StoredPresetAuthCookies): EncryptedEnvelope;
|
|
24
|
+
export declare function decryptPresetAuthCookies(value: unknown): StoredPresetAuthCookies | undefined;
|
|
25
|
+
export declare function hasStoredAuthCookies(raw: unknown): boolean;
|
|
26
|
+
export declare function buildAuthCookiesMeta(cookies: StoredPresetAuthCookies): StoredPresetAuthCookiesMeta;
|
|
27
|
+
export interface StorageStateCookie {
|
|
28
|
+
name: string;
|
|
29
|
+
value: string;
|
|
30
|
+
domain: string;
|
|
31
|
+
path: string;
|
|
32
|
+
expires: number;
|
|
33
|
+
httpOnly: boolean;
|
|
34
|
+
secure: boolean;
|
|
35
|
+
sameSite: 'Strict' | 'Lax' | 'None';
|
|
36
|
+
}
|
|
37
|
+
export interface StorageStateOrigin {
|
|
38
|
+
origin: string;
|
|
39
|
+
localStorage: Array<{
|
|
40
|
+
name: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
export interface PlaywrightStorageState {
|
|
45
|
+
cookies: StorageStateCookie[];
|
|
46
|
+
origins: StorageStateOrigin[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Normalize a Playwright storageState payload, dropping anything that doesn't
|
|
50
|
+
* match the expected shape. Returns undefined if the payload is empty (no
|
|
51
|
+
* cookies and no origin data).
|
|
52
|
+
*/
|
|
53
|
+
export declare function normalizeStorageState(value: unknown): PlaywrightStorageState | undefined;
|
|
54
|
+
export declare function encryptStorageState(state: PlaywrightStorageState): EncryptedEnvelope;
|
|
55
|
+
export declare function decryptStorageState(value: unknown): PlaywrightStorageState | undefined;
|
|
56
|
+
export declare function summarizeStorageState(state: PlaywrightStorageState): {
|
|
57
|
+
cookieCount: number;
|
|
58
|
+
originCount: number;
|
|
59
|
+
domains: string[];
|
|
60
|
+
};
|
|
11
61
|
export declare function preparePresetConfigForStorage<T extends Record<string, unknown>>(config: T): T;
|
|
12
62
|
export declare function hydratePresetConfigFromStorage<T extends Record<string, unknown>>(raw: unknown): T;
|