opensteer 0.6.12 → 0.7.0
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.
- package/README.md +256 -184
- package/dist/chunk-PQYA6IX2.js +32571 -0
- package/dist/chunk-PQYA6IX2.js.map +1 -0
- package/dist/cli/bin.cjs +38201 -0
- package/dist/cli/bin.cjs.map +1 -0
- package/dist/cli/bin.d.cts +1 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +5612 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/index.cjs +31342 -14617
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4437 -658
- package/dist/index.d.ts +4437 -658
- package/dist/index.js +438 -374
- package/dist/index.js.map +1 -0
- package/package.json +56 -62
- package/skills/README.md +21 -20
- package/skills/opensteer/SKILL.md +60 -194
- package/skills/opensteer/references/cli-reference.md +69 -113
- package/skills/opensteer/references/request-workflow.md +81 -0
- package/skills/opensteer/references/sdk-reference.md +101 -154
- package/CHANGELOG.md +0 -75
- package/bin/opensteer.mjs +0 -1423
- package/dist/browser-profile-client-CGXc0-P9.d.cts +0 -228
- package/dist/browser-profile-client-DHLzMf-K.d.ts +0 -228
- package/dist/chunk-2ES46WCO.js +0 -1437
- package/dist/chunk-3H5RRIMZ.js +0 -69
- package/dist/chunk-AVXUMEDG.js +0 -62
- package/dist/chunk-DN3GI5CH.js +0 -57
- package/dist/chunk-FAHE5DB2.js +0 -190
- package/dist/chunk-K5CL76MG.js +0 -81
- package/dist/chunk-RC4IPQDZ.js +0 -13828
- package/dist/chunk-U724TBY6.js +0 -1262
- package/dist/chunk-ZRCFF546.js +0 -77
- package/dist/cli/auth.cjs +0 -2022
- package/dist/cli/auth.d.cts +0 -114
- package/dist/cli/auth.d.ts +0 -114
- package/dist/cli/auth.js +0 -15
- package/dist/cli/local-profile.cjs +0 -197
- package/dist/cli/local-profile.d.cts +0 -18
- package/dist/cli/local-profile.d.ts +0 -18
- package/dist/cli/local-profile.js +0 -97
- package/dist/cli/profile.cjs +0 -17869
- package/dist/cli/profile.d.cts +0 -79
- package/dist/cli/profile.d.ts +0 -79
- package/dist/cli/profile.js +0 -1328
- package/dist/cli/server.cjs +0 -16553
- package/dist/cli/server.d.cts +0 -2
- package/dist/cli/server.d.ts +0 -2
- package/dist/cli/server.js +0 -977
- package/dist/cli/skills-installer.cjs +0 -230
- package/dist/cli/skills-installer.d.cts +0 -28
- package/dist/cli/skills-installer.d.ts +0 -28
- package/dist/cli/skills-installer.js +0 -201
- package/dist/extractor-4Q3TFZJB.js +0 -8
- package/dist/resolver-MGN64KCP.js +0 -7
- package/dist/types-Cr10igF3.d.cts +0 -345
- package/dist/types-Cr10igF3.d.ts +0 -345
- package/skills/electron/SKILL.md +0 -87
- package/skills/electron/references/opensteer-electron-recipes.md +0 -88
- package/skills/electron/references/opensteer-electron-workflow.md +0 -85
- package/skills/opensteer/references/examples.md +0 -118
package/README.md
CHANGED
|
@@ -1,208 +1,152 @@
|
|
|
1
|
-
# Opensteer
|
|
1
|
+
# Opensteer Package
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`opensteer` is the main product surface for the repository. It exposes:
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
21
|
+
CLI:
|
|
10
22
|
|
|
11
23
|
```bash
|
|
12
24
|
npm i -g opensteer
|
|
13
25
|
opensteer skills install
|
|
14
26
|
```
|
|
15
27
|
|
|
16
|
-
SDK
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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
|
-
##
|
|
50
|
+
## SDK
|
|
50
51
|
|
|
51
52
|
```ts
|
|
52
53
|
import { Opensteer } from "opensteer";
|
|
53
54
|
|
|
54
|
-
const opensteer = new Opensteer({
|
|
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.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
await opensteer.snapshot(
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
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(
|
|
85
|
+
console.log(snapshot.html);
|
|
86
|
+
console.log(extracted);
|
|
70
87
|
} finally {
|
|
71
88
|
await opensteer.close();
|
|
72
89
|
}
|
|
73
90
|
```
|
|
74
91
|
|
|
75
|
-
|
|
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({
|
|
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.
|
|
93
|
-
const
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
129
|
+
const opensteer = Opensteer.attach({
|
|
130
|
+
name: "docs-example",
|
|
131
|
+
rootDir: process.cwd(),
|
|
132
|
+
});
|
|
174
133
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
--
|
|
219
|
-
--
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
234
|
-
|
|
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
|
-
##
|
|
229
|
+
## Connect To Real Browser
|
|
237
230
|
|
|
238
|
-
-
|
|
239
|
-
-
|
|
240
|
-
-
|
|
241
|
-
-
|
|
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
|
-
|
|
236
|
+
When you are launching a browser yourself for `attach-live`, prefer a dedicated profile directory:
|
|
248
237
|
|
|
249
238
|
```bash
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|