@llblab/pi-telegram 0.7.1 → 0.8.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.
package/index.ts CHANGED
@@ -5,18 +5,19 @@
5
5
  */
6
6
 
7
7
  import * as Api from "./lib/api.ts";
8
- import * as AttachmentHandlers from "./lib/attachment-handlers.ts";
9
- import * as Attachments from "./lib/attachments.ts";
10
- import * as Commands from "./lib/commands.ts";
8
+ import * as OutboundAttachments from "./lib/outbound-attachments.ts";
11
9
  import * as CommandTemplates from "./lib/command-templates.ts";
10
+ import * as Commands from "./lib/commands.ts";
12
11
  import * as Config from "./lib/config.ts";
12
+ import * as InboundHandlers from "./lib/inbound-handlers.ts";
13
13
  import * as Keyboard from "./lib/keyboard.ts";
14
14
  import * as Lifecycle from "./lib/lifecycle.ts";
15
15
  import * as Locks from "./lib/locks.ts";
16
16
  import * as Media from "./lib/media.ts";
17
- import * as Menu from "./lib/menu.ts";
18
17
  import * as MenuQueue from "./lib/menu-queue.ts";
18
+ import * as Menu from "./lib/menu.ts";
19
19
  import * as Model from "./lib/model.ts";
20
+ import * as OutboundHandlers from "./lib/outbound-handlers.ts";
20
21
  import * as Pi from "./lib/pi.ts";
21
22
  import * as Polling from "./lib/polling.ts";
22
23
  import * as Preview from "./lib/preview.ts";
@@ -24,11 +25,11 @@ import * as PromptTemplates from "./lib/prompt-templates.ts";
24
25
  import * as Prompts from "./lib/prompts.ts";
25
26
  import * as Queue from "./lib/queue.ts";
26
27
  import * as Replies from "./lib/replies.ts";
27
- import * as Runtime from "./lib/runtime.ts";
28
28
  import * as Routing from "./lib/routing.ts";
29
+ import * as Runtime from "./lib/runtime.ts";
29
30
  import * as Setup from "./lib/setup.ts";
30
- import * as OutboundHandlers from "./lib/outbound-handlers.ts";
31
31
  import * as Status from "./lib/status.ts";
32
+ import * as TextGroups from "./lib/text-groups.ts";
32
33
 
33
34
  type ActivePiModel = NonNullable<Pi.ExtensionContext["model"]>;
34
35
  type RuntimeTelegramQueueItem = Queue.TelegramQueueItem<Pi.ExtensionContext>;
@@ -67,6 +68,10 @@ export default function (pi: Pi.ExtensionAPI) {
67
68
  Api.TelegramMessage,
68
69
  Pi.ExtensionContext
69
70
  >();
71
+ const textGroupRuntime = TextGroups.createTelegramTextGroupController<
72
+ Api.TelegramMessage,
73
+ Pi.ExtensionContext
74
+ >();
70
75
  const telegramQueueStore =
71
76
  Queue.createTelegramQueueStore<Pi.ExtensionContext>();
72
77
  const deferredQueueDispatchRuntime =
@@ -109,15 +114,13 @@ export default function (pi: Pi.ExtensionAPI) {
109
114
  queue.incrementNextPriorityReactionOrder,
110
115
  updateStatus,
111
116
  });
112
- const attachmentHandlerRuntime =
113
- AttachmentHandlers.createTelegramAttachmentHandlerRuntime<Pi.ExtensionContext>(
114
- {
115
- getHandlers: configStore.getAttachmentHandlers,
116
- execCommand: CommandTemplates.execCommandTemplate,
117
- getCwd: Pi.getExtensionContextCwd,
118
- recordRuntimeEvent,
119
- },
120
- );
117
+ const inboundHandlerRuntime =
118
+ InboundHandlers.createTelegramInboundHandlerRuntime<Pi.ExtensionContext>({
119
+ getHandlers: configStore.getInboundHandlers,
120
+ execCommand: CommandTemplates.execCommandTemplate,
121
+ getCwd: Pi.getExtensionContextCwd,
122
+ recordRuntimeEvent,
123
+ });
121
124
 
122
125
  // --- Telegram API ---
123
126
 
