@wirecat/max-cli 0.0.0 → 0.43.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 (546) hide show
  1. package/LICENSE +204 -0
  2. package/README.md +531 -0
  3. package/dist/adapter/max-adapter.d.ts +17 -0
  4. package/dist/adapter/max-adapter.d.ts.map +1 -0
  5. package/dist/adapter/max-adapter.js +364 -0
  6. package/dist/adapter/max-adapter.js.map +1 -0
  7. package/dist/app.d.ts +3 -0
  8. package/dist/app.d.ts.map +1 -0
  9. package/dist/app.js +9 -0
  10. package/dist/app.js.map +1 -0
  11. package/dist/bin/max.d.ts +3 -0
  12. package/dist/bin/max.d.ts.map +1 -0
  13. package/dist/bin/max.js +20 -0
  14. package/dist/bin/max.js.map +1 -0
  15. package/dist/bot/adapter.d.ts +25 -0
  16. package/dist/bot/adapter.d.ts.map +1 -0
  17. package/dist/bot/adapter.js +404 -0
  18. package/dist/bot/adapter.js.map +1 -0
  19. package/dist/bot/auth.d.ts +13 -0
  20. package/dist/bot/auth.d.ts.map +1 -0
  21. package/dist/bot/auth.js +9 -0
  22. package/dist/bot/auth.js.map +1 -0
  23. package/dist/bot/client.d.ts +26 -0
  24. package/dist/bot/client.d.ts.map +1 -0
  25. package/dist/bot/client.js +105 -0
  26. package/dist/bot/client.js.map +1 -0
  27. package/dist/bot/generated/manifest.d.ts +3 -0
  28. package/dist/bot/generated/manifest.d.ts.map +1 -0
  29. package/dist/bot/generated/manifest.js +1232 -0
  30. package/dist/bot/generated/manifest.js.map +1 -0
  31. package/dist/bot/generated/schemas.d.ts +271 -0
  32. package/dist/bot/generated/schemas.d.ts.map +1 -0
  33. package/dist/bot/generated/schemas.js +869 -0
  34. package/dist/bot/generated/schemas.js.map +1 -0
  35. package/dist/bot/generated/types.d.ts +1088 -0
  36. package/dist/bot/generated/types.d.ts.map +1 -0
  37. package/dist/bot/generated/types.js +5 -0
  38. package/dist/bot/generated/types.js.map +1 -0
  39. package/dist/bot/input.d.ts +6 -0
  40. package/dist/bot/input.d.ts.map +1 -0
  41. package/dist/bot/input.js +6 -0
  42. package/dist/bot/input.js.map +1 -0
  43. package/dist/bot/joins.d.ts +26 -0
  44. package/dist/bot/joins.d.ts.map +1 -0
  45. package/dist/bot/joins.js +56 -0
  46. package/dist/bot/joins.js.map +1 -0
  47. package/dist/bot/keep.d.ts +25 -0
  48. package/dist/bot/keep.d.ts.map +1 -0
  49. package/dist/bot/keep.js +98 -0
  50. package/dist/bot/keep.js.map +1 -0
  51. package/dist/bot/map.d.ts +14 -0
  52. package/dist/bot/map.d.ts.map +1 -0
  53. package/dist/bot/map.js +101 -0
  54. package/dist/bot/map.js.map +1 -0
  55. package/dist/bot/mcp-tools.d.ts +4 -0
  56. package/dist/bot/mcp-tools.d.ts.map +1 -0
  57. package/dist/bot/mcp-tools.js +78 -0
  58. package/dist/bot/mcp-tools.js.map +1 -0
  59. package/dist/bot/permissions.d.ts +14 -0
  60. package/dist/bot/permissions.d.ts.map +1 -0
  61. package/dist/bot/permissions.js +88 -0
  62. package/dist/bot/permissions.js.map +1 -0
  63. package/dist/bot/registry.d.ts +11 -0
  64. package/dist/bot/registry.d.ts.map +1 -0
  65. package/dist/bot/registry.js +13 -0
  66. package/dist/bot/registry.js.map +1 -0
  67. package/dist/bot/russian-trusted-root.d.ts +8 -0
  68. package/dist/bot/russian-trusted-root.d.ts.map +1 -0
  69. package/dist/bot/russian-trusted-root.js +41 -0
  70. package/dist/bot/russian-trusted-root.js.map +1 -0
  71. package/dist/bot/transport.d.ts +46 -0
  72. package/dist/bot/transport.d.ts.map +1 -0
  73. package/dist/bot/transport.js +252 -0
  74. package/dist/bot/transport.js.map +1 -0
  75. package/dist/bot/uploads.d.ts +42 -0
  76. package/dist/bot/uploads.d.ts.map +1 -0
  77. package/dist/bot/uploads.js +145 -0
  78. package/dist/bot/uploads.js.map +1 -0
  79. package/dist/client.d.ts +650 -0
  80. package/dist/client.d.ts.map +1 -0
  81. package/dist/client.js +2836 -0
  82. package/dist/client.js.map +1 -0
  83. package/dist/commands/account.d.ts +3 -0
  84. package/dist/commands/account.d.ts.map +1 -0
  85. package/dist/commands/account.js +4 -0
  86. package/dist/commands/account.js.map +1 -0
  87. package/dist/commands/bot-comments.d.ts +3 -0
  88. package/dist/commands/bot-comments.d.ts.map +1 -0
  89. package/dist/commands/bot-comments.js +74 -0
  90. package/dist/commands/bot-comments.js.map +1 -0
  91. package/dist/commands/bot-context.d.ts +38 -0
  92. package/dist/commands/bot-context.d.ts.map +1 -0
  93. package/dist/commands/bot-context.js +121 -0
  94. package/dist/commands/bot-context.js.map +1 -0
  95. package/dist/commands/bot-members.d.ts +14 -0
  96. package/dist/commands/bot-members.d.ts.map +1 -0
  97. package/dist/commands/bot-members.js +64 -0
  98. package/dist/commands/bot-members.js.map +1 -0
  99. package/dist/commands/bot-messenger.d.ts +10 -0
  100. package/dist/commands/bot-messenger.d.ts.map +1 -0
  101. package/dist/commands/bot-messenger.js +101 -0
  102. package/dist/commands/bot-messenger.js.map +1 -0
  103. package/dist/commands/bot-reads.d.ts +4 -0
  104. package/dist/commands/bot-reads.d.ts.map +1 -0
  105. package/dist/commands/bot-reads.js +13 -0
  106. package/dist/commands/bot-reads.js.map +1 -0
  107. package/dist/commands/bot-sends.d.ts +13 -0
  108. package/dist/commands/bot-sends.d.ts.map +1 -0
  109. package/dist/commands/bot-sends.js +103 -0
  110. package/dist/commands/bot-sends.js.map +1 -0
  111. package/dist/commands/bot-setup.d.ts +3 -0
  112. package/dist/commands/bot-setup.d.ts.map +1 -0
  113. package/dist/commands/bot-setup.js +20 -0
  114. package/dist/commands/bot-setup.js.map +1 -0
  115. package/dist/commands/bot.d.ts +3 -0
  116. package/dist/commands/bot.d.ts.map +1 -0
  117. package/dist/commands/bot.js +60 -0
  118. package/dist/commands/bot.js.map +1 -0
  119. package/dist/commands/calls.d.ts +3 -0
  120. package/dist/commands/calls.d.ts.map +1 -0
  121. package/dist/commands/calls.js +4 -0
  122. package/dist/commands/calls.js.map +1 -0
  123. package/dist/commands/chats.d.ts +3 -0
  124. package/dist/commands/chats.d.ts.map +1 -0
  125. package/dist/commands/chats.js +46 -0
  126. package/dist/commands/chats.js.map +1 -0
  127. package/dist/commands/commands.d.ts +2 -0
  128. package/dist/commands/commands.d.ts.map +1 -0
  129. package/dist/commands/commands.js +4 -0
  130. package/dist/commands/commands.js.map +1 -0
  131. package/dist/commands/complete.d.ts +2 -0
  132. package/dist/commands/complete.d.ts.map +1 -0
  133. package/dist/commands/complete.js +34 -0
  134. package/dist/commands/complete.js.map +1 -0
  135. package/dist/commands/config.d.ts +3 -0
  136. package/dist/commands/config.d.ts.map +1 -0
  137. package/dist/commands/config.js +170 -0
  138. package/dist/commands/config.js.map +1 -0
  139. package/dist/commands/contacts.d.ts +10 -0
  140. package/dist/commands/contacts.d.ts.map +1 -0
  141. package/dist/commands/contacts.js +80 -0
  142. package/dist/commands/contacts.js.map +1 -0
  143. package/dist/commands/context.d.ts +126 -0
  144. package/dist/commands/context.d.ts.map +1 -0
  145. package/dist/commands/context.js +137 -0
  146. package/dist/commands/context.js.map +1 -0
  147. package/dist/commands/doctor.d.ts +24 -0
  148. package/dist/commands/doctor.d.ts.map +1 -0
  149. package/dist/commands/doctor.js +308 -0
  150. package/dist/commands/doctor.js.map +1 -0
  151. package/dist/commands/mcp.d.ts +36 -0
  152. package/dist/commands/mcp.d.ts.map +1 -0
  153. package/dist/commands/mcp.js +214 -0
  154. package/dist/commands/mcp.js.map +1 -0
  155. package/dist/commands/messages.d.ts +3 -0
  156. package/dist/commands/messages.d.ts.map +1 -0
  157. package/dist/commands/messages.js +105 -0
  158. package/dist/commands/messages.js.map +1 -0
  159. package/dist/commands/models.d.ts +3 -0
  160. package/dist/commands/models.d.ts.map +1 -0
  161. package/dist/commands/models.js +4 -0
  162. package/dist/commands/models.js.map +1 -0
  163. package/dist/commands/paging.d.ts +59 -0
  164. package/dist/commands/paging.d.ts.map +1 -0
  165. package/dist/commands/paging.js +77 -0
  166. package/dist/commands/paging.js.map +1 -0
  167. package/dist/commands/recipients.d.ts +9 -0
  168. package/dist/commands/recipients.d.ts.map +1 -0
  169. package/dist/commands/recipients.js +74 -0
  170. package/dist/commands/recipients.js.map +1 -0
  171. package/dist/commands/runs.d.ts +2 -0
  172. package/dist/commands/runs.d.ts.map +1 -0
  173. package/dist/commands/runs.js +4 -0
  174. package/dist/commands/runs.js.map +1 -0
  175. package/dist/commands/sends.d.ts +3 -0
  176. package/dist/commands/sends.d.ts.map +1 -0
  177. package/dist/commands/sends.js +4 -0
  178. package/dist/commands/sends.js.map +1 -0
  179. package/dist/commands/serve-members.d.ts +14 -0
  180. package/dist/commands/serve-members.d.ts.map +1 -0
  181. package/dist/commands/serve-members.js +54 -0
  182. package/dist/commands/serve-members.js.map +1 -0
  183. package/dist/commands/serve-stems.d.ts +9 -0
  184. package/dist/commands/serve-stems.d.ts.map +1 -0
  185. package/dist/commands/serve-stems.js +26 -0
  186. package/dist/commands/serve-stems.js.map +1 -0
  187. package/dist/commands/serve.d.ts +10 -0
  188. package/dist/commands/serve.d.ts.map +1 -0
  189. package/dist/commands/serve.js +79 -0
  190. package/dist/commands/serve.js.map +1 -0
  191. package/dist/commands/server.d.ts +16 -0
  192. package/dist/commands/server.d.ts.map +1 -0
  193. package/dist/commands/server.js +51 -0
  194. package/dist/commands/server.js.map +1 -0
  195. package/dist/commands/session.d.ts +15 -0
  196. package/dist/commands/session.d.ts.map +1 -0
  197. package/dist/commands/session.js +169 -0
  198. package/dist/commands/session.js.map +1 -0
  199. package/dist/commands/setup.d.ts +3 -0
  200. package/dist/commands/setup.d.ts.map +1 -0
  201. package/dist/commands/setup.js +168 -0
  202. package/dist/commands/setup.js.map +1 -0
  203. package/dist/commands/skill.d.ts +3 -0
  204. package/dist/commands/skill.d.ts.map +1 -0
  205. package/dist/commands/skill.js +7 -0
  206. package/dist/commands/skill.js.map +1 -0
  207. package/dist/commands/stickers.d.ts +3 -0
  208. package/dist/commands/stickers.d.ts.map +1 -0
  209. package/dist/commands/stickers.js +4 -0
  210. package/dist/commands/stickers.js.map +1 -0
  211. package/dist/commands/upgrade.d.ts +2 -0
  212. package/dist/commands/upgrade.d.ts.map +1 -0
  213. package/dist/commands/upgrade.js +14 -0
  214. package/dist/commands/upgrade.js.map +1 -0
  215. package/dist/commands/watch.d.ts +27 -0
  216. package/dist/commands/watch.d.ts.map +1 -0
  217. package/dist/commands/watch.js +105 -0
  218. package/dist/commands/watch.js.map +1 -0
  219. package/dist/config.d.ts +385 -0
  220. package/dist/config.d.ts.map +1 -0
  221. package/dist/config.js +372 -0
  222. package/dist/config.js.map +1 -0
  223. package/dist/deadline.d.ts +2 -0
  224. package/dist/deadline.d.ts.map +1 -0
  225. package/dist/deadline.js +2 -0
  226. package/dist/deadline.js.map +1 -0
  227. package/dist/diagnose.d.ts +143 -0
  228. package/dist/diagnose.d.ts.map +1 -0
  229. package/dist/diagnose.js +183 -0
  230. package/dist/diagnose.js.map +1 -0
  231. package/dist/domain/map.d.ts +65 -0
  232. package/dist/domain/map.d.ts.map +1 -0
  233. package/dist/domain/map.js +431 -0
  234. package/dist/domain/map.js.map +1 -0
  235. package/dist/domain/models.d.ts +238 -0
  236. package/dist/domain/models.d.ts.map +1 -0
  237. package/dist/domain/models.js +17 -0
  238. package/dist/domain/models.js.map +1 -0
  239. package/dist/download.d.ts +38 -0
  240. package/dist/download.d.ts.map +1 -0
  241. package/dist/download.js +199 -0
  242. package/dist/download.js.map +1 -0
  243. package/dist/format-markdown.d.ts +13 -0
  244. package/dist/format-markdown.d.ts.map +1 -0
  245. package/dist/format-markdown.js +241 -0
  246. package/dist/format-markdown.js.map +1 -0
  247. package/dist/generated/client.generated.d.ts +95 -0
  248. package/dist/generated/client.generated.d.ts.map +1 -0
  249. package/dist/generated/client.generated.js +91 -0
  250. package/dist/generated/client.generated.js.map +1 -0
  251. package/dist/generated/opcodes.generated.d.ts +76 -0
  252. package/dist/generated/opcodes.generated.d.ts.map +1 -0
  253. package/dist/generated/opcodes.generated.js +76 -0
  254. package/dist/generated/opcodes.generated.js.map +1 -0
  255. package/dist/generated/operations.generated.d.ts +502 -0
  256. package/dist/generated/operations.generated.d.ts.map +1 -0
  257. package/dist/generated/operations.generated.js +72 -0
  258. package/dist/generated/operations.generated.js.map +1 -0
  259. package/dist/inbox-point.d.ts +3 -0
  260. package/dist/inbox-point.d.ts.map +1 -0
  261. package/dist/inbox-point.js +17 -0
  262. package/dist/inbox-point.js.map +1 -0
  263. package/dist/install/postinstall.d.ts +8 -0
  264. package/dist/install/postinstall.d.ts.map +1 -0
  265. package/dist/install/postinstall.js +62 -0
  266. package/dist/install/postinstall.js.map +1 -0
  267. package/dist/install.d.ts +43 -0
  268. package/dist/install.d.ts.map +1 -0
  269. package/dist/install.js +142 -0
  270. package/dist/install.js.map +1 -0
  271. package/dist/markdown.d.ts +13 -0
  272. package/dist/markdown.d.ts.map +1 -0
  273. package/dist/markdown.js +6 -0
  274. package/dist/markdown.js.map +1 -0
  275. package/dist/mcp/instructions.d.ts +13 -0
  276. package/dist/mcp/instructions.d.ts.map +1 -0
  277. package/dist/mcp/instructions.js +16 -0
  278. package/dist/mcp/instructions.js.map +1 -0
  279. package/dist/mcp/legacy-check.d.ts +12 -0
  280. package/dist/mcp/legacy-check.d.ts.map +1 -0
  281. package/dist/mcp/legacy-check.js +44 -0
  282. package/dist/mcp/legacy-check.js.map +1 -0
  283. package/dist/mcp/photo.d.ts +9 -0
  284. package/dist/mcp/photo.d.ts.map +1 -0
  285. package/dist/mcp/photo.js +38 -0
  286. package/dist/mcp/photo.js.map +1 -0
  287. package/dist/mcp/prompts.d.ts +7 -0
  288. package/dist/mcp/prompts.d.ts.map +1 -0
  289. package/dist/mcp/prompts.js +100 -0
  290. package/dist/mcp/prompts.js.map +1 -0
  291. package/dist/mcp/resources.d.ts +15 -0
  292. package/dist/mcp/resources.d.ts.map +1 -0
  293. package/dist/mcp/resources.js +56 -0
  294. package/dist/mcp/resources.js.map +1 -0
  295. package/dist/mcp/server.d.ts +31 -0
  296. package/dist/mcp/server.d.ts.map +1 -0
  297. package/dist/mcp/server.js +116 -0
  298. package/dist/mcp/server.js.map +1 -0
  299. package/dist/mcp/session.d.ts +30 -0
  300. package/dist/mcp/session.d.ts.map +1 -0
  301. package/dist/mcp/session.js +109 -0
  302. package/dist/mcp/session.js.map +1 -0
  303. package/dist/mcp/shared.d.ts +14 -0
  304. package/dist/mcp/shared.d.ts.map +1 -0
  305. package/dist/mcp/shared.js +46 -0
  306. package/dist/mcp/shared.js.map +1 -0
  307. package/dist/mcp/tools.d.ts +30 -0
  308. package/dist/mcp/tools.d.ts.map +1 -0
  309. package/dist/mcp/tools.js +248 -0
  310. package/dist/mcp/tools.js.map +1 -0
  311. package/dist/messenger.d.ts +15 -0
  312. package/dist/messenger.d.ts.map +1 -0
  313. package/dist/messenger.js +149 -0
  314. package/dist/messenger.js.map +1 -0
  315. package/dist/moderation/check.d.ts +103 -0
  316. package/dist/moderation/check.d.ts.map +1 -0
  317. package/dist/moderation/check.js +273 -0
  318. package/dist/moderation/check.js.map +1 -0
  319. package/dist/moderation/points.d.ts +8 -0
  320. package/dist/moderation/points.d.ts.map +1 -0
  321. package/dist/moderation/points.js +21 -0
  322. package/dist/moderation/points.js.map +1 -0
  323. package/dist/moderation/rules.d.ts +7 -0
  324. package/dist/moderation/rules.d.ts.map +1 -0
  325. package/dist/moderation/rules.js +24 -0
  326. package/dist/moderation/rules.js.map +1 -0
  327. package/dist/online.d.ts +23 -0
  328. package/dist/online.d.ts.map +1 -0
  329. package/dist/online.js +87 -0
  330. package/dist/online.js.map +1 -0
  331. package/dist/output.d.ts +2 -0
  332. package/dist/output.d.ts.map +1 -0
  333. package/dist/output.js +2 -0
  334. package/dist/output.js.map +1 -0
  335. package/dist/permissions.d.ts +20 -0
  336. package/dist/permissions.d.ts.map +1 -0
  337. package/dist/permissions.js +76 -0
  338. package/dist/permissions.js.map +1 -0
  339. package/dist/profile.d.ts +33 -0
  340. package/dist/profile.d.ts.map +1 -0
  341. package/dist/profile.js +60 -0
  342. package/dist/profile.js.map +1 -0
  343. package/dist/program.d.ts +10 -0
  344. package/dist/program.d.ts.map +1 -0
  345. package/dist/program.js +172 -0
  346. package/dist/program.js.map +1 -0
  347. package/dist/protocol/connection.d.ts +83 -0
  348. package/dist/protocol/connection.d.ts.map +1 -0
  349. package/dist/protocol/connection.js +301 -0
  350. package/dist/protocol/connection.js.map +1 -0
  351. package/dist/protocol/frame.d.ts +55 -0
  352. package/dist/protocol/frame.d.ts.map +1 -0
  353. package/dist/protocol/frame.js +149 -0
  354. package/dist/protocol/frame.js.map +1 -0
  355. package/dist/protocol/lz4.d.ts +15 -0
  356. package/dist/protocol/lz4.d.ts.map +1 -0
  357. package/dist/protocol/lz4.js +157 -0
  358. package/dist/protocol/lz4.js.map +1 -0
  359. package/dist/record.d.ts +41 -0
  360. package/dist/record.d.ts.map +1 -0
  361. package/dist/record.js +104 -0
  362. package/dist/record.js.map +1 -0
  363. package/dist/rendering/messages.d.ts +24 -0
  364. package/dist/rendering/messages.d.ts.map +1 -0
  365. package/dist/rendering/messages.js +172 -0
  366. package/dist/rendering/messages.js.map +1 -0
  367. package/dist/report.d.ts +43 -0
  368. package/dist/report.d.ts.map +1 -0
  369. package/dist/report.js +104 -0
  370. package/dist/report.js.map +1 -0
  371. package/dist/resolve.d.ts +6 -0
  372. package/dist/resolve.d.ts.map +1 -0
  373. package/dist/resolve.js +5 -0
  374. package/dist/resolve.js.map +1 -0
  375. package/dist/sends.d.ts +17 -0
  376. package/dist/sends.d.ts.map +1 -0
  377. package/dist/sends.js +97 -0
  378. package/dist/sends.js.map +1 -0
  379. package/dist/server/lines.d.ts +23 -0
  380. package/dist/server/lines.d.ts.map +1 -0
  381. package/dist/server/lines.js +56 -0
  382. package/dist/server/lines.js.map +1 -0
  383. package/dist/server/replies.d.ts +31 -0
  384. package/dist/server/replies.d.ts.map +1 -0
  385. package/dist/server/replies.js +95 -0
  386. package/dist/server/replies.js.map +1 -0
  387. package/dist/server/server-connection.d.ts +55 -0
  388. package/dist/server/server-connection.d.ts.map +1 -0
  389. package/dist/server/server-connection.js +245 -0
  390. package/dist/server/server-connection.js.map +1 -0
  391. package/dist/server/server.d.ts +88 -0
  392. package/dist/server/server.d.ts.map +1 -0
  393. package/dist/server/server.js +634 -0
  394. package/dist/server/server.js.map +1 -0
  395. package/dist/server/start.d.ts +37 -0
  396. package/dist/server/start.d.ts.map +1 -0
  397. package/dist/server/start.js +102 -0
  398. package/dist/server/start.js.map +1 -0
  399. package/dist/server/subscribe.d.ts +9 -0
  400. package/dist/server/subscribe.d.ts.map +1 -0
  401. package/dist/server/subscribe.js +26 -0
  402. package/dist/server/subscribe.js.map +1 -0
  403. package/dist/session/adopt.d.ts +22 -0
  404. package/dist/session/adopt.d.ts.map +1 -0
  405. package/dist/session/adopt.js +34 -0
  406. package/dist/session/adopt.js.map +1 -0
  407. package/dist/session/browser.d.ts +55 -0
  408. package/dist/session/browser.d.ts.map +1 -0
  409. package/dist/session/browser.js +321 -0
  410. package/dist/session/browser.js.map +1 -0
  411. package/dist/session/handshake.d.ts +57 -0
  412. package/dist/session/handshake.d.ts.map +1 -0
  413. package/dist/session/handshake.js +40 -0
  414. package/dist/session/handshake.js.map +1 -0
  415. package/dist/session/login.d.ts +20 -0
  416. package/dist/session/login.d.ts.map +1 -0
  417. package/dist/session/login.js +66 -0
  418. package/dist/session/login.js.map +1 -0
  419. package/dist/session/prompt.d.ts +2 -0
  420. package/dist/session/prompt.d.ts.map +1 -0
  421. package/dist/session/prompt.js +2 -0
  422. package/dist/session/prompt.js.map +1 -0
  423. package/dist/session/qr-terminal.d.ts +9 -0
  424. package/dist/session/qr-terminal.d.ts.map +1 -0
  425. package/dist/session/qr-terminal.js +34 -0
  426. package/dist/session/qr-terminal.js.map +1 -0
  427. package/dist/session/store.d.ts +76 -0
  428. package/dist/session/store.d.ts.map +1 -0
  429. package/dist/session/store.js +134 -0
  430. package/dist/session/store.js.map +1 -0
  431. package/dist/skill.d.ts +7 -0
  432. package/dist/skill.d.ts.map +1 -0
  433. package/dist/skill.js +8 -0
  434. package/dist/skill.js.map +1 -0
  435. package/dist/spec/check.d.ts +16 -0
  436. package/dist/spec/check.d.ts.map +1 -0
  437. package/dist/spec/check.js +44 -0
  438. package/dist/spec/check.js.map +1 -0
  439. package/dist/spec/define.d.ts +108 -0
  440. package/dist/spec/define.d.ts.map +1 -0
  441. package/dist/spec/define.js +47 -0
  442. package/dist/spec/define.js.map +1 -0
  443. package/dist/spec/guards.d.ts +16 -0
  444. package/dist/spec/guards.d.ts.map +1 -0
  445. package/dist/spec/guards.js +30 -0
  446. package/dist/spec/guards.js.map +1 -0
  447. package/dist/spec/identity.d.ts +57 -0
  448. package/dist/spec/identity.d.ts.map +1 -0
  449. package/dist/spec/identity.js +53 -0
  450. package/dist/spec/identity.js.map +1 -0
  451. package/dist/spec/index.d.ts +15 -0
  452. package/dist/spec/index.d.ts.map +1 -0
  453. package/dist/spec/index.js +84 -0
  454. package/dist/spec/index.js.map +1 -0
  455. package/dist/spec/operations/account.d.ts +39 -0
  456. package/dist/spec/operations/account.d.ts.map +1 -0
  457. package/dist/spec/operations/account.js +103 -0
  458. package/dist/spec/operations/account.js.map +1 -0
  459. package/dist/spec/operations/assets.d.ts +17 -0
  460. package/dist/spec/operations/assets.d.ts.map +1 -0
  461. package/dist/spec/operations/assets.js +43 -0
  462. package/dist/spec/operations/assets.js.map +1 -0
  463. package/dist/spec/operations/attachments.d.ts +15 -0
  464. package/dist/spec/operations/attachments.d.ts.map +1 -0
  465. package/dist/spec/operations/attachments.js +40 -0
  466. package/dist/spec/operations/attachments.js.map +1 -0
  467. package/dist/spec/operations/banners.d.ts +7 -0
  468. package/dist/spec/operations/banners.d.ts.map +1 -0
  469. package/dist/spec/operations/banners.js +16 -0
  470. package/dist/spec/operations/banners.js.map +1 -0
  471. package/dist/spec/operations/calls.d.ts +8 -0
  472. package/dist/spec/operations/calls.d.ts.map +1 -0
  473. package/dist/spec/operations/calls.js +25 -0
  474. package/dist/spec/operations/calls.js.map +1 -0
  475. package/dist/spec/operations/chats.d.ts +115 -0
  476. package/dist/spec/operations/chats.d.ts.map +1 -0
  477. package/dist/spec/operations/chats.js +331 -0
  478. package/dist/spec/operations/chats.js.map +1 -0
  479. package/dist/spec/operations/contacts.d.ts +39 -0
  480. package/dist/spec/operations/contacts.d.ts.map +1 -0
  481. package/dist/spec/operations/contacts.js +135 -0
  482. package/dist/spec/operations/contacts.js.map +1 -0
  483. package/dist/spec/operations/folders.d.ts +31 -0
  484. package/dist/spec/operations/folders.d.ts.map +1 -0
  485. package/dist/spec/operations/folders.js +94 -0
  486. package/dist/spec/operations/folders.js.map +1 -0
  487. package/dist/spec/operations/login.d.ts +64 -0
  488. package/dist/spec/operations/login.d.ts.map +1 -0
  489. package/dist/spec/operations/login.js +105 -0
  490. package/dist/spec/operations/login.js.map +1 -0
  491. package/dist/spec/operations/messages.d.ts +142 -0
  492. package/dist/spec/operations/messages.d.ts.map +1 -0
  493. package/dist/spec/operations/messages.js +347 -0
  494. package/dist/spec/operations/messages.js.map +1 -0
  495. package/dist/spec/operations/session.d.ts +120 -0
  496. package/dist/spec/operations/session.d.ts.map +1 -0
  497. package/dist/spec/operations/session.js +202 -0
  498. package/dist/spec/operations/session.js.map +1 -0
  499. package/dist/spec/operations/uploads.d.ts +31 -0
  500. package/dist/spec/operations/uploads.d.ts.map +1 -0
  501. package/dist/spec/operations/uploads.js +59 -0
  502. package/dist/spec/operations/uploads.js.map +1 -0
  503. package/dist/spec/scalars.d.ts +17 -0
  504. package/dist/spec/scalars.d.ts.map +1 -0
  505. package/dist/spec/scalars.js +33 -0
  506. package/dist/spec/scalars.js.map +1 -0
  507. package/dist/transcribe/index.d.ts +70 -0
  508. package/dist/transcribe/index.d.ts.map +1 -0
  509. package/dist/transcribe/index.js +127 -0
  510. package/dist/transcribe/index.js.map +1 -0
  511. package/dist/transcribe/install.d.ts +2 -0
  512. package/dist/transcribe/install.d.ts.map +1 -0
  513. package/dist/transcribe/install.js +2 -0
  514. package/dist/transcribe/install.js.map +1 -0
  515. package/dist/transcribe/models.d.ts +5 -0
  516. package/dist/transcribe/models.d.ts.map +1 -0
  517. package/dist/transcribe/models.js +6 -0
  518. package/dist/transcribe/models.js.map +1 -0
  519. package/dist/transcribe/speech.d.ts +25 -0
  520. package/dist/transcribe/speech.d.ts.map +1 -0
  521. package/dist/transcribe/speech.js +107 -0
  522. package/dist/transcribe/speech.js.map +1 -0
  523. package/dist/update.d.ts +31 -0
  524. package/dist/update.d.ts.map +1 -0
  525. package/dist/update.js +69 -0
  526. package/dist/update.js.map +1 -0
  527. package/dist/upload.d.ts +15 -0
  528. package/dist/upload.d.ts.map +1 -0
  529. package/dist/upload.js +97 -0
  530. package/dist/upload.js.map +1 -0
  531. package/dist/version.d.ts +2 -0
  532. package/dist/version.d.ts.map +1 -0
  533. package/dist/version.js +2 -0
  534. package/dist/version.js.map +1 -0
  535. package/dist/voice.d.ts +9 -0
  536. package/dist/voice.d.ts.map +1 -0
  537. package/dist/voice.js +36 -0
  538. package/dist/voice.js.map +1 -0
  539. package/dist/wire-events.d.ts +23 -0
  540. package/dist/wire-events.d.ts.map +1 -0
  541. package/dist/wire-events.js +47 -0
  542. package/dist/wire-events.js.map +1 -0
  543. package/install/postinstall.mjs +3 -0
  544. package/install/windows.ps1 +160 -0
  545. package/package.json +120 -3
  546. package/skills/max-cli/SKILL.md +523 -0
