DSH plugin Typert RPC: lookup, descriptor and gateway
Typert remote calls are not “JSON-ify a method name and arguments”; they are a three-layer type contract: declarations decide which host objects are addressable, descriptors decide how parameters and results are encoded, and the Gateway decides who may call and which resources they may touch. Mixing the layers produces “works locally, fails remotely with lookup unavailable” or “a cancellation signal in args breaks the codec”.
DeepSeek Harness: Declarations: which objects are addressable
Remote calls cannot pass object references; every object needs a wire identity, and LookupMap and ContextMap are that declaration. Two maps:(source)
TypertLookupMap— associates a host object type with a wire identity. Expected: a parameter is recognized as a lookup, not an ordinary object.TypertContextMap— associates a scoped context category with a wire identity. Expected: a method can select a context receiver.- Declaration merging — business object packages extend the empty maps, and generated descriptors reference the keys. Expected: host and client builds see the same declaration.
After a lookup resolver unloads, the registry keeps the wire declaration. SRC discovery still classifies the parameter as a lookup and fails because it is unavailable; it never accepts the wire value as an ordinary object. That is “fail rather than mis-accept”.
DeepSeek Harness: Descriptors: how arguments and results are encoded
InvocationDescriptor is local reflection, not a wire message; requests send only the endpoint and named args. Key fields:(source)
| Field | Purpose |
|---|---|
service / namespace / method | locate the method |
parameters | ordered business parameters with wire names and codecs |
invocation | direct or context receiver |
scope | optional context projection |
uplink | codec for client-to-host stream items |
cancellation | reserved out-of-band signal parameter |
result | codec for the unary result or each stream item |
Strict codecs carry a generated schema factory; SRC codecs only require JSON-safe input and do not restore structural types. A unary result codec can provide encode() for byte-bearing subtrees and decode() to validate native bytes; pure JSON results need no byte handling.
Cancellation is an out-of-band carrier signal injected after business parameters, never in args. Do not put signal into the descriptor’s parameter list as a normal input.
DeepSeek Harness: Calls: methods, streams, and cancellation
createTypertRemoteInfo returns a lazy class instance; the method index references descriptors, and callers get a remote method with input/invoke rather than a raw function. Three capabilities:(source)
- Unary call — mode omitted;
invokesends one request and returns the result. Expected: parameters encode by descriptor. - Stream call —
mode: 'stream'; the host returnsRemoteStream<Out, In>. Expected: the client gets aRemoteStreamHandlewithsend,end, anddispose. - Context receiver — a method that only uses a context receiver stays in the descriptor and scope declarations. Expected: no extra business parameter.
method.input(options?) accepts only strict?: boolean and returns a cached TypertRemoteValue; it does not change host dispatch or result. Reading metadata or schema never initiates a network call.
DeepSeek Harness: A minimal declaration example
Declare the lookup first and let generated descriptors reference it; do not hand-write wire fields. Structure:(source)
declare module '@deepseek-ai/dsh-typert-protocol' {
interface TypertLookupMap {
'my-service/session': Session
}
}
The generator emits a TypertLookupDefinition with key, parameter, wire, and host/wire type symbols; a runtime provider resolves the wire value back to a live object. The method exposes only named args, and cancellation is injected after business parameters.
If the lookup resolver unloads, the registry keeps the wire declaration and later calls fail as unavailable instead of accepting the wire value as a normal object.
DeepSeek Harness: Permissions and resources
Typert access control lives in the Gateway and resource policy, not inside the method. Key points:(source)
- Principal is fixed —
PeerScopefixes the principal at creation in host code; no wire field can set it. Expected: a caller cannot claim another identity. - Resource declaration —
@Remote({ resources })or@RemoteScope(key, { resources })reads resource identity; then lookup parameters or scope Context, then defaults intypert.resources. - Global resource — a call that touches no resource uses the built-in
global. Expected: identity-less resources still need policy. - Only non-owner calls are checked — a policy must bind a role on every resource.
If the method can modify data, declare resource kinds before discussing roles; otherwise the Gateway can only treat it as global.
DeepSeek Harness: Three integration forms
Direct unary methods, context receivers, and remote streams increase in complexity. Three:(source)
- Direct unary method — simplest, good for CRUD and queries. Expected: arguments and results are JSON or declared lookups.
- Context receiver — for methods that need a scoped context. Expected: the receiver derives from Context, not business parameters.
- Remote stream — for continuous push or bidirectional traffic. Expected: the client holds the handle and is responsible for
endordispose.
A stream handle that is neither iterated nor disposed keeps the host stream alive. When the carrier disconnects, iteration fails and the handle ends.
Choosing a codec
Pure JSON, byte-bearing subtrees, and strict structure need different codecs. Three:
- Pure JSON — no byte handling or client decode; use a normal codec. Expected: arguments and results are lossless JSON.
- Byte-bearing subtree — a unary result uses
encode()to project bytes into attachments anddecode()to validate native bytes. Expected:Uint8Arraydoes not degrade into a plain object. - Strict structure — a strict codec carries the generated schema factory. Expected: the receiver validates the declared structure.
SRC codecs only enforce JSON-safe input and do not restore structural types; do not rely on SRC alone when you need type guarantees.
DeepSeek Harness FAQ
Why does a call work locally but fail remotely with lookup unavailable? Remote calls find objects by wire identity. If the resolver is unloaded or unregistered, SRC refuses to treat the wire value as an ordinary object. Confirm both the declaration and the runtime resolver.
Can I pass a Uint8Array directly as a parameter?
Only with codec support for byte subtrees. Unary results can use encode()/decode(); do not assume bytes survive with pure JSON.
Does the uplink enter the parameter list for a stream?
No. The uplink is read through RemoteInvocation.uplink(), and the descriptor declares its codec separately.
The short version: Typert works when declaration, description, and authorization each hold; putting cancellation or object references into args breaks one of them.
FAQ
DeepSeek Harness: lookupMap associates a host object type with a wire identity so a remote call can find the live object by identity. ContextMap associates a scoped context category with a wire identity so a call can select a receiver context. Both are extended by declaration merging.
DeepSeek Harness: no. InvocationDescriptor is local reflection information. Host and consumer builds generate corresponding descriptors, but the request sends only the endpoint and named args, not the descriptor itself.
DeepSeek Harness: cancellation is an out-of-band carrier signal injected after the business parameters; it never enters args. Business arguments stay clean, and cancellation is not mistaken for a normal input.
DeepSeek Harness: the registry keeps the wire declaration. SRC discovery still classifies that parameter as a lookup and fails because it is unavailable, rather than accepting the wire value as an ordinary object.
DeepSeek Harness: in dsh-api-remote-access. A non-owner call is allowed only when the principal kind’s policy binds a role containing the endpoint action on every accessed resource. The Gateway reads resource identity from @Remote resources or the default typert.resources.
Related Terms
- TypertLookupMap
- TypertLookupMap is a merge-extensible map associating a host object type with its wire identity. Generated descriptors reference these keys, and a runtime provider resolves the live object.— DeepSeek Harness reference - Typert remote calls
- InvocationDescriptor
- InvocationDescriptor is the local reflection description of one exported method call, including id, service, method, parameters, codecs, result codec, and optional uplink or cancellation. It is not a wire message.— DeepSeek Harness reference - Typert remote calls
- RemoteStream
- RemoteStream is one remote stream on the host side. The host iterates it as AsyncIterable<Out>, while In marks the client-to-host uplink type; the client receives a RemoteStreamHandle.— DeepSeek Harness reference - Typert remote calls
- PeerScope
- PeerScope is one peer’s session on a host, containing id, connection-lifetime context, fixed principal, cancellation signal, and interaction capability. Remote streams end with the peer.— DeepSeek Harness reference - Typert remote calls
Sources
- DeepSeek Harness reference - Typert remote calls· deepseek-ai
- DeepSeek Harness reference - API Gateway· deepseek-ai