@@ -152,19 +155,23 @@ export default function (pi: Pi.ExtensionAPI) {
152
155
 
153
156
  // --- Reply Runtime Wiring ---
154
157
 
155
- const {
156
- replyTransport,
157
- sendTextReply,
158
- sendMarkdownReply,
159
- editInteractiveMessage,
160
- sendInteractiveMessage,
161
- } =
158
+ const replyRuntime =
162
159
  Replies.createTelegramRenderedMessageDeliveryRuntime<Keyboard.TelegramInlineKeyboardMarkup>(
163
160
  {
164
161
  sendMessage,
165
162
  editMessage: editTelegramMessageText,
166
163
  },
167
164
  );
165
+ const { replyTransport, editInteractiveMessage, sendInteractiveMessage } =
166
+ replyRuntime;
167
+ const { sendTextReply, sendMarkdownReply } =
168
+ OutboundHandlers.createTelegramOutboundTextReplyRuntime({
169
+ sendTextReply: replyRuntime.sendTextReply,
170
+ sendMarkdownReply: replyRuntime.sendMarkdownReply,
171
+ execCommand: CommandTemplates.execCommandTemplate,
172
+ getHandlers: configStore.getOutboundHandlers,
173
+ recordRuntimeEvent,
174
+ });
168
175
  const dispatchNextQueuedTelegramTurn =
169
176
  Queue.createTelegramQueueDispatchRuntime<Pi.ExtensionContext>({
170
177
  ...telegramQueueStore,
@@ -193,6 +200,13 @@ export default function (pi: Pi.ExtensionAPI) {
193
200
  editMessageText: editTelegramMessageText,
194
201
  ...replyTransport,
195
202
  });
203
+ const { finalizeMarkdownPreview } =
204
+ OutboundHandlers.createTelegramOutboundTextPreviewRuntime({
205
+ finalizeMarkdownPreview: previewRuntime.finalizeMarkdown,
206
+ execCommand: CommandTemplates.execCommandTemplate,
207
+ getHandlers: configStore.getOutboundHandlers,
208
+ recordRuntimeEvent,
209
+ });
196
210
 
197
211
  // --- Bridge Setup ---
198
212
 
@@ -213,9 +227,8 @@ export default function (pi: Pi.ExtensionAPI) {
213
227
  appendQueuedItem: queueMutationRuntime.append,
214
228
  updateStatus,
215
229
  });
216
- const getQueueItemCount = Queue.createTelegramQueueItemCountGetter(
217
- telegramQueueStore,
218
- );
230
+ const getQueueItemCount =
231
+ Queue.createTelegramQueueItemCountGetter(telegramQueueStore);
219
232
  const getPromptTemplateCommands =
220
233
  PromptTemplates.createTelegramPromptTemplateCommandGetter({
221
234
  getCommands,
@@ -277,6 +290,7 @@ export default function (pi: Pi.ExtensionAPI) {
277
290
  bridgeRuntime,
278
291
  activeTurnRuntime,
279
292
  mediaGroupRuntime,
293
+ textGroupRuntime,
280
294
  telegramQueueStore,
281
295
  queueMutationRuntime,
282
296
  modelMenuRuntime,
@@ -286,7 +300,7 @@ export default function (pi: Pi.ExtensionAPI) {
286
300
  openQueueMenu: queueMenuRuntime.openQueueMenu,
287
301
  queueMenuCallbackHandler: queueMenuRuntime.handleCallbackQuery,
288
302
  buttonActionStore,
289
- attachmentHandlerRuntime,
303
+ inboundHandlerRuntime,
290
304
  updateStatus,
291
305
  dispatchNextQueuedTelegramTurn,
292
306
  answerCallbackQuery,
@@ -342,7 +356,10 @@ export default function (pi: Pi.ExtensionAPI) {
342
356
  prepareTempDir,
343
357
  updateStatus,
344
358
  unbindDeferredDispatchContext: deferredQueueDispatchRuntime.unbind,
345
- clearPendingMediaGroups: mediaGroupRuntime.clear,
359
+ clearPendingMediaGroups: TextGroups.createTelegramGroupedInputClearer({
360
+ clearMediaGroups: mediaGroupRuntime.clear,
361
+ clearTextGroups: textGroupRuntime.clear,
362
+ }),
346
363
  clearModelMenuState: modelMenuRuntime.clear,
347
364
  getActiveTurnChatId: activeTurnRuntime.getChatId,
348
365
  clearPreview: previewRuntime.clear,
@@ -358,7 +375,7 @@ export default function (pi: Pi.ExtensionAPI) {
358
375
 
359
376
  // --- Extension API Bindings ---
360
377
 
361
- Attachments.registerTelegramAttachmentTool(pi, {
378
+ OutboundAttachments.registerTelegramOutboundAttachmentTool(pi, {
362
379
  getActiveTurn: activeTurnRuntime.get,
363
380
  recordRuntimeEvent,
364
381
  });
@@ -393,7 +410,7 @@ export default function (pi: Pi.ExtensionAPI) {
393
410
  clearDispatchPending: lifecycle.clearDispatchPending,
394
411
  });
395
412
  const queuedAttachmentSender =
396
- Attachments.createTelegramQueuedAttachmentSender({
413
+ OutboundAttachments.createTelegramQueuedOutboundAttachmentSender({
397
414
  sendMultipart: callMultipart,
398
415
  sendTextReply,
399
416
  recordRuntimeEvent,
@@ -428,14 +445,15 @@ export default function (pi: Pi.ExtensionAPI) {
428
445
  updateStatus,
429
446
  getActiveTurn: activeTurnRuntime.get,
430
447
  extractAssistant: Replies.extractLatestAssistantMessageText,
431
- getPreserveQueuedTurnsAsHistory: lifecycle.shouldPreserveQueuedTurnsAsHistory,
448
+ getPreserveQueuedTurnsAsHistory:
449
+ lifecycle.shouldPreserveQueuedTurnsAsHistory,
432
450
  resetRuntimeState: agentEndResetter,
433
451
  dispatchNextQueuedTelegramTurn,
434
452
  requestDeferredDispatchNextQueuedTelegramTurn:
435
453
  deferredQueueDispatchRuntime.request,
436
454
  clearPreview: previewRuntime.clear,
437
455
  setPreviewPendingText: previewRuntime.setPendingText,
438
- finalizeMarkdownPreview: previewRuntime.finalizeMarkdown,
456
+ finalizeMarkdownPreview,
439
457
  sendMarkdownReply,
440
458
  sendTextReply,
441
459
  sendQueuedAttachments: queuedAttachmentSender,
@@ -447,7 +465,9 @@ export default function (pi: Pi.ExtensionAPI) {
447
465
  });
448
466
  // Wire transport-level reply dedup reset via lifecycle
449
467
  Lifecycle.setResetTransportReplyDedup(Replies.resetTransportReplyDedup);
450
- const agentStartWithDedupReset = Lifecycle.createAgentStartDedupHook(agentLifecycleHooks.onAgentStart);
468
+ const agentStartWithDedupReset = Lifecycle.createAgentStartDedupHook(
469
+ agentLifecycleHooks.onAgentStart,
470
+ );
451
471
  Lifecycle.registerTelegramLifecycleHooks(pi, {
452
472
  ...sessionLifecycleRuntime,
453
473
  ...agentLifecycleHooks,
package/lib/config.ts CHANGED
@@ -9,7 +9,7 @@ import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
9
9
  import { homedir } from "node:os";
10
10
  import { join, resolve } from "node:path";
11
11
 
12
- import type { TelegramAttachmentHandlerConfig } from "./attachment-handlers.ts";
12
+ import type { TelegramInboundHandlerConfig } from "./inbound-handlers.ts";
13
13
  import type { CommandTemplateObjectConfig } from "./command-templates.ts";
14
14
 
15
15
  function getAgentDir(): string {
@@ -39,7 +39,8 @@ export interface TelegramConfig {
39
39
  botId?: number;
40
40
  allowedUserId?: number;
41
41
  lastUpdateId?: number;
42
- attachmentHandlers?: TelegramAttachmentHandlerConfig[];
42
+ inboundHandlers?: TelegramInboundHandlerConfig[];
43
+ attachmentHandlers?: TelegramInboundHandlerConfig[];
43
44
  outboundHandlers?: TelegramOutboundHandlerConfig[];
44
45
  }
45
46
 
@@ -50,7 +51,8 @@ export interface TelegramConfigStore {
50
51
  getBotToken: () => string | undefined;
51
52
  hasBotToken: () => boolean;
52
53
  getAllowedUserId: () => number | undefined;
53
- getAttachmentHandlers: () => TelegramAttachmentHandlerConfig[] | undefined;
54
+ getInboundHandlers: () => TelegramInboundHandlerConfig[] | undefined;
55
+ getAttachmentHandlers: () => TelegramInboundHandlerConfig[] | undefined;
54
56
  getOutboundHandlers: () => TelegramOutboundHandlerConfig[] | undefined;
55
57
  setAllowedUserId: (userId: number) => void;
56
58
  load: () => Promise<void>;
@@ -104,6 +106,10 @@ export function createTelegramConfigStore(
104
106
  getBotToken: () => config.botToken,
105
107
  hasBotToken: () => !!config.botToken,
106
108
  getAllowedUserId: () => config.allowedUserId,
109
+ getInboundHandlers: () => [
110
+ ...(config.inboundHandlers ?? []),
111
+ ...(config.attachmentHandlers ?? []),
112
+ ],
107
113
  getAttachmentHandlers: () => config.attachmentHandlers,
108
114
  getOutboundHandlers: () => config.outboundHandlers,
109
115
  setAllowedUserId: (userId) => {