autokap 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/assets/cursors/macos.svg +4 -0
  2. package/assets/cursors/windows.svg +15 -0
  3. package/assets/skill/OPCODE-REFERENCE.md +607 -0
  4. package/assets/skill/README.md +39 -0
  5. package/assets/skill/SKILL.md +453 -468
  6. package/assets/skill/STUDIO-SKILL.md +476 -0
  7. package/assets/skill/references/examples.md +104 -0
  8. package/assets/skill/references/interactive-demo.md +225 -0
  9. package/assets/skill/references/mock-data.md +178 -0
  10. package/dist/action-verifier.d.ts +29 -0
  11. package/dist/action-verifier.js +133 -0
  12. package/dist/agent-action-recovery.d.ts +45 -0
  13. package/dist/agent-action-recovery.js +370 -0
  14. package/dist/agent-message-utils.d.ts +21 -0
  15. package/dist/agent-message-utils.js +77 -0
  16. package/dist/agent-url-utils.d.ts +30 -0
  17. package/dist/agent-url-utils.js +138 -0
  18. package/dist/agent.d.ts +92 -8
  19. package/dist/agent.js +2936 -781
  20. package/dist/ak-tree.d.ts +39 -0
  21. package/dist/ak-tree.js +368 -0
  22. package/dist/alt-text.d.ts +26 -0
  23. package/dist/alt-text.js +55 -0
  24. package/dist/auth-capture.d.ts +17 -0
  25. package/dist/auth-capture.js +164 -0
  26. package/dist/benchmark.d.ts +59 -0
  27. package/dist/benchmark.js +135 -0
  28. package/dist/browser-bar.d.ts +14 -6
  29. package/dist/browser-bar.js +145 -8
  30. package/dist/browser-pool.d.ts +7 -0
  31. package/dist/browser-pool.js +15 -5
  32. package/dist/browser-utils.d.ts +31 -0
  33. package/dist/browser-utils.js +97 -0
  34. package/dist/browser.d.ts +51 -1
  35. package/dist/browser.js +1481 -31
  36. package/dist/capture-alt-text.js +2 -1
  37. package/dist/capture-language-preflight.js +14 -0
  38. package/dist/capture-llm-page-identity.js +22 -10
  39. package/dist/capture-page-identity.d.ts +5 -7
  40. package/dist/capture-page-identity.js +211 -78
  41. package/dist/capture-preset-credentials.d.ts +50 -0
  42. package/dist/capture-preset-credentials.js +127 -0
  43. package/dist/capture-request-plan.d.ts +2 -2
  44. package/dist/capture-request-plan.js +64 -16
  45. package/dist/capture-run-optimizer.js +48 -33
  46. package/dist/capture-selector-memory.d.ts +5 -0
  47. package/dist/capture-selector-memory.js +18 -0
  48. package/dist/capture-strategy.d.ts +36 -0
  49. package/dist/capture-strategy.js +95 -0
  50. package/dist/capture-studio-sync.d.ts +1 -0
  51. package/dist/capture-studio-sync.js +9 -3
  52. package/dist/capture-surface-contract.d.ts +36 -0
  53. package/dist/capture-surface-contract.js +299 -0
  54. package/dist/capture-transition-engine.d.ts +28 -0
  55. package/dist/capture-transition-engine.js +292 -0
  56. package/dist/capture-variant-state.d.ts +2 -0
  57. package/dist/capture-variant-state.js +26 -0
  58. package/dist/capture-verification.d.ts +35 -0
  59. package/dist/capture-verification.js +95 -0
  60. package/dist/capture-viewport-lock.d.ts +48 -0
  61. package/dist/capture-viewport-lock.js +74 -0
  62. package/dist/circuit-breaker.d.ts +42 -0
  63. package/dist/circuit-breaker.js +119 -0
  64. package/dist/cli-config.d.ts +8 -1
  65. package/dist/cli-config.js +62 -6
  66. package/dist/cli-contract.d.ts +15 -0
  67. package/dist/cli-contract.js +167 -0
  68. package/dist/cli-runner-local.d.ts +12 -0
  69. package/dist/cli-runner-local.js +102 -0
  70. package/dist/cli-runner.d.ts +34 -0
  71. package/dist/cli-runner.js +433 -0
  72. package/dist/cli-utils.d.ts +0 -1
  73. package/dist/cli-utils.js +2 -5
  74. package/dist/cli.js +1005 -267
  75. package/dist/clip-orchestrator.js +9 -2
  76. package/dist/clip-postprocess.js +25 -16
  77. package/dist/cookie-dismiss.d.ts +2 -0
  78. package/dist/cookie-dismiss.js +48 -13
  79. package/dist/cost-logging.d.ts +8 -0
  80. package/dist/cost-logging.js +160 -46
  81. package/dist/cost-resolution-monitor.d.ts +16 -0
  82. package/dist/cost-resolution-monitor.js +34 -0
  83. package/dist/credential-templates.js +2 -2
  84. package/dist/cursor-overlay-script.d.ts +6 -0
  85. package/dist/cursor-overlay-script.js +169 -0
  86. package/dist/dom-css-purger.d.ts +65 -0
  87. package/dist/dom-css-purger.js +333 -0
  88. package/dist/dom-font-inliner.d.ts +45 -0
  89. package/dist/dom-font-inliner.js +148 -0
  90. package/dist/dom-patch-resolver.d.ts +52 -0
  91. package/dist/dom-patch-resolver.js +242 -0
  92. package/dist/dom-serializer.d.ts +82 -0
  93. package/dist/dom-serializer.js +378 -0
  94. package/dist/element-capture.d.ts +1 -41
  95. package/dist/element-capture.js +202 -446
  96. package/dist/env-validation.d.ts +5 -0
  97. package/dist/env-validation.js +29 -0
  98. package/dist/execution-schema.d.ts +4423 -0
  99. package/dist/execution-schema.js +507 -0
  100. package/dist/execution-types.d.ts +886 -0
  101. package/dist/execution-types.js +65 -0
  102. package/dist/fonts-loader.d.ts +14 -0
  103. package/dist/fonts-loader.js +55 -0
  104. package/dist/hybrid-navigator.js +12 -12
  105. package/dist/index.d.ts +9 -6
  106. package/dist/index.js +10 -4
  107. package/dist/legacy/agent-action-recovery.d.ts +45 -0
  108. package/dist/legacy/agent-action-recovery.js +370 -0
  109. package/dist/legacy/agent-message-utils.d.ts +21 -0
  110. package/dist/legacy/agent-message-utils.js +77 -0
  111. package/dist/legacy/agent-url-utils.d.ts +30 -0
  112. package/dist/legacy/agent-url-utils.js +138 -0
  113. package/dist/legacy/agent.d.ts +226 -0
  114. package/dist/legacy/agent.js +6666 -0
  115. package/dist/legacy/clip-orchestrator.d.ts +148 -0
  116. package/dist/legacy/clip-orchestrator.js +957 -0
  117. package/dist/legacy/credential-templates.d.ts +5 -0
  118. package/dist/legacy/credential-templates.js +60 -0
  119. package/dist/legacy/hybrid-navigator.d.ts +138 -0
  120. package/dist/legacy/hybrid-navigator.js +468 -0
  121. package/dist/legacy/llm-usage.d.ts +17 -0
  122. package/dist/legacy/llm-usage.js +45 -0
  123. package/dist/legacy/prompt-cache.d.ts +10 -0
  124. package/dist/legacy/prompt-cache.js +24 -0
  125. package/dist/legacy/prompts.d.ts +175 -0
  126. package/dist/legacy/prompts.js +1038 -0
  127. package/dist/legacy/tools.d.ts +4 -0
  128. package/dist/legacy/tools.js +216 -0
  129. package/dist/legacy/video-agent.d.ts +143 -0
  130. package/dist/legacy/video-agent.js +4788 -0
  131. package/dist/legacy/video-observation.d.ts +36 -0
  132. package/dist/legacy/video-observation.js +192 -0
  133. package/dist/legacy/video-planner.d.ts +12 -0
  134. package/dist/legacy/video-planner.js +501 -0
  135. package/dist/legacy/video-prompts.d.ts +37 -0
  136. package/dist/legacy/video-prompts.js +569 -0
  137. package/dist/legacy/video-tools.d.ts +3 -0
  138. package/dist/legacy/video-tools.js +59 -0
  139. package/dist/legacy/video-variant-state.d.ts +29 -0
  140. package/dist/legacy/video-variant-state.js +80 -0
  141. package/dist/legacy/vision-model.d.ts +17 -0
  142. package/dist/legacy/vision-model.js +74 -0
  143. package/dist/llm-healer.d.ts +63 -0
  144. package/dist/llm-healer.js +166 -0
  145. package/dist/llm-provider.d.ts +29 -0
  146. package/dist/llm-provider.js +80 -0
  147. package/dist/logger.d.ts +6 -2
  148. package/dist/logger.js +15 -1
  149. package/dist/mockup-html.js +35 -25
  150. package/dist/mockup.d.ts +95 -2
  151. package/dist/mockup.js +427 -166
  152. package/dist/mouse-animation.d.ts +2 -2
  153. package/dist/mouse-animation.js +34 -20
  154. package/dist/opcode-actions.d.ts +42 -0
  155. package/dist/opcode-actions.js +511 -0
  156. package/dist/opcode-runner.d.ts +51 -0
  157. package/dist/opcode-runner.js +770 -0
  158. package/dist/openrouter-client.d.ts +40 -0
  159. package/dist/openrouter-client.js +16 -0
  160. package/dist/overlay-engine.d.ts +24 -0
  161. package/dist/overlay-engine.js +176 -0
  162. package/dist/postcondition.d.ts +16 -0
  163. package/dist/postcondition.js +269 -0
  164. package/dist/program-patcher.d.ts +25 -0
  165. package/dist/program-patcher.js +44 -0
  166. package/dist/prompts.d.ts +13 -5
  167. package/dist/prompts.js +224 -351
  168. package/dist/provider-config.d.ts +12 -0
  169. package/dist/provider-config.js +15 -0
  170. package/dist/recovery-chain.d.ts +37 -0
  171. package/dist/recovery-chain.js +350 -0
  172. package/dist/remote-browser.d.ts +28 -4
  173. package/dist/remote-browser.js +60 -5
  174. package/dist/safari-browser-bar.d.ts +15 -0
  175. package/dist/safari-browser-bar.js +95 -0
  176. package/dist/safari-toolbar-asset.d.ts +15 -0
  177. package/dist/safari-toolbar-asset.js +12 -0
  178. package/dist/security.d.ts +2 -1
  179. package/dist/security.js +49 -10
  180. package/dist/selector-resolver.d.ts +34 -0
  181. package/dist/selector-resolver.js +181 -0
  182. package/dist/semantic-resolver.d.ts +35 -0
  183. package/dist/semantic-resolver.js +161 -0
  184. package/dist/server-capture-runtime.d.ts +5 -3
  185. package/dist/server-capture-runtime.js +42 -95
  186. package/dist/server-credit-usage.d.ts +2 -2
  187. package/dist/server-project-webhooks.d.ts +15 -1
  188. package/dist/server-project-webhooks.js +34 -8
  189. package/dist/server-screenshot-watermark.js +27 -5
  190. package/dist/session-profile.js +164 -1
  191. package/dist/sf-pro-symbols.d.ts +1 -0
  192. package/dist/sf-pro-symbols.js +55 -0
  193. package/dist/skill-packaging.d.ts +28 -0
  194. package/dist/skill-packaging.js +169 -0
  195. package/dist/smart-wait.d.ts +27 -0
  196. package/dist/smart-wait.js +81 -0
  197. package/dist/status-bar-render.d.ts +20 -0
  198. package/dist/status-bar-render.js +410 -0
  199. package/dist/status-bar.d.ts +9 -0
  200. package/dist/status-bar.js +298 -14
  201. package/dist/svg-browser-bar.d.ts +33 -0
  202. package/dist/svg-browser-bar.js +206 -0
  203. package/dist/svg-status-bar.d.ts +36 -0
  204. package/dist/svg-status-bar.js +597 -0
  205. package/dist/svg-text.d.ts +61 -0
  206. package/dist/svg-text.js +118 -0
  207. package/dist/tools.js +89 -451
  208. package/dist/types.d.ts +240 -5
  209. package/dist/types.js +23 -1
  210. package/dist/v2/action-verifier.d.ts +29 -0
  211. package/dist/v2/action-verifier.js +133 -0
  212. package/dist/v2/alt-text.d.ts +26 -0
  213. package/dist/v2/alt-text.js +55 -0
  214. package/dist/v2/benchmark.d.ts +59 -0
  215. package/dist/v2/benchmark.js +135 -0
  216. package/dist/v2/capture-strategy.d.ts +30 -0
  217. package/dist/v2/capture-strategy.js +67 -0
  218. package/dist/v2/capture-verification.d.ts +35 -0
  219. package/dist/v2/capture-verification.js +95 -0
  220. package/dist/v2/circuit-breaker.d.ts +42 -0
  221. package/dist/v2/circuit-breaker.js +119 -0
  222. package/dist/v2/cli-runner-local.d.ts +11 -0
  223. package/dist/v2/cli-runner-local.js +91 -0
  224. package/dist/v2/cli-runner.d.ts +34 -0
  225. package/dist/v2/cli-runner.js +300 -0
  226. package/dist/v2/compiler-prompts.d.ts +27 -0
  227. package/dist/v2/compiler-prompts.js +123 -0
  228. package/dist/v2/compiler.d.ts +37 -0
  229. package/dist/v2/compiler.js +147 -0
  230. package/dist/v2/explorer.d.ts +41 -0
  231. package/dist/v2/explorer.js +56 -0
  232. package/dist/v2/index.d.ts +37 -0
  233. package/dist/v2/index.js +31 -0
  234. package/dist/v2/llm-healer.d.ts +62 -0
  235. package/dist/v2/llm-healer.js +166 -0
  236. package/dist/v2/llm-provider.d.ts +29 -0
  237. package/dist/v2/llm-provider.js +80 -0
  238. package/dist/v2/opcode-runner.d.ts +47 -0
  239. package/dist/v2/opcode-runner.js +634 -0
  240. package/dist/v2/overlay-engine.d.ts +24 -0
  241. package/dist/v2/overlay-engine.js +150 -0
  242. package/dist/v2/postcondition.d.ts +16 -0
  243. package/dist/v2/postcondition.js +249 -0
  244. package/dist/v2/program-patcher.d.ts +25 -0
  245. package/dist/v2/program-patcher.js +44 -0
  246. package/dist/v2/recovery-chain.d.ts +30 -0
  247. package/dist/v2/recovery-chain.js +368 -0
  248. package/dist/v2/schema.d.ts +2580 -0
  249. package/dist/v2/schema.js +295 -0
  250. package/dist/v2/selector-resolver.d.ts +34 -0
  251. package/dist/v2/selector-resolver.js +181 -0
  252. package/dist/v2/semantic-resolver.d.ts +35 -0
  253. package/dist/v2/semantic-resolver.js +161 -0
  254. package/dist/v2/smart-wait.d.ts +27 -0
  255. package/dist/v2/smart-wait.js +81 -0
  256. package/dist/v2/types.d.ts +444 -0
  257. package/dist/v2/types.js +19 -0
  258. package/dist/v2/web-playwright-local.d.ts +69 -0
  259. package/dist/v2/web-playwright-local.js +392 -0
  260. package/dist/version.d.ts +1 -0
  261. package/dist/version.js +5 -0
  262. package/dist/video-agent.js +18 -13
  263. package/dist/video-planner.js +2 -1
  264. package/dist/video-prompts.js +3 -3
  265. package/dist/web-playwright-local.d.ts +126 -0
  266. package/dist/web-playwright-local.js +819 -0
  267. package/dist/ws-auth.js +4 -1
  268. package/dist/ws-broadcast.d.ts +34 -0
  269. package/dist/ws-broadcast.js +85 -0
  270. package/dist/ws-connection-limits.d.ts +12 -0
  271. package/dist/ws-connection-limits.js +44 -0
  272. package/dist/ws-handler-utils.d.ts +32 -0
  273. package/dist/ws-handler-utils.js +139 -0
  274. package/dist/ws-handler.js +294 -164
  275. package/dist/ws-metrics-server.d.ts +9 -0
  276. package/dist/ws-metrics-server.js +31 -0
  277. package/dist/ws-server.js +41 -1
  278. package/package.json +51 -34
