@leemour/max-cli 0.4.0 → 0.6.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 (190) hide show
  1. package/README.md +14 -5
  2. package/dist/bin/max.js +0 -0
  3. package/dist/cache/store.d.ts +14 -8
  4. package/dist/cache/store.d.ts.map +1 -1
  5. package/dist/cache/store.js +30 -5
  6. package/dist/cache/store.js.map +1 -1
  7. package/dist/client.d.ts +93 -5
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +347 -59
  10. package/dist/client.js.map +1 -1
  11. package/dist/commands/chats.d.ts.map +1 -1
  12. package/dist/commands/chats.js +20 -0
  13. package/dist/commands/chats.js.map +1 -1
  14. package/dist/commands/commands.d.ts +8 -0
  15. package/dist/commands/commands.d.ts.map +1 -0
  16. package/dist/commands/commands.js +36 -0
  17. package/dist/commands/commands.js.map +1 -0
  18. package/dist/commands/config.d.ts.map +1 -1
  19. package/dist/commands/config.js +29 -0
  20. package/dist/commands/config.js.map +1 -1
  21. package/dist/commands/contacts.d.ts.map +1 -1
  22. package/dist/commands/contacts.js +18 -0
  23. package/dist/commands/contacts.js.map +1 -1
  24. package/dist/commands/context.d.ts +18 -0
  25. package/dist/commands/context.d.ts.map +1 -1
  26. package/dist/commands/context.js +22 -0
  27. package/dist/commands/context.js.map +1 -1
  28. package/dist/commands/inbox.d.ts +14 -0
  29. package/dist/commands/inbox.d.ts.map +1 -0
  30. package/dist/commands/inbox.js +90 -0
  31. package/dist/commands/inbox.js.map +1 -0
  32. package/dist/commands/messages.d.ts.map +1 -1
  33. package/dist/commands/messages.js +55 -4
  34. package/dist/commands/messages.js.map +1 -1
  35. package/dist/commands/reactions.d.ts +3 -0
  36. package/dist/commands/reactions.d.ts.map +1 -0
  37. package/dist/commands/reactions.js +26 -0
  38. package/dist/commands/reactions.js.map +1 -0
  39. package/dist/commands/recipients.d.ts +9 -0
  40. package/dist/commands/recipients.d.ts.map +1 -0
  41. package/dist/commands/recipients.js +68 -0
  42. package/dist/commands/recipients.js.map +1 -0
  43. package/dist/commands/sends.d.ts +4 -0
  44. package/dist/commands/sends.d.ts.map +1 -0
  45. package/dist/commands/sends.js +21 -0
  46. package/dist/commands/sends.js.map +1 -0
  47. package/dist/commands/session.d.ts.map +1 -1
  48. package/dist/commands/session.js +80 -15
  49. package/dist/commands/session.js.map +1 -1
  50. package/dist/commands/skill.d.ts.map +1 -1
  51. package/dist/commands/skill.js +2 -1
  52. package/dist/commands/skill.js.map +1 -1
  53. package/dist/config.d.ts +54 -13
  54. package/dist/config.d.ts.map +1 -1
  55. package/dist/config.js +98 -16
  56. package/dist/config.js.map +1 -1
  57. package/dist/domain/map.d.ts +3 -1
  58. package/dist/domain/map.d.ts.map +1 -1
  59. package/dist/domain/map.js +15 -1
  60. package/dist/domain/map.js.map +1 -1
  61. package/dist/domain/models.d.ts +55 -1
  62. package/dist/domain/models.d.ts.map +1 -1
  63. package/dist/domain/models.js.map +1 -1
  64. package/dist/download.d.ts +15 -0
  65. package/dist/download.d.ts.map +1 -0
  66. package/dist/download.js +60 -0
  67. package/dist/download.js.map +1 -0
  68. package/dist/generated/client.generated.d.ts +14 -0
  69. package/dist/generated/client.generated.d.ts.map +1 -1
  70. package/dist/generated/client.generated.js +14 -0
  71. package/dist/generated/client.generated.js.map +1 -1
  72. package/dist/generated/opcodes.generated.d.ts +15 -0
  73. package/dist/generated/opcodes.generated.d.ts.map +1 -1
  74. package/dist/generated/opcodes.generated.js +15 -0
  75. package/dist/generated/opcodes.generated.js.map +1 -1
  76. package/dist/generated/operations.generated.d.ts +99 -1
  77. package/dist/generated/operations.generated.d.ts.map +1 -1
  78. package/dist/generated/operations.generated.js +13 -1
  79. package/dist/generated/operations.generated.js.map +1 -1
  80. package/dist/markdown.d.ts +18 -0
  81. package/dist/markdown.d.ts.map +1 -0
  82. package/dist/markdown.js +52 -0
  83. package/dist/markdown.js.map +1 -0
  84. package/dist/program.d.ts.map +1 -1
  85. package/dist/program.js +10 -0
  86. package/dist/program.js.map +1 -1
  87. package/dist/rendering/messages.d.ts.map +1 -1
  88. package/dist/rendering/messages.js +6 -0
  89. package/dist/rendering/messages.js.map +1 -1
  90. package/dist/resolve.d.ts +15 -0
  91. package/dist/resolve.d.ts.map +1 -0
  92. package/dist/resolve.js +48 -0
  93. package/dist/resolve.js.map +1 -0
  94. package/dist/runs/recording.d.ts.map +1 -1
  95. package/dist/runs/recording.js +7 -0
  96. package/dist/runs/recording.js.map +1 -1
  97. package/dist/runs/run.d.ts +2 -0
  98. package/dist/runs/run.d.ts.map +1 -1
  99. package/dist/runs/run.js +1 -0
  100. package/dist/runs/run.js.map +1 -1
  101. package/dist/sends/guard.d.ts +26 -0
  102. package/dist/sends/guard.d.ts.map +1 -0
  103. package/dist/sends/guard.js +48 -0
  104. package/dist/sends/guard.js.map +1 -0
  105. package/dist/sends/journal.d.ts +29 -0
  106. package/dist/sends/journal.d.ts.map +1 -0
  107. package/dist/sends/journal.js +40 -0
  108. package/dist/sends/journal.js.map +1 -0
  109. package/dist/sends/recipients.d.ts +29 -0
  110. package/dist/sends/recipients.d.ts.map +1 -0
  111. package/dist/sends/recipients.js +62 -0
  112. package/dist/sends/recipients.js.map +1 -0
  113. package/dist/session/adopt.d.ts.map +1 -1
  114. package/dist/session/adopt.js +7 -6
  115. package/dist/session/adopt.js.map +1 -1
  116. package/dist/session/browser.d.ts +55 -0
  117. package/dist/session/browser.d.ts.map +1 -0
  118. package/dist/session/browser.js +292 -0
  119. package/dist/session/browser.js.map +1 -0
  120. package/dist/session/handshake.d.ts +3 -1
  121. package/dist/session/handshake.d.ts.map +1 -1
  122. package/dist/session/handshake.js +3 -1
  123. package/dist/session/handshake.js.map +1 -1
  124. package/dist/session/login.d.ts +20 -0
  125. package/dist/session/login.d.ts.map +1 -0
  126. package/dist/session/login.js +66 -0
  127. package/dist/session/login.js.map +1 -0
  128. package/dist/session/prompt.d.ts +3 -1
  129. package/dist/session/prompt.d.ts.map +1 -1
  130. package/dist/session/prompt.js +2 -2
  131. package/dist/session/prompt.js.map +1 -1
  132. package/dist/session/qr-terminal.d.ts +9 -0
  133. package/dist/session/qr-terminal.d.ts.map +1 -0
  134. package/dist/session/qr-terminal.js +34 -0
  135. package/dist/session/qr-terminal.js.map +1 -0
  136. package/dist/session/store.d.ts +2 -0
  137. package/dist/session/store.d.ts.map +1 -1
  138. package/dist/session/store.js +2 -0
  139. package/dist/session/store.js.map +1 -1
  140. package/dist/spec/index.d.ts.map +1 -1
  141. package/dist/spec/index.js +14 -1
  142. package/dist/spec/index.js.map +1 -1
  143. package/dist/spec/operations/attachments.d.ts +15 -0
  144. package/dist/spec/operations/attachments.d.ts.map +1 -0
  145. package/dist/spec/operations/attachments.js +38 -0
  146. package/dist/spec/operations/attachments.js.map +1 -0
  147. package/dist/spec/operations/login.d.ts +64 -0
  148. package/dist/spec/operations/login.d.ts.map +1 -0
  149. package/dist/spec/operations/login.js +99 -0
  150. package/dist/spec/operations/login.js.map +1 -0
  151. package/dist/spec/operations/messages.d.ts +27 -1
  152. package/dist/spec/operations/messages.d.ts.map +1 -1
  153. package/dist/spec/operations/messages.js +46 -2
  154. package/dist/spec/operations/messages.js.map +1 -1
  155. package/dist/testing/mock-max.d.ts +10 -4
  156. package/dist/testing/mock-max.d.ts.map +1 -1
  157. package/dist/testing/mock-max.js +5 -1
  158. package/dist/testing/mock-max.js.map +1 -1
  159. package/dist/testing/sandbox.js +3 -0
  160. package/dist/testing/sandbox.js.map +1 -1
  161. package/dist/testing/unscripted.d.ts +2 -0
  162. package/dist/testing/unscripted.d.ts.map +1 -0
  163. package/dist/testing/unscripted.js +18 -0
  164. package/dist/testing/unscripted.js.map +1 -0
  165. package/dist/version.d.ts +1 -1
  166. package/dist/version.js +1 -1
  167. package/package.json +31 -22
  168. package/skills/max-cli/SKILL.md +25 -6
  169. package/dist/commands/login.d.ts +0 -15
  170. package/dist/commands/login.d.ts.map +0 -1
  171. package/dist/commands/login.js +0 -43
  172. package/dist/commands/login.js.map +0 -1
  173. package/dist/commands/logout.d.ts +0 -10
  174. package/dist/commands/logout.d.ts.map +0 -1
  175. package/dist/commands/logout.js +0 -22
  176. package/dist/commands/logout.js.map +0 -1
  177. package/dist/commands/me.d.ts +0 -3
  178. package/dist/commands/me.d.ts.map +0 -1
  179. package/dist/commands/me.js +0 -18
  180. package/dist/commands/me.js.map +0 -1
  181. package/dist/commands/send.d.ts +0 -10
  182. package/dist/commands/send.d.ts.map +0 -1
  183. package/dist/commands/send.js +0 -30
  184. package/dist/commands/send.js.map +0 -1
  185. package/dist/protocol/session.d.ts +0 -54
  186. package/dist/protocol/session.d.ts.map +0 -1
  187. package/dist/protocol/session.js +0 -57
  188. package/dist/protocol/session.js.map +0 -1
  189. package/dist/spec/operations/auth.d.ts +0 -42
  190. package/dist/spec/operations/auth.d.ts.map +0 -1
