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
@@ -1,453 +1,206 @@
1
1
  ---
2
2
  name: libretto
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)"
3
+ description: "Browser automation CLI for building, maintaining, and running browser automation workflows by inspecting live pages and prototyping interactions."
4
4
  license: MIT
5
5
  metadata:
6
6
  author: saffron-health
7
- version: "0.2.4"
7
+ version: "0.4.2"
8
8
  ---
9
9
 
10
- # Browser Integration with Libretto CLI
10
+ ## How Libretto Works
11
11
 
12
- Use the `npx libretto` CLI to automate web interactions, debug browser agent jobs, and prototype fixes.
12
+ - Libretto is a CLI for exploring live websites and building or debugging reusable browser automation scripts.
13
+ - Use Libretto to inspect the real site first: open pages, observe state, inspect requests, and prototype interactions before writing code.
14
+ - Libretto work must end in script changes. Create or edit the workflow file instead of stopping at interactive exploration.
13
15
 
14
- ## Session Access
16
+ ## Default Integration Approach
15
17
 
16
- Libretto sessions are **full-access by default** (no approval prompts). You can use `exec` immediately after opening a session. `run` starts its own workflow browser process and requires the target session to be available.
18
+ - Prefer network requests first for new integrations.
19
+ - Read `references/site-security-review.md` before committing to a network-first approach on a new site.
20
+ - Fall back to passive interception or Playwright-driven UI automation when the security review rules network requests out, the request path is not workable, or the user explicitly asks for Playwright.
17
21
 
18
- **Rules:**
22
+ ## Setup
19
23
 
20
- - Always announce which session you opened and what page you are on.
21
- - Use `snapshot`, `network`, and `actions` first when debugging unknown page state.
22
- - Before any potentially mutating action (submit/save/delete, or non-idempotent API calls), describe what you are about to do and wait for explicit user confirmation.
24
+ - Ask the user to set up snapshot analysis before relying on `snapshot` for page understanding.
25
+ - Use `npx libretto init` for first-time workspace setup.
26
+ - If credentials are already available, `npx libretto ai configure openai|anthropic|gemini|vertex` is usually enough.
23
27
 
24
- ## Ask, Don't Guess
28
+ ## Working Rules
25
29
 
26
- If it's not obvious which element to click or what value to enter, **ask the user** — don't try multiple things hoping one works. Present what you see on the page and let the user tell you where to go. One question is faster than a 30-second timeout from a wrong guess.
30
+ - Announce which session you are using and what page you are on.
31
+ - Ask instead of guessing when it is unclear what to click, type, or submit.
32
+ - Read and follow guidelines in `references/code-generation-rules.md` before generating or editing production workflow code.
33
+ - After interactive exploration and code generation, test key logic with `exec`, then verify the workflow file with `run --headless`.
34
+ - Get explicit user confirmation before mutating actions or replaying network requests that may have side effects.
35
+ - Never run multiple `exec` commands at the same time.
36
+ - Keep the browser session open until the user says the session is done.
27
37
 
28
38
  ## Commands
29
39
 
30
- ```bash
31
- npx libretto open <url> [--headed|--headless] # Launch browser and navigate (headed by default)
32
- npx libretto exec <code> [--visualize] # Execute Playwright TypeScript code (--visualize enables ghost cursor + highlight)
33
- npx libretto run <integrationFile> <integrationExport> [--params <json> | --params-file <path>] [--auth-profile <domain>] [--headed|--headless] # Execute integration actions
34
- npx libretto resume # Resume a paused workflow for the current session
35
- npx libretto snapshot --objective "<what to find>" [--context "<situational info>"]
36
- npx libretto save <url|domain> # Save session (cookies, localStorage) to .libretto/profiles/
37
- npx libretto network # Show last 20 captured network requests
38
- npx libretto actions # Show last 20 captured user/agent actions
39
- npx libretto pages # List open pages in the session
40
- npx libretto close # Close the browser
41
- ```
42
-
43
- All commands accept `--session <name>` for isolated browser instances (default: `default`).
44
- Built-in sessions: `default`, `dev-server`, `browser-agent`.
45
-
46
- ## Visualize Mode (`--visualize`)
47
-
48
- 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.
49
-
50
- ## Workflow Pause/Resume (`pause()`)
51
-
52
- Workflows pause by calling `await pause()` (imported from `"libretto"`). In production (`NODE_ENV=production`) it is a no-op.
53
-
54
- - There are no pause options to pass at call sites. Pause is session-scoped and resolved from the active session.
55
- - `npx libretto run ...` waits until the workflow either completes or hits the next `pause()`.
56
- - On pause, the workflow process stays alive and keeps browser/session state.
57
- - `npx libretto resume --session <name>` sends resume signal and then waits until completion or the next pause.
58
- - For multi-pause workflows, call `resume` repeatedly until the workflow completes.
59
-
60
- ## Workflow Failures and Reruns
61
-
62
- - `npx libretto run` always uses the same failure-inspection behavior; no separate debug flag is needed.
63
- - On workflow failure, Libretto prints the workflow error and keeps the browser open for inspection.
64
- - After a failed run, use `npx libretto exec --session <name> "<code>"` to inspect or prototype fixes.
65
- - Re-running `npx libretto run ... --session <name>` re-runs the workflow for that session.
66
- - If the same session still has a failed workflow worker, Libretto releases that failed worker process before rerunning.
67
-
68
- ## Globals Available in `exec`
69
-
70
- `page`, `context`, `state`, `browser`, `networkLog({ last?, filter?, method? })`, `actionLog({ last?, filter?, action?, source? })`, `console`, `fetch`, `Buffer`, `URL`, `setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`
71
-
72
- The `state` object is scoped to a single `exec` invocation and resets on the next call.
40
+ ### `open`
73
41
 
