description: "The shared Typert Remote protocol: decorators, wire descriptors, codecs, and provider contracts used by business packages, generated artifacts, the Host Gateway, and the Client API."
English | 中文
With dsh-typert-protocol, business packages can expose Host methods to Remote clients: mark a method with @Remote (or @RemoteScope for scoped receivers), bind the service to a wire namespace, and associate Host objects and scoped Contexts with wire identities through the merge-extensible protocol maps. Generated artifacts, the Host Gateway, and the Client API consume the same invocation descriptors, codecs, and provider contracts, so one declaration set stays in sync across every face. The package registers no Cordis service and runs no TypeScript analysis; it declares types and decorator markers only.
This package is for business-package and assembly maintainers who expose Host capabilities to Remote clients. It is a declarations library: mark methods, bind services, and let the generated pipeline and the Gateway do the rest.
A business package marks a public instance method with @Remote (or @RemoteScope(key) when the receiver comes from a scoped Context), and the owning service either extends TypertRemoteService or declares a typertRemote binding through bindTypertRemote():
import { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'
export class GoalService extends TypertRemoteService {
@Remote
async create(agentId: string, objective: string): Promise<GoalResult> {
...
}
}
Generation turns the method into a wire endpoint under the service's namespace; Clients call it as a typed method through ctx.remote (see the API Gateway reference). A method opts into cooperative cancellation by declaring signal: AbortSignal as its final parameter — the signal is injected, never a JSON parameter or lookup field.
Complex Host objects cannot cross the wire directly. A business package declares the association through the merge-extensible TypertLookupMap and TypertContextMap. Host and Client Context adapters both map Context to a wire identity and that identity back to Context; the Host adapter also owns the stable wire declaration. Host composition may override its synchronous or asynchronous resolver. A resolver that refuses on policy grounds throws RemoteError with its own code, which reaches the caller unchanged.
One class carries every Remote failure: RemoteError, holding a stable <domain>/<reason> code and the details typed for that code. This package declares the universal carrier codes (gateway/bad-request, gateway/cancelled, gateway/internal) and owns RemoteErrorDetailsMap, the merge-extensible table every other package extends beside its own throwing code:
declare module '@deepseek-ai/dsh-typert-protocol' {
interface RemoteErrorDetailsMap {
'goal/not-found': { readonly goalId: string }
}
}
throw new RemoteError('goal/not-found', `goal "${id}" does not exist`, { goalId: id })
An owner throws at the failure point; no package writes an error-class family or an exit-mapping function. A caller discriminates by code — never by instanceof — and a code branch narrows details with no cast, because RemoteFailure is the code-discriminated union of RemoteError instances. Infrastructure that must recognize a failure carried across a module or realm copy of the class calls remoteErrorOf(value), which reads a structural marker instead of the prototype chain.
The Host assembly extends TypertRemoteEventSelection with the Cordis events it forwards to consumers, which narrows the ctx.remote.$on key set. TypertForwardableEvent accepts unscoped void notifications and scoped async waterfalls whose final next() callback returns the event's result type. TypertClientEventListener derives the Client listener from that same Events member while preserving signals, optional and readonly fields, arrays, callbacks, and result types. TypertClientRemote exposes only $mount() and $on(); event transport remains private to Gateway.
Read these pages when the package-level contract is not enough; they move from the declarations to the runtime and the call path.
None, as compiler-independent Remote protocol declarations register nothing model-facing.
No direct effect; the declared contracts reach a request only when an assembly places them in one.
These limits define what the declarations can represent; they are current package constraints, not a task backlog.