@leemour/max-cli 0.12.0 → 0.14.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 (149) hide show
  1. package/README.md +92 -19
  2. package/dist/bot/auth.d.ts +23 -0
  3. package/dist/bot/auth.d.ts.map +1 -0
  4. package/dist/bot/auth.js +36 -0
  5. package/dist/bot/auth.js.map +1 -0
  6. package/dist/bot/client.d.ts +20 -0
  7. package/dist/bot/client.d.ts.map +1 -0
  8. package/dist/bot/client.js +91 -0
  9. package/dist/bot/client.js.map +1 -0
  10. package/dist/bot/generated/manifest.d.ts +3 -0
  11. package/dist/bot/generated/manifest.d.ts.map +1 -0
  12. package/dist/bot/generated/manifest.js +1232 -0
  13. package/dist/bot/generated/manifest.js.map +1 -0
  14. package/dist/bot/generated/schemas.d.ts +271 -0
  15. package/dist/bot/generated/schemas.d.ts.map +1 -0
  16. package/dist/bot/generated/schemas.js +869 -0
  17. package/dist/bot/generated/schemas.js.map +1 -0
  18. package/dist/bot/generated/types.d.ts +1088 -0
  19. package/dist/bot/generated/types.d.ts.map +1 -0
  20. package/dist/bot/generated/types.js +5 -0
  21. package/dist/bot/generated/types.js.map +1 -0
  22. package/dist/bot/input.d.ts +10 -0
  23. package/dist/bot/input.d.ts.map +1 -0
  24. package/dist/bot/input.js +88 -0
  25. package/dist/bot/input.js.map +1 -0
  26. package/dist/bot/map.d.ts +11 -0
  27. package/dist/bot/map.d.ts.map +1 -0
  28. package/dist/bot/map.js +76 -0
  29. package/dist/bot/map.js.map +1 -0
  30. package/dist/bot/permissions.d.ts +14 -0
  31. package/dist/bot/permissions.d.ts.map +1 -0
  32. package/dist/bot/permissions.js +53 -0
  33. package/dist/bot/permissions.js.map +1 -0
  34. package/dist/bot/registry.d.ts +27 -0
  35. package/dist/bot/registry.d.ts.map +1 -0
  36. package/dist/bot/registry.js +68 -0
  37. package/dist/bot/registry.js.map +1 -0
  38. package/dist/bot/russian-trusted-root.d.ts +8 -0
  39. package/dist/bot/russian-trusted-root.d.ts.map +1 -0
  40. package/dist/bot/russian-trusted-root.js +41 -0
  41. package/dist/bot/russian-trusted-root.js.map +1 -0
  42. package/dist/bot/transport.d.ts +41 -0
  43. package/dist/bot/transport.d.ts.map +1 -0
  44. package/dist/bot/transport.js +200 -0
  45. package/dist/bot/transport.js.map +1 -0
  46. package/dist/client.d.ts +32 -1
  47. package/dist/client.d.ts.map +1 -1
  48. package/dist/client.js +174 -18
  49. package/dist/client.js.map +1 -1
  50. package/dist/commands/bot-context.d.ts +21 -0
  51. package/dist/commands/bot-context.d.ts.map +1 -0
  52. package/dist/commands/bot-context.js +59 -0
  53. package/dist/commands/bot-context.js.map +1 -0
  54. package/dist/commands/bot-reads.d.ts +7 -0
  55. package/dist/commands/bot-reads.d.ts.map +1 -0
  56. package/dist/commands/bot-reads.js +103 -0
  57. package/dist/commands/bot-reads.js.map +1 -0
  58. package/dist/commands/bot-sends.d.ts +12 -0
  59. package/dist/commands/bot-sends.d.ts.map +1 -0
  60. package/dist/commands/bot-sends.js +225 -0
  61. package/dist/commands/bot-sends.js.map +1 -0
  62. package/dist/commands/bot.d.ts +3 -0
  63. package/dist/commands/bot.d.ts.map +1 -0
  64. package/dist/commands/bot.js +145 -0
  65. package/dist/commands/bot.js.map +1 -0
  66. package/dist/commands/chats.d.ts.map +1 -1
  67. package/dist/commands/chats.js +65 -1
  68. package/dist/commands/chats.js.map +1 -1
  69. package/dist/commands/context.d.ts +10 -1
  70. package/dist/commands/context.d.ts.map +1 -1
  71. package/dist/commands/context.js.map +1 -1
  72. package/dist/commands/doctor.d.ts +6 -0
  73. package/dist/commands/doctor.d.ts.map +1 -1
  74. package/dist/commands/doctor.js +57 -7
  75. package/dist/commands/doctor.js.map +1 -1
  76. package/dist/commands/mcp.d.ts +24 -0
  77. package/dist/commands/mcp.d.ts.map +1 -1
  78. package/dist/commands/mcp.js +80 -14
  79. package/dist/commands/mcp.js.map +1 -1
  80. package/dist/commands/models.d.ts.map +1 -1
  81. package/dist/commands/models.js +13 -2
  82. package/dist/commands/models.js.map +1 -1
  83. package/dist/commands/review.d.ts +8 -0
  84. package/dist/commands/review.d.ts.map +1 -0
  85. package/dist/commands/review.js +96 -0
  86. package/dist/commands/review.js.map +1 -0
  87. package/dist/commands/rules.d.ts +7 -0
  88. package/dist/commands/rules.d.ts.map +1 -0
  89. package/dist/commands/rules.js +69 -0
  90. package/dist/commands/rules.js.map +1 -0
  91. package/dist/diagnose.d.ts +19 -1
  92. package/dist/diagnose.d.ts.map +1 -1
  93. package/dist/diagnose.js +37 -1
  94. package/dist/diagnose.js.map +1 -1
  95. package/dist/domain/map.d.ts +6 -1
  96. package/dist/domain/map.d.ts.map +1 -1
  97. package/dist/domain/map.js +34 -1
  98. package/dist/domain/map.js.map +1 -1
  99. package/dist/domain/models.d.ts +79 -0
  100. package/dist/domain/models.d.ts.map +1 -1
  101. package/dist/domain/models.js.map +1 -1
  102. package/dist/generated/operations.generated.d.ts +3 -1
  103. package/dist/generated/operations.generated.d.ts.map +1 -1
  104. package/dist/install.d.ts +43 -0
  105. package/dist/install.d.ts.map +1 -0
  106. package/dist/install.js +142 -0
  107. package/dist/install.js.map +1 -0
  108. package/dist/mcp/prompts.d.ts.map +1 -1
  109. package/dist/mcp/prompts.js +28 -0
  110. package/dist/mcp/prompts.js.map +1 -1
  111. package/dist/mcp/tools.d.ts.map +1 -1
  112. package/dist/mcp/tools.js +39 -1
  113. package/dist/mcp/tools.js.map +1 -1
  114. package/dist/moderation/rules.d.ts +56 -0
  115. package/dist/moderation/rules.d.ts.map +1 -0
  116. package/dist/moderation/rules.js +138 -0
  117. package/dist/moderation/rules.js.map +1 -0
  118. package/dist/online.d.ts +23 -0
  119. package/dist/online.d.ts.map +1 -0
  120. package/dist/online.js +87 -0
  121. package/dist/online.js.map +1 -0
  122. package/dist/program.d.ts.map +1 -1
  123. package/dist/program.js +20 -3
  124. package/dist/program.js.map +1 -1
  125. package/dist/protocol/connection.d.ts.map +1 -1
  126. package/dist/protocol/connection.js +12 -1
  127. package/dist/protocol/connection.js.map +1 -1
  128. package/dist/report.d.ts.map +1 -1
  129. package/dist/report.js +13 -2
  130. package/dist/report.js.map +1 -1
  131. package/dist/review.d.ts +41 -0
  132. package/dist/review.d.ts.map +1 -0
  133. package/dist/review.js +111 -0
  134. package/dist/review.js.map +1 -0
  135. package/dist/spec/operations/chats.d.ts +4 -1
  136. package/dist/spec/operations/chats.d.ts.map +1 -1
  137. package/dist/spec/operations/chats.js +10 -4
  138. package/dist/spec/operations/chats.js.map +1 -1
  139. package/dist/transcribe/index.d.ts +1 -0
  140. package/dist/transcribe/index.d.ts.map +1 -1
  141. package/dist/transcribe/index.js +8 -4
  142. package/dist/transcribe/index.js.map +1 -1
  143. package/dist/transcribe/speech.d.ts.map +1 -1
  144. package/dist/transcribe/speech.js +2 -0
  145. package/dist/transcribe/speech.js.map +1 -1
  146. package/dist/version.d.ts +1 -1
  147. package/dist/version.js +1 -1
  148. package/package.json +14 -6
  149. package/skills/max-cli/SKILL.md +26 -1