@@ -1,6 +1,8 @@
1
+ import { attachmentsFile, attachmentsVideo } from "./operations/attachments.js";
1
2
  import { chatMark, chatsHistory, chatsList } from "./operations/chats.js";
2
3
  import { contactsInfo, profile, unidentified36 } from "./operations/contacts.js";
3
- import { messageDelete, messagesSend } from "./operations/messages.js";
4
+ import { loginByQr, loginPassword, loginQrRequest, loginQrStatus, loginSmsCode, loginSmsRequest, qrApprove, } from "./operations/login.js";
5
+ import { messageDelete, messagesReact, messagesReactions, messagesSend } from "./operations/messages.js";
4
6
  import { logout, sessionInit, sessionLogin } from "./operations/session.js";
5
7
  export { checkResponse } from "./check.js";
6
8
  export * from "./define.js";
@@ -16,6 +18,13 @@ export const spec = [
16
18
  sessionInit,
17
19
  sessionLogin,
18
20
  logout,
21
+ loginQrRequest,
22
+ loginQrStatus,
23
+ loginByQr,
24
+ qrApprove,
25
+ loginSmsRequest,
26
+ loginSmsCode,
27
+ loginPassword,
19
28
  contactsInfo,
20
29
  profile,
21
30
  unidentified36,
@@ -23,7 +32,11 @@ export const spec = [
23
32
  chatMark,
24
33
  chatsList,
25
34
  messagesSend,
35
+ messagesReact,
36
+ messagesReactions,
26
37
  messageDelete,
38
+ attachmentsVideo,
39
+ attachmentsFile,
27
40
  ];
28
41
  export const operations = spec.filter((entry) => entry.kind === "operation");
29
42
  export const reservations = spec.filter((entry) => entry.kind === "reservation");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/spec/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAChF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACtE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE3E,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC1C,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAE5B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAqB;IACpC,WAAW;IACX,YAAY;IACZ,MAAM;IACN,YAAY;IACZ,OAAO;IACP,cAAc;IACd,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,YAAY;IACZ,aAAa;CACd,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAyB,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAsB,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAA;AAEtH,MAAM,CAAC,MAAM,YAAY,GAA2B,IAAI,CAAC,MAAM,CAC7D,CAAC,KAAK,EAAwB,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,CAC9D,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/spec/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAC/E,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAChF,OAAO,EACL,SAAS,EACT,aAAa,EACb,cAAc,EACd,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,GACV,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACxG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE3E,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC1C,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAE5B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAqB;IACpC,WAAW;IACX,YAAY;IACZ,MAAM;IACN,cAAc;IACd,aAAa;IACb,SAAS;IACT,SAAS;IACT,eAAe;IACf,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,OAAO;IACP,cAAc;IACd,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,YAAY;IACZ,aAAa;IACb,iBAAiB;IACjB,aAAa;IACb,gBAAgB;IAChB,eAAe;CAChB,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAyB,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAsB,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAA;AAEtH,MAAM,CAAC,MAAM,YAAY,GAA2B,IAAI,CAAC,MAAM,CAC7D,CAAC,KAAK,EAAwB,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,CAC9D,CAAA"}
@@ -0,0 +1,15 @@
1
+ import * as v from "valibot";
2
+ export declare const attachmentsFile: import("../define.js").Operation<v.StrictObjectSchema<{
3
+ readonly chatId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
4
+ readonly messageId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
5
+ readonly fileId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
6
+ }, undefined>, v.LooseObjectSchema<{
7
+ readonly url: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
8
+ readonly unsafe: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
9
+ }, undefined>>;
10
+ export declare const attachmentsVideo: import("../define.js").Operation<v.StrictObjectSchema<{
11
+ readonly chatId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
12
+ readonly messageId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
13
+ readonly videoId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
14
+ }, undefined>, v.LooseObjectSchema<{}, undefined>>;
15
+ //# sourceMappingURL=attachments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../../src/spec/operations/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAI5B,eAAO,MAAM,eAAe;;;;;;;cAiB1B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;kDAiB3B,CAAA"}
@@ -0,0 +1,38 @@
1
+ import * as v from "valibot";
2
+ import { defineOperation } from "../define.js";
3
+ import { id } from "../scalars.js";
4
+ export const attachmentsFile = defineOperation({
5
+ name: "attachments.file",
6
+ constant: "FILE_DOWNLOAD",
7
+ opcode: 88,
8
+ auth: true,
9
+ request: v.strictObject({
10
+ chatId: id(),
11
+ messageId: id(),
12
+ fileId: id(),
13
+ }),
14
+ response: v.looseObject({ url: v.optional(v.string()), unsafe: v.optional(v.boolean()) }),
15
+ provenance: {
16
+ confidence: "measured",
17
+ sources: ["measured against MAX 2026-09-23 (`pnpm probe:download`)", "tsmax getFileById", "PyMax get_file_by_id"],
18
+ notes: "A file attachment carries `fileId` and no link; this answers `{unsafe, url}`, and the link opens without credentials.",
19
+ },
20
+ });
21
+ export const attachmentsVideo = defineOperation({
22
+ name: "attachments.video",
23
+ constant: "VIDEO_PLAY",
24
+ opcode: 83,
25
+ auth: true,
26
+ request: v.strictObject({
27
+ chatId: id(),
28
+ messageId: id(),
29
+ videoId: id(),
30
+ }),
31
+ response: v.looseObject({}),
32
+ provenance: {
33
+ confidence: "measured",
34
+ sources: ["measured against MAX 2026-09-23 (`pnpm probe:download`)", "tsmax getVideoById", "PyMax get_video_by_id"],
35
+ notes: "Answers `cache` and one key per rendition — `MP4_720`, `HLS`, `DASH`, `EXTERNAL` were seen. The MP4 link opens without credentials.",
36
+ },
37
+ });
38
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../src/spec/operations/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AAElC,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;IAC7C,IAAI,EAAE,kBAAkB;IACxB,QAAQ,EAAE,eAAe;IACzB,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,CAAC,CAAC,YAAY,CAAC;QACtB,MAAM,EAAE,EAAE,EAAE;QACZ,SAAS,EAAE,EAAE,EAAE;QACf,MAAM,EAAE,EAAE,EAAE;KACb,CAAC;IACF,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;IACzF,UAAU,EAAE;QACV,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,CAAC,yDAAyD,EAAE,mBAAmB,EAAE,sBAAsB,CAAC;QACjH,KAAK,EACH,uHAAuH;KAC1H;CACF,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAC;IAC9C,IAAI,EAAE,mBAAmB;IACzB,QAAQ,EAAE,YAAY;IACtB,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,CAAC,CAAC,YAAY,CAAC;QACtB,MAAM,EAAE,EAAE,EAAE;QACZ,SAAS,EAAE,EAAE,EAAE;QACf,OAAO,EAAE,EAAE,EAAE;KACd,CAAC;IACF,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC;IAC3B,UAAU,EAAE;QACV,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,CAAC,yDAAyD,EAAE,oBAAoB,EAAE,uBAAuB,CAAC;QACnH,KAAK,EACH,qIAAqI;KACxI;CACF,CAAC,CAAA"}
@@ -0,0 +1,64 @@
1
+ import * as v from "valibot";
2
+ export declare const loginQrRequest: import("../define.js").Operation<v.StrictObjectSchema<{}, undefined>, v.LooseObjectSchema<{
3
+ readonly qrLink: v.StringSchema<undefined>;
4
+ readonly trackId: v.StringSchema<undefined>;
5
+ readonly pollingInterval: v.NumberSchema<undefined>;
6
+ readonly expiresAt: v.NumberSchema<undefined>;
7
+ }, undefined>>;
8
+ export declare const loginQrStatus: import("../define.js").Operation<v.StrictObjectSchema<{
9
+ readonly trackId: v.StringSchema<undefined>;
10
+ }, undefined>, v.LooseObjectSchema<{
11
+ readonly status: v.LooseObjectSchema<{
12
+ readonly expiresAt: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
13
+ readonly loginAvailable: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
14
+ }, undefined>;
15
+ }, undefined>>;
16
+ export declare const loginByQr: import("../define.js").Operation<v.StrictObjectSchema<{
17
+ readonly trackId: v.StringSchema<undefined>;
18
+ }, undefined>, v.LooseObjectSchema<{
19
+ tokenAttrs: v.OptionalSchema<v.LooseObjectSchema<{
20
+ readonly LOGIN: v.OptionalSchema<v.LooseObjectSchema<{
21
+ readonly token: v.StringSchema<undefined>;
22
+ }, undefined>, undefined>;
23
+ }, undefined>, undefined>;
24
+ passwordChallenge: v.OptionalSchema<v.LooseObjectSchema<{
25
+ readonly trackId: v.StringSchema<undefined>;
26
+ readonly hint: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
27
+ }, undefined>, undefined>;
28
+ }, undefined>>;
29
+ export declare const loginSmsRequest: import("../define.js").Operation<v.StrictObjectSchema<{
30
+ readonly phone: v.StringSchema<undefined>;
31
+ readonly type: v.LiteralSchema<"START_AUTH", undefined>;
32
+ readonly language: v.StringSchema<undefined>;
33
+ }, undefined>, v.LooseObjectSchema<{
34
+ readonly token: v.StringSchema<undefined>;
35
+ readonly codeLength: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
36
+ }, undefined>>;
37
+ export declare const loginSmsCode: import("../define.js").Operation<v.StrictObjectSchema<{
38
+ readonly token: v.StringSchema<undefined>;
39
+ readonly verifyCode: v.StringSchema<undefined>;
40
+ readonly authTokenType: v.LiteralSchema<"CHECK_CODE", undefined>;
41
+ }, undefined>, v.LooseObjectSchema<{
42
+ tokenAttrs: v.OptionalSchema<v.LooseObjectSchema<{
43
+ readonly LOGIN: v.OptionalSchema<v.LooseObjectSchema<{
44
+ readonly token: v.StringSchema<undefined>;
45
+ }, undefined>, undefined>;
46
+ }, undefined>, undefined>;
47
+ passwordChallenge: v.OptionalSchema<v.LooseObjectSchema<{
48
+ readonly trackId: v.StringSchema<undefined>;
49
+ readonly hint: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
50
+ }, undefined>, undefined>;
51
+ }, undefined>>;
52
+ export declare const loginPassword: import("../define.js").Operation<v.StrictObjectSchema<{
53
+ readonly trackId: v.StringSchema<undefined>;
54
+ readonly password: v.StringSchema<undefined>;
55
+ }, undefined>, v.LooseObjectSchema<{
56
+ readonly tokenAttrs: v.OptionalSchema<v.LooseObjectSchema<{
57
+ readonly LOGIN: v.OptionalSchema<v.LooseObjectSchema<{
58
+ readonly token: v.StringSchema<undefined>;
59
+ }, undefined>, undefined>;
60
+ }, undefined>, undefined>;
61
+ readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
62
+ }, undefined>>;
63
+ export declare const qrApprove: import("../define.js").Reservation;
64
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/spec/operations/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAe5B,eAAO,MAAM,cAAc;;;;;cAgBzB,CAAA;AAEF,eAAO,MAAM,aAAa;;;;;;;cAexB,CAAA;AAEF,eAAO,MAAM,SAAS;;;;;;;;;;;;cAWpB,CAAA;AAEF,eAAO,MAAM,eAAe;;;;;;;cAa1B,CAAA;AAEF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;cAQvB,CAAA;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;cAYxB,CAAA;AAEF,eAAO,MAAM,SAAS,oCAOpB,CAAA"}
@@ -0,0 +1,99 @@
1
+ import * as v from "valibot";
2
+ import { defineOperation, reserveOpcode } from "../define.js";
3
+ /**
4
+ * How MAX hands over a token once a person has proved who they are — by QR, SMS code or password.
5
+ * ⚠ **It is a credential**: nothing prints it, logs it or puts it in a fixture.
6
+ */
7
+ const Issued = {
8
+ tokenAttrs: v.optional(v.looseObject({ LOGIN: v.optional(v.looseObject({ token: v.string() })) })),
9
+ passwordChallenge: v.optional(v.looseObject({ trackId: v.string(), hint: v.optional(v.string()) })),
10
+ };
11
+ const PYMAX = "PyMax 2.4.1 src/pymax/api/auth/service.py, GitHub 53103f0";
12
+ const DOCS = "max-api-docs/protocol/auth.md (dac4b19)";
13
+ export const loginQrRequest = defineOperation({
14
+ name: "login.qrRequest",
15
+ constant: "GET_QR",
16
+ opcode: 288,
17
+ auth: false,
18
+ request: v.strictObject({}),
19
+ response: v.looseObject({
20
+ qrLink: v.string(),
21
+ trackId: v.string(),
22
+ pollingInterval: v.number(),
23
+ expiresAt: v.number(),
24
+ }),
25
+ provenance: {
26
+ confidence: "measured",
27
+ sources: ["measured against MAX 2026-09-24: `session start qr` logged in", PYMAX, DOCS],
28
+ },
29
+ });
30
+ export const loginQrStatus = defineOperation({
31
+ name: "login.qrStatus",
32
+ constant: "GET_QR_STATUS",
33
+ opcode: 289,
34
+ auth: false,
35
+ request: v.strictObject({ trackId: v.string() }),
36
+ response: v.looseObject({
37
+ status: v.looseObject({ expiresAt: v.optional(v.number()), loginAvailable: v.optional(v.boolean()) }),
38
+ }),
39
+ provenance: {
40
+ confidence: "measured",
41
+ sources: ["measured against MAX 2026-09-24: `session start qr` logged in", PYMAX, DOCS],
42
+ notes: "`loginAvailable` is in PyMax only. The protocol notes say the token arrives as a push of opcode 18 instead.",
43
+ },
44
+ });
45
+ export const loginByQr = defineOperation({
46
+ name: "login.byQr",
47
+ constant: "LOGIN_BY_QR",
48
+ opcode: 291,
49
+ auth: false,
50
+ request: v.strictObject({ trackId: v.string() }),
51
+ response: v.looseObject(Issued),
52
+ provenance: {
53
+ confidence: "measured",
54
+ sources: ["measured against MAX 2026-09-24: `session start qr` logged in", PYMAX],
55
+ },
56
+ });
57
+ export const loginSmsRequest = defineOperation({
58
+ name: "login.smsRequest",
59
+ constant: "AUTH_REQUEST",
60
+ opcode: 17,
61
+ auth: false,
62
+ request: v.strictObject({ phone: v.string(), type: v.literal("START_AUTH"), language: v.string() }),
63
+ response: v.looseObject({ token: v.string(), codeLength: v.optional(v.number()) }),
64
+ provenance: {
65
+ confidence: "confirmed",
66
+ sources: [PYMAX, DOCS],
67
+ notes: "Measured 2026-09-24: MAX refused the first request with a captcha demand, which only the web page can solve. So `session start sms` opens web.max.ru instead of sending this; nothing sends it.",
68
+ },
69
+ });
70
+ export const loginSmsCode = defineOperation({
71
+ name: "login.smsCode",
72
+ constant: "AUTH",
73
+ opcode: 18,
74
+ auth: false,
75
+ request: v.strictObject({ token: v.string(), verifyCode: v.string(), authTokenType: v.literal("CHECK_CODE") }),
76
+ response: v.looseObject(Issued),
77
+ provenance: { confidence: "confirmed", sources: [PYMAX, DOCS] },
78
+ });
79
+ export const loginPassword = defineOperation({
80
+ name: "login.password",
81
+ constant: "AUTH_LOGIN_CHECK_PASSWORD",
82
+ opcode: 115,
83
+ auth: false,
84
+ request: v.strictObject({ trackId: v.string(), password: v.string() }),
85
+ response: v.looseObject({ tokenAttrs: Issued.tokenAttrs, error: v.optional(v.string()) }),
86
+ provenance: {
87
+ confidence: "measured",
88
+ sources: ["measured against MAX 2026-09-24: `session start qr` on an account with a cloud password", PYMAX],
89
+ notes: "A wrong password is refused as `password2fa.wrong`, and the same `trackId` takes another attempt.",
90
+ },
91
+ });
92
+ export const qrApprove = reserveOpcode({
93
+ name: "login.qrApprove",
94
+ constant: "AUTH_QR_APPROVE",
95
+ opcode: 290,
96
+ reason: "The phone's side of a QR login: it lets whoever showed the code into the owner's account. A CLI logging itself in never approves anybody.",
97
+ provenance: { confidence: "observed", sources: [PYMAX] },
98
+ });
99
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/spec/operations/login.ts"],"names":[],"mappings":"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"}
@@ -8,12 +8,38 @@ export declare const messagesSend: import("../define.js").Operation<v.StrictObje
8
8
  * never be regenerated on a retry: a fresh one means a second message in somebody's chat.
9
9
  */
10
10
  readonly cid: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>]>;
