libretto 0.2.3 → 0.2.5

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 (42) hide show
  1. package/README.md +78 -184
  2. package/dist/cli/cli.js +8 -2
  3. package/dist/cli/commands/browser.js +26 -3
  4. package/dist/cli/commands/execution.js +50 -11
  5. package/dist/cli/commands/init.js +95 -0
  6. package/dist/cli/core/browser.js +131 -6
  7. package/dist/cli/core/context.js +5 -0
  8. package/dist/cli/core/session.js +13 -13
  9. package/dist/cli/workers/run-integration-runtime.js +64 -59
  10. package/dist/cli/workers/run-integration-worker-protocol.js +12 -0
  11. package/dist/cli/workers/run-integration-worker.js +13 -30
  12. package/dist/index.cjs +5 -12
  13. package/dist/index.d.cts +4 -2
  14. package/dist/index.d.ts +4 -2
  15. package/dist/index.js +5 -15
  16. package/dist/shared/debug/index.cjs +4 -6
  17. package/dist/shared/debug/index.d.cts +1 -2
  18. package/dist/shared/debug/index.d.ts +1 -2
  19. package/dist/shared/debug/index.js +3 -8
  20. package/dist/shared/debug/pause.cjs +58 -24
  21. package/dist/shared/debug/pause.d.cts +13 -20
  22. package/dist/shared/debug/pause.d.ts +13 -20
  23. package/dist/shared/debug/pause.js +46 -21
  24. package/dist/shared/llm/ai-sdk-adapter.cjs +67 -0
  25. package/dist/shared/llm/ai-sdk-adapter.d.cts +22 -0
  26. package/dist/shared/llm/ai-sdk-adapter.d.ts +22 -0
  27. package/dist/shared/llm/ai-sdk-adapter.js +43 -0
  28. package/dist/shared/llm/index.cjs +5 -2
  29. package/dist/shared/llm/index.d.cts +2 -0
  30. package/dist/shared/llm/index.d.ts +2 -0
  31. package/dist/shared/llm/index.js +3 -1
  32. package/dist/shared/llm/types.d.cts +32 -0
  33. package/dist/shared/llm/types.d.ts +32 -0
  34. package/dist/shared/run/api.cjs +0 -7
  35. package/dist/shared/run/api.d.cts +0 -1
  36. package/dist/shared/run/api.d.ts +0 -1
  37. package/dist/shared/run/api.js +0 -8
  38. package/dist/shared/workflow/workflow.d.cts +11 -24
  39. package/dist/shared/workflow/workflow.d.ts +11 -24
  40. package/package.json +4 -10
  41. package/skill/SKILL.md +18 -5
  42. package/skill/code-generation-rules.md +7 -10
@@ -18,18 +18,11 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var api_exports = {};
20
20
  __export(api_exports, {
21
- DebugPauseSignal: () => import_pause.DebugPauseSignal,
22
- debugPause: () => import_pause.debugPause,
23
- isDebugPauseSignal: () => import_pause.isDebugPauseSignal,
24
21
  launchBrowser: () => import_browser.launchBrowser
25
22
  });
26
23
  module.exports = __toCommonJS(api_exports);
27
24
  var import_browser = require("./browser.js");
28
- var import_pause = require("../debug/pause.js");
29
25
  // Annotate the CommonJS export names for ESM import in node:
30
26
  0 && (module.exports = {
31
- DebugPauseSignal,
32
- debugPause,
33
- isDebugPauseSignal,
34
27
  launchBrowser
35
28
  });
@@ -1,3 +1,2 @@
1
1
  export { BrowserSession, LaunchBrowserArgs, launchBrowser } from './browser.cjs';
2
- export { DebugPauseContext, DebugPauseDetails, DebugPauseSignal, debugPause, isDebugPauseSignal } from '../debug/pause.cjs';
3
2
  import 'playwright';
@@ -1,3 +1,2 @@
1
1
  export { BrowserSession, LaunchBrowserArgs, launchBrowser } from './browser.js';