74
- ## CRITICAL: No try/catch in exec
42
+ - Open a page before using `exec` or `snapshot`.
43
+ - Use `open` at the start of script authoring when you need live page state to decide how the workflow should work.
44
+ - Use headed mode when the user needs to log in or watch the workflow.
75
45
 
76
- **Never use try/catch or .catch() in exec code.** Let errors throw so they surface as exec failures. When an exec fails, you get the full error message (e.g., "intercepts pointer events", "Timeout 30000ms exceeded") — use that to diagnose the problem and write a corrected exec.
77
-
78
- **Why:** A try/catch inside exec hides failures from you. A click that times out takes 30 seconds — if you retry it in a loop with try/catch, you'll silently burn minutes on the same broken selector with no way to recover. Without try/catch, the error comes back immediately and you can reason about what went wrong.
79
-
80
- **Instead of try/catch, use check-first patterns:**
46
+ ```bash
47
+ npx libretto open https://example.com --headed
48
+ npx libretto open https://example.com --headless --session debug-example
49
+ ```
81
50
 
82
- ```typescript
83
- // BAD — silently retries for minutes
84
- try {
85
- await btn.click();
86
- } catch {
87
- /* retry or ignore */
88
- }
51
+ ### `connect`
89
52
 
90
- // GOODcheck first, fail fast
91
- if (await btn.isVisible()) await btn.click();
53
+ - Use `connect` to attach to any existing Chrome DevTools Protocol (CDP) endpoint a browser started with `--remote-debugging-port`, an Electron app, or any other CDP-compatible target.
54
+ - After connecting, `exec`, `snapshot`, `pages`, and all other session commands work normally.
55
+ - Libretto does not manage the connected process's lifecycle. `close` clears the session but does not terminate the remote process.
92
56
 
93
- // GOOD — check existence before acting
94
- if ((await page.locator(".cookie-banner").count()) > 0) {
95
- await page.locator(".cookie-banner button").click();
96
- }
57
+ ```bash
58
+ npx libretto connect http://127.0.0.1:9222 --session my-session
59
+ npx libretto connect http://127.0.0.1:9223 --session another-session
97
60
  ```
98
61
 
99
- If an action fails despite an element being visible, you should not keep retrying it. Instead you can try the following debugging steps:
100
-
101
- 1. Take a snapshot to inspect what's covering the element
102
- 2. Try `{ force: true }` to bypass actionability checks
103
- 3. Try a completely different approach (e.g., opening a dialog via a different button)
62
+ ### `snapshot`
104
63
 
105
- ## Workflow: Browse and Interact
64
+ - Use `snapshot` as the primary page observation tool.
65
+ - Always provide both `--objective` and `--context`.
66
+ - Use it before guessing at selectors, after workflow failures, and whenever the visible page state is unclear.
67
+ - When analysis is involved, expect it to take time. Use a timeout of at least 2 minutes for shell-wrapped calls.
106
68
 
107
69
  ```bash
108
- # Open a page
109
- npx libretto open https://example.com
110
-
111
- # Interact with elements
112
- npx libretto exec "await page.locator('button:has-text(\"Sign in\")').click()"
113
- npx libretto exec "await page.fill('input[name=\"email\"]', 'user@example.com')"
114
-
115
- # Understand the page — always provide objective and context
116
70
  npx libretto snapshot \
