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
package/README.md CHANGED
@@ -1,70 +1,137 @@
1
+ <!-- Generated from packages/libretto/README.template.md by `pnpm sync:mirrors`. Do not edit directly. -->
2
+
1
3
  # Libretto
2
4
 
3
- Libretto gives your coding agent superpowers for building, debugging, and maintaining browser RPA integrations.
5
+ [![npm version](https://img.shields.io/npm/v/libretto)](https://www.npmjs.com/package/libretto)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+ [![GitHub Discussions](https://img.shields.io/github/discussions/saffron-health/libretto)](https://github.com/saffron-health/libretto/discussions)
4
8
 
5
- It is designed for engineering teams that automate workflows in web apps and want to move from brittle browser-only scripts to faster, more reliable network-first integrations.
9
+ Libretto is a toolkit for building robust web integrations. It gives your coding agent a live browser and a token-efficient CLI to:
6
10
 
7
- ## Installation
11
+ - Inspect live pages with minimal context overhead
12
+ - Capture network traffic to reverse-engineer site APIs
13
+ - Record user actions and replay them as automation scripts
14
+ - Debug broken workflows interactively against the real site
8
15
 
9
- ```bash
10
- npm install --save-dev libretto
11
- ```
16
+ We at [Saffron Health](https://saffron.health) built Libretto to help us maintain our browser integrations to common healthcare software. We're open-sourcing it so other teams have an easier time doing the same thing.
17
+
18
+ https://github.com/user-attachments/assets/9b9a0ab3-5133-4b20-b3be-459943349d18
12
19
 
13
- Chromium is downloaded automatically via a `postinstall` script. If postinstall scripts are disabled (e.g. `--ignore-scripts`, common in monorepos), run init manually:
20
+ ## Installation
14
21
 
15
22
  ```bash
23
+ npm install libretto
24
+
25
+ # Install skill, download Chromium if not already installed, configure snapshot analysis
16
26
  npx libretto init
17
- ```
18
27
 
19
- This installs the Chromium browser binary and optionally configures an AI subagent (Gemini, Claude, or Codex) that can analyze page snapshots without consuming the coding agent's context window.
28
+ # Configure or change the snapshot analysis model (see Configuration section below). `npx libretto init` sets this up the first time.
29
+ npx libretto ai configure <openai | anthropic | gemini | vertex>
30
+ ```
20
31
 
21
- ## Usage
32
+ ## Use cases
22
33
 
23
- Libretto is usually used through prompts with the Libretto skill.
34
+ Libretto is designed to be used as a skill through your coding agent. Here are some example prompts:
24
35
 
25
36
  ### One-shot script generation
26
37
 
27
- ```text
28
- Use the Libretto skill. Go on LinkedIn and scrape the first 10 posts for content, who posted it, the number of reactions, the first 25 comments, and the first 25 reposts.
29
- ```
38
+ > Use the Libretto skill. Go on LinkedIn and scrape the first 10 posts for content, who posted it, the number of reactions, the first 25 comments, and the first 25 reposts.
39
+
40
+ Your coding agent will open a window for you to log into LinkedIn, and then automatically start exploring.
30
41
 
31
42
  ### Interactive script building
32
43
 
33
- ```text
34
- Use the Libretto skill. Let's interactively build a script to scrape scheduling info from the eClinicalWorks EHR.
35
- ```
44
+ > I'm gonna show you a workflow in the eclinicalworks EHR to get a patient's primary insurance ID. Use libretto skill to turn it into a playwright script that takes patient name and dob as input to get back the insurance ID. URL is ...
45
+
46
+ Libretto can read your actions you perform in the browser, so you can perform a workflow, then ask it to use your actions to rebuild the workflow.
36
47
 
37
48
  ### Convert browser automation to network requests
38
49
 
39
- ```text
40
- We have a browser script at ./integration.ts that automates going to Hacker News and getting the first 10 posts. Convert it to direct network scripts instead. Use the Libretto skill.
41
- ```
50
+ > We have a browser script at ./integration.ts that automates going to Hacker News and getting the first 10 posts. Convert it to direct network scripts instead. Use the Libretto skill.
51
+
52
+ Libretto can read network requests from the browser, which it can use to reverse engineer the API and create a script that directly calls those requests. Directly making API calls is faster, and more reliable, than UI automation. You can also ask Libretto to conduct a security analysis which analyzes the requests for common security cookies, so you can understand whether a network request approach will be safe.
42
53
 
43
54
  ### Fix broken integrations
44
55
 
45
- ```text
46
- We have a browser script at ./integration.ts that is supposed to go to Availity and perform an eligibility check for a patient. But I'm getting a broken selector error when I run it. Fix it. Use the Libretto skill.
56
+ > We have a browser script at ./integration.ts that is supposed to go to Availity and perform an eligibility check for a patient. But I'm getting a broken selector error when I run it. Fix it. Use the Libretto skill.
57
+
58
+ Agents can use Libretto to reproduce the failure, pause the workflow at any point, inspect the live page, and fix issues, all autonomously.
59
+
60
+ ### CLI usage
61
+
62
+ You can also use Libretto directly from the command line. All commands accept `--session <name>` to target a specific session.
63
+
64
+ ```bash
65
+ npx libretto init # interactive; run yourself, not through an agent
66
+ npx libretto open <url> # launch browser and open a URL (headed by default)
67
+ npx libretto snapshot --objective "..." --context "..." # capture PNG + HTML and analyze with an LLM
68
+ npx libretto exec "<code>" # execute Playwright TypeScript against the open page (single quoted argument)
69
+ echo "<code>" | npx libretto exec - # intentionally read Playwright TypeScript from stdin
70
+ npx libretto run <file> <workflowName> # run an exported workflow from a file
71
+ npx libretto resume # resume a paused workflow
72
+ npx libretto network # view captured network requests
73
+ npx libretto actions # view captured user/agent actions
74
+ npx libretto pages # list open pages in the session
75
+ npx libretto save <domain> # save browser session (cookies, localStorage) for reuse
76
+ npx libretto close # close the browser
77
+ npx libretto ai configure <provider> # configure snapshot analysis model
78
+ ```
79
+
80
+ ## Configuration
81
+
82
+ All Libretto state lives in a `.libretto/` directory at your project root. Configuration is stored in `.libretto/config.json`.
83
+
84
+ ### Config file
85
+
86
+ `.libretto/config.json` controls snapshot analysis and viewport settings:
87
+
88
+ ```json
89
+ {
90
+ "version": 1,
91
+ "ai": {
92
+ "model": "openai/gpt-5.4",
93
+ "updatedAt": "2026-01-01T00:00:00.000Z"
94
+ },
95
+ "viewport": { "width": 1280, "height": 800 }
96
+ }
47
97
  ```
48
98
 
49
- You can also run workflows directly from the CLI:
99
+ The `ai` field configures which model Libretto uses for snapshot analysis — extracting selectors, identifying interactive elements, or diagnosing why a step failed. This keeps heavy visual context out of your coding agent's context window. Snapshot analysis is required.
100
+
101
+ The easiest way to set the model is through the CLI:
50
102
 
51
103
  ```bash
52
- npx libretto help
53
- npx libretto run ./integration.ts main
104
+ npx libretto ai configure <openai | anthropic | gemini | vertex>
54
105
  ```
55
106
 
56
- ## The `.libretto/` directory
107
+ Provider credentials are read from environment variables or a `.env` file at your project root: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY` / `GOOGLE_GENERATIVE_AI_API_KEY`, or `GOOGLE_CLOUD_PROJECT` for Vertex.
108
+
109
+ The `viewport` field sets the default browser viewport size. Both fields are optional.
110
+
111
+ ### Sessions
57
112
 
58
- Libretto stores local runtime state in a `.libretto/` directory at your project root. Sensitive directories (`sessions/` and `profiles/`) are automatically git-ignored via `.libretto/.gitignore`.
113
+ Each Libretto session gets its own directory under `.libretto/sessions/<name>/` containing runtime state. Sessions are git-ignored.
59
114
 
60
- - **`profiles/<domain>.json`**Saved browser sessions (cookies, localStorage) for authenticated sites. Created via `npx libretto save <domain>`. Machine-local and never committed.
61
- - **`sessions/<name>/`**Per-session runtime state:
62
- - `state.json` — Session metadata (debug port, PID, status)
63
- - `logs.jsonl` — Structured session logs
64
- - `network.jsonl`Captured network requests (URLs, methods, headers, response status)
65
- - `actions.jsonl` — Recorded user actions (clicks, fills, navigations)
66
- - `snapshots/` — Screenshot PNGs and HTML snapshots captured via `npx libretto snapshot`
67
- - **`ai.json`** — AI runtime configuration set via `npx libretto ai configure`.
115
+ - `state.json`session metadata (debug port, PID, status)
116
+ - `logs.jsonl`structured session logs
117
+ - `network.jsonl` — captured network requests
118
+ - `actions.jsonl` — recorded user actions
119
+ - `snapshots/`screenshot PNGs and HTML snapshots
120
+
121
+ ### Profiles
122
+
123
+ Profiles save browser sessions (cookies, localStorage) so you can reuse authenticated state across runs. They are stored in `.libretto/profiles/<domain>.json`, created via `npx libretto save <domain>`. Profiles are machine-local and git-ignored.
124
+
125
+ ## Community
126
+
127
+ Have a question, idea, or want to share what you've built? Join the conversation on [GitHub Discussions](https://github.com/saffron-health/libretto/discussions).
128
+
129
+ - **[Q&A](https://github.com/saffron-health/libretto/discussions/categories/q-a)** — Ask questions and get help
130
+ - **[Ideas](https://github.com/saffron-health/libretto/discussions/categories/ideas)** — Suggest new features or improvements
131
+ - **[Show and tell](https://github.com/saffron-health/libretto/discussions/categories/show-and-tell)** — Share your workflows and automations
132
+ - **[General](https://github.com/saffron-health/libretto/discussions/categories/general)** — Chat about anything Libretto-related
133
+
134
+ Found a bug? Please [open an issue](https://github.com/saffron-health/libretto/issues/new).
68
135
 
69
136
  ## Authors
70
137
 
@@ -76,10 +143,20 @@ For local development in this repository:
76
143
 
77
144
  ```bash
78
145
  pnpm i
79
- pnpm check:skills
80
146
  pnpm build
81
147
  pnpm type-check
82
148
  pnpm test
83
149
  ```
84
150
 
85
- If the mirrored Libretto skill copies drift, run `pnpm i`. In this repository, `postinstall` resyncs them.
151
+ Source layout:
152
+
153
+ - `src/cli/` — CLI commands
154
+ - `src/runtime/` — browser runtime (network, recovery, downloads, extraction)
155
+ - `src/shared/` — shared utilities (config, LLM client, logging, state)
156
+ - `test/` — test files (`*.spec.ts`)
157
+ - `README.template.md` — source of truth for the repo and package READMEs
158
+ - `skills/libretto/` — source of truth for the Libretto skill
159
+
160
+ Run `pnpm sync:mirrors` after editing `README.template.md` or anything under `skills/libretto/`. `pnpm i` also resyncs the skill mirrors through `postinstall`.
161
+
162
+ To check that generated READMEs, skill mirrors, and skill version metadata are in sync without fixing them, run `pnpm check:mirrors`. To release, run `pnpm prepare-release`.
@@ -0,0 +1,160 @@
1
+ # Libretto
2
+
3
+ [![npm version](https://img.shields.io/npm/v/libretto)](https://www.npmjs.com/package/libretto)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+ [![GitHub Discussions](https://img.shields.io/github/discussions/saffron-health/libretto)](https://github.com/saffron-health/libretto/discussions)
6
+
7
+ Libretto is a toolkit for building robust web integrations. It gives your coding agent a live browser and a token-efficient CLI to:
8
+
9
+ - Inspect live pages with minimal context overhead
10
+ - Capture network traffic to reverse-engineer site APIs
11
+ - Record user actions and replay them as automation scripts
12
+ - Debug broken workflows interactively against the real site
13
+
14
+ We at [Saffron Health](https://saffron.health) built Libretto to help us maintain our browser integrations to common healthcare software. We're open-sourcing it so other teams have an easier time doing the same thing.
15
+
16
+ https://github.com/user-attachments/assets/9b9a0ab3-5133-4b20-b3be-459943349d18
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install libretto
22
+
23
+ # Install skill, download Chromium if not already installed, configure snapshot analysis
24
+ npx libretto init
25
+
26
+ # Configure or change the snapshot analysis model (see Configuration section below). `npx libretto init` sets this up the first time.
27
+ npx libretto ai configure <openai | anthropic | gemini | vertex>
28
+ ```
29
+
30
+ ## Use cases
31
+
32
+ Libretto is designed to be used as a skill through your coding agent. Here are some example prompts:
33
+
34
+ ### One-shot script generation
35
+
36
+ > Use the Libretto skill. Go on LinkedIn and scrape the first 10 posts for content, who posted it, the number of reactions, the first 25 comments, and the first 25 reposts.
37
+
38
+ Your coding agent will open a window for you to log into LinkedIn, and then automatically start exploring.
39
+
40
+ ### Interactive script building
41
+
42
+ > I'm gonna show you a workflow in the eclinicalworks EHR to get a patient's primary insurance ID. Use libretto skill to turn it into a playwright script that takes patient name and dob as input to get back the insurance ID. URL is ...
43
+
44
+ Libretto can read your actions you perform in the browser, so you can perform a workflow, then ask it to use your actions to rebuild the workflow.
45
+
46
+ ### Convert browser automation to network requests
47
+
48
+ > We have a browser script at ./integration.ts that automates going to Hacker News and getting the first 10 posts. Convert it to direct network scripts instead. Use the Libretto skill.
49
+
50
+ Libretto can read network requests from the browser, which it can use to reverse engineer the API and create a script that directly calls those requests. Directly making API calls is faster, and more reliable, than UI automation. You can also ask Libretto to conduct a security analysis which analyzes the requests for common security cookies, so you can understand whether a network request approach will be safe.
51
+
52
+ ### Fix broken integrations
53
+
54
+ > We have a browser script at ./integration.ts that is supposed to go to Availity and perform an eligibility check for a patient. But I'm getting a broken selector error when I run it. Fix it. Use the Libretto skill.
55
+
56
+ Agents can use Libretto to reproduce the failure, pause the workflow at any point, inspect the live page, and fix issues, all autonomously.
57
+
58
+ ### CLI usage
59
+
60
+ You can also use Libretto directly from the command line. All commands accept `--session <name>` to target a specific session.
61
+
62
+ ```bash
63
+ npx libretto init # interactive; run yourself, not through an agent
64
+ npx libretto open <url> # launch browser and open a URL (headed by default)
65
+ npx libretto snapshot --objective "..." --context "..." # capture PNG + HTML and analyze with an LLM
66
+ npx libretto exec "<code>" # execute Playwright TypeScript against the open page (single quoted argument)
67
+ echo "<code>" | npx libretto exec - # intentionally read Playwright TypeScript from stdin
68
+ npx libretto run <file> <workflowName> # run an exported workflow from a file
69
+ npx libretto resume # resume a paused workflow
70
+ npx libretto network # view captured network requests
71
+ npx libretto actions # view captured user/agent actions
72
+ npx libretto pages # list open pages in the session
73
+ npx libretto save <domain> # save browser session (cookies, localStorage) for reuse
74
+ npx libretto close # close the browser
75
+ npx libretto ai configure <provider> # configure snapshot analysis model
76
+ ```
77
+
78
+ ## Configuration
79
+
80
+ All Libretto state lives in a `.libretto/` directory at your project root. Configuration is stored in `.libretto/config.json`.
81
+
82
+ ### Config file
83
+
84
+ `.libretto/config.json` controls snapshot analysis and viewport settings:
85
+
86
+ ```json
87
+ {
88
+ "version": 1,
89
+ "ai": {
90
+ "model": "openai/gpt-5.4",
91
+ "updatedAt": "2026-01-01T00:00:00.000Z"
92
+ },
93
+ "viewport": { "width": 1280, "height": 800 }
94
+ }
95
+ ```
96
+
97
+ The `ai` field configures which model Libretto uses for snapshot analysis — extracting selectors, identifying interactive elements, or diagnosing why a step failed. This keeps heavy visual context out of your coding agent's context window. Snapshot analysis is required.
98
+
99
+ The easiest way to set the model is through the CLI:
100
+
101
+ ```bash
102
+ npx libretto ai configure <openai | anthropic | gemini | vertex>
103
+ ```
104
+
105
+ Provider credentials are read from environment variables or a `.env` file at your project root: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY` / `GOOGLE_GENERATIVE_AI_API_KEY`, or `GOOGLE_CLOUD_PROJECT` for Vertex.
106
+
107
+ The `viewport` field sets the default browser viewport size. Both fields are optional.
108
+
109
+ ### Sessions
110
+
111
+ Each Libretto session gets its own directory under `.libretto/sessions/<name>/` containing runtime state. Sessions are git-ignored.
112
+
113
+ - `state.json` — session metadata (debug port, PID, status)
114
+ - `logs.jsonl` — structured session logs
115
+ - `network.jsonl` — captured network requests
116
+ - `actions.jsonl` — recorded user actions
117
+ - `snapshots/` — screenshot PNGs and HTML snapshots
118
+
119
+ ### Profiles
120
+
121
+ Profiles save browser sessions (cookies, localStorage) so you can reuse authenticated state across runs. They are stored in `.libretto/profiles/<domain>.json`, created via `npx libretto save <domain>`. Profiles are machine-local and git-ignored.
122
+
123
+ ## Community
124
+
125
+ Have a question, idea, or want to share what you've built? Join the conversation on [GitHub Discussions](https://github.com/saffron-health/libretto/discussions).
126
+
127
+ - **[Q&A](https://github.com/saffron-health/libretto/discussions/categories/q-a)** — Ask questions and get help
128
+ - **[Ideas](https://github.com/saffron-health/libretto/discussions/categories/ideas)** — Suggest new features or improvements
129
+ - **[Show and tell](https://github.com/saffron-health/libretto/discussions/categories/show-and-tell)** — Share your workflows and automations
130
+ - **[General](https://github.com/saffron-health/libretto/discussions/categories/general)** — Chat about anything Libretto-related
131
+
132
+ Found a bug? Please [open an issue](https://github.com/saffron-health/libretto/issues/new).
133
+
134
+ ## Authors
135
+
136
+ Maintained by the team at [Saffron Health](https://saffron.health).
137
+
138
+ ## Development
139
+
140
+ For local development in this repository:
141
+
142
+ ```bash
143
+ pnpm i
144
+ pnpm build
145
+ pnpm type-check
146
+ pnpm test
147
+ ```
148
+
149
+ Source layout:
150
+
151
+ - `{{LIBRETTO_PATH_PREFIX}}src/cli/` — CLI commands
152
+ - `{{LIBRETTO_PATH_PREFIX}}src/runtime/` — browser runtime (network, recovery, downloads, extraction)
153
+ - `{{LIBRETTO_PATH_PREFIX}}src/shared/` — shared utilities (config, LLM client, logging, state)
154
+ - `{{LIBRETTO_PATH_PREFIX}}test/` — test files (`*.spec.ts`)
155
+ - `{{LIBRETTO_PATH_PREFIX}}README.template.md` — source of truth for the repo and package READMEs
156
+ - `{{LIBRETTO_PATH_PREFIX}}skills/libretto/` — source of truth for the Libretto skill
157
+
158
+ Run `pnpm sync:mirrors` after editing `{{LIBRETTO_PATH_PREFIX}}README.template.md` or anything under `{{LIBRETTO_PATH_PREFIX}}skills/libretto/`. `pnpm i` also resyncs the skill mirrors through `postinstall`.
159
+
160
+ To check that generated READMEs, skill mirrors, and skill version metadata are in sync without fixing them, run `pnpm check:mirrors`. To release, run `pnpm prepare-release`.
package/dist/cli/cli.js CHANGED
@@ -1,19 +1,10 @@
1
- import {
2
- closeLogger,
3
- createLoggerForSession,
4
- ensureLibrettoSetup
5
- } from "./core/context.js";
6
- import {
7
- SESSION_DEFAULT,
8
- validateSessionName
9
- } from "./core/session.js";
1
+ import { ensureLibrettoSetup } from "./core/context.js";
10
2
  import { createCLIApp } from "./router.js";
11
3
  function renderUsage(app) {
12
4
  return `${app.renderHelp()}
13
5
 
14
6
  Options:
15
- --session <name> Use a named session (default: "default")
16
- Built-in sessions: default, dev-server, browser-agent
7
+ --session <name> Use a named session (auto-generated for open/run if omitted)
17
8
 
18
9
  Examples:
19
10
  libretto open https://linkedin.com
@@ -31,7 +22,7 @@ Examples:
31
22
  libretto ai configure openai/gpt-4o
32
23
  libretto snapshot
33
24
  libretto snapshot --objective "Find the submit button" --context "Submitting a referral form, already filled in patient details"
34
- libretto resume --session default
25
+ libretto resume --session my-session
35
26
  libretto close
36
27
  libretto close --all
37
28
  libretto close --all --force
@@ -56,67 +47,6 @@ Sessions:
56
47
  Each session runs an isolated browser instance on a dynamic port.
57
48
  `;
58
49
  }
59
- function readSessionArgBeforePassthrough(rawArgs) {
60
- for (let index = 0; index < rawArgs.length; index += 1) {
61
- const token = rawArgs[index];
62
- if (token === "--") return void 0;
63
- if (token === "--session") {
64
- const value2 = rawArgs[index + 1];
65
- if (!value2 || value2 === "--" || value2.startsWith("--")) {
66
- return null;
67
- }
68
- return value2;
69
- }
70
- if (!token.startsWith("--session=")) continue;
71
- const value = token.slice("--session=".length);
72
- if (value.length === 0 || value === "--" || value.startsWith("--")) {
73
- return null;
74
- }
75
- return value;
76
- }
77
- return void 0;
78
- }
79
- function parseSessionForLog(rawArgs) {
80
- const value = readSessionArgBeforePassthrough(rawArgs);
81
- if (value === void 0 || value === null) {
82
- return SESSION_DEFAULT;
83
- }
84
- try {
85
- validateSessionName(value);
86
- return value;
87
- } catch {
88
- return SESSION_DEFAULT;
89
- }
90
- }
91
- function validateLegacySessionArg(rawArgs) {
92
- const value = readSessionArgBeforePassthrough(rawArgs);
93
- if (value === void 0) return;
94
- if (value === null) {
95
- throw new Error(
96
- `Usage: libretto <command> [--session <name>]
97
- Missing or invalid --session value.`
98
- );
99
- }
100
- validateSessionName(value);
101
- }
102
- function initializeLogger(rawArgs) {
103
- const sessionForLog = parseSessionForLog(rawArgs);
104
- const logger = createLoggerForSession(sessionForLog);
105
- logger.info("cli-start", {
106
- args: rawArgs,
107
- cwd: process.cwd(),
108
- session: sessionForLog
109
- });
110
- return logger;
111
- }
112
- async function withCliLogger(rawArgs, run) {
113
- const logger = initializeLogger(rawArgs);
114
- try {
115
- return await run(logger);
116
- } finally {
117
- await closeLogger(logger);
118
- }
119
- }
120
50
  function isRootHelpRequest(rawArgs) {
121
51
  if (rawArgs.length === 0) return true;
122
52
  if (rawArgs[0] === "--help" || rawArgs[0] === "-h") return true;
@@ -126,32 +56,27 @@ async function runLibrettoCLI() {
126
56
  const rawArgs = process.argv.slice(2);
127
57
  let exitCode = 0;
128
58
  ensureLibrettoSetup();
129
- await withCliLogger(rawArgs, async (logger) => {
130
- const app = createCLIApp(logger);
131
- try {
132
- validateLegacySessionArg(rawArgs);
133
- if (isRootHelpRequest(rawArgs)) {
134
- console.log(renderUsage(app));
135
- return;
136
- }
137
- logger.info("cli-command", { args: rawArgs });
138
- const result = await app.run(rawArgs);
139
- if (typeof result === "string") {
140
- console.log(result);
141
- }
142
- } catch (err) {
143
- logger.error("cli-error", { error: err, args: rawArgs });
144
- const message = err instanceof Error ? err.message : String(err);
145
- if (message.startsWith("Unknown command: ")) {
146
- console.error(`${message}
59
+ const app = createCLIApp();
60
+ try {
61
+ if (isRootHelpRequest(rawArgs)) {
62
+ console.log(renderUsage(app));
63
+ return;
64
+ }
65
+ const result = await app.run(rawArgs);
66
+ if (typeof result === "string") {
67
+ console.log(result);
68
+ }
69
+ } catch (err) {
70
+ const message = err instanceof Error ? err.message : String(err);
71
+ if (message.startsWith("Unknown command: ")) {
72
+ console.error(`${message}
147
73
  `);
148
- console.log(renderUsage(app));
149
- } else {
150
- console.error(message);
151
- }
152
- exitCode = 1;
74
+ console.log(renderUsage(app));
75
+ } else {
76
+ console.error(message);
153
77
  }
154
- });
78
+ exitCode = 1;
79
+ }
155
80
  process.exit(exitCode);
156
81
  }
157
82
  export {