SDK Overview

Diminuendo ships with four official client SDKs — TypeScript, Rust, Python, and Swift — each providing a typed, ergonomic interface to the full 21-message, 51-event wire protocol. The SDKs are designed to be standalone: they carry no gateway-specific dependencies and communicate exclusively over standard WebSocket connections using JSON framing. Any WebSocket-capable runtime can use them.

Design Principles

All four SDKs share a common set of design principles, despite their divergent language idioms:

Full Protocol Parity

Every client message type and every server event type is represented in each SDK. No event is silently dropped. No message type is missing. The SDKs are functionally equivalent — anything one can do, all can do.

Zero Gateway Dependencies

The SDKs do not import gateway code, do not share types via monorepo packages, and do not require code generation. Each SDK defines its own types from the wire protocol specification. This ensures they can be published and used independently.

Native Idioms

TypeScript uses Promises and typed event handlers. Rust uses async channels and serde. Python uses asyncio and dataclasses. Swift uses async/await and Codable. Each SDK feels native to its language — no lowest-common-denominator abstraction.

Adversarial Test Suites

Every SDK has a comprehensive test suite that does not merely verify happy paths, but actively attempts to break the client with malformed data, concurrent operations, timeouts, and edge cases. See Testing Methodology for details.

SDK Comparison

AspectTypeScriptRustPythonSwift
RuntimeNode.js, Bun, Deno, browserstokio (async runtime)asyncio + websocketsSwift Concurrency + URLSessionWebSocketTask
DependenciesZero runtime depstokio, serde, tokio-tungstenite, futures-util, thiserror, tracingwebsocketsNone (Foundation only)
Async ModelPromises + event callbacksmpsc::UnboundedReceiver<ServerEvent>async/await + event callbacksasync/await + AsyncStream<ServerEvent>
Type SystemTypeScript interfaces (compile-time)Rust enums with #[serde(tag = "type")] (compile + runtime)Dataclasses with from_dict parsersCodable enums/structs with CodingKeys
Event Delivery.on(type, handler) with unsubscribeChannel-based (events.recv().await).on(type, handler) with unsubscribeAsyncStream consumption in a for await loop
Wildcard Events.on("*", handler)ServerEvent::Unknown catch-all.on("*", handler).unknown catch-all case
Wire MappingcamelCase (native)#[serde(rename)] from snake_casefrom_dict with explicit key mappingCodingKeys with camelCase
Connection ManagementAuto-reconnect, ping timerManual (application controls lifecycle)Auto-reconnect, ping timerAuto-reconnect, ping timer
Primary Use CaseWeb apps, Node.js servicesTauri desktop apps, CLI toolsScripts, testing, notebooksmacOS/iOS apps, SwiftUI clients
Test Count137 tests178 tests173 tests193 tests

TypeScript SDK

The TypeScript SDK (sdk/typescript/) is a zero-dependency WebSocket client that works in any JavaScript runtime with a standard WebSocket global — browsers, Node.js 21+, Bun, and Deno. It provides a Promise-based API for request-response operations and typed event handlers for streaming events.
import { DiminuendoClient } from "@igentai/diminuendo-client"

const client = new DiminuendoClient({
  url: "ws://localhost:8080/ws",
  token: "eyJ...",
})

await client.connect()

// Request-response: returns typed result
const sessions = await client.listSessions()
const session = await client.createSession("coding-agent", "My Session")
const snapshot = await client.joinSession(session.id)

// Fire-and-forget: streaming interaction
client.runTurn(session.id, "Explain the architecture")

// Typed event handlers with unsubscribe
const unsub = client.on("text_delta", (event) => {
  process.stdout.write(event.text)
})

client.on("turn_complete", (event) => {
  console.log("Done:", event.finalText.slice(0, 100))
  unsub() // unsubscribe from text_delta
})

// Wildcard handler
client.on("*", (event) => {
  console.log(`[${event.type}]`)
})
Key characteristics:
  • Auto-reconnect: Configurable via autoReconnect and reconnectDelay options. On disconnect, the client automatically re-establishes the connection and re-authenticates.
  • Ping keepalive: Sends periodic pings (default 30s) to detect stale connections. The ping() method returns latency in milliseconds.
  • Request chaining: Concurrent requests of the same type to the same session are serialized internally to prevent response mismatching.
  • Typed on(): The event handler’s parameter type is narrowed to the specific event type, providing full IntelliSense and compile-time safety.

TypeScript SDK Reference

Full API documentation, installation, and usage examples.

Rust SDK

The Rust SDK (sdk/rust/) is an async WebSocket client built on tokio, designed primarily for Tauri v2 desktop applications and CLI tools. It uses an mpsc channel pair for event delivery — the client sends messages via methods on DiminuendoClient, and events arrive on an UnboundedReceiver<ServerEvent>.
use diminuendo_sdk::{DiminuendoClient, ClientOptions, ServerEvent, ClientMessage};