117
- --objective "Find the sign-in form fields and submit button" \
118
- --context "Navigated to example.com login page. Expecting email/password inputs and a submit button."
119
-
120
- # Include relevant network calls in context when debugging API interactions
71
+ --objective "Find the sign-in form and submit button" \
72
+ --context "I just opened the login page and need the email field, password field, and submit button."
121
73
  npx libretto snapshot \
122
- --objective "Find why the referral list is empty" \
123
- --context "Logged into eClinicalWorks. Clicked Open Referrals tab. Table appears but shows no rows. Recent POST to /servlet/AjaxServlet returned 200 but with empty body."
124
-
125
- # Done
126
- npx libretto close
74
+ --session debug-example \
75
+ --page <page-id> \
76
+ --objective "Explain why the table is empty" \
77
+ --context "I opened the referrals page, applied filters, and expected rows to appear."
127
78
  ```
128
79
 
129
- ## Workflow: Save and Restore Login Sessions
80
+ ### `exec`
130
81
 
131
- Profiles persist cookies and localStorage across browser launches. They are saved to `.libretto/profiles/<domain>.json` (git-ignored) and loaded automatically on `open`.
82
+ - Use `exec` for focused inspection and short-lived interaction experiments.
83
+ - Use `exec` to validate selectors, inspect data, or prototype a step before you encode it in the workflow file.
84
+ - Let failures throw. Do not hide `exec` failures with `try/catch` or `.catch()`.
85
+ - Do not run multiple `exec` commands in parallel.
132
86
 
133
87
  ```bash
134
- # Open a site in headed mode so you can log in manually
135
- npx libretto open https://portal.example.com --headed
136
-
137
- # ... manually log in in the browser window ...
138
-
139
- # Save the session
140
- npx libretto save portal.example.com
141
-
142
- # Next time you open this domain, you'll be logged in automatically
143
- npx libretto open https://portal.example.com
88
+ npx libretto exec "return await page.url()"
89
+ npx libretto exec "return await page.locator('button').count()"
90
+ npx libretto exec --visualize "await page.locator('button:has-text(\"Continue\")').click()"
144
91
  ```
145
92
 
146
- ## Workflow: Interactive Debugging
93
+ ### `pages`
147
94
 
148
- When browser automation jobs fail (selectors timing out, clicks not working), use the interactive debugging workflow instead of edit-restart cycles. This reduces iteration time from 5-10 minutes to ~30 seconds.
149
-
150
- 1. Add `page.pause()` before the problematic code section
151
- 2. Start the job with `npx browser-agent start` (debug mode is always enabled locally)
152
- 3. Wait ~60 seconds for the browser to hit the breakpoint
153
- 4. Use `npx libretto exec` (with `--session browser-agent`) to inspect and prototype fixes
154
- 5. Once the fix works, codify it in source files
155
- 6. Restart the job to verify end-to-end
95
+ - Use `pages` when a popup, new tab, or second page appears.
96
+ - If `exec`, `snapshot`, `network`, or `actions` complains about multiple pages, list page ids first and then pass `--page`.
156
97
 
157
98
  ```bash
