opensteer 0.6.13 → 0.7.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 (62) hide show
  1. package/README.md +256 -184
  2. package/dist/chunk-7QTHGTGN.js +32589 -0
  3. package/dist/chunk-7QTHGTGN.js.map +1 -0
  4. package/dist/cli/bin.cjs +38219 -0
  5. package/dist/cli/bin.cjs.map +1 -0
  6. package/dist/cli/bin.d.cts +1 -0
  7. package/dist/cli/bin.d.ts +1 -0
  8. package/dist/cli/bin.js +5612 -0
  9. package/dist/cli/bin.js.map +1 -0
  10. package/dist/index.cjs +31327 -16009
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.cts +4440 -670
  13. package/dist/index.d.ts +4440 -670
  14. package/dist/index.js +438 -378
  15. package/dist/index.js.map +1 -0
  16. package/package.json +58 -62
  17. package/skills/README.md +21 -20
  18. package/skills/opensteer/SKILL.md +60 -194
  19. package/skills/opensteer/references/cli-reference.md +69 -113
  20. package/skills/opensteer/references/request-workflow.md +81 -0
  21. package/skills/opensteer/references/sdk-reference.md +101 -154
  22. package/CHANGELOG.md +0 -75
  23. package/bin/opensteer.mjs +0 -1423
  24. package/dist/browser-profile-client-CGXc0-P9.d.cts +0 -228
  25. package/dist/browser-profile-client-DHLzMf-K.d.ts +0 -228
  26. package/dist/chunk-2ES46WCO.js +0 -1437
  27. package/dist/chunk-3H5RRIMZ.js +0 -69
  28. package/dist/chunk-AVXUMEDG.js +0 -62
  29. package/dist/chunk-DN3GI5CH.js +0 -57
  30. package/dist/chunk-FAHE5DB2.js +0 -190
  31. package/dist/chunk-HBTSQ2V4.js +0 -15259
  32. package/dist/chunk-K5CL76MG.js +0 -81
  33. package/dist/chunk-U724TBY6.js +0 -1262
  34. package/dist/chunk-ZRCFF546.js +0 -77
  35. package/dist/cli/auth.cjs +0 -2022
  36. package/dist/cli/auth.d.cts +0 -114
  37. package/dist/cli/auth.d.ts +0 -114
  38. package/dist/cli/auth.js +0 -15
  39. package/dist/cli/local-profile.cjs +0 -197
  40. package/dist/cli/local-profile.d.cts +0 -18
  41. package/dist/cli/local-profile.d.ts +0 -18
  42. package/dist/cli/local-profile.js +0 -97
  43. package/dist/cli/profile.cjs +0 -18548
  44. package/dist/cli/profile.d.cts +0 -79
  45. package/dist/cli/profile.d.ts +0 -79
  46. package/dist/cli/profile.js +0 -1328
  47. package/dist/cli/server.cjs +0 -17232
  48. package/dist/cli/server.d.cts +0 -2
  49. package/dist/cli/server.d.ts +0 -2
  50. package/dist/cli/server.js +0 -977
  51. package/dist/cli/skills-installer.cjs +0 -230
  52. package/dist/cli/skills-installer.d.cts +0 -28
  53. package/dist/cli/skills-installer.d.ts +0 -28
  54. package/dist/cli/skills-installer.js +0 -201
  55. package/dist/extractor-4Q3TFZJB.js +0 -8
  56. package/dist/resolver-MGN64KCP.js +0 -7
  57. package/dist/types-Cr10igF3.d.cts +0 -345
  58. package/dist/types-Cr10igF3.d.ts +0 -345
  59. package/skills/electron/SKILL.md +0 -87
  60. package/skills/electron/references/opensteer-electron-recipes.md +0 -88
  61. package/skills/electron/references/opensteer-electron-workflow.md +0 -85
  62. package/skills/opensteer/references/examples.md +0 -118
package/README.md CHANGED
@@ -1,208 +1,152 @@
1
- # Opensteer
1
+ # Opensteer Package
2
2
 
