libretto 0.5.0 → 0.5.1

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 (116) hide show
  1. package/README.md +106 -36
  2. package/dist/cli/cli.js +22 -97
  3. package/dist/cli/commands/browser.js +86 -59
  4. package/dist/cli/commands/execution.js +199 -86
  5. package/dist/cli/commands/init.js +30 -8
  6. package/dist/cli/commands/logs.js +4 -5
  7. package/dist/cli/commands/shared.js +30 -29
  8. package/dist/cli/commands/snapshot.js +26 -39
  9. package/dist/cli/core/ai-config.js +9 -2
  10. package/dist/cli/core/api-snapshot-analyzer.js +15 -5
  11. package/dist/cli/core/browser.js +132 -29
  12. package/dist/cli/core/context.js +4 -1
  13. package/dist/cli/core/session-telemetry.js +5 -2
  14. package/dist/cli/core/session.js +21 -8
  15. package/dist/cli/core/snapshot-analyzer.js +14 -31
  16. package/dist/cli/core/snapshot-api-config.js +2 -6
  17. package/dist/cli/core/telemetry.js +10 -2
  18. package/dist/cli/framework/simple-cli.js +45 -25
  19. package/dist/cli/router.js +14 -21
  20. package/dist/cli/workers/run-integration-runtime.js +24 -5
  21. package/dist/cli/workers/run-integration-worker-protocol.js +3 -1
  22. package/dist/cli/workers/run-integration-worker.js +1 -4
  23. package/dist/index.d.ts +1 -2
  24. package/dist/index.js +7 -10
  25. package/dist/runtime/download/download.js +5 -1
  26. package/dist/runtime/extract/extract.js +11 -2
  27. package/dist/runtime/network/network.js +8 -1
  28. package/dist/runtime/recovery/agent.js +6 -2
  29. package/dist/runtime/recovery/errors.js +3 -1
  30. package/dist/runtime/recovery/recovery.js +3 -1
  31. package/dist/shared/condense-dom/condense-dom.js +6 -13
  32. package/dist/shared/config/config.d.ts +1 -9
  33. package/dist/shared/config/config.js +0 -18
  34. package/dist/shared/config/index.d.ts +2 -1
  35. package/dist/shared/config/index.js +0 -10
  36. package/dist/shared/debug/pause.js +9 -3
  37. package/dist/shared/instrumentation/instrument.js +101 -5
  38. package/dist/shared/llm/ai-sdk-adapter.js +3 -1
  39. package/dist/shared/llm/client.js +3 -1
  40. package/dist/shared/logger/index.js +4 -1
  41. package/dist/shared/run/api.js +3 -1
  42. package/dist/shared/run/browser.js +7 -2
  43. package/dist/shared/state/session-state.d.ts +2 -1
  44. package/dist/shared/state/session-state.js +5 -2
  45. package/dist/shared/visualization/ghost-cursor.js +19 -10
  46. package/dist/shared/visualization/highlight.js +9 -6
  47. package/dist/shared/workflow/workflow.d.ts +4 -5
  48. package/dist/shared/workflow/workflow.js +3 -5
  49. package/package.json +6 -2
  50. package/scripts/check-skills-sync.mjs +25 -0
  51. package/scripts/compare-eval-summary.mjs +47 -0
  52. package/scripts/postinstall.mjs +15 -15
  53. package/scripts/prepare-release.sh +97 -0
  54. package/scripts/skills-libretto.mjs +103 -0
  55. package/scripts/summarize-evals.mjs +135 -0
  56. package/scripts/sync-skills.mjs +12 -0
  57. package/skills/libretto/SKILL.md +113 -49
  58. package/skills/libretto/references/code-generation-rules.md +208 -0
  59. package/skills/libretto/references/configuration-file-reference.md +53 -0
  60. package/skills/libretto/references/site-security-review.md +143 -0
  61. package/src/cli/cli.ts +23 -110
  62. package/src/cli/commands/browser.ts +94 -70
  63. package/src/cli/commands/execution.ts +233 -102
  64. package/src/cli/commands/init.ts +32 -9
  65. package/src/cli/commands/logs.ts +7 -7
  66. package/src/cli/commands/shared.ts +36 -37
  67. package/src/cli/commands/snapshot.ts +44 -59
  68. package/src/cli/core/ai-config.ts +12 -3
  69. package/src/cli/core/api-snapshot-analyzer.ts +17 -6
  70. package/src/cli/core/browser.ts +178 -41
  71. package/src/cli/core/context.ts +7 -2
  72. package/src/cli/core/session-telemetry.ts +19 -8
  73. package/src/cli/core/session.ts +21 -7
  74. package/src/cli/core/snapshot-analyzer.ts +26 -46
  75. package/src/cli/core/snapshot-api-config.ts +170 -175
  76. package/src/cli/core/telemetry.ts +16 -3
  77. package/src/cli/framework/simple-cli.ts +144 -77
  78. package/src/cli/router.ts +13 -21
  79. package/src/cli/workers/run-integration-runtime.ts +36 -9
  80. package/src/cli/workers/run-integration-worker-protocol.ts +2 -0
  81. package/src/cli/workers/run-integration-worker.ts +1 -4
  82. package/src/index.ts +73 -66
  83. package/src/runtime/download/download.ts +62 -58
  84. package/src/runtime/download/index.ts +5 -5
  85. package/src/runtime/extract/extract.ts +71 -61
  86. package/src/runtime/network/index.ts +3 -3
  87. package/src/runtime/network/network.ts +99 -93
  88. package/src/runtime/recovery/agent.ts +217 -212
  89. package/src/runtime/recovery/errors.ts +107 -104
  90. package/src/runtime/recovery/index.ts +3 -3
  91. package/src/runtime/recovery/recovery.ts +38 -35
  92. package/src/shared/condense-dom/condense-dom.ts +15 -18
  93. package/src/shared/config/config.ts +0 -19
  94. package/src/shared/config/index.ts +0 -5
  95. package/src/shared/debug/pause.ts +57 -51
  96. package/src/shared/instrumentation/errors.ts +64 -62
  97. package/src/shared/instrumentation/index.ts +5 -5
  98. package/src/shared/instrumentation/instrument.ts +339 -209
  99. package/src/shared/llm/ai-sdk-adapter.ts +58 -55
  100. package/src/shared/llm/client.ts +181 -174
  101. package/src/shared/llm/types.ts +39 -39
  102. package/src/shared/logger/index.ts +11 -4
  103. package/src/shared/logger/logger.ts +312 -306
  104. package/src/shared/logger/sinks.ts +118 -114
  105. package/src/shared/paths/paths.ts +50 -49
  106. package/src/shared/paths/repo-root.ts +17 -17
  107. package/src/shared/run/api.ts +5 -1
  108. package/src/shared/run/browser.ts +12 -3
  109. package/src/shared/state/index.ts +9 -9
  110. package/src/shared/state/session-state.ts +46 -43
  111. package/src/shared/visualization/ghost-cursor.ts +161 -148
  112. package/src/shared/visualization/highlight.ts +89 -86
  113. package/src/shared/visualization/index.ts +13 -13
  114. package/src/shared/workflow/workflow.ts +19 -25
  115. package/skills/libretto/references/reverse-engineering-network-requests.md +0 -39
  116. package/skills/libretto/references/user-action-log.md +0 -31
