Files
rutster/Cargo.toml
opencode controller a2d5e38238 feat(brain-realtime): OpenAI wss client pump (spec §4)
Builds session.update with turn_detection: null on handshake (S4,
encoded in the translator's build_openai_session_update; Task 4).
Runs a select! loop over tap-side input (audio_in → append,
function_call_output → conversation.item.create) and OpenAI-side
input (response.audio.delta → tap audio_out, speech_started/stopped
→ tap speech_started/stopped, function_call_arguments.done → tap
function_call). 401 surfaces as OpenAiClientError::AuthFailed.

URL + headers shape tested directly. Full pump loop tested via
MockRealtimeBrain in Task 10 — neither side of this pump is a real
network endpoint in unit tests.
2026-06-30 20:43:34 -04:00

62 lines
2.4 KiB
TOML

# Cargo.toml — rutster workspace root.
# Spec ref: slice-1 §2. The workspace pins shared dep versions here so
# member crates can't drift (§2.1). Each member references with
# `dep.workspace = true`.
[workspace]
resolver = "2"
members = [
"crates/rutster",
"crates/rutster-call-model",
"crates/rutster-media",
"crates/rutster-trunk",
"crates/rutster-tap",
"crates/rutster-tap-echo",
"crates/rutster-brain-realtime",
"crates/rutster-spend",
]
[workspace.package]
license = "GPL-3.0-or-later"
edition = "2024"
repository = "https://git.adlee.work/alee/rutster"
# Pinned versions for all member crates. References are `foo.workspace = true`
# in the member manifest. Keeps the dep tree unified (§2.1).
[workspace.dependencies]
# str0m 0.21: sans-IO WebRTC. Frame API (Event::MediaData + Writer::write).
str0m = "0.21"
# opus 0.3.1: libopus FFI (system libopus required — see README).
opus = "0.3"
# axum 0.7: HTTP signaling surface.
axum = { version = "0.7", features = ["macros"] }
# tokio 1: runtime driving the str0m poll loop (slice-1 deviation per §3.4).
tokio = { version = "1", features = ["full"] }
# dashmap 6: in-process session store.
dashmap = "6"
# uuid 1: ChannelId newtype backing.
uuid = { version = "1", features = ["v4"] }
thiserror = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# tower: used by the binary crate's integration tests (ServiceExt::oneshot
# on the axum Router). Axum re-exports parts of tower but the integration test
# uses `tower::ServiceExt` directly, so it needs to be a workspace dep.
tower = { version = "0.5", features = ["util"] }
# tokio-tungstenite 0.24: WS client + server (slice-2 tap transport).
tokio-tungstenite = { version = "0.24", features = ["connect"] }
# futures-util 0.3: Sink/Stream traits for WebSocketStream.
futures-util = "0.3"
# url 2: tap URL parsing + host validation (spec §4.4).
url = "2"
# base64 0.22: PCM <-> base64 codec for the v1 wire format (spec §3).
base64 = "0.22"
# async-trait 0.1: async fns in trait objects (Tool trait, slice-3 spec §6.1).
async-trait = "0.1"
# http 1: Request/Response builders for the OpenAI WS handshake (slice-3
# spec §5.3). Task 9's main.rs builds the http::Request<...> the tungstenite
# client sends before WS upgrade; `openai_client::openai_headers` produces
# the header pairs the caller stuffs into it.
http = "1"