3
- Browser automation framework for AI agents to explore websites and build complex scrapers directly in your codebase.
3
+ `opensteer` is the main product surface for the repository. It exposes:
4
4
 
5
- Opensteer enables AI agents like Claude Code and Codex to interact with browsers and Electron applications, building scrapers directly in your local codebase. It provides a token-efficient suite of tools and agent skills designed for seamless integration.
5
+ - a semantic SDK with session continuity inside one process
6
+ - a thin JSON-first CLI
7
+ - a local per-session service so CLI commands can share one live browser session
8
+ - browser-native observation and instrumentation primitives
9
+ - deterministic replay through request plans, recipes, and saved evidence
10
+ - HTML-first snapshots, DOM action replay, computer-use actions, descriptor persistence, traces,
11
+ and artifacts
12
+
13
+ The package is organized around three lanes:
14
+
15
+ - `Interact`: open pages, navigate, evaluate, inspect DOM state, manage pages, use computer actions
16
+ - `Observe / Instrument`: capture network, capture scripts, add init scripts, route requests, replace scripts
17
+ - `Replay / Execute`: `direct-http`, `context-http`, `page-http`, reverse workflows, request plans, and recipes
6
18
 
7
19
  ## Install
8
20
 
9
- Main setup (recommended):
21
+ CLI:
10
22
 
11
23
  ```bash
12
24
  npm i -g opensteer
13
25
  opensteer skills install
14
26
  ```
15
27
 
16
- SDK package (when importing `Opensteer` in app code):
28
+ SDK:
17
29
 
18
30
  ```bash
31
+ pnpm add opensteer
32
+ pnpm exec playwright install chromium
33
+
19
34
  # npm
20
35
  npm install opensteer
21
36
 
22
- # pnpm
23
- pnpm add opensteer
24
-
25
- # bun
26
- bun add opensteer
37
+ # Optional ABP backend for `--engine abp`
38
+ pnpm add @opensteer/engine-abp
27
39
  ```
28
40
 
29
- ## Requirements
30
-
31
- - Node.js `>=20`
32
- - Playwright-supported browser runtime
33
- - Model provider API key for LLM-powered resolution/extraction/CUA
34
-
35
- If browser binaries are missing:
36
-
37
- ```bash
38
- npx playwright install chromium
39
- ```
41
+ `opensteer skills install` installs the packaged first-party skill pack through the upstream
42
+ `skills` CLI.
40
43
 
41
- ## What It Does
44
+ `opensteer` installs the Playwright-backed local engine by default. Add
45
+ `@opensteer/engine-abp` only when you need the ABP backend.
42
46
 
43
- - Unified local/cloud execution with the same API surface
44
- - Descriptor-aware actions with selector persistence for replay
45
- - Structured extraction with typed schemas
46
- - CUA agent support (`openai`, `anthropic`, `google`)
47
- - Stealth cursor preview for interactive actions (CLI default on, SDK default off)
47
+ Cloud features require access to an Opensteer Cloud deployment. This repository includes cloud
48
+ client code and shared contracts; the managed Opensteer Cloud service is operated separately.
48
49
 
49
- ## Quick Start: SDK
50
+ ## SDK
50
51
 
51
52
  ```ts
52
53
  import { Opensteer } from "opensteer";
53
54
 
54
- const opensteer = new Opensteer({ name: "quickstart" });
55
+ const opensteer = new Opensteer({
56
+ name: "docs-example",
57
+ rootDir: process.cwd(),
58
+ browser: { headless: true },
59
+ });
55
60
 
56
61
  try {
57
- await opensteer.launch();
58
- await opensteer.goto("https://example.com");
59
-
60
- await opensteer.snapshot({ mode: "action" });
61
- await opensteer.click({ description: "main call to action" });
62
-
63
- await opensteer.snapshot({ mode: "extraction" });
64
- const data = await opensteer.extract({
65
- description: "hero section",
66
- schema: { title: "string", href: "string" },
62
+ await opensteer.open({
63
+ url: "https://example.com",
64
+ browser: {
65
+ headless: true,
66
+ },
67
+ });
68
+ const snapshot = await opensteer.snapshot("action");
69
+ const firstButton = snapshot.counters.find((counter) => counter.tagName === "BUTTON");
70
+ if (firstButton) {
71
+ await opensteer.click({
72
+ element: firstButton.element,
73
+ description: "primary button",
74
+ });
75
+ }
76
+
77
+ const extracted = await opensteer.extract({
78
+ description: "page summary",
79
+ schema: {
80
+ url: { source: "current_url" },
81
+ title: { selector: "title" },
82
+ },
67
83
  });
68
84
 
69
- console.log(data);
85
+ console.log(snapshot.html);
86
+ console.log(extracted);
70
87
  } finally {
71
88
  await opensteer.close();
72
89
  }
73
90
  ```