@@ -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: { zdr: true },
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/list overview of screenshots, captures, or presets
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/edit something
25
- - "editor_route": a dedicated full-page editor (e.g., /presets/abc-123/edit)
26
- - "detail_route": a dedicated detail page that is NOT a modal
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], zdr: true } };
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://autokap.app",
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(15_000),
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: `${kind}:${result[pageId].subjectTokens.slice(0, 4).join(",")}@llm`,
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 GALLERY_RE = /\b(gallery|screenshots|captures|overview|dashboard|list|galerie)\b/i;
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 TEMPLATE_RE = /\b(template|templates|picker|selection|select|choose|search templates|start from scratch|new preset|nouveau preset)\b/i;
69
- const CONFIGURATION_RE = /\b(edit|editor|editing|config|configuration|configure|settings|details|detail|instructions|textarea|form|modifier|modification|modifier|edition)\b/i;
70
- const STRONG_ROUTE_PROMPT_RE = /\b(route|dedicated page|full page|editor page|edit page|preset editor|preset edit page|page d[‘’]edition du preset|page de preset)\b/i;
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 summarizeIdentity(kind, tokens, urlPath) {
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 hasPresetRoute = /\/projects\/[^/]+\/presets\/[^/?#]+/i.test(pageRun.url) || /\/presets\/[^/?#]+/i.test(pageRun.url);
122
- const mentionsGallery = GALLERY_RE.test(context);
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 mentionsTemplate = TEMPLATE_RE.test(promptAndUrl);
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 = hasPresetRoute || (STRONG_ROUTE_PROMPT_RE.test(prompt) && !passiveState);
301
+ const mentionsDedicatedRoute = !mentionsModal
302
+ && !passiveState
303
+ && (STRONG_ROUTE_PROMPT_RE.test(prompt)
304
+ || (hasSpecificPath && mentionsConfiguration));
128
305
  let kind = "unknown";
129
- if (mentionsGallery && !mentionsConfiguration && !mentionsModal && !mentionsTemplate) {
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 || mentionsTemplate || passiveState)) {
321
+ else if (mentionsConfiguration && (mentionsModal || mentionsSelection || passiveState)) {
136
322
  kind = "modal_configuration";
137
323
  }
138
- else if (mentionsModal || mentionsTemplate) {
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 (mentionsGallery) {
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
- ...tokenize(pageId),
149
- ...tokenize(prompt),
150
- ...tokenize(urlPath),
340
+ ...promptSubjectTokens,
341
+ ...pathSubjectTokens,
342
+ ...pageIdSubjectTokens,
151
343
  ]).slice(0, 10);
152
344
  return {
153
345
  kind,
154
- summary: summarizeIdentity(kind, subjectTokens, urlPath),
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" && hasPresetRoute),
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;