@llblab/pi-kit 0.29.1 → 0.30.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 (222) hide show
  1. package/BACKLOG.md +3 -1
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +4 -4
  4. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +12 -0
  5. package/node_modules/@llblab/pi-state-flow/README.md +2 -2
  6. package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +2 -2
  7. package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +17 -8
  8. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +7 -3
  9. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +2 -1
  10. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +3 -2
  11. package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
  12. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +3 -3
  13. package/node_modules/@llblab/pi-state-flow/docs/usage.md +3 -2
  14. package/node_modules/@llblab/pi-state-flow/lib/context.ts +17 -8
  15. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +6 -3
  16. package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +4 -2
  17. package/node_modules/@llblab/pi-state-flow/package.json +1 -1
  18. package/node_modules/@llblab/pi-telegram/AGENTS.md +13 -10
  19. package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -1
  20. package/node_modules/@llblab/pi-telegram/CHANGELOG.md +23 -0
  21. package/node_modules/@llblab/pi-telegram/README.md +10 -11
  22. package/node_modules/@llblab/pi-telegram/api/commands.ts +3 -0
  23. package/node_modules/@llblab/pi-telegram/dist/api/commands.d.ts +1 -1
  24. package/node_modules/@llblab/pi-telegram/dist/lib/activity-verbosity.d.ts +1 -5
  25. package/node_modules/@llblab/pi-telegram/dist/lib/activity-verbosity.js +15 -42
  26. package/node_modules/@llblab/pi-telegram/dist/lib/activity.d.ts +9 -0
  27. package/node_modules/@llblab/pi-telegram/dist/lib/activity.js +39 -10
  28. package/node_modules/@llblab/pi-telegram/dist/lib/agent-messages.js +7 -3
  29. package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +43 -5
  30. package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +164 -20
  31. package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.d.ts +12 -0
  32. package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.js +181 -77
  33. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +111 -31
  34. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +1324 -359
  35. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.d.ts +41 -91
  36. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.js +969 -637
  37. package/node_modules/@llblab/pi-telegram/dist/lib/bus-transport.js +16 -9
  38. package/node_modules/@llblab/pi-telegram/dist/lib/bus.d.ts +215 -18
  39. package/node_modules/@llblab/pi-telegram/dist/lib/bus.js +1048 -327
  40. package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.d.ts +5 -0
  41. package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.js +434 -261
  42. package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.d.ts +26 -5
  43. package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.js +92 -176
  44. package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +168 -82
  45. package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +1409 -291
  46. package/node_modules/@llblab/pi-telegram/dist/lib/config.d.ts +1 -8
  47. package/node_modules/@llblab/pi-telegram/dist/lib/config.js +34 -76
  48. package/node_modules/@llblab/pi-telegram/dist/lib/delivery.d.ts +2 -2
  49. package/node_modules/@llblab/pi-telegram/dist/lib/delivery.js +16 -16
  50. package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +642 -170
  51. package/node_modules/@llblab/pi-telegram/dist/lib/generative-app-worker.mjs +19 -7
  52. package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.d.ts +0 -5
  53. package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.js +61 -49
  54. package/node_modules/@llblab/pi-telegram/dist/lib/inbound.d.ts +5 -0
  55. package/node_modules/@llblab/pi-telegram/dist/lib/inbound.js +35 -59
  56. package/node_modules/@llblab/pi-telegram/dist/lib/journal.d.ts +40 -4
  57. package/node_modules/@llblab/pi-telegram/dist/lib/journal.js +2102 -760
  58. package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.d.ts +2 -6
  59. package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.js +75 -58
  60. package/node_modules/@llblab/pi-telegram/dist/lib/locks.d.ts +34 -3
  61. package/node_modules/@llblab/pi-telegram/dist/lib/locks.js +318 -119
  62. package/node_modules/@llblab/pi-telegram/dist/lib/logging.js +50 -14
  63. package/node_modules/@llblab/pi-telegram/dist/lib/media.d.ts +22 -1
  64. package/node_modules/@llblab/pi-telegram/dist/lib/media.js +46 -28
  65. package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.d.ts +19 -5
  66. package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.js +53 -11
  67. package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.d.ts +5 -4
  68. package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.js +45 -63
  69. package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.d.ts +5 -4
  70. package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.js +114 -78
  71. package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.d.ts +1 -1
  72. package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.js +8 -25
  73. package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.d.ts +6 -1
  74. package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.js +14 -21
  75. package/node_modules/@llblab/pi-telegram/dist/lib/menu.d.ts +8 -61
  76. package/node_modules/@llblab/pi-telegram/dist/lib/menu.js +92 -164
  77. package/node_modules/@llblab/pi-telegram/dist/lib/model.d.ts +1 -1
  78. package/node_modules/@llblab/pi-telegram/dist/lib/model.js +2 -16
  79. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.d.ts +6 -27
  80. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.js +45 -38
  81. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-buttons.js +22 -16
  82. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.d.ts +0 -2
  83. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.js +51 -64
  84. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-voice.js +6 -3
  85. package/node_modules/@llblab/pi-telegram/dist/lib/outbound.d.ts +6 -6
  86. package/node_modules/@llblab/pi-telegram/dist/lib/outbound.js +61 -51
  87. package/node_modules/@llblab/pi-telegram/dist/lib/ownership.js +6 -2
  88. package/node_modules/@llblab/pi-telegram/dist/lib/paths.d.ts +5 -0
  89. package/node_modules/@llblab/pi-telegram/dist/lib/paths.js +37 -21
  90. package/node_modules/@llblab/pi-telegram/dist/lib/pi.d.ts +2 -0
  91. package/node_modules/@llblab/pi-telegram/dist/lib/pi.js +8 -1
  92. package/node_modules/@llblab/pi-telegram/dist/lib/polling.d.ts +23 -37
  93. package/node_modules/@llblab/pi-telegram/dist/lib/polling.js +71 -52
  94. package/node_modules/@llblab/pi-telegram/dist/lib/preview.js +39 -19
  95. package/node_modules/@llblab/pi-telegram/dist/lib/process-identity.d.ts +24 -0
  96. package/node_modules/@llblab/pi-telegram/dist/lib/process-identity.js +133 -0
  97. package/node_modules/@llblab/pi-telegram/dist/lib/prompts.js +2 -7
  98. package/node_modules/@llblab/pi-telegram/dist/lib/queue.d.ts +16 -16
  99. package/node_modules/@llblab/pi-telegram/dist/lib/queue.js +261 -116
  100. package/node_modules/@llblab/pi-telegram/dist/lib/recovery.d.ts +2 -83
  101. package/node_modules/@llblab/pi-telegram/dist/lib/recovery.js +20 -274
  102. package/node_modules/@llblab/pi-telegram/dist/lib/replies.d.ts +16 -24
  103. package/node_modules/@llblab/pi-telegram/dist/lib/replies.js +99 -116
  104. package/node_modules/@llblab/pi-telegram/dist/lib/routing.d.ts +121 -7
  105. package/node_modules/@llblab/pi-telegram/dist/lib/routing.js +4750 -1161
  106. package/node_modules/@llblab/pi-telegram/dist/lib/runtime.d.ts +1 -11
  107. package/node_modules/@llblab/pi-telegram/dist/lib/sections.d.ts +4 -29
  108. package/node_modules/@llblab/pi-telegram/dist/lib/sections.js +7 -20
  109. package/node_modules/@llblab/pi-telegram/dist/lib/skills.js +4 -3
  110. package/node_modules/@llblab/pi-telegram/dist/lib/status.js +86 -57
  111. package/node_modules/@llblab/pi-telegram/dist/lib/sync.d.ts +6 -3
  112. package/node_modules/@llblab/pi-telegram/dist/lib/sync.js +112 -45
  113. package/node_modules/@llblab/pi-telegram/dist/lib/target.d.ts +4 -0
  114. package/node_modules/@llblab/pi-telegram/dist/lib/target.js +18 -0
  115. package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.d.ts +18 -11
  116. package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.js +165 -49
  117. package/node_modules/@llblab/pi-telegram/dist/lib/text-groups.js +4 -39
  118. package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.d.ts +6 -27
  119. package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.js +369 -186
  120. package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.d.ts +1 -2
  121. package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.js +58 -38
  122. package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.d.ts +28 -8
  123. package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.js +175 -66
  124. package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.d.ts +42 -16
  125. package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.js +90 -50
  126. package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +88 -24
  127. package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +2276 -842
  128. package/node_modules/@llblab/pi-telegram/dist/lib/time-injection.js +1 -2
  129. package/node_modules/@llblab/pi-telegram/dist/lib/turns.js +1 -19
  130. package/node_modules/@llblab/pi-telegram/dist/lib/updates.d.ts +178 -82
  131. package/node_modules/@llblab/pi-telegram/dist/lib/updates.js +2438 -645
  132. package/node_modules/@llblab/pi-telegram/dist/lib/voice.d.ts +7 -22
  133. package/node_modules/@llblab/pi-telegram/dist/lib/voice.js +7 -22
  134. package/node_modules/@llblab/pi-telegram/dist/lib/wire.js +1 -1
  135. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.d.ts +3 -1
  136. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.js +425 -211
  137. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-identity.js +8 -13
  138. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.d.ts +1 -1
  139. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.js +328 -140
  140. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-slots.js +8 -4
  141. package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
  142. package/node_modules/@llblab/pi-telegram/docs/architecture.md +43 -35
  143. package/node_modules/@llblab/pi-telegram/docs/inbound.md +1 -1
  144. package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +15 -3
  145. package/node_modules/@llblab/pi-telegram/docs/outbound.md +1 -1
  146. package/node_modules/@llblab/pi-telegram/docs/public-api.md +29 -1
  147. package/node_modules/@llblab/pi-telegram/docs/ui-style.md +25 -8
  148. package/node_modules/@llblab/pi-telegram/lib/activity-verbosity.ts +59 -82
  149. package/node_modules/@llblab/pi-telegram/lib/activity.ts +146 -102
  150. package/node_modules/@llblab/pi-telegram/lib/agent-messages.ts +12 -5
  151. package/node_modules/@llblab/pi-telegram/lib/bindings.ts +390 -82
  152. package/node_modules/@llblab/pi-telegram/lib/bus-api.ts +262 -99
  153. package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +2440 -601
  154. package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +2209 -1290
  155. package/node_modules/@llblab/pi-telegram/lib/bus-transport.ts +46 -12
  156. package/node_modules/@llblab/pi-telegram/lib/bus.ts +1673 -444
  157. package/node_modules/@llblab/pi-telegram/lib/channel-posts.ts +848 -327
  158. package/node_modules/@llblab/pi-telegram/lib/command-templates.ts +152 -265
  159. package/node_modules/@llblab/pi-telegram/lib/commands.ts +2398 -555
  160. package/node_modules/@llblab/pi-telegram/lib/config.ts +177 -170
  161. package/node_modules/@llblab/pi-telegram/lib/delivery.ts +41 -29
  162. package/node_modules/@llblab/pi-telegram/lib/extension.ts +1209 -431
  163. package/node_modules/@llblab/pi-telegram/lib/generative-app-worker.mjs +19 -7
  164. package/node_modules/@llblab/pi-telegram/lib/generative-apps.ts +324 -211
  165. package/node_modules/@llblab/pi-telegram/lib/inbound.ts +95 -97
  166. package/node_modules/@llblab/pi-telegram/lib/journal.ts +5329 -1712
  167. package/node_modules/@llblab/pi-telegram/lib/keyboard.ts +1 -3
  168. package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +128 -78
  169. package/node_modules/@llblab/pi-telegram/lib/locks.ts +703 -212
  170. package/node_modules/@llblab/pi-telegram/lib/logging.ts +147 -58
  171. package/node_modules/@llblab/pi-telegram/lib/media.ts +82 -43
  172. package/node_modules/@llblab/pi-telegram/lib/menu-model.ts +85 -18
  173. package/node_modules/@llblab/pi-telegram/lib/menu-queue.ts +88 -129
  174. package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +260 -155
  175. package/node_modules/@llblab/pi-telegram/lib/menu-status.ts +20 -60
  176. package/node_modules/@llblab/pi-telegram/lib/menu-thinking.ts +41 -56
  177. package/node_modules/@llblab/pi-telegram/lib/menu.ts +112 -285
  178. package/node_modules/@llblab/pi-telegram/lib/model.ts +8 -22
  179. package/node_modules/@llblab/pi-telegram/lib/outbound-attachments.ts +156 -125
  180. package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +76 -49
  181. package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +96 -94
  182. package/node_modules/@llblab/pi-telegram/lib/outbound-voice.ts +33 -27
  183. package/node_modules/@llblab/pi-telegram/lib/outbound.ts +125 -125
  184. package/node_modules/@llblab/pi-telegram/lib/ownership.ts +19 -10
  185. package/node_modules/@llblab/pi-telegram/lib/paths.ts +148 -49
  186. package/node_modules/@llblab/pi-telegram/lib/pi.ts +35 -15
  187. package/node_modules/@llblab/pi-telegram/lib/polling.ts +165 -149
  188. package/node_modules/@llblab/pi-telegram/lib/preview.ts +93 -40
  189. package/node_modules/@llblab/pi-telegram/lib/process-identity.ts +164 -0
  190. package/node_modules/@llblab/pi-telegram/lib/prompts.ts +4 -11
  191. package/node_modules/@llblab/pi-telegram/lib/queue.ts +523 -289
  192. package/node_modules/@llblab/pi-telegram/lib/recovery.ts +50 -454
  193. package/node_modules/@llblab/pi-telegram/lib/rendering.ts +1 -3
  194. package/node_modules/@llblab/pi-telegram/lib/replies.ts +248 -209
  195. package/node_modules/@llblab/pi-telegram/lib/routing.ts +8527 -2149
  196. package/node_modules/@llblab/pi-telegram/lib/runtime.ts +1 -12
  197. package/node_modules/@llblab/pi-telegram/lib/sections.ts +24 -89
  198. package/node_modules/@llblab/pi-telegram/lib/setup.ts +1 -3
  199. package/node_modules/@llblab/pi-telegram/lib/skills.ts +9 -4
  200. package/node_modules/@llblab/pi-telegram/lib/status.ts +215 -110
  201. package/node_modules/@llblab/pi-telegram/lib/sync.ts +488 -359
  202. package/node_modules/@llblab/pi-telegram/lib/target.ts +22 -3
  203. package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +322 -122
  204. package/node_modules/@llblab/pi-telegram/lib/text-groups.ts +5 -39
  205. package/node_modules/@llblab/pi-telegram/lib/thread-cleanup-manager.ts +833 -331
  206. package/node_modules/@llblab/pi-telegram/lib/thread-display.ts +213 -97
  207. package/node_modules/@llblab/pi-telegram/lib/thread-naming.ts +232 -87
  208. package/node_modules/@llblab/pi-telegram/lib/thread-reconciler.ts +155 -72
  209. package/node_modules/@llblab/pi-telegram/lib/threads.ts +5329 -1817
  210. package/node_modules/@llblab/pi-telegram/lib/time-injection.ts +1 -4
  211. package/node_modules/@llblab/pi-telegram/lib/turns.ts +15 -28
  212. package/node_modules/@llblab/pi-telegram/lib/updates.ts +5194 -1600
  213. package/node_modules/@llblab/pi-telegram/lib/voice.ts +7 -35
  214. package/node_modules/@llblab/pi-telegram/lib/wire.ts +1 -1
  215. package/node_modules/@llblab/pi-telegram/lib/workspace-admission.ts +996 -416
  216. package/node_modules/@llblab/pi-telegram/lib/workspace-identity.ts +14 -17
  217. package/node_modules/@llblab/pi-telegram/lib/workspace-retirement.ts +878 -376
  218. package/node_modules/@llblab/pi-telegram/lib/workspace-slots.ts +22 -13
  219. package/node_modules/@llblab/pi-telegram/package.json +1 -1
  220. package/package.json +3 -3
  221. package/node_modules/@llblab/pi-telegram/scripts/check-downgrade.mjs +0 -472
  222. package/node_modules/@llblab/pi-telegram/scripts/measure-workspace.mjs +0 -108