74
91
 
75
- Enable cursor preview in SDK:
76
-
77
- ```ts
78
- const opensteer = new Opensteer({
79
- name: "quickstart",
80
- cursor: { enabled: true },
81
- });
82
- ```
83
-
84
- ## Quick Start: CUA Agent
92
+ Browser-backed replay:
85
93
 
86
94
  ```ts
87
95
  import { Opensteer } from "opensteer";
88
96
 
89
- const opensteer = new Opensteer({ model: "openai/computer-use-preview" });
97
+ const opensteer = new Opensteer({
98
+ name: "browser-backed-replay",
99
+ rootDir: process.cwd(),
100
+ browser: { headless: true },
101
+ });
90
102
 
91
103
  try {
92
- await opensteer.launch();
93
- const agent = opensteer.agent({ mode: "cua" });
94
- const result = await agent.execute({
95
- instruction: "Go to Hacker News and open the top story.",
96
- maxSteps: 20,
104
+ await opensteer.open("https://example.com/app");
105
+ const token = await opensteer.evaluate<string>({
106
+ script: "() => window.exampleToken",
97
107
  });
98
- console.log(result.message);
108
+
109
+ const response = await opensteer.rawRequest({
110
+ transport: "context-http",
111
+ url: "https://example.com/api/items",
112
+ method: "POST",
113
+ body: {
114
+ json: { token },
115
+ },
116
+ });
117
+
118
+ console.log(response.data);
99
119
  } finally {
100
120
  await opensteer.close();
101
121
  }
102
122
  ```
103
123
 
104
- ## Quick Start: CLI
105
-
106
- ```bash
107
- # Open a browser session and bind a selector namespace
108
- opensteer open https://example.com --session demo --name quickstart
109
-
110
- # Action snapshot + interaction
111
- opensteer snapshot action --session demo
112
- opensteer click --description "main call to action" --session demo
113
-
114
- # Cursor controls
115
- opensteer cursor status --session demo
116
- opensteer cursor off --session demo
117
-
118
- # Extraction snapshot + structured extract
119
- opensteer snapshot extraction --session demo
120
- opensteer extract '{"title":"string","href":"string"}' --description "hero section" --session demo
121
-
122
- # Close session
123
- opensteer close --session demo
124
- ```
125
-
126
- For non-interactive runs, set `OPENSTEER_SESSION` or `OPENSTEER_CLIENT_ID`.
127
- Runtime daemon routing for `OPENSTEER_SESSION` is scoped by canonical `cwd`
128
- (`realpath(cwd)`) + logical session id.
129
-
130
- Cursor defaults:
131
-
132
- - CLI sessions: enabled by default (toggle with `--cursor` or `opensteer cursor on|off`)
133
- - SDK instances: disabled by default (set `cursor.enabled: true` to opt in)
134
-
135
- ## For AI Agents
136
-
137
- Use this workflow to keep scripts replayable and maintainable:
138
-
139
- 1. Use Opensteer APIs (`goto`, `snapshot`, `click`, `input`, `extract`) instead of raw Playwright calls.
140
- 2. Keep namespace consistent: SDK `name` must match CLI `--name`.
141
- 3. Take `snapshot({ mode: "action" })` before actions and `snapshot({ mode: "extraction" })` before extraction.
142
- 4. Prefer `description` targeting for persistence and deterministic reruns.
143
- 5. Always wrap runs in `try/finally` and call `close()`.
124
+ Attach to an existing CLI-opened local session:
144
125
 
