libretto 0.4.4 → 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 (194) hide show
  1. package/README.md +106 -36
  2. package/dist/cli/cli.js +39 -113
  3. package/dist/cli/commands/ai.js +1 -1
  4. package/dist/cli/commands/browser.js +87 -60
  5. package/dist/cli/commands/execution.js +201 -88
  6. package/dist/cli/commands/init.js +30 -8
  7. package/dist/cli/commands/logs.js +5 -6
  8. package/dist/cli/commands/shared.js +30 -29
  9. package/dist/cli/commands/snapshot.js +26 -39
  10. package/dist/cli/core/ai-config.js +9 -2
  11. package/dist/cli/core/api-snapshot-analyzer.js +15 -5
  12. package/dist/cli/core/browser.js +141 -33
  13. package/dist/cli/core/context.js +7 -18
  14. package/dist/cli/core/session-telemetry.js +5 -2
  15. package/dist/cli/core/session.js +23 -10
  16. package/dist/cli/core/snapshot-analyzer.js +16 -33
  17. package/dist/cli/core/snapshot-api-config.js +2 -6
  18. package/dist/cli/core/telemetry.js +10 -2
  19. package/dist/cli/framework/simple-cli.js +45 -25
  20. package/dist/cli/router.js +14 -21
  21. package/dist/cli/workers/run-integration-runtime.js +26 -7
  22. package/dist/cli/workers/run-integration-worker-protocol.js +3 -1
  23. package/dist/cli/workers/run-integration-worker.js +1 -4
  24. package/dist/index.d.ts +1 -2
  25. package/dist/index.js +7 -10
  26. package/dist/runtime/download/download.js +5 -1
  27. package/dist/runtime/extract/extract.js +11 -2
  28. package/dist/runtime/network/network.js +8 -1
  29. package/dist/runtime/recovery/agent.js +6 -2
  30. package/dist/runtime/recovery/errors.js +3 -1
  31. package/dist/runtime/recovery/recovery.js +3 -1
  32. package/dist/shared/condense-dom/condense-dom.js +6 -13
  33. package/dist/shared/config/config.d.ts +1 -9
  34. package/dist/shared/config/config.js +0 -18
  35. package/dist/shared/config/index.d.ts +2 -1
  36. package/dist/shared/config/index.js +0 -10
  37. package/dist/shared/debug/pause.js +9 -3
  38. package/dist/shared/instrumentation/instrument.js +101 -5
  39. package/dist/shared/llm/ai-sdk-adapter.js +3 -1
  40. package/dist/shared/llm/client.js +3 -1
  41. package/dist/shared/logger/index.js +4 -1
  42. package/dist/shared/paths/paths.js +2 -1
  43. package/dist/shared/paths/repo-root.d.ts +3 -0
  44. package/dist/shared/paths/repo-root.js +24 -0
  45. package/dist/shared/run/api.js +3 -1
  46. package/dist/shared/run/browser.js +7 -2
  47. package/dist/shared/state/session-state.d.ts +2 -1
  48. package/dist/shared/state/session-state.js +5 -2
  49. package/dist/shared/visualization/ghost-cursor.js +19 -10
  50. package/dist/shared/visualization/highlight.js +9 -6
  51. package/dist/shared/workflow/workflow.d.ts +4 -5
  52. package/dist/shared/workflow/workflow.js +3 -5
  53. package/package.json +11 -8
  54. package/scripts/check-skills-sync.mjs +25 -0
  55. package/scripts/compare-eval-summary.mjs +47 -0
  56. package/scripts/postinstall.mjs +26 -17
  57. package/scripts/prepare-release.sh +97 -0
  58. package/scripts/skills-libretto.mjs +103 -0
  59. package/scripts/summarize-evals.mjs +135 -0
  60. package/scripts/sync-skills.mjs +12 -0
  61. package/skills/libretto/SKILL.md +130 -377
  62. package/skills/libretto/references/auth-profiles.md +30 -0
  63. package/skills/libretto/{code-generation-rules.md → references/code-generation-rules.md} +27 -42
  64. package/skills/libretto/references/configuration-file-reference.md +53 -0
  65. package/skills/libretto/references/pages-and-page-targeting.md +29 -0
  66. package/skills/libretto/references/site-security-review.md +143 -0
  67. package/src/cli/cli.ts +86 -0
  68. package/src/cli/commands/ai.ts +35 -0
  69. package/src/cli/commands/browser.ts +189 -0
  70. package/src/cli/commands/execution.ts +822 -0
  71. package/src/cli/commands/init.ts +350 -0
  72. package/src/cli/commands/logs.ts +128 -0
  73. package/src/cli/commands/shared.ts +69 -0
  74. package/src/cli/commands/snapshot.ts +312 -0
  75. package/src/cli/core/ai-config.ts +264 -0
  76. package/src/cli/core/api-snapshot-analyzer.ts +108 -0
  77. package/src/cli/core/browser.ts +976 -0
  78. package/src/cli/core/context.ts +127 -0
  79. package/src/cli/core/pause-signals.ts +35 -0
  80. package/src/cli/core/session-telemetry.ts +564 -0
  81. package/src/cli/core/session.ts +223 -0
  82. package/src/cli/core/snapshot-analyzer.ts +855 -0
  83. package/src/cli/core/snapshot-api-config.ts +231 -0
  84. package/src/cli/core/telemetry.ts +459 -0
  85. package/src/cli/framework/simple-cli.ts +1340 -0
  86. package/src/cli/index.ts +13 -0
  87. package/src/cli/router.ts +20 -0
  88. package/src/cli/workers/run-integration-runtime.ts +338 -0
  89. package/src/cli/workers/run-integration-worker-protocol.ts +16 -0
  90. package/src/cli/workers/run-integration-worker.ts +72 -0
  91. package/src/index.ts +127 -0
  92. package/src/runtime/download/download.ts +104 -0
  93. package/src/runtime/download/index.ts +7 -0
  94. package/src/runtime/extract/extract.ts +102 -0
  95. package/src/runtime/extract/index.ts +1 -0
  96. package/src/runtime/network/index.ts +5 -0
  97. package/src/runtime/network/network.ts +119 -0
  98. package/{dist/runtime/recovery/agent.cjs → src/runtime/recovery/agent.ts} +114 -76
  99. package/src/runtime/recovery/errors.ts +155 -0
  100. package/src/runtime/recovery/index.ts +7 -0
  101. package/src/runtime/recovery/recovery.ts +53 -0
  102. package/{dist/shared/condense-dom/condense-dom.cjs → src/shared/condense-dom/condense-dom.ts} +249 -124
  103. package/src/shared/config/config.ts +3 -0
  104. package/src/shared/config/index.ts +0 -0
  105. package/src/shared/debug/index.ts +1 -0
  106. package/src/shared/debug/pause.ts +91 -0
  107. package/src/shared/instrumentation/errors.ts +84 -0
  108. package/src/shared/instrumentation/index.ts +9 -0
  109. package/src/shared/instrumentation/instrument.ts +406 -0
  110. package/src/shared/llm/ai-sdk-adapter.ts +81 -0
  111. package/{dist/shared/llm/client.cjs → src/shared/llm/client.ts} +86 -80
  112. package/src/shared/llm/index.ts +3 -0
  113. package/src/shared/llm/types.ts +63 -0
  114. package/src/shared/logger/index.ts +13 -0
  115. package/src/shared/logger/logger.ts +358 -0
  116. package/src/shared/logger/sinks.ts +148 -0
  117. package/src/shared/paths/paths.ts +110 -0
  118. package/src/shared/paths/repo-root.ts +27 -0
  119. package/src/shared/run/api.ts +6 -0
  120. package/src/shared/run/browser.ts +107 -0
  121. package/src/shared/state/index.ts +11 -0
  122. package/src/shared/state/session-state.ts +77 -0
  123. package/src/shared/visualization/ghost-cursor.ts +213 -0
  124. package/src/shared/visualization/highlight.ts +149 -0
  125. package/src/shared/visualization/index.ts +18 -0
  126. package/src/shared/workflow/workflow.ts +36 -0
  127. package/dist/index.cjs +0 -144
  128. package/dist/index.d.cts +0 -21
  129. package/dist/runtime/download/download.cjs +0 -70
  130. package/dist/runtime/download/download.d.cts +0 -35
  131. package/dist/runtime/download/index.cjs +0 -30
  132. package/dist/runtime/download/index.d.cts +0 -3
  133. package/dist/runtime/extract/extract.cjs +0 -88
  134. package/dist/runtime/extract/extract.d.cts +0 -23
  135. package/dist/runtime/extract/index.cjs +0 -28
  136. package/dist/runtime/extract/index.d.cts +0 -5
  137. package/dist/runtime/network/index.cjs +0 -28
  138. package/dist/runtime/network/index.d.cts +0 -4
  139. package/dist/runtime/network/network.cjs +0 -91
  140. package/dist/runtime/network/network.d.cts +0 -28
  141. package/dist/runtime/recovery/agent.d.cts +0 -13
  142. package/dist/runtime/recovery/errors.cjs +0 -124
  143. package/dist/runtime/recovery/errors.d.cts +0 -31
  144. package/dist/runtime/recovery/index.cjs +0 -34
  145. package/dist/runtime/recovery/index.d.cts +0 -7
  146. package/dist/runtime/recovery/recovery.cjs +0 -55
  147. package/dist/runtime/recovery/recovery.d.cts +0 -12
  148. package/dist/shared/condense-dom/condense-dom.d.cts +0 -34
  149. package/dist/shared/config/config.cjs +0 -44
  150. package/dist/shared/config/config.d.cts +0 -10
  151. package/dist/shared/config/index.cjs +0 -32
  152. package/dist/shared/config/index.d.cts +0 -1
  153. package/dist/shared/debug/index.cjs +0 -28
  154. package/dist/shared/debug/index.d.cts +0 -1
  155. package/dist/shared/debug/pause.cjs +0 -86
  156. package/dist/shared/debug/pause.d.cts +0 -12
  157. package/dist/shared/instrumentation/errors.cjs +0 -81
  158. package/dist/shared/instrumentation/errors.d.cts +0 -12
  159. package/dist/shared/instrumentation/index.cjs +0 -35
  160. package/dist/shared/instrumentation/index.d.cts +0 -6
  161. package/dist/shared/instrumentation/instrument.cjs +0 -206
  162. package/dist/shared/instrumentation/instrument.d.cts +0 -32
  163. package/dist/shared/llm/ai-sdk-adapter.cjs +0 -71
  164. package/dist/shared/llm/ai-sdk-adapter.d.cts +0 -22
  165. package/dist/shared/llm/client.d.cts +0 -13
  166. package/dist/shared/llm/index.cjs +0 -31
  167. package/dist/shared/llm/index.d.cts +0 -5
  168. package/dist/shared/llm/types.cjs +0 -16
  169. package/dist/shared/llm/types.d.cts +0 -67
  170. package/dist/shared/logger/index.cjs +0 -37
  171. package/dist/shared/logger/index.d.cts +0 -2
  172. package/dist/shared/logger/logger.cjs +0 -232
  173. package/dist/shared/logger/logger.d.cts +0 -86
  174. package/dist/shared/logger/sinks.cjs +0 -160
  175. package/dist/shared/logger/sinks.d.cts +0 -9
  176. package/dist/shared/paths/paths.cjs +0 -104
  177. package/dist/shared/paths/paths.d.cts +0 -10
  178. package/dist/shared/run/api.cjs +0 -28
  179. package/dist/shared/run/api.d.cts +0 -2
  180. package/dist/shared/run/browser.cjs +0 -98
  181. package/dist/shared/run/browser.d.cts +0 -22
  182. package/dist/shared/state/index.cjs +0 -38
  183. package/dist/shared/state/index.d.cts +0 -2
  184. package/dist/shared/state/session-state.cjs +0 -92
  185. package/dist/shared/state/session-state.d.cts +0 -40
  186. package/dist/shared/visualization/ghost-cursor.cjs +0 -174
  187. package/dist/shared/visualization/ghost-cursor.d.cts +0 -37
  188. package/dist/shared/visualization/highlight.cjs +0 -134
  189. package/dist/shared/visualization/highlight.d.cts +0 -22
  190. package/dist/shared/visualization/index.cjs +0 -45
  191. package/dist/shared/visualization/index.d.cts +0 -3
  192. package/dist/shared/workflow/workflow.cjs +0 -47
  193. package/dist/shared/workflow/workflow.d.cts +0 -21
  194. package/skills/libretto/integration-approach-selection.md +0 -174