11
- readonly elements: v.ArraySchema<v.UnknownSchema, undefined>;
11
+ /** Markup in UTF-16 positions. STRONG, EMPHASIZED, STRIKETHROUGH, MONOSPACED read back from MAX 2026-09-24. */
12
+ readonly elements: v.ArraySchema<v.StrictObjectSchema<{
13
+ readonly type: v.StringSchema<undefined>;
14
+ readonly from: v.NumberSchema<undefined>;
15
+ readonly length: v.NumberSchema<undefined>;
16
+ }, undefined>, undefined>;
12
17
  readonly attaches: v.ArraySchema<v.UnknownSchema, undefined>;
18
+ /** Read back as `{type, chatId, message}` — the quoted message whole (measured 2026-09-23). */
19
+ readonly link: v.OptionalSchema<v.StrictObjectSchema<{
20
+ readonly type: v.LiteralSchema<"REPLY", undefined>;
21
+ readonly messageId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
22
+ }, undefined>, undefined>;
13
23
  }, undefined>;
14
24
  readonly notify: v.BooleanSchema<undefined>;
15
25
  }, undefined>, v.LooseObjectSchema<{
16
26
  readonly message: v.OptionalSchema<v.LooseObjectSchema<{}, undefined>, undefined>;
17
27
  }, undefined>>;