145
- First-party skills:
146
-
147
- - [skills/opensteer/SKILL.md](skills/opensteer/SKILL.md)
148
- - [skills/electron/SKILL.md](skills/electron/SKILL.md)
149
- - [skills/README.md](skills/README.md)
150
-
151
- Install the Opensteer skill pack:
152
-
153
- ```bash
154
- opensteer skills install
155
- ```
156
-
157
- Claude Code marketplace plugin:
158
-
159
- ```text
160
- /plugin marketplace add steerlabs/opensteer
161
- /plugin install opensteer@opensteer-marketplace
162
- ```
163
-
164
- ## Cloud Mode
165
-
166
- Opensteer defaults to local mode. Enable cloud mode with env or constructor options:
167
-
168
- ```bash
169
- OPENSTEER_MODE=cloud
170
- OPENSTEER_API_KEY=<your_api_key>
171
- ```
126
+ ```ts
127
+ import { Opensteer } from "opensteer";
172
128
 
173
- - Interactive CLI login:
129
+ const opensteer = Opensteer.attach({
130
+ name: "docs-example",
131
+ rootDir: process.cwd(),
132
+ });
174
133
 
175
- ```bash
176
- opensteer auth login
177
- opensteer auth status
178
- opensteer auth logout
134
+ try {
135
+ const state = await opensteer.open();
136
+ console.log(state.url);
137
+ } finally {
138
+ await opensteer.disconnect();
139
+ }
179
140
  ```
180
141
 
181
- - `opensteer auth login` opens your default browser when possible. Use
182
- `--no-browser` on remote shells, containers, or CI and paste the printed URL
183
- into a browser manually. In `--json` mode, login prompts go to stderr and the
184
- final JSON result stays on stdout.
185
- - Saved machine logins remain scoped per resolved cloud API host (`baseUrl`).
186
- The CLI also remembers the last selected cloud host, so `opensteer auth
187
- status`, `opensteer auth logout`, and other cloud commands reuse it by
188
- default unless `--base-url` or env vars select a different host.
189
-
190
- - `OPENSTEER_BASE_URL` overrides the default cloud host
191
- - `OPENSTEER_ACCESS_TOKEN` provides bearer auth for cloud commands
192
- - `OPENSTEER_AUTH_SCHEME` supports `api-key` (default) or `bearer`
193
- - Credential precedence: explicit flags > environment variables > saved machine login
194
- - `OPENSTEER_CLOUD_PROFILE_ID` optionally launches into a specific cloud browser profile
195
- - `OPENSTEER_CLOUD_PROFILE_REUSE_IF_ACTIVE` (`true|false`) optionally reuses an active profile session
196
- - `cloud: true` or a `cloud` options object overrides `OPENSTEER_MODE`
197
- - Cloud mode is fail-fast (no automatic fallback to local)
198
- - `Opensteer.from(page)`, `uploadFile`, `exportCookies`, and `importCookies` are local-only
199
-
200
- Select a cloud browser profile in SDK:
142
+ Launch a cloud session with a specific browser profile:
201
143
 
202
144
  ```ts