@@ -0,0 +1,223 @@
1
+ import {
2
+ existsSync,
3
+ mkdirSync,
4
+ readFileSync,
5
+ readdirSync,
6
+ unlinkSync,
7
+ writeFileSync,
8
+ } from "node:fs";
9
+ import type { LoggerApi } from "../../shared/logger/index.js";
10
+ import {
11
+ getSessionDir,
12
+ getSessionLogsPath,
13
+ getSessionStatePath,
14
+ LIBRETTO_SESSIONS_DIR,
15
+ } from "./context.js";
16
+ import {
17
+ SESSION_STATE_VERSION,
18
+ parseSessionStateContent,
19
+ serializeSessionState,
20
+ type SessionStatus,
21
+ type SessionState,
22
+ } from "../../shared/state/index.js";
23
+
24
+ const SESSION_NAME_PATTERN = /^[a-zA-Z0-9._-]+$/;
25
+
26
+ export const SESSION_DEV_SERVER = "dev-server";
27
+ export const SESSION_BROWSER_AGENT = "browser-agent";
28
+
29
+ export function generateSessionName(): string {
30
+ const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
31
+ let id = "";
32
+ for (let i = 0; i < 4; i++) {
33
+ id += chars[Math.floor(Math.random() * chars.length)];
34
+ }
35
+ return `ses-${id}`;
36
+ }
37
+ export { SESSION_STATE_VERSION };
38
+ export type { SessionStatus, SessionState };
39
+
40
+ export function logFileForSession(session: string): string {
41
+ validateSessionName(session);
42
+ const dir = getSessionDir(session);
43
+ mkdirSync(dir, { recursive: true });
44
+ return getSessionLogsPath(session);
45
+ }
46
+
47
+ export function validateSessionName(session: string): void {
48
+ if (
49
+ !SESSION_NAME_PATTERN.test(session) ||
50
+ session.includes("..") ||
51
+ session.includes("/") ||
52
+ session.includes("\\")
53
+ ) {
54
+ throw new Error(
55
+ "Invalid session name. Use only letters, numbers, dots, underscores, and dashes.",
56
+ );
57
+ }
58
+ }
59
+
60
+ export function getStateFilePath(session: string): string {
61
+ validateSessionName(session);
62
+ const sessionDir = getSessionDir(session);
63
+ mkdirSync(sessionDir, { recursive: true });
64
+ return getSessionStatePath(session);
65
+ }
66
+
67
+ export function readSessionState(
68
+ session: string,
69
+ logger?: LoggerApi,
70
+ ): SessionState | null {
71
+ const stateFile = getStateFilePath(session);
72
+ if (!existsSync(stateFile)) {
73
+ logger?.info("session-state-not-found", { session, stateFile });
74
+ return null;
75
+ }
76
+
77
+ try {
78
+ const content = readFileSync(stateFile, "utf-8");
79
+ const state = parseSessionStateContent(content, stateFile);
80
+ logger?.info("session-state-read", {
81
+ session,
82
+ port: state.port,
83
+ pid: state.pid,
84
+ });
85
+ return state;
86
+ } catch (err) {
87
+ logger?.warn("session-state-parse-error", {
88
+ error: err instanceof Error ? err.message : String(err),
89
+ session,
90
+ stateFile,
91
+ });
92
+ return null;
93
+ }
94
+ }
95
+
96
+ export function listSessionsWithStateFile(): string[] {
97
+ if (!existsSync(LIBRETTO_SESSIONS_DIR)) return [];
98
+ return readdirSync(LIBRETTO_SESSIONS_DIR)
99
+ .filter((session) => {
100
+ try {
101
+ validateSessionName(session);
102
+ } catch {
103
+ return false;
104
+ }
105
+ return existsSync(getSessionStatePath(session));
106
+ })
107
+ .sort();
108
+ }
109
+
110
+ function listActiveSessions(): string[] {
111
+ return listSessionsWithStateFile();
112
+ }
113
+
114
+ function throwSessionNotFoundError(session: string): never {
115
+ const active = listActiveSessions();
116
+ const lines = [`No session "${session}" found.`];
117
+ if (active.length > 0) {
118
+ lines.push("");
119
+ lines.push("Active sessions:");
120
+ for (const name of active) {
121
+ lines.push(` ${name}`);
122
+ }
123
+ } else {
124
+ lines.push("");
125
+ lines.push("No active sessions.");
126
+ }
127
+ lines.push("");
128
+ lines.push("Start one with:");
129
+ lines.push(` libretto open <url> --session ${session}`);
130
+ throw new Error(lines.join("\n"));
131
+ }
132
+
133
+ export function assertSessionStateExistsOrThrow(session: string): void {
134
+ const stateFile = getStateFilePath(session);
135
+ if (!existsSync(stateFile)) {
136
+ throwSessionNotFoundError(session);
137
+ }
138
+ }
139
+
140
+ export function readSessionStateOrThrow(session: string): SessionState {
141
+ const stateFile = getStateFilePath(session);
142
+ if (!existsSync(stateFile)) {
143
+ throwSessionNotFoundError(session);
144
+ }
145
+
146
+ try {
147
+ return parseSessionStateContent(
148
+ readFileSync(stateFile, "utf-8"),
149
+ stateFile,
150
+ );
151
+ } catch (err) {
152
+ throw new Error(
153
+ `Could not read session state for "${session}": ${err instanceof Error ? err.message : String(err)}`,
154
+ );
155
+ }
156
+ }
157
+
158
+ export function writeSessionState(
159
+ state: SessionState,
160
+ logger?: LoggerApi,
161
+ ): void {
162
+ const stateFile = getStateFilePath(state.session);
163
+ const fileState = serializeSessionState(state);
164
+ writeFileSync(stateFile, JSON.stringify(fileState, null, 2), "utf-8");
165
+ logger?.info("session-state-write", {
166
+ session: state.session,
167
+ stateFile,
168
+ port: state.port,
169
+ pid: state.pid,
170
+ });
171
+ }
172
+
173
+ export function clearSessionState(session: string, logger?: LoggerApi): void {
174
+ const stateFile = getStateFilePath(session);
175
+ if (!existsSync(stateFile)) {
176
+ logger?.info("session-state-clear-missing", { session, stateFile });
177
+ return;
178
+ }
179
+ unlinkSync(stateFile);
180
+ logger?.info("session-state-cleared", { session, stateFile });
181
+ }
182
+
183
+ function isPidRunning(pid: number): boolean {
184
+ try {
185
+ process.kill(pid, 0);
186
+ return true;
187
+ } catch {
188
+ return false;
189
+ }
190
+ }
191
+
192
+ export function setSessionStatus(
193
+ session: string,
194
+ status: SessionStatus,
195
+ logger?: LoggerApi,
196
+ ): void {
197
+ const state = readSessionState(session, logger);
198
+ if (!state) return;
199
+ if (state.status === status) return;
200
+ writeSessionState(
201
+ {
202
+ ...state,
203
+ status,
204
+ },
205
+ logger,
206
+ );
207
+ }
208
+
209
+ export function assertSessionAvailableForStart(
210
+ session: string,
211
+ logger?: LoggerApi,
212
+ ): void {
213
+ const existingState = readSessionState(session, logger);
214
+ if (!existingState) return;
215
+ if (existingState.pid == null || !isPidRunning(existingState.pid)) {
216
+ setSessionStatus(session, "exited", logger);
217
+ return;
218
+ }
219
+ const endpoint = `http://127.0.0.1:${existingState.port}`;
220
+ throw new Error(
221
+ `Session "${session}" is already open and connected to ${endpoint} (pid ${existingState.pid}). Create a new session or close the current one with: libretto close --session ${session}`,
222
+ );
223
+ }