@fibril/can-core 0.1.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["#pending","#now","readU64Le","#buf","#blobTotalLen","packOneScalar","#onError","#now","#unsubFrame","#buckets","#ownedByNode","#latest","#listeners","#onFrame","#version","#err","#publish","#freePool","#next","I_TOKEN","expandIToken","joinPath","#handle","#topicsByPath","#servicesByPath","#paramsByPath","#topicsByIndex","#servicesByIndex","#paramsByIndex","#next","#reset","#buffer","#transport","#defaultTimeoutMs","#now","#nextCallId","#pending","#unsub","#onFrame","#detachAbort","#allocCallId","#sendCancel","#finishMaybeAccepted","#client","#client","#transport","#framePlan","#ackTimeoutMs","#schemaChunkSize","#schemaReadRetries","#heartbeatTimeoutMs","#autoStart","#onState","#onError","#now","#seq","#acks","#services","#blobCache","#state","#snapshot","#stopped","#unsubFrame","#onFrame","#sweepHandle","#sweep","#setState","#announce","#reprovisionState","#beginBringUp","#error","#schemaRead","#provisioning","#pendingStart","#handleAnnounce","#handleHeartbeat","#handleSchemaData","#lastHeartbeatMs","#enterLost","#onSchemaReadStall","#startSchemaRead","#issueSchemaReadChunk","#finishSchemaRead","#generation","#maybeIssueStart","#onFrameDefineOutcome","#issueStart","#onStartOutcome","#transport","#framePlan","#heartbeatBroadcaster","#dataPlane","#discoverPeriodMs","#initialDiscover","#ackTimeoutMs","#heartbeatTimeoutMs","#serviceTimeoutMs","#autoStart","#now","#onError","#slaves","#listeners","#started","#unsubFrame","#onFrame","#error","#discoverHandle","#emit","#ensureSlave"],"sources":["../src/ack-tracker.ts","../src/can-id.ts","../src/dlc.ts","../src/config-plane.ts","../src/scalar-codec.ts","../src/proto-reader.ts","../src/schema.ts","../src/dynamic-codec.ts","../src/data-plane.ts","../src/frame-planner.ts","../src/default-plan.ts","../src/master-heartbeat.ts","../src/numbering.ts","../src/schema-hash.ts","../src/schema-index.ts","../src/seq-allocator.ts","../src/segmented-transfer.ts","../src/service-client.ts","../src/typed-param.ts","../src/typed-service.ts","../src/node-agent.ts","../src/master-controller.ts"],"sourcesContent":["/**\n * In-flight ACK/NAK ledger keyed by `seq`. Mirrors the per-node `AckEntry`\n * map in `fibril_can_bridge/include/fibril_can_bridge/node_agent.hpp` but\n * pared down for the single-threaded TS master — no deadlines list, the\n * caller polls via {@link sweep}.\n */\n\nexport type AckOutcome =\n | { kind: 'acked' }\n | { kind: 'naked'; reason: number }\n | { kind: 'timed-out' };\n\nexport type AckCallback = (outcome: AckOutcome) => void;\n\ninterface AckEntry {\n deadlineMs: number;\n cb: AckCallback;\n}\n\nexport class AckTracker {\n readonly #pending = new Map<number, AckEntry>();\n readonly #now: () => number;\n\n constructor(now: () => number = () => Date.now()) {\n this.#now = now;\n }\n\n get pendingCount(): number {\n return this.#pending.size;\n }\n\n /** Returns false if `seq` is already tracked; the existing entry is kept. */\n track(seq: number, deadlineMs: number, cb: AckCallback): boolean {\n const key = seq & 0xff;\n if (this.#pending.has(key)) return false;\n this.#pending.set(key, { deadlineMs, cb });\n return true;\n }\n\n /** Idempotent — fires `acked` if `seq` is pending. */\n onAck(seq: number): void {\n const key = seq & 0xff;\n const e = this.#pending.get(key);\n if (!e) return;\n this.#pending.delete(key);\n e.cb({ kind: 'acked' });\n }\n\n /** Idempotent — fires `naked` with the reason if `seq` is pending. */\n onNak(seq: number, reason: number): void {\n const key = seq & 0xff;\n const e = this.#pending.get(key);\n if (!e) return;\n this.#pending.delete(key);\n e.cb({ kind: 'naked', reason });\n }\n\n /** Fire `timed-out` for every entry whose deadline elapsed by `nowMs`. */\n sweep(nowMs: number = this.#now()): void {\n for (const [seq, entry] of this.#pending) {\n if (entry.deadlineMs <= nowMs) {\n this.#pending.delete(seq);\n entry.cb({ kind: 'timed-out' });\n }\n }\n }\n\n /** Drop every entry without firing callbacks. Test-only. */\n clear(): void {\n this.#pending.clear();\n }\n}\n","/**\n * CAN ID layout (Extended) and config-plane / NAK / svc-status / node-state\n * constants. Mirrors SPEC §3, §5, §7 and `fibril_can_runtime/include/fibril_can/fcan_protocol.h`\n * / `fibril_can_bridge/include/fibril_can_bridge/can_id.hpp`.\n *\n * Extended ID layout (29 bit, §3.2):\n * [28:26] channel (3 bit)\n * [25:19] node_id (7 bit, 0x7F = broadcast)\n * [18:11] index (8 bit, service_index / cmd_code)\n * [10:3] seq (8 bit, call_id / seq_num)\n * [2] seg (1 bit, 0=SINGLE, 1=SEGMENT)\n * [1:0] reserved (2 bit, 0)\n *\n * Standard ID (11 bit, §3.1) is dynamically allocated by the master and\n * has no fixed bitfield meaning — kept here only as the wire mask.\n */\n\n// Highest protocol_version this package decodes in full. Higher values\n// still parse.\nexport const PROTOCOL_VERSION = 2;\nexport const MAX_FRAME_PAYLOAD = 64;\n\n// Channel (§3.2)\nexport const CHAN_CONFIG = 0;\nexport const CHAN_SVC_REQUEST = 1;\nexport const CHAN_SVC_RESPONSE = 2;\n\nexport const NODE_ID_BROADCAST = 0x7f;\n\n// Standard ID mask (§3.1)\nexport const STD_ID_MASK = 0x7ff;\n\n// Reserved service indices (§3.3)\nexport const SVC_PARAM_SET = 0xfd;\nexport const SVC_CANCEL = 0xff;\nexport const SVC_MAX_FIRST_CLASS = 0xfc;\n\n// Config-plane command codes (§5.2)\nexport const CMD_DISCOVER = 0x01;\nexport const CMD_ANNOUNCE = 0x02;\nexport const CMD_SCHEMA_READ = 0x03;\nexport const CMD_SCHEMA_DATA = 0x04;\nexport const CMD_HEARTBEAT = 0x05;\nexport const CMD_MASTER_HEARTBEAT = 0x07;\nexport const CMD_FRAME_DEFINE = 0x10;\nexport const CMD_HB_PERIOD = 0x13;\nexport const CMD_START = 0x20;\nexport const CMD_STOP = 0x21;\nexport const CMD_ACK = 0x7e;\nexport const CMD_NAK = 0x7f;\n\n// NAK reason codes (§5.9)\nexport const NAK_UNKNOWN_CMD = 0x01;\nexport const NAK_BAD_LENGTH = 0x02;\nexport const NAK_BAD_PARAM = 0x03;\nexport const NAK_NO_RESOURCE = 0x04;\nexport const NAK_BAD_STATE = 0x05;\nexport const NAK_ID_CONFLICT = 0x06;\nexport const NAK_INDEX_RANGE = 0x07;\nexport const NAK_DIR_MISMATCH = 0x08;\nexport const NAK_SIZE_OVERFLOW = 0x09;\n\n// Node states (§2.4)\nexport const STATE_UNPROVISIONED = 0;\nexport const STATE_PROVISIONED = 1;\nexport const STATE_RUNNING = 2;\nexport const STATE_FAULT = 3;\nexport const STATE_SUSPENDED = 4;\n\n/** Human-readable name for a node_state byte. Unknown values → `unknown(N)`. */\nexport function stateName(state: number): string {\n switch (state) {\n case STATE_UNPROVISIONED:\n return \"UNPROVISIONED\";\n case STATE_PROVISIONED:\n return \"PROVISIONED\";\n case STATE_RUNNING:\n return \"RUNNING\";\n case STATE_FAULT:\n return \"FAULT\";\n case STATE_SUSPENDED:\n return \"SUSPENDED\";\n default:\n return `unknown(${state})`;\n }\n}\n\n// Fault summary (§5.8)\nexport const FAULT_NONE = 0;\nexport const FAULT_NOMEM = 1;\nexport const FAULT_INDEX_OVERFLOW = 2;\nexport const FAULT_ID_CONFLICT = 3;\n\n// Direction (§5.6 of FRAME_DEFINE)\nexport const DIR_TX_S2M = 0;\nexport const DIR_RX_M2S = 1;\n\n// Service status (§7.2)\nexport const SVC_OK = 0x00;\nexport const SVC_ACCEPTED = 0x01;\nexport const SVC_APP_ERROR = 0x02;\nexport const SVC_BUSY = 0x03;\nexport const SVC_UNAVAIL = 0x04;\nexport const SVC_BAD_INDEX = 0x05;\nexport const SVC_BAD_VALUE = 0x06;\nexport const SVC_BAD_LENGTH = 0x08;\n\n// Segmented service transfer (§7.4)\nexport const SEG_FIRST_DATA = 61;\nexport const SEG_REST_DATA = 63;\nexport const SEG_MAX_TOTAL = 1024;\nexport const SEG_MAX_SEQ = 31;\n\n/** Byte offset of segment `seq` within the reassembled buffer (§7.4). */\nexport function segOffset(seq: number): number {\n return seq === 0 ? 0 : SEG_FIRST_DATA + (seq - 1) * SEG_REST_DATA;\n}\n\n/**\n * Build a 29-bit Extended ID from its bitfields (§3.2). Inputs are masked\n * down to their respective field widths.\n */\nexport function makeExtId(\n channel: number,\n nodeId: number,\n index: number,\n seq: number,\n seg = 0,\n): number {\n return (\n (((channel & 0x7) << 26) |\n ((nodeId & 0x7f) << 19) |\n ((index & 0xff) << 11) |\n ((seq & 0xff) << 3) |\n ((seg & 0x1) << 2)) >>>\n 0\n );\n}\n\nexport function extChannel(id: number): number {\n return (id >>> 26) & 0x7;\n}\nexport function extNodeId(id: number): number {\n return (id >>> 19) & 0x7f;\n}\nexport function extIndex(id: number): number {\n return (id >>> 11) & 0xff;\n}\nexport function extSeq(id: number): number {\n return (id >>> 3) & 0xff;\n}\nexport function extSeg(id: number): number {\n return (id >>> 2) & 0x1;\n}\n","import { MAX_FRAME_PAYLOAD } from './can-id.js';\n\n/**\n * CAN FD valid payload sizes in ascending order (§4.3).\n * Mirrors `fibril_can_core/include/fibril_can_core/packing.hpp::kCanFdDlcSteps`\n * and `fibril_can_runtime/src/fcan_wire.c::fcan_quantize_dlc`.\n */\nexport const FD_DLC_STEPS = Object.freeze([\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64,\n]) as readonly number[];\n\n/**\n * Round `bytes` up to the next valid CAN FD payload step. Returns 64 for any\n * input ≥ 64.\n */\nexport function quantizeDlc(bytes: number): number {\n if (bytes >= MAX_FRAME_PAYLOAD) return MAX_FRAME_PAYLOAD;\n for (const step of FD_DLC_STEPS) {\n if (step >= bytes) return step;\n }\n return MAX_FRAME_PAYLOAD;\n}\n\n/**\n * Grow `data` to the next DLC step by appending zero bytes. Returns a new\n * Uint8Array. Never shrinks: if `data` already exceeds 64 bytes (which is\n * a self-inconsistent frame the slave would misparse), the original is\n * returned unchanged so the backend rejects it loudly (parity with\n * `pad_to_dlc` in `fibril_can_bridge/src/config_plane_codec.cpp`).\n */\nexport function padToDlc(data: Uint8Array): Uint8Array {\n if (data.length >= MAX_FRAME_PAYLOAD) return data;\n const padded = new Uint8Array(quantizeDlc(data.length));\n padded.set(data);\n return padded;\n}\n","import type { CanFrameTx } from '@fibril/can-transport';\nimport {\n CHAN_CONFIG,\n CMD_DISCOVER,\n CMD_FRAME_DEFINE,\n CMD_MASTER_HEARTBEAT,\n CMD_SCHEMA_READ,\n CMD_START,\n CMD_STOP,\n makeExtId,\n NODE_ID_BROADCAST,\n} from './can-id.js';\nimport { padToDlc } from './dlc.js';\n\n/**\n * Config-plane wire codec. Mirrors\n * `fibril_can_bridge/include/fibril_can_bridge/config_plane_codec.hpp`\n * and `fibril_can_bridge/src/config_plane_codec.cpp`.\n *\n * All integers are little-endian. Decoders return `null` on malformed input\n * (wrong length etc.); encoders produce CAN frames padded to the next DLC\n * step, matching what the slave sees on the bus.\n */\n\n// ---------------------------------------------------------------------------\n// Message shapes (decoded form of S→M payloads)\n// ---------------------------------------------------------------------------\n\n/** ANNOUNCE payload (S→M, §5.4). */\nexport interface AnnounceMsg {\n schemaHash: bigint;\n protocolVersion: number;\n bootId: number;\n blobLen: number;\n /** Length K, indexed by block-type ordinal. */\n instanceCounts: Uint8Array;\n}\n\n/** HEARTBEAT payload (S→M, §5.8). */\nexport interface HeartbeatMsg {\n bootId: number;\n state: number;\n faultSummary: number;\n}\n\n/** SCHEMA_DATA payload (S→M, §5.5). */\nexport interface SchemaDataMsg {\n offset: number;\n bytes: Uint8Array;\n}\n\n/** NAK payload (S→M, §5.9). */\nexport interface NakMsg {\n cmd: number;\n reason: number;\n}\n\n/** One entry inside a FRAME_DEFINE command (§5.6). */\nexport interface FrameDefineEntry {\n topicIndex: number;\n fieldBitmask: number;\n}\n\n// ---------------------------------------------------------------------------\n// Little-endian primitive helpers (private)\n// ---------------------------------------------------------------------------\n\nfunction readU32Le(p: Uint8Array, off: number): number {\n return (\n ((p[off] ?? 0) |\n ((p[off + 1] ?? 0) << 8) |\n ((p[off + 2] ?? 0) << 16) |\n ((p[off + 3] ?? 0) << 24)) >>>\n 0\n );\n}\nfunction readU64Le(p: Uint8Array, off: number): bigint {\n let r = 0n;\n for (let i = 0; i < 8; i++) {\n r |= BigInt(p[off + i] ?? 0) << BigInt(i * 8);\n }\n return r;\n}\nfunction pushU16(buf: number[], x: number): void {\n buf.push(x & 0xff, (x >>> 8) & 0xff);\n}\nfunction pushU32(buf: number[], x: number): void {\n buf.push(x & 0xff, (x >>> 8) & 0xff, (x >>> 16) & 0xff, (x >>> 24) & 0xff);\n}\n\n// ---------------------------------------------------------------------------\n// Decoders\n// ---------------------------------------------------------------------------\n\nexport function decodeAnnounce(data: Uint8Array): AnnounceMsg | null {\n if (data.length < 18) return null;\n const k = data[17] ?? 0;\n if (data.length < 18 + k) return null;\n return {\n schemaHash: readU64Le(data, 0),\n protocolVersion: data[8] ?? 0,\n bootId: readU32Le(data, 9),\n blobLen: readU32Le(data, 13),\n instanceCounts: data.slice(18, 18 + k),\n };\n}\n\nexport function decodeHeartbeat(data: Uint8Array): HeartbeatMsg | null {\n if (data.length < 6) return null;\n return {\n bootId: readU32Le(data, 0),\n state: data[4] ?? 0,\n faultSummary: data[5] ?? 0,\n };\n}\n\nexport function decodeSchemaData(data: Uint8Array): SchemaDataMsg | null {\n if (data.length < 4) return null;\n return {\n offset: readU32Le(data, 0),\n bytes: data.slice(4),\n };\n}\n\nexport function decodeNak(data: Uint8Array): NakMsg | null {\n if (data.length < 2) return null;\n return { cmd: data[0] ?? 0, reason: data[1] ?? 0 };\n}\n\n// ---------------------------------------------------------------------------\n// Encoders — master-initiated commands\n// ---------------------------------------------------------------------------\n\nfunction configFrame(nodeId: number, cmd: number, seq: number, data: Uint8Array): CanFrameTx {\n // fibril_can is CAN-FD only (SPEC §3, MAX_FRAME_PAYLOAD=64). Mark every\n // emitted frame as FD so transports (gs_usb) don't fall back to the\n // 8-byte classic cap when our payload is quantized to a 12/16/20/24/…\n // FD DLC step.\n return {\n id: makeExtId(CHAN_CONFIG, nodeId, cmd, seq, 0),\n extended: true,\n fd: true,\n data,\n };\n}\n\n/** Broadcast DISCOVER — all nodes re-announce and clear their frame tables. */\nexport function encodeDiscover(): CanFrameTx {\n return configFrame(NODE_ID_BROADCAST, CMD_DISCOVER, 0, new Uint8Array(0));\n}\n\n/** Targeted DISCOVER for a single node (§5.11 reprovisioning). */\nexport function encodeDiscoverTo(nodeId: number): CanFrameTx {\n return configFrame(nodeId, CMD_DISCOVER, 0, new Uint8Array(0));\n}\n\n/** Broadcast MASTER_HEARTBEAT (§5.11). Refreshes slave master-lost watchdogs. */\nexport function encodeMasterHeartbeat(): CanFrameTx {\n return configFrame(NODE_ID_BROADCAST, CMD_MASTER_HEARTBEAT, 0, new Uint8Array(0));\n}\n\nexport function encodeSchemaRead(\n nodeId: number,\n offset: number,\n length: number,\n seq: number,\n): CanFrameTx {\n const buf: number[] = [];\n pushU32(buf, offset);\n buf.push(length & 0xff);\n return configFrame(nodeId, CMD_SCHEMA_READ, seq, padToDlc(new Uint8Array(buf)));\n}\n\nexport function encodeFrameDefine(\n nodeId: number,\n seq: number,\n stdId: number,\n periodUs: number,\n dir: number,\n entries: readonly FrameDefineEntry[],\n): CanFrameTx {\n const buf: number[] = [];\n pushU16(buf, stdId);\n pushU32(buf, periodUs);\n buf.push(dir & 0xff);\n buf.push(entries.length & 0xff);\n for (const e of entries) {\n pushU16(buf, e.topicIndex);\n pushU16(buf, e.fieldBitmask);\n }\n return configFrame(nodeId, CMD_FRAME_DEFINE, seq, padToDlc(new Uint8Array(buf)));\n}\n\nexport function encodeStart(nodeId: number, seq: number): CanFrameTx {\n return configFrame(nodeId, CMD_START, seq, new Uint8Array(0));\n}\n\nexport function encodeStop(nodeId: number, seq: number): CanFrameTx {\n return configFrame(nodeId, CMD_STOP, seq, new Uint8Array(0));\n}\n\n// ---------------------------------------------------------------------------\n// Schema blob reassembly\n// ---------------------------------------------------------------------------\n\n/**\n * Accumulator for SCHEMA_DATA chunks. The slave DLC-pads each response (§4.3)\n * so `chunk.bytes.length` is typically larger than what the master requested;\n * the accumulator clips against `expectedChunkLen` and the remaining blob\n * length to drop those padding bytes (parity with\n * `append_schema_chunk` in `fibril_can_bridge/src/config_plane_codec.cpp`).\n *\n * Out-of-order chunks are rejected (returns 0 from {@link append}).\n */\nexport class SchemaAccumulator {\n readonly #buf: number[] = [];\n readonly #blobTotalLen: number;\n\n constructor(blobTotalLen: number) {\n this.#blobTotalLen = blobTotalLen;\n }\n\n get length(): number {\n return this.#buf.length;\n }\n\n get blobTotalLen(): number {\n return this.#blobTotalLen;\n }\n\n get complete(): boolean {\n return this.#buf.length >= this.#blobTotalLen;\n }\n\n bytes(): Uint8Array {\n return new Uint8Array(this.#buf);\n }\n\n /**\n * Append `chunk` if its offset matches the current accumulator length.\n * Returns the number of bytes actually appended (0 on rejection).\n */\n append(chunk: SchemaDataMsg, expectedChunkLen: number): number {\n if (chunk.offset !== this.#buf.length) return 0;\n const remaining = Math.max(0, this.#blobTotalLen - chunk.offset);\n const cap = Math.min(expectedChunkLen, remaining);\n const take = Math.min(chunk.bytes.length, cap);\n for (let i = 0; i < take; i++) {\n this.#buf.push(chunk.bytes[i] ?? 0);\n }\n return take;\n }\n}\n","/**\n * Scalar type enumeration and little-endian wire codecs. Mirrors\n * `fibril_can_core/include/fibril_can_core/scalar_type.hpp` and\n * `fibril_can_core/src/scalar_type.cpp`.\n *\n * Type ordinal values are part of the protobuf schema blob's enum, so they\n * must not be renumbered.\n */\n\nexport enum ScalarType {\n Bool = 0,\n U8 = 1,\n I8 = 2,\n U16 = 3,\n I16 = 4,\n U32 = 5,\n I32 = 6,\n U64 = 7,\n I64 = 8,\n F32 = 9,\n F64 = 10,\n}\n\nexport const SCALAR_NAMES = Object.freeze([\n 'bool',\n 'u8',\n 'i8',\n 'u16',\n 'i16',\n 'u32',\n 'i32',\n 'u64',\n 'i64',\n 'f32',\n 'f64',\n]) as readonly string[];\n\n/** Wire size in bytes of one scalar element. bool is 1 byte. */\nexport function scalarSize(type: ScalarType): number {\n switch (type) {\n case ScalarType.Bool:\n case ScalarType.U8:\n case ScalarType.I8:\n return 1;\n case ScalarType.U16:\n case ScalarType.I16:\n return 2;\n case ScalarType.U32:\n case ScalarType.I32:\n case ScalarType.F32:\n return 4;\n case ScalarType.U64:\n case ScalarType.I64:\n case ScalarType.F64:\n return 8;\n }\n}\n\nexport function scalarName(type: ScalarType): string | undefined {\n return SCALAR_NAMES[type];\n}\n\nexport function scalarFromName(name: string): ScalarType | undefined {\n const idx = SCALAR_NAMES.indexOf(name);\n return idx >= 0 ? (idx as ScalarType) : undefined;\n}\n\n/**\n * Pack an integer / bool value as little-endian bytes into `out` at `offset`.\n * Writes scalarSize(type) bytes — pass a wide-enough `out`.\n *\n * Pass `bigint` for 64-bit types (U64/I64). `number` is accepted for\n * everything (it is internally widened to bigint so signed callers get the\n * same sign-extension semantics as the C++ `pack_scalar_int_le(uint64_t)`).\n * Signed callers pass the negative number directly; the function performs the\n * 64-bit two's-complement cast.\n */\nexport function packScalarIntLe(\n type: ScalarType,\n value: number | bigint,\n out: Uint8Array,\n offset = 0,\n): void {\n const bytes = scalarSize(type);\n const mask = (1n << 64n) - 1n;\n const bits = (typeof value === 'bigint' ? value : BigInt(value)) & mask;\n for (let i = 0; i < bytes; i++) {\n out[offset + i] = Number((bits >> BigInt(i * 8)) & 0xffn);\n }\n}\n\n/** Bit-cast a float32 to its IEEE-754 little-endian representation. */\nexport function packScalarF32Le(value: number, out: Uint8Array, offset = 0): void {\n new DataView(out.buffer, out.byteOffset, out.byteLength).setFloat32(offset, value, true);\n}\n\n/** Bit-cast a float64 to its IEEE-754 little-endian representation. */\nexport function packScalarF64Le(value: number, out: Uint8Array, offset = 0): void {\n new DataView(out.buffer, out.byteOffset, out.byteLength).setFloat64(offset, value, true);\n}\n\n/**\n * Inverse of {@link packScalarIntLe}. Returns the raw bit pattern as bigint;\n * caller interprets sign via {@link sign-extend} helpers below.\n */\nexport function unpackScalarIntLe(type: ScalarType, src: Uint8Array, offset = 0): bigint {\n const bytes = scalarSize(type);\n let bits = 0n;\n for (let i = 0; i < bytes; i++) {\n bits |= BigInt(src[offset + i] ?? 0) << BigInt(i * 8);\n }\n return bits;\n}\n\nexport function unpackScalarF32Le(src: Uint8Array, offset = 0): number {\n return new DataView(src.buffer, src.byteOffset, src.byteLength).getFloat32(offset, true);\n}\n\nexport function unpackScalarF64Le(src: Uint8Array, offset = 0): number {\n return new DataView(src.buffer, src.byteOffset, src.byteLength).getFloat64(offset, true);\n}\n\n/**\n * Sign-extend a bigint that was read as an unsigned `bytes`-byte field to a\n * signed bigint. Useful for I8/I16/I32/I64 after {@link unpackScalarIntLe}.\n */\nexport function signExtend(bits: bigint, bytes: number): bigint {\n const width = BigInt(bytes * 8);\n const signBit = 1n << (width - 1n);\n return (bits & signBit) === 0n ? bits : bits - (1n << width);\n}\n","/**\n * Minimal proto3 wire-format reader.\n *\n * Implements the strict subset of the protobuf wire format that the\n * fibril_can schema blob uses: varint (wire-type 0) and length-delimited\n * (wire-type 2). Fixed32 / fixed64 / group are skipped harmlessly so unknown\n * future fields do not crash the reader.\n *\n * https://protobuf.dev/programming-guides/encoding/\n */\n\nexport const WIRE_VARINT = 0;\nconst WIRE_FIXED64 = 1;\nexport const WIRE_LENGTH_DELIM = 2;\nconst WIRE_FIXED32 = 5;\n\nexport class ProtoReader {\n private pos = 0;\n\n constructor(\n private readonly buf: Uint8Array,\n private readonly end: number = buf.length,\n ) {}\n\n get done(): boolean {\n return this.pos >= this.end;\n }\n get position(): number {\n return this.pos;\n }\n\n /** Read a base-128 varint as a JS number (overflows ≥ 2^53 wrap silently). */\n readVarint(): number {\n let result = 0;\n let shift = 0;\n while (this.pos < this.end) {\n const b = this.buf[this.pos++];\n if (b === undefined) throw new ProtoError('truncated varint');\n // Promote to bigint at shift ≥ 28 to avoid losing high bits in 32-bit\n // bit-ops. We only ever use this for small uint32 fields though, so\n // staying in Number domain is fine for our schema.\n result |= (b & 0x7f) << shift;\n if ((b & 0x80) === 0) return result >>> 0;\n shift += 7;\n if (shift >= 32) {\n // For our schema this should never happen (no uint64 fields used).\n // Drain remaining bytes and return the low 32 bits.\n while (this.pos < this.end) {\n const c = this.buf[this.pos++];\n if (c === undefined) throw new ProtoError('truncated varint');\n if ((c & 0x80) === 0) break;\n }\n return result >>> 0;\n }\n }\n throw new ProtoError('truncated varint');\n }\n\n /** Read a length-delimited byte slice (no copy). */\n readBytes(): Uint8Array {\n const len = this.readVarint();\n if (this.pos + len > this.end) throw new ProtoError('truncated length-delimited field');\n const slice = this.buf.subarray(this.pos, this.pos + len);\n this.pos += len;\n return slice;\n }\n\n /** Read a length-delimited UTF-8 string. */\n readString(): string {\n const bytes = this.readBytes();\n return new TextDecoder('utf-8', { fatal: false }).decode(bytes);\n }\n\n /** Read a length-delimited sub-message and return a new reader scoped to it. */\n readMessage(): ProtoReader {\n const bytes = this.readBytes();\n return new ProtoReader(bytes);\n }\n\n /**\n * Read the next tag and return both the field number and wire type. The\n * caller is expected to dispatch on field number; unknown fields can be\n * passed to {@link skipValue}.\n */\n readTag(): { field: number; wire: number } {\n const tag = this.readVarint();\n return { field: tag >>> 3, wire: tag & 0x7 };\n }\n\n /** Discard the value associated with `wire`. Used to tolerate unknown fields. */\n skipValue(wire: number): void {\n switch (wire) {\n case WIRE_VARINT:\n this.readVarint();\n return;\n case WIRE_LENGTH_DELIM:\n this.readBytes();\n return;\n case WIRE_FIXED32:\n if (this.pos + 4 > this.end) throw new ProtoError('truncated fixed32');\n this.pos += 4;\n return;\n case WIRE_FIXED64:\n if (this.pos + 8 > this.end) throw new ProtoError('truncated fixed64');\n this.pos += 8;\n return;\n default:\n throw new ProtoError(`unsupported wire type ${wire}`);\n }\n }\n}\n\nexport class ProtoError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ProtoError';\n }\n}\n","import { PROTOCOL_VERSION } from './can-id.js';\nimport { ProtoError, ProtoReader } from './proto-reader.js';\nimport { ScalarType, scalarSize } from './scalar-codec.js';\n\n/**\n * NodeSchema IR + protobuf decoder for the schema blob (§9).\n *\n * Mirrors `fibril_can_core/include/fibril_can_core/ir.hpp` and\n * `fibril_can_core/src/schema_blob.cpp::parse_schema`. Field IDs come from\n * `fibril_can_core/proto/fibril_can.proto`.\n *\n * Master-side notes:\n * - The proto carries `topic_id` / `service_id` / `param_id` / BlockType\n * `type_id` for codegen stability; the master derives equivalent indices\n * from {@link computeNumbering} instead, so these are accepted but\n * discarded on parse.\n * - The proto wire field is `tx_disabled` while the IR holds `tx_enabled`\n * (inverted, matches the C++ side).\n * - `BlockArray.type_id` (proto) → `BlockArray.blockTypeIndex` (IR).\n *\n * The reader skips unknown fields silently so future schema additions do\n * not break old masters.\n */\n\n// --- Field numbers (proto3) ---------------------------------------------------\n\nconst FIELD = {\n Field: {\n name: 1,\n type: 2,\n arrayLen: 3,\n periodUsOverride: 4,\n txDisabled: 5,\n },\n RosMapping: {\n rosType: 1,\n rosName: 2,\n fieldMap: 3,\n },\n Topic: {\n name: 2,\n dir: 3,\n fields: 4,\n defaultPeriodUs: 5,\n ros: 6,\n },\n Service: {\n name: 2,\n request: 3,\n response: 4,\n ros: 5,\n },\n Param: {\n name: 2,\n type: 3,\n arrayLen: 4,\n defaultValue: 5,\n minValue: 6,\n maxValue: 7,\n },\n BlockType: {\n name: 2,\n topics: 3,\n services: 4,\n params: 5,\n },\n BlockArray: {\n typeId: 1,\n rosNamespace: 2,\n },\n Limits: {\n paramSetBatchBytes: 1,\n },\n NodeSchema: {\n protocolVersion: 1,\n nodeName: 2,\n types: 3,\n instances: 4,\n limits: 5,\n },\n} as const;\n\n// --- IR ---------------------------------------------------------------------\n\nexport enum Direction {\n M2S = 0,\n S2M = 1,\n}\n\nexport interface SchemaField {\n name: string;\n type: ScalarType;\n /** 0 = scalar; >0 = fixed-length array of `type`. */\n arrayLen: number;\n /** Per-field override of the owning topic's defaultPeriodUs; undefined = inherit. */\n periodUsOverride?: number;\n /** Master-side planner skips this field if false. Defaults to true. */\n txEnabled: boolean;\n}\n\nexport interface RosMapping {\n rosType: string;\n rosName: string;\n fieldMap: string[];\n}\n\nexport interface SchemaTopic {\n name: string;\n dir: Direction;\n fields: SchemaField[];\n defaultPeriodUs: number;\n ros: RosMapping;\n}\n\nexport interface SchemaService {\n name: string;\n request: SchemaField[];\n response: SchemaField[];\n ros: RosMapping;\n}\n\nexport interface SchemaParam {\n name: string;\n type: ScalarType;\n arrayLen: number;\n /** Little-endian packed payload. Always present for default; min/max may be empty. */\n defaultValue: Uint8Array;\n minValue: Uint8Array;\n maxValue: Uint8Array;\n}\n\nexport interface SchemaBlockType {\n name: string;\n topics: SchemaTopic[];\n services: SchemaService[];\n params: SchemaParam[];\n}\n\nexport interface SchemaBlockArray {\n /** Index into NodeSchema.types (was `type_id` on the wire). */\n blockTypeIndex: number;\n rosNamespace: string;\n}\n\nexport interface WireLimits {\n /** 0 = use bridge default. */\n paramSetBatchBytes: number;\n}\n\nexport interface NodeSchema {\n protocolVersion: number;\n nodeName: string;\n types: SchemaBlockType[];\n instances: SchemaBlockArray[];\n limits: WireLimits;\n}\n\n// --- Field decoders ---------------------------------------------------------\n\nfunction decodeField(r: ProtoReader): SchemaField {\n const f: SchemaField = {\n name: '',\n type: ScalarType.Bool,\n arrayLen: 0,\n txEnabled: true,\n };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Field.name:\n f.name = r.readString();\n break;\n case FIELD.Field.type: {\n const v = r.readVarint();\n if (v > ScalarType.F64) {\n throw new ProtoError(`Field.type out of range: ${v}`);\n }\n f.type = v as ScalarType;\n break;\n }\n case FIELD.Field.arrayLen:\n f.arrayLen = r.readVarint();\n break;\n case FIELD.Field.periodUsOverride: {\n const v = r.readVarint();\n if (v !== 0) f.periodUsOverride = v;\n break;\n }\n case FIELD.Field.txDisabled: {\n const v = r.readVarint();\n f.txEnabled = v === 0;\n break;\n }\n default:\n r.skipValue(wire);\n }\n }\n return f;\n}\n\nfunction decodeRos(r: ProtoReader): RosMapping {\n const ros: RosMapping = { rosType: '', rosName: '', fieldMap: [] };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.RosMapping.rosType:\n ros.rosType = r.readString();\n break;\n case FIELD.RosMapping.rosName:\n ros.rosName = r.readString();\n break;\n case FIELD.RosMapping.fieldMap:\n ros.fieldMap.push(r.readString());\n break;\n default:\n r.skipValue(wire);\n }\n }\n return ros;\n}\n\nfunction decodeTopic(r: ProtoReader): SchemaTopic {\n // proto3 absent-field defaults: enum → 0 (= M2S), so an omitted `dir`\n // means M2S, NOT the IR struct default of S2M. Mirrors C++ parse_schema.\n const t: SchemaTopic = {\n name: '',\n dir: Direction.M2S,\n fields: [],\n defaultPeriodUs: 0,\n ros: { rosType: '', rosName: '', fieldMap: [] },\n };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Topic.name:\n t.name = r.readString();\n break;\n case FIELD.Topic.dir: {\n const v = r.readVarint();\n if (v !== Direction.M2S && v !== Direction.S2M) {\n throw new ProtoError(`Topic.dir out of range: ${v}`);\n }\n t.dir = v;\n break;\n }\n case FIELD.Topic.fields:\n t.fields.push(decodeField(r.readMessage()));\n break;\n case FIELD.Topic.defaultPeriodUs:\n t.defaultPeriodUs = r.readVarint();\n break;\n case FIELD.Topic.ros:\n t.ros = decodeRos(r.readMessage());\n break;\n default:\n r.skipValue(wire);\n }\n }\n return t;\n}\n\nfunction decodeService(r: ProtoReader): SchemaService {\n const s: SchemaService = {\n name: '',\n request: [],\n response: [],\n ros: { rosType: '', rosName: '', fieldMap: [] },\n };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Service.name:\n s.name = r.readString();\n break;\n case FIELD.Service.request:\n s.request.push(decodeField(r.readMessage()));\n break;\n case FIELD.Service.response:\n s.response.push(decodeField(r.readMessage()));\n break;\n case FIELD.Service.ros:\n s.ros = decodeRos(r.readMessage());\n break;\n default:\n r.skipValue(wire);\n }\n }\n return s;\n}\n\nfunction decodeParam(r: ProtoReader): SchemaParam {\n const p: SchemaParam = {\n name: '',\n type: ScalarType.Bool,\n arrayLen: 0,\n defaultValue: new Uint8Array(0),\n minValue: new Uint8Array(0),\n maxValue: new Uint8Array(0),\n };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Param.name:\n p.name = r.readString();\n break;\n case FIELD.Param.type: {\n const v = r.readVarint();\n if (v > ScalarType.F64) throw new ProtoError(`Param.type out of range: ${v}`);\n p.type = v as ScalarType;\n break;\n }\n case FIELD.Param.arrayLen:\n p.arrayLen = r.readVarint();\n break;\n case FIELD.Param.defaultValue:\n p.defaultValue = new Uint8Array(r.readBytes());\n break;\n case FIELD.Param.minValue:\n p.minValue = new Uint8Array(r.readBytes());\n break;\n case FIELD.Param.maxValue:\n p.maxValue = new Uint8Array(r.readBytes());\n break;\n default:\n r.skipValue(wire);\n }\n }\n return p;\n}\n\nfunction decodeBlockType(r: ProtoReader): SchemaBlockType {\n const b: SchemaBlockType = { name: '', topics: [], services: [], params: [] };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.BlockType.name:\n b.name = r.readString();\n break;\n case FIELD.BlockType.topics:\n b.topics.push(decodeTopic(r.readMessage()));\n break;\n case FIELD.BlockType.services:\n b.services.push(decodeService(r.readMessage()));\n break;\n case FIELD.BlockType.params:\n b.params.push(decodeParam(r.readMessage()));\n break;\n default:\n r.skipValue(wire);\n }\n }\n return b;\n}\n\nfunction decodeBlockArray(r: ProtoReader): SchemaBlockArray {\n const a: SchemaBlockArray = { blockTypeIndex: 0, rosNamespace: '' };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.BlockArray.typeId:\n a.blockTypeIndex = r.readVarint();\n break;\n case FIELD.BlockArray.rosNamespace:\n a.rosNamespace = r.readString();\n break;\n default:\n r.skipValue(wire);\n }\n }\n return a;\n}\n\nfunction decodeLimits(r: ProtoReader): WireLimits {\n const l: WireLimits = { paramSetBatchBytes: 0 };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Limits.paramSetBatchBytes:\n l.paramSetBatchBytes = r.readVarint();\n break;\n default:\n r.skipValue(wire);\n }\n }\n return l;\n}\n\nexport interface DecodeSchemaResult {\n schema: NodeSchema;\n /** True when the blob's protocolVersion exceeds this build's {@link PROTOCOL_VERSION}. */\n versionAheadOfMaster: boolean;\n}\n\n/**\n * Parse a schema blob into the master-side IR. Throws {@link ProtoError}\n * on malformed input or `protocolVersion === 0` (proto3 leaves an unset\n * uint32 at 0, so zero means it was never populated).\n */\nexport function decodeSchemaWithMeta(blob: Uint8Array): DecodeSchemaResult {\n const schema: NodeSchema = {\n protocolVersion: 0,\n nodeName: '',\n types: [],\n instances: [],\n limits: { paramSetBatchBytes: 0 },\n };\n const r = new ProtoReader(blob);\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.NodeSchema.protocolVersion:\n schema.protocolVersion = r.readVarint();\n break;\n case FIELD.NodeSchema.nodeName:\n schema.nodeName = r.readString();\n break;\n case FIELD.NodeSchema.types:\n schema.types.push(decodeBlockType(r.readMessage()));\n break;\n case FIELD.NodeSchema.instances:\n schema.instances.push(decodeBlockArray(r.readMessage()));\n break;\n case FIELD.NodeSchema.limits:\n schema.limits = decodeLimits(r.readMessage());\n break;\n default:\n r.skipValue(wire);\n }\n }\n if (schema.protocolVersion === 0) {\n throw new ProtoError(`schema protocol_version is 0 (unset)`);\n }\n for (const arr of schema.instances) {\n if (arr.blockTypeIndex >= schema.types.length) {\n throw new ProtoError(\n `BlockArray.type_id ${arr.blockTypeIndex} out of range (#types=${schema.types.length})`,\n );\n }\n }\n return {\n schema,\n versionAheadOfMaster: schema.protocolVersion > PROTOCOL_VERSION,\n };\n}\n\n/** Shim for callers that don't need the metadata — prefer {@link decodeSchemaWithMeta}. */\nexport function decodeSchema(blob: Uint8Array): NodeSchema {\n return decodeSchemaWithMeta(blob).schema;\n}\n\n/** Wire size in bytes for a single field (scalar or fixed array). */\nexport function fieldWireSize(field: SchemaField): number {\n return scalarSize(field.type) * (field.arrayLen === 0 ? 1 : field.arrayLen);\n}\n","import {\n packScalarF32Le,\n packScalarF64Le,\n packScalarIntLe,\n ScalarType,\n scalarName,\n scalarSize,\n signExtend,\n unpackScalarF32Le,\n unpackScalarF64Le,\n unpackScalarIntLe,\n} from './scalar-codec.js';\nimport { fieldWireSize, type SchemaField } from './schema.js';\n\n/**\n * Field-driven dict ⇄ Uint8Array codec. The runtime equivalent of what\n * codegen would otherwise emit per message — encode/decode is a pure\n * function of the field list ({@link SchemaField}[]) and the JS dict.\n *\n * Conventions (matches CLAUDE.md \"値の表現規約\"):\n * - dict keys are the schema field name verbatim\n * - scalar ↔ JS `number`, except U64/I64 ↔ `bigint`\n * - bool ↔ JS `boolean`\n * - fixed-length array (`arrayLen > 0`) ↔ regular JS array\n * (`number[]` / `bigint[]` / `boolean[]`) of exactly `arrayLen` elements\n *\n * Throws on missing / wrong-shape inputs. Decode tolerates extra trailing\n * bytes (mirrors C++ side: the master ignores trailing slop so that future\n * schema additions don't break older decoders).\n */\n\nexport class DynamicCodecError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'DynamicCodecError';\n }\n}\n\n/** Tag union of accepted JS value shapes for one field. */\nexport type FieldValue = number | bigint | boolean | number[] | bigint[] | boolean[];\n\n/** Dict shape — string-keyed values, one entry per field. */\nexport type Dict = Record<string, FieldValue>;\n\nfunction isInt64(type: ScalarType): boolean {\n return type === ScalarType.U64 || type === ScalarType.I64;\n}\n\nfunction packOneScalar(\n type: ScalarType,\n value: number | bigint | boolean,\n out: Uint8Array,\n offset: number,\n fieldName: string,\n): void {\n switch (type) {\n case ScalarType.Bool: {\n if (typeof value !== 'boolean') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected boolean for bool, got ${typeof value}`,\n );\n }\n out[offset] = value ? 1 : 0;\n return;\n }\n case ScalarType.F32: {\n if (typeof value !== 'number') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected number for f32, got ${typeof value}`,\n );\n }\n packScalarF32Le(value, out, offset);\n return;\n }\n case ScalarType.F64: {\n if (typeof value !== 'number') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected number for f64, got ${typeof value}`,\n );\n }\n packScalarF64Le(value, out, offset);\n return;\n }\n default: {\n // Integer types\n if (isInt64(type)) {\n if (typeof value !== 'bigint') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected bigint for ${scalarName(type)}, got ${typeof value}`,\n );\n }\n } else {\n if (typeof value !== 'number') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected number for ${scalarName(type)}, got ${typeof value}`,\n );\n }\n }\n packScalarIntLe(type, value as number | bigint, out, offset);\n return;\n }\n }\n}\n\nfunction unpackOneScalar(\n type: ScalarType,\n src: Uint8Array,\n offset: number,\n): number | bigint | boolean {\n switch (type) {\n case ScalarType.Bool:\n return (src[offset] ?? 0) !== 0;\n case ScalarType.F32:\n return unpackScalarF32Le(src, offset);\n case ScalarType.F64:\n return unpackScalarF64Le(src, offset);\n case ScalarType.I8:\n case ScalarType.I16:\n case ScalarType.I32: {\n const bits = unpackScalarIntLe(type, src, offset);\n return Number(signExtend(bits, scalarSize(type)));\n }\n case ScalarType.U8:\n case ScalarType.U16:\n case ScalarType.U32:\n return Number(unpackScalarIntLe(type, src, offset));\n case ScalarType.I64: {\n const bits = unpackScalarIntLe(type, src, offset);\n return signExtend(bits, 8);\n }\n case ScalarType.U64:\n return unpackScalarIntLe(type, src, offset);\n }\n}\n\n/**\n * Sum the wire size of a field list. The result is the byte count that\n * {@link encodeFields} will produce.\n */\nexport function fieldsWireSize(fields: readonly SchemaField[]): number {\n let n = 0;\n for (const f of fields) n += fieldWireSize(f);\n return n;\n}\n\n/**\n * Encode a dict into the canonical little-endian wire bytes for `fields`.\n * Returns a fresh `Uint8Array`. Throws {@link DynamicCodecError} on a\n * missing or wrong-shape field.\n */\nexport function encodeFields(fields: readonly SchemaField[], value: Dict): Uint8Array {\n const totalSize = fieldsWireSize(fields);\n const out = new Uint8Array(totalSize);\n let off = 0;\n for (const f of fields) {\n if (!f.txEnabled) {\n // The master-side encoder still allocates wire room for the field —\n // it's the planner's job to drop tx_disabled fields from the frame\n // plan entirely. Here we just leave zeros and move on.\n off += fieldWireSize(f);\n continue;\n }\n const v = value[f.name];\n if (v === undefined) {\n throw new DynamicCodecError(`encodeFields: missing field '${f.name}'`);\n }\n if (f.arrayLen === 0) {\n packOneScalar(f.type, v as number | bigint | boolean, out, off, f.name);\n off += scalarSize(f.type);\n } else {\n if (!Array.isArray(v)) {\n throw new DynamicCodecError(\n `field '${f.name}': expected array of length ${f.arrayLen}, got ${typeof v}`,\n );\n }\n if (v.length !== f.arrayLen) {\n throw new DynamicCodecError(\n `field '${f.name}': expected array length ${f.arrayLen}, got ${v.length}`,\n );\n }\n const stride = scalarSize(f.type);\n for (let i = 0; i < f.arrayLen; i++) {\n packOneScalar(f.type, v[i] as number | bigint | boolean, out, off, f.name);\n off += stride;\n }\n }\n }\n return out;\n}\n\n/**\n * Decode wire bytes into a dict keyed by field name. Extra trailing bytes\n * are ignored. Throws {@link DynamicCodecError} only if the payload is\n * shorter than the field list demands.\n */\nexport function decodeFields(fields: readonly SchemaField[], bytes: Uint8Array): Dict {\n const expected = fieldsWireSize(fields);\n if (bytes.length < expected) {\n throw new DynamicCodecError(\n `decodeFields: payload too short — need ${expected} bytes, got ${bytes.length}`,\n );\n }\n const out: Dict = {};\n let off = 0;\n for (const f of fields) {\n if (f.arrayLen === 0) {\n out[f.name] = unpackOneScalar(f.type, bytes, off);\n off += scalarSize(f.type);\n } else {\n const stride = scalarSize(f.type);\n if (f.type === ScalarType.Bool) {\n const arr: boolean[] = [];\n for (let i = 0; i < f.arrayLen; i++) {\n arr.push(unpackOneScalar(f.type, bytes, off) as boolean);\n off += stride;\n }\n out[f.name] = arr;\n } else if (isInt64(f.type)) {\n const arr: bigint[] = [];\n for (let i = 0; i < f.arrayLen; i++) {\n arr.push(unpackOneScalar(f.type, bytes, off) as bigint);\n off += stride;\n }\n out[f.name] = arr;\n } else {\n const arr: number[] = [];\n for (let i = 0; i < f.arrayLen; i++) {\n arr.push(unpackOneScalar(f.type, bytes, off) as number);\n off += stride;\n }\n out[f.name] = arr;\n }\n }\n }\n return out;\n}\n","import type { CanFrame, ITransport, Unsubscribe } from '@fibril/can-transport';\nimport { type Dict, decodeFields } from './dynamic-codec.js';\nimport type { FramePlan } from './node-agent.js';\nimport { Direction, fieldWireSize, type SchemaField } from './schema.js';\nimport type { SchemaIndex } from './schema-index.js';\n\n/**\n * Master-side decoder for S→M data-plane frames.\n *\n * Listens on the transport for standard-ID frames whose IDs match one of\n * the std_ids configured in any attached slave's {@link FramePlan}. For\n * each match, unpacks the topic entries packed into the frame's payload\n * (in FRAME_DEFINE order) using the schema field bitmask and publishes\n * a decoded {@link Dict} per topic to subscribers.\n *\n * Lifecycle:\n * - `new DataPlaneReceiver({ transport })` registers an `onFrame` tap.\n * - `attachSlave(nodeId, framePlan, schemaIndex)` claims a slave's std_ids.\n * - `detachSlave(nodeId)` releases them (call on RUNNING → not-RUNNING).\n * - `dispose()` unsubscribes and clears all state.\n *\n * Two slaves cannot publish on the same std_id — attaching the second\n * throws. This mirrors the bus-level reality: identical std_ids would\n * collide on the wire.\n *\n * M→S frames (master output, dir `Direction.M2S`) are skipped during\n * attach so the receiver doesn't try to decode echo or self-loopback\n * frames as if they were slave-published.\n */\nexport interface DataPlaneReceiverOptions {\n transport: ITransport;\n /** Non-fatal error sink (decode errors, listener throws). */\n onError?: (err: Error) => void;\n /** Clock override for tests. Default `() => Date.now()`. */\n now?: () => number;\n}\n\nexport type TopicListener = (value: Dict, tsMs: number) => void;\n\nexport interface TopicSample {\n readonly value: Dict;\n readonly tsMs: number;\n}\n\nexport interface TopicStats {\n /** Frames ever decoded into this topic since the slave attached. */\n readonly count: number;\n /** `now()` of the most recent frame. */\n readonly lastRxMs: number;\n /**\n * Rolling rate over the last few samples (Hz). 0 until at least\n * two frames have been seen.\n */\n readonly ratePerSec: number;\n}\n\ninterface PackedEntry {\n path: string;\n fields: SchemaField[];\n offset: number;\n size: number;\n}\n\ninterface FrameBucket {\n nodeId: number;\n stdId: number;\n dir: Direction;\n entries: PackedEntry[];\n}\n\ninterface TopicCache {\n value: Dict;\n tsMs: number;\n count: number;\n /** Ring of recent timestamps for ratePerSec. Capped at RATE_WINDOW. */\n ts: number[];\n}\n\nconst RATE_WINDOW = 16;\n\nfunction maskedFieldsList(fields: readonly SchemaField[], mask: number): SchemaField[] {\n const out: SchemaField[] = [];\n for (let i = 0; i < fields.length; i++) {\n const f = fields[i];\n if (f === undefined) continue;\n if ((mask & (1 << i)) !== 0) out.push(f);\n }\n return out;\n}\n\nfunction sumWireSize(fields: readonly SchemaField[]): number {\n let s = 0;\n for (const f of fields) s += fieldWireSize(f);\n return s;\n}\n\nfunction buildBucket(framePlan: FramePlan, index: SchemaIndex, nodeId: number): FrameBucket {\n let offset = 0;\n const entries: PackedEntry[] = [];\n for (const e of framePlan.entries) {\n const desc = index.topicByIndex(e.topicIndex);\n if (desc === undefined) {\n // Schema/numbering mismatch — skip rather than throw so a partial\n // plan still decodes the entries it can.\n continue;\n }\n const fields = maskedFieldsList(desc.fields, e.fieldBitmask);\n const size = sumWireSize(fields);\n entries.push({ path: desc.path, fields, offset, size });\n offset += size;\n }\n return { nodeId, stdId: framePlan.stdId, dir: framePlan.dir, entries };\n}\n\nfunction topicKey(nodeId: number, path: string): string {\n return `${nodeId}/${path}`;\n}\n\nexport class DataPlaneReceiver {\n readonly #onError: ((err: Error) => void) | undefined;\n readonly #now: () => number;\n readonly #unsubFrame: Unsubscribe;\n\n readonly #buckets = new Map<number, FrameBucket>();\n readonly #ownedByNode = new Map<number, Set<number>>();\n readonly #latest = new Map<string, TopicCache>();\n readonly #listeners = new Map<string, Set<TopicListener>>();\n #version = 0;\n\n constructor(opts: DataPlaneReceiverOptions) {\n this.#onError = opts.onError;\n this.#now = opts.now ?? (() => Date.now());\n this.#unsubFrame = opts.transport.onFrame((f) => this.#onFrame(f));\n }\n\n /**\n * Claim a slave's S→M std_ids. Re-attaching the same nodeId atomically\n * detaches the prior plan first (re-provisioning case).\n */\n attachSlave(nodeId: number, framePlan: readonly FramePlan[], index: SchemaIndex): void {\n this.detachSlave(nodeId);\n const owned = new Set<number>();\n for (const fp of framePlan) {\n if (fp.dir !== Direction.S2M) continue; // master output — not decoded here\n if (this.#buckets.has(fp.stdId)) {\n const other = this.#buckets.get(fp.stdId);\n throw new Error(\n `DataPlaneReceiver: std_id 0x${fp.stdId.toString(16)} claimed by slave 0x${\n other?.nodeId.toString(16) ?? '??'\n }, cannot also attach slave 0x${nodeId.toString(16)}`,\n );\n }\n this.#buckets.set(fp.stdId, buildBucket(fp, index, nodeId));\n owned.add(fp.stdId);\n }\n this.#ownedByNode.set(nodeId, owned);\n }\n\n /** Release a slave's std_ids and drop its cached topic samples. */\n detachSlave(nodeId: number): void {\n const owned = this.#ownedByNode.get(nodeId);\n if (!owned) return;\n for (const id of owned) this.#buckets.delete(id);\n this.#ownedByNode.delete(nodeId);\n const prefix = `${nodeId}/`;\n for (const k of [...this.#latest.keys()]) {\n if (k.startsWith(prefix)) this.#latest.delete(k);\n }\n }\n\n onTopic(nodeId: number, path: string, listener: TopicListener): Unsubscribe {\n const key = topicKey(nodeId, path);\n let set = this.#listeners.get(key);\n if (!set) {\n set = new Set();\n this.#listeners.set(key, set);\n }\n set.add(listener);\n return () => {\n const s = this.#listeners.get(key);\n if (!s) return;\n s.delete(listener);\n if (s.size === 0) this.#listeners.delete(key);\n };\n }\n\n latest(nodeId: number, path: string): TopicSample | null {\n const c = this.#latest.get(topicKey(nodeId, path));\n return c === undefined ? null : { value: c.value, tsMs: c.tsMs };\n }\n\n stats(nodeId: number, path: string): TopicStats | null {\n const c = this.#latest.get(topicKey(nodeId, path));\n if (!c) return null;\n let rate = 0;\n if (c.ts.length >= 2) {\n const newest = c.ts[c.ts.length - 1] ?? 0;\n const oldest = c.ts[0] ?? 0;\n const dt = newest - oldest;\n if (dt > 0) rate = (1000 * (c.ts.length - 1)) / dt;\n }\n return { count: c.count, lastRxMs: c.tsMs, ratePerSec: rate };\n }\n\n /** Paths attached for this slave (in plan order). */\n topicPathsFor(nodeId: number): string[] {\n const owned = this.#ownedByNode.get(nodeId);\n if (!owned) return [];\n const out: string[] = [];\n for (const id of owned) {\n const b = this.#buckets.get(id);\n if (b) for (const e of b.entries) out.push(e.path);\n }\n return out;\n }\n\n /** Bumps on every successfully decoded entry — cheap change detector. */\n get version(): number {\n return this.#version;\n }\n\n dispose(): void {\n this.#unsubFrame();\n this.#buckets.clear();\n this.#ownedByNode.clear();\n this.#latest.clear();\n this.#listeners.clear();\n }\n\n #onFrame(f: CanFrame): void {\n if (f.extended) return; // ext = config / svc planes\n if (f.rtr) return;\n const bucket = this.#buckets.get(f.id);\n if (bucket === undefined) return;\n const tsMs = this.#now();\n for (const e of bucket.entries) {\n if (e.offset + e.size > f.data.length) continue; // truncated frame\n const slice = f.data.subarray(e.offset, e.offset + e.size);\n let dict: Dict;\n try {\n dict = decodeFields(e.fields, slice);\n } catch (err) {\n this.#err(err);\n continue;\n }\n this.#publish(bucket.nodeId, e.path, dict, tsMs);\n }\n }\n\n #publish(nodeId: number, path: string, value: Dict, tsMs: number): void {\n const key = topicKey(nodeId, path);\n let c = this.#latest.get(key);\n if (c === undefined) {\n c = { value, tsMs, count: 0, ts: [] };\n this.#latest.set(key, c);\n } else {\n c.value = value;\n c.tsMs = tsMs;\n }\n c.count++;\n c.ts.push(tsMs);\n if (c.ts.length > RATE_WINDOW) c.ts.shift();\n this.#version++;\n const set = this.#listeners.get(key);\n if (set !== undefined) {\n for (const l of set) {\n try {\n l(value, tsMs);\n } catch (err) {\n this.#err(err);\n }\n }\n }\n }\n\n #err(e: unknown): void {\n if (this.#onError === undefined) return;\n this.#onError(e instanceof Error ? e : new Error(String(e)));\n }\n}\n","import { MAX_FRAME_PAYLOAD, STD_ID_MASK } from './can-id.js';\nimport type { FrameDefineEntry } from './config-plane.js';\nimport type { Direction } from './schema.js';\n\n/**\n * Frame planner — turns a list of \"I want field X at period Y\" requests into\n * the concrete FRAME_DEFINE bodies the master ships to the slave (§6.3).\n *\n * Port of `fibril_can_core/src/frame_planner.cpp` — same bucketing rules:\n * - Group requests by (direction, period_us); never combine across either.\n * - Inside a bucket, bin-pack whole topics into ≤64-byte frames.\n * - A single topic whose declared fields exceed 64 bytes is the sole\n * field-split exception (`emitOversizedTopic`).\n *\n * Determinism is load-bearing: codegen, bridge, and this TS master must\n * produce identical std_id assignments for the same input. Both the\n * bucket map and the per-bucket topic map iterate in ascending key order\n * (matching `std::map` in the C++ reference).\n */\n\nexport interface FieldRequest {\n topicIndex: number;\n /** 0..15, bit position in `fieldBitmask`. */\n fieldId: number;\n /** Wire size of this field. */\n sizeBytes: number;\n /** 0 = on-trigger only. */\n periodUs: number;\n dir: Direction;\n}\n\nexport interface FrameSpec {\n stdCanId: number;\n periodUs: number;\n dir: Direction;\n logicalBytes: number;\n entries: FrameDefineEntry[];\n}\n\n/**\n * 11-bit Standard ID allocator with a free pool for IDs released after a\n * grace window (§11.4.1). `next()` returns `null` on exhaustion rather\n * than wrapping — wrapping past 0x7FF would alias on the wire.\n */\nexport class StdIdAllocator {\n #next = 0x100;\n // Sorted ascending by availableAtMs.\n readonly #freePool: Array<{ availableAtMs: number; id: number }> = [];\n\n next(nowMs: number = Date.now()): number | null {\n if (this.#freePool.length > 0) {\n const head = this.#freePool[0];\n if (head !== undefined && head.availableAtMs <= nowMs) {\n this.#freePool.shift();\n return head.id;\n }\n }\n if (this.#next > STD_ID_MASK) return null;\n const id = this.#next;\n this.#next += 1;\n return id;\n }\n\n release(id: number, availableAtMs: number): void {\n let lo = 0;\n let hi = this.#freePool.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const entry = this.#freePool[mid];\n if (entry !== undefined && entry.availableAtMs < availableAtMs) lo = mid + 1;\n else hi = mid;\n }\n this.#freePool.splice(lo, 0, { availableAtMs, id });\n }\n\n reset(start = 0x100): void {\n this.#next = start;\n this.#freePool.length = 0;\n }\n}\n\ninterface MakeFrameInput {\n topics: Map<number, FieldRequest[]>;\n dir: Direction;\n periodUs: number;\n alloc: StdIdAllocator;\n}\n\nfunction makeFrame(input: MakeFrameInput): FrameSpec | null {\n const id = input.alloc.next();\n if (id === null) return null;\n const entries: FrameDefineEntry[] = [];\n let bytes = 0;\n for (const topicIndex of [...input.topics.keys()].sort((a, b) => a - b)) {\n const fields = input.topics.get(topicIndex);\n if (!fields) continue;\n let mask = 0;\n for (const r of fields) {\n mask |= 1 << r.fieldId;\n bytes += r.sizeBytes;\n }\n entries.push({ topicIndex, fieldBitmask: mask });\n }\n return {\n stdCanId: id,\n periodUs: input.periodUs,\n dir: input.dir,\n logicalBytes: Math.min(bytes, MAX_FRAME_PAYLOAD),\n entries,\n };\n}\n\nfunction emitOversizedTopic(\n fields: FieldRequest[],\n dir: Direction,\n periodUs: number,\n alloc: StdIdAllocator,\n out: FrameSpec[],\n): boolean {\n const sorted = [...fields].sort((a, b) => a.fieldId - b.fieldId);\n let bin: FieldRequest[] = [];\n let binBytes = 0;\n const topicIndex = sorted[0]?.topicIndex ?? 0;\n const flush = (): boolean => {\n if (bin.length === 0) return true;\n const one = new Map<number, FieldRequest[]>([[topicIndex, bin]]);\n const f = makeFrame({ topics: one, dir, periodUs, alloc });\n if (!f) return false;\n out.push(f);\n bin = [];\n binBytes = 0;\n return true;\n };\n for (const r of sorted) {\n if (binBytes + r.sizeBytes > MAX_FRAME_PAYLOAD) {\n if (!flush()) return false;\n }\n bin.push(r);\n binBytes += r.sizeBytes;\n }\n return flush();\n}\n\n/**\n * Plan a slave's frame layout. Returns `null` if the StdIdAllocator runs\n * out of 11-bit IDs mid-plan — the caller MUST surface that; a partial\n * plan would silently drop fields.\n */\nexport function planFrames(\n requests: readonly FieldRequest[],\n alloc: StdIdAllocator,\n): FrameSpec[] | null {\n // Bucket by (dir, period_us). Use a string key but iterate in numeric\n // (dir, period) order to match std::map.\n const buckets = new Map<string, FieldRequest[]>();\n for (const r of requests) {\n const key = `${r.dir}/${r.periodUs}`;\n let bucket = buckets.get(key);\n if (!bucket) {\n bucket = [];\n buckets.set(key, bucket);\n }\n bucket.push(r);\n }\n const sortedKeys = [...buckets.keys()].sort((a, b) => {\n const [aDir, aPeriod] = a.split('/').map(Number) as [number, number];\n const [bDir, bPeriod] = b.split('/').map(Number) as [number, number];\n if (aDir !== bDir) return aDir - bDir;\n return aPeriod - bPeriod;\n });\n\n const out: FrameSpec[] = [];\n for (const key of sortedKeys) {\n const requestsInBucket = buckets.get(key);\n if (!requestsInBucket) continue;\n const [dir, periodUs] = key.split('/').map(Number) as [number, number];\n\n const byTopic = new Map<number, FieldRequest[]>();\n for (const r of requestsInBucket) {\n let arr = byTopic.get(r.topicIndex);\n if (!arr) {\n arr = [];\n byTopic.set(r.topicIndex, arr);\n }\n arr.push(r);\n }\n const topicBytes = new Map<number, number>();\n for (const [topicIndex, fields] of byTopic) {\n let sum = 0;\n for (const r of fields) sum += r.sizeBytes;\n topicBytes.set(topicIndex, sum);\n }\n\n let currentBin = new Map<number, FieldRequest[]>();\n let currentBytes = 0;\n const flush = (): boolean => {\n if (currentBin.size === 0) return true;\n const f = makeFrame({ topics: currentBin, dir, periodUs, alloc });\n if (!f) return false;\n out.push(f);\n currentBin = new Map();\n currentBytes = 0;\n return true;\n };\n\n const sortedTopics = [...byTopic.keys()].sort((a, b) => a - b);\n for (const topicIndex of sortedTopics) {\n const fields = byTopic.get(topicIndex);\n if (!fields) continue;\n const sz = topicBytes.get(topicIndex) ?? 0;\n if (sz > MAX_FRAME_PAYLOAD) {\n if (!flush()) return null;\n if (!emitOversizedTopic(fields, dir, periodUs, alloc, out)) return null;\n continue;\n }\n if (currentBytes + sz > MAX_FRAME_PAYLOAD) {\n if (!flush()) return null;\n }\n currentBin.set(topicIndex, fields);\n currentBytes += sz;\n }\n if (!flush()) return null;\n }\n return out;\n}\n","import type { FieldRequest, FrameSpec } from './frame-planner.js';\nimport { planFrames, StdIdAllocator } from './frame-planner.js';\nimport type { FramePlan } from './node-agent.js';\nimport type { NumberingResult } from './numbering.js';\nimport { Direction, fieldWireSize, type NodeSchema, type SchemaField } from './schema.js';\n\n/**\n * Per-field predicate handed to {@link buildDefaultS2MRequests} (and via\n * it, {@link defaultS2MFramePlan}) so callers can apply a runtime mask on\n * top of the schema-declared `txEnabled`.\n *\n * Contract:\n * - Returning `false` skips the field entirely; the slave will not pack\n * it into any S→M frame. Returning `true` keeps it.\n * - Called only for S→M fields whose schema declares `txEnabled !==\n * false` (schema-disabled fields are filtered out unconditionally).\n * - `topicPath` is the same `'<expanded_ns>/<topic_name>'` string the\n * master uses elsewhere (mirrors {@link SchemaIndex.topicPaths}), so\n * UI override maps can key on the same identifier.\n */\nexport type S2MFieldFilter = (info: {\n topicPath: string;\n topicIndex: number;\n fieldId: number;\n fieldName: string;\n field: SchemaField;\n}) => boolean;\n\nconst I_TOKEN = '{i}';\n\nfunction expandIToken(s: string, value: number): string {\n if (!s.includes(I_TOKEN)) return s;\n return s.split(I_TOKEN).join(String(value));\n}\n\nfunction joinPath(ns: string, name: string): string {\n if (ns.length === 0) return name;\n if (name.length === 0) return ns;\n return `${ns}/${name}`;\n}\n\n/**\n * Synthesize the default {@link FieldRequest} list from a decoded schema +\n * numbering table — every S2M topic field at its declared period\n * (`field.periodUsOverride` if present, else the owning topic's\n * `defaultPeriodUs`), skipping `txEnabled === false` fields.\n *\n * Pass `filter` to layer a runtime per-field mask on top (UI toggles,\n * per-slave overrides). Schema-disabled fields are unconditionally\n * dropped before `filter` is consulted, so callers don't have to repeat\n * the `txEnabled` check.\n *\n * This is the natural input to {@link planFrames} when the master just\n * wants to \"observe everything the slave publishes\" — i.e. the\n * sniffer-style auto-provision path.\n */\nexport function buildDefaultS2MRequests(\n schema: NodeSchema,\n numbering: NumberingResult,\n filter?: S2MFieldFilter,\n): FieldRequest[] {\n const out: FieldRequest[] = [];\n numbering.topics.byIndex.forEach((endpoint, flatIndex) => {\n const block = schema.instances[endpoint.blockArray];\n if (!block) return;\n const type = schema.types[block.blockTypeIndex];\n if (!type) return;\n const topic = type.topics[endpoint.endpoint];\n if (!topic) return;\n if (topic.dir !== Direction.S2M) return;\n // Reconstruct the topic path the same way SchemaIndex does so the\n // filter sees the same identifier the UI shows. Computed lazily — we\n // only need it when a filter is supplied.\n let topicPath: string | null = null;\n topic.fields.forEach((field, fieldId) => {\n if (!field.txEnabled) return;\n if (filter !== undefined) {\n if (topicPath === null) {\n topicPath = joinPath(expandIToken(block.rosNamespace, endpoint.instance), topic.name);\n }\n if (\n !filter({\n topicPath,\n topicIndex: flatIndex,\n fieldId,\n fieldName: field.name,\n field,\n })\n ) {\n return;\n }\n }\n out.push({\n topicIndex: flatIndex,\n fieldId,\n sizeBytes: fieldWireSize(field),\n periodUs: field.periodUsOverride ?? topic.defaultPeriodUs,\n dir: topic.dir,\n });\n });\n });\n return out;\n}\n\n/**\n * One-line FramePlanFactory that subscribes to every S2M field at its\n * declared period using a freshly-allocated {@link StdIdAllocator}.\n *\n * Pass `filter` to apply a runtime per-field mask (e.g. a UI-controlled\n * field-tx-enable map). With no filter, every schema-enabled S→M field is\n * subscribed.\n *\n * Returns `[]` when planning fails (e.g. std_id exhaustion); the caller's\n * NodeAgent will then leave the slave in `provisioning` → `awaiting-announce`\n * with no frames defined, which is the right outcome — partial plans would\n * silently drop fields.\n */\nexport function defaultS2MFramePlan(\n schema: NodeSchema,\n numbering: NumberingResult,\n filter?: S2MFieldFilter,\n): FramePlan[] {\n const requests = buildDefaultS2MRequests(schema, numbering, filter);\n const alloc = new StdIdAllocator();\n const planned = planFrames(requests, alloc);\n if (planned === null) return [];\n return planned.map(\n (s: FrameSpec): FramePlan => ({\n stdId: s.stdCanId,\n periodUs: s.periodUs,\n dir: s.dir,\n entries: s.entries,\n }),\n );\n}\n","import type { ITransport } from '@fibril/can-transport';\nimport { encodeMasterHeartbeat } from './config-plane.js';\n\n/**\n * Broadcasts CMD_MASTER_HEARTBEAT (§5.11) on a fixed period so slaves with\n * a `master_lost_us` watchdog configured do not silence their S→M traffic.\n *\n * Independent of any single {@link NodeAgent} — the heartbeat is a single\n * bus-wide broadcast that refreshes every slave's watchdog. Construct one\n * per transport.\n */\nexport class MasterHeartbeatBroadcaster {\n #handle: ReturnType<typeof setInterval> | null = null;\n\n constructor(\n private readonly transport: ITransport,\n private readonly periodMs: number = 100,\n ) {}\n\n start(): void {\n if (this.#handle !== null) return;\n const tick = (): void => {\n if (!this.transport.isOpen) return;\n void this.transport.send(encodeMasterHeartbeat()).catch(() => {\n // Swallow — the transport's onError surfaces real failures.\n });\n };\n // Send one immediately so a newly-attached slave doesn't wait a full\n // period before its first refresh.\n tick();\n this.#handle = setInterval(tick, this.periodMs);\n }\n\n stop(): void {\n if (this.#handle === null) return;\n clearInterval(this.#handle);\n this.#handle = null;\n }\n\n get running(): boolean {\n return this.#handle !== null;\n }\n}\n","import type { NodeSchema, SchemaBlockType } from './schema.js';\n\n/**\n * Flat-numbering tables for topics, services, and parameters (§4.2).\n *\n * Port of `fibril_can_core/src/numbering.cpp`. Numbering is a pure function\n * of (schema, instance-count-vector). The same tables are derived\n * independently by codegen (with max_count for static checks), the slave\n * runtime (with actual counts at boot) and the master (with counts from the\n * ANNOUNCE frame) — keeping this in one place is what guarantees they agree.\n */\n\n// Reserved service slots (§3.3) — must NOT be produced by numbering.\nexport const SERVICE_INDEX_CANCEL = 0xff;\nexport const SERVICE_INDEX_PARAM_SET = 0xfd;\n/** Maximum first-class service_index produced by numbering (inclusive). */\nexport const SERVICE_INDEX_MAX = 0xfc;\n/** Number of available first-class service slots. */\nexport const SERVICE_INDEX_CAPACITY = SERVICE_INDEX_MAX + 1;\n\nexport enum NumberingError {\n Ok = 'ok',\n ServiceIndexOverflow = 'service_index overflow (>253)',\n TopicIndexOverflow = 'topic_index overflow (>65535)',\n ParamIndexOverflow = 'param_index overflow (>65535)',\n InstanceCountMismatch = 'actual_counts length != #instances',\n BlockTypeOutOfRange = 'BlockArray::blockTypeIndex out of range',\n}\n\n/** Concrete location of one (instance, endpoint) within a NodeSchema. */\nexport interface EndpointKey {\n /** Index into NodeSchema.instances. */\n blockArray: number;\n /** 0..count-1 */\n instance: number;\n /** 0..nEndpoints(type)-1 */\n endpoint: number;\n}\n\n/** Forward + inverse maps for a single endpoint kind. */\nexport interface NumberingTable {\n /**\n * size = Σ_b(actualCounts[b] × nEndpoints(types[instances[b].blockTypeIndex]));\n * the array index IS the flat numbering.\n */\n byIndex: EndpointKey[];\n /** Per-block-array base offsets (size = #blockArrays + 1; last is total). */\n bases: number[];\n}\n\nexport interface NumberingResult {\n topics: NumberingTable;\n services: NumberingTable;\n params: NumberingTable;\n status: NumberingError;\n}\n\ntype EndpointPicker = (bt: SchemaBlockType) => number;\n\nconst N_TOPICS: EndpointPicker = (bt) => bt.topics.length;\nconst N_SERVICES: EndpointPicker = (bt) => bt.services.length;\nconst N_PARAMS: EndpointPicker = (bt) => bt.params.length;\n\nfunction buildTable(\n schema: NodeSchema,\n counts: readonly number[],\n pick: EndpointPicker,\n): NumberingTable {\n const byIndex: EndpointKey[] = [];\n const bases: number[] = [];\n let base = 0;\n bases.push(base);\n for (let b = 0; b < schema.instances.length; b++) {\n const arr = schema.instances[b];\n if (!arr) continue;\n const type = schema.types[arr.blockTypeIndex];\n if (!type) continue; // validated separately in computeNumbering\n const n = pick(type);\n const count = counts[b] ?? 0;\n for (let inst = 0; inst < count; inst++) {\n for (let ep = 0; ep < n; ep++) {\n byIndex.push({ blockArray: b, instance: inst, endpoint: ep });\n }\n }\n base += n * count;\n bases.push(base);\n }\n return { byIndex, bases };\n}\n\n/**\n * Compute the three numbering tables. `actualCounts` must have the same\n * length as `schema.instances`. The result has `status !== Ok` if input is\n * malformed or service_index would overflow into the reserved range\n * (§4.2 §9.4).\n *\n * On error the returned tables are empty but still safe to inspect.\n */\nexport function computeNumbering(\n schema: NodeSchema,\n actualCounts: readonly number[],\n): NumberingResult {\n const empty: NumberingTable = { byIndex: [], bases: [] };\n const fail = (status: NumberingError): NumberingResult => ({\n topics: empty,\n services: empty,\n params: empty,\n status,\n });\n\n if (actualCounts.length !== schema.instances.length) {\n return fail(NumberingError.InstanceCountMismatch);\n }\n for (const arr of schema.instances) {\n if (arr.blockTypeIndex >= schema.types.length) {\n return fail(NumberingError.BlockTypeOutOfRange);\n }\n }\n\n const topics = buildTable(schema, actualCounts, N_TOPICS);\n const services = buildTable(schema, actualCounts, N_SERVICES);\n const params = buildTable(schema, actualCounts, N_PARAMS);\n\n if (topics.byIndex.length > 0xffff) {\n return {\n topics: empty,\n services: empty,\n params: empty,\n status: NumberingError.TopicIndexOverflow,\n };\n }\n if (params.byIndex.length > 0xffff) {\n return {\n topics: empty,\n services: empty,\n params: empty,\n status: NumberingError.ParamIndexOverflow,\n };\n }\n if (services.byIndex.length > SERVICE_INDEX_CAPACITY) {\n return {\n topics: empty,\n services: empty,\n params: empty,\n status: NumberingError.ServiceIndexOverflow,\n };\n }\n\n return { topics, services, params, status: NumberingError.Ok };\n}\n","/**\n * SHA-256 helpers for the schema blob (§5.4, §9.3).\n *\n * Both codegen (C++) and the bridge (C++) hash the entire schema blob with\n * SHA-256 and pack the first 8 bytes as little-endian u64 into the ANNOUNCE\n * frame. This module is the master-side equivalent: hash the blob we\n * received over SCHEMA_DATA and compare with the schema_hash the slave\n * advertised in ANNOUNCE.\n *\n * Uses Web Crypto (`crypto.subtle`) — available in modern browsers and Node\n * ≥ 19 / Deno / Bun, no polyfill needed for our target environments.\n */\n\nexport async function sha256(bytes: Uint8Array): Promise<Uint8Array> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('crypto.subtle is not available in this environment');\n }\n // Copy into a fresh ArrayBuffer-backed view so crypto.subtle accepts it\n // regardless of whether `bytes` is backed by SharedArrayBuffer.\n const owned = new Uint8Array(bytes);\n const digest = await crypto.subtle.digest('SHA-256', owned);\n return new Uint8Array(digest);\n}\n\n/**\n * Compute the ANNOUNCE-shape schema hash: the first 8 bytes of SHA-256(blob),\n * interpreted as a little-endian u64. Mirrors\n * `fibril_can_core/sha256::hash_prefix_u64`.\n */\nexport async function schemaHashPrefix(blob: Uint8Array): Promise<bigint> {\n const digest = await sha256(blob);\n let result = 0n;\n for (let i = 0; i < 8; i++) {\n result |= BigInt(digest[i] ?? 0) << BigInt(i * 8);\n }\n return result;\n}\n","import type { NumberingResult } from './numbering.js';\nimport type { ScalarType } from './scalar-codec.js';\nimport { type Direction, fieldWireSize, type NodeSchema, type SchemaField } from './schema.js';\n\n/**\n * Schema-driven path lookup. Resolves `'<expanded_ns>/<endpoint_name>'`\n * style paths to the flat (topic|service|param) index plus the field IR\n * needed to drive {@link ./dynamic-codec.ts}.\n *\n * Paths are local to a single slave (one {@link NodeAgent}). The block-array\n * `ros_namespace` is expanded by substituting `{i}` with the instance index\n * (mirrors `expand_i_token` in `fibril_can_bridge::node_agent_internal.hpp`).\n *\n * Two endpoints of the same kind sharing a path is a schema error — the\n * index throws on construction. Same path across different kinds (e.g. a\n * topic and a service named `motor0/foo`) is allowed because the caller\n * selects the kind explicitly via `topic()` / `service()` / `param()`.\n */\n\nconst I_TOKEN = '{i}';\n\nfunction expandIToken(s: string, value: number): string {\n if (!s.includes(I_TOKEN)) return s;\n return s.split(I_TOKEN).join(String(value));\n}\n\nfunction joinPath(ns: string, name: string): string {\n if (ns.length === 0) return name;\n if (name.length === 0) return ns;\n return `${ns}/${name}`;\n}\n\n/** Resolved descriptor for one S→M or M→S topic. */\nexport interface TopicDescriptor {\n readonly kind: 'topic';\n readonly path: string;\n readonly topicIndex: number;\n readonly dir: Direction;\n readonly fields: readonly SchemaField[];\n readonly defaultPeriodUs: number;\n readonly wireSize: number;\n}\n\n/** Resolved descriptor for one Service. */\nexport interface ServiceDescriptor {\n readonly kind: 'service';\n readonly path: string;\n readonly serviceIndex: number;\n readonly requestFields: readonly SchemaField[];\n readonly responseFields: readonly SchemaField[];\n readonly requestWireSize: number;\n readonly responseWireSize: number;\n}\n\n/** Resolved descriptor for one Param (single-field). */\nexport interface ParamDescriptor {\n readonly kind: 'param';\n readonly path: string;\n readonly paramIndex: number;\n readonly type: ScalarType;\n /** 0 = scalar; >0 = fixed-length array of `type`. */\n readonly arrayLen: number;\n readonly wireSize: number;\n readonly defaultValue: Uint8Array;\n readonly minValue: Uint8Array;\n readonly maxValue: Uint8Array;\n}\n\nexport type EndpointDescriptor = TopicDescriptor | ServiceDescriptor | ParamDescriptor;\n\nfunction sumFieldsWireSize(fields: readonly SchemaField[]): number {\n let n = 0;\n for (const f of fields) n += fieldWireSize(f);\n return n;\n}\n\n/**\n * Path → descriptor index for one slave. Built once from\n * (schema, numbering) and reused for the lifetime of a snapshot.\n */\nexport class SchemaIndex {\n readonly #topicsByPath = new Map<string, TopicDescriptor>();\n readonly #servicesByPath = new Map<string, ServiceDescriptor>();\n readonly #paramsByPath = new Map<string, ParamDescriptor>();\n readonly #topicsByIndex = new Map<number, TopicDescriptor>();\n readonly #servicesByIndex = new Map<number, ServiceDescriptor>();\n readonly #paramsByIndex = new Map<number, ParamDescriptor>();\n\n constructor(schema: NodeSchema, numbering: NumberingResult, instanceCounts: readonly number[]) {\n if (instanceCounts.length !== schema.instances.length) {\n throw new RangeError(\n `SchemaIndex: instanceCounts.length (${instanceCounts.length}) != schema.instances.length (${schema.instances.length})`,\n );\n }\n for (let arrIdx = 0; arrIdx < schema.instances.length; arrIdx++) {\n const arr = schema.instances[arrIdx];\n if (!arr) continue;\n const block = schema.types[arr.blockTypeIndex];\n if (!block) continue;\n const topicBase = numbering.topics.bases[arrIdx];\n const serviceBase = numbering.services.bases[arrIdx];\n const paramBase = numbering.params.bases[arrIdx];\n if (topicBase === undefined || serviceBase === undefined || paramBase === undefined) {\n // Numbering failed earlier — bases for this block array are absent.\n continue;\n }\n const instCount = instanceCounts[arrIdx] ?? 0;\n\n for (let inst = 0; inst < instCount; inst++) {\n const ns = expandIToken(arr.rosNamespace, inst);\n\n for (let ep = 0; ep < block.topics.length; ep++) {\n const t = block.topics[ep];\n if (!t) continue;\n const path = joinPath(ns, t.name);\n const idx = topicBase + inst * block.topics.length + ep;\n const desc: TopicDescriptor = {\n kind: 'topic',\n path,\n topicIndex: idx,\n dir: t.dir,\n fields: t.fields,\n defaultPeriodUs: t.defaultPeriodUs,\n wireSize: sumFieldsWireSize(t.fields),\n };\n if (this.#topicsByPath.has(path)) {\n throw new Error(`SchemaIndex: duplicate topic path '${path}'`);\n }\n this.#topicsByPath.set(path, desc);\n this.#topicsByIndex.set(idx, desc);\n }\n\n for (let ep = 0; ep < block.services.length; ep++) {\n const s = block.services[ep];\n if (!s) continue;\n const path = joinPath(ns, s.name);\n const idx = serviceBase + inst * block.services.length + ep;\n const desc: ServiceDescriptor = {\n kind: 'service',\n path,\n serviceIndex: idx,\n requestFields: s.request,\n responseFields: s.response,\n requestWireSize: sumFieldsWireSize(s.request),\n responseWireSize: sumFieldsWireSize(s.response),\n };\n if (this.#servicesByPath.has(path)) {\n throw new Error(`SchemaIndex: duplicate service path '${path}'`);\n }\n this.#servicesByPath.set(path, desc);\n this.#servicesByIndex.set(idx, desc);\n }\n\n for (let ep = 0; ep < block.params.length; ep++) {\n const p = block.params[ep];\n if (!p) continue;\n const path = joinPath(ns, p.name);\n const idx = paramBase + inst * block.params.length + ep;\n const wireSize = fieldWireSize({\n name: p.name,\n type: p.type,\n arrayLen: p.arrayLen,\n txEnabled: true,\n });\n const desc: ParamDescriptor = {\n kind: 'param',\n path,\n paramIndex: idx,\n type: p.type,\n arrayLen: p.arrayLen,\n wireSize,\n defaultValue: p.defaultValue,\n minValue: p.minValue,\n maxValue: p.maxValue,\n };\n if (this.#paramsByPath.has(path)) {\n throw new Error(`SchemaIndex: duplicate param path '${path}'`);\n }\n this.#paramsByPath.set(path, desc);\n this.#paramsByIndex.set(idx, desc);\n }\n }\n }\n }\n\n topic(path: string): TopicDescriptor | undefined {\n return this.#topicsByPath.get(path);\n }\n service(path: string): ServiceDescriptor | undefined {\n return this.#servicesByPath.get(path);\n }\n param(path: string): ParamDescriptor | undefined {\n return this.#paramsByPath.get(path);\n }\n\n topicByIndex(idx: number): TopicDescriptor | undefined {\n return this.#topicsByIndex.get(idx);\n }\n serviceByIndex(idx: number): ServiceDescriptor | undefined {\n return this.#servicesByIndex.get(idx);\n }\n paramByIndex(idx: number): ParamDescriptor | undefined {\n return this.#paramsByIndex.get(idx);\n }\n\n /** All topic paths in numbering order. Useful for debugging / sniffer UI. */\n topicPaths(): string[] {\n return [...this.#topicsByPath.keys()];\n }\n servicePaths(): string[] {\n return [...this.#servicesByPath.keys()];\n }\n paramPaths(): string[] {\n return [...this.#paramsByPath.keys()];\n }\n}\n","/**\n * Sequential u8 allocator used for the config-plane `seq` field shared by\n * every command this master has issued to a given slave. Wraps at 256,\n * matching `BridgeNode::alloc_seq` in\n * `fibril_can_bridge/src/bridge_node.cpp` (the bridge wraps on the same\n * boundary; the AckTracker indexes by the wrapped value).\n */\nexport class SeqAllocator {\n #next = 0;\n\n next(): number {\n const v = this.#next & 0xff;\n this.#next = (this.#next + 1) & 0xff;\n return v;\n }\n\n reset(): void {\n this.#next = 0;\n }\n}\n","import type { CanFrameTx } from '@fibril/can-transport';\nimport {\n CHAN_SVC_REQUEST,\n MAX_FRAME_PAYLOAD,\n makeExtId,\n SEG_FIRST_DATA,\n SEG_MAX_SEQ,\n SEG_MAX_TOTAL,\n SEG_REST_DATA,\n segOffset,\n} from './can-id.js';\n/**\n * Build the §7.4 SVC_REQUEST frame stream for a master→slave call. Mirrors\n * `make_svc_request_frames` in\n * `fibril_can_bridge/include/fibril_can_bridge/svc_request.hpp`.\n *\n * - ≤64 byte payload → one SINGLE frame (seg=0).\n * - Larger → seq=0 carries `[0]=0 [1..2]=total_len + ≤61B data`, subsequent\n * seqs carry `[0]=seq + ≤63B data`. Throws on payloads >1024B.\n */\nexport function makeSvcRequestFrames(\n nodeId: number,\n svcIdx: number,\n callId: number,\n payload: Uint8Array,\n): CanFrameTx[] {\n if (payload.length > SEG_MAX_TOTAL) {\n throw new RangeError(\n `service request payload ${payload.length} exceeds SEG_MAX_TOTAL (${SEG_MAX_TOTAL})`,\n );\n }\n if (payload.length <= MAX_FRAME_PAYLOAD) {\n return [\n {\n id: makeExtId(CHAN_SVC_REQUEST, nodeId, svcIdx, callId, 0),\n extended: true,\n fd: true,\n data: payload,\n },\n ];\n }\n const total = payload.length;\n const rest = total - SEG_FIRST_DATA;\n const extras = Math.ceil(rest / SEG_REST_DATA);\n const nSegs = 1 + extras;\n if (nSegs - 1 > SEG_MAX_SEQ) {\n throw new RangeError(`segmented request would need ${nSegs} segments (cap ${SEG_MAX_SEQ + 1})`);\n }\n const out: CanFrameTx[] = [];\n for (let seq = 0; seq < nSegs; seq++) {\n let body: Uint8Array;\n if (seq === 0) {\n const take = Math.min(total, SEG_FIRST_DATA);\n body = new Uint8Array(3 + take);\n body[0] = 0;\n body[1] = total & 0xff;\n body[2] = (total >>> 8) & 0xff;\n body.set(payload.subarray(0, take), 3);\n } else {\n const off = segOffset(seq);\n const take = Math.min(SEG_REST_DATA, total - off);\n body = new Uint8Array(1 + take);\n body[0] = seq;\n body.set(payload.subarray(off, off + take), 1);\n }\n out.push({\n id: makeExtId(CHAN_SVC_REQUEST, nodeId, svcIdx, callId, 1),\n extended: true,\n fd: true,\n data: body,\n });\n }\n return out;\n}\n\n/**\n * Build §7.4 response segments. Used by mock slaves and any TS slave runtime.\n * `channel` is the channel field (typically `CHAN_SVC_RESPONSE`); the payload\n * is `[status, ...response]` so the caller bakes status into the buffer.\n */\nexport function makeSvcSegmentedFrames(\n channel: number,\n nodeId: number,\n svcIdx: number,\n callId: number,\n payload: Uint8Array,\n): CanFrameTx[] {\n if (payload.length > SEG_MAX_TOTAL) {\n throw new RangeError(\n `service response payload ${payload.length} exceeds SEG_MAX_TOTAL (${SEG_MAX_TOTAL})`,\n );\n }\n if (payload.length <= MAX_FRAME_PAYLOAD) {\n return [\n {\n id: makeExtId(channel, nodeId, svcIdx, callId, 0),\n extended: true,\n fd: true,\n data: payload,\n },\n ];\n }\n const total = payload.length;\n const rest = total - SEG_FIRST_DATA;\n const extras = Math.ceil(rest / SEG_REST_DATA);\n const nSegs = 1 + extras;\n if (nSegs - 1 > SEG_MAX_SEQ) {\n throw new RangeError(\n `segmented response would need ${nSegs} segments (cap ${SEG_MAX_SEQ + 1})`,\n );\n }\n const out: CanFrameTx[] = [];\n for (let seq = 0; seq < nSegs; seq++) {\n let body: Uint8Array;\n if (seq === 0) {\n const take = Math.min(total, SEG_FIRST_DATA);\n body = new Uint8Array(3 + take);\n body[0] = 0;\n body[1] = total & 0xff;\n body[2] = (total >>> 8) & 0xff;\n body.set(payload.subarray(0, take), 3);\n } else {\n const off = segOffset(seq);\n const take = Math.min(SEG_REST_DATA, total - off);\n body = new Uint8Array(1 + take);\n body[0] = seq;\n body.set(payload.subarray(off, off + take), 1);\n }\n out.push({\n id: makeExtId(channel, nodeId, svcIdx, callId, 1),\n extended: true,\n fd: true,\n data: body,\n });\n }\n return out;\n}\n\n/**\n * Bitmask of segment seqs required to reassemble a `totalLen`-byte payload.\n * Identical formula to `expected_mask` in\n * `fibril_can_bridge/src/node_agent.cpp` and the slave's `seg_expected_mask`.\n */\nexport function segExpectedMask(totalLen: number): number {\n if (totalLen <= 0) return 0;\n if (totalLen <= SEG_FIRST_DATA) return 1;\n const rest = totalLen - SEG_FIRST_DATA;\n const extras = Math.ceil(rest / SEG_REST_DATA);\n const nSegs = 1 + extras;\n if (nSegs >= 32) return 0xffffffff;\n return (1 << nSegs) - 1;\n}\n\n/**\n * Per-(svc, call_id) reassembly slot. The caller drives one of these per\n * outstanding incoming segmented transfer.\n */\nexport class SegmentReassembler {\n totalLen = 0;\n rxBitmap = 0;\n lastRxMs = 0;\n #buffer: Uint8Array = new Uint8Array(0);\n\n /**\n * Ingest one seg=1 frame. `data` is the frame payload (with the seq /\n * total_len header still attached). Returns the fully-assembled payload\n * once every required segment has arrived; otherwise null. Returns null\n * on protocol violations and resets the slot.\n */\n ingest(data: Uint8Array, nowMs: number): Uint8Array | null {\n if (data.length === 0) return this.#reset();\n const seq = data[0] ?? 0;\n if (seq > SEG_MAX_SEQ) return this.#reset();\n this.lastRxMs = nowMs;\n\n if (seq === 0) {\n if (data.length < 3) return this.#reset();\n const total = ((data[1] ?? 0) | ((data[2] ?? 0) << 8)) & 0xffff;\n if (total === 0 || total > SEG_MAX_TOTAL) return this.#reset();\n if (this.totalLen !== 0 && this.totalLen !== total) {\n this.totalLen = total;\n this.rxBitmap = 0;\n this.#buffer = new Uint8Array(total);\n } else {\n this.totalLen = total;\n if (this.#buffer.length < total) {\n const grown = new Uint8Array(total);\n grown.set(this.#buffer.subarray(0, Math.min(this.#buffer.length, total)));\n this.#buffer = grown;\n }\n }\n const segDataLen = Math.min(data.length - 3, SEG_FIRST_DATA, total);\n if (segDataLen > 0) this.#buffer.set(data.subarray(3, 3 + segDataLen), 0);\n } else {\n const off = segOffset(seq);\n const segDataLen = Math.min(data.length - 1, SEG_REST_DATA);\n if (off + segDataLen > SEG_MAX_TOTAL) return this.#reset();\n if (this.totalLen !== 0 && off + segDataLen > this.totalLen) return this.#reset();\n if (this.#buffer.length < off + segDataLen) {\n const grown = new Uint8Array(off + segDataLen);\n grown.set(this.#buffer);\n this.#buffer = grown;\n }\n if (segDataLen > 0) this.#buffer.set(data.subarray(1, 1 + segDataLen), off);\n }\n this.rxBitmap |= 1 << seq;\n if (this.totalLen === 0) return null;\n const need = segExpectedMask(this.totalLen);\n if ((this.rxBitmap & ~need) !== 0) return this.#reset();\n if ((this.rxBitmap & need) !== need) return null;\n const out = this.#buffer.slice(0, this.totalLen);\n this.#reset();\n return out;\n }\n\n #reset(): null {\n this.totalLen = 0;\n this.rxBitmap = 0;\n this.#buffer = new Uint8Array(0);\n return null;\n }\n}\n","import type { CanFrame, ITransport, Unsubscribe } from '@fibril/can-transport';\nimport {\n CHAN_SVC_REQUEST,\n CHAN_SVC_RESPONSE,\n extChannel,\n extIndex,\n extNodeId,\n extSeg,\n extSeq,\n makeExtId,\n SVC_ACCEPTED,\n SVC_CANCEL,\n} from './can-id.js';\nimport { padToDlc } from './dlc.js';\nimport { makeSvcRequestFrames, SegmentReassembler } from './segmented-transfer.js';\n\n/** Per-call options. */\nexport interface ServiceCallOptions {\n /** Pre-encoded request payload (no status byte — that's response-only). */\n request: Uint8Array;\n /** Override default timeout. Default 250 ms (matches bridge `service_timeout_`). */\n timeoutMs?: number;\n /** Cancel via AbortSignal — fires SVC_CANCEL (§7.5) to the slave. */\n signal?: AbortSignal;\n}\n\n/** Resolved service response. `status === 0` (SVC_OK) is the success path. */\nexport interface ServiceResult {\n status: number;\n data: Uint8Array;\n}\n\n/** Throwable error union for `ServiceClient.call`. */\nexport class ServiceCallError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\nexport class ServiceTimeoutError extends ServiceCallError {\n constructor(message = 'service call timed out') {\n super(message);\n }\n}\nexport class ServiceUnavailableError extends ServiceCallError {\n constructor(message = 'service unavailable (slave lost or reprovisioned)') {\n super(message);\n }\n}\nexport class ServiceCancelledError extends ServiceCallError {\n constructor(message = 'service call cancelled') {\n super(message);\n }\n}\nexport class NoCallSlotError extends ServiceCallError {\n constructor(serviceIndex: number) {\n super(`no free call_id slot for service_index ${serviceIndex}`);\n }\n}\n\ninterface PendingCall {\n serviceIndex: number;\n callId: number;\n deadlineMs: number;\n timeoutMs: number;\n resolve: (r: ServiceResult) => void;\n reject: (err: Error) => void;\n reassembler: SegmentReassembler;\n signal?: AbortSignal;\n abortListener?: () => void;\n acceptedSeen: boolean;\n}\n\n/** Cap on simultaneous in-flight segmented transfers. Matches bridge. */\nconst REASM_MAX_CONCURRENT = 16;\n/** §7.4 reassembly TTL. */\nconst SEG_TIMEOUT_MS = 100;\n\n/**\n * Single-slave master service-call client. Port of NodeAgent's\n * begin_service_call / on_service_response / on_service_segment flow but\n * Promise-based and AbortSignal-aware.\n *\n * One {@link ServiceClient} attaches to the transport and demuxes incoming\n * SVC_RESPONSE frames for a single `nodeId`. NodeAgent owns one per slave\n * and exposes it on the running snapshot.\n */\nexport class ServiceClient {\n readonly nodeId: number;\n readonly #transport: ITransport;\n readonly #defaultTimeoutMs: number;\n readonly #now: () => number;\n\n #unsub: Unsubscribe | null = null;\n\n // Round-robin per-service call_id allocator. 0xFF is reserved as the\n // \"no free slot\" sentinel.\n readonly #nextCallId = new Map<number, number>();\n // Active calls keyed by (svc << 8) | call_id.\n readonly #pending = new Map<number, PendingCall>();\n\n constructor(opts: {\n nodeId: number;\n transport: ITransport;\n defaultTimeoutMs?: number;\n now?: () => number;\n }) {\n this.nodeId = opts.nodeId;\n this.#transport = opts.transport;\n this.#defaultTimeoutMs = opts.defaultTimeoutMs ?? 250;\n this.#now = opts.now ?? (() => Date.now());\n }\n\n attach(): void {\n if (this.#unsub !== null) return;\n this.#unsub = this.#transport.onFrame((f: CanFrame) => this.#onFrame(f));\n }\n\n detach(): void {\n if (this.#unsub === null) return;\n this.#unsub();\n this.#unsub = null;\n }\n\n /** Number of in-flight calls. Testing / introspection. */\n get pendingCount(): number {\n return this.#pending.size;\n }\n\n /**\n * Sweep call deadlines and segment-reassembly TTLs. The owning agent\n * should call this from its periodic sweep loop.\n */\n sweep(nowMs: number = this.#now()): void {\n for (const [key, call] of this.#pending) {\n if (call.deadlineMs <= nowMs) {\n this.#pending.delete(key);\n this.#detachAbort(call);\n call.reject(new ServiceTimeoutError());\n continue;\n }\n // Drop a partially-reassembled response if the slave has gone silent\n // mid-transfer for more than the TTL — matches sweep_service_segments.\n if (call.reassembler.totalLen !== 0 && nowMs - call.reassembler.lastRxMs > SEG_TIMEOUT_MS) {\n // Reset the slot but keep the call active so the slave can retry\n // (e.g. another response variant) until the outer deadline expires.\n call.reassembler.totalLen = 0;\n call.reassembler.rxBitmap = 0;\n }\n }\n }\n\n /** Reject every in-flight call as Unavailable. NodeAgent calls this on lost / reprovision. */\n failAll(reason = 'slave reprovisioning'): void {\n const pending = [...this.#pending.values()];\n this.#pending.clear();\n for (const c of pending) {\n this.#detachAbort(c);\n c.reject(new ServiceUnavailableError(reason));\n }\n }\n\n async call(serviceIndex: number, opts: ServiceCallOptions): Promise<ServiceResult> {\n if (serviceIndex < 0 || serviceIndex > 0xff) {\n throw new RangeError(`serviceIndex out of range: ${serviceIndex}`);\n }\n const callId = this.#allocCallId(serviceIndex);\n if (callId === 0xff) throw new NoCallSlotError(serviceIndex);\n\n const timeoutMs = opts.timeoutMs ?? this.#defaultTimeoutMs;\n const key = (serviceIndex << 8) | callId;\n if (this.#pending.size >= REASM_MAX_CONCURRENT * 4) {\n // Pathological fan-out across many services; let the caller back off.\n // (REASM cap is per-active-segment-stream; this is a softer guard.)\n throw new NoCallSlotError(serviceIndex);\n }\n\n return new Promise<ServiceResult>((resolve, reject) => {\n const call: PendingCall = {\n serviceIndex,\n callId,\n deadlineMs: this.#now() + timeoutMs,\n timeoutMs,\n resolve,\n reject,\n reassembler: new SegmentReassembler(),\n acceptedSeen: false,\n };\n if (opts.signal) {\n call.signal = opts.signal;\n if (opts.signal.aborted) {\n reject(new ServiceCancelledError());\n return;\n }\n call.abortListener = () => {\n if (!this.#pending.has(key)) return;\n this.#pending.delete(key);\n this.#detachAbort(call);\n // SPEC §7.5 — send SVC_CANCEL so the slave doesn't keep computing.\n // Best-effort; if the transport is closed the slave will time out.\n void this.#sendCancel(call.serviceIndex, call.callId).catch(() => {});\n reject(new ServiceCancelledError());\n };\n opts.signal.addEventListener('abort', call.abortListener, { once: true });\n }\n this.#pending.set(key, call);\n // Emit request frames — fire-and-forget; transport errors surface as\n // a timeout rather than killing the promise immediately so a brief\n // disconnect doesn't drop calls mid-flight.\n const frames = makeSvcRequestFrames(this.nodeId, serviceIndex, callId, opts.request);\n for (const f of frames) {\n void this.#transport.send(f).catch(() => {});\n }\n });\n }\n\n // ---------------------------------------------------------------------\n // Frame ingress\n // ---------------------------------------------------------------------\n\n #onFrame(f: CanFrame): void {\n if (!f.extended) return;\n if (extNodeId(f.id) !== this.nodeId) return;\n if (extChannel(f.id) !== CHAN_SVC_RESPONSE) return;\n const svcIdx = extIndex(f.id);\n const callId = extSeq(f.id);\n const seg = extSeg(f.id);\n const key = (svcIdx << 8) | callId;\n const call = this.#pending.get(key);\n if (!call) return;\n\n if (seg === 0) {\n // Single-frame response — first byte is status, rest is payload.\n if (f.data.length === 0) return;\n const status = f.data[0] ?? 0;\n const data = f.data.slice(1);\n this.#finishMaybeAccepted(key, call, status, data);\n return;\n }\n // Segmented response — accumulate.\n const assembled = call.reassembler.ingest(f.data, this.#now());\n if (assembled === null) return;\n if (assembled.length === 0) return;\n const status = assembled[0] ?? 0;\n const data = assembled.slice(1);\n this.#finishMaybeAccepted(key, call, status, data);\n }\n\n #finishMaybeAccepted(key: number, call: PendingCall, status: number, data: Uint8Array): void {\n if (status === SVC_ACCEPTED) {\n // §7.2 — two-stage reply. The slave commits to answering but is\n // still computing. Extend the deadline by another full timeout\n // window and wait for the real status.\n if (!call.acceptedSeen) {\n call.acceptedSeen = true;\n call.deadlineMs = this.#now() + call.timeoutMs;\n }\n return;\n }\n this.#pending.delete(key);\n this.#detachAbort(call);\n call.resolve({ status, data });\n }\n\n #allocCallId(svcIdx: number): number {\n let next = this.#nextCallId.get(svcIdx) ?? 0;\n for (let i = 0; i < 0xff; i++) {\n if (next === 0xff) next = 0;\n const key = (svcIdx << 8) | next;\n if (!this.#pending.has(key)) {\n this.#nextCallId.set(svcIdx, (next + 1) & 0xff);\n return next;\n }\n next = (next + 1) & 0xff;\n }\n return 0xff;\n }\n\n async #sendCancel(svcIdx: number, callId: number): Promise<void> {\n // SVC_CANCEL goes on the SvcRequest channel addressed to the canonical\n // 0xFF service_index (§7.5). Payload is the (svc_idx, call_id) of the\n // call being cancelled.\n const payload = padToDlc(new Uint8Array([svcIdx & 0xff, callId & 0xff]));\n await this.#transport.send({\n id: makeExtId(CHAN_SVC_REQUEST, this.nodeId, SVC_CANCEL, 0, 0),\n extended: true,\n fd: true,\n data: payload,\n });\n }\n\n #detachAbort(call: PendingCall): void {\n if (call.signal && call.abortListener) {\n call.signal.removeEventListener('abort', call.abortListener);\n call.abortListener = undefined;\n }\n }\n}\n","import { SVC_PARAM_SET } from './can-id.js';\nimport {\n packScalarF32Le,\n packScalarF64Le,\n packScalarIntLe,\n ScalarType,\n scalarName,\n scalarSize,\n signExtend,\n unpackScalarF32Le,\n unpackScalarF64Le,\n unpackScalarIntLe,\n} from './scalar-codec.js';\nimport type { ParamDescriptor } from './schema-index.js';\nimport type { ServiceClient } from './service-client.js';\n\n/**\n * Schema-driven typed wrapper around PARAM_SET (SPEC §8.2, reserved\n * service_index 0xFD).\n *\n * Per SPEC §8.1 PARAM is M→S one-way: the master holds the source of truth\n * and re-injects defaults at provisioning time, so this wrapper exposes\n * `.set()` only — there's no `.get()` that queries the slave. The\n * descriptor's decoded default is available via `defaultValue()` for\n * reference / hydration of master-side state.\n *\n * The wire shape for one PARAM_SET request is:\n * [0] count = 1\n * [1..2] u16 param_index (LE)\n * [3..] value (scalar little-endian or fixed-array contiguous)\n *\n * Response is `[0] status [1..2] failed_param_index (when status != OK)`.\n * `set()` resolves with the status code; non-OK includes `failedIndex` so\n * the caller can correlate with a multi-param batch (single-param sets\n * always blame this param).\n */\n\nexport class ParamCodecError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ParamCodecError';\n }\n}\n\nexport interface TypedParamSetOptions {\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport interface TypedParamSetResult {\n /** SPEC §7.2 status (0 = SVC_OK). */\n readonly status: number;\n /**\n * On `status != SVC_OK`, the slave-reported param_index that failed.\n * For a single-param call this is always `descriptor.paramIndex` if the\n * slave fills the field, else `null` (slave omitted the field).\n */\n readonly failedIndex: number | null;\n}\n\nfunction packValueInto(\n desc: ParamDescriptor,\n value: unknown,\n out: Uint8Array,\n offset: number,\n): void {\n if (desc.arrayLen === 0) {\n packOneScalar(desc.type, value, out, offset, desc.path);\n return;\n }\n if (!Array.isArray(value)) {\n throw new ParamCodecError(\n `param '${desc.path}': expected array of length ${desc.arrayLen}, got ${typeof value}`,\n );\n }\n if (value.length !== desc.arrayLen) {\n throw new ParamCodecError(\n `param '${desc.path}': expected array length ${desc.arrayLen}, got ${value.length}`,\n );\n }\n const stride = scalarSize(desc.type);\n for (let i = 0; i < desc.arrayLen; i++) {\n packOneScalar(desc.type, value[i], out, offset + i * stride, desc.path);\n }\n}\n\nfunction packOneScalar(\n type: ScalarType,\n value: unknown,\n out: Uint8Array,\n offset: number,\n pathForErr: string,\n): void {\n switch (type) {\n case ScalarType.Bool:\n if (typeof value !== 'boolean') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected boolean for bool, got ${typeof value}`,\n );\n }\n out[offset] = value ? 1 : 0;\n return;\n case ScalarType.F32:\n if (typeof value !== 'number') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected number for f32, got ${typeof value}`,\n );\n }\n packScalarF32Le(value, out, offset);\n return;\n case ScalarType.F64:\n if (typeof value !== 'number') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected number for f64, got ${typeof value}`,\n );\n }\n packScalarF64Le(value, out, offset);\n return;\n default:\n if (type === ScalarType.U64 || type === ScalarType.I64) {\n if (typeof value !== 'bigint') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected bigint for ${scalarName(type)}, got ${typeof value}`,\n );\n }\n } else if (typeof value !== 'number') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected number for ${scalarName(type)}, got ${typeof value}`,\n );\n }\n packScalarIntLe(type, value as number | bigint, out, offset);\n }\n}\n\nfunction unpackScalar(\n type: ScalarType,\n src: Uint8Array,\n offset: number,\n): number | bigint | boolean {\n switch (type) {\n case ScalarType.Bool:\n return (src[offset] ?? 0) !== 0;\n case ScalarType.F32:\n return unpackScalarF32Le(src, offset);\n case ScalarType.F64:\n return unpackScalarF64Le(src, offset);\n case ScalarType.I8:\n case ScalarType.I16:\n case ScalarType.I32: {\n const bits = unpackScalarIntLe(type, src, offset);\n return Number(signExtend(bits, scalarSize(type)));\n }\n case ScalarType.U8:\n case ScalarType.U16:\n case ScalarType.U32:\n return Number(unpackScalarIntLe(type, src, offset));\n case ScalarType.I64:\n return signExtend(unpackScalarIntLe(type, src, offset), 8);\n case ScalarType.U64:\n return unpackScalarIntLe(type, src, offset);\n }\n}\n\nfunction unpackValue(desc: ParamDescriptor, src: Uint8Array): unknown {\n if (src.length < desc.wireSize) return null;\n if (desc.arrayLen === 0) {\n return unpackScalar(desc.type, src, 0);\n }\n const stride = scalarSize(desc.type);\n const out: Array<number | bigint | boolean> = [];\n for (let i = 0; i < desc.arrayLen; i++) {\n out.push(unpackScalar(desc.type, src, i * stride));\n }\n return out;\n}\n\n/** Build a PARAM_SET request payload for a single (descriptor, value) pair. */\nexport function encodeParamSetSingle(desc: ParamDescriptor, value: unknown): Uint8Array {\n const out = new Uint8Array(1 + 2 + desc.wireSize);\n out[0] = 1; // count\n out[1] = desc.paramIndex & 0xff;\n out[2] = (desc.paramIndex >>> 8) & 0xff;\n packValueInto(desc, value, out, 3);\n return out;\n}\n\nexport class TypedParam<T> {\n readonly path: string;\n readonly descriptor: ParamDescriptor;\n readonly #client: ServiceClient;\n\n constructor(client: ServiceClient, descriptor: ParamDescriptor) {\n this.#client = client;\n this.descriptor = descriptor;\n this.path = descriptor.path;\n }\n\n /**\n * Decode the schema-embedded default value (SPEC §9.1 `default`). Useful\n * to seed the master-side persistence store. Returns `null` if the\n * descriptor carries no default payload.\n */\n defaultValue(): T | null {\n if (this.descriptor.defaultValue.length === 0) return null;\n return unpackValue(this.descriptor, this.descriptor.defaultValue) as T;\n }\n\n /** Send a PARAM_SET with a single entry for this param. */\n async set(value: T, opts: TypedParamSetOptions = {}): Promise<TypedParamSetResult> {\n const request = encodeParamSetSingle(this.descriptor, value);\n const result = await this.#client.call(SVC_PARAM_SET, {\n request,\n timeoutMs: opts.timeoutMs,\n signal: opts.signal,\n });\n let failedIndex: number | null = null;\n if (result.status !== 0 && result.data.length >= 2) {\n failedIndex = (result.data[0] ?? 0) | ((result.data[1] ?? 0) << 8);\n }\n return { status: result.status, failedIndex };\n }\n}\n","import { type Dict, decodeFields, encodeFields } from './dynamic-codec.js';\nimport type { ServiceDescriptor } from './schema-index.js';\nimport type { ServiceClient } from './service-client.js';\n\n/**\n * Schema-driven typed wrapper around {@link ServiceClient.call}.\n *\n * The generic parameters are compile-time only: at runtime, encoding is\n * driven entirely by the {@link ServiceDescriptor}'s field list. Callers\n * supply `Req` / `Resp` interfaces matching the schema fields by name —\n * the runtime trusts the dict layout and packs by field iteration order.\n *\n * Returned on success: `{ status, data }` where `status` is the SPEC §7.2\n * service status (0 = OK) and `data` is the decoded response dict typed as\n * `Resp`. Non-OK responses still return a `data` object — the slave is\n * required to fill the response payload even on failure (§7.2), and the\n * decoder will best-effort attempt it; if the body is shorter than the\n * schema demands, `data` is `null` instead of throwing (so callers can\n * surface the status to the user without losing the whole response).\n */\nexport interface TypedServiceResult<Resp extends Dict> {\n readonly status: number;\n readonly data: Resp | null;\n}\n\nexport interface TypedServiceCallOptions {\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport class TypedService<Req extends Dict, Resp extends Dict> {\n readonly path: string;\n readonly descriptor: ServiceDescriptor;\n readonly #client: ServiceClient;\n\n constructor(client: ServiceClient, descriptor: ServiceDescriptor) {\n this.#client = client;\n this.descriptor = descriptor;\n this.path = descriptor.path;\n }\n\n /** Encode `request`, dispatch via the service plane, decode the response. */\n async call(request: Req, opts: TypedServiceCallOptions = {}): Promise<TypedServiceResult<Resp>> {\n const encoded = encodeFields(this.descriptor.requestFields, request);\n const result = await this.#client.call(this.descriptor.serviceIndex, {\n request: encoded,\n timeoutMs: opts.timeoutMs,\n signal: opts.signal,\n });\n let data: Resp | null = null;\n if (this.descriptor.responseFields.length === 0) {\n // Schema says no payload — keep `data` null so callers don't get an empty\n // object that looks like decoded content.\n data = Object.freeze({}) as unknown as Resp;\n } else if (result.data.length >= this.descriptor.responseWireSize) {\n data = decodeFields(this.descriptor.responseFields, result.data) as Resp;\n }\n return { status: result.status, data };\n }\n}\n","import type { CanFrame, ITransport, Unsubscribe } from '@fibril/can-transport';\nimport { type AckOutcome, AckTracker } from './ack-tracker.js';\nimport {\n CHAN_CONFIG,\n CMD_ACK,\n CMD_ANNOUNCE,\n CMD_HEARTBEAT,\n CMD_NAK,\n CMD_SCHEMA_DATA,\n DIR_RX_M2S,\n DIR_TX_S2M,\n extChannel,\n extIndex,\n extNodeId,\n extSeq,\n STATE_RUNNING,\n STATE_SUSPENDED,\n} from './can-id.js';\nimport {\n type AnnounceMsg,\n decodeAnnounce,\n decodeHeartbeat,\n decodeNak,\n decodeSchemaData,\n encodeDiscoverTo,\n encodeFrameDefine,\n encodeSchemaRead,\n encodeStart,\n encodeStop,\n type FrameDefineEntry,\n SchemaAccumulator,\n} from './config-plane.js';\nimport type { Dict } from './dynamic-codec.js';\nimport { computeNumbering, type NumberingResult } from './numbering.js';\nimport { Direction, decodeSchemaWithMeta, type NodeSchema } from './schema.js';\nimport { schemaHashPrefix } from './schema-hash.js';\nimport { SchemaIndex } from './schema-index.js';\nimport { SeqAllocator } from './seq-allocator.js';\nimport { ServiceClient } from './service-client.js';\nimport { TypedParam } from './typed-param.js';\nimport { TypedService } from './typed-service.js';\n\n/**\n * One planned data-plane CAN frame, supplied by the caller (typically a\n * frame planner — P6) and consumed by {@link NodeAgent} when it issues\n * FRAME_DEFINE during bring-up. Mirrors `FrameSpec` in\n * `fibril_can_bridge/include/fibril_can_bridge/frame_planner.hpp`.\n */\nexport interface FramePlan {\n stdId: number;\n periodUs: number;\n dir: Direction;\n entries: readonly FrameDefineEntry[];\n}\n\n/**\n * Per-bring-up context handed to a {@link FramePlanFactory} callback so the\n * caller can branch on the specific slave being provisioned (e.g. read an\n * external per-nodeId field-enable override map). The same factory is\n * shared across every {@link NodeAgent} the controller spawns, so this is\n * the only way for the factory to discriminate slaves.\n */\nexport interface FramePlanContext {\n /** The slave being provisioned (1..0x7E). */\n readonly nodeId: number;\n}\n\n/**\n * Builds the FRAME_DEFINE plan for a slave once its schema is decoded and\n * numbered. The optional `ctx` argument carries the nodeId so callers that\n * keep per-slave overrides (e.g. UI-controlled S→M field toggles) can fork\n * on it without threading state through {@link NodeAgentOptions}. The\n * 2-arg form is still accepted — extra parameters are simply ignored.\n */\nexport type FramePlanFactory =\n | ((\n schema: NodeSchema,\n numbering: NumberingResult,\n ctx: FramePlanContext,\n ) => readonly FramePlan[])\n | readonly FramePlan[];\n\n/** Phase machine — public for observers. */\nexport type NodeProvisionState =\n | { kind: 'idle' }\n | { kind: 'awaiting-announce' }\n | { kind: 'schema-reading'; received: number; total: number }\n | { kind: 'numbering' }\n | { kind: 'provisioning'; pendingDefines: number }\n /**\n * FRAME_DEFINE completed successfully but START has been withheld by\n * the {@link NodeAgentOptions.autoStart} gate. `startNow()` moves the\n * agent forward. `reprovision()` / a fresh ANNOUNCE re-enter the flow\n * from bring-up.\n */\n | { kind: 'awaiting-start' }\n | { kind: 'running' }\n /** Slave reported node_state = SUSPENDED. Reverts to running on the next non-SUSPENDED HEARTBEAT. */\n | { kind: 'suspended' }\n | { kind: 'lost'; reason: string }\n | { kind: 'blocked'; reason: string };\n\n/** Snapshot available once the slave reaches RUNNING. */\nexport interface NodeRunningSnapshot {\n nodeId: number;\n schemaHash: bigint;\n bootId: number;\n instanceCounts: Uint8Array;\n blob: Uint8Array;\n schema: NodeSchema;\n numbering: NumberingResult;\n framePlan: readonly FramePlan[];\n /** std_id → topic_index map for the data plane (one entry per FRAME_DEFINE). */\n stdIdToTopicIndex: Map<number, number>;\n /** §7 master-side RPC client. Stays valid for the lifetime of the snapshot. */\n services: ServiceClient;\n /**\n * Path → IR descriptor lookup. Drives the typed accessors below.\n * Exposed for sniffer-style introspection (`index.topicPaths()` etc.).\n */\n index: SchemaIndex;\n /**\n * Schema-driven typed RPC wrapper. Throws if `path` is unknown. Generic\n * `Req` / `Resp` are compile-time only — runtime encoding is driven by\n * the schema's field list.\n */\n service<Req extends Dict, Resp extends Dict>(path: string): TypedService<Req, Resp>;\n /**\n * Schema-driven PARAM_SET wrapper. Throws if `path` is unknown.\n * `T` is `number` for scalar params (except U64/I64 → `bigint`),\n * `boolean` for bool, or the array form for fixed-length array params.\n */\n param<T = number | bigint | boolean | number[] | bigint[] | boolean[]>(\n path: string,\n ): TypedParam<T>;\n}\n\nexport interface NodeAgentOptions {\n /** 1..0x7E — broadcast (0x7F) is rejected. */\n nodeId: number;\n /** Already open()'d transport. The agent attaches its own onFrame. */\n transport: ITransport;\n /** Strategy for building the FRAME_DEFINE plan. */\n framePlan: FramePlanFactory;\n /**\n * Per-config-command ACK timeout in ms. Slaves must ACK within this\n * window or the agent abandons the bring-up attempt and waits for the\n * next ANNOUNCE. Default 250 ms (matches bridge's\n * `bring_up_ack_timeout_`).\n */\n ackTimeoutMs?: number;\n /**\n * SCHEMA_READ chunk byte limit. SPEC §4.3 caps a single response at the\n * SINGLE-frame payload (≤59 data bytes after the 4-byte offset header).\n * Default 59.\n */\n schemaChunkSize?: number;\n /**\n * Multiplier on `ackTimeoutMs` used as the schema-read retry budget.\n * Default 3 (one initial + two retries).\n */\n schemaReadRetries?: number;\n /**\n * Heartbeat-loss budget. The agent expects a HEARTBEAT every 100 ms\n * (§14); after this much silence it transitions to `lost`. Default 350.\n */\n heartbeatTimeoutMs?: number;\n /** Per-call default timeout for `services.call()`. Default `ackTimeoutMs`. */\n serviceTimeoutMs?: number;\n /**\n * Gate consulted right before START is issued. When it returns `false`,\n * the agent stops in {@link NodeProvisionState} `awaiting-start` after\n * FRAME_DEFINE ACKs come back; the caller commits with `startNow()`.\n * Read fresh at each decision point so callers can flip the setting at\n * runtime without reconstructing the agent. Default `() => true`.\n */\n autoStart?: () => boolean;\n /** Optional state-change observer. */\n onState?: (state: NodeProvisionState) => void;\n /** Optional non-fatal error observer (decode warnings, hash mismatch). */\n onError?: (err: Error) => void;\n /**\n * Override for the wall clock. Tests pass a deterministic counter.\n * Default `() => Date.now()`.\n */\n now?: () => number;\n}\n\nconst DEFAULT_OPTS = {\n ackTimeoutMs: 250,\n schemaChunkSize: 59,\n schemaReadRetries: 3,\n heartbeatTimeoutMs: 350,\n} as const;\n\ninterface SchemaReadProgress {\n expectedTotal: number;\n acc: SchemaAccumulator;\n inflightSeq: number;\n inflightLen: number;\n retriesLeft: number;\n inflightDeadlineMs: number;\n}\n\ninterface ProvisioningProgress {\n generation: number;\n pendingDefines: number;\n anyFailure: boolean;\n firstNakReason: number;\n plan: readonly FramePlan[];\n stdIdToTopicIndex: Map<number, number>;\n}\n\n/**\n * Snapshot of everything {@link NodeAgent.#issueStart} needs. Held while\n * we are parked in `awaiting-start` so `startNow()` can resume without\n * re-running FRAME_DEFINE.\n */\ninterface PendingStart {\n a: AnnouncedRecord;\n schema: NodeSchema;\n blob: Uint8Array;\n numbering: NumberingResult;\n generation: number;\n progress: ProvisioningProgress;\n}\n\ninterface AnnouncedRecord {\n schemaHash: bigint;\n bootId: number;\n blobLen: number;\n protocolVersion: number;\n instanceCounts: Uint8Array;\n}\n\n/**\n * Per-slave provisioning state machine. Mirrors\n * `fibril_can_bridge::NodeAgent` lifecycle entry points but trimmed for the\n * single-threaded TS master — no ROS entity creation, no PARAM_SET\n * re-injection (P5), no plan computation (P6).\n *\n * Lifecycle: `idle` → `awaiting-announce` → `schema-reading` (skipped if\n * blob already cached on this agent instance) → `numbering` →\n * `provisioning` → `running`. HEARTBEAT loss drops to `lost`; the next\n * ANNOUNCE restarts the flow.\n */\nexport class NodeAgent {\n readonly nodeId: number;\n readonly #transport: ITransport;\n readonly #framePlan: FramePlanFactory;\n readonly #ackTimeoutMs: number;\n readonly #schemaChunkSize: number;\n readonly #schemaReadRetries: number;\n readonly #heartbeatTimeoutMs: number;\n readonly #autoStart: () => boolean;\n readonly #onState?: (s: NodeProvisionState) => void;\n readonly #onError?: (e: Error) => void;\n readonly #now: () => number;\n\n readonly #seq = new SeqAllocator();\n readonly #acks: AckTracker;\n readonly #services: ServiceClient;\n\n #unsubFrame: Unsubscribe | null = null;\n #sweepHandle: ReturnType<typeof setInterval> | null = null;\n #stopped = false;\n\n #state: NodeProvisionState = { kind: 'idle' };\n #announce: AnnouncedRecord | null = null;\n #schemaRead: SchemaReadProgress | null = null;\n #provisioning: ProvisioningProgress | null = null;\n #pendingStart: PendingStart | null = null;\n #snapshot: NodeRunningSnapshot | null = null;\n #generation = 0;\n\n // Cache of (hash → decoded schema + blob) collected so a reboot with the\n // same schema skips SCHEMA_READ. Mirrors NodeRegistry's blob cache.\n readonly #blobCache = new Map<bigint, { blob: Uint8Array; schema: NodeSchema }>();\n\n #lastHeartbeatMs: number | null = null;\n\n constructor(opts: NodeAgentOptions) {\n if (opts.nodeId < 1 || opts.nodeId > 0x7e) {\n throw new RangeError(`nodeId must be 1..0x7E, got ${opts.nodeId}`);\n }\n this.nodeId = opts.nodeId;\n this.#transport = opts.transport;\n this.#framePlan = opts.framePlan;\n this.#ackTimeoutMs = opts.ackTimeoutMs ?? DEFAULT_OPTS.ackTimeoutMs;\n this.#schemaChunkSize = opts.schemaChunkSize ?? DEFAULT_OPTS.schemaChunkSize;\n this.#schemaReadRetries = opts.schemaReadRetries ?? DEFAULT_OPTS.schemaReadRetries;\n this.#heartbeatTimeoutMs = opts.heartbeatTimeoutMs ?? DEFAULT_OPTS.heartbeatTimeoutMs;\n this.#autoStart = opts.autoStart ?? (() => true);\n this.#onState = opts.onState;\n this.#onError = opts.onError;\n this.#now = opts.now ?? (() => Date.now());\n this.#acks = new AckTracker(this.#now);\n this.#services = new ServiceClient({\n nodeId: this.nodeId,\n transport: this.#transport,\n defaultTimeoutMs: opts.serviceTimeoutMs ?? this.#ackTimeoutMs,\n now: this.#now,\n });\n }\n\n /** Service-plane RPC client for this slave. Always available. */\n get services(): ServiceClient {\n return this.#services;\n }\n\n get state(): NodeProvisionState {\n return this.#state;\n }\n\n get snapshot(): NodeRunningSnapshot | null {\n return this.#snapshot;\n }\n\n /**\n * Attach to the transport and wait for ANNOUNCE. Resolves immediately —\n * progress flows via {@link state} / {@link snapshot} / `onState`. Call\n * `stop()` to detach.\n */\n async start(): Promise<void> {\n if (this.#stopped) {\n throw new Error('NodeAgent.start() after stop() is not supported — construct a new agent');\n }\n if (this.#unsubFrame !== null) return; // idempotent\n this.#unsubFrame = this.#transport.onFrame((f: CanFrame) => this.#onFrame(f));\n this.#services.attach();\n // Poll ACK timeouts, HEARTBEAT-lost watchdog, service deadlines / seg\n // TTL at a fixed cadence. 50 ms is well below ackTimeoutMs (250) and\n // gives boot_id changes a reasonable response window.\n this.#sweepHandle = setInterval(() => this.#sweep(), 50);\n this.#setState({ kind: 'awaiting-announce' });\n }\n\n /**\n * Re-run the FRAME_DEFINE / START handshake against the live slave using\n * the most recent ANNOUNCE + cached schema. The {@link FramePlanFactory}\n * is invoked again — callers that key off an external mutable state\n * (e.g. per-field TX-enable overrides) will see the latest values.\n *\n * The agent must have observed an ANNOUNCE already; `reprovision()`\n * before that throws. RUNNING is required so that the slave is known to\n * be reachable — calling during `lost` would race the heartbeat\n * watchdog. Pending service calls are failed and the current snapshot is\n * torn down before the new bring-up begins, mirroring what happens on a\n * boot_id change.\n */\n async reprovision(): Promise<void> {\n if (this.#stopped) throw new Error('NodeAgent.reprovision() after stop()');\n const a = this.#announce;\n if (a === null) {\n throw new Error('NodeAgent.reprovision() called before ANNOUNCE');\n }\n const cached = this.#blobCache.get(a.schemaHash);\n if (!cached) {\n // Shouldn't happen — every successful ANNOUNCE caches the blob — but\n // be explicit instead of silently falling back to schema-read.\n throw new Error('NodeAgent.reprovision(): no cached schema for current ANNOUNCE');\n }\n this.#reprovisionState();\n await this.#beginBringUp(\n {\n schemaHash: a.schemaHash,\n bootId: a.bootId,\n blobLen: a.blobLen,\n protocolVersion: a.protocolVersion,\n instanceCounts: a.instanceCounts,\n },\n cached.schema,\n cached.blob,\n );\n }\n\n /** Detach, send STOP if currently RUNNING, clear all in-flight state. */\n async stop(): Promise<void> {\n if (this.#stopped) return;\n this.#stopped = true;\n if (this.#sweepHandle !== null) {\n clearInterval(this.#sweepHandle);\n this.#sweepHandle = null;\n }\n if (this.#unsubFrame !== null) {\n this.#unsubFrame();\n this.#unsubFrame = null;\n }\n this.#services.detach();\n this.#services.failAll('NodeAgent.stop()');\n if (this.#state.kind === 'running' && this.#transport.isOpen) {\n try {\n await this.#transport.send(encodeStop(this.nodeId, this.#seq.next()));\n } catch (e) {\n this.#error(e);\n }\n }\n this.#acks.clear();\n this.#schemaRead = null;\n this.#provisioning = null;\n this.#pendingStart = null;\n this.#snapshot = null;\n this.#setState({ kind: 'idle' });\n }\n\n // ---------------------------------------------------------------------\n // Frame ingress\n // ---------------------------------------------------------------------\n\n #onFrame(f: CanFrame): void {\n if (!f.extended) return;\n if (extNodeId(f.id) !== this.nodeId) return;\n if (extChannel(f.id) !== CHAN_CONFIG) return;\n const cmd = extIndex(f.id);\n const seq = extSeq(f.id);\n switch (cmd) {\n case CMD_ANNOUNCE:\n this.#handleAnnounce(f.data);\n break;\n case CMD_HEARTBEAT:\n this.#handleHeartbeat(f.data);\n break;\n case CMD_SCHEMA_DATA:\n this.#handleSchemaData(seq, f.data);\n break;\n case CMD_ACK:\n this.#acks.onAck(seq);\n break;\n case CMD_NAK: {\n const m = decodeNak(f.data);\n if (m) this.#acks.onNak(seq, m.reason);\n break;\n }\n default:\n break;\n }\n }\n\n #sweep(): void {\n const now = this.#now();\n this.#acks.sweep(now);\n this.#services.sweep(now);\n if (this.#lastHeartbeatMs !== null && this.#state.kind !== 'lost') {\n if (now - this.#lastHeartbeatMs > this.#heartbeatTimeoutMs) {\n this.#enterLost('heartbeat timeout');\n }\n }\n if (this.#schemaRead && this.#schemaRead.inflightDeadlineMs <= now) {\n this.#onSchemaReadStall();\n }\n }\n\n // ---------------------------------------------------------------------\n // ANNOUNCE\n // ---------------------------------------------------------------------\n\n #handleAnnounce(data: Uint8Array): void {\n const a = decodeAnnounce(data);\n if (!a) {\n this.#error(new Error('malformed ANNOUNCE'));\n return;\n }\n const prev = this.#announce;\n const isReboot = prev !== null && prev.bootId !== a.bootId;\n const isHashChange = prev !== null && prev.schemaHash !== a.schemaHash;\n\n this.#announce = {\n schemaHash: a.schemaHash,\n bootId: a.bootId,\n blobLen: a.blobLen,\n protocolVersion: a.protocolVersion,\n instanceCounts: a.instanceCounts,\n };\n\n // Fresh boot or schema change always reprovisions. A repeat ANNOUNCE\n // with the same (hash, boot_id) while we're mid-bring-up is the SPEC\n // §5.4 \"× 3 spontaneous\" stream — skip it to avoid clobbering state.\n if (this.#state.kind === 'running' && !isReboot && !isHashChange) return;\n if (this.#state.kind === 'provisioning' && !isReboot && !isHashChange) return;\n if (this.#state.kind === 'awaiting-start' && !isReboot && !isHashChange) return;\n if (this.#state.kind === 'schema-reading' && !isReboot && !isHashChange) return;\n\n this.#reprovisionState();\n\n // Cached blob short-circuit.\n const cached = this.#blobCache.get(a.schemaHash);\n if (cached) {\n void this.#beginBringUp(a, cached.schema, cached.blob);\n return;\n }\n this.#startSchemaRead(a);\n }\n\n // ---------------------------------------------------------------------\n // HEARTBEAT\n // ---------------------------------------------------------------------\n\n #handleHeartbeat(data: Uint8Array): void {\n const h = decodeHeartbeat(data);\n if (!h) {\n this.#error(new Error('malformed HEARTBEAT'));\n return;\n }\n this.#lastHeartbeatMs = this.#now();\n if (this.#announce && this.#announce.bootId !== h.bootId) {\n // §5.4 — boot_id changed without an ANNOUNCE arriving first (we may\n // have missed the ANNOUNCE×3 burst). Drop everything and wait for\n // the next ANNOUNCE.\n this.#announce = null;\n this.#reprovisionState();\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n // Recover from `lost`: a fresh heartbeat with the same boot_id means\n // the slave is alive again. The data plane is still wired (we did not\n // teardown the snapshot), so jump straight back to `running` if we\n // had one. Alternatively, the previous bring-up may have parked in\n // `awaiting-start` (autoStart gate blocked START) — put it back\n // there so `startNow()` can still commit.\n if (this.#state.kind === 'lost') {\n if (this.#snapshot !== null) {\n this.#setState({ kind: 'running' });\n } else if (this.#pendingStart !== null) {\n this.#setState({ kind: 'awaiting-start' });\n }\n }\n\n // Snapshot gate: before START ACK the wire byte just echoes the\n // pre-RUNNING lifecycle.\n if (this.#snapshot !== null) {\n const isSuspended = h.state === STATE_SUSPENDED;\n if (isSuspended && this.#state.kind === 'running') {\n this.#setState({ kind: 'suspended' });\n } else if (!isSuspended && this.#state.kind === 'suspended') {\n this.#setState({ kind: 'running' });\n }\n }\n }\n\n // ---------------------------------------------------------------------\n // SCHEMA_READ\n // ---------------------------------------------------------------------\n\n #startSchemaRead(a: AnnounceMsg): void {\n const progress: SchemaReadProgress = {\n expectedTotal: a.blobLen,\n acc: new SchemaAccumulator(a.blobLen),\n inflightSeq: 0,\n inflightLen: 0,\n retriesLeft: this.#schemaReadRetries,\n inflightDeadlineMs: 0,\n };\n this.#schemaRead = progress;\n this.#setState({ kind: 'schema-reading', received: 0, total: a.blobLen });\n this.#issueSchemaReadChunk(progress, false);\n }\n\n #issueSchemaReadChunk(p: SchemaReadProgress, retry: boolean): void {\n const remaining = Math.max(0, p.expectedTotal - p.acc.length);\n if (remaining === 0) return;\n const len = Math.min(remaining, this.#schemaChunkSize);\n const seq = retry ? p.inflightSeq : this.#seq.next();\n p.inflightSeq = seq;\n p.inflightLen = len;\n p.inflightDeadlineMs = this.#now() + this.#ackTimeoutMs;\n void this.#transport\n .send(encodeSchemaRead(this.nodeId, p.acc.length, len, seq))\n .catch((e: unknown) => this.#error(e));\n }\n\n #onSchemaReadStall(): void {\n const p = this.#schemaRead;\n if (!p) return;\n if (p.retriesLeft <= 0) {\n this.#error(new Error(`schema-read stalled (offset ${p.acc.length} of ${p.expectedTotal})`));\n this.#schemaRead = null;\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n p.retriesLeft -= 1;\n this.#issueSchemaReadChunk(p, true);\n }\n\n #handleSchemaData(seq: number, data: Uint8Array): void {\n const p = this.#schemaRead;\n if (!p) return;\n const m = decodeSchemaData(data);\n if (!m) {\n this.#error(new Error('malformed SCHEMA_DATA'));\n return;\n }\n if (m.offset !== p.acc.length) return; // out-of-order, drop\n const took = p.acc.append(m, p.inflightLen);\n if (took === 0) return;\n p.retriesLeft = this.#schemaReadRetries;\n if (!p.acc.complete) {\n this.#setState({ kind: 'schema-reading', received: p.acc.length, total: p.expectedTotal });\n this.#issueSchemaReadChunk(p, false);\n return;\n }\n const blob = p.acc.bytes();\n this.#schemaRead = null;\n void this.#finishSchemaRead(blob);\n void seq;\n }\n\n async #finishSchemaRead(blob: Uint8Array): Promise<void> {\n const a = this.#announce;\n if (!a) return;\n // SPEC §5.4 — verify the SHA-256 prefix matches what ANNOUNCE\n // pre-committed; mismatch means torn transfer / mid-flight reboot.\n let actualHash: bigint;\n try {\n actualHash = await schemaHashPrefix(blob);\n } catch (e) {\n this.#error(e);\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n if (actualHash !== a.schemaHash) {\n this.#error(\n new Error(\n `schema hash mismatch: announced ${a.schemaHash.toString(16)}, actual ${actualHash.toString(16)}`,\n ),\n );\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n let schema: NodeSchema;\n let versionAheadOfMaster: boolean;\n try {\n ({ schema, versionAheadOfMaster } = decodeSchemaWithMeta(blob));\n } catch (e) {\n this.#error(e);\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n if (versionAheadOfMaster) {\n this.#error(\n new Error(\n `node ${this.nodeId}: schema protocol_version=${schema.protocolVersion} exceeds master-known — proceeding with best-effort`,\n ),\n );\n }\n this.#blobCache.set(a.schemaHash, { blob, schema });\n await this.#beginBringUp(a, schema, blob);\n }\n\n // ---------------------------------------------------------------------\n // Bring-up: FRAME_DEFINE → START\n // ---------------------------------------------------------------------\n\n async #beginBringUp(a: AnnouncedRecord, schema: NodeSchema, blob: Uint8Array): Promise<void> {\n this.#setState({ kind: 'numbering' });\n const numbering = computeNumbering(schema, Array.from(a.instanceCounts));\n if (numbering.status !== 'ok') {\n this.#error(new Error(`numbering failed: ${numbering.status}`));\n this.#setState({ kind: 'blocked', reason: `numbering: ${numbering.status}` });\n return;\n }\n const plan: readonly FramePlan[] =\n typeof this.#framePlan === 'function'\n ? this.#framePlan(schema, numbering, { nodeId: this.nodeId })\n : this.#framePlan;\n\n // Targeted DISCOVER so the slave clears any stale frame table from a\n // previous master session — mirrors send_frame_defines().\n try {\n await this.#transport.send(encodeDiscoverTo(this.nodeId));\n } catch (e) {\n this.#error(e);\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n\n const gen = ++this.#generation;\n const stdIdToTopicIndex = new Map<number, number>();\n for (const fp of plan) {\n for (const entry of fp.entries) {\n // First entry wins as the \"primary\" mapping when multiple topics\n // share a frame (rare but the planner permits it).\n if (!stdIdToTopicIndex.has(fp.stdId)) {\n stdIdToTopicIndex.set(fp.stdId, entry.topicIndex);\n }\n }\n }\n const progress: ProvisioningProgress = {\n generation: gen,\n pendingDefines: plan.length,\n anyFailure: false,\n firstNakReason: 0,\n plan,\n stdIdToTopicIndex,\n };\n this.#provisioning = progress;\n\n if (plan.length === 0) {\n // No frames to define — straight to START (or park in awaiting-start).\n // Set 'provisioning' first so a DISCOVER-echo ANNOUNCE that arrives\n // before the (synchronous) autoStart decision hits the early-return\n // in #handleAnnounce instead of restarting bring-up from 'numbering'.\n this.#provisioning.pendingDefines = 0;\n this.#setState({ kind: 'provisioning', pendingDefines: 0 });\n this.#maybeIssueStart(a, schema, blob, numbering, gen, progress);\n return;\n }\n this.#setState({ kind: 'provisioning', pendingDefines: plan.length });\n\n const deadline = this.#now() + this.#ackTimeoutMs;\n for (const fp of plan) {\n const seq = this.#seq.next();\n this.#acks.track(seq, deadline, (outcome) =>\n this.#onFrameDefineOutcome(a, schema, blob, numbering, gen, outcome),\n );\n // SPEC §5.6 — the wire `dir` byte is 0 for S→M, 1 for M→S; this is the\n // opposite of the schema `Direction` enum (M2S=0, S2M=1, inherited from\n // the proto3 default-zero convention). Mirror the C++ bridge mapping in\n // `fibril_can_bridge/src/node_agent_routes.cpp` so the slave doesn't\n // reject FRAME_DEFINE with NAK_DIR_MISMATCH (0x08).\n const wireDir = fp.dir === Direction.S2M ? DIR_TX_S2M : DIR_RX_M2S;\n void this.#transport\n .send(encodeFrameDefine(this.nodeId, seq, fp.stdId, fp.periodUs, wireDir, fp.entries))\n .catch((e: unknown) => this.#error(e));\n }\n }\n\n #onFrameDefineOutcome(\n a: AnnouncedRecord,\n schema: NodeSchema,\n blob: Uint8Array,\n numbering: NumberingResult,\n gen: number,\n outcome: AckOutcome,\n ): void {\n const p = this.#provisioning;\n if (!p || p.generation !== gen) return;\n if (outcome.kind !== 'acked') {\n if (!p.anyFailure) {\n p.anyFailure = true;\n p.firstNakReason = outcome.kind === 'naked' ? outcome.reason : 0;\n }\n }\n if (p.pendingDefines === 0) return;\n p.pendingDefines -= 1;\n this.#setState({ kind: 'provisioning', pendingDefines: p.pendingDefines });\n if (p.pendingDefines > 0) return;\n if (p.anyFailure) {\n this.#error(new Error(`FRAME_DEFINE failed (first NAK reason ${p.firstNakReason})`));\n this.#provisioning = null;\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n this.#maybeIssueStart(a, schema, blob, numbering, gen, p);\n }\n\n /**\n * FRAME_DEFINE has succeeded (or been skipped). Consult the autoStart\n * gate and either fire START immediately or park in `awaiting-start`,\n * remembering enough context that `startNow()` can resume without\n * re-running FRAME_DEFINE.\n */\n #maybeIssueStart(\n a: AnnouncedRecord,\n schema: NodeSchema,\n blob: Uint8Array,\n numbering: NumberingResult,\n gen: number,\n progress: ProvisioningProgress,\n ): void {\n if (this.#autoStart()) {\n this.#issueStart(a, schema, blob, numbering, gen);\n return;\n }\n // Hold the bring-up in-flight so `startNow()` can pick up where we\n // left off. `#provisioning` stays live too — a reprovision path\n // (fresh ANNOUNCE, boot_id change, explicit reprovision()) clears\n // both via `#reprovisionState()`.\n this.#pendingStart = { a, schema, blob, numbering, generation: gen, progress };\n this.#setState({ kind: 'awaiting-start' });\n }\n\n /**\n * Commit the deferred START when {@link NodeAgentOptions.autoStart}\n * gated the previous bring-up. Only legal in `awaiting-start`; any\n * other state throws so callers spot logic bugs instead of racing\n * with a fresh ANNOUNCE.\n */\n async startNow(): Promise<void> {\n if (this.#stopped) throw new Error('NodeAgent.startNow() after stop()');\n if (this.#state.kind !== 'awaiting-start' || this.#pendingStart === null) {\n throw new Error(`NodeAgent.startNow() called in state '${this.#state.kind}'`);\n }\n const p = this.#pendingStart;\n this.#pendingStart = null;\n this.#setState({ kind: 'provisioning', pendingDefines: 0 });\n this.#issueStart(p.a, p.schema, p.blob, p.numbering, p.generation);\n }\n\n #issueStart(\n a: AnnouncedRecord,\n schema: NodeSchema,\n blob: Uint8Array,\n numbering: NumberingResult,\n gen: number,\n ): void {\n const seq = this.#seq.next();\n const deadline = this.#now() + this.#ackTimeoutMs;\n this.#acks.track(seq, deadline, (outcome) =>\n this.#onStartOutcome(a, schema, blob, numbering, gen, outcome),\n );\n void this.#transport.send(encodeStart(this.nodeId, seq)).catch((e: unknown) => this.#error(e));\n }\n\n #onStartOutcome(\n a: AnnouncedRecord,\n schema: NodeSchema,\n blob: Uint8Array,\n numbering: NumberingResult,\n gen: number,\n outcome: AckOutcome,\n ): void {\n const p = this.#provisioning;\n if (!p || p.generation !== gen) return;\n if (outcome.kind !== 'acked') {\n this.#error(\n new Error(\n `START ${outcome.kind === 'naked' ? `NAKed reason=${outcome.reason}` : 'timed out'}`,\n ),\n );\n this.#provisioning = null;\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n const index = new SchemaIndex(schema, numbering, Array.from(a.instanceCounts));\n const client = this.#services;\n this.#snapshot = {\n nodeId: this.nodeId,\n schemaHash: a.schemaHash,\n bootId: a.bootId,\n instanceCounts: a.instanceCounts,\n blob,\n schema,\n numbering,\n framePlan: p.plan,\n stdIdToTopicIndex: p.stdIdToTopicIndex,\n services: client,\n index,\n service<Req extends Dict, Resp extends Dict>(path: string): TypedService<Req, Resp> {\n const desc = index.service(path);\n if (!desc) {\n throw new Error(`unknown service path '${path}'`);\n }\n return new TypedService<Req, Resp>(client, desc);\n },\n param<T>(path: string): TypedParam<T> {\n const desc = index.param(path);\n if (!desc) {\n throw new Error(`unknown param path '${path}'`);\n }\n return new TypedParam<T>(client, desc);\n },\n };\n this.#provisioning = null;\n this.#setState({ kind: 'running' });\n void STATE_RUNNING; // referenced for future per-state hooks\n }\n\n // ---------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------\n\n #reprovisionState(): void {\n this.#acks.clear();\n this.#services.failAll('NodeAgent reprovision');\n this.#schemaRead = null;\n this.#provisioning = null;\n this.#pendingStart = null;\n this.#snapshot = null;\n }\n\n #enterLost(reason: string): void {\n if (this.#state.kind === 'lost') return;\n this.#setState({ kind: 'lost', reason });\n }\n\n #setState(s: NodeProvisionState): void {\n this.#state = s;\n this.#onState?.(s);\n }\n\n #error(e: unknown): void {\n const err = e instanceof Error ? e : new Error(String(e));\n this.#onError?.(err);\n }\n}\n","import type { CanFrame, ITransport, Unsubscribe } from '@fibril/can-transport';\nimport {\n CHAN_CONFIG,\n CMD_ANNOUNCE,\n CMD_HEARTBEAT,\n extChannel,\n extIndex,\n extNodeId,\n NODE_ID_BROADCAST,\n} from './can-id.js';\nimport { encodeDiscover } from './config-plane.js';\nimport { DataPlaneReceiver } from './data-plane.js';\nimport { MasterHeartbeatBroadcaster } from './master-heartbeat.js';\nimport {\n type FramePlanFactory,\n NodeAgent,\n type NodeProvisionState,\n type NodeRunningSnapshot,\n} from './node-agent.js';\n\n/**\n * Multi-slave coordinator.\n *\n * One {@link MasterController} owns:\n * - a single transport (the bus)\n * - one {@link MasterHeartbeatBroadcaster} (shared across slaves)\n * - a single broadcast DISCOVER at start() to flush every slave's frame\n * table and pull fresh ANNOUNCEs onto the bus\n * - a `Map<nodeId, NodeAgent>` of provisioned slaves — auto-spawned on\n * the first ANNOUNCE / HEARTBEAT from a previously-unseen nodeId\n *\n * Periodic broadcast DISCOVER is intentionally NOT done. Broadcast\n * DISCOVER is destructive (§5.11): every receiving slave clears its frame\n * table and drops to UNPROVISIONED. Late-joining slaves are covered by\n * their own spontaneous ANNOUNCE × 3 at boot (§5.4); the user-initiated\n * \"Discover\" button (`discoverNow()`) is the escape hatch for the rare\n * case where the master came up first and missed the burst.\n *\n * Provisioning per slave still goes through {@link NodeAgent}. The\n * controller is the right place to add cross-slave concerns later (PARAM\n * persistence, name ownership, lab-mode multiplexers) without bloating\n * `NodeAgent`.\n *\n * The controller does NOT replace `NodeAgent` for single-slave embedded\n * use cases (e.g. tests, a fixed-topology setup); it sits one layer above\n * and is the natural entrypoint for the Web UI.\n */\n\n/** Default policy hooks applied to every spawned NodeAgent. */\nexport interface MasterControllerOptions {\n /** Already-open()'d transport. The controller attaches its own onFrame. */\n transport: ITransport;\n /** Strategy applied to every spawned NodeAgent. Required. */\n framePlan: FramePlanFactory;\n /** MASTER_HEARTBEAT broadcast period in ms. Default 100 (§5.11). */\n heartbeatPeriodMs?: number;\n /**\n * Broadcast DISCOVER period in ms. Default 0 (disabled). Setting >0 is\n * destructive — every periodic broadcast DISCOVER wipes every slave's\n * frame table and forces re-provisioning, breaking S→M topic flow until\n * each NodeAgent re-pushes its FRAME_DEFINEs. Useful only for very\n * niche reconnect-storm scenarios; prefer `discoverNow()` for on-demand\n * rediscovery and rely on slave spontaneous ANNOUNCE × 3 (§5.4) for\n * normal late-join.\n */\n discoverPeriodMs?: number;\n /**\n * Send a single broadcast DISCOVER inside `start()` to flush stale\n * slave state from a previous master session. Default true. Set false\n * in tests that drive ANNOUNCE manually and need a quiet bus.\n */\n initialDiscover?: boolean;\n /** Per-NodeAgent ACK timeout in ms. Default 250 (matches NodeAgent). */\n ackTimeoutMs?: number;\n /** Per-NodeAgent HEARTBEAT-loss budget in ms. Default 350. */\n heartbeatTimeoutMs?: number;\n /** Per-service-call default timeout in ms. Default `ackTimeoutMs`. */\n serviceTimeoutMs?: number;\n /**\n * Read-through gate applied to every spawned NodeAgent right before it\n * issues START. Callers pass a getter (not a boolean) so the flag can\n * be flipped at runtime — see `NodeAgentOptions.autoStart`. Default\n * `() => true`.\n */\n autoStart?: () => boolean;\n /** Optional clock override (tests). Default `() => Date.now()`. */\n now?: () => number;\n /** Optional non-fatal error sink. */\n onError?: (err: Error) => void;\n}\n\n/** Snapshot of one slave's state as observed by the controller. */\nexport interface ControllerSlaveSnapshot {\n readonly nodeId: number;\n readonly state: NodeProvisionState;\n /** Truthy once the slave reaches RUNNING for the first time. */\n readonly running: NodeRunningSnapshot | null;\n /** `now()` when HEARTBEAT was last seen. null if never. */\n readonly lastHeartbeatMs: number | null;\n /** boot_id observed (from ANNOUNCE or HEARTBEAT). null if neither yet. */\n readonly bootId: number | null;\n /** schema_hash observed in ANNOUNCE. null if not yet ANNOUNCEd. */\n readonly schemaHash: bigint | null;\n}\n\nexport type ControllerListener = (snapshots: readonly ControllerSlaveSnapshot[]) => void;\n\ninterface SlaveRecord {\n agent: NodeAgent;\n state: NodeProvisionState;\n lastHeartbeatMs: number | null;\n bootId: number | null;\n schemaHash: bigint | null;\n}\n\n/** Snapshot type derived from CMD_HEARTBEAT payload — minimal. */\nfunction readU32Le(p: Uint8Array, off: number): number {\n return (\n ((p[off] ?? 0) |\n ((p[off + 1] ?? 0) << 8) |\n ((p[off + 2] ?? 0) << 16) |\n ((p[off + 3] ?? 0) << 24)) >>>\n 0\n );\n}\nfunction readU64Le(p: Uint8Array, off: number): bigint {\n let r = 0n;\n for (let i = 0; i < 8; i++) r |= BigInt(p[off + i] ?? 0) << BigInt(i * 8);\n return r;\n}\n\nexport class MasterController {\n readonly #transport: ITransport;\n readonly #framePlan: FramePlanFactory;\n readonly #heartbeatBroadcaster: MasterHeartbeatBroadcaster;\n readonly #dataPlane: DataPlaneReceiver;\n readonly #discoverPeriodMs: number;\n readonly #initialDiscover: boolean;\n readonly #ackTimeoutMs: number;\n readonly #heartbeatTimeoutMs: number;\n readonly #serviceTimeoutMs: number | undefined;\n readonly #autoStart: () => boolean;\n readonly #now: () => number;\n readonly #onError?: (err: Error) => void;\n\n readonly #slaves = new Map<number, SlaveRecord>();\n readonly #listeners = new Set<ControllerListener>();\n\n #unsubFrame: Unsubscribe | null = null;\n #discoverHandle: ReturnType<typeof setInterval> | null = null;\n #started = false;\n\n constructor(opts: MasterControllerOptions) {\n this.#transport = opts.transport;\n this.#framePlan = opts.framePlan;\n this.#heartbeatBroadcaster = new MasterHeartbeatBroadcaster(\n opts.transport,\n opts.heartbeatPeriodMs ?? 100,\n );\n this.#dataPlane = new DataPlaneReceiver({\n transport: opts.transport,\n ...(opts.onError !== undefined ? { onError: opts.onError } : {}),\n ...(opts.now !== undefined ? { now: opts.now } : {}),\n });\n this.#discoverPeriodMs = opts.discoverPeriodMs ?? 0;\n this.#initialDiscover = opts.initialDiscover ?? true;\n this.#ackTimeoutMs = opts.ackTimeoutMs ?? 250;\n this.#heartbeatTimeoutMs = opts.heartbeatTimeoutMs ?? 350;\n this.#serviceTimeoutMs = opts.serviceTimeoutMs;\n this.#autoStart = opts.autoStart ?? (() => true);\n this.#now = opts.now ?? (() => Date.now());\n this.#onError = opts.onError;\n }\n\n /**\n * Master-side decoder for S→M topic frames. Auto-attached / detached as\n * each slave transitions in and out of `running`. Subscribe with\n * `dataPlane.onTopic(nodeId, path, listener)`; read latest values with\n * `dataPlane.latest(nodeId, path)`.\n */\n get dataPlane(): DataPlaneReceiver {\n return this.#dataPlane;\n }\n\n /**\n * Attach to the transport, start MASTER_HEARTBEAT, fire one initial\n * broadcast DISCOVER to flush stale slave state from a previous master\n * session. New slaves auto-spawn a NodeAgent on first sight.\n */\n start(): void {\n if (this.#started) return;\n this.#started = true;\n this.#heartbeatBroadcaster.start();\n this.#unsubFrame = this.#transport.onFrame((f) => this.#onFrame(f));\n if (this.#initialDiscover) {\n // Single broadcast: pulls every slave back to UNPROVISIONED + a\n // fresh ANNOUNCE, so we don't try to drive a slave that thinks it's\n // still running under the previous master's frame table.\n void this.#transport.send(encodeDiscover()).catch((e) => this.#error(e));\n }\n if (this.#discoverPeriodMs > 0) {\n this.#discoverHandle = setInterval(() => {\n void this.#transport.send(encodeDiscover()).catch((e) => this.#error(e));\n }, this.#discoverPeriodMs);\n }\n }\n\n /** Stop all internals, stop every NodeAgent, detach from the transport. */\n async stop(): Promise<void> {\n if (!this.#started) return;\n this.#started = false;\n if (this.#discoverHandle !== null) {\n clearInterval(this.#discoverHandle);\n this.#discoverHandle = null;\n }\n this.#heartbeatBroadcaster.stop();\n if (this.#unsubFrame) {\n this.#unsubFrame();\n this.#unsubFrame = null;\n }\n const stops = [...this.#slaves.values()].map((r) => r.agent.stop().catch(() => {}));\n this.#slaves.clear();\n this.#dataPlane.dispose();\n await Promise.all(stops);\n this.#emit();\n }\n\n /** Snapshot of all known slaves. Stable identity per call. */\n snapshots(): ControllerSlaveSnapshot[] {\n return [...this.#slaves.values()]\n .map((r) => ({\n nodeId: r.agent.nodeId,\n state: r.state,\n running: r.agent.snapshot,\n lastHeartbeatMs: r.lastHeartbeatMs,\n bootId: r.bootId,\n schemaHash: r.schemaHash,\n }))\n .sort((a, b) => a.nodeId - b.nodeId);\n }\n\n /** Subscribe to slave-set / state-change updates. Fires on every change. */\n onChange(cb: ControllerListener): Unsubscribe {\n this.#listeners.add(cb);\n // Prime the listener with the current snapshot so it doesn't need to\n // race against the first state event.\n cb(this.snapshots());\n return () => {\n this.#listeners.delete(cb);\n };\n }\n\n /**\n * Access the NodeAgent for one slave, if it exists. Returns null until\n * the slave has been observed. Useful for service / param calls from\n * code that already knows the nodeId.\n */\n agent(nodeId: number): NodeAgent | null {\n return this.#slaves.get(nodeId)?.agent ?? null;\n }\n\n /** Issue an ad-hoc broadcast DISCOVER (between periodic firings). */\n async discoverNow(): Promise<void> {\n await this.#transport.send(encodeDiscover());\n }\n\n /**\n * Commit the deferred START on one slave that is parked in\n * `awaiting-start` because the autoStart gate blocked its bring-up.\n * Returns `false` if the slave is unknown or not currently waiting\n * for a manual start; otherwise resolves once START has been queued\n * on the wire (the RUNNING transition arrives later via `onChange`).\n */\n async startNode(nodeId: number): Promise<boolean> {\n const rec = this.#slaves.get(nodeId);\n if (!rec) return false;\n if (rec.state.kind !== 'awaiting-start') return false;\n try {\n await rec.agent.startNow();\n return true;\n } catch (e) {\n this.#error(e);\n return false;\n }\n }\n\n /**\n * Re-run the FRAME_DEFINE / START handshake for one slave so the\n * {@link FramePlanFactory} is consulted again. Use when external state\n * the factory closes over has changed (e.g. per-field TX-enable\n * toggles). Returns `false` when the slave is unknown or has never\n * ANNOUNCEd; otherwise resolves once the new bring-up has been kicked\n * off (it does not await the next RUNNING transition — listen via\n * {@link onChange} instead).\n */\n async reprovision(nodeId: number): Promise<boolean> {\n const rec = this.#slaves.get(nodeId);\n if (!rec) return false;\n try {\n await rec.agent.reprovision();\n return true;\n } catch (e) {\n this.#error(e);\n return false;\n }\n }\n\n // ---------------------------------------------------------------------\n // Frame ingress\n // ---------------------------------------------------------------------\n\n #onFrame(f: CanFrame): void {\n if (!f.extended) return;\n if (extChannel(f.id) !== CHAN_CONFIG) return;\n const nodeId = extNodeId(f.id);\n if (nodeId === 0 || nodeId === NODE_ID_BROADCAST) return; // master frames + reserved\n\n const cmd = extIndex(f.id);\n // Spawn-on-first-sight on ANNOUNCE or HEARTBEAT — both prove a slave is\n // alive on this nodeId. SCHEMA_DATA / ACK / NAK never arrive before a\n // master command, so we only key off ANNOUNCE/HEARTBEAT for spawn.\n if (cmd === CMD_ANNOUNCE) {\n const rec = this.#ensureSlave(nodeId);\n // ANNOUNCE payload layout (§5.4): [0..7] schema_hash u64\n // [8] proto [9] boot_id [10..13] blob_len [14..] instance_counts\n if (f.data.length >= 14) {\n rec.schemaHash = readU64Le(f.data, 0);\n rec.bootId = f.data[9] ?? rec.bootId ?? null;\n void readU32Le; // referenced for future use\n }\n this.#emit();\n return;\n }\n if (cmd === CMD_HEARTBEAT) {\n const rec = this.#ensureSlave(nodeId);\n rec.lastHeartbeatMs = this.#now();\n if (f.data.length >= 1) {\n // HEARTBEAT payload: [0] boot_id [1] state [2] fault_summary\n rec.bootId = f.data[0] ?? rec.bootId ?? null;\n }\n this.#emit();\n }\n }\n\n #ensureSlave(nodeId: number): SlaveRecord {\n let rec = this.#slaves.get(nodeId);\n if (rec) return rec;\n const agent = new NodeAgent({\n nodeId,\n transport: this.#transport,\n framePlan: this.#framePlan,\n ackTimeoutMs: this.#ackTimeoutMs,\n heartbeatTimeoutMs: this.#heartbeatTimeoutMs,\n ...(this.#serviceTimeoutMs !== undefined ? { serviceTimeoutMs: this.#serviceTimeoutMs } : {}),\n autoStart: this.#autoStart,\n now: this.#now,\n onState: (s) => {\n const r = this.#slaves.get(nodeId);\n if (!r) return;\n r.state = s;\n if (s.kind === 'running' && r.agent.snapshot !== null) {\n try {\n this.#dataPlane.attachSlave(nodeId, r.agent.snapshot.framePlan, r.agent.snapshot.index);\n } catch (e) {\n this.#error(e);\n }\n } else {\n this.#dataPlane.detachSlave(nodeId);\n }\n this.#emit();\n },\n onError: (e) => this.#error(e),\n });\n rec = {\n agent,\n state: { kind: 'idle' },\n lastHeartbeatMs: null,\n bootId: null,\n schemaHash: null,\n };\n this.#slaves.set(nodeId, rec);\n void agent.start();\n this.#emit();\n return rec;\n }\n\n #emit(): void {\n const snap = this.snapshots();\n for (const cb of this.#listeners) {\n try {\n cb(snap);\n } catch (e) {\n this.#error(e);\n }\n }\n }\n\n #error(e: unknown): void {\n if (!this.#onError) return;\n this.#onError(e instanceof Error ? e : new Error(String(e)));\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["#pending","#now","readU64Le","#buf","#blobTotalLen","packOneScalar","#onError","#now","#unsubFrame","#buckets","#ownedByNode","#latest","#listeners","#onFrame","#version","#err","#publish","#freePool","#next","I_TOKEN","expandIToken","joinPath","#handle","#topicsByPath","#servicesByPath","#paramsByPath","#topicsByIndex","#servicesByIndex","#paramsByIndex","#next","#reset","#buffer","#transport","#defaultTimeoutMs","#now","#nextCallId","#pending","#unsub","#onFrame","#detachAbort","#allocCallId","#sendCancel","#finishMaybeAccepted","#client","#client","#transport","#framePlan","#ackTimeoutMs","#schemaChunkSize","#schemaReadRetries","#heartbeatTimeoutMs","#autoStart","#onState","#onError","#now","#seq","#acks","#services","#blobCache","#state","#snapshot","#stopped","#unsubFrame","#onFrame","#sweepHandle","#sweep","#setState","#announce","#reprovisionState","#beginBringUp","#error","#schemaRead","#provisioning","#pendingStart","#handleAnnounce","#handleHeartbeat","#handleSchemaData","#lastHeartbeatMs","#enterLost","#onSchemaReadStall","#startSchemaRead","#issueSchemaReadChunk","#finishSchemaRead","#generation","#maybeIssueStart","#onFrameDefineOutcome","#issueStart","#onStartOutcome","#transport","#framePlan","#heartbeatBroadcaster","#dataPlane","#discoverPeriodMs","#initialDiscover","#ackTimeoutMs","#heartbeatTimeoutMs","#serviceTimeoutMs","#autoStart","#now","#onError","#slaves","#listeners","#started","#unsubFrame","#onFrame","#error","#discoverHandle","#emit","#ensureSlave"],"sources":["../src/ack-tracker.ts","../src/can-id.ts","../src/dlc.ts","../src/config-plane.ts","../src/scalar-codec.ts","../src/proto-reader.ts","../src/schema.ts","../src/dynamic-codec.ts","../src/data-plane.ts","../src/frame-planner.ts","../src/default-plan.ts","../src/master-heartbeat.ts","../src/numbering.ts","../src/schema-hash.ts","../src/schema-index.ts","../src/seq-allocator.ts","../src/segmented-transfer.ts","../src/service-client.ts","../src/typed-param.ts","../src/typed-service.ts","../src/node-agent.ts","../src/master-controller.ts"],"sourcesContent":["/** In-flight ACK/NAK ledger keyed by `seq`. Caller polls via {@link sweep}. */\n\nexport type AckOutcome =\n | { kind: 'acked' }\n | { kind: 'naked'; reason: number }\n | { kind: 'timed-out' };\n\nexport type AckCallback = (outcome: AckOutcome) => void;\n\ninterface AckEntry {\n deadlineMs: number;\n cb: AckCallback;\n}\n\nexport class AckTracker {\n readonly #pending = new Map<number, AckEntry>();\n readonly #now: () => number;\n\n constructor(now: () => number = () => Date.now()) {\n this.#now = now;\n }\n\n get pendingCount(): number {\n return this.#pending.size;\n }\n\n /** Returns false if `seq` is already tracked; the existing entry is kept. */\n track(seq: number, deadlineMs: number, cb: AckCallback): boolean {\n const key = seq & 0xff;\n if (this.#pending.has(key)) return false;\n this.#pending.set(key, { deadlineMs, cb });\n return true;\n }\n\n /** Idempotent — fires `acked` if `seq` is pending. */\n onAck(seq: number): void {\n const key = seq & 0xff;\n const e = this.#pending.get(key);\n if (!e) return;\n this.#pending.delete(key);\n e.cb({ kind: 'acked' });\n }\n\n /** Idempotent — fires `naked` with the reason if `seq` is pending. */\n onNak(seq: number, reason: number): void {\n const key = seq & 0xff;\n const e = this.#pending.get(key);\n if (!e) return;\n this.#pending.delete(key);\n e.cb({ kind: 'naked', reason });\n }\n\n /** Fire `timed-out` for every entry whose deadline elapsed by `nowMs`. */\n sweep(nowMs: number = this.#now()): void {\n for (const [seq, entry] of this.#pending) {\n if (entry.deadlineMs <= nowMs) {\n this.#pending.delete(seq);\n entry.cb({ kind: 'timed-out' });\n }\n }\n }\n\n /** Drop every entry without firing callbacks. Test-only. */\n clear(): void {\n this.#pending.clear();\n }\n}\n","/**\n * CAN ID layout (Extended) and config-plane / NAK / svc-status / node-state\n * constants. Mirrors SPEC §3, §5, §7 and `fibril_can_runtime/include/fibril_can/fcan_protocol.h`\n * / `fibril_can_bridge/include/fibril_can_bridge/can_id.hpp`.\n *\n * Extended ID layout (29 bit, §3.2):\n * [28:26] channel (3 bit)\n * [25:19] node_id (7 bit, 0x7F = broadcast)\n * [18:11] index (8 bit, service_index / cmd_code)\n * [10:3] seq (8 bit, call_id / seq_num)\n * [2] seg (1 bit, 0=SINGLE, 1=SEGMENT)\n * [1:0] reserved (2 bit, 0)\n *\n * Standard ID (11 bit, §3.1) is dynamically allocated by the master and\n * has no fixed bitfield meaning — kept here only as the wire mask.\n */\n\n// Highest protocol_version this package decodes in full. Higher values\n// still parse.\nexport const PROTOCOL_VERSION = 2;\nexport const MAX_FRAME_PAYLOAD = 64;\n\n// Channel (§3.2)\nexport const CHAN_CONFIG = 0;\nexport const CHAN_SVC_REQUEST = 1;\nexport const CHAN_SVC_RESPONSE = 2;\n\nexport const NODE_ID_BROADCAST = 0x7f;\n\n// Standard ID mask (§3.1)\nexport const STD_ID_MASK = 0x7ff;\n\n// Reserved service indices (§3.3)\nexport const SVC_PARAM_SET = 0xfd;\nexport const SVC_CANCEL = 0xff;\nexport const SVC_MAX_FIRST_CLASS = 0xfc;\n\n// Config-plane command codes (§5.2)\nexport const CMD_DISCOVER = 0x01;\nexport const CMD_ANNOUNCE = 0x02;\nexport const CMD_SCHEMA_READ = 0x03;\nexport const CMD_SCHEMA_DATA = 0x04;\nexport const CMD_HEARTBEAT = 0x05;\nexport const CMD_MASTER_HEARTBEAT = 0x07;\nexport const CMD_FRAME_DEFINE = 0x10;\nexport const CMD_HB_PERIOD = 0x13;\nexport const CMD_START = 0x20;\nexport const CMD_STOP = 0x21;\nexport const CMD_ACK = 0x7e;\nexport const CMD_NAK = 0x7f;\n\n// NAK reason codes (§5.9)\nexport const NAK_UNKNOWN_CMD = 0x01;\nexport const NAK_BAD_LENGTH = 0x02;\nexport const NAK_BAD_PARAM = 0x03;\nexport const NAK_NO_RESOURCE = 0x04;\nexport const NAK_BAD_STATE = 0x05;\nexport const NAK_ID_CONFLICT = 0x06;\nexport const NAK_INDEX_RANGE = 0x07;\nexport const NAK_DIR_MISMATCH = 0x08;\nexport const NAK_SIZE_OVERFLOW = 0x09;\n\n// Node states (§2.4)\nexport const STATE_UNPROVISIONED = 0;\nexport const STATE_PROVISIONED = 1;\nexport const STATE_RUNNING = 2;\nexport const STATE_FAULT = 3;\nexport const STATE_SUSPENDED = 4;\n\n/** Human-readable name for a node_state byte. Unknown values → `unknown(N)`. */\nexport function stateName(state: number): string {\n switch (state) {\n case STATE_UNPROVISIONED:\n return \"UNPROVISIONED\";\n case STATE_PROVISIONED:\n return \"PROVISIONED\";\n case STATE_RUNNING:\n return \"RUNNING\";\n case STATE_FAULT:\n return \"FAULT\";\n case STATE_SUSPENDED:\n return \"SUSPENDED\";\n default:\n return `unknown(${state})`;\n }\n}\n\n// Fault summary (§5.8)\nexport const FAULT_NONE = 0;\nexport const FAULT_NOMEM = 1;\nexport const FAULT_INDEX_OVERFLOW = 2;\nexport const FAULT_ID_CONFLICT = 3;\n\n// Direction (§5.6 of FRAME_DEFINE)\nexport const DIR_TX_S2M = 0;\nexport const DIR_RX_M2S = 1;\n\n// Service status (§7.2)\nexport const SVC_OK = 0x00;\nexport const SVC_ACCEPTED = 0x01;\nexport const SVC_APP_ERROR = 0x02;\nexport const SVC_BUSY = 0x03;\nexport const SVC_UNAVAIL = 0x04;\nexport const SVC_BAD_INDEX = 0x05;\nexport const SVC_BAD_VALUE = 0x06;\nexport const SVC_BAD_LENGTH = 0x08;\n\n// Segmented service transfer (§7.4)\nexport const SEG_FIRST_DATA = 61;\nexport const SEG_REST_DATA = 63;\nexport const SEG_MAX_TOTAL = 1024;\nexport const SEG_MAX_SEQ = 31;\n\n/** Byte offset of segment `seq` within the reassembled buffer (§7.4). */\nexport function segOffset(seq: number): number {\n return seq === 0 ? 0 : SEG_FIRST_DATA + (seq - 1) * SEG_REST_DATA;\n}\n\n/**\n * Build a 29-bit Extended ID from its bitfields (§3.2). Inputs are masked\n * down to their respective field widths.\n */\nexport function makeExtId(\n channel: number,\n nodeId: number,\n index: number,\n seq: number,\n seg = 0,\n): number {\n return (\n (((channel & 0x7) << 26) |\n ((nodeId & 0x7f) << 19) |\n ((index & 0xff) << 11) |\n ((seq & 0xff) << 3) |\n ((seg & 0x1) << 2)) >>>\n 0\n );\n}\n\nexport function extChannel(id: number): number {\n return (id >>> 26) & 0x7;\n}\nexport function extNodeId(id: number): number {\n return (id >>> 19) & 0x7f;\n}\nexport function extIndex(id: number): number {\n return (id >>> 11) & 0xff;\n}\nexport function extSeq(id: number): number {\n return (id >>> 3) & 0xff;\n}\nexport function extSeg(id: number): number {\n return (id >>> 2) & 0x1;\n}\n","import { MAX_FRAME_PAYLOAD } from './can-id.js';\n\n/** Valid CAN FD payload sizes, ascending. */\nexport const FD_DLC_STEPS = Object.freeze([\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64,\n]) as readonly number[];\n\n/** Round `bytes` up to the next valid CAN FD payload step (caps at 64). */\nexport function quantizeDlc(bytes: number): number {\n if (bytes >= MAX_FRAME_PAYLOAD) return MAX_FRAME_PAYLOAD;\n for (const step of FD_DLC_STEPS) {\n if (step >= bytes) return step;\n }\n return MAX_FRAME_PAYLOAD;\n}\n\n/**\n * Pad `data` to the next DLC step with zeros. Over-length input (>64 B, which\n * the slave would misparse) is returned unchanged so the backend rejects it.\n */\nexport function padToDlc(data: Uint8Array): Uint8Array {\n if (data.length >= MAX_FRAME_PAYLOAD) return data;\n const padded = new Uint8Array(quantizeDlc(data.length));\n padded.set(data);\n return padded;\n}\n","import type { CanFrameTx } from '@fibril/can-transport';\nimport {\n CHAN_CONFIG,\n CMD_DISCOVER,\n CMD_FRAME_DEFINE,\n CMD_MASTER_HEARTBEAT,\n CMD_SCHEMA_READ,\n CMD_START,\n CMD_STOP,\n makeExtId,\n NODE_ID_BROADCAST,\n} from './can-id.js';\nimport { padToDlc } from './dlc.js';\n\n/**\n * Config-plane wire codec. All integers little-endian; decoders return `null`\n * on malformed input; encoders produce CAN-FD frames padded to the next DLC step.\n */\n\n// ---------------------------------------------------------------------------\n// Message shapes (decoded form of S→M payloads)\n// ---------------------------------------------------------------------------\n\n/** ANNOUNCE payload (S→M, §5.4). */\nexport interface AnnounceMsg {\n schemaHash: bigint;\n protocolVersion: number;\n bootId: number;\n blobLen: number;\n /** Length K, indexed by block-type ordinal. */\n instanceCounts: Uint8Array;\n}\n\n/** HEARTBEAT payload (S→M, §5.8). */\nexport interface HeartbeatMsg {\n bootId: number;\n state: number;\n faultSummary: number;\n}\n\n/** SCHEMA_DATA payload (S→M, §5.5). */\nexport interface SchemaDataMsg {\n offset: number;\n bytes: Uint8Array;\n}\n\n/** NAK payload (S→M, §5.9). */\nexport interface NakMsg {\n cmd: number;\n reason: number;\n}\n\n/** One entry inside a FRAME_DEFINE command (§5.6). */\nexport interface FrameDefineEntry {\n topicIndex: number;\n fieldBitmask: number;\n}\n\n// ---------------------------------------------------------------------------\n// Little-endian primitive helpers (private)\n// ---------------------------------------------------------------------------\n\nfunction readU32Le(p: Uint8Array, off: number): number {\n return (\n ((p[off] ?? 0) |\n ((p[off + 1] ?? 0) << 8) |\n ((p[off + 2] ?? 0) << 16) |\n ((p[off + 3] ?? 0) << 24)) >>>\n 0\n );\n}\nfunction readU64Le(p: Uint8Array, off: number): bigint {\n let r = 0n;\n for (let i = 0; i < 8; i++) {\n r |= BigInt(p[off + i] ?? 0) << BigInt(i * 8);\n }\n return r;\n}\nfunction pushU16(buf: number[], x: number): void {\n buf.push(x & 0xff, (x >>> 8) & 0xff);\n}\nfunction pushU32(buf: number[], x: number): void {\n buf.push(x & 0xff, (x >>> 8) & 0xff, (x >>> 16) & 0xff, (x >>> 24) & 0xff);\n}\n\n// ---------------------------------------------------------------------------\n// Decoders\n// ---------------------------------------------------------------------------\n\nexport function decodeAnnounce(data: Uint8Array): AnnounceMsg | null {\n if (data.length < 18) return null;\n const k = data[17] ?? 0;\n if (data.length < 18 + k) return null;\n return {\n schemaHash: readU64Le(data, 0),\n protocolVersion: data[8] ?? 0,\n bootId: readU32Le(data, 9),\n blobLen: readU32Le(data, 13),\n instanceCounts: data.slice(18, 18 + k),\n };\n}\n\nexport function decodeHeartbeat(data: Uint8Array): HeartbeatMsg | null {\n if (data.length < 6) return null;\n return {\n bootId: readU32Le(data, 0),\n state: data[4] ?? 0,\n faultSummary: data[5] ?? 0,\n };\n}\n\nexport function decodeSchemaData(data: Uint8Array): SchemaDataMsg | null {\n if (data.length < 4) return null;\n return {\n offset: readU32Le(data, 0),\n bytes: data.slice(4),\n };\n}\n\nexport function decodeNak(data: Uint8Array): NakMsg | null {\n if (data.length < 2) return null;\n return { cmd: data[0] ?? 0, reason: data[1] ?? 0 };\n}\n\n// ---------------------------------------------------------------------------\n// Encoders — master-initiated commands\n// ---------------------------------------------------------------------------\n\nfunction configFrame(nodeId: number, cmd: number, seq: number, data: Uint8Array): CanFrameTx {\n // Mark every emitted frame as FD — payloads may quantize past 8 bytes.\n return {\n id: makeExtId(CHAN_CONFIG, nodeId, cmd, seq, 0),\n extended: true,\n fd: true,\n data,\n };\n}\n\n/** Broadcast DISCOVER — all nodes re-announce and clear their frame tables. */\nexport function encodeDiscover(): CanFrameTx {\n return configFrame(NODE_ID_BROADCAST, CMD_DISCOVER, 0, new Uint8Array(0));\n}\n\n/** Targeted DISCOVER for a single node (§5.11 reprovisioning). */\nexport function encodeDiscoverTo(nodeId: number): CanFrameTx {\n return configFrame(nodeId, CMD_DISCOVER, 0, new Uint8Array(0));\n}\n\n/** Broadcast MASTER_HEARTBEAT (§5.11). Refreshes slave master-lost watchdogs. */\nexport function encodeMasterHeartbeat(): CanFrameTx {\n return configFrame(NODE_ID_BROADCAST, CMD_MASTER_HEARTBEAT, 0, new Uint8Array(0));\n}\n\nexport function encodeSchemaRead(\n nodeId: number,\n offset: number,\n length: number,\n seq: number,\n): CanFrameTx {\n const buf: number[] = [];\n pushU32(buf, offset);\n buf.push(length & 0xff);\n return configFrame(nodeId, CMD_SCHEMA_READ, seq, padToDlc(new Uint8Array(buf)));\n}\n\nexport function encodeFrameDefine(\n nodeId: number,\n seq: number,\n stdId: number,\n periodUs: number,\n dir: number,\n entries: readonly FrameDefineEntry[],\n): CanFrameTx {\n const buf: number[] = [];\n pushU16(buf, stdId);\n pushU32(buf, periodUs);\n buf.push(dir & 0xff);\n buf.push(entries.length & 0xff);\n for (const e of entries) {\n pushU16(buf, e.topicIndex);\n pushU16(buf, e.fieldBitmask);\n }\n return configFrame(nodeId, CMD_FRAME_DEFINE, seq, padToDlc(new Uint8Array(buf)));\n}\n\nexport function encodeStart(nodeId: number, seq: number): CanFrameTx {\n return configFrame(nodeId, CMD_START, seq, new Uint8Array(0));\n}\n\nexport function encodeStop(nodeId: number, seq: number): CanFrameTx {\n return configFrame(nodeId, CMD_STOP, seq, new Uint8Array(0));\n}\n\n// ---------------------------------------------------------------------------\n// Schema blob reassembly\n// ---------------------------------------------------------------------------\n\n/**\n * SCHEMA_DATA reassembly. Clips each chunk against `expectedChunkLen` and\n * the remaining blob length so DLC padding is discarded. Out-of-order\n * chunks are rejected ({@link append} returns 0).\n */\nexport class SchemaAccumulator {\n readonly #buf: number[] = [];\n readonly #blobTotalLen: number;\n\n constructor(blobTotalLen: number) {\n this.#blobTotalLen = blobTotalLen;\n }\n\n get length(): number {\n return this.#buf.length;\n }\n\n get blobTotalLen(): number {\n return this.#blobTotalLen;\n }\n\n get complete(): boolean {\n return this.#buf.length >= this.#blobTotalLen;\n }\n\n bytes(): Uint8Array {\n return new Uint8Array(this.#buf);\n }\n\n /**\n * Append `chunk` if its offset matches the current accumulator length.\n * Returns the number of bytes actually appended (0 on rejection).\n */\n append(chunk: SchemaDataMsg, expectedChunkLen: number): number {\n if (chunk.offset !== this.#buf.length) return 0;\n const remaining = Math.max(0, this.#blobTotalLen - chunk.offset);\n const cap = Math.min(expectedChunkLen, remaining);\n const take = Math.min(chunk.bytes.length, cap);\n for (let i = 0; i < take; i++) {\n this.#buf.push(chunk.bytes[i] ?? 0);\n }\n return take;\n }\n}\n","/**\n * Scalar type enum and little-endian wire codecs. The ordinal values are\n * part of the protobuf schema blob and must not be renumbered.\n */\n\nexport enum ScalarType {\n Bool = 0,\n U8 = 1,\n I8 = 2,\n U16 = 3,\n I16 = 4,\n U32 = 5,\n I32 = 6,\n U64 = 7,\n I64 = 8,\n F32 = 9,\n F64 = 10,\n}\n\nexport const SCALAR_NAMES = Object.freeze([\n 'bool',\n 'u8',\n 'i8',\n 'u16',\n 'i16',\n 'u32',\n 'i32',\n 'u64',\n 'i64',\n 'f32',\n 'f64',\n]) as readonly string[];\n\n/** Wire size in bytes of one scalar element. bool is 1 byte. */\nexport function scalarSize(type: ScalarType): number {\n switch (type) {\n case ScalarType.Bool:\n case ScalarType.U8:\n case ScalarType.I8:\n return 1;\n case ScalarType.U16:\n case ScalarType.I16:\n return 2;\n case ScalarType.U32:\n case ScalarType.I32:\n case ScalarType.F32:\n return 4;\n case ScalarType.U64:\n case ScalarType.I64:\n case ScalarType.F64:\n return 8;\n }\n}\n\nexport function scalarName(type: ScalarType): string | undefined {\n return SCALAR_NAMES[type];\n}\n\nexport function scalarFromName(name: string): ScalarType | undefined {\n const idx = SCALAR_NAMES.indexOf(name);\n return idx >= 0 ? (idx as ScalarType) : undefined;\n}\n\n/**\n * Pack an int/bool as little-endian into `out[offset..offset+scalarSize(type))`.\n * `number` is widened to bigint so signed negatives sign-extend to 64-bit\n * two's complement before truncation, matching C++ `pack_scalar_int_le`.\n */\nexport function packScalarIntLe(\n type: ScalarType,\n value: number | bigint,\n out: Uint8Array,\n offset = 0,\n): void {\n const bytes = scalarSize(type);\n const mask = (1n << 64n) - 1n;\n const bits = (typeof value === 'bigint' ? value : BigInt(value)) & mask;\n for (let i = 0; i < bytes; i++) {\n out[offset + i] = Number((bits >> BigInt(i * 8)) & 0xffn);\n }\n}\n\n/** Bit-cast a float32 to its IEEE-754 little-endian representation. */\nexport function packScalarF32Le(value: number, out: Uint8Array, offset = 0): void {\n new DataView(out.buffer, out.byteOffset, out.byteLength).setFloat32(offset, value, true);\n}\n\n/** Bit-cast a float64 to its IEEE-754 little-endian representation. */\nexport function packScalarF64Le(value: number, out: Uint8Array, offset = 0): void {\n new DataView(out.buffer, out.byteOffset, out.byteLength).setFloat64(offset, value, true);\n}\n\n/**\n * Inverse of {@link packScalarIntLe}. Returns the raw bit pattern as bigint;\n * caller interprets sign via {@link sign-extend} helpers below.\n */\nexport function unpackScalarIntLe(type: ScalarType, src: Uint8Array, offset = 0): bigint {\n const bytes = scalarSize(type);\n let bits = 0n;\n for (let i = 0; i < bytes; i++) {\n bits |= BigInt(src[offset + i] ?? 0) << BigInt(i * 8);\n }\n return bits;\n}\n\nexport function unpackScalarF32Le(src: Uint8Array, offset = 0): number {\n return new DataView(src.buffer, src.byteOffset, src.byteLength).getFloat32(offset, true);\n}\n\nexport function unpackScalarF64Le(src: Uint8Array, offset = 0): number {\n return new DataView(src.buffer, src.byteOffset, src.byteLength).getFloat64(offset, true);\n}\n\n/**\n * Sign-extend a bigint that was read as an unsigned `bytes`-byte field to a\n * signed bigint. Useful for I8/I16/I32/I64 after {@link unpackScalarIntLe}.\n */\nexport function signExtend(bits: bigint, bytes: number): bigint {\n const width = BigInt(bytes * 8);\n const signBit = 1n << (width - 1n);\n return (bits & signBit) === 0n ? bits : bits - (1n << width);\n}\n","/**\n * Minimal proto3 reader — varint + length-delimited (used by the schema\n * blob) with fixed32 / fixed64 skipped to tolerate future fields.\n * See https://protobuf.dev/programming-guides/encoding/.\n */\n\nexport const WIRE_VARINT = 0;\nconst WIRE_FIXED64 = 1;\nexport const WIRE_LENGTH_DELIM = 2;\nconst WIRE_FIXED32 = 5;\n\nexport class ProtoReader {\n private pos = 0;\n\n constructor(\n private readonly buf: Uint8Array,\n private readonly end: number = buf.length,\n ) {}\n\n get done(): boolean {\n return this.pos >= this.end;\n }\n get position(): number {\n return this.pos;\n }\n\n /** Read a base-128 varint as a JS number (schema uses uint32 only). */\n readVarint(): number {\n let result = 0;\n let shift = 0;\n while (this.pos < this.end) {\n const b = this.buf[this.pos++];\n if (b === undefined) throw new ProtoError('truncated varint');\n result |= (b & 0x7f) << shift;\n if ((b & 0x80) === 0) return result >>> 0;\n shift += 7;\n if (shift >= 32) {\n // Drain any oversized varint and truncate to low 32 bits.\n while (this.pos < this.end) {\n const c = this.buf[this.pos++];\n if (c === undefined) throw new ProtoError('truncated varint');\n if ((c & 0x80) === 0) break;\n }\n return result >>> 0;\n }\n }\n throw new ProtoError('truncated varint');\n }\n\n /** Read a length-delimited byte slice (no copy). */\n readBytes(): Uint8Array {\n const len = this.readVarint();\n if (this.pos + len > this.end) throw new ProtoError('truncated length-delimited field');\n const slice = this.buf.subarray(this.pos, this.pos + len);\n this.pos += len;\n return slice;\n }\n\n /** Read a length-delimited UTF-8 string. */\n readString(): string {\n const bytes = this.readBytes();\n return new TextDecoder('utf-8', { fatal: false }).decode(bytes);\n }\n\n /** Read a length-delimited sub-message and return a new reader scoped to it. */\n readMessage(): ProtoReader {\n const bytes = this.readBytes();\n return new ProtoReader(bytes);\n }\n\n /** Read a tag as `{field, wire}`. Unknown fields dispatch to {@link skipValue}. */\n readTag(): { field: number; wire: number } {\n const tag = this.readVarint();\n return { field: tag >>> 3, wire: tag & 0x7 };\n }\n\n /** Discard the value associated with `wire`. Used to tolerate unknown fields. */\n skipValue(wire: number): void {\n switch (wire) {\n case WIRE_VARINT:\n this.readVarint();\n return;\n case WIRE_LENGTH_DELIM:\n this.readBytes();\n return;\n case WIRE_FIXED32:\n if (this.pos + 4 > this.end) throw new ProtoError('truncated fixed32');\n this.pos += 4;\n return;\n case WIRE_FIXED64:\n if (this.pos + 8 > this.end) throw new ProtoError('truncated fixed64');\n this.pos += 8;\n return;\n default:\n throw new ProtoError(`unsupported wire type ${wire}`);\n }\n }\n}\n\nexport class ProtoError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ProtoError';\n }\n}\n","import { PROTOCOL_VERSION } from './can-id.js';\nimport { ProtoError, ProtoReader } from './proto-reader.js';\nimport { ScalarType, scalarSize } from './scalar-codec.js';\n\n/**\n * NodeSchema IR + protobuf decoder for the schema blob. Master-side notes:\n * - Proto `topic_id` / `service_id` / `param_id` / BlockType `type_id`\n * are accepted but discarded — the master derives indices from\n * {@link computeNumbering}.\n * - Proto wire `tx_disabled` inverts to IR `tx_enabled`.\n * - `BlockArray.type_id` (proto) → `BlockArray.blockTypeIndex` (IR).\n * Unknown fields are skipped so future schema additions don't break masters.\n */\n\n// --- Field numbers (proto3) ---------------------------------------------------\n\nconst FIELD = {\n Field: {\n name: 1,\n type: 2,\n arrayLen: 3,\n periodUsOverride: 4,\n txDisabled: 5,\n },\n RosMapping: {\n rosType: 1,\n rosName: 2,\n fieldMap: 3,\n },\n Topic: {\n name: 2,\n dir: 3,\n fields: 4,\n defaultPeriodUs: 5,\n ros: 6,\n },\n Service: {\n name: 2,\n request: 3,\n response: 4,\n ros: 5,\n },\n Param: {\n name: 2,\n type: 3,\n arrayLen: 4,\n defaultValue: 5,\n minValue: 6,\n maxValue: 7,\n },\n BlockType: {\n name: 2,\n topics: 3,\n services: 4,\n params: 5,\n },\n BlockArray: {\n typeId: 1,\n rosNamespace: 2,\n },\n Limits: {\n paramSetBatchBytes: 1,\n },\n NodeSchema: {\n protocolVersion: 1,\n nodeName: 2,\n types: 3,\n instances: 4,\n limits: 5,\n },\n} as const;\n\n// --- IR ---------------------------------------------------------------------\n\nexport enum Direction {\n M2S = 0,\n S2M = 1,\n}\n\nexport interface SchemaField {\n name: string;\n type: ScalarType;\n /** 0 = scalar; >0 = fixed-length array of `type`. */\n arrayLen: number;\n /** Per-field override of the owning topic's defaultPeriodUs; undefined = inherit. */\n periodUsOverride?: number;\n /** Master-side planner skips this field if false. Defaults to true. */\n txEnabled: boolean;\n}\n\nexport interface RosMapping {\n rosType: string;\n rosName: string;\n fieldMap: string[];\n}\n\nexport interface SchemaTopic {\n name: string;\n dir: Direction;\n fields: SchemaField[];\n defaultPeriodUs: number;\n ros: RosMapping;\n}\n\nexport interface SchemaService {\n name: string;\n request: SchemaField[];\n response: SchemaField[];\n ros: RosMapping;\n}\n\nexport interface SchemaParam {\n name: string;\n type: ScalarType;\n arrayLen: number;\n /** Little-endian packed payload. Always present for default; min/max may be empty. */\n defaultValue: Uint8Array;\n minValue: Uint8Array;\n maxValue: Uint8Array;\n}\n\nexport interface SchemaBlockType {\n name: string;\n topics: SchemaTopic[];\n services: SchemaService[];\n params: SchemaParam[];\n}\n\nexport interface SchemaBlockArray {\n /** Index into NodeSchema.types (was `type_id` on the wire). */\n blockTypeIndex: number;\n rosNamespace: string;\n}\n\nexport interface WireLimits {\n /** 0 = use bridge default. */\n paramSetBatchBytes: number;\n}\n\nexport interface NodeSchema {\n protocolVersion: number;\n nodeName: string;\n types: SchemaBlockType[];\n instances: SchemaBlockArray[];\n limits: WireLimits;\n}\n\n// --- Field decoders ---------------------------------------------------------\n\nfunction decodeField(r: ProtoReader): SchemaField {\n const f: SchemaField = {\n name: '',\n type: ScalarType.Bool,\n arrayLen: 0,\n txEnabled: true,\n };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Field.name:\n f.name = r.readString();\n break;\n case FIELD.Field.type: {\n const v = r.readVarint();\n if (v > ScalarType.F64) {\n throw new ProtoError(`Field.type out of range: ${v}`);\n }\n f.type = v as ScalarType;\n break;\n }\n case FIELD.Field.arrayLen:\n f.arrayLen = r.readVarint();\n break;\n case FIELD.Field.periodUsOverride: {\n const v = r.readVarint();\n if (v !== 0) f.periodUsOverride = v;\n break;\n }\n case FIELD.Field.txDisabled: {\n const v = r.readVarint();\n f.txEnabled = v === 0;\n break;\n }\n default:\n r.skipValue(wire);\n }\n }\n return f;\n}\n\nfunction decodeRos(r: ProtoReader): RosMapping {\n const ros: RosMapping = { rosType: '', rosName: '', fieldMap: [] };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.RosMapping.rosType:\n ros.rosType = r.readString();\n break;\n case FIELD.RosMapping.rosName:\n ros.rosName = r.readString();\n break;\n case FIELD.RosMapping.fieldMap:\n ros.fieldMap.push(r.readString());\n break;\n default:\n r.skipValue(wire);\n }\n }\n return ros;\n}\n\nfunction decodeTopic(r: ProtoReader): SchemaTopic {\n // proto3 absent-field defaults: enum → 0 (= M2S), so an omitted `dir`\n // means M2S, NOT the IR struct default of S2M. Mirrors C++ parse_schema.\n const t: SchemaTopic = {\n name: '',\n dir: Direction.M2S,\n fields: [],\n defaultPeriodUs: 0,\n ros: { rosType: '', rosName: '', fieldMap: [] },\n };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Topic.name:\n t.name = r.readString();\n break;\n case FIELD.Topic.dir: {\n const v = r.readVarint();\n if (v !== Direction.M2S && v !== Direction.S2M) {\n throw new ProtoError(`Topic.dir out of range: ${v}`);\n }\n t.dir = v;\n break;\n }\n case FIELD.Topic.fields:\n t.fields.push(decodeField(r.readMessage()));\n break;\n case FIELD.Topic.defaultPeriodUs:\n t.defaultPeriodUs = r.readVarint();\n break;\n case FIELD.Topic.ros:\n t.ros = decodeRos(r.readMessage());\n break;\n default:\n r.skipValue(wire);\n }\n }\n return t;\n}\n\nfunction decodeService(r: ProtoReader): SchemaService {\n const s: SchemaService = {\n name: '',\n request: [],\n response: [],\n ros: { rosType: '', rosName: '', fieldMap: [] },\n };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Service.name:\n s.name = r.readString();\n break;\n case FIELD.Service.request:\n s.request.push(decodeField(r.readMessage()));\n break;\n case FIELD.Service.response:\n s.response.push(decodeField(r.readMessage()));\n break;\n case FIELD.Service.ros:\n s.ros = decodeRos(r.readMessage());\n break;\n default:\n r.skipValue(wire);\n }\n }\n return s;\n}\n\nfunction decodeParam(r: ProtoReader): SchemaParam {\n const p: SchemaParam = {\n name: '',\n type: ScalarType.Bool,\n arrayLen: 0,\n defaultValue: new Uint8Array(0),\n minValue: new Uint8Array(0),\n maxValue: new Uint8Array(0),\n };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Param.name:\n p.name = r.readString();\n break;\n case FIELD.Param.type: {\n const v = r.readVarint();\n if (v > ScalarType.F64) throw new ProtoError(`Param.type out of range: ${v}`);\n p.type = v as ScalarType;\n break;\n }\n case FIELD.Param.arrayLen:\n p.arrayLen = r.readVarint();\n break;\n case FIELD.Param.defaultValue:\n p.defaultValue = new Uint8Array(r.readBytes());\n break;\n case FIELD.Param.minValue:\n p.minValue = new Uint8Array(r.readBytes());\n break;\n case FIELD.Param.maxValue:\n p.maxValue = new Uint8Array(r.readBytes());\n break;\n default:\n r.skipValue(wire);\n }\n }\n return p;\n}\n\nfunction decodeBlockType(r: ProtoReader): SchemaBlockType {\n const b: SchemaBlockType = { name: '', topics: [], services: [], params: [] };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.BlockType.name:\n b.name = r.readString();\n break;\n case FIELD.BlockType.topics:\n b.topics.push(decodeTopic(r.readMessage()));\n break;\n case FIELD.BlockType.services:\n b.services.push(decodeService(r.readMessage()));\n break;\n case FIELD.BlockType.params:\n b.params.push(decodeParam(r.readMessage()));\n break;\n default:\n r.skipValue(wire);\n }\n }\n return b;\n}\n\nfunction decodeBlockArray(r: ProtoReader): SchemaBlockArray {\n const a: SchemaBlockArray = { blockTypeIndex: 0, rosNamespace: '' };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.BlockArray.typeId:\n a.blockTypeIndex = r.readVarint();\n break;\n case FIELD.BlockArray.rosNamespace:\n a.rosNamespace = r.readString();\n break;\n default:\n r.skipValue(wire);\n }\n }\n return a;\n}\n\nfunction decodeLimits(r: ProtoReader): WireLimits {\n const l: WireLimits = { paramSetBatchBytes: 0 };\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.Limits.paramSetBatchBytes:\n l.paramSetBatchBytes = r.readVarint();\n break;\n default:\n r.skipValue(wire);\n }\n }\n return l;\n}\n\nexport interface DecodeSchemaResult {\n schema: NodeSchema;\n /** True when the blob's protocolVersion exceeds this build's {@link PROTOCOL_VERSION}. */\n versionAheadOfMaster: boolean;\n}\n\n/**\n * Parse a schema blob into the master-side IR. Throws {@link ProtoError}\n * on malformed input or `protocolVersion === 0` (proto3 leaves an unset\n * uint32 at 0, so zero means it was never populated).\n */\nexport function decodeSchemaWithMeta(blob: Uint8Array): DecodeSchemaResult {\n const schema: NodeSchema = {\n protocolVersion: 0,\n nodeName: '',\n types: [],\n instances: [],\n limits: { paramSetBatchBytes: 0 },\n };\n const r = new ProtoReader(blob);\n while (!r.done) {\n const { field, wire } = r.readTag();\n switch (field) {\n case FIELD.NodeSchema.protocolVersion:\n schema.protocolVersion = r.readVarint();\n break;\n case FIELD.NodeSchema.nodeName:\n schema.nodeName = r.readString();\n break;\n case FIELD.NodeSchema.types:\n schema.types.push(decodeBlockType(r.readMessage()));\n break;\n case FIELD.NodeSchema.instances:\n schema.instances.push(decodeBlockArray(r.readMessage()));\n break;\n case FIELD.NodeSchema.limits:\n schema.limits = decodeLimits(r.readMessage());\n break;\n default:\n r.skipValue(wire);\n }\n }\n if (schema.protocolVersion === 0) {\n throw new ProtoError(`schema protocol_version is 0 (unset)`);\n }\n for (const arr of schema.instances) {\n if (arr.blockTypeIndex >= schema.types.length) {\n throw new ProtoError(\n `BlockArray.type_id ${arr.blockTypeIndex} out of range (#types=${schema.types.length})`,\n );\n }\n }\n return {\n schema,\n versionAheadOfMaster: schema.protocolVersion > PROTOCOL_VERSION,\n };\n}\n\n/** Shim for callers that don't need the metadata — prefer {@link decodeSchemaWithMeta}. */\nexport function decodeSchema(blob: Uint8Array): NodeSchema {\n return decodeSchemaWithMeta(blob).schema;\n}\n\n/** Wire size in bytes for a single field (scalar or fixed array). */\nexport function fieldWireSize(field: SchemaField): number {\n return scalarSize(field.type) * (field.arrayLen === 0 ? 1 : field.arrayLen);\n}\n","import {\n packScalarF32Le,\n packScalarF64Le,\n packScalarIntLe,\n ScalarType,\n scalarName,\n scalarSize,\n signExtend,\n unpackScalarF32Le,\n unpackScalarF64Le,\n unpackScalarIntLe,\n} from './scalar-codec.js';\nimport { fieldWireSize, type SchemaField } from './schema.js';\n\n/**\n * Field-driven dict ⇄ Uint8Array codec. Throws on shape mismatch; decode\n * tolerates trailing bytes so future schema additions don't break decoders.\n */\n\nexport class DynamicCodecError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'DynamicCodecError';\n }\n}\n\nexport type FieldValue = number | bigint | boolean | number[] | bigint[] | boolean[];\nexport type Dict = Record<string, FieldValue>;\n\nfunction isInt64(type: ScalarType): boolean {\n return type === ScalarType.U64 || type === ScalarType.I64;\n}\n\nfunction packOneScalar(\n type: ScalarType,\n value: number | bigint | boolean,\n out: Uint8Array,\n offset: number,\n fieldName: string,\n): void {\n switch (type) {\n case ScalarType.Bool: {\n if (typeof value !== 'boolean') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected boolean for bool, got ${typeof value}`,\n );\n }\n out[offset] = value ? 1 : 0;\n return;\n }\n case ScalarType.F32: {\n if (typeof value !== 'number') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected number for f32, got ${typeof value}`,\n );\n }\n packScalarF32Le(value, out, offset);\n return;\n }\n case ScalarType.F64: {\n if (typeof value !== 'number') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected number for f64, got ${typeof value}`,\n );\n }\n packScalarF64Le(value, out, offset);\n return;\n }\n default: {\n if (isInt64(type)) {\n if (typeof value !== 'bigint') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected bigint for ${scalarName(type)}, got ${typeof value}`,\n );\n }\n } else {\n if (typeof value !== 'number') {\n throw new DynamicCodecError(\n `field '${fieldName}': expected number for ${scalarName(type)}, got ${typeof value}`,\n );\n }\n }\n packScalarIntLe(type, value as number | bigint, out, offset);\n return;\n }\n }\n}\n\nfunction unpackOneScalar(\n type: ScalarType,\n src: Uint8Array,\n offset: number,\n): number | bigint | boolean {\n switch (type) {\n case ScalarType.Bool:\n return (src[offset] ?? 0) !== 0;\n case ScalarType.F32:\n return unpackScalarF32Le(src, offset);\n case ScalarType.F64:\n return unpackScalarF64Le(src, offset);\n case ScalarType.I8:\n case ScalarType.I16:\n case ScalarType.I32: {\n const bits = unpackScalarIntLe(type, src, offset);\n return Number(signExtend(bits, scalarSize(type)));\n }\n case ScalarType.U8:\n case ScalarType.U16:\n case ScalarType.U32:\n return Number(unpackScalarIntLe(type, src, offset));\n case ScalarType.I64: {\n const bits = unpackScalarIntLe(type, src, offset);\n return signExtend(bits, 8);\n }\n case ScalarType.U64:\n return unpackScalarIntLe(type, src, offset);\n }\n}\n\n/**\n * Sum the wire size of a field list. The result is the byte count that\n * {@link encodeFields} will produce.\n */\nexport function fieldsWireSize(fields: readonly SchemaField[]): number {\n let n = 0;\n for (const f of fields) n += fieldWireSize(f);\n return n;\n}\n\n/** Encode a dict into little-endian wire bytes. Throws on missing / wrong-shape fields. */\nexport function encodeFields(fields: readonly SchemaField[], value: Dict): Uint8Array {\n const totalSize = fieldsWireSize(fields);\n const out = new Uint8Array(totalSize);\n let off = 0;\n for (const f of fields) {\n if (!f.txEnabled) {\n // Slot stays reserved (zero-filled); the frame planner is responsible\n // for excluding tx_disabled fields from the plan entirely.\n off += fieldWireSize(f);\n continue;\n }\n const v = value[f.name];\n if (v === undefined) {\n throw new DynamicCodecError(`encodeFields: missing field '${f.name}'`);\n }\n if (f.arrayLen === 0) {\n packOneScalar(f.type, v as number | bigint | boolean, out, off, f.name);\n off += scalarSize(f.type);\n } else {\n if (!Array.isArray(v)) {\n throw new DynamicCodecError(\n `field '${f.name}': expected array of length ${f.arrayLen}, got ${typeof v}`,\n );\n }\n if (v.length !== f.arrayLen) {\n throw new DynamicCodecError(\n `field '${f.name}': expected array length ${f.arrayLen}, got ${v.length}`,\n );\n }\n const stride = scalarSize(f.type);\n for (let i = 0; i < f.arrayLen; i++) {\n packOneScalar(f.type, v[i] as number | bigint | boolean, out, off, f.name);\n off += stride;\n }\n }\n }\n return out;\n}\n\n/** Decode wire bytes into a dict. Trailing bytes are ignored; throws only if too short. */\nexport function decodeFields(fields: readonly SchemaField[], bytes: Uint8Array): Dict {\n const expected = fieldsWireSize(fields);\n if (bytes.length < expected) {\n throw new DynamicCodecError(\n `decodeFields: payload too short — need ${expected} bytes, got ${bytes.length}`,\n );\n }\n const out: Dict = {};\n let off = 0;\n for (const f of fields) {\n if (f.arrayLen === 0) {\n out[f.name] = unpackOneScalar(f.type, bytes, off);\n off += scalarSize(f.type);\n } else {\n const stride = scalarSize(f.type);\n if (f.type === ScalarType.Bool) {\n const arr: boolean[] = [];\n for (let i = 0; i < f.arrayLen; i++) {\n arr.push(unpackOneScalar(f.type, bytes, off) as boolean);\n off += stride;\n }\n out[f.name] = arr;\n } else if (isInt64(f.type)) {\n const arr: bigint[] = [];\n for (let i = 0; i < f.arrayLen; i++) {\n arr.push(unpackOneScalar(f.type, bytes, off) as bigint);\n off += stride;\n }\n out[f.name] = arr;\n } else {\n const arr: number[] = [];\n for (let i = 0; i < f.arrayLen; i++) {\n arr.push(unpackOneScalar(f.type, bytes, off) as number);\n off += stride;\n }\n out[f.name] = arr;\n }\n }\n }\n return out;\n}\n","import type { CanFrame, ITransport, Unsubscribe } from '@fibril/can-transport';\nimport { type Dict, decodeFields } from './dynamic-codec.js';\nimport type { FramePlan } from './node-agent.js';\nimport { Direction, fieldWireSize, type SchemaField } from './schema.js';\nimport type { SchemaIndex } from './schema-index.js';\n\n/**\n * Master-side decoder for S→M data-plane frames. `attachSlave` claims a\n * slave's std_ids; two slaves cannot share a std_id (throws). M→S frames\n * are skipped so echo / self-loopback isn't decoded as slave-published.\n */\nexport interface DataPlaneReceiverOptions {\n transport: ITransport;\n /** Non-fatal error sink (decode errors, listener throws). */\n onError?: (err: Error) => void;\n /** Clock override for tests. Default `() => Date.now()`. */\n now?: () => number;\n}\n\nexport type TopicListener = (value: Dict, tsMs: number) => void;\n\nexport interface TopicSample {\n readonly value: Dict;\n readonly tsMs: number;\n}\n\nexport interface TopicStats {\n readonly count: number;\n /** `now()` of the most recent frame. */\n readonly lastRxMs: number;\n /** Rolling rate in Hz over the last {@link RATE_WINDOW} samples; 0 with <2 samples. */\n readonly ratePerSec: number;\n}\n\ninterface PackedEntry {\n path: string;\n fields: SchemaField[];\n offset: number;\n size: number;\n}\n\ninterface FrameBucket {\n nodeId: number;\n stdId: number;\n dir: Direction;\n entries: PackedEntry[];\n}\n\ninterface TopicCache {\n value: Dict;\n tsMs: number;\n count: number;\n /** Rolling window of timestamps for ratePerSec, capped at RATE_WINDOW. */\n ts: number[];\n}\n\nconst RATE_WINDOW = 16;\n\nfunction maskedFieldsList(fields: readonly SchemaField[], mask: number): SchemaField[] {\n const out: SchemaField[] = [];\n for (let i = 0; i < fields.length; i++) {\n const f = fields[i];\n if (f === undefined) continue;\n if ((mask & (1 << i)) !== 0) out.push(f);\n }\n return out;\n}\n\nfunction sumWireSize(fields: readonly SchemaField[]): number {\n let s = 0;\n for (const f of fields) s += fieldWireSize(f);\n return s;\n}\n\nfunction buildBucket(framePlan: FramePlan, index: SchemaIndex, nodeId: number): FrameBucket {\n let offset = 0;\n const entries: PackedEntry[] = [];\n for (const e of framePlan.entries) {\n const desc = index.topicByIndex(e.topicIndex);\n if (desc === undefined) {\n // Skip unknown entries so a partial plan still decodes what it can.\n continue;\n }\n const fields = maskedFieldsList(desc.fields, e.fieldBitmask);\n const size = sumWireSize(fields);\n entries.push({ path: desc.path, fields, offset, size });\n offset += size;\n }\n return { nodeId, stdId: framePlan.stdId, dir: framePlan.dir, entries };\n}\n\nfunction topicKey(nodeId: number, path: string): string {\n return `${nodeId}/${path}`;\n}\n\nexport class DataPlaneReceiver {\n readonly #onError: ((err: Error) => void) | undefined;\n readonly #now: () => number;\n readonly #unsubFrame: Unsubscribe;\n\n readonly #buckets = new Map<number, FrameBucket>();\n readonly #ownedByNode = new Map<number, Set<number>>();\n readonly #latest = new Map<string, TopicCache>();\n readonly #listeners = new Map<string, Set<TopicListener>>();\n #version = 0;\n\n constructor(opts: DataPlaneReceiverOptions) {\n this.#onError = opts.onError;\n this.#now = opts.now ?? (() => Date.now());\n this.#unsubFrame = opts.transport.onFrame((f) => this.#onFrame(f));\n }\n\n /** Claim a slave's S→M std_ids. Re-attach atomically detaches the prior plan. */\n attachSlave(nodeId: number, framePlan: readonly FramePlan[], index: SchemaIndex): void {\n this.detachSlave(nodeId);\n const owned = new Set<number>();\n for (const fp of framePlan) {\n if (fp.dir !== Direction.S2M) continue;\n if (this.#buckets.has(fp.stdId)) {\n const other = this.#buckets.get(fp.stdId);\n throw new Error(\n `DataPlaneReceiver: std_id 0x${fp.stdId.toString(16)} claimed by slave 0x${\n other?.nodeId.toString(16) ?? '??'\n }, cannot also attach slave 0x${nodeId.toString(16)}`,\n );\n }\n this.#buckets.set(fp.stdId, buildBucket(fp, index, nodeId));\n owned.add(fp.stdId);\n }\n this.#ownedByNode.set(nodeId, owned);\n }\n\n /** Release a slave's std_ids and drop its cached topic samples. */\n detachSlave(nodeId: number): void {\n const owned = this.#ownedByNode.get(nodeId);\n if (!owned) return;\n for (const id of owned) this.#buckets.delete(id);\n this.#ownedByNode.delete(nodeId);\n const prefix = `${nodeId}/`;\n for (const k of [...this.#latest.keys()]) {\n if (k.startsWith(prefix)) this.#latest.delete(k);\n }\n }\n\n onTopic(nodeId: number, path: string, listener: TopicListener): Unsubscribe {\n const key = topicKey(nodeId, path);\n let set = this.#listeners.get(key);\n if (!set) {\n set = new Set();\n this.#listeners.set(key, set);\n }\n set.add(listener);\n return () => {\n const s = this.#listeners.get(key);\n if (!s) return;\n s.delete(listener);\n if (s.size === 0) this.#listeners.delete(key);\n };\n }\n\n latest(nodeId: number, path: string): TopicSample | null {\n const c = this.#latest.get(topicKey(nodeId, path));\n return c === undefined ? null : { value: c.value, tsMs: c.tsMs };\n }\n\n stats(nodeId: number, path: string): TopicStats | null {\n const c = this.#latest.get(topicKey(nodeId, path));\n if (!c) return null;\n let rate = 0;\n if (c.ts.length >= 2) {\n const newest = c.ts[c.ts.length - 1] ?? 0;\n const oldest = c.ts[0] ?? 0;\n const dt = newest - oldest;\n if (dt > 0) rate = (1000 * (c.ts.length - 1)) / dt;\n }\n return { count: c.count, lastRxMs: c.tsMs, ratePerSec: rate };\n }\n\n /** Paths attached for this slave (in plan order). */\n topicPathsFor(nodeId: number): string[] {\n const owned = this.#ownedByNode.get(nodeId);\n if (!owned) return [];\n const out: string[] = [];\n for (const id of owned) {\n const b = this.#buckets.get(id);\n if (b) for (const e of b.entries) out.push(e.path);\n }\n return out;\n }\n\n /** Bumps on every successfully decoded entry — cheap change detector. */\n get version(): number {\n return this.#version;\n }\n\n dispose(): void {\n this.#unsubFrame();\n this.#buckets.clear();\n this.#ownedByNode.clear();\n this.#latest.clear();\n this.#listeners.clear();\n }\n\n #onFrame(f: CanFrame): void {\n if (f.extended) return;\n if (f.rtr) return;\n const bucket = this.#buckets.get(f.id);\n if (bucket === undefined) return;\n const tsMs = this.#now();\n for (const e of bucket.entries) {\n if (e.offset + e.size > f.data.length) continue;\n const slice = f.data.subarray(e.offset, e.offset + e.size);\n let dict: Dict;\n try {\n dict = decodeFields(e.fields, slice);\n } catch (err) {\n this.#err(err);\n continue;\n }\n this.#publish(bucket.nodeId, e.path, dict, tsMs);\n }\n }\n\n #publish(nodeId: number, path: string, value: Dict, tsMs: number): void {\n const key = topicKey(nodeId, path);\n let c = this.#latest.get(key);\n if (c === undefined) {\n c = { value, tsMs, count: 0, ts: [] };\n this.#latest.set(key, c);\n } else {\n c.value = value;\n c.tsMs = tsMs;\n }\n c.count++;\n c.ts.push(tsMs);\n if (c.ts.length > RATE_WINDOW) c.ts.shift();\n this.#version++;\n const set = this.#listeners.get(key);\n if (set !== undefined) {\n for (const l of set) {\n try {\n l(value, tsMs);\n } catch (err) {\n this.#err(err);\n }\n }\n }\n }\n\n #err(e: unknown): void {\n if (this.#onError === undefined) return;\n this.#onError(e instanceof Error ? e : new Error(String(e)));\n }\n}\n","import { MAX_FRAME_PAYLOAD, STD_ID_MASK } from './can-id.js';\nimport type { FrameDefineEntry } from './config-plane.js';\nimport type { Direction } from './schema.js';\n\n/**\n * Field-requests → FRAME_DEFINE bodies. Groups by (dir, period_us) and\n * bin-packs whole topics into ≤64-byte frames; a topic that exceeds 64 B\n * is the sole field-split exception. Iteration order is ascending on\n * every level so codegen / bridge / master produce identical std_ids.\n */\n\nexport interface FieldRequest {\n topicIndex: number;\n /** 0..15, bit position in `fieldBitmask`. */\n fieldId: number;\n /** Wire size of this field. */\n sizeBytes: number;\n /** 0 = on-trigger only. */\n periodUs: number;\n dir: Direction;\n}\n\nexport interface FrameSpec {\n stdCanId: number;\n periodUs: number;\n dir: Direction;\n logicalBytes: number;\n entries: FrameDefineEntry[];\n}\n\n/**\n * 11-bit std_id allocator with a delayed free pool. `next()` returns `null`\n * on exhaustion — wrapping past 0x7FF would alias on the wire.\n */\nexport class StdIdAllocator {\n #next = 0x100;\n readonly #freePool: Array<{ availableAtMs: number; id: number }> = [];\n\n next(nowMs: number = Date.now()): number | null {\n if (this.#freePool.length > 0) {\n const head = this.#freePool[0];\n if (head !== undefined && head.availableAtMs <= nowMs) {\n this.#freePool.shift();\n return head.id;\n }\n }\n if (this.#next > STD_ID_MASK) return null;\n const id = this.#next;\n this.#next += 1;\n return id;\n }\n\n release(id: number, availableAtMs: number): void {\n let lo = 0;\n let hi = this.#freePool.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const entry = this.#freePool[mid];\n if (entry !== undefined && entry.availableAtMs < availableAtMs) lo = mid + 1;\n else hi = mid;\n }\n this.#freePool.splice(lo, 0, { availableAtMs, id });\n }\n\n reset(start = 0x100): void {\n this.#next = start;\n this.#freePool.length = 0;\n }\n}\n\ninterface MakeFrameInput {\n topics: Map<number, FieldRequest[]>;\n dir: Direction;\n periodUs: number;\n alloc: StdIdAllocator;\n}\n\nfunction makeFrame(input: MakeFrameInput): FrameSpec | null {\n const id = input.alloc.next();\n if (id === null) return null;\n const entries: FrameDefineEntry[] = [];\n let bytes = 0;\n for (const topicIndex of [...input.topics.keys()].sort((a, b) => a - b)) {\n const fields = input.topics.get(topicIndex);\n if (!fields) continue;\n let mask = 0;\n for (const r of fields) {\n mask |= 1 << r.fieldId;\n bytes += r.sizeBytes;\n }\n entries.push({ topicIndex, fieldBitmask: mask });\n }\n return {\n stdCanId: id,\n periodUs: input.periodUs,\n dir: input.dir,\n logicalBytes: Math.min(bytes, MAX_FRAME_PAYLOAD),\n entries,\n };\n}\n\nfunction emitOversizedTopic(\n fields: FieldRequest[],\n dir: Direction,\n periodUs: number,\n alloc: StdIdAllocator,\n out: FrameSpec[],\n): boolean {\n const sorted = [...fields].sort((a, b) => a.fieldId - b.fieldId);\n let bin: FieldRequest[] = [];\n let binBytes = 0;\n const topicIndex = sorted[0]?.topicIndex ?? 0;\n const flush = (): boolean => {\n if (bin.length === 0) return true;\n const one = new Map<number, FieldRequest[]>([[topicIndex, bin]]);\n const f = makeFrame({ topics: one, dir, periodUs, alloc });\n if (!f) return false;\n out.push(f);\n bin = [];\n binBytes = 0;\n return true;\n };\n for (const r of sorted) {\n if (binBytes + r.sizeBytes > MAX_FRAME_PAYLOAD) {\n if (!flush()) return false;\n }\n bin.push(r);\n binBytes += r.sizeBytes;\n }\n return flush();\n}\n\n/**\n * Plan a slave's frame layout. Returns `null` on std_id exhaustion — a\n * partial plan would silently drop fields.\n */\nexport function planFrames(\n requests: readonly FieldRequest[],\n alloc: StdIdAllocator,\n): FrameSpec[] | null {\n // Bucket keys sort by numeric (dir, period) so iteration matches std::map.\n const buckets = new Map<string, FieldRequest[]>();\n for (const r of requests) {\n const key = `${r.dir}/${r.periodUs}`;\n let bucket = buckets.get(key);\n if (!bucket) {\n bucket = [];\n buckets.set(key, bucket);\n }\n bucket.push(r);\n }\n const sortedKeys = [...buckets.keys()].sort((a, b) => {\n const [aDir, aPeriod] = a.split('/').map(Number) as [number, number];\n const [bDir, bPeriod] = b.split('/').map(Number) as [number, number];\n if (aDir !== bDir) return aDir - bDir;\n return aPeriod - bPeriod;\n });\n\n const out: FrameSpec[] = [];\n for (const key of sortedKeys) {\n const requestsInBucket = buckets.get(key);\n if (!requestsInBucket) continue;\n const [dir, periodUs] = key.split('/').map(Number) as [number, number];\n\n const byTopic = new Map<number, FieldRequest[]>();\n for (const r of requestsInBucket) {\n let arr = byTopic.get(r.topicIndex);\n if (!arr) {\n arr = [];\n byTopic.set(r.topicIndex, arr);\n }\n arr.push(r);\n }\n const topicBytes = new Map<number, number>();\n for (const [topicIndex, fields] of byTopic) {\n let sum = 0;\n for (const r of fields) sum += r.sizeBytes;\n topicBytes.set(topicIndex, sum);\n }\n\n let currentBin = new Map<number, FieldRequest[]>();\n let currentBytes = 0;\n const flush = (): boolean => {\n if (currentBin.size === 0) return true;\n const f = makeFrame({ topics: currentBin, dir, periodUs, alloc });\n if (!f) return false;\n out.push(f);\n currentBin = new Map();\n currentBytes = 0;\n return true;\n };\n\n const sortedTopics = [...byTopic.keys()].sort((a, b) => a - b);\n for (const topicIndex of sortedTopics) {\n const fields = byTopic.get(topicIndex);\n if (!fields) continue;\n const sz = topicBytes.get(topicIndex) ?? 0;\n if (sz > MAX_FRAME_PAYLOAD) {\n if (!flush()) return null;\n if (!emitOversizedTopic(fields, dir, periodUs, alloc, out)) return null;\n continue;\n }\n if (currentBytes + sz > MAX_FRAME_PAYLOAD) {\n if (!flush()) return null;\n }\n currentBin.set(topicIndex, fields);\n currentBytes += sz;\n }\n if (!flush()) return null;\n }\n return out;\n}\n","import type { FieldRequest, FrameSpec } from './frame-planner.js';\nimport { planFrames, StdIdAllocator } from './frame-planner.js';\nimport type { FramePlan } from './node-agent.js';\nimport type { NumberingResult } from './numbering.js';\nimport { Direction, fieldWireSize, type NodeSchema, type SchemaField } from './schema.js';\n\n/**\n * Predicate for masking S→M fields on top of the schema-declared `txEnabled`.\n * Only called for fields with `txEnabled !== false`. Return `false` to drop\n * the field. `topicPath` mirrors {@link SchemaIndex.topicPaths}.\n */\nexport type S2MFieldFilter = (info: {\n topicPath: string;\n topicIndex: number;\n fieldId: number;\n fieldName: string;\n field: SchemaField;\n}) => boolean;\n\nconst I_TOKEN = '{i}';\n\nfunction expandIToken(s: string, value: number): string {\n if (!s.includes(I_TOKEN)) return s;\n return s.split(I_TOKEN).join(String(value));\n}\n\nfunction joinPath(ns: string, name: string): string {\n if (ns.length === 0) return name;\n if (name.length === 0) return ns;\n return `${ns}/${name}`;\n}\n\n/**\n * Every schema-enabled S→M field at its declared period\n * (`field.periodUsOverride` ?? topic's `defaultPeriodUs`), optionally masked\n * further by `filter`. Feeds {@link planFrames} for the observe-everything\n * auto-provision path.\n */\nexport function buildDefaultS2MRequests(\n schema: NodeSchema,\n numbering: NumberingResult,\n filter?: S2MFieldFilter,\n): FieldRequest[] {\n const out: FieldRequest[] = [];\n numbering.topics.byIndex.forEach((endpoint, flatIndex) => {\n const block = schema.instances[endpoint.blockArray];\n if (!block) return;\n const type = schema.types[block.blockTypeIndex];\n if (!type) return;\n const topic = type.topics[endpoint.endpoint];\n if (!topic) return;\n if (topic.dir !== Direction.S2M) return;\n // Computed lazily — only needed when `filter` is supplied.\n let topicPath: string | null = null;\n topic.fields.forEach((field, fieldId) => {\n if (!field.txEnabled) return;\n if (filter !== undefined) {\n if (topicPath === null) {\n topicPath = joinPath(expandIToken(block.rosNamespace, endpoint.instance), topic.name);\n }\n if (\n !filter({\n topicPath,\n topicIndex: flatIndex,\n fieldId,\n fieldName: field.name,\n field,\n })\n ) {\n return;\n }\n }\n out.push({\n topicIndex: flatIndex,\n fieldId,\n sizeBytes: fieldWireSize(field),\n periodUs: field.periodUsOverride ?? topic.defaultPeriodUs,\n dir: topic.dir,\n });\n });\n });\n return out;\n}\n\n/**\n * FramePlanFactory subscribing to every schema-enabled S→M field (optionally\n * masked by `filter`) with a fresh {@link StdIdAllocator}. Returns `[]` on\n * planning failure so NodeAgent stalls in `awaiting-announce` — a partial\n * plan would silently drop fields.\n */\nexport function defaultS2MFramePlan(\n schema: NodeSchema,\n numbering: NumberingResult,\n filter?: S2MFieldFilter,\n): FramePlan[] {\n const requests = buildDefaultS2MRequests(schema, numbering, filter);\n const alloc = new StdIdAllocator();\n const planned = planFrames(requests, alloc);\n if (planned === null) return [];\n return planned.map(\n (s: FrameSpec): FramePlan => ({\n stdId: s.stdCanId,\n periodUs: s.periodUs,\n dir: s.dir,\n entries: s.entries,\n }),\n );\n}\n","import type { ITransport } from '@fibril/can-transport';\nimport { encodeMasterHeartbeat } from './config-plane.js';\n\n/**\n * Broadcasts CMD_MASTER_HEARTBEAT (§5.11) on a fixed period so slaves with\n * a `master_lost_us` watchdog configured do not silence their S→M traffic.\n *\n * Independent of any single {@link NodeAgent} — the heartbeat is a single\n * bus-wide broadcast that refreshes every slave's watchdog. Construct one\n * per transport.\n */\nexport class MasterHeartbeatBroadcaster {\n #handle: ReturnType<typeof setInterval> | null = null;\n\n constructor(\n private readonly transport: ITransport,\n private readonly periodMs: number = 100,\n ) {}\n\n start(): void {\n if (this.#handle !== null) return;\n const tick = (): void => {\n if (!this.transport.isOpen) return;\n void this.transport.send(encodeMasterHeartbeat()).catch(() => {\n // Swallow — the transport's onError surfaces real failures.\n });\n };\n // Send one immediately so a newly-attached slave doesn't wait a full\n // period before its first refresh.\n tick();\n this.#handle = setInterval(tick, this.periodMs);\n }\n\n stop(): void {\n if (this.#handle === null) return;\n clearInterval(this.#handle);\n this.#handle = null;\n }\n\n get running(): boolean {\n return this.#handle !== null;\n }\n}\n","import type { NodeSchema, SchemaBlockType } from './schema.js';\n\n/**\n * Flat-numbering tables for topics, services, and parameters — a pure\n * function of (schema, instance-count-vector). Codegen, slave runtime, and\n * master all derive these tables through the same function.\n */\n\n// Reserved service slots — must NOT be produced by numbering.\nexport const SERVICE_INDEX_CANCEL = 0xff;\nexport const SERVICE_INDEX_PARAM_SET = 0xfd;\nexport const SERVICE_INDEX_MAX = 0xfc;\nexport const SERVICE_INDEX_CAPACITY = SERVICE_INDEX_MAX + 1;\n\nexport enum NumberingError {\n Ok = 'ok',\n ServiceIndexOverflow = 'service_index overflow (>253)',\n TopicIndexOverflow = 'topic_index overflow (>65535)',\n ParamIndexOverflow = 'param_index overflow (>65535)',\n InstanceCountMismatch = 'actual_counts length != #instances',\n BlockTypeOutOfRange = 'BlockArray::blockTypeIndex out of range',\n}\n\nexport interface EndpointKey {\n blockArray: number;\n instance: number;\n endpoint: number;\n}\n\nexport interface NumberingTable {\n /** Array index is the flat numbering. */\n byIndex: EndpointKey[];\n /** Per-block-array base offsets. Length = #blockArrays + 1; last is total. */\n bases: number[];\n}\n\nexport interface NumberingResult {\n topics: NumberingTable;\n services: NumberingTable;\n params: NumberingTable;\n status: NumberingError;\n}\n\ntype EndpointPicker = (bt: SchemaBlockType) => number;\n\nconst N_TOPICS: EndpointPicker = (bt) => bt.topics.length;\nconst N_SERVICES: EndpointPicker = (bt) => bt.services.length;\nconst N_PARAMS: EndpointPicker = (bt) => bt.params.length;\n\nfunction buildTable(\n schema: NodeSchema,\n counts: readonly number[],\n pick: EndpointPicker,\n): NumberingTable {\n const byIndex: EndpointKey[] = [];\n const bases: number[] = [];\n let base = 0;\n bases.push(base);\n for (let b = 0; b < schema.instances.length; b++) {\n const arr = schema.instances[b];\n if (!arr) continue;\n const type = schema.types[arr.blockTypeIndex];\n if (!type) continue;\n const n = pick(type);\n const count = counts[b] ?? 0;\n for (let inst = 0; inst < count; inst++) {\n for (let ep = 0; ep < n; ep++) {\n byIndex.push({ blockArray: b, instance: inst, endpoint: ep });\n }\n }\n base += n * count;\n bases.push(base);\n }\n return { byIndex, bases };\n}\n\n/**\n * `actualCounts.length` must equal `schema.instances.length`. On any error\n * the returned tables are empty and `status !== Ok`.\n */\nexport function computeNumbering(\n schema: NodeSchema,\n actualCounts: readonly number[],\n): NumberingResult {\n const empty: NumberingTable = { byIndex: [], bases: [] };\n const fail = (status: NumberingError): NumberingResult => ({\n topics: empty,\n services: empty,\n params: empty,\n status,\n });\n\n if (actualCounts.length !== schema.instances.length) {\n return fail(NumberingError.InstanceCountMismatch);\n }\n for (const arr of schema.instances) {\n if (arr.blockTypeIndex >= schema.types.length) {\n return fail(NumberingError.BlockTypeOutOfRange);\n }\n }\n\n const topics = buildTable(schema, actualCounts, N_TOPICS);\n const services = buildTable(schema, actualCounts, N_SERVICES);\n const params = buildTable(schema, actualCounts, N_PARAMS);\n\n if (topics.byIndex.length > 0xffff) {\n return {\n topics: empty,\n services: empty,\n params: empty,\n status: NumberingError.TopicIndexOverflow,\n };\n }\n if (params.byIndex.length > 0xffff) {\n return {\n topics: empty,\n services: empty,\n params: empty,\n status: NumberingError.ParamIndexOverflow,\n };\n }\n if (services.byIndex.length > SERVICE_INDEX_CAPACITY) {\n return {\n topics: empty,\n services: empty,\n params: empty,\n status: NumberingError.ServiceIndexOverflow,\n };\n }\n\n return { topics, services, params, status: NumberingError.Ok };\n}\n","export async function sha256(bytes: Uint8Array): Promise<Uint8Array> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('crypto.subtle is not available in this environment');\n }\n // crypto.subtle rejects SharedArrayBuffer-backed views; copy to a fresh one.\n const owned = new Uint8Array(bytes);\n const digest = await crypto.subtle.digest('SHA-256', owned);\n return new Uint8Array(digest);\n}\n\n/** First 8 bytes of SHA-256(blob) as little-endian u64 — the ANNOUNCE shape. */\nexport async function schemaHashPrefix(blob: Uint8Array): Promise<bigint> {\n const digest = await sha256(blob);\n let result = 0n;\n for (let i = 0; i < 8; i++) {\n result |= BigInt(digest[i] ?? 0) << BigInt(i * 8);\n }\n return result;\n}\n","import type { NumberingResult } from './numbering.js';\nimport type { ScalarType } from './scalar-codec.js';\nimport { type Direction, fieldWireSize, type NodeSchema, type SchemaField } from './schema.js';\n\n/**\n * Path (`<expanded_ns>/<endpoint_name>`) → descriptor lookup for one slave.\n * Duplicate path within the same kind throws; the same path across kinds\n * is allowed (caller selects via `topic()` / `service()` / `param()`).\n */\n\nconst I_TOKEN = '{i}';\n\nfunction expandIToken(s: string, value: number): string {\n if (!s.includes(I_TOKEN)) return s;\n return s.split(I_TOKEN).join(String(value));\n}\n\nfunction joinPath(ns: string, name: string): string {\n if (ns.length === 0) return name;\n if (name.length === 0) return ns;\n return `${ns}/${name}`;\n}\n\n/** Resolved descriptor for one S→M or M→S topic. */\nexport interface TopicDescriptor {\n readonly kind: 'topic';\n readonly path: string;\n readonly topicIndex: number;\n readonly dir: Direction;\n readonly fields: readonly SchemaField[];\n readonly defaultPeriodUs: number;\n readonly wireSize: number;\n}\n\n/** Resolved descriptor for one Service. */\nexport interface ServiceDescriptor {\n readonly kind: 'service';\n readonly path: string;\n readonly serviceIndex: number;\n readonly requestFields: readonly SchemaField[];\n readonly responseFields: readonly SchemaField[];\n readonly requestWireSize: number;\n readonly responseWireSize: number;\n}\n\n/** Resolved descriptor for one Param (single-field). */\nexport interface ParamDescriptor {\n readonly kind: 'param';\n readonly path: string;\n readonly paramIndex: number;\n readonly type: ScalarType;\n /** 0 = scalar; >0 = fixed-length array of `type`. */\n readonly arrayLen: number;\n readonly wireSize: number;\n readonly defaultValue: Uint8Array;\n readonly minValue: Uint8Array;\n readonly maxValue: Uint8Array;\n}\n\nexport type EndpointDescriptor = TopicDescriptor | ServiceDescriptor | ParamDescriptor;\n\nfunction sumFieldsWireSize(fields: readonly SchemaField[]): number {\n let n = 0;\n for (const f of fields) n += fieldWireSize(f);\n return n;\n}\n\nexport class SchemaIndex {\n readonly #topicsByPath = new Map<string, TopicDescriptor>();\n readonly #servicesByPath = new Map<string, ServiceDescriptor>();\n readonly #paramsByPath = new Map<string, ParamDescriptor>();\n readonly #topicsByIndex = new Map<number, TopicDescriptor>();\n readonly #servicesByIndex = new Map<number, ServiceDescriptor>();\n readonly #paramsByIndex = new Map<number, ParamDescriptor>();\n\n constructor(schema: NodeSchema, numbering: NumberingResult, instanceCounts: readonly number[]) {\n if (instanceCounts.length !== schema.instances.length) {\n throw new RangeError(\n `SchemaIndex: instanceCounts.length (${instanceCounts.length}) != schema.instances.length (${schema.instances.length})`,\n );\n }\n for (let arrIdx = 0; arrIdx < schema.instances.length; arrIdx++) {\n const arr = schema.instances[arrIdx];\n if (!arr) continue;\n const block = schema.types[arr.blockTypeIndex];\n if (!block) continue;\n const topicBase = numbering.topics.bases[arrIdx];\n const serviceBase = numbering.services.bases[arrIdx];\n const paramBase = numbering.params.bases[arrIdx];\n if (topicBase === undefined || serviceBase === undefined || paramBase === undefined) {\n // Numbering failed earlier for this block array.\n continue;\n }\n const instCount = instanceCounts[arrIdx] ?? 0;\n\n for (let inst = 0; inst < instCount; inst++) {\n const ns = expandIToken(arr.rosNamespace, inst);\n\n for (let ep = 0; ep < block.topics.length; ep++) {\n const t = block.topics[ep];\n if (!t) continue;\n const path = joinPath(ns, t.name);\n const idx = topicBase + inst * block.topics.length + ep;\n const desc: TopicDescriptor = {\n kind: 'topic',\n path,\n topicIndex: idx,\n dir: t.dir,\n fields: t.fields,\n defaultPeriodUs: t.defaultPeriodUs,\n wireSize: sumFieldsWireSize(t.fields),\n };\n if (this.#topicsByPath.has(path)) {\n throw new Error(`SchemaIndex: duplicate topic path '${path}'`);\n }\n this.#topicsByPath.set(path, desc);\n this.#topicsByIndex.set(idx, desc);\n }\n\n for (let ep = 0; ep < block.services.length; ep++) {\n const s = block.services[ep];\n if (!s) continue;\n const path = joinPath(ns, s.name);\n const idx = serviceBase + inst * block.services.length + ep;\n const desc: ServiceDescriptor = {\n kind: 'service',\n path,\n serviceIndex: idx,\n requestFields: s.request,\n responseFields: s.response,\n requestWireSize: sumFieldsWireSize(s.request),\n responseWireSize: sumFieldsWireSize(s.response),\n };\n if (this.#servicesByPath.has(path)) {\n throw new Error(`SchemaIndex: duplicate service path '${path}'`);\n }\n this.#servicesByPath.set(path, desc);\n this.#servicesByIndex.set(idx, desc);\n }\n\n for (let ep = 0; ep < block.params.length; ep++) {\n const p = block.params[ep];\n if (!p) continue;\n const path = joinPath(ns, p.name);\n const idx = paramBase + inst * block.params.length + ep;\n const wireSize = fieldWireSize({\n name: p.name,\n type: p.type,\n arrayLen: p.arrayLen,\n txEnabled: true,\n });\n const desc: ParamDescriptor = {\n kind: 'param',\n path,\n paramIndex: idx,\n type: p.type,\n arrayLen: p.arrayLen,\n wireSize,\n defaultValue: p.defaultValue,\n minValue: p.minValue,\n maxValue: p.maxValue,\n };\n if (this.#paramsByPath.has(path)) {\n throw new Error(`SchemaIndex: duplicate param path '${path}'`);\n }\n this.#paramsByPath.set(path, desc);\n this.#paramsByIndex.set(idx, desc);\n }\n }\n }\n }\n\n topic(path: string): TopicDescriptor | undefined {\n return this.#topicsByPath.get(path);\n }\n service(path: string): ServiceDescriptor | undefined {\n return this.#servicesByPath.get(path);\n }\n param(path: string): ParamDescriptor | undefined {\n return this.#paramsByPath.get(path);\n }\n\n topicByIndex(idx: number): TopicDescriptor | undefined {\n return this.#topicsByIndex.get(idx);\n }\n serviceByIndex(idx: number): ServiceDescriptor | undefined {\n return this.#servicesByIndex.get(idx);\n }\n paramByIndex(idx: number): ParamDescriptor | undefined {\n return this.#paramsByIndex.get(idx);\n }\n\n /** All topic paths in numbering order. Useful for debugging / sniffer UI. */\n topicPaths(): string[] {\n return [...this.#topicsByPath.keys()];\n }\n servicePaths(): string[] {\n return [...this.#servicesByPath.keys()];\n }\n paramPaths(): string[] {\n return [...this.#paramsByPath.keys()];\n }\n}\n","/** Wrapping u8 counter for the config-plane `seq` byte. */\nexport class SeqAllocator {\n #next = 0;\n\n next(): number {\n const v = this.#next & 0xff;\n this.#next = (this.#next + 1) & 0xff;\n return v;\n }\n\n reset(): void {\n this.#next = 0;\n }\n}\n","import type { CanFrameTx } from '@fibril/can-transport';\nimport {\n CHAN_SVC_REQUEST,\n MAX_FRAME_PAYLOAD,\n makeExtId,\n SEG_FIRST_DATA,\n SEG_MAX_SEQ,\n SEG_MAX_TOTAL,\n SEG_REST_DATA,\n segOffset,\n} from './can-id.js';\n/**\n * SVC_REQUEST frames for a master→slave call. ≤64 B → one SINGLE frame;\n * larger → seq 0 carries `[0]=0 [1..2]=total + ≤61 B data`, later seqs\n * carry `[0]=seq + ≤63 B data`. Throws on payloads >1024 B.\n */\nexport function makeSvcRequestFrames(\n nodeId: number,\n svcIdx: number,\n callId: number,\n payload: Uint8Array,\n): CanFrameTx[] {\n if (payload.length > SEG_MAX_TOTAL) {\n throw new RangeError(\n `service request payload ${payload.length} exceeds SEG_MAX_TOTAL (${SEG_MAX_TOTAL})`,\n );\n }\n if (payload.length <= MAX_FRAME_PAYLOAD) {\n return [\n {\n id: makeExtId(CHAN_SVC_REQUEST, nodeId, svcIdx, callId, 0),\n extended: true,\n fd: true,\n data: payload,\n },\n ];\n }\n const total = payload.length;\n const rest = total - SEG_FIRST_DATA;\n const extras = Math.ceil(rest / SEG_REST_DATA);\n const nSegs = 1 + extras;\n if (nSegs - 1 > SEG_MAX_SEQ) {\n throw new RangeError(`segmented request would need ${nSegs} segments (cap ${SEG_MAX_SEQ + 1})`);\n }\n const out: CanFrameTx[] = [];\n for (let seq = 0; seq < nSegs; seq++) {\n let body: Uint8Array;\n if (seq === 0) {\n const take = Math.min(total, SEG_FIRST_DATA);\n body = new Uint8Array(3 + take);\n body[0] = 0;\n body[1] = total & 0xff;\n body[2] = (total >>> 8) & 0xff;\n body.set(payload.subarray(0, take), 3);\n } else {\n const off = segOffset(seq);\n const take = Math.min(SEG_REST_DATA, total - off);\n body = new Uint8Array(1 + take);\n body[0] = seq;\n body.set(payload.subarray(off, off + take), 1);\n }\n out.push({\n id: makeExtId(CHAN_SVC_REQUEST, nodeId, svcIdx, callId, 1),\n extended: true,\n fd: true,\n data: body,\n });\n }\n return out;\n}\n\n/**\n * Response segments (for mock slaves / TS slave runtime). `payload` must\n * already carry `[status, ...body]`; `channel` is typically CHAN_SVC_RESPONSE.\n */\nexport function makeSvcSegmentedFrames(\n channel: number,\n nodeId: number,\n svcIdx: number,\n callId: number,\n payload: Uint8Array,\n): CanFrameTx[] {\n if (payload.length > SEG_MAX_TOTAL) {\n throw new RangeError(\n `service response payload ${payload.length} exceeds SEG_MAX_TOTAL (${SEG_MAX_TOTAL})`,\n );\n }\n if (payload.length <= MAX_FRAME_PAYLOAD) {\n return [\n {\n id: makeExtId(channel, nodeId, svcIdx, callId, 0),\n extended: true,\n fd: true,\n data: payload,\n },\n ];\n }\n const total = payload.length;\n const rest = total - SEG_FIRST_DATA;\n const extras = Math.ceil(rest / SEG_REST_DATA);\n const nSegs = 1 + extras;\n if (nSegs - 1 > SEG_MAX_SEQ) {\n throw new RangeError(\n `segmented response would need ${nSegs} segments (cap ${SEG_MAX_SEQ + 1})`,\n );\n }\n const out: CanFrameTx[] = [];\n for (let seq = 0; seq < nSegs; seq++) {\n let body: Uint8Array;\n if (seq === 0) {\n const take = Math.min(total, SEG_FIRST_DATA);\n body = new Uint8Array(3 + take);\n body[0] = 0;\n body[1] = total & 0xff;\n body[2] = (total >>> 8) & 0xff;\n body.set(payload.subarray(0, take), 3);\n } else {\n const off = segOffset(seq);\n const take = Math.min(SEG_REST_DATA, total - off);\n body = new Uint8Array(1 + take);\n body[0] = seq;\n body.set(payload.subarray(off, off + take), 1);\n }\n out.push({\n id: makeExtId(channel, nodeId, svcIdx, callId, 1),\n extended: true,\n fd: true,\n data: body,\n });\n }\n return out;\n}\n\n/** Bitmask of seg-seqs required to reassemble a `totalLen`-byte payload. */\nexport function segExpectedMask(totalLen: number): number {\n if (totalLen <= 0) return 0;\n if (totalLen <= SEG_FIRST_DATA) return 1;\n const rest = totalLen - SEG_FIRST_DATA;\n const extras = Math.ceil(rest / SEG_REST_DATA);\n const nSegs = 1 + extras;\n if (nSegs >= 32) return 0xffffffff;\n return (1 << nSegs) - 1;\n}\n\n/** Per-(svc, call_id) reassembly slot for one segmented transfer. */\nexport class SegmentReassembler {\n totalLen = 0;\n rxBitmap = 0;\n lastRxMs = 0;\n #buffer: Uint8Array = new Uint8Array(0);\n\n /**\n * Ingest one seg=1 frame (payload with seq / total_len header attached).\n * Returns the assembled payload once complete, else null. Resets the slot\n * on protocol violation.\n */\n ingest(data: Uint8Array, nowMs: number): Uint8Array | null {\n if (data.length === 0) return this.#reset();\n const seq = data[0] ?? 0;\n if (seq > SEG_MAX_SEQ) return this.#reset();\n this.lastRxMs = nowMs;\n\n if (seq === 0) {\n if (data.length < 3) return this.#reset();\n const total = ((data[1] ?? 0) | ((data[2] ?? 0) << 8)) & 0xffff;\n if (total === 0 || total > SEG_MAX_TOTAL) return this.#reset();\n if (this.totalLen !== 0 && this.totalLen !== total) {\n this.totalLen = total;\n this.rxBitmap = 0;\n this.#buffer = new Uint8Array(total);\n } else {\n this.totalLen = total;\n if (this.#buffer.length < total) {\n const grown = new Uint8Array(total);\n grown.set(this.#buffer.subarray(0, Math.min(this.#buffer.length, total)));\n this.#buffer = grown;\n }\n }\n const segDataLen = Math.min(data.length - 3, SEG_FIRST_DATA, total);\n if (segDataLen > 0) this.#buffer.set(data.subarray(3, 3 + segDataLen), 0);\n } else {\n const off = segOffset(seq);\n const segDataLen = Math.min(data.length - 1, SEG_REST_DATA);\n if (off + segDataLen > SEG_MAX_TOTAL) return this.#reset();\n if (this.totalLen !== 0 && off + segDataLen > this.totalLen) return this.#reset();\n if (this.#buffer.length < off + segDataLen) {\n const grown = new Uint8Array(off + segDataLen);\n grown.set(this.#buffer);\n this.#buffer = grown;\n }\n if (segDataLen > 0) this.#buffer.set(data.subarray(1, 1 + segDataLen), off);\n }\n this.rxBitmap |= 1 << seq;\n if (this.totalLen === 0) return null;\n const need = segExpectedMask(this.totalLen);\n if ((this.rxBitmap & ~need) !== 0) return this.#reset();\n if ((this.rxBitmap & need) !== need) return null;\n const out = this.#buffer.slice(0, this.totalLen);\n this.#reset();\n return out;\n }\n\n #reset(): null {\n this.totalLen = 0;\n this.rxBitmap = 0;\n this.#buffer = new Uint8Array(0);\n return null;\n }\n}\n","import type { CanFrame, ITransport, Unsubscribe } from '@fibril/can-transport';\nimport {\n CHAN_SVC_REQUEST,\n CHAN_SVC_RESPONSE,\n extChannel,\n extIndex,\n extNodeId,\n extSeg,\n extSeq,\n makeExtId,\n SVC_ACCEPTED,\n SVC_CANCEL,\n} from './can-id.js';\nimport { padToDlc } from './dlc.js';\nimport { makeSvcRequestFrames, SegmentReassembler } from './segmented-transfer.js';\n\n/** Per-call options. */\nexport interface ServiceCallOptions {\n /** Pre-encoded request payload (no status byte — that's response-only). */\n request: Uint8Array;\n /** Override default timeout. Default 250 ms (matches bridge `service_timeout_`). */\n timeoutMs?: number;\n /** Cancel via AbortSignal — fires SVC_CANCEL (§7.5) to the slave. */\n signal?: AbortSignal;\n}\n\n/** Resolved service response. `status === 0` (SVC_OK) is the success path. */\nexport interface ServiceResult {\n status: number;\n data: Uint8Array;\n}\n\n/** Throwable error union for `ServiceClient.call`. */\nexport class ServiceCallError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\nexport class ServiceTimeoutError extends ServiceCallError {\n constructor(message = 'service call timed out') {\n super(message);\n }\n}\nexport class ServiceUnavailableError extends ServiceCallError {\n constructor(message = 'service unavailable (slave lost or reprovisioned)') {\n super(message);\n }\n}\nexport class ServiceCancelledError extends ServiceCallError {\n constructor(message = 'service call cancelled') {\n super(message);\n }\n}\nexport class NoCallSlotError extends ServiceCallError {\n constructor(serviceIndex: number) {\n super(`no free call_id slot for service_index ${serviceIndex}`);\n }\n}\n\ninterface PendingCall {\n serviceIndex: number;\n callId: number;\n deadlineMs: number;\n timeoutMs: number;\n resolve: (r: ServiceResult) => void;\n reject: (err: Error) => void;\n reassembler: SegmentReassembler;\n signal?: AbortSignal;\n abortListener?: () => void;\n acceptedSeen: boolean;\n}\n\n/** Cap on simultaneous in-flight segmented transfers. Matches bridge. */\nconst REASM_MAX_CONCURRENT = 16;\n/** §7.4 reassembly TTL. */\nconst SEG_TIMEOUT_MS = 100;\n\n/**\n * Promise-based, AbortSignal-aware service-call client for one slave.\n * NodeAgent owns one per slave and exposes it on the running snapshot.\n */\nexport class ServiceClient {\n readonly nodeId: number;\n readonly #transport: ITransport;\n readonly #defaultTimeoutMs: number;\n readonly #now: () => number;\n\n #unsub: Unsubscribe | null = null;\n\n // Round-robin per-service call_id allocator. 0xFF = \"no free slot\".\n readonly #nextCallId = new Map<number, number>();\n readonly #pending = new Map<number, PendingCall>();\n\n constructor(opts: {\n nodeId: number;\n transport: ITransport;\n defaultTimeoutMs?: number;\n now?: () => number;\n }) {\n this.nodeId = opts.nodeId;\n this.#transport = opts.transport;\n this.#defaultTimeoutMs = opts.defaultTimeoutMs ?? 250;\n this.#now = opts.now ?? (() => Date.now());\n }\n\n attach(): void {\n if (this.#unsub !== null) return;\n this.#unsub = this.#transport.onFrame((f: CanFrame) => this.#onFrame(f));\n }\n\n detach(): void {\n if (this.#unsub === null) return;\n this.#unsub();\n this.#unsub = null;\n }\n\n /** Number of in-flight calls. Testing / introspection. */\n get pendingCount(): number {\n return this.#pending.size;\n }\n\n /**\n * Sweep call deadlines and segment-reassembly TTLs. The owning agent\n * should call this from its periodic sweep loop.\n */\n sweep(nowMs: number = this.#now()): void {\n for (const [key, call] of this.#pending) {\n if (call.deadlineMs <= nowMs) {\n this.#pending.delete(key);\n this.#detachAbort(call);\n call.reject(new ServiceTimeoutError());\n continue;\n }\n if (call.reassembler.totalLen !== 0 && nowMs - call.reassembler.lastRxMs > SEG_TIMEOUT_MS) {\n // Silent mid-transfer — reset the reassembler but keep the call\n // alive so the slave can retry until the outer deadline.\n call.reassembler.totalLen = 0;\n call.reassembler.rxBitmap = 0;\n }\n }\n }\n\n /** Reject every in-flight call as Unavailable. NodeAgent calls this on lost / reprovision. */\n failAll(reason = 'slave reprovisioning'): void {\n const pending = [...this.#pending.values()];\n this.#pending.clear();\n for (const c of pending) {\n this.#detachAbort(c);\n c.reject(new ServiceUnavailableError(reason));\n }\n }\n\n async call(serviceIndex: number, opts: ServiceCallOptions): Promise<ServiceResult> {\n if (serviceIndex < 0 || serviceIndex > 0xff) {\n throw new RangeError(`serviceIndex out of range: ${serviceIndex}`);\n }\n const callId = this.#allocCallId(serviceIndex);\n if (callId === 0xff) throw new NoCallSlotError(serviceIndex);\n\n const timeoutMs = opts.timeoutMs ?? this.#defaultTimeoutMs;\n const key = (serviceIndex << 8) | callId;\n if (this.#pending.size >= REASM_MAX_CONCURRENT * 4) {\n // Soft guard against pathological cross-service fan-out.\n throw new NoCallSlotError(serviceIndex);\n }\n\n return new Promise<ServiceResult>((resolve, reject) => {\n const call: PendingCall = {\n serviceIndex,\n callId,\n deadlineMs: this.#now() + timeoutMs,\n timeoutMs,\n resolve,\n reject,\n reassembler: new SegmentReassembler(),\n acceptedSeen: false,\n };\n if (opts.signal) {\n call.signal = opts.signal;\n if (opts.signal.aborted) {\n reject(new ServiceCancelledError());\n return;\n }\n call.abortListener = () => {\n if (!this.#pending.has(key)) return;\n this.#pending.delete(key);\n this.#detachAbort(call);\n void this.#sendCancel(call.serviceIndex, call.callId).catch(() => {});\n reject(new ServiceCancelledError());\n };\n opts.signal.addEventListener('abort', call.abortListener, { once: true });\n }\n this.#pending.set(key, call);\n // Fire-and-forget send — transport errors surface as timeouts so a\n // brief disconnect doesn't drop the call mid-flight.\n const frames = makeSvcRequestFrames(this.nodeId, serviceIndex, callId, opts.request);\n for (const f of frames) {\n void this.#transport.send(f).catch(() => {});\n }\n });\n }\n\n // ---------------------------------------------------------------------\n // Frame ingress\n // ---------------------------------------------------------------------\n\n #onFrame(f: CanFrame): void {\n if (!f.extended) return;\n if (extNodeId(f.id) !== this.nodeId) return;\n if (extChannel(f.id) !== CHAN_SVC_RESPONSE) return;\n const svcIdx = extIndex(f.id);\n const callId = extSeq(f.id);\n const seg = extSeg(f.id);\n const key = (svcIdx << 8) | callId;\n const call = this.#pending.get(key);\n if (!call) return;\n\n if (seg === 0) {\n if (f.data.length === 0) return;\n const status = f.data[0] ?? 0;\n const data = f.data.slice(1);\n this.#finishMaybeAccepted(key, call, status, data);\n return;\n }\n const assembled = call.reassembler.ingest(f.data, this.#now());\n if (assembled === null) return;\n if (assembled.length === 0) return;\n const status = assembled[0] ?? 0;\n const data = assembled.slice(1);\n this.#finishMaybeAccepted(key, call, status, data);\n }\n\n #finishMaybeAccepted(key: number, call: PendingCall, status: number, data: Uint8Array): void {\n if (status === SVC_ACCEPTED) {\n // Two-stage reply: extend the deadline while the slave computes.\n if (!call.acceptedSeen) {\n call.acceptedSeen = true;\n call.deadlineMs = this.#now() + call.timeoutMs;\n }\n return;\n }\n this.#pending.delete(key);\n this.#detachAbort(call);\n call.resolve({ status, data });\n }\n\n #allocCallId(svcIdx: number): number {\n let next = this.#nextCallId.get(svcIdx) ?? 0;\n for (let i = 0; i < 0xff; i++) {\n if (next === 0xff) next = 0;\n const key = (svcIdx << 8) | next;\n if (!this.#pending.has(key)) {\n this.#nextCallId.set(svcIdx, (next + 1) & 0xff);\n return next;\n }\n next = (next + 1) & 0xff;\n }\n return 0xff;\n }\n\n async #sendCancel(svcIdx: number, callId: number): Promise<void> {\n // SVC_CANCEL rides the SvcRequest channel on service_index 0xFF.\n const payload = padToDlc(new Uint8Array([svcIdx & 0xff, callId & 0xff]));\n await this.#transport.send({\n id: makeExtId(CHAN_SVC_REQUEST, this.nodeId, SVC_CANCEL, 0, 0),\n extended: true,\n fd: true,\n data: payload,\n });\n }\n\n #detachAbort(call: PendingCall): void {\n if (call.signal && call.abortListener) {\n call.signal.removeEventListener('abort', call.abortListener);\n call.abortListener = undefined;\n }\n }\n}\n","import { SVC_PARAM_SET } from './can-id.js';\nimport {\n packScalarF32Le,\n packScalarF64Le,\n packScalarIntLe,\n ScalarType,\n scalarName,\n scalarSize,\n signExtend,\n unpackScalarF32Le,\n unpackScalarF64Le,\n unpackScalarIntLe,\n} from './scalar-codec.js';\nimport type { ParamDescriptor } from './schema-index.js';\nimport type { ServiceClient } from './service-client.js';\n\n/**\n * Typed wrapper around PARAM_SET (service_index 0xFD). PARAM is M→S\n * one-way, so this exposes `.set()` and `.defaultValue()` only.\n */\n\nexport class ParamCodecError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ParamCodecError';\n }\n}\n\nexport interface TypedParamSetOptions {\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport interface TypedParamSetResult {\n /** SVC_OK = 0; non-zero = slave error code. */\n readonly status: number;\n /** Slave-reported failing param_index (non-OK only); null if omitted. */\n readonly failedIndex: number | null;\n}\n\nfunction packValueInto(\n desc: ParamDescriptor,\n value: unknown,\n out: Uint8Array,\n offset: number,\n): void {\n if (desc.arrayLen === 0) {\n packOneScalar(desc.type, value, out, offset, desc.path);\n return;\n }\n if (!Array.isArray(value)) {\n throw new ParamCodecError(\n `param '${desc.path}': expected array of length ${desc.arrayLen}, got ${typeof value}`,\n );\n }\n if (value.length !== desc.arrayLen) {\n throw new ParamCodecError(\n `param '${desc.path}': expected array length ${desc.arrayLen}, got ${value.length}`,\n );\n }\n const stride = scalarSize(desc.type);\n for (let i = 0; i < desc.arrayLen; i++) {\n packOneScalar(desc.type, value[i], out, offset + i * stride, desc.path);\n }\n}\n\nfunction packOneScalar(\n type: ScalarType,\n value: unknown,\n out: Uint8Array,\n offset: number,\n pathForErr: string,\n): void {\n switch (type) {\n case ScalarType.Bool:\n if (typeof value !== 'boolean') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected boolean for bool, got ${typeof value}`,\n );\n }\n out[offset] = value ? 1 : 0;\n return;\n case ScalarType.F32:\n if (typeof value !== 'number') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected number for f32, got ${typeof value}`,\n );\n }\n packScalarF32Le(value, out, offset);\n return;\n case ScalarType.F64:\n if (typeof value !== 'number') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected number for f64, got ${typeof value}`,\n );\n }\n packScalarF64Le(value, out, offset);\n return;\n default:\n if (type === ScalarType.U64 || type === ScalarType.I64) {\n if (typeof value !== 'bigint') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected bigint for ${scalarName(type)}, got ${typeof value}`,\n );\n }\n } else if (typeof value !== 'number') {\n throw new ParamCodecError(\n `param '${pathForErr}': expected number for ${scalarName(type)}, got ${typeof value}`,\n );\n }\n packScalarIntLe(type, value as number | bigint, out, offset);\n }\n}\n\nfunction unpackScalar(\n type: ScalarType,\n src: Uint8Array,\n offset: number,\n): number | bigint | boolean {\n switch (type) {\n case ScalarType.Bool:\n return (src[offset] ?? 0) !== 0;\n case ScalarType.F32:\n return unpackScalarF32Le(src, offset);\n case ScalarType.F64:\n return unpackScalarF64Le(src, offset);\n case ScalarType.I8:\n case ScalarType.I16:\n case ScalarType.I32: {\n const bits = unpackScalarIntLe(type, src, offset);\n return Number(signExtend(bits, scalarSize(type)));\n }\n case ScalarType.U8:\n case ScalarType.U16:\n case ScalarType.U32:\n return Number(unpackScalarIntLe(type, src, offset));\n case ScalarType.I64:\n return signExtend(unpackScalarIntLe(type, src, offset), 8);\n case ScalarType.U64:\n return unpackScalarIntLe(type, src, offset);\n }\n}\n\nfunction unpackValue(desc: ParamDescriptor, src: Uint8Array): unknown {\n if (src.length < desc.wireSize) return null;\n if (desc.arrayLen === 0) {\n return unpackScalar(desc.type, src, 0);\n }\n const stride = scalarSize(desc.type);\n const out: Array<number | bigint | boolean> = [];\n for (let i = 0; i < desc.arrayLen; i++) {\n out.push(unpackScalar(desc.type, src, i * stride));\n }\n return out;\n}\n\n/** Build a PARAM_SET request payload for a single (descriptor, value) pair. */\nexport function encodeParamSetSingle(desc: ParamDescriptor, value: unknown): Uint8Array {\n const out = new Uint8Array(1 + 2 + desc.wireSize);\n out[0] = 1;\n out[1] = desc.paramIndex & 0xff;\n out[2] = (desc.paramIndex >>> 8) & 0xff;\n packValueInto(desc, value, out, 3);\n return out;\n}\n\nexport class TypedParam<T> {\n readonly path: string;\n readonly descriptor: ParamDescriptor;\n readonly #client: ServiceClient;\n\n constructor(client: ServiceClient, descriptor: ParamDescriptor) {\n this.#client = client;\n this.descriptor = descriptor;\n this.path = descriptor.path;\n }\n\n /** Decoded schema default; `null` if the descriptor carries no default. */\n defaultValue(): T | null {\n if (this.descriptor.defaultValue.length === 0) return null;\n return unpackValue(this.descriptor, this.descriptor.defaultValue) as T;\n }\n\n /** Send a PARAM_SET with a single entry for this param. */\n async set(value: T, opts: TypedParamSetOptions = {}): Promise<TypedParamSetResult> {\n const request = encodeParamSetSingle(this.descriptor, value);\n const result = await this.#client.call(SVC_PARAM_SET, {\n request,\n timeoutMs: opts.timeoutMs,\n signal: opts.signal,\n });\n let failedIndex: number | null = null;\n if (result.status !== 0 && result.data.length >= 2) {\n failedIndex = (result.data[0] ?? 0) | ((result.data[1] ?? 0) << 8);\n }\n return { status: result.status, failedIndex };\n }\n}\n","import { type Dict, decodeFields, encodeFields } from './dynamic-codec.js';\nimport type { ServiceDescriptor } from './schema-index.js';\nimport type { ServiceClient } from './service-client.js';\n\n/**\n * Result of a {@link TypedService.call}. `status` follows SPEC §7.2 (0 = OK);\n * `data` is best-effort even on non-OK, and `null` if the response body is\n * shorter than the schema demands.\n */\nexport interface TypedServiceResult<Resp extends Dict> {\n readonly status: number;\n readonly data: Resp | null;\n}\n\nexport interface TypedServiceCallOptions {\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport class TypedService<Req extends Dict, Resp extends Dict> {\n readonly path: string;\n readonly descriptor: ServiceDescriptor;\n readonly #client: ServiceClient;\n\n constructor(client: ServiceClient, descriptor: ServiceDescriptor) {\n this.#client = client;\n this.descriptor = descriptor;\n this.path = descriptor.path;\n }\n\n /** Encode `request`, dispatch via the service plane, decode the response. */\n async call(request: Req, opts: TypedServiceCallOptions = {}): Promise<TypedServiceResult<Resp>> {\n const encoded = encodeFields(this.descriptor.requestFields, request);\n const result = await this.#client.call(this.descriptor.serviceIndex, {\n request: encoded,\n timeoutMs: opts.timeoutMs,\n signal: opts.signal,\n });\n let data: Resp | null = null;\n if (this.descriptor.responseFields.length === 0) {\n data = Object.freeze({}) as unknown as Resp;\n } else if (result.data.length >= this.descriptor.responseWireSize) {\n data = decodeFields(this.descriptor.responseFields, result.data) as Resp;\n }\n return { status: result.status, data };\n }\n}\n","import type { CanFrame, ITransport, Unsubscribe } from '@fibril/can-transport';\nimport { type AckOutcome, AckTracker } from './ack-tracker.js';\nimport {\n CHAN_CONFIG,\n CMD_ACK,\n CMD_ANNOUNCE,\n CMD_HEARTBEAT,\n CMD_NAK,\n CMD_SCHEMA_DATA,\n DIR_RX_M2S,\n DIR_TX_S2M,\n extChannel,\n extIndex,\n extNodeId,\n extSeq,\n STATE_RUNNING,\n STATE_SUSPENDED,\n} from './can-id.js';\nimport {\n type AnnounceMsg,\n decodeAnnounce,\n decodeHeartbeat,\n decodeNak,\n decodeSchemaData,\n encodeDiscoverTo,\n encodeFrameDefine,\n encodeSchemaRead,\n encodeStart,\n encodeStop,\n type FrameDefineEntry,\n SchemaAccumulator,\n} from './config-plane.js';\nimport type { Dict } from './dynamic-codec.js';\nimport { computeNumbering, type NumberingResult } from './numbering.js';\nimport { Direction, decodeSchemaWithMeta, type NodeSchema } from './schema.js';\nimport { schemaHashPrefix } from './schema-hash.js';\nimport { SchemaIndex } from './schema-index.js';\nimport { SeqAllocator } from './seq-allocator.js';\nimport { ServiceClient } from './service-client.js';\nimport { TypedParam } from './typed-param.js';\nimport { TypedService } from './typed-service.js';\n\n/** One planned data-plane CAN frame consumed by FRAME_DEFINE during bring-up. */\nexport interface FramePlan {\n stdId: number;\n periodUs: number;\n dir: Direction;\n entries: readonly FrameDefineEntry[];\n}\n\n/** Context handed to {@link FramePlanFactory} so it can branch on the slave. */\nexport interface FramePlanContext {\n readonly nodeId: number;\n}\n\n/**\n * Builds the FRAME_DEFINE plan once schema and numbering are known.\n * `ctx.nodeId` lets a shared factory fork on the specific slave.\n */\nexport type FramePlanFactory =\n | ((\n schema: NodeSchema,\n numbering: NumberingResult,\n ctx: FramePlanContext,\n ) => readonly FramePlan[])\n | readonly FramePlan[];\n\n/** Phase machine — public for observers. */\nexport type NodeProvisionState =\n | { kind: 'idle' }\n | { kind: 'awaiting-announce' }\n | { kind: 'schema-reading'; received: number; total: number }\n | { kind: 'numbering' }\n | { kind: 'provisioning'; pendingDefines: number }\n /** FRAME_DEFINE done, autoStart blocked START. `startNow()` moves forward. */\n | { kind: 'awaiting-start' }\n | { kind: 'running' }\n /** Slave reported SUSPENDED. Reverts to running on the next non-SUSPENDED HEARTBEAT. */\n | { kind: 'suspended' }\n | { kind: 'lost'; reason: string }\n | { kind: 'blocked'; reason: string };\n\n/** Snapshot available once the slave reaches RUNNING. */\nexport interface NodeRunningSnapshot {\n nodeId: number;\n schemaHash: bigint;\n bootId: number;\n instanceCounts: Uint8Array;\n blob: Uint8Array;\n schema: NodeSchema;\n numbering: NumberingResult;\n framePlan: readonly FramePlan[];\n /** std_id → topic_index map for the data plane (one entry per FRAME_DEFINE). */\n stdIdToTopicIndex: Map<number, number>;\n /** §7 master-side RPC client. Stays valid for the lifetime of the snapshot. */\n services: ServiceClient;\n /** Path → IR descriptor lookup; drives `service()` / `param()` below. */\n index: SchemaIndex;\n /** Typed RPC wrapper. Throws if `path` is unknown. */\n service<Req extends Dict, Resp extends Dict>(path: string): TypedService<Req, Resp>;\n /** Typed PARAM_SET wrapper. Throws if `path` is unknown. */\n param<T = number | bigint | boolean | number[] | bigint[] | boolean[]>(\n path: string,\n ): TypedParam<T>;\n}\n\nexport interface NodeAgentOptions {\n /** 1..0x7E — broadcast (0x7F) is rejected. */\n nodeId: number;\n /** Already open()'d transport. The agent attaches its own onFrame. */\n transport: ITransport;\n /** Strategy for building the FRAME_DEFINE plan. */\n framePlan: FramePlanFactory;\n /** Per-config-command ACK timeout in ms. Default 250. */\n ackTimeoutMs?: number;\n /** SCHEMA_READ chunk byte limit — caps at the SINGLE-frame payload. Default 59. */\n schemaChunkSize?: number;\n /** SCHEMA_READ retry budget. Default 3. */\n schemaReadRetries?: number;\n /** HEARTBEAT-loss budget in ms. Default 350. */\n heartbeatTimeoutMs?: number;\n /** Per-call default timeout for `services.call()`. Default `ackTimeoutMs`. */\n serviceTimeoutMs?: number;\n /**\n * Gate consulted before each START. Returning `false` parks in\n * `awaiting-start`; caller commits with `startNow()`. Read fresh each\n * time so the flag can flip at runtime. Default `() => true`.\n */\n autoStart?: () => boolean;\n /** Optional state-change observer. */\n onState?: (state: NodeProvisionState) => void;\n /** Optional non-fatal error observer. */\n onError?: (err: Error) => void;\n /** Wall-clock override for tests. Default `() => Date.now()`. */\n now?: () => number;\n}\n\nconst DEFAULT_OPTS = {\n ackTimeoutMs: 250,\n schemaChunkSize: 59,\n schemaReadRetries: 3,\n heartbeatTimeoutMs: 350,\n} as const;\n\ninterface SchemaReadProgress {\n expectedTotal: number;\n acc: SchemaAccumulator;\n inflightSeq: number;\n inflightLen: number;\n retriesLeft: number;\n inflightDeadlineMs: number;\n}\n\ninterface ProvisioningProgress {\n generation: number;\n pendingDefines: number;\n anyFailure: boolean;\n firstNakReason: number;\n plan: readonly FramePlan[];\n stdIdToTopicIndex: Map<number, number>;\n}\n\n/**\n * Snapshot of everything {@link NodeAgent.#issueStart} needs. Held while\n * we are parked in `awaiting-start` so `startNow()` can resume without\n * re-running FRAME_DEFINE.\n */\ninterface PendingStart {\n a: AnnouncedRecord;\n schema: NodeSchema;\n blob: Uint8Array;\n numbering: NumberingResult;\n generation: number;\n progress: ProvisioningProgress;\n}\n\ninterface AnnouncedRecord {\n schemaHash: bigint;\n bootId: number;\n blobLen: number;\n protocolVersion: number;\n instanceCounts: Uint8Array;\n}\n\n/**\n * Per-slave provisioning state machine.\n * `idle` → `awaiting-announce` → `schema-reading` (skipped on cache hit) →\n * `numbering` → `provisioning` → `running`. HEARTBEAT loss drops to `lost`;\n * the next ANNOUNCE restarts the flow.\n */\nexport class NodeAgent {\n readonly nodeId: number;\n readonly #transport: ITransport;\n readonly #framePlan: FramePlanFactory;\n readonly #ackTimeoutMs: number;\n readonly #schemaChunkSize: number;\n readonly #schemaReadRetries: number;\n readonly #heartbeatTimeoutMs: number;\n readonly #autoStart: () => boolean;\n readonly #onState?: (s: NodeProvisionState) => void;\n readonly #onError?: (e: Error) => void;\n readonly #now: () => number;\n\n readonly #seq = new SeqAllocator();\n readonly #acks: AckTracker;\n readonly #services: ServiceClient;\n\n #unsubFrame: Unsubscribe | null = null;\n #sweepHandle: ReturnType<typeof setInterval> | null = null;\n #stopped = false;\n\n #state: NodeProvisionState = { kind: 'idle' };\n #announce: AnnouncedRecord | null = null;\n #schemaRead: SchemaReadProgress | null = null;\n #provisioning: ProvisioningProgress | null = null;\n #pendingStart: PendingStart | null = null;\n #snapshot: NodeRunningSnapshot | null = null;\n #generation = 0;\n\n // (hash → schema+blob) so reboot with an unchanged schema skips SCHEMA_READ.\n readonly #blobCache = new Map<bigint, { blob: Uint8Array; schema: NodeSchema }>();\n\n #lastHeartbeatMs: number | null = null;\n\n constructor(opts: NodeAgentOptions) {\n if (opts.nodeId < 1 || opts.nodeId > 0x7e) {\n throw new RangeError(`nodeId must be 1..0x7E, got ${opts.nodeId}`);\n }\n this.nodeId = opts.nodeId;\n this.#transport = opts.transport;\n this.#framePlan = opts.framePlan;\n this.#ackTimeoutMs = opts.ackTimeoutMs ?? DEFAULT_OPTS.ackTimeoutMs;\n this.#schemaChunkSize = opts.schemaChunkSize ?? DEFAULT_OPTS.schemaChunkSize;\n this.#schemaReadRetries = opts.schemaReadRetries ?? DEFAULT_OPTS.schemaReadRetries;\n this.#heartbeatTimeoutMs = opts.heartbeatTimeoutMs ?? DEFAULT_OPTS.heartbeatTimeoutMs;\n this.#autoStart = opts.autoStart ?? (() => true);\n this.#onState = opts.onState;\n this.#onError = opts.onError;\n this.#now = opts.now ?? (() => Date.now());\n this.#acks = new AckTracker(this.#now);\n this.#services = new ServiceClient({\n nodeId: this.nodeId,\n transport: this.#transport,\n defaultTimeoutMs: opts.serviceTimeoutMs ?? this.#ackTimeoutMs,\n now: this.#now,\n });\n }\n\n /** Service-plane RPC client for this slave. Always available. */\n get services(): ServiceClient {\n return this.#services;\n }\n\n get state(): NodeProvisionState {\n return this.#state;\n }\n\n get snapshot(): NodeRunningSnapshot | null {\n return this.#snapshot;\n }\n\n /**\n * Attach and wait for ANNOUNCE. Resolves immediately; progress flows via\n * {@link state} / {@link snapshot} / `onState`.\n */\n async start(): Promise<void> {\n if (this.#stopped) {\n throw new Error('NodeAgent.start() after stop() is not supported — construct a new agent');\n }\n if (this.#unsubFrame !== null) return;\n this.#unsubFrame = this.#transport.onFrame((f: CanFrame) => this.#onFrame(f));\n this.#services.attach();\n // 50 ms sweep — well below ackTimeoutMs (250).\n this.#sweepHandle = setInterval(() => this.#sweep(), 50);\n this.#setState({ kind: 'awaiting-announce' });\n }\n\n /**\n * Re-run FRAME_DEFINE / START against the live slave with the most recent\n * ANNOUNCE + cached schema. Invokes {@link FramePlanFactory} again so\n * per-slave overrides pick up their latest values. Requires a prior\n * ANNOUNCE. Tears down the current snapshot and fails pending service\n * calls, mirroring a boot_id change.\n */\n async reprovision(): Promise<void> {\n if (this.#stopped) throw new Error('NodeAgent.reprovision() after stop()');\n const a = this.#announce;\n if (a === null) {\n throw new Error('NodeAgent.reprovision() called before ANNOUNCE');\n }\n const cached = this.#blobCache.get(a.schemaHash);\n if (!cached) {\n throw new Error('NodeAgent.reprovision(): no cached schema for current ANNOUNCE');\n }\n this.#reprovisionState();\n await this.#beginBringUp(\n {\n schemaHash: a.schemaHash,\n bootId: a.bootId,\n blobLen: a.blobLen,\n protocolVersion: a.protocolVersion,\n instanceCounts: a.instanceCounts,\n },\n cached.schema,\n cached.blob,\n );\n }\n\n /** Detach, send STOP if currently RUNNING, clear all in-flight state. */\n async stop(): Promise<void> {\n if (this.#stopped) return;\n this.#stopped = true;\n if (this.#sweepHandle !== null) {\n clearInterval(this.#sweepHandle);\n this.#sweepHandle = null;\n }\n if (this.#unsubFrame !== null) {\n this.#unsubFrame();\n this.#unsubFrame = null;\n }\n this.#services.detach();\n this.#services.failAll('NodeAgent.stop()');\n if (this.#state.kind === 'running' && this.#transport.isOpen) {\n try {\n await this.#transport.send(encodeStop(this.nodeId, this.#seq.next()));\n } catch (e) {\n this.#error(e);\n }\n }\n this.#acks.clear();\n this.#schemaRead = null;\n this.#provisioning = null;\n this.#pendingStart = null;\n this.#snapshot = null;\n this.#setState({ kind: 'idle' });\n }\n\n // ---------------------------------------------------------------------\n // Frame ingress\n // ---------------------------------------------------------------------\n\n #onFrame(f: CanFrame): void {\n if (!f.extended) return;\n if (extNodeId(f.id) !== this.nodeId) return;\n if (extChannel(f.id) !== CHAN_CONFIG) return;\n const cmd = extIndex(f.id);\n const seq = extSeq(f.id);\n switch (cmd) {\n case CMD_ANNOUNCE:\n this.#handleAnnounce(f.data);\n break;\n case CMD_HEARTBEAT:\n this.#handleHeartbeat(f.data);\n break;\n case CMD_SCHEMA_DATA:\n this.#handleSchemaData(seq, f.data);\n break;\n case CMD_ACK:\n this.#acks.onAck(seq);\n break;\n case CMD_NAK: {\n const m = decodeNak(f.data);\n if (m) this.#acks.onNak(seq, m.reason);\n break;\n }\n default:\n break;\n }\n }\n\n #sweep(): void {\n const now = this.#now();\n this.#acks.sweep(now);\n this.#services.sweep(now);\n if (this.#lastHeartbeatMs !== null && this.#state.kind !== 'lost') {\n if (now - this.#lastHeartbeatMs > this.#heartbeatTimeoutMs) {\n this.#enterLost('heartbeat timeout');\n }\n }\n if (this.#schemaRead && this.#schemaRead.inflightDeadlineMs <= now) {\n this.#onSchemaReadStall();\n }\n }\n\n // ---------------------------------------------------------------------\n // ANNOUNCE\n // ---------------------------------------------------------------------\n\n #handleAnnounce(data: Uint8Array): void {\n const a = decodeAnnounce(data);\n if (!a) {\n this.#error(new Error('malformed ANNOUNCE'));\n return;\n }\n const prev = this.#announce;\n const isReboot = prev !== null && prev.bootId !== a.bootId;\n const isHashChange = prev !== null && prev.schemaHash !== a.schemaHash;\n\n this.#announce = {\n schemaHash: a.schemaHash,\n bootId: a.bootId,\n blobLen: a.blobLen,\n protocolVersion: a.protocolVersion,\n instanceCounts: a.instanceCounts,\n };\n\n // Repeat ANNOUNCE mid-bring-up (the SPEC §5.4 \"× 3\" stream) — skip so\n // it doesn't clobber state. Reboot or hash change reprovisions.\n if (this.#state.kind === 'running' && !isReboot && !isHashChange) return;\n if (this.#state.kind === 'provisioning' && !isReboot && !isHashChange) return;\n if (this.#state.kind === 'awaiting-start' && !isReboot && !isHashChange) return;\n if (this.#state.kind === 'schema-reading' && !isReboot && !isHashChange) return;\n\n this.#reprovisionState();\n\n const cached = this.#blobCache.get(a.schemaHash);\n if (cached) {\n void this.#beginBringUp(a, cached.schema, cached.blob);\n return;\n }\n this.#startSchemaRead(a);\n }\n\n // ---------------------------------------------------------------------\n // HEARTBEAT\n // ---------------------------------------------------------------------\n\n #handleHeartbeat(data: Uint8Array): void {\n const h = decodeHeartbeat(data);\n if (!h) {\n this.#error(new Error('malformed HEARTBEAT'));\n return;\n }\n this.#lastHeartbeatMs = this.#now();\n if (this.#announce && this.#announce.bootId !== h.bootId) {\n // boot_id changed without a preceding ANNOUNCE — missed the ×3 burst.\n this.#announce = null;\n this.#reprovisionState();\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n // Recover from `lost` while the snapshot / pendingStart are still live.\n if (this.#state.kind === 'lost') {\n if (this.#snapshot !== null) {\n this.#setState({ kind: 'running' });\n } else if (this.#pendingStart !== null) {\n this.#setState({ kind: 'awaiting-start' });\n }\n }\n\n // Suspended tracking only kicks in once we've reached RUNNING.\n if (this.#snapshot !== null) {\n const isSuspended = h.state === STATE_SUSPENDED;\n if (isSuspended && this.#state.kind === 'running') {\n this.#setState({ kind: 'suspended' });\n } else if (!isSuspended && this.#state.kind === 'suspended') {\n this.#setState({ kind: 'running' });\n }\n }\n }\n\n // ---------------------------------------------------------------------\n // SCHEMA_READ\n // ---------------------------------------------------------------------\n\n #startSchemaRead(a: AnnounceMsg): void {\n const progress: SchemaReadProgress = {\n expectedTotal: a.blobLen,\n acc: new SchemaAccumulator(a.blobLen),\n inflightSeq: 0,\n inflightLen: 0,\n retriesLeft: this.#schemaReadRetries,\n inflightDeadlineMs: 0,\n };\n this.#schemaRead = progress;\n this.#setState({ kind: 'schema-reading', received: 0, total: a.blobLen });\n this.#issueSchemaReadChunk(progress, false);\n }\n\n #issueSchemaReadChunk(p: SchemaReadProgress, retry: boolean): void {\n const remaining = Math.max(0, p.expectedTotal - p.acc.length);\n if (remaining === 0) return;\n const len = Math.min(remaining, this.#schemaChunkSize);\n const seq = retry ? p.inflightSeq : this.#seq.next();\n p.inflightSeq = seq;\n p.inflightLen = len;\n p.inflightDeadlineMs = this.#now() + this.#ackTimeoutMs;\n void this.#transport\n .send(encodeSchemaRead(this.nodeId, p.acc.length, len, seq))\n .catch((e: unknown) => this.#error(e));\n }\n\n #onSchemaReadStall(): void {\n const p = this.#schemaRead;\n if (!p) return;\n if (p.retriesLeft <= 0) {\n this.#error(new Error(`schema-read stalled (offset ${p.acc.length} of ${p.expectedTotal})`));\n this.#schemaRead = null;\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n p.retriesLeft -= 1;\n this.#issueSchemaReadChunk(p, true);\n }\n\n #handleSchemaData(seq: number, data: Uint8Array): void {\n const p = this.#schemaRead;\n if (!p) return;\n const m = decodeSchemaData(data);\n if (!m) {\n this.#error(new Error('malformed SCHEMA_DATA'));\n return;\n }\n if (m.offset !== p.acc.length) return; // out-of-order, drop\n const took = p.acc.append(m, p.inflightLen);\n if (took === 0) return;\n p.retriesLeft = this.#schemaReadRetries;\n if (!p.acc.complete) {\n this.#setState({ kind: 'schema-reading', received: p.acc.length, total: p.expectedTotal });\n this.#issueSchemaReadChunk(p, false);\n return;\n }\n const blob = p.acc.bytes();\n this.#schemaRead = null;\n void this.#finishSchemaRead(blob);\n void seq;\n }\n\n async #finishSchemaRead(blob: Uint8Array): Promise<void> {\n const a = this.#announce;\n if (!a) return;\n // Hash mismatch indicates a torn transfer / mid-flight reboot.\n let actualHash: bigint;\n try {\n actualHash = await schemaHashPrefix(blob);\n } catch (e) {\n this.#error(e);\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n if (actualHash !== a.schemaHash) {\n this.#error(\n new Error(\n `schema hash mismatch: announced ${a.schemaHash.toString(16)}, actual ${actualHash.toString(16)}`,\n ),\n );\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n let schema: NodeSchema;\n let versionAheadOfMaster: boolean;\n try {\n ({ schema, versionAheadOfMaster } = decodeSchemaWithMeta(blob));\n } catch (e) {\n this.#error(e);\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n if (versionAheadOfMaster) {\n this.#error(\n new Error(\n `node ${this.nodeId}: schema protocol_version=${schema.protocolVersion} exceeds master-known — proceeding with best-effort`,\n ),\n );\n }\n this.#blobCache.set(a.schemaHash, { blob, schema });\n await this.#beginBringUp(a, schema, blob);\n }\n\n // ---------------------------------------------------------------------\n // Bring-up: FRAME_DEFINE → START\n // ---------------------------------------------------------------------\n\n async #beginBringUp(a: AnnouncedRecord, schema: NodeSchema, blob: Uint8Array): Promise<void> {\n this.#setState({ kind: 'numbering' });\n const numbering = computeNumbering(schema, Array.from(a.instanceCounts));\n if (numbering.status !== 'ok') {\n this.#error(new Error(`numbering failed: ${numbering.status}`));\n this.#setState({ kind: 'blocked', reason: `numbering: ${numbering.status}` });\n return;\n }\n const plan: readonly FramePlan[] =\n typeof this.#framePlan === 'function'\n ? this.#framePlan(schema, numbering, { nodeId: this.nodeId })\n : this.#framePlan;\n\n // Targeted DISCOVER clears any stale frame table from a prior master.\n try {\n await this.#transport.send(encodeDiscoverTo(this.nodeId));\n } catch (e) {\n this.#error(e);\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n\n const gen = ++this.#generation;\n const stdIdToTopicIndex = new Map<number, number>();\n for (const fp of plan) {\n for (const entry of fp.entries) {\n // First entry wins when multiple topics share a frame.\n if (!stdIdToTopicIndex.has(fp.stdId)) {\n stdIdToTopicIndex.set(fp.stdId, entry.topicIndex);\n }\n }\n }\n const progress: ProvisioningProgress = {\n generation: gen,\n pendingDefines: plan.length,\n anyFailure: false,\n firstNakReason: 0,\n plan,\n stdIdToTopicIndex,\n };\n this.#provisioning = progress;\n\n if (plan.length === 0) {\n // Set 'provisioning' before START so a DISCOVER-echo ANNOUNCE hits the\n // early-return in #handleAnnounce instead of restarting from 'numbering'.\n this.#provisioning.pendingDefines = 0;\n this.#setState({ kind: 'provisioning', pendingDefines: 0 });\n this.#maybeIssueStart(a, schema, blob, numbering, gen, progress);\n return;\n }\n this.#setState({ kind: 'provisioning', pendingDefines: plan.length });\n\n const deadline = this.#now() + this.#ackTimeoutMs;\n for (const fp of plan) {\n const seq = this.#seq.next();\n this.#acks.track(seq, deadline, (outcome) =>\n this.#onFrameDefineOutcome(a, schema, blob, numbering, gen, outcome),\n );\n // Schema `Direction` (M2S=0, S2M=1) is inverse of the wire `dir` byte.\n const wireDir = fp.dir === Direction.S2M ? DIR_TX_S2M : DIR_RX_M2S;\n void this.#transport\n .send(encodeFrameDefine(this.nodeId, seq, fp.stdId, fp.periodUs, wireDir, fp.entries))\n .catch((e: unknown) => this.#error(e));\n }\n }\n\n #onFrameDefineOutcome(\n a: AnnouncedRecord,\n schema: NodeSchema,\n blob: Uint8Array,\n numbering: NumberingResult,\n gen: number,\n outcome: AckOutcome,\n ): void {\n const p = this.#provisioning;\n if (!p || p.generation !== gen) return;\n if (outcome.kind !== 'acked') {\n if (!p.anyFailure) {\n p.anyFailure = true;\n p.firstNakReason = outcome.kind === 'naked' ? outcome.reason : 0;\n }\n }\n if (p.pendingDefines === 0) return;\n p.pendingDefines -= 1;\n this.#setState({ kind: 'provisioning', pendingDefines: p.pendingDefines });\n if (p.pendingDefines > 0) return;\n if (p.anyFailure) {\n this.#error(new Error(`FRAME_DEFINE failed (first NAK reason ${p.firstNakReason})`));\n this.#provisioning = null;\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n this.#maybeIssueStart(a, schema, blob, numbering, gen, p);\n }\n\n /**\n * Fire START if autoStart allows, else park in `awaiting-start` with\n * enough context that `startNow()` can resume without re-running FRAME_DEFINE.\n */\n #maybeIssueStart(\n a: AnnouncedRecord,\n schema: NodeSchema,\n blob: Uint8Array,\n numbering: NumberingResult,\n gen: number,\n progress: ProvisioningProgress,\n ): void {\n if (this.#autoStart()) {\n this.#issueStart(a, schema, blob, numbering, gen);\n return;\n }\n // Hold `#provisioning` and `#pendingStart` live — a reprovision path\n // clears both via `#reprovisionState()`.\n this.#pendingStart = { a, schema, blob, numbering, generation: gen, progress };\n this.#setState({ kind: 'awaiting-start' });\n }\n\n /**\n * Commit the deferred START. Only legal in `awaiting-start`; throws\n * elsewhere so callers spot logic bugs instead of racing a fresh ANNOUNCE.\n */\n async startNow(): Promise<void> {\n if (this.#stopped) throw new Error('NodeAgent.startNow() after stop()');\n if (this.#state.kind !== 'awaiting-start' || this.#pendingStart === null) {\n throw new Error(`NodeAgent.startNow() called in state '${this.#state.kind}'`);\n }\n const p = this.#pendingStart;\n this.#pendingStart = null;\n this.#setState({ kind: 'provisioning', pendingDefines: 0 });\n this.#issueStart(p.a, p.schema, p.blob, p.numbering, p.generation);\n }\n\n #issueStart(\n a: AnnouncedRecord,\n schema: NodeSchema,\n blob: Uint8Array,\n numbering: NumberingResult,\n gen: number,\n ): void {\n const seq = this.#seq.next();\n const deadline = this.#now() + this.#ackTimeoutMs;\n this.#acks.track(seq, deadline, (outcome) =>\n this.#onStartOutcome(a, schema, blob, numbering, gen, outcome),\n );\n void this.#transport.send(encodeStart(this.nodeId, seq)).catch((e: unknown) => this.#error(e));\n }\n\n #onStartOutcome(\n a: AnnouncedRecord,\n schema: NodeSchema,\n blob: Uint8Array,\n numbering: NumberingResult,\n gen: number,\n outcome: AckOutcome,\n ): void {\n const p = this.#provisioning;\n if (!p || p.generation !== gen) return;\n if (outcome.kind !== 'acked') {\n this.#error(\n new Error(\n `START ${outcome.kind === 'naked' ? `NAKed reason=${outcome.reason}` : 'timed out'}`,\n ),\n );\n this.#provisioning = null;\n this.#setState({ kind: 'awaiting-announce' });\n return;\n }\n const index = new SchemaIndex(schema, numbering, Array.from(a.instanceCounts));\n const client = this.#services;\n this.#snapshot = {\n nodeId: this.nodeId,\n schemaHash: a.schemaHash,\n bootId: a.bootId,\n instanceCounts: a.instanceCounts,\n blob,\n schema,\n numbering,\n framePlan: p.plan,\n stdIdToTopicIndex: p.stdIdToTopicIndex,\n services: client,\n index,\n service<Req extends Dict, Resp extends Dict>(path: string): TypedService<Req, Resp> {\n const desc = index.service(path);\n if (!desc) {\n throw new Error(`unknown service path '${path}'`);\n }\n return new TypedService<Req, Resp>(client, desc);\n },\n param<T>(path: string): TypedParam<T> {\n const desc = index.param(path);\n if (!desc) {\n throw new Error(`unknown param path '${path}'`);\n }\n return new TypedParam<T>(client, desc);\n },\n };\n this.#provisioning = null;\n this.#setState({ kind: 'running' });\n void STATE_RUNNING;\n }\n\n // ---------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------\n\n #reprovisionState(): void {\n this.#acks.clear();\n this.#services.failAll('NodeAgent reprovision');\n this.#schemaRead = null;\n this.#provisioning = null;\n this.#pendingStart = null;\n this.#snapshot = null;\n }\n\n #enterLost(reason: string): void {\n if (this.#state.kind === 'lost') return;\n this.#setState({ kind: 'lost', reason });\n }\n\n #setState(s: NodeProvisionState): void {\n this.#state = s;\n this.#onState?.(s);\n }\n\n #error(e: unknown): void {\n const err = e instanceof Error ? e : new Error(String(e));\n this.#onError?.(err);\n }\n}\n","import type { CanFrame, ITransport, Unsubscribe } from '@fibril/can-transport';\nimport {\n CHAN_CONFIG,\n CMD_ANNOUNCE,\n CMD_HEARTBEAT,\n extChannel,\n extIndex,\n extNodeId,\n NODE_ID_BROADCAST,\n} from './can-id.js';\nimport { encodeDiscover } from './config-plane.js';\nimport { DataPlaneReceiver } from './data-plane.js';\nimport { MasterHeartbeatBroadcaster } from './master-heartbeat.js';\nimport {\n type FramePlanFactory,\n NodeAgent,\n type NodeProvisionState,\n type NodeRunningSnapshot,\n} from './node-agent.js';\n\n/**\n * Multi-slave coordinator. Owns the transport, one MASTER_HEARTBEAT\n * broadcaster, and a `Map<nodeId, NodeAgent>` populated on first sight of\n * ANNOUNCE / HEARTBEAT. Broadcast DISCOVER is destructive so it is fired\n * only once at start(); use `discoverNow()` on demand.\n */\n\n/** Default policy hooks applied to every spawned NodeAgent. */\nexport interface MasterControllerOptions {\n /** Already-open()'d transport. The controller attaches its own onFrame. */\n transport: ITransport;\n /** Strategy applied to every spawned NodeAgent. Required. */\n framePlan: FramePlanFactory;\n /** MASTER_HEARTBEAT broadcast period in ms. Default 100 (§5.11). */\n heartbeatPeriodMs?: number;\n /**\n * Periodic broadcast DISCOVER period in ms. Default 0 (disabled). Each\n * firing wipes every slave's frame table — prefer `discoverNow()`.\n */\n discoverPeriodMs?: number;\n /** One broadcast DISCOVER inside `start()` to flush stale slaves. Default true. */\n initialDiscover?: boolean;\n /** Per-NodeAgent ACK timeout in ms. Default 250 (matches NodeAgent). */\n ackTimeoutMs?: number;\n /** Per-NodeAgent HEARTBEAT-loss budget in ms. Default 350. */\n heartbeatTimeoutMs?: number;\n /** Per-service-call default timeout in ms. Default `ackTimeoutMs`. */\n serviceTimeoutMs?: number;\n /** Getter (not a boolean) gating START on every spawned NodeAgent. Default `() => true`. */\n autoStart?: () => boolean;\n /** Optional clock override (tests). Default `() => Date.now()`. */\n now?: () => number;\n /** Optional non-fatal error sink. */\n onError?: (err: Error) => void;\n}\n\n/** Snapshot of one slave's state as observed by the controller. */\nexport interface ControllerSlaveSnapshot {\n readonly nodeId: number;\n readonly state: NodeProvisionState;\n /** Truthy once the slave reaches RUNNING for the first time. */\n readonly running: NodeRunningSnapshot | null;\n /** `now()` when HEARTBEAT was last seen. null if never. */\n readonly lastHeartbeatMs: number | null;\n /** boot_id observed (from ANNOUNCE or HEARTBEAT). null if neither yet. */\n readonly bootId: number | null;\n /** schema_hash observed in ANNOUNCE. null if not yet ANNOUNCEd. */\n readonly schemaHash: bigint | null;\n}\n\nexport type ControllerListener = (snapshots: readonly ControllerSlaveSnapshot[]) => void;\n\ninterface SlaveRecord {\n agent: NodeAgent;\n state: NodeProvisionState;\n lastHeartbeatMs: number | null;\n bootId: number | null;\n schemaHash: bigint | null;\n}\n\nfunction readU32Le(p: Uint8Array, off: number): number {\n return (\n ((p[off] ?? 0) |\n ((p[off + 1] ?? 0) << 8) |\n ((p[off + 2] ?? 0) << 16) |\n ((p[off + 3] ?? 0) << 24)) >>>\n 0\n );\n}\nfunction readU64Le(p: Uint8Array, off: number): bigint {\n let r = 0n;\n for (let i = 0; i < 8; i++) r |= BigInt(p[off + i] ?? 0) << BigInt(i * 8);\n return r;\n}\n\nexport class MasterController {\n readonly #transport: ITransport;\n readonly #framePlan: FramePlanFactory;\n readonly #heartbeatBroadcaster: MasterHeartbeatBroadcaster;\n readonly #dataPlane: DataPlaneReceiver;\n readonly #discoverPeriodMs: number;\n readonly #initialDiscover: boolean;\n readonly #ackTimeoutMs: number;\n readonly #heartbeatTimeoutMs: number;\n readonly #serviceTimeoutMs: number | undefined;\n readonly #autoStart: () => boolean;\n readonly #now: () => number;\n readonly #onError?: (err: Error) => void;\n\n readonly #slaves = new Map<number, SlaveRecord>();\n readonly #listeners = new Set<ControllerListener>();\n\n #unsubFrame: Unsubscribe | null = null;\n #discoverHandle: ReturnType<typeof setInterval> | null = null;\n #started = false;\n\n constructor(opts: MasterControllerOptions) {\n this.#transport = opts.transport;\n this.#framePlan = opts.framePlan;\n this.#heartbeatBroadcaster = new MasterHeartbeatBroadcaster(\n opts.transport,\n opts.heartbeatPeriodMs ?? 100,\n );\n this.#dataPlane = new DataPlaneReceiver({\n transport: opts.transport,\n ...(opts.onError !== undefined ? { onError: opts.onError } : {}),\n ...(opts.now !== undefined ? { now: opts.now } : {}),\n });\n this.#discoverPeriodMs = opts.discoverPeriodMs ?? 0;\n this.#initialDiscover = opts.initialDiscover ?? true;\n this.#ackTimeoutMs = opts.ackTimeoutMs ?? 250;\n this.#heartbeatTimeoutMs = opts.heartbeatTimeoutMs ?? 350;\n this.#serviceTimeoutMs = opts.serviceTimeoutMs;\n this.#autoStart = opts.autoStart ?? (() => true);\n this.#now = opts.now ?? (() => Date.now());\n this.#onError = opts.onError;\n }\n\n /**\n * S→M topic decoder. Auto-attaches / detaches on each slave's `running`\n * transition; subscribe via `dataPlane.onTopic` / read via `dataPlane.latest`.\n */\n get dataPlane(): DataPlaneReceiver {\n return this.#dataPlane;\n }\n\n start(): void {\n if (this.#started) return;\n this.#started = true;\n this.#heartbeatBroadcaster.start();\n this.#unsubFrame = this.#transport.onFrame((f) => this.#onFrame(f));\n if (this.#initialDiscover) {\n void this.#transport.send(encodeDiscover()).catch((e) => this.#error(e));\n }\n if (this.#discoverPeriodMs > 0) {\n this.#discoverHandle = setInterval(() => {\n void this.#transport.send(encodeDiscover()).catch((e) => this.#error(e));\n }, this.#discoverPeriodMs);\n }\n }\n\n /** Stop all internals, stop every NodeAgent, detach from the transport. */\n async stop(): Promise<void> {\n if (!this.#started) return;\n this.#started = false;\n if (this.#discoverHandle !== null) {\n clearInterval(this.#discoverHandle);\n this.#discoverHandle = null;\n }\n this.#heartbeatBroadcaster.stop();\n if (this.#unsubFrame) {\n this.#unsubFrame();\n this.#unsubFrame = null;\n }\n const stops = [...this.#slaves.values()].map((r) => r.agent.stop().catch(() => {}));\n this.#slaves.clear();\n this.#dataPlane.dispose();\n await Promise.all(stops);\n this.#emit();\n }\n\n /** Snapshot of all known slaves. Stable identity per call. */\n snapshots(): ControllerSlaveSnapshot[] {\n return [...this.#slaves.values()]\n .map((r) => ({\n nodeId: r.agent.nodeId,\n state: r.state,\n running: r.agent.snapshot,\n lastHeartbeatMs: r.lastHeartbeatMs,\n bootId: r.bootId,\n schemaHash: r.schemaHash,\n }))\n .sort((a, b) => a.nodeId - b.nodeId);\n }\n\n /** Subscribe to slave-set / state-change updates. Fires immediately with the current snapshot, then on every change. */\n onChange(cb: ControllerListener): Unsubscribe {\n this.#listeners.add(cb);\n cb(this.snapshots());\n return () => {\n this.#listeners.delete(cb);\n };\n }\n\n /** NodeAgent for one slave, or null if not yet observed. */\n agent(nodeId: number): NodeAgent | null {\n return this.#slaves.get(nodeId)?.agent ?? null;\n }\n\n /** Ad-hoc broadcast DISCOVER. */\n async discoverNow(): Promise<void> {\n await this.#transport.send(encodeDiscover());\n }\n\n /**\n * Commit the deferred START on a slave parked in `awaiting-start`.\n * Returns `false` if the slave is unknown or not waiting; the RUNNING\n * transition arrives later via `onChange`.\n */\n async startNode(nodeId: number): Promise<boolean> {\n const rec = this.#slaves.get(nodeId);\n if (!rec) return false;\n if (rec.state.kind !== 'awaiting-start') return false;\n try {\n await rec.agent.startNow();\n return true;\n } catch (e) {\n this.#error(e);\n return false;\n }\n }\n\n /**\n * Re-run FRAME_DEFINE / START so the {@link FramePlanFactory} is consulted\n * again (e.g. after a UI-driven field-tx-enable change). Returns `false`\n * if unknown / never ANNOUNCEd; resolves once bring-up is kicked off, not\n * when RUNNING is reached — listen via {@link onChange}.\n */\n async reprovision(nodeId: number): Promise<boolean> {\n const rec = this.#slaves.get(nodeId);\n if (!rec) return false;\n try {\n await rec.agent.reprovision();\n return true;\n } catch (e) {\n this.#error(e);\n return false;\n }\n }\n\n // ---------------------------------------------------------------------\n // Frame ingress\n // ---------------------------------------------------------------------\n\n #onFrame(f: CanFrame): void {\n if (!f.extended) return;\n if (extChannel(f.id) !== CHAN_CONFIG) return;\n const nodeId = extNodeId(f.id);\n if (nodeId === 0 || nodeId === NODE_ID_BROADCAST) return; // master frames + reserved\n\n const cmd = extIndex(f.id);\n if (cmd === CMD_ANNOUNCE) {\n const rec = this.#ensureSlave(nodeId);\n if (f.data.length >= 14) {\n rec.schemaHash = readU64Le(f.data, 0);\n rec.bootId = f.data[9] ?? rec.bootId ?? null;\n void readU32Le;\n }\n this.#emit();\n return;\n }\n if (cmd === CMD_HEARTBEAT) {\n const rec = this.#ensureSlave(nodeId);\n rec.lastHeartbeatMs = this.#now();\n if (f.data.length >= 1) {\n rec.bootId = f.data[0] ?? rec.bootId ?? null;\n }\n this.#emit();\n }\n }\n\n #ensureSlave(nodeId: number): SlaveRecord {\n let rec = this.#slaves.get(nodeId);\n if (rec) return rec;\n const agent = new NodeAgent({\n nodeId,\n transport: this.#transport,\n framePlan: this.#framePlan,\n ackTimeoutMs: this.#ackTimeoutMs,\n heartbeatTimeoutMs: this.#heartbeatTimeoutMs,\n ...(this.#serviceTimeoutMs !== undefined ? { serviceTimeoutMs: this.#serviceTimeoutMs } : {}),\n autoStart: this.#autoStart,\n now: this.#now,\n onState: (s) => {\n const r = this.#slaves.get(nodeId);\n if (!r) return;\n r.state = s;\n if (s.kind === 'running' && r.agent.snapshot !== null) {\n try {\n this.#dataPlane.attachSlave(nodeId, r.agent.snapshot.framePlan, r.agent.snapshot.index);\n } catch (e) {\n this.#error(e);\n }\n } else {\n this.#dataPlane.detachSlave(nodeId);\n }\n this.#emit();\n },\n onError: (e) => this.#error(e),\n });\n rec = {\n agent,\n state: { kind: 'idle' },\n lastHeartbeatMs: null,\n bootId: null,\n schemaHash: null,\n };\n this.#slaves.set(nodeId, rec);\n void agent.start();\n this.#emit();\n return rec;\n }\n\n #emit(): void {\n const snap = this.snapshots();\n for (const cb of this.#listeners) {\n try {\n cb(snap);\n } catch (e) {\n this.#error(e);\n }\n }\n }\n\n #error(e: unknown): void {\n if (!this.#onError) return;\n this.#onError(e instanceof Error ? e : new Error(String(e)));\n }\n}\n"],"mappings":"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"}