145
+ import { Opensteer } from "opensteer";
146
+
203
147
  const opensteer = new Opensteer({
204
148
  cloud: {
205
- accessToken: process.env.OPENSTEER_ACCESS_TOKEN,
149
+ apiKey: process.env.OPENSTEER_API_KEY!,
206
150
  browserProfile: {
207
151
  profileId: "bp_123",
208
152
  reuseIfActive: true,
@@ -211,56 +155,184 @@ const opensteer = new Opensteer({
211
155
  });
212
156
  ```
213
157
 
214
- Sync local profile cookies into a cloud profile:
158
+ Sync cookies from a live Chromium browser into an existing cloud profile:
159
+
160
+ ```ts
161
+ import { OpensteerCloudClient } from "opensteer";
162
+
163
+ const client = new OpensteerCloudClient({
164
+ apiKey: process.env.OPENSTEER_API_KEY!,
165
+ baseUrl: process.env.OPENSTEER_BASE_URL ?? "https://api.opensteer.dev",
166
+ });
167
+
168
+ await client.syncBrowserProfileCookies({
169
+ profileId: "bp_123",
170
+ attachEndpoint: "9222",
171
+ domains: ["github.com"],
172
+ });
173
+ ```
174
+
175
+ ## CLI
215
176
 
216
177
  ```bash
178
+ opensteer open https://example.com --name docs-example --headless true
179
+ opensteer open https://example.com --name docs-example --browser attach-live --attach-endpoint 9222
180
+ opensteer open https://example.com --name docs-example --browser snapshot-session \
181
+ --source-user-data-dir "~/Library/Application Support/Google/Chrome" \
182
+ --source-profile-directory Default
183
+ opensteer open https://example.com --name docs-example --browser snapshot-authenticated \
184
+ --source-user-data-dir "~/Library/Application Support/Google/Chrome" \
185
+ --source-profile-directory "Profile 1"
186
+ opensteer browser discover
187
+ opensteer browser inspect --endpoint 9222
188
+ opensteer local-profile list
189
+ opensteer local-profile inspect --user-data-dir "~/Library/Application Support/Opensteer Chrome"
190
+ opensteer local-profile unlock --user-data-dir "~/Library/Application Support/Opensteer Chrome"
217
191
  opensteer profile sync \
218
- --from-profile-dir ~/Library/Application\ Support/Google/Chrome/Default \
219
- --to-profile-id bp_123 \
192
+ --profile-id bp_123 \
193
+ --attach-endpoint 9222 \
220
194
  --domain github.com
195
+ opensteer open https://example.com --name docs-example --engine abp
196
+ opensteer snapshot action --name docs-example
197
+ opensteer click 3 --name docs-example --description "primary button"
198
+ opensteer extract --name docs-example --description "page summary" \
199
+ --schema '{"url":{"source":"current_url"},"title":{"selector":"title"}}'
200
+ opensteer computer '{"type":"screenshot"}' --name docs-example
201
+ opensteer close --name docs-example
221
202
  ```
222
203
 
223
- ## Resolution and Replay
204
+ CLI long flags are canonical kebab-case, for example `--root-dir`, `--network-tag`, and
205
+ `--press-enter`. Unknown flags and flags used on the wrong command fail fast instead of being
206
+ silently ignored.
224
207
 
225
- For descriptor-aware actions (`click`, `input`, `hover`, `select`, `scroll`):
208
+ Action and data commands print JSON to stdout. Help commands print human-readable usage text.
209
+ Browser state does not live in the CLI process. It lives
210
+ in the local session service recorded under `.opensteer/runtime/sessions/<name>/service.json`.
211
+ `opensteer computer` prints compact screenshot metadata and points at the persisted image through
212
+ `screenshot.path` for local shells and `screenshot.payload.uri` for the canonical file-backed
213
+ location.
226
214
 
227
- 1. Reuse persisted selector path from `description`
228
- 2. Try snapshot counter (`element`)
229
- 3. Try explicit CSS selector (`selector`)
230
- 4. Use LLM resolution (`description` required)
231
- 5. Return actionable error
215
+ Use `--engine <playwright|abp>` on `open` to choose the backend for a new session. You can also
216
+ set `OPENSTEER_ENGINE=abp` to change the default engine for `open` in the current shell. Engine
217
+ selection is fixed when the session service starts, so `OPENSTEER_ENGINE` and `--engine` only
218
+ affect `open`, not commands like `snapshot` or `click` that attach to an existing session.
219
+ When using `--engine abp`, Opensteer accepts the ABP launch options it can actually honor:
220
+ `--headless`, `--executable-path`, and equivalent `--browser-json` fields for `headless`, `args`,
221
+ and `executablePath`. Unsupported shared browser/context options fail fast instead of being
222
+ ignored.
232
223
 
233
- When step 2-4 succeeds and `description` is present, selector paths are cached
234
- in `.opensteer/selectors/<namespace>` for deterministic replay.
224
+ Use `opensteer local-profile inspect` to diagnose whether a live Chromium profile is safe to reuse
225
+ as a snapshot source or whether it should be attached via CDP instead. `opensteer local-profile unlock`
226
+ remains limited to explicit `stale_lock` recovery; Opensteer does not mutate or take ownership of
227
+ real user-data-dirs as part of `open`.
235
228
 
236
- ## Docs
229
+ ## Connect To Real Browser
237
230
 
238
- - [Getting Started](docs/getting-started.md)
239
- - [API Reference](docs/api-reference.md)
240
- - [CLI Reference](docs/cli-reference.md)
241
- - [Cloud Integration](docs/cloud-integration.md)
242
- - [Selectors and Storage](docs/selectors.md)
243
- - [HTML Cleaning and Snapshot Modes](docs/html-cleaning.md)
244
- - [Live Web Validation Suite](docs/live-web-tests.md)
245
- - [Skills](docs/skills.md)
231
+ - `managed` launches a fresh isolated Chrome/Chromium process with a temporary `user-data-dir`.
232
+ - `snapshot-session` copies a source profile into a temporary owned browser directory without full authenticated OS-integrated state. Use it when persisted cookies/storage are enough.
233
+ - `snapshot-authenticated` copies a source profile into a temporary owned browser directory and preserves the authenticated browser state needed for harder replay cases.
234
+ - `attach-live` connects to an already-running Chrome/Chromium instance. Pass `endpoint` for an explicit CDP target, or omit it to auto-discover a locally attachable browser.
246
235
 
247
- ## Development
236
+ When you are launching a browser yourself for `attach-live`, prefer a dedicated profile directory:
248
237
 
249
238
  ```bash
250
- pnpm install
251
- pnpm typecheck
252
- pnpm test
253
- pnpm build
239
+ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
240
+ --user-data-dir="$HOME/Library/Application Support/Opensteer Chrome" \
241
+ --remote-debugging-port=9222
254
242
  ```
255
243
 
256
- ## Community
244
+ When attaching to an existing browser, Opensteer may land on an already-open tab such as `chrome://newtab`. Pass `--fresh-tab` when you want a clean working page immediately after attach.
257
245
 
258
- - [Contributing](CONTRIBUTING.md)
259
- - [Code of Conduct](CODE_OF_CONDUCT.md)
260
- - [Security Policy](SECURITY.md)
261
- - [Discussions](https://github.com/steerlabs/opensteer/discussions)
262
- - [Changelog](CHANGELOG.md)
246
+ ## Transport Guide
263
247
 
264
- ## License
248
+ - `direct-http`: use when the request is replayable without a browser
249
+ - `context-http`: use when browser cookies or browser session state are required
250
+ - `page-http`: use when request execution must happen inside the live page JavaScript world
251
+
252
+ `goto()` plus `waitForNetwork()` is a separate pattern. It is how you observe the
253
+ page's own traffic; it is not a transport.
254
+
255
+ ## Session Root
256
+
257
+ By default, Opensteer writes into:
258
+
259
+ ```text
260
+ <cwd>/.opensteer
261
+ ```
262
+
263
+ Important subtrees:
264
+
265
+ ```text
266
+ .opensteer/
267
+ artifacts/
268
+ traces/
269
+ registry/
270
+ runtime/
271
+ sessions/
272
+ ```
265
273
 
266
- [MIT](LICENSE)
274
+ ## Public Methods
275
+
276
+ - `Opensteer.attach({ name?, rootDir? })`
277
+ - `discoverLocalCdpBrowsers({ timeoutMs? })`
278
+ - `inspectCdpEndpoint({ endpoint, headers?, timeoutMs? })`
279
+ - `inspectLocalBrowserProfile({ userDataDir? })`
280
+ - `unlockLocalBrowserProfile({ userDataDir })`
281
+ - `open(url | { url?, name?, browser?, context? })`
282
+ - `goto(url | { url, networkTag? })`
283
+ - `evaluate(script | { script, pageRef?, args? })`
284
+ - `evaluateJson({ script, pageRef?, args? })`
285
+ - `waitForNetwork({ ...filters, pageRef?, includeBodies?, timeoutMs? })`
286
+ - `waitForResponse({ ...filters, pageRef?, includeBodies?, timeoutMs? })`
287
+ - `listPages()`
288
+ - `newPage({ url?, openerPageRef? })`
289
+ - `activatePage({ pageRef })`
290
+ - `closePage({ pageRef })`
291
+ - `waitForPage({ openerPageRef?, urlIncludes?, timeoutMs? })`
292
+ - `snapshot("action" | "extraction")`
293
+ - `click({ element | selector | description, networkTag? })`
294
+ - `hover({ element | selector | description, networkTag? })`
295
+ - `input({ element | selector | description, text, networkTag? })`
296
+ - `scroll({ element | selector | description, direction, amount, networkTag? })`
297
+ - `extract({ description, schema? })`
298
+ - `queryNetwork({ source?, recordId?, requestId?, actionId?, tag?, url?, hostname?, path?, method?, status?, resourceType?, pageRef?, includeBodies?, limit? })`
299
+ - `saveNetwork({ tag, ...filters })`
300
+ - `clearNetwork({ tag? })`
301
+ - `captureScripts({ pageRef?, includeInline?, includeExternal?, includeDynamic?, includeWorkers?, urlFilter?, persist? })`
302
+ - `addInitScript({ script, args?, pageRef? })`
303
+ - `route({ urlPattern, resourceTypes?, times?, handler })`
304
+ - `interceptScript({ urlPattern, handler, times? })`
305
+ - `rawRequest({ transport?, pageRef?, url, method?, headers?, body?, followRedirects? })`
306
+ - `inferRequestPlan({ recordId, key, version, lifecycle? })`
307
+ - `writeRequestPlan({ key, version, payload, lifecycle?, tags?, provenance?, freshness? })`
308
+ - `getRequestPlan({ key, version? })`
309
+ - `listRequestPlans({ key? })`
310
+ - `writeRecipe({ key, version, payload, tags?, provenance? })`
311
+ - `getRecipe({ key, version? })`
312
+ - `listRecipes({ key? })`
313
+ - `runRecipe({ key, version?, input? })`
314
+ - `request(key, { path?, query?, headers?, body? })`
315
+ - `computerExecute({ action, screenshot?, networkTag? })`
316
+ - `disconnect()`
317
+ - `close()`
318
+
319
+ `element` targets use counters from the latest snapshot. `description` replays a stored descriptor.
320
+ `selector` resolves a CSS selector directly and, when not explicitly scoped, searches the current
321
+ page before falling back to child frames.
322
+
323
+ Use `disconnect()` for attached sessions when you want to release the SDK handle but keep the
324
+ underlying session alive. Use `close()` when you want to destructively end the session.
325
+
326
+ Profile inspection is independent from session ownership. `inspectLocalBrowserProfile()` returns a
327
+ structured status union (`available`, `unsupported_default_user_data_dir`, `opensteer_owned`,
328
+ `browser_owned`, `stale_lock`) that launch, CLI, and SDK all consume. Failed owned launches throw
329
+ `OpensteerLocalProfileUnavailableError` with the inspection attached for programmatic handling.
330
+
331
+ The reverse-engineering workflow is: perform a browser action, inspect traffic with
332
+ `queryNetwork()`, optionally instrument with `addInitScript()`, `route()`, or
333
+ `captureScripts()`, experiment with `rawRequest()`, promote a record with
334
+ `inferRequestPlan()`, then replay with `request()`.
335
+
336
+ `route()` and `interceptScript()` are only available on owned local SDK sessions.
337
+ They are not available on attached or cloud proxy sessions because they rely on a
338
+ live in-process route handler.