package/README.md CHANGED
@@ -4,13 +4,52 @@
4
4
 
5
5
  # max-cli
6
6
 
7
- Ваш личный аккаунт мессенджера [MAX](https://max.ru) в терминале и в ИИ-агентах. `max` — программа для терминала и
8
- MCP-сервер: читайте и пишите в чаты сами или поручите это Claude, Codex, Cursor и другим агентам.
7
+ Ваши боты [MAX](https://max.ru) и ваш личный аккаунт — в терминале и в ИИ-агентах. `max` —
8
+ программа для терминала и MCP-сервер: пишите от имени бота через официальный Bot API, а в свои
9
+ чаты — сами или руками Claude, Codex, Cursor и других агентов.
9
10
 
10
- > ⚠️ **max-cli использует неофициальный внутренний API MAX.** API может измениться без
11
- > предупреждения, а использование инструмента может нарушать условия сервиса. Вы используете
12
- > max-cli на свой риск; авторы и контрибьюторы не несут ответственности за блокировки аккаунтов,
13
- > потерю данных или другие последствия.
11
+ ```sh
12
+ max sales bot messages send "Команда продаж" "Сборка готова" # от имени бота
13
+ max messages send "Иван Петров" "Опаздываю на 15 минут" # от вашего имени
14
+ ```
15
+
16
+ ## Бот
17
+
18
+ `max bot` работает с ботом через **официальный** [Bot API MAX](https://dev.max.ru/docs-api) по токену
19
+ бота. Ботов может быть несколько: каждый хранится под именем, которое вы выбираете, и это имя —
20
+ первое слово команды.
21
+
22
+ ```sh
23
+ max sales bot auth set # токен — в скрытом вводе, MAX его проверит
24
+ max sales bot me # какой это бот
25
+ max sales bot messages send -72894839451 "Сборка готова"
26
+ max sales bot messages list -72894839451
27
+ max sales bot recipients add -72894839451 # писать только сюда
28
+ max bot list --check # все боты на этом компьютере
29
+ ```
30
+
31
+ - **Сообщения и чаты.** Отправка в чат по номеру, человеку как `user:<номер>` или в чат по
32
+ названию; правка, удаление, чтение, закрепление. `chats list` — чаты, которые бот видел: списка
33
+ чатов бота у MAX нет.
34
+ - **Любая операция API.** Все операции Bot API доступны как `max bot api <операция>` — с флагами
35
+ для параметров и JSON-телом, которое сверяется со схемой до отправки.
36
+ - **Бот не напишет лишнего.** У каждого бота свой список чатов, куда ему можно писать, и журнал
37
+ всего, что он отправил, — без текста. Профиль только для чтения и `allow` действуют и на бота.
38
+ - **Токен не в файле.** Токен бота — в системном хранилище паролей, отдельно от вашего.
39
+
40
+ Бота создают на [business.max.ru](https://business.max.ru/self); MAX выдаёт их подтверждённым
41
+ организациям, ИП и самозанятым. Полностью — [docs/bot.md](docs/bot.md).
42
+
43
+ ## Личный аккаунт
44
+
45
+ `max` без слова `bot` работает с вашим личным аккаунтом: как ещё одно ваше устройство, со всеми
46
+ чатами, историей, группами и контактами.
47
+
48
+ > ⚠️ **Для личного аккаунта max-cli использует неофициальный внутренний API MAX.** API может
49
+ > измениться без предупреждения, а использование инструмента может нарушать условия сервиса. Вы
50
+ > используете max-cli на свой риск; авторы и контрибьюторы не несут ответственности за блокировки
51
+ > аккаунтов, потерю данных или другие последствия. Бот работает через официальный API, и к нему
52
+ > это не относится.
14
53
 
15
54
  ```sh
16
55
  max chats list --limit 5
@@ -18,6 +57,8 @@ max messages list "Иван Петров"
18
57
  max messages send "Иван Петров" "Опаздываю на 15 минут"
19
58
  ```
20
59
 
60
+ Всё ниже, до раздела «Установка», — про личный аккаунт. Полностью — [docs/usage.md](docs/usage.md).
61
+
21
62
  ## Как это использовать
22
63
 
23
64
  Самое полезное — поручить переписку агенту: Claude, Codex или другому. Он читает чаты через `max`
@@ -27,14 +68,34 @@ max messages send "Иван Петров" "Опаздываю на 15 минут
27
68
  сводку: кто ждёт ответа, что срочно, что можно не читать.
28
69
  - **Отчёты.** Итог недели по рабочему чату: что решили, кто что взял на себя, какие вопросы
29
70
  остались без ответа.
30
- - **Кто кому должен.** Агент находит в переписке обещания, долги и договорённости и собирает их в
31
- список: кто, что, когда и в каком чате.
71
+ - **Кто кому должен.** `max review` одним вызовом отдаёт всё, что было в переписке с прошлого
72
+ обзора, — ваши сообщения тоже, голосовые — текстом. Агент раскладывает это на «я должен», «жду от
73
+ других» и «нужно уточнить», а прежде чем назвать что-то просроченным, проверяет рабочие группы:
74
+ может, уже сделано.
32
75
  - **Напоминания.** Кому вы обещали ответить и не ответили; чей вопрос висит третий день.
33
76
  - **Черновики ответов.** Агент предлагает текст, а отправляете вы — или он сам, если вы разрешили
34
77
  писать в этот чат.
35
78
  - **Поиск.** «Когда мы договорились о встрече с Иваном?» — ответ с датой и самим сообщением.
36
79
 
37
- Как настроить агента под каждую задачу — готовые запросы, расписание и ограничения:
80
+ Как это выглядит:
81
+
82
+ ```text
83
+ Вы: Что я кому обещал за последние три дня?
84
+ Агент: (вызывает max review: 12 чатов, 3 голосовых расшифровано)
85
+ Я должен
86
+ · Ивану Петрову — прислать счёт до пятницы. «Иван Петров», 24.09
87
+ Жду от других
88
+ · Ольга — макет к 25.09. В группе «Дизайн» его пока нет
89
+ Нужно уточнить
90
+ · «Проект Альфа»: кто везёт образцы — договорились «потом решим», 25.09
91
+ Следующий обзор — с 26.09, 14:05.
92
+ Вы: Напомни Ольге про макет.
93
+ Агент: Черновик: «Ольга, привет! Как там макет?» Отправить?
94
+ Вы: Да.
95
+ ```
96
+
97
+ Агент ничего не отправляет без вашего «да», а чтение не ставит отметку «прочитано». Как настроить
98
+ агента под каждую задачу — готовые запросы, расписание и ограничения:
38
99
  [docs/recipes.md](docs/recipes.md).
39
100
 
40
101
  ## Как это работает
@@ -48,9 +109,11 @@ max messages send "Иван Петров" "Опаздываю на 15 минут
48
109
  - **Агент с терминалом** — Claude Code, Codex, Gemini CLI. Он сам вызывает команды `max`. Дайте
49
110
  ему навык (skill) — инструкцию, как работать с `max`: одна команда, см.
50
111
  [ниже](#для-скриптов-и-агентов).
51
- - **Агент без терминала** — Claude Desktop, Cursor и другие клиенты MCP. Подключите `max mcp`.
52
- По умолчанию агент только читает. Отправку можно разрешить, в том числе с вашим подтверждением
53
- каждого сообщения.
112
+ - **Агент без терминала** — Claude Desktop, Cursor и другие клиенты MCP. Подключите `max mcp`:
113
+ готовую запись для их настроек печатает `max mcp config`. Там же есть команды `/catch-up` (что
114
+ нового), `/review` (кто кому должен), `/reply` (черновик ответа) и `/find` (поиск). По умолчанию
115
+ агент только читает. Отправку можно разрешить, в том числе с вашим подтверждением каждого
116
+ сообщения.
54
117
 
55
118
  [![npm](https://img.shields.io/npm/v/@leemour/max-cli)](https://www.npmjs.com/package/@leemour/max-cli)
56
119
  [![CI](https://github.com/leemour/max-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/leemour/max-cli/actions/workflows/ci.yml)
@@ -62,7 +125,7 @@ max messages send "Иван Петров" "Опаздываю на 15 минут
62
125
  ## Что умеет
63
126
 
64
127
  - **Читать.** Чаты, история, одно сообщение вместе с соседними, непрочитанное во всех чатах
65
- сразу (`max inbox`), новые сообщения по мере прихода (`max watch`), скачивание вложений,
128
+ сразу (`max inbox`), вся переписка с прошлого обзора для разбора «кто кому должен» (`max review`), новые сообщения по мере прихода (`max watch`), скачивание вложений,
66
129
  расшифровка голосовых в текст на вашем компьютере, выгрузка переписки в JSONL или Markdown.
67
130
  - **Искать.** Сообщения — по тексту всего прочитанного, без подключения к MAX. Чаты и контакты —
68
131
  по части названия или имени.
@@ -135,11 +198,13 @@ max messages send "Иван Петров" "Опаздываю на 15 минут
135
198
  | опросы | — | ✅ | — |
136
199
  | пароль и двухфакторный вход, фото профиля | — | ✅ | — |
137
200
 
138
- Если нужен бот со своим аккаунтом, а не ваш личный аккаунт, — это официальный
139
- [Bot API MAX](https://dev.max.ru/docs).
201
+ Для бота есть `max bot` — через официальный Bot API, отдельно от личного аккаунта
202
+ ([docs/bot.md](docs/bot.md)). Таблица выше — про личный аккаунт.
140
203
 
141
204
  ## Содержание
142
205
 
206
+ - [Бот](#бот)
207
+ - [Личный аккаунт](#личный-аккаунт)
143
208
  - [Установка](#установка)
144
209
  - [Вход](#вход)
145
210
  - [Использование](#использование)
@@ -169,8 +234,11 @@ npm install -g @leemour/max-cli
169
234
  max --version
170
235
  ```
171
236
 
172
- Нужен **Node 22 или новее**, либо **Bun 1.3+**. Подробности, переменные окружения и то, куда
173
- ложатся файлы, — [docs/installation.md](docs/installation.md).
237
+ Нужен **Node 22 или новее**, либо **Bun 1.3+**. Работает на macOS, Linux и Windows. Подробности,
238
+ переменные окружения и то, куда ложатся файлы, — [docs/installation.md](docs/installation.md).
239
+
240
+ Если после установки команда `max` не находится, `npx @leemour/max-cli doctor` скажет почему и
241
+ напечатает команду, которая это исправит.
174
242
 
175
243
  ## Вход
176
244
 
@@ -257,9 +325,13 @@ Claude Desktop, Cursor и другие клиенты MCP подключаютс
257
325
  видите чат и текст и отвечаете «да» или «нет». Подробно — [docs/mcp.md](docs/mcp.md).
258
326
 
259
327
  ```sh
260
- claude mcp add max -- max mcp
328
+ claude mcp add max -- max mcp # Claude Code
329
+ max mcp config # запись для Claude Desktop, Cursor и других — с полными путями
261
330
  ```
262
331
 
332
+ Команды сервера — `/catch-up`, `/review`, `/reply`, `/find` — готовые просьбы: агент знает, какие
333
+ инструменты вызвать и чего не делать.
334
+
263
335
  ### Ответы в JSON
264
336
 
265
337
  ```sh
@@ -303,7 +375,8 @@ max chats list --json
303
375
  ## Документация
304
376
 
305
377
  - [docs/installation.md](docs/installation.md) — установка, обновление, куда что ложится
306
- - [docs/usage.md](docs/usage.md) — вход, чтение, отправка, машинный режим
378
+ - [docs/bot.md](docs/bot.md) — бот: токен, несколько ботов, сообщения, чаты, список получателей, любая операция API
379
+ - [docs/usage.md](docs/usage.md) — личный аккаунт: вход, чтение, отправка, машинный режим
307
380
  - [docs/sessions.md](docs/sessions.md) — токен, хранилище паролей, профили
308
381
  - [docs/configuration.md](docs/configuration.md) — настройки, переменные, порядок разрешения
309
382
  - [docs/mcp.md](docs/mcp.md) — MCP-сервер: подключение, отправка, соединение с MAX
@@ -0,0 +1,23 @@
1
+ import { type CredentialSource, type KeyringStore } from "@leemour/cli-core";
2
+ export interface BotTokenStoreOptions {
3
+ profile: string;
4
+ env?: NodeJS.ProcessEnv;
5
+ keyring?: KeyringStore;
6
+ configDir?: string;
7
+ }
8
+ /**
9
+ * A bot token per profile, beside — never inside — the personal session: keyring account
10
+ * `bot:<profile>`, environment variable `MAX_BOT_TOKEN`, then a 0600 file (`NEED-295`).
11
+ */
12
+ export declare class BotTokenStore {
13
+ #private;
14
+ readonly profile: string;
15
+ constructor({ profile, env, keyring, configDir }: BotTokenStoreOptions);
16
+ read(): {
17
+ token: string;
18
+ source: CredentialSource;
19
+ } | undefined;
20
+ write(token: string): CredentialSource;
21
+ remove(): CredentialSource[];
22
+ }
23
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/bot/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,YAAY,EAGlB,MAAM,mBAAmB,CAAA;AAI1B,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,qBAAa,aAAa;;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IAIxB,YAAY,EAAE,OAAO,EAAE,GAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,oBAAoB,EAanF;IAED,IAAI,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,gBAAgB,CAAA;KAAE,GAAG,SAAS,CAG9D;IAED,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAErC;IAED,MAAM,IAAI,gBAAgB,EAAE,CAE3B;CACF"}
@@ -0,0 +1,36 @@
1
+ import { Credentials, pathsAreOverridden, resolvePaths, } from "@leemour/cli-core";
2
+ const APP = "max-cli";
3
+ /**
4
+ * A bot token per profile, beside — never inside — the personal session: keyring account
5
+ * `bot:<profile>`, environment variable `MAX_BOT_TOKEN`, then a 0600 file (`NEED-295`).
6
+ */
7
+ export class BotTokenStore {
8
+ profile;
9
+ #account;
10
+ #credentials;
11
+ constructor({ profile, env = process.env, keyring, configDir }) {
12
+ const paths = resolvePaths({ appName: APP, prefix: "MAX", env });
13
+ this.profile = profile;
14
+ this.#account = `bot:${profile}`;
15
+ this.#credentials = new Credentials({
16
+ configDir: configDir ?? paths.config,
17
+ service: APP,
18
+ envVar: "MAX_BOT_TOKEN",
19
+ isolated: pathsAreOverridden({ appName: APP, prefix: "MAX", env }),
20
+ ...(keyring ? { keyring } : {}),
21
+ env,
22
+ warn: (message) => process.stderr.write(`${message}\n`),
23
+ });
24
+ }
25
+ read() {
26
+ const stored = this.#credentials.read(this.#account);
27
+ return stored ? { token: stored.secret, source: stored.source } : undefined;
28
+ }
29
+ write(token) {
30
+ return this.#credentials.write(this.#account, token);
31
+ }
32
+ remove() {
33
+ return this.#credentials.remove(this.#account);
34
+ }
35
+ }
36
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/bot/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EAEX,kBAAkB,EAClB,YAAY,GACb,MAAM,mBAAmB,CAAA;AAE1B,MAAM,GAAG,GAAG,SAAS,CAAA;AASrB;;;GAGG;AACH,MAAM,OAAO,aAAa;IACf,OAAO,CAAQ;IACf,QAAQ,CAAQ;IAChB,YAAY,CAAa;IAElC,YAAY,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAwB;QAClF,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;QAChE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,QAAQ,GAAG,OAAO,OAAO,EAAE,CAAA;QAChC,IAAI,CAAC,YAAY,GAAG,IAAI,WAAW,CAAC;YAClC,SAAS,EAAE,SAAS,IAAI,KAAK,CAAC,MAAM;YACpC,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,eAAe;YACvB,QAAQ,EAAE,kBAAkB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;YAClE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,GAAG;YACH,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC;SACxD,CAAC,CAAA;IACJ,CAAC;IAED,IAAI;QACF,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACpD,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IAC7E,CAAC;IAED,KAAK,CAAC,KAAa;QACjB,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IACtD,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAChD,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ import type { ManifestOperation } from "@leemour/cli-core/codegen";
2
+ import type { Chat, Message } from "@leemour/cli-messaging";
3
+ import type { BotInfo as BotInfoType } from "./generated/types.js";
4
+ import { type CallInput, type TransportOptions } from "./transport.js";
5
+ /** Every operation of the committed schema, as the manifest describes it. */
6
+ export declare const botOperations: readonly ManifestOperation[];
7
+ /** The one door to the Bot API: generated operations stay behind it. */
8
+ export declare class BotApiClient {
9
+ #private;
10
+ constructor(options: TransportOptions);
11
+ me(): Promise<BotInfoType>;
12
+ chat(chatId: string): Promise<Chat>;
13
+ message(messageId: string, selfId?: string): Promise<Message>;
14
+ /** Newest last, as MAX returns them. */
15
+ messages(chatId: string, count: number, selfId?: string): Promise<Message[]>;
16
+ /** A message from any answer — a send's result, an update — decoded the same way as a read. */
17
+ decodeMessage(raw: unknown, selfId?: string): Message;
18
+ call(operation: ManifestOperation, input: CallInput): Promise<unknown>;
19
+ }
20
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/bot/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAClE,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAI3D,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAyB,MAAM,sBAAsB,CAAA;AAEzF,OAAO,EAAgB,KAAK,SAAS,EAAa,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAE/F,6EAA6E;AAC7E,eAAO,MAAM,aAAa,EAAE,SAAS,iBAAiB,EAAe,CAAA;AAUrE,wEAAwE;AACxE,qBAAa,YAAY;;IAGvB,YAAY,OAAO,EAAE,gBAAgB,EAEpC;IAEK,EAAE,IAAI,OAAO,CAAC,WAAW,CAAC,CAU/B;IAEK,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGxC;IAEK,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGlE;IAED,wCAAwC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAKjF;IAED,+FAA+F;IAC/F,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAEpD;IAED,IAAI,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAErE;CAyCF"}
@@ -0,0 +1,91 @@
1
+ import { CliError } from "@leemour/cli-core";
2
+ import * as v from "valibot";
3
+ import { operations } from "./generated/manifest.js";
4
+ import { BotInfo, Chat as ChatSchema, Message as MessageSchema } from "./generated/schemas.js";
5
+ import { toChat, toMessage } from "./map.js";
6
+ import { BotTransport, plainJson } from "./transport.js";
7
+ /** Every operation of the committed schema, as the manifest describes it. */
8
+ export const botOperations = operations;
9
+ const operationById = new Map(operations.map((operation) => [operation.id, operation]));
10
+ const required = (id) => {
11
+ const operation = operationById.get(id);
12
+ if (!operation)
13
+ throw new CliError("configuration_error", `the generated manifest has no operation ${id}`);
14
+ return operation;
15
+ };
16
+ /** The one door to the Bot API: generated operations stay behind it. */
17
+ export class BotApiClient {
18
+ #transport;
19
+ constructor(options) {
20
+ this.#transport = new BotTransport(options);
21
+ }
22
+ async me() {
23
+ const answer = await this.#transport.call(required("getMyInfo"));
24
+ const parsed = v.safeParse(BotInfo, answer);
25
+ if (!parsed.success) {
26
+ throw new CliError("invalid_response", "MAX answered getMyInfo in a shape this version does not know", {
27
+ operation: "getMyInfo",
28
+ fields: parsed.issues.map((issue) => v.getDotPath(issue) ?? "(root)"),
29
+ });
30
+ }
31
+ return parsed.output;
32
+ }
33
+ async chat(chatId) {
34
+ const answer = await this.#transport.call(required("getChat"), { path: { chatId } });
35
+ return toChat(this.#decode(ChatSchema, answer, "getChat"));
36
+ }
37
+ async message(messageId, selfId) {
38
+ const answer = await this.#transport.call(required("getMessageById"), { path: { messageId } });
39
+ return this.#message(answer, selfId);
40
+ }
41
+ /** Newest last, as MAX returns them. */
42
+ async messages(chatId, count, selfId) {
43
+ const answer = (await this.#transport.call(required("getMessages"), {
44
+ query: { chat_id: chatId, count: String(count) },
45
+ }));
46
+ return (answer?.messages ?? []).map((raw) => this.#message(raw, selfId));
47
+ }
48
+ /** A message from any answer — a send's result, an update — decoded the same way as a read. */
49
+ decodeMessage(raw, selfId) {
50
+ return this.#message(raw, selfId);
51
+ }
52
+ call(operation, input) {
53
+ return this.#transport.call(operation, input);
54
+ }
55
+ #decode(schema, answer, operation) {
56
+ const parsed = v.safeParse(schema, answer);
57
+ if (!parsed.success) {
58
+ throw new CliError("invalid_response", `MAX answered ${operation} in a shape this version does not know`, {
59
+ operation,
60
+ fields: parsed.issues.map((issue) => v.getDotPath(issue) ?? "(root)"),
61
+ });
62
+ }
63
+ return parsed.output;
64
+ }
65
+ /**
66
+ * One message MAX added something new to (an attachment type newer than the schema, `RISK-51`)
67
+ * still shows its text and time rather than failing the whole list.
68
+ */
69
+ #message(raw, selfId) {
70
+ const parsed = v.safeParse(MessageSchema, raw);
71
+ if (parsed.success)
72
+ return toMessage(parsed.output, selfId);
73
+ const loose = plainJson(raw);
74
+ return {
75
+ id: String(loose.body?.mid ?? "unknown"),
76
+ chatId: String(loose.recipient?.chat_id ?? "unknown"),
77
+ senderId: null,
78
+ senderName: null,
79
+ timestamp: new Date(Number(loose.timestamp ?? 0)).toISOString(),
80
+ editedAt: null,
81
+ text: loose.body?.text ?? "",
82
+ outgoing: null,
83
+ attachments: [],
84
+ replyTo: null,
85
+ forwardedFrom: null,
86
+ reactions: null,
87
+ providerMetadata: { unparsed: parsed.issues.map((issue) => v.getDotPath(issue) ?? "(root)") },
88
+ };
89
+ }
90
+ }
91
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/bot/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ManifestOperation } from "@leemour/cli-core/codegen";
2
+ export declare const operations: readonly ManifestOperation[];
3
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/bot/generated/manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAElE,eAAO,MAAM,UAAU,EAAE,SAAS,iBAAiB,EA4tClD,CAAA"}