Package: dappco.re/go/inference/model/state
File: go/model/state/identity.go
Aliased into: dappco.re/go/inference (via identity.go —
inference.ModelIdentity etc. are aliases of these types)
Six DTOs that travel with every durable artefact in the system:
| Type | What it identifies |
|---|---|
ModelIdentity |
which model produced/expects this — hash, arch, quant, ctx-len |
TokenizerIdentity |
which tokenizer + chat template — BOS/EOS/PAD ids, template hash |
AdapterIdentity |
which LoRA/adapter is active — hash, rank, alpha, target keys, base-model hash |
RuntimeIdentity |
which runtime/device produced it — backend name, device, version, cache mode |
SamplerConfig |
reproducible sampling — temp, top-k, top-p, repeat penalty, stop tokens |
StateRef |
typed reference to one external blob — kind, URI, hash, size, encoding |
Plus the envelope:
| Type | Role |
|---|---|
Bundle (StateBundle alias) |
the full state envelope a sleep emits — model + tokenizer + adapter + sampler + runtime + prompt hash + KV refs + probe refs + State refs + labels |
Agent memory is about lifecycle (Wake/Sleep/Fork). Identity is about compatibility checking at lifecycle boundaries:
- A wake refuses to restore a Gemma-3 bundle into a Gemma-4 session (model arch differs).
- A wake refuses to restore an adapter-on bundle into an adapter-off
session (
AdapterIdentity.Hashdiffers). - A wake records which runtime produced the bundle so audit can trace
divergent results back to "this bundle came from
engine/hipvsengine/metal".
Bundle.KVRefs / ProbeRefs / StateRefs are arrays of StateRef
because one bundle commonly fans out to multiple blobs — KV blocks are
chunked, probes are per-layer, State frames are sequenced.
The hash is what WakeRequest.SkipCompatibilityCheck flips off. By
default a wake compares req.Model.Hash to bundle.Model.Hash and
rejects on mismatch — even if the architecture matches, a quantisation
re-pack or weight delta produces a different hash and would silently
corrupt KV.
Hash format is backend-defined (typically SHA-256 of safetensor index file + adapter file), but the contract is "same hash → same weights → KV is valid".
The state package keeps the portable SamplerConfig shape. The
inference parent package converts to/from its richer
GenerateConfig (which includes GenerateOption plumbing) via two
free functions in inference/identity.go:
inference.SamplerConfigFromGenerateConfig(cfg) → SamplerConfig
inference.GenerateConfigFromSamplerConfig(cfg) → GenerateConfigThis is deliberate — the bundle stores the outcome of the option choices, not the option-function chain.
model/state/agent_memory.go—RefcarriesStateRefs []StateRefmodel/state/store.go— chunk metadatamodel/state/session/— bundle encode/decode; snapshot/restore stores Bundle alongside KV blocksagent/— eval reports embedModelIdentity+AdapterIdentityfor reproducibilityeval/benchmark surface — bench reports carryRuntimeIdentity