soothe-client 0.3.1

WebSocket client for talking to a running soothe-daemon
Documentation

soothe-client (Rust)

Talk to a running soothe-daemon over WebSocket — send prompts, stream agent turns, run jobs.

cargo add soothe-client

Requires a local daemon (default ws://127.0.0.1:8765).

Quick start

use soothe_client::appkit::{DaemonSession, SendTurnOptions};
use soothe_client::TEXT_COMPLETION;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let session = DaemonSession::new("ws://127.0.0.1:8765", None);
    session.connect(None).await?;
    session
        .send_turn(
            "Summarize this in one sentence: agents need tools.",
            Some(SendTurnOptions {
                intent_hint: Some(TEXT_COMPLETION.into()),
                ..Default::default()
            }),
        )
        .await?;
    for chunk in session.iter_turn_chunks(None).await? {
        println!("{} {:?}", chunk.mode, chunk.data);
    }
    session.close().await?;
    Ok(())
}

More patterns: examples/ (hello → streaming → multi-turn → pool → jobs).

Route to a specialist with preferred_subagent (canonical ids: deep_research, academic_research, browser_use, planner):

use soothe_client::{Client, SendInputOptions};

# async fn demo() -> Result<(), soothe_client::errors::Error> {
let client = Client::new("ws://127.0.0.1:8765");
client.connect().await?;
client
    .send_input(
        "Research recent agent evaluation benchmarks",
        SendInputOptions {
            preferred_subagent: Some("deep_research".into()),
            ..Default::default()
        },
    )
    .await?;
# Ok(())
# }

What you get

Need Use
One conversation, stream replies appkit::DaemonSession
Jobs / cron (async) AsyncCommandClient
Jobs / cron (scripts / sync) CommandClient
Raw WebSocket / custom RPCs Client
Many users / HTTP backend ConnectionPool + TurnRunner (+ optional SseBroadcaster)

DaemonSession uses a dual-socket layout (stream + RPC sidecar): peels leftover prior-goal terminals, applies early chunk filtering, ignores premature soothe.stream.end until the turn has progress, drains a short post-idle window, and sends delivery_ack on terminal frames.

TurnRunner ends turns via TurnBoundary (gated stream.end / idle / stopped), with pre-send settle-drain and arm-before-end so pooled leftovers cannot end the next turn early.

Develop

make check                 # fmt + clippy + unit tests
make test-integration      # live suite (needs soothed)
make test-examples         # live 01–06 (needs soothed)

Compatibility

Same protocol-1 WebSocket contract as soothe-client-python, soothe-client-go, and @mirasoth/soothe-client.

License

MIT