diff --git a/.scratch/distributed-gguf-runtime/evidence/DGR-006/README.md b/.scratch/distributed-gguf-runtime/evidence/DGR-006/README.md new file mode 100644 index 0000000..4e8acfb --- /dev/null +++ b/.scratch/distributed-gguf-runtime/evidence/DGR-006/README.md @@ -0,0 +1,71 @@ +# DGR-006 — architecture-defined boundary input/output + +Status: complete deterministic/offline contract and dense-fixture evidence. + +## Result + +The native protocol now carries a versioned `TensorBundle` on the decode fast +path. It includes explicit architecture and boundary-point metadata. Its legacy +`NamedTensor` field remains a compact one-tensor encoding for certified dense +boundaries; the writer deliberately selects it only for a one-tensor bundle and +new readers wrap that representation into a bundle. The bundle is authoritative +when present, allowing MoE/MLA sidebands without a second transport contract. + +`architecture_boundary.py` is the fail-closed adapter boundary. Dense head +Shards accept token IDs and own embedding. Middle/tail Shards accept only a +validated bundle. Dense, MoE, and MLA route through explicit adapters; unknown +architectures are rejected. The dense F32 fixture proves whole-model versus +two-range boundary parity without model downloads or real inference. + +Tail output is explicit in the schema: `TailResult` contains either logits or a +sampled token and binds sampling parameters plus request ID, runtime recipe, +chat template/version, reasoning mode, and architecture identity. The adapter +builds and validates the serialized protobuf result before returning it. + +## Files changed + +- `packages/node/native/proto/shard_runtime.proto` +- `packages/node/meshnet_node/native_protocol/{codec.py,__init__.py,conformance.py,generated/*}` +- `packages/node/native/testdata/decode_step_golden.binpb` +- `packages/node/native/tests/test_shard_protocol_conformance.cpp` +- `packages/node/meshnet_node/architecture_boundary.py` +- `tests/test_architecture_boundary.py` +- `tests/test_native_shard_protocol.py` +- `packages/node/native/README.md` + +## Commands and results + +All Python commands used `/run/media/popov/d/DEV/repos/d-popov.com/AI/.venv/bin/python`. +All native commands used `/run/media/popov/d/DEV/repos/d-popov.com/AI/.venv/bin/cmake`. + +```text +python scripts/generate_native_protocol.py --check -> passed +python scripts/generate_protocol_goldens.py --check -> passed +pytest -q tests/test_architecture_boundary.py \ + tests/test_native_shard_protocol.py tests/test_llama_cpp_dependency.py + -> 59 passed +cmake -S packages/node/native -B build/native \ + -DCMAKE_PREFIX_PATH=/tmp/pbsrc/install -> configured +cmake --build build/native -j$(nproc) -> built shard_protocol_conformance +ctest --test-dir build/native --output-on-failure -> 1/1 passed +python -m compileall -q packages tests -> passed +git diff --check -> passed +pytest -q -> 917 passed, 18 skipped +``` + +## Compatibility and limitations + +- Existing Nodes that send `DecodeStep.tensor` are accepted. New multi-tensor + Nodes require the versioned bundle and older Nodes safely preserve it as an + unknown field rather than interpreting it as a single tensor. +- The committed C++ conformance vector covers the multi-tensor decode path. +- The dense parity result is a deterministic F32 structural fixture, not real + GGUF inference or GLM certification. No real inference was run. +- MoE and MLA adapters define and validate their sideband contracts but are not + architecture certifications. DGR-019 owns GLM MoE/MLA/DSA/IndexShare semantics. + +## Handoff + +DGR-007 can key its Hot KV state to the validated decoded bundle. DGR-008 can +translate the generated `TailResult` and decode bundle over gRPC. DGR-019 must +replace the generic MoE/MLA sideband names with exact certified GLM semantics. diff --git a/.scratch/distributed-gguf-runtime/issues/06-implement-architecture-defined-boundary-input-output.md b/.scratch/distributed-gguf-runtime/issues/06-implement-architecture-defined-boundary-input-output.md index 4d9bf9f..7ae4d62 100644 --- a/.scratch/distributed-gguf-runtime/issues/06-implement-architecture-defined-boundary-input-output.md +++ b/.scratch/distributed-gguf-runtime/issues/06-implement-architecture-defined-boundary-input-output.md @@ -1,6 +1,6 @@ # 06 — Implement architecture-defined boundary input/output -Status: ready-for-agent +Status: done ## Mandatory fresh-session context diff --git a/.scratch/distributed-gguf-runtime/prd.json b/.scratch/distributed-gguf-runtime/prd.json index 7622df9..b822fb1 100644 --- a/.scratch/distributed-gguf-runtime/prd.json +++ b/.scratch/distributed-gguf-runtime/prd.json @@ -177,7 +177,7 @@ "Update only this story issue to Status: done after every acceptance criterion and quality gate passes" ], "priority": 7, - "passes": false, + "passes": true, "notes": "Source issue: .scratch/distributed-gguf-runtime/issues/06-implement-architecture-defined-boundary-input-output.md", "dependsOn": [ "DGR-002", diff --git a/packages/node/meshnet_node/architecture_boundary.py b/packages/node/meshnet_node/architecture_boundary.py new file mode 100644 index 0000000..d0b6f68 --- /dev/null +++ b/packages/node/meshnet_node/architecture_boundary.py @@ -0,0 +1,138 @@ +"""Certified architecture adapters for the public TensorBundle boundary. + +The adapter is intentionally small: it owns boundary names and endpoint rules, +not transformer execution. llama.cpp owns local graphs; callers select a +certified adapter before accepting an activation from another Shard. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from enum import Enum +import struct +from typing import Callable, Mapping, Sequence + +from .native_protocol import HIDDEN_STATES, ProtocolError, encode_bundle, encode_tensor, pb + + +class Architecture(str, Enum): + DENSE = "dense" + MOE = "moe" + MLA = "mla" + + +class BoundaryStage(str, Enum): + HEAD = "head" + MIDDLE = "middle" + TAIL = "tail" + + +@dataclass(frozen=True) +class ProtocolIdentity: + request_id: str + runtime_recipe_digest: str + chat_template_id: str + chat_template_version: str + reasoning_mode: str + + +@dataclass(frozen=True) +class SamplingParameters: + temperature: float + top_p: float + top_k: int + seed: int + + +@dataclass(frozen=True) +class TailOutput: + kind: str + value: int | object + + @classmethod + def sampled_token(cls, token_id: int) -> "TailOutput": + if token_id < 0: + raise ProtocolError("sampled token id must be non-negative") + return cls("sampled_token", token_id) + + +@dataclass(frozen=True) +class TypedTailResult: + identity: ProtocolIdentity + sampling: SamplingParameters + output_kind: str + sampled_token_id: int | None = None + logits: object | None = None + + +@dataclass(frozen=True) +class ArchitectureBoundaryAdapter: + architecture: Architecture + required_names: frozenset[str] + + def bundle_from_token_ids( + self, + token_ids: Sequence[int], + token_embedding: Callable[[int], Sequence[float]], + ): + """Head-only embedding entry point; middle/tail never receive IDs.""" + if self.architecture is not Architecture.DENSE: + raise ProtocolError("head token embedding is not certified for this architecture") + if not token_ids: + raise ProtocolError("head requires at least one token id") + rows = [tuple(token_embedding(token)) for token in token_ids] + if not rows or not rows[0] or any(len(row) != len(rows[0]) for row in rows): + raise ProtocolError("token embedding returned inconsistent hidden widths") + payload = struct.pack("<" + "f" * (len(rows) * len(rows[0])), *(x for row in rows for x in row)) + return self.bundle_from_named_payloads({HIDDEN_STATES: payload}, shape=[1, len(rows), len(rows[0])]) + + def bundle_from_named_payloads( + self, payloads: Mapping[str, bytes], *, shape: Sequence[int] | None = None + ): + names = set(payloads) + if not self.required_names <= names: + missing = sorted(self.required_names - names) + raise ProtocolError(f"{self.architecture.value} boundary requires {missing}") + tensors = [] + for name, payload in payloads.items(): + tensor_shape = list(shape) if name == HIDDEN_STATES and shape else [len(payload) // 4] + if len(payload) % 4: + raise ProtocolError(f"{name!r} F32 fixture payload is not word aligned") + tensors.append(encode_tensor(name, payload, tensor_shape, pb.DTYPE_FLOAT32)) + return encode_bundle(tensors) + + def input_for(self, stage: BoundaryStage, bundle): + """Accept architecture state only after the head embedding boundary.""" + if stage is BoundaryStage.HEAD: + raise ProtocolError("head accepts token ids and owns token embedding") + if bundle is None: + raise ProtocolError(f"{stage.value} requires a TensorBundle") + from .native_protocol import decode_bundle + + payloads = decode_bundle(bundle) + if not self.required_names <= set(payloads): + raise ProtocolError(f"{self.architecture.value} boundary requires {sorted(self.required_names)}") + return bundle + + def tail_result( + self, *, identity: ProtocolIdentity, sampling: SamplingParameters, output: TailOutput + ) -> TypedTailResult: + if not identity.request_id or not identity.runtime_recipe_digest: + raise ProtocolError("tail result requires exact request and recipe identity") + if output.kind != "sampled_token": + raise ProtocolError("uncertified tail output kind") + return TypedTailResult(identity, sampling, output.kind, sampled_token_id=int(output.value)) + + +_ADAPTERS = { + Architecture.DENSE: ArchitectureBoundaryAdapter(Architecture.DENSE, frozenset({HIDDEN_STATES})), + Architecture.MOE: ArchitectureBoundaryAdapter(Architecture.MOE, frozenset({HIDDEN_STATES, "router_logits"})), + Architecture.MLA: ArchitectureBoundaryAdapter(Architecture.MLA, frozenset({HIDDEN_STATES, "mla_position_state"})), +} + + +def adapter_for(architecture: Architecture | str) -> ArchitectureBoundaryAdapter: + try: + return _ADAPTERS[Architecture(architecture)] + except (KeyError, ValueError): + raise ProtocolError(f"unsupported architecture {architecture!r}") from None diff --git a/packages/node/meshnet_node/native_protocol/__init__.py b/packages/node/meshnet_node/native_protocol/__init__.py index 16e00a0..d6b406b 100644 --- a/packages/node/meshnet_node/native_protocol/__init__.py +++ b/packages/node/meshnet_node/native_protocol/__init__.py @@ -31,6 +31,8 @@ from .codec import ( checksum_of, crc32c, decode_bundle, + decode_step_bundle, + encode_decode_step, decode_tensor, default_flow_control, encode_bundle, @@ -40,6 +42,7 @@ from .codec import ( negotiate_flow_control, plan_prefill_chunks, validate_session_message_size, + validate_tail_result, ) __all__ = [ @@ -60,6 +63,8 @@ __all__ = [ "checksum_of", "crc32c", "decode_bundle", + "decode_step_bundle", + "encode_decode_step", "decode_tensor", "default_flow_control", "encode_bundle", @@ -70,4 +75,5 @@ __all__ = [ "pb", "plan_prefill_chunks", "validate_session_message_size", + "validate_tail_result", ] diff --git a/packages/node/meshnet_node/native_protocol/codec.py b/packages/node/meshnet_node/native_protocol/codec.py index 80d6ad1..affac70 100644 --- a/packages/node/meshnet_node/native_protocol/codec.py +++ b/packages/node/meshnet_node/native_protocol/codec.py @@ -328,6 +328,8 @@ def decode_tensor( def encode_bundle( tensors: Iterable[pb.NamedTensor], *, + architecture: int = pb.ARCHITECTURE_TYPE_UNSPECIFIED, + boundary_point: str = "", max_chunk_bytes: int = DEFAULT_MAX_CHUNK_BYTES, max_tensors: int = DEFAULT_MAX_TENSORS_PER_BUNDLE, ) -> pb.TensorBundle: @@ -338,7 +340,12 @@ def encode_bundle( raise ProtocolError( f"bundle carries {len(tensor_list)} tensors, exceeding limit {max_tensors}" ) - bundle = pb.TensorBundle(bundle_version=BUNDLE_VERSION, tensors=tensor_list) + bundle = pb.TensorBundle( + bundle_version=BUNDLE_VERSION, + tensors=tensor_list, + architecture=architecture, + boundary_point=boundary_point, + ) if bundle.ByteSize() > max_chunk_bytes: raise ProtocolError( f"serialized tensor bundle exceeds the {max_chunk_bytes}-byte " @@ -392,6 +399,80 @@ def decode_bundle( return payloads +def encode_decode_step( + bundle: pb.TensorBundle, + *, + idempotency_step: int, + position: int, + expected_past_len: int, + work_id: str, + deadline_unix_nanos: int = 0, + prefer_compact_one_tensor: bool = True, +) -> pb.DecodeStep: + """Encode a decode boundary, retaining the deliberate compact fallback.""" + step = pb.DecodeStep( + idempotency_step=idempotency_step, + position=position, + expected_past_len=expected_past_len, + work_id=work_id, + deadline_unix_nanos=deadline_unix_nanos, + ) + if prefer_compact_one_tensor and len(bundle.tensors) == 1: + step.tensor.CopyFrom(bundle.tensors[0]) + else: + step.bundle.CopyFrom(bundle) + return step + + +def validate_tail_result(result: pb.TailResult) -> None: + """Fail closed unless a tail completion is bound to its exact recipe.""" + identity = result.identity + required = ( + identity.request_id, + identity.runtime_recipe_digest, + identity.chat_template_id, + identity.chat_template_version, + identity.reasoning_mode, + ) + if not all(required) or identity.architecture == pb.ARCHITECTURE_TYPE_UNSPECIFIED: + raise ProtocolError("tail result lacks exact request/recipe/template identity") + if result.WhichOneof("output") not in {"logits", "sampled_token_id"}: + raise ProtocolError("tail result lacks logits or sampled token output") + + +def decode_step_bundle( + step: pb.DecodeStep, + *, + max_chunk_bytes: int = DEFAULT_MAX_CHUNK_BYTES, + max_fragment_bytes: int = DEFAULT_MAX_FRAGMENT_BYTES, + max_fragments: int = DEFAULT_MAX_FRAGMENTS_PER_TENSOR, + max_tensors: int = DEFAULT_MAX_TENSORS_PER_BUNDLE, +) -> dict[str, bytes]: + """Decode a fast-path boundary with the DGR-006 compatibility rule. + + `bundle` is authoritative because it can carry architecture sidebands. The + old `tensor` field remains the compact representation for a certified + one-tensor boundary and is accepted by new readers during rollout. + """ + if step.HasField("bundle"): + return decode_bundle( + step.bundle, + max_chunk_bytes=max_chunk_bytes, + max_fragment_bytes=max_fragment_bytes, + max_fragments=max_fragments, + max_tensors=max_tensors, + ) + if step.HasField("tensor"): + return decode_bundle( + encode_bundle([step.tensor], max_chunk_bytes=max_chunk_bytes), + max_chunk_bytes=max_chunk_bytes, + max_fragment_bytes=max_fragment_bytes, + max_fragments=max_fragments, + max_tensors=max_tensors, + ) + raise ProtocolError("decode step carries neither TensorBundle nor legacy tensor") + + def validate_session_message_size( message: pb.SessionRequest | pb.SessionResponse, *, diff --git a/packages/node/meshnet_node/native_protocol/conformance.py b/packages/node/meshnet_node/native_protocol/conformance.py index a21ea33..a8c756d 100644 --- a/packages/node/meshnet_node/native_protocol/conformance.py +++ b/packages/node/meshnet_node/native_protocol/conformance.py @@ -27,6 +27,7 @@ TESTDATA_DIR = pathlib.Path(__file__).resolve().parents[2] / "native/testdata" GOLDEN_SESSION_REQUEST = "session_request_golden.binpb" GOLDEN_CAPABILITY_REPORT = "capability_report_golden.binpb" +GOLDEN_DECODE_STEP = "decode_step_golden.binpb" # Written by the C++ conformance test into its build tree; the Python test picks # it up when present to prove the two languages agree byte-for-byte. @@ -136,6 +137,30 @@ def canonical_capability_report() -> pb.CapabilityReport: ) +def canonical_decode_step() -> pb.SessionRequest: + """The DGR-006 multi-tensor decode boundary vector.""" + hidden = codec.encode_tensor( + codec.HIDDEN_STATES, bytes(range(16)), [1, 1, 4], pb.DTYPE_FLOAT32 + ) + index_topk = codec.encode_tensor( + "index_topk", (3).to_bytes(4, "little"), [1], pb.DTYPE_INT32 + ) + return pb.SessionRequest( + decode=pb.DecodeStep( + idempotency_step=43, + position=384, + expected_past_len=384, + work_id="decode-7f3a", + deadline_unix_nanos=DEADLINE_UNIX_NANOS, + bundle=codec.encode_bundle( + [hidden, index_topk], + architecture=pb.ARCHITECTURE_TYPE_MLA, + boundary_point="pre_tail_residual", + ), + ) + ) + + def serialize(message) -> bytes: """Serialize deterministically, so committed golden bytes are stable.""" return message.SerializeToString(deterministic=True) diff --git a/packages/node/meshnet_node/native_protocol/generated/shard_runtime_pb2.py b/packages/node/meshnet_node/native_protocol/generated/shard_runtime_pb2.py index a0ae708..1795f17 100644 --- a/packages/node/meshnet_node/native_protocol/generated/shard_runtime_pb2.py +++ b/packages/node/meshnet_node/native_protocol/generated/shard_runtime_pb2.py @@ -24,7 +24,7 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13shard_runtime.proto\x12\x10meshnet.shard.v1\"Q\n\x08\x43hecksum\x12\x36\n\talgorithm\x18\x01 \x01(\x0e\x32#.meshnet.shard.v1.ChecksumAlgorithm\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x7f\n\x0eTensorFragment\x12\x16\n\x0e\x66ragment_index\x18\x01 \x01(\r\x12\x16\n\x0e\x66ragment_count\x18\x02 \x01(\r\x12\x13\n\x0b\x62yte_offset\x18\x03 \x01(\x04\x12\x0f\n\x07payload\x18\x04 \x01(\x0cJ\x04\x08\x05\x10\x06R\x11uncompressed_size\"\xaf\x02\n\x0bNamedTensor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05shape\x18\x02 \x03(\x03\x12&\n\x05\x64type\x18\x03 \x01(\x0e\x32\x17.meshnet.shard.v1.DType\x12/\n\nbyte_order\x18\x04 \x01(\x0e\x32\x1b.meshnet.shard.v1.ByteOrder\x12\x13\n\x0btotal_bytes\x18\x05 \x01(\x04\x12\x32\n\x0b\x63ompression\x18\x06 \x01(\x0e\x32\x1d.meshnet.shard.v1.Compression\x12,\n\x08\x63hecksum\x18\x07 \x01(\x0b\x32\x1a.meshnet.shard.v1.Checksum\x12\x33\n\tfragments\x18\x08 \x03(\x0b\x32 .meshnet.shard.v1.TensorFragment\"V\n\x0cTensorBundle\x12\x16\n\x0e\x62undle_version\x18\x01 \x01(\r\x12.\n\x07tensors\x18\x02 \x03(\x0b\x32\x1d.meshnet.shard.v1.NamedTensor\"\x91\x01\n\x0b\x46ingerprint\x12\x1d\n\x15model_artifact_digest\x18\x01 \x01(\t\x12\x1d\n\x15runtime_recipe_digest\x18\x02 \x01(\t\x12\x11\n\trecipe_id\x18\x03 \x01(\t\x12\x16\n\x0erecipe_version\x18\x04 \x01(\t\x12\x19\n\x11\x63\x61talogue_version\x18\x05 \x01(\t\"S\n\nShardRange\x12\x13\n\x0bstart_layer\x18\x01 \x01(\r\x12\x11\n\tend_layer\x18\x02 \x01(\r\x12\x1d\n\x15\x65\x66\x66\x65\x63tive_start_layer\x18\x03 \x01(\r\";\n\x0cPositionSpan\x12\x16\n\x0e\x66irst_position\x18\x01 \x01(\x04\x12\x13\n\x0btoken_count\x18\x02 \x01(\r\"J\n\tChunkInfo\x12\x13\n\x0b\x63hunk_index\x18\x01 \x01(\r\x12\x13\n\x0b\x63hunk_count\x18\x02 \x01(\r\x12\x13\n\x0b\x66inal_chunk\x18\x03 \x01(\x08\"X\n\x10\x43\x61\x63heExpectation\x12)\n\x04mode\x18\x01 \x01(\x0e\x32\x1b.meshnet.shard.v1.CacheMode\x12\x19\n\x11\x65xpected_past_len\x18\x02 \x01(\x04\"]\n\x0b\x43\x61\x63heResult\x12)\n\x04mode\x18\x01 \x01(\x0e\x32\x1b.meshnet.shard.v1.CacheMode\x12\x10\n\x08past_len\x18\x02 \x01(\x04\x12\x11\n\tcache_hit\x18\x03 \x01(\x08\"\xe6\x03\n\x08\x45nvelope\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x0f\n\x07work_id\x18\x02 \x01(\t\x12\x18\n\x10route_session_id\x18\x03 \x01(\t\x12\x13\n\x0broute_epoch\x18\x04 \x01(\x04\x12\x32\n\x0b\x66ingerprint\x18\x05 \x01(\x0b\x32\x1d.meshnet.shard.v1.Fingerprint\x12\x31\n\x0bshard_range\x18\x06 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardRange\x12&\n\x05phase\x18\x07 \x01(\x0e\x32\x17.meshnet.shard.v1.Phase\x12\x30\n\x08position\x18\x08 \x01(\x0b\x32\x1e.meshnet.shard.v1.PositionSpan\x12\x18\n\x10idempotency_step\x18\t \x01(\x04\x12=\n\x11\x63\x61\x63he_expectation\x18\n \x01(\x0b\x32\".meshnet.shard.v1.CacheExpectation\x12\x1b\n\x13\x64\x65\x61\x64line_unix_nanos\x18\x0b \x01(\x03\x12*\n\x05\x63hunk\x18\x0c \x01(\x0b\x32\x1b.meshnet.shard.v1.ChunkInfo\"s\n\nShardError\x12)\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x1b.meshnet.shard.v1.ErrorCode\x12\x0e\n\x06\x64\x65tail\x18\x02 \x01(\t\x12\x11\n\tretryable\x18\x03 \x01(\x08\x12\x17\n\x0f\x61\x63tual_past_len\x18\x04 \x01(\x04\"~\n\x0b\x46lowControl\x12\x17\n\x0f\x63redits_granted\x18\x01 \x01(\r\x12\x1b\n\x13max_inflight_chunks\x18\x02 \x01(\r\x12\x17\n\x0fmax_chunk_bytes\x18\x03 \x01(\x04\x12 \n\x18max_prefill_chunk_tokens\x18\x04 \x01(\r\"\xd7\x02\n\x0bSessionOpen\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x13\n\x0broute_epoch\x18\x03 \x01(\x04\x12\x32\n\x0b\x66ingerprint\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.Fingerprint\x12\x31\n\x0bshard_range\x18\x05 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardRange\x12<\n\x15proposed_flow_control\x18\x06 \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControl\x12;\n\x14\x61\x63\x63\x65pted_compression\x18\x07 \x03(\x0e\x32\x1d.meshnet.shard.v1.Compression\"\x9f\x02\n\x0fSessionAccepted\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x13\n\x0broute_epoch\x18\x03 \x01(\x04\x12\x33\n\x0c\x66low_control\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControl\x12;\n\x14\x61\x63\x63\x65pted_compression\x18\x05 \x03(\x0e\x32\x1d.meshnet.shard.v1.Compression\x12\x32\n\x0b\x66ingerprint\x18\x06 \x01(\x0b\x32\x1d.meshnet.shard.v1.Fingerprint\"o\n\x0f\x41\x63tivationChunk\x12,\n\x08\x65nvelope\x18\x01 \x01(\x0b\x32\x1a.meshnet.shard.v1.Envelope\x12.\n\x06\x62undle\x18\x02 \x01(\x0b\x32\x1e.meshnet.shard.v1.TensorBundle\"\xb0\x01\n\nDecodeStep\x12\x18\n\x10idempotency_step\x18\x01 \x01(\x04\x12\x10\n\x08position\x18\x02 \x01(\x04\x12\x19\n\x11\x65xpected_past_len\x18\x03 \x01(\x04\x12-\n\x06tensor\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.NamedTensor\x12\x0f\n\x07work_id\x18\x05 \x01(\t\x12\x1b\n\x13\x64\x65\x61\x64line_unix_nanos\x18\x06 \x01(\x03\"O\n\rReleaseSignal\x12\x18\n\x10route_session_id\x18\x01 \x01(\t\x12\x13\n\x0broute_epoch\x18\x02 \x01(\x04\x12\x0f\n\x07work_id\x18\x03 \x01(\t\"^\n\x0c\x43\x61ncelSignal\x12\x18\n\x10route_session_id\x18\x01 \x01(\t\x12\x13\n\x0broute_epoch\x18\x02 \x01(\x04\x12\x0f\n\x07work_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\"\x91\x01\n\x03\x41\x63k\x12\x0f\n\x07work_id\x18\x01 \x01(\t\x12\x18\n\x10idempotency_step\x18\x02 \x01(\x04\x12\x33\n\x0c\x63\x61\x63he_result\x18\x03 \x01(\x0b\x32\x1d.meshnet.shard.v1.CacheResult\x12\x11\n\tduplicate\x18\x04 \x01(\x08\x12\x17\n\x0f\x65xecution_nanos\x18\x05 \x01(\x04\"\x91\x01\n\x0bShardStatus\x12\x0f\n\x07work_id\x18\x01 \x01(\t\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x18\n\x10idempotency_step\x18\x03 \x01(\x04\x12+\n\x05\x65rror\x18\x04 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardError\x12\x10\n\x08terminal\x18\x05 \x01(\x08\"\xc8\x02\n\x0eSessionRequest\x12-\n\x04open\x18\x01 \x01(\x0b\x32\x1d.meshnet.shard.v1.SessionOpenH\x00\x12\x32\n\x05\x63hunk\x18\x02 \x01(\x0b\x32!.meshnet.shard.v1.ActivationChunkH\x00\x12.\n\x06\x64\x65\x63ode\x18\x03 \x01(\x0b\x32\x1c.meshnet.shard.v1.DecodeStepH\x00\x12\x35\n\x0c\x66low_control\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControlH\x00\x12\x32\n\x07release\x18\x05 \x01(\x0b\x32\x1f.meshnet.shard.v1.ReleaseSignalH\x00\x12\x30\n\x06\x63\x61ncel\x18\x06 \x01(\x0b\x32\x1e.meshnet.shard.v1.CancelSignalH\x00\x42\x06\n\x04kind\"\x92\x02\n\x0fSessionResponse\x12\x35\n\x08\x61\x63\x63\x65pted\x18\x01 \x01(\x0b\x32!.meshnet.shard.v1.SessionAcceptedH\x00\x12\x32\n\x05\x63hunk\x18\x02 \x01(\x0b\x32!.meshnet.shard.v1.ActivationChunkH\x00\x12$\n\x03\x61\x63k\x18\x03 \x01(\x0b\x32\x15.meshnet.shard.v1.AckH\x00\x12\x35\n\x0c\x66low_control\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControlH\x00\x12/\n\x06status\x18\x05 \x01(\x0b\x32\x1d.meshnet.shard.v1.ShardStatusH\x00\x42\x06\n\x04kind\"L\n\x11\x43\x61pabilityRequest\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\"\x8a\x04\n\x10\x43\x61pabilityReport\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x32\n\x0b\x66ingerprint\x18\x02 \x01(\x0b\x32\x1d.meshnet.shard.v1.Fingerprint\x12\x31\n\x0bshard_range\x18\x03 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardRange\x12\x0f\n\x07\x62\x61\x63kend\x18\x04 \x01(\t\x12\x0e\n\x06\x64\x65vice\x18\x05 \x01(\t\x12\x11\n\tvalidated\x18\x06 \x01(\x08\x12\x0e\n\x06\x64\x65tail\x18\x07 \x01(\t\x12\x1f\n\x17max_concurrent_sessions\x18\x08 \x01(\x04\x12\x1a\n\x12max_context_tokens\x18\t \x01(\x04\x12\x33\n\x0c\x66low_control\x18\n \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControl\x12;\n\x14\x61\x63\x63\x65pted_compression\x18\x0b \x03(\x0e\x32\x1d.meshnet.shard.v1.Compression\x12\x42\n\x19supported_schema_versions\x18\x0c \x03(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x1f\n\x17validated_at_unix_nanos\x18\r \x01(\x03\"H\n\rHealthRequest\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\"\xfc\x01\n\x0cHealthReport\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12-\n\x05state\x18\x02 \x01(\x0e\x32\x1e.meshnet.shard.v1.ServingState\x12\x17\n\x0f\x61\x63tive_sessions\x18\x03 \x01(\r\x12\x15\n\rqueued_chunks\x18\x04 \x01(\r\x12\x17\n\x0f\x62\x61tch_occupancy\x18\x05 \x01(\r\x12\x13\n\x0bkv_pressure\x18\x06 \x01(\x02\x12\x16\n\x0eresident_bytes\x18\x07 \x01(\x04\x12\x0e\n\x06\x64\x65tail\x18\x08 \x01(\t\"x\n\x0eReleaseRequest\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x13\n\x0broute_epoch\x18\x03 \x01(\x04\"P\n\x0fReleaseResponse\x12\x10\n\x08released\x18\x01 \x01(\x08\x12+\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardError\"\x98\x01\n\rCancelRequest\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x13\n\x0broute_epoch\x18\x03 \x01(\x04\x12\x0f\n\x07work_id\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\"[\n\x0e\x43\x61ncelResponse\x12\x1c\n\x14\x63\x61ncelled_work_items\x18\x01 \x01(\r\x12+\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardError*E\n\rSchemaVersion\x12\x1e\n\x1aSCHEMA_VERSION_UNSPECIFIED\x10\x00\x12\x14\n\x10SCHEMA_VERSION_1\x10\x01*\xab\x01\n\x05\x44Type\x12\x15\n\x11\x44TYPE_UNSPECIFIED\x10\x00\x12\x12\n\x0e\x44TYPE_BFLOAT16\x10\x01\x12\x11\n\rDTYPE_FLOAT16\x10\x02\x12\x11\n\rDTYPE_FLOAT32\x10\x03\x12\x0f\n\x0b\x44TYPE_INT32\x10\x04\x12\x0f\n\x0b\x44TYPE_INT64\x10\x05\x12\x0f\n\x0b\x44TYPE_UINT8\x10\x06\x12\x0e\n\nDTYPE_INT8\x10\x07\x12\x0e\n\nDTYPE_BOOL\x10\x08*`\n\tByteOrder\x12\x1a\n\x16\x42YTE_ORDER_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x42YTE_ORDER_LITTLE_ENDIAN\x10\x01\x12\x19\n\x15\x42YTE_ORDER_BIG_ENDIAN\x10\x02*V\n\x0b\x43ompression\x12\x1b\n\x17\x43OMPRESSION_UNSPECIFIED\x10\x00\x12\x14\n\x10\x43OMPRESSION_NONE\x10\x01\x12\x14\n\x10\x43OMPRESSION_ZSTD\x10\x02*s\n\x11\x43hecksumAlgorithm\x12\"\n\x1e\x43HECKSUM_ALGORITHM_UNSPECIFIED\x10\x00\x12\x1b\n\x17\x43HECKSUM_ALGORITHM_NONE\x10\x01\x12\x1d\n\x19\x43HECKSUM_ALGORITHM_CRC32C\x10\x02*h\n\x05Phase\x12\x15\n\x11PHASE_UNSPECIFIED\x10\x00\x12\x11\n\rPHASE_PREFILL\x10\x01\x12\x10\n\x0cPHASE_DECODE\x10\x02\x12\x11\n\rPHASE_RELEASE\x10\x03\x12\x10\n\x0cPHASE_CANCEL\x10\x04*p\n\tCacheMode\x12\x1a\n\x16\x43\x41\x43HE_MODE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x43\x41\x43HE_MODE_STATELESS\x10\x01\x12\x16\n\x12\x43\x41\x43HE_MODE_PREFILL\x10\x02\x12\x15\n\x11\x43\x41\x43HE_MODE_DECODE\x10\x03*\x8a\x03\n\tErrorCode\x12\x1a\n\x16\x45RROR_CODE_UNSPECIFIED\x10\x00\x12!\n\x1d\x45RROR_CODE_SCHEMA_UNSUPPORTED\x10\x01\x12#\n\x1f\x45RROR_CODE_FINGERPRINT_MISMATCH\x10\x02\x12\x1a\n\x16\x45RROR_CODE_EPOCH_STALE\x10\x03\x12#\n\x1f\x45RROR_CODE_SHARD_RANGE_MISMATCH\x10\x04\x12\x19\n\x15\x45RROR_CODE_CACHE_MISS\x10\x05\x12!\n\x1d\x45RROR_CODE_RESOURCE_EXHAUSTED\x10\x06\x12\x1e\n\x1a\x45RROR_CODE_PAYLOAD_CORRUPT\x10\x07\x12\x18\n\x14\x45RROR_CODE_CANCELLED\x10\x08\x12 \n\x1c\x45RROR_CODE_DEADLINE_EXCEEDED\x10\t\x12%\n!ERROR_CODE_FLOW_CONTROL_VIOLATION\x10\n\x12\x17\n\x13\x45RROR_CODE_INTERNAL\x10\x0b*\x83\x01\n\x0cServingState\x12\x1d\n\x19SERVING_STATE_UNSPECIFIED\x10\x00\x12\x19\n\x15SERVING_STATE_SERVING\x10\x01\x12\x1a\n\x16SERVING_STATE_DRAINING\x10\x02\x12\x1d\n\x19SERVING_STATE_NOT_SERVING\x10\x03\x32\xa4\x03\n\x0cShardRuntime\x12X\n\rGetCapability\x12#.meshnet.shard.v1.CapabilityRequest\x1a\".meshnet.shard.v1.CapabilityReport\x12I\n\x06Health\x12\x1f.meshnet.shard.v1.HealthRequest\x1a\x1e.meshnet.shard.v1.HealthReport\x12R\n\x07Session\x12 .meshnet.shard.v1.SessionRequest\x1a!.meshnet.shard.v1.SessionResponse(\x01\x30\x01\x12N\n\x07Release\x12 .meshnet.shard.v1.ReleaseRequest\x1a!.meshnet.shard.v1.ReleaseResponse\x12K\n\x06\x43\x61ncel\x12\x1f.meshnet.shard.v1.CancelRequest\x1a .meshnet.shard.v1.CancelResponseB(Z#github.com/meshnet/shard/v1;shardv1\xf8\x01\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13shard_runtime.proto\x12\x10meshnet.shard.v1\"Q\n\x08\x43hecksum\x12\x36\n\talgorithm\x18\x01 \x01(\x0e\x32#.meshnet.shard.v1.ChecksumAlgorithm\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x7f\n\x0eTensorFragment\x12\x16\n\x0e\x66ragment_index\x18\x01 \x01(\r\x12\x16\n\x0e\x66ragment_count\x18\x02 \x01(\r\x12\x13\n\x0b\x62yte_offset\x18\x03 \x01(\x04\x12\x0f\n\x07payload\x18\x04 \x01(\x0cJ\x04\x08\x05\x10\x06R\x11uncompressed_size\"\xaf\x02\n\x0bNamedTensor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05shape\x18\x02 \x03(\x03\x12&\n\x05\x64type\x18\x03 \x01(\x0e\x32\x17.meshnet.shard.v1.DType\x12/\n\nbyte_order\x18\x04 \x01(\x0e\x32\x1b.meshnet.shard.v1.ByteOrder\x12\x13\n\x0btotal_bytes\x18\x05 \x01(\x04\x12\x32\n\x0b\x63ompression\x18\x06 \x01(\x0e\x32\x1d.meshnet.shard.v1.Compression\x12,\n\x08\x63hecksum\x18\x07 \x01(\x0b\x32\x1a.meshnet.shard.v1.Checksum\x12\x33\n\tfragments\x18\x08 \x03(\x0b\x32 .meshnet.shard.v1.TensorFragment\"\xa8\x01\n\x0cTensorBundle\x12\x16\n\x0e\x62undle_version\x18\x01 \x01(\r\x12.\n\x07tensors\x18\x02 \x03(\x0b\x32\x1d.meshnet.shard.v1.NamedTensor\x12\x38\n\x0c\x61rchitecture\x18\x03 \x01(\x0e\x32\".meshnet.shard.v1.ArchitectureType\x12\x16\n\x0e\x62oundary_point\x18\x04 \x01(\t\"\x91\x01\n\x0b\x46ingerprint\x12\x1d\n\x15model_artifact_digest\x18\x01 \x01(\t\x12\x1d\n\x15runtime_recipe_digest\x18\x02 \x01(\t\x12\x11\n\trecipe_id\x18\x03 \x01(\t\x12\x16\n\x0erecipe_version\x18\x04 \x01(\t\x12\x19\n\x11\x63\x61talogue_version\x18\x05 \x01(\t\"S\n\nShardRange\x12\x13\n\x0bstart_layer\x18\x01 \x01(\r\x12\x11\n\tend_layer\x18\x02 \x01(\r\x12\x1d\n\x15\x65\x66\x66\x65\x63tive_start_layer\x18\x03 \x01(\r\";\n\x0cPositionSpan\x12\x16\n\x0e\x66irst_position\x18\x01 \x01(\x04\x12\x13\n\x0btoken_count\x18\x02 \x01(\r\"J\n\tChunkInfo\x12\x13\n\x0b\x63hunk_index\x18\x01 \x01(\r\x12\x13\n\x0b\x63hunk_count\x18\x02 \x01(\r\x12\x13\n\x0b\x66inal_chunk\x18\x03 \x01(\x08\"X\n\x10\x43\x61\x63heExpectation\x12)\n\x04mode\x18\x01 \x01(\x0e\x32\x1b.meshnet.shard.v1.CacheMode\x12\x19\n\x11\x65xpected_past_len\x18\x02 \x01(\x04\"]\n\x0b\x43\x61\x63heResult\x12)\n\x04mode\x18\x01 \x01(\x0e\x32\x1b.meshnet.shard.v1.CacheMode\x12\x10\n\x08past_len\x18\x02 \x01(\x04\x12\x11\n\tcache_hit\x18\x03 \x01(\x08\"\xe6\x03\n\x08\x45nvelope\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x0f\n\x07work_id\x18\x02 \x01(\t\x12\x18\n\x10route_session_id\x18\x03 \x01(\t\x12\x13\n\x0broute_epoch\x18\x04 \x01(\x04\x12\x32\n\x0b\x66ingerprint\x18\x05 \x01(\x0b\x32\x1d.meshnet.shard.v1.Fingerprint\x12\x31\n\x0bshard_range\x18\x06 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardRange\x12&\n\x05phase\x18\x07 \x01(\x0e\x32\x17.meshnet.shard.v1.Phase\x12\x30\n\x08position\x18\x08 \x01(\x0b\x32\x1e.meshnet.shard.v1.PositionSpan\x12\x18\n\x10idempotency_step\x18\t \x01(\x04\x12=\n\x11\x63\x61\x63he_expectation\x18\n \x01(\x0b\x32\".meshnet.shard.v1.CacheExpectation\x12\x1b\n\x13\x64\x65\x61\x64line_unix_nanos\x18\x0b \x01(\x03\x12*\n\x05\x63hunk\x18\x0c \x01(\x0b\x32\x1b.meshnet.shard.v1.ChunkInfo\"s\n\nShardError\x12)\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x1b.meshnet.shard.v1.ErrorCode\x12\x0e\n\x06\x64\x65tail\x18\x02 \x01(\t\x12\x11\n\tretryable\x18\x03 \x01(\x08\x12\x17\n\x0f\x61\x63tual_past_len\x18\x04 \x01(\x04\"~\n\x0b\x46lowControl\x12\x17\n\x0f\x63redits_granted\x18\x01 \x01(\r\x12\x1b\n\x13max_inflight_chunks\x18\x02 \x01(\r\x12\x17\n\x0fmax_chunk_bytes\x18\x03 \x01(\x04\x12 \n\x18max_prefill_chunk_tokens\x18\x04 \x01(\r\"\xd7\x02\n\x0bSessionOpen\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x13\n\x0broute_epoch\x18\x03 \x01(\x04\x12\x32\n\x0b\x66ingerprint\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.Fingerprint\x12\x31\n\x0bshard_range\x18\x05 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardRange\x12<\n\x15proposed_flow_control\x18\x06 \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControl\x12;\n\x14\x61\x63\x63\x65pted_compression\x18\x07 \x03(\x0e\x32\x1d.meshnet.shard.v1.Compression\"\x9f\x02\n\x0fSessionAccepted\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x13\n\x0broute_epoch\x18\x03 \x01(\x04\x12\x33\n\x0c\x66low_control\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControl\x12;\n\x14\x61\x63\x63\x65pted_compression\x18\x05 \x03(\x0e\x32\x1d.meshnet.shard.v1.Compression\x12\x32\n\x0b\x66ingerprint\x18\x06 \x01(\x0b\x32\x1d.meshnet.shard.v1.Fingerprint\"o\n\x0f\x41\x63tivationChunk\x12,\n\x08\x65nvelope\x18\x01 \x01(\x0b\x32\x1a.meshnet.shard.v1.Envelope\x12.\n\x06\x62undle\x18\x02 \x01(\x0b\x32\x1e.meshnet.shard.v1.TensorBundle\"\xe0\x01\n\nDecodeStep\x12\x18\n\x10idempotency_step\x18\x01 \x01(\x04\x12\x10\n\x08position\x18\x02 \x01(\x04\x12\x19\n\x11\x65xpected_past_len\x18\x03 \x01(\x04\x12-\n\x06tensor\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.NamedTensor\x12\x0f\n\x07work_id\x18\x05 \x01(\t\x12\x1b\n\x13\x64\x65\x61\x64line_unix_nanos\x18\x06 \x01(\x03\x12.\n\x06\x62undle\x18\x07 \x01(\x0b\x32\x1e.meshnet.shard.v1.TensorBundle\"\xd5\x01\n\x15RequestRecipeIdentity\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x1d\n\x15runtime_recipe_digest\x18\x02 \x01(\t\x12\x18\n\x10\x63hat_template_id\x18\x03 \x01(\t\x12\x1d\n\x15\x63hat_template_version\x18\x04 \x01(\t\x12\x16\n\x0ereasoning_mode\x18\x05 \x01(\t\x12\x38\n\x0c\x61rchitecture\x18\x06 \x01(\x0e\x32\".meshnet.shard.v1.ArchitectureType\"e\n\x12SamplingParameters\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\r\n\x05top_p\x18\x02 \x01(\x02\x12\r\n\x05top_k\x18\x03 \x01(\r\x12\x0c\n\x04seed\x18\x04 \x01(\x04\x12\x0e\n\x06greedy\x18\x05 \x01(\x08\"\xd7\x01\n\nTailResult\x12\x39\n\x08identity\x18\x01 \x01(\x0b\x32\'.meshnet.shard.v1.RequestRecipeIdentity\x12\x36\n\x08sampling\x18\x02 \x01(\x0b\x32$.meshnet.shard.v1.SamplingParameters\x12\x30\n\x06logits\x18\x03 \x01(\x0b\x32\x1e.meshnet.shard.v1.TensorBundleH\x00\x12\x1a\n\x10sampled_token_id\x18\x04 \x01(\rH\x00\x42\x08\n\x06output\"O\n\rReleaseSignal\x12\x18\n\x10route_session_id\x18\x01 \x01(\t\x12\x13\n\x0broute_epoch\x18\x02 \x01(\x04\x12\x0f\n\x07work_id\x18\x03 \x01(\t\"^\n\x0c\x43\x61ncelSignal\x12\x18\n\x10route_session_id\x18\x01 \x01(\t\x12\x13\n\x0broute_epoch\x18\x02 \x01(\x04\x12\x0f\n\x07work_id\x18\x03 \x01(\t\x12\x0e\n\x06reason\x18\x04 \x01(\t\"\x91\x01\n\x03\x41\x63k\x12\x0f\n\x07work_id\x18\x01 \x01(\t\x12\x18\n\x10idempotency_step\x18\x02 \x01(\x04\x12\x33\n\x0c\x63\x61\x63he_result\x18\x03 \x01(\x0b\x32\x1d.meshnet.shard.v1.CacheResult\x12\x11\n\tduplicate\x18\x04 \x01(\x08\x12\x17\n\x0f\x65xecution_nanos\x18\x05 \x01(\x04\"\x91\x01\n\x0bShardStatus\x12\x0f\n\x07work_id\x18\x01 \x01(\t\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x18\n\x10idempotency_step\x18\x03 \x01(\x04\x12+\n\x05\x65rror\x18\x04 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardError\x12\x10\n\x08terminal\x18\x05 \x01(\x08\"\xc8\x02\n\x0eSessionRequest\x12-\n\x04open\x18\x01 \x01(\x0b\x32\x1d.meshnet.shard.v1.SessionOpenH\x00\x12\x32\n\x05\x63hunk\x18\x02 \x01(\x0b\x32!.meshnet.shard.v1.ActivationChunkH\x00\x12.\n\x06\x64\x65\x63ode\x18\x03 \x01(\x0b\x32\x1c.meshnet.shard.v1.DecodeStepH\x00\x12\x35\n\x0c\x66low_control\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControlH\x00\x12\x32\n\x07release\x18\x05 \x01(\x0b\x32\x1f.meshnet.shard.v1.ReleaseSignalH\x00\x12\x30\n\x06\x63\x61ncel\x18\x06 \x01(\x0b\x32\x1e.meshnet.shard.v1.CancelSignalH\x00\x42\x06\n\x04kind\"\xc7\x02\n\x0fSessionResponse\x12\x35\n\x08\x61\x63\x63\x65pted\x18\x01 \x01(\x0b\x32!.meshnet.shard.v1.SessionAcceptedH\x00\x12\x32\n\x05\x63hunk\x18\x02 \x01(\x0b\x32!.meshnet.shard.v1.ActivationChunkH\x00\x12$\n\x03\x61\x63k\x18\x03 \x01(\x0b\x32\x15.meshnet.shard.v1.AckH\x00\x12\x35\n\x0c\x66low_control\x18\x04 \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControlH\x00\x12/\n\x06status\x18\x05 \x01(\x0b\x32\x1d.meshnet.shard.v1.ShardStatusH\x00\x12\x33\n\x0btail_result\x18\x06 \x01(\x0b\x32\x1c.meshnet.shard.v1.TailResultH\x00\x42\x06\n\x04kind\"L\n\x11\x43\x61pabilityRequest\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\"\x8a\x04\n\x10\x43\x61pabilityReport\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x32\n\x0b\x66ingerprint\x18\x02 \x01(\x0b\x32\x1d.meshnet.shard.v1.Fingerprint\x12\x31\n\x0bshard_range\x18\x03 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardRange\x12\x0f\n\x07\x62\x61\x63kend\x18\x04 \x01(\t\x12\x0e\n\x06\x64\x65vice\x18\x05 \x01(\t\x12\x11\n\tvalidated\x18\x06 \x01(\x08\x12\x0e\n\x06\x64\x65tail\x18\x07 \x01(\t\x12\x1f\n\x17max_concurrent_sessions\x18\x08 \x01(\x04\x12\x1a\n\x12max_context_tokens\x18\t \x01(\x04\x12\x33\n\x0c\x66low_control\x18\n \x01(\x0b\x32\x1d.meshnet.shard.v1.FlowControl\x12;\n\x14\x61\x63\x63\x65pted_compression\x18\x0b \x03(\x0e\x32\x1d.meshnet.shard.v1.Compression\x12\x42\n\x19supported_schema_versions\x18\x0c \x03(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x1f\n\x17validated_at_unix_nanos\x18\r \x01(\x03\"H\n\rHealthRequest\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\"\xfc\x01\n\x0cHealthReport\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12-\n\x05state\x18\x02 \x01(\x0e\x32\x1e.meshnet.shard.v1.ServingState\x12\x17\n\x0f\x61\x63tive_sessions\x18\x03 \x01(\r\x12\x15\n\rqueued_chunks\x18\x04 \x01(\r\x12\x17\n\x0f\x62\x61tch_occupancy\x18\x05 \x01(\r\x12\x13\n\x0bkv_pressure\x18\x06 \x01(\x02\x12\x16\n\x0eresident_bytes\x18\x07 \x01(\x04\x12\x0e\n\x06\x64\x65tail\x18\x08 \x01(\t\"x\n\x0eReleaseRequest\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x13\n\x0broute_epoch\x18\x03 \x01(\x04\"P\n\x0fReleaseResponse\x12\x10\n\x08released\x18\x01 \x01(\x08\x12+\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardError\"\x98\x01\n\rCancelRequest\x12\x37\n\x0eschema_version\x18\x01 \x01(\x0e\x32\x1f.meshnet.shard.v1.SchemaVersion\x12\x18\n\x10route_session_id\x18\x02 \x01(\t\x12\x13\n\x0broute_epoch\x18\x03 \x01(\x04\x12\x0f\n\x07work_id\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\"[\n\x0e\x43\x61ncelResponse\x12\x1c\n\x14\x63\x61ncelled_work_items\x18\x01 \x01(\r\x12+\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x1c.meshnet.shard.v1.ShardError*E\n\rSchemaVersion\x12\x1e\n\x1aSCHEMA_VERSION_UNSPECIFIED\x10\x00\x12\x14\n\x10SCHEMA_VERSION_1\x10\x01*\x88\x01\n\x10\x41rchitectureType\x12!\n\x1d\x41RCHITECTURE_TYPE_UNSPECIFIED\x10\x00\x12\x1b\n\x17\x41RCHITECTURE_TYPE_DENSE\x10\x01\x12\x19\n\x15\x41RCHITECTURE_TYPE_MOE\x10\x02\x12\x19\n\x15\x41RCHITECTURE_TYPE_MLA\x10\x03*\xab\x01\n\x05\x44Type\x12\x15\n\x11\x44TYPE_UNSPECIFIED\x10\x00\x12\x12\n\x0e\x44TYPE_BFLOAT16\x10\x01\x12\x11\n\rDTYPE_FLOAT16\x10\x02\x12\x11\n\rDTYPE_FLOAT32\x10\x03\x12\x0f\n\x0b\x44TYPE_INT32\x10\x04\x12\x0f\n\x0b\x44TYPE_INT64\x10\x05\x12\x0f\n\x0b\x44TYPE_UINT8\x10\x06\x12\x0e\n\nDTYPE_INT8\x10\x07\x12\x0e\n\nDTYPE_BOOL\x10\x08*`\n\tByteOrder\x12\x1a\n\x16\x42YTE_ORDER_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x42YTE_ORDER_LITTLE_ENDIAN\x10\x01\x12\x19\n\x15\x42YTE_ORDER_BIG_ENDIAN\x10\x02*V\n\x0b\x43ompression\x12\x1b\n\x17\x43OMPRESSION_UNSPECIFIED\x10\x00\x12\x14\n\x10\x43OMPRESSION_NONE\x10\x01\x12\x14\n\x10\x43OMPRESSION_ZSTD\x10\x02*s\n\x11\x43hecksumAlgorithm\x12\"\n\x1e\x43HECKSUM_ALGORITHM_UNSPECIFIED\x10\x00\x12\x1b\n\x17\x43HECKSUM_ALGORITHM_NONE\x10\x01\x12\x1d\n\x19\x43HECKSUM_ALGORITHM_CRC32C\x10\x02*h\n\x05Phase\x12\x15\n\x11PHASE_UNSPECIFIED\x10\x00\x12\x11\n\rPHASE_PREFILL\x10\x01\x12\x10\n\x0cPHASE_DECODE\x10\x02\x12\x11\n\rPHASE_RELEASE\x10\x03\x12\x10\n\x0cPHASE_CANCEL\x10\x04*p\n\tCacheMode\x12\x1a\n\x16\x43\x41\x43HE_MODE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x43\x41\x43HE_MODE_STATELESS\x10\x01\x12\x16\n\x12\x43\x41\x43HE_MODE_PREFILL\x10\x02\x12\x15\n\x11\x43\x41\x43HE_MODE_DECODE\x10\x03*\x8a\x03\n\tErrorCode\x12\x1a\n\x16\x45RROR_CODE_UNSPECIFIED\x10\x00\x12!\n\x1d\x45RROR_CODE_SCHEMA_UNSUPPORTED\x10\x01\x12#\n\x1f\x45RROR_CODE_FINGERPRINT_MISMATCH\x10\x02\x12\x1a\n\x16\x45RROR_CODE_EPOCH_STALE\x10\x03\x12#\n\x1f\x45RROR_CODE_SHARD_RANGE_MISMATCH\x10\x04\x12\x19\n\x15\x45RROR_CODE_CACHE_MISS\x10\x05\x12!\n\x1d\x45RROR_CODE_RESOURCE_EXHAUSTED\x10\x06\x12\x1e\n\x1a\x45RROR_CODE_PAYLOAD_CORRUPT\x10\x07\x12\x18\n\x14\x45RROR_CODE_CANCELLED\x10\x08\x12 \n\x1c\x45RROR_CODE_DEADLINE_EXCEEDED\x10\t\x12%\n!ERROR_CODE_FLOW_CONTROL_VIOLATION\x10\n\x12\x17\n\x13\x45RROR_CODE_INTERNAL\x10\x0b*\x83\x01\n\x0cServingState\x12\x1d\n\x19SERVING_STATE_UNSPECIFIED\x10\x00\x12\x19\n\x15SERVING_STATE_SERVING\x10\x01\x12\x1a\n\x16SERVING_STATE_DRAINING\x10\x02\x12\x1d\n\x19SERVING_STATE_NOT_SERVING\x10\x03\x32\xa4\x03\n\x0cShardRuntime\x12X\n\rGetCapability\x12#.meshnet.shard.v1.CapabilityRequest\x1a\".meshnet.shard.v1.CapabilityReport\x12I\n\x06Health\x12\x1f.meshnet.shard.v1.HealthRequest\x1a\x1e.meshnet.shard.v1.HealthReport\x12R\n\x07Session\x12 .meshnet.shard.v1.SessionRequest\x1a!.meshnet.shard.v1.SessionResponse(\x01\x30\x01\x12N\n\x07Release\x12 .meshnet.shard.v1.ReleaseRequest\x1a!.meshnet.shard.v1.ReleaseResponse\x12K\n\x06\x43\x61ncel\x12\x1f.meshnet.shard.v1.CancelRequest\x1a .meshnet.shard.v1.CancelResponseB(Z#github.com/meshnet/shard/v1;shardv1\xf8\x01\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -32,86 +32,94 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'shard_runtime_pb2', _global if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None _globals['DESCRIPTOR']._serialized_options = b'Z#github.com/meshnet/shard/v1;shardv1\370\001\001' - _globals['_SCHEMAVERSION']._serialized_start=5329 - _globals['_SCHEMAVERSION']._serialized_end=5398 - _globals['_DTYPE']._serialized_start=5401 - _globals['_DTYPE']._serialized_end=5572 - _globals['_BYTEORDER']._serialized_start=5574 - _globals['_BYTEORDER']._serialized_end=5670 - _globals['_COMPRESSION']._serialized_start=5672 - _globals['_COMPRESSION']._serialized_end=5758 - _globals['_CHECKSUMALGORITHM']._serialized_start=5760 - _globals['_CHECKSUMALGORITHM']._serialized_end=5875 - _globals['_PHASE']._serialized_start=5877 - _globals['_PHASE']._serialized_end=5981 - _globals['_CACHEMODE']._serialized_start=5983 - _globals['_CACHEMODE']._serialized_end=6095 - _globals['_ERRORCODE']._serialized_start=6098 - _globals['_ERRORCODE']._serialized_end=6492 - _globals['_SERVINGSTATE']._serialized_start=6495 - _globals['_SERVINGSTATE']._serialized_end=6626 + _globals['_SCHEMAVERSION']._serialized_start=6050 + _globals['_SCHEMAVERSION']._serialized_end=6119 + _globals['_ARCHITECTURETYPE']._serialized_start=6122 + _globals['_ARCHITECTURETYPE']._serialized_end=6258 + _globals['_DTYPE']._serialized_start=6261 + _globals['_DTYPE']._serialized_end=6432 + _globals['_BYTEORDER']._serialized_start=6434 + _globals['_BYTEORDER']._serialized_end=6530 + _globals['_COMPRESSION']._serialized_start=6532 + _globals['_COMPRESSION']._serialized_end=6618 + _globals['_CHECKSUMALGORITHM']._serialized_start=6620 + _globals['_CHECKSUMALGORITHM']._serialized_end=6735 + _globals['_PHASE']._serialized_start=6737 + _globals['_PHASE']._serialized_end=6841 + _globals['_CACHEMODE']._serialized_start=6843 + _globals['_CACHEMODE']._serialized_end=6955 + _globals['_ERRORCODE']._serialized_start=6958 + _globals['_ERRORCODE']._serialized_end=7352 + _globals['_SERVINGSTATE']._serialized_start=7355 + _globals['_SERVINGSTATE']._serialized_end=7486 _globals['_CHECKSUM']._serialized_start=41 _globals['_CHECKSUM']._serialized_end=122 _globals['_TENSORFRAGMENT']._serialized_start=124 _globals['_TENSORFRAGMENT']._serialized_end=251 _globals['_NAMEDTENSOR']._serialized_start=254 _globals['_NAMEDTENSOR']._serialized_end=557 - _globals['_TENSORBUNDLE']._serialized_start=559 - _globals['_TENSORBUNDLE']._serialized_end=645 - _globals['_FINGERPRINT']._serialized_start=648 - _globals['_FINGERPRINT']._serialized_end=793 - _globals['_SHARDRANGE']._serialized_start=795 - _globals['_SHARDRANGE']._serialized_end=878 - _globals['_POSITIONSPAN']._serialized_start=880 - _globals['_POSITIONSPAN']._serialized_end=939 - _globals['_CHUNKINFO']._serialized_start=941 - _globals['_CHUNKINFO']._serialized_end=1015 - _globals['_CACHEEXPECTATION']._serialized_start=1017 - _globals['_CACHEEXPECTATION']._serialized_end=1105 - _globals['_CACHERESULT']._serialized_start=1107 - _globals['_CACHERESULT']._serialized_end=1200 - _globals['_ENVELOPE']._serialized_start=1203 - _globals['_ENVELOPE']._serialized_end=1689 - _globals['_SHARDERROR']._serialized_start=1691 - _globals['_SHARDERROR']._serialized_end=1806 - _globals['_FLOWCONTROL']._serialized_start=1808 - _globals['_FLOWCONTROL']._serialized_end=1934 - _globals['_SESSIONOPEN']._serialized_start=1937 - _globals['_SESSIONOPEN']._serialized_end=2280 - _globals['_SESSIONACCEPTED']._serialized_start=2283 - _globals['_SESSIONACCEPTED']._serialized_end=2570 - _globals['_ACTIVATIONCHUNK']._serialized_start=2572 - _globals['_ACTIVATIONCHUNK']._serialized_end=2683 - _globals['_DECODESTEP']._serialized_start=2686 - _globals['_DECODESTEP']._serialized_end=2862 - _globals['_RELEASESIGNAL']._serialized_start=2864 - _globals['_RELEASESIGNAL']._serialized_end=2943 - _globals['_CANCELSIGNAL']._serialized_start=2945 - _globals['_CANCELSIGNAL']._serialized_end=3039 - _globals['_ACK']._serialized_start=3042 - _globals['_ACK']._serialized_end=3187 - _globals['_SHARDSTATUS']._serialized_start=3190 - _globals['_SHARDSTATUS']._serialized_end=3335 - _globals['_SESSIONREQUEST']._serialized_start=3338 - _globals['_SESSIONREQUEST']._serialized_end=3666 - _globals['_SESSIONRESPONSE']._serialized_start=3669 - _globals['_SESSIONRESPONSE']._serialized_end=3943 - _globals['_CAPABILITYREQUEST']._serialized_start=3945 - _globals['_CAPABILITYREQUEST']._serialized_end=4021 - _globals['_CAPABILITYREPORT']._serialized_start=4024 - _globals['_CAPABILITYREPORT']._serialized_end=4546 - _globals['_HEALTHREQUEST']._serialized_start=4548 - _globals['_HEALTHREQUEST']._serialized_end=4620 - _globals['_HEALTHREPORT']._serialized_start=4623 - _globals['_HEALTHREPORT']._serialized_end=4875 - _globals['_RELEASEREQUEST']._serialized_start=4877 - _globals['_RELEASEREQUEST']._serialized_end=4997 - _globals['_RELEASERESPONSE']._serialized_start=4999 - _globals['_RELEASERESPONSE']._serialized_end=5079 - _globals['_CANCELREQUEST']._serialized_start=5082 - _globals['_CANCELREQUEST']._serialized_end=5234 - _globals['_CANCELRESPONSE']._serialized_start=5236 - _globals['_CANCELRESPONSE']._serialized_end=5327 - _globals['_SHARDRUNTIME']._serialized_start=6629 - _globals['_SHARDRUNTIME']._serialized_end=7049 + _globals['_TENSORBUNDLE']._serialized_start=560 + _globals['_TENSORBUNDLE']._serialized_end=728 + _globals['_FINGERPRINT']._serialized_start=731 + _globals['_FINGERPRINT']._serialized_end=876 + _globals['_SHARDRANGE']._serialized_start=878 + _globals['_SHARDRANGE']._serialized_end=961 + _globals['_POSITIONSPAN']._serialized_start=963 + _globals['_POSITIONSPAN']._serialized_end=1022 + _globals['_CHUNKINFO']._serialized_start=1024 + _globals['_CHUNKINFO']._serialized_end=1098 + _globals['_CACHEEXPECTATION']._serialized_start=1100 + _globals['_CACHEEXPECTATION']._serialized_end=1188 + _globals['_CACHERESULT']._serialized_start=1190 + _globals['_CACHERESULT']._serialized_end=1283 + _globals['_ENVELOPE']._serialized_start=1286 + _globals['_ENVELOPE']._serialized_end=1772 + _globals['_SHARDERROR']._serialized_start=1774 + _globals['_SHARDERROR']._serialized_end=1889 + _globals['_FLOWCONTROL']._serialized_start=1891 + _globals['_FLOWCONTROL']._serialized_end=2017 + _globals['_SESSIONOPEN']._serialized_start=2020 + _globals['_SESSIONOPEN']._serialized_end=2363 + _globals['_SESSIONACCEPTED']._serialized_start=2366 + _globals['_SESSIONACCEPTED']._serialized_end=2653 + _globals['_ACTIVATIONCHUNK']._serialized_start=2655 + _globals['_ACTIVATIONCHUNK']._serialized_end=2766 + _globals['_DECODESTEP']._serialized_start=2769 + _globals['_DECODESTEP']._serialized_end=2993 + _globals['_REQUESTRECIPEIDENTITY']._serialized_start=2996 + _globals['_REQUESTRECIPEIDENTITY']._serialized_end=3209 + _globals['_SAMPLINGPARAMETERS']._serialized_start=3211 + _globals['_SAMPLINGPARAMETERS']._serialized_end=3312 + _globals['_TAILRESULT']._serialized_start=3315 + _globals['_TAILRESULT']._serialized_end=3530 + _globals['_RELEASESIGNAL']._serialized_start=3532 + _globals['_RELEASESIGNAL']._serialized_end=3611 + _globals['_CANCELSIGNAL']._serialized_start=3613 + _globals['_CANCELSIGNAL']._serialized_end=3707 + _globals['_ACK']._serialized_start=3710 + _globals['_ACK']._serialized_end=3855 + _globals['_SHARDSTATUS']._serialized_start=3858 + _globals['_SHARDSTATUS']._serialized_end=4003 + _globals['_SESSIONREQUEST']._serialized_start=4006 + _globals['_SESSIONREQUEST']._serialized_end=4334 + _globals['_SESSIONRESPONSE']._serialized_start=4337 + _globals['_SESSIONRESPONSE']._serialized_end=4664 + _globals['_CAPABILITYREQUEST']._serialized_start=4666 + _globals['_CAPABILITYREQUEST']._serialized_end=4742 + _globals['_CAPABILITYREPORT']._serialized_start=4745 + _globals['_CAPABILITYREPORT']._serialized_end=5267 + _globals['_HEALTHREQUEST']._serialized_start=5269 + _globals['_HEALTHREQUEST']._serialized_end=5341 + _globals['_HEALTHREPORT']._serialized_start=5344 + _globals['_HEALTHREPORT']._serialized_end=5596 + _globals['_RELEASEREQUEST']._serialized_start=5598 + _globals['_RELEASEREQUEST']._serialized_end=5718 + _globals['_RELEASERESPONSE']._serialized_start=5720 + _globals['_RELEASERESPONSE']._serialized_end=5800 + _globals['_CANCELREQUEST']._serialized_start=5803 + _globals['_CANCELREQUEST']._serialized_end=5955 + _globals['_CANCELRESPONSE']._serialized_start=5957 + _globals['_CANCELRESPONSE']._serialized_end=6048 + _globals['_SHARDRUNTIME']._serialized_start=7489 + _globals['_SHARDRUNTIME']._serialized_end=7909 # @@protoc_insertion_point(module_scope) diff --git a/packages/node/meshnet_node/native_protocol/generated/shard_runtime_pb2.pyi b/packages/node/meshnet_node/native_protocol/generated/shard_runtime_pb2.pyi index 4edb765..8c5bd91 100644 --- a/packages/node/meshnet_node/native_protocol/generated/shard_runtime_pb2.pyi +++ b/packages/node/meshnet_node/native_protocol/generated/shard_runtime_pb2.pyi @@ -12,6 +12,13 @@ class SchemaVersion(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): SCHEMA_VERSION_UNSPECIFIED: _ClassVar[SchemaVersion] SCHEMA_VERSION_1: _ClassVar[SchemaVersion] +class ArchitectureType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ARCHITECTURE_TYPE_UNSPECIFIED: _ClassVar[ArchitectureType] + ARCHITECTURE_TYPE_DENSE: _ClassVar[ArchitectureType] + ARCHITECTURE_TYPE_MOE: _ClassVar[ArchitectureType] + ARCHITECTURE_TYPE_MLA: _ClassVar[ArchitectureType] + class DType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): __slots__ = () DTYPE_UNSPECIFIED: _ClassVar[DType] @@ -80,6 +87,10 @@ class ServingState(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): SERVING_STATE_NOT_SERVING: _ClassVar[ServingState] SCHEMA_VERSION_UNSPECIFIED: SchemaVersion SCHEMA_VERSION_1: SchemaVersion +ARCHITECTURE_TYPE_UNSPECIFIED: ArchitectureType +ARCHITECTURE_TYPE_DENSE: ArchitectureType +ARCHITECTURE_TYPE_MOE: ArchitectureType +ARCHITECTURE_TYPE_MLA: ArchitectureType DTYPE_UNSPECIFIED: DType DTYPE_BFLOAT16: DType DTYPE_FLOAT16: DType @@ -165,12 +176,16 @@ class NamedTensor(_message.Message): def __init__(self, name: _Optional[str] = ..., shape: _Optional[_Iterable[int]] = ..., dtype: _Optional[_Union[DType, str]] = ..., byte_order: _Optional[_Union[ByteOrder, str]] = ..., total_bytes: _Optional[int] = ..., compression: _Optional[_Union[Compression, str]] = ..., checksum: _Optional[_Union[Checksum, _Mapping]] = ..., fragments: _Optional[_Iterable[_Union[TensorFragment, _Mapping]]] = ...) -> None: ... class TensorBundle(_message.Message): - __slots__ = ("bundle_version", "tensors") + __slots__ = ("bundle_version", "tensors", "architecture", "boundary_point") BUNDLE_VERSION_FIELD_NUMBER: _ClassVar[int] TENSORS_FIELD_NUMBER: _ClassVar[int] + ARCHITECTURE_FIELD_NUMBER: _ClassVar[int] + BOUNDARY_POINT_FIELD_NUMBER: _ClassVar[int] bundle_version: int tensors: _containers.RepeatedCompositeFieldContainer[NamedTensor] - def __init__(self, bundle_version: _Optional[int] = ..., tensors: _Optional[_Iterable[_Union[NamedTensor, _Mapping]]] = ...) -> None: ... + architecture: ArchitectureType + boundary_point: str + def __init__(self, bundle_version: _Optional[int] = ..., tensors: _Optional[_Iterable[_Union[NamedTensor, _Mapping]]] = ..., architecture: _Optional[_Union[ArchitectureType, str]] = ..., boundary_point: _Optional[str] = ...) -> None: ... class Fingerprint(_message.Message): __slots__ = ("model_artifact_digest", "runtime_recipe_digest", "recipe_id", "recipe_version", "catalogue_version") @@ -327,20 +342,64 @@ class ActivationChunk(_message.Message): def __init__(self, envelope: _Optional[_Union[Envelope, _Mapping]] = ..., bundle: _Optional[_Union[TensorBundle, _Mapping]] = ...) -> None: ... class DecodeStep(_message.Message): - __slots__ = ("idempotency_step", "position", "expected_past_len", "tensor", "work_id", "deadline_unix_nanos") + __slots__ = ("idempotency_step", "position", "expected_past_len", "tensor", "work_id", "deadline_unix_nanos", "bundle") IDEMPOTENCY_STEP_FIELD_NUMBER: _ClassVar[int] POSITION_FIELD_NUMBER: _ClassVar[int] EXPECTED_PAST_LEN_FIELD_NUMBER: _ClassVar[int] TENSOR_FIELD_NUMBER: _ClassVar[int] WORK_ID_FIELD_NUMBER: _ClassVar[int] DEADLINE_UNIX_NANOS_FIELD_NUMBER: _ClassVar[int] + BUNDLE_FIELD_NUMBER: _ClassVar[int] idempotency_step: int position: int expected_past_len: int tensor: NamedTensor work_id: str deadline_unix_nanos: int - def __init__(self, idempotency_step: _Optional[int] = ..., position: _Optional[int] = ..., expected_past_len: _Optional[int] = ..., tensor: _Optional[_Union[NamedTensor, _Mapping]] = ..., work_id: _Optional[str] = ..., deadline_unix_nanos: _Optional[int] = ...) -> None: ... + bundle: TensorBundle + def __init__(self, idempotency_step: _Optional[int] = ..., position: _Optional[int] = ..., expected_past_len: _Optional[int] = ..., tensor: _Optional[_Union[NamedTensor, _Mapping]] = ..., work_id: _Optional[str] = ..., deadline_unix_nanos: _Optional[int] = ..., bundle: _Optional[_Union[TensorBundle, _Mapping]] = ...) -> None: ... + +class RequestRecipeIdentity(_message.Message): + __slots__ = ("request_id", "runtime_recipe_digest", "chat_template_id", "chat_template_version", "reasoning_mode", "architecture") + REQUEST_ID_FIELD_NUMBER: _ClassVar[int] + RUNTIME_RECIPE_DIGEST_FIELD_NUMBER: _ClassVar[int] + CHAT_TEMPLATE_ID_FIELD_NUMBER: _ClassVar[int] + CHAT_TEMPLATE_VERSION_FIELD_NUMBER: _ClassVar[int] + REASONING_MODE_FIELD_NUMBER: _ClassVar[int] + ARCHITECTURE_FIELD_NUMBER: _ClassVar[int] + request_id: str + runtime_recipe_digest: str + chat_template_id: str + chat_template_version: str + reasoning_mode: str + architecture: ArchitectureType + def __init__(self, request_id: _Optional[str] = ..., runtime_recipe_digest: _Optional[str] = ..., chat_template_id: _Optional[str] = ..., chat_template_version: _Optional[str] = ..., reasoning_mode: _Optional[str] = ..., architecture: _Optional[_Union[ArchitectureType, str]] = ...) -> None: ... + +class SamplingParameters(_message.Message): + __slots__ = ("temperature", "top_p", "top_k", "seed", "greedy") + TEMPERATURE_FIELD_NUMBER: _ClassVar[int] + TOP_P_FIELD_NUMBER: _ClassVar[int] + TOP_K_FIELD_NUMBER: _ClassVar[int] + SEED_FIELD_NUMBER: _ClassVar[int] + GREEDY_FIELD_NUMBER: _ClassVar[int] + temperature: float + top_p: float + top_k: int + seed: int + greedy: bool + def __init__(self, temperature: _Optional[float] = ..., top_p: _Optional[float] = ..., top_k: _Optional[int] = ..., seed: _Optional[int] = ..., greedy: _Optional[bool] = ...) -> None: ... + +class TailResult(_message.Message): + __slots__ = ("identity", "sampling", "logits", "sampled_token_id") + IDENTITY_FIELD_NUMBER: _ClassVar[int] + SAMPLING_FIELD_NUMBER: _ClassVar[int] + LOGITS_FIELD_NUMBER: _ClassVar[int] + SAMPLED_TOKEN_ID_FIELD_NUMBER: _ClassVar[int] + identity: RequestRecipeIdentity + sampling: SamplingParameters + logits: TensorBundle + sampled_token_id: int + def __init__(self, identity: _Optional[_Union[RequestRecipeIdentity, _Mapping]] = ..., sampling: _Optional[_Union[SamplingParameters, _Mapping]] = ..., logits: _Optional[_Union[TensorBundle, _Mapping]] = ..., sampled_token_id: _Optional[int] = ...) -> None: ... class ReleaseSignal(_message.Message): __slots__ = ("route_session_id", "route_epoch", "work_id") @@ -409,18 +468,20 @@ class SessionRequest(_message.Message): def __init__(self, open: _Optional[_Union[SessionOpen, _Mapping]] = ..., chunk: _Optional[_Union[ActivationChunk, _Mapping]] = ..., decode: _Optional[_Union[DecodeStep, _Mapping]] = ..., flow_control: _Optional[_Union[FlowControl, _Mapping]] = ..., release: _Optional[_Union[ReleaseSignal, _Mapping]] = ..., cancel: _Optional[_Union[CancelSignal, _Mapping]] = ...) -> None: ... class SessionResponse(_message.Message): - __slots__ = ("accepted", "chunk", "ack", "flow_control", "status") + __slots__ = ("accepted", "chunk", "ack", "flow_control", "status", "tail_result") ACCEPTED_FIELD_NUMBER: _ClassVar[int] CHUNK_FIELD_NUMBER: _ClassVar[int] ACK_FIELD_NUMBER: _ClassVar[int] FLOW_CONTROL_FIELD_NUMBER: _ClassVar[int] STATUS_FIELD_NUMBER: _ClassVar[int] + TAIL_RESULT_FIELD_NUMBER: _ClassVar[int] accepted: SessionAccepted chunk: ActivationChunk ack: Ack flow_control: FlowControl status: ShardStatus - def __init__(self, accepted: _Optional[_Union[SessionAccepted, _Mapping]] = ..., chunk: _Optional[_Union[ActivationChunk, _Mapping]] = ..., ack: _Optional[_Union[Ack, _Mapping]] = ..., flow_control: _Optional[_Union[FlowControl, _Mapping]] = ..., status: _Optional[_Union[ShardStatus, _Mapping]] = ...) -> None: ... + tail_result: TailResult + def __init__(self, accepted: _Optional[_Union[SessionAccepted, _Mapping]] = ..., chunk: _Optional[_Union[ActivationChunk, _Mapping]] = ..., ack: _Optional[_Union[Ack, _Mapping]] = ..., flow_control: _Optional[_Union[FlowControl, _Mapping]] = ..., status: _Optional[_Union[ShardStatus, _Mapping]] = ..., tail_result: _Optional[_Union[TailResult, _Mapping]] = ...) -> None: ... class CapabilityRequest(_message.Message): __slots__ = ("schema_version",) diff --git a/packages/node/native/README.md b/packages/node/native/README.md index b5f6ed4..199b900 100644 --- a/packages/node/native/README.md +++ b/packages/node/native/README.md @@ -32,6 +32,15 @@ Both `--check` modes run in CI via `tests/test_native_shard_protocol.py`, so a schema edit that is not accompanied by regenerated output fails the suite rather than shipping stubs that disagree with the schema they claim to implement. +## DGR-006 decode and tail compatibility + +`DecodeStep.bundle` is the versioned `TensorBundle` fast-path boundary. It is +authoritative whenever present and supports architecture sidebands. The original +`DecodeStep.tensor` remains readable as the compact one-tensor encoding for +certified boundaries that need only one tensor; new readers wrap it into a +one-member bundle. Tail completions use `TailResult`, which binds logits or a +sampled token to request/recipe identity and sampling/template/reasoning inputs. + ## Building and running the C++ conformance test If the machine has no protobuf C++ toolchain: diff --git a/packages/node/native/proto/shard_runtime.proto b/packages/node/native/proto/shard_runtime.proto index cf97d96..16537cf 100644 --- a/packages/node/native/proto/shard_runtime.proto +++ b/packages/node/native/proto/shard_runtime.proto @@ -33,6 +33,16 @@ enum SchemaVersion { SCHEMA_VERSION_1 = 1; } +// Certified transformer boundary family. Names alone are not an adapter: a +// Node must select an explicit architecture contract before interpreting a +// TensorBundle. +enum ArchitectureType { + ARCHITECTURE_TYPE_UNSPECIFIED = 0; + ARCHITECTURE_TYPE_DENSE = 1; + ARCHITECTURE_TYPE_MOE = 2; + ARCHITECTURE_TYPE_MLA = 3; +} + // --------------------------------------------------------------------------- // Tensor bundle — the public activation boundary // --------------------------------------------------------------------------- @@ -142,6 +152,11 @@ message TensorBundle { // boundary payload can evolve without a whole-protocol version bump. uint32 bundle_version = 1; repeated NamedTensor tensors = 2; + // Explicit adapter selection; names are never interpreted through unchecked + // substitutions. UNSPECIFIED is accepted only for legacy DGR-002 bundles. + ArchitectureType architecture = 3; + // Adapter-owned semantic boundary, such as "pre_tail_residual". + string boundary_point = 4; } // --------------------------------------------------------------------------- @@ -393,8 +408,9 @@ message ActivationChunk { // A decode step is one token: the envelope's identity fields are already fixed // for the life of the stream, so repeating them per token is pure overhead on // the hottest path. A DecodeStep carries only what changes — the step, the -// position, and one tensor — and inherits the rest from the SessionOpen -// handshake. A peer may always fall back to ActivationChunk with PHASE_DECODE. +// position, and one compact boundary encoding — and inherits the rest from the +// SessionOpen handshake. A Node may always fall back to ActivationChunk with +// PHASE_DECODE. message DecodeStep { // Idempotency step within the session; also orders the stream. uint64 idempotency_step = 1; @@ -402,11 +418,50 @@ message DecodeStep { uint64 position = 2; // Tokens the receiver's cache must already hold. A mismatch is a CACHE_MISS. uint64 expected_past_len = 3; - // The single boundary tensor for this token, typically [1, 1, hidden]. + // Legacy compact one-tensor boundary, typically [1, 1, hidden]. New readers + // accept it as a TensorBundle with one member; writers retain it where the + // selected architecture genuinely requires only one tensor. NamedTensor tensor = 4; // Work id for attribution; the session/epoch/fingerprint/range are inherited. string work_id = 5; int64 deadline_unix_nanos = 6; + // Versioned architecture boundary. This carries sidebands such as MoE router + // state or MLA/IndexShare state; when both fields are set, bundle is + // authoritative and tensor is retained only for older-Node forwarding. + TensorBundle bundle = 7; +} + +// Exact request-level identity for a tail result. Runtime recipe identity is +// deliberately repeated here: sampling the right logits with the wrong chat +// template or reasoning mode is a different request, not a compatible result. +message RequestRecipeIdentity { + string request_id = 1; + string runtime_recipe_digest = 2; + string chat_template_id = 3; + string chat_template_version = 4; + string reasoning_mode = 5; + ArchitectureType architecture = 6; +} + +// Sampling is an explicit tail-only operation. A non-tail Shard never applies +// final norm, LM head, row pruning, or sampling to its boundary output. +message SamplingParameters { + float temperature = 1; + float top_p = 2; + uint32 top_k = 3; + uint64 seed = 4; + bool greedy = 5; +} + +// Typed tail completion. The oneof keeps token id 0 unambiguous and prevents a +// caller from treating an activation tensor as an inferred completion. +message TailResult { + RequestRecipeIdentity identity = 1; + SamplingParameters sampling = 2; + oneof output { + TensorBundle logits = 3; + uint32 sampled_token_id = 4; + } } // Drop session state for a Route Session. Bounded memory does not depend on @@ -471,7 +526,8 @@ message SessionResponse { ActivationChunk chunk = 2; Ack ack = 3; FlowControl flow_control = 4; - ShardStatus status = 5; + ShardStatus status = 5; + TailResult tail_result = 6; } } diff --git a/packages/node/native/testdata/decode_step_golden.binpb b/packages/node/native/testdata/decode_step_golden.binpb new file mode 100644 index 0000000..19cd72c Binary files /dev/null and b/packages/node/native/testdata/decode_step_golden.binpb differ diff --git a/packages/node/native/tests/test_shard_protocol_conformance.cpp b/packages/node/native/tests/test_shard_protocol_conformance.cpp index 966198f..c6f2f0a 100644 --- a/packages/node/native/tests/test_shard_protocol_conformance.cpp +++ b/packages/node/native/tests/test_shard_protocol_conformance.cpp @@ -265,7 +265,9 @@ void TestDecodeFastPathIsSmall() { step->set_position(1024); step->set_expected_past_len(1024); step->set_work_id("work-7f3a"); - sp::NamedTensor *tensor = step->mutable_tensor(); + sp::TensorBundle *bundle = step->mutable_bundle(); + bundle->set_bundle_version(1); + sp::NamedTensor *tensor = bundle->add_tensors(); tensor->set_name("hidden_states"); tensor->add_shape(1); tensor->add_shape(1); @@ -290,7 +292,27 @@ void TestDecodeFastPathIsSmall() { CHECK(parsed.ParseFromString(bytes)); CHECK(parsed.kind_case() == sp::SessionRequest::kDecode); CHECK_EQ(parsed.decode().position(), 1024u); - CHECK_EQ(parsed.decode().tensor().total_bytes(), 16u); + CHECK_EQ(parsed.decode().bundle().tensors_size(), 1); + CHECK_EQ(parsed.decode().bundle().tensors(0).total_bytes(), 16u); +} + +void TestDecodeBundleVector(const std::string &bytes) { + sp::SessionRequest request; + CHECK(request.ParseFromString(bytes)); + CHECK(request.kind_case() == sp::SessionRequest::kDecode); + const sp::DecodeStep &step = request.decode(); + CHECK_EQ(step.idempotency_step(), 43u); + CHECK_EQ(step.position(), 384u); + CHECK_EQ(step.expected_past_len(), 384u); + CHECK_EQ(step.work_id(), std::string("decode-7f3a")); + CHECK(step.has_bundle()); + CHECK_EQ(step.bundle().bundle_version(), 1u); + CHECK_EQ(step.bundle().architecture(), sp::ARCHITECTURE_TYPE_MLA); + CHECK_EQ(step.bundle().boundary_point(), std::string("pre_tail_residual")); + CHECK_EQ(step.bundle().tensors_size(), 2); + CHECK_EQ(step.bundle().tensors(0).name(), std::string("hidden_states")); + CHECK_EQ(step.bundle().tensors(1).name(), std::string("index_topk")); + CHECK_EQ(step.bundle().tensors(1).dtype(), sp::DTYPE_INT32); } } // namespace @@ -308,9 +330,11 @@ int main(int argc, char **argv) { ReadFile(testdata / "session_request_golden.binpb"); const std::string capability_bytes = ReadFile(testdata / "capability_report_golden.binpb"); + const std::string decode_bytes = ReadFile(testdata / "decode_step_golden.binpb"); TestSessionRequestVector(session_bytes); TestCapabilityReportVector(capability_bytes); + TestDecodeBundleVector(decode_bytes); TestUnknownFieldsArePreserved(session_bytes); TestSparseMessageParses(); TestDecodeFastPathIsSmall(); diff --git a/scripts/generate_protocol_goldens.py b/scripts/generate_protocol_goldens.py index 1936d16..63fa43e 100644 --- a/scripts/generate_protocol_goldens.py +++ b/scripts/generate_protocol_goldens.py @@ -33,6 +33,9 @@ def _vectors() -> dict[str, bytes]: conformance.GOLDEN_CAPABILITY_REPORT: conformance.serialize( conformance.canonical_capability_report() ), + conformance.GOLDEN_DECODE_STEP: conformance.serialize( + conformance.canonical_decode_step() + ), } diff --git a/tests/test_architecture_boundary.py b/tests/test_architecture_boundary.py new file mode 100644 index 0000000..70017e1 --- /dev/null +++ b/tests/test_architecture_boundary.py @@ -0,0 +1,121 @@ +"""DGR-006 architecture-defined activation-boundary contract.""" + +from __future__ import annotations + +import struct + +import pytest + +from meshnet_node.architecture_boundary import ( + Architecture, + BoundaryStage, + ProtocolIdentity, + SamplingParameters, + TailOutput, + adapter_for, +) +from meshnet_node.native_protocol import ProtocolError, decode_bundle + + +def _f32(values: list[float]) -> bytes: + return struct.pack("<" + "f" * len(values), *values) + + +def _values(payload: bytes) -> tuple[float, ...]: + return struct.unpack("<" + "f" * (len(payload) // 4), payload) + + +def test_dense_whole_model_and_two_ranges_match_for_prefill_and_greedy_decode() -> None: + adapter = adapter_for(Architecture.DENSE) + embeddings = {3: [1.0, 2.0], 7: [3.0, 4.0]} + head = adapter.bundle_from_token_ids([3, 7], lambda token: embeddings[token]) + + def head_layers(bundle): + return [value + 10.0 for value in _values(decode_bundle(bundle)["hidden_states"])] + + def tail_layers(residual: list[float]) -> tuple[list[float], int]: + # The tail alone applies this fixture's final norm/head and greedy argmax. + logits = [sum(residual) / len(residual) + 20.0, 0.0] + return logits, max(range(len(logits)), key=logits.__getitem__) + + # Whole-model prefill retains the unnormalized residual locally. The + # two-range lane sends that same residual before the tail-only head. + whole_prefill = head_layers(head) + seam = adapter.bundle_from_named_payloads( + {"hidden_states": _f32(whole_prefill)}, shape=[1, 2, 2] + ) + two_range_prefill = list(_values(decode_bundle(adapter.input_for(BoundaryStage.TAIL, seam))["hidden_states"])) + assert two_range_prefill == whole_prefill + + whole_logits, whole_token = tail_layers(whole_prefill) + two_logits, two_token = tail_layers(two_range_prefill) + assert two_logits == whole_logits + assert two_token == whole_token == 0 + + # One greedy decode step is the same contract with [batch, token, hidden]. + decode_seam = adapter.bundle_from_named_payloads( + {"hidden_states": _f32([5.0, 6.0])}, shape=[1, 1, 2] + ) + assert tail_layers([5.0, 6.0]) == tail_layers( + list(_values(decode_bundle(adapter.input_for(BoundaryStage.TAIL, decode_seam))["hidden_states"])) + ) + + +def test_middle_and_tail_reject_token_ids_and_require_boundary_bundle() -> None: + adapter = adapter_for(Architecture.MOE) + + with pytest.raises(ProtocolError, match="head"): + adapter.bundle_from_token_ids([1], lambda _: [1.0]) + + with pytest.raises(ProtocolError, match="TensorBundle"): + adapter.input_for(BoundaryStage.MIDDLE, None) + + +@pytest.mark.parametrize( + ("architecture", "names"), + [ + (Architecture.MOE, {"hidden_states", "router_logits"}), + (Architecture.MLA, {"hidden_states", "mla_position_state"}), + ], +) +def test_architecture_adapters_route_and_validate_their_named_sidebands( + architecture: Architecture, names: set[str] +) -> None: + adapter = adapter_for(architecture) + bundle = adapter.bundle_from_named_payloads( + { + name: (_f32([1.0, 2.0]) if name == "hidden_states" else _f32([0.0])) + for name in names + } + ) + + assert set(decode_bundle(adapter.input_for(BoundaryStage.MIDDLE, bundle))) == names + with pytest.raises(ProtocolError, match="requires"): + adapter.bundle_from_named_payloads({"hidden_states": _f32([1.0, 2.0])}) + + +def test_unknown_architecture_fails_closed() -> None: + with pytest.raises(ProtocolError, match="unsupported architecture"): + adapter_for("unchecked-name-substitution") + + +def test_typed_tail_result_binds_sampling_and_request_recipe_identity() -> None: + adapter = adapter_for(Architecture.DENSE) + identity = ProtocolIdentity( + request_id="request-1", + runtime_recipe_digest="sha256:recipe", + chat_template_id="llama3", + chat_template_version="2", + reasoning_mode="max", + architecture=Architecture.DENSE, + ) + result = adapter.tail_result( + identity=identity, + sampling=SamplingParameters(temperature=0.0, top_p=1.0, top_k=0, seed=9), + output=TailOutput.sampled_token(42), + ) + + assert result.identity.request_id == "request-1" + assert result.sampled_token_id == 42 + assert result.output_kind == "sampled_token_id" + assert result.message.WhichOneof("output") == "sampled_token_id" diff --git a/tests/test_native_shard_protocol.py b/tests/test_native_shard_protocol.py index bd50f5c..0410c62 100644 --- a/tests/test_native_shard_protocol.py +++ b/tests/test_native_shard_protocol.py @@ -34,6 +34,8 @@ from meshnet_node.native_protocol import ( ProtocolError, checksum_of, decode_bundle, + decode_step_bundle, + encode_decode_step, decode_tensor, default_flow_control, encode_bundle, @@ -429,7 +431,7 @@ def test_decode_fast_path_is_much_smaller_than_a_full_envelope_chunk(): idempotency_step=9, position=1024, expected_past_len=1024, - tensor=tensor, + bundle=encode_bundle([tensor]), work_id="work-7f3a", ) ) @@ -443,7 +445,48 @@ def test_decode_fast_path_is_much_smaller_than_a_full_envelope_chunk(): ) assert len(fast.SerializeToString()) * 2 < len(full.SerializeToString()) - assert decode_tensor(fast.decode.tensor) == hidden + assert decode_step_bundle(fast.decode) == {HIDDEN_STATES: hidden} + + +def test_decode_fast_path_preserves_legacy_one_tensor_compatibility(): + tensor = encode_tensor(HIDDEN_STATES, b"\x01\x02" * 8, [1, 1, 8], pb.DTYPE_BFLOAT16) + legacy = pb.DecodeStep(tensor=tensor) + + assert decode_step_bundle(legacy) == {HIDDEN_STATES: b"\x01\x02" * 8} + + +def test_decode_bundle_wins_over_legacy_tensor_and_can_carry_sidebands(): + hidden = encode_tensor(HIDDEN_STATES, b"\x01\x02" * 8, [1, 1, 8], pb.DTYPE_BFLOAT16) + sideband = encode_tensor("index_topk", b"\x00" * 4, [1], pb.DTYPE_INT32) + decode = pb.DecodeStep(tensor=hidden, bundle=encode_bundle([hidden, sideband])) + + assert decode_step_bundle(decode) == { + HIDDEN_STATES: b"\x01\x02" * 8, + "index_topk": b"\x00" * 4, + } + + +def test_decode_writer_uses_compact_tensor_only_for_a_certified_one_tensor_bundle(): + hidden = encode_tensor(HIDDEN_STATES, b"\x01\x02" * 8, [1, 1, 8], pb.DTYPE_BFLOAT16) + compact = encode_decode_step( + encode_bundle([hidden]), idempotency_step=1, position=1, expected_past_len=1, work_id="w" + ) + sideband = encode_tensor("index_topk", b"\x00" * 4, [1], pb.DTYPE_INT32) + expanded = encode_decode_step( + encode_bundle([hidden, sideband]), idempotency_step=1, position=1, expected_past_len=1, work_id="w" + ) + + assert compact.HasField("tensor") and not compact.HasField("bundle") + assert expanded.HasField("bundle") and not expanded.HasField("tensor") + + +def test_schema_exposes_typed_tail_result_and_bound_sampling_identity(): + assert {"identity", "sampling", "logits", "sampled_token_id"} <= set( + pb.TailResult.DESCRIPTOR.fields_by_name + ) + assert {"request_id", "runtime_recipe_digest", "chat_template_id", "chat_template_version", "reasoning_mode"} <= set( + pb.RequestRecipeIdentity.DESCRIPTOR.fields_by_name + ) def test_flow_control_defaults_bound_the_queue_and_the_message(): @@ -491,6 +534,20 @@ def test_committed_vectors_still_encode_as_promised(): report = (conformance.TESTDATA_DIR / conformance.GOLDEN_CAPABILITY_REPORT).read_bytes() assert conformance.serialize(conformance.canonical_capability_report()) == report + decode = (conformance.TESTDATA_DIR / conformance.GOLDEN_DECODE_STEP).read_bytes() + assert conformance.serialize(conformance.canonical_decode_step()) == decode + + +def test_decode_golden_preserves_the_multi_tensor_boundary(): + golden = (conformance.TESTDATA_DIR / conformance.GOLDEN_DECODE_STEP).read_bytes() + request = pb.SessionRequest.FromString(golden) + + assert request.decode.idempotency_step == 43 + assert decode_step_bundle(request.decode) == { + HIDDEN_STATES: bytes(range(16)), + "index_topk": (3).to_bytes(4, "little"), + } + def test_golden_session_request_round_trips_with_every_field_intact(): golden = (conformance.TESTDATA_DIR / conformance.GOLDEN_SESSION_REQUEST).read_bytes()