@@ -3,25 +3,25 @@ import type z from "zod";
3
3
  import type { MinimalLogger } from "../../shared/logger/logger.js";
4
4
 
5
5
  export type RequestConfig = {
6
- url: string;
7
- method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
8
- headers?: Record<string, string>;
9
- body?: Record<string, any> | string;
10
- /** How to serialize the body. Defaults to "json". */
11
- bodyType?: "json" | "form";
12
- /** How to parse the response. Defaults to "json". */
13
- responseType?: "json" | "text" | "xml";
6
+ url: string;
7
+ method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
8
+ headers?: Record<string, string>;
9
+ body?: Record<string, any> | string;
10
+ /** How to serialize the body. Defaults to "json". */
11
+ bodyType?: "json" | "form";
12
+ /** How to parse the response. Defaults to "json". */
13
+ responseType?: "json" | "text" | "xml";
14
14
  };
15
15
 
16
16
  export type PageRequestOptions<T extends z.ZodType | undefined = undefined> = {
17
- logger?: MinimalLogger;
18
- /** Optional Zod schema to validate the response body. */
19
- schema?: T;
17
+ logger?: MinimalLogger;
18
+ /** Optional Zod schema to validate the response body. */
19
+ schema?: T;
20
20
  };
21
21
 
22
22
  type PageRequestResult<T extends z.ZodType | undefined> = T extends z.ZodType
23
- ? z.infer<T>
24
- : any;
23
+ ? z.infer<T>
24
+ : any;
25
25
 
26
26
  /**
27
27
  * Executes a fetch() call inside the browser context via page.evaluate().
@@ -29,85 +29,91 @@ type PageRequestResult<T extends z.ZodType | undefined> = T extends z.ZodType
29
29
  * validation, and logging.
30
30
  */
