@leemour/max-cli 0.7.0 → 0.9.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.
Files changed (192) hide show
  1. package/README.md +198 -79
  2. package/dist/cache/schema.d.ts +13 -8
  3. package/dist/cache/schema.d.ts.map +1 -1
  4. package/dist/cache/schema.js +84 -23
  5. package/dist/cache/schema.js.map +1 -1
  6. package/dist/cache/store.d.ts +15 -0
  7. package/dist/cache/store.d.ts.map +1 -1
  8. package/dist/cache/store.js +32 -3
  9. package/dist/cache/store.js.map +1 -1
  10. package/dist/client.d.ts +28 -1
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +112 -13
  13. package/dist/client.js.map +1 -1
  14. package/dist/commands/chats.d.ts.map +1 -1
  15. package/dist/commands/chats.js +8 -0
  16. package/dist/commands/chats.js.map +1 -1
  17. package/dist/commands/config.d.ts.map +1 -1
  18. package/dist/commands/config.js +6 -2
  19. package/dist/commands/config.js.map +1 -1
  20. package/dist/commands/context.d.ts +14 -2
  21. package/dist/commands/context.d.ts.map +1 -1
  22. package/dist/commands/context.js +18 -19
  23. package/dist/commands/context.js.map +1 -1
  24. package/dist/commands/export.d.ts +3 -0
  25. package/dist/commands/export.d.ts.map +1 -0
  26. package/dist/commands/export.js +83 -0
  27. package/dist/commands/export.js.map +1 -0
  28. package/dist/commands/mcp.d.ts.map +1 -1
  29. package/dist/commands/mcp.js +9 -2
  30. package/dist/commands/mcp.js.map +1 -1
  31. package/dist/commands/messages.d.ts.map +1 -1
  32. package/dist/commands/messages.js +126 -3
  33. package/dist/commands/messages.js.map +1 -1
  34. package/dist/commands/models.d.ts +7 -0
  35. package/dist/commands/models.d.ts.map +1 -0
  36. package/dist/commands/models.js +47 -0
  37. package/dist/commands/models.js.map +1 -0
  38. package/dist/commands/serve.d.ts.map +1 -1
  39. package/dist/commands/serve.js +50 -2
  40. package/dist/commands/serve.js.map +1 -1
  41. package/dist/commands/session.d.ts.map +1 -1
  42. package/dist/commands/session.js +13 -3
  43. package/dist/commands/session.js.map +1 -1
  44. package/dist/commands/watch.d.ts.map +1 -1
  45. package/dist/commands/watch.js +12 -16
  46. package/dist/commands/watch.js.map +1 -1
  47. package/dist/config.d.ts +18 -2
  48. package/dist/config.d.ts.map +1 -1
  49. package/dist/config.js +58 -4
  50. package/dist/config.js.map +1 -1
  51. package/dist/domain/map.d.ts.map +1 -1
  52. package/dist/domain/map.js +5 -0
  53. package/dist/domain/map.js.map +1 -1
  54. package/dist/domain/models.d.ts +14 -0
  55. package/dist/domain/models.d.ts.map +1 -1
  56. package/dist/domain/models.js.map +1 -1
  57. package/dist/download.d.ts +2 -0
  58. package/dist/download.d.ts.map +1 -1
  59. package/dist/download.js +11 -0
  60. package/dist/download.js.map +1 -1
  61. package/dist/export.d.ts +26 -0
  62. package/dist/export.d.ts.map +1 -0
  63. package/dist/export.js +75 -0
  64. package/dist/export.js.map +1 -0
  65. package/dist/generated/client.generated.d.ts +2 -0
  66. package/dist/generated/client.generated.d.ts.map +1 -1
  67. package/dist/generated/client.generated.js +2 -0
  68. package/dist/generated/client.generated.js.map +1 -1
  69. package/dist/generated/opcodes.generated.d.ts +0 -9
  70. package/dist/generated/opcodes.generated.d.ts.map +1 -1
  71. package/dist/generated/opcodes.generated.js +0 -9
  72. package/dist/generated/opcodes.generated.js.map +1 -1
  73. package/dist/generated/operations.generated.d.ts +24 -6
  74. package/dist/generated/operations.generated.d.ts.map +1 -1
  75. package/dist/generated/operations.generated.js +4 -2
  76. package/dist/generated/operations.generated.js.map +1 -1
  77. package/dist/mcp/confirm.d.ts +7 -0
  78. package/dist/mcp/confirm.d.ts.map +1 -1
  79. package/dist/mcp/confirm.js +16 -7
  80. package/dist/mcp/confirm.js.map +1 -1
  81. package/dist/mcp/instructions.d.ts +5 -1
  82. package/dist/mcp/instructions.d.ts.map +1 -1
  83. package/dist/mcp/instructions.js +16 -2
  84. package/dist/mcp/instructions.js.map +1 -1
  85. package/dist/mcp/server.d.ts +3 -1
  86. package/dist/mcp/server.d.ts.map +1 -1
  87. package/dist/mcp/server.js +22 -3
  88. package/dist/mcp/server.js.map +1 -1
  89. package/dist/mcp/session.d.ts +1 -1
  90. package/dist/mcp/session.d.ts.map +1 -1
  91. package/dist/mcp/session.js +1 -1
  92. package/dist/mcp/session.js.map +1 -1
  93. package/dist/mcp/tools.d.ts +8 -1
  94. package/dist/mcp/tools.d.ts.map +1 -1
  95. package/dist/mcp/tools.js +87 -10
  96. package/dist/mcp/tools.js.map +1 -1
  97. package/dist/program.d.ts.map +1 -1
  98. package/dist/program.js +6 -2
  99. package/dist/program.js.map +1 -1
  100. package/dist/protocol/connection.d.ts +2 -1
  101. package/dist/protocol/connection.d.ts.map +1 -1
  102. package/dist/protocol/connection.js +45 -14
  103. package/dist/protocol/connection.js.map +1 -1
  104. package/dist/protocol/frame.d.ts +22 -14
  105. package/dist/protocol/frame.d.ts.map +1 -1
  106. package/dist/protocol/frame.js +116 -37
  107. package/dist/protocol/frame.js.map +1 -1
  108. package/dist/protocol/lz4.d.ts +15 -0
  109. package/dist/protocol/lz4.d.ts.map +1 -0
  110. package/dist/protocol/lz4.js +154 -0
  111. package/dist/protocol/lz4.js.map +1 -0
  112. package/dist/sends/guard.d.ts +7 -3
  113. package/dist/sends/guard.d.ts.map +1 -1
  114. package/dist/sends/guard.js +32 -11
  115. package/dist/sends/guard.js.map +1 -1
  116. package/dist/sends/journal.d.ts +6 -1
  117. package/dist/sends/journal.d.ts.map +1 -1
  118. package/dist/sends/journal.js.map +1 -1
  119. package/dist/sends/permissions.d.ts +11 -0
  120. package/dist/sends/permissions.d.ts.map +1 -0
  121. package/dist/sends/permissions.js +47 -0
  122. package/dist/sends/permissions.js.map +1 -0
  123. package/dist/server/lines.d.ts +4 -0
  124. package/dist/server/lines.d.ts.map +1 -1
  125. package/dist/server/lines.js +11 -2
  126. package/dist/server/lines.js.map +1 -1
  127. package/dist/server/server-connection.d.ts +25 -15
  128. package/dist/server/server-connection.d.ts.map +1 -1
  129. package/dist/server/server-connection.js +69 -63
  130. package/dist/server/server-connection.js.map +1 -1
  131. package/dist/server/server.d.ts +7 -0
  132. package/dist/server/server.d.ts.map +1 -1
  133. package/dist/server/server.js +84 -19
  134. package/dist/server/server.js.map +1 -1
  135. package/dist/server/start.d.ts +23 -1
  136. package/dist/server/start.d.ts.map +1 -1
  137. package/dist/server/start.js +61 -7
  138. package/dist/server/start.js.map +1 -1
  139. package/dist/session/adopt.d.ts.map +1 -1
  140. package/dist/session/adopt.js +4 -0
  141. package/dist/session/adopt.js.map +1 -1
  142. package/dist/session/handshake.d.ts +5 -3
  143. package/dist/session/handshake.d.ts.map +1 -1
  144. package/dist/session/handshake.js +3 -3
  145. package/dist/session/handshake.js.map +1 -1
  146. package/dist/spec/identity.d.ts +5 -4
  147. package/dist/spec/identity.d.ts.map +1 -1
  148. package/dist/spec/identity.js +5 -4
  149. package/dist/spec/identity.js.map +1 -1
  150. package/dist/spec/index.js +4 -4
  151. package/dist/spec/index.js.map +1 -1
  152. package/dist/spec/operations/chats.d.ts +16 -6
  153. package/dist/spec/operations/chats.d.ts.map +1 -1
  154. package/dist/spec/operations/chats.js +38 -9
  155. package/dist/spec/operations/chats.js.map +1 -1
  156. package/dist/spec/operations/messages.d.ts +13 -1
  157. package/dist/spec/operations/messages.d.ts.map +1 -1
  158. package/dist/spec/operations/messages.js +18 -4
  159. package/dist/spec/operations/messages.js.map +1 -1
  160. package/dist/spec/operations/session.d.ts +5 -4
  161. package/dist/spec/operations/session.d.ts.map +1 -1
  162. package/dist/spec/operations/session.js +7 -6
  163. package/dist/spec/operations/session.js.map +1 -1
  164. package/dist/spec/scalars.js +2 -2
  165. package/dist/testing/mock-max.d.ts +5 -1
  166. package/dist/testing/mock-max.d.ts.map +1 -1
  167. package/dist/testing/mock-max.js +6 -3
  168. package/dist/testing/mock-max.js.map +1 -1
  169. package/dist/transcribe/index.d.ts +34 -0
  170. package/dist/transcribe/index.d.ts.map +1 -0
  171. package/dist/transcribe/index.js +43 -0
  172. package/dist/transcribe/index.js.map +1 -0
  173. package/dist/transcribe/install.d.ts +18 -0
  174. package/dist/transcribe/install.d.ts.map +1 -0
  175. package/dist/transcribe/install.js +67 -0
  176. package/dist/transcribe/install.js.map +1 -0
  177. package/dist/transcribe/models.d.ts +32 -0
  178. package/dist/transcribe/models.d.ts.map +1 -0
  179. package/dist/transcribe/models.js +124 -0
  180. package/dist/transcribe/models.js.map +1 -0
  181. package/dist/transcribe/speech.d.ts +25 -0
  182. package/dist/transcribe/speech.d.ts.map +1 -0
  183. package/dist/transcribe/speech.js +105 -0
  184. package/dist/transcribe/speech.js.map +1 -0
  185. package/dist/update.d.ts +1 -11
  186. package/dist/update.d.ts.map +1 -1
  187. package/dist/update.js +14 -42
  188. package/dist/update.js.map +1 -1
  189. package/dist/version.d.ts +1 -1
  190. package/dist/version.js +1 -1
  191. package/package.json +9 -3
  192. package/skills/max-cli/SKILL.md +19 -3