28
+ export declare const messagesReactions: import("../define.js").Operation<v.StrictObjectSchema<{
29
+ readonly chatId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
30
+ readonly messageIds: v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>, undefined>;
31
+ }, undefined>, v.LooseObjectSchema<{
32
+ readonly messagesReactions: v.OptionalSchema<v.LooseObjectSchema<{}, undefined>, undefined>;
33
+ }, undefined>>;
34
+ export declare const messagesReact: import("../define.js").Operation<v.StrictObjectSchema<{
35
+ readonly chatId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
36
+ readonly messageId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "an id is a whole number written as a string">, v.TransformAction<string, bigint>]>;
37
+ readonly reaction: v.StrictObjectSchema<{
38
+ readonly reactionType: v.LiteralSchema<"EMOJI", undefined>;
39
+ readonly id: v.StringSchema<undefined>;
40
+ }, undefined>;
41
+ }, undefined>, v.LooseObjectSchema<{
42
+ readonly reactionInfo: v.OptionalSchema<v.LooseObjectSchema<{}, undefined>, undefined>;
43
+ }, undefined>>;
18
44
  export declare const messageDelete: import("../define.js").Reservation;
19
45
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/spec/operations/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAI5B,eAAO,MAAM,YAAY;;;;QASnB;;;WAGG;;;;;;;;cAaP,CAAA;AAEF,eAAO,MAAM,aAAa,oCAOxB,CAAA"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/spec/operations/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAI5B,eAAO,MAAM,YAAY;;;;QASnB;;;WAGG;;QAEH,+GAA+G;;;;;;;QAG/G,+FAA+F;;;;;;;;;cAcnG,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;;;cAiB5B,CAAA;AAEF,eAAO,MAAM,aAAa;;;;;;;;;cAqBxB,CAAA;AAEF,eAAO,MAAM,aAAa,oCAOxB,CAAA"}
@@ -15,18 +15,62 @@ export const messagesSend = defineOperation({
15
15
  * never be regenerated on a retry: a fresh one means a second message in somebody's chat.
16
16
  */
17
17
  cid: v.pipe(v.number(), v.integer()),
18
- elements: v.array(v.unknown()),
18
+ /** Markup in UTF-16 positions. STRONG, EMPHASIZED, STRIKETHROUGH, MONOSPACED read back from MAX 2026-09-24. */
19
+ elements: v.array(v.strictObject({ type: v.string(), from: v.number(), length: v.number() })),
19
20
  attaches: v.array(v.unknown()),
21
+ /** Read back as `{type, chatId, message}` — the quoted message whole (measured 2026-09-23). */
22
+ link: v.optional(v.strictObject({ type: v.literal("REPLY"), messageId: id() })),
20
23
  }),
