Subscribe to a WebSocket feed
Open a WebSocket, subscribe to a topic and collect its updates until the server closes.
Generated by cargo run -p agent_docs from compiler/examples/. Edit the example files, then regenerate.
Open a WebSocket, subscribe to a topic and collect its updates until the server closes.
WebSocket.connect opens the connection and runs the callback with the Socket; when the
callback returns, fails or is cancelled the connection is closed (1001 if it is still open), and
returning the socket from the callback is V6003. There are no event listeners: a message or
the close is a value WebSocket.receive returns, and WebSocket.messages(sock) is the same as a
source that ends at the close, so filter, map and to_list(max) read it with a stated
bound. max_message caps each message at 64 KiB in both directions; a larger one from the
server ends the connection with 1009.
The manifest grants feed.example.com:443, the port a wss URL uses by default; a main that
declares WebSocket with an empty net list exits 75 at startup. The tests run against
WebSocket.scripted: Reply answers the subscription, Push sends updates, Close ends the
feed, and a send the script does not expect fails with SocketError(Failed(...)) instead of
waiting. No test opens a socket.
Source project · harness mode: test.
From the repository root, with this checkout's sakura on PATH:
cd compiler/examples/websocket_client
sakura check --json
sakura test --jsonManifest and permissions
[package]
name = "websocket_client"
version = "0.1.0"
edition = "2026"
[permissions]
net = ["feed.example.com:443"]Source and tests
src/main.sak includes all required imports and tests.
import std/stream.{Source, StreamError}
import std/websocket.{Binary, Close, Message, Options, Push, Reply, SocketError, Text, WebSocket}
/// Subscribes to `topic` on a feed server and returns up to `max` text updates, in order, until
/// the server closes the connection. A binary frame is skipped. Every message is at most 64 KiB.
pub fn updates(url: String, topic: String, max: Int) -> List<String>
! {WebSocket, Fail<SocketError | StreamError>}
requires max >= 0
{
let opts = Options { ..WebSocket.options(), subprotocols: ["feed.v1"], max_message: 65_536 }
WebSocket.connect(url, opts, fn(sock) {
WebSocket.send(sock, Text("subscribe {topic}"))
WebSocket.messages(sock).filter(is_text).map(text_of).to_list(max)
})
}
fn is_text(m: Message) -> Bool {
match m {
Text(_) => true,
Binary(_) => false,
}
}
fn text_of(m: Message) -> String {
match m {
Text(s) => s,
Binary(_) => "",
}
}
test "updates arrive in order until the server closes" {
let script = [
Reply(Text("subscribe prices"), Text("ok")),
Push(Text("BTC 1")),
Push(Binary(Bytes.from_list([0]))),
Push(Text("BTC 2")),
Close(1000, "end of feed"),
]
with WebSocket.scripted(script) {
expect_eq(
try { updates("wss://feed.example.com/live", "prices", 10) },
Ok(["ok", "BTC 1", "BTC 2"]),
)
}
}
test "more updates than asked for fail instead of growing" {
let script = [Reply(Text("subscribe a"), Text("1")), Push(Text("2")), Push(Text("3"))]
with WebSocket.scripted(script) {
let got = try { updates("wss://feed.example.com/live", "a", 2) }
expect(String.contains("{got}", "MaxItems"))
}
}
test "a server that answers the wrong subscription is a typed failure" {
with WebSocket.scripted([Reply(Text("subscribe b"), Text("ok"))]) {
let got = try { updates("wss://feed.example.com/live", "a", 10) }
expect(String.contains("{got}", "Failed"))
}
}Compiler provenance and regeneration
Finish only when no holes remain, independent tests pass, the requested target builds, and contracts/tests/permissions have not been weakened. Repeat the frozen baseline check after the final edits. Report missing prerequisites and failing checks explicitly; do not claim a skipped test passed.
These ten projects teach supported Sakura APIs on the JavaScript backend. Each
project is exercised offline by cargo test -p sakura_cli --test examples;
HTTP and LLM exchanges are synthetic committed cassettes, with no network or API keys.
Use Node 26 for execution, including its built-in SQLite implementation.
The initial API baseline is compiler revision
5cae349516c21714d90d36e87f1cfd6debe980c6.
CI reruns these projects against the compiler in the same checkout. Build that
checkout's CLI and run sakura --version and sakura prompt before adapting a recipe.
Sakura Lang is pre-1.0: read STABILITY.md before depending on an API. An installed
skill's frontmatter records its compiler version and build revision. These teaching examples are separate from the agent
evaluation tasks.
The source of each page is its example's recipe.md, sakura.toml,
src/main.sak and fixture files. Run cargo run -p agent_docs from compiler/
to regenerate the cookbook and skill reference. Edit those sources, not the rendered pages.
Last updated