@llblab/pi-telegram 0.3.0 → 0.4.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/lib/routing.ts ADDED
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Telegram inbound routing composition
3
+ * Wires authorized updates into menus, commands, media grouping, and prompt queueing
4
+ */
5
+
6
+ import * as Commands from "./commands.ts";
7
+ import type { TelegramConfigStore } from "./config.ts";
8
+ import type { TelegramAttachmentHandlerRuntime } from "./handlers.ts";
9
+ import * as Media from "./media.ts";
10
+ import * as Menu from "./menu.ts";
11
+ import * as Model from "./model.ts";
12
+ import * as Queue from "./queue.ts";
13
+ import type { TelegramBridgeRuntime } from "./runtime.ts";
14
+ import * as Turns from "./turns.ts";
15
+ import * as Updates from "./updates.ts";
16
+
17
+ export type TelegramRoutedMessage = Updates.TelegramUpdateMessage &
18
+ Media.TelegramMediaMessage &
19
+ Media.TelegramMediaGroupMessage &
20
+ Commands.TelegramCommandRuntimeMessage &
21
+ Turns.TelegramTurnMessage;
22
+
23
+ export type TelegramRoutedCallbackQuery = Updates.TelegramCallbackQuery &
24
+ Menu.MenuCallbackQuery;
25
+
26
+ export interface TelegramInboundRouteRuntimeDeps<
27
+ TUpdate extends Updates.TelegramUpdateFlow & {
28
+ message?: TMessage;
29
+ edited_message?: TMessage;
30
+ callback_query?: TCallbackQuery;
31
+ },
32
+ TMessage extends TelegramRoutedMessage,
33
+ TCallbackQuery extends TelegramRoutedCallbackQuery,
34
+ TContext,
35
+ TModel extends Model.MenuModel,
36
+ > {
37
+ configStore: Pick<
38
+ TelegramConfigStore,
39
+ "getAllowedUserId" | "setAllowedUserId" | "persist"
40
+ >;
41
+ bridgeRuntime: TelegramBridgeRuntime;
42
+ activeTurnRuntime: Queue.TelegramActiveTurnStore;
43
+ mediaGroupRuntime: Media.TelegramMediaGroupController<TMessage>;
44
+ telegramQueueStore: Queue.TelegramQueueStateStore<TContext>;
45
+ queueMutationRuntime: Queue.TelegramQueueMutationController<TContext>;
46
+ modelMenuRuntime: Menu.TelegramModelMenuRuntime<TModel>;
47
+ currentModelRuntime: Model.CurrentModelRuntime<TContext, TModel>;
48
+ modelSwitchController: Model.TelegramModelSwitchController<
49
+ TContext,
50
+ Model.ScopedTelegramModel<TModel>
51
+ >;
52
+ menuActions: Menu.TelegramMenuActionRuntime<TContext, TModel>;
53
+ attachmentHandlerRuntime: TelegramAttachmentHandlerRuntime<TContext>;
54
+ updateStatus: (ctx: TContext, error?: string) => void;
55
+ dispatchNextQueuedTelegramTurn: (ctx: TContext) => void;
56
+ answerCallbackQuery: (
57
+ callbackQueryId: string,
58
+ text?: string,
59
+ ) => Promise<void>;
60
+ sendTextReply: (
61
+ chatId: number,
62
+ replyToMessageId: number,
63
+ text: string,
64
+ ) => Promise<number | undefined>;
65
+ setMyCommands: Commands.TelegramBotCommandRegistrationDeps["setMyCommands"];
66
+ downloadFile: Media.DownloadTelegramMessageFilesDeps["downloadFile"];
67
+ getThinkingLevel: () => Model.ThinkingLevel;
68
+ setThinkingLevel: (level: Model.ThinkingLevel) => void;
69
+ setModel: (model: TModel) => Promise<boolean>;
70
+ isIdle: (ctx: TContext) => boolean;
71
+ hasPendingMessages: (ctx: TContext) => boolean;
72
+ compact: (
73
+ ctx: TContext,
74
+ callbacks: { onComplete: () => void; onError: (error: unknown) => void },
75
+ ) => void;
76
+ recordRuntimeEvent?: (
77
+ category: string,
78
+ error: unknown,
79
+ details?: Record<string, unknown>,
80
+ ) => void;
81
+ }
82
+
83
+ export function createTelegramInboundRouteRuntime<
84
+ TUpdate extends Updates.TelegramUpdateFlow & {
85
+ message?: TMessage;
86
+ edited_message?: TMessage;
87
+ callback_query?: TCallbackQuery;
88
+ },
89
+ TMessage extends TelegramRoutedMessage,
90
+ TCallbackQuery extends TelegramRoutedCallbackQuery,
91
+ TContext,
92
+ TModel extends Model.MenuModel,
93
+ >(
94
+ deps: TelegramInboundRouteRuntimeDeps<
95
+ TUpdate,
96
+ TMessage,
97
+ TCallbackQuery,
98
+ TContext,
99
+ TModel
100
+ >,
101
+ ): Updates.TelegramUpdateRuntimeController<TContext, TUpdate> {
102
+ const callbackHandler = Menu.createTelegramMenuCallbackHandlerForContext<
103
+ TCallbackQuery,
104
+ TContext,
105
+ TModel
106
+ >({
107
+ getStoredModelMenuState: deps.modelMenuRuntime.getState,
108
+ getActiveModel: deps.currentModelRuntime.get,
109
+ getThinkingLevel: deps.getThinkingLevel,
110
+ setThinkingLevel: deps.setThinkingLevel,
111
+ updateStatus: deps.updateStatus,
112
+ updateModelMenuMessage: deps.menuActions.updateModelMenuMessage,
113
+ updateThinkingMenuMessage: deps.menuActions.updateThinkingMenuMessage,
114
+ updateStatusMessage: deps.menuActions.updateStatusMessage,
115
+ answerCallbackQuery: deps.answerCallbackQuery,
116
+ isIdle: deps.isIdle,
117
+ hasActiveTelegramTurn: deps.activeTurnRuntime.has,
118
+ hasAbortHandler: deps.bridgeRuntime.abort.hasHandler,
119
+ getActiveToolExecutions: deps.bridgeRuntime.lifecycle.getActiveToolExecutions,
120
+ setModel: deps.setModel,
121
+ setCurrentModel: deps.currentModelRuntime.setCurrentModel,
122
+ stagePendingModelSwitch: deps.modelSwitchController.stagePendingSwitch,
123
+ restartInterruptedTelegramTurn:
124
+ deps.modelSwitchController.restartInterruptedTurn,
125
+ });
126
+ const commandHandler = Commands.createTelegramCommandHandlerTargetRuntime<
127
+ TMessage,
128
+ TContext
129
+ >({
130
+ hasAbortHandler: deps.bridgeRuntime.abort.hasHandler,
131
+ clearPendingModelSwitch: deps.modelSwitchController.clearPendingSwitch,
132
+ hasQueuedTelegramItems: deps.telegramQueueStore.hasQueuedItems,
133
+ setPreserveQueuedTurnsAsHistory:
134
+ deps.bridgeRuntime.lifecycle.setPreserveQueuedTurnsAsHistory,
135
+ abortCurrentTurn: deps.bridgeRuntime.abort.abortTurn,
136
+ isIdle: deps.isIdle,
137
+ hasPendingMessages: deps.hasPendingMessages,
138
+ hasActiveTelegramTurn: deps.activeTurnRuntime.has,
139
+ hasDispatchPending: deps.bridgeRuntime.lifecycle.hasDispatchPending,
140
+ isCompactionInProgress: deps.bridgeRuntime.lifecycle.isCompactionInProgress,
141
+ setCompactionInProgress: deps.bridgeRuntime.lifecycle.setCompactionInProgress,
142
+ updateStatus: deps.updateStatus,
143
+ dispatchNextQueuedTelegramTurn: deps.dispatchNextQueuedTelegramTurn,
144
+ compact: deps.compact,
145
+ allocateItemOrder: deps.bridgeRuntime.queue.allocateItemOrder,
146
+ allocateControlOrder: deps.bridgeRuntime.queue.allocateControlOrder,
147
+ appendControlItem: deps.queueMutationRuntime.append,
148
+ showStatus: deps.menuActions.sendStatusMessage,
149
+ openModelMenu: deps.menuActions.openModelMenu,
150
+ getAllowedUserId: deps.configStore.getAllowedUserId,
151
+ setAllowedUserId: deps.configStore.setAllowedUserId,
152
+ setMyCommands: deps.setMyCommands,
153
+ persistConfig: deps.configStore.persist,
154
+ sendTextReply: deps.sendTextReply,
155
+ recordRuntimeEvent: deps.recordRuntimeEvent,
156
+ });
157
+ const promptEnqueue = Queue.createTelegramPromptEnqueueController<
158
+ TMessage,
159
+ TContext
160
+ >({
161
+ ...deps.telegramQueueStore,
162
+ getPreserveQueuedTurnsAsHistory:
163
+ deps.bridgeRuntime.lifecycle.shouldPreserveQueuedTurnsAsHistory,
164
+ setPreserveQueuedTurnsAsHistory:
165
+ deps.bridgeRuntime.lifecycle.setPreserveQueuedTurnsAsHistory,
166
+ createTurn: Turns.createTelegramPromptTurnRuntimeBuilder<
167
+ TMessage,
168
+ TContext
169
+ >({
170
+ allocateQueueOrder: deps.bridgeRuntime.queue.allocateItemOrder,
171
+ downloadFile: deps.downloadFile,
172
+ processAttachments: deps.attachmentHandlerRuntime.process,
173
+ }),
174
+ updateStatus: deps.updateStatus,
175
+ dispatchNextQueuedTelegramTurn: deps.dispatchNextQueuedTelegramTurn,
176
+ }).enqueue;
177
+ const commandOrPrompt = Commands.createTelegramCommandOrPromptRuntime<
178
+ TMessage,
179
+ TContext
180
+ >({
181
+ extractRawText: Media.extractFirstTelegramMessageText,
182
+ handleCommand: commandHandler,
183
+ enqueueTurn: promptEnqueue,
184
+ });
185
+ const mediaDispatch = Media.createTelegramMediaGroupDispatchRuntime<
186
+ TMessage,
187
+ TContext
188
+ >({
189
+ mediaGroups: deps.mediaGroupRuntime,
190
+ dispatchMessages: commandOrPrompt.dispatchMessages,
191
+ });
192
+ const editRuntime = Turns.createTelegramQueuedPromptEditRuntime<
193
+ TMessage,
194
+ TContext
195
+ >({
196
+ ...deps.telegramQueueStore,
197
+ updateStatus: deps.updateStatus,
198
+ });
199
+ return Updates.createTelegramPairedUpdateRuntime<TContext, TUpdate>({
200
+ getAllowedUserId: deps.configStore.getAllowedUserId,
201
+ setAllowedUserId: deps.configStore.setAllowedUserId,
202
+ persistConfig: deps.configStore.persist,
203
+ updateStatus: deps.updateStatus,
204
+ removePendingMediaGroupMessages: deps.mediaGroupRuntime.removeMessages,
205
+ removeQueuedTelegramTurnsByMessageIds:
206
+ deps.queueMutationRuntime.removeByMessageIds,
207
+ clearQueuedTelegramTurnPriorityByMessageId:
208
+ deps.queueMutationRuntime.clearPriorityByMessageId,
209
+ prioritizeQueuedTelegramTurnByMessageId:
210
+ deps.queueMutationRuntime.prioritizeByMessageId,
211
+ answerCallbackQuery: deps.answerCallbackQuery,
212
+ handleAuthorizedTelegramCallbackQuery: callbackHandler,
213
+ sendTextReply: deps.sendTextReply,
214
+ handleAuthorizedTelegramMessage: mediaDispatch.handleMessage,
215
+ handleAuthorizedTelegramEditedMessage: editRuntime.updateFromEditedMessage,
216
+ });
217
+ }
package/lib/setup.ts CHANGED
@@ -21,6 +21,11 @@ export interface TelegramSetupUser {
21
21
  username?: string;
22
22
  }