21
24
  notify: v.boolean(),
22
25
  }),
23
26
  response: v.looseObject({ message: v.optional(v.looseObject({})) }),
24
27
  provenance: {
25
28
  confidence: "measured",
26
- sources: ["measured against MAX 2026-09-19, including deduplication by `cid` across two connections"],
29
+ sources: [
30
+ "measured against MAX 2026-09-19, including deduplication by `cid` across two connections",
31
+ "`link` and `elements` measured 2026-09-23 in Saved messages (`pnpm probe:reply`); shapes from tsmax and PyMax",
32
+ ],
27
33
  notes: "How long MAX remembers a `cid` is still unmeasured (`PROTO-2`); the two probes were seconds apart.",
28
34
  },
29
35
  });
36
+ export const messagesReactions = defineOperation({
37
+ name: "messages.reactions",
38
+ constant: "MSG_GET_REACTIONS",
39
+ opcode: 180,
40
+ auth: true,
41
+ request: v.strictObject({ chatId: id(), messageIds: v.array(id()) }),
42
+ response: v.looseObject({ messagesReactions: v.optional(v.looseObject({})) }),
43
+ provenance: {
44
+ confidence: "measured",
45
+ sources: [
46
+ "measured against MAX 2026-09-24 in Saved messages (`pnpm probe:message-shapes`)",
47
+ "tsmax getReactions",
48
+ "PyMax get_reactions",
49
+ ],
50
+ notes: "Answers `{messagesReactions: {<message id>: {counters: [{count, reaction}], yourReaction, totalCount}}}`. History carries no reactions (measured 2026-09-23), so this is the only way to read them.",
51
+ },
52
+ });
53
+ export const messagesReact = defineOperation({
54
+ name: "messages.react",
55
+ constant: "MSG_REACTION",
56
+ opcode: 178,
57
+ auth: true,
58
+ request: v.strictObject({
59
+ chatId: id(),
60
+ messageId: id(),
61
+ reaction: v.strictObject({ reactionType: v.literal("EMOJI"), id: v.string() }),
62
+ }),
63
+ response: v.looseObject({ reactionInfo: v.optional(v.looseObject({})) }),
64
+ provenance: {
65
+ confidence: "measured",
66
+ sources: [
67
+ "measured against MAX 2026-09-23 in Saved messages (`pnpm probe:reply`)",
68
+ "tsmax addReaction",
69
+ "PyMax add_reaction",
70
+ ],
71
+ notes: "Answers `{reactionInfo: {counters: [{count, reaction}], yourReaction, totalCount}}`. Allowed by the owner (`NEED-141`).",
72
+ },
73
+ });
30
74
  export const messageDelete = reserveOpcode({
31
75
  name: "messages.delete",
32
76
  constant: "MSG_DELETE",
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../src/spec/operations/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AAElC,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;IAC1C,IAAI,EAAE,eAAe;IACrB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,CAAC,CAAC,YAAY,CAAC;QACtB,MAAM,EAAE,EAAE,EAAE;QACZ,OAAO,EAAE,CAAC,CAAC,YAAY,CAAC;YACtB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;YAChB;;;eAGG;YACH,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACpC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAC9B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SAC/B,CAAC;QACF,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;KACpB,CAAC;IACF,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACnE,UAAU,EAAE;QACV,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,CAAC,0FAA0F,CAAC;QACrG,KAAK,EAAE,oGAAoG;KAC5G;CACF,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IACzC,IAAI,EAAE,iBAAiB;IACvB,QAAQ,EAAE,YAAY;IACtB,MAAM,EAAE,EAAE;IACV,MAAM,EACJ,wJAAwJ;IAC1J,UAAU,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;CAC3D,CAAC,CAAA"}
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../src/spec/operations/messages.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,13 @@
1
1
  import type { WebSocket } from "ws";
2
2
  import { type Payload } from "../protocol/frame.js";
3
3
  export interface MockMaxOptions {
4
- /** One answer per opcode. An opcode with no answer is an unexpected call, and the test fails. */
5
- /** A function may return `undefined` to stay silent, which is how a timeout is scripted. */
6
- answers: Record<number, Payload | (() => Payload | undefined)>;
4
+ /**
5
+ * One answer per opcode. An opcode with no answer is an unexpected call, and the test fails.
6
+ * A function may return `undefined` to stay silent, which is how a timeout is scripted — and
7
+ * the only way a test says it means a request to go unanswered. It is handed the request, so
8
+ * one answer can differ by chat.
9
+ */
10
+ answers: Record<number, Payload | ((request: Payload) => Payload | undefined)>;
7
11
  /** Opcodes to refuse, as MAX does: `cmd=3` with an `error` in the payload. */
8
12
  refuse?: Record<number, string>;
9
13
  }
@@ -14,10 +18,12 @@ export interface MockMax {
14
18
  opcode: number;
15
19
  payload: Payload;
16
20
  }[];
17
- /** Calls with no scripted answer. A test that ignores these can pass for the wrong reason. */
21
+ /** Calls with no scripted answer. Any left at the end of a test fail it (`unscripted.ts`). */
18
22
  unexpected: number[];
19
23
  closed: boolean;
20
24
  }
25
+ /** Every mock built since the last call, and forgets them — so each test sees only its own. */
26
+ export declare const takeBuiltMocks: () => MockMax[];
21
27
  /**
22
28
  * MAX, scripted. **No timers, no network, no waiting**: an answer is delivered on the next tick,
23
29
  * so a timeout test costs nothing and a suite cannot reach the real service.
@@ -1 +1 @@
1
- {"version":3,"file":"mock-max.d.ts","sourceRoot":"","sources":["../../src/testing/mock-max.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAqC,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAEtF,MAAM,WAAW,cAAc;IAC7B,iGAAiG;IACjG,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAA;IAC9D,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,OAAO;IACtB,YAAY,EAAE,MAAM,SAAS,CAAA;IAC7B,sFAAsF;IACtF,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAC5C,8FAA8F;IAC9F,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,MAAM,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,qBAA0B,cAAc,KAAG,OAyDlE,CAAA"}
1
+ {"version":3,"file":"mock-max.d.ts","sourceRoot":"","sources":["../../src/testing/mock-max.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAqC,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAEtF,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,SAAS,CAAC,CAAC,CAAA;IAC9E,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,OAAO;IACtB,YAAY,EAAE,MAAM,SAAS,CAAA;IAC7B,sFAAsF;IACtF,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAC5C,8FAA8F;IAC9F,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,MAAM,EAAE,OAAO,CAAA;CAChB;AAID,+FAA+F;AAC/F,eAAO,MAAM,cAAc,QAAO,OAAO,EAAqB,CAAA;AAE9D;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,qBAA0B,cAAc,KAAG,OA0DlE,CAAA"}
@@ -1,5 +1,8 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  import { Command, decodeFrame, encodeFrame } from "../protocol/frame.js";
3
+ const built = [];
4
+ /** Every mock built since the last call, and forgets them — so each test sees only its own. */
5
+ export const takeBuiltMocks = () => built.splice(0);
3
6
  /**
4
7
  * MAX, scripted. **No timers, no network, no waiting**: an answer is delivered on the next tick,
5
8
  * so a timeout test costs nothing and a suite cannot reach the real service.
@@ -15,6 +18,7 @@ export const mockMax = ({ answers, refuse = {} }) => {
15
18
  return socket;
16
19
  };
17
20
  const state = { createSocket, sent: [], unexpected: [], closed: false };
21
+ built.push(state);
18
22
  const socket = new (class extends EventEmitter {
19
23
  readyState = 1;
20
24
  OPEN = 1;
@@ -33,7 +37,7 @@ export const mockMax = ({ answers, refuse = {} }) => {
33
37
  state.unexpected.push(frame.opcode);
34
38
  return;
35
39
  }
36
- const payload = typeof answer === "function" ? answer() : answer;
40
+ const payload = typeof answer === "function" ? answer(frame.payload ?? {}) : answer;
37
41
  if (payload === undefined)
38
42
  return; // Silence: the caller will time out, as MAX sometimes does.
39
43
  this.answer({ seq: frame.seq ?? 0, opcode: frame.opcode, payload, cmd: Command.RESPONSE });
@@ -1 +1 @@
1
- {"version":3,"file":"mock-max.js","sourceRoot":"","sources":["../../src/testing/mock-max.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAgB,MAAM,sBAAsB,CAAA;AAmBtF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,EAAE,EAAkB,EAAW,EAAE;IAC3E,gGAAgG;IAChG,kEAAkE;IAClE,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,cAAc,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QACzC,OAAO,MAA8B,CAAA;IACvC,CAAC,CAAA;IACD,MAAM,KAAK,GAAY,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;IAEhF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAM,SAAQ,YAAY;QAC5C,UAAU,GAAG,CAAC,CAAA;QACL,IAAI,GAAG,CAAC,CAAA;QACR,UAAU,GAAG,CAAC,CAAA;QACd,OAAO,GAAG,CAAC,CAAA;QAEpB,IAAI,CAAC,GAAW;YACd,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;YAC9B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,CAAA;YAEvE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACpC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;gBAC3G,OAAM;YACR,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;gBACnC,OAAM;YACR,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;YAChE,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAM,CAAC,4DAA4D;YAE9F,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC5F,CAAC;QAED,MAAM,CAAC,KAAsE;YAC3E,cAAc,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAChE,CAAC;QAED;;;;;;;WAOG;QACH,KAAK;YACH,KAAK,CAAC,MAAM,GAAG,IAAI,CAAA;YACnB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAA;YACnB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC,CAAA;QAC7F,CAAC;KACF,CAAC,EAAE,CAAA;IAEJ,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
1
+ {"version":3,"file":"mock-max.js","sourceRoot":"","sources":["../../src/testing/mock-max.ts"],"names":[],"mappings":"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"}
@@ -27,5 +27,8 @@ process.env.MAX_CONFIG_DIR = join(sandbox, "config");
27
27
  process.env.MAX_STATE_DIR = join(sandbox, "state");
28
28
  process.env.MAX_CACHE_DIR = join(sandbox, "cache");
29
29
  process.env.TMPDIR = sandbox;
30
+ // Read before the keyring, so a token exported in the shell would log the suite in to the real account.
31
+ delete process.env.MAX_TOKEN;
32
+ process.env.MAX_TEST_SANDBOX = "1";
30
33
  afterAll(() => rmSync(sandbox, { recursive: true, force: true }));
31
34
  //# sourceMappingURL=sandbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/testing/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAA;AAExD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AACpD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,OAAO,CAAA;AAE5B,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/testing/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAA;AAExD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AACpD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,OAAO,CAAA;AAC5B,wGAAwG;AACxG,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAA;AAC5B,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAA;AAElC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=unscripted.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unscripted.d.ts","sourceRoot":"","sources":["../../src/testing/unscripted.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { afterEach } from "vitest";
2
+ import { Opcode } from "../generated/opcodes.generated.js";
3
+ import { takeBuiltMocks } from "./mock-max.js";
4
+ const names = new Map(Object.entries(Opcode).map(([name, opcode]) => [opcode, name]));
5
+ /**
6
+ * **A request the scripted MAX has no answer for fails the test that made it.** Without this the
7
+ * mock stays silent, the client times out, and the test fails — if at all — on a symptom three
8
+ * steps downstream. A test that means a request to go unanswered scripts it as `() => undefined`.
9
+ */
10
+ afterEach(() => {
11
+ const unscripted = takeBuiltMocks().flatMap((max) => max.unexpected);
12
+ if (unscripted.length === 0)
13
+ return;
14
+ const listed = unscripted.map((opcode) => `${names.get(opcode) ?? "unknown"} (${opcode})`).join(", ");
15
+ throw new Error(`the scripted MAX was asked for ${listed} and has no answer scripted — add one, or script silence ` +
16
+ "with `() => undefined` if the test means the request to go unanswered");
17
+ });
18
+ //# sourceMappingURL=unscripted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unscripted.js","sourceRoot":"","sources":["../../src/testing/unscripted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAiB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;AAErG;;;;GAIG;AACH,SAAS,CAAC,GAAG,EAAE;IACb,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACpE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAEnC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACrG,MAAM,IAAI,KAAK,CACb,kCAAkC,MAAM,2DAA2D;QACjG,uEAAuE,CAC1E,CAAA;AACH,CAAC,CAAC,CAAA"}
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  /** The one the running command reports. `pnpm version:check` fails when it and package.json disagree. */
2
- export declare const VERSION = "0.4.0";
2
+ export declare const VERSION = "0.6.0";
3
3
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /** The one the running command reports. `pnpm version:check` fails when it and package.json disagree. */
2
- export const VERSION = "0.4.0";
2
+ export const VERSION = "0.6.0";
3
3
  //# sourceMappingURL=version.js.map