let options = ClientOptions {
    url: "ws://localhost:8080/ws".into(),
    token: "eyJ...".into(),
};

let (client, mut events) = DiminuendoClient::connect(options).await?;

// Send messages
client.send(ClientMessage::ListSessions { include_archived: None }).await?;
client.send(ClientMessage::CreateSession {
    agent_type: "coding-agent".into(),
    name: Some("My Session".into()),
}).await?;

// Receive events
while let Some(event) = events.recv().await {
    match event {
        ServerEvent::SessionList { sessions } => {
            println!("Found {} sessions", sessions.len());
        }
        ServerEvent::TextDelta { text, .. } => {
            print!("{text}");
        }
        ServerEvent::TurnComplete { final_text, .. } => {
            println!("\nDone: {}", &final_text[..100]);
        }
        ServerEvent::Error { code, message } => {
            eprintln!("[{code}] {message}");
        }
        ServerEvent::Unknown => {
            // Future event types are gracefully ignored
        }
        _ => {}
    }
}
Key characteristics:
  • Send + Sync: The client is safe to share across Tauri command handlers and tokio tasks. All operations are non-blocking.
  • Serde-based types: All 21 ClientMessage variants and 51 ServerEvent variants derive Serialize/Deserialize with exact camelCase wire mapping via #[serde(rename)].
  • Unknown variant: The ServerEvent enum includes #[serde(other)] Unknown, so future event types added to the protocol do not cause deserialization failures.
  • Background I/O: A spawned tokio task handles all WebSocket reads and writes, decoupling the application from I/O scheduling.

Rust SDK Reference

Full API documentation, Cargo setup, and Tauri integration guide.

Python SDK

The Python SDK (sdk/python/) is an asyncio-based WebSocket client using the websockets library. It provides a callback-based event model with wildcard support, and dataclass-based types with from_dict class methods for parsing wire data.
from diminuendo_sdk import DiminuendoClient, ClientOptions, ServerEvent

client = DiminuendoClient(ClientOptions(
    url="ws://localhost:8080/ws",
    token="eyJ...",
))

await client.connect()

# Request-response methods
sessions = await client.list_sessions()
session = await client.create_session("coding-agent", "My Session")
snapshot = await client.join_session(session.id)

# Fire-and-forget
await client.run_turn(session.id, "Explain the architecture")

# Event handlers with unsubscribe
def on_delta(event: ServerEvent):
    print(event.text, end="", flush=True)

unsub = client.on("text_delta", on_delta)

def on_complete(event: ServerEvent):
    print(f"\nDone: {event.final_text[:100]}")
    unsub()

client.on("turn_complete", on_complete)

# Wildcard
client.on("*", lambda e: print(f"[{e.type}]", e.data))
Key characteristics:
  • Dataclass types: SessionMeta, FileEntry, IterationMeta, FileContent, StateSnapshot, and HistoryItem are @dataclass types with from_dict class methods that handle the camelCase-to-snake_case mapping.
  • ServerEvent wrapper: All events are wrapped in a ServerEvent dataclass with convenience properties: session_id, turn_id, text, final_text, error_code, error_message, seq, ts, and category checks like is_turn_event, is_tool_event, is_thinking_event.
  • Auto-reconnect: Configurable via auto_reconnect and reconnect_delay options.
  • Predicate-based requests: Internal request/response matching uses predicates, allowing the client to wait for specific response types without blocking other event processing.

Python SDK Reference

Full API documentation, pip installation, and usage examples.

Swift SDK

The Swift SDK (sdk/swift/) is an actor-based client built on Swift Concurrency and URLSessionWebSocketTask. It delivers events through an AsyncStream<ServerEvent> and uses Codable for all 21 client messages and 51 server events. It has zero third-party dependencies.
import DiminuendoSDK

let client = DiminuendoClient(options: .init(
    url: "ws://localhost:8080/ws",
    token: ""
))

try await client.connect()

Task {
    for await event in await client.events {
        if case let .textDelta(_, _, text, _, _) = event {
            print(text, terminator: "")
        }
    }
}

let session = try await client.createSession(agentType: "coding-agent", name: "My Session")
let snapshot = try await client.joinSession(sessionId: session.id)
try await client.runTurn(sessionId: session.id, text: "Explain this codebase")
Key characteristics:
  • Actor-based concurrency: The client is a Swift actor, providing inherent thread safety for all mutable state. All public types are Sendable.
  • AsyncStream event delivery: Events arrive via AsyncStream<ServerEvent> for idiomatic for await loops in SwiftUI views or background tasks.
  • Zero third-party dependencies: Uses only Foundation’s URLSessionWebSocketTask for WebSocket communication.
  • Auto-reconnect and ping keepalive: Configurable via ClientOptions, matching the behavior of the TypeScript and Python SDKs.

