# car-server-core

Transport-neutral library for the [Common Agent Runtime](https://github.com/Parslee-ai/car) JSON-RPC dispatcher.

## What it does

Holds the JSON-RPC dispatcher, per-client session state, and the WebSocket channel plumbing. Used by `car-server` (the standalone WebSocket binary) and by any future embedder that wants to expose CAR's protocol over a different transport (e.g. `tokhn-daemon`).

The standalone `car-server` binary is a thin wrapper that loads `~/.car/env`, initializes telemetry, spawns the dream loop, binds a TCP listener, and on each connection calls `run_dispatch`.

## Library boundary contract

This library MUST NOT:
- spawn the dream loop (caller decides),
- initialize telemetry (caller decides),
- load `~/.car/env` (caller decides).

Those bootstraps stay in the embedder's `main`. The contract prevents the dual-memgine bug: if the library silently spawned its own dream loop, embedded users would end up with two memgine engines (the embedder's plus the library's).

## Lock primitive

`ClientSession.memgine` uses `Arc<tokio::sync::Mutex<MemgineEngine>>` per the "one-wrapper rule" — dispatcher handlers can hold the lock across `.await` points without risking poisoning, and tokio's `Mutex` does not poison so a panicking handler does not poison the engine for sibling connections.

## Embedder usage

```rust,ignore
use car_server_core::{ServerState, ServerStateConfig, run_dispatch};

// Build the shared server state.
let state = ServerState::embedded(ServerStateConfig::default()).await?;

// On each accepted WebSocket connection:
tokio::spawn(async move {
    run_dispatch(ws, state.clone()).await;
});
```

## Where it fits

The full method reference is in [`docs/websocket-protocol.md`](../../../docs/websocket-protocol.md) — that document describes the wire format produced by this crate's dispatcher.