@@ -4,16 +4,21 @@
4
4
  * Owns pi-facing tool, command, and lifecycle hook registration for the entrypoint
5
5
  */
6
6
 
7
- import * as Activity from "./activity.ts";
8
7
  import * as ActivityVerbosity from "./activity-verbosity.ts";
8
+ import * as Activity from "./activity.ts";
9
+ import * as BusApi from "./bus-api.ts";
10
+ import type { TelegramBusFollowerCommandOwner } from "./bus-follower.ts";
11
+ import type { TelegramBusLiveRebindWorkState } from "./bus.ts";
9
12
  import * as ChannelPosts from "./channel-posts.ts";
10
13
  import * as CommandTemplates from "./command-templates.ts";
11
14
  import * as Commands from "./commands.ts";
12
15
  import * as Config from "./config.ts";
13
16
  import * as Delivery from "./delivery.ts";
17
+ import * as GenerativeApps from "./generative-apps.ts";
14
18
  import * as Keyboard from "./keyboard.ts";
15
19
  import * as Lifecycle from "./lifecycle.ts";
16
20
  import * as Locks from "./locks.ts";
21
+ import * as Menu from "./menu.ts";
17
22
  import * as Model from "./model.ts";
18
23
  import * as OutboundAttachments from "./outbound-attachments.ts";