Swift SDK Reference

Full API documentation, Swift Package Manager setup, and macOS/iOS guidance.

Protocol Coverage Matrix

Every client message and server event is implemented in all four SDKs. The following table confirms full parity:
Message TypeTypeScriptRustPythonSwift
authenticateYesYesYesYes
list_sessionsYesYesYesYes
create_sessionYesYesYesYes
rename_sessionYesYesYesYes
archive_sessionYesYesYesYes
unarchive_sessionYesYesYesYes
delete_sessionYesYesYesYes
join_sessionYesYesYesYes
leave_sessionYesYesYesYes
run_turnYesYesYesYes
stop_turnYesYesYesYes
steerYesYesYesYes
answer_questionYesYesYesYes
get_historyYesYesYesYes
get_eventsYesYesYesYes
pingYesYesYesYes
list_filesYesYesYesYes
read_fileYesYesYesYes
file_historyYesYesYesYes
file_at_iterationYesYesYesYes
manage_membersYesYesYesYes
Event TypeTypeScriptRustPythonSwift
welcomeYesYesYesYes
connectedYesYesYesYes
authenticatedYesYesYesYes
heartbeatYesYesYesYes
session_listYesYesYesYes
session_createdYesYesYesYes
session_updatedYesYesYesYes
session_archivedYesYesYesYes
session_unarchivedYesYesYesYes
session_deletedYesYesYesYes
session_stateYesYesYesYes
state_snapshotYesYesYesYes
stream_snapshotYesYesYesYes
turn_startedYesYesYesYes
text_deltaYesYesYesYes
turn_completeYesYesYesYes
turn_errorYesYesYesYes
message.deltaYesYesYesYes
message.completeYesYesYesYes
tool_callYesYesYesYes
tool_resultYesYesYesYes
tool_call_startYesYesYesYes
tool_call_deltaYesYesYesYes
tool_errorYesYesYesYes
question_requestedYesYesYesYes
permission_requestedYesYesYesYes
approval_resolvedYesYesYesYes
thinking_startYesYesYesYes
thinking_progressYesYesYesYes
thinking_completeYesYesYesYes
terminal_streamYesYesYesYes
terminal_completeYesYesYesYes
sandbox_initYesYesYesYes
sandbox_provisioningYesYesYesYes
sandbox_readyYesYesYesYes
sandbox_removedYesYesYesYes
usage_updateYesYesYesYes
usage_contextYesYesYesYes
gapYesYesYesYes
replay_completeYesYesYesYes
file_listYesYesYesYes
file_contentYesYesYesYes
file_history_resultYesYesYesYes
file_changedYesYesYesYes
steer_sentYesYesYesYes
stop_acknowledgedYesYesYesYes
server_shutdownYesYesYesYes
historyYesYesYesYes
eventsYesYesYesYes
member_listYesYesYesYes
member_updatedYesYesYesYes
member_removedYesYesYesYes
errorYesYesYesYes
pongYesYesYesYes

Testing

The SDKs collectively include 681 tests and approximately 3,100 assertions, covering every message type, every event type, every error code, and a range of adversarial edge cases. With the gateway’s 9 integration tests, the repository totals 690 tests. The testing methodology follows a Popperian epistemology — tests are designed to refute, not confirm, and confidence comes from the failure to find bugs despite aggressive attempts.

Testing Methodology

Detailed explanation of the adversarial testing approach, test architecture per SDK, and what makes the test suites severe.

Running the Tests

bun test
Run all tests across all SDKs in a single command:
bun test && \
(cd sdk/typescript && bun test) && \
(cd sdk/rust && cargo test) && \
(cd sdk/python && python -m pytest tests/ -v) && \
(cd sdk/swift && swift test)
This is the full test suite that must pass before any code is merged.

Coverage Statistics

SDKTestsAssertionsMessage TypesEvent TypesError Types
TypeScript137~60021/2151/51All
Rust178~80021/2151/51All
Python173~80021/2151/51All
Swift193~90021/2151/51All
Total (SDKs)681~3,10021/2151/51All
The gateway itself has an additional 9 integration tests that validate the server-side protocol handling, session lifecycle, event mapping, and error paths against an in-process gateway instance with SQLite in-memory databases and mock Podium connections. Tests follow the severe testing methodology: adversarial mindset, falsifiable claims with strong oracles (mock gateway as reference implementation), edge cases where bugs actually hide (not happy-path confirmation). Every test is designed to fail if the implementation is wrong — no type-only checks, no constructor-existence tests, no trivial round-trips with hardcoded inputs.