When caller and callee run in the same process, a unary Call pays the
full network tax — pool.Get, dial, codec-over-socket, and the transport
pump — even though the handler table is right there. This adds an opt-in
fast-path that dispatches directly.
- internal/network: a neutral registry (transport.Message in/out) so
client and server wire up without importing each other. A running server
registers a dispatcher under its name on Start, deregisters on Stop.
- server: localDispatch serves a request in-process through the same
router (identical wrappers/codecs/error mapping) over an in-memory
socket — no dial, no pipe, no gob.
- client: LocalDispatch() opt-in. In call(), a unary request whose body and
response are raw frames (codec/bytes.Frame — the agent/MCP/flow shape)
dispatches locally; everything else falls back to the network path
unchanged.
Correctness test proves the fast-path returns byte-identical replies to
the network path; benchmark shows ~545µs -> ~28µs (~20x) and ~3.6x fewer
allocations. Off by default. Covers #4817 (path b); the zero-copy typed
path remains a follow-up.
Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL
Co-authored-by: Claude <noreply@anthropic.com>