158
- # Start job in background
159
- npx browser-agent start \
160
- --job-type pull-open-referrals \
161
- --tenant-slug hhb \
162
- --params '{"vendorName":"eClinicalWorks"}'
163
-
164
- # Inspect page state
165
- npx libretto exec --session browser-agent "return await page.url();"
166
- npx libretto snapshot --session browser-agent \
167
- --objective "Find dropdown menus and their current selections" \
168
- --context "Browser agent hit breakpoint during pull-open-referrals job. Need to inspect dropdown state."
169
-
170
- # List dropdown options
171
- npx libretto exec --session browser-agent "return await page.locator('option').allTextContents();"
172
-
173
- # Test a fix
174
- npx libretto exec --session browser-agent "await page.locator('.dropdown-trigger').click(); return 'clicked';"
99
+ npx libretto pages --session debug-example
100
+ npx libretto exec --session debug-example --page <page-id> "return await page.url()"
175
101
  ```
176
102
 
177
- ## Snapshot — The Primary Observation Tool
178
-
179
- The `snapshot` command captures a PNG screenshot + HTML and (when `--objective` is provided) runs analysis through the configured AI runtime (`codex`, `claude`, or `gemini` via `npx libretto ai configure ...`). `--context` is optional (but recommended for better results). This is the single way to understand what's on the page — use it any time you need to inspect page structure, find elements, or debug what's happening.
180
-
181
- **Never use `page.screenshot()` via `exec` to understand the page.** Use the `snapshot` command instead — it captures the screenshot, HTML, and runs analysis with selectors. Raw screenshots give you an image with no analysis; `snapshot` gives you the answer.
182
-
183
- ### What to Put in `--objective`
184
-
185
- The objective tells the vision agent what you're looking for. Be specific:
186
-
187
- - "Find the referral status column in the table"
188
- - "Find the error message or alert preventing form submission"
189
- - "Identify all dropdown menus on the page and their current selections"
190
-
191
- ### What to Put in `--context`
103
+ ### `network`
192
104
 
193
- Context gives the vision agent situational awareness. Include:
194
-
195
- 1. **Where you are** — page, step, state (e.g., "On the eClinicalWorks referral list page")
196
- 2. **What you did** — actions taken (e.g., "Clicked 'Open Referrals' tab, selected department 'Cardiology'")
197
- 3. **What you expect** — desired state (e.g., "Expecting a table of open referrals with patient names")
198
- 4. **Relevant selectors** — any CSS selectors, data-testids, or element identifiers you already know about
199
- 5. **Task context** — what the automation is trying to accomplish overall
200
- 6. **Network calls** — any relevant HTTP requests/responses (e.g., "POST /api/referrals returned 200 with empty array")
105
+ - Use `network` to inspect the requests the page already made.
106
+ - Prefer this when discovering how a site loads data or when validating whether a network-first approach is workable.
107
+ - Filter aggressively by method, URL pattern, and page when the log is noisy.
201
108
 
202
109
  ```bash
203
- npx libretto snapshot \
204
- --objective "Find the referral status column in the table" \
205
- --context "Logged into eClinicalWorks as admin. Navigated to Referrals > Open Referrals tab. Expecting a table of open referrals with columns for patient name, provider, and status."
206
-
207
- # Debugging example
208
- npx libretto snapshot \
209
- --objective "Find the error message or alert" \
210
- --context "Clicked Submit on the new referral form after filling in all required fields. Expected to see a success confirmation, but the page appears to still be on the form."
110
+ npx libretto network --session debug-example --last 20
111
+ npx libretto network --session debug-example --method POST --filter 'referral|patient'
112
+ npx libretto network --session debug-example --page <page-id>
211
113
  ```
212
114
 
213
- ## Inspecting Raw DOM with `exec`
214
-
215
- When the snapshot doesn't give you enough detail — why an element is hidden, what directives or event handlers it has, how it's styled — use `exec` with `page.evaluate` to query the raw DOM directly.
216
-
217
- - **`outerHTML`** — See the complete markup of an element including all attributes.
218
- ```bash
219
- npx libretto exec "const el = await page.locator('#myElement').elementHandle(); return await page.evaluate(el => el.outerHTML.substring(0, 500), el);"
220
- ```
221
- - **Computed styles / parent chain** — Debug why Playwright can't click an element.
222
- ```bash
223
- npx libretto exec "const el = await page.locator('#myElement').elementHandle(); return await page.evaluate(el => { const chain = []; let n = el; for (let i = 0; i < 8 && n; i++) { const s = getComputedStyle(n); chain.push({ tag: n.tagName, id: n.id, display: s.display, visibility: s.visibility }); n = n.parentElement; } return chain; }, el);"
224
- ```
225
- - **Any DOM property** — `page.evaluate` gives you full access: `getBoundingClientRect()`, `dataset`, `children`, `classList`, attached event listeners, etc.
115
+ ### `actions`
226
116
 
227
- ## Tips
228
-
229
- - **Never use `page.screenshot()` via `exec`.** Use `npx libretto snapshot` instead — it captures the viewport plus HTML and returns analyzed output with 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).
230
- - **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.
231
- - `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`.
232
- - `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.
233
- - Use `return <value>` in `exec` to print results. Strings print raw; objects print as JSON.
234
- - For iframe content, access via `page.locator('iframe[name="..."]').contentFrame()`.
235
- - Multiple sessions allow parallel browser instances: `--session test1`, `--session test2`.
236
-
237
- ## Network Logging
238
-
239
- Network requests are captured automatically for Libretto-managed browser sessions (for example from `npx libretto open` and `npx libretto run`). Non-static HTTP responses are logged to `.libretto/sessions/<session>/network.jsonl`.
240
-
241
- ### CLI: `npx libretto network`
242
-
243
- ```bash
244
- npx libretto network # show last 20 requests
245
- npx libretto network --last 50 # show last 50
246
- npx libretto network --filter 'referral|patient' # regex filter on URL
247
- npx libretto network --method POST # filter by HTTP method
248
- npx libretto network --clear # truncate the log file
249
- ```
250
-
251
- ### In exec: `networkLog()`
117
+ - Use `actions` when you need a quick record of recent user or agent interactions in the current session.
118
+ - Keep it lightweight. It is a helper for orientation, not the main integration-building workflow.
252
119
 
