@jungjaehoon/mama-os 0.78.0 → 0.79.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 (288) hide show
  1. package/CHANGELOG.md +311 -0
  2. package/README.md +38 -24
  3. package/db/migrations/002-model-runs-parent-index.sql +11 -0
  4. package/db/migrations/003-upkeep-settled.sql +15 -0
  5. package/dist/api/google-read-actions.d.ts +30 -0
  6. package/dist/api/google-read-actions.d.ts.map +1 -0
  7. package/dist/api/google-read-actions.js +256 -0
  8. package/dist/api/google-read-actions.js.map +1 -0
  9. package/dist/api/record-actions.d.ts.map +1 -1
  10. package/dist/api/record-actions.js +23 -5
  11. package/dist/api/record-actions.js.map +1 -1
  12. package/dist/api/report-handler.d.ts +0 -6
  13. package/dist/api/report-handler.d.ts.map +1 -1
  14. package/dist/api/report-handler.js +0 -54
  15. package/dist/api/report-handler.js.map +1 -1
  16. package/dist/api/security-events.d.ts +1 -1
  17. package/dist/api/security-events.d.ts.map +1 -1
  18. package/dist/api/security-events.js.map +1 -1
  19. package/dist/api/source-actions.d.ts +9 -0
  20. package/dist/api/source-actions.d.ts.map +1 -1
  21. package/dist/api/source-actions.js +49 -0
  22. package/dist/api/source-actions.js.map +1 -1
  23. package/dist/api/viewer-request-security.d.ts +14 -1
  24. package/dist/api/viewer-request-security.d.ts.map +1 -1
  25. package/dist/api/viewer-request-security.js +26 -3
  26. package/dist/api/viewer-request-security.js.map +1 -1
  27. package/dist/api/viewer-server.d.ts +7 -0
  28. package/dist/api/viewer-server.d.ts.map +1 -1
  29. package/dist/api/viewer-server.js +32 -0
  30. package/dist/api/viewer-server.js.map +1 -1
  31. package/dist/api/work-actions.d.ts +19 -2
  32. package/dist/api/work-actions.d.ts.map +1 -1
  33. package/dist/api/work-actions.js +15 -0
  34. package/dist/api/work-actions.js.map +1 -1
  35. package/dist/cli/commands/backup.d.ts +7 -6
  36. package/dist/cli/commands/backup.d.ts.map +1 -1
  37. package/dist/cli/commands/backup.js +44 -7
  38. package/dist/cli/commands/backup.js.map +1 -1
  39. package/dist/cli/commands/control.d.ts +22 -4
  40. package/dist/cli/commands/control.d.ts.map +1 -1
  41. package/dist/cli/commands/control.js +172 -11
  42. package/dist/cli/commands/control.js.map +1 -1
  43. package/dist/cli/commands/daemon.d.ts +13 -2
  44. package/dist/cli/commands/daemon.d.ts.map +1 -1
  45. package/dist/cli/commands/daemon.js +211 -5
  46. package/dist/cli/commands/daemon.js.map +1 -1
  47. package/dist/cli/commands/init-questions.d.ts +98 -0
  48. package/dist/cli/commands/init-questions.d.ts.map +1 -0
  49. package/dist/cli/commands/init-questions.js +420 -0
  50. package/dist/cli/commands/init-questions.js.map +1 -0
  51. package/dist/cli/commands/init-section.d.ts +13 -0
  52. package/dist/cli/commands/init-section.d.ts.map +1 -0
  53. package/dist/cli/commands/init-section.js +375 -0
  54. package/dist/cli/commands/init-section.js.map +1 -0
  55. package/dist/cli/commands/init.d.ts +56 -2
  56. package/dist/cli/commands/init.d.ts.map +1 -1
  57. package/dist/cli/commands/init.js +562 -351
  58. package/dist/cli/commands/init.js.map +1 -1
  59. package/dist/cli/commands/node-move.d.ts +20 -0
  60. package/dist/cli/commands/node-move.d.ts.map +1 -0
  61. package/dist/cli/commands/node-move.js +289 -0
  62. package/dist/cli/commands/node-move.js.map +1 -0
  63. package/dist/cli/commands/register-owner.d.ts +3 -0
  64. package/dist/cli/commands/register-owner.d.ts.map +1 -1
  65. package/dist/cli/commands/register-owner.js +2 -0
  66. package/dist/cli/commands/register-owner.js.map +1 -1
  67. package/dist/cli/commands/restore.d.ts +2 -0
  68. package/dist/cli/commands/restore.d.ts.map +1 -1
  69. package/dist/cli/commands/restore.js +7 -0
  70. package/dist/cli/commands/restore.js.map +1 -1
  71. package/dist/cli/commands/service.d.ts +16 -0
  72. package/dist/cli/commands/service.d.ts.map +1 -1
  73. package/dist/cli/commands/service.js +36 -8
  74. package/dist/cli/commands/service.js.map +1 -1
  75. package/dist/cli/commands/tools.d.ts +1 -1
  76. package/dist/cli/commands/tools.d.ts.map +1 -1
  77. package/dist/cli/commands/tools.js +8 -3
  78. package/dist/cli/commands/tools.js.map +1 -1
  79. package/dist/cli/commands/uninstall.d.ts.map +1 -1
  80. package/dist/cli/commands/uninstall.js +78 -5
  81. package/dist/cli/commands/uninstall.js.map +1 -1
  82. package/dist/cli/commands/update.d.ts +59 -0
  83. package/dist/cli/commands/update.d.ts.map +1 -0
  84. package/dist/cli/commands/update.js +948 -0
  85. package/dist/cli/commands/update.js.map +1 -0
  86. package/dist/cli/index.js +8 -4
  87. package/dist/cli/index.js.map +1 -1
  88. package/dist/cli/launch-files.d.ts +36 -0
  89. package/dist/cli/launch-files.d.ts.map +1 -1
  90. package/dist/cli/launch-files.js +94 -1
  91. package/dist/cli/launch-files.js.map +1 -1
  92. package/dist/cli/prompt.d.ts +2 -1
  93. package/dist/cli/prompt.d.ts.map +1 -1
  94. package/dist/cli/prompt.js +5 -2
  95. package/dist/cli/prompt.js.map +1 -1
  96. package/dist/cli/runtime/backup.d.ts +17 -1
  97. package/dist/cli/runtime/backup.d.ts.map +1 -1
  98. package/dist/cli/runtime/backup.js +32 -4
  99. package/dist/cli/runtime/backup.js.map +1 -1
  100. package/dist/cli/runtime/daemon-control.d.ts +92 -7
  101. package/dist/cli/runtime/daemon-control.d.ts.map +1 -1
  102. package/dist/cli/runtime/daemon-control.js +183 -8
  103. package/dist/cli/runtime/daemon-control.js.map +1 -1
  104. package/dist/cli/runtime/default-roots.d.ts +27 -0
  105. package/dist/cli/runtime/default-roots.d.ts.map +1 -0
  106. package/dist/cli/runtime/default-roots.js +61 -0
  107. package/dist/cli/runtime/default-roots.js.map +1 -0
  108. package/dist/cli/runtime/diagnostics.d.ts +25 -0
  109. package/dist/cli/runtime/diagnostics.d.ts.map +1 -1
  110. package/dist/cli/runtime/diagnostics.js +249 -63
  111. package/dist/cli/runtime/diagnostics.js.map +1 -1
  112. package/dist/cli/runtime/init-state.d.ts +20 -0
  113. package/dist/cli/runtime/init-state.d.ts.map +1 -0
  114. package/dist/cli/runtime/init-state.js +51 -0
  115. package/dist/cli/runtime/init-state.js.map +1 -0
  116. package/dist/cli/runtime/install-kind.d.ts +54 -0
  117. package/dist/cli/runtime/install-kind.d.ts.map +1 -0
  118. package/dist/cli/runtime/install-kind.js +164 -0
  119. package/dist/cli/runtime/install-kind.js.map +1 -0
  120. package/dist/cli/runtime/node-move-journal.d.ts +44 -0
  121. package/dist/cli/runtime/node-move-journal.d.ts.map +1 -0
  122. package/dist/cli/runtime/node-move-journal.js +48 -0
  123. package/dist/cli/runtime/node-move-journal.js.map +1 -0
  124. package/dist/cli/runtime/release-check.d.ts +94 -0
  125. package/dist/cli/runtime/release-check.d.ts.map +1 -0
  126. package/dist/cli/runtime/release-check.js +316 -0
  127. package/dist/cli/runtime/release-check.js.map +1 -0
  128. package/dist/cli/runtime/setup-page.d.ts +57 -0
  129. package/dist/cli/runtime/setup-page.d.ts.map +1 -0
  130. package/dist/cli/runtime/setup-page.js +266 -0
  131. package/dist/cli/runtime/setup-page.js.map +1 -0
  132. package/dist/cli/runtime/source-tools.d.ts +60 -0
  133. package/dist/cli/runtime/source-tools.d.ts.map +1 -0
  134. package/dist/cli/runtime/source-tools.js +170 -0
  135. package/dist/cli/runtime/source-tools.js.map +1 -0
  136. package/dist/cli/runtime/telegram-pairing.d.ts +73 -0
  137. package/dist/cli/runtime/telegram-pairing.d.ts.map +1 -0
  138. package/dist/cli/runtime/telegram-pairing.js +184 -0
  139. package/dist/cli/runtime/telegram-pairing.js.map +1 -0
  140. package/dist/cli/runtime/update-journal.d.ts +135 -0
  141. package/dist/cli/runtime/update-journal.d.ts.map +1 -0
  142. package/dist/cli/runtime/update-journal.js +144 -0
  143. package/dist/cli/runtime/update-journal.js.map +1 -0
  144. package/dist/cli/runtime/update-progress.d.ts +95 -0
  145. package/dist/cli/runtime/update-progress.d.ts.map +1 -0
  146. package/dist/cli/runtime/update-progress.js +154 -0
  147. package/dist/cli/runtime/update-progress.js.map +1 -0
  148. package/dist/cli/runtime/update-request.d.ts +58 -0
  149. package/dist/cli/runtime/update-request.d.ts.map +1 -0
  150. package/dist/cli/runtime/update-request.js +172 -0
  151. package/dist/cli/runtime/update-request.js.map +1 -0
  152. package/dist/connectors/calendar/index.d.ts +5 -1
  153. package/dist/connectors/calendar/index.d.ts.map +1 -1
  154. package/dist/connectors/calendar/index.js +19 -28
  155. package/dist/connectors/calendar/index.js.map +1 -1
  156. package/dist/connectors/chatwork/index.d.ts.map +1 -1
  157. package/dist/connectors/chatwork/index.js +7 -3
  158. package/dist/connectors/chatwork/index.js.map +1 -1
  159. package/dist/connectors/config-loader.d.ts +5 -0
  160. package/dist/connectors/config-loader.d.ts.map +1 -1
  161. package/dist/connectors/config-loader.js +8 -0
  162. package/dist/connectors/config-loader.js.map +1 -1
  163. package/dist/connectors/discord/index.d.ts.map +1 -1
  164. package/dist/connectors/discord/index.js +4 -3
  165. package/dist/connectors/discord/index.js.map +1 -1
  166. package/dist/connectors/drive/index.d.ts.map +1 -1
  167. package/dist/connectors/drive/index.js +15 -13
  168. package/dist/connectors/drive/index.js.map +1 -1
  169. package/dist/connectors/framework/gws-utils.d.ts +62 -0
  170. package/dist/connectors/framework/gws-utils.d.ts.map +1 -1
  171. package/dist/connectors/framework/gws-utils.js +133 -3
  172. package/dist/connectors/framework/gws-utils.js.map +1 -1
  173. package/dist/connectors/framework/types.d.ts +24 -0
  174. package/dist/connectors/framework/types.d.ts.map +1 -1
  175. package/dist/connectors/framework/types.js +9 -0
  176. package/dist/connectors/framework/types.js.map +1 -1
  177. package/dist/connectors/gmail/index.d.ts.map +1 -1
  178. package/dist/connectors/gmail/index.js +14 -13
  179. package/dist/connectors/gmail/index.js.map +1 -1
  180. package/dist/connectors/index.d.ts +4 -4
  181. package/dist/connectors/index.d.ts.map +1 -1
  182. package/dist/connectors/index.js +4 -10
  183. package/dist/connectors/index.js.map +1 -1
  184. package/dist/connectors/notion/index.d.ts.map +1 -1
  185. package/dist/connectors/notion/index.js +5 -3
  186. package/dist/connectors/notion/index.js.map +1 -1
  187. package/dist/connectors/sheets/index.d.ts.map +1 -1
  188. package/dist/connectors/sheets/index.js +17 -12
  189. package/dist/connectors/sheets/index.js.map +1 -1
  190. package/dist/connectors/slack/index.d.ts.map +1 -1
  191. package/dist/connectors/slack/index.js +9 -3
  192. package/dist/connectors/slack/index.js.map +1 -1
  193. package/dist/connectors/telegram/index.d.ts.map +1 -1
  194. package/dist/connectors/telegram/index.js +4 -3
  195. package/dist/connectors/telegram/index.js.map +1 -1
  196. package/dist/connectors/trello/index.d.ts +1 -1
  197. package/dist/connectors/trello/index.d.ts.map +1 -1
  198. package/dist/connectors/trello/index.js +10 -5
  199. package/dist/connectors/trello/index.js.map +1 -1
  200. package/dist/gateways/discord.d.ts +6 -0
  201. package/dist/gateways/discord.d.ts.map +1 -1
  202. package/dist/gateways/discord.js +38 -27
  203. package/dist/gateways/discord.js.map +1 -1
  204. package/dist/gateways/slack.d.ts +6 -0
  205. package/dist/gateways/slack.d.ts.map +1 -1
  206. package/dist/gateways/slack.js +38 -27
  207. package/dist/gateways/slack.js.map +1 -1
  208. package/dist/gateways/telegram-commands.d.ts +124 -0
  209. package/dist/gateways/telegram-commands.d.ts.map +1 -0
  210. package/dist/gateways/telegram-commands.js +131 -0
  211. package/dist/gateways/telegram-commands.js.map +1 -0
  212. package/dist/gateways/telegram.d.ts +20 -0
  213. package/dist/gateways/telegram.d.ts.map +1 -1
  214. package/dist/gateways/telegram.js +138 -34
  215. package/dist/gateways/telegram.js.map +1 -1
  216. package/dist/gateways/turn-contract.d.ts +11 -0
  217. package/dist/gateways/turn-contract.d.ts.map +1 -1
  218. package/dist/runtime/action-surface.d.ts +1 -1
  219. package/dist/runtime/action-surface.d.ts.map +1 -1
  220. package/dist/runtime/action-surface.js +10 -0
  221. package/dist/runtime/action-surface.js.map +1 -1
  222. package/dist/runtime/backend-security.d.ts +23 -2
  223. package/dist/runtime/backend-security.d.ts.map +1 -1
  224. package/dist/runtime/backend-security.js +50 -5
  225. package/dist/runtime/backend-security.js.map +1 -1
  226. package/dist/runtime/member-paths.d.ts +15 -7
  227. package/dist/runtime/member-paths.d.ts.map +1 -1
  228. package/dist/runtime/member-paths.js +64 -12
  229. package/dist/runtime/member-paths.js.map +1 -1
  230. package/dist/runtime/member-session.d.ts +4 -0
  231. package/dist/runtime/member-session.d.ts.map +1 -1
  232. package/dist/runtime/member-session.js +23 -2
  233. package/dist/runtime/member-session.js.map +1 -1
  234. package/dist/runtime/native-session.d.ts +2 -0
  235. package/dist/runtime/native-session.d.ts.map +1 -1
  236. package/dist/runtime/native-session.js +1 -0
  237. package/dist/runtime/native-session.js.map +1 -1
  238. package/dist/runtime/owner-runtime.d.ts +63 -1
  239. package/dist/runtime/owner-runtime.d.ts.map +1 -1
  240. package/dist/runtime/owner-runtime.js +180 -3
  241. package/dist/runtime/owner-runtime.js.map +1 -1
  242. package/dist/runtime/owner-system-prompt.d.ts.map +1 -1
  243. package/dist/runtime/owner-system-prompt.js +0 -1
  244. package/dist/runtime/owner-system-prompt.js.map +1 -1
  245. package/dist/runtime/principal-access.d.ts +2 -0
  246. package/dist/runtime/principal-access.d.ts.map +1 -1
  247. package/dist/runtime/principal-access.js +7 -0
  248. package/dist/runtime/principal-access.js.map +1 -1
  249. package/dist/runtime/principal-sessions.d.ts.map +1 -1
  250. package/dist/runtime/principal-sessions.js +8 -1
  251. package/dist/runtime/principal-sessions.js.map +1 -1
  252. package/dist/runtime/record-orders.d.ts.map +1 -1
  253. package/dist/runtime/record-orders.js +3 -29
  254. package/dist/runtime/record-orders.js.map +1 -1
  255. package/dist/runtime/report-scheduler.d.ts +9 -2
  256. package/dist/runtime/report-scheduler.d.ts.map +1 -1
  257. package/dist/runtime/report-scheduler.js +37 -10
  258. package/dist/runtime/report-scheduler.js.map +1 -1
  259. package/dist/runtime/stimulus-delivery.d.ts +3 -0
  260. package/dist/runtime/stimulus-delivery.d.ts.map +1 -1
  261. package/dist/runtime/stimulus-delivery.js +19 -3
  262. package/dist/runtime/stimulus-delivery.js.map +1 -1
  263. package/dist/runtime/tools-paths.d.ts +7 -0
  264. package/dist/runtime/tools-paths.d.ts.map +1 -1
  265. package/dist/runtime/tools-paths.js +11 -5
  266. package/dist/runtime/tools-paths.js.map +1 -1
  267. package/dist/runtime/upkeep-close.d.ts +17 -0
  268. package/dist/runtime/upkeep-close.d.ts.map +1 -0
  269. package/dist/runtime/upkeep-close.js +127 -0
  270. package/dist/runtime/upkeep-close.js.map +1 -0
  271. package/dist/runtime/upkeep-orders.d.ts +124 -0
  272. package/dist/runtime/upkeep-orders.d.ts.map +1 -0
  273. package/dist/runtime/upkeep-orders.js +310 -0
  274. package/dist/runtime/upkeep-orders.js.map +1 -0
  275. package/dist/runtime/upkeep-reconcile.d.ts +25 -0
  276. package/dist/runtime/upkeep-reconcile.d.ts.map +1 -0
  277. package/dist/runtime/upkeep-reconcile.js +231 -0
  278. package/dist/runtime/upkeep-reconcile.js.map +1 -0
  279. package/dist/runtime/upkeep-writeback.d.ts +22 -0
  280. package/dist/runtime/upkeep-writeback.d.ts.map +1 -0
  281. package/dist/runtime/upkeep-writeback.js +203 -0
  282. package/dist/runtime/upkeep-writeback.js.map +1 -0
  283. package/dist/utils/untrusted-content.d.ts.map +1 -1
  284. package/dist/utils/untrusted-content.js +8 -1
  285. package/dist/utils/untrusted-content.js.map +1 -1
  286. package/install/install.sh +457 -0
  287. package/install/node.json +9 -0
  288. package/package.json +3 -4
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UPDATE_REFUSED = exports.TELEGRAM_HOST_COMMANDS = void 0;
4
+ exports.hostCommand = hostCommand;
5
+ exports.helpText = helpText;
6
+ exports.whoamiText = whoamiText;
7
+ exports.startOverText = startOverText;
8
+ exports.stopText = stopText;
9
+ exports.updateText = updateText;
10
+ exports.updateGroupText = updateGroupText;
11
+ exports.statusText = statusText;
12
+ /**
13
+ * Commands the host answers itself, before any turn: the menu the bot registers and the list
14
+ * /help prints. Any other command text goes to MAMA as an ordinary message.
15
+ */
16
+ exports.TELEGRAM_HOST_COMMANDS = [
17
+ { command: 'whoami', description: 'Your Telegram ID and how MAMA knows you' },
18
+ { command: 'status', description: 'Whether MAMA is working, and on what' },
19
+ { command: 'stop', description: 'Stop the turn running in this conversation' },
20
+ { command: 'new', description: 'Start this conversation over' },
21
+ { command: 'update', description: 'Update MAMA to the latest release (owners)' },
22
+ { command: 'help', description: 'The commands MAMA answers itself' },
23
+ ];
24
+ /**
25
+ * The host command a message opens with; `other_bot` for a command addressed to another bot
26
+ * (`/status@other_bot`), which is not for MAMA at all; null for anything else, an unknown
27
+ * command included, which stays an ordinary message.
28
+ */
29
+ function hostCommand(message, botUsername) {
30
+ const first = message.entities?.[0];
31
+ if (!message.text || first?.type !== 'bot_command' || first.offset !== 0)
32
+ return null;
33
+ const [name, addressee] = message.text.slice(1, first.length).split('@', 2);
34
+ if (addressee !== undefined && addressee.toLowerCase() !== botUsername().toLowerCase())
35
+ return 'other_bot';
36
+ const command = name.toLowerCase();
37
+ return exports.TELEGRAM_HOST_COMMANDS.some((entry) => entry.command === command)
38
+ ? command
39
+ : null;
40
+ }
41
+ function helpText() {
42
+ return [
43
+ 'Commands MAMA answers itself, without a turn:',
44
+ ...exports.TELEGRAM_HOST_COMMANDS.map(({ command, description }) => `/${command}: ${description}`),
45
+ 'Anything else goes to MAMA as a message.',
46
+ ].join('\n');
47
+ }
48
+ function whoamiText(input) {
49
+ const lines = [
50
+ `Telegram ID: ${input.userId}`,
51
+ `MAMA knows you as ${input.owner ? 'an owner' : 'a member'} (${input.principalId}).`,
52
+ ];
53
+ if (!input.privateChat) {
54
+ const group = `This group (${input.chatId}) is ${input.commonChannel ? "MAMA's common channel" : 'a group MAMA admits'}`;
55
+ lines.push(input.owner
56
+ ? `${group}; your messages here run in the common session.`
57
+ : `${group}; your messages here run in your own conversation for this group.`);
58
+ }
59
+ return lines.join('\n');
60
+ }
61
+ function startOverText(result, target, owner) {
62
+ // A member's own conversation is reset with their group conversations (member-session.ts);
63
+ // an owner's group messages go to the common session instead, which this does not reset.
64
+ const memberDm = target.kind === 'member' && target.room === undefined;
65
+ if (result === 'busy')
66
+ return 'MAMA is still busy with work that would carry into a new conversation. Wait a moment, then send /new again.';
67
+ if (memberDm && !owner)
68
+ return 'Started over: your next message, here or in a group, begins a new conversation. What MAMA has saved stays.';
69
+ if (memberDm)
70
+ return 'Started over: your next message here begins a new conversation; the common group goes on until /new there. What MAMA has saved stays.';
71
+ return 'Started over: the next message here begins a new conversation. What MAMA has saved stays.';
72
+ }
73
+ function stopText(result, target) {
74
+ if (result === 'idle')
75
+ return 'Nothing is running in this conversation.';
76
+ if (result === 'starting')
77
+ return 'A turn here is starting or finishing. Send /stop again in a moment.';
78
+ return target.kind === 'common'
79
+ ? "Stopped the common session's running turn. A message it was answering is told it was interrupted; anything waiting still runs."
80
+ : 'Stopped the turn running in this conversation. Its message is told it was interrupted; messages sent after it still run.';
81
+ }
82
+ function updateText(result) {
83
+ if (result.kind === 'busy')
84
+ return result.source === 'job'
85
+ ? `An /update started at ${result.since} still runs; it reports to the chat it was started from. This one starts nothing.`
86
+ : `An update has held the install since ${result.since}; this /update starts nothing.`;
87
+ if (result.kind === 'repeated')
88
+ return 'This /update was already received and started an update. Send /update again for another.';
89
+ if (result.kind === 'checkout')
90
+ return [
91
+ '/update serves npm installs. This install is a checkout, which updates by git:',
92
+ ...result.steps,
93
+ ].join('\n');
94
+ if (result.kind === 'not_updatable')
95
+ return `/update cannot update this install: ${result.reason}`;
96
+ return result.to === null
97
+ ? `Updating ${result.from} to the latest release; progress follows.`
98
+ : `Updating ${result.from} → ${result.to}; progress follows.`;
99
+ }
100
+ /**
101
+ * What a group is told when the answer names paths (a checkout's steps, why an install cannot be
102
+ * updated): the full answer goes to the owner's DM, as /status keeps the owner's view there.
103
+ * `dm`: whether that DM send went out.
104
+ */
105
+ function updateGroupText(result, dm) {
106
+ const where = dm
107
+ ? 'the details are in your DM'
108
+ : 'MAMA could not send the details to your DM; send /update there';
109
+ return result.kind === 'checkout'
110
+ ? `This install updates by git, not /update; ${where}.`
111
+ : `/update cannot update this install; ${where}.`;
112
+ }
113
+ /** Who may run /update: an owner, in their own DM or the common channel. */
114
+ exports.UPDATE_REFUSED = 'Only an owner can run /update, in their own DM with MAMA or in the common group.';
115
+ function statusText(status) {
116
+ const lines = [
117
+ `MAMA ${status.version}, running since ${status.since}`,
118
+ `This conversation: ${status.conversationRunning ? 'a turn is running' : 'idle'}`,
119
+ ];
120
+ if (status.owner === undefined) {
121
+ lines.push(`Inputs not yet done: ${status.inputsWaiting}`);
122
+ return lines;
123
+ }
124
+ lines.push(`All conversations: ${status.owner.turnsRunning} turns running, ${status.inputsWaiting} inputs not yet done`);
125
+ const failing = status.owner.sources.filter((source) => !source.healthy);
126
+ if (status.owner.sources.length > 0)
127
+ lines.push(`Sources: ${status.owner.sources.length - failing.length} of ${status.owner.sources.length} polling` +
128
+ (failing.length > 0 ? `; failing: ${failing.map((source) => source.name).join(', ')}` : ''));
129
+ return lines;
130
+ }
131
+ //# sourceMappingURL=telegram-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram-commands.js","sourceRoot":"","sources":["../../src/gateways/telegram-commands.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import type { ActionResult, JudgmentAccess, PrincipalRepository } from '@jungjae
2
2
  import type { MemberSelection } from '../api/member-enrollment.js';
