stitchkit 0.100.2 → 0.101.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 (242) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/README.md +2 -1
  3. package/dist/entrypoints/agent-runtime/browser.js +119 -119
  4. package/dist/entrypoints/agent-runtime/coding-tools.js +15 -20
  5. package/dist/entrypoints/agent-runtime/harness.js +55 -63
  6. package/dist/entrypoints/agent-runtime/openrouter.js +6 -6
  7. package/dist/entrypoints/agent-runtime/sandbox.js +20 -25
  8. package/dist/entrypoints/agent-runtime/sqlite/bun.js +11 -13
  9. package/dist/entrypoints/agent-runtime/sqlite/node.js +11 -13
  10. package/dist/entrypoints/agent-runtime/testing.js +32 -34
  11. package/dist/entrypoints/agent-runtime.js +395 -402
  12. package/dist/entrypoints/application/diagnostic-journal.js +26 -27
  13. package/dist/entrypoints/application/directory-inbox.js +16 -17
  14. package/dist/entrypoints/application/grammy.js +13 -13
  15. package/dist/entrypoints/application/opentelemetry.js +13 -13
  16. package/dist/entrypoints/application/schemas.js +24 -24
  17. package/dist/entrypoints/application.js +209 -210
  18. package/dist/entrypoints/bin/upgrade-cli.js +2 -2
  19. package/dist/entrypoints/cli.js +81 -84
  20. package/dist/entrypoints/contract.js +54 -57
  21. package/dist/entrypoints/declaration.js +22 -22
  22. package/dist/entrypoints/files.js +18 -21
  23. package/dist/entrypoints/geo.js +7 -8
  24. package/dist/entrypoints/google.js +2 -2
  25. package/dist/entrypoints/index.js +150 -154
  26. package/dist/entrypoints/live.js +45 -47
  27. package/dist/entrypoints/node.js +68 -74
  28. package/dist/entrypoints/oauth.js +6 -6
  29. package/dist/entrypoints/observability.d.ts +1 -0
  30. package/dist/entrypoints/observability.d.ts.map +1 -1
  31. package/dist/entrypoints/observability.js +116 -87
  32. package/dist/entrypoints/primitives.js +35 -35
  33. package/dist/entrypoints/react/keyboard.d.ts +4 -0
  34. package/dist/entrypoints/react/keyboard.d.ts.map +1 -0
  35. package/dist/entrypoints/react/keyboard.js +397 -0
  36. package/dist/entrypoints/react.js +10 -10
  37. package/dist/entrypoints/release.js +7 -7
  38. package/dist/entrypoints/remote.js +15 -17
  39. package/dist/entrypoints/server.js +198 -200
  40. package/dist/entrypoints/telegram/html.d.ts +5 -0
  41. package/dist/entrypoints/telegram/html.d.ts.map +1 -0
  42. package/dist/entrypoints/telegram/html.js +26 -0
  43. package/dist/entrypoints/telegram/screens.d.ts +14 -0
  44. package/dist/entrypoints/telegram/screens.d.ts.map +1 -0
  45. package/dist/entrypoints/telegram/screens.js +2028 -0
  46. package/dist/entrypoints/telegram.d.ts +11 -3
  47. package/dist/entrypoints/telegram.d.ts.map +1 -1
  48. package/dist/entrypoints/telegram.js +779 -159
  49. package/dist/entrypoints/testing.js +75 -79
  50. package/dist/entrypoints/tools/connections.js +30 -32
  51. package/dist/entrypoints/tools/contract.js +18 -20
  52. package/dist/entrypoints/tools/invoker.js +12 -17
  53. package/dist/entrypoints/tools.js +224 -229
  54. package/dist/entrypoints/tracking/server.js +6 -6
  55. package/dist/entrypoints/tracking.js +40 -42
  56. package/dist/entrypoints/voice.js +3 -3
  57. package/dist/{index-eaysmdtq.js → index-0ndk4555.js} +56 -56
  58. package/dist/{index-2bxbyab0.js → index-1bx1xv1k.js} +1 -1
  59. package/dist/{index-p5r7qpdd.js → index-1eeqpadm.js} +4 -4
  60. package/dist/{index-hadmp193.js → index-3ct7hhq6.js} +210 -210
  61. package/dist/{index-e01r054k.js → index-45tdvqa3.js} +26 -26
  62. package/dist/{index-dce5wxcq.js → index-4s0fep5q.js} +8 -8
  63. package/dist/index-50ejfz75.js +9 -0
  64. package/dist/{index-m9zn6cpq.js → index-5107q189.js} +12 -12
  65. package/dist/{index-sbdmyz75.js → index-5cc6r990.js} +3 -3
  66. package/dist/{index-c6bxbsnc.js → index-7kxw1awn.js} +2 -2
  67. package/dist/{index-0r0fbk7z.js → index-7z9ym7t8.js} +28 -28
  68. package/dist/{index-p7hgdyhb.js → index-814xpr6d.js} +2 -2
  69. package/dist/{index-gtj3zc53.js → index-8kzct1d6.js} +99 -99
  70. package/dist/{index-1zbbzgfh.js → index-9pw0a51a.js} +4 -4
  71. package/dist/{index-79z7m7dt.js → index-a9pd417t.js} +35 -35
  72. package/dist/{index-ham5sz8m.js → index-aaj97r4y.js} +45 -45
  73. package/dist/{index-s812ycat.js → index-aan6hqb9.js} +3 -3
  74. package/dist/{index-10x2hbx0.js → index-adhgd4pe.js} +44 -44
  75. package/dist/{index-2gxzjvyr.js → index-afjvjyck.js} +23 -23
  76. package/dist/{index-qmy6zq75.js → index-ahvsksw5.js} +16 -16
  77. package/dist/{index-hr4tzbwq.js → index-ap3gqe56.js} +3 -3
  78. package/dist/{index-znfs20ss.js → index-b2bz0kdm.js} +16 -16
  79. package/dist/{index-r066jx76.js → index-c6aagrbd.js} +148 -120
  80. package/dist/{index-k30h66yd.js → index-ck71tbcf.js} +9 -9
  81. package/dist/{index-eqqvgdb3.js → index-ct75c3at.js} +2 -2
  82. package/dist/{index-gw8bmyaj.js → index-djjhhgjk.js} +41 -41
  83. package/dist/{index-8qt2m66q.js → index-dvwj1f43.js} +43 -43
  84. package/dist/index-e05cjgtf.js +144 -0
  85. package/dist/{index-yw4fzmdz.js → index-e6c2spsd.js} +79 -30
  86. package/dist/{index-fhwqwxe0.js → index-ej331hah.js} +1 -1
  87. package/dist/{index-9t3dffv2.js → index-ewbaywk5.js} +5 -5
  88. package/dist/{index-7p1f0vp2.js → index-fyphpknh.js} +25 -25
  89. package/dist/{index-83bdg97s.js → index-g149e9pk.js} +1 -1
  90. package/dist/{index-ngfhvfpd.js → index-g6a3na27.js} +4 -4
  91. package/dist/{index-qwhynv6x.js → index-h124epcf.js} +20 -20
  92. package/dist/{index-h6eeys1v.js → index-h97tqqp1.js} +9 -9
  93. package/dist/{index-zcgf3gqf.js → index-hby4qhax.js} +10 -10
  94. package/dist/{index-5jrd0yng.js → index-j8aw2c0e.js} +4 -4
  95. package/dist/{index-d8m8zpd8.js → index-jzczzcsb.js} +14 -14
  96. package/dist/index-kqnd6a85.js +26 -0
  97. package/dist/{index-35mh5bhj.js → index-kw1ws0cs.js} +12 -12
  98. package/dist/{index-4gcnakhx.js → index-m38ej7e5.js} +2 -2
  99. package/dist/{index-ndddxtyx.js → index-m79yr938.js} +19 -19
  100. package/dist/{index-5p2m7we1.js → index-m9fndta6.js} +11 -11
  101. package/dist/index-mnkk1ffz.js +150 -0
  102. package/dist/index-n15jny5b.js +4 -0
  103. package/dist/{index-2vtcmrj9.js → index-n53mswt3.js} +20 -20
  104. package/dist/{index-bt14acb5.js → index-n5yqxd3d.js} +21 -21
  105. package/dist/{index-bm5rx7n6.js → index-n9tyz8z3.js} +12 -12
  106. package/dist/index-nmaqxdx7.js +463 -0
  107. package/dist/{index-mqv3b5rh.js → index-nx6eazt0.js} +30 -30
  108. package/dist/{index-3z73fh2c.js → index-q0th8q0z.js} +9 -9
  109. package/dist/{index-v260df89.js → index-qjeggp8w.js} +20 -20
  110. package/dist/{index-zfrhfn82.js → index-r1z0rd9c.js} +20 -20
  111. package/dist/{index-wqgjfstn.js → index-r5c4fedv.js} +3 -3
  112. package/dist/{index-cyktc4bp.js → index-r5hsgkz5.js} +118 -118
  113. package/dist/{index-0b1ess5e.js → index-r7a7r7ha.js} +1 -1
  114. package/dist/{index-1j8pm5t0.js → index-rfkh44ss.js} +15 -15
  115. package/dist/index-rz3z13e9.js +47 -0
  116. package/dist/{index-k6gpggb9.js → index-s80awwsw.js} +35 -35
  117. package/dist/{index-vqr7f7v8.js → index-ssmd41kh.js} +124 -124
  118. package/dist/index-sznqf8fx.js +20 -0
  119. package/dist/{index-ensd0r74.js → index-v14qqmys.js} +41 -41
  120. package/dist/{index-paz6sgdp.js → index-v4a2fjtk.js} +36 -36
  121. package/dist/{index-d9pk3td4.js → index-w0eqdhyd.js} +14 -14
  122. package/dist/{index-5qn1kx34.js → index-w575evhq.js} +29 -29
  123. package/dist/{index-3gye9wzb.js → index-w5s3xftz.js} +26 -26
  124. package/dist/{index-tm88avnj.js → index-wykebpn9.js} +3 -3
  125. package/dist/{index-sh3s86na.js → index-xkhk5d6g.js} +17 -17
  126. package/dist/{index-6k1937bx.js → index-xqhede6x.js} +4 -4
  127. package/dist/{index-f4fx2tza.js → index-zs4ms3th.js} +181 -181
  128. package/dist/{index-k5hsfc3j.js → index-zsvzhjtk.js} +1 -1
  129. package/dist/internal/secret-shapes.d.ts +21 -0
  130. package/dist/internal/secret-shapes.d.ts.map +1 -0
  131. package/dist/observability/bounded-logger.d.ts +2 -0
  132. package/dist/observability/bounded-logger.d.ts.map +1 -1
  133. package/dist/observability/sanitize.d.ts +6 -0
  134. package/dist/observability/sanitize.d.ts.map +1 -1
  135. package/dist/observability/secret-values.d.ts +25 -0
  136. package/dist/observability/secret-values.d.ts.map +1 -0
  137. package/dist/react/keyboard/hooks.d.ts +71 -0
  138. package/dist/react/keyboard/hooks.d.ts.map +1 -0
  139. package/dist/react/keyboard/layers.d.ts +98 -0
  140. package/dist/react/keyboard/layers.d.ts.map +1 -0
  141. package/dist/react/keyboard/zone.d.ts +139 -0
  142. package/dist/react/keyboard/zone.d.ts.map +1 -0
  143. package/dist/telegram/bot-api.d.ts +7 -4
  144. package/dist/telegram/bot-api.d.ts.map +1 -1
  145. package/dist/telegram/crypto.d.ts +16 -0
  146. package/dist/telegram/crypto.d.ts.map +1 -0
  147. package/dist/telegram/html/check.d.ts +26 -0
  148. package/dist/telegram/html/check.d.ts.map +1 -0
  149. package/dist/telegram/html/nodes.d.ts +70 -0
  150. package/dist/telegram/html/nodes.d.ts.map +1 -0
  151. package/dist/telegram/html/parse.d.ts +35 -0
  152. package/dist/telegram/html/parse.d.ts.map +1 -0
  153. package/dist/telegram/html/render.d.ts +39 -0
  154. package/dist/telegram/html/render.d.ts.map +1 -0
  155. package/dist/telegram/init-data.d.ts +3 -44
  156. package/dist/telegram/init-data.d.ts.map +1 -1
  157. package/dist/telegram/operator-channel.d.ts +19 -3
  158. package/dist/telegram/operator-channel.d.ts.map +1 -1
  159. package/dist/telegram/operator-dedupe.d.ts +44 -0
  160. package/dist/telegram/operator-dedupe.d.ts.map +1 -0
  161. package/dist/telegram/screens/callback-codec.d.ts +34 -0
  162. package/dist/telegram/screens/callback-codec.d.ts.map +1 -0
  163. package/dist/telegram/screens/dispatch.d.ts +22 -0
  164. package/dist/telegram/screens/dispatch.d.ts.map +1 -0
  165. package/dist/telegram/screens/display.d.ts +70 -0
  166. package/dist/telegram/screens/display.d.ts.map +1 -0
  167. package/dist/telegram/screens/execute.d.ts +57 -0
  168. package/dist/telegram/screens/execute.d.ts.map +1 -0
  169. package/dist/telegram/screens/html.d.ts +36 -0
  170. package/dist/telegram/screens/html.d.ts.map +1 -0
  171. package/dist/telegram/screens/outcome.d.ts +74 -0
  172. package/dist/telegram/screens/outcome.d.ts.map +1 -0
  173. package/dist/telegram/screens/path.d.ts +29 -0
  174. package/dist/telegram/screens/path.d.ts.map +1 -0
  175. package/dist/telegram/screens/reconcile.d.ts +67 -0
  176. package/dist/telegram/screens/reconcile.d.ts.map +1 -0
  177. package/dist/telegram/screens/registry.d.ts +23 -0
  178. package/dist/telegram/screens/registry.d.ts.map +1 -0
  179. package/dist/telegram/screens/render.d.ts +70 -0
  180. package/dist/telegram/screens/render.d.ts.map +1 -0
  181. package/dist/telegram/screens/runtime.d.ts +133 -0
  182. package/dist/telegram/screens/runtime.d.ts.map +1 -0
  183. package/dist/telegram/screens/screen-types.d.ts +130 -0
  184. package/dist/telegram/screens/screen-types.d.ts.map +1 -0
  185. package/dist/telegram/screens/screen.d.ts +138 -0
  186. package/dist/telegram/screens/screen.d.ts.map +1 -0
  187. package/dist/telegram/screens/state.d.ts +115 -0
  188. package/dist/telegram/screens/state.d.ts.map +1 -0
  189. package/dist/telegram/screens/telegram-screens.d.ts +18 -0
  190. package/dist/telegram/screens/telegram-screens.d.ts.map +1 -0
  191. package/dist/telegram/screens/test-chat-telegram.d.ts +47 -0
  192. package/dist/telegram/screens/test-chat-telegram.d.ts.map +1 -0
  193. package/dist/telegram/screens/test-chat.d.ts +66 -0
  194. package/dist/telegram/screens/test-chat.d.ts.map +1 -0
  195. package/dist/telegram/screens/view.d.ts +89 -0
  196. package/dist/telegram/screens/view.d.ts.map +1 -0
  197. package/dist/telegram/send-failure.d.ts +25 -0
  198. package/dist/telegram/send-failure.d.ts.map +1 -1
  199. package/dist/telegram/update-intake.d.ts +82 -0
  200. package/dist/telegram/update-intake.d.ts.map +1 -0
  201. package/dist/telegram/update-store-check.d.ts +22 -0
  202. package/dist/telegram/update-store-check.d.ts.map +1 -0
  203. package/dist/telegram/update-store-postgres.d.ts +33 -0
  204. package/dist/telegram/update-store-postgres.d.ts.map +1 -0
  205. package/dist/telegram/update-store-sqlite.d.ts +26 -0
  206. package/dist/telegram/update-store-sqlite.d.ts.map +1 -0
  207. package/dist/telegram/update-store.d.ts +67 -0
  208. package/dist/telegram/update-store.d.ts.map +1 -0
  209. package/dist/telegram/user.d.ts +51 -0
  210. package/dist/telegram/user.d.ts.map +1 -0
  211. package/dist/telegram/webhook.d.ts +105 -0
  212. package/dist/telegram/webhook.d.ts.map +1 -0
  213. package/dist/tools/cli/args-fields.d.ts +8 -0
  214. package/dist/tools/cli/args-fields.d.ts.map +1 -1
  215. package/dist/tools/cli/args-route.d.ts.map +1 -1
  216. package/dist/tools/cli/args.d.ts.map +1 -1
  217. package/dist/tools/cli/help.d.ts.map +1 -1
  218. package/llms/cli.txt +8 -2
  219. package/llms/observability.txt +15 -2
  220. package/llms/react-keyboard.txt +193 -0
  221. package/llms/server.4.txt +16 -0
  222. package/llms/stitchkit.txt +10 -4
  223. package/llms/telegram-html.txt +35 -0
  224. package/llms/telegram-screens.txt +365 -0
  225. package/llms/telegram.txt +245 -11
  226. package/llms/{upgrading-0.74.0-0.100.0.txt → upgrading-0.74.0-0.101.0.txt} +39 -3
  227. package/llms/upgrading.txt +1 -1
  228. package/llms-full.txt +889 -19
  229. package/llms.txt +12 -7
  230. package/package.json +17 -2
  231. package/dist/index-2k4yrqkc.js +0 -9
  232. package/dist/index-crykmqkr.js +0 -26
  233. package/dist/index-y64k3s0h.js +0 -150
  234. package/dist/index-y91ry9h2.js +0 -4
  235. /package/dist/{index-hffjpmq9.js → index-9jfdm5tg.js} +0 -0
  236. /package/dist/{index-zjjyynm3.js → index-d4pa2bgs.js} +0 -0
  237. /package/dist/{index-rxfy4cq7.js → index-dwfv9a85.js} +0 -0
  238. /package/dist/{index-5jm36zv1.js → index-gfk7nrht.js} +0 -0
  239. /package/dist/{index-b9aefrqd.js → index-n1dqr7gf.js} +0 -0
  240. /package/dist/{index-q3pyb9n0.js → index-sykb5ag7.js} +0 -0
  241. /package/dist/{index-48ffdxgk.js → index-xhzq2qvj.js} +0 -0
  242. /package/dist/{index-kzfs85xp.js → index-zsarb5xp.js} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/telegram/html/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAIL,KAAK,gBAAgB,EAEtB,MAAM,SAAS,CAAC;AAiDjB,MAAM,MAAM,KAAK,GACb;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD,CAAC;AAkBN,mGAAmG;AACnG,wBAAiB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAsD1D;AAwMD,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAapE"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The tree back to markup, and the operations that go through the tree:
