libretto 0.5.3-experimental.5 → 0.5.3

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 (126) hide show
  1. package/README.md +114 -37
  2. package/README.template.md +160 -0
  3. package/dist/cli/cli.js +22 -97
  4. package/dist/cli/commands/browser.js +86 -59
  5. package/dist/cli/commands/deploy.js +148 -0
  6. package/dist/cli/commands/execution.js +218 -96
  7. package/dist/cli/commands/init.js +34 -29
  8. package/dist/cli/commands/logs.js +4 -5
  9. package/dist/cli/commands/shared.js +30 -29
  10. package/dist/cli/commands/snapshot.js +26 -39
  11. package/dist/cli/core/ai-config.js +21 -4
  12. package/dist/cli/core/api-snapshot-analyzer.js +15 -5
  13. package/dist/cli/core/browser.js +207 -37
  14. package/dist/cli/core/context.js +4 -1
  15. package/dist/cli/core/deploy-artifact.js +687 -0
  16. package/dist/cli/core/session-telemetry.js +434 -174
  17. package/dist/cli/core/session.js +21 -8
  18. package/dist/cli/core/snapshot-analyzer.js +14 -31
  19. package/dist/cli/core/snapshot-api-config.js +2 -6
  20. package/dist/cli/core/telemetry.js +20 -4
  21. package/dist/cli/framework/simple-cli.js +144 -43
  22. package/dist/cli/router.js +16 -21
  23. package/dist/cli/workers/run-integration-runtime.js +25 -45
  24. package/dist/cli/workers/run-integration-worker-protocol.js +3 -2
  25. package/dist/cli/workers/run-integration-worker.js +1 -4
  26. package/dist/index.d.ts +1 -2
  27. package/dist/index.js +13 -10
  28. package/dist/runtime/download/download.js +5 -1
  29. package/dist/runtime/extract/extract.js +11 -2
  30. package/dist/runtime/network/network.js +8 -1
  31. package/dist/runtime/recovery/agent.js +6 -2
  32. package/dist/runtime/recovery/errors.js +3 -1
  33. package/dist/runtime/recovery/recovery.js +3 -1
  34. package/dist/shared/condense-dom/condense-dom.js +17 -69
  35. package/dist/shared/config/config.d.ts +1 -9
  36. package/dist/shared/config/config.js +0 -18
  37. package/dist/shared/config/index.d.ts +2 -1
  38. package/dist/shared/config/index.js +0 -10
  39. package/dist/shared/debug/pause.js +9 -3
  40. package/dist/shared/dom-semantics.d.ts +8 -0
  41. package/dist/shared/dom-semantics.js +69 -0
  42. package/dist/shared/instrumentation/instrument.js +101 -5
  43. package/dist/shared/llm/ai-sdk-adapter.js +3 -1
  44. package/dist/shared/llm/client.js +3 -1
  45. package/dist/shared/logger/index.js +4 -1
  46. package/dist/shared/run/api.js +3 -1
  47. package/dist/shared/run/browser.js +47 -3
  48. package/dist/shared/state/session-state.d.ts +2 -1
  49. package/dist/shared/state/session-state.js +5 -2
  50. package/dist/shared/visualization/ghost-cursor.js +36 -14
  51. package/dist/shared/visualization/highlight.js +9 -6
  52. package/dist/shared/workflow/workflow.d.ts +18 -10
  53. package/dist/shared/workflow/workflow.js +50 -5
  54. package/package.json +14 -6
  55. package/scripts/generate-changelog.ts +132 -0
  56. package/scripts/postinstall.mjs +4 -3
  57. package/scripts/skills-libretto.mjs +2 -88
  58. package/scripts/summarize-evals.mjs +32 -10
  59. package/skills/libretto/SKILL.md +132 -62
  60. package/skills/libretto/references/action-logs.md +101 -0
  61. package/skills/libretto/references/auth-profiles.md +1 -2
  62. package/skills/libretto/references/code-generation-rules.md +176 -0
  63. package/skills/libretto/references/configuration-file-reference.md +53 -0
  64. package/skills/libretto/references/pages-and-page-targeting.md +1 -1
  65. package/skills/libretto/references/site-security-review.md +143 -0
  66. package/src/cli/cli.ts +23 -110
  67. package/src/cli/commands/browser.ts +94 -70
  68. package/src/cli/commands/deploy.ts +198 -0
  69. package/src/cli/commands/execution.ts +251 -111
  70. package/src/cli/commands/init.ts +37 -33
  71. package/src/cli/commands/logs.ts +7 -7
  72. package/src/cli/commands/shared.ts +36 -37
  73. package/src/cli/commands/snapshot.ts +44 -59
  74. package/src/cli/core/ai-config.ts +24 -4
  75. package/src/cli/core/api-snapshot-analyzer.ts +17 -6
  76. package/src/cli/core/browser.ts +260 -49
  77. package/src/cli/core/context.ts +7 -2
  78. package/src/cli/core/deploy-artifact.ts +938 -0
  79. package/src/cli/core/session-telemetry.ts +449 -197
  80. package/src/cli/core/session.ts +21 -7
  81. package/src/cli/core/snapshot-analyzer.ts +26 -46
  82. package/src/cli/core/snapshot-api-config.ts +170 -175
  83. package/src/cli/core/telemetry.ts +39 -4
  84. package/src/cli/framework/simple-cli.ts +281 -98
  85. package/src/cli/router.ts +15 -21
  86. package/src/cli/workers/run-integration-runtime.ts +35 -57
  87. package/src/cli/workers/run-integration-worker-protocol.ts +2 -1
  88. package/src/cli/workers/run-integration-worker.ts +1 -4
  89. package/src/index.ts +77 -67
  90. package/src/runtime/download/download.ts +62 -58
  91. package/src/runtime/download/index.ts +5 -5
  92. package/src/runtime/extract/extract.ts +71 -61
  93. package/src/runtime/network/index.ts +3 -3
  94. package/src/runtime/network/network.ts +99 -93
  95. package/src/runtime/recovery/agent.ts +217 -212
  96. package/src/runtime/recovery/errors.ts +107 -104
  97. package/src/runtime/recovery/index.ts +3 -3
  98. package/src/runtime/recovery/recovery.ts +38 -35
  99. package/src/shared/condense-dom/condense-dom.ts +27 -82
  100. package/src/shared/config/config.ts +0 -19
  101. package/src/shared/config/index.ts +0 -5
  102. package/src/shared/debug/pause.ts +57 -51
  103. package/src/shared/dom-semantics.ts +68 -0
  104. package/src/shared/instrumentation/errors.ts +64 -62
  105. package/src/shared/instrumentation/index.ts +5 -5
  106. package/src/shared/instrumentation/instrument.ts +339 -209
  107. package/src/shared/llm/ai-sdk-adapter.ts +58 -55
  108. package/src/shared/llm/client.ts +181 -174
  109. package/src/shared/llm/types.ts +39 -39
  110. package/src/shared/logger/index.ts +11 -4
  111. package/src/shared/logger/logger.ts +312 -306
  112. package/src/shared/logger/sinks.ts +118 -114
  113. package/src/shared/paths/paths.ts +50 -49
  114. package/src/shared/paths/repo-root.ts +17 -17
  115. package/src/shared/run/api.ts +5 -1
  116. package/src/shared/run/browser.ts +65 -3
  117. package/src/shared/state/index.ts +9 -9
  118. package/src/shared/state/session-state.ts +46 -43
  119. package/src/shared/visualization/ghost-cursor.ts +180 -149
  120. package/src/shared/visualization/highlight.ts +89 -86
  121. package/src/shared/visualization/index.ts +13 -13
  122. package/src/shared/workflow/workflow.ts +107 -30
  123. package/scripts/check-skills-sync.mjs +0 -23
  124. package/scripts/prepare-release.sh +0 -97
  125. package/skills/libretto/references/reverse-engineering-network-requests.md +0 -75
  126. package/skills/libretto/references/user-action-log.md +0 -31
