@llblab/pi-telegram 0.11.1 → 0.12.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 (45) hide show
  1. package/AGENTS.md +17 -12
  2. package/BACKLOG.md +0 -10
  3. package/CHANGELOG.md +33 -2
  4. package/README.md +42 -25
  5. package/api/inbound.ts +14 -0
  6. package/api/keyboard.ts +10 -0
  7. package/api/outbound.ts +11 -0
  8. package/api/sections.ts +17 -0
  9. package/api/updates.ts +11 -0
  10. package/api/voice.ts +24 -0
  11. package/docs/README.md +7 -5
  12. package/docs/architecture.md +176 -135
  13. package/docs/callback-namespaces.md +3 -3
  14. package/docs/command-templates.md +81 -24
  15. package/docs/{inbound-handlers.md → inbound.md} +13 -10
  16. package/docs/locks.md +3 -3
  17. package/docs/{outbound-handlers.md → outbound.md} +13 -10
  18. package/docs/public-api.md +266 -0
  19. package/docs/{extension-sections.md → sections.md} +31 -27
  20. package/docs/ui-style.md +165 -0
  21. package/docs/{external-handlers.md → updates.md} +33 -31
  22. package/docs/voice.md +17 -14
  23. package/index.ts +86 -261
  24. package/lib/bindings.ts +301 -0
  25. package/lib/command-templates.ts +163 -32
  26. package/lib/commands.ts +114 -1
  27. package/lib/config.ts +45 -4
  28. package/lib/{inbound-handlers.ts → inbound.ts} +5 -4
  29. package/lib/lifecycle.ts +122 -1
  30. package/lib/menu-model.ts +3 -3
  31. package/lib/menu-queue.ts +1 -1
  32. package/lib/menu-settings.ts +63 -32
  33. package/lib/menu-status.ts +1 -1
  34. package/lib/menu.ts +1 -1
  35. package/lib/{outbound-handlers.ts → outbound.ts} +21 -11
  36. package/lib/pi.ts +4 -0
  37. package/lib/polling.ts +4 -3
  38. package/lib/preview.ts +1 -1
  39. package/lib/routing.ts +45 -13
  40. package/lib/{extension-sections.ts → sections.ts} +37 -8
  41. package/lib/time-injection.ts +1 -1
  42. package/lib/updates.ts +121 -1
  43. package/lib/voice.ts +33 -14
  44. package/package.json +11 -1
  45. package/lib/external-handlers.ts +0 -166
package/index.ts CHANGED
@@ -5,18 +5,11 @@
5
5
  */
6
6
 
7
7
  import * as Api from "./lib/api.ts";
8
+ import * as Bindings from "./lib/bindings.ts";
8
9
  import * as CommandTemplates from "./lib/command-templates.ts";
9
10
  import * as Commands from "./lib/commands.ts";
10
11
  import * as Config from "./lib/config.ts";
11
- import {
12
- createTelegramExtensionSectionRegistry,
13
- setGlobalTelegramSectionRegistry,
14
- registerTelegramSection,
15
- type TelegramSectionRegistry,
16
- } from "./lib/extension-sections.ts";
17
- import { createTelegramExternalHandleUpdate } from "./lib/external-handlers.ts";
18
- import * as InboundHandlers from "./lib/inbound-handlers.ts";
19
- import * as Keyboard from "./lib/keyboard.ts";
12
+ import * as Inbound from "./lib/inbound.ts";
20
13
  import * as Lifecycle from "./lib/lifecycle.ts";
21
14
  import * as Locks from "./lib/locks.ts";
22
15
  import * as Media from "./lib/media.ts";
@@ -24,63 +17,23 @@ import * as MenuQueue from "./lib/menu-queue.ts";
24
17
  import * as MenuSettings from "./lib/menu-settings.ts";
25
18
  import * as Menu from "./lib/menu.ts";
26
19
  import * as Model from "./lib/model.ts";
27
- import * as OutboundAttachments from "./lib/outbound-attachments.ts";
28
- import * as OutboundHandlers from "./lib/outbound-handlers.ts";
20
+ import * as Outbound from "./lib/outbound.ts";
29
21
  import * as Pi from "./lib/pi.ts";
30
22
  import * as Polling from "./lib/polling.ts";
31
23
  import * as Preview from "./lib/preview.ts";
32
24
  import * as PromptTemplates from "./lib/prompt-templates.ts";
