Skip to content

Wire contract

Raku and the Node sidecar speak JSON-RPC 2.0 over stdio with NDJSON framing. Each message is a single line of compact JSON terminated by \n. The wire is never pretty-printed; a raw newline inside a message would break framing.

Messages

Request:

1
{"jsonrpc":"2.0","id":1,"method":"ping","params":{}}

Success response:

1
{"jsonrpc":"2.0","id":1,"result":"pong"}

Failure response:

1
{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"...","data":{"name":"Error","stack":"..."}}}

Every request carries a unique id. The sidecar echoes that id on the matching response so Raku can correlate replies to in-flight calls. Responses may arrive in any order; correlation is by id, not arrival order.

Error codes

The sidecar follows the JSON-RPC 2.0 reserved range and adds one implementation-defined code for Playwright failures.

Code Meaning
-32700 Parse error: the line was not valid JSON.
-32600 Invalid request: missing or non-string method.
-32601 Method not found.
-32000 A Playwright or handler error was thrown.

A failure response carries the original error name and stack in data so the Raku side can rebuild a typed exception.

Handle model

Browser objects never cross the wire. The sidecar keeps a registry mapping opaque string handles to live objects (a Browser, BrowserContext, Page, Locator, or ElementHandle). Handles are minted as kind@N:

1
2
3
4
browser@1
context@1
page@1
loc@7

A method that creates an object returns its handle. A later request passes the handle back in params.handle (or another named field) and the sidecar resolves it to the live object before acting. Resolving an unknown handle is an error.

Methods

Method Params Result
ping none "pong"
launch { headless: Bool } a browser@N handle
close { handle: "kind@N" } null

launch starts Chromium. close closes the object behind a handle and forgets it. When the sidecar's stdin closes, it closes every browser it launched before exiting.