3
+ * cleaning, cutting to Telegram's limits, measuring.
4
+ *
5
+ * Telegram's limits count the text after the markup is parsed — 4096 for a
6
+ * message, 1024 for a caption — so a long text is cut by what the reader
7
+ * sees, never by the length of its tags. A cut prefers a paragraph break, then
8
+ * a line break, then a space, then any place that does not split a character
9
+ * or a custom emoji; every element open across the cut is closed in one part
10
+ * and opened again, with its attributes, in the next. Length is counted in
11
+ * UTF-16 code units, the unit of Telegram's entity offsets: a text within the
12
+ * limit by this count is within it however Telegram counts.
13
+ */
14
+ import { type TelegramHtmlNode } from './nodes.js';
15
+ /** `&`, `<` and `>` as Telegram's HTML requires them, and `"` for attributes. */
16
+ export declare function escapeTelegramHtml(text: string): string;
17
+ /** The markup Telegram parses back into exactly these nodes. */
18
+ export declare function renderTelegramHtml(nodes: readonly TelegramHtmlNode[]): string;
19
+ /** Any markup as markup Telegram accepts: its tags, its nesting, its escaping. */
20
+ export declare function sanitizeTelegramHtml(markup: string): string;
21
+ /** What the reader sees: the text of the markup, entities decoded. */
22
+ export declare function telegramHtmlText(markup: string): string;
23
+ export interface TelegramHtmlLimitOptions {
24
+ /** Visible characters per part. Default 4096 — a message; 1024 for a caption. */
25
+ readonly limit?: number;
26
+ }
27
+ /**
28
+ * Cut markup into parts Telegram accepts one by one, each within `limit`
29
+ * visible characters and each valid on its own. Markup that fits is one part;
30
+ * text with nothing visible is no parts.
31
+ */
32
+ export declare function splitTelegramHtml(markup: string, options?: TelegramHtmlLimitOptions): string[];
33
+ export interface TelegramHtmlTruncateOptions extends TelegramHtmlLimitOptions {
34
+ /** Appended when text was cut. Default `…`. */
35
+ readonly ellipsis?: string;
36
+ }
37
+ /** Markup cut to `limit` visible characters, the ellipsis included, still valid. */
38
+ export declare function truncateTelegramHtml(markup: string, options?: TelegramHtmlTruncateOptions): string;
39
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/telegram/html/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAIL,KAAK,gBAAgB,EAGtB,MAAM,SAAS,CAAC;AAGjB,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvD;AA4BD,gEAAgE;AAChE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAS7E;AAED,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AA+FD,MAAM,WAAW,wBAAwB;IACvC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,wBAA6B,GACrC,MAAM,EAAE,CAkBV;AAED,MAAM,WAAW,2BAA4B,SAAQ,wBAAwB;IAC3E,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,2BAAgC,GACxC,MAAM,CAWR"}
@@ -22,52 +22,12 @@
22
22
  * Not a domain model (→ ADR 0002): "Telegram signed this string" is a fact