19
24
  import * as OutboundHandlers from "./outbound.ts";
@@ -26,9 +31,159 @@ import * as Routing from "./routing.ts";
26
31
  import * as Runtime from "./runtime.ts";
27
32
  import * as Setup from "./setup.ts";
28
33
  import * as Status from "./status.ts";
29
- import * as TelegramApi from "./telegram-api.ts";
30
34
  import type { TelegramTarget } from "./target.ts";
31
- import * as GenerativeApps from "./generative-apps.ts";
35
+ import * as TelegramApi from "./telegram-api.ts";
36
+
37
+ /** Compose any registered held command over captured recipient effects; no ordinary follower API fallback. */
38
+ export function createTelegramFollowerSelectedCommandBinding<
39
+ TContext,
40
+ TModel extends Model.MenuModel = Model.MenuModel,
41
+ >(deps: {
42
+ ctx: TContext;
43
+ operationId: string;
44
+ registrationGeneration: string;
45
+ name: string;
46
+ target: TelegramTarget & { threadId: number };
47
+ recipient: Pick<
48
+ TelegramBusFollowerCommandOwner<TContext>,
49
+ "isCurrent" | "assertRecipientCurrent"
50
+ >;
51
+ command: Pick<
52
+ ReturnType<
53
+ typeof Commands.createTelegramCommandHandlerTargetRuntime<
54
+ Commands.TelegramCommandRuntimeMessage,
55
+ TContext
56
+ >
57
+ >,
58
+ "prepareHeldCommand" | "canPrepareHeldCommand"
59
+ >;
60
+ menu?: Omit<
61
+ Menu.TelegramMenuActionRuntimeDeps<TContext, TModel>,
62
+ "sendTextReply" | "sendInteractiveMessage" | "editInteractiveMessage"
63
+ >;
64
+ deliver: Parameters<
65
+ typeof BusApi.createTelegramSelectedMenuTextApi
66
+ >[0]["deliver"];
67
+ recordOwnership: NonNullable<
68
+ Replies.TelegramRenderedMessageDeliveryRuntimeDeps<Menu.TelegramReplyMarkup>["recordOwnership"]
69
+ >;
70
+ }): TelegramBusFollowerCommandOwner<TContext> | undefined {
71
+ const {
72
+ ctx,
73
+ operationId,
74
+ registrationGeneration,
75
+ name,
76
+ recipient,
77
+ command,
78
+ deliver,
79
+ recordOwnership,
80
+ } = deps,
81
+ target = { ...deps.target };
82
+ const prepare = command.prepareHeldCommand,
83
+ canPrepare = command.canPrepareHeldCommand;
84
+ const isCurrent = recipient.isCurrent,
85
+ assertRecipientCurrent = recipient.assertRecipientCurrent,
86
+ menu = deps.menu,
87
+ menuPorts = menu && { ...menu };
88
+ if (
89
+ [
90
+ prepare,
91
+ canPrepare,
92
+ isCurrent,
93
+ assertRecipientCurrent,
94
+ deliver,
95
+ recordOwnership,
96
+ ].some((port) => typeof port !== "function") ||
97
+ (menuPorts &&
98
+ [
99
+ menuPorts.getModelMenuState,
100
+ menuPorts.storeModelMenuState,
101
+ menuPorts.getActiveModel,
102
+ menuPorts.getThinkingLevel,
103
+ menuPorts.buildStatusHtml,
104
+ menuPorts.isIdle,
105
+ menuPorts.canOfferInFlightModelSwitch,
106
+ ].some((port) => typeof port !== "function"))
107
+ )
108
+ return undefined;
109
+ const portsCurrent = () =>
110
+ deps.ctx === ctx &&
111
+ deps.operationId === operationId &&
112
+ deps.registrationGeneration === registrationGeneration &&
113
+ deps.name === name &&
114
+ deps.recipient === recipient &&
115
+ recipient.isCurrent === isCurrent &&
116
+ recipient.assertRecipientCurrent === assertRecipientCurrent &&
117
+ deps.command === command &&
118
+ command.prepareHeldCommand === prepare &&
119
+ command.canPrepareHeldCommand === canPrepare &&
120
+ deps.deliver === deliver &&
121
+ deps.recordOwnership === recordOwnership &&
122
+ deps.menu === menu &&
123
+ (!menuPorts ||
124
+ Object.entries(menuPorts).every(
125
+ ([key, value]) => Reflect.get(menu!, key) === value,
126
+ ));
127
+ const current = () =>
128
+ portsCurrent() && isCurrent.call(recipient) && portsCurrent();
129
+ if (!current()) return undefined;
130
+ const api = BusApi.createTelegramSelectedMenuTextApi({
131
+ operationId,
132
+ registrationGeneration,
133
+ target,
134
+ assertAuthority: assertRecipientCurrent,
135
+ deliver,
136
+ });
137
+ const rendered =
138
+ Replies.createTelegramRenderedMessageDeliveryRuntime<Menu.TelegramReplyMarkup>(
139
+ {
140
+ sendMessage: api.sendMessage,
141
+ editMessage: api.editMessageText,
142
+ recordOwnership,
143
+ async sendRichMessage() {
144
+ throw new Error(
145
+ "Selected command has no rich or ordinary API fallback.",
146
+ );
147
+ },
148
+ },
149
+ );
150
+ const menus =
151
+ menuPorts &&
152
+ Menu.createTelegramMenuActionRuntime({
153
+ ...menuPorts,
154
+ sendTextReply: rendered.sendTextReply,
155
+ sendInteractiveMessage: rendered.sendInteractiveMessage,
156
+ editInteractiveMessage: rendered.editInteractiveMessage,
157
+ });
158
+ const effects = {
159
+ sendTextReply: rendered.sendTextReply,
160
+ ...(menus ? { showStatus: menus.sendStatusMessage } : {}),
161
+ };
162
+ if (!canPrepare.call(command, name, effects) || !current()) return undefined;
163
+ return {
164
+ isCurrent: current,
165
+ assertRecipientCurrent,
166
+ prepare(readiness, context, input) {
167
+ if (
168
+ !current() ||
169
+ context !== ctx ||
170
+ input.target.chatId !== target.chatId ||
171
+ input.target.threadId !== target.threadId ||
172
+ input.assertRecipientCurrent !== assertRecipientCurrent
173
+ )
174
+ return undefined;
175
+ const plan = prepare.call(
176
+ command,
177
+ name,
178
+ readiness,
179
+ context,
180
+ input,
181
+ effects,
182
+ );
183
+ return current() ? plan : undefined;
184
+ },
185
+ };
186
+ }
32
187
 