253
120
  ```bash
254
- npx libretto exec "return await networkLog()"
255
- npx libretto exec "return await networkLog({ filter: 'servlet', last: 5 })"
256
- npx libretto exec "return await networkLog({ method: 'POST' })"
121
+ npx libretto actions --session debug-example --last 20
122
+ npx libretto actions --session debug-example --action click --source user
257
123
  ```
258
124
 
259
- Returns an array of objects with: `ts`, `method`, `url`, `status`, `contentType`, `postData` (POST/PUT/PATCH only, first 2000 chars), `size`, `durationMs`.
260
-
261
- **Note:** Network logging works for Libretto-managed sessions. It does not capture requests for external sessions like `--session browser-agent`.
125
+ ### `run`
262
126
 
263
- ## Action Logging
264
-
265
- Browser actions are captured automatically for Libretto-managed browser sessions (for example from `npx libretto open` and `npx libretto run`). Both user interactions (manual clicks, typing in the headed browser window) and agent actions (programmatic Playwright API calls via `exec`) are logged to `.libretto/sessions/<session>/actions.jsonl` with a `source` field of `'user'` or `'agent'` to distinguish the two.
266
-
267
- ### CLI: `npx libretto actions`
127
+ - Use `run` to verify a workflow file after creating it or editing it.
128
+ - If the workflow fails, Libretto keeps the browser open. Inspect the failed state with `snapshot` and `exec` before editing code.
129
+ - If the workflow pauses, resume it with `npx libretto resume --session <name>`.
130
+ - Re-run the same workflow after each fix to verify the browser behavior end to end.
268
131
 
269
132
  ```bash
270
- npx libretto actions # show last 20 actions
271
- npx libretto actions --last 50 # show last 50
272
- npx libretto actions --filter 'button|input' # regex filter on selector/value
273
- npx libretto actions --action click # filter by action type
274
- npx libretto actions --source user # only manual user actions
275
- npx libretto actions --source agent # only programmatic agent actions
276
- npx libretto actions --clear # truncate the log file
133
+ npx libretto run ./integration.ts main
134
+ npx libretto run ./integration.ts main --params '{"status":"open"}'
135
+ npx libretto run ./integration.ts main --auth-profile app.example.com --headed
277
136
  ```
278
137
 
279
- ### In exec: `actionLog()`
138
+ ### `resume`
280
139
 
