@zqagent/shared 0.1.0 → 0.3.8

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.
@@ -26,8 +26,10 @@ __export(wire_exports, {
26
26
  FrameError: () => FrameError,
27
27
  FrameType: () => FrameType,
28
28
  MAX_FRAME_BYTES: () => MAX_FRAME_BYTES,
29
+ MAX_STREAM_BUFFER_BYTES: () => MAX_STREAM_BUFFER_BYTES,
29
30
  PROTOCOL_VERSION: () => PROTOCOL_VERSION,
30
31
  Reader: () => Reader,
32
+ StreamDecoder: () => StreamDecoder,
31
33
  Utf8Error: () => Utf8Error,
32
34
  WIRE_FIXED32: () => WIRE_FIXED32,
33
35
  WIRE_FIXED64: () => WIRE_FIXED64,
@@ -373,6 +375,7 @@ var FrameError = class extends Error {
373
375
  }
374
376
  };
375
377
  var MIN_HEADER_BYTES = 5;
378
+ var MAX_STREAM_BUFFER_BYTES = MAX_FRAME_BYTES * 2 + 64;
376
379
  function encodeFrame(frame) {
377
380
  if (!Number.isInteger(frame.type) || frame.type < 0 || frame.type > 15) {
378
381
  throw new FrameError(`\u975E\u6CD5\u5E27\u7C7B\u578B: ${frame.type}`);
@@ -451,8 +454,86 @@ function frameTypeFromName(name) {
451
454
  if (!(name in FrameType)) throw new FrameError(`\u672A\u77E5\u5E27\u7C7B\u578B\u540D: ${name}`);
452
455
  return FrameType[name];
453
456
  }
457
+ function peekVarint(b, at) {
458
+ let value = 0n;
459
+ let shift = 0n;
460
+ for (let i = 0; i < 10; i++) {
461
+ if (at + i >= b.length) return null;
462
+ const byte = b[at + i];
463
+ if (i === 9 && byte > 1) return "bad";
464
+ value |= BigInt(byte & 127) << shift;
465
+ if ((byte & 128) === 0) {
466
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) return "bad";
467
+ return { value: Number(value), size: i + 1 };
468
+ }
469
+ shift += 7n;
470
+ }
471
+ return "bad";
472
+ }
473
+ var StreamDecoder = class {
474
+ constructor(maxBuffer = MAX_STREAM_BUFFER_BYTES) {
475
+ this.maxBuffer = maxBuffer;
476
+ }
477
+ maxBuffer;
478
+ buf = new Uint8Array(0);
479
+ /** 已缓存但尚未解出的字节数 */
480
+ get buffered() {
481
+ return this.buf.length;
482
+ }
483
+ /** 丢弃缓存(协议错误后重新同步用) */
484
+ reset() {
485
+ this.buf = new Uint8Array(0);
486
+ }
487
+ push(chunk) {
488
+ if (this.buf.length === 0) {
489
+ this.buf = chunk.slice();
490
+ } else {
491
+ const next = new Uint8Array(this.buf.length + chunk.length);
492
+ next.set(this.buf, 0);
493
+ next.set(chunk, this.buf.length);
494
+ this.buf = next;
495
+ }
496
+ if (this.buf.length > this.maxBuffer) {
497
+ throw new FrameError(`\u63A5\u6536\u7F13\u51B2\u8D85\u9650: ${this.buf.length} > ${this.maxBuffer}`);
498
+ }
499
+ }
500
+ /** 解出下一帧;不足返回 `null`。协议错误抛 `FrameError`。 */
501
+ nextFrame() {
502
+ const b = this.buf;
503
+ if (b.length < MIN_HEADER_BYTES) return null;
504
+ if (b[0] !== FRAME_MAGIC[0] || b[1] !== FRAME_MAGIC[1]) {
505
+ throw new FrameError("magic \u4E0D\u7B26\uFF08\u975E\u672C\u534F\u8BAE\u6D41\u91CF\uFF09");
506
+ }
507
+ const verType = b[2];
508
+ const version = verType >> 4;
509
+ const type = verType & 15;
510
+ if (version !== PROTOCOL_VERSION) {
511
+ throw new FrameError(`\u4E0D\u652F\u6301\u7684\u534F\u8BAE\u7248\u672C: ${version}`);
512
+ }
513
+ if (!KNOWN_TYPES.has(type)) {
514
+ throw new FrameError(`\u672A\u5B9A\u4E49\u7684\u5E27\u7C7B\u578B: ${type}`);
515
+ }
516
+ const seqPeek = peekVarint(b, 3);
517
+ if (seqPeek === null) return null;
518
+ if (seqPeek === "bad") throw new FrameError("\u5E27\u5934 varint \u975E\u6CD5: seq");
519
+ const lenPeek = peekVarint(b, 3 + seqPeek.size);
520
+ if (lenPeek === null) return null;
521
+ if (lenPeek === "bad") throw new FrameError("\u5E27\u5934 varint \u975E\u6CD5: len");
522
+ if (lenPeek.value > MAX_FRAME_BYTES) {
523
+ throw new FrameError(`\u8F7D\u8377\u8D85\u9650: ${lenPeek.value} > ${MAX_FRAME_BYTES}`);
524
+ }
525
+ const header = 3 + seqPeek.size + lenPeek.size;
526
+ const total = header + lenPeek.value;
527
+ if (b.length < total) return null;
528
+ const payload = b.slice(header, total);
529
+ this.buf = b.subarray(total);
530
+ return { type, seq: seqPeek.value, payload };
531
+ }
532
+ };
454
533
 
455
534
  // src/wire/messages.ts
535
+ var MSG_KIND_NODE_STATE = 1;
536
+ var MSG_KIND_STATUS = 2;
456
537
  function encodeEnvelope(env) {
457
538
  const w = new Writer(128);
458
539
  w.uint64Field(1, env.t);
@@ -578,6 +659,7 @@ function encodeStatus(st) {
578
659
  w.stringField(6, st.mode ?? "");
579
660
  w.stringField(7, st.version ?? "");
580
661
  w.stringField(8, st.ip ?? "");
662
+ w.uint64Field(9, MSG_KIND_STATUS);
581
663
  return w.finish();
582
664
  }
583
665
  function decodeStatus(bytes) {
@@ -618,6 +700,11 @@ function decodeStatus(bytes) {
618
700
  if (wire !== WIRE_LEN) r.skip(wire);
619
701
  else st.ip = r.string();
620
702
  break;
703
+ case 9: {
704
+ if (wire !== WIRE_VARINT) r.skip(wire);
705
+ else checkMsgKind("Status", Number(r.varint()), MSG_KIND_STATUS);
706
+ break;
707
+ }
621
708
  default:
622
709
  r.skip(wire);
623
710
  }
@@ -957,6 +1044,7 @@ function encodeNodeState(n) {
957
1044
  w.stringField(5, n.version ?? "");
958
1045
  w.stringField(6, n.ip ?? "");
959
1046
  w.bytesField(7, n.detail ?? EMPTY);
1047
+ w.uint64Field(9, MSG_KIND_NODE_STATE);
960
1048
  return w.finish();
961
1049
  }
962
1050
  function decodeNodeState(bytes) {
@@ -993,12 +1081,24 @@ function decodeNodeState(bytes) {
993
1081
  if (wire !== WIRE_LEN) r.skip(wire);
994
1082
  else n.detail = r.lenPrefixed();
995
1083
  break;
1084
+ case 9: {
1085
+ if (wire !== WIRE_VARINT) r.skip(wire);
1086
+ else checkMsgKind("NodeState", Number(r.varint()), MSG_KIND_NODE_STATE);
1087
+ break;
1088
+ }
996
1089
  default:
997
1090
  r.skip(wire);
998
1091
  }
999
1092
  }
1000
1093
  return n;
1001
1094
  }
1095
+ function checkMsgKind(label, actual, expected) {
1096
+ if (actual !== 0 && actual !== expected) {
1097
+ throw new WireError(
1098
+ `${label} \u5E27\u7684\u8EAB\u4EFD\u6807\u8BB0\u4E0D\u7B26\uFF08msg_kind=${actual}\uFF0C\u671F\u671B ${expected}\uFF09\uFF1A\u5F88\u53EF\u80FD\u7528\u9519\u4E86\u89E3\u7801\u5668`
1099
+ );
1100
+ }
1101
+ }
1002
1102
  function encodeSnapshot(snap) {
1003
1103
  const w = new Writer(128);
1004
1104
  for (const node of snap.nodes) {
@@ -1109,8 +1209,10 @@ function fromHex(hex) {
1109
1209
  FrameError,
1110
1210
  FrameType,
1111
1211
  MAX_FRAME_BYTES,
1212
+ MAX_STREAM_BUFFER_BYTES,
1112
1213
  PROTOCOL_VERSION,
1113
1214
  Reader,
1215
+ StreamDecoder,
1114
1216
  Utf8Error,
1115
1217
  WIRE_FIXED32,
1116
1218
  WIRE_FIXED64,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/wire/index.ts","../../src/wire/utf8.ts","../../src/wire/varint.ts","../../src/wire/frame.ts","../../src/wire/messages.ts","../../src/wire/hex.ts"],"sourcesContent":["/**\n * 线协议 v1:帧 + 消息编解码(node: 无依赖)\n *\n * 权威契约见 proto/fleet.proto,规范见 docs/wire-protocol.md。\n *\n * 本模块**平台中立**:只用 `Uint8Array`,不 import 任何 Node 内置模块,因此\n * Node(节点/core/hub)、浏览器(console-core/portal)、小程序三处共用同一份实现。\n * 平台相关的部分只有签名——Node 侧见 `./node.js`,浏览器/小程序侧用 Web Crypto。\n */\nexport {\n Writer,\n Reader,\n WireError,\n WIRE_VARINT,\n WIRE_FIXED32,\n WIRE_FIXED64,\n WIRE_LEN,\n EMPTY_BYTES,\n} from \"./varint.js\";\nexport {\n FRAME_MAGIC,\n PROTOCOL_VERSION,\n MAX_FRAME_BYTES,\n CAP_DEFLATE,\n FrameType,\n FrameError,\n encodeFrame,\n decodeFrame,\n encodeCompressedPayload,\n decodeCompressedPayload,\n frameTypeName,\n frameTypeFromName,\n type Frame,\n type FrameTypeName,\n type FrameTypeValue,\n} from \"./frame.js\";\nexport {\n encodeEnvelope,\n decodeEnvelope,\n signableBytes,\n encodeAck,\n decodeAck,\n encodeStatus,\n decodeStatus,\n encodeEvent,\n decodeEvent,\n encodeInfo,\n decodeInfo,\n encodeNotify,\n decodeNotify,\n encodeTerminalData,\n decodeTerminalData,\n encodeAuth,\n decodeAuth,\n signableAuthBytes,\n encodeAuthOk,\n decodeAuthOk,\n encodeNodeState,\n decodeNodeState,\n encodeSnapshot,\n decodeSnapshot,\n encodeSubscribe,\n decodeSubscribe,\n decodeSubscribeDetail,\n encodeUnsubscribe,\n decodeUnsubscribe,\n encodeResume,\n decodeResume,\n type Envelope,\n type Ack,\n type Status,\n type EventMsg,\n type Info,\n type NotifyMsg,\n type TerminalData,\n type Auth,\n type AuthOk,\n type NodeState,\n type Snapshot,\n} from \"./messages.js\";\nexport { utf8Encode, utf8Decode, Utf8Error } from \"./utf8.js\";\nexport { toHex, fromHex } from \"./hex.js\";\n","/**\n * UTF-8 编解码(手工实现,零依赖)\n *\n * 不依赖 TextEncoder/TextDecoder:小程序的 JS 运行时(部分基础库)不保证提供这两个全局,\n * 而本模块必须能被 Node / 浏览器 / 小程序三处共用。严格校验(拒绝孤立代理项、过长编码、\n * 超出码点范围)以对齐 protobuf 对 `string` 字段的 UTF-8 要求。\n */\n\nexport class Utf8Error extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"Utf8Error\";\n }\n}\n\n/** 字符串 → UTF-8 字节 */\nexport function utf8Encode(s: string): Uint8Array {\n const buf = new Uint8Array(s.length * 4); // 每字符最多 4 字节(上界)\n let n = 0;\n for (let i = 0; i < s.length; i++) {\n let cp = s.charCodeAt(i);\n if (cp >= 0xd800 && cp <= 0xdbff) {\n const lo = i + 1 < s.length ? s.charCodeAt(i + 1) : 0;\n if (lo < 0xdc00 || lo > 0xdfff) throw new Utf8Error(\"孤立的 UTF-16 高代理项\");\n cp = 0x10000 + ((cp - 0xd800) << 10) + (lo - 0xdc00);\n i++;\n } else if (cp >= 0xdc00 && cp <= 0xdfff) {\n throw new Utf8Error(\"孤立的 UTF-16 低代理项\");\n }\n if (cp < 0x80) {\n buf[n++] = cp;\n } else if (cp < 0x800) {\n buf[n++] = 0xc0 | (cp >> 6);\n buf[n++] = 0x80 | (cp & 0x3f);\n } else if (cp < 0x10000) {\n buf[n++] = 0xe0 | (cp >> 12);\n buf[n++] = 0x80 | ((cp >> 6) & 0x3f);\n buf[n++] = 0x80 | (cp & 0x3f);\n } else {\n buf[n++] = 0xf0 | (cp >> 18);\n buf[n++] = 0x80 | ((cp >> 12) & 0x3f);\n buf[n++] = 0x80 | ((cp >> 6) & 0x3f);\n buf[n++] = 0x80 | (cp & 0x3f);\n }\n }\n return buf.slice(0, n);\n}\n\n/** UTF-8 字节 → 字符串(严格校验) */\nexport function utf8Decode(b: Uint8Array): string {\n let out = \"\";\n let i = 0;\n while (i < b.length) {\n const c = b[i]!;\n if (c < 0x80) {\n out += String.fromCharCode(c);\n i++;\n continue;\n }\n let cp: number;\n let need: number;\n let min: number;\n if ((c & 0xe0) === 0xc0) {\n cp = c & 0x1f;\n need = 1;\n min = 0x80;\n } else if ((c & 0xf0) === 0xe0) {\n cp = c & 0x0f;\n need = 2;\n min = 0x800;\n } else if ((c & 0xf8) === 0xf0) {\n cp = c & 0x07;\n need = 3;\n min = 0x10000;\n } else {\n throw new Utf8Error(`非法 UTF-8 起始字节 0x${c.toString(16)}`);\n }\n if (i + need >= b.length) throw new Utf8Error(\"UTF-8 序列被截断\");\n for (let k = 1; k <= need; k++) {\n const cc = b[i + k]!;\n if ((cc & 0xc0) !== 0x80) throw new Utf8Error(`非法 UTF-8 续接字节 0x${cc.toString(16)}`);\n cp = (cp << 6) | (cc & 0x3f);\n }\n if (cp < min) throw new Utf8Error(\"UTF-8 过长编码(overlong)\");\n if (cp > 0x10ffff) throw new Utf8Error(\"码点超出 U+10FFFF\");\n if (cp >= 0xd800 && cp <= 0xdfff) throw new Utf8Error(\"UTF-8 编码了 UTF-16 代理项\");\n i += need + 1;\n if (cp < 0x10000) {\n out += String.fromCharCode(cp);\n } else {\n const v = cp - 0x10000;\n out += String.fromCharCode(0xd800 + (v >> 10), 0xdc00 + (v & 0x3ff));\n }\n }\n return out;\n}\n","/**\n * 最小 protobuf 原语(varint + length-delimited 读写,零依赖)\n *\n * Node 与浏览器/小程序共用:只用 `Uint8Array`(`Buffer` 是其子类)与 `DataView`,\n * 不触碰任何平台 API。编码规则严格对齐 proto3 线格式(默认值省略、字段号升序),\n * 以便与 Rust 侧 `prost` 产出**逐字节一致**的结果(见 docs/wire-protocol.md §5)。\n */\nimport { utf8Encode, utf8Decode } from \"./utf8.js\";\n\nexport const WIRE_VARINT = 0;\nexport const WIRE_FIXED64 = 1;\nexport const WIRE_LEN = 2;\nexport const WIRE_FIXED32 = 5;\n\nexport class WireError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WireError\";\n }\n}\n\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\nconst EMPTY = new Uint8Array(0);\n\n/** 增量字节写入器(自动扩容) */\nexport class Writer {\n private buf: Uint8Array;\n private len = 0;\n\n constructor(initialCapacity = 64) {\n this.buf = new Uint8Array(Math.max(8, initialCapacity));\n }\n\n private ensure(n: number): void {\n if (this.len + n <= this.buf.length) return;\n let cap = this.buf.length * 2;\n while (cap < this.len + n) cap *= 2;\n const next = new Uint8Array(cap);\n next.set(this.buf.subarray(0, this.len));\n this.buf = next;\n }\n\n /** 裸字节(帧头用,不带任何前缀) */\n u8(b: number): void {\n this.ensure(1);\n this.buf[this.len++] = b & 0xff;\n }\n\n raw(b: Uint8Array): void {\n this.ensure(b.length);\n this.buf.set(b, this.len);\n this.len += b.length;\n }\n\n /** 无符号 varint(接受 number 或 bigint) */\n varint(v: number | bigint): void {\n let x = typeof v === \"bigint\" ? v : BigInt(v);\n if (x < 0n) throw new WireError(\"varint 不接受负值\");\n this.ensure(10);\n while (x >= 0x80n) {\n this.buf[this.len++] = Number((x & 0x7fn) | 0x80n);\n x >>= 7n;\n }\n this.buf[this.len++] = Number(x);\n }\n\n tag(field: number, wire: number): void {\n this.varint((field << 3) | wire);\n }\n\n /** length-delimited:长度 varint + 内容 */\n lenPrefixed(b: Uint8Array): void {\n this.varint(b.length);\n this.raw(b);\n }\n\n // ---- proto3 字段:默认值不写线 ----\n\n uint64Field(field: number, v: number | bigint): void {\n const x = typeof v === \"bigint\" ? v : BigInt(v);\n if (x === 0n) return;\n this.tag(field, WIRE_VARINT);\n this.varint(x);\n }\n\n boolField(field: number, v: boolean): void {\n if (!v) return;\n this.tag(field, WIRE_VARINT);\n this.varint(1);\n }\n\n stringField(field: number, v: string): void {\n if (v === \"\") return;\n this.tag(field, WIRE_LEN);\n this.lenPrefixed(utf8Encode(v));\n }\n\n bytesField(field: number, v: Uint8Array): void {\n if (v.length === 0) return;\n this.tag(field, WIRE_LEN);\n this.lenPrefixed(v);\n }\n\n finish(): Uint8Array {\n return this.buf.slice(0, this.len);\n }\n\n get length(): number {\n return this.len;\n }\n}\n\n/** 顺序字节读取器(越界一律判错) */\nexport class Reader {\n private pos = 0;\n\n constructor(private readonly buf: Uint8Array) {}\n\n get remaining(): number {\n return this.buf.length - this.pos;\n }\n\n get eof(): boolean {\n return this.pos >= this.buf.length;\n }\n\n varint(): bigint {\n let shift = 0n;\n let result = 0n;\n for (let i = 0; i < 10; i++) {\n if (this.pos >= this.buf.length) throw new WireError(\"varint 越界\");\n const b = this.buf[this.pos++]!;\n result |= BigInt(b & 0x7f) << shift;\n if ((b & 0x80) === 0) {\n if (i === 9 && b > 1) throw new WireError(\"varint 溢出(超过 64 位)\");\n return result;\n }\n shift += 7n;\n }\n throw new WireError(\"varint 超过 10 字节\");\n }\n\n /** u64 → number(超安全整数范围即判错,避免静默精度丢失) */\n u64(): number {\n const v = this.varint();\n if (v > MAX_SAFE) throw new WireError(`u64 超出 JS 安全整数范围: ${v}`);\n return Number(v);\n }\n\n tag(): { field: number; wire: number } {\n const t = this.varint();\n const field = Number(t >> 3n);\n const wire = Number(t & 7n);\n if (field <= 0) throw new WireError(\"字段号必须 ≥ 1\");\n return { field, wire };\n }\n\n /** 取 n 个字节(越界判错) */\n take(n: number): Uint8Array {\n if (!Number.isInteger(n) || n < 0) throw new WireError(`非法长度: ${n}`);\n if (this.pos + n > this.buf.length) {\n throw new WireError(`读取越界:需要 ${n} 字节,剩余 ${this.buf.length - this.pos}`);\n }\n const out = this.buf.subarray(this.pos, this.pos + n);\n this.pos += n;\n return out;\n }\n\n /** length-delimited:读长度再取其内容 */\n lenPrefixed(): Uint8Array {\n return this.take(this.u64());\n }\n\n string(): string {\n return utf8Decode(this.lenPrefixed());\n }\n\n /** 跳过未知字段(前向兼容的关键:未来新增字段号不应导致解析失败) */\n skip(wire: number): void {\n switch (wire) {\n case WIRE_VARINT:\n this.varint();\n return;\n case WIRE_LEN:\n this.lenPrefixed();\n return;\n case WIRE_FIXED64:\n this.take(8);\n return;\n case WIRE_FIXED32:\n this.take(4);\n return;\n default:\n throw new WireError(`不支持的 wire type: ${wire}`);\n }\n }\n}\n\nexport { EMPTY as EMPTY_BYTES };\n","/**\n * 帧编解码(magic + ver/type + seq + len + payload)\n *\n * 规范见 docs/wire-protocol.md §1/§6。节点面与终端面共用同一套帧。\n */\nimport { Reader, Writer, WireError } from \"./varint.js\";\n\n/** ASCII \"ZQ\":用于在公网暴露面上廉价丢弃非法流量 */\nexport const FRAME_MAGIC = [0x5a, 0x51] as const;\nexport const PROTOCOL_VERSION = 1;\n/**\n * 载荷上限:16MB。\n *\n * 需要容纳聊天附件(单次最多 10MB 原文件 → base64 约 13.4MB)。\n * 节点上报的事件仍受各自更小的业务上限约束,这里只是帧级防线。\n */\nexport const MAX_FRAME_BYTES = 16 * 1024 * 1024;\n\n/**\n * 能力位(`Auth.caps` / `AuthOk.caps`):对端声明支持帧级压缩。\n *\n * 压缩帧用 type 0(`COMPRESSED`)承载,旧对端收到会当未知类型安全丢弃——\n * 不崩,但会**静默丢消息**。因此必须先协商,确认双方都支持才发送。\n */\nexport const CAP_DEFLATE = 1 << 0;\n\n/** 帧类型(低 4 位)。M1 已实现载荷的消息见 docs/wire-protocol.md §3 */\nexport const FrameType = {\n /**\n * 帧级压缩容器(原 `HELLO` 占位,从未实现握手)。\n *\n * payload = `[内部帧类型 1 字节][deflate-raw 压缩后的内部 payload]`;\n * seq 沿用内层帧的 seq,解压后与原帧语义完全一致。\n */\n COMPRESSED: 0,\n AUTH: 1,\n SNAPSHOT: 2,\n STATUS: 3,\n INFO: 4,\n EVENT: 5,\n NOTIFY: 6,\n CMD: 7,\n ACK: 8,\n SUBSCRIBE: 9,\n UNSUBSCRIBE: 10,\n RESUME: 11,\n PING: 12,\n PONG: 13,\n /** 握手结果(服务端 → 客户端)。与 AUTH 分开,避免「同类型双向」的解析歧义 */\n AUTH_OK: 14,\n /**\n * 命令终端数据(`TerminalData`)。\n *\n * 注意低 4 位的 16 个取值到此用尽:之后再扩帧类型只能升协议版本。\n * 与 `EVENT` 分开是**性能隔离**(终端数据不进事件环形缓冲、不分配全局游标、\n * 不走事件扇出队列),理由见 `proto/fleet.proto` 的 `TerminalData`。\n */\n TERMINAL: 15,\n} as const;\nexport type FrameTypeName = keyof typeof FrameType;\nexport type FrameTypeValue = (typeof FrameType)[FrameTypeName];\n\nconst KNOWN_TYPES = new Set<number>(Object.values(FrameType));\n\nexport class FrameError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameError\";\n }\n}\n\nexport interface Frame {\n type: FrameTypeValue;\n /** 单调递增序号(用于去重与断线续传定位) */\n seq: number;\n payload: Uint8Array;\n}\n\n/** 帧头长度下界:magic(2) + ver/type(1) + seq(≥1) + len(≥1) */\nconst MIN_HEADER_BYTES = 5;\n\nexport function encodeFrame(frame: {\n type: number;\n seq: number;\n payload: Uint8Array;\n}): Uint8Array {\n if (!Number.isInteger(frame.type) || frame.type < 0 || frame.type > 15) {\n throw new FrameError(`非法帧类型: ${frame.type}`);\n }\n if (frame.payload.length > MAX_FRAME_BYTES) {\n throw new FrameError(`载荷超限: ${frame.payload.length} > ${MAX_FRAME_BYTES}`);\n }\n const w = new Writer(frame.payload.length + MIN_HEADER_BYTES);\n w.u8(FRAME_MAGIC[0]);\n w.u8(FRAME_MAGIC[1]);\n w.u8((PROTOCOL_VERSION << 4) | frame.type);\n w.varint(frame.seq);\n w.varint(frame.payload.length);\n w.raw(frame.payload);\n return w.finish();\n}\n\n/**\n * 解码入口:**先校验头部再分配**——`len` 在分配/切分前就与实际上限和剩余字节比对,\n * 避免畸形头部引发的大内存分配。\n */\nexport function decodeFrame(bytes: Uint8Array): Frame {\n if (bytes.length < MIN_HEADER_BYTES) {\n throw new FrameError(`帧过短: ${bytes.length} 字节`);\n }\n if (bytes[0] !== FRAME_MAGIC[0] || bytes[1] !== FRAME_MAGIC[1]) {\n throw new FrameError(\"magic 不符(非本协议流量)\");\n }\n const verType = bytes[2]!;\n const version = verType >> 4;\n const type = verType & 0x0f;\n if (version !== PROTOCOL_VERSION) {\n throw new FrameError(`不支持的协议版本: ${version}`);\n }\n if (!KNOWN_TYPES.has(type)) {\n throw new FrameError(`未定义的帧类型: ${type}`);\n }\n\n let r: Reader;\n let seq: number;\n let len: number;\n try {\n r = new Reader(bytes.subarray(3));\n seq = r.u64();\n len = r.u64();\n } catch (e) {\n throw new FrameError(`帧头解析失败: ${e instanceof WireError ? e.message : String(e)}`);\n }\n if (len > MAX_FRAME_BYTES) {\n throw new FrameError(`载荷超限: ${len} > ${MAX_FRAME_BYTES}`);\n }\n if (r.remaining !== len) {\n throw new FrameError(`len(${len}) 与剩余字节(${r.remaining})不符`);\n }\n const payload = r.take(len);\n return { type: type as FrameTypeValue, seq, payload };\n}\n\n/** 帧类型名(日志/向量文件用) */\nexport function frameTypeName(type: number): FrameTypeName {\n for (const [name, value] of Object.entries(FrameType)) {\n if (value === type) return name as FrameTypeName;\n }\n throw new FrameError(`未定义的帧类型: ${type}`);\n}\n\n// ===================== 帧级压缩容器 =====================\n//\n// 只做**结构**编解码,压缩/解压本身由调用方完成(Node 用 `node:zlib`,\n// 浏览器侧暂无同步实现故不启用)。这样本文件保持零依赖,可直接打进前端包。\n/**\n * 组装 `COMPRESSED` 容器的 payload:`[内部类型 1 字节][deflate-raw 字节]`。\n *\n * @param innerType 内部帧类型(不能是 COMPRESSED,禁止嵌套)\n * @param deflated 用 **raw deflate**(无 zlib 头)压缩后的内部 payload\n */\nexport function encodeCompressedPayload(innerType: number, deflated: Uint8Array): Uint8Array {\n if (innerType === FrameType.COMPRESSED) {\n throw new FrameError(\"压缩帧不得嵌套\");\n }\n const out = new Uint8Array(deflated.length + 1);\n out[0] = innerType;\n out.set(deflated, 1);\n return out;\n}\n\n/**\n * 拆出内部类型与 deflate 字节。结构非法时返回 null(调用方丢帧并计数)。\n *\n * 注意这里**不解压**:解压后的体积上限由调用方按 `MAX_FRAME_BYTES` 校验。\n */\nexport function decodeCompressedPayload(\n payload: Uint8Array,\n): { type: number; deflated: Uint8Array } | null {\n if (payload.length < 2) return null;\n const type = payload[0]!;\n if (type === FrameType.COMPRESSED) return null;\n if (!KNOWN_TYPES.has(type)) return null;\n return { type, deflated: payload.subarray(1) };\n}\n\n/** 帧类型名 → 值(向量文件用) */\nexport function frameTypeFromName(name: string): FrameTypeValue {\n // type 0 在压缩落地前叫 HELLO(占位、从未实现):保留旧名解析,\n // 避免历史向量/日志解析失败。\n if (name === \"HELLO\") return FrameType.COMPRESSED;\n if (!(name in FrameType)) throw new FrameError(`未知帧类型名: ${name}`);\n return FrameType[name as FrameTypeName];\n}\n","/**\n * 消息编解码(Envelope / Ack / Status / Event)\n *\n * 字段定义见 proto/fleet.proto。手写编解码,规则与 prost 对齐(proto3 默认值省略、\n * 字段号升序、string 严格 UTF-8),未知字段按 wire type 跳过以支持前向兼容。\n *\n * 签名:`signableBytes()` 给出「不含 sig」的编码字节;`sig` 是 10 号字段(最后),\n * 因此 `encode(env, sig 置空) === signableBytes(env)` 恒成立,校验方可重编码比对。\n */\nimport { Reader, Writer, WIRE_LEN, WIRE_VARINT, WireError, EMPTY_BYTES } from \"./varint.js\";\n\n/** 与现有 FleetCmdEnvelope(packages/shared/src/fleet.ts:159-178)语义一致 */\nexport interface Envelope {\n /** 毫秒时间戳 */\n t: number;\n nonce: string;\n reqId: string;\n type: string;\n clientId: string;\n nodeId: string;\n projectId?: string;\n sessionId?: string;\n /** 载荷字节(按 type 选择强类型消息或 JSON 字节) */\n payload?: Uint8Array;\n /**\n * 执行预算(毫秒,可选):由发起方指定,网关据此决定等待回执的上限。\n * 0/缺省表示按 `type` 的默认分级(见 docs/wire-protocol.md §5.2)。\n */\n timeoutMs?: number;\n /** HMAC-SHA256 原始 32 字节(**必须是最后一个字段**:其前缀即签名字节) */\n sig?: Uint8Array;\n}\n\nexport interface Ack {\n reqId: string;\n type: string;\n ok: boolean;\n error?: string;\n data?: Uint8Array;\n}\n\nexport interface Status {\n nodeId: string;\n online: boolean;\n /** 毫秒时间戳(现有 JSON 协议为 ISO 字符串,映射在 M2) */\n ts: number;\n label?: string;\n platform?: string;\n mode?: string;\n version?: string;\n ip?: string;\n}\n\nexport interface EventMsg {\n seq: number;\n ts: number;\n type: string;\n projectId?: string;\n sessionId?: string;\n data?: Uint8Array;\n /**\n * 事件来源节点。由**网关**按连接绑定的 nodeId 填充(节点上行时留空)。\n *\n * 终端面一条连接可订阅多个节点,缺了它就无法分辨事件来自哪台节点。\n */\n nodeId?: string;\n}\n\n/**\n * 命令终端数据(`FrameType.TERMINAL`)。\n *\n * 与 `EventMsg` 完全平行的另一条通道,**不是** Event 的一种:它不参与\n * seq 游标、不入事件环形缓冲、不跨副本广播(理由见 proto 注释)。\n */\nexport interface TerminalData {\n /** 目标节点;节点上行时留空,由网关按连接绑定填充 */\n nodeId?: string;\n /** 终端实例 ID(节点侧生成,`t_` 前缀;与会话 ID 不同空间) */\n terminalId: string;\n /**\n * 帧种类:\n * opened | data | exited | error —— 节点 → 网关 → 终端\n * input | resize —— 终端 → 网关 → 节点\n *\n * 开/关终端不走这条通道(见 `terminal_create` / `terminal_close` 指令)。\n */\n kind: string;\n /** data/input 为原始字节;resize 为 JSON 字节({\"cols\":N,\"rows\":N}) */\n data?: Uint8Array;\n /** 终端内局部序号(仅该终端内有效,不参与 resume);文件流中为 stream_id */\n seq?: number;\n /**\n * 通道:0/缺省 = 终端;1 = 文件流(音视频预览)。\n *\n * 文件流复用 TERMINAL 帧以避开协议版本升级(帧类型低 4 位已用尽),\n * 但网关按该字段分流,不会 fanout 给终端连接。\n */\n channel?: number;\n /**\n * P2P 打洞信令(`channel=2`)的会话标识。\n *\n * 网关按它把信令**回发给发起连接**,不 fanout——否则双方公网 IP 会泄漏给\n * 同一节点的其他协作者。\n */\n session?: string;\n}\n\n// ===================== Envelope =====================\n\nexport function encodeEnvelope(env: Envelope): Uint8Array {\n const w = new Writer(128);\n w.uint64Field(1, env.t);\n w.stringField(2, env.nonce);\n w.stringField(3, env.reqId);\n w.stringField(4, env.type);\n w.stringField(5, env.clientId);\n w.stringField(6, env.nodeId);\n w.stringField(7, env.projectId ?? \"\");\n w.stringField(8, env.sessionId ?? \"\");\n w.bytesField(9, env.payload ?? EMPTY_BYTES);\n w.uint64Field(10, env.timeoutMs ?? 0);\n w.bytesField(11, env.sig ?? EMPTY_BYTES);\n return w.finish();\n}\n\n/** 参与签名的字节(字段 1..10,不含 sig) */\nexport function signableBytes(env: Envelope): Uint8Array {\n return encodeEnvelope({ ...env, sig: undefined });\n}\n\nexport function decodeEnvelope(bytes: Uint8Array): Envelope {\n const r = new Reader(bytes);\n const env: Envelope = { t: 0, nonce: \"\", reqId: \"\", type: \"\", clientId: \"\", nodeId: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else env.t = r.u64();\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.nonce = r.string();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.reqId = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.type = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.clientId = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.nodeId = r.string();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.projectId = r.string();\n break;\n case 8:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.sessionId = r.string();\n break;\n case 9:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.payload = r.lenPrefixed();\n break;\n case 10:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else env.timeoutMs = r.u64();\n break;\n case 11:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.sig = r.lenPrefixed();\n break;\n default:\n r.skip(wire);\n }\n }\n return env;\n}\n\n// ===================== Ack =====================\n\nexport function encodeAck(ack: Ack): Uint8Array {\n const w = new Writer(64);\n w.stringField(1, ack.reqId);\n w.stringField(2, ack.type);\n w.boolField(3, ack.ok);\n w.stringField(4, ack.error ?? \"\");\n w.bytesField(5, ack.data ?? EMPTY_BYTES);\n return w.finish();\n}\n\nexport function decodeAck(bytes: Uint8Array): Ack {\n const r = new Reader(bytes);\n const ack: Ack = { reqId: \"\", type: \"\", ok: false };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ack.reqId = r.string();\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ack.type = r.string();\n break;\n case 3:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else ack.ok = r.varint() !== 0n;\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ack.error = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ack.data = r.lenPrefixed();\n break;\n default:\n r.skip(wire);\n }\n }\n return ack;\n}\n\n// ===================== Status =====================\n\nexport function encodeStatus(st: Status): Uint8Array {\n const w = new Writer(96);\n w.stringField(1, st.nodeId);\n w.boolField(2, st.online);\n w.uint64Field(3, st.ts);\n w.stringField(4, st.label ?? \"\");\n w.stringField(5, st.platform ?? \"\");\n w.stringField(6, st.mode ?? \"\");\n w.stringField(7, st.version ?? \"\");\n w.stringField(8, st.ip ?? \"\");\n return w.finish();\n}\n\nexport function decodeStatus(bytes: Uint8Array): Status {\n const r = new Reader(bytes);\n const st: Status = { nodeId: \"\", online: false, ts: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.nodeId = r.string();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else st.online = r.varint() !== 0n;\n break;\n case 3:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else st.ts = r.u64();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.label = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.platform = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.mode = r.string();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.version = r.string();\n break;\n case 8:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.ip = r.string();\n break;\n default:\n r.skip(wire);\n }\n }\n return st;\n}\n\n// ===================== Event =====================\n\nexport function encodeEvent(ev: EventMsg): Uint8Array {\n const w = new Writer(128);\n w.uint64Field(1, ev.seq);\n w.uint64Field(2, ev.ts);\n w.stringField(3, ev.type);\n w.stringField(4, ev.projectId ?? \"\");\n w.stringField(5, ev.sessionId ?? \"\");\n w.bytesField(6, ev.data ?? EMPTY_BYTES);\n w.stringField(7, ev.nodeId ?? \"\");\n return w.finish();\n}\n\nexport function decodeEvent(bytes: Uint8Array): EventMsg {\n const r = new Reader(bytes);\n const ev: EventMsg = { seq: 0, ts: 0, type: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else ev.seq = r.u64();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else ev.ts = r.u64();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.type = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.projectId = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.sessionId = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.data = r.lenPrefixed();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.nodeId = r.string();\n break;\n default:\n r.skip(wire);\n }\n }\n return ev;\n}\n\nexport { WireError };\n\n// ===================== 节点能力/项目快照 =====================\n\nexport interface Info {\n nodeId: string;\n platform?: string;\n version?: string;\n ip?: string;\n /** 项目数 */\n projects: number;\n /** 会话数 */\n sessions: number;\n /** 运行中的会话数 */\n running: number;\n /** 等待审批/提问的会话数 */\n waiting: number;\n /** 毫秒时间戳 */\n ts: number;\n /**\n * 节点上报的**原始 info JSON**(含 label / 项目明细 / stats / usage)。\n *\n * 5..9 的计数供网关快速聚合;本字段原样承载完整快照,供控制面读取\n * (替代从前经 MQTT retained info 的那条路径),避免为视图反复改 schema。\n */\n detail?: Uint8Array;\n}\n\nexport function encodeInfo(info: Info): Uint8Array {\n const w = new Writer(96);\n w.stringField(1, info.nodeId);\n w.stringField(2, info.platform ?? \"\");\n w.stringField(3, info.version ?? \"\");\n w.stringField(4, info.ip ?? \"\");\n w.uint64Field(5, info.projects);\n w.uint64Field(6, info.sessions);\n w.uint64Field(7, info.running);\n w.uint64Field(8, info.waiting);\n w.uint64Field(9, info.ts);\n w.bytesField(10, info.detail ?? EMPTY_BYTES);\n return w.finish();\n}\n\nexport function decodeInfo(bytes: Uint8Array): Info {\n const r = new Reader(bytes);\n const info: Info = { nodeId: \"\", projects: 0, sessions: 0, running: 0, waiting: 0, ts: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.nodeId = r.string();\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.platform = r.string();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.version = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.ip = r.string();\n break;\n case 5:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.projects = r.u64();\n break;\n case 6:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.sessions = r.u64();\n break;\n case 7:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.running = r.u64();\n break;\n case 8:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.waiting = r.u64();\n break;\n case 9:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.ts = r.u64();\n break;\n case 10:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.detail = r.lenPrefixed();\n break;\n default:\n r.skip(wire);\n }\n }\n return info;\n}\n\n// ===================== 通知(需可靠送达的上行) =====================\n\n/**\n * 节点通知:审批请求 / 提问 / 回合完成 / 错误。\n *\n * 与 `EventMsg` 的分工:Event 是高频实时进度,Notify 是低频但重要(审批/提问挂起必须\n * 让终端看到)。两者共用网关分配的 `seq` 游标与缓冲,因此 `resume` 时都能回放。\n */\nexport interface NotifyMsg {\n /** 由网关分配的游标(节点上报时留 0) */\n seq: number;\n ts: number;\n kind: string;\n projectId?: string;\n sessionId?: string;\n data?: Uint8Array;\n /** 通知来源节点;由网关填充(多路复用终端据此归属到具体节点) */\n nodeId?: string;\n}\n\nexport function encodeNotify(n: NotifyMsg): Uint8Array {\n const w = new Writer(160);\n w.uint64Field(1, n.seq);\n w.uint64Field(2, n.ts);\n w.stringField(3, n.kind);\n w.stringField(4, n.projectId ?? \"\");\n w.stringField(5, n.sessionId ?? \"\");\n w.bytesField(6, n.data ?? EMPTY_BYTES);\n w.stringField(7, n.nodeId ?? \"\");\n return w.finish();\n}\n\nexport function decodeNotify(bytes: Uint8Array): NotifyMsg {\n const r = new Reader(bytes);\n const n: NotifyMsg = { seq: 0, ts: 0, kind: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else n.seq = r.u64();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else n.ts = r.u64();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.kind = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.projectId = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.sessionId = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.data = r.lenPrefixed();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.nodeId = r.string();\n break;\n default:\n r.skip(wire);\n }\n }\n return n;\n}\n\n// ===================== 握手 / 认证 =====================\n\nexport interface Auth {\n /** 节点面:nodeId;终端面:userId */\n id: string;\n /** 毫秒时间戳(±60s 窗口) */\n ts: number;\n nonce: string;\n /** 协议能力版本 */\n proto: number;\n /** \"node\" | \"terminal\" */\n kind: string;\n /** 终端载体:\"web\" | \"miniapp\" | \"app\"(节点面留空) */\n client?: string;\n /**\n * 终端面 = HMAC-SHA256(terminalSecret, signableAuthBytes);节点面 = HMAC-SHA256(fleetSecret, …)\n *\n * 注意 `scope`/`expires` 在 `token` **之后**:proto3 按字段号升序编码,因此它们仍在\n * `signableAuthBytes` 内 —— 即**同样受签名完整性保护**(改 scope 会让 token 失效)。\n */\n token?: Uint8Array;\n /** 终端面被授权的 nodeId 列表(非空时网关严格校验;见 `verifyTerminalAuth`) */\n scope?: string[];\n /** 终端面过期时刻(毫秒);>0 时网关跳过 ±60s 窗口 */\n expires?: number;\n /**\n * 客户端能力位(见 `frame.ts` 的 `CAP_DEFLATE`)。\n *\n * 只用于声明支持;节点只有在 `AuthOk.caps` 也回同样位时才启用压缩上行。\n * 旧网关忽略未知字段,行为不变。\n */\n caps?: number;\n}\n\nexport interface AuthOk {\n ok: boolean;\n error?: string;\n serverTs: number;\n /** 网关能力位(语义同 `Auth.caps`);旧网关不回此字段(视为 0) */\n caps?: number;\n}\n\nexport function encodeAuth(auth: Auth): Uint8Array {\n const w = new Writer(64);\n w.stringField(1, auth.id);\n w.uint64Field(2, auth.ts);\n w.stringField(3, auth.nonce);\n // 注意:proto3 默认值省略 → proto=0 与 proto=1 不同,proto=0 不出现在线格式中\n w.uint64Field(4, auth.proto);\n w.stringField(5, auth.kind);\n w.stringField(6, auth.client ?? \"\");\n w.bytesField(7, auth.token ?? EMPTY_BYTES);\n // repeated string 在 protobuf 中是重复 tag(非 packed),逐个写即可\n for (const id of auth.scope ?? []) w.stringField(8, id);\n w.uint64Field(9, auth.expires ?? 0);\n w.uint64Field(10, auth.caps ?? 0);\n return w.finish();\n}\n\n/**\n * 参与签名的字节:清空 `token` 后编码。\n *\n * `scope`/`expires` 字段号大于 `token`,但 prost/本实现都按字段号升序编码,\n * 因此它们**仍在签名字节内**(受完整性保护),不是「token 之后的免费字段」。\n */\nexport function signableAuthBytes(auth: Auth): Uint8Array {\n return encodeAuth({ ...auth, token: undefined });\n}\n\nexport function decodeAuth(bytes: Uint8Array): Auth {\n const r = new Reader(bytes);\n const auth: Auth = { id: \"\", ts: 0, nonce: \"\", proto: 0, kind: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.id = r.string();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else auth.ts = r.u64();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.nonce = r.string();\n break;\n case 4:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else auth.proto = r.u64();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.kind = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.client = r.string();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.token = r.lenPrefixed();\n break;\n case 8:\n if (wire !== WIRE_LEN) r.skip(wire);\n else (auth.scope ??= []).push(r.string());\n break;\n case 9:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else auth.expires = r.u64();\n break;\n case 10:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else auth.caps = r.u64();\n break;\n default:\n r.skip(wire);\n }\n }\n return auth;\n}\n\nexport function encodeAuthOk(ok: AuthOk): Uint8Array {\n const w = new Writer(48);\n w.boolField(1, ok.ok);\n w.stringField(2, ok.error ?? \"\");\n w.uint64Field(3, ok.serverTs);\n w.uint64Field(4, ok.caps ?? 0);\n return w.finish();\n}\n\nexport function decodeAuthOk(bytes: Uint8Array): AuthOk {\n const r = new Reader(bytes);\n const out: AuthOk = { ok: false, serverTs: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else out.ok = r.varint() !== 0n;\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else out.error = r.string();\n break;\n case 3:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else out.serverTs = r.u64();\n break;\n case 4:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else out.caps = r.u64();\n break;\n default:\n r.skip(wire);\n }\n }\n return out;\n}\n\n// ===================== 终端数据 =====================\n\nexport function encodeTerminalData(td: TerminalData): Uint8Array {\n const w = new Writer(64 + (td.data?.length ?? 0));\n w.stringField(1, td.nodeId ?? \"\");\n w.stringField(2, td.terminalId);\n w.stringField(3, td.kind);\n w.bytesField(4, td.data ?? EMPTY_BYTES);\n w.uint64Field(5, td.seq ?? 0);\n // 0 = 终端:不写字段,保持与旧端字节兼容(proto3 默认值不上线)\n if (td.channel) w.uint64Field(6, td.channel);\n if (td.session) w.stringField(7, td.session);\n return w.finish();\n}\n\nexport function decodeTerminalData(bytes: Uint8Array): TerminalData {\n const r = new Reader(bytes);\n const td: TerminalData = { terminalId: \"\", kind: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.nodeId = r.string();\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.terminalId = r.string();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.kind = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.data = r.lenPrefixed();\n break;\n case 5:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else td.seq = r.u64();\n break;\n case 6:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else td.channel = r.u64();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.session = r.string();\n break;\n default:\n r.skip(wire);\n }\n }\n return td;\n}\n\n// ===================== 快照 / 订阅 =====================\n\nexport interface NodeState {\n nodeId: string;\n online: boolean;\n lastSeen: number;\n platform?: string;\n version?: string;\n ip?: string;\n /**\n * 节点上报的原始 info JSON(`Info.detail` 的转发),供终端快照读取项目/统计。\n *\n * 快照借此**替代 MQTT retained info**:订阅后一次拿到,不必逐节点发指令。\n * 节点从未上报过 INFO 时为空。\n */\n detail?: Uint8Array;\n}\n\nexport interface Snapshot {\n nodes: NodeState[];\n /** 当前事件游标(客户端据此发起 resume) */\n seq: number;\n}\n\nexport function encodeNodeState(n: NodeState): Uint8Array {\n const w = new Writer(96);\n w.stringField(1, n.nodeId);\n w.boolField(2, n.online);\n w.uint64Field(3, n.lastSeen);\n w.stringField(4, n.platform ?? \"\");\n w.stringField(5, n.version ?? \"\");\n w.stringField(6, n.ip ?? \"\");\n w.bytesField(7, n.detail ?? EMPTY_BYTES);\n return w.finish();\n}\n\nexport function decodeNodeState(bytes: Uint8Array): NodeState {\n const r = new Reader(bytes);\n const n: NodeState = { nodeId: \"\", online: false, lastSeen: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.nodeId = r.string();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else n.online = r.varint() !== 0n;\n break;\n case 3:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else n.lastSeen = r.u64();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.platform = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.version = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.ip = r.string();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.detail = r.lenPrefixed();\n break;\n default:\n r.skip(wire);\n }\n }\n return n;\n}\n\nexport function encodeSnapshot(snap: Snapshot): Uint8Array {\n const w = new Writer(128);\n for (const node of snap.nodes) {\n w.tag(1, WIRE_LEN);\n w.lenPrefixed(encodeNodeState(node));\n }\n w.uint64Field(2, snap.seq);\n return w.finish();\n}\n\nexport function decodeSnapshot(bytes: Uint8Array): Snapshot {\n const r = new Reader(bytes);\n const snap: Snapshot = { nodes: [], seq: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else snap.nodes.push(decodeNodeState(r.lenPrefixed()));\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else snap.seq = r.u64();\n break;\n default:\n r.skip(wire);\n }\n }\n return snap;\n}\n\nfunction encodeNodeIds(ids: string[]): Uint8Array {\n const w = new Writer(64);\n for (const id of ids) w.stringField(1, id);\n return w.finish();\n}\n\nfunction decodeNodeIds(bytes: Uint8Array): string[] {\n const r = new Reader(bytes);\n const ids: string[] = [];\n while (!r.eof) {\n const { field, wire } = r.tag();\n if (field === 1 && wire === WIRE_LEN) ids.push(r.string());\n else r.skip(wire);\n }\n return ids;\n}\n\n/**\n * 订阅帧:节点列表 + 是否要内容增量。\n *\n * `noDetail` 用反向布尔的 `.proto` 字段(`Subscribe.no_detail`):默认 false\n * 表示「要细节」,与本字段出现前的行为一致。只有双方(控制台/网关)都支持时\n * 才会真正省下带宽;旧网关忽略未知字段,退化为全量推送。\n */\nexport function encodeSubscribe(ids: string[], noDetail = false): Uint8Array {\n if (!noDetail) return encodeNodeIds(ids);\n const w = new Writer(64);\n for (const id of ids) w.stringField(1, id);\n w.boolField(2, true);\n return w.finish();\n}\n\n/** 只取节点列表(保持既有调用方与测试的返回类型不变) */\nexport const decodeSubscribe = decodeNodeIds;\n\n/** 连 `no_detail` 一起解出(网关侧 / 测试需要判定订阅意图时用) */\nexport function decodeSubscribeDetail(bytes: Uint8Array): {\n nodeIds: string[];\n noDetail: boolean;\n} {\n const r = new Reader(bytes);\n const nodeIds: string[] = [];\n let noDetail = false;\n while (!r.eof) {\n const { field, wire } = r.tag();\n if (field === 1 && wire === WIRE_LEN) nodeIds.push(r.string());\n else if (field === 2 && wire === WIRE_VARINT) noDetail = r.varint() !== 0n;\n else r.skip(wire);\n }\n return { nodeIds, noDetail };\n}\nexport const encodeUnsubscribe = encodeNodeIds;\nexport const decodeUnsubscribe = decodeNodeIds;\n\nexport function encodeResume(since: number, nodeIds: string[] = []): Uint8Array {\n const w = new Writer(16 + nodeIds.length * 16);\n w.uint64Field(1, since);\n for (const id of nodeIds) w.stringField(2, id);\n return w.finish();\n}\n\nexport function decodeResume(bytes: Uint8Array): { since: number; nodeIds: string[] } {\n const r = new Reader(bytes);\n let since = 0;\n const nodeIds: string[] = [];\n while (!r.eof) {\n const { field, wire } = r.tag();\n if (field === 1 && wire === WIRE_VARINT) since = r.u64();\n else if (field === 2 && wire === WIRE_LEN) nodeIds.push(r.string());\n else r.skip(wire);\n }\n return { since, nodeIds };\n}","/** 十六进制编解码(可移植,向量文件与调试用) */\n\nexport function toHex(bytes: Uint8Array): string {\n let out = \"\";\n for (const b of bytes) out += b.toString(16).padStart(2, \"0\");\n return out;\n}\n\nexport function fromHex(hex: string): Uint8Array {\n const s = hex.trim();\n if (s.length % 2 !== 0) throw new Error(`十六进制长度必须为偶数: ${s.length}`);\n const out = new Uint8Array(s.length / 2);\n for (let i = 0; i < out.length; i++) {\n const byte = Number.parseInt(s.slice(i * 2, i * 2 + 2), 16);\n if (Number.isNaN(byte)) throw new Error(`非法十六进制内容: ${s.slice(i * 2, i * 2 + 2)}`);\n out[i] = byte;\n }\n return out;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/wire/index.ts","../../src/wire/utf8.ts","../../src/wire/varint.ts","../../src/wire/frame.ts","../../src/wire/messages.ts","../../src/wire/hex.ts"],"sourcesContent":["/**\n * 线协议 v1:帧 + 消息编解码(node: 无依赖)\n *\n * 权威契约见 proto/fleet.proto,规范见 docs/wire-protocol.md。\n *\n * 本模块**平台中立**:只用 `Uint8Array`,不 import 任何 Node 内置模块,因此\n * Node(节点/core/hub)、浏览器(console-core/portal)、小程序三处共用同一份实现。\n * 平台相关的部分只有签名——Node 侧见 `./node.js`,浏览器/小程序侧用 Web Crypto。\n */\nexport {\n Writer,\n Reader,\n WireError,\n WIRE_VARINT,\n WIRE_FIXED32,\n WIRE_FIXED64,\n WIRE_LEN,\n EMPTY_BYTES,\n} from \"./varint.js\";\nexport {\n FRAME_MAGIC,\n PROTOCOL_VERSION,\n MAX_FRAME_BYTES,\n CAP_DEFLATE,\n FrameType,\n FrameError,\n encodeFrame,\n decodeFrame,\n encodeCompressedPayload,\n decodeCompressedPayload,\n StreamDecoder,\n MAX_STREAM_BUFFER_BYTES,\n frameTypeName,\n frameTypeFromName,\n type Frame,\n type FrameTypeName,\n type FrameTypeValue,\n} from \"./frame.js\";\nexport {\n encodeEnvelope,\n decodeEnvelope,\n signableBytes,\n encodeAck,\n decodeAck,\n encodeStatus,\n decodeStatus,\n encodeEvent,\n decodeEvent,\n encodeInfo,\n decodeInfo,\n encodeNotify,\n decodeNotify,\n encodeTerminalData,\n decodeTerminalData,\n encodeAuth,\n decodeAuth,\n signableAuthBytes,\n encodeAuthOk,\n decodeAuthOk,\n encodeNodeState,\n decodeNodeState,\n encodeSnapshot,\n decodeSnapshot,\n encodeSubscribe,\n decodeSubscribe,\n decodeSubscribeDetail,\n encodeUnsubscribe,\n decodeUnsubscribe,\n encodeResume,\n decodeResume,\n type Envelope,\n type Ack,\n type Status,\n type EventMsg,\n type Info,\n type NotifyMsg,\n type TerminalData,\n type Auth,\n type AuthOk,\n type NodeState,\n type Snapshot,\n} from \"./messages.js\";\nexport { utf8Encode, utf8Decode, Utf8Error } from \"./utf8.js\";\nexport { toHex, fromHex } from \"./hex.js\";\n","/**\n * UTF-8 编解码(手工实现,零依赖)\n *\n * 不依赖 TextEncoder/TextDecoder:小程序的 JS 运行时(部分基础库)不保证提供这两个全局,\n * 而本模块必须能被 Node / 浏览器 / 小程序三处共用。严格校验(拒绝孤立代理项、过长编码、\n * 超出码点范围)以对齐 protobuf 对 `string` 字段的 UTF-8 要求。\n */\n\nexport class Utf8Error extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"Utf8Error\";\n }\n}\n\n/** 字符串 → UTF-8 字节 */\nexport function utf8Encode(s: string): Uint8Array {\n const buf = new Uint8Array(s.length * 4); // 每字符最多 4 字节(上界)\n let n = 0;\n for (let i = 0; i < s.length; i++) {\n let cp = s.charCodeAt(i);\n if (cp >= 0xd800 && cp <= 0xdbff) {\n const lo = i + 1 < s.length ? s.charCodeAt(i + 1) : 0;\n if (lo < 0xdc00 || lo > 0xdfff) throw new Utf8Error(\"孤立的 UTF-16 高代理项\");\n cp = 0x10000 + ((cp - 0xd800) << 10) + (lo - 0xdc00);\n i++;\n } else if (cp >= 0xdc00 && cp <= 0xdfff) {\n throw new Utf8Error(\"孤立的 UTF-16 低代理项\");\n }\n if (cp < 0x80) {\n buf[n++] = cp;\n } else if (cp < 0x800) {\n buf[n++] = 0xc0 | (cp >> 6);\n buf[n++] = 0x80 | (cp & 0x3f);\n } else if (cp < 0x10000) {\n buf[n++] = 0xe0 | (cp >> 12);\n buf[n++] = 0x80 | ((cp >> 6) & 0x3f);\n buf[n++] = 0x80 | (cp & 0x3f);\n } else {\n buf[n++] = 0xf0 | (cp >> 18);\n buf[n++] = 0x80 | ((cp >> 12) & 0x3f);\n buf[n++] = 0x80 | ((cp >> 6) & 0x3f);\n buf[n++] = 0x80 | (cp & 0x3f);\n }\n }\n return buf.slice(0, n);\n}\n\n/** UTF-8 字节 → 字符串(严格校验) */\nexport function utf8Decode(b: Uint8Array): string {\n let out = \"\";\n let i = 0;\n while (i < b.length) {\n const c = b[i]!;\n if (c < 0x80) {\n out += String.fromCharCode(c);\n i++;\n continue;\n }\n let cp: number;\n let need: number;\n let min: number;\n if ((c & 0xe0) === 0xc0) {\n cp = c & 0x1f;\n need = 1;\n min = 0x80;\n } else if ((c & 0xf0) === 0xe0) {\n cp = c & 0x0f;\n need = 2;\n min = 0x800;\n } else if ((c & 0xf8) === 0xf0) {\n cp = c & 0x07;\n need = 3;\n min = 0x10000;\n } else {\n throw new Utf8Error(`非法 UTF-8 起始字节 0x${c.toString(16)}`);\n }\n if (i + need >= b.length) throw new Utf8Error(\"UTF-8 序列被截断\");\n for (let k = 1; k <= need; k++) {\n const cc = b[i + k]!;\n if ((cc & 0xc0) !== 0x80) throw new Utf8Error(`非法 UTF-8 续接字节 0x${cc.toString(16)}`);\n cp = (cp << 6) | (cc & 0x3f);\n }\n if (cp < min) throw new Utf8Error(\"UTF-8 过长编码(overlong)\");\n if (cp > 0x10ffff) throw new Utf8Error(\"码点超出 U+10FFFF\");\n if (cp >= 0xd800 && cp <= 0xdfff) throw new Utf8Error(\"UTF-8 编码了 UTF-16 代理项\");\n i += need + 1;\n if (cp < 0x10000) {\n out += String.fromCharCode(cp);\n } else {\n const v = cp - 0x10000;\n out += String.fromCharCode(0xd800 + (v >> 10), 0xdc00 + (v & 0x3ff));\n }\n }\n return out;\n}\n","/**\n * 最小 protobuf 原语(varint + length-delimited 读写,零依赖)\n *\n * Node 与浏览器/小程序共用:只用 `Uint8Array`(`Buffer` 是其子类)与 `DataView`,\n * 不触碰任何平台 API。编码规则严格对齐 proto3 线格式(默认值省略、字段号升序),\n * 以便与 Rust 侧 `prost` 产出**逐字节一致**的结果(见 docs/wire-protocol.md §5)。\n */\nimport { utf8Encode, utf8Decode } from \"./utf8.js\";\n\nexport const WIRE_VARINT = 0;\nexport const WIRE_FIXED64 = 1;\nexport const WIRE_LEN = 2;\nexport const WIRE_FIXED32 = 5;\n\nexport class WireError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WireError\";\n }\n}\n\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\nconst EMPTY = new Uint8Array(0);\n\n/** 增量字节写入器(自动扩容) */\nexport class Writer {\n private buf: Uint8Array;\n private len = 0;\n\n constructor(initialCapacity = 64) {\n this.buf = new Uint8Array(Math.max(8, initialCapacity));\n }\n\n private ensure(n: number): void {\n if (this.len + n <= this.buf.length) return;\n let cap = this.buf.length * 2;\n while (cap < this.len + n) cap *= 2;\n const next = new Uint8Array(cap);\n next.set(this.buf.subarray(0, this.len));\n this.buf = next;\n }\n\n /** 裸字节(帧头用,不带任何前缀) */\n u8(b: number): void {\n this.ensure(1);\n this.buf[this.len++] = b & 0xff;\n }\n\n raw(b: Uint8Array): void {\n this.ensure(b.length);\n this.buf.set(b, this.len);\n this.len += b.length;\n }\n\n /** 无符号 varint(接受 number 或 bigint) */\n varint(v: number | bigint): void {\n let x = typeof v === \"bigint\" ? v : BigInt(v);\n if (x < 0n) throw new WireError(\"varint 不接受负值\");\n this.ensure(10);\n while (x >= 0x80n) {\n this.buf[this.len++] = Number((x & 0x7fn) | 0x80n);\n x >>= 7n;\n }\n this.buf[this.len++] = Number(x);\n }\n\n tag(field: number, wire: number): void {\n this.varint((field << 3) | wire);\n }\n\n /** length-delimited:长度 varint + 内容 */\n lenPrefixed(b: Uint8Array): void {\n this.varint(b.length);\n this.raw(b);\n }\n\n // ---- proto3 字段:默认值不写线 ----\n\n uint64Field(field: number, v: number | bigint): void {\n const x = typeof v === \"bigint\" ? v : BigInt(v);\n if (x === 0n) return;\n this.tag(field, WIRE_VARINT);\n this.varint(x);\n }\n\n boolField(field: number, v: boolean): void {\n if (!v) return;\n this.tag(field, WIRE_VARINT);\n this.varint(1);\n }\n\n stringField(field: number, v: string): void {\n if (v === \"\") return;\n this.tag(field, WIRE_LEN);\n this.lenPrefixed(utf8Encode(v));\n }\n\n bytesField(field: number, v: Uint8Array): void {\n if (v.length === 0) return;\n this.tag(field, WIRE_LEN);\n this.lenPrefixed(v);\n }\n\n finish(): Uint8Array {\n return this.buf.slice(0, this.len);\n }\n\n get length(): number {\n return this.len;\n }\n}\n\n/** 顺序字节读取器(越界一律判错) */\nexport class Reader {\n private pos = 0;\n\n constructor(private readonly buf: Uint8Array) {}\n\n get remaining(): number {\n return this.buf.length - this.pos;\n }\n\n get eof(): boolean {\n return this.pos >= this.buf.length;\n }\n\n varint(): bigint {\n let shift = 0n;\n let result = 0n;\n for (let i = 0; i < 10; i++) {\n if (this.pos >= this.buf.length) throw new WireError(\"varint 越界\");\n const b = this.buf[this.pos++]!;\n result |= BigInt(b & 0x7f) << shift;\n if ((b & 0x80) === 0) {\n if (i === 9 && b > 1) throw new WireError(\"varint 溢出(超过 64 位)\");\n return result;\n }\n shift += 7n;\n }\n throw new WireError(\"varint 超过 10 字节\");\n }\n\n /** u64 → number(超安全整数范围即判错,避免静默精度丢失) */\n u64(): number {\n const v = this.varint();\n if (v > MAX_SAFE) throw new WireError(`u64 超出 JS 安全整数范围: ${v}`);\n return Number(v);\n }\n\n tag(): { field: number; wire: number } {\n const t = this.varint();\n const field = Number(t >> 3n);\n const wire = Number(t & 7n);\n if (field <= 0) throw new WireError(\"字段号必须 ≥ 1\");\n return { field, wire };\n }\n\n /** 取 n 个字节(越界判错) */\n take(n: number): Uint8Array {\n if (!Number.isInteger(n) || n < 0) throw new WireError(`非法长度: ${n}`);\n if (this.pos + n > this.buf.length) {\n throw new WireError(`读取越界:需要 ${n} 字节,剩余 ${this.buf.length - this.pos}`);\n }\n const out = this.buf.subarray(this.pos, this.pos + n);\n this.pos += n;\n return out;\n }\n\n /** length-delimited:读长度再取其内容 */\n lenPrefixed(): Uint8Array {\n return this.take(this.u64());\n }\n\n string(): string {\n return utf8Decode(this.lenPrefixed());\n }\n\n /** 跳过未知字段(前向兼容的关键:未来新增字段号不应导致解析失败) */\n skip(wire: number): void {\n switch (wire) {\n case WIRE_VARINT:\n this.varint();\n return;\n case WIRE_LEN:\n this.lenPrefixed();\n return;\n case WIRE_FIXED64:\n this.take(8);\n return;\n case WIRE_FIXED32:\n this.take(4);\n return;\n default:\n throw new WireError(`不支持的 wire type: ${wire}`);\n }\n }\n}\n\nexport { EMPTY as EMPTY_BYTES };\n","/**\n * 帧编解码(magic + ver/type + seq + len + payload)\n *\n * 规范见 docs/wire-protocol.md §1/§6。节点面与终端面共用同一套帧。\n */\nimport { Reader, Writer, WireError } from \"./varint.js\";\n\n/** ASCII \"ZQ\":用于在公网暴露面上廉价丢弃非法流量 */\nexport const FRAME_MAGIC = [0x5a, 0x51] as const;\nexport const PROTOCOL_VERSION = 1;\n/**\n * 载荷上限:16MB。\n *\n * 需要容纳聊天附件(单次最多 10MB 原文件 → base64 约 13.4MB)。\n * 节点上报的事件仍受各自更小的业务上限约束,这里只是帧级防线。\n */\nexport const MAX_FRAME_BYTES = 16 * 1024 * 1024;\n\n/**\n * 能力位(`Auth.caps` / `AuthOk.caps`):对端声明支持帧级压缩。\n *\n * 压缩帧用 type 0(`COMPRESSED`)承载,旧对端收到会当未知类型安全丢弃——\n * 不崩,但会**静默丢消息**。因此必须先协商,确认双方都支持才发送。\n */\nexport const CAP_DEFLATE = 1 << 0;\n\n/** 帧类型(低 4 位)。M1 已实现载荷的消息见 docs/wire-protocol.md §3 */\nexport const FrameType = {\n /**\n * 帧级压缩容器(原 `HELLO` 占位,从未实现握手)。\n *\n * payload = `[内部帧类型 1 字节][deflate-raw 压缩后的内部 payload]`;\n * seq 沿用内层帧的 seq,解压后与原帧语义完全一致。\n */\n COMPRESSED: 0,\n AUTH: 1,\n SNAPSHOT: 2,\n STATUS: 3,\n INFO: 4,\n EVENT: 5,\n NOTIFY: 6,\n CMD: 7,\n ACK: 8,\n SUBSCRIBE: 9,\n UNSUBSCRIBE: 10,\n RESUME: 11,\n PING: 12,\n PONG: 13,\n /** 握手结果(服务端 → 客户端)。与 AUTH 分开,避免「同类型双向」的解析歧义 */\n AUTH_OK: 14,\n /**\n * 命令终端数据(`TerminalData`)。\n *\n * 注意低 4 位的 16 个取值到此用尽:之后再扩帧类型只能升协议版本。\n * 与 `EVENT` 分开是**性能隔离**(终端数据不进事件环形缓冲、不分配全局游标、\n * 不走事件扇出队列),理由见 `proto/fleet.proto` 的 `TerminalData`。\n */\n TERMINAL: 15,\n} as const;\nexport type FrameTypeName = keyof typeof FrameType;\nexport type FrameTypeValue = (typeof FrameType)[FrameTypeName];\n\nconst KNOWN_TYPES = new Set<number>(Object.values(FrameType));\n\nexport class FrameError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameError\";\n }\n}\n\nexport interface Frame {\n type: FrameTypeValue;\n /** 单调递增序号(用于去重与断线续传定位) */\n seq: number;\n payload: Uint8Array;\n}\n\n/** 帧头长度下界:magic(2) + ver/type(1) + seq(≥1) + len(≥1) */\nconst MIN_HEADER_BYTES = 5;\n\n/**\n * 流式解码的缓冲上限:`2 × 帧上限`。\n *\n * 与 Rust 侧 `gateway/src/stream.rs` 的 `MAX_BUFFER_BYTES` 同口径:缓冲里可能残留\n * 一条合法但未收满的帧,同时下一条 WS 消息也已到达,两者都合法。\n */\nexport const MAX_STREAM_BUFFER_BYTES = MAX_FRAME_BYTES * 2 + 64;\n\nexport function encodeFrame(frame: {\n type: number;\n seq: number;\n payload: Uint8Array;\n}): Uint8Array {\n if (!Number.isInteger(frame.type) || frame.type < 0 || frame.type > 15) {\n throw new FrameError(`非法帧类型: ${frame.type}`);\n }\n if (frame.payload.length > MAX_FRAME_BYTES) {\n throw new FrameError(`载荷超限: ${frame.payload.length} > ${MAX_FRAME_BYTES}`);\n }\n const w = new Writer(frame.payload.length + MIN_HEADER_BYTES);\n w.u8(FRAME_MAGIC[0]);\n w.u8(FRAME_MAGIC[1]);\n w.u8((PROTOCOL_VERSION << 4) | frame.type);\n w.varint(frame.seq);\n w.varint(frame.payload.length);\n w.raw(frame.payload);\n return w.finish();\n}\n\n/**\n * 解码入口:**先校验头部再分配**——`len` 在分配/切分前就与实际上限和剩余字节比对,\n * 避免畸形头部引发的大内存分配。\n */\nexport function decodeFrame(bytes: Uint8Array): Frame {\n if (bytes.length < MIN_HEADER_BYTES) {\n throw new FrameError(`帧过短: ${bytes.length} 字节`);\n }\n if (bytes[0] !== FRAME_MAGIC[0] || bytes[1] !== FRAME_MAGIC[1]) {\n throw new FrameError(\"magic 不符(非本协议流量)\");\n }\n const verType = bytes[2]!;\n const version = verType >> 4;\n const type = verType & 0x0f;\n if (version !== PROTOCOL_VERSION) {\n throw new FrameError(`不支持的协议版本: ${version}`);\n }\n if (!KNOWN_TYPES.has(type)) {\n throw new FrameError(`未定义的帧类型: ${type}`);\n }\n\n let r: Reader;\n let seq: number;\n let len: number;\n try {\n r = new Reader(bytes.subarray(3));\n seq = r.u64();\n len = r.u64();\n } catch (e) {\n throw new FrameError(`帧头解析失败: ${e instanceof WireError ? e.message : String(e)}`);\n }\n if (len > MAX_FRAME_BYTES) {\n throw new FrameError(`载荷超限: ${len} > ${MAX_FRAME_BYTES}`);\n }\n if (r.remaining !== len) {\n throw new FrameError(`len(${len}) 与剩余字节(${r.remaining})不符`);\n }\n const payload = r.take(len);\n return { type: type as FrameTypeValue, seq, payload };\n}\n\n/** 帧类型名(日志/向量文件用) */\nexport function frameTypeName(type: number): FrameTypeName {\n for (const [name, value] of Object.entries(FrameType)) {\n if (value === type) return name as FrameTypeName;\n }\n throw new FrameError(`未定义的帧类型: ${type}`);\n}\n\n// ===================== 帧级压缩容器 =====================\n//\n// 只做**结构**编解码,压缩/解压本身由调用方完成(Node 用 `node:zlib`,\n// 浏览器侧暂无同步实现故不启用)。这样本文件保持零依赖,可直接打进前端包。\n/**\n * 组装 `COMPRESSED` 容器的 payload:`[内部类型 1 字节][deflate-raw 字节]`。\n *\n * @param innerType 内部帧类型(不能是 COMPRESSED,禁止嵌套)\n * @param deflated 用 **raw deflate**(无 zlib 头)压缩后的内部 payload\n */\nexport function encodeCompressedPayload(innerType: number, deflated: Uint8Array): Uint8Array {\n if (innerType === FrameType.COMPRESSED) {\n throw new FrameError(\"压缩帧不得嵌套\");\n }\n const out = new Uint8Array(deflated.length + 1);\n out[0] = innerType;\n out.set(deflated, 1);\n return out;\n}\n\n/**\n * 拆出内部类型与 deflate 字节。结构非法时返回 null(调用方丢帧并计数)。\n *\n * 注意这里**不解压**:解压后的体积上限由调用方按 `MAX_FRAME_BYTES` 校验。\n */\nexport function decodeCompressedPayload(\n payload: Uint8Array,\n): { type: number; deflated: Uint8Array } | null {\n if (payload.length < 2) return null;\n const type = payload[0]!;\n if (type === FrameType.COMPRESSED) return null;\n if (!KNOWN_TYPES.has(type)) return null;\n return { type, deflated: payload.subarray(1) };\n}\n\n/** 帧类型名 → 值(向量文件用) */\nexport function frameTypeFromName(name: string): FrameTypeValue {\n // type 0 在压缩落地前叫 HELLO(占位、从未实现):保留旧名解析,\n // 避免历史向量/日志解析失败。\n if (name === \"HELLO\") return FrameType.COMPRESSED;\n if (!(name in FrameType)) throw new FrameError(`未知帧类型名: ${name}`);\n return FrameType[name as FrameTypeName];\n}\n\ntype Peeked = { value: number; size: number } | null | \"bad\";\n\n/** 窥探一个 varint:`null` = 字节不足;`\"bad\"` = 协议非法(>10 字节 / 超 64 位) */\nfunction peekVarint(b: Uint8Array, at: number): Peeked {\n let value = 0n;\n let shift = 0n;\n for (let i = 0; i < 10; i++) {\n if (at + i >= b.length) return null;\n const byte = b[at + i]!;\n // 第 10 个字节只剩 1 个有效位(与 Reader.varint / Rust peek_varint 一致)\n if (i === 9 && byte > 1) return \"bad\";\n value |= BigInt(byte & 0x7f) << shift;\n if ((byte & 0x80) === 0) {\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) return \"bad\";\n return { value: Number(value), size: i + 1 };\n }\n shift += 7n;\n }\n return \"bad\";\n}\n\n/**\n * 字节流 → 帧 的增量解码器。\n *\n * WebSocket 的消息边界不可依赖(分片、粘包、future batching、中间层 coalescing 都会\n * 让一条消息里出现多条帧)。早先客户端用 `decodeFrame` 要求「一条消息恰好一帧」,\n * 一旦出现合并就会整体抛错并丢掉**全部**帧,而且无法重新同步。\n *\n * 语义与 Rust 侧 `gateway/src/stream.rs` 对齐:\n * - 字节不足 → `nextFrame()` 返回 `null`(不消费任何字节);\n * - 协议非法 → 抛 `FrameError`,调用方应断开并重建解码器;\n * - 缓冲超过 `maxBuffer` → 抛错(防半帧永久堆积)。\n *\n * 压缩帧原样返回(`type = COMPRESSED`):解压是异步 API,由调用方决定。\n */\nexport class StreamDecoder {\n private buf: Uint8Array = new Uint8Array(0);\n\n constructor(private readonly maxBuffer: number = MAX_STREAM_BUFFER_BYTES) {}\n\n /** 已缓存但尚未解出的字节数 */\n get buffered(): number {\n return this.buf.length;\n }\n\n /** 丢弃缓存(协议错误后重新同步用) */\n reset(): void {\n this.buf = new Uint8Array(0);\n }\n\n push(chunk: Uint8Array): void {\n if (this.buf.length === 0) {\n this.buf = chunk.slice();\n } else {\n const next = new Uint8Array(this.buf.length + chunk.length);\n next.set(this.buf, 0);\n next.set(chunk, this.buf.length);\n this.buf = next;\n }\n if (this.buf.length > this.maxBuffer) {\n throw new FrameError(`接收缓冲超限: ${this.buf.length} > ${this.maxBuffer}`);\n }\n }\n\n /** 解出下一帧;不足返回 `null`。协议错误抛 `FrameError`。 */\n nextFrame(): Frame | null {\n const b = this.buf;\n if (b.length < MIN_HEADER_BYTES) return null;\n if (b[0] !== FRAME_MAGIC[0] || b[1] !== FRAME_MAGIC[1]) {\n throw new FrameError(\"magic 不符(非本协议流量)\");\n }\n const verType = b[2]!;\n const version = verType >> 4;\n const type = verType & 0x0f;\n if (version !== PROTOCOL_VERSION) {\n throw new FrameError(`不支持的协议版本: ${version}`);\n }\n if (!KNOWN_TYPES.has(type)) {\n throw new FrameError(`未定义的帧类型: ${type}`);\n }\n const seqPeek = peekVarint(b, 3);\n if (seqPeek === null) return null;\n if (seqPeek === \"bad\") throw new FrameError(\"帧头 varint 非法: seq\");\n const lenPeek = peekVarint(b, 3 + seqPeek.size);\n if (lenPeek === null) return null;\n if (lenPeek === \"bad\") throw new FrameError(\"帧头 varint 非法: len\");\n if (lenPeek.value > MAX_FRAME_BYTES) {\n throw new FrameError(`载荷超限: ${lenPeek.value} > ${MAX_FRAME_BYTES}`);\n }\n const header = 3 + seqPeek.size + lenPeek.size;\n const total = header + lenPeek.value;\n if (b.length < total) return null;\n const payload = b.slice(header, total);\n this.buf = b.subarray(total);\n return { type: type as FrameTypeValue, seq: seqPeek.value, payload };\n }\n}\n","/**\n * 消息编解码(Envelope / Ack / Status / Event)\n *\n * 字段定义见 proto/fleet.proto。手写编解码,规则与 prost 对齐(proto3 默认值省略、\n * 字段号升序、string 严格 UTF-8),未知字段按 wire type 跳过以支持前向兼容。\n *\n * 签名:`signableBytes()` 给出「不含 sig」的编码字节;`sig` 是 10 号字段(最后),\n * 因此 `encode(env, sig 置空) === signableBytes(env)` 恒成立,校验方可重编码比对。\n */\nimport { Reader, Writer, WIRE_LEN, WIRE_VARINT, WireError, EMPTY_BYTES } from \"./varint.js\";\n\n/** 与现有 FleetCmdEnvelope(packages/shared/src/fleet.ts:159-178)语义一致 */\nexport interface Envelope {\n /** 毫秒时间戳 */\n t: number;\n nonce: string;\n reqId: string;\n type: string;\n clientId: string;\n nodeId: string;\n projectId?: string;\n sessionId?: string;\n /** 载荷字节(按 type 选择强类型消息或 JSON 字节) */\n payload?: Uint8Array;\n /**\n * 执行预算(毫秒,可选):由发起方指定,网关据此决定等待回执的上限。\n * 0/缺省表示按 `type` 的默认分级(见 docs/wire-protocol.md §5.2)。\n */\n timeoutMs?: number;\n /** HMAC-SHA256 原始 32 字节(**必须是最后一个字段**:其前缀即签名字节) */\n sig?: Uint8Array;\n}\n\nexport interface Ack {\n reqId: string;\n type: string;\n ok: boolean;\n error?: string;\n data?: Uint8Array;\n}\n\n/**\n * `STATUS` 帧的消息身份标记。\n *\n * 该帧类型**同时承载**上行 `Status` 与下行 `NodeState`:两者字段 1..3 同构\n * (string / bool / uint64),错用解码器不会报错、只会静默读到错值\n * (`ts` 被当成 `last_seen`)。编码方写入标记,解码方据此拒绝错配。\n */\nexport const MSG_KIND_NODE_STATE = 1;\nexport const MSG_KIND_STATUS = 2;\n\nexport interface Status {\n nodeId: string;\n online: boolean;\n /** 毫秒时间戳(现有 JSON 协议为 ISO 字符串,映射在 M2) */\n ts: number;\n label?: string;\n platform?: string;\n mode?: string;\n version?: string;\n ip?: string;\n}\n\nexport interface EventMsg {\n seq: number;\n ts: number;\n type: string;\n projectId?: string;\n sessionId?: string;\n data?: Uint8Array;\n /**\n * 事件来源节点。由**网关**按连接绑定的 nodeId 填充(节点上行时留空)。\n *\n * 终端面一条连接可订阅多个节点,缺了它就无法分辨事件来自哪台节点。\n */\n nodeId?: string;\n}\n\n/**\n * 命令终端数据(`FrameType.TERMINAL`)。\n *\n * 与 `EventMsg` 完全平行的另一条通道,**不是** Event 的一种:它不参与\n * seq 游标、不入事件环形缓冲、不跨副本广播(理由见 proto 注释)。\n */\nexport interface TerminalData {\n /** 目标节点;节点上行时留空,由网关按连接绑定填充 */\n nodeId?: string;\n /** 终端实例 ID(节点侧生成,`t_` 前缀;与会话 ID 不同空间) */\n terminalId: string;\n /**\n * 帧种类:\n * opened | data | exited | error —— 节点 → 网关 → 终端\n * input | resize —— 终端 → 网关 → 节点\n *\n * 开/关终端不走这条通道(见 `terminal_create` / `terminal_close` 指令)。\n */\n kind: string;\n /** data/input 为原始字节;resize 为 JSON 字节({\"cols\":N,\"rows\":N}) */\n data?: Uint8Array;\n /** 终端内局部序号(仅该终端内有效,不参与 resume);文件流中为 stream_id */\n seq?: number;\n /**\n * 通道:0/缺省 = 终端;1 = 文件流(音视频预览)。\n *\n * 文件流复用 TERMINAL 帧以避开协议版本升级(帧类型低 4 位已用尽),\n * 但网关按该字段分流,不会 fanout 给终端连接。\n */\n channel?: number;\n /**\n * P2P 打洞信令(`channel=2`)的会话标识。\n *\n * 网关按它把信令**回发给发起连接**,不 fanout——否则双方公网 IP 会泄漏给\n * 同一节点的其他协作者。\n */\n session?: string;\n}\n\n// ===================== Envelope =====================\n\nexport function encodeEnvelope(env: Envelope): Uint8Array {\n const w = new Writer(128);\n w.uint64Field(1, env.t);\n w.stringField(2, env.nonce);\n w.stringField(3, env.reqId);\n w.stringField(4, env.type);\n w.stringField(5, env.clientId);\n w.stringField(6, env.nodeId);\n w.stringField(7, env.projectId ?? \"\");\n w.stringField(8, env.sessionId ?? \"\");\n w.bytesField(9, env.payload ?? EMPTY_BYTES);\n w.uint64Field(10, env.timeoutMs ?? 0);\n w.bytesField(11, env.sig ?? EMPTY_BYTES);\n return w.finish();\n}\n\n/** 参与签名的字节(字段 1..10,不含 sig) */\nexport function signableBytes(env: Envelope): Uint8Array {\n return encodeEnvelope({ ...env, sig: undefined });\n}\n\nexport function decodeEnvelope(bytes: Uint8Array): Envelope {\n const r = new Reader(bytes);\n const env: Envelope = { t: 0, nonce: \"\", reqId: \"\", type: \"\", clientId: \"\", nodeId: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else env.t = r.u64();\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.nonce = r.string();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.reqId = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.type = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.clientId = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.nodeId = r.string();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.projectId = r.string();\n break;\n case 8:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.sessionId = r.string();\n break;\n case 9:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.payload = r.lenPrefixed();\n break;\n case 10:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else env.timeoutMs = r.u64();\n break;\n case 11:\n if (wire !== WIRE_LEN) r.skip(wire);\n else env.sig = r.lenPrefixed();\n break;\n default:\n r.skip(wire);\n }\n }\n return env;\n}\n\n// ===================== Ack =====================\n\nexport function encodeAck(ack: Ack): Uint8Array {\n const w = new Writer(64);\n w.stringField(1, ack.reqId);\n w.stringField(2, ack.type);\n w.boolField(3, ack.ok);\n w.stringField(4, ack.error ?? \"\");\n w.bytesField(5, ack.data ?? EMPTY_BYTES);\n return w.finish();\n}\n\nexport function decodeAck(bytes: Uint8Array): Ack {\n const r = new Reader(bytes);\n const ack: Ack = { reqId: \"\", type: \"\", ok: false };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ack.reqId = r.string();\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ack.type = r.string();\n break;\n case 3:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else ack.ok = r.varint() !== 0n;\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ack.error = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ack.data = r.lenPrefixed();\n break;\n default:\n r.skip(wire);\n }\n }\n return ack;\n}\n\n// ===================== Status =====================\n\nexport function encodeStatus(st: Status): Uint8Array {\n const w = new Writer(96);\n w.stringField(1, st.nodeId);\n w.boolField(2, st.online);\n w.uint64Field(3, st.ts);\n w.stringField(4, st.label ?? \"\");\n w.stringField(5, st.platform ?? \"\");\n w.stringField(6, st.mode ?? \"\");\n w.stringField(7, st.version ?? \"\");\n w.stringField(8, st.ip ?? \"\");\n w.uint64Field(9, MSG_KIND_STATUS);\n return w.finish();\n}\n\nexport function decodeStatus(bytes: Uint8Array): Status {\n const r = new Reader(bytes);\n const st: Status = { nodeId: \"\", online: false, ts: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.nodeId = r.string();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else st.online = r.varint() !== 0n;\n break;\n case 3:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else st.ts = r.u64();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.label = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.platform = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.mode = r.string();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.version = r.string();\n break;\n case 8:\n if (wire !== WIRE_LEN) r.skip(wire);\n else st.ip = r.string();\n break;\n case 9: {\n if (wire !== WIRE_VARINT) r.skip(wire);\n else checkMsgKind(\"Status\", Number(r.varint()), MSG_KIND_STATUS);\n break;\n }\n default:\n r.skip(wire);\n }\n }\n return st;\n}\n\n// ===================== Event =====================\n\nexport function encodeEvent(ev: EventMsg): Uint8Array {\n const w = new Writer(128);\n w.uint64Field(1, ev.seq);\n w.uint64Field(2, ev.ts);\n w.stringField(3, ev.type);\n w.stringField(4, ev.projectId ?? \"\");\n w.stringField(5, ev.sessionId ?? \"\");\n w.bytesField(6, ev.data ?? EMPTY_BYTES);\n w.stringField(7, ev.nodeId ?? \"\");\n return w.finish();\n}\n\nexport function decodeEvent(bytes: Uint8Array): EventMsg {\n const r = new Reader(bytes);\n const ev: EventMsg = { seq: 0, ts: 0, type: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else ev.seq = r.u64();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else ev.ts = r.u64();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.type = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.projectId = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.sessionId = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.data = r.lenPrefixed();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else ev.nodeId = r.string();\n break;\n default:\n r.skip(wire);\n }\n }\n return ev;\n}\n\nexport { WireError };\n\n// ===================== 节点能力/项目快照 =====================\n\nexport interface Info {\n nodeId: string;\n platform?: string;\n version?: string;\n ip?: string;\n /** 项目数 */\n projects: number;\n /** 会话数 */\n sessions: number;\n /** 运行中的会话数 */\n running: number;\n /** 等待审批/提问的会话数 */\n waiting: number;\n /** 毫秒时间戳 */\n ts: number;\n /**\n * 节点上报的**原始 info JSON**(含 label / 项目明细 / stats / usage)。\n *\n * 5..9 的计数供网关快速聚合;本字段原样承载完整快照,供控制面读取\n * (替代从前经 MQTT retained info 的那条路径),避免为视图反复改 schema。\n */\n detail?: Uint8Array;\n}\n\nexport function encodeInfo(info: Info): Uint8Array {\n const w = new Writer(96);\n w.stringField(1, info.nodeId);\n w.stringField(2, info.platform ?? \"\");\n w.stringField(3, info.version ?? \"\");\n w.stringField(4, info.ip ?? \"\");\n w.uint64Field(5, info.projects);\n w.uint64Field(6, info.sessions);\n w.uint64Field(7, info.running);\n w.uint64Field(8, info.waiting);\n w.uint64Field(9, info.ts);\n w.bytesField(10, info.detail ?? EMPTY_BYTES);\n return w.finish();\n}\n\nexport function decodeInfo(bytes: Uint8Array): Info {\n const r = new Reader(bytes);\n const info: Info = { nodeId: \"\", projects: 0, sessions: 0, running: 0, waiting: 0, ts: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.nodeId = r.string();\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.platform = r.string();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.version = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.ip = r.string();\n break;\n case 5:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.projects = r.u64();\n break;\n case 6:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.sessions = r.u64();\n break;\n case 7:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.running = r.u64();\n break;\n case 8:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.waiting = r.u64();\n break;\n case 9:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else info.ts = r.u64();\n break;\n case 10:\n if (wire !== WIRE_LEN) r.skip(wire);\n else info.detail = r.lenPrefixed();\n break;\n default:\n r.skip(wire);\n }\n }\n return info;\n}\n\n// ===================== 通知(需可靠送达的上行) =====================\n\n/**\n * 节点通知:审批请求 / 提问 / 回合完成 / 错误。\n *\n * 与 `EventMsg` 的分工:Event 是高频实时进度,Notify 是低频但重要(审批/提问挂起必须\n * 让终端看到)。两者共用网关分配的 `seq` 游标与缓冲,因此 `resume` 时都能回放。\n */\nexport interface NotifyMsg {\n /** 由网关分配的游标(节点上报时留 0) */\n seq: number;\n ts: number;\n kind: string;\n projectId?: string;\n sessionId?: string;\n data?: Uint8Array;\n /** 通知来源节点;由网关填充(多路复用终端据此归属到具体节点) */\n nodeId?: string;\n}\n\nexport function encodeNotify(n: NotifyMsg): Uint8Array {\n const w = new Writer(160);\n w.uint64Field(1, n.seq);\n w.uint64Field(2, n.ts);\n w.stringField(3, n.kind);\n w.stringField(4, n.projectId ?? \"\");\n w.stringField(5, n.sessionId ?? \"\");\n w.bytesField(6, n.data ?? EMPTY_BYTES);\n w.stringField(7, n.nodeId ?? \"\");\n return w.finish();\n}\n\nexport function decodeNotify(bytes: Uint8Array): NotifyMsg {\n const r = new Reader(bytes);\n const n: NotifyMsg = { seq: 0, ts: 0, kind: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else n.seq = r.u64();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else n.ts = r.u64();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.kind = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.projectId = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.sessionId = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.data = r.lenPrefixed();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.nodeId = r.string();\n break;\n default:\n r.skip(wire);\n }\n }\n return n;\n}\n\n// ===================== 握手 / 认证 =====================\n\nexport interface Auth {\n /** 节点面:nodeId;终端面:userId */\n id: string;\n /** 毫秒时间戳(±60s 窗口) */\n ts: number;\n nonce: string;\n /** 协议能力版本 */\n proto: number;\n /** \"node\" | \"terminal\" */\n kind: string;\n /** 终端载体:\"web\" | \"miniapp\" | \"app\"(节点面留空) */\n client?: string;\n /**\n * 终端面 = HMAC-SHA256(terminalSecret, signableAuthBytes);节点面 = HMAC-SHA256(fleetSecret, …)\n *\n * 注意 `scope`/`expires` 在 `token` **之后**:proto3 按字段号升序编码,因此它们仍在\n * `signableAuthBytes` 内 —— 即**同样受签名完整性保护**(改 scope 会让 token 失效)。\n */\n token?: Uint8Array;\n /** 终端面被授权的 nodeId 列表(非空时网关严格校验;见 `verifyTerminalAuth`) */\n scope?: string[];\n /** 终端面过期时刻(毫秒);>0 时网关跳过 ±60s 窗口 */\n expires?: number;\n /**\n * 客户端能力位(见 `frame.ts` 的 `CAP_DEFLATE`)。\n *\n * 只用于声明支持;节点只有在 `AuthOk.caps` 也回同样位时才启用压缩上行。\n * 旧网关忽略未知字段,行为不变。\n */\n caps?: number;\n}\n\nexport interface AuthOk {\n ok: boolean;\n error?: string;\n serverTs: number;\n /** 网关能力位(语义同 `Auth.caps`);旧网关不回此字段(视为 0) */\n caps?: number;\n}\n\nexport function encodeAuth(auth: Auth): Uint8Array {\n const w = new Writer(64);\n w.stringField(1, auth.id);\n w.uint64Field(2, auth.ts);\n w.stringField(3, auth.nonce);\n // 注意:proto3 默认值省略 → proto=0 与 proto=1 不同,proto=0 不出现在线格式中\n w.uint64Field(4, auth.proto);\n w.stringField(5, auth.kind);\n w.stringField(6, auth.client ?? \"\");\n w.bytesField(7, auth.token ?? EMPTY_BYTES);\n // repeated string 在 protobuf 中是重复 tag(非 packed),逐个写即可\n for (const id of auth.scope ?? []) w.stringField(8, id);\n w.uint64Field(9, auth.expires ?? 0);\n w.uint64Field(10, auth.caps ?? 0);\n return w.finish();\n}\n\n/**\n * 参与签名的字节:清空 `token` 后编码。\n *\n * `scope`/`expires` 字段号大于 `token`,但 prost/本实现都按字段号升序编码,\n * 因此它们**仍在签名字节内**(受完整性保护),不是「token 之后的免费字段」。\n */\nexport function signableAuthBytes(auth: Auth): Uint8Array {\n return encodeAuth({ ...auth, token: undefined });\n}\n\nexport function decodeAuth(bytes: Uint8Array): Auth {\n const r = new Reader(bytes);\n const auth: Auth = { id: \"\", ts: 0, nonce: \"\", proto: 0, kind: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.id = r.string();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else auth.ts = r.u64();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.nonce = r.string();\n break;\n case 4:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else auth.proto = r.u64();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.kind = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.client = r.string();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else auth.token = r.lenPrefixed();\n break;\n case 8:\n if (wire !== WIRE_LEN) r.skip(wire);\n else (auth.scope ??= []).push(r.string());\n break;\n case 9:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else auth.expires = r.u64();\n break;\n case 10:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else auth.caps = r.u64();\n break;\n default:\n r.skip(wire);\n }\n }\n return auth;\n}\n\nexport function encodeAuthOk(ok: AuthOk): Uint8Array {\n const w = new Writer(48);\n w.boolField(1, ok.ok);\n w.stringField(2, ok.error ?? \"\");\n w.uint64Field(3, ok.serverTs);\n w.uint64Field(4, ok.caps ?? 0);\n return w.finish();\n}\n\nexport function decodeAuthOk(bytes: Uint8Array): AuthOk {\n const r = new Reader(bytes);\n const out: AuthOk = { ok: false, serverTs: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else out.ok = r.varint() !== 0n;\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else out.error = r.string();\n break;\n case 3:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else out.serverTs = r.u64();\n break;\n case 4:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else out.caps = r.u64();\n break;\n default:\n r.skip(wire);\n }\n }\n return out;\n}\n\n// ===================== 终端数据 =====================\n\nexport function encodeTerminalData(td: TerminalData): Uint8Array {\n const w = new Writer(64 + (td.data?.length ?? 0));\n w.stringField(1, td.nodeId ?? \"\");\n w.stringField(2, td.terminalId);\n w.stringField(3, td.kind);\n w.bytesField(4, td.data ?? EMPTY_BYTES);\n w.uint64Field(5, td.seq ?? 0);\n // 0 = 终端:不写字段,保持与旧端字节兼容(proto3 默认值不上线)\n if (td.channel) w.uint64Field(6, td.channel);\n if (td.session) w.stringField(7, td.session);\n return w.finish();\n}\n\nexport function decodeTerminalData(bytes: Uint8Array): TerminalData {\n const r = new Reader(bytes);\n const td: TerminalData = { terminalId: \"\", kind: \"\" };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.nodeId = r.string();\n break;\n case 2:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.terminalId = r.string();\n break;\n case 3:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.kind = r.string();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.data = r.lenPrefixed();\n break;\n case 5:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else td.seq = r.u64();\n break;\n case 6:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else td.channel = r.u64();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else td.session = r.string();\n break;\n default:\n r.skip(wire);\n }\n }\n return td;\n}\n\n// ===================== 快照 / 订阅 =====================\n\nexport interface NodeState {\n nodeId: string;\n online: boolean;\n lastSeen: number;\n platform?: string;\n version?: string;\n ip?: string;\n /**\n * 节点上报的原始 info JSON(`Info.detail` 的转发),供终端快照读取项目/统计。\n *\n * 快照借此**替代 MQTT retained info**:订阅后一次拿到,不必逐节点发指令。\n * 节点从未上报过 INFO 时为空。\n */\n detail?: Uint8Array;\n}\n\nexport interface Snapshot {\n nodes: NodeState[];\n /** 当前事件游标(客户端据此发起 resume) */\n seq: number;\n}\n\nexport function encodeNodeState(n: NodeState): Uint8Array {\n const w = new Writer(96);\n w.stringField(1, n.nodeId);\n w.boolField(2, n.online);\n w.uint64Field(3, n.lastSeen);\n w.stringField(4, n.platform ?? \"\");\n w.stringField(5, n.version ?? \"\");\n w.stringField(6, n.ip ?? \"\");\n w.bytesField(7, n.detail ?? EMPTY_BYTES);\n // 字段号必须与 `Status.msg_kind` 一致(9),否则错配无法被识别\n w.uint64Field(9, MSG_KIND_NODE_STATE);\n return w.finish();\n}\n\nexport function decodeNodeState(bytes: Uint8Array): NodeState {\n const r = new Reader(bytes);\n const n: NodeState = { nodeId: \"\", online: false, lastSeen: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.nodeId = r.string();\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else n.online = r.varint() !== 0n;\n break;\n case 3:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else n.lastSeen = r.u64();\n break;\n case 4:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.platform = r.string();\n break;\n case 5:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.version = r.string();\n break;\n case 6:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.ip = r.string();\n break;\n case 7:\n if (wire !== WIRE_LEN) r.skip(wire);\n else n.detail = r.lenPrefixed();\n break;\n case 9: {\n if (wire !== WIRE_VARINT) r.skip(wire);\n else checkMsgKind(\"NodeState\", Number(r.varint()), MSG_KIND_NODE_STATE);\n break;\n }\n default:\n r.skip(wire);\n }\n }\n return n;\n}\n\n/**\n * 校验 `STATUS` 帧的身份标记。\n *\n * `0`(旧实现未填)放行——否则新网关与新客户端会让旧版本直接不可用。\n * 非 0 且不匹配说明**用错了解码器**(把 NodeState 当 Status 解),\n * 这种错用此前会静默读到错值,这里改成显式报错。\n */\nfunction checkMsgKind(label: string, actual: number, expected: number): void {\n if (actual !== 0 && actual !== expected) {\n throw new WireError(\n `${label} 帧的身份标记不符(msg_kind=${actual},期望 ${expected}):很可能用错了解码器`,\n );\n }\n}\n\nexport function encodeSnapshot(snap: Snapshot): Uint8Array {\n const w = new Writer(128);\n for (const node of snap.nodes) {\n w.tag(1, WIRE_LEN);\n w.lenPrefixed(encodeNodeState(node));\n }\n w.uint64Field(2, snap.seq);\n return w.finish();\n}\n\nexport function decodeSnapshot(bytes: Uint8Array): Snapshot {\n const r = new Reader(bytes);\n const snap: Snapshot = { nodes: [], seq: 0 };\n while (!r.eof) {\n const { field, wire } = r.tag();\n switch (field) {\n case 1:\n if (wire !== WIRE_LEN) r.skip(wire);\n else snap.nodes.push(decodeNodeState(r.lenPrefixed()));\n break;\n case 2:\n if (wire !== WIRE_VARINT) r.skip(wire);\n else snap.seq = r.u64();\n break;\n default:\n r.skip(wire);\n }\n }\n return snap;\n}\n\nfunction encodeNodeIds(ids: string[]): Uint8Array {\n const w = new Writer(64);\n for (const id of ids) w.stringField(1, id);\n return w.finish();\n}\n\nfunction decodeNodeIds(bytes: Uint8Array): string[] {\n const r = new Reader(bytes);\n const ids: string[] = [];\n while (!r.eof) {\n const { field, wire } = r.tag();\n if (field === 1 && wire === WIRE_LEN) ids.push(r.string());\n else r.skip(wire);\n }\n return ids;\n}\n\n/**\n * 订阅帧:节点列表 + 是否要内容增量。\n *\n * `noDetail` 用反向布尔的 `.proto` 字段(`Subscribe.no_detail`):默认 false\n * 表示「要细节」,与本字段出现前的行为一致。只有双方(控制台/网关)都支持时\n * 才会真正省下带宽;旧网关忽略未知字段,退化为全量推送。\n */\nexport function encodeSubscribe(ids: string[], noDetail = false): Uint8Array {\n if (!noDetail) return encodeNodeIds(ids);\n const w = new Writer(64);\n for (const id of ids) w.stringField(1, id);\n w.boolField(2, true);\n return w.finish();\n}\n\n/** 只取节点列表(保持既有调用方与测试的返回类型不变) */\nexport const decodeSubscribe = decodeNodeIds;\n\n/** 连 `no_detail` 一起解出(网关侧 / 测试需要判定订阅意图时用) */\nexport function decodeSubscribeDetail(bytes: Uint8Array): {\n nodeIds: string[];\n noDetail: boolean;\n} {\n const r = new Reader(bytes);\n const nodeIds: string[] = [];\n let noDetail = false;\n while (!r.eof) {\n const { field, wire } = r.tag();\n if (field === 1 && wire === WIRE_LEN) nodeIds.push(r.string());\n else if (field === 2 && wire === WIRE_VARINT) noDetail = r.varint() !== 0n;\n else r.skip(wire);\n }\n return { nodeIds, noDetail };\n}\nexport const encodeUnsubscribe = encodeNodeIds;\nexport const decodeUnsubscribe = decodeNodeIds;\n\nexport function encodeResume(since: number, nodeIds: string[] = []): Uint8Array {\n const w = new Writer(16 + nodeIds.length * 16);\n w.uint64Field(1, since);\n for (const id of nodeIds) w.stringField(2, id);\n return w.finish();\n}\n\nexport function decodeResume(bytes: Uint8Array): { since: number; nodeIds: string[] } {\n const r = new Reader(bytes);\n let since = 0;\n const nodeIds: string[] = [];\n while (!r.eof) {\n const { field, wire } = r.tag();\n if (field === 1 && wire === WIRE_VARINT) since = r.u64();\n else if (field === 2 && wire === WIRE_LEN) nodeIds.push(r.string());\n else r.skip(wire);\n }\n return { since, nodeIds };\n}","/** 十六进制编解码(可移植,向量文件与调试用) */\n\nexport function toHex(bytes: Uint8Array): string {\n let out = \"\";\n for (const b of bytes) out += b.toString(16).padStart(2, \"0\");\n return out;\n}\n\nexport function fromHex(hex: string): Uint8Array {\n const s = hex.trim();\n if (s.length % 2 !== 0) throw new Error(`十六进制长度必须为偶数: ${s.length}`);\n const out = new Uint8Array(s.length / 2);\n for (let i = 0; i < out.length; i++) {\n const byte = Number.parseInt(s.slice(i * 2, i * 2 + 2), 16);\n if (Number.isNaN(byte)) throw new Error(`非法十六进制内容: ${s.slice(i * 2, i * 2 + 2)}`);\n out[i] = byte;\n }\n return out;\n}\n"],"mappings":"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","names":[]}
@@ -113,6 +113,13 @@ interface Frame {
113
113
  seq: number;
114
114
  payload: Uint8Array;
115
115
  }
116
+ /**
117
+ * 流式解码的缓冲上限:`2 × 帧上限`。
118
+ *
119
+ * 与 Rust 侧 `gateway/src/stream.rs` 的 `MAX_BUFFER_BYTES` 同口径:缓冲里可能残留
120
+ * 一条合法但未收满的帧,同时下一条 WS 消息也已到达,两者都合法。
121
+ */
122
+ declare const MAX_STREAM_BUFFER_BYTES: number;
116
123
  declare function encodeFrame(frame: {
117
124
  type: number;
118
125
  seq: number;
@@ -143,6 +150,32 @@ declare function decodeCompressedPayload(payload: Uint8Array): {
143
150
  } | null;
144
151
  /** 帧类型名 → 值(向量文件用) */
145
152
  declare function frameTypeFromName(name: string): FrameTypeValue;
153
+ /**
154
+ * 字节流 → 帧 的增量解码器。
155
+ *
156
+ * WebSocket 的消息边界不可依赖(分片、粘包、future batching、中间层 coalescing 都会
157
+ * 让一条消息里出现多条帧)。早先客户端用 `decodeFrame` 要求「一条消息恰好一帧」,
158
+ * 一旦出现合并就会整体抛错并丢掉**全部**帧,而且无法重新同步。
159
+ *
160
+ * 语义与 Rust 侧 `gateway/src/stream.rs` 对齐:
161
+ * - 字节不足 → `nextFrame()` 返回 `null`(不消费任何字节);
162
+ * - 协议非法 → 抛 `FrameError`,调用方应断开并重建解码器;
163
+ * - 缓冲超过 `maxBuffer` → 抛错(防半帧永久堆积)。
164
+ *
165
+ * 压缩帧原样返回(`type = COMPRESSED`):解压是异步 API,由调用方决定。
166
+ */
167
+ declare class StreamDecoder {
168
+ private readonly maxBuffer;
169
+ private buf;
170
+ constructor(maxBuffer?: number);
171
+ /** 已缓存但尚未解出的字节数 */
172
+ get buffered(): number;
173
+ /** 丢弃缓存(协议错误后重新同步用) */
174
+ reset(): void;
175
+ push(chunk: Uint8Array): void;
176
+ /** 解出下一帧;不足返回 `null`。协议错误抛 `FrameError`。 */
177
+ nextFrame(): Frame | null;
178
+ }
146
179
 
147
180
  /**
148
181
  * UTF-8 编解码(手工实现,零依赖)
@@ -163,4 +196,4 @@ declare function utf8Decode(b: Uint8Array): string;
163
196
  declare function toHex(bytes: Uint8Array): string;
164
197
  declare function fromHex(hex: string): Uint8Array;
165
198
 
166
- export { CAP_DEFLATE, EMPTY as EMPTY_BYTES, FRAME_MAGIC, type Frame, FrameError, FrameType, type FrameTypeName, type FrameTypeValue, MAX_FRAME_BYTES, PROTOCOL_VERSION, Reader, Utf8Error, WIRE_FIXED32, WIRE_FIXED64, WIRE_LEN, WIRE_VARINT, WireError, Writer, decodeCompressedPayload, decodeFrame, encodeCompressedPayload, encodeFrame, frameTypeFromName, frameTypeName, fromHex, toHex, utf8Decode, utf8Encode };
199
+ export { CAP_DEFLATE, EMPTY as EMPTY_BYTES, FRAME_MAGIC, type Frame, FrameError, FrameType, type FrameTypeName, type FrameTypeValue, MAX_FRAME_BYTES, MAX_STREAM_BUFFER_BYTES, PROTOCOL_VERSION, Reader, StreamDecoder, Utf8Error, WIRE_FIXED32, WIRE_FIXED64, WIRE_LEN, WIRE_VARINT, WireError, Writer, decodeCompressedPayload, decodeFrame, encodeCompressedPayload, encodeFrame, frameTypeFromName, frameTypeName, fromHex, toHex, utf8Decode, utf8Encode };
@@ -113,6 +113,13 @@ interface Frame {
113
113
  seq: number;
114
114
  payload: Uint8Array;
115
115
  }
116
+ /**
117
+ * 流式解码的缓冲上限:`2 × 帧上限`。
118
+ *
119
+ * 与 Rust 侧 `gateway/src/stream.rs` 的 `MAX_BUFFER_BYTES` 同口径:缓冲里可能残留
120
+ * 一条合法但未收满的帧,同时下一条 WS 消息也已到达,两者都合法。
121
+ */
122
+ declare const MAX_STREAM_BUFFER_BYTES: number;
116
123
  declare function encodeFrame(frame: {
117
124
  type: number;
118
125
  seq: number;
@@ -143,6 +150,32 @@ declare function decodeCompressedPayload(payload: Uint8Array): {
143
150
  } | null;
144
151
  /** 帧类型名 → 值(向量文件用) */
145
152
  declare function frameTypeFromName(name: string): FrameTypeValue;
153
+ /**
154
+ * 字节流 → 帧 的增量解码器。
155
+ *
156
+ * WebSocket 的消息边界不可依赖(分片、粘包、future batching、中间层 coalescing 都会
157
+ * 让一条消息里出现多条帧)。早先客户端用 `decodeFrame` 要求「一条消息恰好一帧」,
158
+ * 一旦出现合并就会整体抛错并丢掉**全部**帧,而且无法重新同步。
159
+ *
160
+ * 语义与 Rust 侧 `gateway/src/stream.rs` 对齐:
161
+ * - 字节不足 → `nextFrame()` 返回 `null`(不消费任何字节);
162
+ * - 协议非法 → 抛 `FrameError`,调用方应断开并重建解码器;
163
+ * - 缓冲超过 `maxBuffer` → 抛错(防半帧永久堆积)。
164
+ *
165
+ * 压缩帧原样返回(`type = COMPRESSED`):解压是异步 API,由调用方决定。
166
+ */
167
+ declare class StreamDecoder {
168
+ private readonly maxBuffer;
169
+ private buf;
170
+ constructor(maxBuffer?: number);
171
+ /** 已缓存但尚未解出的字节数 */
172
+ get buffered(): number;
173
+ /** 丢弃缓存(协议错误后重新同步用) */
174
+ reset(): void;
175
+ push(chunk: Uint8Array): void;
176
+ /** 解出下一帧;不足返回 `null`。协议错误抛 `FrameError`。 */
177
+ nextFrame(): Frame | null;
178
+ }
146
179
 
147
180
  /**
148
181
  * UTF-8 编解码(手工实现,零依赖)
@@ -163,4 +196,4 @@ declare function utf8Decode(b: Uint8Array): string;
163
196
  declare function toHex(bytes: Uint8Array): string;
164
197
  declare function fromHex(hex: string): Uint8Array;
165
198
 
166
- export { CAP_DEFLATE, EMPTY as EMPTY_BYTES, FRAME_MAGIC, type Frame, FrameError, FrameType, type FrameTypeName, type FrameTypeValue, MAX_FRAME_BYTES, PROTOCOL_VERSION, Reader, Utf8Error, WIRE_FIXED32, WIRE_FIXED64, WIRE_LEN, WIRE_VARINT, WireError, Writer, decodeCompressedPayload, decodeFrame, encodeCompressedPayload, encodeFrame, frameTypeFromName, frameTypeName, fromHex, toHex, utf8Decode, utf8Encode };
199
+ export { CAP_DEFLATE, EMPTY as EMPTY_BYTES, FRAME_MAGIC, type Frame, FrameError, FrameType, type FrameTypeName, type FrameTypeValue, MAX_FRAME_BYTES, MAX_STREAM_BUFFER_BYTES, PROTOCOL_VERSION, Reader, StreamDecoder, Utf8Error, WIRE_FIXED32, WIRE_FIXED64, WIRE_LEN, WIRE_VARINT, WireError, Writer, decodeCompressedPayload, decodeFrame, encodeCompressedPayload, encodeFrame, frameTypeFromName, frameTypeName, fromHex, toHex, utf8Decode, utf8Encode };