@@ -0,0 +1,68 @@
1
+ export const TEST_ATTRIBUTE_NAMES = [
2
+ "data-testid",
3
+ "data-test",
4
+ "data-qa",
5
+ "data-cy",
6
+ ] as const;
7
+
8
+ export const TRUSTED_ATTRIBUTE_NAMES = [
9
+ "id",
10
+ "name",
11
+ "for",
12
+ "tabindex",
13
+ "contenteditable",
14
+ "role",
15
+ "title",
16
+ "alt",
17
+ "type",
18
+ "value",
19
+ "placeholder",
20
+ "autocomplete",
21
+ "href",
22
+ "action",
23
+ "method",
24
+ "src",
25
+ ] as const;
26
+
27
+ export const INTERACTIVE_TAG_NAMES = [
28
+ "a",
29
+ "button",
30
+ "input",
31
+ "select",
32
+ "textarea",
33
+ "form",
34
+ "details",
35
+ "dialog",
36
+ "label",
37
+ ] as const;
38
+
39
+ export const INTERACTIVE_ROLE_NAMES = [
40
+ "button",
41
+ "link",
42
+ "tab",
43
+ "menuitem",
44
+ "checkbox",
45
+ "radio",
46
+ "switch",
47
+ "slider",
48
+ "combobox",
49
+ ] as const;
50
+
51
+ export function filterSemanticClasses(value: string): string {
52
+ const classes = value.split(/\s+/).filter(Boolean);
53
+ const kept = classes.filter((cls) => !isObfuscatedClass(cls));
54
+ return kept.join(" ");
55
+ }
56
+
57
+ export function isObfuscatedClass(cls: string): boolean {
58
+ if (cls.length > 80) return true;
59
+ if (/^_?[0-9a-f]{6,}$/i.test(cls)) return true;
60
+ if (/^[a-z]+_[0-9a-f]{4,}$/i.test(cls)) return true;
61
+ if (/^[a-z]{1,2}[0-9]{2,}$/i.test(cls)) return true;
62
+
63
+ const digits = (cls.match(/[0-9]/g) || []).length;
64
+ const letters = (cls.match(/[a-zA-Z]/g) || []).length;
65
+ if (cls.length >= 6 && digits >= letters * 0.5 && digits >= 2) return true;
66
+
67
+ return false;
68
+ }
@@ -8,75 +8,77 @@ import type { Page, Locator } from "playwright";
8
8
  * Best-effort: if any probe fails, we skip that check silently.
