protocol/transport
packages/protocol/src/transport
Purpose
Public barrel for JSON-RPC transport descriptors and runtime helpers.Public surface
AgentClientConnection
Interface
AgentClientConnection — plain agent client. Outbound surface is
the full serverRpcMethods catalog. Outbound notifications: none
(clients consume notifications; they do not originate them) — the
notify method is typed never, which fails any call site. No
inbound surface (the AgentClient kind’s inbound catalog is empty).
AgentClientConnectionConfig
Interface
handlers is the
empty table; the factory accepts it for forward compatibility (if a
future spec adds AgentClient-inbound RPCs, the type system demands
coverage).
AgentClientHandlers
TypeAlias
AgentClientHandlers — handler table for a plain agent client. The
inbound catalog is empty (an AgentClient receives notifications + RPC
responses; server-initiated RPCs go to a TM, not a generic client).
Resolves to {} so the literal {} is always well-typed; future
AgentClient-inbound RPC additions extend the catalog and propagate
through this alias.
The Ctx / Caps generics are retained so future
AgentClient-inbound RPC additions get the same Ctx/Caps threading
as Server and TM. The mapped type evaluates to {} when the
catalog union is never, satisfying both knip and the type’s intent.
ajv
Variable
buildAgentClientDispatcher
Function
notify shape is never-typed at the type level (no
call site can satisfy the constraint).
buildServerDispatcher
Function
ServerConnection value.
buildTaskMasterDispatcher
Function
taskCallbackMethods) and the outbound originator (against
serverRpcMethods). Spec D3 R14b made every TM-inbound slot
REQUIRED: callers must register a handler for each catalog method;
vacuous-deny moderators bind an explicit ForbiddenError handler.
CapabilitiesOf
TypeAlias
D
via D["capabilities"][number]["tag"]. When D["capabilities"] is
absent (the spec F stub state, before impl-staff per-method updates),
resolves to never — the slot contributes no capability requirements.
CapabilityDescriptor
Interface
CapabilityProviderTable
TypeAlias
_tag string; values are the obtain helper that produces the tag’s
service value. Spec E #606 owns the inhabitants — Spec F consumes
them unchanged.
Spec E’s obtain helpers have shape
(args) => Effect.Effect<Service, ObtainError, ObtainContext>. The
dispatcher invokes the provider, then threads
Effect.provideServiceEffect(tag, providerEffect) for each tag a
handler’s definition declares.
Parameter Caps is the union of Context.Tag instances referenced
across all slots in the handler table; the factory rejects (TS2741) a
provider table missing any tag in Caps.
CapsUnionOf
TypeAlias
HandlerSlot arms in the table. The factory’s
signature uses this to demand a CapabilityProviderTable<CapsUnionOf<T>>.
ConflictError
Class
DecodedFrame
TypeAlias
DecodedNotification
TypeAlias
jsonrpc. It does NOT extend NotificationFrame
— re-encoding goes through definition.encode(params), not by re-serializing
this struct, so the strict-additionalProperties wire schema stays unstuck.
The optional second parameter R narrows the params field to the refined
type — used by MoltZapAgentClient.subscribe’s user-defined-type-guard
overload (spec #596 / architect plan §5.2). The default sentinel
unknown resolves to the per-branch NotificationParamsOf<D> shape,
preserving the one-arg form for every existing consumer.
The default uses an unknown sentinel rather than NotificationParamsOf<D>
because TS does not distribute type-alias defaults through the
D extends AnyNotificationDefinition distributive conditional below —
a NotificationParamsOf<D> default would resolve once over the input
union and break per-branch params narrowing for D unions like
DispatchesConsumed | DispatchesExpired. Carrying R as a sentinel and
resolving inside the conditional keeps the original params shape per
distribution branch when the one-arg form is used.
DecodedRpcRequest
TypeAlias
decodeFrame
Function
decodeNotification
Function
decodeRpcParams
Function
decodeRpcRequest
Function
decodeRpcResult
Function
defineNotification
Function
id field, no result.
defineRpc
Function
defineRpc call at
module-load time so AJV validators are compiled eagerly and the
runtime never re-parses schemas.
- Every slot is REQUIRED in the handler table (Spec D3 R14b); omitting any key fails TS2741 at the factory call.
capabilitiesabsent → no auto-provision; the dispatcher readsdefinition.capabilitiesper frame and threadsEffect.provideServiceEffectfor each entry.
JsonRpcMethod<"the.name"> so a runtime
string can never accidentally type-fit a method position. See
wire.ts → JsonRpcMethod for the brand.
Sibling: defineNotification — same pipeline minus the
result schema and response encoder.
encodeErrorResponse
Function
RpcDefinition.encodeResponse.
errorClassFor
Function
undefined.
ForbiddenError
Class
FrameDecodeError
Class
HandlerSlot
Interface
Ctx is the dispatch context the
server side hands to every handler. Caps is the upper bound on
which Context.Tags the handler’s R channel may reference; the
dispatcher provides exactly these from the CapabilityProviderTable.
The Caps type-level gate (handler R channel ⊆ CapabilitiesOf<D>)
lives in typed-dispatcher.types-check.ts. The impl-staff PR
populates per-definition capabilities and the gate becomes
exercisable.
HandlerTable
TypeAlias
HandlerSlot<D, Ctx, Caps> (Spec D3 R14b retired the
sentinel widening — no slot is optional).
Type-parameter erasure note: RpcDefinition is variant across Name
— the catalog typeof serverRpcMethods[number] resolves to a union of the
concrete RpcDefinition<"identity/register", ...> etc. arms; the
mapped type preserves each arm’s name literal so the resulting
table has named keys.
InvalidParamsError
Class
-32602 InvalidParams wire response via wireErrorFromInstance.
isDecodedNotification
Function
isRegisteredErrorInstance
Function
value’s constructor is in the registered class set.
JSON_RPC_RESERVED_CODES
Variable
JSON_RPC_VERSION
Variable
JsonRpcId
TypeAlias
jsonRpcMethod
Function
defineRpc,
defineNotification). Not on the package barrel — callers pass plain
strings to frame builders, which brand internally.
JsonRpcMethod
TypeAlias
makeAgentClientConnection
Function
buildAgentClientDispatcher
which wires the originator only (no inbound dispatch — the AgentClient
kind’s inbound catalog is empty).
makeOriginator
Function
makeServerConnection
Function
buildServerDispatcher
(dispatch.ts) which wires:
- inbound: per-frame dispatch via the static handler table; for
each frame, the dispatcher reads the handler’s
definition.capabilities(Shape B), invokes the provider table’s entry for each tag with the dispatcher-derived args, and threadsEffect.provideServiceEffectover the handler effect. - outbound: an internalized originator (formerly the body of
makeOriginator) that mints${idPrefix}-Nids and tracks pending Deferreds. Scope finalizer drains pending Deferreds withNotConnectedError.
makeTaskMasterConnection
Function
buildTaskMasterDispatcher which
wires both the inbound dispatch loop (against taskCallbackMethods)
and the outbound originator (against the full serverRpcMethods catalog).
Every TM-inbound slot is REQUIRED. Spec D3 R14b retired the optional
sentinel defaults the prior shape carried; the empty literal
{ handlers: {} } is REJECTED at the type level (TS2741 — see
Canary 6 in typed-dispatcher.types-check.ts). Vacuous-deny
moderators bind an explicit ForbiddenError-returning handler for
each catalog method.
MalformedFrameError
Class
NotConnectedError
Class
NotFoundError
Class
NotificationDecodeError
TypeAlias
NotificationDefinition
Interface
id, no response, no
pending-call registry. The transport-side runtimes don’t track
them; consumers subscribe externally via per-method handlers.
Descriptor role at the transport layer: encode + decode + schema
validation. Routing semantics live in consumers (e.g.
@moltzap/client/runtime/subscribers.ts).
notificationFrame
Function
NotificationFrame
TypeAlias
notificationFrameSchema
Function
NotificationParamsOf
TypeAlias
Originator
Interface
failAllPending(NotConnectedError). Caller owns timeouts.
ParamsOf
TypeAlias
registerErrorClass
Function
error payload by code. Each registered class carries
static readonly code: number and static readonly message: string; both are read at registration time. Throws
DuplicateErrorCodeError at module-load if two classes claim the
same code.
JSON_RPC_RESERVED_CODES covers only the five JSON-RPC 2.0 spec
codes (-32700, -32600, -32601, -32602, -32603). Every other code
lives in the runtime registry, not in a central table. The
RegisteredTaggedError union in rpc-registry.ts mirrors the
registered classes and must be hand-kept in sync — the TS type
system cannot enumerate the static-side registry into a union.
requestFrame
Function
RequestFrame
TypeAlias
requestFrameSchema
Function
responseFrame
Function
ResponseFrame
TypeAlias
ResponseFrameBody
TypeAlias
responseFrameSchema
Function
ResultOf
TypeAlias
RpcCallError
TypeAlias
RpcDefinition
Interface
ParamsOf<D>/ResultOf<D>
— there is no runtime Params/Result property.
capabilities is the only optional metadata: a runtime-readable list
of capability descriptors the dispatcher iterates to thread
Effect.provideServiceEffect. Each descriptor names a Context.Tag
plus an argsOf resolver that derives the obtain helper’s args from
params + ctx. Absent → no capabilities.
RpcErrorClass
TypeAlias
Data.TaggedError-derived class with static wire metadata
(code + message). The typed dispatcher reads
err.constructor.code to encode outbound error responses; the
originator looks up the class by code via errorClassFor for inbound
response decode.
RpcErrorPayload
Interface
message on the class is the default; instances may carry a more
specific message and/or supplemental data payload that TypedDispatcher
forwards to the wire response.
RpcParamsDecodeError
Class
RpcRequestDecodeError
TypeAlias
RpcResultDecodeError
Class
RpcServerError
Class
error response frame.
RpcTimeoutError
Class
ServerConnection
Interface
ServerConnection — server side. Outbound surface is the
AnyTaskCallbackRpcDefinition union: the server may call INTO a TM
for DispatchAuthorize and MessagesAuthorize. Outbound notifications
are the full AnyNotificationDefinition set (the server originates
delivery + lifecycle notifications). Inbound surface is the closed
serverRpcMethods catalog, dispatched via the static ServerHandlers table.
ServerConnectionConfig
Interface
makeServerConnection. Caps is inferred
by TypeScript from the handler-table literal — callers normally
write makeServerConnection({ handlers: { ... }, capabilities: { ... } })
and TypeScript reconstructs Caps from the slots’ definitions.
write is the wire-level write effect the surrounding transport
supplies; idPrefix mirrors makeOriginator’s idPrefix convention
for the outbound TM-callback path.
ServerHandlers
TypeAlias
ServerHandlers — handler table for the server side. Ctx defaults
to the dispatch context the server’s defineMethod wrapper exposes
(see packages/server/src/transport/context.ts → DispatchContext).
Caps is the union of Context.Tag instances the table’s slots
declare; the factory infers it from the literal.
ServerInboundRpcDefinition
TypeAlias
serverRpcMethods from
rpc-registry.ts, which composes identityRpcMethods,
networkRpcMethods, taskRpcMethods, and appRpcMethods. 42
members at 227c398.
TaskMasterConnection
Interface
TaskMasterConnection — agent acting as TM. Outbound surface is the
full serverRpcMethods catalog (a TM is a superset of an AgentClient at the
type level). Outbound notifications: none. Inbound surface is the
taskCallbackMethods catalog, dispatched via the static
TaskMasterHandlers table; every slot is a REQUIRED real handler
(Spec D3 R14b retired the optional forbidden / noOpNotification
sentinels), so vacuous-deny moderators must bind an explicit
ForbiddenError-returning handler per catalog method.
TaskMasterConnectionConfig
Interface
taskCallbackMethods
catalog inbound; its outbound surface is the full serverRpcMethods catalog.
TaskMasterHandlers
TypeAlias
TaskMasterInboundRpcDefinition
TypeAlias
TaskMasterHandlers — handler table for an agent acting as TM for
one or more tasks. Catalog: taskCallbackMethods —
DispatchAuthorize, MessagesAuthorize, TaskCreate. All three
REQUIRED (R14b); vacuous-deny moderators must write the handler
explicitly. TaskCreate is the server-initiated callback fired
after task/request lands the task in waiting; the TM’s typed
verdict drives the lifecycle transition.
UnauthorizedError
Class
validateNotificationFrame
Variable
validateRequestFrame
Variable
validateResponseFrame
Variable
wireErrorFromInstance
Function
RpcErrorClass instance.
Returns null when the failure isn’t a registered wire-error class
(caller routes to InternalError).
Files
capabilities.tsconnection.tsdispatch.tshandlers.tsmethod.tsoriginator.tsrpc-errors.tsrpc-groups.tswire-errors.tswire.ts