Skip to content
2 min read · 327 words

@nhtio/adk/batteries/encoding

Opt-in serialization battery: make the ADK primitives round-trip through @nhtio/encoder.

Remarks

The ADK primitives already carry the @nhtio/encoder custom-class contract — they implement the Symbol.for('@nhtio/encoder:toEncoded' | ':fromEncoded') methods with zero dependency on the encoder. That half works whether or not @nhtio/encoder is installed. This battery wires up the other half — the part that genuinely needs the encoder — and nothing else imports it:

  1. registerAdkEncodables() — tells the decoder how to map each custom:<ClassName> wire tag back to its constructor. Call it once, before your first decode(). Without it, encode() still works but decode() throws on every ADK primitive.
  2. Auto-registers the in-memory and fetch reader resolvers (they carry no live binding, so they need nothing from you). Durable-store resolvers — flydrive Disk, OPFS root — you register yourself with registerSpoolReaderResolver / registerMediaReaderResolver, because only you hold the live binding the serialised locator cannot carry.

::: what this battery does NOT do It serialises the conversation graph, not your storage. It does not persist anything — it turns a live object tree into a string and back. It does not conjure live bindings: a reader handle decodes to a working reader only if you registered a resolver for its tag. It does not make closures portable: a @nhtio/adk!Tool handler serialises by source text only (see @nhtio/adk!Tool). And it cannot serialise a @nhtio/adk!TurnGate — a live pending Promise has no serialised form. :::

Examples

Register once at startup, then encode/decode freely.

typescript
import { encode, decode } from "@nhtio/encoder";
import { registerAdkEncodables } from "@nhtio/adk/batteries/encoding";

registerAdkEncodables();

const wire = encode(message); // a Message with nested Identity / Tokenizable / Media
const restored = decode<Message>(wire); // instanceof Message, nested primitives intact

Durable-store media/artifacts need a resolver carrying the live binding.

typescript
import { Disk } from "flydrive";
import { FlydriveSpoolReader } from "@nhtio/adk/batteries/storage/flydrive";
import {
  registerAdkEncodables,
  registerSpoolReaderResolver,
} from "@nhtio/adk/batteries/encoding";

registerAdkEncodables();
const disk = new Disk(myDriver);
registerSpoolReaderResolver("spool:flydrive", (locator) => {
  const { key, streamThresholdBytes } = locator as {
    key: string;
    streamThresholdBytes?: number;
  };
  return new FlydriveSpoolReader(disk, key, { streamThresholdBytes });
});

Functions

FunctionDescription
registerAdkEncodablesRegister every ADK primitive with the @nhtio/encoder decoder, and auto-register the binding-free reader resolvers (in-memory, fetch).

References

LocatorValue

Re-exports LocatorValue


MediaReaderResolver

Re-exports MediaReaderResolver


ReaderDescriptor

Re-exports ReaderDescriptor


registerMediaReaderResolver

Re-exports registerMediaReaderResolver


registerSpoolReaderResolver

Re-exports registerSpoolReaderResolver


resolveMediaReader

Re-exports resolveMediaReader


resolveSpoolReader

Re-exports resolveSpoolReader


SpoolReaderResolver

Re-exports SpoolReaderResolver