@naeemo/capnp 0.5.2 → 0.7.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["net","net","RpcConnection","SchemaNodeType","SchemaNodeType","SchemaFormat","SchemaNodeType","deserializeSchemaRequest","serializeSchemaResponse"],"sources":["../src/core/pointer.ts","../src/core/segment.ts","../src/core/message-builder.ts","../src/core/list.ts","../src/core/message-reader.ts","../src/core/union.ts","../src/rpc/message-serializer.ts","../src/rpc/websocket-transport.ts","../src/rpc/tcp-transport.ts","../src/rpc/ezrpc-transport.ts","../src/rpc/capability-client.ts","../src/rpc/sturdyrefs.ts","../src/rpc/performance.ts","../src/rpc/connection-manager.ts","../src/rpc/level3-handlers.ts","../src/rpc/level4-types.ts","../src/rpc/level4-handlers.ts","../src/rpc/stream.ts","../src/rpc/bulk.ts","../src/rpc/realtime.ts","../src/rpc/stream-manager.ts","../src/rpc/streaming-connection.ts","../src/rpc/dynamic-reader.ts","../src/rpc/dynamic-writer.ts","../src/rpc/schema-capability.ts"],"sourcesContent":["/**\n * Cap'n Proto 指针编解码\n * 纯 TypeScript 实现\n */\n\nexport enum PointerTag {\n STRUCT = 0,\n LIST = 1,\n FAR = 2,\n OTHER = 3,\n}\n\nexport enum ElementSize {\n VOID = 0,\n BIT = 1,\n BYTE = 2,\n TWO_BYTES = 3,\n FOUR_BYTES = 4,\n EIGHT_BYTES = 5,\n POINTER = 6,\n COMPOSITE = 7,\n INLINE_COMPOSITE = 7, // Alias for COMPOSITE\n}\n\nexport interface StructPointer {\n tag: PointerTag.STRUCT;\n offset: number; // 字偏移(有符号)\n dataWords: number; // 数据段字数\n pointerCount: number; // 指针段字数\n}\n\nexport interface ListPointer {\n tag: PointerTag.LIST;\n offset: number;\n elementSize: ElementSize;\n elementCount: number;\n}\n\nexport interface FarPointer {\n tag: PointerTag.FAR;\n doubleFar: boolean;\n targetSegment: number;\n targetOffset: number;\n}\n\nexport type Pointer = StructPointer | ListPointer | FarPointer | { tag: PointerTag.OTHER };\n\n/**\n * 解码指针(64位)\n */\nexport function decodePointer(ptr: bigint): Pointer {\n const tag = Number(ptr & BigInt(3)) as PointerTag;\n\n switch (tag) {\n case PointerTag.STRUCT: {\n const offset = Number(ptr >> BigInt(2)) & 0x3fffffff;\n const signedOffset = offset >= 0x20000000 ? offset - 0x40000000 : offset;\n const dataWords = Number((ptr >> BigInt(32)) & BigInt(0xffff));\n const pointerCount = Number((ptr >> BigInt(48)) & BigInt(0xffff));\n return { tag, offset: signedOffset, dataWords, pointerCount };\n }\n\n case PointerTag.LIST: {\n const offset = Number(ptr >> BigInt(2)) & 0x3fffffff;\n const signedOffset = offset >= 0x20000000 ? offset - 0x40000000 : offset;\n const elementSize = Number((ptr >> BigInt(32)) & BigInt(7)) as ElementSize;\n const elementCount = Number((ptr >> BigInt(35)) & BigInt(0x1fffffff));\n return { tag, offset: signedOffset, elementSize, elementCount };\n }\n\n case PointerTag.FAR: {\n const doubleFar = Boolean((ptr >> BigInt(2)) & BigInt(1));\n const targetOffset = Number((ptr >> BigInt(3)) & BigInt(0x1fffffff));\n const targetSegment = Number((ptr >> BigInt(32)) & BigInt(0xffffffff));\n return { tag, doubleFar, targetSegment, targetOffset };\n }\n\n default:\n return { tag: PointerTag.OTHER };\n }\n}\n\n/**\n * 编码 Struct 指针\n */\nexport function encodeStructPointer(\n offset: number,\n dataWords: number,\n pointerCount: number\n): bigint {\n const offsetBits = BigInt(offset < 0 ? offset + 0x40000000 : offset) & BigInt(0x3fffffff);\n return (\n (offsetBits << BigInt(2)) |\n (BigInt(dataWords) << BigInt(32)) |\n (BigInt(pointerCount) << BigInt(48))\n );\n}\n\n/**\n * 编码 List 指针\n */\nexport function encodeListPointer(\n offset: number,\n elementSize: ElementSize,\n elementCount: number\n): bigint {\n const offsetBits = BigInt(offset < 0 ? offset + 0x40000000 : offset) & BigInt(0x3fffffff);\n return (\n (offsetBits << BigInt(2)) |\n BigInt(1) | // LIST tag\n (BigInt(elementSize) << BigInt(32)) |\n (BigInt(elementCount) << BigInt(35))\n );\n}\n\n/**\n * 编码 Far 指针\n */\nexport function encodeFarPointer(segment: number, offset: number, doubleFar = false): bigint {\n const offsetBits = BigInt(offset) & BigInt(0x1fffffff);\n const segmentBits = BigInt(segment) & BigInt(0xffffffff);\n\n return (\n (segmentBits << BigInt(32)) |\n (offsetBits << BigInt(3)) |\n (doubleFar ? BigInt(1) << BigInt(2) : BigInt(0)) |\n BigInt(2)\n ); // FAR tag\n}\n","/**\n * Cap'n Proto Segment 管理\n * 纯 TypeScript 实现\n */\n\nexport const WORD_SIZE = 8;\n\nexport class Segment {\n private buffer: ArrayBuffer;\n private view: DataView;\n private _size: number; // 当前已使用字节数\n\n constructor(initialCapacity = 1024) {\n this.buffer = new ArrayBuffer(initialCapacity);\n this.view = new DataView(this.buffer);\n this._size = 0;\n }\n\n /**\n * 从现有 buffer 创建(用于读取)\n */\n static fromBuffer(buffer: ArrayBuffer): Segment {\n const seg = new Segment(0);\n seg.buffer = buffer;\n seg.view = new DataView(buffer);\n seg._size = buffer.byteLength;\n return seg;\n }\n\n /**\n * 确保容量足够\n */\n private ensureCapacity(minBytes: number): void {\n if (this.buffer.byteLength >= minBytes) return;\n\n // 双倍扩展\n let newCapacity = this.buffer.byteLength * 2;\n while (newCapacity < minBytes) {\n newCapacity *= 2;\n }\n\n const newBuffer = new ArrayBuffer(newCapacity);\n new Uint8Array(newBuffer).set(new Uint8Array(this.buffer, 0, this._size));\n this.buffer = newBuffer;\n this.view = new DataView(newBuffer);\n }\n\n /**\n * 分配空间,返回字偏移\n */\n allocate(words: number): number {\n const bytes = words * WORD_SIZE;\n const offset = this._size;\n this.ensureCapacity(offset + bytes);\n this._size = offset + bytes;\n return offset / WORD_SIZE;\n }\n\n /**\n * 获取字(64位)\n */\n getWord(wordOffset: number): bigint {\n const byteOffset = wordOffset * WORD_SIZE;\n if (byteOffset + 8 > this._size) {\n throw new Error(\n `Offset ${wordOffset} is outside the bounds of the segment (${this.wordCount} words)`\n );\n }\n const low = BigInt(this.view.getUint32(byteOffset, true));\n const high = BigInt(this.view.getUint32(byteOffset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 设置字(64位)\n */\n setWord(wordOffset: number, value: bigint): void {\n const byteOffset = wordOffset * WORD_SIZE;\n if (byteOffset + 8 > this.buffer.byteLength) {\n throw new Error(`Offset ${wordOffset} is outside the bounds of the segment`);\n }\n this.view.setUint32(byteOffset, Number(value & BigInt(0xffffffff)), true);\n this.view.setUint32(byteOffset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 获取原始 buffer(只读到 _size)\n */\n asUint8Array(): Uint8Array {\n return new Uint8Array(this.buffer, 0, this._size);\n }\n\n /**\n * 获取底层 ArrayBuffer\n */\n getArrayBuffer(): ArrayBuffer {\n return this.buffer;\n }\n\n /**\n * 获取字数量\n */\n get wordCount(): number {\n return this._size / WORD_SIZE;\n }\n\n /**\n * 获取字节数量\n */\n get byteLength(): number {\n return this._size;\n }\n\n /**\n * 获取 DataView\n */\n get dataView(): DataView {\n return this.view;\n }\n}\n","/**\n * Cap'n Proto MessageBuilder\n * 纯 TypeScript 实现\n */\n\nimport { ListBuilder } from './list.js';\nimport { ElementSize, PointerTag, encodeListPointer, encodeStructPointer } from './pointer.js';\nimport { Segment, WORD_SIZE } from './segment.js';\n\nexport class MessageBuilder {\n private segment: Segment;\n private rootSet = false;\n\n constructor() {\n // 预留消息头空间(假设单段)\n this.segment = new Segment(1024);\n // 预留 8 字节给段大小\n this.segment.allocate(1);\n }\n\n /**\n * 初始化根结构\n */\n initRoot(dataWords: number, pointerCount: number): StructBuilder {\n if (this.rootSet) {\n throw new Error('Root already initialized');\n }\n\n // 分配根结构空间\n const size = dataWords + pointerCount;\n const structOffset = this.segment.allocate(size);\n\n // 在位置 0 写入根指针\n const rootPtr = encodeStructPointer(structOffset - 1, dataWords, pointerCount);\n this.segment.setWord(0, rootPtr);\n\n this.rootSet = true;\n\n return new StructBuilder(this, 0, structOffset, dataWords, pointerCount);\n }\n\n /**\n * 序列化为 ArrayBuffer\n */\n toArrayBuffer(): ArrayBuffer {\n const segmentData = this.segment.asUint8Array();\n const wordCount = this.segment.wordCount;\n\n // 构建消息头\n // 第一个字:段数量-1(低32位)和第一段大小(高32位)\n const header = new ArrayBuffer(8);\n const headerView = new DataView(header);\n headerView.setUint32(0, 0, true); // 段数量-1 = 0(单段)\n headerView.setUint32(4, wordCount, true); // 第一段大小\n\n // 合并头和数据\n const result = new Uint8Array(8 + segmentData.byteLength);\n result.set(new Uint8Array(header), 0);\n result.set(segmentData, 8);\n\n return result.buffer;\n }\n\n /**\n * 获取段(内部使用)\n */\n getSegment(): Segment {\n return this.segment;\n }\n}\n\n/**\n * 结构构建器\n */\nexport class StructBuilder {\n constructor(\n private message: MessageBuilder,\n private segmentIndex: number,\n private wordOffset: number,\n private dataWords: number,\n private pointerCount: number\n ) {}\n\n /**\n * 设置 bool 字段\n */\n setBool(bitOffset: number, value: boolean): void {\n const byteOffset = Math.floor(bitOffset / 8);\n const bitInByte = bitOffset % 8;\n const segment = this.message.getSegment();\n const view = segment.dataView;\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n\n const current = view.getUint8(offset);\n const newValue = value ? current | (1 << bitInByte) : current & ~(1 << bitInByte);\n view.setUint8(offset, newValue);\n }\n\n /**\n * 设置 int8 字段\n */\n setInt8(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt8(this.wordOffset * WORD_SIZE + byteOffset, value);\n }\n\n /**\n * 设置 int16 字段\n */\n setInt16(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt16(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 int32 字段\n */\n setInt32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 int64 字段\n */\n setInt64(byteOffset: number, value: bigint): void {\n const segment = this.message.getSegment();\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n segment.dataView.setUint32(offset, Number(value & BigInt(0xffffffff)), true);\n segment.dataView.setInt32(offset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 设置 uint8 字段\n */\n setUint8(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint8(this.wordOffset * WORD_SIZE + byteOffset, value);\n }\n\n /**\n * 设置 uint16 字段\n */\n setUint16(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint16(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 uint32 字段\n */\n setUint32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 uint64 字段\n */\n setUint64(byteOffset: number, value: bigint): void {\n const segment = this.message.getSegment();\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n segment.dataView.setUint32(offset, Number(value & BigInt(0xffffffff)), true);\n segment.dataView.setUint32(offset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 设置 float32 字段\n */\n setFloat32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setFloat32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 float64 字段\n */\n setFloat64(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setFloat64(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 获取 uint16 字段(用于 UnionBuilder 读取 tag)\n */\n getUint16(byteOffset: number): number {\n const segment = this.message.getSegment();\n return segment.dataView.getUint16(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 设置文本字段\n */\n setText(pointerIndex: number, value: string): void {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 编码文本\n const bytes = new TextEncoder().encode(`${value}\\0`);\n const wordCount = Math.ceil(bytes.length / WORD_SIZE);\n const listOffset = segment.allocate(wordCount);\n\n // 写入文本数据\n new Uint8Array(segment.dataView.buffer, listOffset * WORD_SIZE, bytes.length).set(bytes);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, ElementSize.BYTE, bytes.length);\n segment.setWord(ptrOffset, ptr);\n }\n\n /**\n * 初始化嵌套结构\n */\n initStruct(pointerIndex: number, dataWords: number, pointerCount: number): StructBuilder {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 分配结构空间\n const size = dataWords + pointerCount;\n const structOffset = segment.allocate(size);\n\n // 写入指针\n const ptr = encodeStructPointer(structOffset - ptrOffset - 1, dataWords, pointerCount);\n segment.setWord(ptrOffset, ptr);\n\n return new StructBuilder(this.message, 0, structOffset, dataWords, pointerCount);\n }\n\n /**\n * 初始化列表\n */\n initList<T>(\n pointerIndex: number,\n elementSize: ElementSize,\n elementCount: number,\n structSize?: { dataWords: number; pointerCount: number }\n ): ListBuilder<T> {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 计算列表大小\n let elementWords = 1;\n if (elementSize === ElementSize.BYTE) elementWords = 1;\n else if (elementSize === ElementSize.TWO_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.FOUR_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.EIGHT_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.COMPOSITE && structSize) {\n elementWords = structSize.dataWords + structSize.pointerCount;\n }\n\n const totalWords = elementWords * elementCount;\n const listOffset = segment.allocate(totalWords);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, elementSize, elementCount);\n segment.setWord(ptrOffset, ptr);\n\n return new ListBuilder<T>(this.message, elementSize, elementCount, structSize, listOffset);\n }\n}\n","/**\n * Cap'n Proto List 实现\n * 纯 TypeScript\n */\n\nimport { type MessageBuilder, StructBuilder } from './message-builder.js';\nimport { type MessageReader, StructReader } from './message-reader.js';\nimport { ElementSize, type ListPointer, PointerTag, decodePointer } from './pointer.js';\nimport { type Segment, WORD_SIZE } from './segment.js';\n\n/**\n * ListReader - 读取列表\n */\nexport class ListReader<T> {\n private segment: Segment;\n private startOffset: number; // 字偏移\n private segmentIndex: number;\n\n constructor(\n private message: MessageReader,\n segmentIndex: number,\n private elementSize: ElementSize,\n private elementCount: number,\n private structSize: { dataWords: number; pointerCount: number } | undefined,\n wordOffset: number\n ) {\n this.segmentIndex = segmentIndex;\n this.segment = message.getSegment(segmentIndex)!;\n this.startOffset = wordOffset;\n }\n\n /**\n * 列表长度\n */\n get length(): number {\n return this.elementCount;\n }\n\n /**\n * 获取元素(基础类型)\n */\n getPrimitive(index: number): number | bigint {\n if (index < 0 || index >= this.elementCount) {\n throw new RangeError('Index out of bounds');\n }\n\n switch (this.elementSize) {\n case ElementSize.BIT: {\n const byteOffset = Math.floor(index / 8);\n const bitInByte = index % 8;\n const byte = this.segment.dataView.getUint8(this.startOffset * WORD_SIZE + byteOffset);\n return (byte & (1 << bitInByte)) !== 0 ? 1 : 0;\n }\n\n case ElementSize.BYTE:\n return this.segment.dataView.getUint8(this.startOffset * WORD_SIZE + index);\n\n case ElementSize.TWO_BYTES:\n return this.segment.dataView.getUint16(this.startOffset * WORD_SIZE + index * 2, true);\n\n case ElementSize.FOUR_BYTES:\n return this.segment.dataView.getUint32(this.startOffset * WORD_SIZE + index * 4, true);\n\n case ElementSize.EIGHT_BYTES: {\n const offset = this.startOffset * WORD_SIZE + index * 8;\n const low = BigInt(this.segment.dataView.getUint32(offset, true));\n const high = BigInt(this.segment.dataView.getUint32(offset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n default:\n throw new Error(`Unsupported element size: ${this.elementSize}`);\n }\n }\n\n /**\n * 获取结构元素\n */\n getStruct(index: number): StructReader {\n if (!this.structSize) {\n throw new Error('Not a struct list');\n }\n\n const { dataWords, pointerCount } = this.structSize;\n const size = dataWords + pointerCount;\n const offset = this.startOffset + index * size;\n\n return new StructReader(this.message, this.segmentIndex, offset, dataWords, pointerCount);\n }\n\n /**\n * 迭代器\n */\n *[Symbol.iterator](): Iterator<T> {\n for (let i = 0; i < this.elementCount; i++) {\n yield this.getPrimitive(i) as T;\n }\n }\n}\n\n/**\n * ListBuilder - 构建列表\n */\nexport class ListBuilder<_T> {\n private segment: Segment;\n private startOffset: number;\n\n constructor(\n private message: MessageBuilder,\n private elementSize: ElementSize,\n private elementCount: number,\n private structSize: { dataWords: number; pointerCount: number } | undefined,\n wordOffset: number\n ) {\n this.segment = message.getSegment();\n this.startOffset = wordOffset;\n }\n\n /**\n * 列表长度\n */\n get length(): number {\n return this.elementCount;\n }\n\n /**\n * 设置基础类型元素\n */\n setPrimitive(index: number, value: number | bigint): void {\n if (index < 0 || index >= this.elementCount) {\n throw new RangeError('Index out of bounds');\n }\n\n switch (this.elementSize) {\n case ElementSize.BIT: {\n const byteOffset = Math.floor(index / 8);\n const bitInByte = index % 8;\n const offset = this.startOffset * WORD_SIZE + byteOffset;\n const current = this.segment.dataView.getUint8(offset);\n const newValue = value ? current | (1 << bitInByte) : current & ~(1 << bitInByte);\n this.segment.dataView.setUint8(offset, newValue);\n break;\n }\n\n case ElementSize.BYTE:\n this.segment.dataView.setUint8(this.startOffset * WORD_SIZE + index, Number(value));\n break;\n\n case ElementSize.TWO_BYTES:\n this.segment.dataView.setUint16(\n this.startOffset * WORD_SIZE + index * 2,\n Number(value),\n true\n );\n break;\n\n case ElementSize.FOUR_BYTES:\n this.segment.dataView.setUint32(\n this.startOffset * WORD_SIZE + index * 4,\n Number(value),\n true\n );\n break;\n\n case ElementSize.EIGHT_BYTES: {\n const offset = this.startOffset * WORD_SIZE + index * 8;\n const bigValue = value as bigint;\n this.segment.dataView.setUint32(offset, Number(bigValue & BigInt(0xffffffff)), true);\n this.segment.dataView.setUint32(offset + 4, Number(bigValue >> BigInt(32)), true);\n break;\n }\n\n default:\n throw new Error(`Unsupported element size: ${this.elementSize}`);\n }\n }\n\n /**\n * 获取结构元素(用于修改)\n */\n getStruct(index: number): StructBuilder {\n if (!this.structSize) {\n throw new Error('Not a struct list');\n }\n\n const { dataWords, pointerCount } = this.structSize;\n const size = dataWords + pointerCount;\n const offset = this.startOffset + index * size;\n\n return new StructBuilder(this.message, 0, offset, dataWords, pointerCount);\n }\n}\n","/**\n * Cap'n Proto MessageReader\n * 纯 TypeScript 实现\n */\n\nimport { ListReader } from './list.js';\nimport {\n ElementSize,\n type FarPointer,\n type ListPointer,\n PointerTag,\n type StructPointer,\n decodePointer,\n} from './pointer.js';\nimport { Segment, WORD_SIZE } from './segment.js';\n\nexport class MessageReader {\n private segments: Segment[];\n\n constructor(buffer: ArrayBuffer | Uint8Array) {\n const uint8Array = buffer instanceof ArrayBuffer ? new Uint8Array(buffer) : buffer;\n\n // 初始化空段数组(用于无效消息)\n this.segments = [];\n\n // 检查最小大小(至少需要8字节的头部)\n if (uint8Array.byteLength < 8) {\n // 消息太小,视为空消息\n return;\n }\n\n // 解析消息头\n // 第一个字:段数量-1(低32位)和第一段大小(高32位)\n const view = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength);\n const firstWordLow = view.getUint32(0, true);\n const firstWordHigh = view.getUint32(4, true);\n\n const segmentCount = (firstWordLow & 0xffffffff) + 1;\n const firstSegmentSize = firstWordHigh;\n\n let offset = 8;\n const segmentSizes: number[] = [firstSegmentSize];\n\n // 读取剩余段大小\n for (let i = 1; i < segmentCount; i++) {\n if (offset + 4 > uint8Array.byteLength) {\n // 消息过早结束,视为空消息\n this.segments = [];\n return;\n }\n segmentSizes.push(view.getUint32(offset, true));\n offset += 4;\n }\n\n // 对齐到 8 字节\n offset = (offset + 7) & ~7;\n\n // 检查是否有足够的空间容纳段表\n if (offset > uint8Array.byteLength) {\n this.segments = [];\n return;\n }\n\n // 创建段\n this.segments = [];\n for (const size of segmentSizes) {\n if (offset + size * WORD_SIZE > uint8Array.byteLength) {\n // 段数据不足,截断或视为空消息\n // 官方实现:返回已读取的部分\n break;\n }\n const segmentBuffer = uint8Array.slice(offset, offset + size * WORD_SIZE);\n this.segments.push(Segment.fromBuffer(segmentBuffer.buffer));\n offset += size * WORD_SIZE;\n }\n }\n\n /**\n * 获取根结构\n */\n getRoot(_dataWords: number, _pointerCount: number): StructReader {\n // root 指针在位置 0,解析它找到实际数据位置\n const segment = this.segments[0];\n const ptr = decodePointer(segment.getWord(0));\n\n if (ptr.tag === PointerTag.STRUCT) {\n const structPtr = ptr as StructPointer;\n const dataOffset = 1 + structPtr.offset; // 跳过指针本身\n return new StructReader(this, 0, dataOffset, structPtr.dataWords, structPtr.pointerCount);\n }\n\n if (ptr.tag === PointerTag.FAR) {\n // Far pointer: 指向另一个 segment 中的 landing pad\n const farPtr = ptr as FarPointer;\n const targetSegment = this.getSegment(farPtr.targetSegment);\n if (!targetSegment) {\n throw new Error(`Far pointer references non-existent segment ${farPtr.targetSegment}`);\n }\n\n if (farPtr.doubleFar) {\n // Double-far: landing pad 本身也是一个 far 指针\n // landing pad 位置: targetOffset 指向的位置\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.FAR) {\n throw new Error('Double-far landing pad is not a far pointer');\n }\n const innerFarPtr = landingPadPtr as FarPointer;\n const finalSegment = this.getSegment(innerFarPtr.targetSegment);\n if (!finalSegment) {\n throw new Error(\n `Double-far references non-existent segment ${innerFarPtr.targetSegment}`\n );\n }\n // 实际的 struct 指针在 innerFarPtr.targetOffset\n const structPtr = decodePointer(\n finalSegment.getWord(innerFarPtr.targetOffset)\n ) as StructPointer;\n const dataOffset = innerFarPtr.targetOffset + 1 + structPtr.offset;\n return new StructReader(\n this,\n innerFarPtr.targetSegment,\n dataOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n // Single-far: landing pad 是实际的 struct 指针\n const structPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset)) as StructPointer;\n const dataOffset = farPtr.targetOffset + 1 + structPtr.offset;\n return new StructReader(\n this,\n farPtr.targetSegment,\n dataOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n\n throw new Error(`Root pointer is not a struct or far pointer: ${ptr.tag}`);\n }\n\n /**\n * 获取段\n */\n getSegment(index: number): Segment | undefined {\n return this.segments[index];\n }\n\n /**\n * 解析指针,处理 far pointer 间接寻址\n * 返回 { segmentIndex, wordOffset, pointer },其中 pointer 是实际的 struct/list 指针\n */\n resolvePointer(\n segmentIndex: number,\n wordOffset: number\n ): { segmentIndex: number; wordOffset: number; pointer: StructPointer | ListPointer } | null {\n const segment = this.getSegment(segmentIndex);\n if (!segment) return null;\n\n const ptrValue = segment.getWord(wordOffset);\n if (ptrValue === 0n) return null;\n\n const ptr = decodePointer(ptrValue);\n\n if (ptr.tag === PointerTag.STRUCT || ptr.tag === PointerTag.LIST) {\n // 直接指针,计算目标偏移\n const targetOffset = wordOffset + 1 + ptr.offset;\n return {\n segmentIndex,\n wordOffset: targetOffset,\n pointer: ptr as StructPointer | ListPointer,\n };\n }\n\n if (ptr.tag === PointerTag.FAR) {\n const farPtr = ptr as FarPointer;\n const targetSegment = this.getSegment(farPtr.targetSegment);\n if (!targetSegment) return null;\n\n if (farPtr.doubleFar) {\n // Double-far: landing pad 指向另一个 far 指针\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.FAR) return null;\n const innerFarPtr = landingPadPtr as FarPointer;\n const finalSegment = this.getSegment(innerFarPtr.targetSegment);\n if (!finalSegment) return null;\n const finalPtr = decodePointer(finalSegment.getWord(innerFarPtr.targetOffset));\n if (finalPtr.tag !== PointerTag.STRUCT && finalPtr.tag !== PointerTag.LIST) return null;\n const targetOffset = innerFarPtr.targetOffset + 1 + finalPtr.offset;\n return {\n segmentIndex: innerFarPtr.targetSegment,\n wordOffset: targetOffset,\n pointer: finalPtr as StructPointer | ListPointer,\n };\n }\n // Single-far: landing pad 是实际的指针\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.STRUCT && landingPadPtr.tag !== PointerTag.LIST)\n return null;\n const targetOffset = farPtr.targetOffset + 1 + landingPadPtr.offset;\n return {\n segmentIndex: farPtr.targetSegment,\n wordOffset: targetOffset,\n pointer: landingPadPtr as StructPointer | ListPointer,\n };\n }\n\n return null;\n }\n\n /**\n * 段数量\n */\n get segmentCount(): number {\n return this.segments.length;\n }\n}\n\n/**\n * 结构读取器\n */\nexport class StructReader {\n constructor(\n private message: MessageReader,\n private segmentIndex: number,\n private wordOffset: number,\n private dataWords: number,\n private pointerCount: number\n ) {}\n\n /**\n * 获取 bool 字段\n */\n getBool(bitOffset: number): boolean {\n const byteOffset = Math.floor(bitOffset / 8);\n const bitInByte = bitOffset % 8;\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查:确保在 data section 内\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset >= dataSectionEnd) {\n return false; // 越界返回默认值\n }\n\n const byte = segment.dataView.getUint8(dataOffset);\n return (byte & (1 << bitInByte)) !== 0;\n }\n\n /**\n * 获取 int8 字段\n */\n getInt8(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset >= dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getInt8(dataOffset);\n }\n\n /**\n * 获取 int16 字段\n */\n getInt16(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 2 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getInt16(dataOffset, true);\n }\n\n /**\n * 获取 int32 字段\n */\n getInt32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getInt32(dataOffset, true);\n }\n\n /**\n * 获取 int64 字段\n */\n getInt64(byteOffset: number): bigint {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) {\n return BigInt(0);\n }\n\n const low = BigInt(segment.dataView.getUint32(dataOffset, true));\n const high = BigInt(segment.dataView.getInt32(dataOffset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 获取 uint8 字段\n */\n getUint8(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset >= dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getUint8(dataOffset);\n }\n\n /**\n * 获取 uint16 字段\n */\n getUint16(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 2 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getUint16(dataOffset, true);\n }\n\n /**\n * 获取 uint32 字段\n */\n getUint32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getUint32(dataOffset, true);\n }\n\n /**\n * 获取 uint64 字段\n */\n getUint64(byteOffset: number): bigint {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) {\n return BigInt(0);\n }\n\n const low = BigInt(segment.dataView.getUint32(dataOffset, true));\n const high = BigInt(segment.dataView.getUint32(dataOffset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 获取 float32 字段\n */\n getFloat32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getFloat32(dataOffset, true);\n }\n\n /**\n * 获取 float64 字段\n */\n getFloat64(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getFloat64(dataOffset, true);\n }\n\n /**\n * 获取文本字段\n */\n getText(pointerIndex: number): string {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return '';\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.LIST) return '';\n\n const listPtr = pointer as ListPointer;\n const segment = this.message.getSegment(segmentIndex)!;\n\n // Text is stored as List(UInt8) with NUL terminator\n // elementCount includes the NUL terminator\n const byteLength = listPtr.elementCount > 0 ? listPtr.elementCount - 1 : 0;\n if (byteLength === 0) return '';\n\n // 读取文本字节\n const bytes = new Uint8Array(segment.dataView.buffer, wordOffset * WORD_SIZE, byteLength);\n return new TextDecoder().decode(bytes);\n }\n\n /**\n * 获取嵌套结构\n */\n getStruct(\n pointerIndex: number,\n _dataWords: number,\n _pointerCount: number\n ): StructReader | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return undefined;\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.STRUCT) return undefined;\n\n const structPtr = pointer as StructPointer;\n\n return new StructReader(\n this.message,\n segmentIndex,\n wordOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n\n /**\n * 获取列表\n */\n getList<T>(\n pointerIndex: number,\n _elementSize: ElementSize,\n structSize?: { dataWords: number; pointerCount: number }\n ): ListReader<T> | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return undefined;\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.LIST) return undefined;\n\n const listPtr = pointer as ListPointer;\n let targetOffset = wordOffset;\n let elementCount = listPtr.elementCount;\n let actualStructSize = structSize;\n const segment = this.message.getSegment(segmentIndex)!;\n\n // For INLINE_COMPOSITE lists, read the tag word\n if (listPtr.elementSize === ElementSize.COMPOSITE) {\n // 边界检查:确保有足够的空间读取 tag word\n if (targetOffset < 0 || targetOffset >= segment.wordCount) {\n return undefined;\n }\n\n try {\n const tagWord = segment.getWord(targetOffset);\n // Tag word: elementCount (32 bits) | dataWords (16 bits) | pointerCount (16 bits)\n elementCount = Number(tagWord & BigInt(0xffffffff));\n const dataWords = Number((tagWord >> BigInt(32)) & BigInt(0xffff));\n const pointerCount = Number((tagWord >> BigInt(48)) & BigInt(0xffff));\n actualStructSize = { dataWords, pointerCount };\n targetOffset += 1; // Skip tag word\n } catch {\n return undefined;\n }\n }\n\n return new ListReader<T>(\n this.message,\n segmentIndex,\n listPtr.elementSize,\n elementCount,\n actualStructSize,\n targetOffset\n );\n }\n}\n","/**\n * Cap'n Proto Union 支持\n * 纯 TypeScript 实现\n */\n\nimport { MessageBuilder, type StructBuilder } from './message-builder.js';\nimport { MessageReader, type StructReader } from './message-reader.js';\nimport { ElementSize } from './pointer.js';\n\n/**\n * UnionReader - 读取 Union 的 tag 和 variant\n */\nexport class UnionReader {\n constructor(\n private struct: StructReader,\n private tagOffset: number, // tag 的字节偏移\n private variants: Map<number, string> // tag 值 -> variant 名称\n ) {}\n\n /**\n * 获取当前激活的 variant tag\n */\n getTag(): number {\n return this.struct.getUint16(this.tagOffset);\n }\n\n /**\n * 获取当前激活的 variant 名称\n */\n getVariantName(): string | undefined {\n return this.variants.get(this.getTag());\n }\n\n /**\n * 检查是否是某个 variant\n */\n is(variantTag: number): boolean {\n return this.getTag() === variantTag;\n }\n}\n\n/**\n * UnionBuilder - 设置 Union 的 tag 和 variant\n */\nexport class UnionBuilder {\n constructor(\n private struct: StructBuilder,\n private tagOffset: number\n ) {}\n\n /**\n * 获取当前 tag\n */\n getTag(): number {\n return this.struct.getUint16(this.tagOffset);\n }\n\n /**\n * 设置 tag\n */\n setTag(tag: number): void {\n this.struct.setUint16(this.tagOffset, tag);\n }\n\n /**\n * 初始化某个 variant(自动设置 tag)\n */\n initVariant(tag: number, initFn: () => void): void {\n this.setTag(tag);\n initFn();\n }\n}\n\n/**\n * 创建 UnionReader 的工厂函数\n */\nexport function createUnionReader(\n struct: StructReader,\n tagOffset: number,\n variants: Record<number, string>\n): UnionReader {\n return new UnionReader(\n struct,\n tagOffset,\n new Map(Object.entries(variants).map(([k, v]) => [Number(k), v]))\n );\n}\n\n/**\n * 创建 UnionBuilder 的工厂函数\n */\nexport function createUnionBuilder(struct: StructBuilder, tagOffset: number): UnionBuilder {\n return new UnionBuilder(struct, tagOffset);\n}\n","/**\n * RPC Message Serialization\n *\n * Implements full serialization/deserialization of RPC messages using\n * the existing MessageBuilder/MessageReader infrastructure.\n *\n * Reference: rpc.capnp schema\n */\n\nimport { MessageBuilder, type StructBuilder } from '../core/message-builder.js';\nimport { MessageReader, type StructReader } from '../core/message-reader.js';\nimport { ElementSize } from '../core/pointer.js';\nimport type {\n Bootstrap,\n Call,\n CapDescriptor,\n Disembargo,\n Exception,\n Finish,\n MessageTarget,\n Payload,\n PromisedAnswer,\n PromisedAnswerOp,\n Provide,\n Release,\n Resolve,\n Return,\n RpcMessage,\n SendResultsTo,\n} from './rpc-types.js';\n\n// ========================================================================================\n// Constants from rpc.capnp schema\n// ========================================================================================\n\n// Message union tags\nconst MSG_UNIMPLEMENTED = 0;\nconst MSG_ABORT = 1;\nconst MSG_BOOTSTRAP = 8;\nconst MSG_CALL = 2;\nconst MSG_RETURN = 3;\nconst MSG_FINISH = 4;\nconst MSG_RESOLVE = 5;\nconst MSG_RELEASE = 6;\nconst MSG_DISEMBARGO = 13;\nconst MSG_PROVIDE = 10;\nconst MSG_ACCEPT = 11;\nconst MSG_JOIN = 12;\n\n// Return union tags\nconst RET_RESULTS = 0;\nconst RET_EXCEPTION = 1;\nconst RET_CANCELED = 2;\nconst RET_RESULTS_SENT_ELSEWHERE = 3;\nconst RET_TAKE_FROM_OTHER_QUESTION = 4;\nconst RET_ACCEPT_FROM_THIRD_PARTY = 5;\n\n// SendResultsTo union tags\nconst SEND_TO_CALLER = 0;\nconst SEND_TO_YOURSELF = 1;\nconst SEND_TO_THIRD_PARTY = 2;\n\n// MessageTarget union tags\nconst TARGET_IMPORTED_CAP = 0;\nconst TARGET_PROMISED_ANSWER = 1;\n\n// CapDescriptor union tags\nconst CAP_NONE = 0;\nconst CAP_SENDER_HOSTED = 1;\nconst CAP_SENDER_PROMISE = 2;\nconst CAP_RECEIVER_HOSTED = 3;\nconst CAP_RECEIVER_ANSWER = 4;\nconst CAP_THIRD_PARTY_HOSTED = 5;\n\n// Resolve union tags\nconst RESOLVE_CAP = 0;\nconst RESOLVE_EXCEPTION = 1;\n\n// Disembargo context union tags\nconst DISEMBARGO_SENDER_LOOPBACK = 0;\nconst DISEMBARGO_RECEIVER_LOOPBACK = 1;\nconst DISEMBARGO_ACCEPT = 2;\nconst DISEMBARGO_PROVIDE = 3;\n\n// PromisedAnswer.Op union tags\nconst OP_NOOP = 0;\nconst OP_GET_POINTER_FIELD = 1;\n\n// Exception type union tags\nconst EXC_FAILED = 0;\nconst EXC_OVERLOADED = 1;\nconst EXC_DISCONNECTED = 2;\nconst EXC_UNIMPLEMENTED = 3;\n\n// ========================================================================================\n// Serialization: RpcMessage -> Uint8Array\n// ========================================================================================\n\nexport function serializeRpcMessage(message: RpcMessage): Uint8Array {\n const builder = new MessageBuilder();\n // Message struct: 6 data words, 1 pointer\n // union + questionId/answerId/promiseId/etc + padding\n const root = builder.initRoot(6, 1);\n\n switch (message.type) {\n case 'unimplemented':\n serializeUnimplemented(root, message.message);\n break;\n case 'abort':\n serializeAbort(root, message.exception);\n break;\n case 'bootstrap':\n serializeBootstrap(root, message.bootstrap);\n break;\n case 'call':\n serializeCall(root, message.call);\n break;\n case 'return':\n serializeReturn(root, message.return);\n break;\n case 'finish':\n serializeFinish(root, message.finish);\n break;\n case 'resolve':\n serializeResolve(root, message.resolve);\n break;\n case 'release':\n serializeRelease(root, message.release);\n break;\n case 'disembargo':\n serializeDisembargo(root, message.disembargo);\n break;\n case 'provide':\n serializeProvide(root, message.provide);\n break;\n case 'accept':\n serializeAccept(root, message.accept);\n break;\n case 'join':\n serializeJoin(root, message.join);\n break;\n }\n\n return new Uint8Array(builder.toArrayBuffer());\n}\n\nfunction serializeUnimplemented(root: StructBuilder, message: RpcMessage): void {\n // Set union tag\n root.setUint16(0, MSG_UNIMPLEMENTED);\n // Serialize nested message in pointer 0\n const _nestedData = serializeRpcMessage(message);\n const nestedBuilder = root.initStruct(0, 0, 1);\n // Copy nested data into the struct's content pointer\n // For simplicity, we store the serialized message as data bytes\n // In a full implementation, we'd properly embed the message structure\n const _contentPtr = nestedBuilder.initStruct(0, 0, 0);\n // Store length and data\n // This is a simplified approach - proper implementation would parse the nested message\n}\n\nfunction serializeAbort(root: StructBuilder, exception: Exception): void {\n root.setUint16(0, MSG_ABORT);\n serializeException(root, 0, exception);\n}\n\nfunction serializeBootstrap(root: StructBuilder, bootstrap: Bootstrap): void {\n root.setUint16(0, MSG_BOOTSTRAP);\n root.setUint32(8, bootstrap.questionId);\n // deprecatedObjectId is deprecated, skip\n}\n\nfunction serializeCall(root: StructBuilder, call: Call): void {\n root.setUint16(0, MSG_CALL);\n root.setUint32(8, call.questionId);\n root.setUint64(16, call.interfaceId);\n root.setUint16(24, call.methodId);\n root.setBool(208, call.allowThirdPartyTailCall); // bit 208 = word 26, bit 0\n root.setBool(209, call.noPromisePipelining); // bit 209\n root.setBool(210, call.onlyPromisePipeline); // bit 210\n\n // Serialize target in pointer 0\n serializeMessageTarget(root.initStruct(0, 2, 1), call.target);\n\n // Serialize params in pointer 1\n serializePayload(root.initStruct(1, 2, 2), call.params);\n\n // Serialize sendResultsTo in pointer 2\n serializeSendResultsTo(root.initStruct(2, 2, 1), call.sendResultsTo);\n}\n\nfunction serializeReturn(root: StructBuilder, ret: Return): void {\n root.setUint16(0, MSG_RETURN);\n root.setUint32(8, ret.answerId);\n root.setBool(192, ret.releaseParamCaps); // bit 192 = word 24, bit 0\n root.setBool(193, ret.noFinishNeeded); // bit 193\n\n // Serialize result based on type\n switch (ret.result.type) {\n case 'results':\n root.setUint16(2, RET_RESULTS);\n serializePayload(root.initStruct(0, 2, 2), ret.result.payload);\n break;\n case 'exception':\n root.setUint16(2, RET_EXCEPTION);\n serializeException(root, 0, ret.result.exception);\n break;\n case 'canceled':\n root.setUint16(2, RET_CANCELED);\n break;\n case 'resultsSentElsewhere':\n root.setUint16(2, RET_RESULTS_SENT_ELSEWHERE);\n break;\n case 'takeFromOtherQuestion':\n root.setUint16(2, RET_TAKE_FROM_OTHER_QUESTION);\n root.setUint32(12, ret.result.questionId);\n break;\n case 'acceptFromThirdParty':\n root.setUint16(2, RET_ACCEPT_FROM_THIRD_PARTY);\n // ThirdPartyCapId in pointer 0\n break;\n }\n}\n\nfunction serializeFinish(root: StructBuilder, finish: Finish): void {\n root.setUint16(0, MSG_FINISH);\n root.setUint32(8, finish.questionId);\n root.setBool(192, finish.releaseResultCaps); // bit 192\n root.setBool(193, finish.requireEarlyCancellationWorkaround); // bit 193\n}\n\nfunction serializeResolve(root: StructBuilder, resolve: Resolve): void {\n root.setUint16(0, MSG_RESOLVE);\n root.setUint32(8, resolve.promiseId);\n\n switch (resolve.resolution.type) {\n case 'cap':\n root.setUint16(2, RESOLVE_CAP);\n serializeCapDescriptor(root.initStruct(0, 2, 1), resolve.resolution.cap);\n break;\n case 'exception':\n root.setUint16(2, RESOLVE_EXCEPTION);\n serializeException(root, 0, resolve.resolution.exception);\n break;\n }\n}\n\nfunction serializeRelease(root: StructBuilder, release: Release): void {\n root.setUint16(0, MSG_RELEASE);\n root.setUint32(8, release.id);\n root.setUint32(12, release.referenceCount);\n}\n\nfunction serializeDisembargo(root: StructBuilder, disembargo: Disembargo): void {\n root.setUint16(0, MSG_DISEMBARGO);\n serializeMessageTarget(root.initStruct(0, 2, 1), disembargo.target);\n\n switch (disembargo.context.type) {\n case 'senderLoopback':\n root.setUint16(2, DISEMBARGO_SENDER_LOOPBACK);\n root.setUint32(12, disembargo.context.embargoId);\n break;\n case 'receiverLoopback':\n root.setUint16(2, DISEMBARGO_RECEIVER_LOOPBACK);\n root.setUint32(12, disembargo.context.embargoId);\n break;\n case 'accept':\n root.setUint16(2, DISEMBARGO_ACCEPT);\n break;\n case 'provide':\n root.setUint16(2, DISEMBARGO_PROVIDE);\n root.setUint32(12, disembargo.context.questionId);\n break;\n }\n}\n\nfunction serializeProvide(root: StructBuilder, provide: Provide): void {\n root.setUint16(0, MSG_PROVIDE);\n root.setUint32(8, provide.questionId);\n serializeMessageTarget(root.initStruct(0, 2, 1), provide.target);\n // RecipientId in pointer 1 - placeholder\n}\n\nfunction serializeAccept(\n _root: StructBuilder,\n _accept: { provision: { id: Uint8Array }; embargo: boolean }\n): void {\n // Level 3 - not fully implemented\n}\n\nfunction serializeJoin(\n _root: StructBuilder,\n _join: { otherCap: MessageTarget; joinId: number }\n): void {\n // Level 4 - not fully implemented\n}\n\n// ========================================================================================\n// Supporting Type Serialization\n// ========================================================================================\n\nfunction serializeMessageTarget(builder: StructBuilder, target: MessageTarget): void {\n switch (target.type) {\n case 'importedCap':\n builder.setUint16(0, TARGET_IMPORTED_CAP);\n builder.setUint32(8, target.importId);\n break;\n case 'promisedAnswer':\n builder.setUint16(0, TARGET_PROMISED_ANSWER);\n serializePromisedAnswer(builder.initStruct(0, 2, 1), target.promisedAnswer);\n break;\n }\n}\n\nfunction serializePromisedAnswer(builder: StructBuilder, promisedAnswer: PromisedAnswer): void {\n builder.setUint32(0, promisedAnswer.questionId);\n // Transform list in pointer 0\n if (promisedAnswer.transform.length > 0) {\n const listBuilder = builder.initList(\n 0,\n ElementSize.INLINE_COMPOSITE,\n promisedAnswer.transform.length,\n {\n dataWords: 2,\n pointerCount: 0,\n }\n );\n for (let i = 0; i < promisedAnswer.transform.length; i++) {\n serializePromisedAnswerOp(listBuilder.getStruct(i), promisedAnswer.transform[i]);\n }\n }\n}\n\nfunction serializePromisedAnswerOp(builder: StructBuilder, op: PromisedAnswerOp): void {\n switch (op.type) {\n case 'noop':\n builder.setUint16(0, OP_NOOP);\n break;\n case 'getPointerField':\n builder.setUint16(0, OP_GET_POINTER_FIELD);\n builder.setUint16(8, op.fieldIndex);\n break;\n }\n}\n\nfunction serializePayload(builder: StructBuilder, payload: Payload): void {\n // Content (AnyPointer) - store as data bytes in pointer 0\n if (payload.content.length > 0) {\n // For now, store raw bytes - in full implementation this would be a proper struct\n const _contentBuilder = builder.initStruct(0, Math.ceil(payload.content.length / 8), 0);\n // Copy bytes into the struct\n }\n\n // Cap table list in pointer 1\n if (payload.capTable.length > 0) {\n const listBuilder = builder.initList(1, ElementSize.EIGHT_BYTES, payload.capTable.length, {\n dataWords: 2,\n pointerCount: 1,\n });\n for (let i = 0; i < payload.capTable.length; i++) {\n serializeCapDescriptor(listBuilder.getStruct(i), payload.capTable[i]);\n }\n }\n}\n\nfunction serializeCapDescriptor(builder: StructBuilder, cap: CapDescriptor): void {\n switch (cap.type) {\n case 'none':\n builder.setUint16(0, CAP_NONE);\n break;\n case 'senderHosted':\n builder.setUint16(0, CAP_SENDER_HOSTED);\n builder.setUint32(8, cap.exportId);\n break;\n case 'senderPromise':\n builder.setUint16(0, CAP_SENDER_PROMISE);\n builder.setUint32(8, cap.exportId);\n break;\n case 'receiverHosted':\n builder.setUint16(0, CAP_RECEIVER_HOSTED);\n builder.setUint32(8, cap.importId);\n break;\n case 'receiverAnswer':\n builder.setUint16(0, CAP_RECEIVER_ANSWER);\n serializePromisedAnswer(builder.initStruct(0, 2, 1), cap.promisedAnswer);\n break;\n case 'thirdPartyHosted':\n builder.setUint16(0, CAP_THIRD_PARTY_HOSTED);\n // ThirdPartyCapId in pointer 0\n break;\n }\n}\n\nfunction serializeSendResultsTo(builder: StructBuilder, sendTo: SendResultsTo): void {\n switch (sendTo.type) {\n case 'caller':\n builder.setUint16(0, SEND_TO_CALLER);\n break;\n case 'yourself':\n builder.setUint16(0, SEND_TO_YOURSELF);\n break;\n case 'thirdParty':\n builder.setUint16(0, SEND_TO_THIRD_PARTY);\n // RecipientId in pointer 0\n break;\n }\n}\n\nfunction serializeException(\n builder: StructBuilder,\n pointerIndex: number,\n exception: Exception\n): void {\n const excBuilder = builder.initStruct(pointerIndex, 2, 1);\n excBuilder.setText(0, exception.reason);\n\n // Exception type union\n switch (exception.type) {\n case 'failed':\n excBuilder.setUint16(0, EXC_FAILED);\n break;\n case 'overloaded':\n excBuilder.setUint16(0, EXC_OVERLOADED);\n break;\n case 'disconnected':\n excBuilder.setUint16(0, EXC_DISCONNECTED);\n break;\n case 'unimplemented':\n excBuilder.setUint16(0, EXC_UNIMPLEMENTED);\n break;\n }\n}\n\n// ========================================================================================\n// Deserialization: Uint8Array -> RpcMessage\n// ========================================================================================\n\nexport function deserializeRpcMessage(data: Uint8Array): RpcMessage {\n const reader = new MessageReader(data);\n const root = reader.getRoot(6, 1);\n\n const unionTag = root.getUint16(0);\n\n switch (unionTag) {\n case MSG_UNIMPLEMENTED:\n return { type: 'unimplemented', message: deserializeUnimplemented(root) };\n case MSG_ABORT:\n return { type: 'abort', exception: deserializeException(root, 0) };\n case MSG_BOOTSTRAP:\n return { type: 'bootstrap', bootstrap: deserializeBootstrap(root) };\n case MSG_CALL:\n return { type: 'call', call: deserializeCall(root) };\n case MSG_RETURN:\n return { type: 'return', return: deserializeReturn(root) };\n case MSG_FINISH:\n return { type: 'finish', finish: deserializeFinish(root) };\n case MSG_RESOLVE:\n return { type: 'resolve', resolve: deserializeResolve(root) };\n case MSG_RELEASE:\n return { type: 'release', release: deserializeRelease(root) };\n case MSG_DISEMBARGO:\n return { type: 'disembargo', disembargo: deserializeDisembargo(root) };\n case MSG_PROVIDE:\n return { type: 'provide', provide: deserializeProvide(root) };\n case MSG_ACCEPT:\n return { type: 'accept', accept: deserializeAccept(root) };\n case MSG_JOIN:\n return { type: 'join', join: deserializeJoin(root) };\n default:\n throw new Error(`Unknown message union tag: ${unionTag}`);\n }\n}\n\nfunction deserializeUnimplemented(_root: StructReader): RpcMessage {\n // For now, return a placeholder - full implementation would deserialize nested message\n return {\n type: 'abort',\n exception: { reason: 'Unimplemented message received', type: 'unimplemented' },\n };\n}\n\nfunction deserializeBootstrap(root: StructReader): Bootstrap {\n return {\n questionId: root.getUint32(8),\n };\n}\n\nfunction deserializeCall(root: StructReader): Call {\n const targetStruct = root.getStruct(0, 2, 1);\n const paramsStruct = root.getStruct(1, 2, 2);\n const sendToStruct = root.getStruct(2, 2, 1);\n\n return {\n questionId: root.getUint32(8),\n interfaceId: root.getUint64(16),\n methodId: root.getUint16(24),\n allowThirdPartyTailCall: root.getBool(208),\n noPromisePipelining: root.getBool(209),\n onlyPromisePipeline: root.getBool(210),\n target: targetStruct\n ? deserializeMessageTarget(targetStruct)\n : { type: 'importedCap', importId: 0 },\n params: paramsStruct\n ? deserializePayload(paramsStruct)\n : { content: new Uint8Array(0), capTable: [] },\n sendResultsTo: sendToStruct ? deserializeSendResultsTo(sendToStruct) : { type: 'caller' },\n };\n}\n\nfunction deserializeReturn(root: StructReader): Return {\n const resultTag = root.getUint16(2);\n let result: Return['result'];\n\n switch (resultTag) {\n case RET_RESULTS:\n result = {\n type: 'results',\n payload: root.getStruct(0, 2, 2)\n ? deserializePayload(root.getStruct(0, 2, 2)!)\n : { content: new Uint8Array(0), capTable: [] },\n };\n break;\n case RET_EXCEPTION:\n result = { type: 'exception', exception: deserializeException(root, 0) };\n break;\n case RET_CANCELED:\n result = { type: 'canceled' };\n break;\n case RET_RESULTS_SENT_ELSEWHERE:\n result = { type: 'resultsSentElsewhere' };\n break;\n case RET_TAKE_FROM_OTHER_QUESTION:\n result = { type: 'takeFromOtherQuestion', questionId: root.getUint32(12) };\n break;\n case RET_ACCEPT_FROM_THIRD_PARTY:\n result = { type: 'acceptFromThirdParty', thirdPartyCapId: { id: new Uint8Array(0) } };\n break;\n default:\n result = { type: 'canceled' };\n }\n\n return {\n answerId: root.getUint32(8),\n releaseParamCaps: root.getBool(192),\n noFinishNeeded: root.getBool(193),\n result,\n };\n}\n\nfunction deserializeFinish(root: StructReader): Finish {\n return {\n questionId: root.getUint32(8),\n releaseResultCaps: root.getBool(192),\n requireEarlyCancellationWorkaround: root.getBool(193),\n };\n}\n\nfunction deserializeResolve(root: StructReader): Resolve {\n const resolutionTag = root.getUint16(2);\n let resolution: Resolve['resolution'];\n\n switch (resolutionTag) {\n case RESOLVE_CAP:\n resolution = {\n type: 'cap',\n cap: root.getStruct(0, 2, 1)\n ? deserializeCapDescriptor(root.getStruct(0, 2, 1)!)\n : { type: 'none' },\n };\n break;\n case RESOLVE_EXCEPTION:\n resolution = { type: 'exception', exception: deserializeException(root, 0) };\n break;\n default:\n resolution = {\n type: 'exception',\n exception: { reason: 'Unknown resolution type', type: 'failed' },\n };\n }\n\n return {\n promiseId: root.getUint32(8),\n resolution,\n };\n}\n\nfunction deserializeRelease(root: StructReader): Release {\n return {\n id: root.getUint32(8),\n referenceCount: root.getUint32(12),\n };\n}\n\nfunction deserializeDisembargo(root: StructReader): Disembargo {\n const targetStruct = root.getStruct(0, 2, 1);\n const contextTag = root.getUint16(2);\n let context: Disembargo['context'];\n\n switch (contextTag) {\n case DISEMBARGO_SENDER_LOOPBACK:\n context = { type: 'senderLoopback', embargoId: root.getUint32(12) };\n break;\n case DISEMBARGO_RECEIVER_LOOPBACK:\n context = { type: 'receiverLoopback', embargoId: root.getUint32(12) };\n break;\n case DISEMBARGO_ACCEPT:\n context = { type: 'accept' };\n break;\n case DISEMBARGO_PROVIDE:\n context = { type: 'provide', questionId: root.getUint32(12) };\n break;\n default:\n context = { type: 'accept' };\n }\n\n return {\n target: targetStruct\n ? deserializeMessageTarget(targetStruct)\n : { type: 'importedCap', importId: 0 },\n context,\n };\n}\n\nfunction deserializeProvide(root: StructReader): Provide {\n const targetStruct = root.getStruct(0, 2, 1);\n return {\n questionId: root.getUint32(8),\n target: targetStruct\n ? deserializeMessageTarget(targetStruct)\n : { type: 'importedCap', importId: 0 },\n recipient: { id: new Uint8Array(0) },\n };\n}\n\nfunction deserializeAccept(_root: StructReader): {\n questionId: number;\n provision: { id: Uint8Array };\n embargo: boolean;\n} {\n // Level 3 - placeholder\n return { questionId: 0, provision: { id: new Uint8Array(0) }, embargo: false };\n}\n\nfunction deserializeJoin(_root: StructReader): {\n questionId: number;\n target: MessageTarget;\n otherCap: MessageTarget;\n joinId: number;\n} {\n // Level 4 - placeholder\n return {\n questionId: 0,\n target: { type: 'importedCap', importId: 0 },\n otherCap: { type: 'importedCap', importId: 0 },\n joinId: 0,\n };\n}\n\n// ========================================================================================\n// Supporting Type Deserialization\n// ========================================================================================\n\nfunction deserializeMessageTarget(root: StructReader): MessageTarget {\n const tag = root.getUint16(0);\n\n switch (tag) {\n case TARGET_IMPORTED_CAP:\n return { type: 'importedCap', importId: root.getUint32(8) };\n case TARGET_PROMISED_ANSWER: {\n const promisedAnswerStruct = root.getStruct(0, 2, 1);\n return {\n type: 'promisedAnswer',\n promisedAnswer: promisedAnswerStruct\n ? deserializePromisedAnswer(promisedAnswerStruct)\n : { questionId: 0, transform: [] },\n };\n }\n default:\n return { type: 'importedCap', importId: 0 };\n }\n}\n\nfunction deserializePromisedAnswer(root: StructReader): PromisedAnswer {\n const transformList = root.getList<StructReader>(0, ElementSize.INLINE_COMPOSITE, {\n dataWords: 2,\n pointerCount: 0,\n });\n const transform: PromisedAnswerOp[] = [];\n\n if (transformList) {\n for (let i = 0; i < transformList.length; i++) {\n transform.push(deserializePromisedAnswerOp(transformList.getStruct(i)));\n }\n }\n\n return {\n questionId: root.getUint32(0),\n transform,\n };\n}\n\nfunction deserializePromisedAnswerOp(root: StructReader): PromisedAnswerOp {\n const tag = root.getUint16(0);\n\n switch (tag) {\n case OP_NOOP:\n return { type: 'noop' };\n case OP_GET_POINTER_FIELD:\n return { type: 'getPointerField', fieldIndex: root.getUint16(8) };\n default:\n return { type: 'noop' };\n }\n}\n\nfunction deserializePayload(root: StructReader): Payload {\n // Content - for now, return empty\n // In full implementation, would deserialize the AnyPointer content\n const capTableList = root.getList<StructReader>(1, ElementSize.EIGHT_BYTES, {\n dataWords: 2,\n pointerCount: 1,\n });\n const capTable: CapDescriptor[] = [];\n\n if (capTableList) {\n for (let i = 0; i < capTableList.length; i++) {\n capTable.push(deserializeCapDescriptor(capTableList.getStruct(i)));\n }\n }\n\n return {\n content: new Uint8Array(0),\n capTable,\n };\n}\n\nfunction deserializeCapDescriptor(root: StructReader): CapDescriptor {\n const tag = root.getUint16(0);\n\n switch (tag) {\n case CAP_NONE:\n return { type: 'none' };\n case CAP_SENDER_HOSTED:\n return { type: 'senderHosted', exportId: root.getUint32(8) };\n case CAP_SENDER_PROMISE:\n return { type: 'senderPromise', exportId: root.getUint32(8) };\n case CAP_RECEIVER_HOSTED:\n return { type: 'receiverHosted', importId: root.getUint32(8) };\n case CAP_RECEIVER_ANSWER: {\n const promisedAnswerStruct = root.getStruct(0, 2, 1);\n return {\n type: 'receiverAnswer',\n promisedAnswer: promisedAnswerStruct\n ? deserializePromisedAnswer(promisedAnswerStruct)\n : { questionId: 0, transform: [] },\n };\n }\n case CAP_THIRD_PARTY_HOSTED:\n return { type: 'thirdPartyHosted', thirdPartyCapId: { id: new Uint8Array(0) } };\n default:\n return { type: 'none' };\n }\n}\n\nfunction deserializeSendResultsTo(root: StructReader): SendResultsTo {\n const tag = root.getUint16(0);\n\n switch (tag) {\n case SEND_TO_CALLER:\n return { type: 'caller' };\n case SEND_TO_YOURSELF:\n return { type: 'yourself' };\n case SEND_TO_THIRD_PARTY:\n return { type: 'thirdParty', recipientId: { id: new Uint8Array(0) } };\n default:\n return { type: 'caller' };\n }\n}\n\nfunction deserializeException(root: StructReader, pointerIndex: number): Exception {\n const excStruct = root.getStruct(pointerIndex, 2, 1);\n if (!excStruct) {\n return { reason: 'Unknown error', type: 'failed' };\n }\n\n const typeTag = excStruct.getUint16(0);\n let type: Exception['type'];\n\n switch (typeTag) {\n case EXC_FAILED:\n type = 'failed';\n break;\n case EXC_OVERLOADED:\n type = 'overloaded';\n break;\n case EXC_DISCONNECTED:\n type = 'disconnected';\n break;\n case EXC_UNIMPLEMENTED:\n type = 'unimplemented';\n break;\n default:\n type = 'failed';\n }\n\n return {\n reason: excStruct.getText(0),\n type,\n };\n}\n","/**\n * WebSocket Transport Implementation\n *\n * Implements RpcTransport over WebSocket for browser and Node.js compatibility.\n */\n\nimport { deserializeRpcMessage, serializeRpcMessage } from './message-serializer.js';\nimport type { RpcMessage } from './rpc-types.js';\nimport type { RpcTransport, WebSocketTransportOptions } from './transport.js';\n\n// Message framing: length-prefixed binary messages\n// Format: [4 bytes: message length (little-endian)] [N bytes: message data]\n\nexport class WebSocketTransport implements RpcTransport {\n private ws: WebSocket | null = null;\n private messageQueue: RpcMessage[] = [];\n private receiveQueue: Array<{\n resolve: (msg: RpcMessage | null) => void;\n reject: (err: Error) => void;\n }> = [];\n private _connected = false;\n private pendingBuffer: Uint8Array | null = null;\n private pendingLength = 0;\n\n onClose?: (reason?: Error) => void;\n onError?: (error: Error) => void;\n\n constructor(\n url: string,\n private options: WebSocketTransportOptions = {}\n ) {\n this.connect(url);\n }\n\n static async connect(\n url: string,\n options?: WebSocketTransportOptions\n ): Promise<WebSocketTransport> {\n const transport = new WebSocketTransport(url, options);\n await transport.waitForConnection();\n return transport;\n }\n\n static fromWebSocket(ws: WebSocket, options?: WebSocketTransportOptions): WebSocketTransport {\n const transport = new WebSocketTransport('internal', options);\n transport.attachWebSocket(ws);\n return transport;\n }\n\n get connected(): boolean {\n return this._connected;\n }\n\n private connect(url: string): void {\n this.ws = new WebSocket(url);\n this.ws.binaryType = this.options.binaryType ?? 'arraybuffer';\n\n this.ws.onopen = () => {\n this._connected = true;\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this._connected = false;\n this.flushReceiveQueue(null);\n this.onClose?.();\n };\n\n this.ws.onerror = (_error) => {\n const err = new Error('WebSocket error');\n this.onError?.(err);\n };\n }\n\n private attachWebSocket(ws: WebSocket): void {\n this.ws = ws;\n this.ws.binaryType = this.options.binaryType ?? 'arraybuffer';\n this._connected = ws.readyState === WebSocket.OPEN;\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this._connected = false;\n this.flushReceiveQueue(null);\n this.onClose?.();\n };\n\n this.ws.onerror = (_error) => {\n const err = new Error('WebSocket error');\n this.onError?.(err);\n };\n }\n\n private waitForConnection(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this._connected) {\n resolve();\n return;\n }\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n }, this.options.connectTimeoutMs ?? 10000);\n\n const checkConnection = () => {\n if (this._connected) {\n clearTimeout(timeout);\n resolve();\n } else if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {\n clearTimeout(timeout);\n reject(new Error('Connection failed'));\n } else {\n setTimeout(checkConnection, 10);\n }\n };\n\n checkConnection();\n });\n }\n\n private handleMessage(data: ArrayBuffer | Blob): void {\n // For Phase 1, we'll implement basic message handling\n // Full implementation would parse the Cap'n Proto message\n if (data instanceof ArrayBuffer) {\n this.processBinaryMessage(new Uint8Array(data));\n } else {\n // Blob handling for browser compatibility\n const reader = new FileReader();\n reader.onload = () => {\n this.processBinaryMessage(new Uint8Array(reader.result as ArrayBuffer));\n };\n reader.readAsArrayBuffer(data);\n }\n }\n\n private processBinaryMessage(data: Uint8Array): void {\n // Length-prefixed framing\n let offset = 0;\n\n while (offset < data.length) {\n if (this.pendingBuffer === null) {\n // Start of new message\n if (offset + 4 > data.length) {\n // Not enough data for length header\n this.pendingBuffer = data.slice(offset);\n this.pendingLength = -1;\n break;\n }\n\n const length = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, true);\n offset += 4;\n\n if (offset + length > data.length) {\n // Not enough data for full message\n this.pendingBuffer = data.slice(offset - 4);\n this.pendingLength = length;\n break;\n }\n\n const messageData = data.slice(offset, offset + length);\n offset += length;\n this.handleRpcMessage(messageData);\n } else {\n // Continuation of pending message\n if (this.pendingLength === -1) {\n // Still need length header\n const needed = 4 - this.pendingBuffer.length;\n if (data.length - offset < needed) {\n this.pendingBuffer = new Uint8Array([...this.pendingBuffer, ...data.slice(offset)]);\n break;\n }\n\n const tempBuffer = new Uint8Array(this.pendingBuffer.length + needed);\n tempBuffer.set(this.pendingBuffer);\n tempBuffer.set(data.slice(offset, offset + needed), this.pendingBuffer.length);\n\n this.pendingLength = new DataView(tempBuffer.buffer, 0, 4).getUint32(0, true);\n this.pendingBuffer = null;\n offset += needed;\n } else {\n // Have length, need message body\n const needed = this.pendingLength - this.pendingBuffer.length;\n if (data.length - offset < needed) {\n this.pendingBuffer = new Uint8Array([...this.pendingBuffer, ...data.slice(offset)]);\n break;\n }\n\n const messageData = new Uint8Array(this.pendingLength);\n messageData.set(this.pendingBuffer);\n messageData.set(data.slice(offset, offset + needed), this.pendingBuffer.length);\n\n offset += needed;\n this.pendingBuffer = null;\n this.handleRpcMessage(messageData);\n }\n }\n }\n }\n\n private handleRpcMessage(data: Uint8Array): void {\n // Parse the RPC message from binary data\n // For Phase 1, this is a placeholder - full implementation would deserialize\n const message = this.deserializeMessage(data);\n\n // Fulfill pending receive\n if (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(message);\n } else {\n this.messageQueue.push(message);\n }\n }\n\n private deserializeMessage(data: Uint8Array): RpcMessage {\n return deserializeRpcMessage(data);\n }\n\n private serializeMessage(message: RpcMessage): Uint8Array {\n return serializeRpcMessage(message);\n }\n\n async send(message: RpcMessage): Promise<void> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error('WebSocket not connected');\n }\n\n const data = this.serializeMessage(message);\n const frame = new Uint8Array(4 + data.length);\n new DataView(frame.buffer).setUint32(0, data.length, true);\n frame.set(data, 4);\n\n this.ws.send(frame);\n }\n\n async receive(): Promise<RpcMessage | null> {\n // Check queued messages first\n if (this.messageQueue.length > 0) {\n return this.messageQueue.shift()!;\n }\n\n // If closed, return null\n if (!this._connected) {\n return null;\n }\n\n // Wait for next message\n return new Promise((resolve, reject) => {\n this.receiveQueue.push({ resolve, reject });\n });\n }\n\n close(reason?: Error): void {\n this._connected = false;\n this.ws?.close();\n this.flushReceiveQueue(null);\n this.onClose?.(reason);\n }\n\n private flushReceiveQueue(value: RpcMessage | null): void {\n while (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(value);\n }\n }\n}\n","/**\n * TCP Transport Implementation for Node.js\n *\n * Implements RpcTransport over raw TCP socket for C++ interop testing.\n * This allows direct communication with the official Cap'n Proto C++ implementation.\n */\n\nimport * as net from 'node:net';\nimport { deserializeRpcMessage, serializeRpcMessage } from './message-serializer.js';\nimport type { RpcMessage } from './rpc-types.js';\nimport type { RpcTransport } from './transport.js';\n\nexport interface TcpTransportOptions {\n /** Connection timeout in milliseconds */\n connectTimeoutMs?: number;\n}\n\n/**\n * TCP Transport for Cap'n Proto RPC\n *\n * Uses length-prefixed binary message framing compatible with Cap'n Proto C++ implementation.\n * Format: [4 bytes: message length (little-endian)] [N bytes: message data]\n */\nexport class TcpTransport implements RpcTransport {\n private socket: net.Socket | null = null;\n private messageQueue: RpcMessage[] = [];\n private receiveQueue: Array<{\n resolve: (msg: RpcMessage | null) => void;\n reject: (err: Error) => void;\n }> = [];\n private _connected = false;\n private pendingBuffer: Buffer = Buffer.alloc(0);\n private pendingLength = 0;\n private hasPendingLength = false;\n\n onClose?: (reason?: Error) => void;\n onError?: (error: Error) => void;\n\n constructor(\n private host: string,\n private port: number,\n private options: TcpTransportOptions = {}\n ) {}\n\n static async connect(\n host: string,\n port: number,\n options?: TcpTransportOptions\n ): Promise<TcpTransport> {\n const transport = new TcpTransport(host, port, options);\n await transport.connect();\n return transport;\n }\n\n static fromSocket(socket: net.Socket, options?: TcpTransportOptions): TcpTransport {\n const transport = new TcpTransport('', 0, options);\n transport.attachSocket(socket);\n return transport;\n }\n\n get connected(): boolean {\n return this._connected && this.socket?.readyState === 'open';\n }\n\n private connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.socket?.destroy();\n reject(new Error('Connection timeout'));\n }, this.options.connectTimeoutMs ?? 10000);\n\n this.socket = new net.Socket();\n\n this.socket.on('connect', () => {\n clearTimeout(timeout);\n this._connected = true;\n resolve();\n });\n\n this.socket.on('data', (data: Buffer) => {\n this.handleData(data);\n });\n\n this.socket.on('close', (hadError: boolean) => {\n this._connected = false;\n this.flushReceiveQueue(null);\n if (hadError) {\n this.onClose?.(new Error('Connection closed with error'));\n } else {\n this.onClose?.();\n }\n });\n\n this.socket.on('error', (err: Error) => {\n clearTimeout(timeout);\n this._connected = false;\n this.onError?.(err);\n reject(err);\n });\n\n this.socket.on('end', () => {\n this._connected = false;\n });\n\n this.socket.connect(this.port, this.host);\n });\n }\n\n private attachSocket(socket: net.Socket): void {\n this.socket = socket;\n this._connected = socket.readyState === 'open';\n\n socket.on('data', (data: Buffer) => {\n this.handleData(data);\n });\n\n socket.on('close', (hadError: boolean) => {\n this._connected = false;\n this.flushReceiveQueue(null);\n if (hadError) {\n this.onClose?.(new Error('Connection closed with error'));\n } else {\n this.onClose?.();\n }\n });\n\n socket.on('error', (err: Error) => {\n this._connected = false;\n this.onError?.(err);\n });\n\n socket.on('end', () => {\n this._connected = false;\n });\n }\n\n private handleData(data: Buffer): void {\n // Append new data to pending buffer\n this.pendingBuffer = Buffer.concat([this.pendingBuffer, data]);\n\n // Process complete messages\n while (this.pendingBuffer.length >= 4) {\n if (!this.hasPendingLength) {\n // Read message length (4 bytes, little-endian)\n this.pendingLength = this.pendingBuffer.readUInt32LE(0);\n this.hasPendingLength = true;\n\n // Sanity check: max message size 64MB\n if (this.pendingLength > 64 * 1024 * 1024) {\n this.onError?.(new Error(`Message too large: ${this.pendingLength} bytes`));\n this.close(new Error('Message too large'));\n return;\n }\n }\n\n // Check if we have the full message\n const totalLength = 4 + this.pendingLength;\n if (this.pendingBuffer.length < totalLength) {\n break; // Wait for more data\n }\n\n // Extract message data\n const messageData = this.pendingBuffer.subarray(4, totalLength);\n this.pendingBuffer = this.pendingBuffer.subarray(totalLength);\n this.hasPendingLength = false;\n\n // Parse and handle the message\n try {\n const message = deserializeRpcMessage(new Uint8Array(messageData));\n this.handleRpcMessage(message);\n } catch (err) {\n this.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n }\n }\n\n private handleRpcMessage(message: RpcMessage): void {\n if (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(message);\n } else {\n this.messageQueue.push(message);\n }\n }\n\n async send(message: RpcMessage): Promise<void> {\n if (!this.socket || this.socket.readyState !== 'open') {\n throw new Error('Socket not connected');\n }\n\n const data = serializeRpcMessage(message);\n const frame = Buffer.allocUnsafe(4 + data.length);\n frame.writeUInt32LE(data.length, 0);\n frame.set(data, 4);\n\n return new Promise((resolve, reject) => {\n this.socket!.write(frame, (err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n }\n\n async receive(): Promise<RpcMessage | null> {\n // Check queued messages first\n if (this.messageQueue.length > 0) {\n return this.messageQueue.shift()!;\n }\n\n // If closed, return null\n if (!this._connected) {\n return null;\n }\n\n // Wait for next message\n return new Promise((resolve, reject) => {\n this.receiveQueue.push({ resolve, reject });\n });\n }\n\n close(reason?: Error): void {\n this._connected = false;\n this.socket?.end();\n this.socket?.destroy();\n this.flushReceiveQueue(null);\n this.onClose?.(reason);\n }\n\n private flushReceiveQueue(value: RpcMessage | null): void {\n while (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(value);\n }\n }\n}\n","/**\n * EzRpc TCP Transport\n *\n * Implements RpcTransport over raw TCP socket for C++ EzRpc compatibility.\n * Does NOT use length-prefixed framing - sends raw Cap'n Proto messages.\n */\n\nimport * as net from 'node:net';\nimport { deserializeRpcMessage, serializeRpcMessage } from './message-serializer.js';\nimport type { RpcMessage } from './rpc-types.js';\nimport type { RpcTransport } from './transport.js';\n\nexport interface EzRpcTransportOptions {\n connectTimeoutMs?: number;\n}\n\n/**\n * EzRpc TCP Transport\n *\n * Compatible with Cap'n Proto C++ EzRpcServer/EzRpcClient.\n * Sends raw Cap'n Proto messages without length prefix.\n */\nexport class EzRpcTransport implements RpcTransport {\n private socket: net.Socket | null = null;\n private messageQueue: RpcMessage[] = [];\n private receiveQueue: Array<{\n resolve: (msg: RpcMessage | null) => void;\n reject: (err: Error) => void;\n }> = [];\n private _connected = false;\n private pendingBuffer = Buffer.alloc(0);\n\n onClose?: (reason?: Error) => void;\n onError?: (error: Error) => void;\n\n constructor(\n private host: string,\n private port: number,\n private options: EzRpcTransportOptions = {}\n ) {}\n\n static async connect(\n host: string,\n port: number,\n options?: EzRpcTransportOptions\n ): Promise<EzRpcTransport> {\n const transport = new EzRpcTransport(host, port, options);\n await transport.doConnect();\n return transport;\n }\n\n get connected(): boolean {\n return this._connected && this.socket !== null && !this.socket.destroyed;\n }\n\n private doConnect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.socket?.destroy();\n reject(new Error(`Connection timeout: failed to connect to ${this.host}:${this.port}`));\n }, this.options.connectTimeoutMs ?? 10000);\n\n this.socket = new net.Socket();\n\n this.socket.on('connect', () => {\n clearTimeout(timeout);\n this._connected = true;\n resolve();\n });\n\n this.socket.on('data', (data: Buffer) => {\n try {\n this.handleData(data);\n } catch (err) {\n this.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n });\n\n this.socket.on('close', (hadError: boolean) => {\n const wasConnected = this._connected;\n this._connected = false;\n\n // Reject pending receive calls\n const error = hadError\n ? new Error('Connection closed with error')\n : new Error('Connection closed');\n this.flushReceiveQueueWithError(error);\n\n if (wasConnected) {\n this.onClose?.(hadError ? error : undefined);\n }\n });\n\n this.socket.on('error', (err: Error) => {\n clearTimeout(timeout);\n this._connected = false;\n this.flushReceiveQueueWithError(err);\n this.onError?.(err);\n reject(err);\n });\n\n this.socket.connect(this.port, this.host);\n });\n }\n\n private handleData(data: Buffer): void {\n // For EzRpc, we assume each 'data' event contains exactly one message\n // This is how KJ async I/O typically works\n\n // If we have pending data, append it\n if (this.pendingBuffer.length > 0) {\n this.pendingBuffer = Buffer.concat([this.pendingBuffer, data]);\n } else {\n this.pendingBuffer = Buffer.from(data);\n }\n\n // Try to parse messages from the buffer\n // Cap'n Proto messages have an 8-byte header we can use to determine size\n while (this.pendingBuffer.length >= 8) {\n const segmentCount = this.pendingBuffer.readUInt32LE(0) + 1;\n const firstSegmentSize = this.pendingBuffer.readUInt32LE(4);\n\n // Calculate total message size\n // Header: 8 bytes\n // Segment sizes: (segmentCount - 1) * 4 bytes (if segmentCount > 1)\n // Data: sum of all segment sizes * 8 bytes\n let headerSize = 8;\n if (segmentCount > 1) {\n headerSize += (segmentCount - 1) * 4;\n }\n\n // For now, assume single segment\n const messageSize = headerSize + firstSegmentSize * 8;\n\n if (this.pendingBuffer.length < messageSize) {\n // Not enough data yet\n break;\n }\n\n // Extract the message\n const messageData = this.pendingBuffer.subarray(0, messageSize);\n this.pendingBuffer = this.pendingBuffer.subarray(messageSize);\n\n try {\n const message = deserializeRpcMessage(new Uint8Array(messageData));\n if (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(message);\n } else {\n this.messageQueue.push(message);\n }\n } catch (err) {\n this.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n }\n }\n\n async send(message: RpcMessage): Promise<void> {\n if (!this.connected) {\n throw new Error(`Cannot send: socket not connected to ${this.host}:${this.port}`);\n }\n\n const data = serializeRpcMessage(message);\n\n return new Promise((resolve, reject) => {\n this.socket!.write(Buffer.from(data), (err) => {\n if (err) {\n reject(new Error(`Failed to send message: ${err.message}`));\n } else {\n resolve();\n }\n });\n });\n }\n\n async receive(): Promise<RpcMessage | null> {\n // 先检查队列中的消息\n if (this.messageQueue.length > 0) {\n return this.messageQueue.shift()!;\n }\n\n // 如果已断开连接,返回 null\n if (!this.connected) {\n return null;\n }\n\n // 等待下一条消息\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n // 从队列中移除自己\n const index = this.receiveQueue.findIndex((item) => item.resolve === resolve);\n if (index !== -1) {\n this.receiveQueue.splice(index, 1);\n }\n reject(new Error('Receive timeout'));\n }, 30000); // 30 秒超时\n\n this.receiveQueue.push({\n resolve: (msg) => {\n clearTimeout(timeoutId);\n resolve(msg);\n },\n reject: (err) => {\n clearTimeout(timeoutId);\n reject(err);\n },\n });\n });\n }\n\n close(reason?: Error): void {\n this._connected = false;\n this.socket?.end();\n this.socket?.destroy();\n this.flushReceiveQueue(null);\n this.onClose?.(reason);\n }\n\n private flushReceiveQueueWithError(error: Error): void {\n while (this.receiveQueue.length > 0) {\n const { reject } = this.receiveQueue.shift()!;\n reject(error);\n }\n }\n\n private flushReceiveQueue(value: RpcMessage | null): void {\n while (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(value);\n }\n }\n}\n","/**\n * CapabilityClient\n *\n * Base class for client-side capability references.\n * Provides the foundation for making method calls on remote objects.\n */\n\nimport type { PipelineClient } from './pipeline.js';\nimport type { RpcConnection } from './rpc-connection.js';\nimport type { ImportId, InterfaceId, MethodId, Payload } from './rpc-types.js';\n\n/** Base interface for all capability clients */\nexport interface CapabilityClient {\n /** The connection this capability belongs to */\n readonly connection: RpcConnection;\n\n /** The import ID for this capability (if imported) */\n readonly importId?: ImportId;\n\n /** Check if this capability is still valid */\n isValid(): boolean;\n\n /** Release this capability reference */\n release(): void;\n}\n\n/** Base class for capability client implementations */\nexport abstract class BaseCapabilityClient implements CapabilityClient {\n constructor(\n public readonly connection: RpcConnection,\n public readonly importId?: ImportId\n ) {}\n\n isValid(): boolean {\n // In full implementation, check if the import is still valid\n return true;\n }\n\n release(): void {\n if (this.importId !== undefined) {\n this.connection.release(this.importId, 1);\n }\n }\n\n /** Make a method call on this capability and return a PipelineClient */\n protected _call(_interfaceId: InterfaceId, _methodId: MethodId, params: unknown): PipelineClient {\n if (!this.importId) {\n throw new Error('Cannot call method on capability without import ID');\n }\n\n // Serialize params to Payload\n const _payload = this.serializeParams(params);\n\n // Use callPipelined to get a PipelineClient\n // Note: callPipelined returns Promise<PipelineClient>, but we need to await it\n // This is a design issue - for now, we throw an error indicating async is needed\n throw new Error('Use _callAsync instead for async call support');\n }\n\n /** Make an async method call on this capability */\n protected async _callAsync(\n interfaceId: InterfaceId,\n methodId: MethodId,\n params: unknown\n ): Promise<PipelineClient> {\n if (!this.importId) {\n throw new Error('Cannot call method on capability without import ID');\n }\n\n // Serialize params to Payload\n const payload = this.serializeParams(params);\n\n // Use callPipelined to get a PipelineClient\n return this.connection.callPipelined(this.importId, interfaceId, methodId, payload);\n }\n\n /** Serialize parameters to Payload */\n protected serializeParams(_params: unknown): Payload {\n // TODO: Implement proper parameter serialization\n // For now, return empty payload\n return {\n content: new Uint8Array(),\n capTable: [],\n };\n }\n}\n\n/** Factory for creating capability clients */\nexport interface CapabilityClientFactory<T extends CapabilityClient> {\n create(connection: RpcConnection, importId?: ImportId): T;\n}\n","/**\n * SturdyRefs - Level 2 RPC Feature\n *\n * SturdyRefs provide persistent capability references that survive\n * connection disconnections and can be restored on reconnection.\n *\n * Key concepts:\n * - SturdyRef: A persistent reference to a capability\n * - Restore: Reconnect to a capability using its SturdyRef\n * - Save: Create a SturdyRef from a live capability\n */\n\nimport type { RpcConnection } from './rpc-connection.js';\nimport type { ExportId, ImportId, QuestionId, RpcMessage } from './rpc-types.js';\n\n// ========================================================================================\n// Types\n// ========================================================================================\n\n/**\n * A SturdyRef token that can be persisted and later used to restore a capability\n */\nexport interface SturdyRef {\n /** The vat ID where the capability lives */\n vatId: string;\n /** The local ID of the capability within that vat */\n localId: string;\n /** Optional: Version or generation number for validation */\n version?: number;\n /** Optional: Expiration timestamp */\n expiresAt?: number;\n /** Optional: Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * A stored SturdyRef with its associated capability info\n */\ninterface StoredSturdyRef {\n ref: SturdyRef;\n exportId: ExportId;\n capability: unknown;\n createdAt: number;\n lastAccessedAt: number;\n}\n\n/**\n * Options for saving a capability as a SturdyRef\n */\nexport interface SaveOptions {\n /** Custom local ID (auto-generated if not provided) */\n localId?: string;\n /** Expiration time in milliseconds from now */\n ttlMs?: number;\n /** Metadata to attach to the SturdyRef */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Options for restoring a capability from a SturdyRef\n */\nexport interface RestoreOptions {\n /** Timeout for the restore operation */\n timeoutMs?: number;\n}\n\n// ========================================================================================\n// SturdyRef Manager (Server-side)\n// ========================================================================================\n\n/**\n * Manages SturdyRefs on the server side.\n * Stores the mapping between SturdyRef tokens and live capabilities.\n */\nexport class SturdyRefManager {\n private vatId: string;\n private storedRefs = new Map<string, StoredSturdyRef>();\n private localIdCounter = 0;\n\n constructor(vatId: string) {\n this.vatId = vatId;\n }\n\n /**\n * Save a capability as a SturdyRef\n */\n saveCapability(capability: unknown, exportId: ExportId, options?: SaveOptions): SturdyRef {\n const localId = options?.localId ?? this.generateLocalId();\n const now = Date.now();\n\n const ref: SturdyRef = {\n vatId: this.vatId,\n localId,\n version: 1,\n expiresAt: options?.ttlMs ? now + options.ttlMs : undefined,\n metadata: options?.metadata,\n };\n\n const stored: StoredSturdyRef = {\n ref,\n exportId,\n capability,\n createdAt: now,\n lastAccessedAt: now,\n };\n\n this.storedRefs.set(localId, stored);\n return ref;\n }\n\n /**\n * Restore a capability from a SturdyRef token\n */\n restoreCapability(ref: SturdyRef): { capability: unknown; exportId: ExportId } | null {\n // Validate the SturdyRef belongs to this vat\n if (ref.vatId !== this.vatId) {\n console.warn(`SturdyRef vatId mismatch: ${ref.vatId} !== ${this.vatId}`);\n return null;\n }\n\n const stored = this.storedRefs.get(ref.localId);\n if (!stored) {\n console.warn(`SturdyRef not found: ${ref.localId}`);\n return null;\n }\n\n // Check expiration\n if (stored.ref.expiresAt && Date.now() > stored.ref.expiresAt) {\n console.warn(`SturdyRef expired: ${ref.localId}`);\n this.storedRefs.delete(ref.localId);\n return null;\n }\n\n // Update last accessed time\n stored.lastAccessedAt = Date.now();\n\n return {\n capability: stored.capability,\n exportId: stored.exportId,\n };\n }\n\n /**\n * Drop a SturdyRef\n */\n dropSturdyRef(localId: string): boolean {\n return this.storedRefs.delete(localId);\n }\n\n /**\n * Get all active SturdyRefs\n */\n getActiveRefs(): SturdyRef[] {\n const now = Date.now();\n const active: SturdyRef[] = [];\n\n for (const [localId, stored] of this.storedRefs) {\n // Clean up expired refs\n if (stored.ref.expiresAt && now > stored.ref.expiresAt) {\n this.storedRefs.delete(localId);\n continue;\n }\n active.push(stored.ref);\n }\n\n return active;\n }\n\n /**\n * Clean up expired SturdyRefs\n */\n cleanupExpired(): number {\n const now = Date.now();\n let cleaned = 0;\n\n for (const [localId, stored] of this.storedRefs) {\n if (stored.ref.expiresAt && now > stored.ref.expiresAt) {\n this.storedRefs.delete(localId);\n cleaned++;\n }\n }\n\n return cleaned;\n }\n\n private generateLocalId(): string {\n return `ref-${++this.localIdCounter}-${Date.now()}`;\n }\n}\n\n// ========================================================================================\n// Restore Handler (Client-side)\n// ========================================================================================\n\n/**\n * Handles Restore messages on the client side.\n * Manages reconnecting to capabilities after disconnections.\n */\nexport class RestoreHandler {\n private connection: RpcConnection;\n private pendingRestores = new Map<\n QuestionId,\n {\n resolve: (importId: ImportId) => void;\n reject: (error: Error) => void;\n timeout: ReturnType<typeof setTimeout>;\n }\n >();\n private questionIdCounter = 0;\n\n constructor(connection: RpcConnection) {\n this.connection = connection;\n }\n\n /**\n * Send a Restore message to restore a capability from a SturdyRef\n */\n async restore(ref: SturdyRef, options?: RestoreOptions): Promise<ImportId> {\n const questionId = ++this.questionIdCounter;\n const timeoutMs = options?.timeoutMs ?? 30000;\n\n return new Promise((resolve, reject) => {\n // Set up timeout\n const timeout = setTimeout(() => {\n this.pendingRestores.delete(questionId);\n reject(new Error(`Restore timeout after ${timeoutMs}ms`));\n }, timeoutMs);\n\n this.pendingRestores.set(questionId, { resolve, reject, timeout });\n\n // Send Restore message (using Call message with special interface)\n // In the actual protocol, this would be a specific Restore message type\n // For now, we use a special method call\n this.sendRestoreMessage(questionId, ref).catch((error) => {\n clearTimeout(timeout);\n this.pendingRestores.delete(questionId);\n reject(error);\n });\n });\n }\n\n /**\n * Handle a Restore response\n */\n handleRestoreResponse(questionId: QuestionId, importId: ImportId): void {\n const pending = this.pendingRestores.get(questionId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRestores.delete(questionId);\n pending.resolve(importId);\n }\n }\n\n /**\n * Handle a Restore failure\n */\n handleRestoreFailure(questionId: QuestionId, reason: string): void {\n const pending = this.pendingRestores.get(questionId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRestores.delete(questionId);\n pending.reject(new Error(`Restore failed: ${reason}`));\n }\n }\n\n /**\n * Cancel all pending restores (e.g., on disconnect)\n */\n cancelAll(reason: string): void {\n for (const [_questionId, pending] of this.pendingRestores) {\n clearTimeout(pending.timeout);\n pending.reject(new Error(`Restore canceled: ${reason}`));\n }\n this.pendingRestores.clear();\n }\n\n private async sendRestoreMessage(questionId: QuestionId, ref: SturdyRef): Promise<void> {\n // Serialize the SturdyRef\n const refData = JSON.stringify(ref);\n\n // In the actual implementation, this would send a proper Restore message\n // For now, we simulate it\n const restoreMsg: RpcMessage = {\n type: 'call',\n call: {\n questionId,\n target: { type: 'importedCap', importId: 0 }, // Special import for restore service\n interfaceId: BigInt('0xffffffffffffffff'), // Special interface ID for restore\n methodId: 0, // restore method\n allowThirdPartyTailCall: false,\n noPromisePipelining: false,\n onlyPromisePipeline: false,\n params: {\n content: new TextEncoder().encode(refData),\n capTable: [],\n },\n sendResultsTo: { type: 'caller' },\n },\n };\n\n // This would be sent through the connection\n // await this.connection.send(restoreMsg);\n console.log('Sending restore message:', restoreMsg);\n }\n}\n\n// ========================================================================================\n// SturdyRef Utilities\n// ========================================================================================\n\n/**\n * Serialize a SturdyRef to a string for storage\n */\nexport function serializeSturdyRef(ref: SturdyRef): string {\n return JSON.stringify(ref);\n}\n\n/**\n * Deserialize a SturdyRef from a string\n */\nexport function deserializeSturdyRef(data: string): SturdyRef | null {\n try {\n const parsed = JSON.parse(data);\n\n // Validate required fields\n if (typeof parsed.vatId !== 'string' || typeof parsed.localId !== 'string') {\n return null;\n }\n\n return {\n vatId: parsed.vatId,\n localId: parsed.localId,\n version: parsed.version,\n expiresAt: parsed.expiresAt,\n metadata: parsed.metadata,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a SturdyRef is valid (not expired)\n */\nexport function isSturdyRefValid(ref: SturdyRef): boolean {\n if (ref.expiresAt && Date.now() > ref.expiresAt) {\n return false;\n }\n return true;\n}\n\n/**\n * Create a SturdyRef from components\n */\nexport function createSturdyRef(\n vatId: string,\n localId: string,\n options?: Omit<SaveOptions, 'localId'>\n): SturdyRef {\n return {\n vatId,\n localId,\n version: 1,\n expiresAt: options?.ttlMs ? Date.now() + options.ttlMs : undefined,\n metadata: options?.metadata,\n };\n}\n","/**\n * Performance Optimizations for RPC\n *\n * Phase 3: Performance improvements\n * - Multi-segment message support\n * - Memory pooling\n * - Zero-copy paths where possible\n */\n\nimport { Segment } from '../core/segment.js';\n\n// ========================================================================================\n// Memory Pool\n// ========================================================================================\n\ninterface PooledBuffer {\n buffer: ArrayBuffer;\n size: number;\n lastUsed: number;\n}\n\n/**\n * Memory pool for reusing ArrayBuffers\n * Reduces GC pressure for frequent allocations\n */\nexport class MemoryPool {\n private pools = new Map<number, PooledBuffer[]>();\n private maxPoolSize: number;\n private maxBufferAge: number;\n\n constructor(options?: { maxPoolSize?: number; maxBufferAgeMs?: number }) {\n this.maxPoolSize = options?.maxPoolSize ?? 100;\n this.maxBufferAge = options?.maxBufferAgeMs ?? 60000; // 1 minute\n }\n\n /**\n * Acquire a buffer of at least the requested size\n */\n acquire(size: number): ArrayBuffer {\n // Round up to nearest power of 2 for better pooling\n const pooledSize = this.roundUpSize(size);\n const pool = this.pools.get(pooledSize);\n\n if (pool && pool.length > 0) {\n const now = Date.now();\n // Find a buffer that's not too old\n const index = pool.findIndex((b) => now - b.lastUsed < this.maxBufferAge);\n\n if (index >= 0) {\n const pooled = pool.splice(index, 1)[0];\n return pooled.buffer;\n }\n }\n\n // Allocate new buffer\n return new ArrayBuffer(pooledSize);\n }\n\n /**\n * Release a buffer back to the pool\n */\n release(buffer: ArrayBuffer): void {\n const size = buffer.byteLength;\n\n // Don't pool very small or very large buffers\n if (size < 64 || size > 1024 * 1024) {\n return;\n }\n\n let pool = this.pools.get(size);\n if (!pool) {\n pool = [];\n this.pools.set(size, pool);\n }\n\n if (pool.length < this.maxPoolSize) {\n pool.push({\n buffer,\n size,\n lastUsed: Date.now(),\n });\n }\n }\n\n /**\n * Clear all pooled buffers\n */\n clear(): void {\n this.pools.clear();\n }\n\n /**\n * Get pool statistics\n */\n getStats(): { totalBuffers: number; totalBytes: number; sizes: number[] } {\n let totalBuffers = 0;\n let totalBytes = 0;\n const sizes: number[] = [];\n\n for (const [size, pool] of this.pools) {\n totalBuffers += pool.length;\n totalBytes += size * pool.length;\n sizes.push(size);\n }\n\n return { totalBuffers, totalBytes, sizes };\n }\n\n private roundUpSize(size: number): number {\n // Round up to nearest power of 2, minimum 64 bytes\n if (size <= 64) return 64;\n if (size <= 128) return 128;\n if (size <= 256) return 256;\n if (size <= 512) return 512;\n if (size <= 1024) return 1024;\n if (size <= 2048) return 2048;\n if (size <= 4096) return 4096;\n if (size <= 8192) return 8192;\n if (size <= 16384) return 16384;\n if (size <= 32768) return 32768;\n if (size <= 65536) return 65536;\n return size;\n }\n}\n\n// ========================================================================================\n// Multi-Segment Message Builder\n// ========================================================================================\n\n/**\n * Options for multi-segment message building\n */\nexport interface MultiSegmentOptions {\n /** Initial segment size */\n initialSegmentSize?: number;\n /** Maximum segment size */\n maxSegmentSize?: number;\n /** Whether to allow multiple segments */\n allowMultipleSegments?: boolean;\n}\n\n/**\n * Builder for multi-segment messages\n * Optimizes memory usage for large messages\n */\nexport class MultiSegmentMessageBuilder {\n private segments: Segment[] = [];\n private options: Required<MultiSegmentOptions>;\n private currentSegment: Segment;\n private totalSize = 0;\n\n constructor(options?: MultiSegmentOptions) {\n this.options = {\n initialSegmentSize: options?.initialSegmentSize ?? 8192,\n maxSegmentSize: options?.maxSegmentSize ?? 65536,\n allowMultipleSegments: options?.allowMultipleSegments ?? true,\n };\n\n this.currentSegment = new Segment(this.options.initialSegmentSize);\n this.segments.push(this.currentSegment);\n }\n\n /**\n * Allocate space in the message\n */\n allocate(size: number): { segment: Segment; offset: number } {\n // Align to 8 bytes and convert to words\n const alignedBytes = (size + 7) & ~7;\n const words = alignedBytes / 8;\n\n // Check if current segment has enough space\n // Segment capacity is the buffer size, not the current size\n const currentCapacity = this.currentSegment.byteLength;\n const currentUsed = this.currentSegment.wordCount * 8; // wordCount * 8 = bytes used\n const remainingSpace = currentCapacity - currentUsed;\n\n if (remainingSpace >= alignedBytes) {\n // Current segment has enough space\n const wordOffset = this.currentSegment.allocate(words);\n this.totalSize += alignedBytes;\n return { segment: this.currentSegment, offset: wordOffset * 8 };\n }\n\n // Need a new segment\n if (!this.options.allowMultipleSegments) {\n throw new Error('Message too large for single segment');\n }\n\n // Create new segment\n const newSegmentSize = Math.min(\n Math.max(alignedBytes, this.options.initialSegmentSize),\n this.options.maxSegmentSize\n );\n this.currentSegment = new Segment(newSegmentSize);\n this.segments.push(this.currentSegment);\n\n const newWordOffset = this.currentSegment.allocate(words);\n this.totalSize += alignedBytes;\n return { segment: this.currentSegment, offset: newWordOffset * 8 };\n }\n\n /**\n * Get all segments\n */\n getSegments(): readonly Segment[] {\n return this.segments;\n }\n\n /**\n * Get the total size of all segments\n */\n getTotalSize(): number {\n return this.totalSize;\n }\n\n /**\n * Get the number of segments\n */\n getSegmentCount(): number {\n return this.segments.length;\n }\n\n /**\n * Serialize to a single buffer (for transport)\n */\n toBuffer(): ArrayBuffer {\n if (this.segments.length === 1) {\n // Single segment - use asUint8Array to get the used portion\n const segmentData = this.segments[0].asUint8Array();\n return segmentData.buffer.slice(\n segmentData.byteOffset,\n segmentData.byteOffset + segmentData.byteLength\n ) as ArrayBuffer;\n }\n\n // Multi-segment - need to serialize with segment table\n // This is a simplified version - full implementation would include\n // the segment table at the beginning\n const totalSize = this.segments.reduce((sum, seg) => sum + seg.byteLength, 0);\n const result = new ArrayBuffer(totalSize + 8 * this.segments.length); // Space for segment table\n const view = new DataView(result);\n const bytes = new Uint8Array(result);\n\n // Write segment table\n view.setUint32(0, this.segments.length - 1, true); // Segment count - 1\n view.setUint32(4, 0, true); // Padding for first segment size (in words)\n\n let offset = 8;\n for (let i = 0; i < this.segments.length; i++) {\n const segment = this.segments[i];\n if (i > 0) {\n view.setUint32(offset, segment.byteLength / 8, true); // Segment size in words\n offset += 4;\n }\n\n // Copy segment data\n const segmentBuffer = new Uint8Array(segment.byteLength);\n // Copy data from segment's DataView\n const segmentData = segment.dataView;\n for (let i = 0; i < segment.byteLength; i++) {\n segmentBuffer[i] = segmentData.getUint8(i);\n }\n bytes.set(segmentBuffer, offset);\n offset += segment.byteLength;\n }\n\n return result;\n }\n}\n\n// ========================================================================================\n// Zero-Copy Utilities\n// ========================================================================================\n\n/**\n * View into a buffer without copying\n */\nexport interface ZeroCopyView {\n buffer: ArrayBuffer;\n byteOffset: number;\n byteLength: number;\n}\n\n/**\n * Create a zero-copy view of a buffer\n */\nexport function createZeroCopyView(\n buffer: ArrayBuffer,\n byteOffset = 0,\n byteLength?: number\n): ZeroCopyView {\n return {\n buffer,\n byteOffset,\n byteLength: byteLength ?? buffer.byteLength - byteOffset,\n };\n}\n\n/**\n * Check if two buffers are the same underlying memory\n */\nexport function isSameBuffer(a: ArrayBuffer, b: ArrayBuffer): boolean {\n try {\n // This is a hack to check if two buffers are the same\n // In a real implementation, we'd use a more reliable method\n return a === b;\n } catch {\n return false;\n }\n}\n\n/**\n * Copy data between buffers using the fastest available method\n */\nexport function fastCopy(\n src: ArrayBuffer,\n dst: ArrayBuffer,\n srcOffset = 0,\n dstOffset = 0,\n length?: number\n): void {\n const len = length ?? Math.min(src.byteLength - srcOffset, dst.byteLength - dstOffset);\n const srcView = new Uint8Array(src, srcOffset, len);\n const dstView = new Uint8Array(dst, dstOffset, len);\n dstView.set(srcView);\n}\n\n// ========================================================================================\n// RPC Message Optimization\n// ========================================================================================\n\n/**\n * Options for RPC message building\n */\nexport interface RpcMessageOptions {\n /** Use multi-segment messages */\n useMultiSegment?: boolean;\n /** Initial segment size */\n initialSegmentSize?: number;\n /** Use memory pooling */\n useMemoryPool?: boolean;\n /** Memory pool instance */\n memoryPool?: MemoryPool;\n}\n\n/**\n * Optimized RPC message builder\n */\nexport class OptimizedRpcMessageBuilder {\n private options: Required<RpcMessageOptions>;\n private pool: MemoryPool;\n\n constructor(options?: RpcMessageOptions) {\n this.options = {\n useMultiSegment: options?.useMultiSegment ?? true,\n initialSegmentSize: options?.initialSegmentSize ?? 8192,\n useMemoryPool: options?.useMemoryPool ?? true,\n memoryPool: options?.memoryPool ?? new MemoryPool(),\n };\n this.pool = this.options.memoryPool;\n }\n\n /**\n * Build a message with optimizations applied\n */\n buildMessage(content: Uint8Array): ArrayBuffer {\n const totalSize = 8 + content.length; // Header + content\n\n if (this.options.useMemoryPool) {\n const buffer = this.pool.acquire(totalSize);\n const view = new DataView(buffer);\n const bytes = new Uint8Array(buffer);\n\n // Write header (simplified)\n view.setUint32(0, 0, true); // Single segment indicator\n view.setUint32(4, content.length / 8, true); // Size in words\n\n // Copy content\n bytes.set(content, 8);\n\n return buffer;\n }\n\n // Standard allocation\n const buffer = new ArrayBuffer(totalSize);\n const view = new DataView(buffer);\n const bytes = new Uint8Array(buffer);\n\n view.setUint32(0, 0, true);\n view.setUint32(4, content.length / 8, true);\n bytes.set(content, 8);\n\n return buffer;\n }\n\n /**\n * Release a buffer back to the pool\n */\n releaseBuffer(buffer: ArrayBuffer): void {\n if (this.options.useMemoryPool) {\n this.pool.release(buffer);\n }\n }\n\n /**\n * Get pool statistics\n */\n getPoolStats(): { totalBuffers: number; totalBytes: number; sizes: number[] } {\n return this.pool.getStats();\n }\n}\n\n// ========================================================================================\n// Global Memory Pool (Singleton)\n// ========================================================================================\n\nlet globalMemoryPool: MemoryPool | null = null;\n\n/**\n * Get the global memory pool instance\n */\nexport function getGlobalMemoryPool(): MemoryPool {\n if (!globalMemoryPool) {\n globalMemoryPool = new MemoryPool();\n }\n return globalMemoryPool;\n}\n\n/**\n * Configure the global memory pool\n */\nexport function configureGlobalMemoryPool(options: {\n maxPoolSize?: number;\n maxBufferAgeMs?: number;\n}): void {\n globalMemoryPool = new MemoryPool(options);\n}\n","/**\n * Connection Manager\n *\n * Manages multiple RPC connections for Level 3 RPC (Three-way introductions).\n * Handles connection pooling, automatic connection establishment, and routing\n * of messages between vats.\n *\n * Level 3 RPC allows capabilities to be passed between vats that don't have\n * a direct connection, and enables those vats to form direct connections.\n */\n\nimport type { RpcConnection, RpcConnectionOptions } from './rpc-connection.js';\nimport type { ProvisionId, RecipientId, ThirdPartyCapId } from './rpc-types.js';\nimport type { RpcTransport } from './transport.js';\n\n/** Unique identifier for a vat */\nexport interface VatId {\n /** The raw vat identifier */\n id: Uint8Array;\n}\n\n/** Connection metadata */\nexport interface ConnectionInfo {\n /** The connection instance */\n connection: RpcConnection;\n /** The vat ID of the remote peer */\n remoteVatId: VatId;\n /** When the connection was established */\n establishedAt: Date;\n /** Last activity timestamp */\n lastActivity: Date;\n /** Connection state */\n state: 'connecting' | 'connected' | 'closing' | 'closed';\n}\n\n/** Pending provision waiting for acceptance */\nexport interface PendingProvision {\n /** Unique provision ID */\n provisionId: ProvisionId;\n /** The vat ID of the intended recipient */\n recipientId: VatId;\n /** The capability being provided */\n targetExportId: number;\n /** When the provision was created */\n createdAt: Date;\n /** Question ID from the Provide message */\n questionId: number;\n /** Whether this provision is embargoed (for cycle breaking) */\n embargoed: boolean;\n}\n\n/** Options for ConnectionManager */\nexport interface ConnectionManagerOptions {\n /** This vat's own ID */\n selfVatId: VatId;\n /** Factory function to create connections */\n connectionFactory: (vatId: VatId, address?: string) => Promise<RpcTransport>;\n /** Default connection options */\n connectionOptions?: RpcConnectionOptions;\n /** Maximum number of concurrent connections */\n maxConnections?: number;\n /** Connection idle timeout in milliseconds */\n idleTimeoutMs?: number;\n /** Whether to automatically establish connections to third parties */\n autoConnect?: boolean;\n}\n\n/**\n * ConnectionManager manages multiple RPC connections for Level 3 RPC.\n *\n * Key responsibilities:\n * 1. Maintain a pool of connections to other vats\n * 2. Handle automatic connection establishment for third-party capabilities\n * 3. Manage pending provisions (capabilities waiting to be picked up)\n * 4. Route messages to the appropriate connection\n * 5. Handle connection lifecycle (connect, disconnect, reconnect)\n */\nexport class ConnectionManager {\n private options: ConnectionManagerOptions;\n private connections = new Map<string, ConnectionInfo>();\n private pendingProvisions = new Map<string, PendingProvision>();\n private connectionPromises = new Map<string, Promise<RpcConnection>>();\n\n constructor(options: ConnectionManagerOptions) {\n this.options = {\n maxConnections: 100,\n idleTimeoutMs: 300000, // 5 minutes\n autoConnect: true,\n ...options,\n };\n }\n\n // ========================================================================================\n // Connection Management\n // ========================================================================================\n\n /**\n * Register an existing connection with the manager.\n * This is called when a connection is established (either inbound or outbound).\n */\n registerConnection(vatId: VatId, connection: RpcConnection): ConnectionInfo {\n const vatIdKey = this.vatIdToKey(vatId);\n\n const info: ConnectionInfo = {\n connection,\n remoteVatId: vatId,\n establishedAt: new Date(),\n lastActivity: new Date(),\n state: 'connected',\n };\n\n this.connections.set(vatIdKey, info);\n\n // Set up cleanup on connection close\n // Note: The connection's onClose handler should be set by the caller\n\n return info;\n }\n\n /**\n * Get or establish a connection to a vat.\n * If autoConnect is enabled and no connection exists, a new one will be created.\n */\n async getConnection(vatId: VatId): Promise<RpcConnection | undefined> {\n const vatIdKey = this.vatIdToKey(vatId);\n\n // Check for existing connection\n const existing = this.connections.get(vatIdKey);\n if (existing && existing.state === 'connected') {\n existing.lastActivity = new Date();\n return existing.connection;\n }\n\n // Check for in-progress connection\n const pending = this.connectionPromises.get(vatIdKey);\n if (pending) {\n return pending;\n }\n\n // Auto-connect if enabled\n if (this.options.autoConnect) {\n return this.establishConnection(vatId);\n }\n\n return undefined;\n }\n\n /**\n * Establish a new connection to a vat.\n */\n async establishConnection(vatId: VatId, address?: string): Promise<RpcConnection> {\n const vatIdKey = this.vatIdToKey(vatId);\n\n // Check if already connecting\n if (this.connectionPromises.has(vatIdKey)) {\n return this.connectionPromises.get(vatIdKey)!;\n }\n\n // Create connection promise\n const connectPromise = this.doEstablishConnection(vatId, address);\n this.connectionPromises.set(vatIdKey, connectPromise);\n\n try {\n const connection = await connectPromise;\n return connection;\n } finally {\n this.connectionPromises.delete(vatIdKey);\n }\n }\n\n private async doEstablishConnection(vatId: VatId, address?: string): Promise<RpcConnection> {\n const { RpcConnection } = await import('./rpc-connection.js');\n\n // Create transport using the factory\n const transport = await this.options.connectionFactory(vatId, address);\n\n // Create and start the connection\n const connection = new RpcConnection(transport, this.options.connectionOptions);\n await connection.start();\n\n // Register the connection\n this.registerConnection(vatId, connection);\n\n return connection;\n }\n\n /**\n * Close a connection to a vat.\n */\n async closeConnection(vatId: VatId): Promise<void> {\n const vatIdKey = this.vatIdToKey(vatId);\n const info = this.connections.get(vatIdKey);\n\n if (info) {\n info.state = 'closing';\n await info.connection.stop();\n this.connections.delete(vatIdKey);\n }\n }\n\n /**\n * Close all connections.\n */\n async closeAll(): Promise<void> {\n const closePromises: Promise<void>[] = [];\n\n for (const [_vatIdKey, info] of this.connections) {\n info.state = 'closing';\n closePromises.push(\n info.connection.stop().catch(() => {\n // Ignore errors during shutdown\n })\n );\n }\n\n await Promise.all(closePromises);\n this.connections.clear();\n this.pendingProvisions.clear();\n }\n\n // ========================================================================================\n // Provision Management (for Provide/Accept)\n // ========================================================================================\n\n /**\n * Create a pending provision for a third-party capability.\n * Called when we receive a Provide message.\n */\n createPendingProvision(\n provisionId: ProvisionId,\n recipientId: VatId,\n targetExportId: number,\n questionId: number,\n embargoed: boolean\n ): PendingProvision {\n const provisionKey = this.provisionIdToKey(provisionId);\n\n const provision: PendingProvision = {\n provisionId,\n recipientId,\n targetExportId,\n questionId,\n createdAt: new Date(),\n embargoed,\n };\n\n this.pendingProvisions.set(provisionKey, provision);\n return provision;\n }\n\n /**\n * Get a pending provision by ID.\n */\n getPendingProvision(provisionId: ProvisionId): PendingProvision | undefined {\n const provisionKey = this.provisionIdToKey(provisionId);\n return this.pendingProvisions.get(provisionKey);\n }\n\n /**\n * Remove a pending provision (when it's been accepted or expired).\n */\n removePendingProvision(provisionId: ProvisionId): boolean {\n const provisionKey = this.provisionIdToKey(provisionId);\n return this.pendingProvisions.delete(provisionKey);\n }\n\n /**\n * Find provisions for a specific recipient.\n */\n findProvisionsForRecipient(recipientId: VatId): PendingProvision[] {\n const recipientKey = this.vatIdToKey(recipientId);\n const result: PendingProvision[] = [];\n\n for (const provision of this.pendingProvisions.values()) {\n if (this.vatIdToKey(provision.recipientId) === recipientKey) {\n result.push(provision);\n }\n }\n\n return result;\n }\n\n /**\n * Clean up expired provisions.\n */\n cleanupExpiredProvisions(maxAgeMs = 300000): number {\n const now = Date.now();\n let removed = 0;\n\n for (const [key, provision] of this.pendingProvisions) {\n if (now - provision.createdAt.getTime() > maxAgeMs) {\n this.pendingProvisions.delete(key);\n removed++;\n }\n }\n\n return removed;\n }\n\n // ========================================================================================\n // Third-Party Capability Resolution\n // ========================================================================================\n\n /**\n * Resolve a third-party capability ID to a connection.\n * This is the core of Level 3 RPC - automatically establishing connections\n * to third parties when capabilities are passed between vats.\n */\n async resolveThirdPartyCap(thirdPartyCapId: ThirdPartyCapId): Promise<\n | {\n connection: RpcConnection;\n provisionId: ProvisionId;\n }\n | undefined\n > {\n // Parse the ThirdPartyCapId to extract vat ID and provision ID\n const parsed = this.parseThirdPartyCapId(thirdPartyCapId);\n if (!parsed) {\n return undefined;\n }\n\n // Get or establish connection to the third party\n const connection = await this.getConnection(parsed.vatId);\n if (!connection) {\n return undefined;\n }\n\n return {\n connection,\n provisionId: parsed.provisionId,\n };\n }\n\n /**\n * Parse a ThirdPartyCapId to extract vat ID and provision ID.\n * The format is implementation-specific, but typically:\n * - First N bytes: vat ID\n * - Remaining bytes: provision ID\n */\n private parseThirdPartyCapId(thirdPartyCapId: ThirdPartyCapId):\n | {\n vatId: VatId;\n provisionId: ProvisionId;\n }\n | undefined {\n // Default implementation: first 32 bytes are vat ID, rest is provision ID\n // This can be overridden by the application\n const data = thirdPartyCapId.id;\n\n if (data.length < 32) {\n return undefined;\n }\n\n const vatIdBytes = data.slice(0, 32);\n const provisionIdBytes = data.slice(32);\n\n return {\n vatId: { id: vatIdBytes },\n provisionId: { id: provisionIdBytes },\n };\n }\n\n // ========================================================================================\n // Utility Methods\n // ========================================================================================\n\n /**\n * Get all active connections.\n */\n getAllConnections(): ConnectionInfo[] {\n return Array.from(this.connections.values());\n }\n\n /**\n * Get the number of active connections.\n */\n getConnectionCount(): number {\n return this.connections.size;\n }\n\n /**\n * Get the number of pending provisions.\n */\n getPendingProvisionCount(): number {\n return this.pendingProvisions.size;\n }\n\n /**\n * Check if a connection exists to a vat.\n */\n hasConnection(vatId: VatId): boolean {\n const vatIdKey = this.vatIdToKey(vatId);\n const info = this.connections.get(vatIdKey);\n return info !== undefined && info.state === 'connected';\n }\n\n /**\n * Update the last activity timestamp for a connection.\n */\n touchConnection(vatId: VatId): void {\n const vatIdKey = this.vatIdToKey(vatId);\n const info = this.connections.get(vatIdKey);\n if (info) {\n info.lastActivity = new Date();\n }\n }\n\n // ========================================================================================\n // Private Helpers\n // ========================================================================================\n\n private vatIdToKey(vatId: VatId): string {\n // Convert Uint8Array to hex string for use as Map key\n return Array.from(vatId.id)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n private provisionIdToKey(provisionId: ProvisionId): string {\n return Array.from(provisionId.id)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n}\n\n/**\n * Create a ThirdPartyCapId from vat ID and provision ID.\n */\nexport function createThirdPartyCapId(vatId: VatId, provisionId: ProvisionId): ThirdPartyCapId {\n // Concatenate vat ID and provision ID\n const combined = new Uint8Array(vatId.id.length + provisionId.id.length);\n combined.set(vatId.id, 0);\n combined.set(provisionId.id, vatId.id.length);\n\n return { id: combined };\n}\n\n/**\n * Create a RecipientId from a vat ID.\n */\nexport function createRecipientId(vatId: VatId): RecipientId {\n return { id: vatId.id };\n}\n\n/**\n * Create a ProvisionId from raw bytes.\n */\nexport function createProvisionId(id: Uint8Array): ProvisionId {\n return { id };\n}\n\n/**\n * Generate a random provision ID.\n */\nexport function generateProvisionId(): ProvisionId {\n const id = new Uint8Array(32);\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n crypto.getRandomValues(id);\n } else {\n // Fallback for Node.js\n const { randomBytes } = require('node:crypto');\n randomBytes(32).copy(id);\n }\n return { id };\n}\n\n/**\n * Generate a random vat ID.\n */\nexport function generateVatId(): VatId {\n const id = new Uint8Array(32);\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n crypto.getRandomValues(id);\n } else {\n // Fallback for Node.js\n const { randomBytes } = require('node:crypto');\n randomBytes(32).copy(id);\n }\n return { id };\n}\n","/**\n * Level 3 RPC Message Handlers\n *\n * Implements the three-way introduction protocol for Level 3 RPC:\n * - Provide: Offer a capability to a third party\n * - Accept: Accept a capability from a third party\n * - Embargo handling for cycle breaking\n *\n * The three-way introduction protocol allows capabilities to be passed between\n * vats that don't have a direct connection, enabling those vats to form direct\n * connections.\n */\n\nimport type { ConnectionManager, PendingProvision, VatId } from './connection-manager.js';\nimport { createThirdPartyCapId, generateProvisionId } from './connection-manager.js';\nimport type { RpcConnection } from './rpc-connection.js';\nimport type {\n Accept,\n CapDescriptor,\n Disembargo,\n ExportId,\n ImportId,\n MessageTarget,\n Provide,\n RecipientId,\n RpcMessage,\n ThirdPartyCapId,\n} from './rpc-types.js';\n\n/** Options for Level3Handlers */\nexport interface Level3HandlersOptions {\n /** The connection this handler is attached to */\n connection: RpcConnection;\n /** The connection manager for managing third-party connections */\n connectionManager: ConnectionManager;\n /** This vat's ID */\n selfVatId: VatId;\n /** Handler for incoming Provide messages */\n onProvide?: (provide: Provide) => Promise<void>;\n /** Handler for incoming Accept messages */\n onAccept?: (accept: Accept) => Promise<void>;\n}\n\n/**\n * Manages Level 3 RPC message handling for a connection.\n *\n * This class handles:\n * 1. Provide messages - when someone wants to give us a capability to share with a third party\n * 2. Accept messages - when a third party wants to pick up a capability we provided\n * 3. Embargo handling - breaking cycles in introduction graphs\n */\nexport class Level3Handlers {\n private options: Level3HandlersOptions;\n private pendingAccepts = new Map<number, PendingAccept>();\n private embargoedCalls = new Map<number, EmbargoedCall[]>();\n private nextEmbargoId = 1;\n\n constructor(options: Level3HandlersOptions) {\n this.options = options;\n }\n\n // ========================================================================================\n // Provide Message Handling\n // ========================================================================================\n\n /**\n * Handle an incoming Provide message.\n *\n * When we receive a Provide message, it means someone wants us to hold a capability\n * and make it available to a specific third party. We:\n * 1. Create a pending provision\n * 2. Return an answer acknowledging receipt\n * 3. Wait for the third party to Accept\n */\n async handleProvide(provide: Provide): Promise<void> {\n const { questionId, target, recipient } = provide;\n const { connectionManager } = this.options;\n\n // Generate a unique provision ID\n const provisionId = generateProvisionId();\n\n // Extract the target export ID from the MessageTarget\n const targetExportId = this.extractTargetExportId(target);\n if (targetExportId === undefined) {\n // Can't provide this target - send exception\n await this.sendReturnException(\n questionId,\n 'Invalid provide target: must be a hosted capability'\n );\n return;\n }\n\n // Create the pending provision\n const _provision: PendingProvision = connectionManager.createPendingProvision(\n provisionId,\n this.recipientIdToVatId(recipient),\n targetExportId,\n questionId,\n false // Not embargoed by default\n );\n\n // Call the custom handler if provided\n if (this.options.onProvide) {\n await this.options.onProvide(provide);\n }\n\n // Send Return with the provision info\n // The provision ID is embedded in the answer for reference\n await this.sendReturnResults(questionId, {\n provisionId: provisionId.id,\n });\n }\n\n /**\n * Send a Provide message to offer a capability to a third party.\n *\n * This is called when we want to introduce a third party to a capability we hold.\n * For example, Alice calls this to offer Bob access to Carol's capability.\n */\n async sendProvide(\n target: MessageTarget,\n recipient: RecipientId\n ): Promise<{ questionId: number; provisionId: ThirdPartyCapId }> {\n const { connection } = this.options;\n\n // Create a question for this provide\n const questionId = connection.createQuestion();\n\n const provideMsg: RpcMessage = {\n type: 'provide',\n provide: {\n questionId,\n target,\n recipient,\n },\n };\n\n await connection.sendCall(provideMsg.provide as any);\n\n // Wait for the return to get the provision ID\n const _result = await connection.waitForAnswer(questionId);\n\n // Extract provision ID from result\n // In a full implementation, we'd parse the result payload\n const provisionId: ThirdPartyCapId = {\n id: new Uint8Array(0),\n };\n\n return { questionId, provisionId };\n }\n\n // ========================================================================================\n // Accept Message Handling\n // ========================================================================================\n\n /**\n * Handle an incoming Accept message.\n *\n * When we receive an Accept message, it means a third party wants to pick up\n * a capability we previously agreed to provide. We:\n * 1. Look up the pending provision\n * 2. Verify the recipient matches\n * 3. Return the capability\n */\n async handleAccept(accept: Accept): Promise<void> {\n const { questionId, provision, embargo } = accept;\n const { connectionManager } = this.options;\n\n // Find the pending provision\n const pendingProvision = connectionManager.getPendingProvision(provision);\n\n if (!pendingProvision) {\n // No such provision - send exception\n await this.sendReturnException(\n questionId,\n 'Invalid provision ID: no pending provision found'\n );\n return;\n }\n\n // Remove the pending provision\n connectionManager.removePendingProvision(provision);\n\n // If embargoed, set up embargo handling\n if (embargo || pendingProvision.embargoed) {\n await this.handleEmbargoedAccept(questionId, pendingProvision);\n return;\n }\n\n // Return the capability\n const capDescriptor: CapDescriptor = {\n type: 'senderHosted',\n exportId: pendingProvision.targetExportId as ExportId,\n };\n\n await this.sendReturnCapability(questionId, capDescriptor);\n\n // Call the custom handler if provided\n if (this.options.onAccept) {\n await this.options.onAccept(accept);\n }\n }\n\n /**\n * Send an Accept message to pick up a capability from a third party.\n *\n * This is called when we receive a third-party capability and want to\n * establish a direct connection to use it.\n */\n async sendAccept(\n targetConnection: RpcConnection,\n provision: { id: Uint8Array },\n embargo = false\n ): Promise<ImportId> {\n const questionId = targetConnection.createQuestion();\n\n const acceptMsg: RpcMessage = {\n type: 'accept',\n accept: {\n questionId,\n provision: provision as any,\n embargo,\n },\n };\n\n await targetConnection.sendCall(acceptMsg.accept as any);\n\n // Wait for the return\n const _result = await targetConnection.waitForAnswer(questionId);\n\n // In a full implementation, we'd extract the import ID from the result\n // For now, return a placeholder\n return 0 as ImportId;\n }\n\n // ========================================================================================\n // Embargo Handling (Cycle Breaking)\n // ========================================================================================\n\n /**\n * Handle an embargoed accept.\n *\n * Embargoes are used to break cycles in the introduction graph. For example,\n * if Alice introduces Bob to Carol and Carol to Bob simultaneously, both\n * introductions use embargo=true to prevent deadlock.\n */\n private async handleEmbargoedAccept(\n questionId: number,\n provision: PendingProvision\n ): Promise<void> {\n // Store the pending accept\n const pendingAccept: PendingAccept = {\n questionId,\n provision,\n embargoId: this.nextEmbargoId++,\n };\n\n this.pendingAccepts.set(questionId, pendingAccept);\n\n // Send a Return with resultsSentElsewhere to indicate we're waiting\n await this.sendReturnResultsSentElsewhere(questionId);\n\n // The embargo will be lifted when we receive a Disembargo message\n }\n\n /**\n * Handle a Disembargo message.\n *\n * Disembargo messages are used to lift embargoes on capabilities.\n */\n async handleDisembargo(disembargo: Disembargo): Promise<void> {\n const { target, context } = disembargo;\n\n switch (context.type) {\n case 'senderLoopback':\n // Echo back as receiverLoopback\n await this.sendDisembargoEcho(disembargo);\n break;\n\n case 'receiverLoopback':\n // Embargo lifted - process any pending calls\n await this.liftEmbargo(context.embargoId);\n break;\n\n case 'accept':\n // Embargo on a third-party accept can be lifted\n await this.liftAcceptEmbargo(target);\n break;\n\n case 'provide':\n // Embargo on a provision can be lifted\n await this.liftProvideEmbargo(context.questionId);\n break;\n }\n }\n\n /**\n * Lift an embargo by ID.\n */\n private async liftEmbargo(embargoId: number): Promise<void> {\n // Find and process embargoed calls\n const calls = this.embargoedCalls.get(embargoId);\n if (calls) {\n for (const call of calls) {\n // Re-send the call\n await this.resendEmbargoedCall(call);\n }\n this.embargoedCalls.delete(embargoId);\n }\n }\n\n /**\n * Lift an embargo on an accept.\n */\n private async liftAcceptEmbargo(target: MessageTarget): Promise<void> {\n // Find pending accepts for this target and complete them\n for (const [questionId, pendingAccept] of this.pendingAccepts) {\n if (this.matchesTarget(pendingAccept.provision.targetExportId, target)) {\n // Return the capability\n const capDescriptor: CapDescriptor = {\n type: 'senderHosted',\n exportId: pendingAccept.provision.targetExportId as ExportId,\n };\n\n await this.sendReturnCapability(pendingAccept.questionId, capDescriptor);\n this.pendingAccepts.delete(questionId);\n }\n }\n }\n\n /**\n * Lift an embargo on a provide.\n */\n private async liftProvideEmbargo(_questionId: number): Promise<void> {\n // Find the pending provision and mark it as no longer embargoed\n const { connectionManager } = this.options;\n\n for (const _provision of connectionManager.getAllConnections()) {\n // This is a simplified implementation\n // In a full implementation, we'd track provisions by question ID\n }\n }\n\n // ========================================================================================\n // Third-Party Capability Handling\n // ========================================================================================\n\n /**\n * Handle receiving a third-party capability.\n *\n * When we receive a CapDescriptor with type 'thirdPartyHosted', we need to:\n * 1. Establish a connection to the third party (if not already connected)\n * 2. Send an Accept message to pick up the capability\n * 3. Return a local import ID for the capability\n */\n async handleThirdPartyCapability(\n thirdPartyCapId: ThirdPartyCapId\n ): Promise<ImportId | undefined> {\n const { connectionManager } = this.options;\n\n // Resolve the third-party capability\n const resolved = await connectionManager.resolveThirdPartyCap(thirdPartyCapId);\n if (!resolved) {\n return undefined;\n }\n\n const { connection, provisionId } = resolved;\n\n // Send Accept to pick up the capability\n const importId = await this.sendAccept(connection, provisionId);\n\n return importId;\n }\n\n /**\n * Create a third-party capability descriptor.\n *\n * This is called when we want to pass a capability to a peer, but the capability\n * is actually hosted by a third party. We create a ThirdPartyCapId that allows\n * the recipient to connect directly to the third party.\n */\n createThirdPartyCapDescriptor(\n _hostedConnection: RpcConnection,\n exportId: ExportId,\n recipientVatId: VatId\n ): CapDescriptor {\n const { connectionManager, selfVatId } = this.options;\n\n // Generate a provision ID\n const provisionId = generateProvisionId();\n\n // Create the ThirdPartyCapId\n // Format: [selfVatId (32 bytes)] [provisionId (32 bytes)]\n const thirdPartyCapId = createThirdPartyCapId(selfVatId, provisionId);\n\n // Create a pending provision for this\n connectionManager.createPendingProvision(\n provisionId,\n recipientVatId,\n exportId,\n 0, // No question ID for this type of provision\n false\n );\n\n return {\n type: 'thirdPartyHosted',\n thirdPartyCapId,\n };\n }\n\n // ========================================================================================\n // Helper Methods\n // ========================================================================================\n\n private extractTargetExportId(target: MessageTarget): number | undefined {\n if (target.type === 'importedCap') {\n return target.importId;\n }\n // promisedAnswer targets are not supported for Provide\n return undefined;\n }\n\n private recipientIdToVatId(recipient: RecipientId): VatId {\n return { id: recipient.id };\n }\n\n private matchesTarget(exportId: number, target: MessageTarget): boolean {\n if (target.type === 'importedCap') {\n return target.importId === exportId;\n }\n return false;\n }\n\n private async sendReturnResults(questionId: number, _results: unknown): Promise<void> {\n const { connection } = this.options;\n\n // In a full implementation, we'd serialize the results\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'results',\n payload: {\n content: new Uint8Array(0),\n capTable: [],\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendReturnCapability(questionId: number, cap: CapDescriptor): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'results',\n payload: {\n content: new Uint8Array(0),\n capTable: [cap],\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendReturnException(questionId: number, reason: string): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'exception',\n exception: {\n reason,\n type: 'failed',\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendReturnResultsSentElsewhere(questionId: number): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'resultsSentElsewhere',\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendDisembargoEcho(disembargo: Disembargo): Promise<void> {\n const { connection } = this.options;\n\n if (disembargo.context.type !== 'senderLoopback') {\n return;\n }\n\n const echoMsg: RpcMessage = {\n type: 'disembargo',\n disembargo: {\n target: disembargo.target,\n context: {\n type: 'receiverLoopback',\n embargoId: disembargo.context.embargoId,\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendDisembargo(echoMsg.disembargo);\n }\n\n private async resendEmbargoedCall(_call: EmbargoedCall): Promise<void> {\n // In a full implementation, we'd re-send the call\n // For now, this is a placeholder\n }\n}\n\n/** Pending accept waiting for embargo to be lifted */\ninterface PendingAccept {\n questionId: number;\n provision: PendingProvision;\n embargoId: number;\n}\n\n/** An embargoed call waiting to be re-sent */\ninterface EmbargoedCall {\n questionId: number;\n target: MessageTarget;\n interfaceId: bigint;\n methodId: number;\n params: unknown;\n embargoId: number;\n}\n","/**\n * Level 4 RPC: Reference Equality / Join Operations\n *\n * Level 4 RPC allows verifying that capability references received from different\n * sources point to the same underlying object. This is crucial for:\n *\n * 1. **Escrow Agents**: Verifying that two parties are referring to the same object\n * before acting as a trusted intermediary.\n * 2. **Consensus Verification**: Ensuring multiple parties agree on the identity\n * of an object.\n * 3. **Security**: Preventing spoofing attacks where an attacker might try to\n * substitute a different object.\n *\n * ## Core Concept\n *\n * When Alice receives capability references from both Bob and Carol that should\n * point to the same object (e.g., a shared resource), she can use Join to verify\n * this:\n *\n * ```\n * Alice receives cap1 from Bob → points to object X (via proxy P1)\n * Alice receives cap2 from Carol → points to object X (via proxy P2)\n * Alice sends Join(cap1, cap2) to P1\n * P1 verifies that both caps point to the same underlying object\n * Result: confirmed equal or not equal\n * ```\n *\n * ## Object Identity\n *\n * Object identity is determined by:\n * - **Vat ID**: The vat hosting the object\n * - **Object ID**: A unique identifier within that vat\n * - **Identity Hash**: A cryptographic hash of the object's identity\n *\n * ## Join Protocol\n *\n * 1. Alice sends Join message to the first capability's host (P1)\n * 2. P1 receives the Join request with two capability references\n * 3. P1 verifies that both references resolve to the same underlying object\n * 4. P1 returns the result (equal or not equal)\n *\n * ## Escrow Agent Pattern\n *\n * ```\n * Bob wants to sell an object to Carol\n * Alice acts as escrow agent\n * Bob sends Alice a reference to the object\n * Carol sends Alice a reference to the same object\n * Alice verifies (via Join) that both refer to the same object\n * Alice holds payment from Carol\n * Bob transfers object to Carol\n * Alice releases payment to Bob\n * ```\n *\n * ## Implementation Notes\n *\n * - Join operations are idempotent\n * - Results are cached to avoid redundant verification\n * - Multiple capabilities can be joined in a single operation\n * - The operation may involve network calls to resolve proxies\n *\n * @module level4-handlers\n */\n\n/**\n * Object identity information used for equality verification.\n */\nexport interface ObjectIdentity {\n /** The vat ID of the object host */\n vatId: Uint8Array;\n\n /** The unique object ID within the vat */\n objectId: Uint8Array;\n\n /** Optional identity hash/fingerprint for verification */\n identityHash?: Uint8Array;\n\n /** Timestamp when this identity was established */\n establishedAt: number;\n}\n\n/**\n * Result of a Join operation.\n */\nexport interface JoinResult {\n /** Whether the capabilities are equal (point to the same object) */\n equal: boolean;\n\n /** If equal, the shared object identity */\n identity?: ObjectIdentity;\n\n /** If not equal, reasons for inequality */\n inequalityReason?: string;\n\n /** The join operation ID */\n joinId: number;\n}\n\n/**\n * Options for a Join operation.\n */\nexport interface JoinOptions {\n /** Timeout for the join operation in milliseconds */\n timeoutMs?: number;\n\n /** Whether to require cryptographic verification */\n requireCryptoVerification?: boolean;\n\n /** Whether to cache the result */\n cacheResult?: boolean;\n\n /** TTL for cached results in milliseconds */\n cacheTtlMs?: number;\n}\n\n/**\n * Default join options.\n */\nexport const DEFAULT_JOIN_OPTIONS: Required<JoinOptions> = {\n timeoutMs: 30000,\n requireCryptoVerification: true,\n cacheResult: true,\n cacheTtlMs: 300000, // 5 minutes\n};\n\n/**\n * Status of a pending Join operation.\n */\nexport interface PendingJoin {\n /** The join operation ID */\n joinId: number;\n\n /** The first capability target */\n target1: unknown;\n\n /** The second capability target */\n target2: unknown;\n\n /** When the join was initiated */\n startedAt: number;\n\n /** Resolve function for the promise */\n resolve: (result: JoinResult) => void;\n\n /** Reject function for the promise */\n reject: (error: Error) => void;\n}\n\n/**\n * Cached join result.\n */\nexport interface CachedJoinResult {\n /** The cached result */\n result: JoinResult;\n\n /** When the result was cached */\n cachedAt: number;\n\n /** The targets that were joined */\n targets: [string, string]; // Hashed target identifiers\n}\n\n/**\n * Configuration for the escrow agent mode.\n */\nexport interface EscrowConfig {\n /** Whether escrow mode is enabled */\n enabled: boolean;\n\n /** Required number of parties for consensus */\n requiredParties: number;\n\n /** Timeout for escrow operations */\n timeoutMs: number;\n\n /** Callback when consensus is reached */\n onConsensus?: (identity: ObjectIdentity, parties: string[]) => void;\n\n /** Callback when consensus fails */\n onConsensusFailure?: (reason: string, parties: string[]) => void;\n}\n\n/**\n * Default escrow configuration.\n */\nexport const DEFAULT_ESCROW_CONFIG: EscrowConfig = {\n enabled: false,\n requiredParties: 2,\n timeoutMs: 60000,\n};\n\n/**\n * Security policy for Join operations.\n */\nexport interface JoinSecurityPolicy {\n /** Whether to verify identity hashes */\n verifyIdentityHashes: boolean;\n\n /** Whether to check for revoked objects */\n checkRevocation: boolean;\n\n /** Maximum depth for proxy resolution */\n maxProxyDepth: number;\n\n /** Whether to log all join operations */\n auditLog: boolean;\n\n /** Allowed vats for join operations (empty = all allowed) */\n allowedVats: Uint8Array[];\n}\n\n/**\n * Default join security policy.\n */\nexport const DEFAULT_JOIN_SECURITY_POLICY: JoinSecurityPolicy = {\n verifyIdentityHashes: true,\n checkRevocation: true,\n maxProxyDepth: 10,\n auditLog: true,\n allowedVats: [],\n};\n","/**\n * Level 4 RPC: Reference Equality / Join Operations\n *\n * This module implements the Level 4 RPC protocol for verifying that capability\n * references point to the same underlying object.\n *\n * Reference: https://capnproto.org/rpc.html (Level 4: Reference equality / joining)\n */\n\nimport type { ConnectionManager, VatId } from './connection-manager.js';\nimport type { Level3Handlers } from './level3-handlers.js';\nimport {\n type CachedJoinResult,\n DEFAULT_ESCROW_CONFIG,\n DEFAULT_JOIN_OPTIONS,\n DEFAULT_JOIN_SECURITY_POLICY,\n type EscrowConfig,\n type JoinOptions,\n type JoinResult,\n type JoinSecurityPolicy,\n type ObjectIdentity,\n type PendingJoin,\n} from './level4-types.js';\nimport type { RpcConnection } from './rpc-connection.js';\nimport type { Join, MessageTarget, QuestionId, RpcMessage } from './rpc-types.js';\n\n/** Options for Level4Handlers */\nexport interface Level4HandlersOptions {\n /** The connection this handler is attached to */\n connection: RpcConnection;\n\n /** The connection manager for multi-vat scenarios */\n connectionManager?: ConnectionManager;\n\n /** Level 3 handlers (required for proxy resolution) */\n level3Handlers?: Level3Handlers;\n\n /** This vat's ID */\n selfVatId?: VatId;\n\n /** Join operation options */\n joinOptions?: JoinOptions;\n\n /** Escrow agent configuration */\n escrowConfig?: EscrowConfig;\n\n /** Security policy */\n securityPolicy?: JoinSecurityPolicy;\n\n /** Handler for incoming Join messages */\n onJoin?: (join: Join) => Promise<JoinResult>;\n}\n\n/**\n * Manages Level 4 RPC message handling for reference equality verification.\n *\n * This class handles:\n * 1. Join messages - verifying that two capabilities point to the same object\n * 2. Object identity tracking and caching\n * 3. Escrow agent functionality for consensus verification\n * 4. Security verification (anti-spoofing)\n *\n * ## Usage Example\n *\n * ```typescript\n * const level4Handlers = new Level4Handlers({\n * connection,\n * connectionManager,\n * level3Handlers,\n * selfVatId,\n * });\n *\n * // Enable escrow mode for consensus verification\n * level4Handlers.setEscrowConfig({\n * enabled: true,\n * requiredParties: 2,\n * });\n *\n * // Send a Join request\n * const result = await level4Handlers.sendJoin(target1, target2);\n * if (result.equal) {\n * console.log('Capabilities point to the same object!');\n * }\n * ```\n */\nexport class Level4Handlers {\n private options: Level4HandlersOptions;\n private pendingJoins = new Map<number, PendingJoin>();\n private joinResultsCache = new Map<string, CachedJoinResult>();\n private objectIdentities = new Map<number, ObjectIdentity>();\n private nextJoinId = 1;\n private escrowConfig: EscrowConfig;\n private securityPolicy: JoinSecurityPolicy;\n private joinOptions: Required<JoinOptions>;\n\n // Escrow state\n private escrowParties = new Map<string, { target: unknown; identity?: ObjectIdentity }>();\n private escrowConsensus?: {\n identity: ObjectIdentity;\n parties: string[];\n };\n\n constructor(options: Level4HandlersOptions) {\n this.options = options;\n this.escrowConfig = { ...DEFAULT_ESCROW_CONFIG, ...options.escrowConfig };\n this.securityPolicy = { ...DEFAULT_JOIN_SECURITY_POLICY, ...options.securityPolicy };\n this.joinOptions = { ...DEFAULT_JOIN_OPTIONS, ...options.joinOptions };\n }\n\n // ========================================================================================\n // Join Message Handling\n // ========================================================================================\n\n /**\n * Handle an incoming Join message.\n *\n * When we receive a Join message, we need to verify whether the two\n * capability references point to the same underlying object.\n *\n * The verification process:\n * 1. Resolve both targets to their underlying objects\n * 2. Compare object identities (vat ID + object ID)\n * 3. Optionally verify identity hashes cryptographically\n * 4. Return the result\n */\n async handleJoin(join: Join): Promise<void> {\n const { questionId, target, otherCap, joinId } = join;\n\n try {\n // Check cache first\n const cacheKey = this.getCacheKey(target, otherCap);\n const cached = this.joinResultsCache.get(cacheKey);\n if (cached && Date.now() - cached.cachedAt < this.joinOptions.cacheTtlMs) {\n await this.sendJoinResult(questionId, cached.result);\n return;\n }\n\n // Resolve both targets to their identities\n const identity1 = await this.resolveTargetToIdentity(target);\n const identity2 = await this.resolveTargetToIdentity(otherCap);\n\n // Compare identities\n const result = this.compareIdentities(identity1, identity2, joinId);\n\n // Cache the result if enabled\n if (this.joinOptions.cacheResult) {\n this.joinResultsCache.set(cacheKey, {\n result,\n cachedAt: Date.now(),\n targets: [this.hashTarget(target), this.hashTarget(otherCap)],\n });\n }\n\n // Log for audit if enabled\n if (this.securityPolicy.auditLog) {\n this.logJoinOperation(target, otherCap, result);\n }\n\n // Send the result\n await this.sendJoinResult(questionId, result);\n\n // Call custom handler if provided\n if (this.options.onJoin) {\n await this.options.onJoin(join);\n }\n } catch (error) {\n // Send exception result\n await this.sendJoinException(\n questionId,\n error instanceof Error ? error.message : 'Join operation failed'\n );\n }\n }\n\n /**\n * Send a Join message to verify that two capabilities point to the same object.\n *\n * @param target1 First capability target\n * @param target2 Second capability target\n * @returns Promise resolving to the join result\n */\n async sendJoin(target1: MessageTarget, target2: MessageTarget): Promise<JoinResult> {\n const { connection } = this.options;\n const joinId = this.nextJoinId++;\n const questionId = connection.createQuestion();\n\n // Create pending join\n const pendingJoin: PendingJoin = {\n joinId,\n target1,\n target2,\n startedAt: Date.now(),\n resolve: () => {},\n reject: () => {},\n };\n\n const completionPromise = new Promise<JoinResult>((resolve, reject) => {\n pendingJoin.resolve = resolve;\n pendingJoin.reject = reject;\n });\n\n this.pendingJoins.set(joinId, pendingJoin);\n\n // Set timeout\n const timeoutMs = this.joinOptions.timeoutMs;\n const timeoutId = setTimeout(() => {\n this.pendingJoins.delete(joinId);\n pendingJoin.reject(new Error(`Join operation timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n // Override resolve to clear timeout\n const originalResolve = pendingJoin.resolve;\n pendingJoin.resolve = (result: JoinResult) => {\n clearTimeout(timeoutId);\n this.pendingJoins.delete(joinId);\n originalResolve(result);\n };\n\n try {\n const joinMsg: RpcMessage = {\n type: 'join',\n join: {\n questionId,\n target: target1,\n otherCap: target2,\n joinId,\n },\n };\n\n await connection.sendCall(joinMsg.join as any);\n\n // Wait for the result\n const result = await completionPromise;\n return result;\n } catch (error) {\n clearTimeout(timeoutId);\n this.pendingJoins.delete(joinId);\n throw error;\n }\n }\n\n /**\n * Complete a pending join operation with the result.\n * This is called when we receive a Return message for a Join.\n */\n completeJoin(joinId: number, result: JoinResult): void {\n const pending = this.pendingJoins.get(joinId);\n if (pending) {\n pending.resolve(result);\n this.pendingJoins.delete(joinId);\n }\n }\n\n // ========================================================================================\n // Object Identity Resolution\n // ========================================================================================\n\n /**\n * Resolve a MessageTarget to its ObjectIdentity.\n *\n * This may involve:\n * 1. Looking up local exports\n * 2. Resolving promises\n * 3. Following third-party capabilities\n * 4. Verifying proxy chains\n */\n private async resolveTargetToIdentity(target: MessageTarget): Promise<ObjectIdentity | null> {\n if (target.type === 'importedCap') {\n // Check if we have cached identity for this import\n const cached = this.objectIdentities.get(target.importId);\n if (cached) {\n return cached;\n }\n\n // Get the import and resolve its identity\n const importEntry = this.options.connection.getImport(target.importId);\n if (!importEntry) {\n return null;\n }\n\n // For local imports, we need to query the remote vat for identity\n // In a full implementation, this would involve a network call\n // For now, return a placeholder\n return null;\n }\n\n if (target.type === 'promisedAnswer') {\n // Wait for the promise to resolve\n const { questionId } = target.promisedAnswer;\n\n // Wait for the answer\n try {\n const _answer = await this.options.connection.waitForAnswer(questionId);\n // Extract capability from answer and resolve identity\n // This is simplified - full implementation would handle transforms\n return null;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n\n /**\n * Compare two object identities for equality.\n */\n private compareIdentities(\n identity1: ObjectIdentity | null,\n identity2: ObjectIdentity | null,\n joinId: number\n ): JoinResult {\n // Both null = equal (both are null capabilities)\n if (!identity1 && !identity2) {\n return { equal: true, joinId };\n }\n\n // One null, one not = not equal\n if (!identity1 || !identity2) {\n return {\n equal: false,\n joinId,\n inequalityReason: 'One capability is null, the other is not',\n };\n }\n\n // Compare vat IDs\n if (!this.arraysEqual(identity1.vatId, identity2.vatId)) {\n return {\n equal: false,\n joinId,\n inequalityReason: 'Capabilities hosted by different vats',\n };\n }\n\n // Compare object IDs\n if (!this.arraysEqual(identity1.objectId, identity2.objectId)) {\n return {\n equal: false,\n joinId,\n inequalityReason: 'Different object IDs within the same vat',\n };\n }\n\n // Verify identity hashes if required\n if (this.securityPolicy.verifyIdentityHashes) {\n if (identity1.identityHash && identity2.identityHash) {\n if (!this.arraysEqual(identity1.identityHash, identity2.identityHash)) {\n return {\n equal: false,\n joinId,\n inequalityReason: 'Identity hash mismatch (possible spoofing attempt)',\n };\n }\n }\n }\n\n // All checks passed - identities are equal\n return {\n equal: true,\n joinId,\n identity: identity1,\n };\n }\n\n // ========================================================================================\n // Escrow Agent Functionality\n // ========================================================================================\n\n /**\n * Set the escrow configuration.\n */\n setEscrowConfig(config: Partial<EscrowConfig>): void {\n this.escrowConfig = { ...this.escrowConfig, ...config };\n }\n\n /**\n * Register a party in an escrow consensus verification.\n *\n * This is used when multiple parties need to verify they are referring\n * to the same object (e.g., in a trade or agreement).\n *\n * @param partyId Unique identifier for the party\n * @param target The capability reference from this party\n * @returns Whether consensus has been reached\n */\n async registerEscrowParty(\n partyId: string,\n target: unknown\n ): Promise<{ consensus: boolean; identity?: ObjectIdentity }> {\n if (!this.escrowConfig.enabled) {\n throw new Error('Escrow mode is not enabled');\n }\n\n // Check if party already registered\n if (this.escrowParties.has(partyId)) {\n throw new Error(`Party ${partyId} is already registered`);\n }\n\n // Register the party\n this.escrowParties.set(partyId, { target });\n\n // If we have enough parties, verify consensus\n if (this.escrowParties.size >= this.escrowConfig.requiredParties) {\n const consensus = await this.verifyEscrowConsensus();\n\n if (consensus.consensus) {\n this.escrowConsensus = {\n identity: consensus.identity!,\n parties: Array.from(this.escrowParties.keys()),\n };\n\n if (this.escrowConfig.onConsensus) {\n this.escrowConfig.onConsensus(consensus.identity!, Array.from(this.escrowParties.keys()));\n }\n } else {\n if (this.escrowConfig.onConsensusFailure) {\n this.escrowConfig.onConsensusFailure(\n consensus.reason!,\n Array.from(this.escrowParties.keys())\n );\n }\n }\n\n return { consensus: consensus.consensus, identity: consensus.identity };\n }\n\n return { consensus: false };\n }\n\n /**\n * Verify that all registered escrow parties refer to the same object.\n */\n private async verifyEscrowConsensus(): Promise<{\n consensus: boolean;\n identity?: ObjectIdentity;\n reason?: string;\n }> {\n const parties = Array.from(this.escrowParties.entries());\n\n if (parties.length < this.escrowConfig.requiredParties) {\n return { consensus: false, reason: 'Not enough parties registered' };\n }\n\n // Use the first party's target as the reference\n const [firstPartyId, firstParty] = parties[0];\n\n // Resolve first party's identity\n const firstIdentity = await this.resolveTargetToIdentity(firstParty.target as MessageTarget);\n if (!firstIdentity) {\n return { consensus: false, reason: `Could not resolve identity for party ${firstPartyId}` };\n }\n\n // Compare with all other parties\n for (const [partyId, party] of parties.slice(1)) {\n const identity = await this.resolveTargetToIdentity(party.target as MessageTarget);\n const comparison = this.compareIdentities(firstIdentity, identity, 0);\n\n if (!comparison.equal) {\n return {\n consensus: false,\n reason: `Party ${partyId} refers to a different object: ${comparison.inequalityReason}`,\n };\n }\n }\n\n // All parties refer to the same object\n return { consensus: true, identity: firstIdentity };\n }\n\n /**\n * Clear all escrow state.\n */\n clearEscrow(): void {\n this.escrowParties.clear();\n this.escrowConsensus = undefined;\n }\n\n /**\n * Get the current escrow consensus if reached.\n */\n getEscrowConsensus(): { identity: ObjectIdentity; parties: string[] } | undefined {\n return this.escrowConsensus;\n }\n\n // ========================================================================================\n // Security & Anti-Spoofing\n // ========================================================================================\n\n /**\n * Set the security policy.\n */\n setSecurityPolicy(policy: Partial<JoinSecurityPolicy>): void {\n this.securityPolicy = { ...this.securityPolicy, ...policy };\n }\n\n /**\n * Verify that a vat is allowed to participate in join operations.\n */\n private isVatAllowed(vatId: Uint8Array): boolean {\n if (this.securityPolicy.allowedVats.length === 0) {\n return true; // All vats allowed if no restrictions\n }\n\n return this.securityPolicy.allowedVats.some((allowed) => this.arraysEqual(allowed, vatId));\n }\n\n /**\n * Generate a cryptographic identity hash for an object.\n *\n * This creates a verifiable fingerprint of the object's identity\n * that can be used to detect spoofing attempts.\n */\n async generateIdentityHash(vatId: Uint8Array, objectId: Uint8Array): Promise<Uint8Array> {\n // Combine vat ID and object ID\n const combined = new Uint8Array(vatId.length + objectId.length);\n combined.set(vatId, 0);\n combined.set(objectId, vatId.length);\n\n // Use SubtleCrypto for hashing if available\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const hashBuffer = await crypto.subtle.digest('SHA-256', combined);\n return new Uint8Array(hashBuffer);\n }\n\n // Fallback: simple hash for Node.js\n const { createHash } = require('node:crypto');\n const hash = createHash('sha256');\n hash.update(combined);\n return hash.digest();\n }\n\n // ========================================================================================\n // Caching & Cleanup\n // ========================================================================================\n\n /**\n * Clear the join results cache.\n */\n clearCache(): void {\n this.joinResultsCache.clear();\n }\n\n /**\n * Clean up expired cache entries.\n */\n cleanupExpiredCache(): number {\n const now = Date.now();\n let removed = 0;\n\n for (const [key, entry] of this.joinResultsCache) {\n if (now - entry.cachedAt > this.joinOptions.cacheTtlMs) {\n this.joinResultsCache.delete(key);\n removed++;\n }\n }\n\n return removed;\n }\n\n /**\n * Get cache statistics.\n */\n getCacheStats(): { size: number; hitRate: number } {\n return {\n size: this.joinResultsCache.size,\n hitRate: 0, // Would need to track hits/misses\n };\n }\n\n // ========================================================================================\n // Helper Methods\n // ========================================================================================\n\n private getCacheKey(target1: MessageTarget, target2: MessageTarget): string {\n // Create a consistent cache key regardless of order\n const hash1 = this.hashTarget(target1);\n const hash2 = this.hashTarget(target2);\n\n // Sort to ensure (A,B) and (B,A) have the same key\n const sorted = [hash1, hash2].sort();\n return `join:${sorted[0]}:${sorted[1]}`;\n }\n\n private hashTarget(target: MessageTarget): string {\n if (target.type === 'importedCap') {\n return `import:${target.importId}`;\n }\n if (target.type === 'promisedAnswer') {\n return `answer:${target.promisedAnswer.questionId}`;\n }\n return 'unknown';\n }\n\n private arraysEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n private async sendJoinResult(questionId: QuestionId, result: JoinResult): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'results',\n payload: {\n content: this.serializeJoinResult(result),\n capTable: [],\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendJoinException(questionId: QuestionId, reason: string): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'exception',\n exception: {\n reason,\n type: 'failed',\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private serializeJoinResult(result: JoinResult): Uint8Array {\n // Simple serialization - in production, use proper Cap'n Proto encoding\n const obj = {\n equal: result.equal,\n joinId: result.joinId,\n inequalityReason: result.inequalityReason,\n };\n return new TextEncoder().encode(JSON.stringify(obj));\n }\n\n private logJoinOperation(\n target1: MessageTarget,\n target2: MessageTarget,\n result: JoinResult\n ): void {\n console.log('[Level4] Join operation:', {\n target1: this.hashTarget(target1),\n target2: this.hashTarget(target2),\n equal: result.equal,\n joinId: result.joinId,\n timestamp: new Date().toISOString(),\n });\n }\n}\n\n// Re-export types\nexport type {\n JoinOptions,\n ObjectIdentity,\n PendingJoin,\n CachedJoinResult,\n EscrowConfig,\n JoinSecurityPolicy,\n} from './level4-types.js';\nexport {\n DEFAULT_JOIN_OPTIONS,\n DEFAULT_ESCROW_CONFIG,\n DEFAULT_JOIN_SECURITY_POLICY,\n} from './level4-types.js';\n","/**\n * Stream Abstraction for Cap'n Proto RPC\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Provides Stream interface for bidirectional streaming with:\n * - Backpressure handling\n * - Flow control window management\n * - Chunked transfer\n * - Progress notifications\n */\n\nimport type { RpcMessage } from './rpc-types.js';\nimport type { RpcTransport } from './transport.js';\n\n/** Stream state */\nexport type StreamState = 'connecting' | 'open' | 'closing' | 'closed' | 'error';\n\n/** Stream direction */\nexport type StreamDirection = 'inbound' | 'outbound' | 'bidirectional';\n\n/** Stream priority levels */\nexport enum StreamPriority {\n CRITICAL = 0, // Must not drop, immediate delivery\n HIGH = 1, // High priority, minimal delay\n NORMAL = 2, // Normal priority (default)\n LOW = 3, // Low priority, can be delayed\n BACKGROUND = 4, // Background tasks, lowest priority\n}\n\n/** Flow control window configuration */\nexport interface FlowControlConfig {\n /** Initial window size in bytes */\n initialWindowSize: number;\n /** Maximum window size in bytes */\n maxWindowSize: number;\n /** Minimum window size before backpressure */\n minWindowSize: number;\n /** Window update threshold (update when window drops below this) */\n windowUpdateThreshold: number;\n /** Window update increment size */\n windowUpdateIncrement: number;\n}\n\n/** Default flow control configuration */\nexport const DEFAULT_FLOW_CONTROL: FlowControlConfig = {\n initialWindowSize: 65536, // 64KB\n maxWindowSize: 1048576, // 1MB\n minWindowSize: 4096, // 4KB\n windowUpdateThreshold: 16384, // 16KB\n windowUpdateIncrement: 32768, // 32KB\n};\n\n/** Stream configuration options */\nexport interface StreamOptions {\n /** Stream ID (unique within connection) */\n streamId: number;\n /** Stream direction */\n direction: StreamDirection;\n /** Stream priority */\n priority?: StreamPriority;\n /** Flow control configuration */\n flowControl?: Partial<FlowControlConfig>;\n /** Enable progress notifications */\n enableProgress?: boolean;\n /** Progress notification interval in bytes */\n progressInterval?: number;\n /** Stream metadata */\n metadata?: Record<string, string>;\n}\n\n/** Chunk of data in a stream */\nexport interface StreamChunk {\n /** Chunk data */\n data: Uint8Array;\n /** Whether this is the final chunk */\n endOfStream?: boolean;\n /** Chunk sequence number (for ordering) */\n sequenceNumber?: number;\n /** Timestamp when chunk was sent */\n timestamp?: number;\n}\n\n/** Progress notification */\nexport interface StreamProgress {\n /** Stream ID */\n streamId: number;\n /** Total bytes sent/received */\n bytesTransferred: number;\n /** Total bytes expected (if known) */\n totalBytes?: number;\n /** Progress percentage (0-100) */\n percentage?: number;\n /** Transfer rate in bytes per second */\n transferRate?: number;\n /** Estimated time remaining in milliseconds */\n estimatedTimeRemaining?: number;\n}\n\n/** Flow control window state */\ninterface FlowControlWindow {\n /** Current window size */\n currentSize: number;\n /** Maximum window size */\n maxSize: number;\n /** Bytes sent/received in current window */\n bytesInWindow: number;\n /** Whether backpressure is active */\n backpressureActive: boolean;\n}\n\n/** Stream event handlers */\nexport interface StreamEventHandlers {\n /** Called when data is received */\n onData?: (chunk: StreamChunk) => void | Promise<void>;\n /** Called when stream is opened */\n onOpen?: () => void;\n /** Called when stream is closed */\n onClose?: () => void;\n /** Called when progress updates */\n onProgress?: (progress: StreamProgress) => void;\n /** Called when backpressure state changes */\n onBackpressure?: (active: boolean) => void;\n /** Called when an error occurs */\n onError?: (error: Error) => void;\n}\n\n/**\n * Stream abstraction for Cap'n Proto RPC\n *\n * Manages bidirectional streaming with flow control and backpressure.\n */\nexport class Stream {\n private options: StreamOptions;\n private handlers: StreamEventHandlers;\n private state: StreamState = 'connecting';\n private error?: Error;\n\n // Flow control\n private sendWindow: FlowControlWindow;\n private receiveWindow: FlowControlWindow;\n private flowControlConfig: FlowControlConfig;\n\n // Data buffering\n private sendBuffer: StreamChunk[] = [];\n private receiveBuffer: StreamChunk[] = [];\n private maxBufferSize = 1048576; // 1MB max buffer\n\n // Progress tracking\n private bytesSent = 0;\n private bytesReceived = 0;\n private totalBytesExpected?: number;\n private lastProgressUpdate = 0;\n private progressUpdateInterval: number;\n private transferStartTime?: number;\n\n // Chunk sequencing\n private nextSendSequence = 0;\n private nextExpectedSequence = 0;\n\n // Promise resolvers for async operations\n private openResolver?: () => void;\n private openRejector?: (error: Error) => void;\n private closeResolver?: () => void;\n\n constructor(options: StreamOptions, handlers: StreamEventHandlers = {}) {\n this.options = options;\n this.handlers = handlers;\n\n // Initialize flow control\n this.flowControlConfig = {\n ...DEFAULT_FLOW_CONTROL,\n ...options.flowControl,\n };\n\n this.sendWindow = {\n currentSize: this.flowControlConfig.initialWindowSize,\n maxSize: this.flowControlConfig.maxWindowSize,\n bytesInWindow: 0,\n backpressureActive: false,\n };\n\n this.receiveWindow = {\n currentSize: this.flowControlConfig.initialWindowSize,\n maxSize: this.flowControlConfig.maxWindowSize,\n bytesInWindow: 0,\n backpressureActive: false,\n };\n\n this.progressUpdateInterval = options.progressInterval ?? 65536; // 64KB default\n }\n\n /** Get stream ID */\n get id(): number {\n return this.options.streamId;\n }\n\n /** Get stream direction */\n get direction(): StreamDirection {\n return this.options.direction;\n }\n\n /** Get stream priority */\n get priority(): StreamPriority {\n return this.options.priority ?? StreamPriority.NORMAL;\n }\n\n /** Get current stream state */\n get currentState(): StreamState {\n return this.state;\n }\n\n /** Get whether stream is open */\n get isOpen(): boolean {\n return this.state === 'open';\n }\n\n /** Get whether backpressure is active for sending */\n get isBackpressureActive(): boolean {\n return this.sendWindow.backpressureActive;\n }\n\n /** Get bytes sent */\n get bytesSentCount(): number {\n return this.bytesSent;\n }\n\n /** Get bytes received */\n get bytesReceivedCount(): number {\n return this.bytesReceived;\n }\n\n /** Get metadata */\n get metadata(): Record<string, string> | undefined {\n return this.options.metadata;\n }\n\n /**\n * Open the stream\n */\n async open(): Promise<void> {\n if (this.state !== 'connecting') {\n throw new Error(`Cannot open stream in state: ${this.state}`);\n }\n\n return new Promise((resolve, reject) => {\n this.openResolver = resolve;\n this.openRejector = reject;\n\n // Transition to open state\n this.transitionState('open');\n this.transferStartTime = Date.now();\n\n // Notify handlers\n this.handlers.onOpen?.();\n });\n }\n\n /**\n * Send data through the stream\n *\n * Respects flow control and handles backpressure.\n */\n async send(data: Uint8Array, endOfStream = false): Promise<void> {\n if (this.state !== 'open') {\n throw new Error(`Cannot send in state: ${this.state}`);\n }\n\n // Check if we need to wait for window update\n if (this.sendWindow.bytesInWindow + data.length > this.sendWindow.currentSize) {\n // Wait for window update\n await this.waitForWindowUpdate();\n }\n\n // Create chunk\n const chunk: StreamChunk = {\n data,\n endOfStream,\n sequenceNumber: this.nextSendSequence++,\n timestamp: Date.now(),\n };\n\n // Update flow control\n this.sendWindow.bytesInWindow += data.length;\n this.bytesSent += data.length;\n\n // Check for backpressure\n this.checkBackpressure();\n\n // Send the chunk\n await this.sendChunk(chunk);\n\n // Report progress\n this.reportProgress();\n }\n\n /**\n * Send a chunk of data\n *\n * Override in subclasses to implement actual transport.\n */\n protected async sendChunk(chunk: StreamChunk): Promise<void> {\n // To be implemented by transport-specific subclass\n // This base class just buffers\n this.sendBuffer.push(chunk);\n }\n\n /**\n * Receive data from the stream\n *\n * Returns buffered data or waits for new data.\n */\n async receive(): Promise<StreamChunk | null> {\n if (this.receiveBuffer.length > 0) {\n return this.receiveBuffer.shift()!;\n }\n\n if (this.state === 'closed') {\n return null;\n }\n\n // Wait for data\n return new Promise((resolve, reject) => {\n const checkBuffer = () => {\n if (this.receiveBuffer.length > 0) {\n resolve(this.receiveBuffer.shift()!);\n } else if (this.state === 'closed') {\n resolve(null);\n } else if (this.state === 'error') {\n reject(this.error ?? new Error('Stream error'));\n } else {\n setTimeout(checkBuffer, 10);\n }\n };\n checkBuffer();\n });\n }\n\n /**\n * Handle incoming chunk from transport\n */\n handleIncomingChunk(chunk: StreamChunk): void {\n if (this.state !== 'open' && this.state !== 'closing') {\n return;\n }\n\n // Update receive window\n this.receiveWindow.bytesInWindow += chunk.data.length;\n this.bytesReceived += chunk.data.length;\n\n // Check if we need to send window update\n this.checkReceiveWindow();\n\n // Buffer or deliver chunk\n if (this.handlers.onData) {\n // Deliver immediately if handler is registered\n Promise.resolve(this.handlers.onData(chunk)).catch((err) => {\n this.handleError(err);\n });\n } else {\n // Buffer for later\n this.receiveBuffer.push(chunk);\n }\n\n // Report progress\n this.reportProgress();\n\n // Handle end of stream\n if (chunk.endOfStream) {\n this.transitionState('closing');\n }\n }\n\n /**\n * Update the send window (called when receiving window update from peer)\n */\n updateSendWindow(increment: number): void {\n this.sendWindow.currentSize = Math.min(\n this.sendWindow.currentSize + increment,\n this.sendWindow.maxSize\n );\n\n // Check if we can release backpressure\n if (this.sendWindow.backpressureActive) {\n const available = this.sendWindow.currentSize - this.sendWindow.bytesInWindow;\n if (available >= this.flowControlConfig.minWindowSize) {\n this.sendWindow.backpressureActive = false;\n this.handlers.onBackpressure?.(false);\n }\n }\n }\n\n /**\n * Acknowledge received bytes (called to update peer's send window)\n */\n acknowledgeBytes(bytes: number): void {\n this.receiveWindow.bytesInWindow = Math.max(0, this.receiveWindow.bytesInWindow - bytes);\n\n // Check if we should send window update\n if (this.receiveWindow.bytesInWindow < this.flowControlConfig.windowUpdateThreshold) {\n this.sendWindowUpdate();\n }\n }\n\n /**\n * Close the stream gracefully\n */\n async close(): Promise<void> {\n if (this.state === 'closed' || this.state === 'closing') {\n return;\n }\n\n this.transitionState('closing');\n\n // Wait for any pending sends to complete\n await this.drainSendBuffer();\n\n // Send end-of-stream marker\n await this.sendChunk({ data: new Uint8Array(0), endOfStream: true });\n\n this.transitionState('closed');\n this.handlers.onClose?.();\n }\n\n /**\n * Abort the stream with an error\n */\n abort(error: Error): void {\n this.error = error;\n this.transitionState('error');\n this.handlers.onError?.(error);\n }\n\n /**\n * Set total bytes expected (for progress calculation)\n */\n setTotalBytesExpected(total: number): void {\n this.totalBytesExpected = total;\n }\n\n /**\n * Wait for the stream to be ready for sending\n */\n async ready(): Promise<void> {\n if (this.state === 'open' && !this.sendWindow.backpressureActive) {\n return;\n }\n\n if (this.state !== 'open') {\n throw new Error(`Stream not open: ${this.state}`);\n }\n\n return this.waitForWindowUpdate();\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private transitionState(newState: StreamState): void {\n const _oldState = this.state;\n this.state = newState;\n\n // Resolve/reject pending promises\n if (newState === 'open' && this.openResolver) {\n this.openResolver();\n this.openResolver = undefined;\n this.openRejector = undefined;\n } else if (newState === 'error' && this.openRejector) {\n this.openRejector(this.error ?? new Error('Stream error'));\n this.openResolver = undefined;\n this.openRejector = undefined;\n }\n\n if (newState === 'closed' && this.closeResolver) {\n this.closeResolver();\n this.closeResolver = undefined;\n }\n }\n\n private checkBackpressure(): void {\n const available = this.sendWindow.currentSize - this.sendWindow.bytesInWindow;\n\n if (available < this.flowControlConfig.minWindowSize && !this.sendWindow.backpressureActive) {\n this.sendWindow.backpressureActive = true;\n this.handlers.onBackpressure?.(true);\n }\n }\n\n private checkReceiveWindow(): void {\n if (this.receiveWindow.bytesInWindow < this.flowControlConfig.windowUpdateThreshold) {\n this.sendWindowUpdate();\n }\n }\n\n private async waitForWindowUpdate(): Promise<void> {\n return new Promise((resolve, reject) => {\n const checkWindow = () => {\n const available = this.sendWindow.currentSize - this.sendWindow.bytesInWindow;\n\n if (this.state === 'error') {\n reject(this.error ?? new Error('Stream error'));\n return;\n }\n\n if (this.state !== 'open') {\n reject(new Error('Stream closed'));\n return;\n }\n\n if (available >= this.flowControlConfig.minWindowSize) {\n resolve();\n return;\n }\n\n setTimeout(checkWindow, 10);\n };\n\n checkWindow();\n });\n }\n\n private async drainSendBuffer(): Promise<void> {\n // In the base Stream class, sendBuffer is just for buffering\n // Subclasses that actually send data should override this\n // For now, just clear the buffer\n this.sendBuffer.length = 0;\n }\n\n private sendWindowUpdate(): void {\n // To be implemented by transport layer\n // This would send a window update message to the peer\n }\n\n private reportProgress(): void {\n if (!this.options.enableProgress || !this.handlers.onProgress) {\n return;\n }\n\n const now = Date.now();\n const bytesTransferred = Math.max(this.bytesSent, this.bytesReceived);\n\n // Check if it's time to report progress\n if (bytesTransferred - this.lastProgressUpdate < this.progressUpdateInterval) {\n return;\n }\n\n this.lastProgressUpdate = bytesTransferred;\n\n // Calculate transfer rate\n let transferRate: number | undefined;\n if (this.transferStartTime) {\n const elapsed = (now - this.transferStartTime) / 1000;\n if (elapsed > 0) {\n transferRate = bytesTransferred / elapsed;\n }\n }\n\n // Calculate percentage and ETA\n let percentage: number | undefined;\n let estimatedTimeRemaining: number | undefined;\n\n if (this.totalBytesExpected && this.totalBytesExpected > 0) {\n percentage = Math.min(100, (bytesTransferred / this.totalBytesExpected) * 100);\n\n if (transferRate && transferRate > 0) {\n const remaining = this.totalBytesExpected - bytesTransferred;\n estimatedTimeRemaining = (remaining / transferRate) * 1000;\n }\n }\n\n const progress: StreamProgress = {\n streamId: this.id,\n bytesTransferred,\n totalBytes: this.totalBytesExpected,\n percentage,\n transferRate,\n estimatedTimeRemaining,\n };\n\n this.handlers.onProgress(progress);\n }\n\n private handleError(error: Error): void {\n this.error = error;\n this.transitionState('error');\n this.handlers.onError?.(error);\n }\n}\n\n/**\n * Create a new stream\n */\nexport function createStream(options: StreamOptions, handlers?: StreamEventHandlers): Stream {\n return new Stream(options, handlers);\n}\n\n/**\n * Check if an object is a Stream\n */\nexport function isStream(obj: unknown): obj is Stream {\n return obj instanceof Stream;\n}\n","/**\n * Bulk API - High-volume data transfer with flow control\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Features:\n * - Backpressure mechanism\n * - Flow control window management\n * - Chunked transfer\n * - Progress notifications\n */\n\nimport type { RpcConnection } from './rpc-connection.js';\nimport {\n DEFAULT_FLOW_CONTROL,\n type FlowControlConfig,\n Stream,\n type StreamChunk,\n type StreamEventHandlers,\n type StreamOptions,\n StreamPriority,\n type StreamProgress,\n} from './stream.js';\n\n/** Bulk transfer configuration */\nexport interface BulkTransferConfig {\n /** Chunk size for transfer */\n chunkSize: number;\n /** Flow control configuration */\n flowControl?: Partial<FlowControlConfig>;\n /** Enable progress notifications */\n enableProgress?: boolean;\n /** Progress notification interval in bytes */\n progressInterval?: number;\n /** Maximum concurrent chunks in flight */\n maxConcurrentChunks?: number;\n /** Timeout for chunk acknowledgment */\n chunkAckTimeoutMs?: number;\n}\n\n/** Default bulk transfer configuration */\nexport const DEFAULT_BULK_CONFIG: BulkTransferConfig = {\n chunkSize: 16384, // 16KB chunks\n enableProgress: true,\n progressInterval: 65536, // 64KB\n maxConcurrentChunks: 8, // 8 concurrent chunks\n chunkAckTimeoutMs: 30000, // 30 seconds\n};\n\n/** Bulk transfer state */\nexport type BulkTransferState =\n | 'pending'\n | 'transferring'\n | 'paused'\n | 'completed'\n | 'cancelled'\n | 'error';\n\n/** Bulk transfer direction */\nexport type BulkTransferDirection = 'upload' | 'download';\n\n/** Bulk transfer metadata */\nexport interface BulkTransferMetadata {\n /** Transfer ID */\n id: string;\n /** File or resource name */\n name?: string;\n /** Total size in bytes (if known) */\n totalSize?: number;\n /** MIME type */\n contentType?: string;\n /** Custom metadata */\n custom?: Record<string, string>;\n}\n\n/** Bulk transfer statistics */\nexport interface BulkTransferStats {\n /** Bytes transferred */\n bytesTransferred: number;\n /** Total bytes (if known) */\n totalBytes?: number;\n /** Transfer rate in bytes per second */\n transferRate: number;\n /** Time elapsed in milliseconds */\n elapsedTime: number;\n /** Estimated time remaining in milliseconds */\n estimatedTimeRemaining?: number;\n /** Number of chunks transferred */\n chunksTransferred: number;\n /** Number of chunks acknowledged */\n chunksAcknowledged: number;\n /** Current window size */\n currentWindowSize: number;\n /** Whether backpressure is active */\n backpressureActive: boolean;\n}\n\n/** Chunk acknowledgment */\ninterface ChunkAck {\n sequenceNumber: number;\n bytesAcknowledged: number;\n}\n\n/** Bulk transfer event handlers */\nexport interface BulkTransferHandlers {\n /** Called when transfer starts */\n onStart?: () => void;\n /** Called when progress updates */\n onProgress?: (progress: StreamProgress) => void;\n /** Called when backpressure state changes */\n onBackpressure?: (active: boolean) => void;\n /** Called when transfer completes */\n onComplete?: () => void;\n /** Called when transfer is cancelled */\n onCancel?: () => void;\n /** Called when an error occurs */\n onError?: (error: Error) => void;\n}\n\n/**\n * Bulk transfer manager\n *\n * Manages high-volume data transfers with flow control and backpressure.\n */\nexport class BulkTransfer {\n private stream: Stream;\n private config: BulkTransferConfig;\n private handlers: BulkTransferHandlers;\n private metadata: BulkTransferMetadata;\n private direction: BulkTransferDirection;\n\n // State\n private state: BulkTransferState = 'pending';\n private error?: Error;\n\n // Transfer tracking\n private chunksInFlight = 0;\n private chunksAcknowledged = 0;\n private totalChunks = 0;\n private startTime?: number;\n private endTime?: number;\n\n // Chunk tracking\n private pendingChunks: Map<\n number,\n { chunk: StreamChunk; timeout: ReturnType<typeof setTimeout> }\n > = new Map();\n private chunkAckCallbacks: Map<number, () => void> = new Map();\n\n // Flow control\n private currentWindowSize: number;\n\n // Data source/sink\n private dataSource?: AsyncIterable<Uint8Array> | (() => Promise<Uint8Array | null>);\n private dataSink?: (chunk: Uint8Array) => Promise<void>;\n\n constructor(\n stream: Stream,\n direction: BulkTransferDirection,\n metadata: BulkTransferMetadata,\n config: Partial<BulkTransferConfig> = {},\n handlers: BulkTransferHandlers = {}\n ) {\n this.stream = stream;\n this.direction = direction;\n this.metadata = metadata;\n this.config = { ...DEFAULT_BULK_CONFIG, ...config };\n this.handlers = handlers;\n this.currentWindowSize =\n this.config.flowControl?.initialWindowSize ?? DEFAULT_FLOW_CONTROL.initialWindowSize;\n\n // Set up stream event handlers\n this.setupStreamHandlers();\n }\n\n /** Get transfer ID */\n get id(): string {\n return this.metadata.id;\n }\n\n /** Get current state */\n get currentState(): BulkTransferState {\n return this.state;\n }\n\n /** Get transfer statistics */\n get stats(): BulkTransferStats {\n const now = Date.now();\n const elapsed = this.startTime ? (this.endTime ?? now) - this.startTime : 0;\n const bytesTransferred = this.stream.bytesSentCount + this.stream.bytesReceivedCount;\n\n let transferRate = 0;\n if (elapsed > 0) {\n transferRate = (bytesTransferred / elapsed) * 1000;\n }\n\n let estimatedTimeRemaining: number | undefined;\n if (this.metadata.totalSize && transferRate > 0) {\n const remaining = this.metadata.totalSize - bytesTransferred;\n estimatedTimeRemaining = (remaining / transferRate) * 1000;\n }\n\n return {\n bytesTransferred,\n totalBytes: this.metadata.totalSize,\n transferRate,\n elapsedTime: elapsed,\n estimatedTimeRemaining,\n chunksTransferred: this.chunksAcknowledged + this.pendingChunks.size,\n chunksAcknowledged: this.chunksAcknowledged,\n currentWindowSize: this.currentWindowSize,\n backpressureActive: this.stream.isBackpressureActive,\n };\n }\n\n /**\n * Set the data source for upload\n */\n setDataSource(source: AsyncIterable<Uint8Array> | (() => Promise<Uint8Array | null>)): void {\n if (this.direction !== 'upload') {\n throw new Error('Data source only valid for uploads');\n }\n this.dataSource = source;\n }\n\n /**\n * Set the data sink for download\n */\n setDataSink(sink: (chunk: Uint8Array) => Promise<void>): void {\n if (this.direction !== 'download') {\n throw new Error('Data sink only valid for downloads');\n }\n this.dataSink = sink;\n }\n\n /**\n * Start the bulk transfer\n */\n async start(): Promise<void> {\n if (this.state !== 'pending') {\n throw new Error(`Cannot start transfer in state: ${this.state}`);\n }\n\n this.state = 'transferring';\n this.startTime = Date.now();\n this.handlers.onStart?.();\n\n // Set total size for progress tracking\n if (this.metadata.totalSize) {\n this.stream.setTotalBytesExpected(this.metadata.totalSize);\n }\n\n try {\n if (this.direction === 'upload') {\n await this.performUpload();\n } else {\n await this.performDownload();\n }\n\n if (this.state === 'transferring') {\n this.state = 'completed';\n this.endTime = Date.now();\n this.handlers.onComplete?.();\n }\n } catch (err) {\n this.handleError(err as Error);\n }\n }\n\n /**\n * Pause the transfer\n */\n pause(): void {\n if (this.state === 'transferring') {\n this.state = 'paused';\n }\n }\n\n /**\n * Resume the transfer\n */\n resume(): void {\n if (this.state === 'paused') {\n this.state = 'transferring';\n }\n }\n\n /**\n * Cancel the transfer\n */\n cancel(): void {\n if (this.state === 'completed' || this.state === 'error' || this.state === 'cancelled') {\n return;\n }\n\n this.state = 'cancelled';\n this.endTime = Date.now();\n\n // Clear pending timeouts\n for (const { timeout } of this.pendingChunks.values()) {\n clearTimeout(timeout);\n }\n this.pendingChunks.clear();\n\n this.handlers.onCancel?.();\n }\n\n /**\n * Handle chunk acknowledgment from peer\n */\n handleChunkAck(ack: ChunkAck): void {\n const pending = this.pendingChunks.get(ack.sequenceNumber);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingChunks.delete(ack.sequenceNumber);\n this.chunksAcknowledged++;\n this.chunksInFlight--;\n\n // Update window size\n this.currentWindowSize += ack.bytesAcknowledged;\n\n // Resolve pending ack callback\n const callback = this.chunkAckCallbacks.get(ack.sequenceNumber);\n if (callback) {\n callback();\n this.chunkAckCallbacks.delete(ack.sequenceNumber);\n }\n }\n }\n\n /**\n * Update flow control window\n */\n updateWindow(newWindowSize: number): void {\n this.currentWindowSize = newWindowSize;\n this.stream.updateSendWindow(newWindowSize);\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private setupStreamHandlers(): void {\n const _streamHandlers: StreamEventHandlers = {\n onData: async (chunk) => {\n // Handle incoming data for downloads\n if (this.direction === 'download' && this.dataSink) {\n await this.dataSink(chunk.data);\n\n // Send acknowledgment\n await this.sendChunkAck(chunk.sequenceNumber ?? 0, chunk.data.length);\n }\n },\n onBackpressure: (active) => {\n this.handlers.onBackpressure?.(active);\n },\n onProgress: (progress) => {\n this.handlers.onProgress?.(progress);\n },\n onError: (error) => {\n this.handleError(error);\n },\n };\n\n // Note: Stream handlers are set during construction\n // This is a simplified implementation\n }\n\n private async performUpload(): Promise<void> {\n if (!this.dataSource) {\n throw new Error('No data source set for upload');\n }\n\n if (Symbol.asyncIterator in this.dataSource) {\n // AsyncIterable source\n for await (const data of this.dataSource as AsyncIterable<Uint8Array>) {\n if (this.state !== 'transferring') {\n break;\n }\n\n await this.sendChunkWithFlowControl(data);\n }\n } else {\n // Function source\n const sourceFn = this.dataSource as () => Promise<Uint8Array | null>;\n while (this.state === 'transferring') {\n const data = await sourceFn();\n if (!data || data.length === 0) {\n break;\n }\n\n await this.sendChunkWithFlowControl(data);\n }\n }\n\n // Wait for all chunks to be acknowledged\n await this.waitForAllAcks();\n }\n\n private async performDownload(): Promise<void> {\n if (!this.dataSink) {\n throw new Error('No data sink set for download');\n }\n\n // Download is handled by onData callback\n // Just wait for completion\n while (this.state === 'transferring') {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n\n private async sendChunkWithFlowControl(data: Uint8Array): Promise<void> {\n // Wait for available window\n while (this.chunksInFlight >= (this.config.maxConcurrentChunks ?? 8)) {\n if (this.state !== 'transferring') {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n\n // Wait for stream to be ready (backpressure)\n await this.stream.ready();\n\n const sequenceNumber = this.totalChunks++;\n\n // Send the chunk\n await this.stream.send(data, false);\n this.chunksInFlight++;\n\n // Set up acknowledgment timeout\n const timeout = setTimeout(() => {\n this.handleChunkTimeout(sequenceNumber);\n }, this.config.chunkAckTimeoutMs ?? 30000);\n\n this.pendingChunks.set(sequenceNumber, {\n chunk: { data, sequenceNumber, timestamp: Date.now() },\n timeout,\n });\n }\n\n private async sendChunkAck(_sequenceNumber: number, _bytes: number): Promise<void> {\n // Send acknowledgment to peer\n // This would be implemented via the RPC connection\n }\n\n private handleChunkTimeout(sequenceNumber: number): void {\n const pending = this.pendingChunks.get(sequenceNumber);\n if (pending) {\n this.pendingChunks.delete(sequenceNumber);\n this.chunksInFlight--;\n\n // Could implement retry logic here\n this.handleError(new Error(`Chunk ${sequenceNumber} acknowledgment timeout`));\n }\n }\n\n private async waitForAllAcks(): Promise<void> {\n // In a real implementation, we would wait for acknowledgments from the peer\n // For now, just clear pending chunks immediately (simulating immediate ack)\n // This allows the transfer to complete without actual network acknowledgments\n for (const [sequenceNumber, { timeout }] of this.pendingChunks) {\n clearTimeout(timeout);\n this.handleChunkAck({\n sequenceNumber,\n bytesAcknowledged: 0, // Unknown, but doesn't matter for completion\n });\n }\n this.pendingChunks.clear();\n }\n\n private handleError(error: Error): void {\n if (this.state === 'completed' || this.state === 'error') {\n return;\n }\n\n this.error = error;\n this.state = 'error';\n this.endTime = Date.now();\n\n // Clear pending timeouts\n for (const { timeout } of this.pendingChunks.values()) {\n clearTimeout(timeout);\n }\n\n this.handlers.onError?.(error);\n }\n}\n\n/**\n * Bulk transfer manager\n *\n * Manages multiple concurrent bulk transfers.\n */\nexport class BulkTransferManager {\n private transfers: Map<string, BulkTransfer> = new Map();\n private streams: Map<number, Stream> = new Map();\n private nextStreamId = 1;\n\n /**\n * Create a new bulk transfer\n */\n createTransfer(\n direction: BulkTransferDirection,\n metadata: BulkTransferMetadata,\n config?: Partial<BulkTransferConfig>,\n handlers?: BulkTransferHandlers\n ): BulkTransfer {\n const streamId = this.nextStreamId++;\n\n const streamOptions: StreamOptions = {\n streamId,\n direction: direction === 'upload' ? 'outbound' : 'inbound',\n priority: StreamPriority.NORMAL,\n enableProgress: config?.enableProgress ?? true,\n progressInterval: config?.progressInterval,\n flowControl: config?.flowControl,\n };\n\n const stream = new Stream(streamOptions, {\n onProgress: handlers?.onProgress,\n onBackpressure: handlers?.onBackpressure,\n onError: handlers?.onError,\n });\n\n this.streams.set(streamId, stream);\n\n const transfer = new BulkTransfer(stream, direction, metadata, config, handlers);\n this.transfers.set(metadata.id, transfer);\n\n return transfer;\n }\n\n /**\n * Get a transfer by ID\n */\n getTransfer(id: string): BulkTransfer | undefined {\n return this.transfers.get(id);\n }\n\n /**\n * Get a stream by ID\n */\n getStream(id: number): Stream | undefined {\n return this.streams.get(id);\n }\n\n /**\n * Remove a transfer\n */\n removeTransfer(id: string): boolean {\n const transfer = this.transfers.get(id);\n if (transfer) {\n transfer.cancel();\n this.transfers.delete(id);\n return true;\n }\n return false;\n }\n\n /**\n * Get all active transfers\n */\n getActiveTransfers(): BulkTransfer[] {\n return Array.from(this.transfers.values()).filter(\n (t) =>\n t.currentState === 'pending' ||\n t.currentState === 'transferring' ||\n t.currentState === 'paused'\n );\n }\n\n /**\n * Get transfer statistics summary\n */\n getStatsSummary(): {\n totalTransfers: number;\n activeTransfers: number;\n completedTransfers: number;\n totalBytesTransferred: number;\n } {\n const transfers = Array.from(this.transfers.values());\n const active = transfers.filter((t) => t.currentState === 'transferring');\n const completed = transfers.filter((t) => t.currentState === 'completed');\n\n const totalBytes = transfers.reduce((sum, t) => sum + t.stats.bytesTransferred, 0);\n\n return {\n totalTransfers: transfers.length,\n activeTransfers: active.length,\n completedTransfers: completed.length,\n totalBytesTransferred: totalBytes,\n };\n }\n\n /**\n * Close all transfers\n */\n async closeAll(): Promise<void> {\n for (const transfer of this.transfers.values()) {\n transfer.cancel();\n }\n this.transfers.clear();\n this.streams.clear();\n }\n}\n\n/**\n * Create a bulk transfer manager\n */\nexport function createBulkTransferManager(): BulkTransferManager {\n return new BulkTransferManager();\n}\n","/**\n * Realtime API - Real-time communication with prioritization\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Features:\n * - Message priority queues\n * - Message drop policies for latency-sensitive scenarios\n * - Bandwidth adaptation\n * - Jitter buffer management\n */\n\nimport {\n type FlowControlConfig,\n type Stream,\n type StreamChunk,\n type StreamOptions,\n StreamPriority,\n} from './stream.js';\n\n/** Message priority levels (extends StreamPriority) */\nexport { StreamPriority as MessagePriority };\n\n/** Message drop policy for latency-sensitive scenarios */\nexport enum DropPolicy {\n /** Never drop messages */\n NEVER = 'never',\n /** Drop oldest messages when queue is full */\n DROP_OLDEST = 'drop_oldest',\n /** Drop newest messages when queue is full */\n DROP_NEWEST = 'drop_newest',\n /** Drop low priority messages first */\n DROP_LOW_PRIORITY = 'drop_low_priority',\n /** Drop messages that exceed max latency */\n DROP_STALE = 'drop_stale',\n}\n\n/** Realtime stream configuration */\nexport interface RealtimeConfig {\n /** Target latency in milliseconds */\n targetLatencyMs: number;\n /** Maximum acceptable latency in milliseconds */\n maxLatencyMs: number;\n /** Jitter buffer size in milliseconds */\n jitterBufferMs: number;\n /** Message queue size limit */\n maxQueueSize: number;\n /** Drop policy for queue management */\n dropPolicy: DropPolicy;\n /** Enable adaptive bitrate */\n adaptiveBitrate: boolean;\n /** Minimum bitrate in bytes per second */\n minBitrate: number;\n /** Maximum bitrate in bytes per second */\n maxBitrate: number;\n /** Bandwidth measurement window in milliseconds */\n bandwidthWindowMs: number;\n}\n\n/** Default realtime configuration */\nexport const DEFAULT_REALTIME_CONFIG: RealtimeConfig = {\n targetLatencyMs: 50,\n maxLatencyMs: 200,\n jitterBufferMs: 30,\n maxQueueSize: 1000,\n dropPolicy: DropPolicy.DROP_STALE,\n adaptiveBitrate: true,\n minBitrate: 16000, // 16 KB/s\n maxBitrate: 10485760, // 10 MB/s\n bandwidthWindowMs: 1000,\n};\n\n/** Realtime message */\nexport interface RealtimeMessage {\n /** Message ID */\n id: string;\n /** Message priority */\n priority: StreamPriority;\n /** Message timestamp */\n timestamp: number;\n /** Message data */\n data: Uint8Array;\n /** Message type/category */\n type?: string;\n /** Sequence number for ordering */\n sequenceNumber: number;\n /** Whether message is critical (cannot be dropped) */\n critical?: boolean;\n}\n\n/** Bandwidth statistics */\nexport interface BandwidthStats {\n /** Current bitrate in bytes per second */\n currentBitrate: number;\n /** Measured bandwidth in bytes per second */\n measuredBandwidth: number;\n /** Packet loss rate (0-1) */\n packetLossRate: number;\n /** Average latency in milliseconds */\n averageLatencyMs: number;\n /** Jitter in milliseconds */\n jitterMs: number;\n /** Congestion level (0-1) */\n congestionLevel: number;\n}\n\n/** Jitter buffer entry */\ninterface JitterBufferEntry {\n message: RealtimeMessage;\n receivedAt: number;\n playoutTime: number;\n}\n\n/** Realtime stream event handlers */\nexport interface RealtimeStreamHandlers {\n /** Called when a message is received */\n onMessage?: (message: RealtimeMessage) => void | Promise<void>;\n /** Called when messages are dropped */\n onDrop?: (messages: RealtimeMessage[], reason: string) => void;\n /** Called when bandwidth is adapted */\n onBandwidthAdapt?: (newBitrate: number, stats: BandwidthStats) => void;\n /** Called when latency changes */\n onLatencyChange?: (latencyMs: number) => void;\n /** Called when stream is ready to play */\n onReady?: () => void;\n /** Called on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Priority queue for realtime messages\n */\nclass PriorityMessageQueue {\n private queues: Map<StreamPriority, RealtimeMessage[]> = new Map();\n private totalSize = 0;\n private maxSize: number;\n private dropPolicy: DropPolicy;\n private maxLatencyMs: number;\n\n constructor(maxSize: number, dropPolicy: DropPolicy, maxLatencyMs: number) {\n this.maxSize = maxSize;\n this.dropPolicy = dropPolicy;\n this.maxLatencyMs = maxLatencyMs;\n\n // Initialize queues for each priority level\n for (let i = 0; i <= 4; i++) {\n this.queues.set(i as StreamPriority, []);\n }\n }\n\n /** Get total queue size */\n get size(): number {\n return this.totalSize;\n }\n\n /** Check if queue is empty */\n get isEmpty(): boolean {\n return this.totalSize === 0;\n }\n\n /** Enqueue a message */\n enqueue(message: RealtimeMessage): boolean {\n // Check if message is stale\n if (this.dropPolicy === DropPolicy.DROP_STALE) {\n const age = Date.now() - message.timestamp;\n if (age > this.maxLatencyMs && !message.critical) {\n return false; // Message dropped\n }\n }\n\n // Check if queue is full\n if (this.totalSize >= this.maxSize) {\n if (!this.handleQueueFull(message)) {\n return false;\n }\n }\n\n const queue = this.queues.get(message.priority)!;\n queue.push(message);\n this.totalSize++;\n\n return true;\n }\n\n /** Dequeue the highest priority message */\n dequeue(): RealtimeMessage | undefined {\n // Check queues from highest to lowest priority\n for (let priority = 0; priority <= 4; priority++) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0) {\n this.totalSize--;\n return queue.shift()!;\n }\n }\n return undefined;\n }\n\n /** Peek at the highest priority message without removing */\n peek(): RealtimeMessage | undefined {\n for (let priority = 0; priority <= 4; priority++) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0) {\n return queue[0];\n }\n }\n return undefined;\n }\n\n /** Remove stale messages */\n removeStale(): RealtimeMessage[] {\n const now = Date.now();\n const removed: RealtimeMessage[] = [];\n\n for (const [priority, queue] of this.queues) {\n const remaining: RealtimeMessage[] = [];\n for (const msg of queue) {\n if (now - msg.timestamp <= this.maxLatencyMs || msg.critical) {\n remaining.push(msg);\n } else {\n removed.push(msg);\n this.totalSize--;\n }\n }\n this.queues.set(priority, remaining);\n }\n\n return removed;\n }\n\n /** Clear all messages */\n clear(): RealtimeMessage[] {\n const all: RealtimeMessage[] = [];\n for (const queue of this.queues.values()) {\n all.push(...queue);\n }\n for (const queue of this.queues.values()) {\n queue.length = 0;\n }\n this.totalSize = 0;\n return all;\n }\n\n private handleQueueFull(newMessage: RealtimeMessage): boolean {\n switch (this.dropPolicy) {\n case DropPolicy.NEVER:\n return false;\n\n case DropPolicy.DROP_OLDEST:\n // Remove oldest message from lowest priority queue\n for (let priority = 4; priority >= 0; priority--) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0 && priority >= newMessage.priority) {\n queue.shift();\n this.totalSize--;\n return true;\n }\n }\n return false;\n\n case DropPolicy.DROP_NEWEST:\n // Don't add the new message if it's lower priority\n if (newMessage.priority >= StreamPriority.NORMAL) {\n return false;\n }\n return true;\n\n case DropPolicy.DROP_LOW_PRIORITY:\n // Remove a message from lower priority than the new message\n for (let priority = 4; priority > newMessage.priority; priority--) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0) {\n queue.shift();\n this.totalSize--;\n return true;\n }\n }\n return false;\n\n case DropPolicy.DROP_STALE: {\n // Remove stale messages first\n const stale = this.removeStale();\n if (stale.length > 0) {\n return true;\n }\n // Fall through to DROP_OLDEST\n for (let priority = 4; priority >= 0; priority--) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0 && priority >= newMessage.priority) {\n queue.shift();\n this.totalSize--;\n return true;\n }\n }\n return false;\n }\n\n default:\n return false;\n }\n }\n}\n\n/**\n * Realtime stream for low-latency communication\n *\n * Manages message prioritization, jitter buffering, and bandwidth adaptation.\n */\nexport class RealtimeStream {\n private stream: Stream;\n private config: RealtimeConfig;\n private handlers: RealtimeStreamHandlers;\n\n // Message queues\n private sendQueue: PriorityMessageQueue;\n private receiveQueue: PriorityMessageQueue;\n\n // Jitter buffer\n private jitterBuffer: JitterBufferEntry[] = [];\n private jitterBufferTargetSize: number;\n\n // Bandwidth adaptation\n private bandwidthStats: BandwidthStats = {\n currentBitrate: 0,\n measuredBandwidth: 0,\n packetLossRate: 0,\n averageLatencyMs: 0,\n jitterMs: 0,\n congestionLevel: 0,\n };\n private bitrateHistory: number[] = [];\n private latencyHistory: number[] = [];\n private lastBandwidthUpdate = 0;\n\n // Sequence numbers\n private nextSendSequence = 0;\n private nextExpectedSequence = 0;\n private receivedSequences: Set<number> = new Set();\n\n // State\n private isRunning = false;\n private sendInterval?: ReturnType<typeof setInterval>;\n private jitterInterval?: ReturnType<typeof setInterval>;\n private bandwidthInterval?: ReturnType<typeof setInterval>;\n\n constructor(\n stream: Stream,\n config: Partial<RealtimeConfig> = {},\n handlers: RealtimeStreamHandlers = {}\n ) {\n this.stream = stream;\n this.config = { ...DEFAULT_REALTIME_CONFIG, ...config };\n this.handlers = handlers;\n\n this.sendQueue = new PriorityMessageQueue(\n this.config.maxQueueSize,\n this.config.dropPolicy,\n this.config.maxLatencyMs\n );\n\n this.receiveQueue = new PriorityMessageQueue(\n this.config.maxQueueSize,\n this.config.dropPolicy,\n this.config.maxLatencyMs\n );\n\n // Calculate jitter buffer target size based on jitter buffer time\n this.jitterBufferTargetSize = Math.ceil(\n this.config.jitterBufferMs / this.config.targetLatencyMs\n );\n\n this.setupStreamHandlers();\n }\n\n /** Get current bandwidth statistics */\n get stats(): BandwidthStats {\n return { ...this.bandwidthStats };\n }\n\n /** Get current send queue size */\n get sendQueueSize(): number {\n return this.sendQueue.size;\n }\n\n /** Get current receive queue size */\n get receiveQueueSize(): number {\n return this.receiveQueue.size;\n }\n\n /** Get jitter buffer size */\n get jitterBufferSize(): number {\n return this.jitterBuffer.length;\n }\n\n /**\n * Start the realtime stream\n */\n start(): void {\n if (this.isRunning) return;\n\n this.isRunning = true;\n\n // Start send loop\n this.sendInterval = setInterval(() => {\n this.processSendQueue();\n }, this.config.targetLatencyMs / 2);\n\n // Start jitter buffer processing\n this.jitterInterval = setInterval(() => {\n this.processJitterBuffer();\n }, this.config.targetLatencyMs / 4);\n\n // Start bandwidth monitoring\n if (this.config.adaptiveBitrate) {\n this.bandwidthInterval = setInterval(() => {\n this.updateBandwidthStats();\n }, this.config.bandwidthWindowMs);\n }\n\n this.handlers.onReady?.();\n }\n\n /**\n * Stop the realtime stream\n */\n stop(): void {\n this.isRunning = false;\n\n if (this.sendInterval) {\n clearInterval(this.sendInterval);\n this.sendInterval = undefined;\n }\n\n if (this.jitterInterval) {\n clearInterval(this.jitterInterval);\n this.jitterInterval = undefined;\n }\n\n if (this.bandwidthInterval) {\n clearInterval(this.bandwidthInterval);\n this.bandwidthInterval = undefined;\n }\n\n // Clear queues\n const dropped = this.sendQueue.clear();\n if (dropped.length > 0) {\n this.handlers.onDrop?.(dropped, 'stream stopped');\n }\n }\n\n /**\n * Send a realtime message\n */\n sendMessage(\n data: Uint8Array,\n priority: StreamPriority = StreamPriority.NORMAL,\n options: { type?: string; critical?: boolean } = {}\n ): boolean {\n if (!this.isRunning) {\n return false;\n }\n\n const message: RealtimeMessage = {\n id: this.generateMessageId(),\n priority,\n timestamp: Date.now(),\n data,\n type: options.type,\n sequenceNumber: this.nextSendSequence++,\n critical: options.critical,\n };\n\n const enqueued = this.sendQueue.enqueue(message);\n\n if (!enqueued) {\n this.handlers.onDrop?.([message], 'queue full');\n return false;\n }\n\n return true;\n }\n\n /**\n * Receive the next message (blocking)\n */\n async receiveMessage(): Promise<RealtimeMessage | undefined> {\n return new Promise((resolve) => {\n const checkQueue = () => {\n const message = this.receiveQueue.dequeue();\n if (message) {\n resolve(message);\n } else if (!this.isRunning) {\n resolve(undefined);\n } else {\n setTimeout(checkQueue, 5);\n }\n };\n checkQueue();\n });\n }\n\n /**\n * Set target bitrate (for manual bitrate control)\n */\n setTargetBitrate(bitrate: number): void {\n this.bandwidthStats.currentBitrate = Math.max(\n this.config.minBitrate,\n Math.min(this.config.maxBitrate, bitrate)\n );\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private setupStreamHandlers(): void {\n // Set up stream data handler\n const originalOnData = (\n this.stream as unknown as { handlers?: { onData?: (chunk: StreamChunk) => void } }\n ).handlers?.onData;\n\n (this.stream as unknown as { handlers: { onData?: (chunk: StreamChunk) => void } }).handlers = {\n ...(this.stream as unknown as { handlers: { onData?: (chunk: StreamChunk) => void } })\n .handlers,\n onData: (chunk: StreamChunk) => {\n this.handleIncomingData(chunk);\n originalOnData?.(chunk);\n },\n };\n }\n\n private handleIncomingData(chunk: StreamChunk): void {\n try {\n // Parse message from chunk\n const message = this.deserializeMessage(chunk.data);\n\n // Track sequence number for packet loss calculation\n if (message.sequenceNumber > this.nextExpectedSequence) {\n // Packet loss detected\n const lost = message.sequenceNumber - this.nextExpectedSequence;\n this.bandwidthStats.packetLossRate = this.bandwidthStats.packetLossRate * 0.9 + lost * 0.1;\n }\n this.nextExpectedSequence = message.sequenceNumber + 1;\n\n // Calculate latency\n const latency = Date.now() - message.timestamp;\n this.latencyHistory.push(latency);\n if (this.latencyHistory.length > 100) {\n this.latencyHistory.shift();\n }\n\n // Add to jitter buffer\n const playoutTime = Date.now() + this.config.jitterBufferMs;\n this.jitterBuffer.push({\n message,\n receivedAt: Date.now(),\n playoutTime,\n });\n\n // Sort jitter buffer by sequence number\n this.jitterBuffer.sort((a, b) => a.message.sequenceNumber - b.message.sequenceNumber);\n } catch (error) {\n this.handlers.onError?.(error as Error);\n }\n }\n\n private processSendQueue(): void {\n if (!this.isRunning || this.sendQueue.isEmpty) {\n return;\n }\n\n // Check bandwidth limit\n if (this.config.adaptiveBitrate) {\n const currentBitrate = this.bandwidthStats.currentBitrate;\n const maxBytesPerInterval = (currentBitrate * this.config.targetLatencyMs) / 1000 / 2;\n\n let bytesSent = 0;\n while (bytesSent < maxBytesPerInterval) {\n const message = this.sendQueue.dequeue();\n if (!message) break;\n\n this.sendMessageToStream(message);\n bytesSent += message.data.length;\n }\n } else {\n // Send one message per interval\n const message = this.sendQueue.dequeue();\n if (message) {\n this.sendMessageToStream(message);\n }\n }\n\n // Remove stale messages from queue\n if (this.config.dropPolicy === DropPolicy.DROP_STALE) {\n const stale = this.sendQueue.removeStale();\n if (stale.length > 0) {\n this.handlers.onDrop?.(stale, 'stale');\n }\n }\n }\n\n private sendMessageToStream(message: RealtimeMessage): void {\n try {\n const data = this.serializeMessage(message);\n this.stream.send(data).catch((err) => {\n this.handlers.onError?.(err);\n });\n\n // Track bitrate\n this.bitrateHistory.push(data.length);\n if (this.bitrateHistory.length > 100) {\n this.bitrateHistory.shift();\n }\n } catch (error) {\n this.handlers.onError?.(error as Error);\n }\n }\n\n private processJitterBuffer(): void {\n if (!this.isRunning || this.jitterBuffer.length === 0) {\n return;\n }\n\n const now = Date.now();\n\n // Process messages that have reached their playout time\n while (this.jitterBuffer.length > 0) {\n const entry = this.jitterBuffer[0];\n\n // Wait until we have enough messages in the buffer\n if (this.jitterBuffer.length < this.jitterBufferTargetSize && entry.playoutTime > now) {\n break;\n }\n\n if (entry.playoutTime <= now) {\n this.jitterBuffer.shift();\n this.receiveQueue.enqueue(entry.message);\n this.handlers.onMessage?.(entry.message);\n } else {\n break;\n }\n }\n\n // Remove stale messages from jitter buffer\n const maxAge = this.config.maxLatencyMs * 2;\n const stale: RealtimeMessage[] = [];\n this.jitterBuffer = this.jitterBuffer.filter((entry) => {\n if (now - entry.receivedAt > maxAge && !entry.message.critical) {\n stale.push(entry.message);\n return false;\n }\n return true;\n });\n\n if (stale.length > 0) {\n this.handlers.onDrop?.(stale, 'jitter buffer stale');\n }\n }\n\n private updateBandwidthStats(): void {\n const now = Date.now();\n const windowMs = this.config.bandwidthWindowMs;\n\n // Calculate measured bandwidth\n if (this.bitrateHistory.length >= 2) {\n const totalBytes = this.bitrateHistory.reduce((a, b) => a + b, 0);\n this.bandwidthStats.measuredBandwidth = (totalBytes / windowMs) * 1000;\n }\n\n // Calculate average latency\n if (this.latencyHistory.length > 0) {\n const avgLatency =\n this.latencyHistory.reduce((a, b) => a + b, 0) / this.latencyHistory.length;\n this.bandwidthStats.averageLatencyMs = avgLatency;\n\n // Calculate jitter (standard deviation of latency)\n const variance =\n this.latencyHistory.reduce((sum, lat) => sum + (lat - avgLatency) ** 2, 0) /\n this.latencyHistory.length;\n this.bandwidthStats.jitterMs = Math.sqrt(variance);\n\n this.handlers.onLatencyChange?.(avgLatency);\n }\n\n // Calculate congestion level\n const queueUtilization = this.sendQueue.size / this.config.maxQueueSize;\n const latencyRatio = this.bandwidthStats.averageLatencyMs / this.config.targetLatencyMs;\n this.bandwidthStats.congestionLevel = Math.min(1, (queueUtilization + latencyRatio) / 2);\n\n // Adapt bitrate\n if (this.config.adaptiveBitrate) {\n this.adaptBitrate();\n }\n\n this.lastBandwidthUpdate = now;\n }\n\n private adaptBitrate(): void {\n const { congestionLevel, packetLossRate } = this.bandwidthStats;\n let newBitrate = this.bandwidthStats.currentBitrate;\n\n if (congestionLevel > 0.7 || packetLossRate > 0.05) {\n // Decrease bitrate\n newBitrate = newBitrate * 0.8;\n } else if (congestionLevel < 0.3 && packetLossRate < 0.01) {\n // Increase bitrate\n newBitrate = newBitrate * 1.05;\n }\n\n // Clamp to min/max\n newBitrate = Math.max(this.config.minBitrate, Math.min(this.config.maxBitrate, newBitrate));\n\n if (newBitrate !== this.bandwidthStats.currentBitrate) {\n this.bandwidthStats.currentBitrate = newBitrate;\n this.handlers.onBandwidthAdapt?.(newBitrate, this.bandwidthStats);\n }\n }\n\n private serializeMessage(message: RealtimeMessage): Uint8Array {\n // Simple serialization: JSON header + binary data\n const header = JSON.stringify({\n id: message.id,\n priority: message.priority,\n timestamp: message.timestamp,\n type: message.type,\n sequenceNumber: message.sequenceNumber,\n critical: message.critical,\n dataLength: message.data.length,\n });\n\n const headerBytes = new TextEncoder().encode(header);\n const headerLength = new Uint8Array(4);\n new DataView(headerLength.buffer).setUint32(0, headerBytes.length, true);\n\n const result = new Uint8Array(4 + headerBytes.length + message.data.length);\n result.set(headerLength, 0);\n result.set(headerBytes, 4);\n result.set(message.data, 4 + headerBytes.length);\n\n return result;\n }\n\n private deserializeMessage(data: Uint8Array): RealtimeMessage {\n const headerLength = new DataView(data.buffer, data.byteOffset, 4).getUint32(0, true);\n const headerBytes = data.slice(4, 4 + headerLength);\n const header = JSON.parse(new TextDecoder().decode(headerBytes));\n\n return {\n id: header.id,\n priority: header.priority,\n timestamp: header.timestamp,\n type: header.type,\n sequenceNumber: header.sequenceNumber,\n critical: header.critical,\n data: data.slice(4 + headerLength, 4 + headerLength + header.dataLength),\n };\n }\n\n private generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n}\n\n/**\n * Realtime stream manager\n */\nexport class RealtimeStreamManager {\n private streams: Map<number, RealtimeStream> = new Map();\n private nextStreamId = 1;\n\n /**\n * Create a new realtime stream\n */\n createStream(\n baseStream: Stream,\n config?: Partial<RealtimeConfig>,\n handlers?: RealtimeStreamHandlers\n ): RealtimeStream {\n const streamId = this.nextStreamId++;\n const stream = new RealtimeStream(baseStream, config, handlers);\n this.streams.set(streamId, stream);\n return stream;\n }\n\n /**\n * Get a stream by ID\n */\n getStream(id: number): RealtimeStream | undefined {\n return this.streams.get(id);\n }\n\n /**\n * Remove a stream\n */\n removeStream(id: number): boolean {\n const stream = this.streams.get(id);\n if (stream) {\n stream.stop();\n this.streams.delete(id);\n return true;\n }\n return false;\n }\n\n /**\n * Get all active streams\n */\n getActiveStreams(): RealtimeStream[] {\n return Array.from(this.streams.values());\n }\n\n /**\n * Stop all streams\n */\n stopAll(): void {\n for (const stream of this.streams.values()) {\n stream.stop();\n }\n this.streams.clear();\n }\n}\n\n/**\n * Create a realtime stream manager\n */\nexport function createRealtimeStreamManager(): RealtimeStreamManager {\n return new RealtimeStreamManager();\n}\n","/**\n * Stream Management - Unified stream lifecycle management\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Manages:\n * - Stream creation and registration\n * - Bidirectional stream support\n * - Stream lifecycle (open, close, error handling)\n * - Stream multiplexing over a single connection\n */\n\nimport {\n type BulkTransfer,\n type BulkTransferConfig,\n BulkTransferManager,\n type BulkTransferMetadata,\n} from './bulk.js';\nimport {\n type RealtimeConfig,\n type RealtimeStream,\n type RealtimeStreamHandlers,\n RealtimeStreamManager,\n} from './realtime.js';\nimport type { RpcConnection } from './rpc-connection.js';\nimport {\n Stream,\n type StreamDirection,\n type StreamOptions,\n StreamPriority,\n type StreamState,\n} from './stream.js';\nimport type { RpcTransport } from './transport.js';\n\n/** Stream type */\nexport enum StreamType {\n /** Standard stream */\n STANDARD = 'standard',\n /** Bulk transfer stream */\n BULK = 'bulk',\n /** Realtime stream */\n REALTIME = 'realtime',\n}\n\n/** Stream info */\nexport interface StreamInfo {\n /** Stream ID */\n id: number;\n /** Stream type */\n type: StreamType;\n /** Stream direction */\n direction: StreamDirection;\n /** Stream priority */\n priority: StreamPriority;\n /** Current state */\n state: StreamState;\n /** Creation timestamp */\n createdAt: number;\n /** Bytes transferred */\n bytesTransferred: number;\n /** Metadata */\n metadata?: Record<string, string>;\n}\n\n/** Stream manager configuration */\nexport interface StreamManagerConfig {\n /** Maximum number of concurrent streams */\n maxStreams: number;\n /** Default stream priority */\n defaultPriority: StreamPriority;\n /** Enable stream multiplexing */\n enableMultiplexing: boolean;\n /** Idle timeout in milliseconds */\n idleTimeoutMs: number;\n}\n\n/** Default stream manager configuration */\nexport const DEFAULT_STREAM_MANAGER_CONFIG: StreamManagerConfig = {\n maxStreams: 100,\n defaultPriority: StreamPriority.NORMAL,\n enableMultiplexing: true,\n idleTimeoutMs: 300000, // 5 minutes\n};\n\n/** Stream creation options */\nexport interface CreateStreamOptions {\n /** Stream type */\n type?: StreamType;\n /** Stream direction */\n direction?: StreamDirection;\n /** Stream priority */\n priority?: StreamPriority;\n /** Stream metadata */\n metadata?: Record<string, string>;\n /** Flow control configuration */\n flowControl?: Partial<import('./stream.js').FlowControlConfig>;\n}\n\n/** Stream manager event handlers */\nexport interface StreamManagerHandlers {\n /** Called when a stream is created */\n onStreamCreate?: (info: StreamInfo) => void;\n /** Called when a stream is opened */\n onStreamOpen?: (info: StreamInfo) => void;\n /** Called when a stream is closed */\n onStreamClose?: (info: StreamInfo) => void;\n /** Called when a stream errors */\n onStreamError?: (info: StreamInfo, error: Error) => void;\n /** Called when stream count changes */\n onStreamCountChange?: (count: number) => void;\n}\n\n/**\n * Stream manager\n *\n * Manages all streams for an RPC connection.\n */\nexport class StreamManager {\n private config: StreamManagerConfig;\n private handlers: StreamManagerHandlers;\n private connection?: RpcConnection;\n private transport?: RpcTransport;\n\n // Stream registries\n private streams: Map<number, Stream> = new Map();\n private streamTypes: Map<number, StreamType> = new Map();\n private streamInfos: Map<number, StreamInfo> = new Map();\n private nextStreamId = 1;\n\n // Sub-managers\n private bulkManager: BulkTransferManager;\n private realtimeManager: RealtimeStreamManager;\n\n // Lifecycle\n private idleTimeout?: ReturnType<typeof setTimeout>;\n private isRunning = false;\n\n constructor(config: Partial<StreamManagerConfig> = {}, handlers: StreamManagerHandlers = {}) {\n this.config = { ...DEFAULT_STREAM_MANAGER_CONFIG, ...config };\n this.handlers = handlers;\n this.bulkManager = new BulkTransferManager();\n this.realtimeManager = new RealtimeStreamManager();\n }\n\n /** Get the number of active streams */\n get streamCount(): number {\n return this.streams.size;\n }\n\n /** Get the maximum number of streams */\n get maxStreams(): number {\n return this.config.maxStreams;\n }\n\n /** Get all stream infos */\n get allStreamInfos(): StreamInfo[] {\n return Array.from(this.streamInfos.values());\n }\n\n /**\n * Attach to an RPC connection\n */\n attach(connection: RpcConnection, transport?: RpcTransport): void {\n this.connection = connection;\n this.transport = transport;\n this.isRunning = true;\n this.resetIdleTimeout();\n }\n\n /**\n * Detach from connection\n */\n detach(): void {\n this.closeAllStreams();\n this.isRunning = false;\n this.connection = undefined;\n this.transport = undefined;\n\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n this.idleTimeout = undefined;\n }\n }\n\n /**\n * Create a new stream\n */\n createStream(options: CreateStreamOptions = {}): Stream {\n if (this.streams.size >= this.config.maxStreams) {\n throw new Error(`Maximum number of streams (${this.config.maxStreams}) reached`);\n }\n\n const streamId = this.nextStreamId++;\n const type = options.type ?? StreamType.STANDARD;\n\n const streamOptions: StreamOptions = {\n streamId,\n direction: options.direction ?? 'bidirectional',\n priority: options.priority ?? this.config.defaultPriority ?? StreamPriority.NORMAL,\n metadata: options.metadata,\n flowControl: options.flowControl,\n };\n\n const stream = new Stream(streamOptions, {\n onOpen: () => {\n this.updateStreamState(streamId, 'open');\n this.handlers.onStreamOpen?.(this.getStreamInfo(streamId)!);\n },\n onClose: () => {\n this.updateStreamState(streamId, 'closed');\n this.handlers.onStreamClose?.(this.getStreamInfo(streamId)!);\n this.removeStream(streamId);\n },\n onError: (error) => {\n this.updateStreamState(streamId, 'error');\n const info = this.getStreamInfo(streamId);\n if (info) {\n this.handlers.onStreamError?.(info, error);\n }\n },\n });\n\n this.streams.set(streamId, stream);\n this.streamTypes.set(streamId, type);\n\n const info: StreamInfo = {\n id: streamId,\n type,\n direction: streamOptions.direction,\n priority: streamOptions.priority ?? StreamPriority.NORMAL,\n state: 'connecting',\n createdAt: Date.now(),\n bytesTransferred: 0,\n metadata: options.metadata,\n };\n this.streamInfos.set(streamId, info);\n\n this.handlers.onStreamCreate?.(info);\n this.handlers.onStreamCountChange?.(this.streams.size);\n\n this.resetIdleTimeout();\n\n return stream;\n }\n\n /**\n * Create a bulk transfer stream\n */\n createBulkStream(\n direction: 'upload' | 'download',\n metadata: BulkTransferMetadata,\n config?: Partial<BulkTransferConfig>,\n handlers?: import('./bulk.js').BulkTransferHandlers\n ): BulkTransfer {\n const _stream = this.createStream({\n type: StreamType.BULK,\n direction: direction === 'upload' ? 'outbound' : 'inbound',\n priority: StreamPriority.NORMAL,\n metadata: metadata.custom,\n });\n\n return this.bulkManager.createTransfer(direction, metadata, config, handlers);\n }\n\n /**\n * Create a realtime stream\n */\n createRealtimeStream(\n config?: Partial<RealtimeConfig>,\n handlers?: RealtimeStreamHandlers\n ): RealtimeStream {\n const stream = this.createStream({\n type: StreamType.REALTIME,\n direction: 'bidirectional',\n priority: StreamPriority.HIGH,\n });\n\n return this.realtimeManager.createStream(stream, config, handlers);\n }\n\n /**\n * Get a stream by ID\n */\n getStream(id: number): Stream | undefined {\n return this.streams.get(id);\n }\n\n /**\n * Get stream info by ID\n */\n getStreamInfo(id: number): StreamInfo | undefined {\n return this.streamInfos.get(id);\n }\n\n /**\n * Get stream type by ID\n */\n getStreamType(id: number): StreamType | undefined {\n return this.streamTypes.get(id);\n }\n\n /**\n * Get bulk transfer by ID\n */\n getBulkTransfer(id: string): BulkTransfer | undefined {\n return this.bulkManager.getTransfer(id);\n }\n\n /**\n * Get realtime stream by ID\n */\n getRealtimeStream(id: number): RealtimeStream | undefined {\n return this.realtimeManager.getStream(id);\n }\n\n /**\n * Close a specific stream\n */\n async closeStream(id: number): Promise<boolean> {\n const stream = this.streams.get(id);\n if (!stream) {\n return false;\n }\n\n await stream.close();\n this.removeStream(id);\n return true;\n }\n\n /**\n * Close all streams\n */\n async closeAllStreams(): Promise<void> {\n const closePromises: Promise<void>[] = [];\n\n for (const [_id, stream] of this.streams) {\n closePromises.push(\n stream.close().catch(() => {\n // Ignore errors during bulk close\n })\n );\n }\n\n await Promise.all(closePromises);\n\n this.streams.clear();\n this.streamTypes.clear();\n this.streamInfos.clear();\n this.bulkManager.closeAll();\n this.realtimeManager.stopAll();\n\n this.handlers.onStreamCountChange?.(0);\n }\n\n /**\n * Get streams by type\n */\n getStreamsByType(type: StreamType): StreamInfo[] {\n return this.allStreamInfos.filter((info) => info.type === type);\n }\n\n /**\n * Get streams by state\n */\n getStreamsByState(state: StreamState): StreamInfo[] {\n return this.allStreamInfos.filter((info) => info.state === state);\n }\n\n /**\n * Get statistics\n */\n getStatistics(): {\n totalStreams: number;\n activeStreams: number;\n streamsByType: Record<StreamType, number>;\n streamsByState: Record<StreamState, number>;\n totalBytesTransferred: number;\n } {\n const infos = this.allStreamInfos;\n const active = infos.filter((i) => i.state === 'open');\n\n const byType: Record<StreamType, number> = {\n [StreamType.STANDARD]: 0,\n [StreamType.BULK]: 0,\n [StreamType.REALTIME]: 0,\n };\n\n const byState: Record<StreamState, number> = {\n connecting: 0,\n open: 0,\n closing: 0,\n closed: 0,\n error: 0,\n };\n\n let totalBytes = 0;\n\n for (const info of infos) {\n byType[info.type]++;\n byState[info.state]++;\n totalBytes += info.bytesTransferred;\n }\n\n return {\n totalStreams: infos.length,\n activeStreams: active.length,\n streamsByType: byType,\n streamsByState: byState,\n totalBytesTransferred: totalBytes,\n };\n }\n\n /**\n * Update stream priority\n */\n updatePriority(id: number, priority: StreamPriority): boolean {\n const info = this.streamInfos.get(id);\n if (!info) {\n return false;\n }\n\n info.priority = priority;\n return true;\n }\n\n /**\n * Pause all streams (backpressure)\n */\n pauseAll(): void {\n for (const _stream of this.streams.values()) {\n // Streams don't have a direct pause method, but we can use backpressure\n // This is a simplified implementation\n }\n }\n\n /**\n * Resume all streams\n */\n resumeAll(): void {\n for (const _stream of this.streams.values()) {\n // Resume from backpressure\n }\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private removeStream(id: number): void {\n this.streams.delete(id);\n this.streamTypes.delete(id);\n this.streamInfos.delete(id);\n\n this.handlers.onStreamCountChange?.(this.streams.size);\n this.resetIdleTimeout();\n }\n\n private updateStreamState(id: number, state: StreamState): void {\n const info = this.streamInfos.get(id);\n if (info) {\n info.state = state;\n }\n }\n\n private resetIdleTimeout(): void {\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n }\n\n if (!this.isRunning || this.streams.size > 0) {\n return;\n }\n\n this.idleTimeout = setTimeout(() => {\n if (this.streams.size === 0) {\n // No active streams, could emit an event or take action\n }\n }, this.config.idleTimeoutMs);\n }\n}\n\n/**\n * Create a stream manager\n */\nexport function createStreamManager(\n config?: Partial<StreamManagerConfig>,\n handlers?: StreamManagerHandlers\n): StreamManager {\n return new StreamManager(config, handlers);\n}\n\n// Re-export types\nexport type { Stream, StreamOptions, StreamState, StreamDirection } from './stream.js';\nexport { StreamPriority } from './stream.js';\nexport type {\n BulkTransfer,\n BulkTransferConfig,\n BulkTransferMetadata,\n} from './bulk.js';\nexport { BulkTransferManager } from './bulk.js';\nexport type {\n RealtimeStream,\n RealtimeConfig,\n RealtimeStreamHandlers,\n} from './realtime.js';\nexport { RealtimeStreamManager } from './realtime.js';\n","/**\n * Streaming RpcConnection Extension\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Extends RpcConnection with streaming capabilities:\n * - Stream creation and management\n * - Integration with existing Pipeline\n * * Stream capability negotiation\n */\n\nimport type { BulkTransferConfig, BulkTransferHandlers, BulkTransferMetadata } from './bulk.js';\nimport type { RealtimeConfig, RealtimeStreamHandlers } from './realtime.js';\nimport { RpcConnection, type RpcConnectionOptions } from './rpc-connection.js';\nimport type { ExportId, ImportId, RpcMessage } from './rpc-types.js';\nimport {\n type BulkTransfer,\n type CreateStreamOptions,\n type RealtimeStream,\n type Stream,\n StreamManager,\n type StreamManagerConfig,\n type StreamManagerHandlers,\n StreamType,\n} from './stream-manager.js';\nimport type { RpcTransport } from './transport.js';\n\n/** Streaming capability flags */\nexport interface StreamingCapabilities {\n /** Standard streaming supported */\n standardStreams: boolean;\n /** Bulk transfer supported */\n bulkTransfer: boolean;\n /** Realtime streaming supported */\n realtimeStreams: boolean;\n /** Maximum concurrent streams */\n maxConcurrentStreams: number;\n /** Maximum stream window size */\n maxWindowSize: number;\n /** Supported flow control algorithms */\n flowControlAlgorithms: string[];\n}\n\n/** Default streaming capabilities */\nexport const DEFAULT_STREAMING_CAPABILITIES: StreamingCapabilities = {\n standardStreams: true,\n bulkTransfer: true,\n realtimeStreams: true,\n maxConcurrentStreams: 100,\n maxWindowSize: 1048576, // 1MB\n flowControlAlgorithms: ['sliding-window', 'rate-based'],\n};\n\n/** Extended RPC connection options with streaming */\nexport interface StreamingRpcConnectionOptions extends RpcConnectionOptions {\n /** Stream manager configuration */\n streamManagerConfig?: Partial<StreamManagerConfig>;\n /** Stream manager event handlers */\n streamManagerHandlers?: StreamManagerHandlers;\n /** Local streaming capabilities */\n localCapabilities?: Partial<StreamingCapabilities>;\n /** Enable streaming support */\n enableStreaming?: boolean;\n}\n\n/**\n * Extended RPC connection with streaming support\n *\n * This class wraps RpcConnection and adds stream management capabilities.\n * It can be used as a drop-in replacement for RpcConnection.\n */\nexport class StreamingRpcConnection extends RpcConnection {\n private streamManager: StreamManager;\n private localCapabilities: StreamingCapabilities;\n private remoteCapabilities?: StreamingCapabilities;\n private streamingEnabled: boolean;\n\n constructor(transport: RpcTransport, options: StreamingRpcConnectionOptions = {}) {\n super(transport, options);\n\n this.streamingEnabled = options.enableStreaming ?? true;\n this.localCapabilities = { ...DEFAULT_STREAMING_CAPABILITIES, ...options.localCapabilities };\n\n // Create stream manager\n this.streamManager = new StreamManager(\n options.streamManagerConfig,\n options.streamManagerHandlers\n );\n\n // Attach to this connection\n this.streamManager.attach(this, transport);\n\n // Set up capability negotiation if streaming is enabled\n if (this.streamingEnabled) {\n this.negotiateCapabilities();\n }\n }\n\n /** Get the stream manager */\n get streams(): StreamManager {\n return this.streamManager;\n }\n\n /** Get local streaming capabilities */\n get capabilities(): StreamingCapabilities {\n return this.localCapabilities;\n }\n\n /** Get remote streaming capabilities (if negotiated) */\n get remoteStreamingCapabilities(): StreamingCapabilities | undefined {\n return this.remoteCapabilities;\n }\n\n /** Check if streaming is enabled */\n get isStreamingEnabled(): boolean {\n return this.streamingEnabled;\n }\n\n /**\n * Create a new standard stream\n */\n createStream(options?: CreateStreamOptions): Stream {\n this.ensureStreamingEnabled();\n return this.streamManager.createStream(options);\n }\n\n /**\n * Create a bulk transfer stream\n */\n createBulkTransfer(\n direction: 'upload' | 'download',\n metadata: BulkTransferMetadata,\n config?: Partial<BulkTransferConfig>,\n handlers?: BulkTransferHandlers\n ): BulkTransfer {\n this.ensureStreamingEnabled();\n this.ensureCapability('bulkTransfer');\n return this.streamManager.createBulkStream(direction, metadata, config, handlers);\n }\n\n /**\n * Create a realtime stream\n */\n createRealtimeStream(\n config?: Partial<RealtimeConfig>,\n handlers?: RealtimeStreamHandlers\n ): RealtimeStream {\n this.ensureStreamingEnabled();\n this.ensureCapability('realtimeStreams');\n return this.streamManager.createRealtimeStream(config, handlers);\n }\n\n /**\n * Get stream statistics\n */\n getStreamStatistics(): ReturnType<StreamManager['getStatistics']> {\n return this.streamManager.getStatistics();\n }\n\n /**\n * Close all streams gracefully\n */\n async closeAllStreams(): Promise<void> {\n await this.streamManager.closeAllStreams();\n }\n\n /**\n * Override stop to properly clean up streams\n */\n override async stop(): Promise<void> {\n await this.closeAllStreams();\n this.streamManager.detach();\n await super.stop();\n }\n\n // =============================================================================\n // Capability Negotiation\n // =============================================================================\n\n /**\n * Negotiate streaming capabilities with remote peer\n *\n * This would typically be done during bootstrap or connection setup.\n * For now, we assume the remote has the same capabilities.\n */\n private async negotiateCapabilities(): Promise<void> {\n // In a full implementation, this would exchange capability messages\n // with the remote peer during connection setup.\n\n // For now, assume remote has same capabilities\n this.remoteCapabilities = { ...this.localCapabilities };\n\n // TODO: Implement actual capability exchange via RPC\n }\n\n /**\n * Update remote capabilities (called when received from peer)\n */\n setRemoteCapabilities(capabilities: StreamingCapabilities): void {\n this.remoteCapabilities = capabilities;\n }\n\n /**\n * Check if a specific capability is supported by both peers\n */\n isCapabilitySupported(capability: keyof StreamingCapabilities): boolean {\n const localValue = this.localCapabilities[capability];\n const remoteValue = this.remoteCapabilities?.[capability];\n\n // For boolean capabilities, both must be true\n if (typeof localValue === 'boolean' && typeof remoteValue === 'boolean') {\n return localValue && remoteValue;\n }\n\n // For numeric capabilities, use the minimum\n if (typeof localValue === 'number' && typeof remoteValue === 'number') {\n return localValue > 0 && remoteValue > 0;\n }\n\n return false;\n }\n\n // =============================================================================\n // Integration with Pipeline\n // =============================================================================\n\n /**\n * Create a stream for pipeline results\n *\n * This allows large pipeline results to be streamed instead of buffered.\n */\n createPipelineStream(questionId: number, options?: CreateStreamOptions): Stream {\n this.ensureStreamingEnabled();\n\n const stream = this.createStream({\n ...options,\n type: StreamType.STANDARD,\n metadata: {\n ...options?.metadata,\n pipelineQuestionId: questionId.toString(),\n },\n });\n\n return stream;\n }\n\n /**\n * Associate a stream with a capability\n *\n * This enables streaming data to/from a capability.\n */\n associateStreamWithCapability(streamId: number, _importId: ImportId | ExportId): void {\n const stream = this.streamManager.getStream(streamId);\n if (!stream) {\n throw new Error(`Stream ${streamId} not found`);\n }\n\n // Store association (would be used by the RPC layer)\n // This is a simplified implementation\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private ensureStreamingEnabled(): void {\n if (!this.streamingEnabled) {\n throw new Error('Streaming is not enabled on this connection');\n }\n }\n\n private ensureCapability(capability: keyof StreamingCapabilities): void {\n if (!this.isCapabilitySupported(capability)) {\n throw new Error(`Capability '${capability}' is not supported by both peers`);\n }\n }\n}\n\n/**\n * Create a streaming RPC connection\n */\nexport function createStreamingConnection(\n transport: RpcTransport,\n options?: StreamingRpcConnectionOptions\n): StreamingRpcConnection {\n return new StreamingRpcConnection(transport, options);\n}\n\n/**\n * Check if a connection supports streaming\n */\nexport function supportsStreaming(connection: RpcConnection): connection is StreamingRpcConnection {\n return connection instanceof StreamingRpcConnection;\n}\n\n// Re-export types from stream-manager\nexport type {\n StreamManager,\n StreamType,\n CreateStreamOptions,\n StreamManagerConfig,\n StreamManagerHandlers,\n Stream,\n BulkTransfer,\n RealtimeStream,\n};\n","/**\n * Phase 7: Dynamic Schema Reader\n *\n * This module provides runtime reading of Cap'n Proto messages using\n * dynamically loaded schema information. This allows reading messages\n * for types not known at compile time.\n */\n\nimport type { ListReader } from '../core/list.js';\nimport { MessageReader, type StructReader } from '../core/message-reader.js';\nimport { ElementSize } from '../core/pointer.js';\nimport type {\n SchemaField,\n SchemaNode,\n SchemaType,\n SchemaTypeKind,\n SchemaValue,\n} from './schema-types.js';\nimport { SchemaNodeType } from './schema-types.js';\n\n/**\n * Dynamic reader for Cap'n Proto messages\n * Provides runtime field access based on schema information\n */\nexport interface DynamicReader {\n /** Get a field value by name */\n get(fieldName: string): unknown;\n\n /** Check if a field exists */\n has(fieldName: string): boolean;\n\n /** Get all field names */\n getFieldNames(): string[];\n\n /** Get the underlying schema node */\n getSchema(): SchemaNode;\n\n /** Get nested struct reader */\n getStruct(fieldName: string): DynamicReader | undefined;\n\n /** Get list field */\n getList(fieldName: string): unknown[] | undefined;\n\n /** Get the raw StructReader */\n getRawReader(): StructReader;\n}\n\n/**\n * Create a dynamic reader from schema and buffer\n *\n * @param schema - The schema node describing the struct type\n * @param buffer - The Cap'n Proto message buffer\n * @returns A DynamicReader for accessing the message fields\n */\nexport function createDynamicReader(\n schema: SchemaNode,\n buffer: ArrayBuffer | Uint8Array\n): DynamicReader {\n const messageReader = new MessageReader(buffer);\n\n if (!schema.structInfo) {\n throw new Error(`Schema node ${schema.displayName} is not a struct`);\n }\n\n const { dataWordCount, pointerCount } = schema.structInfo;\n const structReader = messageReader.getRoot(dataWordCount, pointerCount);\n\n return new DynamicReaderImpl(schema, structReader, messageReader);\n}\n\n/**\n * Create a dynamic reader from an existing StructReader\n *\n * @param schema - The schema node describing the struct type\n * @param structReader - The StructReader to wrap\n * @param messageReader - The underlying MessageReader\n * @returns A DynamicReader for accessing the message fields\n */\nexport function createDynamicReaderFromStruct(\n schema: SchemaNode,\n structReader: StructReader,\n messageReader: MessageReader\n): DynamicReader {\n return new DynamicReaderImpl(schema, structReader, messageReader);\n}\n\n/**\n * Implementation of DynamicReader\n */\nclass DynamicReaderImpl implements DynamicReader {\n private fieldCache: Map<string, SchemaField>;\n private pointerOffset: number;\n\n constructor(\n private schema: SchemaNode,\n private structReader: StructReader,\n private messageReader: MessageReader\n ) {\n this.fieldCache = new Map();\n this.pointerOffset = schema.structInfo?.dataWordCount ?? 0;\n\n // Build field cache\n if (schema.structInfo?.fields) {\n for (const field of schema.structInfo.fields) {\n this.fieldCache.set(field.name, field);\n }\n }\n }\n\n get(fieldName: string): unknown {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n return this.readFieldValue(field);\n }\n\n has(fieldName: string): boolean {\n return this.fieldCache.has(fieldName);\n }\n\n getFieldNames(): string[] {\n return Array.from(this.fieldCache.keys());\n }\n\n getSchema(): SchemaNode {\n return this.schema;\n }\n\n getStruct(fieldName: string): DynamicReader | undefined {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n return undefined;\n }\n\n // Check if field is a struct type\n if (field.type.kind.type !== 'struct') {\n return undefined;\n }\n\n // Get the nested struct reader\n const pointerIndex = this.getPointerIndex(field);\n const nestedStruct = this.structReader.getStruct(pointerIndex, 0, 0);\n if (!nestedStruct) {\n return undefined;\n }\n\n // Note: We don't have the nested schema here, so we return a limited reader\n // In a full implementation, we'd look up the schema by typeId\n return new DynamicStructReaderWithoutSchema(nestedStruct, this.messageReader);\n }\n\n getList(fieldName: string): unknown[] | undefined {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n return undefined;\n }\n\n if (field.type.kind.type !== 'list') {\n return undefined;\n }\n\n const pointerIndex = this.getPointerIndex(field);\n const elementType = field.type.kind.elementType;\n\n return this.readListField(pointerIndex, elementType);\n }\n\n getRawReader(): StructReader {\n return this.structReader;\n }\n\n /**\n * Read a field value based on its type\n */\n private readFieldValue(field: SchemaField): unknown {\n const kind = field.type.kind;\n\n switch (kind.type) {\n case 'void':\n return undefined;\n case 'bool':\n return this.structReader.getBool(field.offset);\n case 'int8':\n return this.structReader.getInt8(field.offset);\n case 'int16':\n return this.structReader.getInt16(field.offset);\n case 'int32':\n return this.structReader.getInt32(field.offset);\n case 'int64':\n return this.structReader.getInt64(field.offset);\n case 'uint8':\n return this.structReader.getUint8(field.offset);\n case 'uint16':\n return this.structReader.getUint16(field.offset);\n case 'uint32':\n return this.structReader.getUint32(field.offset);\n case 'uint64':\n return this.structReader.getUint64(field.offset);\n case 'float32':\n return this.structReader.getFloat32(field.offset);\n case 'float64':\n return this.structReader.getFloat64(field.offset);\n case 'text':\n return this.readTextField(field);\n case 'data':\n return this.readDataField(field);\n case 'list':\n return this.readListFieldBySchema(field);\n case 'enum':\n return this.readEnumField(field);\n case 'struct':\n return this.readStructField(field);\n case 'interface':\n return this.readInterfaceField(field);\n case 'anyPointer':\n return this.readAnyPointerField(field);\n default:\n throw new Error(`Unsupported field type: ${(kind as SchemaTypeKind).type}`);\n }\n }\n\n /**\n * Get the pointer index for a field\n * In Cap'n Proto, pointer fields have offsets that start from 0 for the first pointer\n * The offset is measured in bits from the start of the data section\n * For pointer fields, offset = dataWordCount * 64 + pointerIndex * 64\n * So pointerIndex = (offset - dataWordCount * 64) / 64\n */\n private getPointerIndex(field: SchemaField): number {\n const dataSectionBits = (this.schema.structInfo?.dataWordCount ?? 0) * 64;\n // Pointer offset is measured from the start of the pointer section\n // Each pointer is 64 bits (1 word)\n const pointerIndex = (field.offset - dataSectionBits) / 64;\n return pointerIndex;\n }\n\n /**\n * Read a text field\n */\n private readTextField(field: SchemaField): string {\n const pointerIndex = this.getPointerIndex(field);\n return this.structReader.getText(pointerIndex);\n }\n\n /**\n * Read a data field\n */\n private readDataField(field: SchemaField): Uint8Array {\n const pointerIndex = this.getPointerIndex(field);\n // Data is stored similarly to text but without null terminator\n // For now, we use the same mechanism\n const text = this.structReader.getText(pointerIndex);\n return new TextEncoder().encode(text);\n }\n\n /**\n * Read a list field using schema information\n */\n private readListFieldBySchema(field: SchemaField): unknown[] {\n if (field.type.kind.type !== 'list') {\n throw new Error(`Field '${field.name}' is not a list type`);\n }\n\n const pointerIndex = this.getPointerIndex(field);\n const elementType = field.type.kind.elementType;\n\n return this.readListField(pointerIndex, elementType);\n }\n\n /**\n * Read a list field\n */\n private readListField(pointerIndex: number, elementType: SchemaType): unknown[] {\n // Map element type to ElementSize\n const elementSize = this.mapTypeToElementSize(elementType);\n\n const listReader = this.structReader.getList<unknown>(pointerIndex, elementSize);\n if (!listReader) {\n return [];\n }\n\n // Convert list reader to array\n const result: unknown[] = [];\n const length = listReader.length;\n\n for (let i = 0; i < length; i++) {\n result.push(this.readListElement(listReader, i, elementType));\n }\n\n return result;\n }\n\n /**\n * Map schema type to ElementSize\n */\n private mapTypeToElementSize(type: SchemaType): ElementSize {\n switch (type.kind.type) {\n case 'void':\n return ElementSize.VOID;\n case 'bool':\n return ElementSize.BIT;\n case 'int8':\n case 'uint8':\n return ElementSize.BYTE;\n case 'int16':\n case 'uint16':\n return ElementSize.TWO_BYTES;\n case 'int32':\n case 'uint32':\n case 'float32':\n return ElementSize.FOUR_BYTES;\n case 'int64':\n case 'uint64':\n case 'float64':\n return ElementSize.EIGHT_BYTES;\n case 'struct':\n return ElementSize.COMPOSITE;\n default:\n return ElementSize.POINTER;\n }\n }\n\n /**\n * Read a single list element\n */\n private readListElement(\n listReader: ListReader<unknown>,\n index: number,\n elementType: SchemaType\n ): unknown {\n const kind = elementType.kind;\n\n switch (kind.type) {\n case 'void':\n return undefined;\n case 'bool':\n return listReader.getPrimitive(index) !== 0;\n case 'int8':\n return listReader.getPrimitive(index);\n case 'int16':\n return listReader.getPrimitive(index);\n case 'int32':\n return listReader.getPrimitive(index);\n case 'int64':\n return listReader.getPrimitive(index);\n case 'uint8':\n return listReader.getPrimitive(index);\n case 'uint16':\n return listReader.getPrimitive(index);\n case 'uint32':\n return listReader.getPrimitive(index);\n case 'uint64':\n return listReader.getPrimitive(index);\n case 'float32':\n return listReader.getPrimitive(index);\n case 'float64':\n return listReader.getPrimitive(index);\n case 'struct': {\n const structReader = listReader.getStruct(index);\n if (!structReader) return undefined;\n // Return a wrapper without full schema\n return new DynamicStructReaderWithoutSchema(structReader, this.messageReader);\n }\n default:\n return undefined;\n }\n }\n\n /**\n * Read an enum field\n */\n private readEnumField(field: SchemaField): number {\n // Enums are stored as uint16\n return this.structReader.getUint16(field.offset);\n }\n\n /**\n * Read a struct field\n */\n private readStructField(field: SchemaField): DynamicReader | undefined {\n const pointerIndex = this.getPointerIndex(field);\n const nestedStruct = this.structReader.getStruct(pointerIndex, 0, 0);\n if (!nestedStruct) {\n return undefined;\n }\n\n // Without the nested schema, we return a limited reader\n return new DynamicStructReaderWithoutSchema(nestedStruct, this.messageReader);\n }\n\n /**\n * Read an interface field (capability)\n */\n private readInterfaceField(_field: SchemaField): unknown {\n // Capabilities are stored in the cap table\n // This would require access to the capability table\n throw new Error('Interface fields not yet supported in dynamic reader');\n }\n\n /**\n * Read an anyPointer field\n */\n private readAnyPointerField(_field: SchemaField): unknown {\n // anyPointer can be any type, requires runtime type detection\n throw new Error('anyPointer fields not yet supported in dynamic reader');\n }\n}\n\n/**\n * A limited dynamic reader for structs without schema information\n * Provides basic field access but no type information\n */\nclass DynamicStructReaderWithoutSchema implements DynamicReader {\n constructor(\n private structReader: StructReader,\n private messageReader: MessageReader\n ) {}\n\n get(_fieldName: string): unknown {\n throw new Error('Cannot access fields without schema information');\n }\n\n has(_fieldName: string): boolean {\n return false;\n }\n\n getFieldNames(): string[] {\n return [];\n }\n\n getSchema(): SchemaNode {\n throw new Error('No schema information available');\n }\n\n getStruct(_fieldName: string): DynamicReader | undefined {\n return undefined;\n }\n\n getList(_fieldName: string): unknown[] | undefined {\n return undefined;\n }\n\n getRawReader(): StructReader {\n return this.structReader;\n }\n}\n\n/**\n * Create a dynamic reader for a specific type ID\n * This looks up the schema in a registry and creates the appropriate reader\n *\n * @param typeId - The type ID of the struct\n * @param buffer - The Cap'n Proto message buffer\n * @param schemaRegistry - A map of type IDs to schema nodes\n * @returns A DynamicReader for the message\n */\nexport function createDynamicReaderByTypeId(\n typeId: bigint,\n buffer: ArrayBuffer | Uint8Array,\n schemaRegistry: Map<bigint, SchemaNode>\n): DynamicReader {\n const schema = schemaRegistry.get(typeId);\n if (!schema) {\n throw new Error(`Schema not found for type ID: ${typeId}`);\n }\n\n if (schema.type !== SchemaNodeType.STRUCT) {\n throw new Error(`Type ${typeId} is not a struct`);\n }\n\n return createDynamicReader(schema, buffer);\n}\n\n/**\n * Utility function to dump all fields from a dynamic reader\n * Useful for debugging and exploration\n *\n * @param reader - The DynamicReader to dump\n * @returns An object with all field names and values\n */\nexport function dumpDynamicReader(reader: DynamicReader): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const fieldName of reader.getFieldNames()) {\n try {\n result[fieldName] = reader.get(fieldName);\n } catch (error) {\n result[fieldName] = `<error: ${error}>`;\n }\n }\n\n return result;\n}\n","/**\n * Phase 7: Dynamic Schema Writer\n *\n * This module provides runtime writing of Cap'n Proto messages using\n * dynamically loaded schema information. This allows writing messages\n * for types not known at compile time.\n */\n\nimport type { ListBuilder } from '../core/list.js';\nimport { MessageBuilder, type StructBuilder } from '../core/message-builder.js';\nimport { ElementSize } from '../core/pointer.js';\nimport type { SchemaField, SchemaNode, SchemaType, SchemaValue } from './schema-types.js';\nimport { SchemaNodeType } from './schema-types.js';\n\n/**\n * Dynamic writer for Cap'n Proto messages\n * Provides runtime field setting based on schema information\n */\nexport interface DynamicWriter {\n /** Set a field value by name */\n set(fieldName: string, value: unknown): void;\n\n /** Set multiple fields at once */\n setFields(fields: Record<string, unknown>): void;\n\n /** Initialize a nested struct field */\n initStruct(fieldName: string): DynamicWriter;\n\n /** Initialize a list field */\n initList(fieldName: string, size: number): DynamicListWriter;\n\n /** Set a text field */\n setText(fieldName: string, value: string): void;\n\n /** Set a data field */\n setData(fieldName: string, value: Uint8Array): void;\n\n /** Get the underlying schema node */\n getSchema(): SchemaNode;\n\n /** Get the raw StructBuilder */\n getRawBuilder(): StructBuilder;\n\n /** Serialize the message to a buffer */\n toBuffer(): ArrayBuffer;\n}\n\n/**\n * Dynamic list writer\n * Provides runtime element setting for list fields\n */\nexport interface DynamicListWriter {\n /** Set an element at the specified index */\n set(index: number, value: unknown): void;\n\n /** Get the list size */\n getSize(): number;\n\n /** Initialize a nested struct element */\n initStruct(index: number): DynamicWriter;\n\n /** Set multiple elements at once */\n setAll(values: unknown[]): void;\n}\n\n/**\n * Create a dynamic writer from schema\n *\n * @param schema - The schema node describing the struct type\n * @returns A DynamicWriter for setting message fields\n */\nexport function createDynamicWriter(schema: SchemaNode): DynamicWriter {\n if (!schema.structInfo) {\n throw new Error(`Schema node ${schema.displayName} is not a struct`);\n }\n\n const { dataWordCount, pointerCount } = schema.structInfo;\n const messageBuilder = new MessageBuilder();\n const structBuilder = messageBuilder.initRoot(dataWordCount, pointerCount);\n\n return new DynamicWriterImpl(schema, structBuilder, messageBuilder);\n}\n\n/**\n * Create a dynamic writer for a nested struct\n *\n * @param schema - The schema node describing the struct type\n * @param structBuilder - The StructBuilder to wrap\n * @param messageBuilder - The underlying MessageBuilder\n * @returns A DynamicWriter for setting message fields\n */\nexport function createNestedDynamicWriter(\n schema: SchemaNode,\n structBuilder: StructBuilder,\n messageBuilder: MessageBuilder\n): DynamicWriter {\n return new DynamicWriterImpl(schema, structBuilder, messageBuilder);\n}\n\n/**\n * Implementation of DynamicWriter\n */\nclass DynamicWriterImpl implements DynamicWriter {\n private fieldCache: Map<string, SchemaField>;\n private pointerOffset: number;\n\n constructor(\n private schema: SchemaNode,\n private structBuilder: StructBuilder,\n private messageBuilder: MessageBuilder\n ) {\n this.fieldCache = new Map();\n this.pointerOffset = schema.structInfo?.dataWordCount ?? 0;\n\n // Build field cache\n if (schema.structInfo?.fields) {\n for (const field of schema.structInfo.fields) {\n this.fieldCache.set(field.name, field);\n }\n }\n }\n\n set(fieldName: string, value: unknown): void {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n this.writeFieldValue(field, value);\n }\n\n setFields(fields: Record<string, unknown>): void {\n for (const [name, value] of Object.entries(fields)) {\n this.set(name, value);\n }\n }\n\n initStruct(fieldName: string): DynamicWriter {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n if (field.type.kind.type !== 'struct') {\n throw new Error(`Field '${fieldName}' is not a struct type`);\n }\n\n // For nested structs, we need the nested schema\n // Since we don't have it here, we'll create a placeholder\n const pointerIndex = this.getPointerIndex(field);\n const nestedBuilder = this.structBuilder.initStruct(pointerIndex, 0, 0);\n\n // Return a writer without schema - limited functionality\n return new DynamicWriterWithoutSchema(nestedBuilder, this.messageBuilder);\n }\n\n initList(fieldName: string, size: number): DynamicListWriter {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n if (field.type.kind.type !== 'list') {\n throw new Error(`Field '${fieldName}' is not a list type`);\n }\n\n const pointerIndex = this.getPointerIndex(field);\n const elementType = field.type.kind.elementType;\n\n return this.createListWriter(pointerIndex, size, elementType);\n }\n\n setText(fieldName: string, value: string): void {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n if (field.type.kind.type !== 'text') {\n throw new Error(`Field '${fieldName}' is not a text type`);\n }\n\n const pointerIndex = this.getPointerIndex(field);\n this.structBuilder.setText(pointerIndex, value);\n }\n\n setData(fieldName: string, value: Uint8Array): void {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n if (field.type.kind.type !== 'data') {\n throw new Error(`Field '${fieldName}' is not a data type`);\n }\n\n // Data is stored similarly to text but as bytes\n const pointerIndex = this.getPointerIndex(field);\n const textValue = new TextDecoder().decode(value);\n this.structBuilder.setText(pointerIndex, `${textValue}\\0`);\n }\n\n getSchema(): SchemaNode {\n return this.schema;\n }\n\n getRawBuilder(): StructBuilder {\n return this.structBuilder;\n }\n\n toBuffer(): ArrayBuffer {\n return this.messageBuilder.toArrayBuffer();\n }\n\n /**\n * Write a field value based on its type\n */\n private writeFieldValue(field: SchemaField, value: unknown): void {\n const kind = field.type.kind;\n\n switch (kind.type) {\n case 'void':\n // Void fields don't store any data\n break;\n case 'bool':\n this.structBuilder.setBool(field.offset, Boolean(value));\n break;\n case 'int8':\n this.structBuilder.setInt8(field.offset, Number(value));\n break;\n case 'int16':\n this.structBuilder.setInt16(field.offset, Number(value));\n break;\n case 'int32':\n this.structBuilder.setInt32(field.offset, Number(value));\n break;\n case 'int64':\n this.structBuilder.setInt64(field.offset, BigInt(value as string | number | bigint));\n break;\n case 'uint8':\n this.structBuilder.setUint8(field.offset, Number(value));\n break;\n case 'uint16':\n this.structBuilder.setUint16(field.offset, Number(value));\n break;\n case 'uint32':\n this.structBuilder.setUint32(field.offset, Number(value));\n break;\n case 'uint64':\n this.structBuilder.setUint64(field.offset, BigInt(value as string | number | bigint));\n break;\n case 'float32':\n this.structBuilder.setFloat32(field.offset, Number(value));\n break;\n case 'float64':\n this.structBuilder.setFloat64(field.offset, Number(value));\n break;\n case 'text':\n this.setText(field.name, String(value));\n break;\n case 'data':\n if (value instanceof Uint8Array) {\n this.setData(field.name, value);\n } else {\n throw new Error(`Field '${field.name}' expects Uint8Array`);\n }\n break;\n case 'list':\n if (Array.isArray(value)) {\n const listWriter = this.initList(field.name, value.length);\n listWriter.setAll(value);\n } else {\n throw new Error(`Field '${field.name}' expects an array`);\n }\n break;\n case 'enum':\n this.structBuilder.setUint16(field.offset, Number(value));\n break;\n case 'struct':\n if (typeof value === 'object' && value !== null) {\n const structWriter = this.initStruct(field.name);\n // If value is a record, set its fields\n if (!(value instanceof Uint8Array) && !Array.isArray(value)) {\n structWriter.setFields(value as Record<string, unknown>);\n }\n } else {\n throw new Error(`Field '${field.name}' expects an object`);\n }\n break;\n case 'interface':\n throw new Error('Interface fields not yet supported in dynamic writer');\n case 'anyPointer':\n throw new Error('anyPointer fields not yet supported in dynamic writer');\n default:\n throw new Error(`Unsupported field type: ${(kind as { type: string }).type}`);\n }\n }\n\n /**\n * Get the pointer index for a field\n * In Cap'n Proto, pointer fields have offsets that start from 0 for the first pointer\n * The offset is measured in bits from the start of the data section\n * For pointer fields, offset = dataWordCount * 64 + pointerIndex * 64\n * So pointerIndex = (offset - dataWordCount * 64) / 64\n */\n private getPointerIndex(field: SchemaField): number {\n const dataSectionBits = (this.schema.structInfo?.dataWordCount ?? 0) * 64;\n // Pointer offset is measured from the start of the pointer section\n // Each pointer is 64 bits (1 word)\n const pointerIndex = (field.offset - dataSectionBits) / 64;\n return pointerIndex;\n }\n\n /**\n * Create a list writer for a field\n */\n private createListWriter(\n pointerIndex: number,\n size: number,\n elementType: SchemaType\n ): DynamicListWriter {\n // Map element type to ElementSize\n const elementSize = this.mapTypeToElementSize(elementType);\n\n let structSize: { dataWords: number; pointerCount: number } | undefined;\n if (elementSize === ElementSize.COMPOSITE) {\n // For composite types, we need struct size info\n // Default to 0,0 if not available\n structSize = { dataWords: 0, pointerCount: 0 };\n }\n\n const listBuilder = this.structBuilder.initList<unknown>(\n pointerIndex,\n elementSize,\n size,\n structSize\n );\n\n return new DynamicListWriterImpl(listBuilder, elementType, this.messageBuilder);\n }\n\n /**\n * Map schema type to ElementSize\n */\n private mapTypeToElementSize(type: SchemaType): ElementSize {\n switch (type.kind.type) {\n case 'void':\n return ElementSize.VOID;\n case 'bool':\n return ElementSize.BIT;\n case 'int8':\n case 'uint8':\n return ElementSize.BYTE;\n case 'int16':\n case 'uint16':\n return ElementSize.TWO_BYTES;\n case 'int32':\n case 'uint32':\n case 'float32':\n return ElementSize.FOUR_BYTES;\n case 'int64':\n case 'uint64':\n case 'float64':\n return ElementSize.EIGHT_BYTES;\n case 'struct':\n return ElementSize.COMPOSITE;\n default:\n return ElementSize.POINTER;\n }\n }\n}\n\n/**\n * Implementation of DynamicListWriter\n */\nclass DynamicListWriterImpl implements DynamicListWriter {\n constructor(\n private listBuilder: ListBuilder<unknown>,\n private elementType: SchemaType,\n private messageBuilder: MessageBuilder\n ) {}\n\n set(index: number, value: unknown): void {\n if (index < 0 || index >= this.listBuilder.length) {\n throw new Error(`Index ${index} out of bounds`);\n }\n\n const kind = this.elementType.kind;\n\n switch (kind.type) {\n case 'void':\n // Nothing to set for void\n break;\n case 'bool':\n this.listBuilder.setPrimitive(index, value ? 1 : 0);\n break;\n case 'int8':\n case 'uint8':\n case 'int16':\n case 'uint16':\n case 'int32':\n case 'uint32':\n case 'float32':\n this.listBuilder.setPrimitive(index, Number(value));\n break;\n case 'int64':\n case 'uint64':\n case 'float64':\n this.listBuilder.setPrimitive(index, BigInt(value as string | number | bigint));\n break;\n case 'struct':\n // For struct lists, value should be an object to set fields\n if (typeof value === 'object' && value !== null && !(value instanceof Uint8Array)) {\n const structWriter = this.initStruct(index);\n structWriter.setFields(value as Record<string, unknown>);\n }\n break;\n default:\n throw new Error(`Unsupported list element type: ${kind.type}`);\n }\n }\n\n getSize(): number {\n return this.listBuilder.length;\n }\n\n getLength(): number {\n return this.listBuilder.length;\n }\n\n initStruct(index: number): DynamicWriter {\n const structBuilder = this.listBuilder.getStruct(index);\n return new DynamicWriterWithoutSchema(structBuilder, this.messageBuilder);\n }\n\n setAll(values: unknown[]): void {\n if (values.length > this.getSize()) {\n throw new Error(`Cannot set ${values.length} values in list of size ${this.getSize()}`);\n }\n\n for (let i = 0; i < values.length; i++) {\n this.set(i, values[i]);\n }\n }\n}\n\n/**\n * A limited dynamic writer for structs without full schema information\n * Provides basic field setting but no type validation\n */\nclass DynamicWriterWithoutSchema implements DynamicWriter {\n constructor(\n private structBuilder: StructBuilder,\n private messageBuilder: MessageBuilder\n ) {}\n\n set(fieldName: string, _value: unknown): void {\n // Without schema, we can only support basic operations\n // This is a placeholder that could be extended\n throw new Error(`Cannot set field '${fieldName}' without schema information`);\n }\n\n setFields(_fields: Record<string, unknown>): void {\n throw new Error('Cannot set fields without schema information');\n }\n\n initStruct(_fieldName: string): DynamicWriter {\n throw new Error('Cannot init struct without schema information');\n }\n\n initList(_fieldName: string, _size: number): DynamicListWriter {\n throw new Error('Cannot init list without schema information');\n }\n\n setText(_fieldName: string, _value: string): void {\n throw new Error('Cannot set text without schema information');\n }\n\n setData(_fieldName: string, _value: Uint8Array): void {\n throw new Error('Cannot set data without schema information');\n }\n\n getSchema(): SchemaNode {\n throw new Error('No schema information available');\n }\n\n getRawBuilder(): StructBuilder {\n return this.structBuilder;\n }\n\n toBuffer(): ArrayBuffer {\n return this.messageBuilder.toArrayBuffer();\n }\n}\n\n/**\n * Create a dynamic writer for a specific type ID\n * This looks up the schema in a registry and creates the appropriate writer\n *\n * @param typeId - The type ID of the struct\n * @param schemaRegistry - A map of type IDs to schema nodes\n * @returns A DynamicWriter for the message\n */\nexport function createDynamicWriterByTypeId(\n typeId: bigint,\n schemaRegistry: Map<bigint, SchemaNode>\n): DynamicWriter {\n const schema = schemaRegistry.get(typeId);\n if (!schema) {\n throw new Error(`Schema not found for type ID: ${typeId}`);\n }\n\n if (schema.type !== SchemaNodeType.STRUCT) {\n throw new Error(`Type ${typeId} is not a struct`);\n }\n\n return createDynamicWriter(schema);\n}\n\n/**\n * Utility function to create a message from a plain object\n * Uses schema information to properly serialize the data\n *\n * @param schema - The schema node describing the struct type\n * @param data - The data object to serialize\n * @returns The serialized message buffer\n */\nexport function serializeDynamic(schema: SchemaNode, data: Record<string, unknown>): ArrayBuffer {\n const writer = createDynamicWriter(schema);\n writer.setFields(data);\n return writer.toBuffer();\n}\n\n/**\n * Utility function to create a message from a plain object using type ID\n *\n * @param typeId - The type ID of the struct\n * @param data - The data object to serialize\n * @param schemaRegistry - A map of type IDs to schema nodes\n * @returns The serialized message buffer\n */\nexport function serializeDynamicByTypeId(\n typeId: bigint,\n data: Record<string, unknown>,\n schemaRegistry: Map<bigint, SchemaNode>\n): ArrayBuffer {\n const writer = createDynamicWriterByTypeId(typeId, schemaRegistry);\n writer.setFields(data);\n return writer.toBuffer();\n}\n","/**\n * Phase 7: Schema Capability Implementation\n *\n * Implements the SchemaCapability interface defined in rpc.capnp\n * Provides server-side schema serving and client-side schema fetching\n */\n\nimport type { RpcConnection } from './rpc-connection.js';\nimport { createSchemaRegistry, parseSchemaNodes } from './schema-parser.js';\nimport {\n deserializeSchemaRequest,\n serializeGetSchemaResults,\n serializeListSchemasResults,\n serializeSchemaResponse,\n} from './schema-serializer.js';\nimport type {\n AvailableSchema,\n GetSchemaParams,\n GetSchemaResults,\n ListSchemasResults,\n SchemaNode,\n SchemaPayload,\n SchemaTarget,\n} from './schema-types.js';\nimport { SchemaFormat, SchemaNodeType } from './schema-types.js';\n\n// ============================================================================\n// Schema Capability Server\n// ============================================================================\n\n/**\n * Server-side implementation of the SchemaCapability interface.\n * Provides schema information to remote clients.\n */\nexport class SchemaCapabilityServer {\n private registry: Map<bigint, SchemaNode>;\n private schemasByName: Map<string, SchemaNode>;\n\n /**\n * Create a new SchemaCapabilityServer\n * @param initialSchemas - Optional map of schemas to register initially\n */\n constructor(initialSchemas?: Map<bigint, SchemaNode>) {\n this.registry = new Map(initialSchemas);\n this.schemasByName = new Map();\n\n // Build name index\n for (const schema of this.registry.values()) {\n this.schemasByName.set(schema.displayName, schema);\n }\n }\n\n /**\n * Register a schema node\n * @param node - The schema node to register\n */\n registerSchema(node: SchemaNode): void {\n this.registry.set(node.id, node);\n this.schemasByName.set(node.displayName, node);\n }\n\n /**\n * Unregister a schema by ID\n * @param typeId - The type ID to unregister\n */\n unregisterSchema(typeId: bigint): void {\n const node = this.registry.get(typeId);\n if (node) {\n this.registry.delete(typeId);\n this.schemasByName.delete(node.displayName);\n }\n }\n\n /**\n * Get schema information based on target specification\n * @param params - GetSchemaParams containing target and format\n * @returns GetSchemaResults with the schema payload\n */\n async getSchema(params: GetSchemaParams): Promise<GetSchemaResults> {\n const { target, format = SchemaFormat.BINARY } = params;\n\n let schemaData: Uint8Array;\n let dependencies: Array<{ fileId: bigint; fileName: string; schemaHash?: Uint8Array }> = [];\n\n switch (target.type) {\n case 'byTypeId': {\n const node = this.registry.get(target.typeId);\n if (!node) {\n throw new Error(`Schema not found for type ID: ${target.typeId.toString(16)}`);\n }\n schemaData = this.serializeSchemaNode(node, format);\n dependencies = this.collectDependencies(node);\n break;\n }\n\n case 'byTypeName': {\n const node = this.schemasByName.get(target.typeName);\n if (!node) {\n throw new Error(`Schema not found for type name: ${target.typeName}`);\n }\n schemaData = this.serializeSchemaNode(node, format);\n dependencies = this.collectDependencies(node);\n break;\n }\n\n case 'byFileId': {\n // Get all schemas in a file\n const nodes = this.getSchemasByFileId(target.fileId);\n schemaData = this.serializeSchemaNodes(nodes, format);\n break;\n }\n\n case 'byFileName': {\n // Get all schemas in a file by name\n const nodes = this.getSchemasByFileName(target.fileName);\n schemaData = this.serializeSchemaNodes(nodes, format);\n break;\n }\n\n case 'allSchemas': {\n // Get all schemas\n const nodes = Array.from(this.registry.values());\n schemaData = this.serializeSchemaNodes(nodes, format);\n break;\n }\n\n case 'bootstrapInterface': {\n // Get bootstrap interface schema (if available)\n const bootstrapSchema = this.findBootstrapSchema();\n if (!bootstrapSchema) {\n throw new Error('Bootstrap interface schema not available');\n }\n schemaData = this.serializeSchemaNode(bootstrapSchema, format);\n dependencies = this.collectDependencies(bootstrapSchema);\n break;\n }\n\n default:\n throw new Error(`Unsupported schema target type: ${(target as SchemaTarget).type}`);\n }\n\n return {\n payload: {\n schemaData,\n format,\n dependencies,\n },\n };\n }\n\n /**\n * List all available schemas\n * @returns ListSchemasResults with available schema information\n */\n async listAvailableSchemas(): Promise<ListSchemasResults> {\n const schemas: AvailableSchema[] = [];\n\n for (const node of this.registry.values()) {\n schemas.push({\n typeId: node.id,\n displayName: node.displayName,\n fileId: node.scopeId, // Using scopeId as fileId proxy\n fileName: this.inferFileName(node),\n isInterface: node.type === SchemaNodeType.INTERFACE,\n isStruct: node.type === SchemaNodeType.STRUCT,\n isEnum: node.type === SchemaNodeType.ENUM,\n });\n }\n\n return { schemas };\n }\n\n /**\n * Handle a raw schema request (for RPC integration)\n * @param requestData - The serialized SchemaRequest\n * @returns The serialized SchemaResponse\n */\n handleRequest(requestData: Uint8Array): Uint8Array {\n try {\n const request = deserializeSchemaRequest(requestData);\n\n const _result = this.getSchema({\n target: request.targetSchema,\n });\n\n // Since getSchema is async, we need to handle the promise\n // In a real implementation, this would be properly async\n throw new Error('Async handling not implemented in handleRequest');\n } catch (error) {\n // Return error response\n const errorResponse = {\n answerId: 0,\n result: {\n type: 'exception' as const,\n exception: {\n reason: error instanceof Error ? error.message : 'Unknown error',\n type: 'failed' as const,\n obsoleteIsCallersFault: false,\n obsoleteDurability: 0,\n },\n },\n };\n\n return serializeSchemaResponse(errorResponse);\n }\n }\n\n /**\n * Get the number of registered schemas\n */\n getSchemaCount(): number {\n return this.registry.size;\n }\n\n /**\n * Check if a schema is registered\n */\n hasSchema(typeId: bigint): boolean {\n return this.registry.has(typeId);\n }\n\n // --------------------------------------------------------------------------\n // Private Helper Methods\n // --------------------------------------------------------------------------\n\n private serializeSchemaNode(node: SchemaNode, format: SchemaFormat): Uint8Array {\n switch (format) {\n case SchemaFormat.BINARY:\n return this.serializeToBinary([node]);\n case SchemaFormat.JSON:\n return this.serializeToJson([node]);\n case SchemaFormat.CAPNP:\n return this.serializeToCapnp([node]);\n default:\n throw new Error(`Unsupported schema format: ${format}`);\n }\n }\n\n private serializeSchemaNodes(nodes: SchemaNode[], format: SchemaFormat): Uint8Array {\n switch (format) {\n case SchemaFormat.BINARY:\n return this.serializeToBinary(nodes);\n case SchemaFormat.JSON:\n return this.serializeToJson(nodes);\n case SchemaFormat.CAPNP:\n return this.serializeToCapnp(nodes);\n default:\n throw new Error(`Unsupported schema format: ${format}`);\n }\n }\n\n private serializeToBinary(nodes: SchemaNode[]): Uint8Array {\n // Simplified binary serialization\n // In a full implementation, this would serialize to the actual Cap'n Proto format\n const encoder = new TextEncoder();\n const json = JSON.stringify(nodes, (_key, value) => {\n if (typeof value === 'bigint') {\n return value.toString();\n }\n return value;\n });\n return encoder.encode(json);\n }\n\n private serializeToJson(nodes: SchemaNode[]): Uint8Array {\n const encoder = new TextEncoder();\n const json = JSON.stringify({\n nodes: nodes.map((node) => ({\n id: node.id.toString(),\n displayName: node.displayName,\n displayNamePrefixLength: node.displayNamePrefixLength,\n scopeId: node.scopeId.toString(),\n type: node.type,\n structInfo: node.structInfo,\n enumInfo: node.enumInfo,\n interfaceInfo: node.interfaceInfo,\n })),\n });\n return encoder.encode(json);\n }\n\n private serializeToCapnp(nodes: SchemaNode[]): Uint8Array {\n // Placeholder for actual Cap'n Proto schema language serialization\n // This would generate .capnp source code from the schema nodes\n const lines: string[] = [];\n\n for (const node of nodes) {\n if (node.structInfo) {\n lines.push(`struct ${node.displayName} {`);\n for (const field of node.structInfo.fields) {\n lines.push(` ${field.name} @${field.codeOrder} :${this.typeToCapnp(field.type)};`);\n }\n lines.push('}');\n }\n }\n\n return new TextEncoder().encode(lines.join('\\n'));\n }\n\n private typeToCapnp(type: { kind: { type: string } }): string {\n const kind = type.kind;\n switch (kind.type) {\n case 'void':\n return 'Void';\n case 'bool':\n return 'Bool';\n case 'int8':\n return 'Int8';\n case 'int16':\n return 'Int16';\n case 'int32':\n return 'Int32';\n case 'int64':\n return 'Int64';\n case 'uint8':\n return 'UInt8';\n case 'uint16':\n return 'UInt16';\n case 'uint32':\n return 'UInt32';\n case 'uint64':\n return 'UInt64';\n case 'float32':\n return 'Float32';\n case 'float64':\n return 'Float64';\n case 'text':\n return 'Text';\n case 'data':\n return 'Data';\n case 'list':\n return 'List';\n case 'enum':\n return 'UInt16';\n case 'struct':\n return 'AnyPointer';\n case 'interface':\n return 'Capability';\n default:\n return 'AnyPointer';\n }\n }\n\n private collectDependencies(\n _node: SchemaNode\n ): Array<{ fileId: bigint; fileName: string; schemaHash?: Uint8Array }> {\n // In a full implementation, this would analyze the schema and collect\n // all imported schema dependencies\n return [];\n }\n\n private getSchemasByFileId(fileId: bigint): SchemaNode[] {\n return Array.from(this.registry.values()).filter((node) => node.scopeId === fileId);\n }\n\n private getSchemasByFileName(fileName: string): SchemaNode[] {\n // Infer file name from display name prefix\n return Array.from(this.registry.values()).filter((node) => {\n const inferredFileName = this.inferFileName(node);\n return inferredFileName === fileName || node.displayName.startsWith(fileName);\n });\n }\n\n private inferFileName(node: SchemaNode): string {\n // Infer file name from display name\n // e.g., \"foo.bar.MyStruct\" -> \"foo/bar.capnp\"\n const parts = node.displayName.split('.');\n if (parts.length > 1) {\n return `${parts.slice(0, -1).join('/')}.capnp`;\n }\n return 'unknown.capnp';\n }\n\n private findBootstrapSchema(): SchemaNode | undefined {\n // Look for a schema that might be the bootstrap interface\n // This is a heuristic - in practice, the bootstrap interface would be\n // explicitly registered\n for (const node of this.registry.values()) {\n if (node.type === SchemaNodeType.INTERFACE) {\n return node;\n }\n }\n return undefined;\n }\n}\n\n// ============================================================================\n// Schema Capability Client\n// ============================================================================\n\n/**\n * Client-side implementation for accessing remote SchemaCapability\n */\nexport class SchemaCapabilityClient {\n private connection: RpcConnection;\n\n /**\n * Create a new SchemaCapabilityClient\n * @param connection - The RPC connection to use\n */\n constructor(connection: RpcConnection) {\n this.connection = connection;\n }\n\n /**\n * Fetch schema information from the remote server\n * @param target - The schema target specification\n * @param format - The desired format (defaults to BINARY)\n * @returns The schema node\n */\n async getSchema(\n target: SchemaTarget,\n format: SchemaFormat = SchemaFormat.BINARY\n ): Promise<SchemaNode> {\n // Use the connection's getDynamicSchema method for type ID lookups\n if (target.type === 'byTypeId') {\n return this.connection.getDynamicSchema(target.typeId);\n }\n\n // For other target types, we need to use the schema capability interface\n // This is a simplified implementation\n const _params: GetSchemaParams = { target, format };\n\n // In a full implementation, this would make an RPC call to the schema capability\n // For now, we delegate to the connection's method\n if (target.type === 'byTypeName') {\n return this.connection.getDynamicSchemaByName(target.typeName);\n }\n\n throw new Error(`Schema target type not implemented: ${target.type}`);\n }\n\n /**\n * Fetch schema by type ID\n * @param typeId - The type ID\n * @returns The schema node\n */\n async getSchemaById(typeId: bigint): Promise<SchemaNode> {\n return this.connection.getDynamicSchema(typeId);\n }\n\n /**\n * Fetch schema by type name\n * @param typeName - The fully qualified type name\n * @returns The schema node\n */\n async getSchemaByName(typeName: string): Promise<SchemaNode> {\n return this.connection.getDynamicSchemaByName(typeName);\n }\n\n /**\n * List all available schemas from the remote server\n * @returns Array of available schema information\n */\n async listAvailableSchemas(): Promise<AvailableSchema[]> {\n const schemas = await this.connection.listAvailableSchemas();\n return schemas.map((s) => ({\n typeId: s.typeId,\n displayName: s.displayName,\n fileId: BigInt(0), // Not provided by connection method\n fileName: '', // Not provided by connection method\n isInterface: false, // Not provided by connection method\n isStruct: true,\n isEnum: false,\n }));\n }\n\n /**\n * Fetch multiple schemas at once\n * @param typeIds - Array of type IDs to fetch\n * @returns Map of type ID to schema node\n */\n async getSchemas(typeIds: bigint[]): Promise<Map<bigint, SchemaNode>> {\n const results = new Map<bigint, SchemaNode>();\n\n // Fetch schemas in parallel\n await Promise.all(\n typeIds.map(async (typeId) => {\n try {\n const schema = await this.getSchemaById(typeId);\n results.set(typeId, schema);\n } catch (error) {\n console.warn(`Failed to fetch schema ${typeId.toString(16)}:`, error);\n }\n })\n );\n\n return results;\n }\n\n /**\n * Check if a schema is available on the remote server\n * @param typeId - The type ID to check\n * @returns True if the schema is available\n */\n async hasSchema(typeId: bigint): Promise<boolean> {\n try {\n await this.getSchemaById(typeId);\n return true;\n } catch {\n return false;\n }\n }\n}\n\n// ============================================================================\n// Schema Provider Registration Helper\n// ============================================================================\n\n// Note: RpcConnection.registerSchemaProvider is defined in rpc-connection.ts\n// to avoid circular imports. This file only defines the SchemaCapabilityServer\n// and SchemaCapabilityClient classes.\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["net","net","RpcConnection","SchemaNodeType","SchemaNodeType","SchemaFormat","SchemaNodeType","deserializeSchemaRequest","serializeSchemaResponse","EventEmitter","http","createHash","Duplex","EventEmitter","EventEmitter","WebSocket","WebSocketServer"],"sources":["../src/core/pointer.ts","../src/core/segment.ts","../src/core/message-builder.ts","../src/core/list.ts","../src/core/message-reader.ts","../src/core/union.ts","../src/rpc/message-serializer.ts","../src/rpc/websocket-transport.ts","../src/rpc/tcp-transport.ts","../src/rpc/ezrpc-transport.ts","../src/rpc/capability-client.ts","../src/rpc/sturdyrefs.ts","../src/rpc/performance.ts","../src/rpc/connection-manager.ts","../src/rpc/level3-handlers.ts","../src/rpc/level4-types.ts","../src/rpc/level4-handlers.ts","../src/rpc/stream.ts","../src/rpc/bulk.ts","../src/rpc/realtime.ts","../src/rpc/stream-manager.ts","../src/rpc/streaming-connection.ts","../src/rpc/dynamic-reader.ts","../src/rpc/dynamic-writer.ts","../src/rpc/schema-capability.ts","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/constants.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/buffer-util.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/limiter.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/permessage-deflate.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/validation.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/receiver.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/sender.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/event-target.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/extension.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/stream.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/subprotocol.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js","../node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs","../src/proxy/websocket-proxy.ts"],"sourcesContent":["/**\n * Cap'n Proto 指针编解码\n * 纯 TypeScript 实现\n */\n\nexport enum PointerTag {\n STRUCT = 0,\n LIST = 1,\n FAR = 2,\n OTHER = 3,\n}\n\nexport enum ElementSize {\n VOID = 0,\n BIT = 1,\n BYTE = 2,\n TWO_BYTES = 3,\n FOUR_BYTES = 4,\n EIGHT_BYTES = 5,\n POINTER = 6,\n COMPOSITE = 7,\n INLINE_COMPOSITE = 7, // Alias for COMPOSITE\n}\n\nexport interface StructPointer {\n tag: PointerTag.STRUCT;\n offset: number; // 字偏移(有符号)\n dataWords: number; // 数据段字数\n pointerCount: number; // 指针段字数\n}\n\nexport interface ListPointer {\n tag: PointerTag.LIST;\n offset: number;\n elementSize: ElementSize;\n elementCount: number;\n}\n\nexport interface FarPointer {\n tag: PointerTag.FAR;\n doubleFar: boolean;\n targetSegment: number;\n targetOffset: number;\n}\n\nexport type Pointer = StructPointer | ListPointer | FarPointer | { tag: PointerTag.OTHER };\n\n/**\n * 解码指针(64位)\n */\nexport function decodePointer(ptr: bigint): Pointer {\n const tag = Number(ptr & BigInt(3)) as PointerTag;\n\n switch (tag) {\n case PointerTag.STRUCT: {\n const offset = Number(ptr >> BigInt(2)) & 0x3fffffff;\n const signedOffset = offset >= 0x20000000 ? offset - 0x40000000 : offset;\n const dataWords = Number((ptr >> BigInt(32)) & BigInt(0xffff));\n const pointerCount = Number((ptr >> BigInt(48)) & BigInt(0xffff));\n return { tag, offset: signedOffset, dataWords, pointerCount };\n }\n\n case PointerTag.LIST: {\n const offset = Number(ptr >> BigInt(2)) & 0x3fffffff;\n const signedOffset = offset >= 0x20000000 ? offset - 0x40000000 : offset;\n const elementSize = Number((ptr >> BigInt(32)) & BigInt(7)) as ElementSize;\n const elementCount = Number((ptr >> BigInt(35)) & BigInt(0x1fffffff));\n return { tag, offset: signedOffset, elementSize, elementCount };\n }\n\n case PointerTag.FAR: {\n const doubleFar = Boolean((ptr >> BigInt(2)) & BigInt(1));\n const targetOffset = Number((ptr >> BigInt(3)) & BigInt(0x1fffffff));\n const targetSegment = Number((ptr >> BigInt(32)) & BigInt(0xffffffff));\n return { tag, doubleFar, targetSegment, targetOffset };\n }\n\n default:\n return { tag: PointerTag.OTHER };\n }\n}\n\n/**\n * 编码 Struct 指针\n */\nexport function encodeStructPointer(\n offset: number,\n dataWords: number,\n pointerCount: number\n): bigint {\n const offsetBits = BigInt(offset < 0 ? offset + 0x40000000 : offset) & BigInt(0x3fffffff);\n return (\n (offsetBits << BigInt(2)) |\n (BigInt(dataWords) << BigInt(32)) |\n (BigInt(pointerCount) << BigInt(48))\n );\n}\n\n/**\n * 编码 List 指针\n */\nexport function encodeListPointer(\n offset: number,\n elementSize: ElementSize,\n elementCount: number\n): bigint {\n const offsetBits = BigInt(offset < 0 ? offset + 0x40000000 : offset) & BigInt(0x3fffffff);\n return (\n (offsetBits << BigInt(2)) |\n BigInt(1) | // LIST tag\n (BigInt(elementSize) << BigInt(32)) |\n (BigInt(elementCount) << BigInt(35))\n );\n}\n\n/**\n * 编码 Far 指针\n */\nexport function encodeFarPointer(segment: number, offset: number, doubleFar = false): bigint {\n const offsetBits = BigInt(offset) & BigInt(0x1fffffff);\n const segmentBits = BigInt(segment) & BigInt(0xffffffff);\n\n return (\n (segmentBits << BigInt(32)) |\n (offsetBits << BigInt(3)) |\n (doubleFar ? BigInt(1) << BigInt(2) : BigInt(0)) |\n BigInt(2)\n ); // FAR tag\n}\n","/**\n * Cap'n Proto Segment 管理\n * 纯 TypeScript 实现\n */\n\nexport const WORD_SIZE = 8;\n\nexport class Segment {\n private buffer: ArrayBuffer;\n private view: DataView;\n private _size: number; // 当前已使用字节数\n\n constructor(initialCapacity = 1024) {\n this.buffer = new ArrayBuffer(initialCapacity);\n this.view = new DataView(this.buffer);\n this._size = 0;\n }\n\n /**\n * 从现有 buffer 创建(用于读取)\n */\n static fromBuffer(buffer: ArrayBuffer): Segment {\n const seg = new Segment(0);\n seg.buffer = buffer;\n seg.view = new DataView(buffer);\n seg._size = buffer.byteLength;\n return seg;\n }\n\n /**\n * 确保容量足够\n */\n private ensureCapacity(minBytes: number): void {\n if (this.buffer.byteLength >= minBytes) return;\n\n // 双倍扩展\n let newCapacity = this.buffer.byteLength * 2;\n while (newCapacity < minBytes) {\n newCapacity *= 2;\n }\n\n const newBuffer = new ArrayBuffer(newCapacity);\n new Uint8Array(newBuffer).set(new Uint8Array(this.buffer, 0, this._size));\n this.buffer = newBuffer;\n this.view = new DataView(newBuffer);\n }\n\n /**\n * 分配空间,返回字偏移\n */\n allocate(words: number): number {\n const bytes = words * WORD_SIZE;\n const offset = this._size;\n this.ensureCapacity(offset + bytes);\n this._size = offset + bytes;\n return offset / WORD_SIZE;\n }\n\n /**\n * 获取字(64位)\n */\n getWord(wordOffset: number): bigint {\n const byteOffset = wordOffset * WORD_SIZE;\n if (byteOffset + 8 > this._size) {\n throw new Error(\n `Offset ${wordOffset} is outside the bounds of the segment (${this.wordCount} words)`\n );\n }\n const low = BigInt(this.view.getUint32(byteOffset, true));\n const high = BigInt(this.view.getUint32(byteOffset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 设置字(64位)\n */\n setWord(wordOffset: number, value: bigint): void {\n const byteOffset = wordOffset * WORD_SIZE;\n if (byteOffset + 8 > this.buffer.byteLength) {\n throw new Error(`Offset ${wordOffset} is outside the bounds of the segment`);\n }\n this.view.setUint32(byteOffset, Number(value & BigInt(0xffffffff)), true);\n this.view.setUint32(byteOffset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 获取原始 buffer(只读到 _size)\n */\n asUint8Array(): Uint8Array {\n return new Uint8Array(this.buffer, 0, this._size);\n }\n\n /**\n * 获取底层 ArrayBuffer\n */\n getArrayBuffer(): ArrayBuffer {\n return this.buffer;\n }\n\n /**\n * 获取字数量\n */\n get wordCount(): number {\n return this._size / WORD_SIZE;\n }\n\n /**\n * 获取字节数量\n */\n get byteLength(): number {\n return this._size;\n }\n\n /**\n * 获取 DataView\n */\n get dataView(): DataView {\n return this.view;\n }\n}\n","/**\n * Cap'n Proto MessageBuilder\n * 纯 TypeScript 实现\n */\n\nimport { ListBuilder } from './list.js';\nimport { ElementSize, PointerTag, encodeListPointer, encodeStructPointer } from './pointer.js';\nimport { Segment, WORD_SIZE } from './segment.js';\n\nexport class MessageBuilder {\n private segment: Segment;\n private rootSet = false;\n\n constructor() {\n // 预留消息头空间(假设单段)\n this.segment = new Segment(1024);\n // 预留 8 字节给段大小\n this.segment.allocate(1);\n }\n\n /**\n * 初始化根结构\n */\n initRoot(dataWords: number, pointerCount: number): StructBuilder {\n if (this.rootSet) {\n throw new Error('Root already initialized');\n }\n\n // 分配根结构空间\n const size = dataWords + pointerCount;\n const structOffset = this.segment.allocate(size);\n\n // 在位置 0 写入根指针\n const rootPtr = encodeStructPointer(structOffset - 1, dataWords, pointerCount);\n this.segment.setWord(0, rootPtr);\n\n this.rootSet = true;\n\n return new StructBuilder(this, 0, structOffset, dataWords, pointerCount);\n }\n\n /**\n * 序列化为 ArrayBuffer\n */\n toArrayBuffer(): ArrayBuffer {\n const segmentData = this.segment.asUint8Array();\n const wordCount = this.segment.wordCount;\n\n // 构建消息头\n // 第一个字:段数量-1(低32位)和第一段大小(高32位)\n const header = new ArrayBuffer(8);\n const headerView = new DataView(header);\n headerView.setUint32(0, 0, true); // 段数量-1 = 0(单段)\n headerView.setUint32(4, wordCount, true); // 第一段大小\n\n // 合并头和数据\n const result = new Uint8Array(8 + segmentData.byteLength);\n result.set(new Uint8Array(header), 0);\n result.set(segmentData, 8);\n\n return result.buffer;\n }\n\n /**\n * 获取段(内部使用)\n */\n getSegment(): Segment {\n return this.segment;\n }\n}\n\n/**\n * 结构构建器\n */\nexport class StructBuilder {\n constructor(\n private message: MessageBuilder,\n private segmentIndex: number,\n private wordOffset: number,\n private dataWords: number,\n private pointerCount: number\n ) {}\n\n /**\n * 设置 bool 字段\n */\n setBool(bitOffset: number, value: boolean): void {\n const byteOffset = Math.floor(bitOffset / 8);\n const bitInByte = bitOffset % 8;\n const segment = this.message.getSegment();\n const view = segment.dataView;\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n\n const current = view.getUint8(offset);\n const newValue = value ? current | (1 << bitInByte) : current & ~(1 << bitInByte);\n view.setUint8(offset, newValue);\n }\n\n /**\n * 设置 int8 字段\n */\n setInt8(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt8(this.wordOffset * WORD_SIZE + byteOffset, value);\n }\n\n /**\n * 设置 int16 字段\n */\n setInt16(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt16(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 int32 字段\n */\n setInt32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 int64 字段\n */\n setInt64(byteOffset: number, value: bigint): void {\n const segment = this.message.getSegment();\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n segment.dataView.setUint32(offset, Number(value & BigInt(0xffffffff)), true);\n segment.dataView.setInt32(offset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 设置 uint8 字段\n */\n setUint8(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint8(this.wordOffset * WORD_SIZE + byteOffset, value);\n }\n\n /**\n * 设置 uint16 字段\n */\n setUint16(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint16(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 uint32 字段\n */\n setUint32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 uint64 字段\n */\n setUint64(byteOffset: number, value: bigint): void {\n const segment = this.message.getSegment();\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n segment.dataView.setUint32(offset, Number(value & BigInt(0xffffffff)), true);\n segment.dataView.setUint32(offset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 设置 float32 字段\n */\n setFloat32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setFloat32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 float64 字段\n */\n setFloat64(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setFloat64(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 获取 uint16 字段(用于 UnionBuilder 读取 tag)\n */\n getUint16(byteOffset: number): number {\n const segment = this.message.getSegment();\n return segment.dataView.getUint16(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 设置文本字段\n */\n setText(pointerIndex: number, value: string): void {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 编码文本\n const bytes = new TextEncoder().encode(`${value}\\0`);\n const wordCount = Math.ceil(bytes.length / WORD_SIZE);\n const listOffset = segment.allocate(wordCount);\n\n // 写入文本数据\n new Uint8Array(segment.dataView.buffer, listOffset * WORD_SIZE, bytes.length).set(bytes);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, ElementSize.BYTE, bytes.length);\n segment.setWord(ptrOffset, ptr);\n }\n\n /**\n * 设置数据字段(Uint8Array)\n * @param pointerIndex - 指针索引\n * @param value - Uint8Array 数据\n */\n setData(pointerIndex: number, value: Uint8Array): void {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 处理空数组\n if (value.length === 0) {\n const ptr = encodeListPointer(0, ElementSize.BYTE, 0);\n segment.setWord(ptrOffset, ptr);\n return;\n }\n\n const wordCount = Math.ceil(value.length / WORD_SIZE);\n const listOffset = segment.allocate(wordCount);\n\n // 写入数据\n new Uint8Array(segment.dataView.buffer, listOffset * WORD_SIZE, value.length).set(value);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, ElementSize.BYTE, value.length);\n segment.setWord(ptrOffset, ptr);\n }\n\n /**\n * 初始化嵌套结构\n */\n initStruct(pointerIndex: number, dataWords: number, pointerCount: number): StructBuilder {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 分配结构空间\n const size = dataWords + pointerCount;\n const structOffset = segment.allocate(size);\n\n // 写入指针\n const ptr = encodeStructPointer(structOffset - ptrOffset - 1, dataWords, pointerCount);\n segment.setWord(ptrOffset, ptr);\n\n return new StructBuilder(this.message, 0, structOffset, dataWords, pointerCount);\n }\n\n /**\n * 初始化列表\n */\n initList<T>(\n pointerIndex: number,\n elementSize: ElementSize,\n elementCount: number,\n structSize?: { dataWords: number; pointerCount: number }\n ): ListBuilder<T> {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 计算列表大小\n let elementWords = 1;\n if (elementSize === ElementSize.BYTE) elementWords = 1;\n else if (elementSize === ElementSize.TWO_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.FOUR_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.EIGHT_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.COMPOSITE && structSize) {\n elementWords = structSize.dataWords + structSize.pointerCount;\n }\n\n const totalWords = elementWords * elementCount;\n const listOffset = segment.allocate(totalWords);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, elementSize, elementCount);\n segment.setWord(ptrOffset, ptr);\n\n return new ListBuilder<T>(this.message, elementSize, elementCount, structSize, listOffset);\n }\n}\n","/**\n * Cap'n Proto List 实现\n * 纯 TypeScript\n */\n\nimport { type MessageBuilder, StructBuilder } from './message-builder.js';\nimport { type MessageReader, StructReader } from './message-reader.js';\nimport { ElementSize, type ListPointer, PointerTag, decodePointer } from './pointer.js';\nimport { type Segment, WORD_SIZE } from './segment.js';\n\n/**\n * ListReader - 读取列表\n */\nexport class ListReader<T> {\n private segment: Segment;\n private startOffset: number; // 字偏移\n private segmentIndex: number;\n\n constructor(\n private message: MessageReader,\n segmentIndex: number,\n private elementSize: ElementSize,\n private elementCount: number,\n private structSize: { dataWords: number; pointerCount: number } | undefined,\n wordOffset: number\n ) {\n this.segmentIndex = segmentIndex;\n this.segment = message.getSegment(segmentIndex)!;\n this.startOffset = wordOffset;\n }\n\n /**\n * 列表长度\n */\n get length(): number {\n return this.elementCount;\n }\n\n /**\n * 获取元素(基础类型)\n */\n getPrimitive(index: number): number | bigint {\n if (index < 0 || index >= this.elementCount) {\n throw new RangeError('Index out of bounds');\n }\n\n switch (this.elementSize) {\n case ElementSize.BIT: {\n const byteOffset = Math.floor(index / 8);\n const bitInByte = index % 8;\n const byte = this.segment.dataView.getUint8(this.startOffset * WORD_SIZE + byteOffset);\n return (byte & (1 << bitInByte)) !== 0 ? 1 : 0;\n }\n\n case ElementSize.BYTE:\n return this.segment.dataView.getUint8(this.startOffset * WORD_SIZE + index);\n\n case ElementSize.TWO_BYTES:\n return this.segment.dataView.getUint16(this.startOffset * WORD_SIZE + index * 2, true);\n\n case ElementSize.FOUR_BYTES:\n return this.segment.dataView.getUint32(this.startOffset * WORD_SIZE + index * 4, true);\n\n case ElementSize.EIGHT_BYTES: {\n const offset = this.startOffset * WORD_SIZE + index * 8;\n const low = BigInt(this.segment.dataView.getUint32(offset, true));\n const high = BigInt(this.segment.dataView.getUint32(offset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n default:\n throw new Error(`Unsupported element size: ${this.elementSize}`);\n }\n }\n\n /**\n * 获取结构元素\n */\n getStruct(index: number): StructReader {\n if (!this.structSize) {\n throw new Error('Not a struct list');\n }\n\n const { dataWords, pointerCount } = this.structSize;\n const size = dataWords + pointerCount;\n const offset = this.startOffset + index * size;\n\n return new StructReader(this.message, this.segmentIndex, offset, dataWords, pointerCount);\n }\n\n /**\n * 迭代器\n */\n *[Symbol.iterator](): Iterator<T> {\n for (let i = 0; i < this.elementCount; i++) {\n yield this.getPrimitive(i) as T;\n }\n }\n}\n\n/**\n * ListBuilder - 构建列表\n */\nexport class ListBuilder<_T> {\n private segment: Segment;\n private startOffset: number;\n\n constructor(\n private message: MessageBuilder,\n private elementSize: ElementSize,\n private elementCount: number,\n private structSize: { dataWords: number; pointerCount: number } | undefined,\n wordOffset: number\n ) {\n this.segment = message.getSegment();\n this.startOffset = wordOffset;\n }\n\n /**\n * 列表长度\n */\n get length(): number {\n return this.elementCount;\n }\n\n /**\n * 设置基础类型元素\n */\n setPrimitive(index: number, value: number | bigint): void {\n if (index < 0 || index >= this.elementCount) {\n throw new RangeError('Index out of bounds');\n }\n\n switch (this.elementSize) {\n case ElementSize.BIT: {\n const byteOffset = Math.floor(index / 8);\n const bitInByte = index % 8;\n const offset = this.startOffset * WORD_SIZE + byteOffset;\n const current = this.segment.dataView.getUint8(offset);\n const newValue = value ? current | (1 << bitInByte) : current & ~(1 << bitInByte);\n this.segment.dataView.setUint8(offset, newValue);\n break;\n }\n\n case ElementSize.BYTE:\n this.segment.dataView.setUint8(this.startOffset * WORD_SIZE + index, Number(value));\n break;\n\n case ElementSize.TWO_BYTES:\n this.segment.dataView.setUint16(\n this.startOffset * WORD_SIZE + index * 2,\n Number(value),\n true\n );\n break;\n\n case ElementSize.FOUR_BYTES:\n this.segment.dataView.setUint32(\n this.startOffset * WORD_SIZE + index * 4,\n Number(value),\n true\n );\n break;\n\n case ElementSize.EIGHT_BYTES: {\n const offset = this.startOffset * WORD_SIZE + index * 8;\n const bigValue = value as bigint;\n this.segment.dataView.setUint32(offset, Number(bigValue & BigInt(0xffffffff)), true);\n this.segment.dataView.setUint32(offset + 4, Number(bigValue >> BigInt(32)), true);\n break;\n }\n\n default:\n throw new Error(`Unsupported element size: ${this.elementSize}`);\n }\n }\n\n /**\n * 获取结构元素(用于修改)\n */\n getStruct(index: number): StructBuilder {\n if (!this.structSize) {\n throw new Error('Not a struct list');\n }\n\n const { dataWords, pointerCount } = this.structSize;\n const size = dataWords + pointerCount;\n const offset = this.startOffset + index * size;\n\n return new StructBuilder(this.message, 0, offset, dataWords, pointerCount);\n }\n}\n","/**\n * Cap'n Proto MessageReader\n * 纯 TypeScript 实现\n */\n\nimport { ListReader } from './list.js';\nimport {\n ElementSize,\n type FarPointer,\n type ListPointer,\n PointerTag,\n type StructPointer,\n decodePointer,\n} from './pointer.js';\nimport { Segment, WORD_SIZE } from './segment.js';\n\nexport class MessageReader {\n private segments: Segment[];\n\n constructor(buffer: ArrayBuffer | Uint8Array) {\n const uint8Array = buffer instanceof ArrayBuffer ? new Uint8Array(buffer) : buffer;\n\n // 初始化空段数组(用于无效消息)\n this.segments = [];\n\n // 检查最小大小(至少需要8字节的头部)\n if (uint8Array.byteLength < 8) {\n // 消息太小,视为空消息\n return;\n }\n\n // 解析消息头\n // 第一个字:段数量-1(低32位)和第一段大小(高32位)\n const view = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength);\n const firstWordLow = view.getUint32(0, true);\n const firstWordHigh = view.getUint32(4, true);\n\n const segmentCount = (firstWordLow & 0xffffffff) + 1;\n const firstSegmentSize = firstWordHigh;\n\n let offset = 8;\n const segmentSizes: number[] = [firstSegmentSize];\n\n // 读取剩余段大小\n for (let i = 1; i < segmentCount; i++) {\n if (offset + 4 > uint8Array.byteLength) {\n // 消息过早结束,视为空消息\n this.segments = [];\n return;\n }\n segmentSizes.push(view.getUint32(offset, true));\n offset += 4;\n }\n\n // 对齐到 8 字节\n offset = (offset + 7) & ~7;\n\n // 检查是否有足够的空间容纳段表\n if (offset > uint8Array.byteLength) {\n this.segments = [];\n return;\n }\n\n // 创建段\n this.segments = [];\n for (const size of segmentSizes) {\n if (offset + size * WORD_SIZE > uint8Array.byteLength) {\n // 段数据不足,截断或视为空消息\n // 官方实现:返回已读取的部分\n break;\n }\n const segmentBuffer = uint8Array.slice(offset, offset + size * WORD_SIZE);\n this.segments.push(Segment.fromBuffer(segmentBuffer.buffer));\n offset += size * WORD_SIZE;\n }\n }\n\n /**\n * 获取根结构\n */\n getRoot(_dataWords: number, _pointerCount: number): StructReader {\n // root 指针在位置 0,解析它找到实际数据位置\n const segment = this.segments[0];\n const ptr = decodePointer(segment.getWord(0));\n\n if (ptr.tag === PointerTag.STRUCT) {\n const structPtr = ptr as StructPointer;\n const dataOffset = 1 + structPtr.offset; // 跳过指针本身\n return new StructReader(this, 0, dataOffset, structPtr.dataWords, structPtr.pointerCount);\n }\n\n if (ptr.tag === PointerTag.FAR) {\n // Far pointer: 指向另一个 segment 中的 landing pad\n const farPtr = ptr as FarPointer;\n const targetSegment = this.getSegment(farPtr.targetSegment);\n if (!targetSegment) {\n throw new Error(`Far pointer references non-existent segment ${farPtr.targetSegment}`);\n }\n\n if (farPtr.doubleFar) {\n // Double-far: landing pad 本身也是一个 far 指针\n // landing pad 位置: targetOffset 指向的位置\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.FAR) {\n throw new Error('Double-far landing pad is not a far pointer');\n }\n const innerFarPtr = landingPadPtr as FarPointer;\n const finalSegment = this.getSegment(innerFarPtr.targetSegment);\n if (!finalSegment) {\n throw new Error(\n `Double-far references non-existent segment ${innerFarPtr.targetSegment}`\n );\n }\n // 实际的 struct 指针在 innerFarPtr.targetOffset\n const structPtr = decodePointer(\n finalSegment.getWord(innerFarPtr.targetOffset)\n ) as StructPointer;\n const dataOffset = innerFarPtr.targetOffset + 1 + structPtr.offset;\n return new StructReader(\n this,\n innerFarPtr.targetSegment,\n dataOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n // Single-far: landing pad 是实际的 struct 指针\n const structPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset)) as StructPointer;\n const dataOffset = farPtr.targetOffset + 1 + structPtr.offset;\n return new StructReader(\n this,\n farPtr.targetSegment,\n dataOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n\n throw new Error(`Root pointer is not a struct or far pointer: ${ptr.tag}`);\n }\n\n /**\n * 获取段\n */\n getSegment(index: number): Segment | undefined {\n return this.segments[index];\n }\n\n /**\n * 解析指针,处理 far pointer 间接寻址\n * 返回 { segmentIndex, wordOffset, pointer },其中 pointer 是实际的 struct/list 指针\n */\n resolvePointer(\n segmentIndex: number,\n wordOffset: number\n ): { segmentIndex: number; wordOffset: number; pointer: StructPointer | ListPointer } | null {\n const segment = this.getSegment(segmentIndex);\n if (!segment) return null;\n\n const ptrValue = segment.getWord(wordOffset);\n if (ptrValue === 0n) return null;\n\n const ptr = decodePointer(ptrValue);\n\n if (ptr.tag === PointerTag.STRUCT || ptr.tag === PointerTag.LIST) {\n // 直接指针,计算目标偏移\n const targetOffset = wordOffset + 1 + ptr.offset;\n return {\n segmentIndex,\n wordOffset: targetOffset,\n pointer: ptr as StructPointer | ListPointer,\n };\n }\n\n if (ptr.tag === PointerTag.FAR) {\n const farPtr = ptr as FarPointer;\n const targetSegment = this.getSegment(farPtr.targetSegment);\n if (!targetSegment) return null;\n\n if (farPtr.doubleFar) {\n // Double-far: landing pad 指向另一个 far 指针\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.FAR) return null;\n const innerFarPtr = landingPadPtr as FarPointer;\n const finalSegment = this.getSegment(innerFarPtr.targetSegment);\n if (!finalSegment) return null;\n const finalPtr = decodePointer(finalSegment.getWord(innerFarPtr.targetOffset));\n if (finalPtr.tag !== PointerTag.STRUCT && finalPtr.tag !== PointerTag.LIST) return null;\n const targetOffset = innerFarPtr.targetOffset + 1 + finalPtr.offset;\n return {\n segmentIndex: innerFarPtr.targetSegment,\n wordOffset: targetOffset,\n pointer: finalPtr as StructPointer | ListPointer,\n };\n }\n // Single-far: landing pad 是实际的指针\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.STRUCT && landingPadPtr.tag !== PointerTag.LIST)\n return null;\n const targetOffset = farPtr.targetOffset + 1 + landingPadPtr.offset;\n return {\n segmentIndex: farPtr.targetSegment,\n wordOffset: targetOffset,\n pointer: landingPadPtr as StructPointer | ListPointer,\n };\n }\n\n return null;\n }\n\n /**\n * 段数量\n */\n get segmentCount(): number {\n return this.segments.length;\n }\n}\n\n/**\n * 结构读取器\n */\nexport class StructReader {\n constructor(\n private message: MessageReader,\n private segmentIndex: number,\n private wordOffset: number,\n private dataWords: number,\n private pointerCount: number\n ) {}\n\n /**\n * 获取 bool 字段\n */\n getBool(bitOffset: number): boolean {\n const byteOffset = Math.floor(bitOffset / 8);\n const bitInByte = bitOffset % 8;\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查:确保在 data section 内\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset >= dataSectionEnd) {\n return false; // 越界返回默认值\n }\n\n const byte = segment.dataView.getUint8(dataOffset);\n return (byte & (1 << bitInByte)) !== 0;\n }\n\n /**\n * 获取 int8 字段\n */\n getInt8(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset >= dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getInt8(dataOffset);\n }\n\n /**\n * 获取 int16 字段\n */\n getInt16(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 2 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getInt16(dataOffset, true);\n }\n\n /**\n * 获取 int32 字段\n */\n getInt32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getInt32(dataOffset, true);\n }\n\n /**\n * 获取 int64 字段\n */\n getInt64(byteOffset: number): bigint {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) {\n return BigInt(0);\n }\n\n const low = BigInt(segment.dataView.getUint32(dataOffset, true));\n const high = BigInt(segment.dataView.getInt32(dataOffset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 获取 uint8 字段\n */\n getUint8(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset >= dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getUint8(dataOffset);\n }\n\n /**\n * 获取 uint16 字段\n */\n getUint16(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 2 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getUint16(dataOffset, true);\n }\n\n /**\n * 获取 uint32 字段\n */\n getUint32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getUint32(dataOffset, true);\n }\n\n /**\n * 获取 uint64 字段\n */\n getUint64(byteOffset: number): bigint {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) {\n return BigInt(0);\n }\n\n const low = BigInt(segment.dataView.getUint32(dataOffset, true));\n const high = BigInt(segment.dataView.getUint32(dataOffset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 获取 float32 字段\n */\n getFloat32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 4 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getFloat32(dataOffset, true);\n }\n\n /**\n * 获取 float64 字段\n */\n getFloat64(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const dataOffset = this.wordOffset * WORD_SIZE + byteOffset;\n\n // 边界检查\n const dataSectionEnd = this.wordOffset * WORD_SIZE + this.dataWords * WORD_SIZE;\n if (dataOffset < 0 || dataOffset + 8 > dataSectionEnd) {\n return 0;\n }\n\n return segment.dataView.getFloat64(dataOffset, true);\n }\n\n /**\n * 获取文本字段\n */\n getText(pointerIndex: number): string {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return '';\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.LIST) return '';\n\n const listPtr = pointer as ListPointer;\n const segment = this.message.getSegment(segmentIndex)!;\n\n // Text is stored as List(UInt8) with NUL terminator\n // elementCount includes the NUL terminator\n const byteLength = listPtr.elementCount > 0 ? listPtr.elementCount - 1 : 0;\n if (byteLength === 0) return '';\n\n // 读取文本字节\n const bytes = new Uint8Array(segment.dataView.buffer, wordOffset * WORD_SIZE, byteLength);\n return new TextDecoder().decode(bytes);\n }\n\n /**\n * 获取数据字段\n * Data is stored as List(UInt8) without NUL terminator\n * @param pointerIndex - The index of the pointer in the pointer section\n * @returns Uint8Array of the data content, or undefined if null pointer\n */\n getData(pointerIndex: number): Uint8Array | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return undefined;\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.LIST) return undefined;\n\n const listPtr = pointer as ListPointer;\n const segment = this.message.getSegment(segmentIndex)!;\n\n // Data is stored as List(UInt8) without NUL terminator\n const byteLength = listPtr.elementCount;\n if (byteLength === 0) return new Uint8Array(0);\n\n // Return a copy of the raw bytes\n const bytes = new Uint8Array(segment.dataView.buffer, wordOffset * WORD_SIZE, byteLength);\n return new Uint8Array(bytes);\n }\n\n /**\n * 获取嵌套结构\n */\n getStruct(\n pointerIndex: number,\n _dataWords: number,\n _pointerCount: number\n ): StructReader | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return undefined;\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.STRUCT) return undefined;\n\n const structPtr = pointer as StructPointer;\n\n return new StructReader(\n this.message,\n segmentIndex,\n wordOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n\n /**\n * 获取列表\n */\n getList<T>(\n pointerIndex: number,\n _elementSize: ElementSize,\n structSize?: { dataWords: number; pointerCount: number }\n ): ListReader<T> | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return undefined;\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.LIST) return undefined;\n\n const listPtr = pointer as ListPointer;\n let targetOffset = wordOffset;\n let elementCount = listPtr.elementCount;\n let actualStructSize = structSize;\n const segment = this.message.getSegment(segmentIndex)!;\n\n // For INLINE_COMPOSITE lists, read the tag word\n if (listPtr.elementSize === ElementSize.COMPOSITE) {\n // 边界检查:确保有足够的空间读取 tag word\n if (targetOffset < 0 || targetOffset >= segment.wordCount) {\n return undefined;\n }\n\n try {\n const tagWord = segment.getWord(targetOffset);\n // Tag word: elementCount (32 bits) | dataWords (16 bits) | pointerCount (16 bits)\n elementCount = Number(tagWord & BigInt(0xffffffff));\n const dataWords = Number((tagWord >> BigInt(32)) & BigInt(0xffff));\n const pointerCount = Number((tagWord >> BigInt(48)) & BigInt(0xffff));\n actualStructSize = { dataWords, pointerCount };\n targetOffset += 1; // Skip tag word\n } catch {\n return undefined;\n }\n }\n\n return new ListReader<T>(\n this.message,\n segmentIndex,\n listPtr.elementSize,\n elementCount,\n actualStructSize,\n targetOffset\n );\n }\n}\n","/**\n * Cap'n Proto Union 支持\n * 纯 TypeScript 实现\n */\n\nimport { MessageBuilder, type StructBuilder } from './message-builder.js';\nimport { MessageReader, type StructReader } from './message-reader.js';\nimport { ElementSize } from './pointer.js';\n\n/**\n * UnionReader - 读取 Union 的 tag 和 variant\n */\nexport class UnionReader {\n constructor(\n private struct: StructReader,\n private tagOffset: number, // tag 的字节偏移\n private variants: Map<number, string> // tag 值 -> variant 名称\n ) {}\n\n /**\n * 获取当前激活的 variant tag\n */\n getTag(): number {\n return this.struct.getUint16(this.tagOffset);\n }\n\n /**\n * 获取当前激活的 variant 名称\n */\n getVariantName(): string | undefined {\n return this.variants.get(this.getTag());\n }\n\n /**\n * 检查是否是某个 variant\n */\n is(variantTag: number): boolean {\n return this.getTag() === variantTag;\n }\n}\n\n/**\n * UnionBuilder - 设置 Union 的 tag 和 variant\n */\nexport class UnionBuilder {\n constructor(\n private struct: StructBuilder,\n private tagOffset: number\n ) {}\n\n /**\n * 获取当前 tag\n */\n getTag(): number {\n return this.struct.getUint16(this.tagOffset);\n }\n\n /**\n * 设置 tag\n */\n setTag(tag: number): void {\n this.struct.setUint16(this.tagOffset, tag);\n }\n\n /**\n * 初始化某个 variant(自动设置 tag)\n */\n initVariant(tag: number, initFn: () => void): void {\n this.setTag(tag);\n initFn();\n }\n}\n\n/**\n * 创建 UnionReader 的工厂函数\n */\nexport function createUnionReader(\n struct: StructReader,\n tagOffset: number,\n variants: Record<number, string>\n): UnionReader {\n return new UnionReader(\n struct,\n tagOffset,\n new Map(Object.entries(variants).map(([k, v]) => [Number(k), v]))\n );\n}\n\n/**\n * 创建 UnionBuilder 的工厂函数\n */\nexport function createUnionBuilder(struct: StructBuilder, tagOffset: number): UnionBuilder {\n return new UnionBuilder(struct, tagOffset);\n}\n","/**\n * RPC Message Serialization\n *\n * Implements full serialization/deserialization of RPC messages using\n * the existing MessageBuilder/MessageReader infrastructure.\n *\n * Reference: rpc.capnp schema\n */\n\nimport { MessageBuilder, type StructBuilder } from '../core/message-builder.js';\nimport { MessageReader, type StructReader } from '../core/message-reader.js';\nimport { ElementSize } from '../core/pointer.js';\nimport type {\n Bootstrap,\n Call,\n CapDescriptor,\n Disembargo,\n Exception,\n Finish,\n MessageTarget,\n Payload,\n PromisedAnswer,\n PromisedAnswerOp,\n Provide,\n Release,\n Resolve,\n Return,\n RpcMessage,\n SendResultsTo,\n} from './rpc-types.js';\n\n// ========================================================================================\n// Constants from rpc.capnp schema\n// ========================================================================================\n\n// Message union tags\nconst MSG_UNIMPLEMENTED = 0;\nconst MSG_ABORT = 1;\nconst MSG_BOOTSTRAP = 8;\nconst MSG_CALL = 2;\nconst MSG_RETURN = 3;\nconst MSG_FINISH = 4;\nconst MSG_RESOLVE = 5;\nconst MSG_RELEASE = 6;\nconst MSG_DISEMBARGO = 13;\nconst MSG_PROVIDE = 10;\nconst MSG_ACCEPT = 11;\nconst MSG_JOIN = 12;\n\n// Return union tags\nconst RET_RESULTS = 0;\nconst RET_EXCEPTION = 1;\nconst RET_CANCELED = 2;\nconst RET_RESULTS_SENT_ELSEWHERE = 3;\nconst RET_TAKE_FROM_OTHER_QUESTION = 4;\nconst RET_ACCEPT_FROM_THIRD_PARTY = 5;\n\n// SendResultsTo union tags\nconst SEND_TO_CALLER = 0;\nconst SEND_TO_YOURSELF = 1;\nconst SEND_TO_THIRD_PARTY = 2;\n\n// MessageTarget union tags\nconst TARGET_IMPORTED_CAP = 0;\nconst TARGET_PROMISED_ANSWER = 1;\n\n// CapDescriptor union tags\nconst CAP_NONE = 0;\nconst CAP_SENDER_HOSTED = 1;\nconst CAP_SENDER_PROMISE = 2;\nconst CAP_RECEIVER_HOSTED = 3;\nconst CAP_RECEIVER_ANSWER = 4;\nconst CAP_THIRD_PARTY_HOSTED = 5;\n\n// Resolve union tags\nconst RESOLVE_CAP = 0;\nconst RESOLVE_EXCEPTION = 1;\n\n// Disembargo context union tags\nconst DISEMBARGO_SENDER_LOOPBACK = 0;\nconst DISEMBARGO_RECEIVER_LOOPBACK = 1;\nconst DISEMBARGO_ACCEPT = 2;\nconst DISEMBARGO_PROVIDE = 3;\n\n// PromisedAnswer.Op union tags\nconst OP_NOOP = 0;\nconst OP_GET_POINTER_FIELD = 1;\n\n// Exception type union tags\nconst EXC_FAILED = 0;\nconst EXC_OVERLOADED = 1;\nconst EXC_DISCONNECTED = 2;\nconst EXC_UNIMPLEMENTED = 3;\n\n// ========================================================================================\n// Serialization: RpcMessage -> Uint8Array\n// ========================================================================================\n\nexport function serializeRpcMessage(message: RpcMessage): Uint8Array {\n const builder = new MessageBuilder();\n // Message struct: 6 data words, 1 pointer\n // union + questionId/answerId/promiseId/etc + padding\n const root = builder.initRoot(6, 1);\n\n switch (message.type) {\n case 'unimplemented':\n serializeUnimplemented(root, message.message);\n break;\n case 'abort':\n serializeAbort(root, message.exception);\n break;\n case 'bootstrap':\n serializeBootstrap(root, message.bootstrap);\n break;\n case 'call':\n serializeCall(root, message.call);\n break;\n case 'return':\n serializeReturn(root, message.return);\n break;\n case 'finish':\n serializeFinish(root, message.finish);\n break;\n case 'resolve':\n serializeResolve(root, message.resolve);\n break;\n case 'release':\n serializeRelease(root, message.release);\n break;\n case 'disembargo':\n serializeDisembargo(root, message.disembargo);\n break;\n case 'provide':\n serializeProvide(root, message.provide);\n break;\n case 'accept':\n serializeAccept(root, message.accept);\n break;\n case 'join':\n serializeJoin(root, message.join);\n break;\n }\n\n return new Uint8Array(builder.toArrayBuffer());\n}\n\nfunction serializeUnimplemented(root: StructBuilder, message: RpcMessage): void {\n // Set union tag\n root.setUint16(0, MSG_UNIMPLEMENTED);\n // Serialize nested message in pointer 0\n const _nestedData = serializeRpcMessage(message);\n const nestedBuilder = root.initStruct(0, 0, 1);\n // Copy nested data into the struct's content pointer\n // For simplicity, we store the serialized message as data bytes\n // In a full implementation, we'd properly embed the message structure\n const _contentPtr = nestedBuilder.initStruct(0, 0, 0);\n // Store length and data\n // This is a simplified approach - proper implementation would parse the nested message\n}\n\nfunction serializeAbort(root: StructBuilder, exception: Exception): void {\n root.setUint16(0, MSG_ABORT);\n serializeException(root, 0, exception);\n}\n\nfunction serializeBootstrap(root: StructBuilder, bootstrap: Bootstrap): void {\n root.setUint16(0, MSG_BOOTSTRAP);\n root.setUint32(8, bootstrap.questionId);\n // deprecatedObjectId is deprecated, skip\n}\n\nfunction serializeCall(root: StructBuilder, call: Call): void {\n root.setUint16(0, MSG_CALL);\n root.setUint32(8, call.questionId);\n root.setUint64(16, call.interfaceId);\n root.setUint16(24, call.methodId);\n root.setBool(208, call.allowThirdPartyTailCall); // bit 208 = word 26, bit 0\n root.setBool(209, call.noPromisePipelining); // bit 209\n root.setBool(210, call.onlyPromisePipeline); // bit 210\n\n // Serialize target in pointer 0\n serializeMessageTarget(root.initStruct(0, 2, 1), call.target);\n\n // Serialize params in pointer 1\n serializePayload(root.initStruct(1, 2, 2), call.params);\n\n // Serialize sendResultsTo in pointer 2\n serializeSendResultsTo(root.initStruct(2, 2, 1), call.sendResultsTo);\n}\n\nfunction serializeReturn(root: StructBuilder, ret: Return): void {\n root.setUint16(0, MSG_RETURN);\n root.setUint32(8, ret.answerId);\n root.setBool(192, ret.releaseParamCaps); // bit 192 = word 24, bit 0\n root.setBool(193, ret.noFinishNeeded); // bit 193\n\n // Serialize result based on type\n switch (ret.result.type) {\n case 'results':\n root.setUint16(2, RET_RESULTS);\n serializePayload(root.initStruct(0, 2, 2), ret.result.payload);\n break;\n case 'exception':\n root.setUint16(2, RET_EXCEPTION);\n serializeException(root, 0, ret.result.exception);\n break;\n case 'canceled':\n root.setUint16(2, RET_CANCELED);\n break;\n case 'resultsSentElsewhere':\n root.setUint16(2, RET_RESULTS_SENT_ELSEWHERE);\n break;\n case 'takeFromOtherQuestion':\n root.setUint16(2, RET_TAKE_FROM_OTHER_QUESTION);\n root.setUint32(12, ret.result.questionId);\n break;\n case 'acceptFromThirdParty':\n root.setUint16(2, RET_ACCEPT_FROM_THIRD_PARTY);\n // ThirdPartyCapId in pointer 0\n break;\n }\n}\n\nfunction serializeFinish(root: StructBuilder, finish: Finish): void {\n root.setUint16(0, MSG_FINISH);\n root.setUint32(8, finish.questionId);\n root.setBool(192, finish.releaseResultCaps); // bit 192\n root.setBool(193, finish.requireEarlyCancellationWorkaround); // bit 193\n}\n\nfunction serializeResolve(root: StructBuilder, resolve: Resolve): void {\n root.setUint16(0, MSG_RESOLVE);\n root.setUint32(8, resolve.promiseId);\n\n switch (resolve.resolution.type) {\n case 'cap':\n root.setUint16(2, RESOLVE_CAP);\n serializeCapDescriptor(root.initStruct(0, 2, 1), resolve.resolution.cap);\n break;\n case 'exception':\n root.setUint16(2, RESOLVE_EXCEPTION);\n serializeException(root, 0, resolve.resolution.exception);\n break;\n }\n}\n\nfunction serializeRelease(root: StructBuilder, release: Release): void {\n root.setUint16(0, MSG_RELEASE);\n root.setUint32(8, release.id);\n root.setUint32(12, release.referenceCount);\n}\n\nfunction serializeDisembargo(root: StructBuilder, disembargo: Disembargo): void {\n root.setUint16(0, MSG_DISEMBARGO);\n serializeMessageTarget(root.initStruct(0, 2, 1), disembargo.target);\n\n switch (disembargo.context.type) {\n case 'senderLoopback':\n root.setUint16(2, DISEMBARGO_SENDER_LOOPBACK);\n root.setUint32(12, disembargo.context.embargoId);\n break;\n case 'receiverLoopback':\n root.setUint16(2, DISEMBARGO_RECEIVER_LOOPBACK);\n root.setUint32(12, disembargo.context.embargoId);\n break;\n case 'accept':\n root.setUint16(2, DISEMBARGO_ACCEPT);\n break;\n case 'provide':\n root.setUint16(2, DISEMBARGO_PROVIDE);\n root.setUint32(12, disembargo.context.questionId);\n break;\n }\n}\n\nfunction serializeProvide(root: StructBuilder, provide: Provide): void {\n root.setUint16(0, MSG_PROVIDE);\n root.setUint32(8, provide.questionId);\n serializeMessageTarget(root.initStruct(0, 2, 1), provide.target);\n // RecipientId in pointer 1 - placeholder\n}\n\nfunction serializeAccept(\n _root: StructBuilder,\n _accept: { provision: { id: Uint8Array }; embargo: boolean }\n): void {\n // Level 3 - not fully implemented\n}\n\nfunction serializeJoin(\n _root: StructBuilder,\n _join: { otherCap: MessageTarget; joinId: number }\n): void {\n // Level 4 - not fully implemented\n}\n\n// ========================================================================================\n// Supporting Type Serialization\n// ========================================================================================\n\nfunction serializeMessageTarget(builder: StructBuilder, target: MessageTarget): void {\n switch (target.type) {\n case 'importedCap':\n builder.setUint16(0, TARGET_IMPORTED_CAP);\n builder.setUint32(8, target.importId);\n break;\n case 'promisedAnswer':\n builder.setUint16(0, TARGET_PROMISED_ANSWER);\n serializePromisedAnswer(builder.initStruct(0, 2, 1), target.promisedAnswer);\n break;\n }\n}\n\nfunction serializePromisedAnswer(builder: StructBuilder, promisedAnswer: PromisedAnswer): void {\n builder.setUint32(0, promisedAnswer.questionId);\n // Transform list in pointer 0\n if (promisedAnswer.transform.length > 0) {\n const listBuilder = builder.initList(\n 0,\n ElementSize.INLINE_COMPOSITE,\n promisedAnswer.transform.length,\n {\n dataWords: 2,\n pointerCount: 0,\n }\n );\n for (let i = 0; i < promisedAnswer.transform.length; i++) {\n serializePromisedAnswerOp(listBuilder.getStruct(i), promisedAnswer.transform[i]);\n }\n }\n}\n\nfunction serializePromisedAnswerOp(builder: StructBuilder, op: PromisedAnswerOp): void {\n switch (op.type) {\n case 'noop':\n builder.setUint16(0, OP_NOOP);\n break;\n case 'getPointerField':\n builder.setUint16(0, OP_GET_POINTER_FIELD);\n builder.setUint16(8, op.fieldIndex);\n break;\n }\n}\n\nfunction serializePayload(builder: StructBuilder, payload: Payload): void {\n // Content (AnyPointer) - store as data bytes in pointer 0\n if (payload.content.length > 0) {\n // For now, store raw bytes - in full implementation this would be a proper struct\n const _contentBuilder = builder.initStruct(0, Math.ceil(payload.content.length / 8), 0);\n // Copy bytes into the struct\n }\n\n // Cap table list in pointer 1\n if (payload.capTable.length > 0) {\n const listBuilder = builder.initList(1, ElementSize.EIGHT_BYTES, payload.capTable.length, {\n dataWords: 2,\n pointerCount: 1,\n });\n for (let i = 0; i < payload.capTable.length; i++) {\n serializeCapDescriptor(listBuilder.getStruct(i), payload.capTable[i]);\n }\n }\n}\n\nfunction serializeCapDescriptor(builder: StructBuilder, cap: CapDescriptor): void {\n switch (cap.type) {\n case 'none':\n builder.setUint16(0, CAP_NONE);\n break;\n case 'senderHosted':\n builder.setUint16(0, CAP_SENDER_HOSTED);\n builder.setUint32(8, cap.exportId);\n break;\n case 'senderPromise':\n builder.setUint16(0, CAP_SENDER_PROMISE);\n builder.setUint32(8, cap.exportId);\n break;\n case 'receiverHosted':\n builder.setUint16(0, CAP_RECEIVER_HOSTED);\n builder.setUint32(8, cap.importId);\n break;\n case 'receiverAnswer':\n builder.setUint16(0, CAP_RECEIVER_ANSWER);\n serializePromisedAnswer(builder.initStruct(0, 2, 1), cap.promisedAnswer);\n break;\n case 'thirdPartyHosted':\n builder.setUint16(0, CAP_THIRD_PARTY_HOSTED);\n // ThirdPartyCapId in pointer 0\n break;\n }\n}\n\nfunction serializeSendResultsTo(builder: StructBuilder, sendTo: SendResultsTo): void {\n switch (sendTo.type) {\n case 'caller':\n builder.setUint16(0, SEND_TO_CALLER);\n break;\n case 'yourself':\n builder.setUint16(0, SEND_TO_YOURSELF);\n break;\n case 'thirdParty':\n builder.setUint16(0, SEND_TO_THIRD_PARTY);\n // RecipientId in pointer 0\n break;\n }\n}\n\nfunction serializeException(\n builder: StructBuilder,\n pointerIndex: number,\n exception: Exception\n): void {\n const excBuilder = builder.initStruct(pointerIndex, 2, 1);\n excBuilder.setText(0, exception.reason);\n\n // Exception type union\n switch (exception.type) {\n case 'failed':\n excBuilder.setUint16(0, EXC_FAILED);\n break;\n case 'overloaded':\n excBuilder.setUint16(0, EXC_OVERLOADED);\n break;\n case 'disconnected':\n excBuilder.setUint16(0, EXC_DISCONNECTED);\n break;\n case 'unimplemented':\n excBuilder.setUint16(0, EXC_UNIMPLEMENTED);\n break;\n }\n}\n\n// ========================================================================================\n// Deserialization: Uint8Array -> RpcMessage\n// ========================================================================================\n\nexport function deserializeRpcMessage(data: Uint8Array): RpcMessage {\n const reader = new MessageReader(data);\n const root = reader.getRoot(6, 1);\n\n const unionTag = root.getUint16(0);\n\n switch (unionTag) {\n case MSG_UNIMPLEMENTED:\n return { type: 'unimplemented', message: deserializeUnimplemented(root) };\n case MSG_ABORT:\n return { type: 'abort', exception: deserializeException(root, 0) };\n case MSG_BOOTSTRAP:\n return { type: 'bootstrap', bootstrap: deserializeBootstrap(root) };\n case MSG_CALL:\n return { type: 'call', call: deserializeCall(root) };\n case MSG_RETURN:\n return { type: 'return', return: deserializeReturn(root) };\n case MSG_FINISH:\n return { type: 'finish', finish: deserializeFinish(root) };\n case MSG_RESOLVE:\n return { type: 'resolve', resolve: deserializeResolve(root) };\n case MSG_RELEASE:\n return { type: 'release', release: deserializeRelease(root) };\n case MSG_DISEMBARGO:\n return { type: 'disembargo', disembargo: deserializeDisembargo(root) };\n case MSG_PROVIDE:\n return { type: 'provide', provide: deserializeProvide(root) };\n case MSG_ACCEPT:\n return { type: 'accept', accept: deserializeAccept(root) };\n case MSG_JOIN:\n return { type: 'join', join: deserializeJoin(root) };\n default:\n throw new Error(`Unknown message union tag: ${unionTag}`);\n }\n}\n\nfunction deserializeUnimplemented(_root: StructReader): RpcMessage {\n // For now, return a placeholder - full implementation would deserialize nested message\n return {\n type: 'abort',\n exception: { reason: 'Unimplemented message received', type: 'unimplemented' },\n };\n}\n\nfunction deserializeBootstrap(root: StructReader): Bootstrap {\n return {\n questionId: root.getUint32(8),\n };\n}\n\nfunction deserializeCall(root: StructReader): Call {\n const targetStruct = root.getStruct(0, 2, 1);\n const paramsStruct = root.getStruct(1, 2, 2);\n const sendToStruct = root.getStruct(2, 2, 1);\n\n return {\n questionId: root.getUint32(8),\n interfaceId: root.getUint64(16),\n methodId: root.getUint16(24),\n allowThirdPartyTailCall: root.getBool(208),\n noPromisePipelining: root.getBool(209),\n onlyPromisePipeline: root.getBool(210),\n target: targetStruct\n ? deserializeMessageTarget(targetStruct)\n : { type: 'importedCap', importId: 0 },\n params: paramsStruct\n ? deserializePayload(paramsStruct)\n : { content: new Uint8Array(0), capTable: [] },\n sendResultsTo: sendToStruct ? deserializeSendResultsTo(sendToStruct) : { type: 'caller' },\n };\n}\n\nfunction deserializeReturn(root: StructReader): Return {\n const resultTag = root.getUint16(2);\n let result: Return['result'];\n\n switch (resultTag) {\n case RET_RESULTS:\n result = {\n type: 'results',\n payload: root.getStruct(0, 2, 2)\n ? deserializePayload(root.getStruct(0, 2, 2)!)\n : { content: new Uint8Array(0), capTable: [] },\n };\n break;\n case RET_EXCEPTION:\n result = { type: 'exception', exception: deserializeException(root, 0) };\n break;\n case RET_CANCELED:\n result = { type: 'canceled' };\n break;\n case RET_RESULTS_SENT_ELSEWHERE:\n result = { type: 'resultsSentElsewhere' };\n break;\n case RET_TAKE_FROM_OTHER_QUESTION:\n result = { type: 'takeFromOtherQuestion', questionId: root.getUint32(12) };\n break;\n case RET_ACCEPT_FROM_THIRD_PARTY:\n result = { type: 'acceptFromThirdParty', thirdPartyCapId: { id: new Uint8Array(0) } };\n break;\n default:\n result = { type: 'canceled' };\n }\n\n return {\n answerId: root.getUint32(8),\n releaseParamCaps: root.getBool(192),\n noFinishNeeded: root.getBool(193),\n result,\n };\n}\n\nfunction deserializeFinish(root: StructReader): Finish {\n return {\n questionId: root.getUint32(8),\n releaseResultCaps: root.getBool(192),\n requireEarlyCancellationWorkaround: root.getBool(193),\n };\n}\n\nfunction deserializeResolve(root: StructReader): Resolve {\n const resolutionTag = root.getUint16(2);\n let resolution: Resolve['resolution'];\n\n switch (resolutionTag) {\n case RESOLVE_CAP:\n resolution = {\n type: 'cap',\n cap: root.getStruct(0, 2, 1)\n ? deserializeCapDescriptor(root.getStruct(0, 2, 1)!)\n : { type: 'none' },\n };\n break;\n case RESOLVE_EXCEPTION:\n resolution = { type: 'exception', exception: deserializeException(root, 0) };\n break;\n default:\n resolution = {\n type: 'exception',\n exception: { reason: 'Unknown resolution type', type: 'failed' },\n };\n }\n\n return {\n promiseId: root.getUint32(8),\n resolution,\n };\n}\n\nfunction deserializeRelease(root: StructReader): Release {\n return {\n id: root.getUint32(8),\n referenceCount: root.getUint32(12),\n };\n}\n\nfunction deserializeDisembargo(root: StructReader): Disembargo {\n const targetStruct = root.getStruct(0, 2, 1);\n const contextTag = root.getUint16(2);\n let context: Disembargo['context'];\n\n switch (contextTag) {\n case DISEMBARGO_SENDER_LOOPBACK:\n context = { type: 'senderLoopback', embargoId: root.getUint32(12) };\n break;\n case DISEMBARGO_RECEIVER_LOOPBACK:\n context = { type: 'receiverLoopback', embargoId: root.getUint32(12) };\n break;\n case DISEMBARGO_ACCEPT:\n context = { type: 'accept' };\n break;\n case DISEMBARGO_PROVIDE:\n context = { type: 'provide', questionId: root.getUint32(12) };\n break;\n default:\n context = { type: 'accept' };\n }\n\n return {\n target: targetStruct\n ? deserializeMessageTarget(targetStruct)\n : { type: 'importedCap', importId: 0 },\n context,\n };\n}\n\nfunction deserializeProvide(root: StructReader): Provide {\n const targetStruct = root.getStruct(0, 2, 1);\n return {\n questionId: root.getUint32(8),\n target: targetStruct\n ? deserializeMessageTarget(targetStruct)\n : { type: 'importedCap', importId: 0 },\n recipient: { id: new Uint8Array(0) },\n };\n}\n\nfunction deserializeAccept(_root: StructReader): {\n questionId: number;\n provision: { id: Uint8Array };\n embargo: boolean;\n} {\n // Level 3 - placeholder\n return { questionId: 0, provision: { id: new Uint8Array(0) }, embargo: false };\n}\n\nfunction deserializeJoin(_root: StructReader): {\n questionId: number;\n target: MessageTarget;\n otherCap: MessageTarget;\n joinId: number;\n} {\n // Level 4 - placeholder\n return {\n questionId: 0,\n target: { type: 'importedCap', importId: 0 },\n otherCap: { type: 'importedCap', importId: 0 },\n joinId: 0,\n };\n}\n\n// ========================================================================================\n// Supporting Type Deserialization\n// ========================================================================================\n\nfunction deserializeMessageTarget(root: StructReader): MessageTarget {\n const tag = root.getUint16(0);\n\n switch (tag) {\n case TARGET_IMPORTED_CAP:\n return { type: 'importedCap', importId: root.getUint32(8) };\n case TARGET_PROMISED_ANSWER: {\n const promisedAnswerStruct = root.getStruct(0, 2, 1);\n return {\n type: 'promisedAnswer',\n promisedAnswer: promisedAnswerStruct\n ? deserializePromisedAnswer(promisedAnswerStruct)\n : { questionId: 0, transform: [] },\n };\n }\n default:\n return { type: 'importedCap', importId: 0 };\n }\n}\n\nfunction deserializePromisedAnswer(root: StructReader): PromisedAnswer {\n const transformList = root.getList<StructReader>(0, ElementSize.INLINE_COMPOSITE, {\n dataWords: 2,\n pointerCount: 0,\n });\n const transform: PromisedAnswerOp[] = [];\n\n if (transformList) {\n for (let i = 0; i < transformList.length; i++) {\n transform.push(deserializePromisedAnswerOp(transformList.getStruct(i)));\n }\n }\n\n return {\n questionId: root.getUint32(0),\n transform,\n };\n}\n\nfunction deserializePromisedAnswerOp(root: StructReader): PromisedAnswerOp {\n const tag = root.getUint16(0);\n\n switch (tag) {\n case OP_NOOP:\n return { type: 'noop' };\n case OP_GET_POINTER_FIELD:\n return { type: 'getPointerField', fieldIndex: root.getUint16(8) };\n default:\n return { type: 'noop' };\n }\n}\n\nfunction deserializePayload(root: StructReader): Payload {\n // Content - for now, return empty\n // In full implementation, would deserialize the AnyPointer content\n const capTableList = root.getList<StructReader>(1, ElementSize.EIGHT_BYTES, {\n dataWords: 2,\n pointerCount: 1,\n });\n const capTable: CapDescriptor[] = [];\n\n if (capTableList) {\n for (let i = 0; i < capTableList.length; i++) {\n capTable.push(deserializeCapDescriptor(capTableList.getStruct(i)));\n }\n }\n\n return {\n content: new Uint8Array(0),\n capTable,\n };\n}\n\nfunction deserializeCapDescriptor(root: StructReader): CapDescriptor {\n const tag = root.getUint16(0);\n\n switch (tag) {\n case CAP_NONE:\n return { type: 'none' };\n case CAP_SENDER_HOSTED:\n return { type: 'senderHosted', exportId: root.getUint32(8) };\n case CAP_SENDER_PROMISE:\n return { type: 'senderPromise', exportId: root.getUint32(8) };\n case CAP_RECEIVER_HOSTED:\n return { type: 'receiverHosted', importId: root.getUint32(8) };\n case CAP_RECEIVER_ANSWER: {\n const promisedAnswerStruct = root.getStruct(0, 2, 1);\n return {\n type: 'receiverAnswer',\n promisedAnswer: promisedAnswerStruct\n ? deserializePromisedAnswer(promisedAnswerStruct)\n : { questionId: 0, transform: [] },\n };\n }\n case CAP_THIRD_PARTY_HOSTED:\n return { type: 'thirdPartyHosted', thirdPartyCapId: { id: new Uint8Array(0) } };\n default:\n return { type: 'none' };\n }\n}\n\nfunction deserializeSendResultsTo(root: StructReader): SendResultsTo {\n const tag = root.getUint16(0);\n\n switch (tag) {\n case SEND_TO_CALLER:\n return { type: 'caller' };\n case SEND_TO_YOURSELF:\n return { type: 'yourself' };\n case SEND_TO_THIRD_PARTY:\n return { type: 'thirdParty', recipientId: { id: new Uint8Array(0) } };\n default:\n return { type: 'caller' };\n }\n}\n\nfunction deserializeException(root: StructReader, pointerIndex: number): Exception {\n const excStruct = root.getStruct(pointerIndex, 2, 1);\n if (!excStruct) {\n return { reason: 'Unknown error', type: 'failed' };\n }\n\n const typeTag = excStruct.getUint16(0);\n let type: Exception['type'];\n\n switch (typeTag) {\n case EXC_FAILED:\n type = 'failed';\n break;\n case EXC_OVERLOADED:\n type = 'overloaded';\n break;\n case EXC_DISCONNECTED:\n type = 'disconnected';\n break;\n case EXC_UNIMPLEMENTED:\n type = 'unimplemented';\n break;\n default:\n type = 'failed';\n }\n\n return {\n reason: excStruct.getText(0),\n type,\n };\n}\n","/**\n * WebSocket Transport Implementation\n *\n * Implements RpcTransport over WebSocket for browser and Node.js compatibility.\n */\n\nimport { deserializeRpcMessage, serializeRpcMessage } from './message-serializer.js';\nimport type { RpcMessage } from './rpc-types.js';\nimport type { RpcTransport, WebSocketTransportOptions } from './transport.js';\n\n// Message framing: length-prefixed binary messages\n// Format: [4 bytes: message length (little-endian)] [N bytes: message data]\n\nexport class WebSocketTransport implements RpcTransport {\n private ws: WebSocket | null = null;\n private messageQueue: RpcMessage[] = [];\n private receiveQueue: Array<{\n resolve: (msg: RpcMessage | null) => void;\n reject: (err: Error) => void;\n }> = [];\n private _connected = false;\n private pendingBuffer: Uint8Array | null = null;\n private pendingLength = 0;\n\n onClose?: (reason?: Error) => void;\n onError?: (error: Error) => void;\n\n constructor(\n url: string,\n private options: WebSocketTransportOptions = {}\n ) {\n this.connect(url);\n }\n\n static async connect(\n url: string,\n options?: WebSocketTransportOptions\n ): Promise<WebSocketTransport> {\n const transport = new WebSocketTransport(url, options);\n await transport.waitForConnection();\n return transport;\n }\n\n static fromWebSocket(ws: WebSocket, options?: WebSocketTransportOptions): WebSocketTransport {\n const transport = new WebSocketTransport('internal', options);\n transport.attachWebSocket(ws);\n return transport;\n }\n\n get connected(): boolean {\n return this._connected;\n }\n\n private connect(url: string): void {\n this.ws = new WebSocket(url);\n this.ws.binaryType = this.options.binaryType ?? 'arraybuffer';\n\n this.ws.onopen = () => {\n this._connected = true;\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this._connected = false;\n this.flushReceiveQueue(null);\n this.onClose?.();\n };\n\n this.ws.onerror = (_error) => {\n const err = new Error('WebSocket error');\n this.onError?.(err);\n };\n }\n\n private attachWebSocket(ws: WebSocket): void {\n this.ws = ws;\n this.ws.binaryType = this.options.binaryType ?? 'arraybuffer';\n this._connected = ws.readyState === WebSocket.OPEN;\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this._connected = false;\n this.flushReceiveQueue(null);\n this.onClose?.();\n };\n\n this.ws.onerror = (_error) => {\n const err = new Error('WebSocket error');\n this.onError?.(err);\n };\n }\n\n private waitForConnection(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this._connected) {\n resolve();\n return;\n }\n\n const timeout = setTimeout(() => {\n reject(new Error('Connection timeout'));\n }, this.options.connectTimeoutMs ?? 10000);\n\n const checkConnection = () => {\n if (this._connected) {\n clearTimeout(timeout);\n resolve();\n } else if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {\n clearTimeout(timeout);\n reject(new Error('Connection failed'));\n } else {\n setTimeout(checkConnection, 10);\n }\n };\n\n checkConnection();\n });\n }\n\n private handleMessage(data: ArrayBuffer | Blob): void {\n // For Phase 1, we'll implement basic message handling\n // Full implementation would parse the Cap'n Proto message\n if (data instanceof ArrayBuffer) {\n this.processBinaryMessage(new Uint8Array(data));\n } else {\n // Blob handling for browser compatibility\n const reader = new FileReader();\n reader.onload = () => {\n this.processBinaryMessage(new Uint8Array(reader.result as ArrayBuffer));\n };\n reader.readAsArrayBuffer(data);\n }\n }\n\n private processBinaryMessage(data: Uint8Array): void {\n // Length-prefixed framing\n let offset = 0;\n\n while (offset < data.length) {\n if (this.pendingBuffer === null) {\n // Start of new message\n if (offset + 4 > data.length) {\n // Not enough data for length header\n this.pendingBuffer = data.slice(offset);\n this.pendingLength = -1;\n break;\n }\n\n const length = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, true);\n offset += 4;\n\n if (offset + length > data.length) {\n // Not enough data for full message\n this.pendingBuffer = data.slice(offset - 4);\n this.pendingLength = length;\n break;\n }\n\n const messageData = data.slice(offset, offset + length);\n offset += length;\n this.handleRpcMessage(messageData);\n } else {\n // Continuation of pending message\n if (this.pendingLength === -1) {\n // Still need length header\n const needed = 4 - this.pendingBuffer.length;\n if (data.length - offset < needed) {\n this.pendingBuffer = new Uint8Array([...this.pendingBuffer, ...data.slice(offset)]);\n break;\n }\n\n const tempBuffer = new Uint8Array(this.pendingBuffer.length + needed);\n tempBuffer.set(this.pendingBuffer);\n tempBuffer.set(data.slice(offset, offset + needed), this.pendingBuffer.length);\n\n this.pendingLength = new DataView(tempBuffer.buffer, 0, 4).getUint32(0, true);\n this.pendingBuffer = null;\n offset += needed;\n } else {\n // Have length, need message body\n const needed = this.pendingLength - this.pendingBuffer.length;\n if (data.length - offset < needed) {\n this.pendingBuffer = new Uint8Array([...this.pendingBuffer, ...data.slice(offset)]);\n break;\n }\n\n const messageData = new Uint8Array(this.pendingLength);\n messageData.set(this.pendingBuffer);\n messageData.set(data.slice(offset, offset + needed), this.pendingBuffer.length);\n\n offset += needed;\n this.pendingBuffer = null;\n this.handleRpcMessage(messageData);\n }\n }\n }\n }\n\n private handleRpcMessage(data: Uint8Array): void {\n // Parse the RPC message from binary data\n // For Phase 1, this is a placeholder - full implementation would deserialize\n const message = this.deserializeMessage(data);\n\n // Fulfill pending receive\n if (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(message);\n } else {\n this.messageQueue.push(message);\n }\n }\n\n private deserializeMessage(data: Uint8Array): RpcMessage {\n return deserializeRpcMessage(data);\n }\n\n private serializeMessage(message: RpcMessage): Uint8Array {\n return serializeRpcMessage(message);\n }\n\n async send(message: RpcMessage): Promise<void> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error('WebSocket not connected');\n }\n\n const data = this.serializeMessage(message);\n const frame = new Uint8Array(4 + data.length);\n new DataView(frame.buffer).setUint32(0, data.length, true);\n frame.set(data, 4);\n\n this.ws.send(frame);\n }\n\n async receive(): Promise<RpcMessage | null> {\n // Check queued messages first\n if (this.messageQueue.length > 0) {\n return this.messageQueue.shift()!;\n }\n\n // If closed, return null\n if (!this._connected) {\n return null;\n }\n\n // Wait for next message\n return new Promise((resolve, reject) => {\n this.receiveQueue.push({ resolve, reject });\n });\n }\n\n close(reason?: Error): void {\n this._connected = false;\n this.ws?.close();\n this.flushReceiveQueue(null);\n this.onClose?.(reason);\n }\n\n private flushReceiveQueue(value: RpcMessage | null): void {\n while (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(value);\n }\n }\n}\n","/**\n * TCP Transport Implementation for Node.js\n *\n * Implements RpcTransport over raw TCP socket for C++ interop testing.\n * This allows direct communication with the official Cap'n Proto C++ implementation.\n */\n\nimport * as net from 'node:net';\nimport { deserializeRpcMessage, serializeRpcMessage } from './message-serializer.js';\nimport type { RpcMessage } from './rpc-types.js';\nimport type { RpcTransport } from './transport.js';\n\nexport interface TcpTransportOptions {\n /** Connection timeout in milliseconds */\n connectTimeoutMs?: number;\n}\n\n/**\n * TCP Transport for Cap'n Proto RPC\n *\n * Uses length-prefixed binary message framing compatible with Cap'n Proto C++ implementation.\n * Format: [4 bytes: message length (little-endian)] [N bytes: message data]\n */\nexport class TcpTransport implements RpcTransport {\n private socket: net.Socket | null = null;\n private messageQueue: RpcMessage[] = [];\n private receiveQueue: Array<{\n resolve: (msg: RpcMessage | null) => void;\n reject: (err: Error) => void;\n }> = [];\n private _connected = false;\n private pendingBuffer: Buffer = Buffer.alloc(0);\n private pendingLength = 0;\n private hasPendingLength = false;\n\n onClose?: (reason?: Error) => void;\n onError?: (error: Error) => void;\n\n constructor(\n private host: string,\n private port: number,\n private options: TcpTransportOptions = {}\n ) {}\n\n static async connect(\n host: string,\n port: number,\n options?: TcpTransportOptions\n ): Promise<TcpTransport> {\n const transport = new TcpTransport(host, port, options);\n await transport.connect();\n return transport;\n }\n\n static fromSocket(socket: net.Socket, options?: TcpTransportOptions): TcpTransport {\n const transport = new TcpTransport('', 0, options);\n transport.attachSocket(socket);\n return transport;\n }\n\n get connected(): boolean {\n return this._connected && this.socket?.readyState === 'open';\n }\n\n private connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.socket?.destroy();\n reject(new Error('Connection timeout'));\n }, this.options.connectTimeoutMs ?? 10000);\n\n this.socket = new net.Socket();\n\n this.socket.on('connect', () => {\n clearTimeout(timeout);\n this._connected = true;\n resolve();\n });\n\n this.socket.on('data', (data: Buffer) => {\n this.handleData(data);\n });\n\n this.socket.on('close', (hadError: boolean) => {\n this._connected = false;\n this.flushReceiveQueue(null);\n if (hadError) {\n this.onClose?.(new Error('Connection closed with error'));\n } else {\n this.onClose?.();\n }\n });\n\n this.socket.on('error', (err: Error) => {\n clearTimeout(timeout);\n this._connected = false;\n this.onError?.(err);\n reject(err);\n });\n\n this.socket.on('end', () => {\n this._connected = false;\n });\n\n this.socket.connect(this.port, this.host);\n });\n }\n\n private attachSocket(socket: net.Socket): void {\n this.socket = socket;\n this._connected = socket.readyState === 'open';\n\n socket.on('data', (data: Buffer) => {\n this.handleData(data);\n });\n\n socket.on('close', (hadError: boolean) => {\n this._connected = false;\n this.flushReceiveQueue(null);\n if (hadError) {\n this.onClose?.(new Error('Connection closed with error'));\n } else {\n this.onClose?.();\n }\n });\n\n socket.on('error', (err: Error) => {\n this._connected = false;\n this.onError?.(err);\n });\n\n socket.on('end', () => {\n this._connected = false;\n });\n }\n\n private handleData(data: Buffer): void {\n // Append new data to pending buffer\n this.pendingBuffer = Buffer.concat([this.pendingBuffer, data]);\n\n // Process complete messages\n while (this.pendingBuffer.length >= 4) {\n if (!this.hasPendingLength) {\n // Read message length (4 bytes, little-endian)\n this.pendingLength = this.pendingBuffer.readUInt32LE(0);\n this.hasPendingLength = true;\n\n // Sanity check: max message size 64MB\n if (this.pendingLength > 64 * 1024 * 1024) {\n this.onError?.(new Error(`Message too large: ${this.pendingLength} bytes`));\n this.close(new Error('Message too large'));\n return;\n }\n }\n\n // Check if we have the full message\n const totalLength = 4 + this.pendingLength;\n if (this.pendingBuffer.length < totalLength) {\n break; // Wait for more data\n }\n\n // Extract message data\n const messageData = this.pendingBuffer.subarray(4, totalLength);\n this.pendingBuffer = this.pendingBuffer.subarray(totalLength);\n this.hasPendingLength = false;\n\n // Parse and handle the message\n try {\n const message = deserializeRpcMessage(new Uint8Array(messageData));\n this.handleRpcMessage(message);\n } catch (err) {\n this.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n }\n }\n\n private handleRpcMessage(message: RpcMessage): void {\n if (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(message);\n } else {\n this.messageQueue.push(message);\n }\n }\n\n async send(message: RpcMessage): Promise<void> {\n if (!this.socket || this.socket.readyState !== 'open') {\n throw new Error('Socket not connected');\n }\n\n const data = serializeRpcMessage(message);\n const frame = Buffer.allocUnsafe(4 + data.length);\n frame.writeUInt32LE(data.length, 0);\n frame.set(data, 4);\n\n return new Promise((resolve, reject) => {\n this.socket!.write(frame, (err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n }\n\n async receive(): Promise<RpcMessage | null> {\n // Check queued messages first\n if (this.messageQueue.length > 0) {\n return this.messageQueue.shift()!;\n }\n\n // If closed, return null\n if (!this._connected) {\n return null;\n }\n\n // Wait for next message\n return new Promise((resolve, reject) => {\n this.receiveQueue.push({ resolve, reject });\n });\n }\n\n close(reason?: Error): void {\n this._connected = false;\n this.socket?.end();\n this.socket?.destroy();\n this.flushReceiveQueue(null);\n this.onClose?.(reason);\n }\n\n private flushReceiveQueue(value: RpcMessage | null): void {\n while (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(value);\n }\n }\n}\n","/**\n * EzRpc TCP Transport\n *\n * Implements RpcTransport over raw TCP socket for C++ EzRpc compatibility.\n * Does NOT use length-prefixed framing - sends raw Cap'n Proto messages.\n */\n\nimport * as net from 'node:net';\nimport { deserializeRpcMessage, serializeRpcMessage } from './message-serializer.js';\nimport type { RpcMessage } from './rpc-types.js';\nimport type { RpcTransport } from './transport.js';\n\nexport interface EzRpcTransportOptions {\n connectTimeoutMs?: number;\n}\n\n/**\n * EzRpc TCP Transport\n *\n * Compatible with Cap'n Proto C++ EzRpcServer/EzRpcClient.\n * Sends raw Cap'n Proto messages without length prefix.\n */\nexport class EzRpcTransport implements RpcTransport {\n private socket: net.Socket | null = null;\n private messageQueue: RpcMessage[] = [];\n private receiveQueue: Array<{\n resolve: (msg: RpcMessage | null) => void;\n reject: (err: Error) => void;\n }> = [];\n private _connected = false;\n private pendingBuffer = Buffer.alloc(0);\n\n onClose?: (reason?: Error) => void;\n onError?: (error: Error) => void;\n\n constructor(\n private host: string,\n private port: number,\n private options: EzRpcTransportOptions = {}\n ) {}\n\n static async connect(\n host: string,\n port: number,\n options?: EzRpcTransportOptions\n ): Promise<EzRpcTransport> {\n const transport = new EzRpcTransport(host, port, options);\n await transport.doConnect();\n return transport;\n }\n\n get connected(): boolean {\n return this._connected && this.socket !== null && !this.socket.destroyed;\n }\n\n private doConnect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.socket?.destroy();\n reject(new Error(`Connection timeout: failed to connect to ${this.host}:${this.port}`));\n }, this.options.connectTimeoutMs ?? 10000);\n\n this.socket = new net.Socket();\n\n this.socket.on('connect', () => {\n clearTimeout(timeout);\n this._connected = true;\n resolve();\n });\n\n this.socket.on('data', (data: Buffer) => {\n try {\n this.handleData(data);\n } catch (err) {\n this.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n });\n\n this.socket.on('close', (hadError: boolean) => {\n const wasConnected = this._connected;\n this._connected = false;\n\n // Reject pending receive calls\n const error = hadError\n ? new Error('Connection closed with error')\n : new Error('Connection closed');\n this.flushReceiveQueueWithError(error);\n\n if (wasConnected) {\n this.onClose?.(hadError ? error : undefined);\n }\n });\n\n this.socket.on('error', (err: Error) => {\n clearTimeout(timeout);\n this._connected = false;\n this.flushReceiveQueueWithError(err);\n this.onError?.(err);\n reject(err);\n });\n\n this.socket.connect(this.port, this.host);\n });\n }\n\n private handleData(data: Buffer): void {\n // For EzRpc, we assume each 'data' event contains exactly one message\n // This is how KJ async I/O typically works\n\n // If we have pending data, append it\n if (this.pendingBuffer.length > 0) {\n this.pendingBuffer = Buffer.concat([this.pendingBuffer, data]);\n } else {\n this.pendingBuffer = Buffer.from(data);\n }\n\n // Try to parse messages from the buffer\n // Cap'n Proto messages have an 8-byte header we can use to determine size\n while (this.pendingBuffer.length >= 8) {\n const segmentCount = this.pendingBuffer.readUInt32LE(0) + 1;\n const firstSegmentSize = this.pendingBuffer.readUInt32LE(4);\n\n // Calculate total message size\n // Header: 8 bytes\n // Segment sizes: (segmentCount - 1) * 4 bytes (if segmentCount > 1)\n // Data: sum of all segment sizes * 8 bytes\n let headerSize = 8;\n if (segmentCount > 1) {\n headerSize += (segmentCount - 1) * 4;\n }\n\n // For now, assume single segment\n const messageSize = headerSize + firstSegmentSize * 8;\n\n if (this.pendingBuffer.length < messageSize) {\n // Not enough data yet\n break;\n }\n\n // Extract the message\n const messageData = this.pendingBuffer.subarray(0, messageSize);\n this.pendingBuffer = this.pendingBuffer.subarray(messageSize);\n\n try {\n const message = deserializeRpcMessage(new Uint8Array(messageData));\n if (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(message);\n } else {\n this.messageQueue.push(message);\n }\n } catch (err) {\n this.onError?.(err instanceof Error ? err : new Error(String(err)));\n }\n }\n }\n\n async send(message: RpcMessage): Promise<void> {\n if (!this.connected) {\n throw new Error(`Cannot send: socket not connected to ${this.host}:${this.port}`);\n }\n\n const data = serializeRpcMessage(message);\n\n return new Promise((resolve, reject) => {\n this.socket!.write(Buffer.from(data), (err) => {\n if (err) {\n reject(new Error(`Failed to send message: ${err.message}`));\n } else {\n resolve();\n }\n });\n });\n }\n\n async receive(): Promise<RpcMessage | null> {\n // 先检查队列中的消息\n if (this.messageQueue.length > 0) {\n return this.messageQueue.shift()!;\n }\n\n // 如果已断开连接,返回 null\n if (!this.connected) {\n return null;\n }\n\n // 等待下一条消息\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n // 从队列中移除自己\n const index = this.receiveQueue.findIndex((item) => item.resolve === resolve);\n if (index !== -1) {\n this.receiveQueue.splice(index, 1);\n }\n reject(new Error('Receive timeout'));\n }, 30000); // 30 秒超时\n\n this.receiveQueue.push({\n resolve: (msg) => {\n clearTimeout(timeoutId);\n resolve(msg);\n },\n reject: (err) => {\n clearTimeout(timeoutId);\n reject(err);\n },\n });\n });\n }\n\n close(reason?: Error): void {\n this._connected = false;\n this.socket?.end();\n this.socket?.destroy();\n this.flushReceiveQueue(null);\n this.onClose?.(reason);\n }\n\n private flushReceiveQueueWithError(error: Error): void {\n while (this.receiveQueue.length > 0) {\n const { reject } = this.receiveQueue.shift()!;\n reject(error);\n }\n }\n\n private flushReceiveQueue(value: RpcMessage | null): void {\n while (this.receiveQueue.length > 0) {\n const { resolve } = this.receiveQueue.shift()!;\n resolve(value);\n }\n }\n}\n","/**\n * CapabilityClient\n *\n * Base class for client-side capability references.\n * Provides the foundation for making method calls on remote objects.\n */\n\nimport type { PipelineClient } from './pipeline.js';\nimport type { RpcConnection } from './rpc-connection.js';\nimport type { ImportId, InterfaceId, MethodId, Payload } from './rpc-types.js';\n\n/** Base interface for all capability clients */\nexport interface CapabilityClient {\n /** The connection this capability belongs to */\n readonly connection: RpcConnection;\n\n /** The import ID for this capability (if imported) */\n readonly importId?: ImportId;\n\n /** Check if this capability is still valid */\n isValid(): boolean;\n\n /** Release this capability reference */\n release(): void;\n}\n\n/** Base class for capability client implementations */\nexport abstract class BaseCapabilityClient implements CapabilityClient {\n constructor(\n public readonly connection: RpcConnection,\n public readonly importId?: ImportId\n ) {}\n\n isValid(): boolean {\n // In full implementation, check if the import is still valid\n return true;\n }\n\n release(): void {\n if (this.importId !== undefined) {\n this.connection.release(this.importId, 1);\n }\n }\n\n /** Make a method call on this capability and return a PipelineClient */\n protected _call(_interfaceId: InterfaceId, _methodId: MethodId, params: unknown): PipelineClient {\n if (!this.importId) {\n throw new Error('Cannot call method on capability without import ID');\n }\n\n // Serialize params to Payload\n const _payload = this.serializeParams(params);\n\n // Use callPipelined to get a PipelineClient\n // Note: callPipelined returns Promise<PipelineClient>, but we need to await it\n // This is a design issue - for now, we throw an error indicating async is needed\n throw new Error('Use _callAsync instead for async call support');\n }\n\n /** Make an async method call on this capability */\n protected async _callAsync(\n interfaceId: InterfaceId,\n methodId: MethodId,\n params: unknown\n ): Promise<PipelineClient> {\n if (!this.importId) {\n throw new Error('Cannot call method on capability without import ID');\n }\n\n // Serialize params to Payload\n const payload = this.serializeParams(params);\n\n // Use callPipelined to get a PipelineClient\n return this.connection.callPipelined(this.importId, interfaceId, methodId, payload);\n }\n\n /** Serialize parameters to Payload */\n protected serializeParams(_params: unknown): Payload {\n // TODO: Implement proper parameter serialization\n // For now, return empty payload\n return {\n content: new Uint8Array(),\n capTable: [],\n };\n }\n}\n\n/** Factory for creating capability clients */\nexport interface CapabilityClientFactory<T extends CapabilityClient> {\n create(connection: RpcConnection, importId?: ImportId): T;\n}\n","/**\n * SturdyRefs - Level 2 RPC Feature\n *\n * SturdyRefs provide persistent capability references that survive\n * connection disconnections and can be restored on reconnection.\n *\n * Key concepts:\n * - SturdyRef: A persistent reference to a capability\n * - Restore: Reconnect to a capability using its SturdyRef\n * - Save: Create a SturdyRef from a live capability\n */\n\nimport type { RpcConnection } from './rpc-connection.js';\nimport type { ExportId, ImportId, QuestionId, RpcMessage } from './rpc-types.js';\n\n// ========================================================================================\n// Types\n// ========================================================================================\n\n/**\n * A SturdyRef token that can be persisted and later used to restore a capability\n */\nexport interface SturdyRef {\n /** The vat ID where the capability lives */\n vatId: string;\n /** The local ID of the capability within that vat */\n localId: string;\n /** Optional: Version or generation number for validation */\n version?: number;\n /** Optional: Expiration timestamp */\n expiresAt?: number;\n /** Optional: Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * A stored SturdyRef with its associated capability info\n */\ninterface StoredSturdyRef {\n ref: SturdyRef;\n exportId: ExportId;\n capability: unknown;\n createdAt: number;\n lastAccessedAt: number;\n}\n\n/**\n * Options for saving a capability as a SturdyRef\n */\nexport interface SaveOptions {\n /** Custom local ID (auto-generated if not provided) */\n localId?: string;\n /** Expiration time in milliseconds from now */\n ttlMs?: number;\n /** Metadata to attach to the SturdyRef */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Options for restoring a capability from a SturdyRef\n */\nexport interface RestoreOptions {\n /** Timeout for the restore operation */\n timeoutMs?: number;\n}\n\n// ========================================================================================\n// SturdyRef Manager (Server-side)\n// ========================================================================================\n\n/**\n * Manages SturdyRefs on the server side.\n * Stores the mapping between SturdyRef tokens and live capabilities.\n */\nexport class SturdyRefManager {\n private vatId: string;\n private storedRefs = new Map<string, StoredSturdyRef>();\n private localIdCounter = 0;\n\n constructor(vatId: string) {\n this.vatId = vatId;\n }\n\n /**\n * Save a capability as a SturdyRef\n */\n saveCapability(capability: unknown, exportId: ExportId, options?: SaveOptions): SturdyRef {\n const localId = options?.localId ?? this.generateLocalId();\n const now = Date.now();\n\n const ref: SturdyRef = {\n vatId: this.vatId,\n localId,\n version: 1,\n expiresAt: options?.ttlMs ? now + options.ttlMs : undefined,\n metadata: options?.metadata,\n };\n\n const stored: StoredSturdyRef = {\n ref,\n exportId,\n capability,\n createdAt: now,\n lastAccessedAt: now,\n };\n\n this.storedRefs.set(localId, stored);\n return ref;\n }\n\n /**\n * Restore a capability from a SturdyRef token\n */\n restoreCapability(ref: SturdyRef): { capability: unknown; exportId: ExportId } | null {\n // Validate the SturdyRef belongs to this vat\n if (ref.vatId !== this.vatId) {\n console.warn(`SturdyRef vatId mismatch: ${ref.vatId} !== ${this.vatId}`);\n return null;\n }\n\n const stored = this.storedRefs.get(ref.localId);\n if (!stored) {\n console.warn(`SturdyRef not found: ${ref.localId}`);\n return null;\n }\n\n // Check expiration\n if (stored.ref.expiresAt && Date.now() > stored.ref.expiresAt) {\n console.warn(`SturdyRef expired: ${ref.localId}`);\n this.storedRefs.delete(ref.localId);\n return null;\n }\n\n // Update last accessed time\n stored.lastAccessedAt = Date.now();\n\n return {\n capability: stored.capability,\n exportId: stored.exportId,\n };\n }\n\n /**\n * Drop a SturdyRef\n */\n dropSturdyRef(localId: string): boolean {\n return this.storedRefs.delete(localId);\n }\n\n /**\n * Get all active SturdyRefs\n */\n getActiveRefs(): SturdyRef[] {\n const now = Date.now();\n const active: SturdyRef[] = [];\n\n for (const [localId, stored] of this.storedRefs) {\n // Clean up expired refs\n if (stored.ref.expiresAt && now > stored.ref.expiresAt) {\n this.storedRefs.delete(localId);\n continue;\n }\n active.push(stored.ref);\n }\n\n return active;\n }\n\n /**\n * Clean up expired SturdyRefs\n */\n cleanupExpired(): number {\n const now = Date.now();\n let cleaned = 0;\n\n for (const [localId, stored] of this.storedRefs) {\n if (stored.ref.expiresAt && now > stored.ref.expiresAt) {\n this.storedRefs.delete(localId);\n cleaned++;\n }\n }\n\n return cleaned;\n }\n\n private generateLocalId(): string {\n return `ref-${++this.localIdCounter}-${Date.now()}`;\n }\n}\n\n// ========================================================================================\n// Restore Handler (Client-side)\n// ========================================================================================\n\n/**\n * Handles Restore messages on the client side.\n * Manages reconnecting to capabilities after disconnections.\n */\nexport class RestoreHandler {\n private connection: RpcConnection;\n private pendingRestores = new Map<\n QuestionId,\n {\n resolve: (importId: ImportId) => void;\n reject: (error: Error) => void;\n timeout: ReturnType<typeof setTimeout>;\n }\n >();\n private questionIdCounter = 0;\n\n constructor(connection: RpcConnection) {\n this.connection = connection;\n }\n\n /**\n * Send a Restore message to restore a capability from a SturdyRef\n */\n async restore(ref: SturdyRef, options?: RestoreOptions): Promise<ImportId> {\n const questionId = ++this.questionIdCounter;\n const timeoutMs = options?.timeoutMs ?? 30000;\n\n return new Promise((resolve, reject) => {\n // Set up timeout\n const timeout = setTimeout(() => {\n this.pendingRestores.delete(questionId);\n reject(new Error(`Restore timeout after ${timeoutMs}ms`));\n }, timeoutMs);\n\n this.pendingRestores.set(questionId, { resolve, reject, timeout });\n\n // Send Restore message (using Call message with special interface)\n // In the actual protocol, this would be a specific Restore message type\n // For now, we use a special method call\n this.sendRestoreMessage(questionId, ref).catch((error) => {\n clearTimeout(timeout);\n this.pendingRestores.delete(questionId);\n reject(error);\n });\n });\n }\n\n /**\n * Handle a Restore response\n */\n handleRestoreResponse(questionId: QuestionId, importId: ImportId): void {\n const pending = this.pendingRestores.get(questionId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRestores.delete(questionId);\n pending.resolve(importId);\n }\n }\n\n /**\n * Handle a Restore failure\n */\n handleRestoreFailure(questionId: QuestionId, reason: string): void {\n const pending = this.pendingRestores.get(questionId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRestores.delete(questionId);\n pending.reject(new Error(`Restore failed: ${reason}`));\n }\n }\n\n /**\n * Cancel all pending restores (e.g., on disconnect)\n */\n cancelAll(reason: string): void {\n for (const [_questionId, pending] of this.pendingRestores) {\n clearTimeout(pending.timeout);\n pending.reject(new Error(`Restore canceled: ${reason}`));\n }\n this.pendingRestores.clear();\n }\n\n private async sendRestoreMessage(questionId: QuestionId, ref: SturdyRef): Promise<void> {\n // Serialize the SturdyRef\n const refData = JSON.stringify(ref);\n\n // In the actual implementation, this would send a proper Restore message\n // For now, we simulate it\n const restoreMsg: RpcMessage = {\n type: 'call',\n call: {\n questionId,\n target: { type: 'importedCap', importId: 0 }, // Special import for restore service\n interfaceId: BigInt('0xffffffffffffffff'), // Special interface ID for restore\n methodId: 0, // restore method\n allowThirdPartyTailCall: false,\n noPromisePipelining: false,\n onlyPromisePipeline: false,\n params: {\n content: new TextEncoder().encode(refData),\n capTable: [],\n },\n sendResultsTo: { type: 'caller' },\n },\n };\n\n // This would be sent through the connection\n // await this.connection.send(restoreMsg);\n console.log('Sending restore message:', restoreMsg);\n }\n}\n\n// ========================================================================================\n// SturdyRef Utilities\n// ========================================================================================\n\n/**\n * Serialize a SturdyRef to a string for storage\n */\nexport function serializeSturdyRef(ref: SturdyRef): string {\n return JSON.stringify(ref);\n}\n\n/**\n * Deserialize a SturdyRef from a string\n */\nexport function deserializeSturdyRef(data: string): SturdyRef | null {\n try {\n const parsed = JSON.parse(data);\n\n // Validate required fields\n if (typeof parsed.vatId !== 'string' || typeof parsed.localId !== 'string') {\n return null;\n }\n\n return {\n vatId: parsed.vatId,\n localId: parsed.localId,\n version: parsed.version,\n expiresAt: parsed.expiresAt,\n metadata: parsed.metadata,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a SturdyRef is valid (not expired)\n */\nexport function isSturdyRefValid(ref: SturdyRef): boolean {\n if (ref.expiresAt && Date.now() > ref.expiresAt) {\n return false;\n }\n return true;\n}\n\n/**\n * Create a SturdyRef from components\n */\nexport function createSturdyRef(\n vatId: string,\n localId: string,\n options?: Omit<SaveOptions, 'localId'>\n): SturdyRef {\n return {\n vatId,\n localId,\n version: 1,\n expiresAt: options?.ttlMs ? Date.now() + options.ttlMs : undefined,\n metadata: options?.metadata,\n };\n}\n","/**\n * Performance Optimizations for RPC\n *\n * Phase 3: Performance improvements\n * - Multi-segment message support\n * - Memory pooling\n * - Zero-copy paths where possible\n */\n\nimport { Segment } from '../core/segment.js';\n\n// ========================================================================================\n// Memory Pool\n// ========================================================================================\n\ninterface PooledBuffer {\n buffer: ArrayBuffer;\n size: number;\n lastUsed: number;\n}\n\n/**\n * Memory pool for reusing ArrayBuffers\n * Reduces GC pressure for frequent allocations\n */\nexport class MemoryPool {\n private pools = new Map<number, PooledBuffer[]>();\n private maxPoolSize: number;\n private maxBufferAge: number;\n\n constructor(options?: { maxPoolSize?: number; maxBufferAgeMs?: number }) {\n this.maxPoolSize = options?.maxPoolSize ?? 100;\n this.maxBufferAge = options?.maxBufferAgeMs ?? 60000; // 1 minute\n }\n\n /**\n * Acquire a buffer of at least the requested size\n */\n acquire(size: number): ArrayBuffer {\n // Round up to nearest power of 2 for better pooling\n const pooledSize = this.roundUpSize(size);\n const pool = this.pools.get(pooledSize);\n\n if (pool && pool.length > 0) {\n const now = Date.now();\n // Find a buffer that's not too old\n const index = pool.findIndex((b) => now - b.lastUsed < this.maxBufferAge);\n\n if (index >= 0) {\n const pooled = pool.splice(index, 1)[0];\n return pooled.buffer;\n }\n }\n\n // Allocate new buffer\n return new ArrayBuffer(pooledSize);\n }\n\n /**\n * Release a buffer back to the pool\n */\n release(buffer: ArrayBuffer): void {\n const size = buffer.byteLength;\n\n // Don't pool very small or very large buffers\n if (size < 64 || size > 1024 * 1024) {\n return;\n }\n\n let pool = this.pools.get(size);\n if (!pool) {\n pool = [];\n this.pools.set(size, pool);\n }\n\n if (pool.length < this.maxPoolSize) {\n pool.push({\n buffer,\n size,\n lastUsed: Date.now(),\n });\n }\n }\n\n /**\n * Clear all pooled buffers\n */\n clear(): void {\n this.pools.clear();\n }\n\n /**\n * Get pool statistics\n */\n getStats(): { totalBuffers: number; totalBytes: number; sizes: number[] } {\n let totalBuffers = 0;\n let totalBytes = 0;\n const sizes: number[] = [];\n\n for (const [size, pool] of this.pools) {\n totalBuffers += pool.length;\n totalBytes += size * pool.length;\n sizes.push(size);\n }\n\n return { totalBuffers, totalBytes, sizes };\n }\n\n private roundUpSize(size: number): number {\n // Round up to nearest power of 2, minimum 64 bytes\n if (size <= 64) return 64;\n if (size <= 128) return 128;\n if (size <= 256) return 256;\n if (size <= 512) return 512;\n if (size <= 1024) return 1024;\n if (size <= 2048) return 2048;\n if (size <= 4096) return 4096;\n if (size <= 8192) return 8192;\n if (size <= 16384) return 16384;\n if (size <= 32768) return 32768;\n if (size <= 65536) return 65536;\n return size;\n }\n}\n\n// ========================================================================================\n// Multi-Segment Message Builder\n// ========================================================================================\n\n/**\n * Options for multi-segment message building\n */\nexport interface MultiSegmentOptions {\n /** Initial segment size */\n initialSegmentSize?: number;\n /** Maximum segment size */\n maxSegmentSize?: number;\n /** Whether to allow multiple segments */\n allowMultipleSegments?: boolean;\n}\n\n/**\n * Builder for multi-segment messages\n * Optimizes memory usage for large messages\n */\nexport class MultiSegmentMessageBuilder {\n private segments: Segment[] = [];\n private options: Required<MultiSegmentOptions>;\n private currentSegment: Segment;\n private totalSize = 0;\n\n constructor(options?: MultiSegmentOptions) {\n this.options = {\n initialSegmentSize: options?.initialSegmentSize ?? 8192,\n maxSegmentSize: options?.maxSegmentSize ?? 65536,\n allowMultipleSegments: options?.allowMultipleSegments ?? true,\n };\n\n this.currentSegment = new Segment(this.options.initialSegmentSize);\n this.segments.push(this.currentSegment);\n }\n\n /**\n * Allocate space in the message\n */\n allocate(size: number): { segment: Segment; offset: number } {\n // Align to 8 bytes and convert to words\n const alignedBytes = (size + 7) & ~7;\n const words = alignedBytes / 8;\n\n // Check if current segment has enough space\n // Segment capacity is the buffer size, not the current size\n const currentCapacity = this.currentSegment.byteLength;\n const currentUsed = this.currentSegment.wordCount * 8; // wordCount * 8 = bytes used\n const remainingSpace = currentCapacity - currentUsed;\n\n if (remainingSpace >= alignedBytes) {\n // Current segment has enough space\n const wordOffset = this.currentSegment.allocate(words);\n this.totalSize += alignedBytes;\n return { segment: this.currentSegment, offset: wordOffset * 8 };\n }\n\n // Need a new segment\n if (!this.options.allowMultipleSegments) {\n throw new Error('Message too large for single segment');\n }\n\n // Create new segment\n const newSegmentSize = Math.min(\n Math.max(alignedBytes, this.options.initialSegmentSize),\n this.options.maxSegmentSize\n );\n this.currentSegment = new Segment(newSegmentSize);\n this.segments.push(this.currentSegment);\n\n const newWordOffset = this.currentSegment.allocate(words);\n this.totalSize += alignedBytes;\n return { segment: this.currentSegment, offset: newWordOffset * 8 };\n }\n\n /**\n * Get all segments\n */\n getSegments(): readonly Segment[] {\n return this.segments;\n }\n\n /**\n * Get the total size of all segments\n */\n getTotalSize(): number {\n return this.totalSize;\n }\n\n /**\n * Get the number of segments\n */\n getSegmentCount(): number {\n return this.segments.length;\n }\n\n /**\n * Serialize to a single buffer (for transport)\n */\n toBuffer(): ArrayBuffer {\n if (this.segments.length === 1) {\n // Single segment - use asUint8Array to get the used portion\n const segmentData = this.segments[0].asUint8Array();\n return segmentData.buffer.slice(\n segmentData.byteOffset,\n segmentData.byteOffset + segmentData.byteLength\n ) as ArrayBuffer;\n }\n\n // Multi-segment - need to serialize with segment table\n // This is a simplified version - full implementation would include\n // the segment table at the beginning\n const totalSize = this.segments.reduce((sum, seg) => sum + seg.byteLength, 0);\n const result = new ArrayBuffer(totalSize + 8 * this.segments.length); // Space for segment table\n const view = new DataView(result);\n const bytes = new Uint8Array(result);\n\n // Write segment table\n view.setUint32(0, this.segments.length - 1, true); // Segment count - 1\n view.setUint32(4, 0, true); // Padding for first segment size (in words)\n\n let offset = 8;\n for (let i = 0; i < this.segments.length; i++) {\n const segment = this.segments[i];\n if (i > 0) {\n view.setUint32(offset, segment.byteLength / 8, true); // Segment size in words\n offset += 4;\n }\n\n // Copy segment data\n const segmentBuffer = new Uint8Array(segment.byteLength);\n // Copy data from segment's DataView\n const segmentData = segment.dataView;\n for (let i = 0; i < segment.byteLength; i++) {\n segmentBuffer[i] = segmentData.getUint8(i);\n }\n bytes.set(segmentBuffer, offset);\n offset += segment.byteLength;\n }\n\n return result;\n }\n}\n\n// ========================================================================================\n// Zero-Copy Utilities\n// ========================================================================================\n\n/**\n * View into a buffer without copying\n */\nexport interface ZeroCopyView {\n buffer: ArrayBuffer;\n byteOffset: number;\n byteLength: number;\n}\n\n/**\n * Create a zero-copy view of a buffer\n */\nexport function createZeroCopyView(\n buffer: ArrayBuffer,\n byteOffset = 0,\n byteLength?: number\n): ZeroCopyView {\n return {\n buffer,\n byteOffset,\n byteLength: byteLength ?? buffer.byteLength - byteOffset,\n };\n}\n\n/**\n * Check if two buffers are the same underlying memory\n */\nexport function isSameBuffer(a: ArrayBuffer, b: ArrayBuffer): boolean {\n try {\n // This is a hack to check if two buffers are the same\n // In a real implementation, we'd use a more reliable method\n return a === b;\n } catch {\n return false;\n }\n}\n\n/**\n * Copy data between buffers using the fastest available method\n */\nexport function fastCopy(\n src: ArrayBuffer,\n dst: ArrayBuffer,\n srcOffset = 0,\n dstOffset = 0,\n length?: number\n): void {\n const len = length ?? Math.min(src.byteLength - srcOffset, dst.byteLength - dstOffset);\n const srcView = new Uint8Array(src, srcOffset, len);\n const dstView = new Uint8Array(dst, dstOffset, len);\n dstView.set(srcView);\n}\n\n// ========================================================================================\n// RPC Message Optimization\n// ========================================================================================\n\n/**\n * Options for RPC message building\n */\nexport interface RpcMessageOptions {\n /** Use multi-segment messages */\n useMultiSegment?: boolean;\n /** Initial segment size */\n initialSegmentSize?: number;\n /** Use memory pooling */\n useMemoryPool?: boolean;\n /** Memory pool instance */\n memoryPool?: MemoryPool;\n}\n\n/**\n * Optimized RPC message builder\n */\nexport class OptimizedRpcMessageBuilder {\n private options: Required<RpcMessageOptions>;\n private pool: MemoryPool;\n\n constructor(options?: RpcMessageOptions) {\n this.options = {\n useMultiSegment: options?.useMultiSegment ?? true,\n initialSegmentSize: options?.initialSegmentSize ?? 8192,\n useMemoryPool: options?.useMemoryPool ?? true,\n memoryPool: options?.memoryPool ?? new MemoryPool(),\n };\n this.pool = this.options.memoryPool;\n }\n\n /**\n * Build a message with optimizations applied\n */\n buildMessage(content: Uint8Array): ArrayBuffer {\n const totalSize = 8 + content.length; // Header + content\n\n if (this.options.useMemoryPool) {\n const buffer = this.pool.acquire(totalSize);\n const view = new DataView(buffer);\n const bytes = new Uint8Array(buffer);\n\n // Write header (simplified)\n view.setUint32(0, 0, true); // Single segment indicator\n view.setUint32(4, content.length / 8, true); // Size in words\n\n // Copy content\n bytes.set(content, 8);\n\n return buffer;\n }\n\n // Standard allocation\n const buffer = new ArrayBuffer(totalSize);\n const view = new DataView(buffer);\n const bytes = new Uint8Array(buffer);\n\n view.setUint32(0, 0, true);\n view.setUint32(4, content.length / 8, true);\n bytes.set(content, 8);\n\n return buffer;\n }\n\n /**\n * Release a buffer back to the pool\n */\n releaseBuffer(buffer: ArrayBuffer): void {\n if (this.options.useMemoryPool) {\n this.pool.release(buffer);\n }\n }\n\n /**\n * Get pool statistics\n */\n getPoolStats(): { totalBuffers: number; totalBytes: number; sizes: number[] } {\n return this.pool.getStats();\n }\n}\n\n// ========================================================================================\n// Global Memory Pool (Singleton)\n// ========================================================================================\n\nlet globalMemoryPool: MemoryPool | null = null;\n\n/**\n * Get the global memory pool instance\n */\nexport function getGlobalMemoryPool(): MemoryPool {\n if (!globalMemoryPool) {\n globalMemoryPool = new MemoryPool();\n }\n return globalMemoryPool;\n}\n\n/**\n * Configure the global memory pool\n */\nexport function configureGlobalMemoryPool(options: {\n maxPoolSize?: number;\n maxBufferAgeMs?: number;\n}): void {\n globalMemoryPool = new MemoryPool(options);\n}\n","/**\n * Connection Manager\n *\n * Manages multiple RPC connections for Level 3 RPC (Three-way introductions).\n * Handles connection pooling, automatic connection establishment, and routing\n * of messages between vats.\n *\n * Level 3 RPC allows capabilities to be passed between vats that don't have\n * a direct connection, and enables those vats to form direct connections.\n */\n\nimport type { RpcConnection, RpcConnectionOptions } from './rpc-connection.js';\nimport type { ProvisionId, RecipientId, ThirdPartyCapId } from './rpc-types.js';\nimport type { RpcTransport } from './transport.js';\n\n/** Unique identifier for a vat */\nexport interface VatId {\n /** The raw vat identifier */\n id: Uint8Array;\n}\n\n/** Connection metadata */\nexport interface ConnectionInfo {\n /** The connection instance */\n connection: RpcConnection;\n /** The vat ID of the remote peer */\n remoteVatId: VatId;\n /** When the connection was established */\n establishedAt: Date;\n /** Last activity timestamp */\n lastActivity: Date;\n /** Connection state */\n state: 'connecting' | 'connected' | 'closing' | 'closed';\n}\n\n/** Pending provision waiting for acceptance */\nexport interface PendingProvision {\n /** Unique provision ID */\n provisionId: ProvisionId;\n /** The vat ID of the intended recipient */\n recipientId: VatId;\n /** The capability being provided */\n targetExportId: number;\n /** When the provision was created */\n createdAt: Date;\n /** Question ID from the Provide message */\n questionId: number;\n /** Whether this provision is embargoed (for cycle breaking) */\n embargoed: boolean;\n}\n\n/** Options for ConnectionManager */\nexport interface ConnectionManagerOptions {\n /** This vat's own ID */\n selfVatId: VatId;\n /** Factory function to create connections */\n connectionFactory: (vatId: VatId, address?: string) => Promise<RpcTransport>;\n /** Default connection options */\n connectionOptions?: RpcConnectionOptions;\n /** Maximum number of concurrent connections */\n maxConnections?: number;\n /** Connection idle timeout in milliseconds */\n idleTimeoutMs?: number;\n /** Whether to automatically establish connections to third parties */\n autoConnect?: boolean;\n}\n\n/**\n * ConnectionManager manages multiple RPC connections for Level 3 RPC.\n *\n * Key responsibilities:\n * 1. Maintain a pool of connections to other vats\n * 2. Handle automatic connection establishment for third-party capabilities\n * 3. Manage pending provisions (capabilities waiting to be picked up)\n * 4. Route messages to the appropriate connection\n * 5. Handle connection lifecycle (connect, disconnect, reconnect)\n */\nexport class ConnectionManager {\n private options: ConnectionManagerOptions;\n private connections = new Map<string, ConnectionInfo>();\n private pendingProvisions = new Map<string, PendingProvision>();\n private connectionPromises = new Map<string, Promise<RpcConnection>>();\n\n constructor(options: ConnectionManagerOptions) {\n this.options = {\n maxConnections: 100,\n idleTimeoutMs: 300000, // 5 minutes\n autoConnect: true,\n ...options,\n };\n }\n\n // ========================================================================================\n // Connection Management\n // ========================================================================================\n\n /**\n * Register an existing connection with the manager.\n * This is called when a connection is established (either inbound or outbound).\n */\n registerConnection(vatId: VatId, connection: RpcConnection): ConnectionInfo {\n const vatIdKey = this.vatIdToKey(vatId);\n\n const info: ConnectionInfo = {\n connection,\n remoteVatId: vatId,\n establishedAt: new Date(),\n lastActivity: new Date(),\n state: 'connected',\n };\n\n this.connections.set(vatIdKey, info);\n\n // Set up cleanup on connection close\n // Note: The connection's onClose handler should be set by the caller\n\n return info;\n }\n\n /**\n * Get or establish a connection to a vat.\n * If autoConnect is enabled and no connection exists, a new one will be created.\n */\n async getConnection(vatId: VatId): Promise<RpcConnection | undefined> {\n const vatIdKey = this.vatIdToKey(vatId);\n\n // Check for existing connection\n const existing = this.connections.get(vatIdKey);\n if (existing && existing.state === 'connected') {\n existing.lastActivity = new Date();\n return existing.connection;\n }\n\n // Check for in-progress connection\n const pending = this.connectionPromises.get(vatIdKey);\n if (pending) {\n return pending;\n }\n\n // Auto-connect if enabled\n if (this.options.autoConnect) {\n return this.establishConnection(vatId);\n }\n\n return undefined;\n }\n\n /**\n * Establish a new connection to a vat.\n */\n async establishConnection(vatId: VatId, address?: string): Promise<RpcConnection> {\n const vatIdKey = this.vatIdToKey(vatId);\n\n // Check if already connecting\n if (this.connectionPromises.has(vatIdKey)) {\n return this.connectionPromises.get(vatIdKey)!;\n }\n\n // Create connection promise\n const connectPromise = this.doEstablishConnection(vatId, address);\n this.connectionPromises.set(vatIdKey, connectPromise);\n\n try {\n const connection = await connectPromise;\n return connection;\n } finally {\n this.connectionPromises.delete(vatIdKey);\n }\n }\n\n private async doEstablishConnection(vatId: VatId, address?: string): Promise<RpcConnection> {\n const { RpcConnection } = await import('./rpc-connection.js');\n\n // Create transport using the factory\n const transport = await this.options.connectionFactory(vatId, address);\n\n // Create and start the connection\n const connection = new RpcConnection(transport, this.options.connectionOptions);\n await connection.start();\n\n // Register the connection\n this.registerConnection(vatId, connection);\n\n return connection;\n }\n\n /**\n * Close a connection to a vat.\n */\n async closeConnection(vatId: VatId): Promise<void> {\n const vatIdKey = this.vatIdToKey(vatId);\n const info = this.connections.get(vatIdKey);\n\n if (info) {\n info.state = 'closing';\n await info.connection.stop();\n this.connections.delete(vatIdKey);\n }\n }\n\n /**\n * Close all connections.\n */\n async closeAll(): Promise<void> {\n const closePromises: Promise<void>[] = [];\n\n for (const [_vatIdKey, info] of this.connections) {\n info.state = 'closing';\n closePromises.push(\n info.connection.stop().catch(() => {\n // Ignore errors during shutdown\n })\n );\n }\n\n await Promise.all(closePromises);\n this.connections.clear();\n this.pendingProvisions.clear();\n }\n\n // ========================================================================================\n // Provision Management (for Provide/Accept)\n // ========================================================================================\n\n /**\n * Create a pending provision for a third-party capability.\n * Called when we receive a Provide message.\n */\n createPendingProvision(\n provisionId: ProvisionId,\n recipientId: VatId,\n targetExportId: number,\n questionId: number,\n embargoed: boolean\n ): PendingProvision {\n const provisionKey = this.provisionIdToKey(provisionId);\n\n const provision: PendingProvision = {\n provisionId,\n recipientId,\n targetExportId,\n questionId,\n createdAt: new Date(),\n embargoed,\n };\n\n this.pendingProvisions.set(provisionKey, provision);\n return provision;\n }\n\n /**\n * Get a pending provision by ID.\n */\n getPendingProvision(provisionId: ProvisionId): PendingProvision | undefined {\n const provisionKey = this.provisionIdToKey(provisionId);\n return this.pendingProvisions.get(provisionKey);\n }\n\n /**\n * Remove a pending provision (when it's been accepted or expired).\n */\n removePendingProvision(provisionId: ProvisionId): boolean {\n const provisionKey = this.provisionIdToKey(provisionId);\n return this.pendingProvisions.delete(provisionKey);\n }\n\n /**\n * Find provisions for a specific recipient.\n */\n findProvisionsForRecipient(recipientId: VatId): PendingProvision[] {\n const recipientKey = this.vatIdToKey(recipientId);\n const result: PendingProvision[] = [];\n\n for (const provision of this.pendingProvisions.values()) {\n if (this.vatIdToKey(provision.recipientId) === recipientKey) {\n result.push(provision);\n }\n }\n\n return result;\n }\n\n /**\n * Clean up expired provisions.\n */\n cleanupExpiredProvisions(maxAgeMs = 300000): number {\n const now = Date.now();\n let removed = 0;\n\n for (const [key, provision] of this.pendingProvisions) {\n if (now - provision.createdAt.getTime() > maxAgeMs) {\n this.pendingProvisions.delete(key);\n removed++;\n }\n }\n\n return removed;\n }\n\n // ========================================================================================\n // Third-Party Capability Resolution\n // ========================================================================================\n\n /**\n * Resolve a third-party capability ID to a connection.\n * This is the core of Level 3 RPC - automatically establishing connections\n * to third parties when capabilities are passed between vats.\n */\n async resolveThirdPartyCap(thirdPartyCapId: ThirdPartyCapId): Promise<\n | {\n connection: RpcConnection;\n provisionId: ProvisionId;\n }\n | undefined\n > {\n // Parse the ThirdPartyCapId to extract vat ID and provision ID\n const parsed = this.parseThirdPartyCapId(thirdPartyCapId);\n if (!parsed) {\n return undefined;\n }\n\n // Get or establish connection to the third party\n const connection = await this.getConnection(parsed.vatId);\n if (!connection) {\n return undefined;\n }\n\n return {\n connection,\n provisionId: parsed.provisionId,\n };\n }\n\n /**\n * Parse a ThirdPartyCapId to extract vat ID and provision ID.\n * The format is implementation-specific, but typically:\n * - First N bytes: vat ID\n * - Remaining bytes: provision ID\n */\n private parseThirdPartyCapId(thirdPartyCapId: ThirdPartyCapId):\n | {\n vatId: VatId;\n provisionId: ProvisionId;\n }\n | undefined {\n // Default implementation: first 32 bytes are vat ID, rest is provision ID\n // This can be overridden by the application\n const data = thirdPartyCapId.id;\n\n if (data.length < 32) {\n return undefined;\n }\n\n const vatIdBytes = data.slice(0, 32);\n const provisionIdBytes = data.slice(32);\n\n return {\n vatId: { id: vatIdBytes },\n provisionId: { id: provisionIdBytes },\n };\n }\n\n // ========================================================================================\n // Utility Methods\n // ========================================================================================\n\n /**\n * Get all active connections.\n */\n getAllConnections(): ConnectionInfo[] {\n return Array.from(this.connections.values());\n }\n\n /**\n * Get the number of active connections.\n */\n getConnectionCount(): number {\n return this.connections.size;\n }\n\n /**\n * Get the number of pending provisions.\n */\n getPendingProvisionCount(): number {\n return this.pendingProvisions.size;\n }\n\n /**\n * Check if a connection exists to a vat.\n */\n hasConnection(vatId: VatId): boolean {\n const vatIdKey = this.vatIdToKey(vatId);\n const info = this.connections.get(vatIdKey);\n return info !== undefined && info.state === 'connected';\n }\n\n /**\n * Update the last activity timestamp for a connection.\n */\n touchConnection(vatId: VatId): void {\n const vatIdKey = this.vatIdToKey(vatId);\n const info = this.connections.get(vatIdKey);\n if (info) {\n info.lastActivity = new Date();\n }\n }\n\n // ========================================================================================\n // Private Helpers\n // ========================================================================================\n\n private vatIdToKey(vatId: VatId): string {\n // Convert Uint8Array to hex string for use as Map key\n return Array.from(vatId.id)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n private provisionIdToKey(provisionId: ProvisionId): string {\n return Array.from(provisionId.id)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n}\n\n/**\n * Create a ThirdPartyCapId from vat ID and provision ID.\n */\nexport function createThirdPartyCapId(vatId: VatId, provisionId: ProvisionId): ThirdPartyCapId {\n // Concatenate vat ID and provision ID\n const combined = new Uint8Array(vatId.id.length + provisionId.id.length);\n combined.set(vatId.id, 0);\n combined.set(provisionId.id, vatId.id.length);\n\n return { id: combined };\n}\n\n/**\n * Create a RecipientId from a vat ID.\n */\nexport function createRecipientId(vatId: VatId): RecipientId {\n return { id: vatId.id };\n}\n\n/**\n * Create a ProvisionId from raw bytes.\n */\nexport function createProvisionId(id: Uint8Array): ProvisionId {\n return { id };\n}\n\n/**\n * Generate a random provision ID.\n */\nexport function generateProvisionId(): ProvisionId {\n const id = new Uint8Array(32);\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n crypto.getRandomValues(id);\n } else {\n // Fallback for Node.js\n const { randomBytes } = require('node:crypto');\n randomBytes(32).copy(id);\n }\n return { id };\n}\n\n/**\n * Generate a random vat ID.\n */\nexport function generateVatId(): VatId {\n const id = new Uint8Array(32);\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n crypto.getRandomValues(id);\n } else {\n // Fallback for Node.js\n const { randomBytes } = require('node:crypto');\n randomBytes(32).copy(id);\n }\n return { id };\n}\n","/**\n * Level 3 RPC Message Handlers\n *\n * Implements the three-way introduction protocol for Level 3 RPC:\n * - Provide: Offer a capability to a third party\n * - Accept: Accept a capability from a third party\n * - Embargo handling for cycle breaking\n *\n * The three-way introduction protocol allows capabilities to be passed between\n * vats that don't have a direct connection, enabling those vats to form direct\n * connections.\n */\n\nimport type { ConnectionManager, PendingProvision, VatId } from './connection-manager.js';\nimport { createThirdPartyCapId, generateProvisionId } from './connection-manager.js';\nimport type { RpcConnection } from './rpc-connection.js';\nimport type {\n Accept,\n CapDescriptor,\n Disembargo,\n ExportId,\n ImportId,\n MessageTarget,\n Provide,\n RecipientId,\n RpcMessage,\n ThirdPartyCapId,\n} from './rpc-types.js';\n\n/** Options for Level3Handlers */\nexport interface Level3HandlersOptions {\n /** The connection this handler is attached to */\n connection: RpcConnection;\n /** The connection manager for managing third-party connections */\n connectionManager: ConnectionManager;\n /** This vat's ID */\n selfVatId: VatId;\n /** Handler for incoming Provide messages */\n onProvide?: (provide: Provide) => Promise<void>;\n /** Handler for incoming Accept messages */\n onAccept?: (accept: Accept) => Promise<void>;\n}\n\n/**\n * Manages Level 3 RPC message handling for a connection.\n *\n * This class handles:\n * 1. Provide messages - when someone wants to give us a capability to share with a third party\n * 2. Accept messages - when a third party wants to pick up a capability we provided\n * 3. Embargo handling - breaking cycles in introduction graphs\n */\nexport class Level3Handlers {\n private options: Level3HandlersOptions;\n private pendingAccepts = new Map<number, PendingAccept>();\n private embargoedCalls = new Map<number, EmbargoedCall[]>();\n private nextEmbargoId = 1;\n\n constructor(options: Level3HandlersOptions) {\n this.options = options;\n }\n\n // ========================================================================================\n // Provide Message Handling\n // ========================================================================================\n\n /**\n * Handle an incoming Provide message.\n *\n * When we receive a Provide message, it means someone wants us to hold a capability\n * and make it available to a specific third party. We:\n * 1. Create a pending provision\n * 2. Return an answer acknowledging receipt\n * 3. Wait for the third party to Accept\n */\n async handleProvide(provide: Provide): Promise<void> {\n const { questionId, target, recipient } = provide;\n const { connectionManager } = this.options;\n\n // Generate a unique provision ID\n const provisionId = generateProvisionId();\n\n // Extract the target export ID from the MessageTarget\n const targetExportId = this.extractTargetExportId(target);\n if (targetExportId === undefined) {\n // Can't provide this target - send exception\n await this.sendReturnException(\n questionId,\n 'Invalid provide target: must be a hosted capability'\n );\n return;\n }\n\n // Create the pending provision\n const _provision: PendingProvision = connectionManager.createPendingProvision(\n provisionId,\n this.recipientIdToVatId(recipient),\n targetExportId,\n questionId,\n false // Not embargoed by default\n );\n\n // Call the custom handler if provided\n if (this.options.onProvide) {\n await this.options.onProvide(provide);\n }\n\n // Send Return with the provision info\n // The provision ID is embedded in the answer for reference\n await this.sendReturnResults(questionId, {\n provisionId: provisionId.id,\n });\n }\n\n /**\n * Send a Provide message to offer a capability to a third party.\n *\n * This is called when we want to introduce a third party to a capability we hold.\n * For example, Alice calls this to offer Bob access to Carol's capability.\n */\n async sendProvide(\n target: MessageTarget,\n recipient: RecipientId\n ): Promise<{ questionId: number; provisionId: ThirdPartyCapId }> {\n const { connection } = this.options;\n\n // Create a question for this provide\n const questionId = connection.createQuestion();\n\n const provideMsg: RpcMessage = {\n type: 'provide',\n provide: {\n questionId,\n target,\n recipient,\n },\n };\n\n await connection.sendCall(provideMsg.provide as any);\n\n // Wait for the return to get the provision ID\n const _result = await connection.waitForAnswer(questionId);\n\n // Extract provision ID from result\n // In a full implementation, we'd parse the result payload\n const provisionId: ThirdPartyCapId = {\n id: new Uint8Array(0),\n };\n\n return { questionId, provisionId };\n }\n\n // ========================================================================================\n // Accept Message Handling\n // ========================================================================================\n\n /**\n * Handle an incoming Accept message.\n *\n * When we receive an Accept message, it means a third party wants to pick up\n * a capability we previously agreed to provide. We:\n * 1. Look up the pending provision\n * 2. Verify the recipient matches\n * 3. Return the capability\n */\n async handleAccept(accept: Accept): Promise<void> {\n const { questionId, provision, embargo } = accept;\n const { connectionManager } = this.options;\n\n // Find the pending provision\n const pendingProvision = connectionManager.getPendingProvision(provision);\n\n if (!pendingProvision) {\n // No such provision - send exception\n await this.sendReturnException(\n questionId,\n 'Invalid provision ID: no pending provision found'\n );\n return;\n }\n\n // Remove the pending provision\n connectionManager.removePendingProvision(provision);\n\n // If embargoed, set up embargo handling\n if (embargo || pendingProvision.embargoed) {\n await this.handleEmbargoedAccept(questionId, pendingProvision);\n return;\n }\n\n // Return the capability\n const capDescriptor: CapDescriptor = {\n type: 'senderHosted',\n exportId: pendingProvision.targetExportId as ExportId,\n };\n\n await this.sendReturnCapability(questionId, capDescriptor);\n\n // Call the custom handler if provided\n if (this.options.onAccept) {\n await this.options.onAccept(accept);\n }\n }\n\n /**\n * Send an Accept message to pick up a capability from a third party.\n *\n * This is called when we receive a third-party capability and want to\n * establish a direct connection to use it.\n */\n async sendAccept(\n targetConnection: RpcConnection,\n provision: { id: Uint8Array },\n embargo = false\n ): Promise<ImportId> {\n const questionId = targetConnection.createQuestion();\n\n const acceptMsg: RpcMessage = {\n type: 'accept',\n accept: {\n questionId,\n provision: provision as any,\n embargo,\n },\n };\n\n await targetConnection.sendCall(acceptMsg.accept as any);\n\n // Wait for the return\n const _result = await targetConnection.waitForAnswer(questionId);\n\n // In a full implementation, we'd extract the import ID from the result\n // For now, return a placeholder\n return 0 as ImportId;\n }\n\n // ========================================================================================\n // Embargo Handling (Cycle Breaking)\n // ========================================================================================\n\n /**\n * Handle an embargoed accept.\n *\n * Embargoes are used to break cycles in the introduction graph. For example,\n * if Alice introduces Bob to Carol and Carol to Bob simultaneously, both\n * introductions use embargo=true to prevent deadlock.\n */\n private async handleEmbargoedAccept(\n questionId: number,\n provision: PendingProvision\n ): Promise<void> {\n // Store the pending accept\n const pendingAccept: PendingAccept = {\n questionId,\n provision,\n embargoId: this.nextEmbargoId++,\n };\n\n this.pendingAccepts.set(questionId, pendingAccept);\n\n // Send a Return with resultsSentElsewhere to indicate we're waiting\n await this.sendReturnResultsSentElsewhere(questionId);\n\n // The embargo will be lifted when we receive a Disembargo message\n }\n\n /**\n * Handle a Disembargo message.\n *\n * Disembargo messages are used to lift embargoes on capabilities.\n */\n async handleDisembargo(disembargo: Disembargo): Promise<void> {\n const { target, context } = disembargo;\n\n switch (context.type) {\n case 'senderLoopback':\n // Echo back as receiverLoopback\n await this.sendDisembargoEcho(disembargo);\n break;\n\n case 'receiverLoopback':\n // Embargo lifted - process any pending calls\n await this.liftEmbargo(context.embargoId);\n break;\n\n case 'accept':\n // Embargo on a third-party accept can be lifted\n await this.liftAcceptEmbargo(target);\n break;\n\n case 'provide':\n // Embargo on a provision can be lifted\n await this.liftProvideEmbargo(context.questionId);\n break;\n }\n }\n\n /**\n * Lift an embargo by ID.\n */\n private async liftEmbargo(embargoId: number): Promise<void> {\n // Find and process embargoed calls\n const calls = this.embargoedCalls.get(embargoId);\n if (calls) {\n for (const call of calls) {\n // Re-send the call\n await this.resendEmbargoedCall(call);\n }\n this.embargoedCalls.delete(embargoId);\n }\n }\n\n /**\n * Lift an embargo on an accept.\n */\n private async liftAcceptEmbargo(target: MessageTarget): Promise<void> {\n // Find pending accepts for this target and complete them\n for (const [questionId, pendingAccept] of this.pendingAccepts) {\n if (this.matchesTarget(pendingAccept.provision.targetExportId, target)) {\n // Return the capability\n const capDescriptor: CapDescriptor = {\n type: 'senderHosted',\n exportId: pendingAccept.provision.targetExportId as ExportId,\n };\n\n await this.sendReturnCapability(pendingAccept.questionId, capDescriptor);\n this.pendingAccepts.delete(questionId);\n }\n }\n }\n\n /**\n * Lift an embargo on a provide.\n */\n private async liftProvideEmbargo(_questionId: number): Promise<void> {\n // Find the pending provision and mark it as no longer embargoed\n const { connectionManager } = this.options;\n\n for (const _provision of connectionManager.getAllConnections()) {\n // This is a simplified implementation\n // In a full implementation, we'd track provisions by question ID\n }\n }\n\n // ========================================================================================\n // Third-Party Capability Handling\n // ========================================================================================\n\n /**\n * Handle receiving a third-party capability.\n *\n * When we receive a CapDescriptor with type 'thirdPartyHosted', we need to:\n * 1. Establish a connection to the third party (if not already connected)\n * 2. Send an Accept message to pick up the capability\n * 3. Return a local import ID for the capability\n */\n async handleThirdPartyCapability(\n thirdPartyCapId: ThirdPartyCapId\n ): Promise<ImportId | undefined> {\n const { connectionManager } = this.options;\n\n // Resolve the third-party capability\n const resolved = await connectionManager.resolveThirdPartyCap(thirdPartyCapId);\n if (!resolved) {\n return undefined;\n }\n\n const { connection, provisionId } = resolved;\n\n // Send Accept to pick up the capability\n const importId = await this.sendAccept(connection, provisionId);\n\n return importId;\n }\n\n /**\n * Create a third-party capability descriptor.\n *\n * This is called when we want to pass a capability to a peer, but the capability\n * is actually hosted by a third party. We create a ThirdPartyCapId that allows\n * the recipient to connect directly to the third party.\n */\n createThirdPartyCapDescriptor(\n _hostedConnection: RpcConnection,\n exportId: ExportId,\n recipientVatId: VatId\n ): CapDescriptor {\n const { connectionManager, selfVatId } = this.options;\n\n // Generate a provision ID\n const provisionId = generateProvisionId();\n\n // Create the ThirdPartyCapId\n // Format: [selfVatId (32 bytes)] [provisionId (32 bytes)]\n const thirdPartyCapId = createThirdPartyCapId(selfVatId, provisionId);\n\n // Create a pending provision for this\n connectionManager.createPendingProvision(\n provisionId,\n recipientVatId,\n exportId,\n 0, // No question ID for this type of provision\n false\n );\n\n return {\n type: 'thirdPartyHosted',\n thirdPartyCapId,\n };\n }\n\n // ========================================================================================\n // Helper Methods\n // ========================================================================================\n\n private extractTargetExportId(target: MessageTarget): number | undefined {\n if (target.type === 'importedCap') {\n return target.importId;\n }\n // promisedAnswer targets are not supported for Provide\n return undefined;\n }\n\n private recipientIdToVatId(recipient: RecipientId): VatId {\n return { id: recipient.id };\n }\n\n private matchesTarget(exportId: number, target: MessageTarget): boolean {\n if (target.type === 'importedCap') {\n return target.importId === exportId;\n }\n return false;\n }\n\n private async sendReturnResults(questionId: number, _results: unknown): Promise<void> {\n const { connection } = this.options;\n\n // In a full implementation, we'd serialize the results\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'results',\n payload: {\n content: new Uint8Array(0),\n capTable: [],\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendReturnCapability(questionId: number, cap: CapDescriptor): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'results',\n payload: {\n content: new Uint8Array(0),\n capTable: [cap],\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendReturnException(questionId: number, reason: string): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'exception',\n exception: {\n reason,\n type: 'failed',\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendReturnResultsSentElsewhere(questionId: number): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'resultsSentElsewhere',\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendDisembargoEcho(disembargo: Disembargo): Promise<void> {\n const { connection } = this.options;\n\n if (disembargo.context.type !== 'senderLoopback') {\n return;\n }\n\n const echoMsg: RpcMessage = {\n type: 'disembargo',\n disembargo: {\n target: disembargo.target,\n context: {\n type: 'receiverLoopback',\n embargoId: disembargo.context.embargoId,\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendDisembargo(echoMsg.disembargo);\n }\n\n private async resendEmbargoedCall(_call: EmbargoedCall): Promise<void> {\n // In a full implementation, we'd re-send the call\n // For now, this is a placeholder\n }\n}\n\n/** Pending accept waiting for embargo to be lifted */\ninterface PendingAccept {\n questionId: number;\n provision: PendingProvision;\n embargoId: number;\n}\n\n/** An embargoed call waiting to be re-sent */\ninterface EmbargoedCall {\n questionId: number;\n target: MessageTarget;\n interfaceId: bigint;\n methodId: number;\n params: unknown;\n embargoId: number;\n}\n","/**\n * Level 4 RPC: Reference Equality / Join Operations\n *\n * Level 4 RPC allows verifying that capability references received from different\n * sources point to the same underlying object. This is crucial for:\n *\n * 1. **Escrow Agents**: Verifying that two parties are referring to the same object\n * before acting as a trusted intermediary.\n * 2. **Consensus Verification**: Ensuring multiple parties agree on the identity\n * of an object.\n * 3. **Security**: Preventing spoofing attacks where an attacker might try to\n * substitute a different object.\n *\n * ## Core Concept\n *\n * When Alice receives capability references from both Bob and Carol that should\n * point to the same object (e.g., a shared resource), she can use Join to verify\n * this:\n *\n * ```\n * Alice receives cap1 from Bob → points to object X (via proxy P1)\n * Alice receives cap2 from Carol → points to object X (via proxy P2)\n * Alice sends Join(cap1, cap2) to P1\n * P1 verifies that both caps point to the same underlying object\n * Result: confirmed equal or not equal\n * ```\n *\n * ## Object Identity\n *\n * Object identity is determined by:\n * - **Vat ID**: The vat hosting the object\n * - **Object ID**: A unique identifier within that vat\n * - **Identity Hash**: A cryptographic hash of the object's identity\n *\n * ## Join Protocol\n *\n * 1. Alice sends Join message to the first capability's host (P1)\n * 2. P1 receives the Join request with two capability references\n * 3. P1 verifies that both references resolve to the same underlying object\n * 4. P1 returns the result (equal or not equal)\n *\n * ## Escrow Agent Pattern\n *\n * ```\n * Bob wants to sell an object to Carol\n * Alice acts as escrow agent\n * Bob sends Alice a reference to the object\n * Carol sends Alice a reference to the same object\n * Alice verifies (via Join) that both refer to the same object\n * Alice holds payment from Carol\n * Bob transfers object to Carol\n * Alice releases payment to Bob\n * ```\n *\n * ## Implementation Notes\n *\n * - Join operations are idempotent\n * - Results are cached to avoid redundant verification\n * - Multiple capabilities can be joined in a single operation\n * - The operation may involve network calls to resolve proxies\n *\n * @module level4-handlers\n */\n\n/**\n * Object identity information used for equality verification.\n */\nexport interface ObjectIdentity {\n /** The vat ID of the object host */\n vatId: Uint8Array;\n\n /** The unique object ID within the vat */\n objectId: Uint8Array;\n\n /** Optional identity hash/fingerprint for verification */\n identityHash?: Uint8Array;\n\n /** Timestamp when this identity was established */\n establishedAt: number;\n}\n\n/**\n * Result of a Join operation.\n */\nexport interface JoinResult {\n /** Whether the capabilities are equal (point to the same object) */\n equal: boolean;\n\n /** If equal, the shared object identity */\n identity?: ObjectIdentity;\n\n /** If not equal, reasons for inequality */\n inequalityReason?: string;\n\n /** The join operation ID */\n joinId: number;\n}\n\n/**\n * Options for a Join operation.\n */\nexport interface JoinOptions {\n /** Timeout for the join operation in milliseconds */\n timeoutMs?: number;\n\n /** Whether to require cryptographic verification */\n requireCryptoVerification?: boolean;\n\n /** Whether to cache the result */\n cacheResult?: boolean;\n\n /** TTL for cached results in milliseconds */\n cacheTtlMs?: number;\n}\n\n/**\n * Default join options.\n */\nexport const DEFAULT_JOIN_OPTIONS: Required<JoinOptions> = {\n timeoutMs: 30000,\n requireCryptoVerification: true,\n cacheResult: true,\n cacheTtlMs: 300000, // 5 minutes\n};\n\n/**\n * Status of a pending Join operation.\n */\nexport interface PendingJoin {\n /** The join operation ID */\n joinId: number;\n\n /** The first capability target */\n target1: unknown;\n\n /** The second capability target */\n target2: unknown;\n\n /** When the join was initiated */\n startedAt: number;\n\n /** Resolve function for the promise */\n resolve: (result: JoinResult) => void;\n\n /** Reject function for the promise */\n reject: (error: Error) => void;\n}\n\n/**\n * Cached join result.\n */\nexport interface CachedJoinResult {\n /** The cached result */\n result: JoinResult;\n\n /** When the result was cached */\n cachedAt: number;\n\n /** The targets that were joined */\n targets: [string, string]; // Hashed target identifiers\n}\n\n/**\n * Configuration for the escrow agent mode.\n */\nexport interface EscrowConfig {\n /** Whether escrow mode is enabled */\n enabled: boolean;\n\n /** Required number of parties for consensus */\n requiredParties: number;\n\n /** Timeout for escrow operations */\n timeoutMs: number;\n\n /** Callback when consensus is reached */\n onConsensus?: (identity: ObjectIdentity, parties: string[]) => void;\n\n /** Callback when consensus fails */\n onConsensusFailure?: (reason: string, parties: string[]) => void;\n}\n\n/**\n * Default escrow configuration.\n */\nexport const DEFAULT_ESCROW_CONFIG: EscrowConfig = {\n enabled: false,\n requiredParties: 2,\n timeoutMs: 60000,\n};\n\n/**\n * Security policy for Join operations.\n */\nexport interface JoinSecurityPolicy {\n /** Whether to verify identity hashes */\n verifyIdentityHashes: boolean;\n\n /** Whether to check for revoked objects */\n checkRevocation: boolean;\n\n /** Maximum depth for proxy resolution */\n maxProxyDepth: number;\n\n /** Whether to log all join operations */\n auditLog: boolean;\n\n /** Allowed vats for join operations (empty = all allowed) */\n allowedVats: Uint8Array[];\n}\n\n/**\n * Default join security policy.\n */\nexport const DEFAULT_JOIN_SECURITY_POLICY: JoinSecurityPolicy = {\n verifyIdentityHashes: true,\n checkRevocation: true,\n maxProxyDepth: 10,\n auditLog: true,\n allowedVats: [],\n};\n","/**\n * Level 4 RPC: Reference Equality / Join Operations\n *\n * This module implements the Level 4 RPC protocol for verifying that capability\n * references point to the same underlying object.\n *\n * Reference: https://capnproto.org/rpc.html (Level 4: Reference equality / joining)\n */\n\nimport type { ConnectionManager, VatId } from './connection-manager.js';\nimport type { Level3Handlers } from './level3-handlers.js';\nimport {\n type CachedJoinResult,\n DEFAULT_ESCROW_CONFIG,\n DEFAULT_JOIN_OPTIONS,\n DEFAULT_JOIN_SECURITY_POLICY,\n type EscrowConfig,\n type JoinOptions,\n type JoinResult,\n type JoinSecurityPolicy,\n type ObjectIdentity,\n type PendingJoin,\n} from './level4-types.js';\nimport type { RpcConnection } from './rpc-connection.js';\nimport type { Join, MessageTarget, QuestionId, RpcMessage } from './rpc-types.js';\n\n/** Options for Level4Handlers */\nexport interface Level4HandlersOptions {\n /** The connection this handler is attached to */\n connection: RpcConnection;\n\n /** The connection manager for multi-vat scenarios */\n connectionManager?: ConnectionManager;\n\n /** Level 3 handlers (required for proxy resolution) */\n level3Handlers?: Level3Handlers;\n\n /** This vat's ID */\n selfVatId?: VatId;\n\n /** Join operation options */\n joinOptions?: JoinOptions;\n\n /** Escrow agent configuration */\n escrowConfig?: EscrowConfig;\n\n /** Security policy */\n securityPolicy?: JoinSecurityPolicy;\n\n /** Handler for incoming Join messages */\n onJoin?: (join: Join) => Promise<JoinResult>;\n}\n\n/**\n * Manages Level 4 RPC message handling for reference equality verification.\n *\n * This class handles:\n * 1. Join messages - verifying that two capabilities point to the same object\n * 2. Object identity tracking and caching\n * 3. Escrow agent functionality for consensus verification\n * 4. Security verification (anti-spoofing)\n *\n * ## Usage Example\n *\n * ```typescript\n * const level4Handlers = new Level4Handlers({\n * connection,\n * connectionManager,\n * level3Handlers,\n * selfVatId,\n * });\n *\n * // Enable escrow mode for consensus verification\n * level4Handlers.setEscrowConfig({\n * enabled: true,\n * requiredParties: 2,\n * });\n *\n * // Send a Join request\n * const result = await level4Handlers.sendJoin(target1, target2);\n * if (result.equal) {\n * console.log('Capabilities point to the same object!');\n * }\n * ```\n */\nexport class Level4Handlers {\n private options: Level4HandlersOptions;\n private pendingJoins = new Map<number, PendingJoin>();\n private joinResultsCache = new Map<string, CachedJoinResult>();\n private objectIdentities = new Map<number, ObjectIdentity>();\n private nextJoinId = 1;\n private escrowConfig: EscrowConfig;\n private securityPolicy: JoinSecurityPolicy;\n private joinOptions: Required<JoinOptions>;\n\n // Escrow state\n private escrowParties = new Map<string, { target: unknown; identity?: ObjectIdentity }>();\n private escrowConsensus?: {\n identity: ObjectIdentity;\n parties: string[];\n };\n\n constructor(options: Level4HandlersOptions) {\n this.options = options;\n this.escrowConfig = { ...DEFAULT_ESCROW_CONFIG, ...options.escrowConfig };\n this.securityPolicy = { ...DEFAULT_JOIN_SECURITY_POLICY, ...options.securityPolicy };\n this.joinOptions = { ...DEFAULT_JOIN_OPTIONS, ...options.joinOptions };\n }\n\n // ========================================================================================\n // Join Message Handling\n // ========================================================================================\n\n /**\n * Handle an incoming Join message.\n *\n * When we receive a Join message, we need to verify whether the two\n * capability references point to the same underlying object.\n *\n * The verification process:\n * 1. Resolve both targets to their underlying objects\n * 2. Compare object identities (vat ID + object ID)\n * 3. Optionally verify identity hashes cryptographically\n * 4. Return the result\n */\n async handleJoin(join: Join): Promise<void> {\n const { questionId, target, otherCap, joinId } = join;\n\n try {\n // Check cache first\n const cacheKey = this.getCacheKey(target, otherCap);\n const cached = this.joinResultsCache.get(cacheKey);\n if (cached && Date.now() - cached.cachedAt < this.joinOptions.cacheTtlMs) {\n await this.sendJoinResult(questionId, cached.result);\n return;\n }\n\n // Resolve both targets to their identities\n const identity1 = await this.resolveTargetToIdentity(target);\n const identity2 = await this.resolveTargetToIdentity(otherCap);\n\n // Compare identities\n const result = this.compareIdentities(identity1, identity2, joinId);\n\n // Cache the result if enabled\n if (this.joinOptions.cacheResult) {\n this.joinResultsCache.set(cacheKey, {\n result,\n cachedAt: Date.now(),\n targets: [this.hashTarget(target), this.hashTarget(otherCap)],\n });\n }\n\n // Log for audit if enabled\n if (this.securityPolicy.auditLog) {\n this.logJoinOperation(target, otherCap, result);\n }\n\n // Send the result\n await this.sendJoinResult(questionId, result);\n\n // Call custom handler if provided\n if (this.options.onJoin) {\n await this.options.onJoin(join);\n }\n } catch (error) {\n // Send exception result\n await this.sendJoinException(\n questionId,\n error instanceof Error ? error.message : 'Join operation failed'\n );\n }\n }\n\n /**\n * Send a Join message to verify that two capabilities point to the same object.\n *\n * @param target1 First capability target\n * @param target2 Second capability target\n * @returns Promise resolving to the join result\n */\n async sendJoin(target1: MessageTarget, target2: MessageTarget): Promise<JoinResult> {\n const { connection } = this.options;\n const joinId = this.nextJoinId++;\n const questionId = connection.createQuestion();\n\n // Create pending join\n const pendingJoin: PendingJoin = {\n joinId,\n target1,\n target2,\n startedAt: Date.now(),\n resolve: () => {},\n reject: () => {},\n };\n\n const completionPromise = new Promise<JoinResult>((resolve, reject) => {\n pendingJoin.resolve = resolve;\n pendingJoin.reject = reject;\n });\n\n this.pendingJoins.set(joinId, pendingJoin);\n\n // Set timeout\n const timeoutMs = this.joinOptions.timeoutMs;\n const timeoutId = setTimeout(() => {\n this.pendingJoins.delete(joinId);\n pendingJoin.reject(new Error(`Join operation timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n // Override resolve to clear timeout\n const originalResolve = pendingJoin.resolve;\n pendingJoin.resolve = (result: JoinResult) => {\n clearTimeout(timeoutId);\n this.pendingJoins.delete(joinId);\n originalResolve(result);\n };\n\n try {\n const joinMsg: RpcMessage = {\n type: 'join',\n join: {\n questionId,\n target: target1,\n otherCap: target2,\n joinId,\n },\n };\n\n await connection.sendCall(joinMsg.join as any);\n\n // Wait for the result\n const result = await completionPromise;\n return result;\n } catch (error) {\n clearTimeout(timeoutId);\n this.pendingJoins.delete(joinId);\n throw error;\n }\n }\n\n /**\n * Complete a pending join operation with the result.\n * This is called when we receive a Return message for a Join.\n */\n completeJoin(joinId: number, result: JoinResult): void {\n const pending = this.pendingJoins.get(joinId);\n if (pending) {\n pending.resolve(result);\n this.pendingJoins.delete(joinId);\n }\n }\n\n // ========================================================================================\n // Object Identity Resolution\n // ========================================================================================\n\n /**\n * Resolve a MessageTarget to its ObjectIdentity.\n *\n * This may involve:\n * 1. Looking up local exports\n * 2. Resolving promises\n * 3. Following third-party capabilities\n * 4. Verifying proxy chains\n */\n private async resolveTargetToIdentity(target: MessageTarget): Promise<ObjectIdentity | null> {\n if (target.type === 'importedCap') {\n // Check if we have cached identity for this import\n const cached = this.objectIdentities.get(target.importId);\n if (cached) {\n return cached;\n }\n\n // Get the import and resolve its identity\n const importEntry = this.options.connection.getImport(target.importId);\n if (!importEntry) {\n return null;\n }\n\n // For local imports, we need to query the remote vat for identity\n // In a full implementation, this would involve a network call\n // For now, return a placeholder\n return null;\n }\n\n if (target.type === 'promisedAnswer') {\n // Wait for the promise to resolve\n const { questionId } = target.promisedAnswer;\n\n // Wait for the answer\n try {\n const _answer = await this.options.connection.waitForAnswer(questionId);\n // Extract capability from answer and resolve identity\n // This is simplified - full implementation would handle transforms\n return null;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n\n /**\n * Compare two object identities for equality.\n */\n private compareIdentities(\n identity1: ObjectIdentity | null,\n identity2: ObjectIdentity | null,\n joinId: number\n ): JoinResult {\n // Both null = equal (both are null capabilities)\n if (!identity1 && !identity2) {\n return { equal: true, joinId };\n }\n\n // One null, one not = not equal\n if (!identity1 || !identity2) {\n return {\n equal: false,\n joinId,\n inequalityReason: 'One capability is null, the other is not',\n };\n }\n\n // Compare vat IDs\n if (!this.arraysEqual(identity1.vatId, identity2.vatId)) {\n return {\n equal: false,\n joinId,\n inequalityReason: 'Capabilities hosted by different vats',\n };\n }\n\n // Compare object IDs\n if (!this.arraysEqual(identity1.objectId, identity2.objectId)) {\n return {\n equal: false,\n joinId,\n inequalityReason: 'Different object IDs within the same vat',\n };\n }\n\n // Verify identity hashes if required\n if (this.securityPolicy.verifyIdentityHashes) {\n if (identity1.identityHash && identity2.identityHash) {\n if (!this.arraysEqual(identity1.identityHash, identity2.identityHash)) {\n return {\n equal: false,\n joinId,\n inequalityReason: 'Identity hash mismatch (possible spoofing attempt)',\n };\n }\n }\n }\n\n // All checks passed - identities are equal\n return {\n equal: true,\n joinId,\n identity: identity1,\n };\n }\n\n // ========================================================================================\n // Escrow Agent Functionality\n // ========================================================================================\n\n /**\n * Set the escrow configuration.\n */\n setEscrowConfig(config: Partial<EscrowConfig>): void {\n this.escrowConfig = { ...this.escrowConfig, ...config };\n }\n\n /**\n * Register a party in an escrow consensus verification.\n *\n * This is used when multiple parties need to verify they are referring\n * to the same object (e.g., in a trade or agreement).\n *\n * @param partyId Unique identifier for the party\n * @param target The capability reference from this party\n * @returns Whether consensus has been reached\n */\n async registerEscrowParty(\n partyId: string,\n target: unknown\n ): Promise<{ consensus: boolean; identity?: ObjectIdentity }> {\n if (!this.escrowConfig.enabled) {\n throw new Error('Escrow mode is not enabled');\n }\n\n // Check if party already registered\n if (this.escrowParties.has(partyId)) {\n throw new Error(`Party ${partyId} is already registered`);\n }\n\n // Register the party\n this.escrowParties.set(partyId, { target });\n\n // If we have enough parties, verify consensus\n if (this.escrowParties.size >= this.escrowConfig.requiredParties) {\n const consensus = await this.verifyEscrowConsensus();\n\n if (consensus.consensus) {\n this.escrowConsensus = {\n identity: consensus.identity!,\n parties: Array.from(this.escrowParties.keys()),\n };\n\n if (this.escrowConfig.onConsensus) {\n this.escrowConfig.onConsensus(consensus.identity!, Array.from(this.escrowParties.keys()));\n }\n } else {\n if (this.escrowConfig.onConsensusFailure) {\n this.escrowConfig.onConsensusFailure(\n consensus.reason!,\n Array.from(this.escrowParties.keys())\n );\n }\n }\n\n return { consensus: consensus.consensus, identity: consensus.identity };\n }\n\n return { consensus: false };\n }\n\n /**\n * Verify that all registered escrow parties refer to the same object.\n */\n private async verifyEscrowConsensus(): Promise<{\n consensus: boolean;\n identity?: ObjectIdentity;\n reason?: string;\n }> {\n const parties = Array.from(this.escrowParties.entries());\n\n if (parties.length < this.escrowConfig.requiredParties) {\n return { consensus: false, reason: 'Not enough parties registered' };\n }\n\n // Use the first party's target as the reference\n const [firstPartyId, firstParty] = parties[0];\n\n // Resolve first party's identity\n const firstIdentity = await this.resolveTargetToIdentity(firstParty.target as MessageTarget);\n if (!firstIdentity) {\n return { consensus: false, reason: `Could not resolve identity for party ${firstPartyId}` };\n }\n\n // Compare with all other parties\n for (const [partyId, party] of parties.slice(1)) {\n const identity = await this.resolveTargetToIdentity(party.target as MessageTarget);\n const comparison = this.compareIdentities(firstIdentity, identity, 0);\n\n if (!comparison.equal) {\n return {\n consensus: false,\n reason: `Party ${partyId} refers to a different object: ${comparison.inequalityReason}`,\n };\n }\n }\n\n // All parties refer to the same object\n return { consensus: true, identity: firstIdentity };\n }\n\n /**\n * Clear all escrow state.\n */\n clearEscrow(): void {\n this.escrowParties.clear();\n this.escrowConsensus = undefined;\n }\n\n /**\n * Get the current escrow consensus if reached.\n */\n getEscrowConsensus(): { identity: ObjectIdentity; parties: string[] } | undefined {\n return this.escrowConsensus;\n }\n\n // ========================================================================================\n // Security & Anti-Spoofing\n // ========================================================================================\n\n /**\n * Set the security policy.\n */\n setSecurityPolicy(policy: Partial<JoinSecurityPolicy>): void {\n this.securityPolicy = { ...this.securityPolicy, ...policy };\n }\n\n /**\n * Verify that a vat is allowed to participate in join operations.\n */\n private isVatAllowed(vatId: Uint8Array): boolean {\n if (this.securityPolicy.allowedVats.length === 0) {\n return true; // All vats allowed if no restrictions\n }\n\n return this.securityPolicy.allowedVats.some((allowed) => this.arraysEqual(allowed, vatId));\n }\n\n /**\n * Generate a cryptographic identity hash for an object.\n *\n * This creates a verifiable fingerprint of the object's identity\n * that can be used to detect spoofing attempts.\n */\n async generateIdentityHash(vatId: Uint8Array, objectId: Uint8Array): Promise<Uint8Array> {\n // Combine vat ID and object ID\n const combined = new Uint8Array(vatId.length + objectId.length);\n combined.set(vatId, 0);\n combined.set(objectId, vatId.length);\n\n // Use SubtleCrypto for hashing if available\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const hashBuffer = await crypto.subtle.digest('SHA-256', combined);\n return new Uint8Array(hashBuffer);\n }\n\n // Fallback: simple hash for Node.js\n const { createHash } = require('node:crypto');\n const hash = createHash('sha256');\n hash.update(combined);\n return hash.digest();\n }\n\n // ========================================================================================\n // Caching & Cleanup\n // ========================================================================================\n\n /**\n * Clear the join results cache.\n */\n clearCache(): void {\n this.joinResultsCache.clear();\n }\n\n /**\n * Clean up expired cache entries.\n */\n cleanupExpiredCache(): number {\n const now = Date.now();\n let removed = 0;\n\n for (const [key, entry] of this.joinResultsCache) {\n if (now - entry.cachedAt > this.joinOptions.cacheTtlMs) {\n this.joinResultsCache.delete(key);\n removed++;\n }\n }\n\n return removed;\n }\n\n /**\n * Get cache statistics.\n */\n getCacheStats(): { size: number; hitRate: number } {\n return {\n size: this.joinResultsCache.size,\n hitRate: 0, // Would need to track hits/misses\n };\n }\n\n // ========================================================================================\n // Helper Methods\n // ========================================================================================\n\n private getCacheKey(target1: MessageTarget, target2: MessageTarget): string {\n // Create a consistent cache key regardless of order\n const hash1 = this.hashTarget(target1);\n const hash2 = this.hashTarget(target2);\n\n // Sort to ensure (A,B) and (B,A) have the same key\n const sorted = [hash1, hash2].sort();\n return `join:${sorted[0]}:${sorted[1]}`;\n }\n\n private hashTarget(target: MessageTarget): string {\n if (target.type === 'importedCap') {\n return `import:${target.importId}`;\n }\n if (target.type === 'promisedAnswer') {\n return `answer:${target.promisedAnswer.questionId}`;\n }\n return 'unknown';\n }\n\n private arraysEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n private async sendJoinResult(questionId: QuestionId, result: JoinResult): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'results',\n payload: {\n content: this.serializeJoinResult(result),\n capTable: [],\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private async sendJoinException(questionId: QuestionId, reason: string): Promise<void> {\n const { connection } = this.options;\n\n const returnMsg: RpcMessage = {\n type: 'return',\n return: {\n answerId: questionId,\n releaseParamCaps: true,\n noFinishNeeded: false,\n result: {\n type: 'exception',\n exception: {\n reason,\n type: 'failed',\n },\n },\n },\n };\n\n // @ts-ignore - accessing internal method\n await connection.sendReturn(returnMsg.return);\n }\n\n private serializeJoinResult(result: JoinResult): Uint8Array {\n // Simple serialization - in production, use proper Cap'n Proto encoding\n const obj = {\n equal: result.equal,\n joinId: result.joinId,\n inequalityReason: result.inequalityReason,\n };\n return new TextEncoder().encode(JSON.stringify(obj));\n }\n\n private logJoinOperation(\n target1: MessageTarget,\n target2: MessageTarget,\n result: JoinResult\n ): void {\n console.log('[Level4] Join operation:', {\n target1: this.hashTarget(target1),\n target2: this.hashTarget(target2),\n equal: result.equal,\n joinId: result.joinId,\n timestamp: new Date().toISOString(),\n });\n }\n}\n\n// Re-export types\nexport type {\n JoinOptions,\n ObjectIdentity,\n PendingJoin,\n CachedJoinResult,\n EscrowConfig,\n JoinSecurityPolicy,\n} from './level4-types.js';\nexport {\n DEFAULT_JOIN_OPTIONS,\n DEFAULT_ESCROW_CONFIG,\n DEFAULT_JOIN_SECURITY_POLICY,\n} from './level4-types.js';\n","/**\n * Stream Abstraction for Cap'n Proto RPC\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Provides Stream interface for bidirectional streaming with:\n * - Backpressure handling\n * - Flow control window management\n * - Chunked transfer\n * - Progress notifications\n */\n\nimport type { RpcMessage } from './rpc-types.js';\nimport type { RpcTransport } from './transport.js';\n\n/** Stream state */\nexport type StreamState = 'connecting' | 'open' | 'closing' | 'closed' | 'error';\n\n/** Stream direction */\nexport type StreamDirection = 'inbound' | 'outbound' | 'bidirectional';\n\n/** Stream priority levels */\nexport enum StreamPriority {\n CRITICAL = 0, // Must not drop, immediate delivery\n HIGH = 1, // High priority, minimal delay\n NORMAL = 2, // Normal priority (default)\n LOW = 3, // Low priority, can be delayed\n BACKGROUND = 4, // Background tasks, lowest priority\n}\n\n/** Flow control window configuration */\nexport interface FlowControlConfig {\n /** Initial window size in bytes */\n initialWindowSize: number;\n /** Maximum window size in bytes */\n maxWindowSize: number;\n /** Minimum window size before backpressure */\n minWindowSize: number;\n /** Window update threshold (update when window drops below this) */\n windowUpdateThreshold: number;\n /** Window update increment size */\n windowUpdateIncrement: number;\n}\n\n/** Default flow control configuration */\nexport const DEFAULT_FLOW_CONTROL: FlowControlConfig = {\n initialWindowSize: 65536, // 64KB\n maxWindowSize: 1048576, // 1MB\n minWindowSize: 4096, // 4KB\n windowUpdateThreshold: 16384, // 16KB\n windowUpdateIncrement: 32768, // 32KB\n};\n\n/** Stream configuration options */\nexport interface StreamOptions {\n /** Stream ID (unique within connection) */\n streamId: number;\n /** Stream direction */\n direction: StreamDirection;\n /** Stream priority */\n priority?: StreamPriority;\n /** Flow control configuration */\n flowControl?: Partial<FlowControlConfig>;\n /** Enable progress notifications */\n enableProgress?: boolean;\n /** Progress notification interval in bytes */\n progressInterval?: number;\n /** Stream metadata */\n metadata?: Record<string, string>;\n}\n\n/** Chunk of data in a stream */\nexport interface StreamChunk {\n /** Chunk data */\n data: Uint8Array;\n /** Whether this is the final chunk */\n endOfStream?: boolean;\n /** Chunk sequence number (for ordering) */\n sequenceNumber?: number;\n /** Timestamp when chunk was sent */\n timestamp?: number;\n}\n\n/** Progress notification */\nexport interface StreamProgress {\n /** Stream ID */\n streamId: number;\n /** Total bytes sent/received */\n bytesTransferred: number;\n /** Total bytes expected (if known) */\n totalBytes?: number;\n /** Progress percentage (0-100) */\n percentage?: number;\n /** Transfer rate in bytes per second */\n transferRate?: number;\n /** Estimated time remaining in milliseconds */\n estimatedTimeRemaining?: number;\n}\n\n/** Flow control window state */\ninterface FlowControlWindow {\n /** Current window size */\n currentSize: number;\n /** Maximum window size */\n maxSize: number;\n /** Bytes sent/received in current window */\n bytesInWindow: number;\n /** Whether backpressure is active */\n backpressureActive: boolean;\n}\n\n/** Stream event handlers */\nexport interface StreamEventHandlers {\n /** Called when data is received */\n onData?: (chunk: StreamChunk) => void | Promise<void>;\n /** Called when stream is opened */\n onOpen?: () => void;\n /** Called when stream is closed */\n onClose?: () => void;\n /** Called when progress updates */\n onProgress?: (progress: StreamProgress) => void;\n /** Called when backpressure state changes */\n onBackpressure?: (active: boolean) => void;\n /** Called when an error occurs */\n onError?: (error: Error) => void;\n}\n\n/**\n * Stream abstraction for Cap'n Proto RPC\n *\n * Manages bidirectional streaming with flow control and backpressure.\n */\nexport class Stream {\n private options: StreamOptions;\n private handlers: StreamEventHandlers;\n private state: StreamState = 'connecting';\n private error?: Error;\n\n // Flow control\n private sendWindow: FlowControlWindow;\n private receiveWindow: FlowControlWindow;\n private flowControlConfig: FlowControlConfig;\n\n // Data buffering\n private sendBuffer: StreamChunk[] = [];\n private receiveBuffer: StreamChunk[] = [];\n private maxBufferSize = 1048576; // 1MB max buffer\n\n // Progress tracking\n private bytesSent = 0;\n private bytesReceived = 0;\n private totalBytesExpected?: number;\n private lastProgressUpdate = 0;\n private progressUpdateInterval: number;\n private transferStartTime?: number;\n\n // Chunk sequencing\n private nextSendSequence = 0;\n private nextExpectedSequence = 0;\n\n // Promise resolvers for async operations\n private openResolver?: () => void;\n private openRejector?: (error: Error) => void;\n private closeResolver?: () => void;\n\n constructor(options: StreamOptions, handlers: StreamEventHandlers = {}) {\n this.options = options;\n this.handlers = handlers;\n\n // Initialize flow control\n this.flowControlConfig = {\n ...DEFAULT_FLOW_CONTROL,\n ...options.flowControl,\n };\n\n this.sendWindow = {\n currentSize: this.flowControlConfig.initialWindowSize,\n maxSize: this.flowControlConfig.maxWindowSize,\n bytesInWindow: 0,\n backpressureActive: false,\n };\n\n this.receiveWindow = {\n currentSize: this.flowControlConfig.initialWindowSize,\n maxSize: this.flowControlConfig.maxWindowSize,\n bytesInWindow: 0,\n backpressureActive: false,\n };\n\n this.progressUpdateInterval = options.progressInterval ?? 65536; // 64KB default\n }\n\n /** Get stream ID */\n get id(): number {\n return this.options.streamId;\n }\n\n /** Get stream direction */\n get direction(): StreamDirection {\n return this.options.direction;\n }\n\n /** Get stream priority */\n get priority(): StreamPriority {\n return this.options.priority ?? StreamPriority.NORMAL;\n }\n\n /** Get current stream state */\n get currentState(): StreamState {\n return this.state;\n }\n\n /** Get whether stream is open */\n get isOpen(): boolean {\n return this.state === 'open';\n }\n\n /** Get whether backpressure is active for sending */\n get isBackpressureActive(): boolean {\n return this.sendWindow.backpressureActive;\n }\n\n /** Get bytes sent */\n get bytesSentCount(): number {\n return this.bytesSent;\n }\n\n /** Get bytes received */\n get bytesReceivedCount(): number {\n return this.bytesReceived;\n }\n\n /** Get metadata */\n get metadata(): Record<string, string> | undefined {\n return this.options.metadata;\n }\n\n /**\n * Open the stream\n */\n async open(): Promise<void> {\n if (this.state !== 'connecting') {\n throw new Error(`Cannot open stream in state: ${this.state}`);\n }\n\n return new Promise((resolve, reject) => {\n this.openResolver = resolve;\n this.openRejector = reject;\n\n // Transition to open state\n this.transitionState('open');\n this.transferStartTime = Date.now();\n\n // Notify handlers\n this.handlers.onOpen?.();\n });\n }\n\n /**\n * Send data through the stream\n *\n * Respects flow control and handles backpressure.\n */\n async send(data: Uint8Array, endOfStream = false): Promise<void> {\n if (this.state !== 'open') {\n throw new Error(`Cannot send in state: ${this.state}`);\n }\n\n // Check if we need to wait for window update\n if (this.sendWindow.bytesInWindow + data.length > this.sendWindow.currentSize) {\n // Wait for window update\n await this.waitForWindowUpdate();\n }\n\n // Create chunk\n const chunk: StreamChunk = {\n data,\n endOfStream,\n sequenceNumber: this.nextSendSequence++,\n timestamp: Date.now(),\n };\n\n // Update flow control\n this.sendWindow.bytesInWindow += data.length;\n this.bytesSent += data.length;\n\n // Check for backpressure\n this.checkBackpressure();\n\n // Send the chunk\n await this.sendChunk(chunk);\n\n // Report progress\n this.reportProgress();\n }\n\n /**\n * Send a chunk of data\n *\n * Override in subclasses to implement actual transport.\n */\n protected async sendChunk(chunk: StreamChunk): Promise<void> {\n // To be implemented by transport-specific subclass\n // This base class just buffers\n this.sendBuffer.push(chunk);\n }\n\n /**\n * Receive data from the stream\n *\n * Returns buffered data or waits for new data.\n */\n async receive(): Promise<StreamChunk | null> {\n if (this.receiveBuffer.length > 0) {\n return this.receiveBuffer.shift()!;\n }\n\n if (this.state === 'closed') {\n return null;\n }\n\n // Wait for data\n return new Promise((resolve, reject) => {\n const checkBuffer = () => {\n if (this.receiveBuffer.length > 0) {\n resolve(this.receiveBuffer.shift()!);\n } else if (this.state === 'closed') {\n resolve(null);\n } else if (this.state === 'error') {\n reject(this.error ?? new Error('Stream error'));\n } else {\n setTimeout(checkBuffer, 10);\n }\n };\n checkBuffer();\n });\n }\n\n /**\n * Handle incoming chunk from transport\n */\n handleIncomingChunk(chunk: StreamChunk): void {\n if (this.state !== 'open' && this.state !== 'closing') {\n return;\n }\n\n // Update receive window\n this.receiveWindow.bytesInWindow += chunk.data.length;\n this.bytesReceived += chunk.data.length;\n\n // Check if we need to send window update\n this.checkReceiveWindow();\n\n // Buffer or deliver chunk\n if (this.handlers.onData) {\n // Deliver immediately if handler is registered\n Promise.resolve(this.handlers.onData(chunk)).catch((err) => {\n this.handleError(err);\n });\n } else {\n // Buffer for later\n this.receiveBuffer.push(chunk);\n }\n\n // Report progress\n this.reportProgress();\n\n // Handle end of stream\n if (chunk.endOfStream) {\n this.transitionState('closing');\n }\n }\n\n /**\n * Update the send window (called when receiving window update from peer)\n */\n updateSendWindow(increment: number): void {\n this.sendWindow.currentSize = Math.min(\n this.sendWindow.currentSize + increment,\n this.sendWindow.maxSize\n );\n\n // Check if we can release backpressure\n if (this.sendWindow.backpressureActive) {\n const available = this.sendWindow.currentSize - this.sendWindow.bytesInWindow;\n if (available >= this.flowControlConfig.minWindowSize) {\n this.sendWindow.backpressureActive = false;\n this.handlers.onBackpressure?.(false);\n }\n }\n }\n\n /**\n * Acknowledge received bytes (called to update peer's send window)\n */\n acknowledgeBytes(bytes: number): void {\n this.receiveWindow.bytesInWindow = Math.max(0, this.receiveWindow.bytesInWindow - bytes);\n\n // Check if we should send window update\n if (this.receiveWindow.bytesInWindow < this.flowControlConfig.windowUpdateThreshold) {\n this.sendWindowUpdate();\n }\n }\n\n /**\n * Close the stream gracefully\n */\n async close(): Promise<void> {\n if (this.state === 'closed' || this.state === 'closing') {\n return;\n }\n\n this.transitionState('closing');\n\n // Wait for any pending sends to complete\n await this.drainSendBuffer();\n\n // Send end-of-stream marker\n await this.sendChunk({ data: new Uint8Array(0), endOfStream: true });\n\n this.transitionState('closed');\n this.handlers.onClose?.();\n }\n\n /**\n * Abort the stream with an error\n */\n abort(error: Error): void {\n this.error = error;\n this.transitionState('error');\n this.handlers.onError?.(error);\n }\n\n /**\n * Set total bytes expected (for progress calculation)\n */\n setTotalBytesExpected(total: number): void {\n this.totalBytesExpected = total;\n }\n\n /**\n * Wait for the stream to be ready for sending\n */\n async ready(): Promise<void> {\n if (this.state === 'open' && !this.sendWindow.backpressureActive) {\n return;\n }\n\n if (this.state !== 'open') {\n throw new Error(`Stream not open: ${this.state}`);\n }\n\n return this.waitForWindowUpdate();\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private transitionState(newState: StreamState): void {\n const _oldState = this.state;\n this.state = newState;\n\n // Resolve/reject pending promises\n if (newState === 'open' && this.openResolver) {\n this.openResolver();\n this.openResolver = undefined;\n this.openRejector = undefined;\n } else if (newState === 'error' && this.openRejector) {\n this.openRejector(this.error ?? new Error('Stream error'));\n this.openResolver = undefined;\n this.openRejector = undefined;\n }\n\n if (newState === 'closed' && this.closeResolver) {\n this.closeResolver();\n this.closeResolver = undefined;\n }\n }\n\n private checkBackpressure(): void {\n const available = this.sendWindow.currentSize - this.sendWindow.bytesInWindow;\n\n if (available < this.flowControlConfig.minWindowSize && !this.sendWindow.backpressureActive) {\n this.sendWindow.backpressureActive = true;\n this.handlers.onBackpressure?.(true);\n }\n }\n\n private checkReceiveWindow(): void {\n if (this.receiveWindow.bytesInWindow < this.flowControlConfig.windowUpdateThreshold) {\n this.sendWindowUpdate();\n }\n }\n\n private async waitForWindowUpdate(): Promise<void> {\n return new Promise((resolve, reject) => {\n const checkWindow = () => {\n const available = this.sendWindow.currentSize - this.sendWindow.bytesInWindow;\n\n if (this.state === 'error') {\n reject(this.error ?? new Error('Stream error'));\n return;\n }\n\n if (this.state !== 'open') {\n reject(new Error('Stream closed'));\n return;\n }\n\n if (available >= this.flowControlConfig.minWindowSize) {\n resolve();\n return;\n }\n\n setTimeout(checkWindow, 10);\n };\n\n checkWindow();\n });\n }\n\n private async drainSendBuffer(): Promise<void> {\n // In the base Stream class, sendBuffer is just for buffering\n // Subclasses that actually send data should override this\n // For now, just clear the buffer\n this.sendBuffer.length = 0;\n }\n\n private sendWindowUpdate(): void {\n // To be implemented by transport layer\n // This would send a window update message to the peer\n }\n\n private reportProgress(): void {\n if (!this.options.enableProgress || !this.handlers.onProgress) {\n return;\n }\n\n const now = Date.now();\n const bytesTransferred = Math.max(this.bytesSent, this.bytesReceived);\n\n // Check if it's time to report progress\n if (bytesTransferred - this.lastProgressUpdate < this.progressUpdateInterval) {\n return;\n }\n\n this.lastProgressUpdate = bytesTransferred;\n\n // Calculate transfer rate\n let transferRate: number | undefined;\n if (this.transferStartTime) {\n const elapsed = (now - this.transferStartTime) / 1000;\n if (elapsed > 0) {\n transferRate = bytesTransferred / elapsed;\n }\n }\n\n // Calculate percentage and ETA\n let percentage: number | undefined;\n let estimatedTimeRemaining: number | undefined;\n\n if (this.totalBytesExpected && this.totalBytesExpected > 0) {\n percentage = Math.min(100, (bytesTransferred / this.totalBytesExpected) * 100);\n\n if (transferRate && transferRate > 0) {\n const remaining = this.totalBytesExpected - bytesTransferred;\n estimatedTimeRemaining = (remaining / transferRate) * 1000;\n }\n }\n\n const progress: StreamProgress = {\n streamId: this.id,\n bytesTransferred,\n totalBytes: this.totalBytesExpected,\n percentage,\n transferRate,\n estimatedTimeRemaining,\n };\n\n this.handlers.onProgress(progress);\n }\n\n private handleError(error: Error): void {\n this.error = error;\n this.transitionState('error');\n this.handlers.onError?.(error);\n }\n}\n\n/**\n * Create a new stream\n */\nexport function createStream(options: StreamOptions, handlers?: StreamEventHandlers): Stream {\n return new Stream(options, handlers);\n}\n\n/**\n * Check if an object is a Stream\n */\nexport function isStream(obj: unknown): obj is Stream {\n return obj instanceof Stream;\n}\n","/**\n * Bulk API - High-volume data transfer with flow control\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Features:\n * - Backpressure mechanism\n * - Flow control window management\n * - Chunked transfer\n * - Progress notifications\n */\n\nimport type { RpcConnection } from './rpc-connection.js';\nimport {\n DEFAULT_FLOW_CONTROL,\n type FlowControlConfig,\n Stream,\n type StreamChunk,\n type StreamEventHandlers,\n type StreamOptions,\n StreamPriority,\n type StreamProgress,\n} from './stream.js';\n\n/** Bulk transfer configuration */\nexport interface BulkTransferConfig {\n /** Chunk size for transfer */\n chunkSize: number;\n /** Flow control configuration */\n flowControl?: Partial<FlowControlConfig>;\n /** Enable progress notifications */\n enableProgress?: boolean;\n /** Progress notification interval in bytes */\n progressInterval?: number;\n /** Maximum concurrent chunks in flight */\n maxConcurrentChunks?: number;\n /** Timeout for chunk acknowledgment */\n chunkAckTimeoutMs?: number;\n}\n\n/** Default bulk transfer configuration */\nexport const DEFAULT_BULK_CONFIG: BulkTransferConfig = {\n chunkSize: 16384, // 16KB chunks\n enableProgress: true,\n progressInterval: 65536, // 64KB\n maxConcurrentChunks: 8, // 8 concurrent chunks\n chunkAckTimeoutMs: 30000, // 30 seconds\n};\n\n/** Bulk transfer state */\nexport type BulkTransferState =\n | 'pending'\n | 'transferring'\n | 'paused'\n | 'completed'\n | 'cancelled'\n | 'error';\n\n/** Bulk transfer direction */\nexport type BulkTransferDirection = 'upload' | 'download';\n\n/** Bulk transfer metadata */\nexport interface BulkTransferMetadata {\n /** Transfer ID */\n id: string;\n /** File or resource name */\n name?: string;\n /** Total size in bytes (if known) */\n totalSize?: number;\n /** MIME type */\n contentType?: string;\n /** Custom metadata */\n custom?: Record<string, string>;\n}\n\n/** Bulk transfer statistics */\nexport interface BulkTransferStats {\n /** Bytes transferred */\n bytesTransferred: number;\n /** Total bytes (if known) */\n totalBytes?: number;\n /** Transfer rate in bytes per second */\n transferRate: number;\n /** Time elapsed in milliseconds */\n elapsedTime: number;\n /** Estimated time remaining in milliseconds */\n estimatedTimeRemaining?: number;\n /** Number of chunks transferred */\n chunksTransferred: number;\n /** Number of chunks acknowledged */\n chunksAcknowledged: number;\n /** Current window size */\n currentWindowSize: number;\n /** Whether backpressure is active */\n backpressureActive: boolean;\n}\n\n/** Chunk acknowledgment */\ninterface ChunkAck {\n sequenceNumber: number;\n bytesAcknowledged: number;\n}\n\n/** Bulk transfer event handlers */\nexport interface BulkTransferHandlers {\n /** Called when transfer starts */\n onStart?: () => void;\n /** Called when progress updates */\n onProgress?: (progress: StreamProgress) => void;\n /** Called when backpressure state changes */\n onBackpressure?: (active: boolean) => void;\n /** Called when transfer completes */\n onComplete?: () => void;\n /** Called when transfer is cancelled */\n onCancel?: () => void;\n /** Called when an error occurs */\n onError?: (error: Error) => void;\n}\n\n/**\n * Bulk transfer manager\n *\n * Manages high-volume data transfers with flow control and backpressure.\n */\nexport class BulkTransfer {\n private stream: Stream;\n private config: BulkTransferConfig;\n private handlers: BulkTransferHandlers;\n private metadata: BulkTransferMetadata;\n private direction: BulkTransferDirection;\n\n // State\n private state: BulkTransferState = 'pending';\n private error?: Error;\n\n // Transfer tracking\n private chunksInFlight = 0;\n private chunksAcknowledged = 0;\n private totalChunks = 0;\n private startTime?: number;\n private endTime?: number;\n\n // Chunk tracking\n private pendingChunks: Map<\n number,\n { chunk: StreamChunk; timeout: ReturnType<typeof setTimeout> }\n > = new Map();\n private chunkAckCallbacks: Map<number, () => void> = new Map();\n\n // Flow control\n private currentWindowSize: number;\n\n // Data source/sink\n private dataSource?: AsyncIterable<Uint8Array> | (() => Promise<Uint8Array | null>);\n private dataSink?: (chunk: Uint8Array) => Promise<void>;\n\n constructor(\n stream: Stream,\n direction: BulkTransferDirection,\n metadata: BulkTransferMetadata,\n config: Partial<BulkTransferConfig> = {},\n handlers: BulkTransferHandlers = {}\n ) {\n this.stream = stream;\n this.direction = direction;\n this.metadata = metadata;\n this.config = { ...DEFAULT_BULK_CONFIG, ...config };\n this.handlers = handlers;\n this.currentWindowSize =\n this.config.flowControl?.initialWindowSize ?? DEFAULT_FLOW_CONTROL.initialWindowSize;\n\n // Set up stream event handlers\n this.setupStreamHandlers();\n }\n\n /** Get transfer ID */\n get id(): string {\n return this.metadata.id;\n }\n\n /** Get current state */\n get currentState(): BulkTransferState {\n return this.state;\n }\n\n /** Get transfer statistics */\n get stats(): BulkTransferStats {\n const now = Date.now();\n const elapsed = this.startTime ? (this.endTime ?? now) - this.startTime : 0;\n const bytesTransferred = this.stream.bytesSentCount + this.stream.bytesReceivedCount;\n\n let transferRate = 0;\n if (elapsed > 0) {\n transferRate = (bytesTransferred / elapsed) * 1000;\n }\n\n let estimatedTimeRemaining: number | undefined;\n if (this.metadata.totalSize && transferRate > 0) {\n const remaining = this.metadata.totalSize - bytesTransferred;\n estimatedTimeRemaining = (remaining / transferRate) * 1000;\n }\n\n return {\n bytesTransferred,\n totalBytes: this.metadata.totalSize,\n transferRate,\n elapsedTime: elapsed,\n estimatedTimeRemaining,\n chunksTransferred: this.chunksAcknowledged + this.pendingChunks.size,\n chunksAcknowledged: this.chunksAcknowledged,\n currentWindowSize: this.currentWindowSize,\n backpressureActive: this.stream.isBackpressureActive,\n };\n }\n\n /**\n * Set the data source for upload\n */\n setDataSource(source: AsyncIterable<Uint8Array> | (() => Promise<Uint8Array | null>)): void {\n if (this.direction !== 'upload') {\n throw new Error('Data source only valid for uploads');\n }\n this.dataSource = source;\n }\n\n /**\n * Set the data sink for download\n */\n setDataSink(sink: (chunk: Uint8Array) => Promise<void>): void {\n if (this.direction !== 'download') {\n throw new Error('Data sink only valid for downloads');\n }\n this.dataSink = sink;\n }\n\n /**\n * Start the bulk transfer\n */\n async start(): Promise<void> {\n if (this.state !== 'pending') {\n throw new Error(`Cannot start transfer in state: ${this.state}`);\n }\n\n this.state = 'transferring';\n this.startTime = Date.now();\n this.handlers.onStart?.();\n\n // Set total size for progress tracking\n if (this.metadata.totalSize) {\n this.stream.setTotalBytesExpected(this.metadata.totalSize);\n }\n\n try {\n if (this.direction === 'upload') {\n await this.performUpload();\n } else {\n await this.performDownload();\n }\n\n if (this.state === 'transferring') {\n this.state = 'completed';\n this.endTime = Date.now();\n this.handlers.onComplete?.();\n }\n } catch (err) {\n this.handleError(err as Error);\n }\n }\n\n /**\n * Pause the transfer\n */\n pause(): void {\n if (this.state === 'transferring') {\n this.state = 'paused';\n }\n }\n\n /**\n * Resume the transfer\n */\n resume(): void {\n if (this.state === 'paused') {\n this.state = 'transferring';\n }\n }\n\n /**\n * Cancel the transfer\n */\n cancel(): void {\n if (this.state === 'completed' || this.state === 'error' || this.state === 'cancelled') {\n return;\n }\n\n this.state = 'cancelled';\n this.endTime = Date.now();\n\n // Clear pending timeouts\n for (const { timeout } of this.pendingChunks.values()) {\n clearTimeout(timeout);\n }\n this.pendingChunks.clear();\n\n this.handlers.onCancel?.();\n }\n\n /**\n * Handle chunk acknowledgment from peer\n */\n handleChunkAck(ack: ChunkAck): void {\n const pending = this.pendingChunks.get(ack.sequenceNumber);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingChunks.delete(ack.sequenceNumber);\n this.chunksAcknowledged++;\n this.chunksInFlight--;\n\n // Update window size\n this.currentWindowSize += ack.bytesAcknowledged;\n\n // Resolve pending ack callback\n const callback = this.chunkAckCallbacks.get(ack.sequenceNumber);\n if (callback) {\n callback();\n this.chunkAckCallbacks.delete(ack.sequenceNumber);\n }\n }\n }\n\n /**\n * Update flow control window\n */\n updateWindow(newWindowSize: number): void {\n this.currentWindowSize = newWindowSize;\n this.stream.updateSendWindow(newWindowSize);\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private setupStreamHandlers(): void {\n const _streamHandlers: StreamEventHandlers = {\n onData: async (chunk) => {\n // Handle incoming data for downloads\n if (this.direction === 'download' && this.dataSink) {\n await this.dataSink(chunk.data);\n\n // Send acknowledgment\n await this.sendChunkAck(chunk.sequenceNumber ?? 0, chunk.data.length);\n }\n },\n onBackpressure: (active) => {\n this.handlers.onBackpressure?.(active);\n },\n onProgress: (progress) => {\n this.handlers.onProgress?.(progress);\n },\n onError: (error) => {\n this.handleError(error);\n },\n };\n\n // Note: Stream handlers are set during construction\n // This is a simplified implementation\n }\n\n private async performUpload(): Promise<void> {\n if (!this.dataSource) {\n throw new Error('No data source set for upload');\n }\n\n if (Symbol.asyncIterator in this.dataSource) {\n // AsyncIterable source\n for await (const data of this.dataSource as AsyncIterable<Uint8Array>) {\n if (this.state !== 'transferring') {\n break;\n }\n\n await this.sendChunkWithFlowControl(data);\n }\n } else {\n // Function source\n const sourceFn = this.dataSource as () => Promise<Uint8Array | null>;\n while (this.state === 'transferring') {\n const data = await sourceFn();\n if (!data || data.length === 0) {\n break;\n }\n\n await this.sendChunkWithFlowControl(data);\n }\n }\n\n // Wait for all chunks to be acknowledged\n await this.waitForAllAcks();\n }\n\n private async performDownload(): Promise<void> {\n if (!this.dataSink) {\n throw new Error('No data sink set for download');\n }\n\n // Download is handled by onData callback\n // Just wait for completion\n while (this.state === 'transferring') {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n\n private async sendChunkWithFlowControl(data: Uint8Array): Promise<void> {\n // Wait for available window\n while (this.chunksInFlight >= (this.config.maxConcurrentChunks ?? 8)) {\n if (this.state !== 'transferring') {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, 10));\n }\n\n // Wait for stream to be ready (backpressure)\n await this.stream.ready();\n\n const sequenceNumber = this.totalChunks++;\n\n // Send the chunk\n await this.stream.send(data, false);\n this.chunksInFlight++;\n\n // Set up acknowledgment timeout\n const timeout = setTimeout(() => {\n this.handleChunkTimeout(sequenceNumber);\n }, this.config.chunkAckTimeoutMs ?? 30000);\n\n this.pendingChunks.set(sequenceNumber, {\n chunk: { data, sequenceNumber, timestamp: Date.now() },\n timeout,\n });\n }\n\n private async sendChunkAck(_sequenceNumber: number, _bytes: number): Promise<void> {\n // Send acknowledgment to peer\n // This would be implemented via the RPC connection\n }\n\n private handleChunkTimeout(sequenceNumber: number): void {\n const pending = this.pendingChunks.get(sequenceNumber);\n if (pending) {\n this.pendingChunks.delete(sequenceNumber);\n this.chunksInFlight--;\n\n // Could implement retry logic here\n this.handleError(new Error(`Chunk ${sequenceNumber} acknowledgment timeout`));\n }\n }\n\n private async waitForAllAcks(): Promise<void> {\n // In a real implementation, we would wait for acknowledgments from the peer\n // For now, just clear pending chunks immediately (simulating immediate ack)\n // This allows the transfer to complete without actual network acknowledgments\n for (const [sequenceNumber, { timeout }] of this.pendingChunks) {\n clearTimeout(timeout);\n this.handleChunkAck({\n sequenceNumber,\n bytesAcknowledged: 0, // Unknown, but doesn't matter for completion\n });\n }\n this.pendingChunks.clear();\n }\n\n private handleError(error: Error): void {\n if (this.state === 'completed' || this.state === 'error') {\n return;\n }\n\n this.error = error;\n this.state = 'error';\n this.endTime = Date.now();\n\n // Clear pending timeouts\n for (const { timeout } of this.pendingChunks.values()) {\n clearTimeout(timeout);\n }\n\n this.handlers.onError?.(error);\n }\n}\n\n/**\n * Bulk transfer manager\n *\n * Manages multiple concurrent bulk transfers.\n */\nexport class BulkTransferManager {\n private transfers: Map<string, BulkTransfer> = new Map();\n private streams: Map<number, Stream> = new Map();\n private nextStreamId = 1;\n\n /**\n * Create a new bulk transfer\n */\n createTransfer(\n direction: BulkTransferDirection,\n metadata: BulkTransferMetadata,\n config?: Partial<BulkTransferConfig>,\n handlers?: BulkTransferHandlers\n ): BulkTransfer {\n const streamId = this.nextStreamId++;\n\n const streamOptions: StreamOptions = {\n streamId,\n direction: direction === 'upload' ? 'outbound' : 'inbound',\n priority: StreamPriority.NORMAL,\n enableProgress: config?.enableProgress ?? true,\n progressInterval: config?.progressInterval,\n flowControl: config?.flowControl,\n };\n\n const stream = new Stream(streamOptions, {\n onProgress: handlers?.onProgress,\n onBackpressure: handlers?.onBackpressure,\n onError: handlers?.onError,\n });\n\n this.streams.set(streamId, stream);\n\n const transfer = new BulkTransfer(stream, direction, metadata, config, handlers);\n this.transfers.set(metadata.id, transfer);\n\n return transfer;\n }\n\n /**\n * Get a transfer by ID\n */\n getTransfer(id: string): BulkTransfer | undefined {\n return this.transfers.get(id);\n }\n\n /**\n * Get a stream by ID\n */\n getStream(id: number): Stream | undefined {\n return this.streams.get(id);\n }\n\n /**\n * Remove a transfer\n */\n removeTransfer(id: string): boolean {\n const transfer = this.transfers.get(id);\n if (transfer) {\n transfer.cancel();\n this.transfers.delete(id);\n return true;\n }\n return false;\n }\n\n /**\n * Get all active transfers\n */\n getActiveTransfers(): BulkTransfer[] {\n return Array.from(this.transfers.values()).filter(\n (t) =>\n t.currentState === 'pending' ||\n t.currentState === 'transferring' ||\n t.currentState === 'paused'\n );\n }\n\n /**\n * Get transfer statistics summary\n */\n getStatsSummary(): {\n totalTransfers: number;\n activeTransfers: number;\n completedTransfers: number;\n totalBytesTransferred: number;\n } {\n const transfers = Array.from(this.transfers.values());\n const active = transfers.filter((t) => t.currentState === 'transferring');\n const completed = transfers.filter((t) => t.currentState === 'completed');\n\n const totalBytes = transfers.reduce((sum, t) => sum + t.stats.bytesTransferred, 0);\n\n return {\n totalTransfers: transfers.length,\n activeTransfers: active.length,\n completedTransfers: completed.length,\n totalBytesTransferred: totalBytes,\n };\n }\n\n /**\n * Close all transfers\n */\n async closeAll(): Promise<void> {\n for (const transfer of this.transfers.values()) {\n transfer.cancel();\n }\n this.transfers.clear();\n this.streams.clear();\n }\n}\n\n/**\n * Create a bulk transfer manager\n */\nexport function createBulkTransferManager(): BulkTransferManager {\n return new BulkTransferManager();\n}\n","/**\n * Realtime API - Real-time communication with prioritization\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Features:\n * - Message priority queues\n * - Message drop policies for latency-sensitive scenarios\n * - Bandwidth adaptation\n * - Jitter buffer management\n */\n\nimport {\n type FlowControlConfig,\n type Stream,\n type StreamChunk,\n type StreamOptions,\n StreamPriority,\n} from './stream.js';\n\n/** Message priority levels (extends StreamPriority) */\nexport { StreamPriority as MessagePriority };\n\n/** Message drop policy for latency-sensitive scenarios */\nexport enum DropPolicy {\n /** Never drop messages */\n NEVER = 'never',\n /** Drop oldest messages when queue is full */\n DROP_OLDEST = 'drop_oldest',\n /** Drop newest messages when queue is full */\n DROP_NEWEST = 'drop_newest',\n /** Drop low priority messages first */\n DROP_LOW_PRIORITY = 'drop_low_priority',\n /** Drop messages that exceed max latency */\n DROP_STALE = 'drop_stale',\n}\n\n/** Realtime stream configuration */\nexport interface RealtimeConfig {\n /** Target latency in milliseconds */\n targetLatencyMs: number;\n /** Maximum acceptable latency in milliseconds */\n maxLatencyMs: number;\n /** Jitter buffer size in milliseconds */\n jitterBufferMs: number;\n /** Message queue size limit */\n maxQueueSize: number;\n /** Drop policy for queue management */\n dropPolicy: DropPolicy;\n /** Enable adaptive bitrate */\n adaptiveBitrate: boolean;\n /** Minimum bitrate in bytes per second */\n minBitrate: number;\n /** Maximum bitrate in bytes per second */\n maxBitrate: number;\n /** Bandwidth measurement window in milliseconds */\n bandwidthWindowMs: number;\n}\n\n/** Default realtime configuration */\nexport const DEFAULT_REALTIME_CONFIG: RealtimeConfig = {\n targetLatencyMs: 50,\n maxLatencyMs: 200,\n jitterBufferMs: 30,\n maxQueueSize: 1000,\n dropPolicy: DropPolicy.DROP_STALE,\n adaptiveBitrate: true,\n minBitrate: 16000, // 16 KB/s\n maxBitrate: 10485760, // 10 MB/s\n bandwidthWindowMs: 1000,\n};\n\n/** Realtime message */\nexport interface RealtimeMessage {\n /** Message ID */\n id: string;\n /** Message priority */\n priority: StreamPriority;\n /** Message timestamp */\n timestamp: number;\n /** Message data */\n data: Uint8Array;\n /** Message type/category */\n type?: string;\n /** Sequence number for ordering */\n sequenceNumber: number;\n /** Whether message is critical (cannot be dropped) */\n critical?: boolean;\n}\n\n/** Bandwidth statistics */\nexport interface BandwidthStats {\n /** Current bitrate in bytes per second */\n currentBitrate: number;\n /** Measured bandwidth in bytes per second */\n measuredBandwidth: number;\n /** Packet loss rate (0-1) */\n packetLossRate: number;\n /** Average latency in milliseconds */\n averageLatencyMs: number;\n /** Jitter in milliseconds */\n jitterMs: number;\n /** Congestion level (0-1) */\n congestionLevel: number;\n}\n\n/** Jitter buffer entry */\ninterface JitterBufferEntry {\n message: RealtimeMessage;\n receivedAt: number;\n playoutTime: number;\n}\n\n/** Realtime stream event handlers */\nexport interface RealtimeStreamHandlers {\n /** Called when a message is received */\n onMessage?: (message: RealtimeMessage) => void | Promise<void>;\n /** Called when messages are dropped */\n onDrop?: (messages: RealtimeMessage[], reason: string) => void;\n /** Called when bandwidth is adapted */\n onBandwidthAdapt?: (newBitrate: number, stats: BandwidthStats) => void;\n /** Called when latency changes */\n onLatencyChange?: (latencyMs: number) => void;\n /** Called when stream is ready to play */\n onReady?: () => void;\n /** Called on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Priority queue for realtime messages\n */\nclass PriorityMessageQueue {\n private queues: Map<StreamPriority, RealtimeMessage[]> = new Map();\n private totalSize = 0;\n private maxSize: number;\n private dropPolicy: DropPolicy;\n private maxLatencyMs: number;\n\n constructor(maxSize: number, dropPolicy: DropPolicy, maxLatencyMs: number) {\n this.maxSize = maxSize;\n this.dropPolicy = dropPolicy;\n this.maxLatencyMs = maxLatencyMs;\n\n // Initialize queues for each priority level\n for (let i = 0; i <= 4; i++) {\n this.queues.set(i as StreamPriority, []);\n }\n }\n\n /** Get total queue size */\n get size(): number {\n return this.totalSize;\n }\n\n /** Check if queue is empty */\n get isEmpty(): boolean {\n return this.totalSize === 0;\n }\n\n /** Enqueue a message */\n enqueue(message: RealtimeMessage): boolean {\n // Check if message is stale\n if (this.dropPolicy === DropPolicy.DROP_STALE) {\n const age = Date.now() - message.timestamp;\n if (age > this.maxLatencyMs && !message.critical) {\n return false; // Message dropped\n }\n }\n\n // Check if queue is full\n if (this.totalSize >= this.maxSize) {\n if (!this.handleQueueFull(message)) {\n return false;\n }\n }\n\n const queue = this.queues.get(message.priority)!;\n queue.push(message);\n this.totalSize++;\n\n return true;\n }\n\n /** Dequeue the highest priority message */\n dequeue(): RealtimeMessage | undefined {\n // Check queues from highest to lowest priority\n for (let priority = 0; priority <= 4; priority++) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0) {\n this.totalSize--;\n return queue.shift()!;\n }\n }\n return undefined;\n }\n\n /** Peek at the highest priority message without removing */\n peek(): RealtimeMessage | undefined {\n for (let priority = 0; priority <= 4; priority++) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0) {\n return queue[0];\n }\n }\n return undefined;\n }\n\n /** Remove stale messages */\n removeStale(): RealtimeMessage[] {\n const now = Date.now();\n const removed: RealtimeMessage[] = [];\n\n for (const [priority, queue] of this.queues) {\n const remaining: RealtimeMessage[] = [];\n for (const msg of queue) {\n if (now - msg.timestamp <= this.maxLatencyMs || msg.critical) {\n remaining.push(msg);\n } else {\n removed.push(msg);\n this.totalSize--;\n }\n }\n this.queues.set(priority, remaining);\n }\n\n return removed;\n }\n\n /** Clear all messages */\n clear(): RealtimeMessage[] {\n const all: RealtimeMessage[] = [];\n for (const queue of this.queues.values()) {\n all.push(...queue);\n }\n for (const queue of this.queues.values()) {\n queue.length = 0;\n }\n this.totalSize = 0;\n return all;\n }\n\n private handleQueueFull(newMessage: RealtimeMessage): boolean {\n switch (this.dropPolicy) {\n case DropPolicy.NEVER:\n return false;\n\n case DropPolicy.DROP_OLDEST:\n // Remove oldest message from lowest priority queue\n for (let priority = 4; priority >= 0; priority--) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0 && priority >= newMessage.priority) {\n queue.shift();\n this.totalSize--;\n return true;\n }\n }\n return false;\n\n case DropPolicy.DROP_NEWEST:\n // Don't add the new message if it's lower priority\n if (newMessage.priority >= StreamPriority.NORMAL) {\n return false;\n }\n return true;\n\n case DropPolicy.DROP_LOW_PRIORITY:\n // Remove a message from lower priority than the new message\n for (let priority = 4; priority > newMessage.priority; priority--) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0) {\n queue.shift();\n this.totalSize--;\n return true;\n }\n }\n return false;\n\n case DropPolicy.DROP_STALE: {\n // Remove stale messages first\n const stale = this.removeStale();\n if (stale.length > 0) {\n return true;\n }\n // Fall through to DROP_OLDEST\n for (let priority = 4; priority >= 0; priority--) {\n const queue = this.queues.get(priority as StreamPriority)!;\n if (queue.length > 0 && priority >= newMessage.priority) {\n queue.shift();\n this.totalSize--;\n return true;\n }\n }\n return false;\n }\n\n default:\n return false;\n }\n }\n}\n\n/**\n * Realtime stream for low-latency communication\n *\n * Manages message prioritization, jitter buffering, and bandwidth adaptation.\n */\nexport class RealtimeStream {\n private stream: Stream;\n private config: RealtimeConfig;\n private handlers: RealtimeStreamHandlers;\n\n // Message queues\n private sendQueue: PriorityMessageQueue;\n private receiveQueue: PriorityMessageQueue;\n\n // Jitter buffer\n private jitterBuffer: JitterBufferEntry[] = [];\n private jitterBufferTargetSize: number;\n\n // Bandwidth adaptation\n private bandwidthStats: BandwidthStats = {\n currentBitrate: 0,\n measuredBandwidth: 0,\n packetLossRate: 0,\n averageLatencyMs: 0,\n jitterMs: 0,\n congestionLevel: 0,\n };\n private bitrateHistory: number[] = [];\n private latencyHistory: number[] = [];\n private lastBandwidthUpdate = 0;\n\n // Sequence numbers\n private nextSendSequence = 0;\n private nextExpectedSequence = 0;\n private receivedSequences: Set<number> = new Set();\n\n // State\n private isRunning = false;\n private sendInterval?: ReturnType<typeof setInterval>;\n private jitterInterval?: ReturnType<typeof setInterval>;\n private bandwidthInterval?: ReturnType<typeof setInterval>;\n\n constructor(\n stream: Stream,\n config: Partial<RealtimeConfig> = {},\n handlers: RealtimeStreamHandlers = {}\n ) {\n this.stream = stream;\n this.config = { ...DEFAULT_REALTIME_CONFIG, ...config };\n this.handlers = handlers;\n\n this.sendQueue = new PriorityMessageQueue(\n this.config.maxQueueSize,\n this.config.dropPolicy,\n this.config.maxLatencyMs\n );\n\n this.receiveQueue = new PriorityMessageQueue(\n this.config.maxQueueSize,\n this.config.dropPolicy,\n this.config.maxLatencyMs\n );\n\n // Calculate jitter buffer target size based on jitter buffer time\n this.jitterBufferTargetSize = Math.ceil(\n this.config.jitterBufferMs / this.config.targetLatencyMs\n );\n\n this.setupStreamHandlers();\n }\n\n /** Get current bandwidth statistics */\n get stats(): BandwidthStats {\n return { ...this.bandwidthStats };\n }\n\n /** Get current send queue size */\n get sendQueueSize(): number {\n return this.sendQueue.size;\n }\n\n /** Get current receive queue size */\n get receiveQueueSize(): number {\n return this.receiveQueue.size;\n }\n\n /** Get jitter buffer size */\n get jitterBufferSize(): number {\n return this.jitterBuffer.length;\n }\n\n /**\n * Start the realtime stream\n */\n start(): void {\n if (this.isRunning) return;\n\n this.isRunning = true;\n\n // Start send loop\n this.sendInterval = setInterval(() => {\n this.processSendQueue();\n }, this.config.targetLatencyMs / 2);\n\n // Start jitter buffer processing\n this.jitterInterval = setInterval(() => {\n this.processJitterBuffer();\n }, this.config.targetLatencyMs / 4);\n\n // Start bandwidth monitoring\n if (this.config.adaptiveBitrate) {\n this.bandwidthInterval = setInterval(() => {\n this.updateBandwidthStats();\n }, this.config.bandwidthWindowMs);\n }\n\n this.handlers.onReady?.();\n }\n\n /**\n * Stop the realtime stream\n */\n stop(): void {\n this.isRunning = false;\n\n if (this.sendInterval) {\n clearInterval(this.sendInterval);\n this.sendInterval = undefined;\n }\n\n if (this.jitterInterval) {\n clearInterval(this.jitterInterval);\n this.jitterInterval = undefined;\n }\n\n if (this.bandwidthInterval) {\n clearInterval(this.bandwidthInterval);\n this.bandwidthInterval = undefined;\n }\n\n // Clear queues\n const dropped = this.sendQueue.clear();\n if (dropped.length > 0) {\n this.handlers.onDrop?.(dropped, 'stream stopped');\n }\n }\n\n /**\n * Send a realtime message\n */\n sendMessage(\n data: Uint8Array,\n priority: StreamPriority = StreamPriority.NORMAL,\n options: { type?: string; critical?: boolean } = {}\n ): boolean {\n if (!this.isRunning) {\n return false;\n }\n\n const message: RealtimeMessage = {\n id: this.generateMessageId(),\n priority,\n timestamp: Date.now(),\n data,\n type: options.type,\n sequenceNumber: this.nextSendSequence++,\n critical: options.critical,\n };\n\n const enqueued = this.sendQueue.enqueue(message);\n\n if (!enqueued) {\n this.handlers.onDrop?.([message], 'queue full');\n return false;\n }\n\n return true;\n }\n\n /**\n * Receive the next message (blocking)\n */\n async receiveMessage(): Promise<RealtimeMessage | undefined> {\n return new Promise((resolve) => {\n const checkQueue = () => {\n const message = this.receiveQueue.dequeue();\n if (message) {\n resolve(message);\n } else if (!this.isRunning) {\n resolve(undefined);\n } else {\n setTimeout(checkQueue, 5);\n }\n };\n checkQueue();\n });\n }\n\n /**\n * Set target bitrate (for manual bitrate control)\n */\n setTargetBitrate(bitrate: number): void {\n this.bandwidthStats.currentBitrate = Math.max(\n this.config.minBitrate,\n Math.min(this.config.maxBitrate, bitrate)\n );\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private setupStreamHandlers(): void {\n // Set up stream data handler\n const originalOnData = (\n this.stream as unknown as { handlers?: { onData?: (chunk: StreamChunk) => void } }\n ).handlers?.onData;\n\n (this.stream as unknown as { handlers: { onData?: (chunk: StreamChunk) => void } }).handlers = {\n ...(this.stream as unknown as { handlers: { onData?: (chunk: StreamChunk) => void } })\n .handlers,\n onData: (chunk: StreamChunk) => {\n this.handleIncomingData(chunk);\n originalOnData?.(chunk);\n },\n };\n }\n\n private handleIncomingData(chunk: StreamChunk): void {\n try {\n // Parse message from chunk\n const message = this.deserializeMessage(chunk.data);\n\n // Track sequence number for packet loss calculation\n if (message.sequenceNumber > this.nextExpectedSequence) {\n // Packet loss detected\n const lost = message.sequenceNumber - this.nextExpectedSequence;\n this.bandwidthStats.packetLossRate = this.bandwidthStats.packetLossRate * 0.9 + lost * 0.1;\n }\n this.nextExpectedSequence = message.sequenceNumber + 1;\n\n // Calculate latency\n const latency = Date.now() - message.timestamp;\n this.latencyHistory.push(latency);\n if (this.latencyHistory.length > 100) {\n this.latencyHistory.shift();\n }\n\n // Add to jitter buffer\n const playoutTime = Date.now() + this.config.jitterBufferMs;\n this.jitterBuffer.push({\n message,\n receivedAt: Date.now(),\n playoutTime,\n });\n\n // Sort jitter buffer by sequence number\n this.jitterBuffer.sort((a, b) => a.message.sequenceNumber - b.message.sequenceNumber);\n } catch (error) {\n this.handlers.onError?.(error as Error);\n }\n }\n\n private processSendQueue(): void {\n if (!this.isRunning || this.sendQueue.isEmpty) {\n return;\n }\n\n // Check bandwidth limit\n if (this.config.adaptiveBitrate) {\n const currentBitrate = this.bandwidthStats.currentBitrate;\n const maxBytesPerInterval = (currentBitrate * this.config.targetLatencyMs) / 1000 / 2;\n\n let bytesSent = 0;\n while (bytesSent < maxBytesPerInterval) {\n const message = this.sendQueue.dequeue();\n if (!message) break;\n\n this.sendMessageToStream(message);\n bytesSent += message.data.length;\n }\n } else {\n // Send one message per interval\n const message = this.sendQueue.dequeue();\n if (message) {\n this.sendMessageToStream(message);\n }\n }\n\n // Remove stale messages from queue\n if (this.config.dropPolicy === DropPolicy.DROP_STALE) {\n const stale = this.sendQueue.removeStale();\n if (stale.length > 0) {\n this.handlers.onDrop?.(stale, 'stale');\n }\n }\n }\n\n private sendMessageToStream(message: RealtimeMessage): void {\n try {\n const data = this.serializeMessage(message);\n this.stream.send(data).catch((err) => {\n this.handlers.onError?.(err);\n });\n\n // Track bitrate\n this.bitrateHistory.push(data.length);\n if (this.bitrateHistory.length > 100) {\n this.bitrateHistory.shift();\n }\n } catch (error) {\n this.handlers.onError?.(error as Error);\n }\n }\n\n private processJitterBuffer(): void {\n if (!this.isRunning || this.jitterBuffer.length === 0) {\n return;\n }\n\n const now = Date.now();\n\n // Process messages that have reached their playout time\n while (this.jitterBuffer.length > 0) {\n const entry = this.jitterBuffer[0];\n\n // Wait until we have enough messages in the buffer\n if (this.jitterBuffer.length < this.jitterBufferTargetSize && entry.playoutTime > now) {\n break;\n }\n\n if (entry.playoutTime <= now) {\n this.jitterBuffer.shift();\n this.receiveQueue.enqueue(entry.message);\n this.handlers.onMessage?.(entry.message);\n } else {\n break;\n }\n }\n\n // Remove stale messages from jitter buffer\n const maxAge = this.config.maxLatencyMs * 2;\n const stale: RealtimeMessage[] = [];\n this.jitterBuffer = this.jitterBuffer.filter((entry) => {\n if (now - entry.receivedAt > maxAge && !entry.message.critical) {\n stale.push(entry.message);\n return false;\n }\n return true;\n });\n\n if (stale.length > 0) {\n this.handlers.onDrop?.(stale, 'jitter buffer stale');\n }\n }\n\n private updateBandwidthStats(): void {\n const now = Date.now();\n const windowMs = this.config.bandwidthWindowMs;\n\n // Calculate measured bandwidth\n if (this.bitrateHistory.length >= 2) {\n const totalBytes = this.bitrateHistory.reduce((a, b) => a + b, 0);\n this.bandwidthStats.measuredBandwidth = (totalBytes / windowMs) * 1000;\n }\n\n // Calculate average latency\n if (this.latencyHistory.length > 0) {\n const avgLatency =\n this.latencyHistory.reduce((a, b) => a + b, 0) / this.latencyHistory.length;\n this.bandwidthStats.averageLatencyMs = avgLatency;\n\n // Calculate jitter (standard deviation of latency)\n const variance =\n this.latencyHistory.reduce((sum, lat) => sum + (lat - avgLatency) ** 2, 0) /\n this.latencyHistory.length;\n this.bandwidthStats.jitterMs = Math.sqrt(variance);\n\n this.handlers.onLatencyChange?.(avgLatency);\n }\n\n // Calculate congestion level\n const queueUtilization = this.sendQueue.size / this.config.maxQueueSize;\n const latencyRatio = this.bandwidthStats.averageLatencyMs / this.config.targetLatencyMs;\n this.bandwidthStats.congestionLevel = Math.min(1, (queueUtilization + latencyRatio) / 2);\n\n // Adapt bitrate\n if (this.config.adaptiveBitrate) {\n this.adaptBitrate();\n }\n\n this.lastBandwidthUpdate = now;\n }\n\n private adaptBitrate(): void {\n const { congestionLevel, packetLossRate } = this.bandwidthStats;\n let newBitrate = this.bandwidthStats.currentBitrate;\n\n if (congestionLevel > 0.7 || packetLossRate > 0.05) {\n // Decrease bitrate\n newBitrate = newBitrate * 0.8;\n } else if (congestionLevel < 0.3 && packetLossRate < 0.01) {\n // Increase bitrate\n newBitrate = newBitrate * 1.05;\n }\n\n // Clamp to min/max\n newBitrate = Math.max(this.config.minBitrate, Math.min(this.config.maxBitrate, newBitrate));\n\n if (newBitrate !== this.bandwidthStats.currentBitrate) {\n this.bandwidthStats.currentBitrate = newBitrate;\n this.handlers.onBandwidthAdapt?.(newBitrate, this.bandwidthStats);\n }\n }\n\n private serializeMessage(message: RealtimeMessage): Uint8Array {\n // Simple serialization: JSON header + binary data\n const header = JSON.stringify({\n id: message.id,\n priority: message.priority,\n timestamp: message.timestamp,\n type: message.type,\n sequenceNumber: message.sequenceNumber,\n critical: message.critical,\n dataLength: message.data.length,\n });\n\n const headerBytes = new TextEncoder().encode(header);\n const headerLength = new Uint8Array(4);\n new DataView(headerLength.buffer).setUint32(0, headerBytes.length, true);\n\n const result = new Uint8Array(4 + headerBytes.length + message.data.length);\n result.set(headerLength, 0);\n result.set(headerBytes, 4);\n result.set(message.data, 4 + headerBytes.length);\n\n return result;\n }\n\n private deserializeMessage(data: Uint8Array): RealtimeMessage {\n const headerLength = new DataView(data.buffer, data.byteOffset, 4).getUint32(0, true);\n const headerBytes = data.slice(4, 4 + headerLength);\n const header = JSON.parse(new TextDecoder().decode(headerBytes));\n\n return {\n id: header.id,\n priority: header.priority,\n timestamp: header.timestamp,\n type: header.type,\n sequenceNumber: header.sequenceNumber,\n critical: header.critical,\n data: data.slice(4 + headerLength, 4 + headerLength + header.dataLength),\n };\n }\n\n private generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n}\n\n/**\n * Realtime stream manager\n */\nexport class RealtimeStreamManager {\n private streams: Map<number, RealtimeStream> = new Map();\n private nextStreamId = 1;\n\n /**\n * Create a new realtime stream\n */\n createStream(\n baseStream: Stream,\n config?: Partial<RealtimeConfig>,\n handlers?: RealtimeStreamHandlers\n ): RealtimeStream {\n const streamId = this.nextStreamId++;\n const stream = new RealtimeStream(baseStream, config, handlers);\n this.streams.set(streamId, stream);\n return stream;\n }\n\n /**\n * Get a stream by ID\n */\n getStream(id: number): RealtimeStream | undefined {\n return this.streams.get(id);\n }\n\n /**\n * Remove a stream\n */\n removeStream(id: number): boolean {\n const stream = this.streams.get(id);\n if (stream) {\n stream.stop();\n this.streams.delete(id);\n return true;\n }\n return false;\n }\n\n /**\n * Get all active streams\n */\n getActiveStreams(): RealtimeStream[] {\n return Array.from(this.streams.values());\n }\n\n /**\n * Stop all streams\n */\n stopAll(): void {\n for (const stream of this.streams.values()) {\n stream.stop();\n }\n this.streams.clear();\n }\n}\n\n/**\n * Create a realtime stream manager\n */\nexport function createRealtimeStreamManager(): RealtimeStreamManager {\n return new RealtimeStreamManager();\n}\n","/**\n * Stream Management - Unified stream lifecycle management\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Manages:\n * - Stream creation and registration\n * - Bidirectional stream support\n * - Stream lifecycle (open, close, error handling)\n * - Stream multiplexing over a single connection\n */\n\nimport {\n type BulkTransfer,\n type BulkTransferConfig,\n BulkTransferManager,\n type BulkTransferMetadata,\n} from './bulk.js';\nimport {\n type RealtimeConfig,\n type RealtimeStream,\n type RealtimeStreamHandlers,\n RealtimeStreamManager,\n} from './realtime.js';\nimport type { RpcConnection } from './rpc-connection.js';\nimport {\n Stream,\n type StreamDirection,\n type StreamOptions,\n StreamPriority,\n type StreamState,\n} from './stream.js';\nimport type { RpcTransport } from './transport.js';\n\n/** Stream type */\nexport enum StreamType {\n /** Standard stream */\n STANDARD = 'standard',\n /** Bulk transfer stream */\n BULK = 'bulk',\n /** Realtime stream */\n REALTIME = 'realtime',\n}\n\n/** Stream info */\nexport interface StreamInfo {\n /** Stream ID */\n id: number;\n /** Stream type */\n type: StreamType;\n /** Stream direction */\n direction: StreamDirection;\n /** Stream priority */\n priority: StreamPriority;\n /** Current state */\n state: StreamState;\n /** Creation timestamp */\n createdAt: number;\n /** Bytes transferred */\n bytesTransferred: number;\n /** Metadata */\n metadata?: Record<string, string>;\n}\n\n/** Stream manager configuration */\nexport interface StreamManagerConfig {\n /** Maximum number of concurrent streams */\n maxStreams: number;\n /** Default stream priority */\n defaultPriority: StreamPriority;\n /** Enable stream multiplexing */\n enableMultiplexing: boolean;\n /** Idle timeout in milliseconds */\n idleTimeoutMs: number;\n}\n\n/** Default stream manager configuration */\nexport const DEFAULT_STREAM_MANAGER_CONFIG: StreamManagerConfig = {\n maxStreams: 100,\n defaultPriority: StreamPriority.NORMAL,\n enableMultiplexing: true,\n idleTimeoutMs: 300000, // 5 minutes\n};\n\n/** Stream creation options */\nexport interface CreateStreamOptions {\n /** Stream type */\n type?: StreamType;\n /** Stream direction */\n direction?: StreamDirection;\n /** Stream priority */\n priority?: StreamPriority;\n /** Stream metadata */\n metadata?: Record<string, string>;\n /** Flow control configuration */\n flowControl?: Partial<import('./stream.js').FlowControlConfig>;\n}\n\n/** Stream manager event handlers */\nexport interface StreamManagerHandlers {\n /** Called when a stream is created */\n onStreamCreate?: (info: StreamInfo) => void;\n /** Called when a stream is opened */\n onStreamOpen?: (info: StreamInfo) => void;\n /** Called when a stream is closed */\n onStreamClose?: (info: StreamInfo) => void;\n /** Called when a stream errors */\n onStreamError?: (info: StreamInfo, error: Error) => void;\n /** Called when stream count changes */\n onStreamCountChange?: (count: number) => void;\n}\n\n/**\n * Stream manager\n *\n * Manages all streams for an RPC connection.\n */\nexport class StreamManager {\n private config: StreamManagerConfig;\n private handlers: StreamManagerHandlers;\n private connection?: RpcConnection;\n private transport?: RpcTransport;\n\n // Stream registries\n private streams: Map<number, Stream> = new Map();\n private streamTypes: Map<number, StreamType> = new Map();\n private streamInfos: Map<number, StreamInfo> = new Map();\n private nextStreamId = 1;\n\n // Sub-managers\n private bulkManager: BulkTransferManager;\n private realtimeManager: RealtimeStreamManager;\n\n // Lifecycle\n private idleTimeout?: ReturnType<typeof setTimeout>;\n private isRunning = false;\n\n constructor(config: Partial<StreamManagerConfig> = {}, handlers: StreamManagerHandlers = {}) {\n this.config = { ...DEFAULT_STREAM_MANAGER_CONFIG, ...config };\n this.handlers = handlers;\n this.bulkManager = new BulkTransferManager();\n this.realtimeManager = new RealtimeStreamManager();\n }\n\n /** Get the number of active streams */\n get streamCount(): number {\n return this.streams.size;\n }\n\n /** Get the maximum number of streams */\n get maxStreams(): number {\n return this.config.maxStreams;\n }\n\n /** Get all stream infos */\n get allStreamInfos(): StreamInfo[] {\n return Array.from(this.streamInfos.values());\n }\n\n /**\n * Attach to an RPC connection\n */\n attach(connection: RpcConnection, transport?: RpcTransport): void {\n this.connection = connection;\n this.transport = transport;\n this.isRunning = true;\n this.resetIdleTimeout();\n }\n\n /**\n * Detach from connection\n */\n detach(): void {\n this.closeAllStreams();\n this.isRunning = false;\n this.connection = undefined;\n this.transport = undefined;\n\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n this.idleTimeout = undefined;\n }\n }\n\n /**\n * Create a new stream\n */\n createStream(options: CreateStreamOptions = {}): Stream {\n if (this.streams.size >= this.config.maxStreams) {\n throw new Error(`Maximum number of streams (${this.config.maxStreams}) reached`);\n }\n\n const streamId = this.nextStreamId++;\n const type = options.type ?? StreamType.STANDARD;\n\n const streamOptions: StreamOptions = {\n streamId,\n direction: options.direction ?? 'bidirectional',\n priority: options.priority ?? this.config.defaultPriority ?? StreamPriority.NORMAL,\n metadata: options.metadata,\n flowControl: options.flowControl,\n };\n\n const stream = new Stream(streamOptions, {\n onOpen: () => {\n this.updateStreamState(streamId, 'open');\n this.handlers.onStreamOpen?.(this.getStreamInfo(streamId)!);\n },\n onClose: () => {\n this.updateStreamState(streamId, 'closed');\n this.handlers.onStreamClose?.(this.getStreamInfo(streamId)!);\n this.removeStream(streamId);\n },\n onError: (error) => {\n this.updateStreamState(streamId, 'error');\n const info = this.getStreamInfo(streamId);\n if (info) {\n this.handlers.onStreamError?.(info, error);\n }\n },\n });\n\n this.streams.set(streamId, stream);\n this.streamTypes.set(streamId, type);\n\n const info: StreamInfo = {\n id: streamId,\n type,\n direction: streamOptions.direction,\n priority: streamOptions.priority ?? StreamPriority.NORMAL,\n state: 'connecting',\n createdAt: Date.now(),\n bytesTransferred: 0,\n metadata: options.metadata,\n };\n this.streamInfos.set(streamId, info);\n\n this.handlers.onStreamCreate?.(info);\n this.handlers.onStreamCountChange?.(this.streams.size);\n\n this.resetIdleTimeout();\n\n return stream;\n }\n\n /**\n * Create a bulk transfer stream\n */\n createBulkStream(\n direction: 'upload' | 'download',\n metadata: BulkTransferMetadata,\n config?: Partial<BulkTransferConfig>,\n handlers?: import('./bulk.js').BulkTransferHandlers\n ): BulkTransfer {\n const _stream = this.createStream({\n type: StreamType.BULK,\n direction: direction === 'upload' ? 'outbound' : 'inbound',\n priority: StreamPriority.NORMAL,\n metadata: metadata.custom,\n });\n\n return this.bulkManager.createTransfer(direction, metadata, config, handlers);\n }\n\n /**\n * Create a realtime stream\n */\n createRealtimeStream(\n config?: Partial<RealtimeConfig>,\n handlers?: RealtimeStreamHandlers\n ): RealtimeStream {\n const stream = this.createStream({\n type: StreamType.REALTIME,\n direction: 'bidirectional',\n priority: StreamPriority.HIGH,\n });\n\n return this.realtimeManager.createStream(stream, config, handlers);\n }\n\n /**\n * Get a stream by ID\n */\n getStream(id: number): Stream | undefined {\n return this.streams.get(id);\n }\n\n /**\n * Get stream info by ID\n */\n getStreamInfo(id: number): StreamInfo | undefined {\n return this.streamInfos.get(id);\n }\n\n /**\n * Get stream type by ID\n */\n getStreamType(id: number): StreamType | undefined {\n return this.streamTypes.get(id);\n }\n\n /**\n * Get bulk transfer by ID\n */\n getBulkTransfer(id: string): BulkTransfer | undefined {\n return this.bulkManager.getTransfer(id);\n }\n\n /**\n * Get realtime stream by ID\n */\n getRealtimeStream(id: number): RealtimeStream | undefined {\n return this.realtimeManager.getStream(id);\n }\n\n /**\n * Close a specific stream\n */\n async closeStream(id: number): Promise<boolean> {\n const stream = this.streams.get(id);\n if (!stream) {\n return false;\n }\n\n await stream.close();\n this.removeStream(id);\n return true;\n }\n\n /**\n * Close all streams\n */\n async closeAllStreams(): Promise<void> {\n const closePromises: Promise<void>[] = [];\n\n for (const [_id, stream] of this.streams) {\n closePromises.push(\n stream.close().catch(() => {\n // Ignore errors during bulk close\n })\n );\n }\n\n await Promise.all(closePromises);\n\n this.streams.clear();\n this.streamTypes.clear();\n this.streamInfos.clear();\n this.bulkManager.closeAll();\n this.realtimeManager.stopAll();\n\n this.handlers.onStreamCountChange?.(0);\n }\n\n /**\n * Get streams by type\n */\n getStreamsByType(type: StreamType): StreamInfo[] {\n return this.allStreamInfos.filter((info) => info.type === type);\n }\n\n /**\n * Get streams by state\n */\n getStreamsByState(state: StreamState): StreamInfo[] {\n return this.allStreamInfos.filter((info) => info.state === state);\n }\n\n /**\n * Get statistics\n */\n getStatistics(): {\n totalStreams: number;\n activeStreams: number;\n streamsByType: Record<StreamType, number>;\n streamsByState: Record<StreamState, number>;\n totalBytesTransferred: number;\n } {\n const infos = this.allStreamInfos;\n const active = infos.filter((i) => i.state === 'open');\n\n const byType: Record<StreamType, number> = {\n [StreamType.STANDARD]: 0,\n [StreamType.BULK]: 0,\n [StreamType.REALTIME]: 0,\n };\n\n const byState: Record<StreamState, number> = {\n connecting: 0,\n open: 0,\n closing: 0,\n closed: 0,\n error: 0,\n };\n\n let totalBytes = 0;\n\n for (const info of infos) {\n byType[info.type]++;\n byState[info.state]++;\n totalBytes += info.bytesTransferred;\n }\n\n return {\n totalStreams: infos.length,\n activeStreams: active.length,\n streamsByType: byType,\n streamsByState: byState,\n totalBytesTransferred: totalBytes,\n };\n }\n\n /**\n * Update stream priority\n */\n updatePriority(id: number, priority: StreamPriority): boolean {\n const info = this.streamInfos.get(id);\n if (!info) {\n return false;\n }\n\n info.priority = priority;\n return true;\n }\n\n /**\n * Pause all streams (backpressure)\n */\n pauseAll(): void {\n for (const _stream of this.streams.values()) {\n // Streams don't have a direct pause method, but we can use backpressure\n // This is a simplified implementation\n }\n }\n\n /**\n * Resume all streams\n */\n resumeAll(): void {\n for (const _stream of this.streams.values()) {\n // Resume from backpressure\n }\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private removeStream(id: number): void {\n this.streams.delete(id);\n this.streamTypes.delete(id);\n this.streamInfos.delete(id);\n\n this.handlers.onStreamCountChange?.(this.streams.size);\n this.resetIdleTimeout();\n }\n\n private updateStreamState(id: number, state: StreamState): void {\n const info = this.streamInfos.get(id);\n if (info) {\n info.state = state;\n }\n }\n\n private resetIdleTimeout(): void {\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n }\n\n if (!this.isRunning || this.streams.size > 0) {\n return;\n }\n\n this.idleTimeout = setTimeout(() => {\n if (this.streams.size === 0) {\n // No active streams, could emit an event or take action\n }\n }, this.config.idleTimeoutMs);\n }\n}\n\n/**\n * Create a stream manager\n */\nexport function createStreamManager(\n config?: Partial<StreamManagerConfig>,\n handlers?: StreamManagerHandlers\n): StreamManager {\n return new StreamManager(config, handlers);\n}\n\n// Re-export types\nexport type { Stream, StreamOptions, StreamState, StreamDirection } from './stream.js';\nexport { StreamPriority } from './stream.js';\nexport type {\n BulkTransfer,\n BulkTransferConfig,\n BulkTransferMetadata,\n} from './bulk.js';\nexport { BulkTransferManager } from './bulk.js';\nexport type {\n RealtimeStream,\n RealtimeConfig,\n RealtimeStreamHandlers,\n} from './realtime.js';\nexport { RealtimeStreamManager } from './realtime.js';\n","/**\n * Streaming RpcConnection Extension\n *\n * Phase 5: Flow Control and Realtime Communication\n *\n * Extends RpcConnection with streaming capabilities:\n * - Stream creation and management\n * - Integration with existing Pipeline\n * * Stream capability negotiation\n */\n\nimport type { BulkTransferConfig, BulkTransferHandlers, BulkTransferMetadata } from './bulk.js';\nimport type { RealtimeConfig, RealtimeStreamHandlers } from './realtime.js';\nimport { RpcConnection, type RpcConnectionOptions } from './rpc-connection.js';\nimport type { ExportId, ImportId, RpcMessage } from './rpc-types.js';\nimport {\n type BulkTransfer,\n type CreateStreamOptions,\n type RealtimeStream,\n type Stream,\n StreamManager,\n type StreamManagerConfig,\n type StreamManagerHandlers,\n StreamType,\n} from './stream-manager.js';\nimport type { RpcTransport } from './transport.js';\n\n/** Streaming capability flags */\nexport interface StreamingCapabilities {\n /** Standard streaming supported */\n standardStreams: boolean;\n /** Bulk transfer supported */\n bulkTransfer: boolean;\n /** Realtime streaming supported */\n realtimeStreams: boolean;\n /** Maximum concurrent streams */\n maxConcurrentStreams: number;\n /** Maximum stream window size */\n maxWindowSize: number;\n /** Supported flow control algorithms */\n flowControlAlgorithms: string[];\n}\n\n/** Default streaming capabilities */\nexport const DEFAULT_STREAMING_CAPABILITIES: StreamingCapabilities = {\n standardStreams: true,\n bulkTransfer: true,\n realtimeStreams: true,\n maxConcurrentStreams: 100,\n maxWindowSize: 1048576, // 1MB\n flowControlAlgorithms: ['sliding-window', 'rate-based'],\n};\n\n/** Extended RPC connection options with streaming */\nexport interface StreamingRpcConnectionOptions extends RpcConnectionOptions {\n /** Stream manager configuration */\n streamManagerConfig?: Partial<StreamManagerConfig>;\n /** Stream manager event handlers */\n streamManagerHandlers?: StreamManagerHandlers;\n /** Local streaming capabilities */\n localCapabilities?: Partial<StreamingCapabilities>;\n /** Enable streaming support */\n enableStreaming?: boolean;\n}\n\n/**\n * Extended RPC connection with streaming support\n *\n * This class wraps RpcConnection and adds stream management capabilities.\n * It can be used as a drop-in replacement for RpcConnection.\n */\nexport class StreamingRpcConnection extends RpcConnection {\n private streamManager: StreamManager;\n private localCapabilities: StreamingCapabilities;\n private remoteCapabilities?: StreamingCapabilities;\n private streamingEnabled: boolean;\n\n constructor(transport: RpcTransport, options: StreamingRpcConnectionOptions = {}) {\n super(transport, options);\n\n this.streamingEnabled = options.enableStreaming ?? true;\n this.localCapabilities = { ...DEFAULT_STREAMING_CAPABILITIES, ...options.localCapabilities };\n\n // Create stream manager\n this.streamManager = new StreamManager(\n options.streamManagerConfig,\n options.streamManagerHandlers\n );\n\n // Attach to this connection\n this.streamManager.attach(this, transport);\n\n // Set up capability negotiation if streaming is enabled\n if (this.streamingEnabled) {\n this.negotiateCapabilities();\n }\n }\n\n /** Get the stream manager */\n get streams(): StreamManager {\n return this.streamManager;\n }\n\n /** Get local streaming capabilities */\n get capabilities(): StreamingCapabilities {\n return this.localCapabilities;\n }\n\n /** Get remote streaming capabilities (if negotiated) */\n get remoteStreamingCapabilities(): StreamingCapabilities | undefined {\n return this.remoteCapabilities;\n }\n\n /** Check if streaming is enabled */\n get isStreamingEnabled(): boolean {\n return this.streamingEnabled;\n }\n\n /**\n * Create a new standard stream\n */\n createStream(options?: CreateStreamOptions): Stream {\n this.ensureStreamingEnabled();\n return this.streamManager.createStream(options);\n }\n\n /**\n * Create a bulk transfer stream\n */\n createBulkTransfer(\n direction: 'upload' | 'download',\n metadata: BulkTransferMetadata,\n config?: Partial<BulkTransferConfig>,\n handlers?: BulkTransferHandlers\n ): BulkTransfer {\n this.ensureStreamingEnabled();\n this.ensureCapability('bulkTransfer');\n return this.streamManager.createBulkStream(direction, metadata, config, handlers);\n }\n\n /**\n * Create a realtime stream\n */\n createRealtimeStream(\n config?: Partial<RealtimeConfig>,\n handlers?: RealtimeStreamHandlers\n ): RealtimeStream {\n this.ensureStreamingEnabled();\n this.ensureCapability('realtimeStreams');\n return this.streamManager.createRealtimeStream(config, handlers);\n }\n\n /**\n * Get stream statistics\n */\n getStreamStatistics(): ReturnType<StreamManager['getStatistics']> {\n return this.streamManager.getStatistics();\n }\n\n /**\n * Close all streams gracefully\n */\n async closeAllStreams(): Promise<void> {\n await this.streamManager.closeAllStreams();\n }\n\n /**\n * Override stop to properly clean up streams\n */\n override async stop(): Promise<void> {\n await this.closeAllStreams();\n this.streamManager.detach();\n await super.stop();\n }\n\n // =============================================================================\n // Capability Negotiation\n // =============================================================================\n\n /**\n * Negotiate streaming capabilities with remote peer\n *\n * This would typically be done during bootstrap or connection setup.\n * For now, we assume the remote has the same capabilities.\n */\n private async negotiateCapabilities(): Promise<void> {\n // In a full implementation, this would exchange capability messages\n // with the remote peer during connection setup.\n\n // For now, assume remote has same capabilities\n this.remoteCapabilities = { ...this.localCapabilities };\n\n // TODO: Implement actual capability exchange via RPC\n }\n\n /**\n * Update remote capabilities (called when received from peer)\n */\n setRemoteCapabilities(capabilities: StreamingCapabilities): void {\n this.remoteCapabilities = capabilities;\n }\n\n /**\n * Check if a specific capability is supported by both peers\n */\n isCapabilitySupported(capability: keyof StreamingCapabilities): boolean {\n const localValue = this.localCapabilities[capability];\n const remoteValue = this.remoteCapabilities?.[capability];\n\n // For boolean capabilities, both must be true\n if (typeof localValue === 'boolean' && typeof remoteValue === 'boolean') {\n return localValue && remoteValue;\n }\n\n // For numeric capabilities, use the minimum\n if (typeof localValue === 'number' && typeof remoteValue === 'number') {\n return localValue > 0 && remoteValue > 0;\n }\n\n return false;\n }\n\n // =============================================================================\n // Integration with Pipeline\n // =============================================================================\n\n /**\n * Create a stream for pipeline results\n *\n * This allows large pipeline results to be streamed instead of buffered.\n */\n createPipelineStream(questionId: number, options?: CreateStreamOptions): Stream {\n this.ensureStreamingEnabled();\n\n const stream = this.createStream({\n ...options,\n type: StreamType.STANDARD,\n metadata: {\n ...options?.metadata,\n pipelineQuestionId: questionId.toString(),\n },\n });\n\n return stream;\n }\n\n /**\n * Associate a stream with a capability\n *\n * This enables streaming data to/from a capability.\n */\n associateStreamWithCapability(streamId: number, _importId: ImportId | ExportId): void {\n const stream = this.streamManager.getStream(streamId);\n if (!stream) {\n throw new Error(`Stream ${streamId} not found`);\n }\n\n // Store association (would be used by the RPC layer)\n // This is a simplified implementation\n }\n\n // =============================================================================\n // Private Methods\n // =============================================================================\n\n private ensureStreamingEnabled(): void {\n if (!this.streamingEnabled) {\n throw new Error('Streaming is not enabled on this connection');\n }\n }\n\n private ensureCapability(capability: keyof StreamingCapabilities): void {\n if (!this.isCapabilitySupported(capability)) {\n throw new Error(`Capability '${capability}' is not supported by both peers`);\n }\n }\n}\n\n/**\n * Create a streaming RPC connection\n */\nexport function createStreamingConnection(\n transport: RpcTransport,\n options?: StreamingRpcConnectionOptions\n): StreamingRpcConnection {\n return new StreamingRpcConnection(transport, options);\n}\n\n/**\n * Check if a connection supports streaming\n */\nexport function supportsStreaming(connection: RpcConnection): connection is StreamingRpcConnection {\n return connection instanceof StreamingRpcConnection;\n}\n\n// Re-export types from stream-manager\nexport type {\n StreamManager,\n StreamType,\n CreateStreamOptions,\n StreamManagerConfig,\n StreamManagerHandlers,\n Stream,\n BulkTransfer,\n RealtimeStream,\n};\n","/**\n * Phase 7: Dynamic Schema Reader\n *\n * This module provides runtime reading of Cap'n Proto messages using\n * dynamically loaded schema information. This allows reading messages\n * for types not known at compile time.\n */\n\nimport type { ListReader } from '../core/list.js';\nimport { MessageReader, type StructReader } from '../core/message-reader.js';\nimport { ElementSize } from '../core/pointer.js';\nimport type {\n SchemaField,\n SchemaNode,\n SchemaType,\n SchemaTypeKind,\n SchemaValue,\n} from './schema-types.js';\nimport { SchemaNodeType } from './schema-types.js';\n\n/**\n * Dynamic reader for Cap'n Proto messages\n * Provides runtime field access based on schema information\n */\nexport interface DynamicReader {\n /** Get a field value by name */\n get(fieldName: string): unknown;\n\n /** Check if a field exists */\n has(fieldName: string): boolean;\n\n /** Get all field names */\n getFieldNames(): string[];\n\n /** Get the underlying schema node */\n getSchema(): SchemaNode;\n\n /** Get nested struct reader */\n getStruct(fieldName: string): DynamicReader | undefined;\n\n /** Get list field */\n getList(fieldName: string): unknown[] | undefined;\n\n /** Get the raw StructReader */\n getRawReader(): StructReader;\n}\n\n/**\n * Create a dynamic reader from schema and buffer\n *\n * @param schema - The schema node describing the struct type\n * @param buffer - The Cap'n Proto message buffer\n * @returns A DynamicReader for accessing the message fields\n */\nexport function createDynamicReader(\n schema: SchemaNode,\n buffer: ArrayBuffer | Uint8Array\n): DynamicReader {\n const messageReader = new MessageReader(buffer);\n\n if (!schema.structInfo) {\n throw new Error(`Schema node ${schema.displayName} is not a struct`);\n }\n\n const { dataWordCount, pointerCount } = schema.structInfo;\n const structReader = messageReader.getRoot(dataWordCount, pointerCount);\n\n return new DynamicReaderImpl(schema, structReader, messageReader);\n}\n\n/**\n * Create a dynamic reader from an existing StructReader\n *\n * @param schema - The schema node describing the struct type\n * @param structReader - The StructReader to wrap\n * @param messageReader - The underlying MessageReader\n * @returns A DynamicReader for accessing the message fields\n */\nexport function createDynamicReaderFromStruct(\n schema: SchemaNode,\n structReader: StructReader,\n messageReader: MessageReader\n): DynamicReader {\n return new DynamicReaderImpl(schema, structReader, messageReader);\n}\n\n/**\n * Implementation of DynamicReader\n */\nclass DynamicReaderImpl implements DynamicReader {\n private fieldCache: Map<string, SchemaField>;\n private pointerOffset: number;\n\n constructor(\n private schema: SchemaNode,\n private structReader: StructReader,\n private messageReader: MessageReader\n ) {\n this.fieldCache = new Map();\n this.pointerOffset = schema.structInfo?.dataWordCount ?? 0;\n\n // Build field cache\n if (schema.structInfo?.fields) {\n for (const field of schema.structInfo.fields) {\n this.fieldCache.set(field.name, field);\n }\n }\n }\n\n get(fieldName: string): unknown {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n return this.readFieldValue(field);\n }\n\n has(fieldName: string): boolean {\n return this.fieldCache.has(fieldName);\n }\n\n getFieldNames(): string[] {\n return Array.from(this.fieldCache.keys());\n }\n\n getSchema(): SchemaNode {\n return this.schema;\n }\n\n getStruct(fieldName: string): DynamicReader | undefined {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n return undefined;\n }\n\n // Check if field is a struct type\n if (field.type.kind.type !== 'struct') {\n return undefined;\n }\n\n // Get the nested struct reader\n const pointerIndex = this.getPointerIndex(field);\n const nestedStruct = this.structReader.getStruct(pointerIndex, 0, 0);\n if (!nestedStruct) {\n return undefined;\n }\n\n // Note: We don't have the nested schema here, so we return a limited reader\n // In a full implementation, we'd look up the schema by typeId\n return new DynamicStructReaderWithoutSchema(nestedStruct, this.messageReader);\n }\n\n getList(fieldName: string): unknown[] | undefined {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n return undefined;\n }\n\n if (field.type.kind.type !== 'list') {\n return undefined;\n }\n\n const pointerIndex = this.getPointerIndex(field);\n const elementType = field.type.kind.elementType;\n\n return this.readListField(pointerIndex, elementType);\n }\n\n getRawReader(): StructReader {\n return this.structReader;\n }\n\n /**\n * Read a field value based on its type\n */\n private readFieldValue(field: SchemaField): unknown {\n const kind = field.type.kind;\n\n switch (kind.type) {\n case 'void':\n return undefined;\n case 'bool':\n return this.structReader.getBool(field.offset);\n case 'int8':\n return this.structReader.getInt8(field.offset);\n case 'int16':\n return this.structReader.getInt16(field.offset);\n case 'int32':\n return this.structReader.getInt32(field.offset);\n case 'int64':\n return this.structReader.getInt64(field.offset);\n case 'uint8':\n return this.structReader.getUint8(field.offset);\n case 'uint16':\n return this.structReader.getUint16(field.offset);\n case 'uint32':\n return this.structReader.getUint32(field.offset);\n case 'uint64':\n return this.structReader.getUint64(field.offset);\n case 'float32':\n return this.structReader.getFloat32(field.offset);\n case 'float64':\n return this.structReader.getFloat64(field.offset);\n case 'text':\n return this.readTextField(field);\n case 'data':\n return this.readDataField(field);\n case 'list':\n return this.readListFieldBySchema(field);\n case 'enum':\n return this.readEnumField(field);\n case 'struct':\n return this.readStructField(field);\n case 'interface':\n return this.readInterfaceField(field);\n case 'anyPointer':\n return this.readAnyPointerField(field);\n default:\n throw new Error(`Unsupported field type: ${(kind as SchemaTypeKind).type}`);\n }\n }\n\n /**\n * Get the pointer index for a field\n * In Cap'n Proto, pointer fields have offsets that start from 0 for the first pointer\n * The offset is measured in bits from the start of the data section\n * For pointer fields, offset = dataWordCount * 64 + pointerIndex * 64\n * So pointerIndex = (offset - dataWordCount * 64) / 64\n */\n private getPointerIndex(field: SchemaField): number {\n const dataSectionBits = (this.schema.structInfo?.dataWordCount ?? 0) * 64;\n // Pointer offset is measured from the start of the pointer section\n // Each pointer is 64 bits (1 word)\n const pointerIndex = (field.offset - dataSectionBits) / 64;\n return pointerIndex;\n }\n\n /**\n * Read a text field\n */\n private readTextField(field: SchemaField): string {\n const pointerIndex = this.getPointerIndex(field);\n return this.structReader.getText(pointerIndex);\n }\n\n /**\n * Read a data field\n */\n private readDataField(field: SchemaField): Uint8Array {\n const pointerIndex = this.getPointerIndex(field);\n // Data is stored similarly to text but without null terminator\n // For now, we use the same mechanism\n const text = this.structReader.getText(pointerIndex);\n return new TextEncoder().encode(text);\n }\n\n /**\n * Read a list field using schema information\n */\n private readListFieldBySchema(field: SchemaField): unknown[] {\n if (field.type.kind.type !== 'list') {\n throw new Error(`Field '${field.name}' is not a list type`);\n }\n\n const pointerIndex = this.getPointerIndex(field);\n const elementType = field.type.kind.elementType;\n\n return this.readListField(pointerIndex, elementType);\n }\n\n /**\n * Read a list field\n */\n private readListField(pointerIndex: number, elementType: SchemaType): unknown[] {\n // Map element type to ElementSize\n const elementSize = this.mapTypeToElementSize(elementType);\n\n const listReader = this.structReader.getList<unknown>(pointerIndex, elementSize);\n if (!listReader) {\n return [];\n }\n\n // Convert list reader to array\n const result: unknown[] = [];\n const length = listReader.length;\n\n for (let i = 0; i < length; i++) {\n result.push(this.readListElement(listReader, i, elementType));\n }\n\n return result;\n }\n\n /**\n * Map schema type to ElementSize\n */\n private mapTypeToElementSize(type: SchemaType): ElementSize {\n switch (type.kind.type) {\n case 'void':\n return ElementSize.VOID;\n case 'bool':\n return ElementSize.BIT;\n case 'int8':\n case 'uint8':\n return ElementSize.BYTE;\n case 'int16':\n case 'uint16':\n return ElementSize.TWO_BYTES;\n case 'int32':\n case 'uint32':\n case 'float32':\n return ElementSize.FOUR_BYTES;\n case 'int64':\n case 'uint64':\n case 'float64':\n return ElementSize.EIGHT_BYTES;\n case 'struct':\n return ElementSize.COMPOSITE;\n default:\n return ElementSize.POINTER;\n }\n }\n\n /**\n * Read a single list element\n */\n private readListElement(\n listReader: ListReader<unknown>,\n index: number,\n elementType: SchemaType\n ): unknown {\n const kind = elementType.kind;\n\n switch (kind.type) {\n case 'void':\n return undefined;\n case 'bool':\n return listReader.getPrimitive(index) !== 0;\n case 'int8':\n return listReader.getPrimitive(index);\n case 'int16':\n return listReader.getPrimitive(index);\n case 'int32':\n return listReader.getPrimitive(index);\n case 'int64':\n return listReader.getPrimitive(index);\n case 'uint8':\n return listReader.getPrimitive(index);\n case 'uint16':\n return listReader.getPrimitive(index);\n case 'uint32':\n return listReader.getPrimitive(index);\n case 'uint64':\n return listReader.getPrimitive(index);\n case 'float32':\n return listReader.getPrimitive(index);\n case 'float64':\n return listReader.getPrimitive(index);\n case 'struct': {\n const structReader = listReader.getStruct(index);\n if (!structReader) return undefined;\n // Return a wrapper without full schema\n return new DynamicStructReaderWithoutSchema(structReader, this.messageReader);\n }\n default:\n return undefined;\n }\n }\n\n /**\n * Read an enum field\n */\n private readEnumField(field: SchemaField): number {\n // Enums are stored as uint16\n return this.structReader.getUint16(field.offset);\n }\n\n /**\n * Read a struct field\n */\n private readStructField(field: SchemaField): DynamicReader | undefined {\n const pointerIndex = this.getPointerIndex(field);\n const nestedStruct = this.structReader.getStruct(pointerIndex, 0, 0);\n if (!nestedStruct) {\n return undefined;\n }\n\n // Without the nested schema, we return a limited reader\n return new DynamicStructReaderWithoutSchema(nestedStruct, this.messageReader);\n }\n\n /**\n * Read an interface field (capability)\n */\n private readInterfaceField(_field: SchemaField): unknown {\n // Capabilities are stored in the cap table\n // This would require access to the capability table\n throw new Error('Interface fields not yet supported in dynamic reader');\n }\n\n /**\n * Read an anyPointer field\n */\n private readAnyPointerField(_field: SchemaField): unknown {\n // anyPointer can be any type, requires runtime type detection\n throw new Error('anyPointer fields not yet supported in dynamic reader');\n }\n}\n\n/**\n * A limited dynamic reader for structs without schema information\n * Provides basic field access but no type information\n */\nclass DynamicStructReaderWithoutSchema implements DynamicReader {\n constructor(\n private structReader: StructReader,\n private messageReader: MessageReader\n ) {}\n\n get(_fieldName: string): unknown {\n throw new Error('Cannot access fields without schema information');\n }\n\n has(_fieldName: string): boolean {\n return false;\n }\n\n getFieldNames(): string[] {\n return [];\n }\n\n getSchema(): SchemaNode {\n throw new Error('No schema information available');\n }\n\n getStruct(_fieldName: string): DynamicReader | undefined {\n return undefined;\n }\n\n getList(_fieldName: string): unknown[] | undefined {\n return undefined;\n }\n\n getRawReader(): StructReader {\n return this.structReader;\n }\n}\n\n/**\n * Create a dynamic reader for a specific type ID\n * This looks up the schema in a registry and creates the appropriate reader\n *\n * @param typeId - The type ID of the struct\n * @param buffer - The Cap'n Proto message buffer\n * @param schemaRegistry - A map of type IDs to schema nodes\n * @returns A DynamicReader for the message\n */\nexport function createDynamicReaderByTypeId(\n typeId: bigint,\n buffer: ArrayBuffer | Uint8Array,\n schemaRegistry: Map<bigint, SchemaNode>\n): DynamicReader {\n const schema = schemaRegistry.get(typeId);\n if (!schema) {\n throw new Error(`Schema not found for type ID: ${typeId}`);\n }\n\n if (schema.type !== SchemaNodeType.STRUCT) {\n throw new Error(`Type ${typeId} is not a struct`);\n }\n\n return createDynamicReader(schema, buffer);\n}\n\n/**\n * Utility function to dump all fields from a dynamic reader\n * Useful for debugging and exploration\n *\n * @param reader - The DynamicReader to dump\n * @returns An object with all field names and values\n */\nexport function dumpDynamicReader(reader: DynamicReader): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const fieldName of reader.getFieldNames()) {\n try {\n result[fieldName] = reader.get(fieldName);\n } catch (error) {\n result[fieldName] = `<error: ${error}>`;\n }\n }\n\n return result;\n}\n","/**\n * Phase 7: Dynamic Schema Writer\n *\n * This module provides runtime writing of Cap'n Proto messages using\n * dynamically loaded schema information. This allows writing messages\n * for types not known at compile time.\n */\n\nimport type { ListBuilder } from '../core/list.js';\nimport { MessageBuilder, type StructBuilder } from '../core/message-builder.js';\nimport { ElementSize } from '../core/pointer.js';\nimport type { SchemaField, SchemaNode, SchemaType, SchemaValue } from './schema-types.js';\nimport { SchemaNodeType } from './schema-types.js';\n\n/**\n * Dynamic writer for Cap'n Proto messages\n * Provides runtime field setting based on schema information\n */\nexport interface DynamicWriter {\n /** Set a field value by name */\n set(fieldName: string, value: unknown): void;\n\n /** Set multiple fields at once */\n setFields(fields: Record<string, unknown>): void;\n\n /** Initialize a nested struct field */\n initStruct(fieldName: string): DynamicWriter;\n\n /** Initialize a list field */\n initList(fieldName: string, size: number): DynamicListWriter;\n\n /** Set a text field */\n setText(fieldName: string, value: string): void;\n\n /** Set a data field */\n setData(fieldName: string, value: Uint8Array): void;\n\n /** Get the underlying schema node */\n getSchema(): SchemaNode;\n\n /** Get the raw StructBuilder */\n getRawBuilder(): StructBuilder;\n\n /** Serialize the message to a buffer */\n toBuffer(): ArrayBuffer;\n}\n\n/**\n * Dynamic list writer\n * Provides runtime element setting for list fields\n */\nexport interface DynamicListWriter {\n /** Set an element at the specified index */\n set(index: number, value: unknown): void;\n\n /** Get the list size */\n getSize(): number;\n\n /** Initialize a nested struct element */\n initStruct(index: number): DynamicWriter;\n\n /** Set multiple elements at once */\n setAll(values: unknown[]): void;\n}\n\n/**\n * Create a dynamic writer from schema\n *\n * @param schema - The schema node describing the struct type\n * @returns A DynamicWriter for setting message fields\n */\nexport function createDynamicWriter(schema: SchemaNode): DynamicWriter {\n if (!schema.structInfo) {\n throw new Error(`Schema node ${schema.displayName} is not a struct`);\n }\n\n const { dataWordCount, pointerCount } = schema.structInfo;\n const messageBuilder = new MessageBuilder();\n const structBuilder = messageBuilder.initRoot(dataWordCount, pointerCount);\n\n return new DynamicWriterImpl(schema, structBuilder, messageBuilder);\n}\n\n/**\n * Create a dynamic writer for a nested struct\n *\n * @param schema - The schema node describing the struct type\n * @param structBuilder - The StructBuilder to wrap\n * @param messageBuilder - The underlying MessageBuilder\n * @returns A DynamicWriter for setting message fields\n */\nexport function createNestedDynamicWriter(\n schema: SchemaNode,\n structBuilder: StructBuilder,\n messageBuilder: MessageBuilder\n): DynamicWriter {\n return new DynamicWriterImpl(schema, structBuilder, messageBuilder);\n}\n\n/**\n * Implementation of DynamicWriter\n */\nclass DynamicWriterImpl implements DynamicWriter {\n private fieldCache: Map<string, SchemaField>;\n private pointerOffset: number;\n\n constructor(\n private schema: SchemaNode,\n private structBuilder: StructBuilder,\n private messageBuilder: MessageBuilder\n ) {\n this.fieldCache = new Map();\n this.pointerOffset = schema.structInfo?.dataWordCount ?? 0;\n\n // Build field cache\n if (schema.structInfo?.fields) {\n for (const field of schema.structInfo.fields) {\n this.fieldCache.set(field.name, field);\n }\n }\n }\n\n set(fieldName: string, value: unknown): void {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n this.writeFieldValue(field, value);\n }\n\n setFields(fields: Record<string, unknown>): void {\n for (const [name, value] of Object.entries(fields)) {\n this.set(name, value);\n }\n }\n\n initStruct(fieldName: string): DynamicWriter {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n if (field.type.kind.type !== 'struct') {\n throw new Error(`Field '${fieldName}' is not a struct type`);\n }\n\n // For nested structs, we need the nested schema\n // Since we don't have it here, we'll create a placeholder\n const pointerIndex = this.getPointerIndex(field);\n const nestedBuilder = this.structBuilder.initStruct(pointerIndex, 0, 0);\n\n // Return a writer without schema - limited functionality\n return new DynamicWriterWithoutSchema(nestedBuilder, this.messageBuilder);\n }\n\n initList(fieldName: string, size: number): DynamicListWriter {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n if (field.type.kind.type !== 'list') {\n throw new Error(`Field '${fieldName}' is not a list type`);\n }\n\n const pointerIndex = this.getPointerIndex(field);\n const elementType = field.type.kind.elementType;\n\n return this.createListWriter(pointerIndex, size, elementType);\n }\n\n setText(fieldName: string, value: string): void {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n if (field.type.kind.type !== 'text') {\n throw new Error(`Field '${fieldName}' is not a text type`);\n }\n\n const pointerIndex = this.getPointerIndex(field);\n this.structBuilder.setText(pointerIndex, value);\n }\n\n setData(fieldName: string, value: Uint8Array): void {\n const field = this.fieldCache.get(fieldName);\n if (!field) {\n throw new Error(`Field '${fieldName}' not found in schema ${this.schema.displayName}`);\n }\n\n if (field.type.kind.type !== 'data') {\n throw new Error(`Field '${fieldName}' is not a data type`);\n }\n\n // Data is stored similarly to text but as bytes\n const pointerIndex = this.getPointerIndex(field);\n const textValue = new TextDecoder().decode(value);\n this.structBuilder.setText(pointerIndex, `${textValue}\\0`);\n }\n\n getSchema(): SchemaNode {\n return this.schema;\n }\n\n getRawBuilder(): StructBuilder {\n return this.structBuilder;\n }\n\n toBuffer(): ArrayBuffer {\n return this.messageBuilder.toArrayBuffer();\n }\n\n /**\n * Write a field value based on its type\n */\n private writeFieldValue(field: SchemaField, value: unknown): void {\n const kind = field.type.kind;\n\n switch (kind.type) {\n case 'void':\n // Void fields don't store any data\n break;\n case 'bool':\n this.structBuilder.setBool(field.offset, Boolean(value));\n break;\n case 'int8':\n this.structBuilder.setInt8(field.offset, Number(value));\n break;\n case 'int16':\n this.structBuilder.setInt16(field.offset, Number(value));\n break;\n case 'int32':\n this.structBuilder.setInt32(field.offset, Number(value));\n break;\n case 'int64':\n this.structBuilder.setInt64(field.offset, BigInt(value as string | number | bigint));\n break;\n case 'uint8':\n this.structBuilder.setUint8(field.offset, Number(value));\n break;\n case 'uint16':\n this.structBuilder.setUint16(field.offset, Number(value));\n break;\n case 'uint32':\n this.structBuilder.setUint32(field.offset, Number(value));\n break;\n case 'uint64':\n this.structBuilder.setUint64(field.offset, BigInt(value as string | number | bigint));\n break;\n case 'float32':\n this.structBuilder.setFloat32(field.offset, Number(value));\n break;\n case 'float64':\n this.structBuilder.setFloat64(field.offset, Number(value));\n break;\n case 'text':\n this.setText(field.name, String(value));\n break;\n case 'data':\n if (value instanceof Uint8Array) {\n this.setData(field.name, value);\n } else {\n throw new Error(`Field '${field.name}' expects Uint8Array`);\n }\n break;\n case 'list':\n if (Array.isArray(value)) {\n const listWriter = this.initList(field.name, value.length);\n listWriter.setAll(value);\n } else {\n throw new Error(`Field '${field.name}' expects an array`);\n }\n break;\n case 'enum':\n this.structBuilder.setUint16(field.offset, Number(value));\n break;\n case 'struct':\n if (typeof value === 'object' && value !== null) {\n const structWriter = this.initStruct(field.name);\n // If value is a record, set its fields\n if (!(value instanceof Uint8Array) && !Array.isArray(value)) {\n structWriter.setFields(value as Record<string, unknown>);\n }\n } else {\n throw new Error(`Field '${field.name}' expects an object`);\n }\n break;\n case 'interface':\n throw new Error('Interface fields not yet supported in dynamic writer');\n case 'anyPointer':\n throw new Error('anyPointer fields not yet supported in dynamic writer');\n default:\n throw new Error(`Unsupported field type: ${(kind as { type: string }).type}`);\n }\n }\n\n /**\n * Get the pointer index for a field\n * In Cap'n Proto, pointer fields have offsets that start from 0 for the first pointer\n * The offset is measured in bits from the start of the data section\n * For pointer fields, offset = dataWordCount * 64 + pointerIndex * 64\n * So pointerIndex = (offset - dataWordCount * 64) / 64\n */\n private getPointerIndex(field: SchemaField): number {\n const dataSectionBits = (this.schema.structInfo?.dataWordCount ?? 0) * 64;\n // Pointer offset is measured from the start of the pointer section\n // Each pointer is 64 bits (1 word)\n const pointerIndex = (field.offset - dataSectionBits) / 64;\n return pointerIndex;\n }\n\n /**\n * Create a list writer for a field\n */\n private createListWriter(\n pointerIndex: number,\n size: number,\n elementType: SchemaType\n ): DynamicListWriter {\n // Map element type to ElementSize\n const elementSize = this.mapTypeToElementSize(elementType);\n\n let structSize: { dataWords: number; pointerCount: number } | undefined;\n if (elementSize === ElementSize.COMPOSITE) {\n // For composite types, we need struct size info\n // Default to 0,0 if not available\n structSize = { dataWords: 0, pointerCount: 0 };\n }\n\n const listBuilder = this.structBuilder.initList<unknown>(\n pointerIndex,\n elementSize,\n size,\n structSize\n );\n\n return new DynamicListWriterImpl(listBuilder, elementType, this.messageBuilder);\n }\n\n /**\n * Map schema type to ElementSize\n */\n private mapTypeToElementSize(type: SchemaType): ElementSize {\n switch (type.kind.type) {\n case 'void':\n return ElementSize.VOID;\n case 'bool':\n return ElementSize.BIT;\n case 'int8':\n case 'uint8':\n return ElementSize.BYTE;\n case 'int16':\n case 'uint16':\n return ElementSize.TWO_BYTES;\n case 'int32':\n case 'uint32':\n case 'float32':\n return ElementSize.FOUR_BYTES;\n case 'int64':\n case 'uint64':\n case 'float64':\n return ElementSize.EIGHT_BYTES;\n case 'struct':\n return ElementSize.COMPOSITE;\n default:\n return ElementSize.POINTER;\n }\n }\n}\n\n/**\n * Implementation of DynamicListWriter\n */\nclass DynamicListWriterImpl implements DynamicListWriter {\n constructor(\n private listBuilder: ListBuilder<unknown>,\n private elementType: SchemaType,\n private messageBuilder: MessageBuilder\n ) {}\n\n set(index: number, value: unknown): void {\n if (index < 0 || index >= this.listBuilder.length) {\n throw new Error(`Index ${index} out of bounds`);\n }\n\n const kind = this.elementType.kind;\n\n switch (kind.type) {\n case 'void':\n // Nothing to set for void\n break;\n case 'bool':\n this.listBuilder.setPrimitive(index, value ? 1 : 0);\n break;\n case 'int8':\n case 'uint8':\n case 'int16':\n case 'uint16':\n case 'int32':\n case 'uint32':\n case 'float32':\n this.listBuilder.setPrimitive(index, Number(value));\n break;\n case 'int64':\n case 'uint64':\n case 'float64':\n this.listBuilder.setPrimitive(index, BigInt(value as string | number | bigint));\n break;\n case 'struct':\n // For struct lists, value should be an object to set fields\n if (typeof value === 'object' && value !== null && !(value instanceof Uint8Array)) {\n const structWriter = this.initStruct(index);\n structWriter.setFields(value as Record<string, unknown>);\n }\n break;\n default:\n throw new Error(`Unsupported list element type: ${kind.type}`);\n }\n }\n\n getSize(): number {\n return this.listBuilder.length;\n }\n\n getLength(): number {\n return this.listBuilder.length;\n }\n\n initStruct(index: number): DynamicWriter {\n const structBuilder = this.listBuilder.getStruct(index);\n return new DynamicWriterWithoutSchema(structBuilder, this.messageBuilder);\n }\n\n setAll(values: unknown[]): void {\n if (values.length > this.getSize()) {\n throw new Error(`Cannot set ${values.length} values in list of size ${this.getSize()}`);\n }\n\n for (let i = 0; i < values.length; i++) {\n this.set(i, values[i]);\n }\n }\n}\n\n/**\n * A limited dynamic writer for structs without full schema information\n * Provides basic field setting but no type validation\n */\nclass DynamicWriterWithoutSchema implements DynamicWriter {\n constructor(\n private structBuilder: StructBuilder,\n private messageBuilder: MessageBuilder\n ) {}\n\n set(fieldName: string, _value: unknown): void {\n // Without schema, we can only support basic operations\n // This is a placeholder that could be extended\n throw new Error(`Cannot set field '${fieldName}' without schema information`);\n }\n\n setFields(_fields: Record<string, unknown>): void {\n throw new Error('Cannot set fields without schema information');\n }\n\n initStruct(_fieldName: string): DynamicWriter {\n throw new Error('Cannot init struct without schema information');\n }\n\n initList(_fieldName: string, _size: number): DynamicListWriter {\n throw new Error('Cannot init list without schema information');\n }\n\n setText(_fieldName: string, _value: string): void {\n throw new Error('Cannot set text without schema information');\n }\n\n setData(_fieldName: string, _value: Uint8Array): void {\n throw new Error('Cannot set data without schema information');\n }\n\n getSchema(): SchemaNode {\n throw new Error('No schema information available');\n }\n\n getRawBuilder(): StructBuilder {\n return this.structBuilder;\n }\n\n toBuffer(): ArrayBuffer {\n return this.messageBuilder.toArrayBuffer();\n }\n}\n\n/**\n * Create a dynamic writer for a specific type ID\n * This looks up the schema in a registry and creates the appropriate writer\n *\n * @param typeId - The type ID of the struct\n * @param schemaRegistry - A map of type IDs to schema nodes\n * @returns A DynamicWriter for the message\n */\nexport function createDynamicWriterByTypeId(\n typeId: bigint,\n schemaRegistry: Map<bigint, SchemaNode>\n): DynamicWriter {\n const schema = schemaRegistry.get(typeId);\n if (!schema) {\n throw new Error(`Schema not found for type ID: ${typeId}`);\n }\n\n if (schema.type !== SchemaNodeType.STRUCT) {\n throw new Error(`Type ${typeId} is not a struct`);\n }\n\n return createDynamicWriter(schema);\n}\n\n/**\n * Utility function to create a message from a plain object\n * Uses schema information to properly serialize the data\n *\n * @param schema - The schema node describing the struct type\n * @param data - The data object to serialize\n * @returns The serialized message buffer\n */\nexport function serializeDynamic(schema: SchemaNode, data: Record<string, unknown>): ArrayBuffer {\n const writer = createDynamicWriter(schema);\n writer.setFields(data);\n return writer.toBuffer();\n}\n\n/**\n * Utility function to create a message from a plain object using type ID\n *\n * @param typeId - The type ID of the struct\n * @param data - The data object to serialize\n * @param schemaRegistry - A map of type IDs to schema nodes\n * @returns The serialized message buffer\n */\nexport function serializeDynamicByTypeId(\n typeId: bigint,\n data: Record<string, unknown>,\n schemaRegistry: Map<bigint, SchemaNode>\n): ArrayBuffer {\n const writer = createDynamicWriterByTypeId(typeId, schemaRegistry);\n writer.setFields(data);\n return writer.toBuffer();\n}\n","/**\n * Phase 7: Schema Capability Implementation\n *\n * Implements the SchemaCapability interface defined in rpc.capnp\n * Provides server-side schema serving and client-side schema fetching\n */\n\nimport type { RpcConnection } from './rpc-connection.js';\nimport { createSchemaRegistry, parseSchemaNodes } from './schema-parser.js';\nimport {\n deserializeSchemaRequest,\n serializeGetSchemaResults,\n serializeListSchemasResults,\n serializeSchemaResponse,\n} from './schema-serializer.js';\nimport type {\n AvailableSchema,\n GetSchemaParams,\n GetSchemaResults,\n ListSchemasResults,\n SchemaNode,\n SchemaPayload,\n SchemaTarget,\n} from './schema-types.js';\nimport { SchemaFormat, SchemaNodeType } from './schema-types.js';\n\n// ============================================================================\n// Schema Capability Server\n// ============================================================================\n\n/**\n * Server-side implementation of the SchemaCapability interface.\n * Provides schema information to remote clients.\n */\nexport class SchemaCapabilityServer {\n private registry: Map<bigint, SchemaNode>;\n private schemasByName: Map<string, SchemaNode>;\n\n /**\n * Create a new SchemaCapabilityServer\n * @param initialSchemas - Optional map of schemas to register initially\n */\n constructor(initialSchemas?: Map<bigint, SchemaNode>) {\n this.registry = new Map(initialSchemas);\n this.schemasByName = new Map();\n\n // Build name index\n for (const schema of this.registry.values()) {\n this.schemasByName.set(schema.displayName, schema);\n }\n }\n\n /**\n * Register a schema node\n * @param node - The schema node to register\n */\n registerSchema(node: SchemaNode): void {\n this.registry.set(node.id, node);\n this.schemasByName.set(node.displayName, node);\n }\n\n /**\n * Unregister a schema by ID\n * @param typeId - The type ID to unregister\n */\n unregisterSchema(typeId: bigint): void {\n const node = this.registry.get(typeId);\n if (node) {\n this.registry.delete(typeId);\n this.schemasByName.delete(node.displayName);\n }\n }\n\n /**\n * Get schema information based on target specification\n * @param params - GetSchemaParams containing target and format\n * @returns GetSchemaResults with the schema payload\n */\n async getSchema(params: GetSchemaParams): Promise<GetSchemaResults> {\n const { target, format = SchemaFormat.BINARY } = params;\n\n let schemaData: Uint8Array;\n let dependencies: Array<{ fileId: bigint; fileName: string; schemaHash?: Uint8Array }> = [];\n\n switch (target.type) {\n case 'byTypeId': {\n const node = this.registry.get(target.typeId);\n if (!node) {\n throw new Error(`Schema not found for type ID: ${target.typeId.toString(16)}`);\n }\n schemaData = this.serializeSchemaNode(node, format);\n dependencies = this.collectDependencies(node);\n break;\n }\n\n case 'byTypeName': {\n const node = this.schemasByName.get(target.typeName);\n if (!node) {\n throw new Error(`Schema not found for type name: ${target.typeName}`);\n }\n schemaData = this.serializeSchemaNode(node, format);\n dependencies = this.collectDependencies(node);\n break;\n }\n\n case 'byFileId': {\n // Get all schemas in a file\n const nodes = this.getSchemasByFileId(target.fileId);\n schemaData = this.serializeSchemaNodes(nodes, format);\n break;\n }\n\n case 'byFileName': {\n // Get all schemas in a file by name\n const nodes = this.getSchemasByFileName(target.fileName);\n schemaData = this.serializeSchemaNodes(nodes, format);\n break;\n }\n\n case 'allSchemas': {\n // Get all schemas\n const nodes = Array.from(this.registry.values());\n schemaData = this.serializeSchemaNodes(nodes, format);\n break;\n }\n\n case 'bootstrapInterface': {\n // Get bootstrap interface schema (if available)\n const bootstrapSchema = this.findBootstrapSchema();\n if (!bootstrapSchema) {\n throw new Error('Bootstrap interface schema not available');\n }\n schemaData = this.serializeSchemaNode(bootstrapSchema, format);\n dependencies = this.collectDependencies(bootstrapSchema);\n break;\n }\n\n default:\n throw new Error(`Unsupported schema target type: ${(target as SchemaTarget).type}`);\n }\n\n return {\n payload: {\n schemaData,\n format,\n dependencies,\n },\n };\n }\n\n /**\n * List all available schemas\n * @returns ListSchemasResults with available schema information\n */\n async listAvailableSchemas(): Promise<ListSchemasResults> {\n const schemas: AvailableSchema[] = [];\n\n for (const node of this.registry.values()) {\n schemas.push({\n typeId: node.id,\n displayName: node.displayName,\n fileId: node.scopeId, // Using scopeId as fileId proxy\n fileName: this.inferFileName(node),\n isInterface: node.type === SchemaNodeType.INTERFACE,\n isStruct: node.type === SchemaNodeType.STRUCT,\n isEnum: node.type === SchemaNodeType.ENUM,\n });\n }\n\n return { schemas };\n }\n\n /**\n * Handle a raw schema request (for RPC integration)\n * @param requestData - The serialized SchemaRequest\n * @returns The serialized SchemaResponse\n */\n handleRequest(requestData: Uint8Array): Uint8Array {\n try {\n const request = deserializeSchemaRequest(requestData);\n\n const _result = this.getSchema({\n target: request.targetSchema,\n });\n\n // Since getSchema is async, we need to handle the promise\n // In a real implementation, this would be properly async\n throw new Error('Async handling not implemented in handleRequest');\n } catch (error) {\n // Return error response\n const errorResponse = {\n answerId: 0,\n result: {\n type: 'exception' as const,\n exception: {\n reason: error instanceof Error ? error.message : 'Unknown error',\n type: 'failed' as const,\n obsoleteIsCallersFault: false,\n obsoleteDurability: 0,\n },\n },\n };\n\n return serializeSchemaResponse(errorResponse);\n }\n }\n\n /**\n * Get the number of registered schemas\n */\n getSchemaCount(): number {\n return this.registry.size;\n }\n\n /**\n * Check if a schema is registered\n */\n hasSchema(typeId: bigint): boolean {\n return this.registry.has(typeId);\n }\n\n // --------------------------------------------------------------------------\n // Private Helper Methods\n // --------------------------------------------------------------------------\n\n private serializeSchemaNode(node: SchemaNode, format: SchemaFormat): Uint8Array {\n switch (format) {\n case SchemaFormat.BINARY:\n return this.serializeToBinary([node]);\n case SchemaFormat.JSON:\n return this.serializeToJson([node]);\n case SchemaFormat.CAPNP:\n return this.serializeToCapnp([node]);\n default:\n throw new Error(`Unsupported schema format: ${format}`);\n }\n }\n\n private serializeSchemaNodes(nodes: SchemaNode[], format: SchemaFormat): Uint8Array {\n switch (format) {\n case SchemaFormat.BINARY:\n return this.serializeToBinary(nodes);\n case SchemaFormat.JSON:\n return this.serializeToJson(nodes);\n case SchemaFormat.CAPNP:\n return this.serializeToCapnp(nodes);\n default:\n throw new Error(`Unsupported schema format: ${format}`);\n }\n }\n\n private serializeToBinary(nodes: SchemaNode[]): Uint8Array {\n // Simplified binary serialization\n // In a full implementation, this would serialize to the actual Cap'n Proto format\n const encoder = new TextEncoder();\n const json = JSON.stringify(nodes, (_key, value) => {\n if (typeof value === 'bigint') {\n return value.toString();\n }\n return value;\n });\n return encoder.encode(json);\n }\n\n private serializeToJson(nodes: SchemaNode[]): Uint8Array {\n const encoder = new TextEncoder();\n const json = JSON.stringify({\n nodes: nodes.map((node) => ({\n id: node.id.toString(),\n displayName: node.displayName,\n displayNamePrefixLength: node.displayNamePrefixLength,\n scopeId: node.scopeId.toString(),\n type: node.type,\n structInfo: node.structInfo,\n enumInfo: node.enumInfo,\n interfaceInfo: node.interfaceInfo,\n })),\n });\n return encoder.encode(json);\n }\n\n private serializeToCapnp(nodes: SchemaNode[]): Uint8Array {\n // Placeholder for actual Cap'n Proto schema language serialization\n // This would generate .capnp source code from the schema nodes\n const lines: string[] = [];\n\n for (const node of nodes) {\n if (node.structInfo) {\n lines.push(`struct ${node.displayName} {`);\n for (const field of node.structInfo.fields) {\n lines.push(` ${field.name} @${field.codeOrder} :${this.typeToCapnp(field.type)};`);\n }\n lines.push('}');\n }\n }\n\n return new TextEncoder().encode(lines.join('\\n'));\n }\n\n private typeToCapnp(type: { kind: { type: string } }): string {\n const kind = type.kind;\n switch (kind.type) {\n case 'void':\n return 'Void';\n case 'bool':\n return 'Bool';\n case 'int8':\n return 'Int8';\n case 'int16':\n return 'Int16';\n case 'int32':\n return 'Int32';\n case 'int64':\n return 'Int64';\n case 'uint8':\n return 'UInt8';\n case 'uint16':\n return 'UInt16';\n case 'uint32':\n return 'UInt32';\n case 'uint64':\n return 'UInt64';\n case 'float32':\n return 'Float32';\n case 'float64':\n return 'Float64';\n case 'text':\n return 'Text';\n case 'data':\n return 'Data';\n case 'list':\n return 'List';\n case 'enum':\n return 'UInt16';\n case 'struct':\n return 'AnyPointer';\n case 'interface':\n return 'Capability';\n default:\n return 'AnyPointer';\n }\n }\n\n private collectDependencies(\n _node: SchemaNode\n ): Array<{ fileId: bigint; fileName: string; schemaHash?: Uint8Array }> {\n // In a full implementation, this would analyze the schema and collect\n // all imported schema dependencies\n return [];\n }\n\n private getSchemasByFileId(fileId: bigint): SchemaNode[] {\n return Array.from(this.registry.values()).filter((node) => node.scopeId === fileId);\n }\n\n private getSchemasByFileName(fileName: string): SchemaNode[] {\n // Infer file name from display name prefix\n return Array.from(this.registry.values()).filter((node) => {\n const inferredFileName = this.inferFileName(node);\n return inferredFileName === fileName || node.displayName.startsWith(fileName);\n });\n }\n\n private inferFileName(node: SchemaNode): string {\n // Infer file name from display name\n // e.g., \"foo.bar.MyStruct\" -> \"foo/bar.capnp\"\n const parts = node.displayName.split('.');\n if (parts.length > 1) {\n return `${parts.slice(0, -1).join('/')}.capnp`;\n }\n return 'unknown.capnp';\n }\n\n private findBootstrapSchema(): SchemaNode | undefined {\n // Look for a schema that might be the bootstrap interface\n // This is a heuristic - in practice, the bootstrap interface would be\n // explicitly registered\n for (const node of this.registry.values()) {\n if (node.type === SchemaNodeType.INTERFACE) {\n return node;\n }\n }\n return undefined;\n }\n}\n\n// ============================================================================\n// Schema Capability Client\n// ============================================================================\n\n/**\n * Client-side implementation for accessing remote SchemaCapability\n */\nexport class SchemaCapabilityClient {\n private connection: RpcConnection;\n\n /**\n * Create a new SchemaCapabilityClient\n * @param connection - The RPC connection to use\n */\n constructor(connection: RpcConnection) {\n this.connection = connection;\n }\n\n /**\n * Fetch schema information from the remote server\n * @param target - The schema target specification\n * @param format - The desired format (defaults to BINARY)\n * @returns The schema node\n */\n async getSchema(\n target: SchemaTarget,\n format: SchemaFormat = SchemaFormat.BINARY\n ): Promise<SchemaNode> {\n // Use the connection's getDynamicSchema method for type ID lookups\n if (target.type === 'byTypeId') {\n return this.connection.getDynamicSchema(target.typeId);\n }\n\n // For other target types, we need to use the schema capability interface\n // This is a simplified implementation\n const _params: GetSchemaParams = { target, format };\n\n // In a full implementation, this would make an RPC call to the schema capability\n // For now, we delegate to the connection's method\n if (target.type === 'byTypeName') {\n return this.connection.getDynamicSchemaByName(target.typeName);\n }\n\n throw new Error(`Schema target type not implemented: ${target.type}`);\n }\n\n /**\n * Fetch schema by type ID\n * @param typeId - The type ID\n * @returns The schema node\n */\n async getSchemaById(typeId: bigint): Promise<SchemaNode> {\n return this.connection.getDynamicSchema(typeId);\n }\n\n /**\n * Fetch schema by type name\n * @param typeName - The fully qualified type name\n * @returns The schema node\n */\n async getSchemaByName(typeName: string): Promise<SchemaNode> {\n return this.connection.getDynamicSchemaByName(typeName);\n }\n\n /**\n * List all available schemas from the remote server\n * @returns Array of available schema information\n */\n async listAvailableSchemas(): Promise<AvailableSchema[]> {\n const schemas = await this.connection.listAvailableSchemas();\n return schemas.map((s) => ({\n typeId: s.typeId,\n displayName: s.displayName,\n fileId: BigInt(0), // Not provided by connection method\n fileName: '', // Not provided by connection method\n isInterface: false, // Not provided by connection method\n isStruct: true,\n isEnum: false,\n }));\n }\n\n /**\n * Fetch multiple schemas at once\n * @param typeIds - Array of type IDs to fetch\n * @returns Map of type ID to schema node\n */\n async getSchemas(typeIds: bigint[]): Promise<Map<bigint, SchemaNode>> {\n const results = new Map<bigint, SchemaNode>();\n\n // Fetch schemas in parallel\n await Promise.all(\n typeIds.map(async (typeId) => {\n try {\n const schema = await this.getSchemaById(typeId);\n results.set(typeId, schema);\n } catch (error) {\n console.warn(`Failed to fetch schema ${typeId.toString(16)}:`, error);\n }\n })\n );\n\n return results;\n }\n\n /**\n * Check if a schema is available on the remote server\n * @param typeId - The type ID to check\n * @returns True if the schema is available\n */\n async hasSchema(typeId: bigint): Promise<boolean> {\n try {\n await this.getSchemaById(typeId);\n return true;\n } catch {\n return false;\n }\n }\n}\n\n// ============================================================================\n// Schema Provider Registration Helper\n// ============================================================================\n\n// Note: RpcConnection.registerSchemaProvider is defined in rpc-connection.ts\n// to avoid circular imports. This file only defines the SchemaCapabilityServer\n// and SchemaCapabilityClient classes.\n","'use strict';\n\nconst BINARY_TYPES = ['nodebuffer', 'arraybuffer', 'fragments'];\nconst hasBlob = typeof Blob !== 'undefined';\n\nif (hasBlob) BINARY_TYPES.push('blob');\n\nmodule.exports = {\n BINARY_TYPES,\n CLOSE_TIMEOUT: 30000,\n EMPTY_BUFFER: Buffer.alloc(0),\n GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',\n hasBlob,\n kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),\n kListener: Symbol('kListener'),\n kStatusCode: Symbol('status-code'),\n kWebSocket: Symbol('websocket'),\n NOOP: () => {}\n};\n","'use strict';\n\nconst { EMPTY_BUFFER } = require('./constants');\n\nconst FastBuffer = Buffer[Symbol.species];\n\n/**\n * Merges an array of buffers into a new buffer.\n *\n * @param {Buffer[]} list The array of buffers to concat\n * @param {Number} totalLength The total length of buffers in the list\n * @return {Buffer} The resulting buffer\n * @public\n */\nfunction concat(list, totalLength) {\n if (list.length === 0) return EMPTY_BUFFER;\n if (list.length === 1) return list[0];\n\n const target = Buffer.allocUnsafe(totalLength);\n let offset = 0;\n\n for (let i = 0; i < list.length; i++) {\n const buf = list[i];\n target.set(buf, offset);\n offset += buf.length;\n }\n\n if (offset < totalLength) {\n return new FastBuffer(target.buffer, target.byteOffset, offset);\n }\n\n return target;\n}\n\n/**\n * Masks a buffer using the given mask.\n *\n * @param {Buffer} source The buffer to mask\n * @param {Buffer} mask The mask to use\n * @param {Buffer} output The buffer where to store the result\n * @param {Number} offset The offset at which to start writing\n * @param {Number} length The number of bytes to mask.\n * @public\n */\nfunction _mask(source, mask, output, offset, length) {\n for (let i = 0; i < length; i++) {\n output[offset + i] = source[i] ^ mask[i & 3];\n }\n}\n\n/**\n * Unmasks a buffer using the given mask.\n *\n * @param {Buffer} buffer The buffer to unmask\n * @param {Buffer} mask The mask to use\n * @public\n */\nfunction _unmask(buffer, mask) {\n for (let i = 0; i < buffer.length; i++) {\n buffer[i] ^= mask[i & 3];\n }\n}\n\n/**\n * Converts a buffer to an `ArrayBuffer`.\n *\n * @param {Buffer} buf The buffer to convert\n * @return {ArrayBuffer} Converted buffer\n * @public\n */\nfunction toArrayBuffer(buf) {\n if (buf.length === buf.buffer.byteLength) {\n return buf.buffer;\n }\n\n return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);\n}\n\n/**\n * Converts `data` to a `Buffer`.\n *\n * @param {*} data The data to convert\n * @return {Buffer} The buffer\n * @throws {TypeError}\n * @public\n */\nfunction toBuffer(data) {\n toBuffer.readOnly = true;\n\n if (Buffer.isBuffer(data)) return data;\n\n let buf;\n\n if (data instanceof ArrayBuffer) {\n buf = new FastBuffer(data);\n } else if (ArrayBuffer.isView(data)) {\n buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);\n } else {\n buf = Buffer.from(data);\n toBuffer.readOnly = false;\n }\n\n return buf;\n}\n\nmodule.exports = {\n concat,\n mask: _mask,\n toArrayBuffer,\n toBuffer,\n unmask: _unmask\n};\n\n/* istanbul ignore else */\nif (!process.env.WS_NO_BUFFER_UTIL) {\n try {\n const bufferUtil = require('bufferutil');\n\n module.exports.mask = function (source, mask, output, offset, length) {\n if (length < 48) _mask(source, mask, output, offset, length);\n else bufferUtil.mask(source, mask, output, offset, length);\n };\n\n module.exports.unmask = function (buffer, mask) {\n if (buffer.length < 32) _unmask(buffer, mask);\n else bufferUtil.unmask(buffer, mask);\n };\n } catch (e) {\n // Continue regardless of the error.\n }\n}\n","'use strict';\n\nconst kDone = Symbol('kDone');\nconst kRun = Symbol('kRun');\n\n/**\n * A very simple job queue with adjustable concurrency. Adapted from\n * https://github.com/STRML/async-limiter\n */\nclass Limiter {\n /**\n * Creates a new `Limiter`.\n *\n * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed\n * to run concurrently\n */\n constructor(concurrency) {\n this[kDone] = () => {\n this.pending--;\n this[kRun]();\n };\n this.concurrency = concurrency || Infinity;\n this.jobs = [];\n this.pending = 0;\n }\n\n /**\n * Adds a job to the queue.\n *\n * @param {Function} job The job to run\n * @public\n */\n add(job) {\n this.jobs.push(job);\n this[kRun]();\n }\n\n /**\n * Removes a job from the queue and runs it if possible.\n *\n * @private\n */\n [kRun]() {\n if (this.pending === this.concurrency) return;\n\n if (this.jobs.length) {\n const job = this.jobs.shift();\n\n this.pending++;\n job(this[kDone]);\n }\n }\n}\n\nmodule.exports = Limiter;\n","'use strict';\n\nconst zlib = require('zlib');\n\nconst bufferUtil = require('./buffer-util');\nconst Limiter = require('./limiter');\nconst { kStatusCode } = require('./constants');\n\nconst FastBuffer = Buffer[Symbol.species];\nconst TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);\nconst kPerMessageDeflate = Symbol('permessage-deflate');\nconst kTotalLength = Symbol('total-length');\nconst kCallback = Symbol('callback');\nconst kBuffers = Symbol('buffers');\nconst kError = Symbol('error');\n\n//\n// We limit zlib concurrency, which prevents severe memory fragmentation\n// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913\n// and https://github.com/websockets/ws/issues/1202\n//\n// Intentionally global; it's the global thread pool that's an issue.\n//\nlet zlibLimiter;\n\n/**\n * permessage-deflate implementation.\n */\nclass PerMessageDeflate {\n /**\n * Creates a PerMessageDeflate instance.\n *\n * @param {Object} [options] Configuration options\n * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support\n * for, or request, a custom client window size\n * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/\n * acknowledge disabling of client context takeover\n * @param {Number} [options.concurrencyLimit=10] The number of concurrent\n * calls to zlib\n * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the\n * use of a custom server window size\n * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept\n * disabling of server context takeover\n * @param {Number} [options.threshold=1024] Size (in bytes) below which\n * messages should not be compressed if context takeover is disabled\n * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on\n * deflate\n * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on\n * inflate\n * @param {Boolean} [isServer=false] Create the instance in either server or\n * client mode\n * @param {Number} [maxPayload=0] The maximum allowed message length\n */\n constructor(options, isServer, maxPayload) {\n this._maxPayload = maxPayload | 0;\n this._options = options || {};\n this._threshold =\n this._options.threshold !== undefined ? this._options.threshold : 1024;\n this._isServer = !!isServer;\n this._deflate = null;\n this._inflate = null;\n\n this.params = null;\n\n if (!zlibLimiter) {\n const concurrency =\n this._options.concurrencyLimit !== undefined\n ? this._options.concurrencyLimit\n : 10;\n zlibLimiter = new Limiter(concurrency);\n }\n }\n\n /**\n * @type {String}\n */\n static get extensionName() {\n return 'permessage-deflate';\n }\n\n /**\n * Create an extension negotiation offer.\n *\n * @return {Object} Extension parameters\n * @public\n */\n offer() {\n const params = {};\n\n if (this._options.serverNoContextTakeover) {\n params.server_no_context_takeover = true;\n }\n if (this._options.clientNoContextTakeover) {\n params.client_no_context_takeover = true;\n }\n if (this._options.serverMaxWindowBits) {\n params.server_max_window_bits = this._options.serverMaxWindowBits;\n }\n if (this._options.clientMaxWindowBits) {\n params.client_max_window_bits = this._options.clientMaxWindowBits;\n } else if (this._options.clientMaxWindowBits == null) {\n params.client_max_window_bits = true;\n }\n\n return params;\n }\n\n /**\n * Accept an extension negotiation offer/response.\n *\n * @param {Array} configurations The extension negotiation offers/reponse\n * @return {Object} Accepted configuration\n * @public\n */\n accept(configurations) {\n configurations = this.normalizeParams(configurations);\n\n this.params = this._isServer\n ? this.acceptAsServer(configurations)\n : this.acceptAsClient(configurations);\n\n return this.params;\n }\n\n /**\n * Releases all resources used by the extension.\n *\n * @public\n */\n cleanup() {\n if (this._inflate) {\n this._inflate.close();\n this._inflate = null;\n }\n\n if (this._deflate) {\n const callback = this._deflate[kCallback];\n\n this._deflate.close();\n this._deflate = null;\n\n if (callback) {\n callback(\n new Error(\n 'The deflate stream was closed while data was being processed'\n )\n );\n }\n }\n }\n\n /**\n * Accept an extension negotiation offer.\n *\n * @param {Array} offers The extension negotiation offers\n * @return {Object} Accepted configuration\n * @private\n */\n acceptAsServer(offers) {\n const opts = this._options;\n const accepted = offers.find((params) => {\n if (\n (opts.serverNoContextTakeover === false &&\n params.server_no_context_takeover) ||\n (params.server_max_window_bits &&\n (opts.serverMaxWindowBits === false ||\n (typeof opts.serverMaxWindowBits === 'number' &&\n opts.serverMaxWindowBits > params.server_max_window_bits))) ||\n (typeof opts.clientMaxWindowBits === 'number' &&\n !params.client_max_window_bits)\n ) {\n return false;\n }\n\n return true;\n });\n\n if (!accepted) {\n throw new Error('None of the extension offers can be accepted');\n }\n\n if (opts.serverNoContextTakeover) {\n accepted.server_no_context_takeover = true;\n }\n if (opts.clientNoContextTakeover) {\n accepted.client_no_context_takeover = true;\n }\n if (typeof opts.serverMaxWindowBits === 'number') {\n accepted.server_max_window_bits = opts.serverMaxWindowBits;\n }\n if (typeof opts.clientMaxWindowBits === 'number') {\n accepted.client_max_window_bits = opts.clientMaxWindowBits;\n } else if (\n accepted.client_max_window_bits === true ||\n opts.clientMaxWindowBits === false\n ) {\n delete accepted.client_max_window_bits;\n }\n\n return accepted;\n }\n\n /**\n * Accept the extension negotiation response.\n *\n * @param {Array} response The extension negotiation response\n * @return {Object} Accepted configuration\n * @private\n */\n acceptAsClient(response) {\n const params = response[0];\n\n if (\n this._options.clientNoContextTakeover === false &&\n params.client_no_context_takeover\n ) {\n throw new Error('Unexpected parameter \"client_no_context_takeover\"');\n }\n\n if (!params.client_max_window_bits) {\n if (typeof this._options.clientMaxWindowBits === 'number') {\n params.client_max_window_bits = this._options.clientMaxWindowBits;\n }\n } else if (\n this._options.clientMaxWindowBits === false ||\n (typeof this._options.clientMaxWindowBits === 'number' &&\n params.client_max_window_bits > this._options.clientMaxWindowBits)\n ) {\n throw new Error(\n 'Unexpected or invalid parameter \"client_max_window_bits\"'\n );\n }\n\n return params;\n }\n\n /**\n * Normalize parameters.\n *\n * @param {Array} configurations The extension negotiation offers/reponse\n * @return {Array} The offers/response with normalized parameters\n * @private\n */\n normalizeParams(configurations) {\n configurations.forEach((params) => {\n Object.keys(params).forEach((key) => {\n let value = params[key];\n\n if (value.length > 1) {\n throw new Error(`Parameter \"${key}\" must have only a single value`);\n }\n\n value = value[0];\n\n if (key === 'client_max_window_bits') {\n if (value !== true) {\n const num = +value;\n if (!Number.isInteger(num) || num < 8 || num > 15) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n value = num;\n } else if (!this._isServer) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n } else if (key === 'server_max_window_bits') {\n const num = +value;\n if (!Number.isInteger(num) || num < 8 || num > 15) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n value = num;\n } else if (\n key === 'client_no_context_takeover' ||\n key === 'server_no_context_takeover'\n ) {\n if (value !== true) {\n throw new TypeError(\n `Invalid value for parameter \"${key}\": ${value}`\n );\n }\n } else {\n throw new Error(`Unknown parameter \"${key}\"`);\n }\n\n params[key] = value;\n });\n });\n\n return configurations;\n }\n\n /**\n * Decompress data. Concurrency limited.\n *\n * @param {Buffer} data Compressed data\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @public\n */\n decompress(data, fin, callback) {\n zlibLimiter.add((done) => {\n this._decompress(data, fin, (err, result) => {\n done();\n callback(err, result);\n });\n });\n }\n\n /**\n * Compress data. Concurrency limited.\n *\n * @param {(Buffer|String)} data Data to compress\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @public\n */\n compress(data, fin, callback) {\n zlibLimiter.add((done) => {\n this._compress(data, fin, (err, result) => {\n done();\n callback(err, result);\n });\n });\n }\n\n /**\n * Decompress data.\n *\n * @param {Buffer} data Compressed data\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @private\n */\n _decompress(data, fin, callback) {\n const endpoint = this._isServer ? 'client' : 'server';\n\n if (!this._inflate) {\n const key = `${endpoint}_max_window_bits`;\n const windowBits =\n typeof this.params[key] !== 'number'\n ? zlib.Z_DEFAULT_WINDOWBITS\n : this.params[key];\n\n this._inflate = zlib.createInflateRaw({\n ...this._options.zlibInflateOptions,\n windowBits\n });\n this._inflate[kPerMessageDeflate] = this;\n this._inflate[kTotalLength] = 0;\n this._inflate[kBuffers] = [];\n this._inflate.on('error', inflateOnError);\n this._inflate.on('data', inflateOnData);\n }\n\n this._inflate[kCallback] = callback;\n\n this._inflate.write(data);\n if (fin) this._inflate.write(TRAILER);\n\n this._inflate.flush(() => {\n const err = this._inflate[kError];\n\n if (err) {\n this._inflate.close();\n this._inflate = null;\n callback(err);\n return;\n }\n\n const data = bufferUtil.concat(\n this._inflate[kBuffers],\n this._inflate[kTotalLength]\n );\n\n if (this._inflate._readableState.endEmitted) {\n this._inflate.close();\n this._inflate = null;\n } else {\n this._inflate[kTotalLength] = 0;\n this._inflate[kBuffers] = [];\n\n if (fin && this.params[`${endpoint}_no_context_takeover`]) {\n this._inflate.reset();\n }\n }\n\n callback(null, data);\n });\n }\n\n /**\n * Compress data.\n *\n * @param {(Buffer|String)} data Data to compress\n * @param {Boolean} fin Specifies whether or not this is the last fragment\n * @param {Function} callback Callback\n * @private\n */\n _compress(data, fin, callback) {\n const endpoint = this._isServer ? 'server' : 'client';\n\n if (!this._deflate) {\n const key = `${endpoint}_max_window_bits`;\n const windowBits =\n typeof this.params[key] !== 'number'\n ? zlib.Z_DEFAULT_WINDOWBITS\n : this.params[key];\n\n this._deflate = zlib.createDeflateRaw({\n ...this._options.zlibDeflateOptions,\n windowBits\n });\n\n this._deflate[kTotalLength] = 0;\n this._deflate[kBuffers] = [];\n\n this._deflate.on('data', deflateOnData);\n }\n\n this._deflate[kCallback] = callback;\n\n this._deflate.write(data);\n this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {\n if (!this._deflate) {\n //\n // The deflate stream was closed while data was being processed.\n //\n return;\n }\n\n let data = bufferUtil.concat(\n this._deflate[kBuffers],\n this._deflate[kTotalLength]\n );\n\n if (fin) {\n data = new FastBuffer(data.buffer, data.byteOffset, data.length - 4);\n }\n\n //\n // Ensure that the callback will not be called again in\n // `PerMessageDeflate#cleanup()`.\n //\n this._deflate[kCallback] = null;\n\n this._deflate[kTotalLength] = 0;\n this._deflate[kBuffers] = [];\n\n if (fin && this.params[`${endpoint}_no_context_takeover`]) {\n this._deflate.reset();\n }\n\n callback(null, data);\n });\n }\n}\n\nmodule.exports = PerMessageDeflate;\n\n/**\n * The listener of the `zlib.DeflateRaw` stream `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction deflateOnData(chunk) {\n this[kBuffers].push(chunk);\n this[kTotalLength] += chunk.length;\n}\n\n/**\n * The listener of the `zlib.InflateRaw` stream `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction inflateOnData(chunk) {\n this[kTotalLength] += chunk.length;\n\n if (\n this[kPerMessageDeflate]._maxPayload < 1 ||\n this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload\n ) {\n this[kBuffers].push(chunk);\n return;\n }\n\n this[kError] = new RangeError('Max payload size exceeded');\n this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';\n this[kError][kStatusCode] = 1009;\n this.removeListener('data', inflateOnData);\n\n //\n // The choice to employ `zlib.reset()` over `zlib.close()` is dictated by the\n // fact that in Node.js versions prior to 13.10.0, the callback for\n // `zlib.flush()` is not called if `zlib.close()` is used. Utilizing\n // `zlib.reset()` ensures that either the callback is invoked or an error is\n // emitted.\n //\n this.reset();\n}\n\n/**\n * The listener of the `zlib.InflateRaw` stream `'error'` event.\n *\n * @param {Error} err The emitted error\n * @private\n */\nfunction inflateOnError(err) {\n //\n // There is no need to call `Zlib#close()` as the handle is automatically\n // closed when an error is emitted.\n //\n this[kPerMessageDeflate]._inflate = null;\n\n if (this[kError]) {\n this[kCallback](this[kError]);\n return;\n }\n\n err[kStatusCode] = 1007;\n this[kCallback](err);\n}\n","'use strict';\n\nconst { isUtf8 } = require('buffer');\n\nconst { hasBlob } = require('./constants');\n\n//\n// Allowed token characters:\n//\n// '!', '#', '$', '%', '&', ''', '*', '+', '-',\n// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'\n//\n// tokenChars[32] === 0 // ' '\n// tokenChars[33] === 1 // '!'\n// tokenChars[34] === 0 // '\"'\n// ...\n//\n// prettier-ignore\nconst tokenChars = [\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31\n 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63\n 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111\n 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127\n];\n\n/**\n * Checks if a status code is allowed in a close frame.\n *\n * @param {Number} code The status code\n * @return {Boolean} `true` if the status code is valid, else `false`\n * @public\n */\nfunction isValidStatusCode(code) {\n return (\n (code >= 1000 &&\n code <= 1014 &&\n code !== 1004 &&\n code !== 1005 &&\n code !== 1006) ||\n (code >= 3000 && code <= 4999)\n );\n}\n\n/**\n * Checks if a given buffer contains only correct UTF-8.\n * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by\n * Markus Kuhn.\n *\n * @param {Buffer} buf The buffer to check\n * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`\n * @public\n */\nfunction _isValidUTF8(buf) {\n const len = buf.length;\n let i = 0;\n\n while (i < len) {\n if ((buf[i] & 0x80) === 0) {\n // 0xxxxxxx\n i++;\n } else if ((buf[i] & 0xe0) === 0xc0) {\n // 110xxxxx 10xxxxxx\n if (\n i + 1 === len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i] & 0xfe) === 0xc0 // Overlong\n ) {\n return false;\n }\n\n i += 2;\n } else if ((buf[i] & 0xf0) === 0xe0) {\n // 1110xxxx 10xxxxxx 10xxxxxx\n if (\n i + 2 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong\n (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF)\n ) {\n return false;\n }\n\n i += 3;\n } else if ((buf[i] & 0xf8) === 0xf0) {\n // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n if (\n i + 3 >= len ||\n (buf[i + 1] & 0xc0) !== 0x80 ||\n (buf[i + 2] & 0xc0) !== 0x80 ||\n (buf[i + 3] & 0xc0) !== 0x80 ||\n (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong\n (buf[i] === 0xf4 && buf[i + 1] > 0x8f) ||\n buf[i] > 0xf4 // > U+10FFFF\n ) {\n return false;\n }\n\n i += 4;\n } else {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Determines whether a value is a `Blob`.\n *\n * @param {*} value The value to be tested\n * @return {Boolean} `true` if `value` is a `Blob`, else `false`\n * @private\n */\nfunction isBlob(value) {\n return (\n hasBlob &&\n typeof value === 'object' &&\n typeof value.arrayBuffer === 'function' &&\n typeof value.type === 'string' &&\n typeof value.stream === 'function' &&\n (value[Symbol.toStringTag] === 'Blob' ||\n value[Symbol.toStringTag] === 'File')\n );\n}\n\nmodule.exports = {\n isBlob,\n isValidStatusCode,\n isValidUTF8: _isValidUTF8,\n tokenChars\n};\n\nif (isUtf8) {\n module.exports.isValidUTF8 = function (buf) {\n return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);\n };\n} /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {\n try {\n const isValidUTF8 = require('utf-8-validate');\n\n module.exports.isValidUTF8 = function (buf) {\n return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);\n };\n } catch (e) {\n // Continue regardless of the error.\n }\n}\n","'use strict';\n\nconst { Writable } = require('stream');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst {\n BINARY_TYPES,\n EMPTY_BUFFER,\n kStatusCode,\n kWebSocket\n} = require('./constants');\nconst { concat, toArrayBuffer, unmask } = require('./buffer-util');\nconst { isValidStatusCode, isValidUTF8 } = require('./validation');\n\nconst FastBuffer = Buffer[Symbol.species];\n\nconst GET_INFO = 0;\nconst GET_PAYLOAD_LENGTH_16 = 1;\nconst GET_PAYLOAD_LENGTH_64 = 2;\nconst GET_MASK = 3;\nconst GET_DATA = 4;\nconst INFLATING = 5;\nconst DEFER_EVENT = 6;\n\n/**\n * HyBi Receiver implementation.\n *\n * @extends Writable\n */\nclass Receiver extends Writable {\n /**\n * Creates a Receiver instance.\n *\n * @param {Object} [options] Options object\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {String} [options.binaryType=nodebuffer] The type for binary data\n * @param {Object} [options.extensions] An object containing the negotiated\n * extensions\n * @param {Boolean} [options.isServer=false] Specifies whether to operate in\n * client or server mode\n * @param {Number} [options.maxPayload=0] The maximum allowed message length\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n */\n constructor(options = {}) {\n super();\n\n this._allowSynchronousEvents =\n options.allowSynchronousEvents !== undefined\n ? options.allowSynchronousEvents\n : true;\n this._binaryType = options.binaryType || BINARY_TYPES[0];\n this._extensions = options.extensions || {};\n this._isServer = !!options.isServer;\n this._maxPayload = options.maxPayload | 0;\n this._skipUTF8Validation = !!options.skipUTF8Validation;\n this[kWebSocket] = undefined;\n\n this._bufferedBytes = 0;\n this._buffers = [];\n\n this._compressed = false;\n this._payloadLength = 0;\n this._mask = undefined;\n this._fragmented = 0;\n this._masked = false;\n this._fin = false;\n this._opcode = 0;\n\n this._totalPayloadLength = 0;\n this._messageLength = 0;\n this._fragments = [];\n\n this._errored = false;\n this._loop = false;\n this._state = GET_INFO;\n }\n\n /**\n * Implements `Writable.prototype._write()`.\n *\n * @param {Buffer} chunk The chunk of data to write\n * @param {String} encoding The character encoding of `chunk`\n * @param {Function} cb Callback\n * @private\n */\n _write(chunk, encoding, cb) {\n if (this._opcode === 0x08 && this._state == GET_INFO) return cb();\n\n this._bufferedBytes += chunk.length;\n this._buffers.push(chunk);\n this.startLoop(cb);\n }\n\n /**\n * Consumes `n` bytes from the buffered data.\n *\n * @param {Number} n The number of bytes to consume\n * @return {Buffer} The consumed bytes\n * @private\n */\n consume(n) {\n this._bufferedBytes -= n;\n\n if (n === this._buffers[0].length) return this._buffers.shift();\n\n if (n < this._buffers[0].length) {\n const buf = this._buffers[0];\n this._buffers[0] = new FastBuffer(\n buf.buffer,\n buf.byteOffset + n,\n buf.length - n\n );\n\n return new FastBuffer(buf.buffer, buf.byteOffset, n);\n }\n\n const dst = Buffer.allocUnsafe(n);\n\n do {\n const buf = this._buffers[0];\n const offset = dst.length - n;\n\n if (n >= buf.length) {\n dst.set(this._buffers.shift(), offset);\n } else {\n dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);\n this._buffers[0] = new FastBuffer(\n buf.buffer,\n buf.byteOffset + n,\n buf.length - n\n );\n }\n\n n -= buf.length;\n } while (n > 0);\n\n return dst;\n }\n\n /**\n * Starts the parsing loop.\n *\n * @param {Function} cb Callback\n * @private\n */\n startLoop(cb) {\n this._loop = true;\n\n do {\n switch (this._state) {\n case GET_INFO:\n this.getInfo(cb);\n break;\n case GET_PAYLOAD_LENGTH_16:\n this.getPayloadLength16(cb);\n break;\n case GET_PAYLOAD_LENGTH_64:\n this.getPayloadLength64(cb);\n break;\n case GET_MASK:\n this.getMask();\n break;\n case GET_DATA:\n this.getData(cb);\n break;\n case INFLATING:\n case DEFER_EVENT:\n this._loop = false;\n return;\n }\n } while (this._loop);\n\n if (!this._errored) cb();\n }\n\n /**\n * Reads the first two bytes of a frame.\n *\n * @param {Function} cb Callback\n * @private\n */\n getInfo(cb) {\n if (this._bufferedBytes < 2) {\n this._loop = false;\n return;\n }\n\n const buf = this.consume(2);\n\n if ((buf[0] & 0x30) !== 0x00) {\n const error = this.createError(\n RangeError,\n 'RSV2 and RSV3 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_2_3'\n );\n\n cb(error);\n return;\n }\n\n const compressed = (buf[0] & 0x40) === 0x40;\n\n if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n this._fin = (buf[0] & 0x80) === 0x80;\n this._opcode = buf[0] & 0x0f;\n this._payloadLength = buf[1] & 0x7f;\n\n if (this._opcode === 0x00) {\n if (compressed) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n if (!this._fragmented) {\n const error = this.createError(\n RangeError,\n 'invalid opcode 0',\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n this._opcode = this._fragmented;\n } else if (this._opcode === 0x01 || this._opcode === 0x02) {\n if (this._fragmented) {\n const error = this.createError(\n RangeError,\n `invalid opcode ${this._opcode}`,\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n this._compressed = compressed;\n } else if (this._opcode > 0x07 && this._opcode < 0x0b) {\n if (!this._fin) {\n const error = this.createError(\n RangeError,\n 'FIN must be set',\n true,\n 1002,\n 'WS_ERR_EXPECTED_FIN'\n );\n\n cb(error);\n return;\n }\n\n if (compressed) {\n const error = this.createError(\n RangeError,\n 'RSV1 must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_RSV_1'\n );\n\n cb(error);\n return;\n }\n\n if (\n this._payloadLength > 0x7d ||\n (this._opcode === 0x08 && this._payloadLength === 1)\n ) {\n const error = this.createError(\n RangeError,\n `invalid payload length ${this._payloadLength}`,\n true,\n 1002,\n 'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'\n );\n\n cb(error);\n return;\n }\n } else {\n const error = this.createError(\n RangeError,\n `invalid opcode ${this._opcode}`,\n true,\n 1002,\n 'WS_ERR_INVALID_OPCODE'\n );\n\n cb(error);\n return;\n }\n\n if (!this._fin && !this._fragmented) this._fragmented = this._opcode;\n this._masked = (buf[1] & 0x80) === 0x80;\n\n if (this._isServer) {\n if (!this._masked) {\n const error = this.createError(\n RangeError,\n 'MASK must be set',\n true,\n 1002,\n 'WS_ERR_EXPECTED_MASK'\n );\n\n cb(error);\n return;\n }\n } else if (this._masked) {\n const error = this.createError(\n RangeError,\n 'MASK must be clear',\n true,\n 1002,\n 'WS_ERR_UNEXPECTED_MASK'\n );\n\n cb(error);\n return;\n }\n\n if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;\n else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;\n else this.haveLength(cb);\n }\n\n /**\n * Gets extended payload length (7+16).\n *\n * @param {Function} cb Callback\n * @private\n */\n getPayloadLength16(cb) {\n if (this._bufferedBytes < 2) {\n this._loop = false;\n return;\n }\n\n this._payloadLength = this.consume(2).readUInt16BE(0);\n this.haveLength(cb);\n }\n\n /**\n * Gets extended payload length (7+64).\n *\n * @param {Function} cb Callback\n * @private\n */\n getPayloadLength64(cb) {\n if (this._bufferedBytes < 8) {\n this._loop = false;\n return;\n }\n\n const buf = this.consume(8);\n const num = buf.readUInt32BE(0);\n\n //\n // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned\n // if payload length is greater than this number.\n //\n if (num > Math.pow(2, 53 - 32) - 1) {\n const error = this.createError(\n RangeError,\n 'Unsupported WebSocket frame: payload length > 2^53 - 1',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'\n );\n\n cb(error);\n return;\n }\n\n this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);\n this.haveLength(cb);\n }\n\n /**\n * Payload length has been read.\n *\n * @param {Function} cb Callback\n * @private\n */\n haveLength(cb) {\n if (this._payloadLength && this._opcode < 0x08) {\n this._totalPayloadLength += this._payloadLength;\n if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {\n const error = this.createError(\n RangeError,\n 'Max payload size exceeded',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'\n );\n\n cb(error);\n return;\n }\n }\n\n if (this._masked) this._state = GET_MASK;\n else this._state = GET_DATA;\n }\n\n /**\n * Reads mask bytes.\n *\n * @private\n */\n getMask() {\n if (this._bufferedBytes < 4) {\n this._loop = false;\n return;\n }\n\n this._mask = this.consume(4);\n this._state = GET_DATA;\n }\n\n /**\n * Reads data bytes.\n *\n * @param {Function} cb Callback\n * @private\n */\n getData(cb) {\n let data = EMPTY_BUFFER;\n\n if (this._payloadLength) {\n if (this._bufferedBytes < this._payloadLength) {\n this._loop = false;\n return;\n }\n\n data = this.consume(this._payloadLength);\n\n if (\n this._masked &&\n (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0\n ) {\n unmask(data, this._mask);\n }\n }\n\n if (this._opcode > 0x07) {\n this.controlMessage(data, cb);\n return;\n }\n\n if (this._compressed) {\n this._state = INFLATING;\n this.decompress(data, cb);\n return;\n }\n\n if (data.length) {\n //\n // This message is not compressed so its length is the sum of the payload\n // length of all fragments.\n //\n this._messageLength = this._totalPayloadLength;\n this._fragments.push(data);\n }\n\n this.dataMessage(cb);\n }\n\n /**\n * Decompresses data.\n *\n * @param {Buffer} data Compressed data\n * @param {Function} cb Callback\n * @private\n */\n decompress(data, cb) {\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n\n perMessageDeflate.decompress(data, this._fin, (err, buf) => {\n if (err) return cb(err);\n\n if (buf.length) {\n this._messageLength += buf.length;\n if (this._messageLength > this._maxPayload && this._maxPayload > 0) {\n const error = this.createError(\n RangeError,\n 'Max payload size exceeded',\n false,\n 1009,\n 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'\n );\n\n cb(error);\n return;\n }\n\n this._fragments.push(buf);\n }\n\n this.dataMessage(cb);\n if (this._state === GET_INFO) this.startLoop(cb);\n });\n }\n\n /**\n * Handles a data message.\n *\n * @param {Function} cb Callback\n * @private\n */\n dataMessage(cb) {\n if (!this._fin) {\n this._state = GET_INFO;\n return;\n }\n\n const messageLength = this._messageLength;\n const fragments = this._fragments;\n\n this._totalPayloadLength = 0;\n this._messageLength = 0;\n this._fragmented = 0;\n this._fragments = [];\n\n if (this._opcode === 2) {\n let data;\n\n if (this._binaryType === 'nodebuffer') {\n data = concat(fragments, messageLength);\n } else if (this._binaryType === 'arraybuffer') {\n data = toArrayBuffer(concat(fragments, messageLength));\n } else if (this._binaryType === 'blob') {\n data = new Blob(fragments);\n } else {\n data = fragments;\n }\n\n if (this._allowSynchronousEvents) {\n this.emit('message', data, true);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit('message', data, true);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n } else {\n const buf = concat(fragments, messageLength);\n\n if (!this._skipUTF8Validation && !isValidUTF8(buf)) {\n const error = this.createError(\n Error,\n 'invalid UTF-8 sequence',\n true,\n 1007,\n 'WS_ERR_INVALID_UTF8'\n );\n\n cb(error);\n return;\n }\n\n if (this._state === INFLATING || this._allowSynchronousEvents) {\n this.emit('message', buf, false);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit('message', buf, false);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n }\n }\n\n /**\n * Handles a control message.\n *\n * @param {Buffer} data Data to handle\n * @return {(Error|RangeError|undefined)} A possible error\n * @private\n */\n controlMessage(data, cb) {\n if (this._opcode === 0x08) {\n if (data.length === 0) {\n this._loop = false;\n this.emit('conclude', 1005, EMPTY_BUFFER);\n this.end();\n } else {\n const code = data.readUInt16BE(0);\n\n if (!isValidStatusCode(code)) {\n const error = this.createError(\n RangeError,\n `invalid status code ${code}`,\n true,\n 1002,\n 'WS_ERR_INVALID_CLOSE_CODE'\n );\n\n cb(error);\n return;\n }\n\n const buf = new FastBuffer(\n data.buffer,\n data.byteOffset + 2,\n data.length - 2\n );\n\n if (!this._skipUTF8Validation && !isValidUTF8(buf)) {\n const error = this.createError(\n Error,\n 'invalid UTF-8 sequence',\n true,\n 1007,\n 'WS_ERR_INVALID_UTF8'\n );\n\n cb(error);\n return;\n }\n\n this._loop = false;\n this.emit('conclude', code, buf);\n this.end();\n }\n\n this._state = GET_INFO;\n return;\n }\n\n if (this._allowSynchronousEvents) {\n this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);\n this._state = GET_INFO;\n } else {\n this._state = DEFER_EVENT;\n setImmediate(() => {\n this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);\n this._state = GET_INFO;\n this.startLoop(cb);\n });\n }\n }\n\n /**\n * Builds an error object.\n *\n * @param {function(new:Error|RangeError)} ErrorCtor The error constructor\n * @param {String} message The error message\n * @param {Boolean} prefix Specifies whether or not to add a default prefix to\n * `message`\n * @param {Number} statusCode The status code\n * @param {String} errorCode The exposed error code\n * @return {(Error|RangeError)} The error\n * @private\n */\n createError(ErrorCtor, message, prefix, statusCode, errorCode) {\n this._loop = false;\n this._errored = true;\n\n const err = new ErrorCtor(\n prefix ? `Invalid WebSocket frame: ${message}` : message\n );\n\n Error.captureStackTrace(err, this.createError);\n err.code = errorCode;\n err[kStatusCode] = statusCode;\n return err;\n }\n}\n\nmodule.exports = Receiver;\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex\" }] */\n\n'use strict';\n\nconst { Duplex } = require('stream');\nconst { randomFillSync } = require('crypto');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst { EMPTY_BUFFER, kWebSocket, NOOP } = require('./constants');\nconst { isBlob, isValidStatusCode } = require('./validation');\nconst { mask: applyMask, toBuffer } = require('./buffer-util');\n\nconst kByteLength = Symbol('kByteLength');\nconst maskBuffer = Buffer.alloc(4);\nconst RANDOM_POOL_SIZE = 8 * 1024;\nlet randomPool;\nlet randomPoolPointer = RANDOM_POOL_SIZE;\n\nconst DEFAULT = 0;\nconst DEFLATING = 1;\nconst GET_BLOB_DATA = 2;\n\n/**\n * HyBi Sender implementation.\n */\nclass Sender {\n /**\n * Creates a Sender instance.\n *\n * @param {Duplex} socket The connection socket\n * @param {Object} [extensions] An object containing the negotiated extensions\n * @param {Function} [generateMask] The function used to generate the masking\n * key\n */\n constructor(socket, extensions, generateMask) {\n this._extensions = extensions || {};\n\n if (generateMask) {\n this._generateMask = generateMask;\n this._maskBuffer = Buffer.alloc(4);\n }\n\n this._socket = socket;\n\n this._firstFragment = true;\n this._compress = false;\n\n this._bufferedBytes = 0;\n this._queue = [];\n this._state = DEFAULT;\n this.onerror = NOOP;\n this[kWebSocket] = undefined;\n }\n\n /**\n * Frames a piece of data according to the HyBi WebSocket protocol.\n *\n * @param {(Buffer|String)} data The data to frame\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @return {(Buffer|String)[]} The framed data\n * @public\n */\n static frame(data, options) {\n let mask;\n let merge = false;\n let offset = 2;\n let skipMasking = false;\n\n if (options.mask) {\n mask = options.maskBuffer || maskBuffer;\n\n if (options.generateMask) {\n options.generateMask(mask);\n } else {\n if (randomPoolPointer === RANDOM_POOL_SIZE) {\n /* istanbul ignore else */\n if (randomPool === undefined) {\n //\n // This is lazily initialized because server-sent frames must not\n // be masked so it may never be used.\n //\n randomPool = Buffer.alloc(RANDOM_POOL_SIZE);\n }\n\n randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);\n randomPoolPointer = 0;\n }\n\n mask[0] = randomPool[randomPoolPointer++];\n mask[1] = randomPool[randomPoolPointer++];\n mask[2] = randomPool[randomPoolPointer++];\n mask[3] = randomPool[randomPoolPointer++];\n }\n\n skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;\n offset = 6;\n }\n\n let dataLength;\n\n if (typeof data === 'string') {\n if (\n (!options.mask || skipMasking) &&\n options[kByteLength] !== undefined\n ) {\n dataLength = options[kByteLength];\n } else {\n data = Buffer.from(data);\n dataLength = data.length;\n }\n } else {\n dataLength = data.length;\n merge = options.mask && options.readOnly && !skipMasking;\n }\n\n let payloadLength = dataLength;\n\n if (dataLength >= 65536) {\n offset += 8;\n payloadLength = 127;\n } else if (dataLength > 125) {\n offset += 2;\n payloadLength = 126;\n }\n\n const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);\n\n target[0] = options.fin ? options.opcode | 0x80 : options.opcode;\n if (options.rsv1) target[0] |= 0x40;\n\n target[1] = payloadLength;\n\n if (payloadLength === 126) {\n target.writeUInt16BE(dataLength, 2);\n } else if (payloadLength === 127) {\n target[2] = target[3] = 0;\n target.writeUIntBE(dataLength, 4, 6);\n }\n\n if (!options.mask) return [target, data];\n\n target[1] |= 0x80;\n target[offset - 4] = mask[0];\n target[offset - 3] = mask[1];\n target[offset - 2] = mask[2];\n target[offset - 1] = mask[3];\n\n if (skipMasking) return [target, data];\n\n if (merge) {\n applyMask(data, mask, target, offset, dataLength);\n return [target];\n }\n\n applyMask(data, mask, data, 0, dataLength);\n return [target, data];\n }\n\n /**\n * Sends a close message to the other peer.\n *\n * @param {Number} [code] The status code component of the body\n * @param {(String|Buffer)} [data] The message component of the body\n * @param {Boolean} [mask=false] Specifies whether or not to mask the message\n * @param {Function} [cb] Callback\n * @public\n */\n close(code, data, mask, cb) {\n let buf;\n\n if (code === undefined) {\n buf = EMPTY_BUFFER;\n } else if (typeof code !== 'number' || !isValidStatusCode(code)) {\n throw new TypeError('First argument must be a valid error code number');\n } else if (data === undefined || !data.length) {\n buf = Buffer.allocUnsafe(2);\n buf.writeUInt16BE(code, 0);\n } else {\n const length = Buffer.byteLength(data);\n\n if (length > 123) {\n throw new RangeError('The message must not be greater than 123 bytes');\n }\n\n buf = Buffer.allocUnsafe(2 + length);\n buf.writeUInt16BE(code, 0);\n\n if (typeof data === 'string') {\n buf.write(data, 2);\n } else {\n buf.set(data, 2);\n }\n }\n\n const options = {\n [kByteLength]: buf.length,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x08,\n readOnly: false,\n rsv1: false\n };\n\n if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, buf, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(buf, options), cb);\n }\n }\n\n /**\n * Sends a ping message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Boolean} [mask=false] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback\n * @public\n */\n ping(data, mask, cb) {\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (byteLength > 125) {\n throw new RangeError('The data size must not be greater than 125 bytes');\n }\n\n const options = {\n [kByteLength]: byteLength,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x09,\n readOnly,\n rsv1: false\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, false, options, cb]);\n } else {\n this.getBlobData(data, false, options, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(data, options), cb);\n }\n }\n\n /**\n * Sends a pong message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Boolean} [mask=false] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback\n * @public\n */\n pong(data, mask, cb) {\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (byteLength > 125) {\n throw new RangeError('The data size must not be greater than 125 bytes');\n }\n\n const options = {\n [kByteLength]: byteLength,\n fin: true,\n generateMask: this._generateMask,\n mask,\n maskBuffer: this._maskBuffer,\n opcode: 0x0a,\n readOnly,\n rsv1: false\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, false, options, cb]);\n } else {\n this.getBlobData(data, false, options, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, false, options, cb]);\n } else {\n this.sendFrame(Sender.frame(data, options), cb);\n }\n }\n\n /**\n * Sends a data message to the other peer.\n *\n * @param {*} data The message to send\n * @param {Object} options Options object\n * @param {Boolean} [options.binary=false] Specifies whether `data` is binary\n * or text\n * @param {Boolean} [options.compress=false] Specifies whether or not to\n * compress `data`\n * @param {Boolean} [options.fin=false] Specifies whether the fragment is the\n * last one\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Function} [cb] Callback\n * @public\n */\n send(data, options, cb) {\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n let opcode = options.binary ? 2 : 1;\n let rsv1 = options.compress;\n\n let byteLength;\n let readOnly;\n\n if (typeof data === 'string') {\n byteLength = Buffer.byteLength(data);\n readOnly = false;\n } else if (isBlob(data)) {\n byteLength = data.size;\n readOnly = false;\n } else {\n data = toBuffer(data);\n byteLength = data.length;\n readOnly = toBuffer.readOnly;\n }\n\n if (this._firstFragment) {\n this._firstFragment = false;\n if (\n rsv1 &&\n perMessageDeflate &&\n perMessageDeflate.params[\n perMessageDeflate._isServer\n ? 'server_no_context_takeover'\n : 'client_no_context_takeover'\n ]\n ) {\n rsv1 = byteLength >= perMessageDeflate._threshold;\n }\n this._compress = rsv1;\n } else {\n rsv1 = false;\n opcode = 0;\n }\n\n if (options.fin) this._firstFragment = true;\n\n const opts = {\n [kByteLength]: byteLength,\n fin: options.fin,\n generateMask: this._generateMask,\n mask: options.mask,\n maskBuffer: this._maskBuffer,\n opcode,\n readOnly,\n rsv1\n };\n\n if (isBlob(data)) {\n if (this._state !== DEFAULT) {\n this.enqueue([this.getBlobData, data, this._compress, opts, cb]);\n } else {\n this.getBlobData(data, this._compress, opts, cb);\n }\n } else if (this._state !== DEFAULT) {\n this.enqueue([this.dispatch, data, this._compress, opts, cb]);\n } else {\n this.dispatch(data, this._compress, opts, cb);\n }\n }\n\n /**\n * Gets the contents of a blob as binary data.\n *\n * @param {Blob} blob The blob\n * @param {Boolean} [compress=false] Specifies whether or not to compress\n * the data\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @param {Function} [cb] Callback\n * @private\n */\n getBlobData(blob, compress, options, cb) {\n this._bufferedBytes += options[kByteLength];\n this._state = GET_BLOB_DATA;\n\n blob\n .arrayBuffer()\n .then((arrayBuffer) => {\n if (this._socket.destroyed) {\n const err = new Error(\n 'The socket was closed while the blob was being read'\n );\n\n //\n // `callCallbacks` is called in the next tick to ensure that errors\n // that might be thrown in the callbacks behave like errors thrown\n // outside the promise chain.\n //\n process.nextTick(callCallbacks, this, err, cb);\n return;\n }\n\n this._bufferedBytes -= options[kByteLength];\n const data = toBuffer(arrayBuffer);\n\n if (!compress) {\n this._state = DEFAULT;\n this.sendFrame(Sender.frame(data, options), cb);\n this.dequeue();\n } else {\n this.dispatch(data, compress, options, cb);\n }\n })\n .catch((err) => {\n //\n // `onError` is called in the next tick for the same reason that\n // `callCallbacks` above is.\n //\n process.nextTick(onError, this, err, cb);\n });\n }\n\n /**\n * Dispatches a message.\n *\n * @param {(Buffer|String)} data The message to send\n * @param {Boolean} [compress=false] Specifies whether or not to compress\n * `data`\n * @param {Object} options Options object\n * @param {Boolean} [options.fin=false] Specifies whether or not to set the\n * FIN bit\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Boolean} [options.mask=false] Specifies whether or not to mask\n * `data`\n * @param {Buffer} [options.maskBuffer] The buffer used to store the masking\n * key\n * @param {Number} options.opcode The opcode\n * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be\n * modified\n * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the\n * RSV1 bit\n * @param {Function} [cb] Callback\n * @private\n */\n dispatch(data, compress, options, cb) {\n if (!compress) {\n this.sendFrame(Sender.frame(data, options), cb);\n return;\n }\n\n const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];\n\n this._bufferedBytes += options[kByteLength];\n this._state = DEFLATING;\n perMessageDeflate.compress(data, options.fin, (_, buf) => {\n if (this._socket.destroyed) {\n const err = new Error(\n 'The socket was closed while data was being compressed'\n );\n\n callCallbacks(this, err, cb);\n return;\n }\n\n this._bufferedBytes -= options[kByteLength];\n this._state = DEFAULT;\n options.readOnly = false;\n this.sendFrame(Sender.frame(buf, options), cb);\n this.dequeue();\n });\n }\n\n /**\n * Executes queued send operations.\n *\n * @private\n */\n dequeue() {\n while (this._state === DEFAULT && this._queue.length) {\n const params = this._queue.shift();\n\n this._bufferedBytes -= params[3][kByteLength];\n Reflect.apply(params[0], this, params.slice(1));\n }\n }\n\n /**\n * Enqueues a send operation.\n *\n * @param {Array} params Send operation parameters.\n * @private\n */\n enqueue(params) {\n this._bufferedBytes += params[3][kByteLength];\n this._queue.push(params);\n }\n\n /**\n * Sends a frame.\n *\n * @param {(Buffer | String)[]} list The frame to send\n * @param {Function} [cb] Callback\n * @private\n */\n sendFrame(list, cb) {\n if (list.length === 2) {\n this._socket.cork();\n this._socket.write(list[0]);\n this._socket.write(list[1], cb);\n this._socket.uncork();\n } else {\n this._socket.write(list[0], cb);\n }\n }\n}\n\nmodule.exports = Sender;\n\n/**\n * Calls queued callbacks with an error.\n *\n * @param {Sender} sender The `Sender` instance\n * @param {Error} err The error to call the callbacks with\n * @param {Function} [cb] The first callback\n * @private\n */\nfunction callCallbacks(sender, err, cb) {\n if (typeof cb === 'function') cb(err);\n\n for (let i = 0; i < sender._queue.length; i++) {\n const params = sender._queue[i];\n const callback = params[params.length - 1];\n\n if (typeof callback === 'function') callback(err);\n }\n}\n\n/**\n * Handles a `Sender` error.\n *\n * @param {Sender} sender The `Sender` instance\n * @param {Error} err The error\n * @param {Function} [cb] The first pending callback\n * @private\n */\nfunction onError(sender, err, cb) {\n callCallbacks(sender, err, cb);\n sender.onerror(err);\n}\n","'use strict';\n\nconst { kForOnEventAttribute, kListener } = require('./constants');\n\nconst kCode = Symbol('kCode');\nconst kData = Symbol('kData');\nconst kError = Symbol('kError');\nconst kMessage = Symbol('kMessage');\nconst kReason = Symbol('kReason');\nconst kTarget = Symbol('kTarget');\nconst kType = Symbol('kType');\nconst kWasClean = Symbol('kWasClean');\n\n/**\n * Class representing an event.\n */\nclass Event {\n /**\n * Create a new `Event`.\n *\n * @param {String} type The name of the event\n * @throws {TypeError} If the `type` argument is not specified\n */\n constructor(type) {\n this[kTarget] = null;\n this[kType] = type;\n }\n\n /**\n * @type {*}\n */\n get target() {\n return this[kTarget];\n }\n\n /**\n * @type {String}\n */\n get type() {\n return this[kType];\n }\n}\n\nObject.defineProperty(Event.prototype, 'target', { enumerable: true });\nObject.defineProperty(Event.prototype, 'type', { enumerable: true });\n\n/**\n * Class representing a close event.\n *\n * @extends Event\n */\nclass CloseEvent extends Event {\n /**\n * Create a new `CloseEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {Number} [options.code=0] The status code explaining why the\n * connection was closed\n * @param {String} [options.reason=''] A human-readable string explaining why\n * the connection was closed\n * @param {Boolean} [options.wasClean=false] Indicates whether or not the\n * connection was cleanly closed\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kCode] = options.code === undefined ? 0 : options.code;\n this[kReason] = options.reason === undefined ? '' : options.reason;\n this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;\n }\n\n /**\n * @type {Number}\n */\n get code() {\n return this[kCode];\n }\n\n /**\n * @type {String}\n */\n get reason() {\n return this[kReason];\n }\n\n /**\n * @type {Boolean}\n */\n get wasClean() {\n return this[kWasClean];\n }\n}\n\nObject.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });\nObject.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });\nObject.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });\n\n/**\n * Class representing an error event.\n *\n * @extends Event\n */\nclass ErrorEvent extends Event {\n /**\n * Create a new `ErrorEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {*} [options.error=null] The error that generated this event\n * @param {String} [options.message=''] The error message\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kError] = options.error === undefined ? null : options.error;\n this[kMessage] = options.message === undefined ? '' : options.message;\n }\n\n /**\n * @type {*}\n */\n get error() {\n return this[kError];\n }\n\n /**\n * @type {String}\n */\n get message() {\n return this[kMessage];\n }\n}\n\nObject.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });\nObject.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });\n\n/**\n * Class representing a message event.\n *\n * @extends Event\n */\nclass MessageEvent extends Event {\n /**\n * Create a new `MessageEvent`.\n *\n * @param {String} type The name of the event\n * @param {Object} [options] A dictionary object that allows for setting\n * attributes via object members of the same name\n * @param {*} [options.data=null] The message content\n */\n constructor(type, options = {}) {\n super(type);\n\n this[kData] = options.data === undefined ? null : options.data;\n }\n\n /**\n * @type {*}\n */\n get data() {\n return this[kData];\n }\n}\n\nObject.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });\n\n/**\n * This provides methods for emulating the `EventTarget` interface. It's not\n * meant to be used directly.\n *\n * @mixin\n */\nconst EventTarget = {\n /**\n * Register an event listener.\n *\n * @param {String} type A string representing the event type to listen for\n * @param {(Function|Object)} handler The listener to add\n * @param {Object} [options] An options object specifies characteristics about\n * the event listener\n * @param {Boolean} [options.once=false] A `Boolean` indicating that the\n * listener should be invoked at most once after being added. If `true`,\n * the listener would be automatically removed when invoked.\n * @public\n */\n addEventListener(type, handler, options = {}) {\n for (const listener of this.listeners(type)) {\n if (\n !options[kForOnEventAttribute] &&\n listener[kListener] === handler &&\n !listener[kForOnEventAttribute]\n ) {\n return;\n }\n }\n\n let wrapper;\n\n if (type === 'message') {\n wrapper = function onMessage(data, isBinary) {\n const event = new MessageEvent('message', {\n data: isBinary ? data : data.toString()\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'close') {\n wrapper = function onClose(code, message) {\n const event = new CloseEvent('close', {\n code,\n reason: message.toString(),\n wasClean: this._closeFrameReceived && this._closeFrameSent\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'error') {\n wrapper = function onError(error) {\n const event = new ErrorEvent('error', {\n error,\n message: error.message\n });\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else if (type === 'open') {\n wrapper = function onOpen() {\n const event = new Event('open');\n\n event[kTarget] = this;\n callListener(handler, this, event);\n };\n } else {\n return;\n }\n\n wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];\n wrapper[kListener] = handler;\n\n if (options.once) {\n this.once(type, wrapper);\n } else {\n this.on(type, wrapper);\n }\n },\n\n /**\n * Remove an event listener.\n *\n * @param {String} type A string representing the event type to remove\n * @param {(Function|Object)} handler The listener to remove\n * @public\n */\n removeEventListener(type, handler) {\n for (const listener of this.listeners(type)) {\n if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {\n this.removeListener(type, listener);\n break;\n }\n }\n }\n};\n\nmodule.exports = {\n CloseEvent,\n ErrorEvent,\n Event,\n EventTarget,\n MessageEvent\n};\n\n/**\n * Call an event listener\n *\n * @param {(Function|Object)} listener The listener to call\n * @param {*} thisArg The value to use as `this`` when calling the listener\n * @param {Event} event The event to pass to the listener\n * @private\n */\nfunction callListener(listener, thisArg, event) {\n if (typeof listener === 'object' && listener.handleEvent) {\n listener.handleEvent.call(listener, event);\n } else {\n listener.call(thisArg, event);\n }\n}\n","'use strict';\n\nconst { tokenChars } = require('./validation');\n\n/**\n * Adds an offer to the map of extension offers or a parameter to the map of\n * parameters.\n *\n * @param {Object} dest The map of extension offers or parameters\n * @param {String} name The extension or parameter name\n * @param {(Object|Boolean|String)} elem The extension parameters or the\n * parameter value\n * @private\n */\nfunction push(dest, name, elem) {\n if (dest[name] === undefined) dest[name] = [elem];\n else dest[name].push(elem);\n}\n\n/**\n * Parses the `Sec-WebSocket-Extensions` header into an object.\n *\n * @param {String} header The field value of the header\n * @return {Object} The parsed object\n * @public\n */\nfunction parse(header) {\n const offers = Object.create(null);\n let params = Object.create(null);\n let mustUnescape = false;\n let isEscaping = false;\n let inQuotes = false;\n let extensionName;\n let paramName;\n let start = -1;\n let code = -1;\n let end = -1;\n let i = 0;\n\n for (; i < header.length; i++) {\n code = header.charCodeAt(i);\n\n if (extensionName === undefined) {\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (\n i !== 0 &&\n (code === 0x20 /* ' ' */ || code === 0x09) /* '\\t' */\n ) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n const name = header.slice(start, end);\n if (code === 0x2c) {\n push(offers, name, params);\n params = Object.create(null);\n } else {\n extensionName = name;\n }\n\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else if (paramName === undefined) {\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (code === 0x20 || code === 0x09) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x3b || code === 0x2c) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n push(params, header.slice(start, end), true);\n if (code === 0x2c) {\n push(offers, extensionName, params);\n params = Object.create(null);\n extensionName = undefined;\n }\n\n start = end = -1;\n } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {\n paramName = header.slice(start, i);\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else {\n //\n // The value of a quoted-string after unescaping must conform to the\n // token ABNF, so only token characters are valid.\n // Ref: https://tools.ietf.org/html/rfc6455#section-9.1\n //\n if (isEscaping) {\n if (tokenChars[code] !== 1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n if (start === -1) start = i;\n else if (!mustUnescape) mustUnescape = true;\n isEscaping = false;\n } else if (inQuotes) {\n if (tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (code === 0x22 /* '\"' */ && start !== -1) {\n inQuotes = false;\n end = i;\n } else if (code === 0x5c /* '\\' */) {\n isEscaping = true;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {\n inQuotes = true;\n } else if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (start !== -1 && (code === 0x20 || code === 0x09)) {\n if (end === -1) end = i;\n } else if (code === 0x3b || code === 0x2c) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n let value = header.slice(start, end);\n if (mustUnescape) {\n value = value.replace(/\\\\/g, '');\n mustUnescape = false;\n }\n push(params, paramName, value);\n if (code === 0x2c) {\n push(offers, extensionName, params);\n params = Object.create(null);\n extensionName = undefined;\n }\n\n paramName = undefined;\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n }\n }\n\n if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {\n throw new SyntaxError('Unexpected end of input');\n }\n\n if (end === -1) end = i;\n const token = header.slice(start, end);\n if (extensionName === undefined) {\n push(offers, token, params);\n } else {\n if (paramName === undefined) {\n push(params, token, true);\n } else if (mustUnescape) {\n push(params, paramName, token.replace(/\\\\/g, ''));\n } else {\n push(params, paramName, token);\n }\n push(offers, extensionName, params);\n }\n\n return offers;\n}\n\n/**\n * Builds the `Sec-WebSocket-Extensions` header field value.\n *\n * @param {Object} extensions The map of extensions and parameters to format\n * @return {String} A string representing the given object\n * @public\n */\nfunction format(extensions) {\n return Object.keys(extensions)\n .map((extension) => {\n let configurations = extensions[extension];\n if (!Array.isArray(configurations)) configurations = [configurations];\n return configurations\n .map((params) => {\n return [extension]\n .concat(\n Object.keys(params).map((k) => {\n let values = params[k];\n if (!Array.isArray(values)) values = [values];\n return values\n .map((v) => (v === true ? k : `${k}=${v}`))\n .join('; ');\n })\n )\n .join('; ');\n })\n .join(', ');\n })\n .join(', ');\n}\n\nmodule.exports = { format, parse };\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex|Readable$\", \"caughtErrors\": \"none\" }] */\n\n'use strict';\n\nconst EventEmitter = require('events');\nconst https = require('https');\nconst http = require('http');\nconst net = require('net');\nconst tls = require('tls');\nconst { randomBytes, createHash } = require('crypto');\nconst { Duplex, Readable } = require('stream');\nconst { URL } = require('url');\n\nconst PerMessageDeflate = require('./permessage-deflate');\nconst Receiver = require('./receiver');\nconst Sender = require('./sender');\nconst { isBlob } = require('./validation');\n\nconst {\n BINARY_TYPES,\n CLOSE_TIMEOUT,\n EMPTY_BUFFER,\n GUID,\n kForOnEventAttribute,\n kListener,\n kStatusCode,\n kWebSocket,\n NOOP\n} = require('./constants');\nconst {\n EventTarget: { addEventListener, removeEventListener }\n} = require('./event-target');\nconst { format, parse } = require('./extension');\nconst { toBuffer } = require('./buffer-util');\n\nconst kAborted = Symbol('kAborted');\nconst protocolVersions = [8, 13];\nconst readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];\nconst subprotocolRegex = /^[!#$%&'*+\\-.0-9A-Z^_`|a-z~]+$/;\n\n/**\n * Class representing a WebSocket.\n *\n * @extends EventEmitter\n */\nclass WebSocket extends EventEmitter {\n /**\n * Create a new `WebSocket`.\n *\n * @param {(String|URL)} address The URL to which to connect\n * @param {(String|String[])} [protocols] The subprotocols\n * @param {Object} [options] Connection options\n */\n constructor(address, protocols, options) {\n super();\n\n this._binaryType = BINARY_TYPES[0];\n this._closeCode = 1006;\n this._closeFrameReceived = false;\n this._closeFrameSent = false;\n this._closeMessage = EMPTY_BUFFER;\n this._closeTimer = null;\n this._errorEmitted = false;\n this._extensions = {};\n this._paused = false;\n this._protocol = '';\n this._readyState = WebSocket.CONNECTING;\n this._receiver = null;\n this._sender = null;\n this._socket = null;\n\n if (address !== null) {\n this._bufferedAmount = 0;\n this._isServer = false;\n this._redirects = 0;\n\n if (protocols === undefined) {\n protocols = [];\n } else if (!Array.isArray(protocols)) {\n if (typeof protocols === 'object' && protocols !== null) {\n options = protocols;\n protocols = [];\n } else {\n protocols = [protocols];\n }\n }\n\n initAsClient(this, address, protocols, options);\n } else {\n this._autoPong = options.autoPong;\n this._closeTimeout = options.closeTimeout;\n this._isServer = true;\n }\n }\n\n /**\n * For historical reasons, the custom \"nodebuffer\" type is used by the default\n * instead of \"blob\".\n *\n * @type {String}\n */\n get binaryType() {\n return this._binaryType;\n }\n\n set binaryType(type) {\n if (!BINARY_TYPES.includes(type)) return;\n\n this._binaryType = type;\n\n //\n // Allow to change `binaryType` on the fly.\n //\n if (this._receiver) this._receiver._binaryType = type;\n }\n\n /**\n * @type {Number}\n */\n get bufferedAmount() {\n if (!this._socket) return this._bufferedAmount;\n\n return this._socket._writableState.length + this._sender._bufferedBytes;\n }\n\n /**\n * @type {String}\n */\n get extensions() {\n return Object.keys(this._extensions).join();\n }\n\n /**\n * @type {Boolean}\n */\n get isPaused() {\n return this._paused;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onclose() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onerror() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onopen() {\n return null;\n }\n\n /**\n * @type {Function}\n */\n /* istanbul ignore next */\n get onmessage() {\n return null;\n }\n\n /**\n * @type {String}\n */\n get protocol() {\n return this._protocol;\n }\n\n /**\n * @type {Number}\n */\n get readyState() {\n return this._readyState;\n }\n\n /**\n * @type {String}\n */\n get url() {\n return this._url;\n }\n\n /**\n * Set up the socket and the internal resources.\n *\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Object} options Options object\n * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Number} [options.maxPayload=0] The maximum allowed message size\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @private\n */\n setSocket(socket, head, options) {\n const receiver = new Receiver({\n allowSynchronousEvents: options.allowSynchronousEvents,\n binaryType: this.binaryType,\n extensions: this._extensions,\n isServer: this._isServer,\n maxPayload: options.maxPayload,\n skipUTF8Validation: options.skipUTF8Validation\n });\n\n const sender = new Sender(socket, this._extensions, options.generateMask);\n\n this._receiver = receiver;\n this._sender = sender;\n this._socket = socket;\n\n receiver[kWebSocket] = this;\n sender[kWebSocket] = this;\n socket[kWebSocket] = this;\n\n receiver.on('conclude', receiverOnConclude);\n receiver.on('drain', receiverOnDrain);\n receiver.on('error', receiverOnError);\n receiver.on('message', receiverOnMessage);\n receiver.on('ping', receiverOnPing);\n receiver.on('pong', receiverOnPong);\n\n sender.onerror = senderOnError;\n\n //\n // These methods may not be available if `socket` is just a `Duplex`.\n //\n if (socket.setTimeout) socket.setTimeout(0);\n if (socket.setNoDelay) socket.setNoDelay();\n\n if (head.length > 0) socket.unshift(head);\n\n socket.on('close', socketOnClose);\n socket.on('data', socketOnData);\n socket.on('end', socketOnEnd);\n socket.on('error', socketOnError);\n\n this._readyState = WebSocket.OPEN;\n this.emit('open');\n }\n\n /**\n * Emit the `'close'` event.\n *\n * @private\n */\n emitClose() {\n if (!this._socket) {\n this._readyState = WebSocket.CLOSED;\n this.emit('close', this._closeCode, this._closeMessage);\n return;\n }\n\n if (this._extensions[PerMessageDeflate.extensionName]) {\n this._extensions[PerMessageDeflate.extensionName].cleanup();\n }\n\n this._receiver.removeAllListeners();\n this._readyState = WebSocket.CLOSED;\n this.emit('close', this._closeCode, this._closeMessage);\n }\n\n /**\n * Start a closing handshake.\n *\n * +----------+ +-----------+ +----------+\n * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -\n * | +----------+ +-----------+ +----------+ |\n * +----------+ +-----------+ |\n * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING\n * +----------+ +-----------+ |\n * | | | +---+ |\n * +------------------------+-->|fin| - - - -\n * | +---+ | +---+\n * - - - - -|fin|<---------------------+\n * +---+\n *\n * @param {Number} [code] Status code explaining why the connection is closing\n * @param {(String|Buffer)} [data] The reason why the connection is\n * closing\n * @public\n */\n close(code, data) {\n if (this.readyState === WebSocket.CLOSED) return;\n if (this.readyState === WebSocket.CONNECTING) {\n const msg = 'WebSocket was closed before the connection was established';\n abortHandshake(this, this._req, msg);\n return;\n }\n\n if (this.readyState === WebSocket.CLOSING) {\n if (\n this._closeFrameSent &&\n (this._closeFrameReceived || this._receiver._writableState.errorEmitted)\n ) {\n this._socket.end();\n }\n\n return;\n }\n\n this._readyState = WebSocket.CLOSING;\n this._sender.close(code, data, !this._isServer, (err) => {\n //\n // This error is handled by the `'error'` listener on the socket. We only\n // want to know if the close frame has been sent here.\n //\n if (err) return;\n\n this._closeFrameSent = true;\n\n if (\n this._closeFrameReceived ||\n this._receiver._writableState.errorEmitted\n ) {\n this._socket.end();\n }\n });\n\n setCloseTimer(this);\n }\n\n /**\n * Pause the socket.\n *\n * @public\n */\n pause() {\n if (\n this.readyState === WebSocket.CONNECTING ||\n this.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n this._paused = true;\n this._socket.pause();\n }\n\n /**\n * Send a ping.\n *\n * @param {*} [data] The data to send\n * @param {Boolean} [mask] Indicates whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when the ping is sent\n * @public\n */\n ping(data, mask, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof data === 'function') {\n cb = data;\n data = mask = undefined;\n } else if (typeof mask === 'function') {\n cb = mask;\n mask = undefined;\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n if (mask === undefined) mask = !this._isServer;\n this._sender.ping(data || EMPTY_BUFFER, mask, cb);\n }\n\n /**\n * Send a pong.\n *\n * @param {*} [data] The data to send\n * @param {Boolean} [mask] Indicates whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when the pong is sent\n * @public\n */\n pong(data, mask, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof data === 'function') {\n cb = data;\n data = mask = undefined;\n } else if (typeof mask === 'function') {\n cb = mask;\n mask = undefined;\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n if (mask === undefined) mask = !this._isServer;\n this._sender.pong(data || EMPTY_BUFFER, mask, cb);\n }\n\n /**\n * Resume the socket.\n *\n * @public\n */\n resume() {\n if (\n this.readyState === WebSocket.CONNECTING ||\n this.readyState === WebSocket.CLOSED\n ) {\n return;\n }\n\n this._paused = false;\n if (!this._receiver._writableState.needDrain) this._socket.resume();\n }\n\n /**\n * Send a data message.\n *\n * @param {*} data The message to send\n * @param {Object} [options] Options object\n * @param {Boolean} [options.binary] Specifies whether `data` is binary or\n * text\n * @param {Boolean} [options.compress] Specifies whether or not to compress\n * `data`\n * @param {Boolean} [options.fin=true] Specifies whether the fragment is the\n * last one\n * @param {Boolean} [options.mask] Specifies whether or not to mask `data`\n * @param {Function} [cb] Callback which is executed when data is written out\n * @public\n */\n send(data, options, cb) {\n if (this.readyState === WebSocket.CONNECTING) {\n throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');\n }\n\n if (typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n if (typeof data === 'number') data = data.toString();\n\n if (this.readyState !== WebSocket.OPEN) {\n sendAfterClose(this, data, cb);\n return;\n }\n\n const opts = {\n binary: typeof data !== 'string',\n mask: !this._isServer,\n compress: true,\n fin: true,\n ...options\n };\n\n if (!this._extensions[PerMessageDeflate.extensionName]) {\n opts.compress = false;\n }\n\n this._sender.send(data || EMPTY_BUFFER, opts, cb);\n }\n\n /**\n * Forcibly close the connection.\n *\n * @public\n */\n terminate() {\n if (this.readyState === WebSocket.CLOSED) return;\n if (this.readyState === WebSocket.CONNECTING) {\n const msg = 'WebSocket was closed before the connection was established';\n abortHandshake(this, this._req, msg);\n return;\n }\n\n if (this._socket) {\n this._readyState = WebSocket.CLOSING;\n this._socket.destroy();\n }\n }\n}\n\n/**\n * @constant {Number} CONNECTING\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CONNECTING', {\n enumerable: true,\n value: readyStates.indexOf('CONNECTING')\n});\n\n/**\n * @constant {Number} CONNECTING\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CONNECTING', {\n enumerable: true,\n value: readyStates.indexOf('CONNECTING')\n});\n\n/**\n * @constant {Number} OPEN\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'OPEN', {\n enumerable: true,\n value: readyStates.indexOf('OPEN')\n});\n\n/**\n * @constant {Number} OPEN\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'OPEN', {\n enumerable: true,\n value: readyStates.indexOf('OPEN')\n});\n\n/**\n * @constant {Number} CLOSING\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CLOSING', {\n enumerable: true,\n value: readyStates.indexOf('CLOSING')\n});\n\n/**\n * @constant {Number} CLOSING\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CLOSING', {\n enumerable: true,\n value: readyStates.indexOf('CLOSING')\n});\n\n/**\n * @constant {Number} CLOSED\n * @memberof WebSocket\n */\nObject.defineProperty(WebSocket, 'CLOSED', {\n enumerable: true,\n value: readyStates.indexOf('CLOSED')\n});\n\n/**\n * @constant {Number} CLOSED\n * @memberof WebSocket.prototype\n */\nObject.defineProperty(WebSocket.prototype, 'CLOSED', {\n enumerable: true,\n value: readyStates.indexOf('CLOSED')\n});\n\n[\n 'binaryType',\n 'bufferedAmount',\n 'extensions',\n 'isPaused',\n 'protocol',\n 'readyState',\n 'url'\n].forEach((property) => {\n Object.defineProperty(WebSocket.prototype, property, { enumerable: true });\n});\n\n//\n// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes.\n// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface\n//\n['open', 'error', 'close', 'message'].forEach((method) => {\n Object.defineProperty(WebSocket.prototype, `on${method}`, {\n enumerable: true,\n get() {\n for (const listener of this.listeners(method)) {\n if (listener[kForOnEventAttribute]) return listener[kListener];\n }\n\n return null;\n },\n set(handler) {\n for (const listener of this.listeners(method)) {\n if (listener[kForOnEventAttribute]) {\n this.removeListener(method, listener);\n break;\n }\n }\n\n if (typeof handler !== 'function') return;\n\n this.addEventListener(method, handler, {\n [kForOnEventAttribute]: true\n });\n }\n });\n});\n\nWebSocket.prototype.addEventListener = addEventListener;\nWebSocket.prototype.removeEventListener = removeEventListener;\n\nmodule.exports = WebSocket;\n\n/**\n * Initialize a WebSocket client.\n *\n * @param {WebSocket} websocket The client to initialize\n * @param {(String|URL)} address The URL to which to connect\n * @param {Array} protocols The subprotocols\n * @param {Object} [options] Connection options\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any\n * of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple\n * times in the same tick\n * @param {Boolean} [options.autoPong=true] Specifies whether or not to\n * automatically send a pong in response to a ping\n * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait\n * for the closing handshake to finish after `websocket.close()` is called\n * @param {Function} [options.finishRequest] A function which can be used to\n * customize the headers of each http request before it is sent\n * @param {Boolean} [options.followRedirects=false] Whether or not to follow\n * redirects\n * @param {Function} [options.generateMask] The function used to generate the\n * masking key\n * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the\n * handshake request\n * @param {Number} [options.maxPayload=104857600] The maximum allowed message\n * size\n * @param {Number} [options.maxRedirects=10] The maximum number of redirects\n * allowed\n * @param {String} [options.origin] Value of the `Origin` or\n * `Sec-WebSocket-Origin` header\n * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable\n * permessage-deflate\n * @param {Number} [options.protocolVersion=13] Value of the\n * `Sec-WebSocket-Version` header\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @private\n */\nfunction initAsClient(websocket, address, protocols, options) {\n const opts = {\n allowSynchronousEvents: true,\n autoPong: true,\n closeTimeout: CLOSE_TIMEOUT,\n protocolVersion: protocolVersions[1],\n maxPayload: 100 * 1024 * 1024,\n skipUTF8Validation: false,\n perMessageDeflate: true,\n followRedirects: false,\n maxRedirects: 10,\n ...options,\n socketPath: undefined,\n hostname: undefined,\n protocol: undefined,\n timeout: undefined,\n method: 'GET',\n host: undefined,\n path: undefined,\n port: undefined\n };\n\n websocket._autoPong = opts.autoPong;\n websocket._closeTimeout = opts.closeTimeout;\n\n if (!protocolVersions.includes(opts.protocolVersion)) {\n throw new RangeError(\n `Unsupported protocol version: ${opts.protocolVersion} ` +\n `(supported versions: ${protocolVersions.join(', ')})`\n );\n }\n\n let parsedUrl;\n\n if (address instanceof URL) {\n parsedUrl = address;\n } else {\n try {\n parsedUrl = new URL(address);\n } catch (e) {\n throw new SyntaxError(`Invalid URL: ${address}`);\n }\n }\n\n if (parsedUrl.protocol === 'http:') {\n parsedUrl.protocol = 'ws:';\n } else if (parsedUrl.protocol === 'https:') {\n parsedUrl.protocol = 'wss:';\n }\n\n websocket._url = parsedUrl.href;\n\n const isSecure = parsedUrl.protocol === 'wss:';\n const isIpcUrl = parsedUrl.protocol === 'ws+unix:';\n let invalidUrlMessage;\n\n if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {\n invalidUrlMessage =\n 'The URL\\'s protocol must be one of \"ws:\", \"wss:\", ' +\n '\"http:\", \"https:\", or \"ws+unix:\"';\n } else if (isIpcUrl && !parsedUrl.pathname) {\n invalidUrlMessage = \"The URL's pathname is empty\";\n } else if (parsedUrl.hash) {\n invalidUrlMessage = 'The URL contains a fragment identifier';\n }\n\n if (invalidUrlMessage) {\n const err = new SyntaxError(invalidUrlMessage);\n\n if (websocket._redirects === 0) {\n throw err;\n } else {\n emitErrorAndClose(websocket, err);\n return;\n }\n }\n\n const defaultPort = isSecure ? 443 : 80;\n const key = randomBytes(16).toString('base64');\n const request = isSecure ? https.request : http.request;\n const protocolSet = new Set();\n let perMessageDeflate;\n\n opts.createConnection =\n opts.createConnection || (isSecure ? tlsConnect : netConnect);\n opts.defaultPort = opts.defaultPort || defaultPort;\n opts.port = parsedUrl.port || defaultPort;\n opts.host = parsedUrl.hostname.startsWith('[')\n ? parsedUrl.hostname.slice(1, -1)\n : parsedUrl.hostname;\n opts.headers = {\n ...opts.headers,\n 'Sec-WebSocket-Version': opts.protocolVersion,\n 'Sec-WebSocket-Key': key,\n Connection: 'Upgrade',\n Upgrade: 'websocket'\n };\n opts.path = parsedUrl.pathname + parsedUrl.search;\n opts.timeout = opts.handshakeTimeout;\n\n if (opts.perMessageDeflate) {\n perMessageDeflate = new PerMessageDeflate(\n opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},\n false,\n opts.maxPayload\n );\n opts.headers['Sec-WebSocket-Extensions'] = format({\n [PerMessageDeflate.extensionName]: perMessageDeflate.offer()\n });\n }\n if (protocols.length) {\n for (const protocol of protocols) {\n if (\n typeof protocol !== 'string' ||\n !subprotocolRegex.test(protocol) ||\n protocolSet.has(protocol)\n ) {\n throw new SyntaxError(\n 'An invalid or duplicated subprotocol was specified'\n );\n }\n\n protocolSet.add(protocol);\n }\n\n opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');\n }\n if (opts.origin) {\n if (opts.protocolVersion < 13) {\n opts.headers['Sec-WebSocket-Origin'] = opts.origin;\n } else {\n opts.headers.Origin = opts.origin;\n }\n }\n if (parsedUrl.username || parsedUrl.password) {\n opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;\n }\n\n if (isIpcUrl) {\n const parts = opts.path.split(':');\n\n opts.socketPath = parts[0];\n opts.path = parts[1];\n }\n\n let req;\n\n if (opts.followRedirects) {\n if (websocket._redirects === 0) {\n websocket._originalIpc = isIpcUrl;\n websocket._originalSecure = isSecure;\n websocket._originalHostOrSocketPath = isIpcUrl\n ? opts.socketPath\n : parsedUrl.host;\n\n const headers = options && options.headers;\n\n //\n // Shallow copy the user provided options so that headers can be changed\n // without mutating the original object.\n //\n options = { ...options, headers: {} };\n\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n options.headers[key.toLowerCase()] = value;\n }\n }\n } else if (websocket.listenerCount('redirect') === 0) {\n const isSameHost = isIpcUrl\n ? websocket._originalIpc\n ? opts.socketPath === websocket._originalHostOrSocketPath\n : false\n : websocket._originalIpc\n ? false\n : parsedUrl.host === websocket._originalHostOrSocketPath;\n\n if (!isSameHost || (websocket._originalSecure && !isSecure)) {\n //\n // Match curl 7.77.0 behavior and drop the following headers. These\n // headers are also dropped when following a redirect to a subdomain.\n //\n delete opts.headers.authorization;\n delete opts.headers.cookie;\n\n if (!isSameHost) delete opts.headers.host;\n\n opts.auth = undefined;\n }\n }\n\n //\n // Match curl 7.77.0 behavior and make the first `Authorization` header win.\n // If the `Authorization` header is set, then there is nothing to do as it\n // will take precedence.\n //\n if (opts.auth && !options.headers.authorization) {\n options.headers.authorization =\n 'Basic ' + Buffer.from(opts.auth).toString('base64');\n }\n\n req = websocket._req = request(opts);\n\n if (websocket._redirects) {\n //\n // Unlike what is done for the `'upgrade'` event, no early exit is\n // triggered here if the user calls `websocket.close()` or\n // `websocket.terminate()` from a listener of the `'redirect'` event. This\n // is because the user can also call `request.destroy()` with an error\n // before calling `websocket.close()` or `websocket.terminate()` and this\n // would result in an error being emitted on the `request` object with no\n // `'error'` event listeners attached.\n //\n websocket.emit('redirect', websocket.url, req);\n }\n } else {\n req = websocket._req = request(opts);\n }\n\n if (opts.timeout) {\n req.on('timeout', () => {\n abortHandshake(websocket, req, 'Opening handshake has timed out');\n });\n }\n\n req.on('error', (err) => {\n if (req === null || req[kAborted]) return;\n\n req = websocket._req = null;\n emitErrorAndClose(websocket, err);\n });\n\n req.on('response', (res) => {\n const location = res.headers.location;\n const statusCode = res.statusCode;\n\n if (\n location &&\n opts.followRedirects &&\n statusCode >= 300 &&\n statusCode < 400\n ) {\n if (++websocket._redirects > opts.maxRedirects) {\n abortHandshake(websocket, req, 'Maximum redirects exceeded');\n return;\n }\n\n req.abort();\n\n let addr;\n\n try {\n addr = new URL(location, address);\n } catch (e) {\n const err = new SyntaxError(`Invalid URL: ${location}`);\n emitErrorAndClose(websocket, err);\n return;\n }\n\n initAsClient(websocket, addr, protocols, options);\n } else if (!websocket.emit('unexpected-response', req, res)) {\n abortHandshake(\n websocket,\n req,\n `Unexpected server response: ${res.statusCode}`\n );\n }\n });\n\n req.on('upgrade', (res, socket, head) => {\n websocket.emit('upgrade', res);\n\n //\n // The user may have closed the connection from a listener of the\n // `'upgrade'` event.\n //\n if (websocket.readyState !== WebSocket.CONNECTING) return;\n\n req = websocket._req = null;\n\n const upgrade = res.headers.upgrade;\n\n if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {\n abortHandshake(websocket, socket, 'Invalid Upgrade header');\n return;\n }\n\n const digest = createHash('sha1')\n .update(key + GUID)\n .digest('base64');\n\n if (res.headers['sec-websocket-accept'] !== digest) {\n abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header');\n return;\n }\n\n const serverProt = res.headers['sec-websocket-protocol'];\n let protError;\n\n if (serverProt !== undefined) {\n if (!protocolSet.size) {\n protError = 'Server sent a subprotocol but none was requested';\n } else if (!protocolSet.has(serverProt)) {\n protError = 'Server sent an invalid subprotocol';\n }\n } else if (protocolSet.size) {\n protError = 'Server sent no subprotocol';\n }\n\n if (protError) {\n abortHandshake(websocket, socket, protError);\n return;\n }\n\n if (serverProt) websocket._protocol = serverProt;\n\n const secWebSocketExtensions = res.headers['sec-websocket-extensions'];\n\n if (secWebSocketExtensions !== undefined) {\n if (!perMessageDeflate) {\n const message =\n 'Server sent a Sec-WebSocket-Extensions header but no extension ' +\n 'was requested';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n let extensions;\n\n try {\n extensions = parse(secWebSocketExtensions);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Extensions header';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n const extensionNames = Object.keys(extensions);\n\n if (\n extensionNames.length !== 1 ||\n extensionNames[0] !== PerMessageDeflate.extensionName\n ) {\n const message = 'Server indicated an extension that was not requested';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n try {\n perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Extensions header';\n abortHandshake(websocket, socket, message);\n return;\n }\n\n websocket._extensions[PerMessageDeflate.extensionName] =\n perMessageDeflate;\n }\n\n websocket.setSocket(socket, head, {\n allowSynchronousEvents: opts.allowSynchronousEvents,\n generateMask: opts.generateMask,\n maxPayload: opts.maxPayload,\n skipUTF8Validation: opts.skipUTF8Validation\n });\n });\n\n if (opts.finishRequest) {\n opts.finishRequest(req, websocket);\n } else {\n req.end();\n }\n}\n\n/**\n * Emit the `'error'` and `'close'` events.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {Error} The error to emit\n * @private\n */\nfunction emitErrorAndClose(websocket, err) {\n websocket._readyState = WebSocket.CLOSING;\n //\n // The following assignment is practically useless and is done only for\n // consistency.\n //\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n websocket.emitClose();\n}\n\n/**\n * Create a `net.Socket` and initiate a connection.\n *\n * @param {Object} options Connection options\n * @return {net.Socket} The newly created socket used to start the connection\n * @private\n */\nfunction netConnect(options) {\n options.path = options.socketPath;\n return net.connect(options);\n}\n\n/**\n * Create a `tls.TLSSocket` and initiate a connection.\n *\n * @param {Object} options Connection options\n * @return {tls.TLSSocket} The newly created socket used to start the connection\n * @private\n */\nfunction tlsConnect(options) {\n options.path = undefined;\n\n if (!options.servername && options.servername !== '') {\n options.servername = net.isIP(options.host) ? '' : options.host;\n }\n\n return tls.connect(options);\n}\n\n/**\n * Abort the handshake and emit an error.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to\n * abort or the socket to destroy\n * @param {String} message The error message\n * @private\n */\nfunction abortHandshake(websocket, stream, message) {\n websocket._readyState = WebSocket.CLOSING;\n\n const err = new Error(message);\n Error.captureStackTrace(err, abortHandshake);\n\n if (stream.setHeader) {\n stream[kAborted] = true;\n stream.abort();\n\n if (stream.socket && !stream.socket.destroyed) {\n //\n // On Node.js >= 14.3.0 `request.abort()` does not destroy the socket if\n // called after the request completed. See\n // https://github.com/websockets/ws/issues/1869.\n //\n stream.socket.destroy();\n }\n\n process.nextTick(emitErrorAndClose, websocket, err);\n } else {\n stream.destroy(err);\n stream.once('error', websocket.emit.bind(websocket, 'error'));\n stream.once('close', websocket.emitClose.bind(websocket));\n }\n}\n\n/**\n * Handle cases where the `ping()`, `pong()`, or `send()` methods are called\n * when the `readyState` attribute is `CLOSING` or `CLOSED`.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @param {*} [data] The data to send\n * @param {Function} [cb] Callback\n * @private\n */\nfunction sendAfterClose(websocket, data, cb) {\n if (data) {\n const length = isBlob(data) ? data.size : toBuffer(data).length;\n\n //\n // The `_bufferedAmount` property is used only when the peer is a client and\n // the opening handshake fails. Under these circumstances, in fact, the\n // `setSocket()` method is not called, so the `_socket` and `_sender`\n // properties are set to `null`.\n //\n if (websocket._socket) websocket._sender._bufferedBytes += length;\n else websocket._bufferedAmount += length;\n }\n\n if (cb) {\n const err = new Error(\n `WebSocket is not open: readyState ${websocket.readyState} ` +\n `(${readyStates[websocket.readyState]})`\n );\n process.nextTick(cb, err);\n }\n}\n\n/**\n * The listener of the `Receiver` `'conclude'` event.\n *\n * @param {Number} code The status code\n * @param {Buffer} reason The reason for closing\n * @private\n */\nfunction receiverOnConclude(code, reason) {\n const websocket = this[kWebSocket];\n\n websocket._closeFrameReceived = true;\n websocket._closeMessage = reason;\n websocket._closeCode = code;\n\n if (websocket._socket[kWebSocket] === undefined) return;\n\n websocket._socket.removeListener('data', socketOnData);\n process.nextTick(resume, websocket._socket);\n\n if (code === 1005) websocket.close();\n else websocket.close(code, reason);\n}\n\n/**\n * The listener of the `Receiver` `'drain'` event.\n *\n * @private\n */\nfunction receiverOnDrain() {\n const websocket = this[kWebSocket];\n\n if (!websocket.isPaused) websocket._socket.resume();\n}\n\n/**\n * The listener of the `Receiver` `'error'` event.\n *\n * @param {(RangeError|Error)} err The emitted error\n * @private\n */\nfunction receiverOnError(err) {\n const websocket = this[kWebSocket];\n\n if (websocket._socket[kWebSocket] !== undefined) {\n websocket._socket.removeListener('data', socketOnData);\n\n //\n // On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See\n // https://github.com/websockets/ws/issues/1940.\n //\n process.nextTick(resume, websocket._socket);\n\n websocket.close(err[kStatusCode]);\n }\n\n if (!websocket._errorEmitted) {\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n }\n}\n\n/**\n * The listener of the `Receiver` `'finish'` event.\n *\n * @private\n */\nfunction receiverOnFinish() {\n this[kWebSocket].emitClose();\n}\n\n/**\n * The listener of the `Receiver` `'message'` event.\n *\n * @param {Buffer|ArrayBuffer|Buffer[])} data The message\n * @param {Boolean} isBinary Specifies whether the message is binary or not\n * @private\n */\nfunction receiverOnMessage(data, isBinary) {\n this[kWebSocket].emit('message', data, isBinary);\n}\n\n/**\n * The listener of the `Receiver` `'ping'` event.\n *\n * @param {Buffer} data The data included in the ping frame\n * @private\n */\nfunction receiverOnPing(data) {\n const websocket = this[kWebSocket];\n\n if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);\n websocket.emit('ping', data);\n}\n\n/**\n * The listener of the `Receiver` `'pong'` event.\n *\n * @param {Buffer} data The data included in the pong frame\n * @private\n */\nfunction receiverOnPong(data) {\n this[kWebSocket].emit('pong', data);\n}\n\n/**\n * Resume a readable stream\n *\n * @param {Readable} stream The readable stream\n * @private\n */\nfunction resume(stream) {\n stream.resume();\n}\n\n/**\n * The `Sender` error event handler.\n *\n * @param {Error} The error\n * @private\n */\nfunction senderOnError(err) {\n const websocket = this[kWebSocket];\n\n if (websocket.readyState === WebSocket.CLOSED) return;\n if (websocket.readyState === WebSocket.OPEN) {\n websocket._readyState = WebSocket.CLOSING;\n setCloseTimer(websocket);\n }\n\n //\n // `socket.end()` is used instead of `socket.destroy()` to allow the other\n // peer to finish sending queued data. There is no need to set a timer here\n // because `CLOSING` means that it is already set or not needed.\n //\n this._socket.end();\n\n if (!websocket._errorEmitted) {\n websocket._errorEmitted = true;\n websocket.emit('error', err);\n }\n}\n\n/**\n * Set a timer to destroy the underlying raw socket of a WebSocket.\n *\n * @param {WebSocket} websocket The WebSocket instance\n * @private\n */\nfunction setCloseTimer(websocket) {\n websocket._closeTimer = setTimeout(\n websocket._socket.destroy.bind(websocket._socket),\n websocket._closeTimeout\n );\n}\n\n/**\n * The listener of the socket `'close'` event.\n *\n * @private\n */\nfunction socketOnClose() {\n const websocket = this[kWebSocket];\n\n this.removeListener('close', socketOnClose);\n this.removeListener('data', socketOnData);\n this.removeListener('end', socketOnEnd);\n\n websocket._readyState = WebSocket.CLOSING;\n\n //\n // The close frame might not have been received or the `'end'` event emitted,\n // for example, if the socket was destroyed due to an error. Ensure that the\n // `receiver` stream is closed after writing any remaining buffered data to\n // it. If the readable side of the socket is in flowing mode then there is no\n // buffered data as everything has been already written. If instead, the\n // socket is paused, any possible buffered data will be read as a single\n // chunk.\n //\n if (\n !this._readableState.endEmitted &&\n !websocket._closeFrameReceived &&\n !websocket._receiver._writableState.errorEmitted &&\n this._readableState.length !== 0\n ) {\n const chunk = this.read(this._readableState.length);\n\n websocket._receiver.write(chunk);\n }\n\n websocket._receiver.end();\n\n this[kWebSocket] = undefined;\n\n clearTimeout(websocket._closeTimer);\n\n if (\n websocket._receiver._writableState.finished ||\n websocket._receiver._writableState.errorEmitted\n ) {\n websocket.emitClose();\n } else {\n websocket._receiver.on('error', receiverOnFinish);\n websocket._receiver.on('finish', receiverOnFinish);\n }\n}\n\n/**\n * The listener of the socket `'data'` event.\n *\n * @param {Buffer} chunk A chunk of data\n * @private\n */\nfunction socketOnData(chunk) {\n if (!this[kWebSocket]._receiver.write(chunk)) {\n this.pause();\n }\n}\n\n/**\n * The listener of the socket `'end'` event.\n *\n * @private\n */\nfunction socketOnEnd() {\n const websocket = this[kWebSocket];\n\n websocket._readyState = WebSocket.CLOSING;\n websocket._receiver.end();\n this.end();\n}\n\n/**\n * The listener of the socket `'error'` event.\n *\n * @private\n */\nfunction socketOnError() {\n const websocket = this[kWebSocket];\n\n this.removeListener('error', socketOnError);\n this.on('error', NOOP);\n\n if (websocket) {\n websocket._readyState = WebSocket.CLOSING;\n this.destroy();\n }\n}\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^WebSocket$\" }] */\n'use strict';\n\nconst WebSocket = require('./websocket');\nconst { Duplex } = require('stream');\n\n/**\n * Emits the `'close'` event on a stream.\n *\n * @param {Duplex} stream The stream.\n * @private\n */\nfunction emitClose(stream) {\n stream.emit('close');\n}\n\n/**\n * The listener of the `'end'` event.\n *\n * @private\n */\nfunction duplexOnEnd() {\n if (!this.destroyed && this._writableState.finished) {\n this.destroy();\n }\n}\n\n/**\n * The listener of the `'error'` event.\n *\n * @param {Error} err The error\n * @private\n */\nfunction duplexOnError(err) {\n this.removeListener('error', duplexOnError);\n this.destroy();\n if (this.listenerCount('error') === 0) {\n // Do not suppress the throwing behavior.\n this.emit('error', err);\n }\n}\n\n/**\n * Wraps a `WebSocket` in a duplex stream.\n *\n * @param {WebSocket} ws The `WebSocket` to wrap\n * @param {Object} [options] The options for the `Duplex` constructor\n * @return {Duplex} The duplex stream\n * @public\n */\nfunction createWebSocketStream(ws, options) {\n let terminateOnDestroy = true;\n\n const duplex = new Duplex({\n ...options,\n autoDestroy: false,\n emitClose: false,\n objectMode: false,\n writableObjectMode: false\n });\n\n ws.on('message', function message(msg, isBinary) {\n const data =\n !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;\n\n if (!duplex.push(data)) ws.pause();\n });\n\n ws.once('error', function error(err) {\n if (duplex.destroyed) return;\n\n // Prevent `ws.terminate()` from being called by `duplex._destroy()`.\n //\n // - If the `'error'` event is emitted before the `'open'` event, then\n // `ws.terminate()` is a noop as no socket is assigned.\n // - Otherwise, the error is re-emitted by the listener of the `'error'`\n // event of the `Receiver` object. The listener already closes the\n // connection by calling `ws.close()`. This allows a close frame to be\n // sent to the other peer. If `ws.terminate()` is called right after this,\n // then the close frame might not be sent.\n terminateOnDestroy = false;\n duplex.destroy(err);\n });\n\n ws.once('close', function close() {\n if (duplex.destroyed) return;\n\n duplex.push(null);\n });\n\n duplex._destroy = function (err, callback) {\n if (ws.readyState === ws.CLOSED) {\n callback(err);\n process.nextTick(emitClose, duplex);\n return;\n }\n\n let called = false;\n\n ws.once('error', function error(err) {\n called = true;\n callback(err);\n });\n\n ws.once('close', function close() {\n if (!called) callback(err);\n process.nextTick(emitClose, duplex);\n });\n\n if (terminateOnDestroy) ws.terminate();\n };\n\n duplex._final = function (callback) {\n if (ws.readyState === ws.CONNECTING) {\n ws.once('open', function open() {\n duplex._final(callback);\n });\n return;\n }\n\n // If the value of the `_socket` property is `null` it means that `ws` is a\n // client websocket and the handshake failed. In fact, when this happens, a\n // socket is never assigned to the websocket. Wait for the `'error'` event\n // that will be emitted by the websocket.\n if (ws._socket === null) return;\n\n if (ws._socket._writableState.finished) {\n callback();\n if (duplex._readableState.endEmitted) duplex.destroy();\n } else {\n ws._socket.once('finish', function finish() {\n // `duplex` is not destroyed here because the `'end'` event will be\n // emitted on `duplex` after this `'finish'` event. The EOF signaling\n // `null` chunk is, in fact, pushed when the websocket emits `'close'`.\n callback();\n });\n ws.close();\n }\n };\n\n duplex._read = function () {\n if (ws.isPaused) ws.resume();\n };\n\n duplex._write = function (chunk, encoding, callback) {\n if (ws.readyState === ws.CONNECTING) {\n ws.once('open', function open() {\n duplex._write(chunk, encoding, callback);\n });\n return;\n }\n\n ws.send(chunk, callback);\n };\n\n duplex.on('end', duplexOnEnd);\n duplex.on('error', duplexOnError);\n return duplex;\n}\n\nmodule.exports = createWebSocketStream;\n","'use strict';\n\nconst { tokenChars } = require('./validation');\n\n/**\n * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.\n *\n * @param {String} header The field value of the header\n * @return {Set} The subprotocol names\n * @public\n */\nfunction parse(header) {\n const protocols = new Set();\n let start = -1;\n let end = -1;\n let i = 0;\n\n for (i; i < header.length; i++) {\n const code = header.charCodeAt(i);\n\n if (end === -1 && tokenChars[code] === 1) {\n if (start === -1) start = i;\n } else if (\n i !== 0 &&\n (code === 0x20 /* ' ' */ || code === 0x09) /* '\\t' */\n ) {\n if (end === -1 && start !== -1) end = i;\n } else if (code === 0x2c /* ',' */) {\n if (start === -1) {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n\n if (end === -1) end = i;\n\n const protocol = header.slice(start, end);\n\n if (protocols.has(protocol)) {\n throw new SyntaxError(`The \"${protocol}\" subprotocol is duplicated`);\n }\n\n protocols.add(protocol);\n start = end = -1;\n } else {\n throw new SyntaxError(`Unexpected character at index ${i}`);\n }\n }\n\n if (start === -1 || end !== -1) {\n throw new SyntaxError('Unexpected end of input');\n }\n\n const protocol = header.slice(start, i);\n\n if (protocols.has(protocol)) {\n throw new SyntaxError(`The \"${protocol}\" subprotocol is duplicated`);\n }\n\n protocols.add(protocol);\n return protocols;\n}\n\nmodule.exports = { parse };\n","/* eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"^Duplex$\", \"caughtErrors\": \"none\" }] */\n\n'use strict';\n\nconst EventEmitter = require('events');\nconst http = require('http');\nconst { Duplex } = require('stream');\nconst { createHash } = require('crypto');\n\nconst extension = require('./extension');\nconst PerMessageDeflate = require('./permessage-deflate');\nconst subprotocol = require('./subprotocol');\nconst WebSocket = require('./websocket');\nconst { CLOSE_TIMEOUT, GUID, kWebSocket } = require('./constants');\n\nconst keyRegex = /^[+/0-9A-Za-z]{22}==$/;\n\nconst RUNNING = 0;\nconst CLOSING = 1;\nconst CLOSED = 2;\n\n/**\n * Class representing a WebSocket server.\n *\n * @extends EventEmitter\n */\nclass WebSocketServer extends EventEmitter {\n /**\n * Create a `WebSocketServer` instance.\n *\n * @param {Object} options Configuration options\n * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether\n * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted\n * multiple times in the same tick\n * @param {Boolean} [options.autoPong=true] Specifies whether or not to\n * automatically send a pong in response to a ping\n * @param {Number} [options.backlog=511] The maximum length of the queue of\n * pending connections\n * @param {Boolean} [options.clientTracking=true] Specifies whether or not to\n * track clients\n * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to\n * wait for the closing handshake to finish after `websocket.close()` is\n * called\n * @param {Function} [options.handleProtocols] A hook to handle protocols\n * @param {String} [options.host] The hostname where to bind the server\n * @param {Number} [options.maxPayload=104857600] The maximum allowed message\n * size\n * @param {Boolean} [options.noServer=false] Enable no server mode\n * @param {String} [options.path] Accept only connections matching this path\n * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable\n * permessage-deflate\n * @param {Number} [options.port] The port where to bind the server\n * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S\n * server to use\n * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or\n * not to skip UTF-8 validation for text and close messages\n * @param {Function} [options.verifyClient] A hook to reject connections\n * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`\n * class to use. It must be the `WebSocket` class or class that extends it\n * @param {Function} [callback] A listener for the `listening` event\n */\n constructor(options, callback) {\n super();\n\n options = {\n allowSynchronousEvents: true,\n autoPong: true,\n maxPayload: 100 * 1024 * 1024,\n skipUTF8Validation: false,\n perMessageDeflate: false,\n handleProtocols: null,\n clientTracking: true,\n closeTimeout: CLOSE_TIMEOUT,\n verifyClient: null,\n noServer: false,\n backlog: null, // use default (511 as implemented in net.js)\n server: null,\n host: null,\n path: null,\n port: null,\n WebSocket,\n ...options\n };\n\n if (\n (options.port == null && !options.server && !options.noServer) ||\n (options.port != null && (options.server || options.noServer)) ||\n (options.server && options.noServer)\n ) {\n throw new TypeError(\n 'One and only one of the \"port\", \"server\", or \"noServer\" options ' +\n 'must be specified'\n );\n }\n\n if (options.port != null) {\n this._server = http.createServer((req, res) => {\n const body = http.STATUS_CODES[426];\n\n res.writeHead(426, {\n 'Content-Length': body.length,\n 'Content-Type': 'text/plain'\n });\n res.end(body);\n });\n this._server.listen(\n options.port,\n options.host,\n options.backlog,\n callback\n );\n } else if (options.server) {\n this._server = options.server;\n }\n\n if (this._server) {\n const emitConnection = this.emit.bind(this, 'connection');\n\n this._removeListeners = addListeners(this._server, {\n listening: this.emit.bind(this, 'listening'),\n error: this.emit.bind(this, 'error'),\n upgrade: (req, socket, head) => {\n this.handleUpgrade(req, socket, head, emitConnection);\n }\n });\n }\n\n if (options.perMessageDeflate === true) options.perMessageDeflate = {};\n if (options.clientTracking) {\n this.clients = new Set();\n this._shouldEmitClose = false;\n }\n\n this.options = options;\n this._state = RUNNING;\n }\n\n /**\n * Returns the bound address, the address family name, and port of the server\n * as reported by the operating system if listening on an IP socket.\n * If the server is listening on a pipe or UNIX domain socket, the name is\n * returned as a string.\n *\n * @return {(Object|String|null)} The address of the server\n * @public\n */\n address() {\n if (this.options.noServer) {\n throw new Error('The server is operating in \"noServer\" mode');\n }\n\n if (!this._server) return null;\n return this._server.address();\n }\n\n /**\n * Stop the server from accepting new connections and emit the `'close'` event\n * when all existing connections are closed.\n *\n * @param {Function} [cb] A one-time listener for the `'close'` event\n * @public\n */\n close(cb) {\n if (this._state === CLOSED) {\n if (cb) {\n this.once('close', () => {\n cb(new Error('The server is not running'));\n });\n }\n\n process.nextTick(emitClose, this);\n return;\n }\n\n if (cb) this.once('close', cb);\n\n if (this._state === CLOSING) return;\n this._state = CLOSING;\n\n if (this.options.noServer || this.options.server) {\n if (this._server) {\n this._removeListeners();\n this._removeListeners = this._server = null;\n }\n\n if (this.clients) {\n if (!this.clients.size) {\n process.nextTick(emitClose, this);\n } else {\n this._shouldEmitClose = true;\n }\n } else {\n process.nextTick(emitClose, this);\n }\n } else {\n const server = this._server;\n\n this._removeListeners();\n this._removeListeners = this._server = null;\n\n //\n // The HTTP/S server was created internally. Close it, and rely on its\n // `'close'` event.\n //\n server.close(() => {\n emitClose(this);\n });\n }\n }\n\n /**\n * See if a given request should be handled by this server instance.\n *\n * @param {http.IncomingMessage} req Request object to inspect\n * @return {Boolean} `true` if the request is valid, else `false`\n * @public\n */\n shouldHandle(req) {\n if (this.options.path) {\n const index = req.url.indexOf('?');\n const pathname = index !== -1 ? req.url.slice(0, index) : req.url;\n\n if (pathname !== this.options.path) return false;\n }\n\n return true;\n }\n\n /**\n * Handle a HTTP Upgrade request.\n *\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Function} cb Callback\n * @public\n */\n handleUpgrade(req, socket, head, cb) {\n socket.on('error', socketOnError);\n\n const key = req.headers['sec-websocket-key'];\n const upgrade = req.headers.upgrade;\n const version = +req.headers['sec-websocket-version'];\n\n if (req.method !== 'GET') {\n const message = 'Invalid HTTP method';\n abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);\n return;\n }\n\n if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {\n const message = 'Invalid Upgrade header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n\n if (key === undefined || !keyRegex.test(key)) {\n const message = 'Missing or invalid Sec-WebSocket-Key header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n\n if (version !== 13 && version !== 8) {\n const message = 'Missing or invalid Sec-WebSocket-Version header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {\n 'Sec-WebSocket-Version': '13, 8'\n });\n return;\n }\n\n if (!this.shouldHandle(req)) {\n abortHandshake(socket, 400);\n return;\n }\n\n const secWebSocketProtocol = req.headers['sec-websocket-protocol'];\n let protocols = new Set();\n\n if (secWebSocketProtocol !== undefined) {\n try {\n protocols = subprotocol.parse(secWebSocketProtocol);\n } catch (err) {\n const message = 'Invalid Sec-WebSocket-Protocol header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n }\n\n const secWebSocketExtensions = req.headers['sec-websocket-extensions'];\n const extensions = {};\n\n if (\n this.options.perMessageDeflate &&\n secWebSocketExtensions !== undefined\n ) {\n const perMessageDeflate = new PerMessageDeflate(\n this.options.perMessageDeflate,\n true,\n this.options.maxPayload\n );\n\n try {\n const offers = extension.parse(secWebSocketExtensions);\n\n if (offers[PerMessageDeflate.extensionName]) {\n perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);\n extensions[PerMessageDeflate.extensionName] = perMessageDeflate;\n }\n } catch (err) {\n const message =\n 'Invalid or unacceptable Sec-WebSocket-Extensions header';\n abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);\n return;\n }\n }\n\n //\n // Optionally call external client verification handler.\n //\n if (this.options.verifyClient) {\n const info = {\n origin:\n req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],\n secure: !!(req.socket.authorized || req.socket.encrypted),\n req\n };\n\n if (this.options.verifyClient.length === 2) {\n this.options.verifyClient(info, (verified, code, message, headers) => {\n if (!verified) {\n return abortHandshake(socket, code || 401, message, headers);\n }\n\n this.completeUpgrade(\n extensions,\n key,\n protocols,\n req,\n socket,\n head,\n cb\n );\n });\n return;\n }\n\n if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);\n }\n\n this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);\n }\n\n /**\n * Upgrade the connection to WebSocket.\n *\n * @param {Object} extensions The accepted extensions\n * @param {String} key The value of the `Sec-WebSocket-Key` header\n * @param {Set} protocols The subprotocols\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The network socket between the server and client\n * @param {Buffer} head The first packet of the upgraded stream\n * @param {Function} cb Callback\n * @throws {Error} If called more than once with the same socket\n * @private\n */\n completeUpgrade(extensions, key, protocols, req, socket, head, cb) {\n //\n // Destroy the socket if the client has already sent a FIN packet.\n //\n if (!socket.readable || !socket.writable) return socket.destroy();\n\n if (socket[kWebSocket]) {\n throw new Error(\n 'server.handleUpgrade() was called more than once with the same ' +\n 'socket, possibly due to a misconfiguration'\n );\n }\n\n if (this._state > RUNNING) return abortHandshake(socket, 503);\n\n const digest = createHash('sha1')\n .update(key + GUID)\n .digest('base64');\n\n const headers = [\n 'HTTP/1.1 101 Switching Protocols',\n 'Upgrade: websocket',\n 'Connection: Upgrade',\n `Sec-WebSocket-Accept: ${digest}`\n ];\n\n const ws = new this.options.WebSocket(null, undefined, this.options);\n\n if (protocols.size) {\n //\n // Optionally call external protocol selection handler.\n //\n const protocol = this.options.handleProtocols\n ? this.options.handleProtocols(protocols, req)\n : protocols.values().next().value;\n\n if (protocol) {\n headers.push(`Sec-WebSocket-Protocol: ${protocol}`);\n ws._protocol = protocol;\n }\n }\n\n if (extensions[PerMessageDeflate.extensionName]) {\n const params = extensions[PerMessageDeflate.extensionName].params;\n const value = extension.format({\n [PerMessageDeflate.extensionName]: [params]\n });\n headers.push(`Sec-WebSocket-Extensions: ${value}`);\n ws._extensions = extensions;\n }\n\n //\n // Allow external modification/inspection of handshake headers.\n //\n this.emit('headers', headers, req);\n\n socket.write(headers.concat('\\r\\n').join('\\r\\n'));\n socket.removeListener('error', socketOnError);\n\n ws.setSocket(socket, head, {\n allowSynchronousEvents: this.options.allowSynchronousEvents,\n maxPayload: this.options.maxPayload,\n skipUTF8Validation: this.options.skipUTF8Validation\n });\n\n if (this.clients) {\n this.clients.add(ws);\n ws.on('close', () => {\n this.clients.delete(ws);\n\n if (this._shouldEmitClose && !this.clients.size) {\n process.nextTick(emitClose, this);\n }\n });\n }\n\n cb(ws, req);\n }\n}\n\nmodule.exports = WebSocketServer;\n\n/**\n * Add event listeners on an `EventEmitter` using a map of <event, listener>\n * pairs.\n *\n * @param {EventEmitter} server The event emitter\n * @param {Object.<String, Function>} map The listeners to add\n * @return {Function} A function that will remove the added listeners when\n * called\n * @private\n */\nfunction addListeners(server, map) {\n for (const event of Object.keys(map)) server.on(event, map[event]);\n\n return function removeListeners() {\n for (const event of Object.keys(map)) {\n server.removeListener(event, map[event]);\n }\n };\n}\n\n/**\n * Emit a `'close'` event on an `EventEmitter`.\n *\n * @param {EventEmitter} server The event emitter\n * @private\n */\nfunction emitClose(server) {\n server._state = CLOSED;\n server.emit('close');\n}\n\n/**\n * Handle socket errors.\n *\n * @private\n */\nfunction socketOnError() {\n this.destroy();\n}\n\n/**\n * Close the connection when preconditions are not fulfilled.\n *\n * @param {Duplex} socket The socket of the upgrade request\n * @param {Number} code The HTTP response status code\n * @param {String} [message] The HTTP response body\n * @param {Object} [headers] Additional HTTP response headers\n * @private\n */\nfunction abortHandshake(socket, code, message, headers) {\n //\n // The socket is writable unless the user destroyed or ended it before calling\n // `server.handleUpgrade()` or in the `verifyClient` function, which is a user\n // error. Handling this does not make much sense as the worst that can happen\n // is that some of the data written by the user might be discarded due to the\n // call to `socket.end()` below, which triggers an `'error'` event that in\n // turn causes the socket to be destroyed.\n //\n message = message || http.STATUS_CODES[code];\n headers = {\n Connection: 'close',\n 'Content-Type': 'text/html',\n 'Content-Length': Buffer.byteLength(message),\n ...headers\n };\n\n socket.once('finish', socket.destroy);\n\n socket.end(\n `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\\r\\n` +\n Object.keys(headers)\n .map((h) => `${h}: ${headers[h]}`)\n .join('\\r\\n') +\n '\\r\\n\\r\\n' +\n message\n );\n}\n\n/**\n * Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least\n * one listener for it, otherwise call `abortHandshake()`.\n *\n * @param {WebSocketServer} server The WebSocket server\n * @param {http.IncomingMessage} req The request object\n * @param {Duplex} socket The socket of the upgrade request\n * @param {Number} code The HTTP response status code\n * @param {String} message The HTTP response body\n * @param {Object} [headers] The HTTP response headers\n * @private\n */\nfunction abortHandshakeOrEmitwsClientError(\n server,\n req,\n socket,\n code,\n message,\n headers\n) {\n if (server.listenerCount('wsClientError')) {\n const err = new Error(message);\n Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);\n\n server.emit('wsClientError', err, socket, req);\n } else {\n abortHandshake(socket, code, message, headers);\n }\n}\n","import createWebSocketStream from './lib/stream.js';\nimport Receiver from './lib/receiver.js';\nimport Sender from './lib/sender.js';\nimport WebSocket from './lib/websocket.js';\nimport WebSocketServer from './lib/websocket-server.js';\n\nexport { createWebSocketStream, Receiver, Sender, WebSocket, WebSocketServer };\nexport default WebSocket;\n","/**\n * WebSocket-to-TCP Proxy for Cap'n Proto\n *\n * Allows browsers to connect to native Cap'n Proto services (C++, etc.)\n * via WebSocket. Handles the protocol bridging between WebSocket (browser)\n * and raw TCP (Cap'n Proto services).\n */\n\nimport { EventEmitter } from 'node:events';\nimport { type Socket, createConnection } from 'node:net';\nimport { WebSocket, WebSocketServer } from 'ws';\n\nexport interface ProxyOptions {\n /** WebSocket server port */\n wsPort: number;\n /** Target TCP host */\n targetHost: string;\n /** Target TCP port */\n targetPort: number;\n /** Maximum message size in bytes (default: 16MB) */\n maxMessageSize?: number;\n /** Connection timeout in ms (default: 30000) */\n connectionTimeout?: number;\n /** Enable debug logging */\n debug?: boolean;\n}\n\ninterface ConnectionStats {\n wsMessagesIn: number;\n wsMessagesOut: number;\n tcpBytesIn: number;\n tcpBytesOut: number;\n connectedAt: Date;\n}\n\nclass ProxyConnection extends EventEmitter {\n private ws: WebSocket;\n private tcpSocket: Socket | null = null;\n private stats: ConnectionStats;\n private options: ProxyOptions;\n private closed = false;\n\n constructor(ws: WebSocket, options: ProxyOptions) {\n super();\n this.ws = ws;\n this.options = options;\n this.stats = {\n wsMessagesIn: 0,\n wsMessagesOut: 0,\n tcpBytesIn: 0,\n tcpBytesOut: 0,\n connectedAt: new Date(),\n };\n\n this.setupWebSocket();\n }\n\n private setupWebSocket(): void {\n this.ws.on('message', (data: WebSocket.RawData) => {\n this.handleWebSocketMessage(data);\n });\n\n this.ws.on('close', () => {\n this.log('WebSocket closed');\n this.close();\n });\n\n this.ws.on('error', (err) => {\n this.log('WebSocket error:', err);\n this.emit('error', err);\n this.close();\n });\n\n // Connect to target TCP service\n this.connectToTarget();\n }\n\n private connectToTarget(): void {\n const timeout = this.options.connectionTimeout ?? 30000;\n\n this.tcpSocket = createConnection({\n host: this.options.targetHost,\n port: this.options.targetPort,\n timeout,\n });\n\n this.tcpSocket.on('connect', () => {\n this.log('Connected to target TCP service');\n this.emit('connected');\n });\n\n this.tcpSocket.on('data', (data) => {\n this.handleTcpData(data);\n });\n\n this.tcpSocket.on('close', () => {\n this.log('TCP connection closed');\n this.close();\n });\n\n this.tcpSocket.on('error', (err) => {\n this.log('TCP error:', err);\n this.emit('error', err);\n this.close();\n });\n\n this.tcpSocket.on('timeout', () => {\n this.log('TCP connection timeout');\n this.close();\n });\n }\n\n private handleWebSocketMessage(data: WebSocket.RawData): void {\n if (this.closed) return;\n\n // Handle both single Buffer and Buffer[]\n const buffer = Buffer.isBuffer(data)\n ? data\n : Array.isArray(data)\n ? Buffer.concat(data)\n : Buffer.from(data);\n\n const maxSize = this.options.maxMessageSize ?? 16 * 1024 * 1024;\n if (buffer.length > maxSize) {\n this.log(`Message too large: ${buffer.length} bytes`);\n this.close();\n return;\n }\n\n this.stats.wsMessagesIn++;\n this.stats.tcpBytesOut += buffer.length;\n\n // Forward to TCP service\n if (this.tcpSocket?.writable) {\n this.tcpSocket.write(buffer);\n this.log(`Forwarded ${buffer.length} bytes to TCP`);\n }\n }\n\n private handleTcpData(data: Buffer): void {\n if (this.closed) return;\n\n this.stats.tcpBytesIn += data.length;\n this.stats.wsMessagesOut++;\n\n // Forward to WebSocket client\n if (this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(data);\n this.log(`Forwarded ${data.length} bytes to WebSocket`);\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.options.debug) {\n console.log('[ProxyConnection]', ...args);\n }\n }\n\n getStats(): ConnectionStats {\n return { ...this.stats };\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n\n this.ws.close();\n this.tcpSocket?.destroy();\n\n this.emit('closed');\n }\n}\n\nexport class CapnpWebSocketProxy extends EventEmitter {\n private wss: WebSocketServer;\n private connections = new Map<WebSocket, ProxyConnection>();\n private options: ProxyOptions;\n\n constructor(options: ProxyOptions) {\n super();\n this.options = options;\n this.wss = new WebSocketServer({ port: options.wsPort });\n this.setupServer();\n }\n\n private setupServer(): void {\n this.wss.on('connection', (ws, req) => {\n const clientIp = req.socket.remoteAddress;\n this.log(`New WebSocket connection from ${clientIp}`);\n\n const connection = new ProxyConnection(ws, this.options);\n this.connections.set(ws, connection);\n\n connection.on('connected', () => {\n this.emit('connection', connection);\n });\n\n connection.on('error', (err) => {\n this.emit('error', err, connection);\n });\n\n connection.on('closed', () => {\n this.connections.delete(ws);\n this.emit('disconnection', connection);\n });\n });\n\n this.wss.on('error', (err) => {\n this.emit('error', err);\n });\n }\n\n private log(...args: unknown[]): void {\n if (this.options.debug) {\n console.log('[CapnpWebSocketProxy]', ...args);\n }\n }\n\n getConnectionCount(): number {\n return this.connections.size;\n }\n\n getAllStats(): ConnectionStats[] {\n return Array.from(this.connections.values()).map((c) => c.getStats());\n }\n\n close(): Promise<void> {\n return new Promise((resolve) => {\n // Close all connections\n for (const connection of this.connections.values()) {\n connection.close();\n }\n this.connections.clear();\n\n // Close server\n this.wss.close(() => {\n this.emit('closed');\n resolve();\n });\n });\n }\n}\n\n// CLI entry point\nif (import.meta.url === `file://${process.argv[1]}`) {\n const args = process.argv.slice(2);\n\n // Parse CLI arguments\n let wsPort = 8080;\n let targetHost = 'localhost';\n let targetPort = 8081;\n let debug = false;\n\n for (let i = 0; i < args.length; i++) {\n switch (args[i]) {\n case '--ws-port':\n case '-p':\n wsPort = Number.parseInt(args[++i], 10);\n break;\n case '--target':\n case '-t': {\n const [host, port] = args[++i].split(':');\n targetHost = host;\n targetPort = Number.parseInt(port, 10);\n break;\n }\n case '--debug':\n case '-d':\n debug = true;\n break;\n case '--help':\n case '-h':\n console.log(`\nCap'n Proto WebSocket-to-TCP Proxy\n\nUsage: npx @naeemo/capnp proxy [options]\n\nOptions:\n -p, --ws-port <port> WebSocket server port (default: 8080)\n -t, --target <host:port> Target TCP service (default: localhost:8081)\n -d, --debug Enable debug logging\n -h, --help Show this help\n\nExample:\n npx @naeemo/capnp proxy -p 9000 -t 192.168.1.100:7000\n`);\n process.exit(0);\n }\n }\n\n const proxy = new CapnpWebSocketProxy({\n wsPort,\n targetHost,\n targetPort,\n debug,\n });\n\n console.log('WebSocket-to-TCP Proxy started');\n console.log(` WebSocket: ws://localhost:${wsPort}`);\n console.log(` Target: ${targetHost}:${targetPort}`);\n\n proxy.on('connection', () => {\n console.log(`Active connections: ${proxy.getConnectionCount()}`);\n });\n\n proxy.on('disconnection', () => {\n console.log(`Active connections: ${proxy.getConnectionCount()}`);\n });\n\n process.on('SIGINT', async () => {\n console.log('\\nShutting down...');\n await proxy.close();\n process.exit(0);\n });\n}\n"],"x_google_ignoreList":[25,26,27,28,29,30,31,32,33,34,35,36,37,38],"mappings":"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"}