libretto 0.6.8 → 0.6.10

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 (65) hide show
  1. package/dist/cli/cli.js +2 -0
  2. package/dist/cli/commands/auth.js +535 -0
  3. package/dist/cli/commands/billing.js +74 -0
  4. package/dist/cli/commands/browser.js +8 -3
  5. package/dist/cli/commands/deploy.js +2 -7
  6. package/dist/cli/commands/execution.js +112 -137
  7. package/dist/cli/commands/snapshot.js +38 -126
  8. package/dist/cli/core/ai-model.js +0 -3
  9. package/dist/cli/core/auth-fetch.js +195 -0
  10. package/dist/cli/core/auth-storage.js +52 -0
  11. package/dist/cli/core/browser.js +151 -206
  12. package/dist/cli/core/daemon/config.js +6 -0
  13. package/dist/cli/core/daemon/daemon.js +298 -0
  14. package/dist/cli/core/daemon/exec.js +86 -0
  15. package/dist/cli/core/daemon/index.js +16 -0
  16. package/dist/cli/core/daemon/ipc.js +171 -0
  17. package/dist/cli/core/daemon/pages.js +15 -0
  18. package/dist/cli/core/daemon/snapshot.js +86 -0
  19. package/dist/cli/core/daemon/spawn.js +90 -0
  20. package/dist/cli/core/exec-compiler.js +111 -0
  21. package/dist/cli/core/prompt.js +72 -0
  22. package/dist/cli/core/providers/browserbase.js +1 -0
  23. package/dist/cli/core/providers/kernel.js +1 -0
  24. package/dist/cli/core/providers/libretto-cloud.js +6 -7
  25. package/dist/cli/core/readonly-exec.js +1 -1
  26. package/dist/cli/router.js +4 -0
  27. package/dist/cli/workers/run-integration-runtime.js +0 -5
  28. package/dist/shared/state/session-state.d.ts +1 -0
  29. package/dist/shared/state/session-state.js +2 -1
  30. package/docs/browser-automation-approaches.md +435 -0
  31. package/docs/releasing.md +117 -0
  32. package/package.json +4 -3
  33. package/skills/libretto/SKILL.md +14 -1
  34. package/skills/libretto-readonly/SKILL.md +1 -1
  35. package/src/cli/cli.ts +2 -0
  36. package/src/cli/commands/auth.ts +787 -0
  37. package/src/cli/commands/billing.ts +133 -0
  38. package/src/cli/commands/browser.ts +8 -2
  39. package/src/cli/commands/deploy.ts +2 -7
  40. package/src/cli/commands/execution.ts +139 -187
  41. package/src/cli/commands/snapshot.ts +46 -143
  42. package/src/cli/core/ai-model.ts +4 -5
  43. package/src/cli/core/auth-fetch.ts +283 -0
  44. package/src/cli/core/auth-storage.ts +102 -0
  45. package/src/cli/core/browser.ts +182 -245
  46. package/src/cli/core/daemon/config.ts +46 -0
  47. package/src/cli/core/daemon/daemon.ts +429 -0
  48. package/src/cli/core/daemon/exec.ts +128 -0
  49. package/src/cli/core/daemon/index.ts +24 -0
  50. package/src/cli/core/daemon/ipc.ts +294 -0
  51. package/src/cli/core/daemon/pages.ts +21 -0
  52. package/src/cli/core/daemon/snapshot.ts +114 -0
  53. package/src/cli/core/daemon/spawn.ts +171 -0
  54. package/src/cli/core/exec-compiler.ts +169 -0
  55. package/src/cli/core/prompt.ts +94 -0
  56. package/src/cli/core/providers/browserbase.ts +1 -0
  57. package/src/cli/core/providers/kernel.ts +1 -0
  58. package/src/cli/core/providers/libretto-cloud.ts +13 -7
  59. package/src/cli/core/providers/types.ts +12 -1
  60. package/src/cli/core/readonly-exec.ts +2 -1
  61. package/src/cli/router.ts +4 -0
  62. package/src/cli/workers/run-integration-runtime.ts +0 -6
  63. package/src/shared/state/session-state.ts +1 -0
  64. package/dist/cli/core/browser-daemon.js +0 -122
  65. package/src/cli/core/browser-daemon.ts +0 -198
