@ai-ecoverse/slicc-cdp 1.27.8 → 1.28.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 +85 -0
- package/bin/curlwright.wasm +0 -0
- package/bin/playwright-cli.wasm +0 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,6 +24,17 @@ Event JSON (NDJSON, one object per line):
|
|
|
24
24
|
{"v":1,"standard":"ard","origin":"https://example.com","url":"https://example.com/.well-known/ard.json","via":"well-known","page":"https://example.com/","targetId":"...","status":"valid","summary":{...}}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
Payments over HTTP 402: every response in a watched tab, subresources included, with status 402 is decoded as a payment challenge. The watcher never pays, retries, or sends `PAYMENT-SIGNATURE` or `Authorization: Payment`; it only reads the response the page already got. A protected origin's response is never read.
|
|
28
|
+
|
|
29
|
+
- **`x402`** ([x402](https://github.com/coinbase/x402/tree/main/specs)). V2 is read from the base64 JSON `PAYMENT-REQUIRED` header. V1 is read from the JSON body of a 402 with a JSON content type. The body is fetched once with `Network.getResponseBody` after it has loaded, up to 1 MiB. `summary` is `{status: 402, version, resource, offers: [{scheme, network, amount, asset, payTo, expires, maxTimeoutSeconds}]}`. `amount` is V2's `amount` or V1's `maxAmountRequired`, kept as the string the server sent.
|
|
30
|
+
- **`mpp`** ([Machine Payments Protocol](https://datatracker.ietf.org/doc/draft-httpauth-payment/)). It is read from each `WWW-Authenticate: Payment` challenge, whose `request` parameter is decoded as base64url JSON. `summary` is `{status: 402, resource, offers: [{method, intent, realm, amount, asset, expires}]}`, with `amount` and `asset` (the request's `currency`) as sent. One response can carry both standards.
|
|
31
|
+
- **Invalid challenges:** a challenge that doesn't decode is reported with `status: "invalid"` and a `reason`, and the watcher goes on. Its `summary` is only `{status: 402, challenge}`, the raw header capped at 1 KiB. Possible reasons:
|
|
32
|
+
- `PAYMENT-REQUIRED is not base64 JSON`;
|
|
33
|
+
- `request is not base64url JSON`;
|
|
34
|
+
- `no x402 payload`: a legacy `X-Payment` header, or a body without `x402Version`/`accepts`;
|
|
35
|
+
- `body unavailable`: the body was evicted or the load failed.
|
|
36
|
+
- **Limits:** events are deduplicated per origin, standard and resource, since each paid resource has its own price. A tab reports at most 50 events per payment standard, so a page that loops 402s can't flood the output. `--once` waits up to 2 s after the load event for the tab's requests to finish (and 402 bodies to be read), so the 402s of subresources are reported. A `--once` run can therefore take up to 2 s longer than the load.
|
|
37
|
+
|
|
27
38
|
Sinks:
|
|
28
39
|
|
|
29
40
|
- **stdout** (default): NDJSON. Pipe into `jq` or an agent reader.
|
|
@@ -84,6 +95,80 @@ Inside the kernel the browser socket is `SLICC_CDP_URL`: `ws://127.0.0.1:9222/de
|
|
|
84
95
|
|
|
85
96
|
Routes in the kernel use these CDP methods through the facade, always with a tab's `sessionId`: `Fetch.enable`, `Fetch.disable`, `Fetch.continueRequest`, `Fetch.fulfillRequest`, the `Fetch.requestPaused` event, and `Target.getTargetInfo`. The `slicc-cdp-client` API can also send `Fetch.failRequest`, `Fetch.getResponseBody` and `Fetch.continueResponse`; `playwright-cli` doesn't.
|
|
86
97
|
|
|
98
|
+
## Backend contract
|
|
99
|
+
|
|
100
|
+
This is what `playwright-cli`, `curlwright`, `slicc-cdp-client` and the JS `CDPClient` need from a CDP backend: Chrome, slicc-extension's `sliccExtension.cdp`, bios's link and guard, or slicc-node. `crates/cdp-client/src/contract.rs` holds the same lists. Its unit test scans the production code in `crates/*/src` and fails when a list misses a sessionless call, a handled browser-level event or a session domain, or names one the code no longer uses. It also fails when this section disagrees with the lists or with `shield.rs`, or when a cited function or const no longer holds what it is cited for.
|
|
101
|
+
|
|
102
|
+
One browser WebSocket carries everything. An `http` endpoint is read as `GET /json/version`, which must return `webSocketDebuggerUrl` (`crates/cdp-client/src/connect.rs` `websocket_url_from_version`). When nothing names an endpoint, the host probes the `probe_ports` of the slicc-browsers catalog, `127.0.0.1:9222-9229` (`crates/cdp-client/src/ports.rs` `catalog_from`). Requests are `{id, method, params}` with an optional top-level `sessionId`. Replies are `{id, result}` or `{id, error: {message}}`. The client reports an error as `<method>: <message>` (`crates/cdp-client/src/cdp.rs` `raw_call`). Events are `{method, params}`, with `sessionId` when they come from a session.
|
|
103
|
+
|
|
104
|
+
### Browser-level methods
|
|
105
|
+
|
|
106
|
+
These are sent with no `sessionId`.
|
|
107
|
+
|
|
108
|
+
- `Target.getTargets` with `{}`. Reads `targetId`, `type`, `url` and `title` from each of `targetInfos`. Only `type: "page"` is a tab. The client never lists a protected tab, and a backend may leave them out (`crates/playwright-cli/src/browser.rs` `list_pages`).
|
|
109
|
+
- `Target.getTargetInfo` with `{targetId}`. Reads `targetInfo.type`, `url`, `openerId`. An error for a `frameId` is fine (`crates/cdp-client/src/cdp.rs` `target_protected`).
|
|
110
|
+
- `Target.setDiscoverTargets` with `{discover: true}`, once per connection before the first guard attach (`crates/cdp-client/src/cdp.rs` `touch`). `discover` sends it with the same params (`crates/playwright-cli/src/agent_discover.rs` `run`).
|
|
111
|
+
- `Target.createTarget` with `{url: "about:blank", background}`. Must return `targetId`. Any other `url` is sent as `Page.navigate` on the guard session once the guard is up (`crates/cdp-client/src/cdp.rs` `create_target`).
|
|
112
|
+
- `Target.attachToTarget` with `{targetId, flatten: true}`. Must return `sessionId` (`crates/cdp-client/src/cdp.rs` `attach`).
|
|
113
|
+
- `Target.detachFromTarget` with `{sessionId}` (`crates/cdp-client/src/cdp.rs` `detach`).
|
|
114
|
+
- `Target.closeTarget` with `{targetId}` (`crates/playwright-cli/src/browser.rs` `close_target`).
|
|
115
|
+
- `Target.activateTarget` with `{targetId}`. `open` ignores an error, `tab-select` reports it (`crates/playwright-cli/src/browser.rs` `activate`).
|
|
116
|
+
- `Browser.getVersion` with `{}`. Optional, `webmcp-call` only. Reads `product` as `Chrome/NNN` or `HeadlessChrome/NNN` (`crates/playwright-cli/src/webmcp.rs` `chrome_major_version`).
|
|
117
|
+
- `Slicc.action` with `{phase, kind, ...}`. An optional notification for the slicc panel that is never awaited, so a backend may ignore it or answer with an error (`crates/playwright-cli/src/action.rs` `begin`).
|
|
118
|
+
|
|
119
|
+
The JS `CDPClient` sends only `Target.getTargets` (`src/page.js` `listTargets`) and `Target.attachToTarget` with `flatten: true` (`src/cdp-client.js` `attach`) without a session.
|
|
120
|
+
|
|
121
|
+
### Browser-level events
|
|
122
|
+
|
|
123
|
+
A backend may omit any of these.
|
|
124
|
+
|
|
125
|
+
- `Target.attachedToTarget` with `sessionId` and `targetInfo.targetId`. Registers the guard session if it comes before the attach reply (`crates/cdp-client/src/cdp.rs` `adopt_guard_attach`).
|
|
126
|
+
- `Target.targetCreated` with `targetInfo` (`crates/cdp-client/src/cdp.rs` `watch`).
|
|
127
|
+
- `Target.targetInfoChanged` with `targetInfo`. A protected `url` marks the tab protected (`crates/cdp-client/src/cdp.rs` `watch`).
|
|
128
|
+
- `Target.targetDestroyed` with `targetId` (`crates/cdp-client/src/cdp.rs` `watch`).
|
|
129
|
+
- `Target.detachedFromTarget` with `sessionId` (`crates/cdp-client/src/cdp.rs` `watch`).
|
|
130
|
+
|
|
131
|
+
### Guard
|
|
132
|
+
|
|
133
|
+
- Every attach uses `flatten: true`. A non-flat `Target.attachToTarget` or `Target.setAutoAttach` is refused before it is sent (`crates/cdp-client/src/cdp.rs` `admit`), and so is `autoAttach: true` (`crates/cdp-client/src/cdp.rs` `admit`).
|
|
134
|
+
- Before a tab is used, the client attaches a guard session of its own. It is registered from the `Target.attachToTarget` reply (`crates/cdp-client/src/cdp.rs` `touch`) or from the `Target.attachedToTarget` event (`crates/cdp-client/src/cdp.rs` `adopt_guard_attach`), whichever comes first.
|
|
135
|
+
- `Target.setDiscoverTargets`, the attach and the setup steps share one `GUARD_SETUP` budget of 30 s (`crates/cdp-client/src/cdp.rs` `GUARD_SETUP`).
|
|
136
|
+
- The guard's `Fetch.enable` is `{patterns: [{urlPattern: "*", resourceType: "Document", requestStage: "Request"}]}` and decides per paused request (`crates/cdp-client/src/cdp.rs` `touch`). A backend must accept it. A backend's shield may refuse any interception pattern that names a protected origin, and clients never send one: `route` checks each `pattern` and refuses such a route before `Fetch.enable` is sent (`crates/cdp-client/src/fetch.rs` `enable`). Sending one broke bios and the extension on 2026-10-17.
|
|
137
|
+
- Then `Network.enable` and `Network.setBypassServiceWorker` with `{bypass: true}`, which must succeed (`crates/cdp-client/src/cdp.rs` `touch`).
|
|
138
|
+
- `Page.enable` and `Runtime.enable` are optional. Each gets at most `OPTIONAL_STEP`, 10 s of what is left (`crates/cdp-client/src/cdp.rs` `OPTIONAL_STEP`). An error reply, `<method>: <message>`, is ignored (`crates/cdp-client/src/cdp.rs` `touch`). A timeout prints `slicc: guard: <method> timed out; continuing` (`crates/cdp-client/src/cdp.rs` `touch`).
|
|
139
|
+
- Any other failure detaches the guard and marks the tab unguarded, so every later command on it is refused (`abandon`, `crates/cdp-client/src/cdp.rs` `touch`).
|
|
140
|
+
|
|
141
|
+
### Refused before sending
|
|
142
|
+
|
|
143
|
+
The client refuses these before sending, so a backend needn't implement them (`crates/cdp-client/src/shield.rs` `browser_wide`).
|
|
144
|
+
|
|
145
|
+
- `Target.exposeDevToolsProtocol`.
|
|
146
|
+
- `Target.sendMessageToTarget`. Attach with `flatten: true` instead.
|
|
147
|
+
- `Target.attachToBrowserTarget`.
|
|
148
|
+
- `Tracing.start`.
|
|
149
|
+
- `Extensions.loadUnpacked`.
|
|
150
|
+
- `Network.clearBrowserCookies`.
|
|
151
|
+
- `Storage.clearCookies` unless its `browserContextId` came from this client's `Target.createBrowserContext`.
|
|
152
|
+
- `Browser.resetPermissions` on the same terms.
|
|
153
|
+
- `Browser.setPermission` with no `origin`, on the same terms.
|
|
154
|
+
- `Browser.grantPermissions` with no `origin`, on the same terms.
|
|
155
|
+
- `Network.setRequestInterception`.
|
|
156
|
+
- `Fetch.*` with no `sessionId`.
|
|
157
|
+
|
|
158
|
+
### Session-level domains
|
|
159
|
+
|
|
160
|
+
Everything else goes over a flat session, with a top-level `sessionId`.
|
|
161
|
+
|
|
162
|
+
- `Page`
|
|
163
|
+
- `Runtime`
|
|
164
|
+
- `DOM`
|
|
165
|
+
- `Input`
|
|
166
|
+
- `Network`
|
|
167
|
+
- `Fetch`
|
|
168
|
+
- `Accessibility`
|
|
169
|
+
|
|
170
|
+
`slicc-cdp-client` also lets a caller `IO.read` a stream that a session reply handed out (`crates/cdp-client/src/cdp.rs` `admit`).
|
|
171
|
+
|
|
87
172
|
## Package
|
|
88
173
|
|
|
89
174
|
Node ≥ 24. `npm run lint` runs `slicc-lint`. Releases use semantic-release on `main`. Git `package.json` stays `0.0.0`. The published version is the release tag.
|
package/bin/curlwright.wasm
CHANGED
|
Binary file
|
package/bin/playwright-cli.wasm
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-cdp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
4
|
"description": "SLICC's CDP layer: client, browser API, transports, HAR, and ARIA snapshot",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"chrome": "156.0.8078.4"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@ai-ecoverse/slicc-kernel": "1.
|
|
71
|
+
"@ai-ecoverse/slicc-kernel": "1.122.1",
|
|
72
72
|
"@ai-ecoverse/slicc-shared-web": "1.23.1",
|
|
73
73
|
"@biomejs/biome": "2.5.15",
|
|
74
74
|
"lefthook": "2.2.1",
|