33
- import * as Prompts from "./lib/prompts.ts";
34
25
  import * as Queue from "./lib/queue.ts";
35
26
  import * as Replies from "./lib/replies.ts";
36
27
  import * as Routing from "./lib/routing.ts";
37
28
  import * as Runtime from "./lib/runtime.ts";
38
- import * as Setup from "./lib/setup.ts";
29
+ import * as Sections from "./lib/sections.ts";
39
30
  import * as Status from "./lib/status.ts";
40
31
  import * as TextGroups from "./lib/text-groups.ts";
41
32
  import * as TimeInjection from "./lib/time-injection.ts";
33
+ import * as Updates from "./lib/updates.ts";
42
34
  import * as Voice from "./lib/voice.ts";
43
35
 
44
- const VOICE_EVENT_RECORDER_KEY = "__piTelegramVoiceEventRecorder__";
45
-
46
36
  type ActivePiModel = NonNullable<Pi.ExtensionContext["model"]>;
47
- type RuntimeTelegramQueueItem = Queue.TelegramQueueItem<Pi.ExtensionContext>;
48
-
49
- export {
50
- registerTelegramOutboundHandler,
51
- hasTelegramOutboundHandler,
52
- getTelegramOutboundProgrammaticHandlers,
53
- recordTelegramRuntimeEvent,
54
- } from "./lib/outbound-handlers.ts";
55
-
56
- // --- Voice Integration Exports ---
57
- // Prefer domain imports from ./lib/voice.ts; root exports stay for compatibility.
58
- export {
59
- registerTelegramVoiceSynthesisProvider,
60
- getTelegramVoiceSynthesisProviders,
61
- hasTelegramVoiceSynthesisProvider,
62
- clearTelegramVoiceSynthesisProviders,
63
- planTelegramVoiceReply,
64
- getTelegramVoiceReplyMode,
65
- computeVoiceTurnFlags,
66
- isVoiceTurn,
67
- shouldSuppressPreviewForVoice,
68
- computeVoicePromptContribution,
69
- type TelegramVoiceSynthesisProvider,
70
- type TelegramVoiceTurnView,
71
- type TelegramVoiceSynthesisProviderResult,
72
- type TelegramVoiceReplyMode,
73
- } from "./lib/voice.ts";
74
-
75
- // --- Extension Section Exports ---
76
- export {
77
- registerTelegramSection,
78
- type TelegramSectionRegistration,
79
- type TelegramSectionContext,
80
- type TelegramSectionCallbackContext,
81
- type TelegramSectionView,
82
- type TelegramSectionSettingsRegistration,
83
- } from "./lib/extension-sections.ts";
84
37
 
85
38
  // --- Extension Runtime ---
86
39
 
@@ -96,28 +49,8 @@ export default function (pi: Pi.ExtensionAPI) {
96
49
  const bridgeRuntime = Runtime.createTelegramBridgeRuntime();
97
50
  const { abort, lifecycle, queue, setup, typing } = bridgeRuntime;
98
51
  const configStore = Config.createTelegramConfigStore();
99
- Config.setGlobalTelegramConfigRuntime({
100
- updateVoiceConfig(voice) {
101
- const current = configStore.get();
102
- const next = { ...current, voice: { ...(current.voice ?? {}), ...voice } };
103
- configStore.set(next);
104
- void configStore.persist(next);
105
- },
106
- });
107
- const isProactivePushEnabled =
108
- Config.createTelegramProactivePushChecker(configStore);
109
- const setProactivePushEnabled =
110
- Config.createTelegramProactivePushSetter(configStore);
111
- const getVoiceReplyMode =
112
- Config.createTelegramVoiceReplyModeGetter(configStore);
113
- const isVoiceReplyModeConfigured =
114
- Config.createTelegramVoiceReplyModeConfiguredChecker(configStore);
115
- const setVoiceReplyMode =
116
- Config.createTelegramVoiceReplyModeSetter(configStore);
117
- const getTimeInjectionMode =
118
- Config.createTelegramTimeInjectionModeGetter(configStore);
119
- const setTimeInjectionMode =
120
- Config.createTelegramTimeInjectionModeSetter(configStore);
52
+ Config.bindGlobalTelegramConfigRuntime(configStore);
53
+ const configControls = Config.createTelegramConfigControls(configStore);
121
54
  const lockRuntime = Locks.createTelegramLockRuntime<Pi.ExtensionContext>();
122
55
  const lockOwnershipGuard =
123
56
  Locks.createTelegramLockOwnershipGuard(lockRuntime);
@@ -127,16 +60,13 @@ export default function (pi: Pi.ExtensionAPI) {
127
60
  getActiveTurnChatId: activeTurnRuntime.getChatId,
128
61
  getAllowedUserId: configStore.getAllowedUserId,
129
62
  });