@@ -1,5 +1,9 @@
1
- /** The protocol version the web client pins. Confirmed in tsmax, maxrs and max-api-docs. */
2
- export declare const PROTOCOL_VERSION = 11;
1
+ /**
2
+ * The binary protocol web.max.ru speaks, captured from a live socket on 2026-09-25
3
+ * (`src/testing/fixtures/web-capture-2026-09-25.json`). JSON on protocol 11 was what we used to
4
+ * send, and nothing the web client sends looks like it.
5
+ */
6
+ export declare const PROTOCOL_VERSION = 10;
3
7
  export declare const Command: {
4
8
  readonly REQUEST: 0;
5
9
  readonly RESPONSE: 1;
@@ -11,29 +15,33 @@ export type Payload = Record<string, unknown>;
11
15
  export interface OutboundFrame {
12
16
  seq: number;
13
17
  opcode: number;
14
- /** Absent only in the answer to MAX's ping, which the web client sends with no payload at all. */
18
+ /** Absent, or empty, goes out as a zero-length body — as the web client's ping answer does. */
15
19
  payload?: Payload;
16
20
  cmd?: Command;
17
21
  }
18
22
  export interface InboundFrame {
19
23
  ver: number;
20
24
  cmd: number;
21
- seq: number | null;
25
+ seq: number;
22
26
  opcode: number;
23
27
  payload: Payload | null;
24
28
  }
25
- export declare const encodeFrame: (frame: OutboundFrame) => string;
29
+ /** `ver` `cmd` `seq:u16` `opcode:u16` `flags:u8` `length:u24`, big-endian. */
30
+ export declare const HEADER_BYTES = 10;
31
+ export declare const SEQ_MODULO = 65536;
32
+ export declare const encodeFrame: (frame: OutboundFrame) => Uint8Array;
33
+ /** The header alone, so a body that cannot be read still says which request it answered. */
34
+ export declare const decodeHeader: (bytes: Uint8Array) => Omit<InboundFrame, "payload"> & {
35
+ flags: number;
36
+ length: number;
37
+ };
26
38
  /**
27
- * **Never `JSON.parse`.** Message ids are 64-bit and past `Number.MAX_SAFE_INTEGER` — 18 digits,
28
- * measured — so the built-in parser rounds them and two different messages arrive as one id.
29
- * `lossless-json` hands back a bigint for any integer that would not survive, and every id leaves
30
- * this layer as a string.
31
- *
32
- * ⚠ Measured 2026-09-19: **chat ids on the owner's account reach 14 digits, not 19**, and contact
33
- * ids reach 9 — all comfortably inside a number. The hazard is real and it is the message ids that
34
- * carry it; a 19-digit chat id is an illustration, not something seen.
39
+ * **Integers come back as `number` unless a number would lose digits.** MessagePack hands every
40
+ * 64-bit integer over as a `bigint`, and MAX sends times as 64-bit — a `bigint` timestamp breaks
41
+ * every `Date` and every subtraction above this layer. Message ids are 18 digits, past
42
+ * `Number.MAX_SAFE_INTEGER`, and stay `bigint`; every id leaves the domain mapper as a string.
35
43
  */
36
- export declare const decodeFrame: (raw: string) => InboundFrame;
44
+ export declare const decodeFrame: (bytes: Uint8Array) => InboundFrame;
37
45
  export declare class FrameError extends Error {
38
46
  constructor(what: string);
39
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/protocol/frame.ts"],"names":[],"mappings":"AAEA,4FAA4F;AAC5F,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC,eAAO,MAAM,OAAO;;;;;CAKV,CAAA;AACV,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAA;AAE5D,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAE7C,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,kGAAkG;IAClG,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CACxB;AAED,eAAO,MAAM,WAAW,GAAI,OAAO,aAAa,KAAG,MAOrC,CAAA;AAEd;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,YAczC,CAAA;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACvB,IAAI,EAAE,MAAM;CAIzB;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAK9C,CAAA"}
1
+ {"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/protocol/frame.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC,eAAO,MAAM,OAAO;;;;;CAKV,CAAA;AACV,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAA;AAE5D,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAE7C,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,+FAA+F;IAC/F,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CACxB;AAED,8EAA8E;AAC9E,eAAO,MAAM,YAAY,KAAK,CAAA;AAS9B,eAAO,MAAM,UAAU,QAAW,CAAA;AAKlC,eAAO,MAAM,WAAW,GAAI,OAAO,aAAa,KAAG,UAwBlD,CAAA;AAED,4FAA4F;AAC5F,eAAO,MAAM,YAAY,GAAI,OAAO,UAAU,KAAG,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAgB/G,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,UAAU,KAAG,YAW/C,CAAA;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACvB,IAAI,EAAE,MAAM;CAIzB;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAK9C,CAAA"}
@@ -1,42 +1,89 @@
1
- import { isInteger, isSafeNumber, parse, stringify } from "lossless-json";
2
- /** The protocol version the web client pins. Confirmed in tsmax, maxrs and max-api-docs. */
3
- export const PROTOCOL_VERSION = 11;
1
+ import { decode, ExtData, ExtensionCodec, encode } from "@msgpack/msgpack";
2
+ import { compressBlock, decompressBlock } from "./lz4.js";
3
+ /**
4
+ * The binary protocol web.max.ru speaks, captured from a live socket on 2026-09-25
5
+ * (`src/testing/fixtures/web-capture-2026-09-25.json`). JSON on protocol 11 was what we used to
6
+ * send, and nothing the web client sends looks like it.
7
+ */
8
+ export const PROTOCOL_VERSION = 10;
4
9
  export const Command = {
5
10
  REQUEST: 0,
6
11
  RESPONSE: 1,
7
12
  EVENT: 2,
8
13
  ERROR: 3,
9
14
  };
10
- export const encodeFrame = (frame) => stringify({
11
- ver: PROTOCOL_VERSION,
12
- cmd: frame.cmd ?? Command.REQUEST,
13
- seq: frame.seq,
14
- opcode: frame.opcode,
15
- payload: frame.payload,
16
- });
15
+ /** `ver` `cmd` `seq:u16` `opcode:u16` `flags:u8` `length:u24`, big-endian. */
16
+ export const HEADER_BYTES = 10;
17
+ /** The web client sends 31 bytes plain and 37 compressed; where between them it switches was not seen. */
18
+ const COMPRESS_FROM = 32;
19
+ const ZSTD = 0xff;
20
+ const MAX_LZ4_FLAGS = 0x7f;
21
+ /** MAX wraps a number it means as a 64-bit id or time in extension type 1; so does the web client. */
22
+ const WRAPPED = 1;
23
+ export const SEQ_MODULO = 0x1_0000;
24
+ const wrapped = new ExtensionCodec();
25
+ wrapped.register({ type: WRAPPED, encode: () => null, decode: (data) => decodeBody(data) });
26
+ export const encodeFrame = (frame) => {
27
+ const raw = frame.payload && Object.keys(frame.payload).length > 0 ? encodeBody(frame.payload) : new Uint8Array(0);
28
+ let body = raw;
29
+ let flags = 0;
30
+ if (raw.length >= COMPRESS_FROM) {
31
+ const compressed = compressBlock(raw);
32
+ const factor = Math.ceil(raw.length / compressed.length);
33
+ if (factor <= MAX_LZ4_FLAGS) {
34
+ // Kept even when it came out larger: the web client does the same (47 bytes sent as 49).
35
+ body = compressed;
36
+ flags = factor;
37
+ }
38
+ }
39
+ const bytes = new Uint8Array(HEADER_BYTES + body.length);
40
+ const view = new DataView(bytes.buffer);
41
+ view.setUint8(0, PROTOCOL_VERSION);
42
+ view.setUint8(1, frame.cmd ?? Command.REQUEST);
43
+ view.setUint16(2, frame.seq % SEQ_MODULO);
44
+ view.setUint16(4, frame.opcode);
45
+ view.setUint32(6, ((flags << 24) | body.length) >>> 0);
46
+ bytes.set(body, HEADER_BYTES);
47
+ return bytes;
48
+ };
49
+ /** The header alone, so a body that cannot be read still says which request it answered. */
50
+ export const decodeHeader = (bytes) => {
51
+ if (bytes.length < HEADER_BYTES)
52
+ throw new FrameError(`a frame of ${bytes.length} bytes, shorter than its header`);
53
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
54
+ const packed = view.getUint32(6);
55
+ const header = {
56
+ ver: view.getUint8(0),
57
+ cmd: view.getUint8(1),
58
+ seq: view.getUint16(2),
59
+ opcode: view.getUint16(4),
60
+ flags: packed >>> 24,
61
+ length: packed & 0xff_ffff,
62
+ };
63
+ if (HEADER_BYTES + header.length > bytes.length) {
64
+ throw new FrameError(`a frame that claims ${header.length} bytes and carries ${bytes.length - HEADER_BYTES}`);
65
+ }
66
+ return header;
67
+ };
17
68
  /**
18
- * **Never `JSON.parse`.** Message ids are 64-bit and past `Number.MAX_SAFE_INTEGER` — 18 digits,
19
- * measured — so the built-in parser rounds them and two different messages arrive as one id.
20
- * `lossless-json` hands back a bigint for any integer that would not survive, and every id leaves
21
- * this layer as a string.
22
- *
23
- * ⚠ Measured 2026-09-19: **chat ids on the owner's account reach 14 digits, not 19**, and contact
24
- * ids reach 9 — all comfortably inside a number. The hazard is real and it is the message ids that
25
- * carry it; a 19-digit chat id is an illustration, not something seen.
69
+ * **Integers come back as `number` unless a number would lose digits.** MessagePack hands every
70
+ * 64-bit integer over as a `bigint`, and MAX sends times as 64-bit — a `bigint` timestamp breaks
71
+ * every `Date` and every subtraction above this layer. Message ids are 18 digits, past
72
+ * `Number.MAX_SAFE_INTEGER`, and stay `bigint`; every id leaves the domain mapper as a string.
26
73
  */
27
- export const decodeFrame = (raw) => {
28
- const value = parse(raw, undefined, {
29
- parseNumber: (text) => (isInteger(text) && !isSafeNumber(text) ? BigInt(text) : Number(text)),
30
- });
31
- if (!isRecord(value))
32
- throw new FrameError("a frame that is not an object");
33
- return {
34
- ver: header(value.ver, "ver"),
35
- cmd: header(value.cmd ?? Command.RESPONSE, "cmd"),
36
- seq: value.seq === null || value.seq === undefined ? null : header(value.seq, "seq"),
37
- opcode: header(value.opcode, "opcode"),
38
- payload: isRecord(value.payload) ? value.payload : null,
39
- };
74
+ export const decodeFrame = (bytes) => {
75
+ const { flags, length, ...header } = decodeHeader(bytes);
76
+ let body = bytes.subarray(HEADER_BYTES, HEADER_BYTES + length);
77
+ if (flags === ZSTD)
78
+ throw new FrameError("a zstd-compressed frame, which the web client was never seen receiving");
79
+ if (flags > MAX_LZ4_FLAGS)
80
+ throw new FrameError(`a frame with compression flags ${flags}`);
81
+ if (flags > 0)
82
+ body = decompressBlock(body, flags * length);
83
+ if (body.length === 0)
84
+ return { ...header, payload: null };
85
+ const value = decodeBody(body);
86
+ return { ...header, payload: isRecord(value) ? value : null };
40
87
  };
41
88
  export class FrameError extends Error {
42
89
  constructor(what) {
@@ -57,12 +104,44 @@ export const asId = (value) => {
57
104
  return value;
58
105
  return undefined;
59
106
  };
60
- const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
61
- const header = (value, field) => {
62
- const asNumber = typeof value === "bigint" ? Number(value) : value;
63
- if (typeof asNumber !== "number" || !Number.isSafeInteger(asNumber)) {
64
- throw new FrameError(`a frame whose \`${field}\` is not a whole number`);
107
+ /** A `bigint` is an id we built from a string (`toWireId`), and goes out wrapped the way the web client wraps ids. */
108
+ const encodeBody = (payload) => encode(wrapBigints(payload), { extensionCodec: wrapped, useBigInt64: true, ignoreUndefined: true });
109
+ const decodeBody = (bytes) => narrow(decode(bytes, { extensionCodec: wrapped, useBigInt64: true, mapKeyConverter: asKey }));
110
+ /**
111
+ * ⚠ With `useBigInt64` the library writes every `number` past 32 bits as a **float64**, and MAX
112
+ * refuses a login whose time arrives as one (`proto.payload`, measured 2026-09-25). A whole number
113
+ * that wide goes out as a bare 64-bit integer instead, as the web client sends `from` and
114
+ * `contactsSync`; only a `bigint` — an id — is wrapped.
115
+ */
116
+ const wrapBigints = (value) => {
117
+ if (typeof value === "bigint")
118
+ return new ExtData(WRAPPED, encode(value, { useBigInt64: true }));
119
+ if (typeof value === "number" && Number.isSafeInteger(value) && (value > 0xffff_ffff || value < -0x8000_0000))
120
+ return BigInt(value);
121
+ if (Array.isArray(value))
122
+ return value.map(wrapBigints);
123
+ if (isRecord(value))
124
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, wrapBigints(item)]));
125
+ return value;
126
+ };
127
+ const narrow = (value) => {
128
+ if (typeof value === "bigint")
129
+ return Number.MIN_SAFE_INTEGER <= value && value <= Number.MAX_SAFE_INTEGER ? Number(value) : value;
130
+ if (Array.isArray(value))
131
+ return value.map(narrow);
132
+ if (isRecord(value)) {
133
+ for (const key of Object.keys(value))
134
+ value[key] = narrow(value[key]);
65
135
  }
66
- return asNumber;
136
+ return value;
137
+ };
138
+ /** Map keys are chat and message ids as often as names; ours are always strings. */
139
+ const asKey = (key) => {
140
+ if (typeof key === "string")
141
+ return key;
142
+ if (typeof key === "number" || typeof key === "bigint")
143
+ return String(key);
144
+ throw new FrameError(`a map key of type ${typeof key}`);
67
145
  };
146
+ const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Uint8Array);
68
147
  //# sourceMappingURL=frame.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/protocol/frame.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/protocol/frame.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * LZ4 *block* format — no frame header, no checksum — which is what MAX puts in a frame body.
3
+ *
4
+ * Hand-written because both directions are small and a native binding is what breaks under Bun
5
+ * (REQUIREMENTS §36). The decompressor mirrors the one that read all 73 frames of the 2026-09-25
6
+ * capture; the compressor keeps the format's end-of-block rules, which a lenient decoder such as
7
+ * ours would not notice being broken but MAX's might.
8
+ */
9
+ export declare class Lz4Error extends Error {
10
+ constructor(what: string);
11
+ }
12
+ export declare const compressBlock: (src: Uint8Array) => Uint8Array;
13
+ /** `maxOutput` bounds a hostile or corrupt block; the frame header gives the caller one. */
14
+ export declare const decompressBlock: (src: Uint8Array, maxOutput: number) => Uint8Array;
15
+ //# sourceMappingURL=lz4.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lz4.d.ts","sourceRoot":"","sources":["../../src/protocol/lz4.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,qBAAa,QAAS,SAAQ,KAAK;gBACrB,IAAI,EAAE,MAAM;CAIzB;AAED,eAAO,MAAM,aAAa,GAAI,KAAK,UAAU,KAAG,UA4B/C,CAAA;AAED,4FAA4F;AAC5F,eAAO,MAAM,eAAe,GAAI,KAAK,UAAU,EAAE,WAAW,MAAM,KAAG,UA6BpE,CAAA"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * LZ4 *block* format — no frame header, no checksum — which is what MAX puts in a frame body.
3
+ *
4
+ * Hand-written because both directions are small and a native binding is what breaks under Bun
5
+ * (REQUIREMENTS §36). The decompressor mirrors the one that read all 73 frames of the 2026-09-25
6
+ * capture; the compressor keeps the format's end-of-block rules, which a lenient decoder such as
7
+ * ours would not notice being broken but MAX's might.
8
+ */
9
+ const MIN_MATCH = 4;
10
+ /** The last five bytes of a block are always literals. */
11
+ const LAST_LITERALS = 5;
12
+ /** No match may start within the last twelve bytes. */
13
+ const MF_LIMIT = 12;
14
+ const MAX_OFFSET = 0xffff;
15
+ const HASH_BITS = 12;
16
+ export class Lz4Error extends Error {
17
+ constructor(what) {
18
+ super(`MAX sent an LZ4 block that ${what}`);
19
+ this.name = "Lz4Error";
20
+ }
21
+ }
22
+ export const compressBlock = (src) => {
23
+ const out = new Growable(src.length + (src.length >> 8) + 16);
24
+ const table = new Int32Array(1 << HASH_BITS).fill(-1);
25
+ const matchLimit = src.length - LAST_LITERALS;
26
+ let anchor = 0;
27
+ let i = 0;
28
+ while (i < src.length - MF_LIMIT) {
29
+ const sequence = read32(src, i);
30
+ const slot = Math.imul(sequence, 2654435761) >>> (32 - HASH_BITS);
31
+ const candidate = table[slot];
32
+ table[slot] = i;
33
+ if (candidate < 0 || i - candidate > MAX_OFFSET || read32(src, candidate) !== sequence) {
34
+ i += 1;
35
+ continue;
36
+ }
37
+ let length = MIN_MATCH;
38
+ while (i + length < matchLimit && src[i + length] === src[candidate + length])
39
+ length += 1;
40
+ writeSequence(out, src.subarray(anchor, i), i - candidate, length);
41
+ i += length;
42
+ anchor = i;
43
+ }
44
+ writeSequence(out, src.subarray(anchor), 0, 0);
45
+ return out.bytes();
46
+ };
47
+ /** `maxOutput` bounds a hostile or corrupt block; the frame header gives the caller one. */
48
+ export const decompressBlock = (src, maxOutput) => {
49
+ const out = new Growable(Math.min(maxOutput, src.length * 4));
50
+ let p = 0;
51
+ while (p < src.length) {
52
+ const token = src[p++];
53
+ let literals = token >> 4;
54
+ if (literals === 15)
55
+ literals += readLength(src, () => p++);
56
+ if (p + literals > src.length)
57
+ throw new Lz4Error("runs past its own end");
58
+ out.append(src.subarray(p, p + literals));
59
+ p += literals;
60
+ if (out.length > maxOutput)
61
+ throw new Lz4Error("is larger than its frame allows");
62
+ if (p >= src.length)
63
+ break;
64
+ if (p + 2 > src.length)
65
+ throw new Lz4Error("ends in the middle of an offset");
66
+ const offset = src[p] | (src[p + 1] << 8);
67
+ p += 2;
68
+ if (offset === 0 || offset > out.length)
69
+ throw new Lz4Error("points before its own start");
70
+ let length = token & 15;
71
+ if (length === 15)
72
+ length += readLength(src, () => p++);
73
+ length += MIN_MATCH;
74
+ if (out.length + length > maxOutput)
75
+ throw new Lz4Error("is larger than its frame allows");
76
+ out.copyBack(offset, length);
77
+ }
78
+ return out.bytes();
79
+ };
80
+ const read32 = (bytes, at) => (bytes[at] |
81
+ (bytes[at + 1] << 8) |
82
+ (bytes[at + 2] << 16) |
83
+ (bytes[at + 3] << 24)) >>>
84
+ 0;
85
+ const readLength = (src, next) => {
86
+ let total = 0;
87
+ let byte;
88
+ do {
89
+ const at = next();
90
+ if (at >= src.length)
91
+ throw new Lz4Error("ends in the middle of a length");
92
+ byte = src[at];
93
+ total += byte;
94
+ } while (byte === 255);
95
+ return total;
96
+ };
97
+ const writeLength = (out, value) => {
98
+ let rest = value;
99
+ while (rest >= 255) {
100
+ out.push(255);
101
+ rest -= 255;
102
+ }
103
+ out.push(rest);
104
+ };
105
+ /** A match length of zero means the final, literals-only sequence. */
106
+ const writeSequence = (out, literals, offset, matchLength) => {
107
+ const literalNibble = Math.min(literals.length, 15);
108
+ const matchNibble = matchLength === 0 ? 0 : Math.min(matchLength - MIN_MATCH, 15);
109
+ out.push((literalNibble << 4) | matchNibble);
110
+ if (literals.length >= 15)
111
+ writeLength(out, literals.length - 15);
112
+ out.append(literals);
113
+ if (matchLength === 0)
114
+ return;
115
+ out.push(offset & 0xff);
116
+ out.push(offset >> 8);
117
+ if (matchLength - MIN_MATCH >= 15)
118
+ writeLength(out, matchLength - MIN_MATCH - 15);
119
+ };
120
+ class Growable {
121
+ #buffer;
122
+ length = 0;
123
+ constructor(capacity) {
124
+ this.#buffer = new Uint8Array(Math.max(capacity, 16));
125
+ }
126
+ push(byte) {
127
+ this.#reserve(1);
128
+ this.#buffer[this.length++] = byte;
129
+ }
130
+ append(bytes) {
131
+ this.#reserve(bytes.length);
132
+ this.#buffer.set(bytes, this.length);
133
+ this.length += bytes.length;
134
+ }
135
+ /** Byte by byte on purpose: a match may overlap the bytes it is still producing. */
136
+ copyBack(offset, length) {
137
+ this.#reserve(length);
138
+ const from = this.length - offset;
139
+ for (let k = 0; k < length; k++)
140
+ this.#buffer[this.length + k] = this.#buffer[from + k];
141
+ this.length += length;
142
+ }
143
+ bytes() {
144
+ return this.#buffer.slice(0, this.length);
145
+ }
146
+ #reserve(extra) {
147
+ if (this.length + extra <= this.#buffer.length)
148
+ return;
149
+ const next = new Uint8Array(Math.max(this.#buffer.length * 2, this.length + extra));
150
+ next.set(this.#buffer.subarray(0, this.length));
151
+ this.#buffer = next;
152
+ }
153
+ }
154
+ //# sourceMappingURL=lz4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lz4.js","sourceRoot":"","sources":["../../src/protocol/lz4.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  import type { Id } from "../domain/models.js";
2
- import type { ChatAction, SendEntry, SendJournal, SendKind } from "./journal.js";
2
+ import type { AccountAction, ChatAction, SendEntry, SendJournal, SendKind } from "./journal.js";
3
+ import { type Permission } from "./permissions.js";
3
4
  import type { RecipientList } from "./recipients.js";
4
5
  /** What `MaxClient.messages.send` asks before it sends, and tells after — on every outcome. */
5
6
  export interface SendGuard {
6
7
  /** `null` for a chat that does not exist yet — joining or creating one — or for the account itself: no list can name either. */
7
- check(chatId: Id | null, kind?: SendKind, action?: ChatAction): void;
8
+ check(chatId: Id | null, kind?: SendKind, action?: ChatAction | AccountAction, count?: number): void;
8
9
  record(entry: Omit<SendEntry, "at" | "profile">): void;
9
10
  }
10
11
  export interface SendGuardOptions {
@@ -12,6 +13,9 @@ export interface SendGuardOptions {
12
13
  readOnly: boolean;
13
14
  /** Named in the refusal, so the owner can find what decided it. */
14
15
  readOnlyFrom: string;
16
+ /** `undefined` allows every action; a list only those (`CLI-37`). */
17
+ allow?: readonly Permission[];
18
+ allowFrom?: string;
15
19
  sendsPerHour: number;
16
20
  journal: SendJournal;
17
21
  recipients: RecipientList;
@@ -23,5 +27,5 @@ export interface SendGuardOptions {
23
27
  * agent that edits the configuration itself — that needs a boundary outside this process
24
28
  * (`docs/security.md`).
25
29
  */
26
- export declare const sendGuard: ({ profile, readOnly, readOnlyFrom, sendsPerHour, journal, recipients, warn, now, }: SendGuardOptions) => SendGuard;
30
+ export declare const sendGuard: ({ profile, readOnly, readOnlyFrom, allow, allowFrom, sendsPerHour, journal, recipients, warn, now, }: SendGuardOptions) => SendGuard;
27
31
  //# sourceMappingURL=guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/sends/guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,KAAK,EAAiB,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC/F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAIpD,+FAA+F;AAC/F,MAAM,WAAW,SAAS;IACxB,gIAAgI;IAChI,KAAK,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IACpE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,GAAG,SAAS,CAAC,GAAG,IAAI,CAAA;CACvD;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,WAAW,CAAA;IACpB,UAAU,EAAE,aAAa,CAAA;IACzB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CACjB;AASD;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,oFASvB,gBAAgB,KAAG,SAmDpB,CAAA"}
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/sends/guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC/F,OAAO,EAAE,KAAK,UAAU,EAAiB,MAAM,kBAAkB,CAAA;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAIpD,+FAA+F;AAC/F,MAAM,WAAW,SAAS;IACxB,gIAAgI;IAChI,KAAK,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpG,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,GAAG,SAAS,CAAC,GAAG,IAAI,CAAA;CACvD;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAA;IACpB,qEAAqE;IACrE,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,WAAW,CAAA;IACpB,UAAU,EAAE,aAAa,CAAA;IACzB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CACjB;AAaD;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,sGAWvB,gBAAgB,KAAG,SA8EpB,CAAA"}
@@ -1,20 +1,30 @@
1
1
  import { CliError } from "@leemour/cli-core";
2
+ import { permissionFor } from "./permissions.js";
2
3
  const HOUR_MS = 60 * 60 * 1000;
3
4
  /**
4
5
  * What puts a new message in somebody's chat (`NEED-168`). A reaction, an edit, a quiet pin or a
5
- * change to a chat wakes nobody up; creating a group does — the people in it are told.
6
+ * change to a chat wakes nobody up; creating a group does — the people in it are told. A deletion
7
+ * wakes nobody either, but many at once is what a ban for automation looks like, so each deleted
8
+ * message counts as one (`MAX-47`).
6
9
  */
7
- const countsTowardLimit = ({ kind = "message", action }) => kind === "message" || kind === "forward" || action === "create";
10
+ const countsTowardLimit = ({ kind = "message", action }) => kind === "message" || kind === "forward" || kind === "delete" || action === "create";
11
+ const weightOf = (entry) => (entry.kind === "delete" ? (entry.count ?? 1) : 1);
8
12
  /**
9
13
  * These stop a model that was talked into sending by a message it read. They do **not** stop an
10
14
  * agent that edits the configuration itself — that needs a boundary outside this process
11
15
  * (`docs/security.md`).
12
16
  */
13
- export const sendGuard = ({ profile, readOnly, readOnlyFrom, sendsPerHour, journal, recipients, warn, now = () => new Date(), }) => ({
14
- check: (chatId, kind = "message", action) => {
17
+ export const sendGuard = ({ profile, readOnly, readOnlyFrom, allow, allowFrom = "default", sendsPerHour, journal, recipients, warn, now = () => new Date(), }) => ({
18
+ check: (chatId, kind = "message", action, count = 1) => {
15
19
  if (readOnly) {
16
20
  throw new CliError("permission_error", `profile ${profile} is read-only (readOnly, from the ${readOnlyFrom}) — it cannot send, react, change chats or change the account`);
17
21
  }
22
+ const permission = permissionFor(kind, action);
23
+ if (allow && !allow.includes(permission)) {
24
+ const command = allowFrom === "config defaults" ? "max config set --defaults allow" : `max ${profile} config set allow`;
25
+ throw new CliError("permission_error", `profile ${profile} does not allow ${permission} (allow: ${allow.join(", ") || "nothing"} — from the ${allowFrom}); ` +
26
+ `to allow it: ${command} ${[...allow, permission].join(",")}`, { permission });
27
+ }
18
28
  const allowed = recipients.read();
19
29
  if (chatId !== null && allowed && !allowed.some((chat) => chat.id === chatId)) {
20
30
  throw new CliError("confirmation_required", `chat ${chatId} is not on the recipient list of profile ${profile} — ` +
@@ -22,19 +32,30 @@ export const sendGuard = ({ profile, readOnly, readOnlyFrom, sendsPerHour, journ
22
32
  }
23
33
  if (!countsTowardLimit({ kind, action }))
24
34
  return;
35
+ if (count > sendsPerHour) {
36
+ throw new CliError("rate_limited", `${count} at once is more than the hourly limit of profile ${profile} (sendsPerHour ${sendsPerHour}) — ` +
37
+ "do fewer at a time");
38
+ }
25
39
  const since = now().getTime() - HOUR_MS;
26
40
  const recent = journal
27
41
  .entries()
28
42
  .filter(countsTowardLimit)
29
43
  .filter((entry) => entry.outcome === "sent" || entry.outcome === "outcome_unknown")
30
- .map((entry) => Date.parse(entry.at))
31
- .filter((time) => time > since)
32
- .sort((a, b) => a - b);
33
- if (recent.length >= sendsPerHour) {
34
- // The limit may have been lowered below what the last hour already holds.
35
- const nextMs = (recent[recent.length - sendsPerHour] ?? 0) + HOUR_MS;
44
+ .map((entry) => ({ time: Date.parse(entry.at), weight: weightOf(entry) }))
45
+ .filter(({ time }) => time > since)
46
+ .sort((a, b) => a.time - b.time);
47
+ const used = recent.reduce((sum, { weight }) => sum + weight, 0);
48
+ if (used + count > sendsPerHour) {
49
+ // The limit may have been lowered below what the last hour already holds: it opens when
50
+ // enough of it has aged out, not when the oldest has.
51
+ let freed = 0;
52
+ const opening = recent.find(({ weight }) => {
53
+ freed += weight;
54
+ return used - freed + count <= sendsPerHour;
55
+ });
56
+ const nextMs = (opening?.time ?? 0) + HOUR_MS;
36
57
  const next = new Date(nextMs).toISOString();
37
- throw new CliError("rate_limited", `profile ${profile} has sent ${recent.length} messages in the last hour, and its limit is ` +
58
+ throw new CliError("rate_limited", `profile ${profile} has sent ${used} messages in the last hour, and its limit is ` +
38
59
  `${sendsPerHour} (sendsPerHour) — the next send is possible at ${next}`, { retryAfterMs: nextMs - now().getTime(), retryAt: next });
39
60
  }
40
61
  },
@@ -1 +1 @@
1
- {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/sends/guard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/sends/guard.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import type { Id } from "../domain/models.js";
2
2
  export type SendOutcome = "sent" | "outcome_unknown" | "refused" | "failed";
3
3
  /** Absent in the journal means a message: that is every line written before reactions were guarded. */
4
- export type SendKind = "message" | "reaction" | "edit" | "forward" | "pin" | "chat" | "account";
4
+ export type SendKind = "message" | "reaction" | "edit" | "forward" | "pin" | "read" | "delete" | "chat" | "account";
5
5
  /** What a `chat` entry did. Never a title, a description or a link — only which action. */
6
6
  export type ChatAction = "create" | "join" | "leave" | "members.add" | "members.remove" | "admins.add" | "admins.remove" | "update" | "settings" | "requests.accept" | "requests.decline" | "link.reset";
7
7
  /** What an `account` entry changed. Never the value it changed it to — no name, number or title. */
@@ -18,6 +18,9 @@ export interface SendEntry {
18
18
  /** How many people a `chat` entry added or removed. */
19
19
  people?: number;
20
20
  messageId?: Id;
21
+ /** How many messages a `delete` entry named — each one counts toward the hourly limit. */
22
+ count?: number;
23
+ forEveryone?: boolean;
21
24
  cid?: number;
22
25
  length?: number;
23
26
  /** What was attached, by kind and size — never a file name. */
@@ -25,6 +28,8 @@ export interface SendEntry {
25
28
  kind: "photo" | "file";
26
29
  bytes: number;
27
30
  }[];
31
+ /** When MAX will send it; the entry is written when it was queued, and the guard counted it then. */
32
+ scheduledFor?: string;
28
33
  errorCode?: string;
29
34
  }
30
35
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../src/sends/journal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAA;AAE7C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,iBAAiB,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE3E,uGAAuG;AACvG,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;AAE/F,2FAA2F;AAC3F,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,MAAM,GACN,OAAO,GACP,aAAa,GACb,gBAAgB,GAChB,YAAY,GACZ,eAAe,GACf,QAAQ,GACR,UAAU,GACV,iBAAiB,GACjB,kBAAkB,GAClB,YAAY,CAAA;AAEhB,oGAAoG;AACpG,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,SAAS,GACT,eAAe,GACf,eAAe,GACf,eAAe,GACf,cAAc,CAAA;AAElB,iEAAiE;AACjE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,oHAAoH;IACpH,MAAM,EAAE,EAAE,GAAG,IAAI,CAAA;IACjB,OAAO,EAAE,WAAW,CAAA;IACpB,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,CAAA;IACnC,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,EAAE,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,EAAE,MAAK,MAAM,CAAC,UAAwB,KAAG,MACc,CAAA;AAEnG,qBAAa,WAAW;IACV,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;IAEjC,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAK9B,qGAAqG;IACrG,OAAO,IAAI,SAAS,EAAE;CAkBvB"}
1
+ {"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../src/sends/journal.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAA;AAE7C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,iBAAiB,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE3E,uGAAuG;AACvG,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAA;AAEnH,2FAA2F;AAC3F,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,MAAM,GACN,OAAO,GACP,aAAa,GACb,gBAAgB,GAChB,YAAY,GACZ,eAAe,GACf,QAAQ,GACR,UAAU,GACV,iBAAiB,GACjB,kBAAkB,GAClB,YAAY,CAAA;AAEhB,oGAAoG;AACpG,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,SAAS,GACT,eAAe,GACf,eAAe,GACf,eAAe,GACf,cAAc,CAAA;AAElB,iEAAiE;AACjE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,oHAAoH;IACpH,MAAM,EAAE,EAAE,GAAG,IAAI,CAAA;IACjB,OAAO,EAAE,WAAW,CAAA;IACpB,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,CAAA;IACnC,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,EAAE,CAAA;IACd,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzD,qGAAqG;IACrG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,EAAE,MAAK,MAAM,CAAC,UAAwB,KAAG,MACc,CAAA;AAEnG,qBAAa,WAAW;IACV,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;IAEjC,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAK9B,qGAAqG;IACrG,OAAO,IAAI,SAAS,EAAE;CAkBvB"}