23
23
  * about a transport, the same kind of fact as a bearer token being well-formed.
24
24
  */
25
- import { z } from 'zod';
26
- /**
27
- * The Telegram user record, as our surface names things.
28
- *
29
- * Telegram's wire fields are `snake_case`; every other name this package
30
- * publishes is `camelCase`, and a surface that switches convention because of
31
- * where a value came from makes the caller remember which is which. The
32
- * untouched wire pairs stay available in `raw`.
33
- */
34
- declare const TelegramInitDataUserSchema: z.ZodPipe<z.ZodObject<{
35
- id: z.ZodInt;
36
- is_bot: z.ZodOptional<z.ZodBoolean>;
37
- first_name: z.ZodString;
38
- last_name: z.ZodOptional<z.ZodString>;
39
- username: z.ZodOptional<z.ZodString>;
40
- language_code: z.ZodOptional<z.ZodString>;
41
- is_premium: z.ZodOptional<z.ZodBoolean>;
42
- allows_write_to_pm: z.ZodOptional<z.ZodBoolean>;
43
- photo_url: z.ZodOptional<z.ZodString>;
44
- }, z.core.$strip>, z.ZodTransform<{
45
- id: number;
46
- firstName: string;
47
- isBot?: boolean | undefined;
48
- lastName?: string | undefined;
49
- username?: string | undefined;
50
- languageCode?: string | undefined;
51
- isPremium?: boolean | undefined;
52
- allowsWriteToPm?: boolean | undefined;
53
- photoUrl?: string | undefined;
54
- }, {
55
- id: number;
56
- is_bot?: boolean | undefined;
57
- first_name: string;
58
- last_name?: string | undefined;
59
- username?: string | undefined;
60
- language_code?: string | undefined;
61
- is_premium?: boolean | undefined;
62
- allows_write_to_pm?: boolean | undefined;
63
- photo_url?: string | undefined;
64
- }>>;
65
- export type TelegramInitDataUser = z.infer<typeof TelegramInitDataUserSchema>;
25
+ import { type TelegramUser } from './user.js';
66
26
  export interface TelegramInitData {
67
27
  /** Absent when the Mini App was opened somewhere Telegram sends no user. */
68
- user?: TelegramInitDataUser;
28
+ user?: TelegramUser;
69
29
  /** Whose chat the Mini App was opened from, when Telegram named one. */
70
- receiver?: TelegramInitDataUser;
30
+ receiver?: TelegramUser;
71
31
  /** When Telegram signed this string. */
72
32
  authDate: Date;
73
33
  /** How old the signature was at verification time. */
@@ -130,5 +90,4 @@ export interface VerifyTelegramInitDataOptions {
130
90
  * being configured wrong, and it throws.
131
91
  */
132
92
  export declare function verifyTelegramInitData(options: VerifyTelegramInitDataOptions): Promise<TelegramInitDataVerification>;
133
- export {};
134
93
  //# sourceMappingURL=init-data.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init-data.d.ts","sourceRoot":"","sources":["../../src/telegram/init-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;GAOG;AACH,QAAA,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsB3B,CAAC;AAEN,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,wCAAwC;IACxC,QAAQ,EAAE,IAAI,CAAC;IACf,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,GAC/B,cAAc,GACd,oBAAoB,GACpB,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,MAAM,4BAA4B,GACpC;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACzD;IACE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEN,MAAM,WAAW,6BAA6B;IAC5C,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAiDD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,4BAA4B,CAAC,CAuEvC"}
1
+ {"version":3,"file":"init-data.d.ts","sourceRoot":"","sources":["../../src/telegram/init-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC;AAI9D,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,wCAAwC;IACxC,QAAQ,EAAE,IAAI,CAAC;IACf,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,GAC/B,cAAc,GACd,oBAAoB,GACpB,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,MAAM,4BAA4B,GACpC;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACzD;IACE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEN,MAAM,WAAW,6BAA6B;IAC5C,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAUD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,4BAA4B,CAAC,CAuEvC"}
@@ -13,6 +13,7 @@
13
13
  * What to post stays the application's. This owns the queue, the pacing, the
14
14
  * topics, 429s and the bounded way down.
15
15
  */
16
+ import { type TelegramOperatorDedupe } from './operator-dedupe.js';
16
17
  import { type TelegramSendFailure } from './send-failure.js';
17
18
  export type TelegramChatId = number | string;
18
19
  export interface TelegramOperatorMessage {
@@ -27,9 +28,11 @@ export interface TelegramOperatorDrop<TTopic extends string> {
27
28
  /**
28
29
  * `overflow` — the queue was full and this was the oldest; `refused` —
29
30
  * Telegram said no in a way repeating will not fix; `attempts` — it kept
30
- * failing; `closed` — the channel closed before it was sent.
31
+ * failing; `closed` — the channel closed before it was sent; `repeated`
32
+ * — the same message was sent within the dedupe window; `over-budget` —
33
+ * the window's budget was spent.
31
34
  */
32
- readonly reason: 'overflow' | 'refused' | 'attempts' | 'closed';
35
+ readonly reason: 'overflow' | 'refused' | 'attempts' | 'closed' | 'repeated' | 'over-budget';
33
36
  readonly failure?: TelegramSendFailure;
34
37
  }
35
38
  export interface TelegramOperatorChannelConfig<TTopic extends string> {
@@ -54,6 +57,15 @@ export interface TelegramOperatorChannelConfig<TTopic extends string> {
54
57
  * API file carries `<root>/<token>/…` in its path.
55
58
  */
56
59
  readonly sensitivePatterns?: readonly RegExp[];
60
+ /** Exact secret values to mask as well — `secretValuesFromEnv(process.env)`. */
61
+ readonly sensitiveValues?: readonly string[];
62
+ /**
63
+ * Hold back repeats and storms. The same message — by `fingerprint` — is
64
+ * sent once per window; the next one sent says how many were held back.
65
+ * Past `maxPerWindow` messages in a window the rest are counted, and the
66
+ * count rides on the first message sent after.
67
+ */
68
+ readonly dedupe?: TelegramOperatorDedupe<TTopic>;
57
69
  }
58
70
  export interface TelegramOperatorChannel<TTopic extends string> {
59
71
  /** Queue one message. Returns at once and never throws. */
@@ -73,6 +85,10 @@ export interface TelegramOperatorSenderConfig {
73
85
  readonly parseMode?: 'HTML' | 'MarkdownV2';
74
86
  readonly fetch?: typeof fetch;
75
87
  }
76
- /** The standard `send`: `sendMessage` through the Bot API, no bot library. */
88
+ /**
89
+ * The standard `send`: `sendMessage` through the Bot API, no bot library. With
90
+ * `parseMode: 'HTML'` the text is repaired and cut by what it shows, so a cut
91
+ * never leaves a tag open.
92
+ */
77
93
  export declare function telegramOperatorSender(config: TelegramOperatorSenderConfig): TelegramOperatorChannelConfig<string>['send'];
78
94
  //# sourceMappingURL=operator-channel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"operator-channel.d.ts","sourceRoot":"","sources":["../../src/telegram/operator-channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"operator-channel.d.ts","sourceRoot":"","sources":["../../src/telegram/operator-channel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Repeats and storms held back before they reach a person.
3
+ *
4
+ * One failure in a loop is a hundred identical alerts, and a hundred alerts
5
+ * is a muted chat — after which the one that mattered is not read either. So
6
+ * the same message, by fingerprint, goes once per window and the next one
7
+ * that goes says how many were held back; past a budget per window the rest
8
+ * are counted and the count rides on the first message after. The operator
9
+ * channel uses it through its `dedupe` option; it is exported for senders of
10
+ * their own.
11
+ */
12
+ export interface TelegramOperatorDedupe<TTopic extends string> {
13
+ /** Default 600 000 — ten minutes. */
14
+ readonly windowMs?: number;
15
+ /** Messages sent per window, whatever their fingerprint. Default 20. */
16
+ readonly maxPerWindow?: number;
17
+ /**
18
+ * What makes two messages the same. Default: the topic and the text with
19
+ * numbers, UUIDs and long identifiers blanked — they differ between two
20
+ * occurrences of one failure without making it another.
21
+ */
22
+ readonly fingerprint?: (text: string, topic: TTopic | undefined) => string;
23
+ /** The line added to a message after `count` of its repeats were held back. */
24
+ readonly repeatedLine?: (count: number) => string;
25
+ /** The line added to the first message after `count` were held back by the budget. */
26
+ readonly overBudgetLine?: (count: number) => string;
27
+ /** Default `Date.now`. */
28
+ readonly now?: () => number;
29
+ }
30
+ /** Send `text` — the message with its held-back counts — or hold it back, with why. */
31
+ export type TelegramOperatorDedupeVerdict = {
32
+ readonly send: true;
33
+ readonly text: string;
34
+ } | {
35
+ readonly send: false;
36
+ readonly reason: 'repeated' | 'over-budget';
37
+ };
38
+ /**
39
+ * The dedupe window on its own, for an application that sends alerts itself —
40
+ * its own bot, its own retry — and wants only the decision: whether this
41
+ * message goes, and the text it goes with.
42
+ */
43
+ export declare function createTelegramOperatorDedupe<TTopic extends string = never>(options?: TelegramOperatorDedupe<TTopic>): (text: string, topic?: TTopic) => TelegramOperatorDedupeVerdict;
44
+ //# sourceMappingURL=operator-dedupe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operator-dedupe.d.ts","sourceRoot":"","sources":["../../src/telegram/operator-dedupe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,sBAAsB,CAAC,MAAM,SAAS,MAAM;IAC3D,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;IAC3E,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,sFAAsF;IACtF,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpD,0BAA0B;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAUD,uFAAuF;AACvF,MAAM,MAAM,6BAA6B,GACrC;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAAA;CAAE,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,SAAS,MAAM,GAAG,KAAK,EACxE,OAAO,GAAE,sBAAsB,CAAC,MAAM,CAAM,GAC3C,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,6BAA6B,CAwCjE"}
@@ -0,0 +1,34 @@
1
+ /** Telegram's limit for `callback_data`, in UTF-8 bytes. */
2
+ export declare const CALLBACK_DATA_LIMIT = 64;
3
+ /** A value a param or an action's input may carry through a button. */
4
+ export type ActionValue = string | number | boolean | null;
5
+ export interface CallbackAddress {
6
+ readonly screen: string;
7
+ readonly action?: string;
8
+ readonly params: readonly ActionValue[];
9
+ readonly input?: Readonly<Record<string, ActionValue | undefined>>;
10
+ /** Opens the screen below instead of changing the message it is on. */
11
+ readonly detached?: boolean;
12
+ }
13
+ export type ParsedCallback = {
14
+ readonly kind: 'token';
15
+ readonly token: string;
16
+ } | {
17
+ readonly kind: 'address';
18
+ readonly screen: string;
19
+ readonly action: string | undefined;
20
+ readonly detached: boolean;
21
+ /** Still encoded: the screen decides which are params and which input. */
22
+ readonly segments: readonly string[];
23
+ };
24
+ export declare function utf8Length(text: string): number;
25
+ /** A screen id, action name or token: safe inside the grammar without escaping. */
26
+ export declare function assertCallbackName(kind: string, name: string): void;
27
+ export declare function encodeCallback(address: CallbackAddress): string;
28
+ export declare function encodeToken(token: string): string;
29
+ export declare function parseCallback(body: string): ParsedCallback | null;
30
+ /** Positional path params; `null` when any is malformed. */
31
+ export declare function decodeParams(segments: readonly string[]): ActionValue[] | null;
32
+ /** Named input entries; `null` when any is malformed, unsafe or repeated. */
33
+ export declare function decodeInput(segments: readonly string[]): Record<string, ActionValue> | null;
34
+ //# sourceMappingURL=callback-codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback-codec.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/callback-codec.ts"],"names":[],"mappings":"AA2BA,4DAA4D;AAC5D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,uEAAuE;AACvE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAO3D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC;IACnE,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClD;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,CAAC;AAEN,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMnE;AA0DD,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAkB/D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAYjE;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,CAQ9E;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAY3F"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The three ways a chat reaches a screen: a press, a message, an open.
3
+ *
4
+ * A press is trusted only as far as Telegram vouches for it. Telegram sends
5
+ * the pressed message along with its keyboard, and a `callback_data` that is
6
+ * not on that keyboard was not pressed — it was sent (MTProto lets a client
7
+ * send any bytes) — so it never reaches a handler. What remains is still user
8
+ * input: params go through the screen's schema and every load above it before
9
+ * an action runs.
10
+ */
11
+ import type { Context } from 'grammy';
12
+ import type { Message } from 'grammy/types';
13
+ import { type ScreenOrigin } from './display.js';
14
+ import type { ScreensRuntime } from './runtime.js';
15
+ import type { ScreenInputKind } from './screen-types.js';
16
+ /** The input kind of a message, for `.on(...)`; animations also carry `document`. */
17
+ export declare function inputKindOf(message: Message): ScreenInputKind | undefined;
18
+ export declare function dispatchPress<C extends Context>(runtime: ScreensRuntime<C>, ctx: C): Promise<void>;
19
+ /** Whether the message was taken as input; `false` hands it to the next handler. */
20
+ export declare function dispatchInput<C extends Context>(runtime: ScreensRuntime<C>, ctx: C, message: Message): Promise<boolean>;
21
+ export declare function openScreen<C extends Context>(runtime: ScreensRuntime<C>, ctx: C, origin: ScreenOrigin<C>, previous: 'keep' | 'delete'): Promise<void>;
22
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAA4B,OAAO,EAAE,MAAM,cAAc,CAAC;AAGtE,OAAO,EAEL,KAAK,YAAY,EAKlB,MAAM,WAAW,CAAC;AAMnB,OAAO,KAAK,EAAqB,cAAc,EAAiB,MAAM,WAAW,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AA2BtD,qFAAqF;AACrF,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAczE;AAwKD,wBAAsB,aAAa,CAAC,CAAC,SAAS,OAAO,EACnD,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,GAAG,EAAE,CAAC,GACL,OAAO,CAAC,IAAI,CAAC,CAgFf;AAED,oFAAoF;AACpF,wBAAsB,aAAa,CAAC,CAAC,SAAS,OAAO,EACnD,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,GAAG,EAAE,CAAC,EACN,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,OAAO,CAAC,CAmFlB;AAED,wBAAsB,UAAU,CAAC,CAAC,SAAS,OAAO,EAChD,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,GAAG,EAAE,CAAC,EACN,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAC1B,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * From an outcome to the chat: which screen, then what the chat shows.
3
+ *
4
+ * `settleNavigation` follows an outcome to the screen it names — resolving it,
5
+ * and following again when that screen's load answers with an outcome of its
6
+ * own — collecting the toast and notices met on the way. `displayScreen`
7
+ * renders the settled screen, reconciles it with what the chat shows, carries
8
+ * the plan out and writes the chat's record — also when Telegram refused a
9
+ * call halfway, so the record never claims less or more than the chat shows.
10
+ */
11
+ import type { Context } from 'grammy';
12
+ import type { ActionValue } from './callback-codec.js';
13
+ import { type ScreenApi } from './execute.js';
14
+ import type { TelegramText } from './html.js';
15
+ import type { ScreenNotice, ScreenOutcome, ScreenToast } from './outcome.js';
16
+ import { type ShownMessage } from './reconcile.js';
17
+ import type { RegisteredScreen } from './registry.js';
18
+ import type { ScreensRuntime, ScreenTrigger } from './runtime.js';
19
+ import type { ResolvedScreen } from './screen-types.js';
20
+ import { type ScreenChatState } from './state.js';
21
+ /** Where a chat is, as far as navigation is concerned. */
22
+ export interface ScreenOrigin<C extends Context> {
23
+ readonly entry: RegisteredScreen<C>;
24
+ /** As a button or the record carries them; the screen's schema parses them on resolution. */
25
+ readonly params: Readonly<Record<string, ActionValue>>;
26
+ }
27
+ export interface SettledNavigation<C extends Context> {
28
+ /** Absent when the outcome leads nowhere — a stay with no screen to stay on. */
29
+ readonly target: {
30
+ readonly entry: RegisteredScreen<C>;
31
+ readonly resolved: ResolvedScreen;
32
+ } | undefined;
33
+ readonly toast: ScreenToast | undefined;
34
+ readonly notices: readonly ScreenNotice[];
35
+ }
36
+ export declare function settleNavigation<C extends Context>(runtime: ScreensRuntime<C>, ctx: C, origin: ScreenOrigin<C> | undefined, outcome: ScreenOutcome): Promise<SettledNavigation<C>>;
37
+ /** What the new view is reconciled against. */
38
+ export type DisplayBase =
39
+ /** What the chat's record says it shows. */
40
+ {
41
+ readonly mode: 'state';
42
+ }
43
+ /** A message pressed outside that view. */
44
+ | {
45
+ readonly mode: 'foreign';
46
+ readonly message: ShownMessage;
47
+ }
48
+ /** Nothing: the view is sent below and the old one left as it is. */
49
+ | {
50
+ readonly mode: 'new';
51
+ }
52
+ /** The old view is deleted and the new one sent below. */
53
+ | {
54
+ readonly mode: 'fresh';
55
+ };
56
+ export interface DisplayRequest<C extends Context> {
57
+ readonly ctx: C;
58
+ readonly chat: string;
59
+ readonly chatId: number;
60
+ readonly state: ScreenChatState;
61
+ readonly settled: SettledNavigation<C>;
62
+ readonly base: DisplayBase;
63
+ readonly trigger: ScreenTrigger;
64
+ readonly started: number;
65
+ }
66
+ export declare function sendText(api: ScreenApi, chatId: number, content: TelegramText): Promise<number>;
67
+ /** Delete the chat's remarks whose time has come, and write the record. */
68
+ export declare function sweepDue<C extends Context>(runtime: ScreensRuntime<C>, api: ScreenApi, chat: string, chatId: number): Promise<ScreenChatState>;
69
+ export declare function displayScreen<C extends Context>(runtime: ScreensRuntime<C>, request: DisplayRequest<C>): Promise<void>;
70
+ //# sourceMappingURL=display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/display.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Carrying out a view plan through the Bot API.
3
+ *
4
+ * The plan is what should work; this is what to do when Telegram disagrees.
5
+ * Three refusals are expected in a live chat and none of them is a failure of
6
+ * the screen:
7
+ *
8
+ * - **"message is not modified"** — the edit asked for what is already there
9
+ * (content the record never saw, an adopted message). It is success.
10
+ * - **the message is gone or cannot be edited** — deleted by the user, or not
11
+ * ours. That message and every one after it are sent anew, because a new
12
+ * message lands at the bottom and the order must hold.
13
+ * - **a deletion refused** — Telegram lets a bot delete only messages younger
14
+ * than 48 hours, and a network can drop the call. The view is already right
15
+ * without it; the message loses its buttons instead (an edit has no age
16
+ * limit), so no stale menu stays live, and its id is reported.
17
+ *
18
+ * Anything else — a rate limit, a payload Telegram cannot parse, a network
19
+ * failure — stops the plan. What was already done is not undone: the
20
+ * {@link PlanInterrupted} error carries the messages the chat now shows, with
21
+ * the ones whose content is uncertain marked unknown, so the chat's record is
22
+ * written true and the next render repairs the rest.
23
+ */
24
+ import type { Api } from 'grammy';
25
+ import type { ShownMessage, ViewPlan } from './reconcile.js';
26
+ import type { OutgoingMessage } from './render.js';
27
+ /** The Bot API methods screens call — `ctx.api` provides them. */
28
+ export type ScreenApi = Pick<Api, 'sendMessage' | 'sendRichMessage' | 'sendPhoto' | 'sendVideo' | 'sendAnimation' | 'sendDocument' | 'sendAudio' | 'editMessageText' | 'editMessageCaption' | 'editMessageMedia' | 'editMessageReplyMarkup' | 'deleteMessage' | 'answerCallbackQuery'>;
29
+ export type ChatId = number;
30
+ export interface ExecutionReport {
31
+ readonly sent: number;
32
+ readonly edited: number;
33
+ readonly kept: number;
34
+ readonly deleted: number;
35
+ /** Messages Telegram would not delete; they stay, without buttons. */
36
+ readonly undeleted: readonly number[];
37
+ }
38
+ export interface ExecutedView {
39
+ readonly shown: readonly ShownMessage[];
40
+ readonly report: ExecutionReport;
41
+ }
42
+ /** A plan stopped by a refusal the chat cannot absorb; `shown` is what the chat shows now. */
43
+ export declare class PlanInterrupted extends Error {
44
+ readonly shown: readonly ShownMessage[];
45
+ readonly cause: unknown;
46
+ constructor(shown: readonly ShownMessage[], cause: unknown);
47
+ }
48
+ export declare function sendOutgoing(api: ScreenApi, chatId: ChatId, message: OutgoingMessage): Promise<number>;
49
+ /**
50
+ * Delete messages; a message Telegram will not delete loses its buttons
51
+ * instead. Returns the ids that stayed. Never throws: by the time anything is
52
+ * deleted the new view is in the chat, and failing on this last, optional step
53
+ * would leave the chat's record behind the chat.
54
+ */
55
+ export declare function deleteMessages(api: ScreenApi, chatId: ChatId, ids: readonly number[]): Promise<number[]>;
56
+ export declare function executePlan(api: ScreenApi, chatId: ChatId, plan: ViewPlan): Promise<ExecutedView>;
57
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/execute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAGlC,OAAO,KAAK,EAAY,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,kEAAkE;AAClE,MAAM,MAAM,SAAS,GAAG,IAAI,CAC1B,GAAG,EACD,aAAa,GACb,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,eAAe,GACf,cAAc,GACd,WAAW,GACX,iBAAiB,GACjB,oBAAoB,GACpB,kBAAkB,GAClB,wBAAwB,GACxB,eAAe,GACf,qBAAqB,CACxB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;CAClC;AAED,8FAA8F;AAC9F,qBAAa,eAAgB,SAAQ,KAAK;IAEtC,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE;aACrB,KAAK,EAAE,OAAO;IAFlC,YACW,KAAK,EAAE,SAAS,YAAY,EAAE,EACrB,KAAK,EAAE,OAAO,EAMjC;CACF;AAgBD,wBAAsB,YAAY,CAChC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAyCD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,MAAM,EAAE,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAanB;AAyBD,wBAAsB,WAAW,CAC/B,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,YAAY,CAAC,CAgDvB"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Telegram HTML that cannot be assembled by accident.
3
+ *
4
+ * A screen interpolates values it did not write — a bot's username, an
5
+ * owner's title, a count — into markup it did. With plain strings every one of
6
+ * those is a place where a `<` in somebody's name breaks the message Telegram
7
+ * is asked to parse, or quietly changes what it shows. So markup is a type:
8
+ * the `html` tag escapes every interpolated string and inserts only another
9
+ * `TelegramHtml` as markup, and text the application already holds as Telegram
10
+ * HTML — an owner's stored greeting — enters through `html.raw`, the one place
11
+ * that says "trusted" out loud.
12
+ */
13
+ /** Only `html`, `html.raw` and `html.join` make markup; this key stays in the module. */
14
+ declare const MINT: unique symbol;
15
+ /** Telegram HTML, parsed by Telegram with `parse_mode: 'HTML'`. Made by `html`. */
16
+ export declare class TelegramHtml {
17
+ #private;
18
+ constructor(mint: typeof MINT, markup: string);
19
+ /** The markup as Telegram receives it. */
20
+ toString(): string;
21
+ }
22
+ /** What a screen may put where text goes: plain text, or markup. */
23
+ export type TelegramText = string | TelegramHtml;
24
+ /** A value `html` accepts between its literal parts. */
25
+ export type HtmlValue = string | number | bigint | TelegramHtml | false | null | undefined;
26
+ export interface HtmlTag {
27
+ /** Markup with every interpolated value escaped; a nested `html` stays markup. */
28
+ (literals: TemplateStringsArray, ...values: readonly HtmlValue[]): TelegramHtml;
29
+ /** Markup the application already holds, trusted as it is. */
30
+ raw(markup: string): TelegramHtml;
31
+ /** Several fragments as one, separated by `separator` (escaped unless it is markup). */
32
+ join(parts: readonly HtmlValue[], separator?: string | TelegramHtml): TelegramHtml;
33
+ }
34
+ export declare const html: HtmlTag;
35
+ export {};
36
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,yFAAyF;AACzF,QAAA,MAAM,IAAI,EAAE,OAAO,MAA+B,CAAC;AAEnD,mFAAmF;AACnF,qBAAa,YAAY;;IAGvB,YAAY,IAAI,EAAE,OAAO,IAAI,EAAE,MAAM,EAAE,MAAM,EAO5C;IAED,0CAA0C;IAC1C,QAAQ,IAAI,MAAM,CAEjB;CACF;AAED,oEAAoE;AACpE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,YAAY,CAAC;AAEjD,wDAAwD;AACxD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;AAQ3F,MAAM,WAAW,OAAO;IACtB,kFAAkF;IAClF,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,YAAY,CAAC;IAChF,8DAA8D;IAC9D,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC;IAClC,wFAAwF;IACxF,IAAI,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC;CACpF;AAUD,eAAO,MAAM,IAAI,EAAE,OAUjB,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * What a load, an action or an input answers with.
3
+ *
4
+ * One value, built by chaining, read once by the runtime: where the chat goes
5
+ * next and what it hears on the way. `void` from a handler is `stay()` — show
6
+ * this screen again with fresh data — so a handler that only changes data
7
+ * returns nothing and the screen follows.
8
+ *
9
+ * - `toast` answers the press itself: the small notification Telegram shows
10
+ * over the chat. One per press; the last one wins.
11
+ * - `notice` without a lifetime is a receipt that stays in the chat: it is
12
+ * posted and the screen moves below it, so the conversation reads in order.
13
+ * - `notice` with `expiresInMs` is a remark below the screen that removes
14
+ * itself; the screen stays where it is.
15
+ */
16
+ import type { ActionValue } from './callback-codec.js';
17
+ import type { TelegramText } from './html.js';
18
+ import type { AnyTelegramScreen, ScreenLinkArgs } from './screen-types.js';
19
+ export type ScreenNavigation = {
20
+ readonly type: 'stay';
21
+ } | {
22
+ readonly type: 'back';
23
+ } | {
24
+ readonly type: 'go';
25
+ readonly screen: AnyTelegramScreen;
26
+ readonly params: Readonly<Record<string, ActionValue>>;
27
+ };
28
+ export interface ScreenToast {
29
+ readonly text: string;
30
+ /** Show it as an alert the user must dismiss, not a passing notification. */
31
+ readonly alert: boolean;
32
+ }
33
+ export interface ScreenNotice {
34
+ readonly content: TelegramText;
35
+ /** Removed after this many milliseconds; absent, it stays. */
36
+ readonly expiresInMs?: number;
37
+ }
38
+ export interface NoticeOptions {
39
+ /** Removed after this many milliseconds, at most 2³¹ − 1 (a timer's limit); absent, it stays. */
40
+ readonly expiresInMs?: number;
41
+ }
42
+ export declare class ScreenOutcome {
43
+ #private;
44
+ readonly navigation: ScreenNavigation;
45
+ /** An outcome, told apart from data by its private brand rather than its shape. */
46
+ static is(value: unknown): value is ScreenOutcome;
47
+ readonly toastSpec: ScreenToast | undefined;
48
+ readonly notices: readonly ScreenNotice[];
49
+ constructor(navigation?: ScreenNavigation, toast?: ScreenToast | undefined, notices?: readonly ScreenNotice[]);
50
+ /** Show the current screen again, with fresh data. */
51
+ stay(): ScreenOutcome;
52
+ /** Show another screen. */
53
+ go<TScreen extends AnyTelegramScreen>(screen: TScreen, ...params: ScreenLinkArgs<TScreen>): ScreenOutcome;
54
+ /** Show the parent screen. */
55
+ back(): ScreenOutcome;
56
+ /** Answer the press with a notification (or an alert). */
57
+ toast(text: string, options?: {
58
+ readonly alert?: boolean;
59
+ }): ScreenOutcome;
60
+ /** Post a message: a receipt that stays, or a remark that expires. */
61
+ notice(content: TelegramText, options?: NoticeOptions): ScreenOutcome;
62
+ }
63
+ /** The builders every handler context carries; each starts a fresh outcome. */
64
+ export interface ScreenOutcomeBuilders {
65
+ stay(): ScreenOutcome;
66
+ go<TScreen extends AnyTelegramScreen>(screen: TScreen, ...params: ScreenLinkArgs<TScreen>): ScreenOutcome;
67
+ back(): ScreenOutcome;
68
+ toast(text: string, options?: {
69
+ readonly alert?: boolean;
70
+ }): ScreenOutcome;
71
+ notice(content: TelegramText, options?: NoticeOptions): ScreenOutcome;
72
+ }
73
+ export declare function outcomeBuilders(): ScreenOutcomeBuilders;
74
+ //# sourceMappingURL=outcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/outcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAExE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IACE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;CACxD,CAAC;AAEN,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,iGAAiG;IACjG,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAOD,qBAAa,aAAa;;IAGxB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IAEtC,mFAAmF;IACnF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEhD;IACD,QAAQ,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAE1C,YACE,UAAU,GAAE,gBAAmC,EAC/C,KAAK,GAAE,WAAW,GAAG,SAAqB,EAC1C,OAAO,GAAE,SAAS,YAAY,EAAO,EAKtC;IAED,sDAAsD;IACtD,IAAI,IAAI,aAAa,CAEpB;IAED,2BAA2B;IAC3B,EAAE,CAAC,OAAO,SAAS,iBAAiB,EAClC,MAAM,EAAE,OAAO,EACf,GAAG,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,GACjC,aAAa,CAOf;IAED,8BAA8B;IAC9B,IAAI,IAAI,aAAa,CAEpB;IAED,0DAA0D;IAC1D,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,aAAa,CAa7E;IAED,sEAAsE;IACtE,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,aAAkB,GAAG,aAAa,CAaxE;CACF;AAED,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,IAAI,IAAI,aAAa,CAAC;IACtB,EAAE,CAAC,OAAO,SAAS,iBAAiB,EAClC,MAAM,EAAE,OAAO,EACf,GAAG,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,GACjC,aAAa,CAAC;IACjB,IAAI,IAAI,aAAa,CAAC;IACtB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,aAAa,CAAC;IAC3E,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CAAC;CACvE;AAED,wBAAgB,eAAe,IAAI,qBAAqB,CASvD"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A screen's address: a path whose `:name` segments are its params.
3
+ *
4
+ * The path is the whole navigation model. A screen's parent is the nearest
5
+ * declared screen whose path is a prefix of its own, segment by segment, so
6
+ * "back" is a fact about the tree rather than a history someone has to keep —
7
+ * nothing to lose on a restart, nothing to corrupt when a press arrives from an
8
+ * older message.
9
+ */
10
+ import { type PathParams } from '../../internal/route-pattern.js';
11
+ /** The params a screen path names, as strings (`/bot/:botId` → `{ botId: string }`). */
12
+ export type ScreenPathParams<TPath extends string> = PathParams<TPath>;
13
+ export interface ScreenPath {
14
+ readonly path: string;
15
+ readonly segments: readonly string[];
16
+ /** Param names in path order — the order a button carries them in. */
17
+ readonly params: readonly string[];
18
+ }
19
+ export declare function parseScreenPath(path: string): ScreenPath;
20
+ /** `parent` is a strict prefix of `child`, segment by segment. */
21
+ export declare function isAncestorPath(parent: ScreenPath, child: ScreenPath): boolean;
22
+ /**
23
+ * A short id derived from the path: stable across releases while the path is,
24
+ * and short enough to leave a button room for its params.
25
+ */
26
+ export declare function derivedScreenId(path: string): string;
27
+ /** The concrete chat-facing path, for logs and transitions. */
28
+ export declare function formatScreenPath(path: ScreenPath, params: Readonly<Record<string, string>>): string;
29
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/path.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,8BAA8B,CAAC;AAGlF,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAgBxD;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAG7E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACvC,MAAM,CAMR"}