130
- const buttonActionStore = OutboundHandlers.createTelegramButtonActionStore();
63
+ const buttonActionStore = Outbound.createTelegramButtonActionStore();
131
64
  const pendingModelSwitchStore =
132
65
  Model.createPendingModelSwitchStore<
133
66
  Model.ScopedTelegramModel<ActivePiModel>
134
67
  >();
135
68
  const modelMenuRuntime = Menu.createTelegramModelMenuRuntime<ActivePiModel>();
136
- const sectionRegistry: TelegramSectionRegistry =
137
- createTelegramExtensionSectionRegistry();
138
- setGlobalTelegramSectionRegistry(sectionRegistry);
139
-
69
+ const sectionRegistry = Sections.createAndBindTelegramSectionRegistry();
140
70
 
141
71
  const runtimeEvents = Status.createTelegramRuntimeEventRecorder({
142
72
  getBotToken: configStore.getBotToken,
@@ -146,9 +76,7 @@ export default function (pi: Pi.ExtensionAPI) {
146
76
  getConfig: Config.createTelegramTimeConfigGetter(configStore),
147
77
  recordRuntimeEvent,
148
78
  });
149
- (globalThis as Record<string, unknown>)[
150
- VOICE_EVENT_RECORDER_KEY
151
- ] = recordRuntimeEvent;
79
+ Outbound.bindTelegramRuntimeEventRecorder(recordRuntimeEvent);
152
80
  const getContextModel = Pi.getExtensionContextModel;
153
81
  const isIdle = Pi.isExtensionContextIdle;
154
82
  const hasPendingMessages = Pi.hasExtensionContextPendingMessages;
@@ -165,13 +93,14 @@ export default function (pi: Pi.ExtensionAPI) {
165
93
  Queue.createTelegramQueueStore<Pi.ExtensionContext>();
166
94
  const deferredQueueDispatchRuntime =
167
95
  Queue.createTelegramDeferredQueueDispatchRuntime<Pi.ExtensionContext>({
96
+ delayMs: 50,
168
97
  recordRuntimeEvent,
169
98
  });
170
99
  const pollingControllerState = Polling.createTelegramPollingControllerState();
171
100
  const { getStatusLines, updateStatus } =
172
101
  Status.createTelegramBridgeStatusRuntime<
173
102
  Pi.ExtensionContext,
174
- RuntimeTelegramQueueItem
103
+ Queue.TelegramQueueItem<Pi.ExtensionContext>
175
104
  >({
176
105
  getConfig: configStore.get,
177
106
  isPollingActive: Polling.createTelegramPollingActivityReader(
@@ -188,28 +117,23 @@ export default function (pi: Pi.ExtensionAPI) {
188
117
  getRecentRuntimeEvents: runtimeEvents.getEvents,
189
118
  getRuntimeLockState: lockRuntime.getStatusLabel,
190
119
  });
191
- const currentModelRuntime = Model.createCurrentModelRuntime<
192
- Pi.ExtensionContext,
193
- ActivePiModel
194
- >({
120
+ const currentModelRuntime = Model.createCurrentModelRuntime({
195
121
  getContextModel,
196
122
  updateStatus,
197
123
  });
198
- const queueMutationRuntime =
199
- Queue.createTelegramQueueMutationController<Pi.ExtensionContext>({
200
- ...telegramQueueStore,
201
- getNextPriorityReactionOrder: queue.getNextPriorityReactionOrder,
202
- incrementNextPriorityReactionOrder:
203
- queue.incrementNextPriorityReactionOrder,
204
- updateStatus,
205
- });
206
- const inboundHandlerRuntime =
207
- InboundHandlers.createTelegramInboundHandlerRuntime<Pi.ExtensionContext>({
208
- getHandlers: configStore.getInboundHandlers,
209
- execCommand: CommandTemplates.execCommandTemplate,
210
- getCwd: Pi.getExtensionContextCwd,
211
- recordRuntimeEvent,
212
- });
124
+ const queueMutationRuntime = Queue.createTelegramQueueMutationController({
125
+ ...telegramQueueStore,
126
+ getNextPriorityReactionOrder: queue.getNextPriorityReactionOrder,
127
+ incrementNextPriorityReactionOrder:
128
+ queue.incrementNextPriorityReactionOrder,
129
+ updateStatus,
130
+ });
131
+ const inboundHandlerRuntime = Inbound.createTelegramInboundHandlerRuntime({
132
+ getHandlers: configStore.getInboundHandlers,
133
+ execCommand: CommandTemplates.execCommandTemplate,
134
+ getCwd: Pi.getExtensionContextCwd,
135
+ recordRuntimeEvent,
136
+ });
213
137
 
214
138
  // --- Telegram API ---
215
139
 
@@ -234,36 +158,32 @@ export default function (pi: Pi.ExtensionAPI) {
234
158
  recordRuntimeEvent,
235
159
  });
236
160
 
237
- // --- Message Delivery & Preview ---
161
+ // --- Message Delivery ---
238
162
 
239
163
  const sendGuestReply = Replies.createGuestMarkdownReplySender({
240
164
  renderTelegramMessage: Replies.renderTelegramMessage,
241
165
  answerGuestQuery,
242
166
  });
243
167
 
244
- const promptDispatchRuntime =
245
- Runtime.createTelegramPromptDispatchRuntime<Pi.ExtensionContext>({
246
- lifecycle,
247
- typing,
248
- getDefaultChatId: activeTurnRuntime.getChatId,
249
- sendTypingAction,
250
- updateStatus,
251
- recordRuntimeEvent,
252
- });
168
+ const promptDispatchRuntime = Runtime.createTelegramPromptDispatchRuntime({
169
+ lifecycle,
170
+ typing,
171
+ getDefaultChatId: proactivePushChatIdGetter,
172
+ sendTypingAction,
173
+ updateStatus,
174
+ recordRuntimeEvent,
175
+ });
253
176
 
254
- // --- Reply Runtime Wiring ---
177
+ // --- Reply Runtime & Preview ---
255
178
 
256
- const replyRuntime =
257
- Replies.createTelegramRenderedMessageDeliveryRuntime<Keyboard.TelegramInlineKeyboardMarkup>(
258
- {
259
- sendMessage,
260
- editMessage: editTelegramMessageText,
261
- },
262
- );
179
+ const replyRuntime = Replies.createTelegramRenderedMessageDeliveryRuntime({
180
+ sendMessage,
181
+ editMessage: editTelegramMessageText,
182
+ });
263
183
  const { replyTransport, editInteractiveMessage, sendInteractiveMessage } =
264
184
  replyRuntime;
265
185
  const { sendTextReply, sendMarkdownReply } =
266
- OutboundHandlers.createTelegramOutboundTextReplyRuntime({
186
+ Outbound.createTelegramOutboundTextReplyRuntime({
267
187
  sendTextReply: replyRuntime.sendTextReply,
268
188
  sendMarkdownReply: replyRuntime.sendMarkdownReply,
269
189
  execCommand: CommandTemplates.execCommandTemplate,
@@ -271,7 +191,7 @@ export default function (pi: Pi.ExtensionAPI) {
271
191
  recordRuntimeEvent,
272
192
  });
273
193
  const dispatchNextQueuedTelegramTurn =
274
- Queue.createTelegramQueueDispatchRuntime<Pi.ExtensionContext>({
194
+ Queue.createTelegramQueueDispatchRuntime({
275
195
  ...telegramQueueStore,
276
196
  isCompactionInProgress: lifecycle.isCompactionInProgress,
277
197
  hasActiveTurn: activeTurnRuntime.has,
@@ -285,10 +205,7 @@ export default function (pi: Pi.ExtensionAPI) {
285
205
  ...promptDispatchRuntime,
286
206
  sendUserMessage,
287
207
  }).dispatchNext;
288
- const previewRuntime = Preview.createTelegramAssistantPreviewRuntime<
289
- unknown,
290
- Keyboard.TelegramInlineKeyboardMarkup
291
- >({
208
+ const previewRuntime = Preview.createTelegramAssistantPreviewRuntime({
292
209
  getActiveTurn: activeTurnRuntime.get,
293
210
  isAssistantMessage: Replies.isAssistantAgentMessage,
294
211
  getMessageText: Replies.getAgentMessageText,
@@ -301,20 +218,17 @@ export default function (pi: Pi.ExtensionAPI) {
301
218
  ...replyTransport,
302
219
  });
303
220
  const { finalizeMarkdownPreview } =
304
- OutboundHandlers.createTelegramOutboundTextPreviewRuntime({
221
+ Outbound.createTelegramOutboundTextPreviewRuntime({
305
222
  finalizeMarkdownPreview: previewRuntime.finalizeMarkdown,
306
223
  execCommand: CommandTemplates.execCommandTemplate,
307
224
  getHandlers: configStore.getOutboundHandlers,
308
225
  recordRuntimeEvent,
309
226
  });
310
227
 
311
- // --- Bridge Setup ---
228
+ // --- Model And Menu Setup ---
312
229
 
313
230
  const modelSwitchController =
314
- Model.createTelegramModelSwitchControllerRuntime<
315
- Pi.ExtensionContext,
316
- Model.ScopedTelegramModel<ActivePiModel>
317
- >({
231
+ Model.createTelegramModelSwitchControllerRuntime({
318
232
  isIdle,
319
233
  getPendingModelSwitch: pendingModelSwitchStore.get,
320
234
  setPendingModelSwitch: pendingModelSwitchStore.set,
@@ -334,10 +248,7 @@ export default function (pi: Pi.ExtensionAPI) {
334
248
  getCommands,
335
249
  reservedCommandNames: Commands.TELEGRAM_RESERVED_COMMAND_NAMES,
336
250
  });
337
- const menuActions = Menu.createTelegramMenuActionRuntimeWithStateBuilder<
338
- ActivePiModel,
339
- Pi.ExtensionContext
340
- >({
251
+ const menuActions = Menu.createTelegramMenuActionRuntimeWithStateBuilder({
341
252
  runtime: modelMenuRuntime,
342
253
  createSettingsManager: Pi.createSettingsManager,
343
254
  getActiveModel: currentModelRuntime.get,
@@ -358,14 +269,14 @@ export default function (pi: Pi.ExtensionAPI) {
358
269
  sendInteractiveMessage,
359
270
  sectionRegistry,
360
271
 
361
- // Used by the menu/status system to know whether the current turn is a voice reply
272
+ // Menu/status UI uses this to reflect whether the active Telegram turn expects voice delivery.
362
273
  isVoiceReplyActive: function () {
363
274
  const turn = activeTurnRuntime.get();
364
275
  return Voice.isVoiceTurn(turn);
365
276
  },
366
277
  });
367
278
 
368
- // --- Queue Menu ---
279
+ // --- Queue And Settings Menus ---
369
280
 
370
281
  const getQueueMenuState = Menu.createTelegramModelMenuStateBuilder({
371
282
  runtime: modelMenuRuntime,
@@ -392,26 +303,14 @@ export default function (pi: Pi.ExtensionAPI) {
392
303
  editInteractiveMessage,
393
304
  sendInteractiveMessage,
394
305
  answerCallbackQuery,
395
- isProactivePushEnabled,
396
- getVoiceReplyMode,
397
- isVoiceReplyModeConfigured,
398
- getTimeInjectionMode,
399
- setProactivePushEnabled,
400
- setVoiceReplyMode,
401
- setTimeInjectionMode,
306
+ ...configControls,
402
307
  },
403
308
  sectionRegistry,
404
309
  );
405
310
 
406
311
  // --- Polling ---
407
312
 
408
- const inboundRouteRuntime = Routing.createTelegramInboundRouteRuntime<
409
- Api.TelegramUpdate,
410
- Api.TelegramMessage,
411
- Api.TelegramCallbackQuery,
412
- Pi.ExtensionContext,
413
- ActivePiModel
414
- >({
313
+ const inboundRouteRuntime = Routing.createTelegramInboundRouteRuntime({
415
314
  configStore,
416
315
  bridgeRuntime,
417
316
  activeTurnRuntime,
@@ -460,17 +359,14 @@ export default function (pi: Pi.ExtensionAPI) {
460
359
  compact,
461
360
  recordRuntimeEvent,
462
361
  });
463
- const pollingRuntime = Polling.createTelegramPollingControllerRuntime<
464
- Api.TelegramUpdate,
465
- Pi.ExtensionContext
466
- >({
362
+ const pollingRuntime = Polling.createTelegramPollingControllerRuntime({
467
363
  state: pollingControllerState,
468
364
  getConfig: configStore.get,
469
365
  hasBotToken: configStore.hasBotToken,
470
366
  deleteWebhook,
471
367
  getUpdates,
472
368
  persistConfig: configStore.persist,
473
- handleUpdate: createTelegramExternalHandleUpdate({
369
+ handleUpdate: Updates.createTelegramUpdateHandle({
474
370
  defaultHandle: inboundRouteRuntime.handleUpdate,
475
371
  }),
476
372
  stopTypingLoop: typing.stop,
@@ -485,11 +381,7 @@ export default function (pi: Pi.ExtensionAPI) {
485
381
  updateStatus,
486
382
  recordRuntimeEvent,
487
383
  });
488
- const queueSessionLifecycle = Queue.createTelegramSessionLifecycleRuntime<
489
- Pi.ExtensionContext,
490
- RuntimeTelegramQueueItem,
491
- ActivePiModel
492
- >({
384
+ const queueSessionLifecycle = Queue.createTelegramSessionLifecycleRuntime({
493
385
  getCurrentModel: getContextModel,
494
386
  loadConfig: configStore.load,
495
387
  setQueuedItems: telegramQueueStore.setQueuedItems,
@@ -522,117 +414,50 @@ export default function (pi: Pi.ExtensionAPI) {
522
414
 
523
415
  // --- Extension API Bindings ---
524
416
 
525
- OutboundAttachments.registerTelegramOutboundAttachmentTool(pi, {
526
- getActiveTurn: activeTurnRuntime.get,
527
- recordRuntimeEvent,
528
- });
529
-
530
- Commands.registerTelegramBridgeCommands(pi, {
531
- promptForConfig: Setup.createTelegramSetupPromptRuntime({
532
- getConfig: configStore.get,
533
- setConfig: configStore.set,
534
- setupGuard: setup,
535
- getMe: Api.fetchTelegramBotIdentity,
536
- persistConfig: configStore.persist,
537
- startPolling: lockedPollingRuntime.start,
538
- updateStatus,
539
- recordRuntimeEvent,
540
- }),
417
+ Bindings.registerTelegramCommandsAndTools({
418
+ pi,
419
+ configStore,
420
+ setup,
421
+ activeTurnRuntime,
422
+ lockedPollingRuntime,
541
423
  getStatusLines,
542
- reloadConfig: configStore.load,
543
- hasBotToken: configStore.hasBotToken,
544
- startPolling: lockedPollingRuntime.start,
545
- stopPolling: lockedPollingRuntime.stop,
546
424
  updateStatus,
425
+ recordRuntimeEvent,
547
426
  });
548
427
 
549
428
  // --- Lifecycle Hooks ---
550
429
 
551
- const agentEndResetter = Runtime.createTelegramAgentEndResetter({
430
+ Bindings.registerTelegramLifecycleRuntimeHooks({
431
+ pi,
432
+ sessionLifecycleRuntime: {
433
+ ...sessionLifecycleRuntime,
434
+ onModelSelect: currentModelRuntime.onModelSelect,
435
+ },
436
+ queueSessionLifecycle,
437
+ configStore,
552
438
  abort,
553
439
  typing,
554
- clearActiveTurn: activeTurnRuntime.clear,
555
- resetToolExecutions: lifecycle.resetActiveToolExecutions,
556
- clearPendingModelSwitch: modelSwitchController.clearPendingSwitch,
557
- clearDispatchPending: lifecycle.clearDispatchPending,
558
- });
559
- const queuedAttachmentSender =
560
- OutboundAttachments.createTelegramQueuedOutboundAttachmentSender({
561
- sendMultipart: callMultipart,
562
- sendTextReply,
563
- recordRuntimeEvent,
564
- });
565
- const outboundReplyPlanner =
566
- OutboundHandlers.createTelegramOutboundReplyPlanner(buttonActionStore);
567
- const outboundReplyArtifactSender =
568
- OutboundHandlers.createTelegramOutboundReplyArtifactSender({
569
- execCommand: CommandTemplates.execCommandTemplate,
570
- sendMultipart: callMultipart,
571
- sendTextReply,
572
- sendChatAction,
573
- sendRecordVoiceAction,
574
- getHandlers: configStore.getOutboundHandlers,
575
- recordRuntimeEvent,
576
- });
577
- const agentLifecycleHooks = Queue.createTelegramAgentLifecycleHooks<
578
- Queue.PendingTelegramTurn,
579
- Pi.ExtensionContext,
580
- unknown,
581
- Keyboard.TelegramInlineKeyboardMarkup
582
- >({
583
- setAbortHandler: Runtime.createTelegramContextAbortHandlerSetter(abort),
584
- getQueuedItems: telegramQueueStore.getQueuedItems,
585
- hasPendingDispatch: lifecycle.hasDispatchPending,
586
- hasActiveTurn: activeTurnRuntime.has,
587
- resetToolExecutions: lifecycle.resetActiveToolExecutions,
588
- resetPendingModelSwitch: modelSwitchController.clearPendingSwitch,
589
- setQueuedItems: telegramQueueStore.setQueuedItems,
590
- clearDispatchPending: lifecycle.clearDispatchPending,
591
- setActiveTurn: activeTurnRuntime.set,
592
- createPreviewState: previewRuntime.resetState,
593
- startTypingLoop: promptDispatchRuntime.startTypingLoop,
594
- updateStatus,
595
- getActiveTurn: activeTurnRuntime.get,
596
- extractAssistant: Replies.extractLatestAssistantMessageText,
597
- getPreserveQueuedTurnsAsHistory:
598
- lifecycle.shouldPreserveQueuedTurnsAsHistory,
599
- resetRuntimeState: agentEndResetter,
600
- dispatchNextQueuedTelegramTurn,
601
- requestDeferredDispatchNextQueuedTelegramTurn:
602
- deferredQueueDispatchRuntime.request,
603
- clearPreview: previewRuntime.clear,
604
- setPreviewPendingText: previewRuntime.setPendingText,
605
- finalizeMarkdownPreview,
440
+ lifecycle,
441
+ activeTurnRuntime,
442
+ telegramQueueStore,
443
+ modelSwitchController,
444
+ previewRuntime,
445
+ promptDispatchRuntime,
446
+ deferredQueueDispatchRuntime,
447
+ lockOwnershipGuard,
448
+ buttonActionStore,
449
+ callMultipart,
450
+ sendChatAction,
451
+ sendRecordVoiceAction,
606
452
  sendMarkdownReply,
607
453
  sendTextReply,
608
- sendQueuedAttachments: queuedAttachmentSender,
454
+ dispatchNextQueuedTelegramTurn,
609
455
  answerGuestQuery,
610
456
  sendGuestReply,
611
- planOutboundReply: outboundReplyPlanner,
612
- sendOutboundReplyArtifacts: outboundReplyArtifactSender,
613
- isCurrentOwner: lockOwnershipGuard.ownsContext,
614
- getDefaultChatId: proactivePushChatIdGetter,
615
- isProactivePushEnabled,
457
+ finalizeMarkdownPreview,
458
+ proactivePushChatIdGetter,
459
+ isProactivePushEnabled: configControls.isProactivePushEnabled,
460
+ updateStatus,
616
461
  recordRuntimeEvent,
617
- getActiveToolExecutions: lifecycle.getActiveToolExecutions,
618
- setActiveToolExecutions: lifecycle.setActiveToolExecutions,
619
- triggerPendingModelSwitchAbort: modelSwitchController.triggerPendingAbort,
620
- });
621
- // Wire transport-level reply dedup reset via lifecycle
622
- Lifecycle.setResetTransportReplyDedup(Replies.resetTransportReplyDedup);
623
- const agentStartWithDedupReset = Lifecycle.createAgentStartDedupHook(
624
- agentLifecycleHooks.onAgentStart,
625
- );
626
- Lifecycle.registerTelegramLifecycleHooks(pi, {
627
- ...sessionLifecycleRuntime,
628
- ...agentLifecycleHooks,
629
- onAgentStart: agentStartWithDedupReset,
630
- onBeforeAgentStart: Prompts.createTelegramProactiveBeforeAgentStartHook({
631
- isProactivePushEnabled,
632
- isCurrentOwner: lockOwnershipGuard.ownsContext,
633
- }),
634
- onModelSelect: currentModelRuntime.onModelSelect,
635
- onMessageStart: previewRuntime.onMessageStart,
636
- onMessageUpdate: previewRuntime.onMessageUpdate,
637
462
  });
638
463
  }