@jungjaehoon/mama-os 0.78.0 → 0.79.1

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 +341 -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 +110 -0
  48. package/dist/cli/commands/init-questions.d.ts.map +1 -0
  49. package/dist/cli/commands/init-questions.js +445 -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 +439 -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 +123 -15
  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 +250 -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,266 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultOpenRun = exports.SETUP_PAGE_MS = void 0;
4
+ exports.openSetupPage = openSetupPage;
5
+ const node_child_process_1 = require("node:child_process");
6
+ const node_crypto_1 = require("node:crypto");
7
+ const node_fs_1 = require("node:fs");
8
+ const node_http_1 = require("node:http");
9
+ const node_os_1 = require("node:os");
10
+ const node_path_1 = require("node:path");
11
+ const node_url_1 = require("node:url");
12
+ const viewer_request_security_js_1 = require("../../api/viewer-request-security.js");
13
+ const prompt_js_1 = require("../prompt.js");
14
+ /**
15
+ * The setup page (install.md, W2.4.5b): a page on this machine, served by the running command,
16
+ * where the person enters what must not pass through the conversation or a command line, one
17
+ * named field after another. It listens on 127.0.0.1 at a path of 32 random bytes. Loopback is
18
+ * shared by every account on the machine and `ps` shows every process's arguments, so the URL
19
+ * goes only into a redirect file this account alone can read, which the browser opens: it is
20
+ * never printed and never an argument.
21
+ */
22
+ /** As long as /bind's wait (telegram-pairing.ts) and Codex's device code. */
23
+ exports.SETUP_PAGE_MS = 15 * 60_000;
24
+ /** One form holds one field; the page reads a body into memory, and a larger one is not a form. */
25
+ const BODY_LIMIT = 16 * 1024;
26
+ const defaultOpenRun = (command, args) => new Promise((resolve, reject) => {
27
+ const child = (0, node_child_process_1.spawn)(command, args, { stdio: 'ignore' });
28
+ child.once('error', reject);
29
+ child.once('spawn', () => {
30
+ // A browser left running does not keep setup from exiting.
31
+ child.unref();
32
+ resolve({
33
+ exit: new Promise((exited) => child.once('exit', (status) => exited(status ?? 1))),
34
+ });
35
+ });
36
+ });
37
+ exports.defaultOpenRun = defaultOpenRun;
38
+ /** HH:MM on this machine's clock, as the person reads it. */
39
+ function clock(ms) {
40
+ return new Date(ms).toTimeString().slice(0, 5);
41
+ }
42
+ function escape(text) {
43
+ return text.replace(/[&<>"']/g, (character) => `&#${character.charCodeAt(0)};`);
44
+ }
45
+ /** The whole page, with nothing loaded from anywhere else. */
46
+ function html(body) {
47
+ return `<!doctype html>
48
+ <html lang="en">
49
+ <head>
50
+ <meta charset="utf-8">
51
+ <meta name="viewport" content="width=device-width, initial-scale=1">
52
+ <title>MAMA setup</title>
53
+ <style>
54
+ body { font: 16px/1.5 system-ui, sans-serif; max-width: 34rem; margin: 3rem auto; padding: 0 1rem; color: #1f1f1f; background: #fff; }
55
+ input { font: inherit; width: 100%; box-sizing: border-box; padding: 0.5rem; margin: 0.25rem 0 0.75rem; }
56
+ button { font: inherit; padding: 0.5rem 1rem; }
57
+ .refused { color: #a40000; }
58
+ </style>
59
+ </head>
60
+ <body>
61
+ <h1>MAMA setup</h1>
62
+ ${body}
63
+ </body>
64
+ </html>
65
+ `;
66
+ }
67
+ /**
68
+ * The body as text; `too long` past BODY_LIMIT, whose body is read through and dropped; `gone`
69
+ * when the client went away before sending all of it, which leaves the page as it was.
70
+ */
71
+ function readBody(req) {
72
+ return new Promise((resolve) => {
73
+ const chunks = [];
74
+ let size = 0;
75
+ req.on('data', (chunk) => {
76
+ size += chunk.length;
77
+ if (size <= BODY_LIMIT)
78
+ chunks.push(chunk);
79
+ });
80
+ req.on('end', () => resolve(size > BODY_LIMIT ? 'too long' : Buffer.concat(chunks).toString('utf8')));
81
+ req.on('error', () => resolve('gone'));
82
+ req.on('close', () => {
83
+ if (!req.complete)
84
+ resolve('gone');
85
+ });
86
+ });
87
+ }
88
+ /**
89
+ * Serve the page for `fields`, in order, and open it in the browser. Each field is taken once its
90
+ * check accepts it; after the last, the page shows what that check said and stops.
91
+ */
92
+ async function openSetupPage(options) {
93
+ const { fields, write } = options;
94
+ const nonce = (0, node_crypto_1.randomBytes)(32).toString('base64url');
95
+ const path = Buffer.from(`/${nonce}`);
96
+ const lifetimeMs = options.lifetimeMs ?? exports.SETUP_PAGE_MS;
97
+ const deadline = Date.now() + lifetimeMs;
98
+ const until = clock(deadline);
99
+ let index = 0;
100
+ /** What the page said when the last field was taken, shown above the next one. */
101
+ let notice;
102
+ let checking = false;
103
+ let closed = false;
104
+ let folder;
105
+ const sockets = new Set();
106
+ /** Connections whose request reached a check: their answer comes once the check settles. */
107
+ const answering = new Set();
108
+ let stop;
109
+ const stopped = new Promise((_resolve, reject) => {
110
+ stop = reject;
111
+ });
112
+ // The caller awaits it while it waits on the page; once nothing does, a stop is no unhandled
113
+ // rejection.
114
+ stopped.catch(() => { });
115
+ const close = () => {
116
+ if (closed)
117
+ return;
118
+ closed = true;
119
+ clearTimeout(timer);
120
+ server.close();
121
+ // Any other connection goes now, a half-sent request included: server.close() would wait
122
+ // for it, and setup would never exit.
123
+ for (const socket of sockets)
124
+ if (!answering.has(socket))
125
+ socket.destroy();
126
+ if (folder !== undefined)
127
+ (0, node_fs_1.rmSync)(folder, { recursive: true, force: true });
128
+ write('setup page closed');
129
+ };
130
+ const form = (field, said, refusal) => html([
131
+ said === undefined ? '' : `<p>${escape(said)}</p>`,
132
+ refusal === undefined ? '' : `<p class="refused" role="alert">${escape(refusal)}</p>`,
133
+ '<form method="post" autocomplete="off">',
134
+ `<label for="${escape(field.name)}">${escape(field.label)}</label>`,
135
+ `<input id="${escape(field.name)}" name="${escape(field.name)}" type="text" autocomplete="off" required autofocus${field.secret ? ' spellcheck="false" autocorrect="off" autocapitalize="off"' : ''}>`,
136
+ '<button type="submit">Continue</button>',
137
+ '</form>',
138
+ `<p>This page closes at ${until}.</p>`,
139
+ ]
140
+ .filter(Boolean)
141
+ .join('\n'));
142
+ const send = (res, status, body, headers = {}) => {
143
+ res.writeHead(status, {
144
+ 'Content-Type': 'text/html; charset=utf-8',
145
+ // The browser keeps no copy once the server stops, and tells no other host the URL.
146
+ 'Cache-Control': 'no-store',
147
+ 'Referrer-Policy': 'no-referrer',
148
+ Connection: 'close',
149
+ ...headers,
150
+ });
151
+ res.end(body);
152
+ };
153
+ const handle = async (req, res) => {
154
+ // A rebinding site sends its own name; an SSH forward on another local port still works.
155
+ if (!(0, viewer_request_security_js_1.isAllowedHost)(req))
156
+ return send(res, 421, html('<p>This page answers only at 127.0.0.1 or localhost.</p>'));
157
+ // The nonce is what keeps other accounts on this machine out, so it is compared in constant
158
+ // time. A GET with a query is another path: nothing entered in a URL is taken.
159
+ const requested = Buffer.from(req.url ?? '');
160
+ if (closed || requested.length !== path.length || !(0, node_crypto_1.timingSafeEqual)(requested, path))
161
+ return send(res, 404, html('<p>Not found.</p>'));
162
+ const field = fields[index];
163
+ if (req.method === 'GET')
164
+ return send(res, 200, form(field, notice));
165
+ if (req.method !== 'POST')
166
+ return send(res, 405, html('<p>Not allowed.</p>'), { Allow: 'GET, POST' });
167
+ // A check can take seconds (the pairing code's answer waits for the bot's poll); a second
168
+ // submission meanwhile would answer a question nobody asks.
169
+ if (checking)
170
+ return send(res, 409, form(field, notice, 'The last entry is still being checked; wait for its answer.'));
171
+ checking = true;
172
+ try {
173
+ const body = await readBody(req);
174
+ if (body === 'gone')
175
+ return;
176
+ if (body === 'too long')
177
+ return send(res, 413, form(field, notice, 'That entry is too long for this page.'));
178
+ answering.add(req.socket);
179
+ res.once('close', () => answering.delete(req.socket));
180
+ let said;
181
+ try {
182
+ said = await field.check(new URLSearchParams(body).get(field.name) ?? '');
183
+ }
184
+ catch (error) {
185
+ if (!(error instanceof prompt_js_1.CliInputError))
186
+ throw error;
187
+ // The setup stopped while this entry was checked: its sentence, and no form to send again.
188
+ if (closed)
189
+ return send(res, 200, html(`<p>${escape(error.message)}</p><p>This page has closed.</p>`));
190
+ return send(res, 200, form(field, notice, error.message));
191
+ }
192
+ if (closed)
193
+ return send(res, 200, html(`<p>${escape(said)}</p><p>This page has closed.</p>`));
194
+ index += 1;
195
+ notice = said;
196
+ if (index < fields.length)
197
+ return send(res, 200, form(fields[index], said));
198
+ // One value per field, then the page stops: a later submission cannot change one.
199
+ send(res, 200, html(`<p>${escape(said)}</p>`));
200
+ close();
201
+ }
202
+ finally {
203
+ checking = false;
204
+ }
205
+ };
206
+ const server = (0, node_http_1.createServer)((req, res) => {
207
+ handle(req, res).catch((error) => {
208
+ if (!res.headersSent)
209
+ send(res, 500, html("<p>Setup stopped; the command's output says why.</p>"));
210
+ close();
211
+ stop(error);
212
+ });
213
+ });
214
+ server.on('connection', (socket) => {
215
+ sockets.add(socket);
216
+ socket.once('close', () => sockets.delete(socket));
217
+ });
218
+ await new Promise((resolve, reject) => {
219
+ server.once('error', reject);
220
+ server.listen(0, '127.0.0.1', () => {
221
+ server.off('error', reject);
222
+ resolve();
223
+ });
224
+ }).catch((error) => {
225
+ throw new prompt_js_1.CliInputError(`The setup page could not listen on 127.0.0.1 (${error.code ?? error.message}); a sandbox may forbid it. Let this command listen on localhost, or run it outside the sandbox.`);
226
+ });
227
+ const url = `http://127.0.0.1:${server.address().port}/${nonce}`;
228
+ let file;
229
+ try {
230
+ // mkdtemp makes the folder 0700 for this account; the file is 0600 in it.
231
+ folder = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'mama-setup-'));
232
+ file = (0, node_path_1.join)(folder, 'open.html');
233
+ (0, node_fs_1.writeFileSync)(file, `<!doctype html>\n<meta charset="utf-8">\n<meta name="referrer" content="no-referrer">\n<meta http-equiv="refresh" content="0;url=${url}">\n<title>MAMA setup</title>\n<p><a href="${url}">Open the MAMA setup page</a></p>\n`, { flag: 'wx', mode: 0o600 });
234
+ }
235
+ catch (error) {
236
+ server.close();
237
+ if (folder !== undefined)
238
+ (0, node_fs_1.rmSync)(folder, { recursive: true, force: true });
239
+ throw error;
240
+ }
241
+ // A forgotten setup does not keep a page that takes a secret. Nothing calls close() before this
242
+ // line runs: a request is handled only once this function awaits the opener.
243
+ const timer = setTimeout(() => {
244
+ close();
245
+ stop(new prompt_js_1.CliInputError(`the setup page expired at ${until}; nothing was written`));
246
+ }, lifetimeMs);
247
+ const command = options.platform === 'darwin' ? 'open' : 'xdg-open';
248
+ // The file's path holds no secret: it is the way in when no browser opened.
249
+ const wayIn = `open ${(0, node_url_1.pathToFileURL)(file).href} in the browser; it closes at ${until}`;
250
+ try {
251
+ const { exit } = await (options.openRun ?? exports.defaultOpenRun)(command, [file]);
252
+ write(`setup page: opened in the browser from ${file}; it closes at ${until}`);
253
+ void exit.then((status) => {
254
+ if (status !== 0 && !closed)
255
+ write(`setup page: ${command} exited ${status}, so the browser may not have opened; ${wayIn}`);
256
+ });
257
+ }
258
+ catch (error) {
259
+ const failure = error.code === 'ENOENT'
260
+ ? `${command} is not installed`
261
+ : `${command} failed: ${error.message}`;
262
+ write(`setup page: the browser did not open (${failure}); ${wayIn}`);
263
+ }
264
+ return { stopped, close };
265
+ }
266
+ //# sourceMappingURL=setup-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-page.js","sourceRoot":"","sources":["../../../src/cli/runtime/setup-page.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { AuthRequirement, SourceTool } from '../../connectors/framework/types.js';
2
+ /** What the service runs a source's tool with. */
3
+ export interface ServiceSight {
4
+ /** The folders its PATH names, in order. */
5
+ readonly path: string[];
6
+ /** The Node start.sh runs; `null` when its exec line names none. */
7
+ readonly nodePath: string | null;
8
+ /** What start.sh exports after loading auth.env; none before start.sh is written. */
9
+ readonly exports: Record<string, string>;
10
+ }
11
+ /**
12
+ * start.sh's PATH and Node when it exists; before it does (a setup whose service step has not
13
+ * run), what `mama service install` will write from this shell.
14
+ */
15
+ export declare function serviceSight(root: string, home: string, platform: NodeJS.Platform, planned: () => {
16
+ nodePath: string;
17
+ executablePaths: string[];
18
+ }, toolDirectoryExists?: (path: string) => boolean): ServiceSight;
19
+ export interface SourceToolReport {
20
+ readonly tool: SourceTool;
21
+ /** The sources being enabled that run it. */
22
+ readonly sources: string[];
23
+ /** Where the service finds it; `null` when its PATH does not. */
24
+ readonly servicePath: string | null;
25
+ /** Where this shell finds it when the service does not: `mama service install` adds its folder. */
26
+ readonly shellPath: string | null;
27
+ /** Commands that install it, each one way to do it; empty when the service or this shell has it. */
28
+ readonly install: string[];
29
+ /** The command, from this shell, that runs the tool the service will run, with its login. */
30
+ readonly login: string;
31
+ }
32
+ type Source = {
33
+ readonly name: string;
34
+ readonly needs: readonly AuthRequirement[];
35
+ };
36
+ /**
37
+ * `enabled` is every source that will run, `sources` among them: one login serves every source
38
+ * that runs the tool, so it names the scopes all of them need, and logging in for a new source
39
+ * does not narrow what an earlier one was granted.
40
+ */
41
+ export declare function sourceTools(sources: readonly Source[], service: ServiceSight, install: {
42
+ readonly root: string;
43
+ readonly home: string;
44
+ }, find: {
45
+ /** Where a service whose PATH is `dirs` finds `name`. */
46
+ inDirs(name: string, dirs: readonly string[]): string | undefined;
47
+ /** Where this shell finds `name`. */
48
+ shell(name: string): string | undefined;
49
+ }, enabled?: readonly Source[]): SourceToolReport[];
50
+ /**
51
+ * What `mama init` and `init --section connectors` print for each report: the tool's login, after
52
+ * what it needs first. A tool the service cannot find also gets how to install it, and `next`
53
+ * last: the service does not start while a source's tool is missing from its PATH (the source's
54
+ * start fails boot).
55
+ */
56
+ export declare function sourceToolLines(reports: readonly SourceToolReport[], next: string,
57
+ /** The command that runs this install's `mama`. */
58
+ mama: string): string[];
59
+ export {};
60
+ //# sourceMappingURL=source-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-tools.d.ts","sourceRoot":"","sources":["../../../src/cli/runtime/source-tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAwBvF,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,qFAAqF;IACrF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,OAAO,EAAE,MAAM;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAA;CAAE,EAC9D,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAC9C,YAAY,CA4Bd;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,mGAAmG;IACnG,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,oGAAoG;IACpG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAoBD,KAAK,MAAM,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC;AAWpF;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACzD,IAAI,EAAE;IACJ,yDAAyD;IACzD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAClE,qCAAqC;IACrC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACzC,EACD,OAAO,GAAE,SAAS,MAAM,EAAY,GACnC,gBAAgB,EAAE,CAoDpB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,IAAI,EAAE,MAAM;AACZ,mDAAmD;AACnD,IAAI,EAAE,MAAM,GACX,MAAM,EAAE,CAwBV"}
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serviceSight = serviceSight;
4
+ exports.sourceTools = sourceTools;
5
+ exports.sourceToolLines = sourceToolLines;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ const gws_utils_js_1 = require("../../connectors/framework/gws-utils.js");
9
+ const launch_files_js_1 = require("../launch-files.js");
10
+ const prompt_js_1 = require("../prompt.js");
11
+ const secrets_js_1 = require("../secrets.js");
12
+ const node_move_journal_js_1 = require("./node-move-journal.js");
13
+ /**
14
+ * The tools sources run (docs/development/work/install.md, PR 3, I4): a source names its tool
15
+ * with a `type: 'cli'` requirement, and this says, for the sources being enabled, which of those
16
+ * tools the service cannot find, how to install each and how to log in. It reports; the caller
17
+ * decides: `init --section connectors` refuses a source whose tool the service cannot find
18
+ * (W2.4.5e), since that source's start would stop boot.
19
+ */
20
+ /** Every tool a source runs, by its command. */
21
+ const SOURCE_TOOLS = [gws_utils_js_1.gwsTool];
22
+ /**
23
+ * start.sh's PATH and Node when it exists; before it does (a setup whose service step has not
24
+ * run), what `mama service install` will write from this shell.
25
+ */
26
+ function serviceSight(root, home, platform, planned, toolDirectoryExists) {
27
+ const startPath = (0, node_path_1.join)(root, 'start.sh');
28
+ if ((0, node_fs_1.existsSync)(startPath)) {
29
+ // A read error (EACCES) is its own; only the parse is named as one.
30
+ const text = (0, node_fs_1.readFileSync)(startPath, 'utf8');
31
+ try {
32
+ const reading = (0, launch_files_js_1.readStartScript)(text, home);
33
+ return {
34
+ path: (0, launch_files_js_1.startScriptPath)(reading, home, platform),
35
+ nodePath: (reading.exec === null ? undefined : (0, launch_files_js_1.shellWords)(reading.exec)[1]) ?? null,
36
+ exports: (0, launch_files_js_1.startExports)(reading),
37
+ };
38
+ }
39
+ catch (error) {
40
+ throw new prompt_js_1.CliInputError(`${startPath} does not parse (${error instanceof Error ? error.message : String(error)}); mama service install --replace rewrites it`, { cause: error });
41
+ }
42
+ }
43
+ const launch = planned();
44
+ return {
45
+ path: (0, launch_files_js_1.startPathEntries)({
46
+ ...launch,
47
+ ...(toolDirectoryExists ? { exists: toolDirectoryExists } : {}),
48
+ }),
49
+ nodePath: launch.nodePath,
50
+ exports: {},
51
+ };
52
+ }
53
+ /** `path` under `home` with nothing a shell reads specially in the rest of it. */
54
+ function underHome(path, home) {
55
+ const rest = path.startsWith(`${home}/`) ? path.slice(home.length + 1) : null;
56
+ return rest !== null && /^[\w./-]+$/.test(rest) ? rest : null;
57
+ }
58
+ /** `path` for a shell: `~/...` under `home`, anything else quoted. */
59
+ function shellPath(path, home) {
60
+ const rest = underHome(path, home);
61
+ return rest === null ? (0, secrets_js_1.shellQuote)(path) : `~/${rest}`;
62
+ }
63
+ /** A `PATH=` prefix that puts `folder` first: `$HOME/...` under `home`, anything else quoted. */
64
+ function pathFirst(folder, home) {
65
+ const rest = underHome(folder, home);
66
+ return rest === null ? `PATH=${(0, secrets_js_1.shellQuote)(folder)}:"$PATH"` : `PATH="$HOME/${rest}:$PATH"`;
67
+ }
68
+ /** The tool a `type: 'cli'` requirement names; `undefined` for any other requirement. */
69
+ function toolFor(source, need) {
70
+ if (need.type !== 'cli' || need.cli === undefined)
71
+ return undefined;
72
+ const tool = SOURCE_TOOLS.find(({ command }) => command === need.cli);
73
+ if (tool === undefined)
74
+ throw new Error(`${source} runs ${need.cli}, and nothing says how to install it`);
75
+ return tool;
76
+ }
77
+ /**
78
+ * `enabled` is every source that will run, `sources` among them: one login serves every source
79
+ * that runs the tool, so it names the scopes all of them need, and logging in for a new source
80
+ * does not narrow what an earlier one was granted.
81
+ */
82
+ function sourceTools(sources, service, install, find, enabled = sources) {
83
+ const used = new Map();
84
+ for (const { name, needs } of sources) {
85
+ for (const need of needs) {
86
+ const tool = toolFor(name, need);
87
+ if (tool === undefined)
88
+ continue;
89
+ const names = used.get(tool) ?? [];
90
+ if (!names.includes(name))
91
+ used.set(tool, [...names, name]);
92
+ }
93
+ }
94
+ const scopes = new Map();
95
+ for (const { name, needs } of enabled) {
96
+ for (const need of needs) {
97
+ const tool = toolFor(name, need);
98
+ if (tool === undefined || need.scope === undefined)
99
+ continue;
100
+ scopes.set(tool, (scopes.get(tool) ?? new Set()).add(need.scope));
101
+ }
102
+ }
103
+ const { root, home } = install;
104
+ // An install the install command made (PR 2): start.sh runs ~/.mama/node, and its PATH names
105
+ // ~/.mama/npm/bin. A tool that is a Node script installs there with that Node.
106
+ const nodeBin = (0, node_path_1.dirname)((0, node_move_journal_js_1.managedNodePath)(root));
107
+ const prefix = (0, node_move_journal_js_1.nodeMovePlaces)(root).prefix;
108
+ const managed = service.nodePath === (0, node_move_journal_js_1.managedNodePath)(root) && service.path.includes((0, node_path_1.join)(prefix, 'bin'));
109
+ return [...used].map(([tool, names]) => {
110
+ const onService = find.inDirs(tool.command, service.path) ?? null;
111
+ const onShell = find.shell(tool.command) ?? null;
112
+ const shellOnly = onService === null ? onShell : null;
113
+ const target = onService ?? shellOnly;
114
+ let run;
115
+ if (managed) {
116
+ run = `${pathFirst(nodeBin, home)} ${shellPath(target ?? (0, node_path_1.join)(prefix, 'bin', tool.command), home)}`;
117
+ }
118
+ else {
119
+ run = target === null || target === onShell ? tool.command : shellPath(target, home);
120
+ }
121
+ return {
122
+ tool,
123
+ sources: names,
124
+ servicePath: onService,
125
+ shellPath: shellOnly,
126
+ install: target !== null
127
+ ? []
128
+ : managed
129
+ ? [
130
+ `${pathFirst(nodeBin, home)} ${shellPath((0, node_path_1.join)(nodeBin, 'npm'), home)} install -g --prefix ${shellPath(prefix, home)} ${tool.npmPackage}`,
131
+ ]
132
+ : [`npm install -g ${tool.npmPackage}`, `brew install ${tool.brewFormula}`],
133
+ login: `${run} ${tool.loginArgs}${scopes.has(tool) ? ` ${tool.scopeFlag} ${[...scopes.get(tool)].map(tool.loginScope).sort().join(',')}` : ''}`,
134
+ };
135
+ });
136
+ }
137
+ /**
138
+ * What `mama init` and `init --section connectors` print for each report: the tool's login, after
139
+ * what it needs first. A tool the service cannot find also gets how to install it, and `next`
140
+ * last: the service does not start while a source's tool is missing from its PATH (the source's
141
+ * start fails boot).
142
+ */
143
+ function sourceToolLines(reports, next,
144
+ /** The command that runs this install's `mama`. */
145
+ mama) {
146
+ return reports.flatMap((report) => {
147
+ const { tool, sources } = report;
148
+ const who = sources.join(', ');
149
+ const s = sources.length > 1 ? '' : 's';
150
+ const stops = `MAMA's service does not start with ${who} until ${tool.command} is on its PATH.`;
151
+ if (report.servicePath !== null)
152
+ return [tool.beforeLogin, `Then log in to ${tool.command} for ${who}: ${report.login}`];
153
+ if (report.shellPath !== null)
154
+ return [
155
+ `${who} run${s} ${tool.command}; this shell finds ${report.shellPath}, but the service's PATH does not name ${(0, node_path_1.dirname)(report.shellPath)}. ${mama} service install adds it.`,
156
+ tool.beforeLogin,
157
+ `Then log in to ${tool.command} for ${who}: ${report.login}`,
158
+ `${stops} ${next}`,
159
+ ];
160
+ return [
161
+ `${who} run${s} ${tool.command}, which the service's PATH does not have. Install it${report.install.length > 1 ? ' with one of' : ''}:`,
162
+ ...report.install.map((command) => ` ${command}`),
163
+ tool.beforeLogin,
164
+ `Then log in to ${tool.command} for ${who}:`,
165
+ ` ${report.login}`,
166
+ `${stops} ${next}`,
167
+ ];
168
+ });
169
+ }
170
+ //# sourceMappingURL=source-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-tools.js","sourceRoot":"","sources":["../../../src/cli/runtime/source-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /** One Telegram Bot API call, as doctor makes it; tests replace it. */
2
+ export type TelegramCall = (token: string, method: string, params?: Record<string, string>) => Promise<Record<string, unknown>>;
3
+ export interface Update {
4
+ update_id: number;
5
+ message?: {
6
+ chat?: {
7
+ id: number;
8
+ type?: string;
9
+ };
10
+ from?: {
11
+ id: number;
12
+ is_bot?: boolean;
13
+ };
14
+ /** Set when an anonymous administrator posts as the group itself. */
15
+ sender_chat?: {
16
+ id: number;
17
+ };
18
+ text?: string;
19
+ entities?: Array<{
20
+ type: string;
21
+ offset: number;
22
+ length: number;
23
+ }>;
24
+ };
25
+ }
26
+ interface PairingOptions {
27
+ token: string;
28
+ call: TelegramCall;
29
+ write: (line: string) => void;
30
+ }
31
+ /** The bot's @name, which the pairing instructions give. */
32
+ export declare function botName(options: PairingOptions): Promise<string>;
33
+ /**
34
+ * Make the person setting up the first owner without a typed user ID: everyone who messages the
35
+ * bot privately while init waits gets a code, and the code `ask` returns names the owner. A code
36
+ * reaches only the chat it was sent to, so entering it proves that chat is this person's.
37
+ * Messages the bot held from before are dropped first: they were not sent to this setup, and an
38
+ * old /bind would otherwise name a group without a new word from the owner.
39
+ */
40
+ export declare function pairOwner(options: PairingOptions & {
41
+ botUsername: string;
42
+ /** Ends with a rejection once the signal aborts: a failed poll must not wait for typing. */
43
+ ask: (label: string, signal: AbortSignal) => Promise<string>;
44
+ }): Promise<{
45
+ ownerId: string;
46
+ offset: number;
47
+ groupMessages: Update[];
48
+ }>;
49
+ /**
50
+ * The common channel without a typed chat ID: the paired owner sends /bind in the group, and
51
+ * that group becomes it. Anyone else's message, or a /bind in a private chat, is ignored.
52
+ */
53
+ export declare function bindCommonGroup(options: PairingOptions & {
54
+ botUsername: string;
55
+ ownerId: string;
56
+ offset: number;
57
+ /** Group messages read before this step, checked first. */
58
+ earlier?: readonly Update[];
59
+ now?: () => number;
60
+ waitMs?: number;
61
+ }): Promise<{
62
+ chatId: string;
63
+ offset: number;
64
+ }>;
65
+ /**
66
+ * Mark every update init read as handled, so the daemon's first poll does not take the pairing
67
+ * messages for an owner's questions.
68
+ */
69
+ export declare function confirmUpdates(options: PairingOptions & {
70
+ offset: number;
71
+ }): Promise<void>;
72
+ export {};
73
+ //# sourceMappingURL=telegram-pairing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram-pairing.d.ts","sourceRoot":"","sources":["../../../src/cli/runtime/telegram-pairing.ts"],"names":[],"mappings":"AAGA,uEAAuE;AACvE,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtC,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrC,IAAI,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;QACxC,qEAAqE;QACrE,WAAW,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACpE,CAAC;CACH;AAED,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AA+CD,4DAA4D;AAC5D,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAMtE;AAOD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,cAAc,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,4FAA4F;IAC5F,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9D,GACA,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAsEvE;AAaD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAsC7C;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG"}