surf-cli 2.18.0 → 2.20.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 +276 -8
- package/dist/content/index.js +4 -4
- package/dist/content/index.js.map +1 -1
- package/dist/options/options.html +1 -18
- package/dist/service-worker/index.js +44 -15
- package/dist/service-worker/index.js.map +1 -1
- package/native/cli.cjs +430 -14
- package/native/do-executor.cjs +35 -8
- package/native/doctor.cjs +211 -42
- package/native/endpoint.cjs +121 -36
- package/native/extract.cjs +362 -0
- package/native/host-helpers.cjs +133 -11
- package/native/host-sessions.cjs +10 -0
- package/native/host.cjs +53 -23
- package/native/mcp-server.cjs +25 -0
- package/native/native-host-launch-probe.cjs +69 -0
- package/native/private-state.cjs +25 -1
- package/native/script-options.cjs +33 -0
- package/native/semantic-cli.cjs +764 -0
- package/native/semantic-core.cjs +369 -0
- package/native/semantic-credentials.cjs +207 -0
- package/native/semantic-provider.cjs +61 -0
- package/native/semantic-workflow-executor.cjs +65 -0
- package/native/semantic-workflow-state.cjs +271 -0
- package/native/semantic-workflow.cjs +398 -0
- package/native/stdin-frames.cjs +33 -0
- package/native/tool-scope.cjs +3 -2
- package/native/workflow-definition.cjs +125 -1
- package/native/workflow-runtime.cjs +71 -5
- package/package.json +11 -7
- package/scripts/install-native-host.cjs +103 -60
- package/scripts/uninstall-native-host.cjs +40 -38
- package/scripts/windows-interop.cjs +89 -0
- package/skills/surf/SKILL.md +96 -1
package/skills/surf/SKILL.md
CHANGED
|
@@ -7,11 +7,13 @@ description: Control Chrome browser via CLI for testing, automation, and debuggi
|
|
|
7
7
|
|
|
8
8
|
Control Chrome browser via CLI or Unix socket.
|
|
9
9
|
|
|
10
|
+
Ordinary socket-backed CLI commands report top-level host tool-response errors on stderr with a supplied `[code]` on the first line and exit 1. `--json` additionally writes `{error:{code,message,details?}}` on stdout (missing code becomes `"error"`). `--soft-fail` instead keeps the original stderr warning, empty stdout and exit 0, even with `--json`. This does not cover local validation, transport/parser failures or compound-command errors: do not assume every failure produces JSON. Connection failures remain stderr-only and exit 1, including with `--soft-fail`.
|
|
11
|
+
|
|
10
12
|
## Native Host / Socket Notes
|
|
11
13
|
|
|
12
14
|
For WSL2 with Windows Chrome, run `surf install <extension-id>` inside WSL2. Surf detects WSL2 and writes the Windows-side native messaging manifest plus a wrapper that launches the WSL host. Use `surf install <extension-id> --target linux` only for Linux browsers running inside WSLg.
|
|
13
15
|
|
|
14
|
-
On macOS, Chrome reads the native messaging manifest at `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/surf.browser.host.json`. If native messaging fails, confirm that file exists, its `allowed_origins` extension ID matches `chrome://extensions`, then rerun `surf install <extension-id>`, restart Chrome, reload the extension
|
|
16
|
+
On macOS, Chrome reads the native messaging manifest at `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/surf.browser.host.json`. If native messaging fails, confirm that file exists, its `allowed_origins` extension ID matches `chrome://extensions`, then rerun `surf install <extension-id>`, restart Chrome, and reload the extension. Open Surf's service-worker console from `chrome://extensions`; in **Details > Extension options**, enable **Debug Mode**, reproduce the failure, then disable it when finished.
|
|
15
17
|
|
|
16
18
|
If a command reports `Socket connect failed`, run `surf doctor` first, then check the `Attempted socket:` line. Default sockets are `/tmp/surf.sock` on macOS/Linux/WSL2 and `//./pipe/surf` on Windows. If `SURF_SOCKET` is set, the browser-launched host and the shell running `surf` must use the same value.
|
|
17
19
|
|
|
@@ -34,9 +36,18 @@ surf --remote 100.101.102.103:4321 \
|
|
|
34
36
|
--remote-credential ~/.config/surf/agent-macbook.json \
|
|
35
37
|
page.read
|
|
36
38
|
|
|
39
|
+
# TLS is client-side and requires a TLS-terminating reverse proxy in front of SURF_LISTEN
|
|
40
|
+
surf --remote surf.example.com:443 --remote-tls \
|
|
41
|
+
--remote-tls-ca ~/.config/surf/private-ca.pem \
|
|
42
|
+
--remote-credential ~/.config/surf/agent-macbook.json page.read
|
|
43
|
+
|
|
37
44
|
surf remote revoke agent-macbook # Run on the browser host
|
|
38
45
|
```
|
|
39
46
|
|
|
47
|
+
Environment equivalents are `SURF_REMOTE_TLS=1`, `SURF_REMOTE_TLS_CA`, and
|
|
48
|
+
`SURF_REMOTE_TLS_SERVER_NAME`. A custom CA replaces system roots; Ed25519 credentials remain
|
|
49
|
+
mandatory after TLS validation.
|
|
50
|
+
|
|
40
51
|
Remote paths are client-local by default. `local:./file` is explicit client-local syntax; only `remote:/absolute/path` accesses the browser host directly. Remote transfer supports one upload or ChatGPT/Gemini input and one screenshot, network-export, or Gemini image output. Limits are 256 MiB per file, 512 MiB and 32 files per connection, and 256 KiB decoded chunks. `record`, `aistudio.build`, smoke screenshot directories, directories, and multi-file inputs are not supported remotely. Successful action screenshots and failure `--auto-capture` diagnostics are transferred back to client-local paths.
|
|
41
52
|
|
|
42
53
|
## CLI Quick Reference
|
|
@@ -83,6 +94,83 @@ surf screenshot --full-page --output /tmp/shot.png
|
|
|
83
94
|
surf animate-audit --selector ".thing" --duration 2000 --fps 10
|
|
84
95
|
```
|
|
85
96
|
|
|
97
|
+
## Optional semantic decisions
|
|
98
|
+
|
|
99
|
+
`semantic.act` is a bounded, goal-driven website controller. It repeatedly
|
|
100
|
+
observes the page, lets Jev select the next action from Surf's allowed menu,
|
|
101
|
+
validates and executes that action, and checks the overall goal:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
goal -> observe -> choose -> validate + act -> verify
|
|
105
|
+
^ |
|
|
106
|
+
+-------- incomplete ----------+
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
It returns when the goal is complete, a decision is uncertain, or a configured
|
|
110
|
+
budget is exhausted. Use `semantic.find` for one control, `semantic.filter` for
|
|
111
|
+
relevant page regions, and
|
|
112
|
+
`semantic.verify` for one outcome. Use Jev when the page or happy path is
|
|
113
|
+
unfamiliar; once the path is stable, prefer deterministic Surf commands for
|
|
114
|
+
repeated runs. The agent owns the goal and final confirmation, while Surf retains
|
|
115
|
+
execution authority. Only `semantic.*` sends bounded, value-free page text to
|
|
116
|
+
TypeSafe.
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
surf semantic.find "the settings control"
|
|
120
|
+
surf semantic.verify "Settings were saved" --json
|
|
121
|
+
surf semantic.filter "settings"
|
|
122
|
+
surf semantic.act "Open settings" --max-steps 5
|
|
123
|
+
surf semantic.act "Fill email" --input email="$EMAIL" --allow-write --allow-ref e3
|
|
124
|
+
surf semantic.act 'Add the selected item to the cart' --allow-write --threshold write=0.85
|
|
125
|
+
printf '%s\n' "$TYPESAFE_KEY" | surf semantic auth set
|
|
126
|
+
surf semantic auth status
|
|
127
|
+
surf semantic auth clear
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
For reusable bounded recipes, put only linear `semantic.step` operations in a
|
|
131
|
+
workflow with `"semantic":{"version":1}`. Check it offline with
|
|
132
|
+
`surf workflow.validate flow.json` or `surf do --file flow.json --dry-run`, then
|
|
133
|
+
run with `--allow-semantic`; declared fill/check/click operations also require
|
|
134
|
+
`--allow-write`. Supply private fill slots as a bounded JSON object on stdin:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
printf '%s' '{"quantity":"2"}' | SURF_SESSION=shopping surf do --file flow.json \
|
|
138
|
+
--inputs-stdin --allow-semantic --allow-write --json
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The closed operations are `find`, same-origin direct `open`, `ensureChecked`,
|
|
142
|
+
`fill`, one-shot `click` with an explicit expectation, and `assert`. Search is
|
|
143
|
+
bounded overlapping coverage, not global ranking. Unknown write outcomes stop
|
|
144
|
+
without replay; a later new run can still repeat an external effect. Input
|
|
145
|
+
values never enter provider state, workflow variables, events, or checkpoints.
|
|
146
|
+
|
|
147
|
+
Required argument shapes:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
find target (+ optional search), usually save with "as"
|
|
151
|
+
open target
|
|
152
|
+
ensureChecked target + checked
|
|
153
|
+
fill target + input
|
|
154
|
+
click target + expect
|
|
155
|
+
assert mode + claim (semantic) or predicate (local)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The complete valid six-operation example in the README uses these shapes; start
|
|
159
|
+
from it instead of inventing fields.
|
|
160
|
+
|
|
161
|
+
Every click/fill requires `--allow-write`; repeat `--allow-ref` to narrow it.
|
|
162
|
+
Broad writes use threshold `0.95`; exactly one allowed ref with one applicable
|
|
163
|
+
write uses `0.65`. The applied threshold is included in decision/trace output.
|
|
164
|
+
Repeatable `--threshold name=value` overrides applicable confidence thresholds
|
|
165
|
+
for one run only; defaults remain safer, and overrides never grant write authority.
|
|
166
|
+
`TYPESAFE_API_KEY` is the ephemeral/CI override.
|
|
167
|
+
The shared credential schema is `{"version":1,"apiKey":"..."}` at
|
|
168
|
+
`${XDG_CONFIG_HOME:-~/.config}/typesafe/credentials.json` (Unix/macOS) or
|
|
169
|
+
`%APPDATA%\TypeSafe\credentials.json` (Windows), independent of Surf state and
|
|
170
|
+
the project. POSIX directories/files use `0700`/`0600`; Windows relies on the
|
|
171
|
+
current user's profile ACL. `TYPESAFE_API_KEY` wins. Status reveals only source
|
|
172
|
+
and fingerprint; clear affects all clients using the shared file.
|
|
173
|
+
|
|
86
174
|
## AI Assistants (No API Keys)
|
|
87
175
|
|
|
88
176
|
Query AI models using your browser's logged-in session. Must be logged into the respective service in Chrome.
|
|
@@ -321,6 +409,7 @@ surf page.text # Plain text content only
|
|
|
321
409
|
surf page.html --strip-scripts # Rendered HTML without scripts
|
|
322
410
|
surf page.save --selector "#artifact" --strip-scripts --output page.html # Save one static element
|
|
323
411
|
surf page.state # Modals, loading state, scroll info
|
|
412
|
+
surf frame.diagnose # Why a selector misses: DOM iframes (incl. open shadow roots) vs extension frames vs CDP tree, with warnings; out-of-process frames need frame.switch, not frame.js
|
|
324
413
|
```
|
|
325
414
|
|
|
326
415
|
### Export Rendered HTML
|
|
@@ -398,8 +487,14 @@ surf wait.network # Wait for network idle
|
|
|
398
487
|
surf wait.url "/success" # Wait for URL pattern
|
|
399
488
|
surf wait.dom --stable 100 # Wait for DOM stability
|
|
400
489
|
surf wait.load # Wait for page load complete
|
|
490
|
+
surf wait.ready --selector ".results" # Ready, or fail fast: login / challenge / not-found / error
|
|
491
|
+
surf wait.ready --url-prefix "https://app.example.com/" --empty-text "No results" # empty vs blocked
|
|
492
|
+
surf wait.ready --accept login --json # Return the negative state instead of failing
|
|
493
|
+
surf page.readiness --json # Classify the current page once (state + evidence)
|
|
401
494
|
```
|
|
402
495
|
|
|
496
|
+
Typed readiness states replace "the selector never appeared": exit codes carry `page_login`, `page_challenge`, `page_not_found`, `page_error` or `page_timeout`. Detection uses visible UI (a rendered password field, a login route, the page's wording, a URL outside `--url-prefix`), not site selectors.
|
|
497
|
+
|
|
403
498
|
## Dialog Handling
|
|
404
499
|
|
|
405
500
|
```bash
|