23
23
 
24
+ export interface TelegramPollingStartResult {
25
+ ok: boolean;
26
+ message?: string;
27
+ }
28
+
24
29
  export interface TelegramSetupDeps {
25
30
  hasUI: boolean;
26
31
  env: NodeJS.ProcessEnv;
@@ -34,7 +39,7 @@ export interface TelegramSetupDeps {
34
39
  }>;
35
40
  persistConfig: (config: TelegramSetupConfig) => Promise<void>;
36
41
  notify: (message: string, level: "info" | "error") => void;
37
- startPolling: () => void | Promise<void>;
42
+ startPolling: () => unknown | Promise<unknown>;
38
43
  updateStatus: () => void;
39
44
  }
40
45
 
@@ -61,7 +66,7 @@ export interface TelegramSetupPromptRuntimeDeps<
61
66
  setupGuard: TelegramSetupGuard;
62
67
  getMe: TelegramSetupDeps["getMe"];
63
68
  persistConfig: (config: TelegramSetupConfig) => Promise<void>;
64
- startPolling: (ctx: TContext) => void | Promise<void>;
69
+ startPolling: (ctx: TContext) => unknown | Promise<unknown>;
65
70
  updateStatus: (ctx: TContext) => void;
66
71
  recordRuntimeEvent?: (
67
72
  category: string,
@@ -78,6 +83,12 @@ const TELEGRAM_BOT_TOKEN_ENV_VARS = [
78
83
  "TELEGRAM_KEY",
79
84
  ] as const;
80
85
 
86
+ function isTelegramPollingStartResult(
87
+ value: unknown,
88
+ ): value is TelegramPollingStartResult {
89
+ return !!value && typeof value === "object" && typeof (value as { ok?: unknown }).ok === "boolean";
90
+ }
91
+
81
92
  export function getTelegramBotTokenInputDefault(
82
93
  env: NodeJS.ProcessEnv = process.env,
83
94
  configToken?: string,
@@ -135,7 +146,10 @@ export async function runTelegramSetup(
135
146
  "Send /start to your bot in Telegram to pair this extension with your account.",
136
147
  "info",
137
148
  );
138
- await deps.startPolling();
149
+ const startResult = await deps.startPolling();
150
+ if (isTelegramPollingStartResult(startResult) && startResult.message) {
151
+ deps.notify(startResult.message, startResult.ok ? "info" : "error");
152
+ }
139
153
  deps.updateStatus();
140
154
  return nextConfig;
141
155
  }
package/lib/status.ts CHANGED
@@ -83,6 +83,7 @@ export interface TelegramRuntimeEventRecorderOptions {
83
83
  export interface TelegramBridgeStatusLineState {
84
84
  botUsername?: string;
85
85
  allowedUserId?: number;
86
+ lockState?: string;
86
87
  pollingActive: boolean;
87
88
  lastUpdateId?: number;
88
89
  activeSourceMessageIds?: number[];
@@ -148,6 +149,7 @@ export interface TelegramBridgeStatusRuntimeDeps<
148
149
  getQueuedItems: () => TQueueItem[];
149
150
  formatQueuedStatus: (items: TQueueItem[]) => string;
150
151
  getRecentRuntimeEvents: () => TelegramRuntimeEvent[];
152
+ getRuntimeLockState?: () => string;
151
153
  }
152
154
 
153
155
  export interface TelegramStatusRuntime<
@@ -350,6 +352,7 @@ export function createTelegramBridgeStatusRuntime<
350
352
  return {
351
353
  botUsername: config.botUsername,
352
354
  allowedUserId: config.allowedUserId,
355
+ lockState: deps.getRuntimeLockState?.(),
353
356
  pollingActive: deps.isPollingActive(),
354
357
  lastUpdateId: config.lastUpdateId,
355
358
  activeSourceMessageIds: deps.getActiveSourceMessageIds(),
@@ -404,6 +407,7 @@ export function buildTelegramBridgeStatusLines(
404
407
  "connection:",
405
408
  `- bot: ${state.botUsername ? `@${state.botUsername}` : "not configured"}`,
406
409
  `- allowed user: ${state.allowedUserId ?? "not paired"}`,
410
+ ...(state.lockState ? [`- owner: ${state.lockState}`] : []),
407
411
  "",
408
412
  "polling:",
409
413
  `- state: ${state.pollingActive ? "running" : "stopped"}`,
package/lib/turns.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { readFile } from "node:fs/promises";
7
- import { basename } from "node:path";
7
+ import { basename, dirname, join } from "node:path";
8
8
 
9
9
  import {
10
10
  collectTelegramMessageIds,
@@ -53,9 +53,14 @@ export function truncateTelegramQueueSummary(
53
53
  export function formatTelegramTurnStatusSummary(
54
54
  rawText: string,
55
55
  files: DownloadedTelegramTurnFile[],
56
+ handlerOutputs: string[] = [],
56
57
  ): string {
57
58
  const textSummary = truncateTelegramQueueSummary(rawText);
58
59
  if (textSummary) return textSummary;
60
+ const handlerSummary = truncateTelegramQueueSummary(
61
+ handlerOutputs.join(" "),
62
+ );
63
+ if (handlerSummary) return handlerSummary;
59
64
  if (files.length === 1) {
60
65
  const fileName = basename(
61
66
  files[0]?.fileName || files[0]?.path || "attachment",
@@ -66,10 +71,37 @@ export function formatTelegramTurnStatusSummary(
66
71
  return "(empty message)";
67
72
  }
68
73
 
74
+ function appendTelegramListSection(
75
+ text: string,
76
+ title: string,
77
+ items: string[],
78
+ ): string {
79
+ if (items.length === 0) return text;
80
+ const prefix = text.length > 0 ? `${text}\n\n` : "";
81
+ return `${prefix}[${title}]\n${items.map((item) => `- ${item}`).join("\n")}`;
82
+ }
83
+
84
+ function appendTelegramAttachmentSection(
85
+ text: string,
86
+ files: Pick<DownloadedTelegramTurnFile, "path">[],
87
+ ): string {
88
+ if (files.length === 0) return text;
89
+ const dirs = [...new Set(files.map((file) => dirname(file.path)))];
90
+ const sameDir = dirs.length === 1;
91
+ const header = sameDir ? `[attachments] ${dirs[0]}` : "[attachments]";
92
+ const items = sameDir
93
+ ? files.map((file) => `/${basename(file.path)}`)
94
+ : files.map((file) => file.path);
95
+ const prefix = text.length > 0 ? `${text}\n\n` : "";
96
+ return `${prefix}${header}\n${items.map((item) => `- ${item}`).join("\n")}`;
97
+ }
98
+
69
99
  export function buildTelegramTurnPrompt(options: {
70
100
  telegramPrefix: string;
71
101
  rawText: string;
72
102
  files: DownloadedTelegramTurnFile[];
103
+ promptFiles?: DownloadedTelegramTurnFile[];
104
+ handlerOutputs?: string[];
73
105
  historyTurns?: Pick<PendingTelegramTurn, "historyText">[];
74
106
  }): string {
75
107
  let prompt = options.telegramPrefix;
@@ -87,12 +119,9 @@ export function buildTelegramTurnPrompt(options: {
87
119
  ? `\n${options.rawText}`
88
120
  : ` ${options.rawText}`;
89
121
  }
90
- if (options.files.length > 0) {
91
- prompt += "\n\nTelegram attachments were saved locally:";
92
- for (const file of options.files) {
93
- prompt += `\n- ${file.path}`;
94
- }
95
- }
122
+ const promptFiles = options.promptFiles ?? options.files;
123
+ prompt = appendTelegramAttachmentSection(prompt, promptFiles);
124
+ prompt = appendTelegramListSection(prompt, "outputs", options.handlerOutputs ?? []);
96
125
  return prompt;
97
126
  }
98
127
 
@@ -101,7 +130,7 @@ function splitTelegramPromptAttachmentSuffix(prompt: string): {
101
130
  attachmentSuffix: string;
102
131
  attachmentFiles: DownloadedTelegramTurnFile[];
103
132
  } {
104
- const marker = "\n\nTelegram attachments were saved locally:";
133
+ const marker = "\n\n[attachments]";
105
134
  const markerIndex = prompt.indexOf(marker);
106
135
  if (markerIndex === -1) {
107
136
  return {
@@ -112,11 +141,30 @@ function splitTelegramPromptAttachmentSuffix(prompt: string): {
112
141
  }
113
142
  const promptWithoutAttachments = prompt.slice(0, markerIndex);
114
143
  const attachmentSuffix = prompt.slice(markerIndex);
115
- const attachmentFiles = attachmentSuffix
116
- .split("\n")
144
+ const attachmentLines: string[] = [];
145
+ let readingAttachments = false;
146
+ let attachmentDir: string | undefined;
147
+ for (const line of attachmentSuffix.split("\n")) {
148
+ const trimmed = line.trim();
149
+ const attachmentMatch = trimmed.match(/^\[attachments\](?:\s+(.+))?$/);
150
+ if (attachmentMatch) {
151
+ readingAttachments = true;
152
+ attachmentDir = attachmentMatch[1]?.trim();
153
+ continue;
154
+ }
155
+ if (readingAttachments && /^\[[^\]]+\](?:\s+.*)?$/.test(trimmed)) break;
156
+ if (readingAttachments) attachmentLines.push(line);
157
+ }
158
+ const attachmentFiles = attachmentLines
117
159
  .map((line) => line.match(/^- (.+)$/)?.[1]?.trim())
118
160
  .filter((path): path is string => !!path)
119
- .map((path) => ({ path, fileName: basename(path), isImage: false }));
161
+ .map((path) => (attachmentDir ? join(attachmentDir, path.replace(/^\/+/, "")) : path))
162
+ .map((path) => ({
163
+ path,
164
+ fileName: basename(path),
165
+ isImage: false,
166
+ kind: "document" as const,
167
+ }));
120
168
  return { promptWithoutAttachments, attachmentSuffix, attachmentFiles };
121
169
  }
122
170
 
@@ -242,6 +290,8 @@ export interface BuildTelegramPromptTurnOptions {
242
290
  queueOrder: number;
243
291
  rawText: string;
244
292
  files: DownloadedTelegramTurnFile[];
293
+ promptFiles?: DownloadedTelegramTurnFile[];
294
+ handlerOutputs?: string[];
245
295
  readBinaryFile: (path: string) => Promise<Uint8Array>;
246
296
  inferImageMimeType: (path: string) => string | undefined;
247
297
  }
@@ -251,30 +301,50 @@ export type BuildTelegramPromptTurnRuntimeOptions = Omit<
251
301
  "readBinaryFile"
252
302
  >;
253
303
 
254
- export interface TelegramPromptTurnRuntimeBuilderDeps extends DownloadTelegramMessageFilesDeps {
304
+ export interface TelegramPromptTurnRuntimeBuilderDeps<TContext = unknown>
305
+ extends DownloadTelegramMessageFilesDeps {
255
306
  allocateQueueOrder: () => number;
307
+ processAttachments?: (
308
+ files: DownloadedTelegramTurnFile[],
309
+ rawText: string,
310
+ ctx: TContext,
311
+ ) => Promise<{
312
+ rawText: string;
313
+ promptFiles?: DownloadedTelegramTurnFile[];
314
+ handlerOutputs?: string[];
315
+ }>;
256
316
  }
257
317
 
258
318
  export function createTelegramPromptTurnRuntimeBuilder<
259
319
  TMessage extends TelegramTurnMessage & TelegramMediaMessage,
320
+ TContext = unknown,
260
321
  >(
261
- deps: TelegramPromptTurnRuntimeBuilderDeps,
322
+ deps: TelegramPromptTurnRuntimeBuilderDeps<TContext>,
262
323
  ): (
263
324
  messages: TMessage[],
264
325
  historyTurns?: PendingTelegramTurn[],
326
+ ctx?: TContext,
265
327
  ) => Promise<PendingTelegramTurn> {
266
- return async (messages, historyTurns = []) =>
267
- buildTelegramPromptTurnRuntime({
328
+ return async (messages, historyTurns = [], ctx) => {
329
+ const rawText = extractTelegramMessagesText(messages);
330
+ const files = await downloadTelegramMessageFiles(messages, {
331
+ downloadFile: deps.downloadFile,
332
+ });
333
+ const processed = deps.processAttachments
334
+ ? await deps.processAttachments(files, rawText, ctx as TContext)
335
+ : { rawText, promptFiles: files };
336
+ return buildTelegramPromptTurnRuntime({
268
337
  telegramPrefix: TELEGRAM_PREFIX,
269
338
  messages,
270
339
  historyTurns,
271
340
  queueOrder: deps.allocateQueueOrder(),
272
- rawText: extractTelegramMessagesText(messages),
273
- files: await downloadTelegramMessageFiles(messages, {
274
- downloadFile: deps.downloadFile,
275
- }),
341
+ rawText: processed.rawText,
342
+ files,
343
+ promptFiles: processed.promptFiles,
344
+ handlerOutputs: processed.handlerOutputs,
276
345
  inferImageMimeType: guessMediaType,
277
346
  });
347
+ };
278
348
  }
279
349
 
280
350
  export async function buildTelegramPromptTurn(
@@ -291,6 +361,8 @@ export async function buildTelegramPromptTurn(
291
361
  telegramPrefix: options.telegramPrefix,
292
362
  rawText: options.rawText,
293
363
  files: options.files,
364
+ promptFiles: options.promptFiles,
365
+ handlerOutputs: options.handlerOutputs,
294
366
  historyTurns: options.historyTurns,
295
367
  }),
296
368
  },
@@ -316,10 +388,15 @@ export async function buildTelegramPromptTurn(
316
388
  laneOrder: options.queueOrder,
317
389
  queuedAttachments: [],
318
390
  content,
319
- historyText: formatTelegramHistoryText(options.rawText, options.files),
391
+ historyText: formatTelegramHistoryText(
392
+ options.rawText,
393
+ options.promptFiles ?? options.files,
394
+ options.handlerOutputs,
395
+ ),
320
396
  statusSummary: formatTelegramTurnStatusSummary(
321
397
  options.rawText,
322
- options.files,
398
+ options.promptFiles ?? options.files,
399
+ options.handlerOutputs,
323
400
  ),
324
401
  };
325
402
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-telegram",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "Better Telegram DM bridge extension for pi",
6
6
  "type": "module",