9
9
  */
10
10
  export async function enrichTimeoutError(
11
- err: any,
12
- locator: Locator,
13
- page: Page,
11
+ err: any,
12
+ locator: Locator,
13
+ page: Page,
14
14
  ): Promise<void> {
15
- const reasons: string[] = [];
15
+ const reasons: string[] = [];
16
16
 
17
- try {
18
- const visible = await locator.isVisible().catch(() => null);
19
- if (visible === false) {
20
- reasons.push("Element is not visible");
21
- }
17
+ try {
18
+ const visible = await locator.isVisible().catch(() => null);
19
+ if (visible === false) {
20
+ reasons.push("Element is not visible");
21
+ }
22
22
 
23
- // isInViewport is available in modern Playwright but may not exist in older versions
24
- if (typeof (locator as any).isInViewport === "function") {
25
- const inViewport = await (locator as any).isInViewport().catch(() => null);
26
- if (inViewport === false) {
27
- reasons.push("Element is outside of the viewport");
28
- }
29
- }
23
+ // isInViewport is available in modern Playwright but may not exist in older versions
24
+ if (typeof (locator as any).isInViewport === "function") {
25
+ const inViewport = await (locator as any)
26
+ .isInViewport()
27
+ .catch(() => null);
28
+ if (inViewport === false) {
29
+ reasons.push("Element is outside of the viewport");
30
+ }
31
+ }
30
32
 
31
- const enabled = await locator.isEnabled().catch(() => null);
32
- if (enabled === false) {
33
- reasons.push("Element is not enabled (disabled)");
34
- }
33
+ const enabled = await locator.isEnabled().catch(() => null);
34
+ if (enabled === false) {
35
+ reasons.push("Element is not enabled (disabled)");
36
+ }
35
37
 
36
- // If the element appears visible and in viewport, check for intercepting elements
37
- if (reasons.length === 0) {
38
- const box = await locator.boundingBox().catch(() => null);
39
- if (box) {
40
- const centerX = box.x + box.width / 2;
41
- const centerY = box.y + box.height / 2;
38
+ // If the element appears visible and in viewport, check for intercepting elements
39
+ if (reasons.length === 0) {
40
+ const box = await locator.boundingBox().catch(() => null);
41
+ if (box) {
42
+ const centerX = box.x + box.width / 2;
43
+ const centerY = box.y + box.height / 2;
42
44
 
43
- const interceptInfo = await page
44
- .evaluate(
45
- ({ x, y }) => {
46
- const els = document.elementsFromPoint(x, y);
47
- if (!els || els.length < 2) return null;
48
- const topEl = els[0];
49
- if (!topEl) return null;
45
+ const interceptInfo = await page
46
+ .evaluate(
47
+ ({ x, y }) => {
48
+ const els = document.elementsFromPoint(x, y);
49
+ if (!els || els.length < 2) return null;
50
+ const topEl = els[0];
51
+ if (!topEl) return null;
50
52
 
51
- // Build a brief preview of the intercepting element
52
- const tag = topEl.tagName.toLowerCase();
53
- const id = topEl.id ? `#${topEl.id}` : "";
54
- const cls = topEl.className
55
- ? `.${String(topEl.className).split(/\s+/).slice(0, 2).join(".")}`
56
- : "";
57
- const text = (topEl.textContent || "").trim().slice(0, 40);
58
- return {
59
- tag,
60
- preview: `<${tag}${id}${cls}>${text ? ` "${text}"` : ""}`,
61
- };
62
- },
63
- { x: centerX, y: centerY },
64
- )
65
- .catch(() => null);
53
+ // Build a brief preview of the intercepting element
54
+ const tag = topEl.tagName.toLowerCase();
55
+ const id = topEl.id ? `#${topEl.id}` : "";
56
+ const cls = topEl.className
57
+ ? `.${String(topEl.className).split(/\s+/).slice(0, 2).join(".")}`
58
+ : "";
59
+ const text = (topEl.textContent || "").trim().slice(0, 40);
60
+ return {
61
+ tag,
62
+ preview: `<${tag}${id}${cls}>${text ? ` "${text}"` : ""}`,
63
+ };
64
+ },
65
+ { x: centerX, y: centerY },
66
+ )
67
+ .catch(() => null);
66
68
 
67
- if (interceptInfo) {
68
- reasons.push(
69
- `Element may be intercepted by ${interceptInfo.preview}`,
70
- );
71
- }
72
- }
73
- }
74
- } catch {
75
- // All enrichment is best-effort
76
- }
69
+ if (interceptInfo) {
70
+ reasons.push(
71
+ `Element may be intercepted by ${interceptInfo.preview}`,
72
+ );
73
+ }
74
+ }
75
+ }
76
+ } catch {
77
+ // All enrichment is best-effort
78
+ }
77
79
 
78
- if (reasons.length > 0) {
79
- const enrichment = `\n[libretto diagnostics] ${reasons.join("; ")}`;
80
- err.message = (err.message || "") + enrichment;
81
- }
80
+ if (reasons.length > 0) {
81
+ const enrichment = `\n[libretto diagnostics] ${reasons.join("; ")}`;
82
+ err.message = (err.message || "") + enrichment;
83
+ }
82
84
  }
@@ -1,9 +1,9 @@
1
1
  export {
2
- instrumentPage,
3
- installInstrumentation,
4
- instrumentContext,
5
- type InstrumentationOptions,
6
- type InstrumentedPage,
2
+ instrumentPage,
3
+ installInstrumentation,
4
+ instrumentContext,
5
+ type InstrumentationOptions,
6
+ type InstrumentedPage,
7
7
  } from "./instrument.js";
8
8
 
9
9
  export { enrichTimeoutError } from "./errors.js";