Expand description
Which request and response type each RPC command carries.
§Why this exists
The frontend talks to srv through 284 hand-written command stubs
(frontend/app/store/rpc-api/*.ts) and a 2,819-line hand-maintained
frontend/types/srv-types.d.ts, every one of them headed “keep in sync
with the agentmux-srv RPC”. docs/reports/REPORT_DRY_AND_MODULARITY_AUDIT_2026_09_06.md
§2.1 counted 334 such comments and one live drift found by hand.
The obvious fix — derive the TypeScript types from the Rust ones — does
not work on its own, and docs/specs/SPEC_RPC_BINDINGS_CODEGEN_2026_09_07.md
§2 explains why: which command takes which request and returns which
response is not data anywhere in srv. Each handler picks its request
type inline (serde_json::from_value::<CommandXData>(data)) and builds
its response ad hoc (serde_json::to_value(&x), json!({"ok": true})).
A type generator can emit every struct and still not know how to pair
them into a callable stub.
This module is that missing mapping, recorded as a side effect of
registration itself (RpcEngine::register_typed) rather than written
down a second time — so it cannot drift from the handlers the way a
hand-maintained list would. It is deliberately just the mapping: no
TypeScript is emitted here, and adding a code generator on top is a
separate change against an already-proven registry (spec §3.4 step 1).
§What a binding is
One row per command registered through the typed path, holding the fully
qualified Rust type names of its request and response. Handlers still on
the untyped register_handler contribute nothing — they are simply
absent, which is what makes an incremental migration possible.
Structs§
- RpcBinding
- The request/response pair for one command.
- RpcSchema
- Every typed command registered on one engine.
- TsType
- How a Rust type reads in TypeScript, as ts-rs itself renders it.
Functions§
- ts_type
Tas TypeScript: its ts-rs name, and the exported types that name uses.