2
- export { DebugPauseContext, DebugPauseDetails, DebugPauseSignal, debugPause, isDebugPauseSignal } from '../debug/pause.js';
3
2
  import 'playwright';
@@ -1,12 +1,4 @@
1
1
  import { launchBrowser } from "./browser.js";
2
- import {
3
- debugPause,
4
- DebugPauseSignal,
5
- isDebugPauseSignal
6
- } from "../debug/pause.js";
7
2
  export {
8
- DebugPauseSignal,
9
- debugPause,
10
- isDebugPauseSignal,
11
3
  launchBrowser
12
4
  };
@@ -1,34 +1,21 @@
1
- import { Page, BrowserContext, Browser } from 'playwright';
1
+ import { Page } from 'playwright';
2
2
  import { MinimalLogger } from '../logger/logger.cjs';
3
3
 
4
4
  declare const LIBRETTO_WORKFLOW_BRAND: unique symbol;
5
- type LibrettoAuthProfile = {
6
- type: "local";
7
- domain: string;
8
- };
9
- type LibrettoWorkflowMetadata = {
10
- authProfile?: LibrettoAuthProfile;
11
- };
12
- type LibrettoWorkflowContext = {
13
- logger: MinimalLogger;
5
+ type LibrettoWorkflowMetadata = {};
6
+ type LibrettoWorkflowContext<S = {}> = {
14
7
  page: Page;
15
- context: BrowserContext;
16
- browser: Browser;
17
- session: string;
18
- integrationPath: string;
19
- exportName: string;
20
- headless: boolean;
21
- debug: boolean;
22
- pause: () => Promise<void>;
8
+ logger: MinimalLogger;
9
+ services: S;
23
10
  };
24
- type LibrettoWorkflowHandler<Input = unknown, Output = unknown> = (ctx: LibrettoWorkflowContext, input: Input) => Promise<Output>;
25
- declare class LibrettoWorkflow<Input = unknown, Output = unknown> {
11
+ type LibrettoWorkflowHandler<Input = unknown, Output = unknown, S = {}> = (ctx: LibrettoWorkflowContext<S>, input: Input) => Promise<Output>;
12
+ declare class LibrettoWorkflow<Input = unknown, Output = unknown, S = {}> {
26
13
  readonly [LIBRETTO_WORKFLOW_BRAND] = true;
27
14
  readonly metadata: LibrettoWorkflowMetadata;
28
15
  private readonly handler;
29
- constructor(metadata: LibrettoWorkflowMetadata, handler: LibrettoWorkflowHandler<Input, Output>);
30
- run(ctx: LibrettoWorkflowContext, input: Input): Promise<Output>;
16
+ constructor(metadata: LibrettoWorkflowMetadata, handler: LibrettoWorkflowHandler<Input, Output, S>);
17
+ run(ctx: LibrettoWorkflowContext<S>, input: Input): Promise<Output>;
31
18
  }
32
- declare function workflow<Input = unknown, Output = unknown>(metadata: LibrettoWorkflowMetadata, handler: LibrettoWorkflowHandler<Input, Output>): LibrettoWorkflow<Input, Output>;
19
+ declare function workflow<Input = unknown, Output = unknown, S = {}>(metadata: LibrettoWorkflowMetadata, handler: LibrettoWorkflowHandler<Input, Output, S>): LibrettoWorkflow<Input, Output, S>;
33
20
 
34
- export { LIBRETTO_WORKFLOW_BRAND, type LibrettoAuthProfile, LibrettoWorkflow, type LibrettoWorkflowContext, type LibrettoWorkflowHandler, type LibrettoWorkflowMetadata, workflow };
21
+ export { LIBRETTO_WORKFLOW_BRAND, LibrettoWorkflow, type LibrettoWorkflowContext, type LibrettoWorkflowHandler, type LibrettoWorkflowMetadata, workflow };
@@ -1,34 +1,21 @@
1
- import { Page, BrowserContext, Browser } from 'playwright';
1
+ import { Page } from 'playwright';
2
2
  import { MinimalLogger } from '../logger/logger.js';
3
3
 
4
4
  declare const LIBRETTO_WORKFLOW_BRAND: unique symbol;
5
- type LibrettoAuthProfile = {
6
- type: "local";
7
- domain: string;
8
- };
9
- type LibrettoWorkflowMetadata = {
10
- authProfile?: LibrettoAuthProfile;
11
- };
12
- type LibrettoWorkflowContext = {
13
- logger: MinimalLogger;
5
+ type LibrettoWorkflowMetadata = {};
6
+ type LibrettoWorkflowContext<S = {}> = {
14
7
  page: Page;
15
- context: BrowserContext;
16
- browser: Browser;
17
- session: string;
18
- integrationPath: string;
19
- exportName: string;
20
- headless: boolean;
21
- debug: boolean;
22
- pause: () => Promise<void>;
8
+ logger: MinimalLogger;
9
+ services: S;
23
10
  };
24
- type LibrettoWorkflowHandler<Input = unknown, Output = unknown> = (ctx: LibrettoWorkflowContext, input: Input) => Promise<Output>;
25
- declare class LibrettoWorkflow<Input = unknown, Output = unknown> {
11
+ type LibrettoWorkflowHandler<Input = unknown, Output = unknown, S = {}> = (ctx: LibrettoWorkflowContext<S>, input: Input) => Promise<Output>;
12
+ declare class LibrettoWorkflow<Input = unknown, Output = unknown, S = {}> {
26
13
  readonly [LIBRETTO_WORKFLOW_BRAND] = true;
27
14
  readonly metadata: LibrettoWorkflowMetadata;
28
15
  private readonly handler;
29
- constructor(metadata: LibrettoWorkflowMetadata, handler: LibrettoWorkflowHandler<Input, Output>);
30
- run(ctx: LibrettoWorkflowContext, input: Input): Promise<Output>;
16
+ constructor(metadata: LibrettoWorkflowMetadata, handler: LibrettoWorkflowHandler<Input, Output, S>);
17
+ run(ctx: LibrettoWorkflowContext<S>, input: Input): Promise<Output>;
31
18
  }
32
- declare function workflow<Input = unknown, Output = unknown>(metadata: LibrettoWorkflowMetadata, handler: LibrettoWorkflowHandler<Input, Output>): LibrettoWorkflow<Input, Output>;
19
+ declare function workflow<Input = unknown, Output = unknown, S = {}>(metadata: LibrettoWorkflowMetadata, handler: LibrettoWorkflowHandler<Input, Output, S>): LibrettoWorkflow<Input, Output, S>;
33
20
 
34
- export { LIBRETTO_WORKFLOW_BRAND, type LibrettoAuthProfile, LibrettoWorkflow, type LibrettoWorkflowContext, type LibrettoWorkflowHandler, type LibrettoWorkflowMetadata, workflow };
21
+ export { LIBRETTO_WORKFLOW_BRAND, LibrettoWorkflow, type LibrettoWorkflowContext, type LibrettoWorkflowHandler, type LibrettoWorkflowMetadata, workflow };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libretto",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "AI-powered browser automation library and CLI built on Playwright",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -105,15 +105,9 @@
105
105
  "zod": ">=3.0.0"
106
106
  },
107
107
  "peerDependenciesMeta": {
108
- "@ai-sdk/anthropic": {
109
- "optional": true
110
- },
111
- "@ai-sdk/google-vertex": {
112
- "optional": true
113
- },
114
- "@ai-sdk/openai": {
115
- "optional": true
116
- }
108
+ "@ai-sdk/anthropic": { "optional": true },
109
+ "@ai-sdk/google-vertex": { "optional": true },
110
+ "@ai-sdk/openai": { "optional": true }
117
111
  },
118
112
  "devDependencies": {
119
113
  "@ai-sdk/anthropic": "^3.0.53",
package/skill/SKILL.md CHANGED
@@ -1,6 +1,10 @@
1
1
  ---
2
2
  name: libretto
3
3
  description: "Browser automation CLI for building integrations, with a network-first approach.\n\nWHEN TO USE THIS SKILL:\n- When building a new integration or data extraction workflow against a website\n- When you need to interact with a web page (click, fill, navigate) rather than just read it\n- When debugging browser agent job failures (selectors timing out, clicks not working, elements not found)\n- When you need to test or prototype Playwright interactions before codifying them\n- When you need to save or restore login sessions for authenticated pages\n- When you need to understand what's on a page (use the snapshot command)\n- When scraping dynamic content that requires JavaScript execution\n\nWHEN NOT TO USE THIS SKILL:\n- When you only need to read static web content (use read_web_page instead)\n- When you need to modify browser agent source code (edit files directly)\n- When you need to run a full browser agent job end-to-end (use npx browser-agent CLI)"
4
+ license: MIT
5
+ metadata:
6
+ author: saffron-health
7
+ version: "0.2.2"
4
8
  ---
5
9
 
6
10
  # Browser Integration with Libretto CLI
@@ -41,16 +45,24 @@ Built-in sessions: `default`, `dev-server`, `browser-agent`.
41
45
 
42
46
  Add `--visualize` to any `exec` command to show a ghost cursor and element highlight before each action executes. Use it when the user wants to see what will be clicked/filled before it happens.
43
47
 
44
- ## Workflow Pause/Resume (`ctx.pause()`)
48
+ ## Workflow Pause/Resume (`pause()`)
45
49
 
46
- Workflows pause from inside the workflow function by calling `await ctx.pause()`.
50
+ Workflows pause by calling `await pause()` (imported from `"libretto"`). In production (`NODE_ENV=production`) it is a no-op.
47
51
 
48
52
  - There are no pause options to pass at call sites. Pause is session-scoped and resolved from the active session.
49
- - `npx libretto run ...` waits until the workflow either completes or hits the next `ctx.pause()`.
53
+ - `npx libretto run ...` waits until the workflow either completes or hits the next `pause()`.
50
54
  - On pause, the workflow process stays alive and keeps browser/session state.
51
55
  - `npx libretto resume --session <name>` sends resume signal and then waits until completion or the next pause.
52
56
  - For multi-pause workflows, call `resume` repeatedly until the workflow completes.
53
57
 
58
+ ## Workflow Failures and Reruns
59
+
60
+ - `npx libretto run` always uses the same failure-inspection behavior; no separate debug flag is needed.
61
+ - On workflow failure, Libretto prints the workflow error and keeps the browser open for inspection.
62
+ - After a failed run, use `npx libretto exec --session <name> "<code>"` to inspect or prototype fixes.
63
+ - Re-running `npx libretto run ... --session <name>` re-runs the workflow for that session.
64
+ - If the same session still has a failed workflow worker, Libretto releases that failed worker process before rerunning.
65
+
54
66
  ## Globals Available in `exec`
55
67
 
56
68
  `page`, `context`, `state`, `browser`, `networkLog({ last?, filter?, method? })`, `actionLog({ last?, filter?, action?, source? })`, `console`, `fetch`, `Buffer`, `URL`, `setTimeout`
@@ -214,7 +226,8 @@ When the snapshot doesn't give you enough detail — why an element is hidden, w
214
226
 
215
227
  - **Never use `page.screenshot()` via `exec`.** Use `npx libretto snapshot` instead — it captures the viewport, sends the screenshot + HTML to a vision model, and returns actionable selectors. The `fullPage` option is especially dangerous — it scrolls the entire page to stitch a screenshot, which can crash JavaScript-heavy pages (especially EMR portals like eClinicalWorks).
216
228
  - **Never run `exec` commands in parallel.** Always wait for one `exec` to finish before starting the next. Do not use `run_in_background` for `exec` calls. Running simultaneous `exec` calls opens multiple CDP connections to the same page, which corrupts the page state and kills the browser.
217
- - `open` and `run` require an available session. If the session is already active, Libretto fails fast and asks you to close the existing session or use a different `--session`.
229
+ - `open` requires an available session. If the session is already active, Libretto fails fast and asks you to close the existing session or use a different `--session`.
230
+ - `run` also requires an available session, except for the specific case of a prior failed `run` in the same session; in that case Libretto releases the failed worker and allows rerun.
218
231
  - Use `return <value>` in `exec` to print results. Strings print raw; objects print as JSON.
219
232
  - For iframe content, access via `page.locator('iframe[name="..."]').contentFrame()`.
220
233
  - Multiple sessions allow parallel browser instances: `--session test1`, `--session test2`.
@@ -313,7 +326,7 @@ The browser stays open indefinitely until explicitly closed with `npx libretto c
313
326
 
314
327
  If the site requires login, ask the user how auth should work in the generated workflow:
315
328
 
316
- 1. Save a local profile (recommended for local runs): open in `--headed`, have the user log in manually, run `npx libretto save <domain>`, and generate workflow metadata with `authProfile: { type: "local", domain: "<hostname>" }`.
329
+ 1. Save a local profile (recommended for local runs): open in `--headed`, have the user log in manually, run `npx libretto save <domain>`, and pass `--auth-profile <domain>` when running the workflow (e.g. `npx libretto run ./file.ts main --auth-profile example.com`).
317
330
  2. Use user-managed credential logic in Playwright code (no local profile dependency).
318
331
 
319
332
  If local profile is chosen, include this warning in your generated workflow guidance: local profiles are machine-local (other users/environments will not have them), and sessions can expire so re-login/re-save may be required.
@@ -7,7 +7,7 @@ These rules apply when generating production TypeScript files from interactive b
7
7
  Generated files must export a `workflow()` instance so they can be run via `npx libretto run <file> <exportName>`. Import `workflow` and its types from `"libretto"`:
8
8
 
9
9
  ```typescript
10
- import { workflow, type LibrettoWorkflowContext } from "libretto";
10
+ import { workflow, pause, type LibrettoWorkflowContext } from "libretto";
11
11
 
12
12
  type Input = {
13
13
  // Define the expected input shape — passed via --params JSON
@@ -21,15 +21,11 @@ type Output = {
21
21
  };
22
22
 
23
23
  export const myWorkflow = workflow<Input, Output>(
24
- {
25
- // If the site requires a saved login session:
26
- authProfile: { type: "local", domain: "example.com" },
27
- // Omit authProfile if no login is needed
28
- },
29
- async (ctx: LibrettoWorkflowContext, input: Input): Promise<Output> => {
24
+ {},
25
+ async (ctx, input): Promise<Output> => {
30
26
  const { page } = ctx;
31
27
 
32
- // workflow logic here — use ctx.page, ctx.context, ctx.browser
28
+ // workflow logic here — use ctx.page, ctx.logger, ctx.services
33
29
  await page.goto("https://example.com");
34
30
  // ...
35
31
 
@@ -41,9 +37,10 @@ export const myWorkflow = workflow<Input, Output>(
41
37
  **Key points:**
42
38
 
43
39
  - The named export (e.g., `myWorkflow`) is what you pass as the second arg to `npx libretto run ./file.ts myWorkflow`
44
- - `ctx` provides `page`, `context`, `browser`, `session`, `logger`, `headless`, `integrationPath`, `exportName`
40
+ - `ctx` provides `page`, `logger`, and `services` (generic, default `{}`)
45
41
  - `input` comes from `--params '{"query":"foo"}'` or `--params-file params.json` on the CLI
46
- - If `authProfile` is set with a domain, libretto loads the saved browser profile for that domain (created via `npx libretto save <domain>`)
42
+ - If the site requires a saved login session, pass `--auth-profile <domain>` to the CLI (created via `npx libretto save <domain>`)
43
+ - Use `await pause()` (imported from `"libretto"`) to pause the workflow for debugging. It is a no-op in production.
47
44
  - The browser is launched and closed automatically by the CLI — do not launch or close it in the handler
48
45
 
49
46
  ## Playwright Locators for DOM Interaction