281
- ```bash
282
- npx libretto exec "return await actionLog()"
283
- npx libretto exec "return await actionLog({ source: 'user', last: 5 })"
284
- npx libretto exec "return await actionLog({ action: 'click' })"
285
- ```
286
-
287
- Returns an array of objects with: `ts`, `action`, `source` (`'user'` | `'agent'`), `selector`, `value`, `url`, `duration`, `success`, `error`.
288
-
289
- **Note:** Action logging works for Libretto-managed sessions. It does not capture actions for external sessions like `--session browser-agent`.
290
-
291
- ## Workflow: Creating a New Integration
292
-
293
- Use Libretto CLI interactively to build a brand new integration from scratch. Navigate the real site with the user, discover the network endpoints, and codify the data extraction into a reusable TypeScript script.
294
-
295
- **IMPORTANT:** Do NOT explore the codebase or research existing code before starting. This skill file and the CLI commands below contain everything you need. Jump straight into using the CLI interactively — ask the user for the URL, open the browser, and start working. The only exception is if the user mentions a specific file or piece of code to reference — then read that specific file first, but nothing more.
296
-
297
- ### Approach Selection
298
-
299
- By default, use the **preferred ordering of approaches**: try the network-first approach (`page.evaluate(fetch(...))`) first, then fall back to Playwright DOM automation if that doesn't work (see "Integration Approaches" below).
300
-
301
- **If the user explicitly specifies an approach**, use it instead.
302
-
303
- As part of starting the session, silently run a **security posture review** using the probes from `integration-approach-selection.md` (in this skill's directory) to assess the site's bot detection, fetch interception, and security posture. This tells you:
304
-
305
- - Whether `page.evaluate(fetch(...))` is safe (fetch not patched, no aggressive bot detection)
306
- - Whether `page.on('response', ...)` interception is viable
307
- - Whether you need to restrict to DOM-only extraction
308
-
309
- If the security review reveals that the default network-first approach won't work (e.g., fetch is monkey-patched, aggressive bot detection), **adapt your approach accordingly and tell the user what you found and which approach you're switching to.** You don't need to ask permission to switch — just explain what you discovered and proceed.
310
-
311
- The user may also share context during the session that changes the approach (e.g., they know the site blocks direct fetch). Adapt as needed.
312
-
313
- ### Handling Approach Mismatches
314
-
315
- The security review tells you what's _safe_, but not necessarily what _works_ for every endpoint or data source on the site. As you build the integration, you may find that the recommended approach doesn't produce usable data for a specific part of the workflow. When this happens, **explain what you found, adapt your approach** for that specific part, and keep going.
316
-
317
- Common mismatches:
318
-
319
- - **Unparseable response format** — The fetch call succeeds but returns a proprietary format (RSC wire protocol, protobuf, encrypted payloads) instead of parseable JSON/XML/HTML.
320
- - **Data not in API responses** — The data is server-rendered into HTML or computed client-side; no network response contains it.
321
- - **Endpoint requires unpredictable parameters** — CSRF tokens, request signatures, or session values that rotate and aren't easily extractable.
322
-
323
- These can surface at any point — the first endpoint you try or the fifteenth. Different parts of the same integration often need different approaches.
324
-
325
- ### Starting the Session
326
-
327
- The browser stays open indefinitely until explicitly closed with `npx libretto close` or by the user closing the window. **Do not** set any timeouts, auto-close timers, or call `close` until the user says the workflow session is done. Ensure that you open the browser in `--headed` mode so the user can see what's happening.
328
-
329
- If the site requires login, ask the user how auth should work in the generated workflow:
330
-
331
- 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`).
332
- 2. Use user-managed credential logic in Playwright code (no local profile dependency).
333
-
334
- 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.
335
-
336
- ### Integration Approaches
337
-
338
- There are two main approaches for building an integration. **Try the network-first approach first** — it's faster, more reliable, and less brittle. Fall back to Playwright automation if it doesn't work. Be flexible — different parts of the same integration may use different approaches, and a single workflow often mixes them. The user can also explicitly tell you which approach to use.
339
-
340
- #### Approach 1: Network-First — `page.evaluate(() => fetch(...))` (Try First)
341
-
342
- Use `page.evaluate(() => fetch(...))` to make requests directly in the browser's JavaScript context — for both extracting data and performing actions (form submissions, API calls, etc.). The requests share the browser's TLS fingerprint, cookies, and origin, so they look identical to requests the site's own JS would make.
343
-
344
- **Why this is preferred:** Maximum control and reliability. You call exactly the endpoints you want with the parameters you want, skip fragile UI rendering, and get structured data back. No brittle DOM selectors, no multi-step UI sequences that break when the site changes its layout.
345
-
346
- **How to try it:**
347
-
348
- 1. Use Playwright to navigate the site normally. Network requests are captured automatically.
349
- 2. Check the network log (`npx libretto network` or `networkLog()`) to find API endpoints the site uses.
350
- 3. Recreate a key request with `page.evaluate(() => fetch(...))` and confirm it works.
351
-
352
- If the fetch call succeeds, this is your approach. You'll still use Playwright for navigation, login, and session setup — but data extraction and actions go through direct fetch calls.
353
-
354
- **When it won't work:** If `fetch` is monkey-patched, the site detects non-app-originated requests, or the API uses request signatures you can't replicate.
355
-
356
- #### Approach 2: Playwright Automation (Fallback)
357
-
358
- If direct fetch calls don't work, fall back to driving the UI with Playwright — clicking elements, filling forms, reading text from the DOM.
359
-
360
- **How to try it:**
361
-
362
- 1. Navigate to the page.
363
- 2. Use `npx libretto snapshot` to find selectors.
364
- 3. Drive the UI with Playwright locators (`page.locator(...).click()`, `.fill()`, `.textContent()`, etc.).
365
-
366
- This works regardless of the site's architecture but is slower and more fragile against layout changes.
367
-
368
- **Supplementing with `page.on('response', ...)`:** When using Playwright automation, you can optionally listen to network responses the browser makes as you navigate — `page.on('response', ...)` lets you capture API data that flows through the site's own code without making extra requests. This is useful when the site has API endpoints but blocks direct fetch calls. Set up listeners before the navigation that triggers the requests. Not all sites will have useful responses to intercept — some are entirely server-rendered.
369
-
370
- **The workflow for form submissions and data-heavy actions:**
371
-
372
- 1. Use Playwright to fill out the form, select dropdowns, check boxes — whatever the UI requires
373
- 2. **Ask the user for confirmation before submitting** — describe what you're about to submit and wait for approval
374
- 3. Submit the form — network requests are captured automatically (see "Network Logging" above)
375
- 4. Check the captured requests with `npx libretto network --method POST` or `networkLog()`
376
- 5. Inspect the captured request (URL, method, headers, body) to understand the payload structure
377
- 6. Test recreating that request directly via `page.evaluate(() => fetch(...))` — confirm with the user before sending
378
- 7. In the generated production code, skip the form-filling steps and fire the network request directly, parameterized with the relevant input values
379
-
380
- ### Discovering Network Endpoints
381
-
382
- Network requests are captured automatically in the background (see "Network Logging" above). Use the network log to discover endpoints instead of manually attaching listeners.
140
+ - Workflows pause by calling `await pause()` in the workflow file.
141
+ - Use `resume` when a workflow hit `await pause()`.
142
+ - Keep resuming the same session until the workflow completes or pauses again.
383
143
 
384
144
  ```bash
385
- # Fill out a form
386
- npx libretto exec "await page.locator('#department').selectOption('Cardiology'); return 'selected';"
387
- npx libretto exec "await page.locator('#status').selectOption('Open'); return 'selected';"
388
-
389
- # ASK THE USER before submitting — describe what will be submitted
390
- # Then submit and check what requests fired
391
- npx libretto exec "await page.locator('#submitBtn').click(); await page.waitForTimeout(3000); return 'submitted';"
392
- npx libretto network --method POST --last 5
393
-
394
- # Or query the log programmatically
395
- npx libretto exec "return await networkLog({ method: 'POST', last: 5 })"
145
+ npx libretto resume --session debug-example
396
146
  ```
397
147
 
398
- For page-load requests (data fetched during navigation), just navigate and then check the log:
148
+ ### `save`
149
+
150
+ - Use `save` when the user logs in manually and wants to reuse that authenticated browser state later.
399
151
 
400
152
  ```bash
401
- npx libretto exec "await page.goto('https://portal.example.com/encounters'); await page.waitForTimeout(3000); return 'loaded';"
402
- npx libretto network --last 20
153
+ npx libretto save app.example.com
403
154
  ```
404
155
 
405
- ### Testing a Captured Endpoint
406
-
407
- **Before making any `fetch()` call (GET or POST), always confirm with the user first.** These hit real server endpoints with real session auth — a wrong request could submit data, modify records, or trigger side effects. Describe the URL, method, and parameters you want to test and wait for approval.
156
+ ### `close`
408
157
 
409
- Note: `page.evaluate(() => fetch(...))` works for replaying both fetch-based and XHR-based endpoints — you're making a new request, not replaying the original mechanism.
158
+ - Use `close` only when the user is done with the session.
159
+ - `close --all` is available for workspace cleanup.
410
160
 
411
161
  ```bash
412
- # Recreate the captured request directly — confirm with user first
413
- npx libretto exec "
414
- const resp = await page.evaluate(async () => {
415
- const r = await fetch('/servlet/AjaxServlet', {
416
- method: 'POST',
417
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
418
- body: 'action=getReferrals&department=Cardiology&status=Open'
419
- });
420
- return await r.text();
421
- });
422
- return resp.substring(0, 1000);
423
- "
424
-
425
- # Extract session variables (safe — reads window properties, no server call)
426
- npx libretto exec "
427
- return await page.evaluate(() => ({
428
- sessionDID: (window as any).sessionDID,
429
- userId: (window as any).TrUserId
430
- }));
431
- "
162
+ npx libretto close --session debug-example
163
+ npx libretto close --all
432
164
  ```
433
165
 
434
- ### Generating Code
435
-
436
- After completing interactive exploration, **always generate the TypeScript workflow file before ending the session** — do not wait for the user to ask.
166
+ ## Examples
437
167
 
438
- **STOP AND ASK BEFORE GENERATING CODE.** Once the interactive workflow is figured out, pause and ask:
168
+ ### Building new browser automation workflows
439
169
 
440
- 1. "Are there any existing files or patterns in the codebase you want me to reference?"
441
- 2. Check the action log for user interactions by running `npx libretto actions --source user`. If there are any recorded user interactions, ask: "I see you performed some manual interactions in the browser (clicks, form fills, etc.). Would you like me to incorporate any of those into the generated code?" — and briefly list what you found. If there are no user interactions, skip this question entirely.
442
- 3. "Any other guidance for how the production code should be structured?"
170
+ #### Interactive building
443
171
 
444
- Wait for the user's response before proceeding. Then:
445
-
446
- 1. **Read `code-generation-rules.md`** (in this skill's directory) this is mandatory before writing any code. It contains the authoritative rules for Playwright locator usage, `page.evaluate()` restrictions, network request patterns, and type checking. Do not generate code from memory; always reference this file first.
447
- 2. Run the TypeScript type checker against the file and fix any errors before presenting it as done.
172
+ ```text
173
+ <example>
174
+ [Context: The user wants to build a new browser workflow and does not yet know the page structure]
175
+ Assistant: I'll inspect the real site first if needed, but before I finish I'll create `target-workflow.ts` so the task produces reusable automation code.
176
+ Assistant: [Runs `npx libretto open https://target.example.com --headed`]
177
+ Assistant: [Reads `references/site-security-review.md` before choosing between passive network inspection, direct browser fetch calls, and Playwright-first automation]
178
+ Assistant: [Runs `npx libretto snapshot --objective "Find the next required action" --context "We are starting the workflow from the landing page and need the first meaningful step."`]
179
+ Assistant: [Uses `network`, `snapshot`, and `exec` as needed to understand the site and decide the implementation path]
180
+ Assistant: [Reads `references/code-generation-rules.md` before writing production workflow code]
181
+ Assistant: I found the working path. I'll now update the workflow file outside Libretto and verify it with `npx libretto run ...`.
182
+ </example>
183
+ ```
448
184
 
449
- ## Patient Safety Warning
185
+ ### Debugging existing workflows
186
+
187
+ ```text
188
+ <example>
189
+ [Context: The user has an existing Libretto workflow that is failing]
190
+ Assistant: I'll reproduce the failure first so we can inspect the exact browser state it leaves behind.
191
+ Assistant: [Runs `npx libretto run ./integration.ts main --session debug-flow --headed`]
192
+ Assistant: The workflow failed and Libretto kept the browser open. I'll inspect the page state before changing code.
193
+ Assistant: [Runs `npx libretto snapshot --session debug-flow --objective "Find the blocking error or broken selector target" --context "The workflow just failed after trying to continue from the review step, and I need to identify the visible blocker on the current page."`]
194
+ Assistant: [Runs `npx libretto exec --session debug-flow "...focused inspection or prototype..."`]
195
+ Assistant: [Reads `references/code-generation-rules.md` before patching the workflow file]
196
+ Assistant: I found the issue. I'll patch the workflow code, then rerun `npx libretto run ...` to verify the fix.
197
+ </example>
198
+ ```
450
199
 
451
- Browser automation jobs process real patient health information. The `npx libretto` CLI executes arbitrary code with full page access. **Never execute mutating actions without explicit user confirmation first** (submits, sends, deletes, updates, or other side effects).
200
+ ## References
452
201
 
453
- For debugging steps, see the "Workflow: Interactive Debugging" section in this file.
202
+ - Read `references/configuration-file-reference.md` when you need to inspect or change `.libretto/config.json` for snapshot model selection or viewport defaults.
203
+ - Read `references/site-security-review.md` before reviewing the site's security posture and deciding whether to lead with network requests, passive interception, or Playwright DOM automation on a new site.
204
+ - Read `references/code-generation-rules.md` before writing or editing production workflow files.
205
+ - Read `references/auth-profiles.md` when the site requires login and the simplest path is to save local browser state.
206
+ - Read `references/pages-and-page-targeting.md` when a session has multiple open pages or you need `--page`.
@@ -0,0 +1,30 @@
1
+ # Auth Profiles
2
+
3
+ Use this reference when the target site requires login and the user wants to reuse local authenticated browser state.
4
+
5
+ ## When to Use This
6
+
7
+ - The site requires manual login.
8
+ - The user is running workflows locally.
9
+ - Reusing a saved session is simpler than building credential-handling logic into the workflow.
10
+
11
+ ## Workflow
12
+
13
+ - Open the site in headed mode.
14
+ - Ask the user to log in manually.
15
+ - Save the current session as a profile.
16
+ - Reopen the site or run the workflow with that profile.
17
+
18
+ ## Commands
19
+
20
+ ```bash
21
+ npx libretto open https://app.example.com --headed
22
+ npx libretto save app.example.com
23
+ npx libretto run ./integration.ts main --auth-profile app.example.com
24
+ ```
25
+
26
+ ## Notes
27
+
28
+ - Profiles are local to the current machine.
29
+ - Sessions can expire. If the profile stops working, repeat the login and save flow.
30
+ - Keep auth profiles as a brief operational detail in the main skill, not a full workflow pattern.