opensteer 0.7.1 → 0.8.2
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 +2 -1
- package/dist/{chunk-7QTHGTGN.js → chunk-X3G6QSCF.js} +16206 -16906
- package/dist/chunk-X3G6QSCF.js.map +1 -0
- package/dist/cli/bin.cjs +30118 -35773
- package/dist/cli/bin.cjs.map +1 -1
- package/dist/cli/bin.js +610 -5520
- package/dist/cli/bin.js.map +1 -1
- package/dist/index.cjs +6880 -7361
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +275 -320
- package/dist/index.d.ts +275 -320
- package/dist/index.js +65 -161
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/skills/README.md +14 -2
- package/skills/opensteer/SKILL.md +34 -73
- package/skills/opensteer/references/cli-reference.md +90 -72
- package/skills/opensteer/references/request-workflow.md +145 -9
- package/skills/opensteer/references/sdk-reference.md +168 -32
- package/dist/chunk-7QTHGTGN.js.map +0 -1
|
@@ -1,90 +1,51 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opensteer
|
|
3
|
-
description: "
|
|
3
|
+
description: "Handles Opensteer browser automation, structured DOM extraction, and browser-backed request replay with the Opensteer CLI and SDK. Use when the user mentions Opensteer, browser automation, real Chromium sessions, persistent workspace browser state, descriptor-backed DOM actions or extraction, request plans, recipes, or browser-backed API replay."
|
|
4
|
+
argument-hint: "[goal]"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Opensteer
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
If invoked directly, treat `$ARGUMENTS` as the concrete browser or replay goal. First decide whether the task is primarily DOM automation, request capture/replay, or workspace browser administration.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- CLI exploration: [references/cli-reference.md](references/cli-reference.md)
|
|
13
|
-
- SDK automation: [references/sdk-reference.md](references/sdk-reference.md)
|
|
14
|
-
- Request capture and replay: [references/request-workflow.md](references/request-workflow.md)
|
|
15
|
-
|
|
16
|
-
## Default Workflow
|
|
17
|
-
|
|
18
|
-
1. Start with the CLI when you need to explore a site, inspect state, or prove the workflow on a real page.
|
|
19
|
-
2. Re-snapshot after each meaningful page or DOM change before reusing counters.
|
|
20
|
-
3. Add `--description` when you want selector persistence and later replay.
|
|
21
|
-
4. Move to the SDK when the workflow should become reusable code in the repository.
|
|
22
|
-
5. Move to request capture and request plans when the real target is a browser-backed API.
|
|
23
|
-
|
|
24
|
-
## CLI Exploration
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
opensteer open https://example.com --name my-workflow
|
|
28
|
-
opensteer snapshot action --name my-workflow
|
|
29
|
-
opensteer click 3 --name my-workflow --description "primary button"
|
|
30
|
-
opensteer snapshot extraction --name my-workflow
|
|
31
|
-
opensteer extract --name my-workflow \
|
|
32
|
-
--description "page summary" \
|
|
33
|
-
--schema '{"title":{"selector":"title"},"url":{"source":"current_url"}}'
|
|
34
|
-
opensteer close --name my-workflow
|
|
35
|
-
```
|
|
11
|
+
Use this skill when a task needs a real browser workflow, persistent workspace browser state, structured DOM extraction, or browser-backed request replay.
|
|
36
12
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- Use `opensteer open` once to create the session, then use `goto`, actions, snapshots, and extraction against the same `--name`.
|
|
40
|
-
- Treat counter targets as snapshot-local. Always take a fresh `snapshot action` before reusing counters after the page changes.
|
|
41
|
-
- Use `snapshot extraction` plus `extract` for structured data. Do not treat snapshot HTML as the final data source.
|
|
42
|
-
- Use `--description` whenever the action or extraction should be replayable later.
|
|
43
|
-
|
|
44
|
-
## SDK Automation
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
import { Opensteer } from "opensteer";
|
|
48
|
-
|
|
49
|
-
const opensteer = new Opensteer({
|
|
50
|
-
name: "my-workflow",
|
|
51
|
-
rootDir: process.cwd(),
|
|
52
|
-
browser: { headless: true },
|
|
53
|
-
});
|
|
13
|
+
Choose the reference that matches the job:
|
|
54
14
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
15
|
+
- CLI exploration and browser admin: [references/cli-reference.md](references/cli-reference.md)
|
|
16
|
+
- SDK automation and reusable code: [references/sdk-reference.md](references/sdk-reference.md)
|
|
17
|
+
- Request capture, plans, and recipes: [references/request-workflow.md](references/request-workflow.md)
|
|
58
18
|
|
|
59
|
-
|
|
60
|
-
description: "page summary",
|
|
61
|
-
schema: {
|
|
62
|
-
title: { selector: "title" },
|
|
63
|
-
url: { source: "current_url" },
|
|
64
|
-
},
|
|
65
|
-
});
|
|
19
|
+
## Startup Checks
|
|
66
20
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
```
|
|
21
|
+
- Verify `opensteer` is available in the repo or on `PATH` before planning the workflow.
|
|
22
|
+
- If Chromium binaries are missing, install them through Playwright before debugging page behavior.
|
|
23
|
+
- Reuse an existing workspace id for the same site or feature when one already exists.
|
|
72
24
|
|
|
73
|
-
|
|
25
|
+
## Mental Model
|
|
74
26
|
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
27
|
+
- `workspace` / `--workspace` is the durable unit of state. Persistent workspaces live under `.opensteer/workspaces/<id>`.
|
|
28
|
+
- A workspace stores the browser profile, live browser metadata, artifacts, traces, saved network, DOM descriptors, extraction descriptors, request plans, recipes, auth recipes, and reverse-analysis records.
|
|
29
|
+
- In the SDK, omitting `workspace` creates a temporary root. In the CLI, stateful commands currently require `--workspace <id>`.
|
|
30
|
+
- With a workspace, browser mode defaults to `persistent`. `temporary` creates an isolated browser for the current run. `attach` connects to an already-running Chromium browser.
|
|
31
|
+
- `opensteer browser ...` manages the workspace browser itself. `opensteer close` stops the active session/browser without deleting the workspace. `browser reset` clears cloned browser state. `browser delete` removes workspace browser files.
|
|
32
|
+
- The short CLI only has special parsing for a few common commands. For advanced semantic operations or fields like `persistAsDescription`, use `opensteer run <semantic-operation> --workspace <id> --input-json <json>`.
|
|
33
|
+
- Prefer Opensteer surfaces over raw Playwright so descriptors, extraction payloads, saved network, request plans, recipes, traces, and artifacts stay in the workspace.
|
|
79
34
|
|
|
80
|
-
##
|
|
35
|
+
## Workflow Selection
|
|
81
36
|
|
|
82
|
-
|
|
37
|
+
- Choose the DOM workflow when the answer must come from the rendered page or a real browser interaction.
|
|
38
|
+
- Choose the request workflow when the durable artifact is an HTTP path, request plan, recipe, or reverse-analysis package.
|
|
39
|
+
- Many tasks use both: prove the browser flow first, then capture and promote the underlying request path.
|
|
83
40
|
|
|
84
|
-
|
|
85
|
-
2. Inspect traffic with `queryNetwork()` or `opensteer network query`.
|
|
86
|
-
3. Retry the request with `rawRequest()` or `opensteer request raw`.
|
|
87
|
-
4. Promote the captured request with `inferRequestPlan()` or `opensteer plan infer`.
|
|
88
|
-
5. Replay it with `request()` or `opensteer request execute`.
|
|
41
|
+
## Shared Rules
|
|
89
42
|
|
|
90
|
-
|
|
43
|
+
- Use `snapshot("action")` or `snapshot action` before counter-based `element` targets.
|
|
44
|
+
- Re-snapshot after navigation or DOM-changing actions before reusing element counters.
|
|
45
|
+
- In the SDK, `selector + description` or `element + description` persists a DOM action descriptor. `description` alone reuses it later.
|
|
46
|
+
- In the CLI, the short `click` / `hover` / `input` / `scroll` forms accept exactly one target. Use `opensteer run dom.* --input-json` when you need `persistAsDescription`.
|
|
47
|
+
- For extraction, `description + schema` authors or updates a persisted extraction descriptor. `description` alone replays the stored extraction payload.
|
|
48
|
+
- Extraction schemas are explicit JSON objects and arrays. Each leaf must be `{ element: N }`, `{ selector: "..." }`, optional `attribute`, or `{ source: "current_url" }`.
|
|
49
|
+
- Persisted extraction replay is deterministic and snapshot-backed. Do not replace `extract()` with `evaluate()` or custom DOM parsing when the desired output fits the extraction schema.
|
|
50
|
+
- Use recipes for deterministic setup work. Use auth recipes for auth refresh/setup specifically. They live in separate registries.
|
|
51
|
+
- Do not reach for removed surfaces such as `--name`, `Opensteer.attach()`, cloud/profile-sync helpers, `local-profile`, legacy snapshot browser modes, or `@opensteer/engine-abp`.
|
|
@@ -1,115 +1,133 @@
|
|
|
1
1
|
# Opensteer CLI Reference
|
|
2
2
|
|
|
3
|
-
Use the CLI when you need a fast
|
|
3
|
+
Use the CLI when you need a fast JSON-first loop against a repo-local workspace browser.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Sections
|
|
6
|
+
|
|
7
|
+
- [Quickstart](#quickstart)
|
|
8
|
+
- [Browser Lifecycle And Profile Cloning](#browser-lifecycle-and-profile-cloning)
|
|
9
|
+
- [Browser Modes](#browser-modes)
|
|
10
|
+
- [Advanced Semantic Operations](#advanced-semantic-operations)
|
|
11
|
+
- [Extraction Schema Examples](#extraction-schema-examples)
|
|
12
|
+
|
|
13
|
+
## Quickstart
|
|
6
14
|
|
|
7
15
|
```bash
|
|
8
|
-
opensteer
|
|
9
|
-
opensteer
|
|
10
|
-
opensteer
|
|
11
|
-
opensteer
|
|
12
|
-
opensteer
|
|
13
|
-
opensteer
|
|
16
|
+
opensteer browser status --workspace demo
|
|
17
|
+
opensteer open https://example.com --workspace demo
|
|
18
|
+
opensteer snapshot action --workspace demo
|
|
19
|
+
opensteer click --workspace demo --element 3
|
|
20
|
+
opensteer input --workspace demo --selector "input[type=search]" --text "search term" --press-enter true
|
|
21
|
+
opensteer snapshot extraction --workspace demo
|
|
22
|
+
opensteer extract --workspace demo \
|
|
14
23
|
--description "page summary" \
|
|
15
|
-
--schema '{"title":{"selector":"title"},"url":{"source":"current_url"}}'
|
|
16
|
-
opensteer
|
|
24
|
+
--schema-json '{"title":{"selector":"title"},"url":{"source":"current_url"}}'
|
|
25
|
+
opensteer extract --workspace demo --description "page summary"
|
|
26
|
+
opensteer close --workspace demo
|
|
17
27
|
```
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- Use `--description` when the interaction or extraction should become replayable later.
|
|
25
|
-
- CLI commands return JSON for machine-readable actions and data commands.
|
|
29
|
+
- Stateful CLI commands currently require `--workspace <id>`.
|
|
30
|
+
- With a workspace, browser mode defaults to `persistent`.
|
|
31
|
+
- Use `snapshot action` before `--element <n>` targets.
|
|
32
|
+
- `extract --description --schema-json ...` writes or updates a persisted extraction descriptor.
|
|
33
|
+
- `extract --description ...` replays the stored extraction payload with no schema.
|
|
26
34
|
|
|
27
|
-
##
|
|
35
|
+
## Browser Lifecycle And Profile Cloning
|
|
28
36
|
|
|
29
37
|
```bash
|
|
30
|
-
opensteer
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
opensteer
|
|
38
|
+
opensteer browser clone --workspace github-sync \
|
|
39
|
+
--source-user-data-dir "$HOME/Library/Application Support/Google/Chrome" \
|
|
40
|
+
--source-profile-directory Default
|
|
41
|
+
opensteer open https://github.com --workspace github-sync
|
|
42
|
+
opensteer browser status --workspace github-sync
|
|
43
|
+
opensteer close --workspace github-sync
|
|
44
|
+
opensteer browser reset --workspace github-sync
|
|
45
|
+
opensteer browser delete --workspace github-sync
|
|
34
46
|
```
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
- `browser clone`, `browser reset`, and `browser delete` require a persistent workspace browser.
|
|
49
|
+
- `browser clone` copies a local Chromium profile into `.opensteer/workspaces/<id>/browser/user-data`.
|
|
50
|
+
- `close` stops the active session/browser but keeps the workspace registry, traces, artifacts, and cloned browser data.
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
opensteer open https://example.com --name demo --headless true
|
|
42
|
-
```
|
|
52
|
+
## Browser Modes
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
- `persistent`: default with `--workspace`. Browser state lives in the workspace.
|
|
55
|
+
- `temporary`: isolated browser state for the current run.
|
|
56
|
+
- `attach`: connect to a running Chromium browser.
|
|
45
57
|
|
|
46
58
|
```bash
|
|
47
|
-
opensteer open https://example.com --
|
|
59
|
+
opensteer open https://example.com --workspace demo --browser temporary
|
|
48
60
|
opensteer browser discover
|
|
49
|
-
opensteer browser inspect --endpoint 9222
|
|
61
|
+
opensteer browser inspect --attach-endpoint ws://127.0.0.1:9222/devtools/browser/abc
|
|
62
|
+
opensteer open https://example.com --workspace demo --browser attach --attach-endpoint ws://127.0.0.1:9222/devtools/browser/abc
|
|
50
63
|
```
|
|
51
64
|
|
|
52
|
-
|
|
65
|
+
Common options:
|
|
53
66
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
- `--headless true|false`
|
|
68
|
+
- `--executable-path <path>`
|
|
69
|
+
- `--arg <value>` repeatable
|
|
70
|
+
- `--timeout-ms <ms>`
|
|
71
|
+
- `--context-json <json>`
|
|
72
|
+
- `--fresh-tab true|false` for `--browser attach`
|
|
59
73
|
|
|
60
|
-
|
|
74
|
+
## Advanced Semantic Operations
|
|
75
|
+
|
|
76
|
+
The short CLI only special-cases a small set of commands. For advanced operations and fields not exposed by shorthand parsing, use:
|
|
61
77
|
|
|
62
78
|
```bash
|
|
63
|
-
opensteer
|
|
64
|
-
--source-user-data-dir "~/Library/Application Support/Google/Chrome" \
|
|
65
|
-
--source-profile-directory "Profile 1"
|
|
79
|
+
opensteer run <semantic-operation> --workspace <id> --input-json <json>
|
|
66
80
|
```
|
|
67
81
|
|
|
68
|
-
|
|
82
|
+
Examples:
|
|
69
83
|
|
|
70
84
|
```bash
|
|
71
|
-
opensteer
|
|
72
|
-
|
|
73
|
-
opensteer local-profile unlock --user-data-dir "~/Library/Application Support/Opensteer Chrome"
|
|
74
|
-
```
|
|
85
|
+
opensteer run dom.click --workspace demo \
|
|
86
|
+
--input-json '{"target":{"kind":"selector","selector":"button.primary"},"persistAsDescription":"primary button","networkTag":"load-products"}'
|
|
75
87
|
|
|
76
|
-
|
|
88
|
+
opensteer run page.goto --workspace demo \
|
|
89
|
+
--input-json '{"url":"https://example.com/products","networkTag":"page-load"}'
|
|
77
90
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
--
|
|
91
|
+
opensteer run network.query --workspace demo \
|
|
92
|
+
--input-json '{"tag":"load-products","includeBodies":true,"limit":20}'
|
|
93
|
+
|
|
94
|
+
opensteer run request-plan.infer --workspace demo \
|
|
95
|
+
--input-json '{"recordId":"rec_123","key":"products.search","version":"v1"}'
|
|
96
|
+
|
|
97
|
+
opensteer run request.execute --workspace demo \
|
|
98
|
+
--input-json '{"key":"products.search","query":{"q":"laptop"}}'
|
|
83
99
|
```
|
|
84
100
|
|
|
85
|
-
|
|
101
|
+
- Command aliases such as `network query` and `request-plan infer` still exist, but they usually depend on `--input-json` for nontrivial inputs.
|
|
102
|
+
- Use `run page.goto` when you need `networkTag` on navigation. The short `goto` form only parses the URL positional.
|
|
103
|
+
- Use `run dom.click` / `run dom.input` / `run dom.hover` / `run dom.scroll` when you need `persistAsDescription`.
|
|
86
104
|
|
|
87
|
-
|
|
105
|
+
## Extraction Schema Examples
|
|
88
106
|
|
|
89
107
|
```bash
|
|
90
|
-
opensteer
|
|
91
|
-
opensteer network save --name demo --tag login-flow
|
|
92
|
-
opensteer network diff --name demo --left rec_a --right rec_b
|
|
93
|
-
opensteer network probe --name demo --record-id rec_123
|
|
94
|
-
opensteer network minimize --name demo --record-id rec_123 --transport context-http
|
|
108
|
+
opensteer snapshot extraction --workspace demo
|
|
95
109
|
```
|
|
96
110
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
Infer a plan from a captured record, then execute it:
|
|
111
|
+
Explicit field bindings:
|
|
100
112
|
|
|
101
113
|
```bash
|
|
102
|
-
opensteer
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
114
|
+
opensteer extract --workspace demo \
|
|
115
|
+
--description "page summary" \
|
|
116
|
+
--schema-json '{"title":{"element":3},"price":{"element":7}}'
|
|
117
|
+
|
|
118
|
+
opensteer extract --workspace demo \
|
|
119
|
+
--description "links" \
|
|
120
|
+
--schema-json '{"url":{"selector":"a.primary","attribute":"href"},"pageUrl":{"source":"current_url"}}'
|
|
106
121
|
```
|
|
107
122
|
|
|
108
|
-
|
|
123
|
+
Arrays with representative rows:
|
|
109
124
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
-
|
|
125
|
+
```bash
|
|
126
|
+
opensteer extract --workspace demo \
|
|
127
|
+
--description "items" \
|
|
128
|
+
--schema-json '{"items":[{"title":{"selector":"#products li:nth-child(1) .title"},"price":{"selector":"#products li:nth-child(1) .price"}},{"title":{"selector":"#products li:nth-child(2) .title"},"price":{"selector":"#products li:nth-child(2) .price"}}]}'
|
|
129
|
+
```
|
|
114
130
|
|
|
115
|
-
|
|
131
|
+
- Build the exact JSON object you want. The extractor does not accept semantic placeholders like `"string"` or prompt-style schemas.
|
|
132
|
+
- Use `element` fields only with counters from a fresh snapshot in the same live session.
|
|
133
|
+
- For arrays, include one or more representative objects. Add multiple examples when repeated rows have structural variants.
|
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
Use this workflow when the deliverable is a custom API, a replayable request plan, or a lower-overhead path than full browser automation.
|
|
4
4
|
|
|
5
|
+
## Sections
|
|
6
|
+
|
|
7
|
+
- [Standard Loop](#standard-loop)
|
|
8
|
+
- [Transport Selection](#transport-selection)
|
|
9
|
+
- [SDK Flow](#sdk-flow)
|
|
10
|
+
- [CLI Equivalents](#cli-equivalents)
|
|
11
|
+
- [Transport Probing](#transport-probing)
|
|
12
|
+
- [Auth Token Acquisition](#auth-token-acquisition)
|
|
13
|
+
- [Input Formats](#input-formats)
|
|
14
|
+
- [Practical Guidance](#practical-guidance)
|
|
15
|
+
|
|
16
|
+
## Standard Loop
|
|
17
|
+
|
|
18
|
+
1. Trigger the real browser action that causes the request inside a stable workspace.
|
|
19
|
+
2. Tag the important navigation or interactions with `networkTag`.
|
|
20
|
+
3. Inspect the captured traffic and isolate the relevant records.
|
|
21
|
+
4. Save useful captures to the workspace if they need to survive later analysis.
|
|
22
|
+
5. Prove the request with `rawRequest()`.
|
|
23
|
+
6. Promote the winning record into a request plan.
|
|
24
|
+
7. Add recipes or auth recipes if replay needs deterministic setup.
|
|
25
|
+
8. Replay the plan from code.
|
|
26
|
+
|
|
27
|
+
This workflow should carry equal weight with DOM automation. Use it whenever the browser page is only the launcher for the real target request.
|
|
28
|
+
|
|
5
29
|
## Transport Selection
|
|
6
30
|
|
|
7
31
|
- `direct-http`: the request is replayable without a browser.
|
|
@@ -13,11 +37,17 @@ When in doubt, start with browser-backed capture first. Opensteer treats browser
|
|
|
13
37
|
|
|
14
38
|
## SDK Flow
|
|
15
39
|
|
|
16
|
-
1.
|
|
40
|
+
1. Start a workspace-backed browser flow and tag navigation.
|
|
17
41
|
|
|
18
42
|
```ts
|
|
19
|
-
await opensteer.open(
|
|
43
|
+
await opensteer.open();
|
|
44
|
+
await opensteer.goto({
|
|
45
|
+
url: "https://example.com/app",
|
|
46
|
+
networkTag: "page-load",
|
|
47
|
+
});
|
|
48
|
+
|
|
20
49
|
await opensteer.click({
|
|
50
|
+
selector: "button.load-products",
|
|
21
51
|
description: "load products",
|
|
22
52
|
networkTag: "products-load",
|
|
23
53
|
});
|
|
@@ -56,7 +86,15 @@ await opensteer.inferRequestPlan({
|
|
|
56
86
|
});
|
|
57
87
|
```
|
|
58
88
|
|
|
59
|
-
5.
|
|
89
|
+
5. Save the captured traffic if you want it in the workspace registry.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
await opensteer.saveNetwork({
|
|
93
|
+
tag: "products-load",
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
6. Replay the plan from code.
|
|
60
98
|
|
|
61
99
|
```ts
|
|
62
100
|
const result = await opensteer.request("products.search", {
|
|
@@ -64,18 +102,116 @@ const result = await opensteer.request("products.search", {
|
|
|
64
102
|
});
|
|
65
103
|
```
|
|
66
104
|
|
|
105
|
+
7. Add a recipe or auth recipe if replay needs deterministic setup.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
await opensteer.runRecipe({
|
|
109
|
+
key: "products.setup",
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
await opensteer.runAuthRecipe({
|
|
113
|
+
key: "products.auth",
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
67
117
|
## CLI Equivalents
|
|
68
118
|
|
|
69
119
|
```bash
|
|
70
|
-
opensteer
|
|
71
|
-
opensteer
|
|
72
|
-
|
|
73
|
-
opensteer
|
|
120
|
+
opensteer open --workspace demo
|
|
121
|
+
opensteer run page.goto --workspace demo \
|
|
122
|
+
--input-json '{"url":"https://example.com/app","networkTag":"page-load"}'
|
|
123
|
+
opensteer run dom.click --workspace demo \
|
|
124
|
+
--input-json '{"target":{"kind":"selector","selector":"button.load-products"},"persistAsDescription":"load products","networkTag":"products-load"}'
|
|
125
|
+
opensteer run network.query --workspace demo \
|
|
126
|
+
--input-json '{"tag":"products-load","includeBodies":true,"limit":20}'
|
|
127
|
+
opensteer run request.raw --workspace demo \
|
|
128
|
+
--input-json '{"transport":"context-http","url":"https://example.com/api/products","method":"POST","body":{"json":{"page":1}}}'
|
|
129
|
+
opensteer run request-plan.infer --workspace demo \
|
|
130
|
+
--input-json '{"recordId":"rec_123","key":"products.search","version":"v1"}'
|
|
131
|
+
opensteer run request.execute --workspace demo \
|
|
132
|
+
--input-json '{"key":"products.search","query":{"q":"laptop"}}'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Transport Probing
|
|
136
|
+
|
|
137
|
+
Test each discovered API with multiple transports to determine portability:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
const direct = await opensteer.rawRequest({
|
|
141
|
+
transport: "direct-http",
|
|
142
|
+
url: discoveredUrl,
|
|
143
|
+
method: "GET",
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const context = await opensteer.rawRequest({
|
|
147
|
+
transport: "context-http",
|
|
148
|
+
url: discoveredUrl,
|
|
149
|
+
method: "GET",
|
|
150
|
+
});
|
|
74
151
|
```
|
|
75
152
|
|
|
153
|
+
If `direct-http` returns 200, the API is portable and does not need a browser for future calls. If only `context-http` works, the API depends on browser session state.
|
|
154
|
+
|
|
155
|
+
## Auth Token Acquisition
|
|
156
|
+
|
|
157
|
+
When you discover an auth endpoint, acquire a token and use it to probe for data APIs that may be behind auth:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
const tokenResp = await opensteer.rawRequest({
|
|
161
|
+
transport: "direct-http",
|
|
162
|
+
url: "https://example.com/api/oauth/token?scope=guest",
|
|
163
|
+
method: "POST",
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
let parsed = tokenResp.data;
|
|
167
|
+
if (parsed === undefined) {
|
|
168
|
+
const body = tokenResp.response.body;
|
|
169
|
+
if (!body) {
|
|
170
|
+
throw new Error("Token response had no body");
|
|
171
|
+
}
|
|
172
|
+
parsed = JSON.parse(Buffer.from(body.data, "base64").toString("utf8"));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const token = String((parsed as { access_token: unknown }).access_token);
|
|
176
|
+
|
|
177
|
+
const authed = await opensteer.rawRequest({
|
|
178
|
+
transport: "direct-http",
|
|
179
|
+
url: "https://example.com/api/products",
|
|
180
|
+
method: "GET",
|
|
181
|
+
headers: [{ name: "Authorization", value: `Bearer ${token}` }],
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Input Formats
|
|
186
|
+
|
|
187
|
+
`rawRequest` expects specific shapes:
|
|
188
|
+
|
|
189
|
+
- `headers`: array of `[{ name, value }]`, not `{ key: value }`.
|
|
190
|
+
- `body`: one of `{ json: { ... } }`, `{ text: "..." }`, or `{ base64: "..." }`. Not raw strings.
|
|
191
|
+
- `request.execute` semantic input includes `key` inside the JSON object. The SDK convenience wrapper `opensteer.request(key, input)` adds that for you.
|
|
192
|
+
|
|
76
193
|
## Practical Guidance
|
|
77
194
|
|
|
195
|
+
Mandatory steps:
|
|
196
|
+
|
|
197
|
+
- MUST use `goto({ url, networkTag })` to tag navigation. `networkTag` is NOT supported on `open()`. In the CLI, this means `opensteer run page.goto --input-json ...`.
|
|
198
|
+
- MUST query by tag first (`queryNetwork({ tag })`), then query all traffic to catch async requests.
|
|
199
|
+
- MUST probe every discovered first-party API with transport tests. Do NOT just log URLs.
|
|
200
|
+
- MUST call `saveNetwork({ tag })` before closing the session.
|
|
201
|
+
- Use `queryNetwork({ source: "saved" })` when you want to read previously persisted captures after the live session is gone.
|
|
202
|
+
|
|
203
|
+
Common mistakes:
|
|
204
|
+
|
|
205
|
+
- Do NOT pass headers as `{key: value}`. MUST use `[{name, value}]` arrays.
|
|
206
|
+
- Do NOT pass body as a raw string. MUST wrap it in `{json: {...}}`, `{text: "..."}`, or `{base64: "..."}`.
|
|
207
|
+
- Do NOT skip auth probing. If you find an OAuth endpoint, get a token and re-probe with it.
|
|
208
|
+
- Do NOT treat "no data API found" as failure. It is a valid reverse-engineering conclusion that justifies DOM fallback.
|
|
209
|
+
- Do NOT mix up recipes and auth recipes. They are separate registries and can reuse the same key/version independently.
|
|
210
|
+
|
|
211
|
+
Additional guidance:
|
|
212
|
+
|
|
78
213
|
- Capture the browser action first if authentication, cookies, or minted tokens may matter.
|
|
79
|
-
- Save or tag the useful traffic before minimizing or diffing it.
|
|
80
214
|
- Prefer `direct-http` only after proving the request no longer depends on live browser state.
|
|
81
|
-
-
|
|
215
|
+
- `inferRequestPlan()` throws if the key+version already exists. Catch the error or bump the version.
|
|
216
|
+
- Use recipes when the request plan needs deterministic setup work. Use auth recipes when the setup is specifically auth refresh or login state.
|
|
217
|
+
- Stay in the DOM workflow only when the rendered page itself is the deliverable. Move here when the request is the durable artifact.
|