kcode-jsonrpc-stdio 0.2.1

Asynchronous header-omitted JSON-RPC 2.0 transport over child-process JSONL stdio.
Documentation
# API

```rust
pub const MAX_INBOUND_LINE_BYTES: usize = 8 * 1024 * 1024;
pub const MAX_STDERR_CAPTURE_BYTES: usize = 64 * 1024;

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct RequestId(pub u64);

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum PeerId { Number(serde_json::Number), String(String) }

#[derive(Clone, Debug, PartialEq)]
pub struct RpcError { pub code: i64, pub message: String, pub data: Option<serde_json::Value> }

#[derive(Clone, Debug, PartialEq)]
pub enum IncomingMessage {
    Response { id: PeerId, result: Result<serde_json::Value, RpcError> },
    Request { id: PeerId, method: String, params: serde_json::Value },
    Notification { method: String, params: serde_json::Value },
}

#[derive(Clone, Debug)]
pub struct ProcessExit { pub status: std::process::ExitStatus, pub stderr: String }

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    Json(serde_json::Error),
    InvalidMessage(String),
    InboundLineTooLong,
    ProcessExited(ProcessExit),
    StderrTask(String),
}

impl std::fmt::Display for Error;
impl std::error::Error for Error;
impl From<std::io::Error> for Error;
impl From<serde_json::Error> for Error;

pub struct StdioRpc { /* private fields */ }

impl StdioRpc {
    pub fn spawn(command: tokio::process::Command) -> Result<Self, Error>;
    pub async fn send_request(&mut self, method: impl Into<String>, params: serde_json::Value) -> Result<RequestId, Error>;
    pub async fn send_notification(&mut self, method: impl Into<String>, params: serde_json::Value) -> Result<(), Error>;
    pub async fn next(&mut self) -> Result<IncomingMessage, Error>;
    pub async fn respond(&mut self, id: PeerId, result: serde_json::Value) -> Result<(), Error>;
    pub async fn respond_error(&mut self, id: PeerId, code: i64, message: impl Into<String>, data: Option<serde_json::Value>) -> Result<(), Error>;
    pub async fn shutdown(self) -> Result<ProcessExit, Error>;
}
```

`StdioRpc` owns one child process using JSON-RPC 2.0 semantics with the `jsonrpc` version member omitted and one UTF-8 JSON object per stdin or stdout line. Locally issued request IDs begin at one and increase for the life of the instance. Peer IDs may be integer JSON numbers or strings. Missing parameters are exposed as JSON null. Messages containing a `jsonrpc` member, ambiguous request/response fields, unsupported IDs, malformed JSON, or an over-limit line fail explicitly. An over-limit line is drained before returning so later framing remains aligned. Stderr is drained concurrently; only its first `MAX_STDERR_CAPTURE_BYTES` bytes are retained and returned lossily as UTF-8. The supplied command uses piped standard streams and kill-on-drop. End-of-stdout is returned as `Error::ProcessExited` with status and captured stderr. Distinct values are independent; mutable methods preserve caller-controlled wire order.

- `spawn` must run inside a Tokio runtime. Performance: Not yet benchmarked; Kennedy-owned work is constant apart from operating-system process startup.
- `send_request` serializes, writes, and flushes one line without retries or a timeout. Performance: Not yet benchmarked; work and temporary memory are linear in serialized message bytes.
- `send_notification` serializes, writes, and flushes one line without retries or a timeout. Performance: Not yet benchmarked; work and temporary memory are linear in serialized message bytes.
- `next` reads and parses one line without retries or a timeout. Performance: Not yet benchmarked; work and memory are linear in current-line bytes up to `MAX_INBOUND_LINE_BYTES`.
- `respond` serializes, writes, and flushes one line without retries or a timeout. Performance: Not yet benchmarked; work and temporary memory are linear in serialized message bytes.
- `respond_error` serializes, writes, and flushes one line without retries or a timeout. Performance: Not yet benchmarked; work and temporary memory are linear in serialized message bytes.
- `shutdown` closes stdin, kills a still-running child, and reaps it. Performance: Not yet benchmarked; Kennedy-owned work is constant apart from waiting for operating-system process termination.