3
3
  import { BaseGateway } from './base-gateway.js';
4
4
  import type { OwnerHostExchangeInput, OwnerMessageInput, TurnIntake } from './turn-contract.js';
5
+ import { type TelegramHostCommandPort } from './telegram-commands.js';
5
6
  import { type OwnerMessageLedger, type TelegramMessageLedgerEntry } from './telegram-message-ledger.js';
6
7
  import { type MemberFileDeliveryContext, type TelegramFileDeliveryResult } from '../api/file-delivery.js';
7
8
  export interface TelegramGatewayConfig {
@@ -30,6 +31,8 @@ export interface TelegramGatewayOptions {
30
31
  onMemberSelection?: (selection: MemberSelection) => Promise<ActionResult>;
31
32
  /** Store the final transport receipt as history, outside the owner-message intake. */
32
33
  recordMemberSelection?: (exchange: OwnerHostExchangeInput) => void;
34
+ /** The commands the host answers before any turn (/status, /new). */
35
+ hostCommands: TelegramHostCommandPort;
33
36
  }
34
37
  /** Telegram personal/common ingress and its durable response transport. */
35
38
  export declare class TelegramGateway extends BaseGateway {
@@ -50,6 +53,7 @@ export declare class TelegramGateway extends BaseGateway {
50
53
  private stopIntake;
51
54
  private intakeStopped;
52
55
  private readonly enrollmentCompletions;
56
+ private readonly commandAnswers;
53
57
  private readonly activePresenters;
54
58
  private readonly recentMessageIds;
55
59
  private readonly activeChat;
@@ -57,6 +61,7 @@ export declare class TelegramGateway extends BaseGateway {
57
61
  private readonly pendingEnrollments;
58
62
  private readonly onMemberSelection?;
59
63
  private readonly recordMemberSelection?;
64
+ private readonly hostCommands;
60
65
  private bot;
61
66
  private lastError;
62
67
  private lastMessageAt;
@@ -92,6 +97,14 @@ export declare class TelegramGateway extends BaseGateway {
92
97
  private requireAllowedChat;
93
98
  private handleMessage;
94
99
  private handleMessageInput;
100
+ /** Answer a host command in the chat it came from; no turn and no stored message. */
101
+ private answerHostCommand;
102
+ /**
103
+ * /update: an owner in their DM or the common channel; an owner in another group is refused
104
+ * too, since its members would read the progress. An answer that names paths goes to the
105
+ * owner's DM, and the group is told so.
106
+ */
107
+ private answerUpdate;
95
108
  private acceptMessage;
96
109
  /** Host preparation of a transport-verified envelope accepted while the member was retired. */
97
110
  prepareDeferredMemberInput(principalId: string, input: OwnerMessageInput): Promise<OwnerMessageInput>;
@@ -99,6 +112,13 @@ export declare class TelegramGateway extends BaseGateway {
99
112
  private createResponsePresenter;
100
113
  private deliverReadyEntry;
101
114
  recoverPendingResponses(): Promise<void>;
115
+ /**
116
+ * Recover one owner message as startup recovery does, for an input parked uncertain while the
117
+ * daemon runs (a turn stopped with /stop, or timed out): every other message still in flight
118
+ * keeps its turn and its answer.
119
+ */
120
+ recoverResponse(sourceRef: string): Promise<void>;
121
+ private recoverEntry;
102
122
  private sendMessageNow;
103
123
  private deliverOutboundEntry;
104
124
  private runInChatQueue;
@@ -1 +1 @@
1
- {"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/gateways/telegram.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/gateways/telegram.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ const node_fs_1 = require("node:fs");
10
10
  const node_path_1 = require("node:path");
11
11
  const grammy_1 = require("grammy");
12
12
  const base_gateway_js_1 = require("./base-gateway.js");
13
+ const telegram_commands_js_1 = require("./telegram-commands.js");
13
14
  const telegram_text_entities_js_1 = require("./telegram-text-entities.js");
14
15
  const telegram_format_js_1 = require("./telegram-format.js");
15
16
  const telegram_message_ledger_js_1 = require("./telegram-message-ledger.js");
@@ -89,6 +90,7 @@ class TelegramGateway extends base_gateway_js_1.BaseGateway {
89
90
  this.stopIntake = () => resolve(undefined);
90
91
  });
91
92
  enrollmentCompletions = new Set();
93
+ commandAnswers = new Set();
92
94
  activePresenters = new Map();
93
95
  recentMessageIds = new Map();
94
96
  activeChat = new node_async_hooks_1.AsyncLocalStorage();
@@ -96,6 +98,7 @@ class TelegramGateway extends base_gateway_js_1.BaseGateway {
96
98
  pendingEnrollments = new Map();
97
99
  onMemberSelection;
98
100
  recordMemberSelection;
101
+ hostCommands;
99
102
  bot = null;
100
103
  lastError = null;
101
104
  lastMessageAt;
@@ -110,6 +113,7 @@ class TelegramGateway extends base_gateway_js_1.BaseGateway {
110
113
  this.principalPaths = options.principalPaths;
111
114
  this.onMemberSelection = options.onMemberSelection;
112
115
  this.recordMemberSelection = options.recordMemberSelection;
116
+ this.hostCommands = options.hostCommands;
113
117
  this.config = {
114
118
  enabled: options.config?.enabled ?? true,
115
119
  allowedChats: options.config?.allowedChats ?? [],
@@ -159,6 +163,17 @@ class TelegramGateway extends base_gateway_js_1.BaseGateway {
159
163
  console.error(`telegram handler failed error=${this.lastError}`);
160
164
  });
161
165
  await this.bot.init();
166
+ // The menu only lists the commands; they are answered whether or not it is registered,
167
+ // so a failed registration is logged and the gateway runs on.
168
+ const commands = telegram_commands_js_1.TELEGRAM_HOST_COMMANDS.map(({ command, description }) => ({
169
+ command,
170
+ description,
171
+ }));
172
+ for (const type of ['all_private_chats', 'all_group_chats']) {
173
+ await this.bot.api.setMyCommands(commands, { scope: { type } }).catch((error) => {
174
+ console.error(`telegram command menu failed scope=${type} error=${telegramErrorMessage(error)}`);
175
+ });
176
+ }
162
177
  this.connected = true;
163
178
  this.lastError = null;
164
179
  this.emitEvent({ type: 'connected', source: 'telegram', timestamp: new Date() });
@@ -196,6 +211,7 @@ class TelegramGateway extends base_gateway_js_1.BaseGateway {
196
211
  async drain() {
197
212
  await super.drain();
198
213
  await Promise.allSettled([...this.enrollmentCompletions]);
214
+ await Promise.allSettled([...this.commandAnswers]);
199
215
  await Promise.allSettled([...this.chatTails.values()]);
200
216
  }
201
217
  async stop() {
@@ -563,6 +579,17 @@ class TelegramGateway extends base_gateway_js_1.BaseGateway {
563
579
  return;
564
580
  }
565
581
  const principalId = principal.principalId;
582
+ // A host command is answered now, ahead of any intake waiting in this chat.
583
+ const command = (0, telegram_commands_js_1.hostCommand)(message, () => this.bot.botInfo.username);
584
+ if (command === 'other_bot')
585
+ return;
586
+ if (command !== null) {
587
+ // /new may wait for a member to be served; polling admits other updates meanwhile.
588
+ const answer = this.answerHostCommand(message, command, principalId).catch((error) => this.log(`telegram host command reply failed command=${command} error=${telegramErrorMessage(error)}`));
589
+ this.commandAnswers.add(answer);
590
+ void answer.finally(() => this.commandAnswers.delete(answer));
591
+ return;
592
+ }
566
593
  const recorded = this.messageLedger.get(sourceMessageRef(chatId, message.message_id));
567
594
  const memberRoom = !privateChat && (recorded ? recorded.principalId !== undefined : !this.ownerAllowed(userId));
568
595
  const selectedIntake = () => privateChat || memberRoom
@@ -612,6 +639,71 @@ class TelegramGateway extends base_gateway_js_1.BaseGateway {
612
639
  }
613
640
  await this.acceptMessage(message, principalId, intake);
614
641
  }
642
+ /** Answer a host command in the chat it came from; no turn and no stored message. */
643
+ async answerHostCommand(message, command, principalId) {
644
+ const chatId = String(message.chat.id);
645
+ const userId = String(message.from.id);
646
+ const privateChat = message.chat.type === 'private';
647
+ const owner = this.ownerAllowed(userId);
648
+ // Owners in the common group speak in the common session; everyone else in their own.
649
+ const target = !privateChat && owner
650
+ ? { kind: 'common' }
651
+ : { kind: 'member', principalId, ...(privateChat ? {} : { room: chatId }) };
652
+ let text;
653
+ try {
654
+ if (command === 'help')
655
+ text = (0, telegram_commands_js_1.helpText)();
656
+ else if (command === 'whoami')
657
+ text = (0, telegram_commands_js_1.whoamiText)({
658
+ userId,
659
+ chatId,
660
+ privateChat,
661
+ commonChannel: chatId === this.config.ownerChatId,
662
+ principalId,
663
+ owner,
664
+ });
665
+ else if (command === 'status')
666
+ // Everyone in a group reads the reply, so the owner's view of every conversation stays
667
+ // in the owner's DM.
668
+ text = (0, telegram_commands_js_1.statusText)(await this.hostCommands.status(target, owner && privateChat)).join('\n');
669
+ else if (command === 'stop')
670
+ text = (0, telegram_commands_js_1.stopText)(await this.hostCommands.stopTurn(target), target);
671
+ else if (command === 'update')
672
+ text = await this.answerUpdate(message, owner, privateChat);
673
+ else
674
+ text = (0, telegram_commands_js_1.startOverText)(await this.hostCommands.startOver(target), target, owner);
675
+ }
676
+ catch (error) {
677
+ this.log(`telegram host command failed command=${command} error=${telegramErrorMessage(error)}`);
678
+ text = `MAMA could not answer /${command}; its log has the error.`;
679
+ }
680
+ await this.bot.api.sendMessage(Number(chatId), text, {
681
+ reply_parameters: { message_id: message.message_id, allow_sending_without_reply: true },
682
+ });
683
+ this.log(`telegram host command=${command} chat=${privateChat ? 'private' : 'group'}`);
684
+ }
685
+ /**
686
+ * /update: an owner in their DM or the common channel; an owner in another group is refused
687
+ * too, since its members would read the progress. An answer that names paths goes to the
688
+ * owner's DM, and the group is told so.
689
+ */
690
+ async answerUpdate(message, owner, privateChat) {
691
+ const chatId = String(message.chat.id);
692
+ if (!owner || (!privateChat && chatId !== this.config.ownerChatId))
693
+ return telegram_commands_js_1.UPDATE_REFUSED;
694
+ const result = await this.hostCommands.update({ chatId, messageId: message.message_id });
695
+ if (privateChat || (result.kind !== 'checkout' && result.kind !== 'not_updatable'))
696
+ return (0, telegram_commands_js_1.updateText)(result);
697
+ let dm = true;
698
+ try {
699
+ await this.bot.api.sendMessage(message.from.id, (0, telegram_commands_js_1.updateText)(result));
700
+ }
701
+ catch (error) {
702
+ dm = false;
703
+ this.log(`telegram /update details not sent to DM error=${telegramErrorMessage(error)}`);
704
+ }
705
+ return (0, telegram_commands_js_1.updateGroupText)(result, dm);
706
+ }
615
707
  async acceptMessage(message, principalId, intake, queuedClaim) {
616
708
  const chatId = String(message.chat.id);
617
709
  const privateChat = message.chat.type === 'private';
@@ -828,45 +920,57 @@ class TelegramGateway extends base_gateway_js_1.BaseGateway {
828
920
  }, true);
829
921
  }
830
922
  async recoverPendingResponses() {
831
- for (const entry of this.messageLedger.listUndelivered()) {
832
- try {
833
- if (entry.deliveryUncertain) {
834
- this.log(`telegram delivery requires reconciliation key=${entry.key} state=${entry.state} next_chunk_index=${entry.nextChunkIndex ?? 0}`);
835
- continue;
836
- }
837
- if (entry.key.startsWith('outbound:') && entry.state === 'ready') {
838
- // Personal turn recovery belongs to mailbox reconciliation, which checks the current person
839
- // and input before sending. Gateway startup cannot establish that authority.
840
- if (entry.idempotencyKey && (0, personal_turns_js_1.isPersonalTurnTextKey)(entry.idempotencyKey))
841
- continue;
842
- const chatId = entry.deliveryTarget?.slice('telegram:'.length);
843
- if (!entry.deliveryTarget?.startsWith('telegram:') || !chatId) {
844
- throw new Error('Telegram outbound entry has no valid destination');
845
- }
846
- if (!this.config.allowedChats?.includes(chatId)) {
847
- const recipient = this.registry.resolveByExternal('telegram', 'private', chatId);
848
- if (recipient?.kind !== 'member' || recipient.status !== 'active')
849
- continue;
850
- }
851
- await this.runInChatQueue(chatId, () => this.deliverOutboundEntry(entry.key, chatId));
852
- continue;
853
- }
854
- if (!entry.key.startsWith('telegram:'))
855
- continue;
856
- const intake = await this.responseIntake(entry.key);
857
- if (entry.state === 'ready' && entry.response !== undefined) {
858
- await this.deliverReadyEntry(entry.key);
859
- continue;
923
+ for (const entry of this.messageLedger.listUndelivered())
924
+ await this.recoverEntry(entry);
925
+ }
926
+ /**
927
+ * Recover one owner message as startup recovery does, for an input parked uncertain while the
928
+ * daemon runs (a turn stopped with /stop, or timed out): every other message still in flight
929
+ * keeps its turn and its answer.
930
+ */
931
+ async recoverResponse(sourceRef) {
932
+ const entry = this.messageLedger.get(sourceRef);
933
+ if (entry && entry.state !== 'delivered')
934
+ await this.recoverEntry(entry);
935
+ }
936
+ async recoverEntry(entry) {
937
+ try {
938
+ if (entry.deliveryUncertain) {
939
+ this.log(`telegram delivery requires reconciliation key=${entry.key} state=${entry.state} next_chunk_index=${entry.nextChunkIndex ?? 0}`);
940
+ return;
941
+ }
942
+ if (entry.key.startsWith('outbound:') && entry.state === 'ready') {
943
+ // Personal turn recovery belongs to mailbox reconciliation, which checks the current person
944
+ // and input before sending. Gateway startup cannot establish that authority.
945
+ if (entry.idempotencyKey && (0, personal_turns_js_1.isPersonalTurnTextKey)(entry.idempotencyKey))
946
+ return;
947
+ const chatId = entry.deliveryTarget?.slice('telegram:'.length);
948
+ if (!entry.deliveryTarget?.startsWith('telegram:') || !chatId) {
949
+ throw new Error('Telegram outbound entry has no valid destination');
860
950
  }
861
- if (entry.state === 'processing' && !intake.isPending?.(entry.key)) {
862
- await this.interruptResponse(entry.key);
951
+ if (!this.config.allowedChats?.includes(chatId)) {
952
+ const recipient = this.registry.resolveByExternal('telegram', 'private', chatId);
953
+ if (recipient?.kind !== 'member' || recipient.status !== 'active')
954
+ return;
863
955
  }
956
+ await this.runInChatQueue(chatId, () => this.deliverOutboundEntry(entry.key, chatId));
957
+ return;
864
958
  }
865
- catch (error) {
866
- // Delivery already recorded its progress; one entry must not keep polling from starting.
867
- this.log(`telegram recovery failed key=${entry.key} error=${telegramErrorMessage(error)}`);
959
+ if (!entry.key.startsWith('telegram:'))
960
+ return;
961
+ const intake = await this.responseIntake(entry.key);
962
+ if (entry.state === 'ready' && entry.response !== undefined) {
963
+ await this.deliverReadyEntry(entry.key);
964
+ return;
965
+ }
966
+ if (entry.state === 'processing' && !intake.isPending?.(entry.key)) {
967
+ await this.interruptResponse(entry.key);
868
968
  }
869
969
  }
970
+ catch (error) {
971
+ // Delivery already recorded its progress; one entry must not keep polling from starting.
972
+ this.log(`telegram recovery failed key=${entry.key} error=${telegramErrorMessage(error)}`);
973
+ }
870
974
  }
871
975
  async sendMessageNow(chatId, text, idempotencyKey) {
872
976
  if (!this.bot)