33
188
  type ActivePiModel = NonNullable<Pi.ExtensionContext["model"]>;
34
189
 
@@ -116,12 +271,11 @@ export function createTelegramQueueBindingRuntime<TContext>(deps: {
116
271
  };
117
272
  const mutation = Queue.createTelegramQueueMutationController({
118
273
  ...deps.store,
274
+ hasPendingDispatch: deps.lifecycle.hasDispatchPending,
119
275
  allocateLaneOrder: deps.queue.allocateItemOrder,
120
276
  onItemsDiscarded(items, ctx) {
121
277
  if (!settleDiscardedItems(items, ctx)) {
122
- throw new Error(
123
- "Telegram queue items could not be discarded durably.",
124
- );
278
+ throw new Error("Telegram queue items could not be discarded durably.");
125
279
  }
126
280
  },
127
281
  updateStatus: deps.updateStatus,
@@ -187,19 +341,21 @@ export interface TelegramGenerativeAppLiveSurfaceBinding {
187
341
  | GenerativeApps.GenerativeAppLiveSurfaceRuntime<GenerativeApps.TelegramBindLiveHandle>
188
342
  | undefined;
189
343
  set: (
190
- runtime: GenerativeApps.GenerativeAppLiveSurfaceRuntime<GenerativeApps.TelegramBindLiveHandle>
344
+ runtime:
345
+ | GenerativeApps.GenerativeAppLiveSurfaceRuntime<GenerativeApps.TelegramBindLiveHandle>
191
346
  | undefined,
192
347
  ) => void;
193
348
  shutdown: () => void;
194
349
  }
195
350
 
196
- export function createTelegramGenerativeAppLiveSurfaceBinding():
197
- TelegramGenerativeAppLiveSurfaceBinding {
351
+ export function createTelegramGenerativeAppLiveSurfaceBinding(): TelegramGenerativeAppLiveSurfaceBinding {
198
352
  let current:
199
353
  | GenerativeApps.GenerativeAppLiveSurfaceRuntime<GenerativeApps.TelegramBindLiveHandle>
200
354
  | undefined;
201
355
  return {
202
- get() { return current; },
356
+ get() {
357
+ return current;
358
+ },
203
359
  set(runtime) {
204
360
  current?.shutdown();
205
361
  current = runtime;
@@ -213,17 +369,25 @@ TelegramGenerativeAppLiveSurfaceBinding {
213
369
 
214
370
  export function createTelegramGenerativeAppBoundButtonActionInvoker<
215
371
  TQuery extends {
216
- message?: { chat?: { id?: number }; message_id?: number; message_thread_id?: number };
372
+ message?: {
373
+ chat?: { id?: number };
374
+ message_id?: number;
375
+ message_thread_id?: number;
376
+ };
217
377
  },
218
378
  >(deps: {
219
379
  agentDir: string;
220
380
  assertExecutionCurrent: (query: TQuery) => void;
221
- getExecutionFence: (query: TQuery) => GenerativeApps.GenerativeAppExecutionFence | undefined;
381
+ getExecutionFence: (
382
+ query: TQuery,
383
+ ) => GenerativeApps.GenerativeAppExecutionFence | undefined;
222
384
  getActiveProfileName?: () => string | undefined;
223
385
  getLiveSurfaceRuntime?: () =>
224
386
  | GenerativeApps.GenerativeAppLiveSurfaceRuntime<GenerativeApps.TelegramBindLiveHandle>
225
387
  | undefined;
226
- planOutput: ReturnType<typeof OutboundHandlers.createTelegramOutboundReplyPlanner>;
388
+ planOutput: ReturnType<
389
+ typeof OutboundHandlers.createTelegramOutboundReplyPlanner
390
+ >;
227
391
  sendMarkdownReply: (
228
392
  chatId: number,
229
393
  replyToMessageId: number,
@@ -257,16 +421,18 @@ export function createTelegramGenerativeAppBoundButtonActionInvoker<
257
421
  throw new Error("Generative App callback target is unavailable.");
258
422
  }
259
423
  const liveSurfaces = deps.getLiveSurfaceRuntime?.();
260
- handedOff = liveSurfaces?.take(GenerativeApps.getTelegramBindLiveSurfaceKey(
261
- boundAction.app,
262
- deps.getActiveProfileName?.() ?? "default",
263
- {
264
- chatId,
265
- ...(query.message?.message_thread_id !== undefined
266
- ? { threadId: query.message.message_thread_id }
267
- : {}),
268
- },
269
- ));
424
+ handedOff = liveSurfaces?.take(
425
+ GenerativeApps.getTelegramBindLiveSurfaceKey(
426
+ boundAction.app,
427
+ deps.getActiveProfileName?.() ?? "default",
428
+ {
429
+ chatId,
430
+ ...(query.message?.message_thread_id !== undefined
431
+ ? { threadId: query.message.message_thread_id }
432
+ : {}),
433
+ },
434
+ ),
435
+ );
270
436
  const result = await GenerativeApps.invokeGenerativeApp({
271
437
  agentDir: deps.agentDir,
272
438
  ...(deps.getExecutionFence(query)
@@ -423,7 +589,8 @@ export function createTelegramAssistantOutputBindingRuntime<
423
589
  typeof OutboundHandlers.createTelegramAssistantOutputSender<TTransportStamp>
424
590
  >[0];
425
591
  waitForActivityIdle?: () => Promise<void>;
426
- prepareTelegramPreview?: () => Activity.TelegramAssistantOutputPreparation | undefined;
592
+ prepareTelegramPreview?: () =>
593
+ Activity.TelegramAssistantOutputPreparation | undefined;
427
594
  enqueue?: Activity.TelegramActivityPublicationRuntime["enqueue"];
428
595
  recordRuntimeEvent: TelegramRuntimeEventRecorder;
429
596
  }): TelegramAssistantOutputBindingRuntime<TTransportStamp> {
@@ -437,7 +604,8 @@ export function createTelegramAssistantOutputBindingRuntime<
437
604
  const runtime = Activity.createTelegramAssistantOutputRuntime({
438
605
  ...authority,
439
606
  enqueue: deps.enqueue,
440
- prepareSend: (event) => event.source === "telegram" ? deps.prepareTelegramPreview?.() : undefined,
607
+ prepareSend: (event) =>
608
+ event.source === "telegram" ? deps.prepareTelegramPreview?.() : undefined,
441
609
  async send(event, authority, isAuthorityActive) {
442
610
  await deps.waitForActivityIdle?.();
443
611
  if (!isAuthorityActive()) return;
@@ -467,7 +635,13 @@ type TelegramAssistantOutputAuthority<TTransportStamp> = ReturnType<
467
635
  export interface TelegramBridgePublicationRuntime {
468
636
  enqueue: Activity.TelegramActivityPublicationRuntime["enqueue"];
469
637
  reserve: Activity.TelegramActivityPublicationRuntime["reserve"];
470
- capture: () => { target?: Queue.TelegramQueueTarget; isCurrent: () => boolean };
638
+ hasPending: Activity.TelegramActivityPublicationRuntime["hasPending"];
639
+ beginWork: Activity.TelegramActivityPublicationRuntime["beginWork"];
640
+ hasUnconfirmed: Activity.TelegramActivityPublicationRuntime["hasUnconfirmed"];
641
+ capture: () => {
642
+ target?: Queue.TelegramQueueTarget;
643
+ isCurrent: () => boolean;
644
+ };
471
645
  }
472
646
 
473
647
  export interface TelegramActivityBindingRuntime {
@@ -496,11 +670,10 @@ export function createTelegramActivityBindingRuntime<TTransportStamp>(deps: {
496
670
  >;
497
671
  }): TelegramActivityBindingRuntime {
498
672
  const publication = Activity.createTelegramActivityPublicationRuntime();
499
- const assistantOutputBinding =
500
- createTelegramAssistantOutputBindingRuntime({
501
- ...deps.assistantOutput,
502
- enqueue: publication.enqueue,
503
- });
673
+ const assistantOutputBinding = createTelegramAssistantOutputBindingRuntime({
674
+ ...deps.assistantOutput,
675
+ enqueue: publication.enqueue,
676
+ });
504
677
  const activityVerbosityRuntime =
505
678
  ActivityVerbosity.createTelegramActivityVerbosityRuntime({
506
679
  ...deps.activityVerbosity,
@@ -546,17 +719,88 @@ export function createTelegramActivityBindingRuntime<TTransportStamp>(deps: {
546
719
  publicationRuntime: {
547
720
  enqueue: publication.enqueue,
548
721
  reserve: publication.reserve,
722
+ hasPending: publication.hasPending,
723
+ beginWork: publication.beginWork,
724
+ hasUnconfirmed: publication.hasUnconfirmed,
549
725
  capture() {
550
726
  const authority = assistantOutputBinding.authority.captureAuthority();
551
727
  return {
552
728
  target: authority.target ? { ...authority.target } : undefined,
553
- isCurrent: () => assistantOutputBinding.authority.isAuthorityActive(authority),
729
+ isCurrent: () =>
730
+ assistantOutputBinding.authority.isAuthorityActive(authority),
554
731
  };
555
732
  },
556
733
  },
557
734
  };
558
735
  }
559
736
 
737
+ /** Fresh current work projection; a snapshot is not a cleanup grant or target-application ACK. */
738
+ export function createTelegramLiveTargetWorkObserver<TContext>(deps: {
739
+ queue: Pick<Queue.TelegramQueueStateStore<TContext>, "getQueuedItems">;
740
+ activeTurn: Pick<Queue.TelegramActiveTurnStore, "get">;
741
+ lifecycle: Pick<
742
+ Runtime.TelegramBridgeRuntime["lifecycle"],
743
+ "hasDispatchPending" | "isCompactionInProgress" | "getActiveToolExecutions"
744
+ >;
745
+ isIdle(ctx: TContext): boolean;
746
+ hasPendingMessages(ctx: TContext): boolean;
747
+ hasPendingControl(): boolean;
748
+ publication: Pick<
749
+ TelegramBridgePublicationRuntime,
750
+ "hasPending" | "hasUnconfirmed"
751
+ >;
752
+ activity: Pick<Activity.TelegramActivityRuntime, "hasPending">;
753
+ delivery: Pick<
754
+ ReturnType<typeof Delivery.createTelegramDeliveryLifecycleHooks>,
755
+ "hasPendingTarget"
756
+ >;
757
+ api: Pick<TelegramApi.TelegramApiTargetActivityRuntime, "hasPendingTarget">;
758
+ }): (
759
+ target: TelegramTarget & { threadId: number },
760
+ ctx: TContext,
761
+ ) => TelegramBusLiveRebindWorkState {
762
+ return (target, ctx) => {
763
+ const work = Queue.observeTelegramTargetQueueWork(
764
+ target,
765
+ deps.activeTurn.get(),
766
+ deps.queue.getQueuedItems(),
767
+ );
768
+ const flags = [
769
+ deps.isIdle(ctx),
770
+ deps.hasPendingMessages(ctx),
771
+ deps.lifecycle.hasDispatchPending(),
772
+ deps.lifecycle.isCompactionInProgress(),
773
+ deps.hasPendingControl(),
774
+ ];
775
+ const tools = deps.lifecycle.getActiveToolExecutions();
776
+ const publication = deps.publication.hasPending(),
777
+ unconfirmed = deps.publication.hasUnconfirmed?.(),
778
+ activity = deps.activity.hasPending?.(),
779
+ delivery = deps.delivery.hasPendingTarget(target),
780
+ api = deps.api.hasPendingTarget(target);
781
+ const unknown =
782
+ work.unknown ||
783
+ flags.some((flag) => typeof flag !== "boolean") ||
784
+ !Number.isSafeInteger(tools) ||
785
+ tools < 0 ||
786
+ unconfirmed !== false ||
787
+ [publication, activity, delivery, api].some(
788
+ (flag) => typeof flag !== "boolean",
789
+ );
790
+ return {
791
+ sessionBusy:
792
+ flags[0] !== true || flags.slice(1).some(Boolean) || tools > 0,
793
+ targetWork: work.protected,
794
+ deliveryPending:
795
+ publication === true ||
796
+ activity === true ||
797
+ delivery === true ||
798
+ api === true,
799
+ unknown,
800
+ };
801
+ };
802
+ }
803
+
560
804
  interface TelegramCommandsAndToolsBindingDeps {
561
805
  pi: Pi.ExtensionAPI;
562
806
  agentDir: string;
@@ -566,7 +810,6 @@ interface TelegramCommandsAndToolsBindingDeps {
566
810
  activeTurnRuntime: Queue.TelegramActiveTurnStore<Queue.PendingTelegramTurn>;
567
811
  lockedPollingRuntime: Locks.TelegramLockedPollingRuntime<Pi.ExtensionContext>;
568
812
  stopPolling?: () => Promise<void | string>;
569
- recoverPollingStart?: Commands.TelegramBridgeCommandRegistrationDeps["recoverPollingStart"];
570
813
  getDisconnectThreadName?: () => string | undefined;
571
814
  onTransportChanged?: () => Promise<void> | void;
572
815
  getStatusLines: (
@@ -589,8 +832,12 @@ interface TelegramCommandsAndToolsBindingDeps {
589
832
  OutboundAttachments.TelegramOutboundMessageToolRegistrationDeps["sendChannelMediaMessage"]
590
833
  >;
591
834
  listChannelPosts: ChannelPosts.TelegramChannelPostJournalStore["list"];
592
- mutateChannelPost(input: { action: "edit" | "delete"; operationId: string;
593
- mutationId: string; markdown?: string }): Promise<ChannelPosts.TelegramChannelPostRecord>;
835
+ mutateChannelPost(input: {
836
+ action: "edit" | "delete";
837
+ operationId: string;
838
+ mutationId: string;
839
+ markdown?: string;
840
+ }): Promise<ChannelPosts.TelegramChannelPostRecord>;
594
841
  callMultipart: OutboundHandlers.TelegramVoiceReplySenderDeps["sendMultipart"];
595
842
  getDefaultChatId: () => number | undefined;
596
843
  getDefaultTarget?: () => OutboundAttachments.TelegramQueuedOutboundAttachmentTurnView["target"];
@@ -598,13 +845,16 @@ interface TelegramCommandsAndToolsBindingDeps {
598
845
  routeAgentMessage?: OutboundAttachments.TelegramOutboundMessageToolRegistrationDeps["routeAgentMessage"];
599
846
  canSendDirect: () => boolean;
600
847
  setGenerativeAppLiveSurfaceRuntime?: (
601
- runtime: GenerativeApps.GenerativeAppLiveSurfaceRuntime<GenerativeApps.TelegramBindLiveHandle>
848
+ runtime:
849
+ | GenerativeApps.GenerativeAppLiveSurfaceRuntime<GenerativeApps.TelegramBindLiveHandle>
602
850
  | undefined,
603
851
  ) => void;
604
852
  updateStatus: TelegramBridgeStatusUpdater;
605
853
  isContextCurrent: (ctx: Pi.ExtensionContext) => boolean;
606
854
  getSessionGeneration: () => number;
607
- connectionIntent: NonNullable<Commands.TelegramBridgeCommandRegistrationDeps["connectionIntent"]>;
855
+ connectionIntent: NonNullable<
856
+ Commands.TelegramBridgeCommandRegistrationDeps["connectionIntent"]
857
+ >;
608
858
  recordRuntimeEvent: TelegramRuntimeEventRecorder;
609
859
  }
610
860
 
@@ -617,7 +867,6 @@ export function registerTelegramCommandsAndTools({
617
867
  activeTurnRuntime,
618
868
  lockedPollingRuntime,
619
869
  stopPolling,
620
- recoverPollingStart,
621
870
  getDisconnectThreadName,
622
871
  onTransportChanged,
623
872
  getStatusLines,
@@ -648,23 +897,27 @@ export function registerTelegramCommandsAndTools({
648
897
  ? { setLiveSurfaceRuntime: setGenerativeAppLiveSurfaceRuntime }
649
898
  : {}),
650
899
  isDeliveryHandleCurrent: Delivery.isTelegramDeliveryHandleCurrent,
651
- editView: (handle, view) => Delivery.editTelegramView(
652
- handle as Delivery.TelegramDeliveryHandle,
653
- view as Delivery.TelegramDeliveryView,
654
- ),
900
+ editView: (handle, view) =>
901
+ Delivery.editTelegramView(
902
+ handle as Delivery.TelegramDeliveryHandle,
903
+ view as Delivery.TelegramDeliveryView,
904
+ ),
655
905
  planOutput: OutboundHandlers.createTelegramOutboundReplyPlanner(
656
906
  buttonActionStore,
657
- Config.createTelegramConfigControls(configStore).getAssistantRenderingMode,
907
+ Config.createTelegramConfigControls(configStore)
908
+ .getAssistantRenderingMode,
658
909
  ),
659
910
  sendMarkdownReply,
660
- sendView: (view, options) => Delivery.sendTelegramView(
661
- view as Delivery.TelegramDeliveryView,
662
- options,
663
- ),
911
+ sendView: (view, options) =>
912
+ Delivery.sendTelegramView(view as Delivery.TelegramDeliveryView, options),
664
913
  recordRuntimeEvent,
665
914
  });
666
- ChannelPosts.registerTelegramChannelPostMutationTool(pi, { mutate: mutateChannelPost });
667
- ChannelPosts.registerTelegramChannelPostListTool(pi, { list: listChannelPosts });
915
+ ChannelPosts.registerTelegramChannelPostMutationTool(pi, {
916
+ mutate: mutateChannelPost,
917
+ });
918
+ ChannelPosts.registerTelegramChannelPostListTool(pi, {
919
+ list: listChannelPosts,
920
+ });
668
921
  OutboundAttachments.registerTelegramOutboundAttachmentTool(pi, {
669
922
  getActiveTurn: activeTurnRuntime.get,
670
923
  getDefaultChatId,
@@ -680,11 +933,11 @@ export function registerTelegramCommandsAndTools({
680
933
  resolveAgentTarget,
681
934
  routeAgentMessage,
682
935
  canSendDirect,
683
- planMessage:
684
- OutboundHandlers.createTelegramOutboundReplyPlanner(
685
- buttonActionStore,
686
- Config.createTelegramConfigControls(configStore).getAssistantRenderingMode,
687
- ),
936
+ planMessage: OutboundHandlers.createTelegramOutboundReplyPlanner(
937
+ buttonActionStore,
938
+ Config.createTelegramConfigControls(configStore)
939
+ .getAssistantRenderingMode,
940
+ ),
688
941
  sendMarkdownMessage: (chatId, markdown, options) =>
689
942
  sendMarkdownReply(chatId, undefined, markdown, options),
690
943
  sendChannelMarkdownMessage,
@@ -747,7 +1000,8 @@ export function registerTelegramCommandsAndTools({
747
1000
  );
748
1001
  }
749
1002
  await configStore.load();
750
- const latestProfile = configStore.getStoredConfig().profiles?.[profileName];
1003
+ const latestProfile =
1004
+ configStore.getStoredConfig().profiles?.[profileName];
751
1005
  configStore.setProfile(profileName, {
752
1006
  ...profile,
753
1007
  threadDisplayMode: latestProfile?.threadDisplayMode,
@@ -781,7 +1035,10 @@ export function registerTelegramCommandsAndTools({
781
1035
  if (completion.status === "success") {
782
1036
  queueAgentConnectionContext(true);
783
1037
  if (profileName) {
784
- ctx.ui.notify(`Profile "${profileName}" saved and connected.`, "info");
1038
+ ctx.ui.notify(
1039
+ `Profile "${profileName}" saved and connected.`,
1040
+ "info",
1041
+ );
785
1042
  }
786
1043
  }
787
1044
  },
@@ -790,9 +1047,9 @@ export function registerTelegramCommandsAndTools({
790
1047
  hasBotToken: configStore.hasBotToken,
791
1048
  getBotTokenDiagnostic: configStore.getBotTokenDiagnostic,
792
1049
  startPolling: lockedPollingRuntime.start,
793
- recordConnectionEvent: (error, phase) => recordRuntimeEvent("connection", error, { phase }),
1050
+ recordConnectionEvent: (error, phase) =>
1051
+ recordRuntimeEvent("connection", error, { phase }),
794
1052
  stopPolling: stopPolling ?? lockedPollingRuntime.stop,
795
- recoverPollingStart,
796
1053
  getDisconnectThreadName,
797
1054
  queueAgentConnectionContext,
798
1055
  updateStatus,
@@ -838,7 +1095,11 @@ interface TelegramLifecycleBindingDeps {
838
1095
  diagnostics?: { onSessionStart(): void; onSessionShutdown(): Promise<void> };
839
1096
  assistantOutputRuntime: Pick<
840
1097
  Activity.TelegramAssistantOutputRuntime,
841
- "start" | "beginTurn" | "hasAdmittedTelegramIntermediate" | "waitForIdle" | "stop"
1098
+ | "start"
1099
+ | "beginTurn"
1100
+ | "hasAdmittedTelegramIntermediate"
1101
+ | "waitForIdle"
1102
+ | "stop"
842
1103
  >;
843
1104
  sessionLifecycleRuntime: Pick<
844
1105
  Lifecycle.TelegramLifecycleRegistrationDeps,
@@ -865,7 +1126,10 @@ interface TelegramLifecycleBindingDeps {
865
1126
  deferredQueueDispatchRuntime: Queue.TelegramDeferredQueueDispatchRuntime<Pi.ExtensionContext>;
866
1127
  modelContextAvailabilityRuntime: Prompts.TelegramModelContextAvailabilityRuntime;
867
1128
  disconnectOnQuit?: () => Promise<unknown>;
868
- onSessionStarted?: (event: Pi.SessionStartEvent, ctx: Pi.ExtensionContext) => void;
1129
+ onSessionStarted?: (
1130
+ event: Pi.SessionStartEvent,
1131
+ ctx: Pi.ExtensionContext,
1132
+ ) => void;
869
1133
  shutdownGenerativeAppLiveSurfaces?: () => void;
870
1134
  resolveAutomaticThreadCleanupEnabled?: () => boolean | Promise<boolean>;
871
1135
  buttonActionStore: OutboundHandlers.TelegramButtonActionStore;
@@ -1112,16 +1376,20 @@ export function registerTelegramLifecycleRuntimeHooks({
1112
1376
  { replyToPrompt: false },
1113
1377
  );
1114
1378
  };
1115
- let pendingFinalPublication: {
1116
- turn: Queue.PendingTelegramTurn;
1117
- reservation: Activity.TelegramActivityPublicationReservation;
1118
- } | undefined;
1379
+ let pendingFinalPublication:
1380
+ | {
1381
+ turn: Queue.PendingTelegramTurn;
1382
+ reservation: Activity.TelegramActivityPublicationReservation;
1383
+ }
1384
+ | undefined;
1119
1385
  const cancelPendingFinalPublication = (): void => {
1120
1386
  pendingFinalPublication?.reservation.cancel();
1121
1387
  pendingFinalPublication = undefined;
1122
1388
  };
1123
1389
  const recordPublicationFailure = (error: unknown): void => {
1124
- recordRuntimeEvent("delivery", error, { phase: "agent-end-background-delivery" });
1390
+ recordRuntimeEvent("delivery", error, {
1391
+ phase: "agent-end-background-delivery",
1392
+ });
1125
1393
  };
1126
1394
  const scheduleActiveTurnDelivery = (task: () => Promise<void>): void => {
1127
1395
  void publicationRuntime.enqueue(task).catch(recordPublicationFailure);
@@ -1158,7 +1426,8 @@ export function registerTelegramLifecycleRuntimeHooks({
1158
1426
  loadConfig: configStore.load,
1159
1427
  extractAssistant: Replies.extractRunAssistantMessage,
1160
1428
  isAssistantAlreadyPublished: (assistant) =>
1161
- !!assistant.text && assistantOutputRuntime.hasAdmittedTelegramIntermediate(assistant.text),
1429
+ !!assistant.text &&
1430
+ assistantOutputRuntime.hasAdmittedTelegramIntermediate(assistant.text),
1162
1431
  getFoldQueuedPromptsIntoHistory:
1163
1432
  lifecycle.shouldFoldQueuedPromptsIntoHistory,
1164
1433
  resetRuntimeState: agentEndResetter,
@@ -1174,9 +1443,12 @@ export function registerTelegramLifecycleRuntimeHooks({
1174
1443
  pendingFinalPublication = undefined;
1175
1444
  const matches = pending?.turn === activeTurnRuntime.get();
1176
1445
  if (!matches) pending?.reservation.cancel();
1177
- const reservation = matches && pending ? pending.reservation : publicationRuntime.reserve();
1446
+ const reservation =
1447
+ matches && pending ? pending.reservation : publicationRuntime.reserve();
1178
1448
  return {
1179
- schedule: (task) => { void reservation.publish(task).catch(recordPublicationFailure); },
1449
+ schedule: (task) => {
1450
+ void reservation.publish(task).catch(recordPublicationFailure);
1451
+ },
1180
1452
  cancel: reservation.cancel,
1181
1453
  };
1182
1454
  },
@@ -1202,9 +1474,9 @@ export function registerTelegramLifecycleRuntimeHooks({
1202
1474
  setActiveToolExecutions: lifecycle.setActiveToolExecutions,
1203
1475
  triggerPendingModelSwitchAbort: modelSwitchController.triggerPendingAbort,
1204
1476
  });
1205
- Lifecycle.setResetTransportReplyDedup(Replies.resetTransportReplyDedup);
1206
1477
  const agentStartWithDedupReset = Lifecycle.createAgentStartDedupHook(
1207
1478
  agentLifecycleHooks.onAgentStart,
1479
+ Replies.resetTransportReplyDedup,
1208
1480
  scheduleActiveTurnDelivery,
1209
1481
  );
1210
1482
  let uiPromptActive = false;
@@ -1229,23 +1501,32 @@ export function registerTelegramLifecycleRuntimeHooks({
1229
1501
  };
1230
1502
  let observedAutomaticCompaction = false;
1231
1503
  let agentWorkActive = false;
1232
- const prepareCompactionNotice = (text: string, ctx: Pi.ExtensionContext): (() => Promise<void>) => {
1504
+ const prepareCompactionNotice = (
1505
+ text: string,
1506
+ ctx: Pi.ExtensionContext,
1507
+ ): (() => Promise<void>) => {
1233
1508
  const authority = publicationRuntime.capture();
1234
1509
  const turn = activeTurnRuntime.get();
1235
1510
  const selectedTarget = turn?.target ?? authority.target;
1236
1511
  const target = selectedTarget ? { ...selectedTarget } : undefined;
1237
1512
  const replyToMessageId = turn?.replyToMessageId;
1238
1513
  return async () => {
1239
- if (!target || !isSessionContextActive(ctx) || !authority.isCurrent()) return;
1514
+ if (!target || !isSessionContextActive(ctx) || !authority.isCurrent())
1515
+ return;
1240
1516
  if (turn && isTurnTransportActive?.(turn) === false) return;
1241
1517
  try {
1242
- await sendMarkdownReply(target.chatId, replyToMessageId, text, { target });
1518
+ await sendMarkdownReply(target.chatId, replyToMessageId, text, {
1519
+ target,
1520
+ });
1243
1521
  } catch (error) {
1244
1522
  recordRuntimeEvent("delivery", error, { phase: "compaction-notice" });
1245
1523
  }
1246
1524
  };
1247
1525
  };
1248
- const sendCompactionNotice = (text: string, ctx: Pi.ExtensionContext): void => {
1526
+ const sendCompactionNotice = (
1527
+ text: string,
1528
+ ctx: Pi.ExtensionContext,
1529
+ ): void => {
1249
1530
  scheduleActiveTurnDelivery(prepareCompactionNotice(text, ctx));
1250
1531
  };
1251
1532
  const compactionObserver = Lifecycle.createTelegramCompactionObserverRuntime({
@@ -1324,7 +1605,11 @@ export function registerTelegramLifecycleRuntimeHooks({
1324
1605
  if (shouldNotify) observedAutomaticCompaction = true;
1325
1606
  activityRuntime.onCompactionStart(Pi.getSessionCompactionReason(event));
1326
1607
  compactionObserver.onSessionBeforeCompact(event, ctx);
1327
- if (shouldNotify) sendCompactionNotice(Commands.TELEGRAM_COMPACTION_STARTED_MARKDOWN, ctx);
1608
+ if (shouldNotify)
1609
+ sendCompactionNotice(
1610
+ Commands.TELEGRAM_COMPACTION_STARTED_MARKDOWN,
1611
+ ctx,
1612
+ );
1328
1613
  },
1329
1614
  async onSessionCompact(event, ctx) {
1330
1615
  if (!isSessionContextActive(ctx)) return;
@@ -1332,7 +1617,10 @@ export function registerTelegramLifecycleRuntimeHooks({
1332
1617
  compactionObserver.onSessionCompact(event, ctx);
1333
1618
  if (observedAutomaticCompaction) {
1334
1619
  observedAutomaticCompaction = false;
1335
- sendCompactionNotice(Commands.TELEGRAM_COMPACTION_COMPLETED_MARKDOWN, ctx);
1620
+ sendCompactionNotice(
1621
+ Commands.TELEGRAM_COMPACTION_COMPLETED_MARKDOWN,
1622
+ ctx,
1623
+ );
1336
1624
  }
1337
1625
  },
1338
1626
  async onSessionCompactFailed(event, ctx) {
@@ -1400,13 +1688,29 @@ export function registerTelegramLifecycleRuntimeHooks({
1400
1688
  previewRuntime.seal();
1401
1689
  activityRuntime.onAssistantMessageEnd(event.message.stopReason);
1402
1690
  }
1403
- if (event.message.role !== "assistant" || event.message.stopReason === "toolUse" || event.message.stopReason === "aborted") return;
1691
+ if (
1692
+ event.message.role !== "assistant" ||
1693
+ event.message.stopReason === "toolUse" ||
1694
+ event.message.stopReason === "aborted"
1695
+ )
1696
+ return;
1404
1697
  const turn = activeTurnRuntime.get();
1405
- if (!turn || turn.guestQueryId || pendingFinalPublication?.turn === turn) return;
1698
+ if (!turn || turn.guestQueryId || pendingFinalPublication?.turn === turn)
1699
+ return;
1406
1700
  cancelPendingFinalPublication();
1407
- const assistant = Replies.extractLatestAssistantMessageText([event.message]);
1408
- if (!assistant.text && assistant.stopReason !== "error" && turn.queuedAttachments.length === 0) return;
1409
- pendingFinalPublication = { turn, reservation: publicationRuntime.reserve() };
1701
+ const assistant = Replies.extractLatestAssistantMessageText([
1702
+ event.message,
1703
+ ]);
1704
+ if (
1705
+ !assistant.text &&
1706
+ assistant.stopReason !== "error" &&
1707
+ turn.queuedAttachments.length === 0
1708
+ )
1709
+ return;
1710
+ pendingFinalPublication = {
1711
+ turn,
1712
+ reservation: publicationRuntime.reserve(),
1713
+ };
1410
1714
  },
1411
1715
  onUiPromptStart(event, ctx) {
1412
1716
  if (!isSessionContextActive(ctx)) return;
@@ -1426,7 +1730,10 @@ export function registerTelegramLifecycleRuntimeHooks({
1426
1730
  },
1427
1731
  async onAgentEnd(event, ctx) {
1428
1732
  if (!isSessionContextActive(ctx)) return;
1429
- if (pendingFinalPublication && pendingFinalPublication.turn !== activeTurnRuntime.get()) {
1733
+ if (
1734
+ pendingFinalPublication &&
1735
+ pendingFinalPublication.turn !== activeTurnRuntime.get()
1736
+ ) {
1430
1737
  cancelPendingFinalPublication();
1431
1738
  return;
1432
1739
  }
@@ -1439,7 +1746,8 @@ export function registerTelegramLifecycleRuntimeHooks({
1439
1746
  try {
1440
1747
  await agentLifecycleHooks.onAgentSettled(event, ctx);
1441
1748
  } finally {
1442
- if (pendingFinalPublication === pending) cancelPendingFinalPublication();
1749
+ if (pendingFinalPublication === pending)
1750
+ cancelPendingFinalPublication();
1443
1751
  }
1444
1752
  if (!isSessionContextActive(ctx)) return;
1445
1753
  agentWorkActive = false;