@@ -0,0 +1,634 @@
1
+ import { chmodSync, mkdirSync, rmSync } from "node:fs";
2
+ import { connect, createServer } from "node:net";
3
+ import { dirname } from "node:path";
4
+ import { CliError } from "@wirecat/cli-core";
5
+ import * as v from "valibot";
6
+ import { FIRST_TAB_SYNC, isJoinRequest, MaxClient, } from "../client.js";
7
+ import { resolveSettings } from "../config.js";
8
+ import { Opcode } from "../generated/opcodes.generated.js";
9
+ import { assertReadable } from "../permissions.js";
10
+ import { Connection, ProtocolError } from "../protocol/connection.js";
11
+ import { asId } from "../protocol/frame.js";
12
+ import { maxRecord } from "../record.js";
13
+ import { guardFor } from "../sends.js";
14
+ import { objectOf } from "../spec/guards.js";
15
+ import { VERSION } from "../version.js";
16
+ import { fromLine, lineReader, toLine } from "./lines.js";
17
+ import { serverReplies } from "./replies.js";
18
+ import { forwardedOperation, OPERATIONS_FINGERPRINT, stopServer } from "./server-connection.js";
19
+ /** The web client's keep-alive interval (web.max.ru bundle, 2026-09-24). A different one is a fingerprint. */
20
+ const PING_EVERY_MS = 30_000;
21
+ /**
22
+ * A hidden web tab sends its one telemetry event this long after it opened, and nothing after
23
+ * (frames captured 2026-09-25, `docs/dev/capture/2026-09-25-web-tab.md`).
24
+ */
25
+ const TELEMETRY_AFTER_MS = 20_000;
26
+ /** How long after its login answer the tab's chat list appeared in the same capture. */
27
+ const CHAT_LIST_SHOWN_AFTER_MS = 500;
28
+ /** A message arrived — what MAX pushes, and what a send through this server is handed on as. */
29
+ const NEW_MESSAGE = 128;
30
+ const CHAT_CHANGED = 135;
31
+ const CONFIG_CHANGED = 134;
32
+ /** A request is a command's payload; a message with its markup is a few kilobytes. */
33
+ const MAX_REQUEST_LENGTH = 1024 * 1024;
34
+ /** A login MAX counts; after one, the next background login waits at least this long. */
35
+ const REFRESH_EVERY_MS = 60_000;
36
+ /**
37
+ * **One logged-in connection per profile, kept open** (`MAX-16`), and a Unix socket beside the
38
+ * profile's state for local readers.
39
+ *
40
+ * It reopens REQUIREMENTS §3 and §18 on purpose and only here: every other command stays one-shot.
41
+ * What it does on the wire copies web.max.ru — a ping every 30 s, MAX's pings answered, each new
42
+ * message acknowledged (`Connection` with `live`). It never marks anything read. It sends on its own
43
+ * only what the owner's reply rules answer, to the people and chats their audience allows (`NEED-645`).
44
+ *
45
+ * The socket answers `{"subscribe": true}` with a stream of `ServerEvent` lines and
46
+ * `{"status": true}` with one. For a command reusing the connection (`ServerConnection`) it answers
47
+ * `{"id", "login": true}` with the login it holds, and `{"id", "opcode", "payload"}` by passing the
48
+ * request to MAX — sends included (`NEED-229`). **Every write goes through the send guard here**,
49
+ * and is journaled here (`NEED-269`): anything of the owner's can write to this socket, not only a
50
+ * command that checked first. An operation the specification does not declare is not passed on.
51
+ */
52
+ export class MaxServer {
53
+ #options;
54
+ #record;
55
+ #subscribers = new Set();
56
+ #listener;
57
+ #client;
58
+ #ping;
59
+ #retry;
60
+ #attempt = 0;
61
+ #stopped = false;
62
+ /** Every client on the socket — a command, `max mcp`, `max watch`. Idle means none at all. */
63
+ #open = new Set();
64
+ /** Message ids already handed to watchers, newest last. */
65
+ #seen = new Set();
66
+ /** Settles when a connection is up; replaced while the server reconnects. */
67
+ #up;
68
+ #markUp = () => { };
69
+ #refresh;
70
+ #lastRefresh = 0;
71
+ #lastUse = Date.now();
72
+ #startedAt = new Date().toISOString();
73
+ #idle;
74
+ #telemetry;
75
+ /** What the last reads after login answered, sent back on the next login as the tab does (`MAX-52`). */
76
+ #tabSync = FIRST_TAB_SYNC;
77
+ /** The last connection's login, kept past a drop so the next login resumes it (`MAX-51`). */
78
+ #resume;
79
+ #handing = Promise.resolve();
80
+ #connecting = new Set();
81
+ #replies;
82
+ #members;
83
+ #finish;
84
+ /** Settles when the server stops — cleanly, or with the error that stopped it. */
85
+ done;
86
+ constructor(options) {
87
+ this.#options = options;
88
+ this.#members = options.members?.(() => (this.#stopped ? undefined : this.#client));
89
+ this.#record = maxRecord({ account: () => options.store.readState().viewerId });
90
+ this.#replies = serverReplies({
91
+ profile: options.store.profile,
92
+ since: Date.parse(this.#startedAt),
93
+ owner: () => options.store.readState().viewerId,
94
+ client: () => this.#client,
95
+ guard: () => options.guard?.() ??
96
+ // A rule has nobody to ask: a level of `ask` is not a yes.
97
+ guardFor(resolveSettings({ profile: options.store.profile }), options.note, async (key) => {
98
+ throw new CliError("confirmation_required", `${key} asks before it acts — serve has nobody to ask`);
99
+ }),
100
+ note: options.note,
101
+ });
102
+ this.#up = new Promise((resolve) => {
103
+ this.#markUp = resolve;
104
+ });
105
+ this.done = new Promise((resolve, reject) => {
106
+ this.#finish = (error) => (error ? reject(error) : resolve());
107
+ });
108
+ }
109
+ get connected() {
110
+ return this.#client !== undefined;
111
+ }
112
+ /** Logs in first: a token that does not work should fail here, before anything listens. */
113
+ async start() {
114
+ // The socket first: whoever binds it is the profile's one server, and a second one learns it
115
+ // before it has logged in — not after, with a login MAX has already counted.
116
+ const sessionId = Date.now();
117
+ try {
118
+ await this.#listen();
119
+ await this.#connect();
120
+ }
121
+ catch (error) {
122
+ await this.stop();
123
+ throw error;
124
+ }
125
+ finally {
126
+ rmSync(startingPath(this.#options.store), { force: true });
127
+ }
128
+ if (this.#stopped)
129
+ return;
130
+ this.#reportChatList(sessionId, Date.now() + CHAT_LIST_SHOWN_AFTER_MS);
131
+ const { idleMs } = this.#options;
132
+ if (idleMs !== undefined) {
133
+ this.#idle = setInterval(() => {
134
+ if (this.#open.size === 0 && Date.now() - this.#lastUse >= idleMs) {
135
+ this.#options.note(`nobody has used it for ${Math.round(idleMs / 60_000)} min — stopping`);
136
+ void this.stop();
137
+ }
138
+ }, Math.min(idleMs, 30_000));
139
+ }
140
+ }
141
+ async stop(error) {
142
+ if (this.#stopped)
143
+ return;
144
+ this.#stopped = true;
145
+ // Anyone still waiting for a connection gets "not connected" rather than waiting forever.
146
+ this.#markUp();
147
+ clearInterval(this.#ping);
148
+ clearTimeout(this.#retry);
149
+ clearTimeout(this.#refresh);
150
+ clearInterval(this.#idle);
151
+ clearTimeout(this.#telemetry);
152
+ await Promise.all([...this.#connecting].map((client) => client.close()));
153
+ for (const socket of this.#open)
154
+ socket.destroy();
155
+ this.#subscribers.clear();
156
+ // Only the server that bound the socket removes it: one refused as "already running" would
157
+ // otherwise delete the running server's socket and let a third start beside it.
158
+ if (this.#listener) {
159
+ await new Promise((resolve) => this.#listener?.close(() => resolve()));
160
+ if (process.platform !== "win32")
161
+ rmSync(this.#options.store.socketPath(), { force: true });
162
+ }
163
+ try {
164
+ this.#replies.stop();
165
+ await this.#members?.stop().catch(() => this.#options.note("daily member fetching could not close its store"));
166
+ await this.#handing;
167
+ await this.#replies.settled();
168
+ await this.#client?.close();
169
+ }
170
+ finally {
171
+ this.#client = undefined;
172
+ await this.#replies.close();
173
+ await this.#record.close();
174
+ this.#finish?.(error);
175
+ }
176
+ }
177
+ /**
178
+ * Logs in on a new connection and, once that worked, makes it the server's — closing the one it
179
+ * replaces, if any. Pushes that arrive before the login finishes are held and replayed, not
180
+ * dropped: `Connection` has already acknowledged them, so MAX will not send them again.
181
+ */
182
+ async #connect() {
183
+ if (this.#stopped)
184
+ return;
185
+ const { store, timeoutMs, events } = this.#options;
186
+ let mine;
187
+ const early = [];
188
+ const connection = (this.#options.connection ??
189
+ ((hooks) => new Connection({ ...hooks, live: true, ...(timeoutMs ? { timeoutMs } : {}) })))({
190
+ onEvent: (frame) => {
191
+ if (mine)
192
+ this.#pushed(mine, frame.opcode, frame.payload ?? {});
193
+ else
194
+ early.push([frame.opcode, frame.payload ?? {}]);
195
+ },
196
+ onClose: (error) => {
197
+ if (mine && mine === this.#client)
198
+ this.#lost(error);
199
+ },
200
+ onError: (error) => this.#options.note(`a pushed frame was dropped: ${error.message}`),
201
+ });
202
+ const resume = this.#client?.live.resumeFrom() ?? this.#resume;
203
+ const client = new MaxClient({
204
+ store,
205
+ connection,
206
+ // `#forward` guards every write a command hands this server, before this client sends it.
207
+ sends: "caller",
208
+ fullLogin: true,
209
+ ...(resume ? { resume } : {}),
210
+ warn: this.#options.note,
211
+ record: this.#record,
212
+ ...(events ? { events } : {}),
213
+ });
214
+ this.#connecting.add(client);
215
+ try {
216
+ await client.connect();
217
+ }
218
+ catch (error) {
219
+ // A socket left open after a refused login keeps the process alive after it said it failed.
220
+ await client.close();
221
+ throw error;
222
+ }
223
+ finally {
224
+ this.#connecting.delete(client);
225
+ }
226
+ const replaced = this.#client;
227
+ if (this.#stopped) {
228
+ await client.close();
229
+ return;
230
+ }
231
+ mine = client;
232
+ this.#client = client;
233
+ this.#members?.start();
234
+ this.#markUp();
235
+ this.#attempt = 0;
236
+ this.#lastRefresh = Date.now();
237
+ clearInterval(this.#ping);
238
+ this.#ping = setInterval(() => {
239
+ client.live.ping().catch(() => { });
240
+ }, this.#options.pingEveryMs ?? PING_EVERY_MS);
241
+ if (replaced)
242
+ await replaced.close().catch(() => { });
243
+ else
244
+ this.#broadcast({ event: "status", connected: true, at: new Date().toISOString() });
245
+ for (const [opcode, payload] of early)
246
+ this.#pushed(client, opcode, payload);
247
+ client.live
248
+ .readLikeTab(this.#tabSync)
249
+ .then((next) => {
250
+ this.#tabSync = next;
251
+ })
252
+ .catch((error) => this.#options.note(`the reads after login were not all answered: ${error.message}`));
253
+ }
254
+ /** Once per server, never again after a reconnect: the tab it copies keeps its session too. */
255
+ #reportChatList(sessionId, at) {
256
+ const wait = Math.max(0, sessionId + (this.#options.telemetryAfterMs ?? TELEMETRY_AFTER_MS) - Date.now());
257
+ this.#telemetry = setTimeout(() => {
258
+ this.#client?.live
259
+ .chatListShown({ at, sessionId })
260
+ .catch((error) => this.#options.note(`telemetry was not sent: ${error.message}`));
261
+ }, wait);
262
+ }
263
+ #pushed(client, opcode, payload) {
264
+ const whole = objectOf(payload.chat);
265
+ const news = whole.id === undefined || client.live.news(whole);
266
+ if (!client.live.patch(opcode, payload))
267
+ this.#goneStale();
268
+ // In arrival order: an edit waits on a name lookup, and must not reach a watcher after the deletion behind it.
269
+ this.#handing = this.#handing.then(async () => {
270
+ try {
271
+ const message = await client.live.message(opcode, payload);
272
+ if (message) {
273
+ this.#replies.arrived(message);
274
+ this.#broadcast({ event: "message", message });
275
+ }
276
+ const change = await client.live.change(opcode, payload);
277
+ if (change && (change.event !== "chat" || news))
278
+ this.#broadcast({ event: "change", change });
279
+ }
280
+ catch (error) {
281
+ this.#options.note(`a pushed message could not be read: ${error.message}`);
282
+ }
283
+ });
284
+ }
285
+ /**
286
+ * The login can no longer be handed out. Rather than wait for a drop that may be hours away, log
287
+ * in again in the background — at most once a minute, since each is a login MAX counts.
288
+ */
289
+ #goneStale() {
290
+ if (this.#refresh || this.#stopped)
291
+ return;
292
+ const every = this.#options.refreshEveryMs ?? REFRESH_EVERY_MS;
293
+ const wait = Math.max(0, this.#lastRefresh + every - Date.now());
294
+ this.#refresh = setTimeout(() => {
295
+ this.#connect()
296
+ .catch((error) => {
297
+ if (refusedLogin(error))
298
+ void this.stop(error);
299
+ else
300
+ this.#options.note(`could not log in again: ${error.message}`);
301
+ })
302
+ .finally(() => {
303
+ this.#refresh = undefined;
304
+ });
305
+ }, wait);
306
+ }
307
+ #lost(error) {
308
+ clearInterval(this.#ping);
309
+ const client = this.#client;
310
+ this.#resume = client?.live.resumeFrom();
311
+ this.#client = undefined;
312
+ this.#up = new Promise((resolve) => {
313
+ this.#markUp = resolve;
314
+ });
315
+ client?.close().catch(() => { });
316
+ if (this.#stopped)
317
+ return;
318
+ this.#broadcast({ event: "status", connected: false, at: new Date().toISOString() });
319
+ this.#reconnectLater(error);
320
+ }
321
+ #reconnectLater(error) {
322
+ if (this.#stopped)
323
+ return;
324
+ const wait = (this.#options.retryAfterMs ?? backoff)(this.#attempt);
325
+ this.#attempt += 1;
326
+ this.#options.note(`${error.message} — connecting again in ${Math.round(wait / 1000)}s`);
327
+ this.#retry = setTimeout(() => {
328
+ this.#connect().catch((failure) => {
329
+ if (refusedLogin(failure))
330
+ this.stop(failure);
331
+ else
332
+ this.#reconnectLater(failure);
333
+ });
334
+ }, wait);
335
+ }
336
+ #broadcast(event) {
337
+ if (event.event !== "status") {
338
+ try {
339
+ assertReadable(resolveSettings({ profile: this.#options.store.profile }), "messages.watch");
340
+ }
341
+ catch {
342
+ for (const socket of this.#subscribers)
343
+ socket.destroy();
344
+ this.#subscribers.clear();
345
+ return;
346
+ }
347
+ }
348
+ if (event.event === "message") {
349
+ // A retried send answers with the same message, and MAX repeats pushes after a hiccup.
350
+ if (this.#seen.has(event.message.id))
351
+ return;
352
+ this.#seen.add(event.message.id);
353
+ if (this.#seen.size > 500)
354
+ this.#seen.delete(this.#seen.values().next().value);
355
+ }
356
+ const line = toLine(event);
357
+ for (const socket of this.#subscribers)
358
+ socket.write(line);
359
+ }
360
+ async #listen() {
361
+ const path = this.#options.store.socketPath();
362
+ // A server a command started gives way to one started by hand; one started by hand does not.
363
+ if ((await answers(path)) && !(!this.#options.startedByCommand && (await stopServer(path)) === "stopped")) {
364
+ throw new CliError("validation_error", `a server is already running for profile "${this.#options.store.profile}"`);
365
+ }
366
+ if (this.#stopped)
367
+ return;
368
+ const pipe = process.platform === "win32";
369
+ // macOS takes 104 bytes with the terminator, Linux 108; past that `listen` says only EINVAL.
370
+ if (!pipe && Buffer.byteLength(path) > 103) {
371
+ throw new CliError("configuration_error", `the server's socket path is ${Buffer.byteLength(path)} bytes, more than this system allows (103): ${path} — ` +
372
+ "a shorter profile name or MAX_STATE_DIR fixes it");
373
+ }
374
+ if (!pipe) {
375
+ // Nobody answers on it, so it is what a crashed server left behind.
376
+ rmSync(path, { force: true });
377
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
378
+ // The socket is open to everyone between `listen` and its `chmod`; only the directory keeps
379
+ // others out then, and `mkdirSync` leaves an existing one as it found it.
380
+ chmodSync(dirname(path), 0o700);
381
+ }
382
+ const listener = createServer((socket) => this.#serve(socket));
383
+ await new Promise((resolve, reject) => {
384
+ listener.once("error", reject);
385
+ listener.listen(path, () => resolve());
386
+ });
387
+ if (this.#stopped) {
388
+ await new Promise((resolve) => listener.close(() => resolve()));
389
+ if (!pipe)
390
+ rmSync(path, { force: true });
391
+ return;
392
+ }
393
+ if (!pipe)
394
+ chmodSync(path, 0o600);
395
+ this.#listener = listener;
396
+ }
397
+ #serve(socket) {
398
+ this.#open.add(socket);
399
+ socket.on("error", () => this.#subscribers.delete(socket));
400
+ socket.on("close", () => {
401
+ this.#subscribers.delete(socket);
402
+ this.#open.delete(socket);
403
+ this.#lastUse = Date.now();
404
+ });
405
+ socket.on("data", lineReader((line) => {
406
+ this.#request(socket, line).catch(() => socket.destroy());
407
+ }, { maxLength: MAX_REQUEST_LENGTH, onTooLong: () => socket.destroy() }));
408
+ }
409
+ async #request(socket, line) {
410
+ let request;
411
+ try {
412
+ request = fromLine(line);
413
+ }
414
+ catch {
415
+ socket.write(toLine({ error: { code: "bad_request", message: "one JSON object per line" } }));
416
+ return;
417
+ }
418
+ const status = {
419
+ event: "status",
420
+ connected: this.connected,
421
+ at: new Date().toISOString(),
422
+ byHand: !this.#options.startedByCommand,
423
+ pid: process.pid,
424
+ version: VERSION,
425
+ operations: OPERATIONS_FINGERPRINT,
426
+ startedAt: this.#startedAt,
427
+ };
428
+ const { id } = request;
429
+ this.#lastUse = Date.now();
430
+ if (request.subscribe === true) {
431
+ try {
432
+ assertReadable(resolveSettings({ profile: this.#options.store.profile }), "messages.watch");
433
+ }
434
+ catch (error) {
435
+ socket.end(toLine({ id, ...refusal(error) }));
436
+ return;
437
+ }
438
+ this.#subscribers.add(socket);
439
+ socket.write(toLine(status));
440
+ }
441
+ else if (request.status === true) {
442
+ socket.write(toLine(status));
443
+ }
444
+ else if (request.stop === true) {
445
+ // Only the owner can reach this socket (mode 600). `max session end` asks, so a forgotten
446
+ // session is not kept alive by a server a command started — one started by hand stays.
447
+ if (!this.#options.startedByCommand && request.force !== true) {
448
+ socket.end(toLine({ id, stopped: false, reason: "started by hand; Ctrl-C, or `max serve --stop`" }));
449
+ return;
450
+ }
451
+ socket.end(toLine({ id, stopped: true }));
452
+ await this.stop();
453
+ }
454
+ else if (request.login === true) {
455
+ try {
456
+ const settings = resolveSettings({ profile: this.#options.store.profile });
457
+ for (const key of ["messages", "chats", "contacts", "account"])
458
+ assertReadable(settings, key);
459
+ }
460
+ catch (error) {
461
+ socket.write(toLine({ id, ...refusal(error) }));
462
+ return;
463
+ }
464
+ // A request that arrives while the server logs in, or logs in again, waits for it: the
465
+ // command's own timeout is what gives up, not this. A login a deletion made stale is still
466
+ // handed out — only a deleted last message can be wrong in it — while a fresh one is fetched.
467
+ await this.#up;
468
+ const client = this.#client;
469
+ socket.write(toLine(client
470
+ ? { id, payload: client.live.snapshot() }
471
+ : { id, error: { code: "unavailable", message: "not connected" } }));
472
+ }
473
+ else if (typeof request.opcode === "number") {
474
+ const operationId = typeof request.operationId === "string" ? request.operationId : undefined;
475
+ socket.write(toLine({ id, ...(await this.#forward(request.opcode, request.payload, operationId, request.approvals)) }));
476
+ }
477
+ else {
478
+ socket.write(toLine({ id, error: { code: "bad_request", message: "subscribe, status, login or an opcode" } }));
479
+ }
480
+ }
481
+ async #forward(opcode, payload, operationId, approvals) {
482
+ await this.#up;
483
+ const client = this.#client;
484
+ const operation = forwardedOperation(opcode);
485
+ if (!operation) {
486
+ return { error: { code: "not_allowed", message: `opcode ${opcode} is not one the server passes on` } };
487
+ }
488
+ if (!client)
489
+ return { error: { code: "unavailable", message: "not connected" } };
490
+ const request = (payload ?? {});
491
+ // The shape the specification allows, checked here as `buildRequest` checks it in a command:
492
+ // an id crosses the socket as a `bigint`, and the schema reads the string it was built from.
493
+ if (!v.safeParse(operation.request, asStrings(request)).success) {
494
+ return refusal(new CliError("validation_error", `${operation.name}: not a request this version of max sends`));
495
+ }
496
+ if (!operation.guard) {
497
+ try {
498
+ assertReadable(resolveSettings({ profile: this.#options.store.profile }), operation.name === "chats.history" || operation.name.startsWith("attachments.")
499
+ ? "messages"
500
+ : operation.name.startsWith("folders.")
501
+ ? `chats.${operation.name}`
502
+ : operation.name);
503
+ }
504
+ catch (error) {
505
+ return refusal(error);
506
+ }
507
+ return this.#pass(client, opcode, request);
508
+ }
509
+ let entry;
510
+ let guard;
511
+ try {
512
+ entry = { ...operation.guard(request), ...(operationId === undefined ? {} : { operationId }) };
513
+ // Read again for every write, so `config set readOnly true` needs no restart.
514
+ guard =
515
+ this.#options.guard?.() ??
516
+ guardFor(resolveSettings({ profile: this.#options.store.profile }), this.#options.note, async (key) => {
517
+ if (!Array.isArray(approvals) || !approvals.includes(key))
518
+ throw new CliError("confirmation_required", `${key} asks before it acts — this request has no explicit confirmation`);
519
+ });
520
+ }
521
+ catch (error) {
522
+ return refusal(error);
523
+ }
524
+ try {
525
+ await guard.ask?.(entry);
526
+ guard.check(entry);
527
+ }
528
+ catch (error) {
529
+ guard.record({ ...entry, outcome: "refused", errorCode: asCliError(error).code });
530
+ return refusal(error);
531
+ }
532
+ return this.#sendJournaled(client, opcode, request, guard, entry);
533
+ }
534
+ async #sendJournaled(client, opcode, request, guard, entry) {
535
+ const answer = await this.#pass(client, opcode, request);
536
+ const error = answer.error;
537
+ if (!error) {
538
+ const reply = objectOf(answer.payload);
539
+ const messageId = asId(objectOf(reply.message).id);
540
+ const chatId = entry.chatId ?? asId(reply.chatId) ?? asId(objectOf(reply.chat).id) ?? null;
541
+ guard.record({ ...entry, chatId, ...(messageId ? { messageId } : {}), outcome: "sent" });
542
+ }
543
+ else if (error.code === "refused") {
544
+ // MAX's "not yet" while an upload is processed: the command asks again, and that is one message.
545
+ if (!error.message?.includes("attachment.not.ready")) {
546
+ guard.record({ ...entry, outcome: "failed", errorCode: "provider_error" });
547
+ }
548
+ }
549
+ else {
550
+ guard.record({ ...entry, outcome: "outcome_unknown", errorCode: "timeout" });
551
+ }
552
+ return answer;
553
+ }
554
+ async #pass(client, opcode, request) {
555
+ try {
556
+ const answer = await client.live.forward(opcode, request);
557
+ // MAX does not push a message back to the connection that sent it, and every send now comes
558
+ // through this one — so `max watch` would never see what `max` itself sent. The answer
559
+ // carries the message; hand it on as if it had been pushed. A scheduled one is not sent yet.
560
+ const scheduled = request.message?.delayedAttributes;
561
+ if (opcode === Opcode.MSG_SEND && answer.message && !scheduled) {
562
+ this.#pushed(client, NEW_MESSAGE, { chatId: request.chatId, message: answer.message });
563
+ }
564
+ // Nor a chat we changed: the answer carries it whole, as a 135 push would. Without this the
565
+ // owner's own rename showed the old title until something else touched the chat.
566
+ // Not a group looked at by its link, nor one the owner only asked to join: the owner is not in it.
567
+ const joinRequest = opcode === Opcode.CHAT_JOIN && isJoinRequest(objectOf(answer.chat));
568
+ if (answer.chat && opcode !== Opcode.LINK_INFO && !joinRequest)
569
+ this.#pushed(client, CHAT_CHANGED, { chat: answer.chat });
570
+ // The same for a contact we renamed: commands keep the login's contacts in the shared store.
571
+ if (objectOf(answer.contact).id !== undefined)
572
+ client.live.contact(objectOf(answer.contact));
573
+ // Nor our own settings change, which other sessions hear as 134 (measured 2026-10-08): without
574
+ // this, `account privacy show` after `set` read the setting from before it.
575
+ if (opcode === Opcode.CONFIG) {
576
+ const sent = objectOf(request.settings);
577
+ this.#pushed(client, CONFIG_CHANGED, {
578
+ config: { hash: answer.hash, user: answer.user ?? sent.user, chats: sent.chats },
579
+ });
580
+ }
581
+ // Nor does it push our own deletion back; the chat's last message may be the one deleted.
582
+ if (opcode === Opcode.MSG_DELETE)
583
+ this.#goneStale();
584
+ return { payload: answer };
585
+ }
586
+ catch (error) {
587
+ if (error instanceof ProtocolError) {
588
+ return { error: { code: "refused", message: error.message, payload: error.payload } };
589
+ }
590
+ return { error: { code: "unavailable", message: error instanceof Error ? error.message : String(error) } };
591
+ }
592
+ }
593
+ }
594
+ const asStrings = (value) => {
595
+ if (typeof value === "bigint")
596
+ return value.toString();
597
+ if (Array.isArray(value))
598
+ return value.map(asStrings);
599
+ if (typeof value === "object" && value !== null) {
600
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, asStrings(item)]));
601
+ }
602
+ return value;
603
+ };
604
+ const asCliError = (error) => error instanceof CliError
605
+ ? error
606
+ : new CliError("validation_error", error instanceof Error ? error.message : String(error));
607
+ /** `guard` tells the command's `ServerConnection` to rethrow it as the same error, exit code included. */
608
+ const refusal = (error) => {
609
+ const { code, message, details } = asCliError(error);
610
+ return { error: { code, message, details, guard: true } };
611
+ };
612
+ /**
613
+ * **MAX answered the login and said no** — as opposed to a network that dropped or a MAX that did
614
+ * not answer. Only those two are retried. A refusal is not: a token MAX no longer takes will not
615
+ * start working, and a login repeated after the limit error kept a PyMax account locked (PyMax
616
+ * #106). Any refusal counts, not only the recognised limit, because what that error says is a claim
617
+ * (`NEED-266`).
618
+ */
619
+ export const refusedLogin = (error) => error instanceof CliError &&
620
+ (error.code === "authentication_error" || error.code === "rate_limited" || error.code === "provider_error");
621
+ /** 1 s, 2 s, 4 s … a minute at most — a server that hammers MAX after a drop looks like nothing MAX knows. */
622
+ const backoff = (attempt) => Math.min(60_000, 1000 * 2 ** attempt);
623
+ /** Present while a server is being started in the background, so two commands do not start two. */
624
+ export const startingPath = (store) => store.serverFile(".sock.starting");
625
+ /** Whether something is listening on the socket — a live server, not a leftover file. */
626
+ export const answers = (path) => new Promise((resolve) => {
627
+ const probe = connect(path);
628
+ probe.once("connect", () => {
629
+ probe.destroy();
630
+ resolve(true);
631
+ });
632
+ probe.once("error", () => resolve(false));
633
+ });
634
+ //# sourceMappingURL=server.js.map