@@ -1,198 +0,0 @@
1
- /**
2
- * Browser daemon process.
3
- *
4
- * Launched as a detached child process by `runOpen()` in `browser.ts`.
5
- * Receives configuration as a JSON string in `process.argv[2]`.
6
- *
7
- * Responsibilities:
8
- * - Launch Chromium with the specified settings
9
- * - Create a browser context and page
10
- * - Install session telemetry (network/action logging)
11
- * - Navigate to the requested URL
12
- * - Stay alive until the browser disconnects or a signal is received
13
- */
14
-
15
- import { chromium } from "playwright";
16
- import { mkdir, unlink } from "node:fs/promises";
17
- import { appendFileSync } from "node:fs";
18
- import { installSessionTelemetry } from "./session-telemetry.js";
19
- import {
20
- getSessionDir,
21
- getSessionLogsPath,
22
- getSessionNetworkLogPath,
23
- getSessionActionsLogPath,
24
- getSessionStatePath,
25
- } from "./context.js";
26
-
27
- // ── Config schema ──────────────────────────────────────────────────────
28
-
29
- type DaemonConfig = {
30
- port: number;
31
- url: string;
32
- session: string;
33
- headed: boolean;
34
- viewport: { width: number; height: number };
35
- storageStatePath?: string;
36
- windowPosition?: { x: number; y: number };
37
- };
38
-
39
- const config: DaemonConfig = JSON.parse(process.argv[2]);
40
-
41
- // ── Derived paths ──────────────────────────────────────────────────────
42
-
43
- const sessionDir = getSessionDir(config.session);
44
- await mkdir(sessionDir, { recursive: true });
45
-
46
- const logFile = getSessionLogsPath(config.session);
47
- const networkLogFile = getSessionNetworkLogPath(config.session);
48
- const actionsLogFile = getSessionActionsLogPath(config.session);
49
-
50
- type TelemetryEntry = Record<string, unknown>;
51
-
52
- function childLog(
53
- level: string,
54
- event: string,
55
- data: Record<string, unknown> = {},
56
- ): void {
57
- const entry = JSON.stringify({
58
- timestamp: new Date().toISOString(),
59
- id: Math.random().toString(36).slice(2, 10),
60
- level,
61
- scope: "libretto.child",
62
- event,
63
- data,
64
- });
65
- appendFileSync(logFile, entry + "\n");
66
- }
67
-
68
- function logAction(entry: TelemetryEntry): void {
69
- appendFileSync(actionsLogFile, JSON.stringify(entry) + "\n");
70
- }
71
-
72
- function logNetwork(entry: TelemetryEntry): void {
73
- appendFileSync(networkLogFile, JSON.stringify(entry) + "\n");
74
- }
75
-
76
- // ── Launch browser ─────────────────────────────────────────────────────
77
-
78
- const windowPositionArg = config.windowPosition
79
- ? `--window-position=${config.windowPosition.x},${config.windowPosition.y}`
80
- : undefined;
81
-
82
- const launchArgs = [
83
- "--disable-blink-features=AutomationControlled",
84
- `--remote-debugging-port=${config.port}`,
85
- "--remote-debugging-address=127.0.0.1",
86
- "--no-focus-on-check",
87
- ...(windowPositionArg ? [windowPositionArg] : []),
88
- ];
89
-
90
- const browser = await chromium.launch({
91
- headless: !config.headed,
92
- args: launchArgs,
93
- });
94
-
95
- async function cleanupSessionState(): Promise<void> {
96
- const sessionStatePath = getSessionStatePath(config.session);
97
- try {
98
- await unlink(sessionStatePath);
99
- } catch (err) {
100
- if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
101
- }
102
- }
103
-
104
- let shuttingDown = false;
105
- let wakeDaemon: () => void;
106
- const sleepPromise = new Promise<void>((resolve) => {
107
- wakeDaemon = resolve;
108
- });
109
-
110
- async function shutdown(
111
- reason: string,
112
- closeBrowser: boolean,
113
- ): Promise<void> {
114
- if (shuttingDown) return;
115
- shuttingDown = true;
116
- try {
117
- childLog("info", reason, { port: config.port });
118
- await cleanupSessionState();
119
- if (closeBrowser) await browser.close();
120
- } finally {
121
- wakeDaemon();
122
- }
123
- }
124
-
125
- browser.on("disconnected", () => {
126
- void shutdown("browser-disconnected-exiting", false);
127
- });
128
-
129
- // ── Create context & page ──────────────────────────────────────────────
130
-
131
- const context = await browser.newContext({
132
- ...(config.storageStatePath ? { storageState: config.storageStatePath } : {}),
133
- viewport: {
134
- width: config.viewport.width,
135
- height: config.viewport.height,
136
- },
137
- userAgent:
138
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
139
- });
140
-
141
- const page = await context.newPage();
142
-
143
- // ── Page defaults & telemetry ──────────────────────────────────────────
144
-
145
- page.setDefaultTimeout(30000);
146
- page.setDefaultNavigationTimeout(45000);
147
-
148
- await installSessionTelemetry({
149
- context,
150
- initialPage: page,
151
- includeUserDomActions: true,
152
- logAction,
153
- logNetwork,
154
- });
155
-
156
- // ── Navigate ───────────────────────────────────────────────────────────
157
-
158
- await page.goto(config.url);
159
-
160
- // ── Process lifecycle ──────────────────────────────────────────────────
161
-
162
- process.on("SIGTERM", () => {
163
- void shutdown("child-sigterm", true);
164
- });
165
-
166
- process.on("SIGINT", () => {
167
- void shutdown("child-sigint", true);
168
- });
169
-
170
- process.on("uncaughtException", (err) => {
171
- childLog("error", "uncaught-exception", {
172
- message: err.message,
173
- stack: err.stack,
174
- });
175
- process.exit(1);
176
- });
177
-
178
- process.on("unhandledRejection", (reason) => {
179
- childLog("warn", "unhandled-rejection", { reason: String(reason) });
180
- });
181
-
182
- process.on("exit", (code) => {
183
- childLog("info", "child-exit", {
184
- code,
185
- pid: process.pid,
186
- port: config.port,
187
- });
188
- });
189
-
190
- childLog("info", "child-launched", {
191
- port: config.port,
192
- pid: process.pid,
193
- session: config.session,
194
- });
195
-
196
- // Keep the daemon alive until the browser disconnects or a signal arrives.
197
- await sleepPromise;
198
- process.exit(0);