31
31
  export async function pageRequest<T extends z.ZodType | undefined = undefined>(
32
- page: Page,
33
- config: RequestConfig,
34
- options?: PageRequestOptions<T>,
32
+ page: Page,
33
+ config: RequestConfig,
34
+ options?: PageRequestOptions<T>,
35
35
  ): Promise<PageRequestResult<T>> {
36
- const { url, method = "GET", headers = {}, body, bodyType = "json", responseType = "json" } = config;
37
- const { logger, schema } = options ?? {};
38
-
39
- const startTime = Date.now();
40
-
41
- // Build fetch options to pass into page.evaluate
42
- const fetchHeaders: Record<string, string> = { ...headers };
43
- let fetchBody: string | undefined;
44
-
45
- if (body !== undefined) {
46
- if (bodyType === "form") {
47
- fetchHeaders["Content-Type"] = "application/x-www-form-urlencoded";
48
- if (typeof body === "string") {
49
- fetchBody = body;
50
- } else {
51
- fetchBody = new URLSearchParams(
52
- Object.entries(body).map(([k, v]) => [k, String(v)]),
53
- ).toString();
54
- }
55
- } else {
56
- fetchHeaders["Content-Type"] = "application/json";
57
- fetchBody = typeof body === "string" ? body : JSON.stringify(body);
58
- }
59
- }
60
-
61
- const result = await page.evaluate(
62
- async ({ url, method, headers, body, responseType }) => {
63
- const res = await fetch(url, {
64
- method,
65
- headers,
66
- body: body ?? undefined,
67
- });
68
-
69
- const status = res.status;
70
- const ok = res.ok;
71
- let data: any;
72
-
73
- if (responseType === "json") {
74
- data = await res.json();
75
- } else {
76
- data = await res.text();
77
- }
78
-
79
- return { status, ok, data };
80
- },
81
- { url, method, headers: fetchHeaders, body: fetchBody, responseType },
82
- );
83
-
84
- const duration = Date.now() - startTime;
85
-
86
- if (!result.ok) {
87
- logger?.warn("network:request:error", {
88
- method,
89
- url,
90
- status: result.status,
91
- duration,
92
- body: typeof result.data === "string"
93
- ? result.data.slice(0, 500)
94
- : undefined,
95
- });
96
- throw new Error(
97
- `pageRequest failed: ${method} ${url} returned ${result.status}`,
98
- );
99
- }
100
-
101
- logger?.info("network:request", {
102
- method,
103
- url,
104
- status: result.status,
105
- duration,
106
- });
107
-
108
- if (schema) {
109
- return schema.parse(result.data) as PageRequestResult<T>;
110
- }
111
-
112
- return result.data as PageRequestResult<T>;
36
+ const {
37
+ url,
38
+ method = "GET",
39
+ headers = {},
40
+ body,
41
+ bodyType = "json",
42
+ responseType = "json",
43
+ } = config;
44
+ const { logger, schema } = options ?? {};
45
+
46
+ const startTime = Date.now();
47
+
48
+ // Build fetch options to pass into page.evaluate
49
+ const fetchHeaders: Record<string, string> = { ...headers };
50
+ let fetchBody: string | undefined;
51
+
52
+ if (body !== undefined) {
53
+ if (bodyType === "form") {
54
+ fetchHeaders["Content-Type"] = "application/x-www-form-urlencoded";
55
+ if (typeof body === "string") {
56
+ fetchBody = body;
57
+ } else {
58
+ fetchBody = new URLSearchParams(
59
+ Object.entries(body).map(([k, v]) => [k, String(v)]),
60
+ ).toString();
61
+ }
62
+ } else {
63
+ fetchHeaders["Content-Type"] = "application/json";
64
+ fetchBody = typeof body === "string" ? body : JSON.stringify(body);
65
+ }
66
+ }
67
+
68
+ const result = await page.evaluate(
69
+ async ({ url, method, headers, body, responseType }) => {
70
+ const res = await fetch(url, {
71
+ method,
72
+ headers,
73
+ body: body ?? undefined,
74
+ });
75
+
76
+ const status = res.status;
77
+ const ok = res.ok;
78
+ let data: any;
79
+
80
+ if (responseType === "json") {
81
+ data = await res.json();
82
+ } else {
83
+ data = await res.text();
84
+ }
85
+
86
+ return { status, ok, data };
87
+ },
88
+ { url, method, headers: fetchHeaders, body: fetchBody, responseType },
89
+ );
90
+
91
+ const duration = Date.now() - startTime;
92
+
93
+ if (!result.ok) {
94
+ logger?.warn("network:request:error", {
95
+ method,
96
+ url,
97
+ status: result.status,
98
+ duration,
99
+ body:
100
+ typeof result.data === "string" ? result.data.slice(0, 500) : undefined,
101
+ });
102
+ throw new Error(
103
+ `pageRequest failed: ${method} ${url} returned ${result.status}`,
104
+ );
105
+ }
106
+
107
+ logger?.info("network:request", {
108
+ method,
109
+ url,
110
+ status: result.status,
111
+ duration,
112
+ });
113
+
114
+ if (schema) {
115
+ return schema.parse(result.data) as PageRequestResult<T>;
116
+ }
117
+
118
+ return result.data as PageRequestResult<T>;
113
119
  }