@llblab/pi-telegram 0.17.4 → 0.18.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/AGENTS.md +67 -32
- package/BACKLOG.md +59 -14
- package/CHANGELOG.md +40 -15
- package/README.md +63 -35
- package/docs/README.md +3 -1
- package/docs/architecture.md +55 -23
- package/docs/callback-namespaces.md +1 -1
- package/docs/inbound.md +1 -1
- package/docs/locks.md +0 -2
- package/docs/multi-instance-bus.md +483 -0
- package/docs/outbound.md +4 -3
- package/docs/public-api.md +12 -10
- package/docs/sections.md +2 -2
- package/docs/ui-style.md +76 -0
- package/index.ts +789 -32
- package/lib/bindings.ts +68 -12
- package/lib/bus-api.ts +314 -0
- package/lib/bus-follower.ts +853 -0
- package/lib/bus-leader.ts +915 -0
- package/lib/bus.ts +866 -0
- package/lib/command-templates.ts +9 -11
- package/lib/commands.ts +133 -47
- package/lib/config.ts +53 -5
- package/lib/lifecycle.ts +23 -7
- package/lib/locks.ts +230 -66
- package/lib/media.ts +30 -2
- package/lib/menu-model.ts +48 -17
- package/lib/menu-queue.ts +51 -20
- package/lib/menu-settings.ts +9 -5
- package/lib/menu-status.ts +3 -0
- package/lib/menu-thinking.ts +3 -0
- package/lib/menu.ts +67 -26
- package/lib/outbound-attachments.ts +102 -17
- package/lib/outbound-buttons.ts +6 -2
- package/lib/outbound-voice.ts +31 -11
- package/lib/outbound.ts +6 -4
- package/lib/ownership.ts +119 -0
- package/lib/pi.ts +26 -3
- package/lib/polling.ts +477 -7
- package/lib/preview.ts +141 -88
- package/lib/prompt-templates.ts +3 -3
- package/lib/prompts.ts +80 -30
- package/lib/queue.ts +193 -91
- package/lib/rendering.ts +0 -25
- package/lib/replies.ts +187 -55
- package/lib/routing.ts +1673 -9
- package/lib/runtime-log.ts +123 -0
- package/lib/runtime.ts +84 -12
- package/lib/sections.ts +28 -21
- package/lib/setup.ts +1 -1
- package/lib/status.ts +532 -9
- package/lib/sync.ts +618 -0
- package/lib/target.ts +49 -0
- package/lib/telegram-api.ts +405 -40
- package/lib/text-groups.ts +5 -1
- package/lib/thread-reconciler.ts +915 -0
- package/lib/threads.ts +2205 -0
- package/lib/turns.ts +48 -3
- package/lib/updates.ts +355 -32
- package/package.json +24 -2
- package/screenshot.png +0 -0
- package/docs/telegram-bot-api-rich-messages.md +0 -890
package/lib/menu-model.ts
CHANGED
|
@@ -24,6 +24,7 @@ export type TelegramModelScope = "all" | "scoped";
|
|
|
24
24
|
|
|
25
25
|
export interface TelegramModelMenuState<TModel extends MenuModel = MenuModel> {
|
|
26
26
|
chatId: number;
|
|
27
|
+
threadId?: number;
|
|
27
28
|
messageId: number;
|
|
28
29
|
page: number;
|
|
29
30
|
scope: TelegramModelScope;
|
|
@@ -91,6 +92,7 @@ export interface TelegramModelMenuRuntimeOptions<
|
|
|
91
92
|
TModel extends MenuModel = MenuModel,
|
|
92
93
|
> {
|
|
93
94
|
chatId: number;
|
|
95
|
+
threadId?: number;
|
|
94
96
|
activeModel: TModel | undefined;
|
|
95
97
|
cachedInputs: CachedTelegramModelMenuInputs<TModel> | undefined;
|
|
96
98
|
cacheTtlMs: number;
|
|
@@ -136,6 +138,7 @@ export interface TelegramMenuMessageRuntimeDeps {
|
|
|
136
138
|
text: string,
|
|
137
139
|
mode: "markdown" | "html" | "plain",
|
|
138
140
|
replyMarkup: TelegramReplyMarkup,
|
|
141
|
+
options?: { target?: { chatId: number; threadId?: number } },
|
|
139
142
|
) => Promise<number | undefined>;
|
|
140
143
|
}
|
|
141
144
|
|
|
@@ -178,6 +181,7 @@ export interface BuildTelegramModelMenuStateParams<
|
|
|
178
181
|
TModel extends MenuModel = MenuModel,
|
|
179
182
|
> {
|
|
180
183
|
chatId: number;
|
|
184
|
+
threadId?: number;
|
|
181
185
|
activeModel: TModel | undefined;
|
|
182
186
|
availableModels: TModel[];
|
|
183
187
|
configuredScopedModelPatterns: string[];
|
|
@@ -240,6 +244,7 @@ export interface TelegramModelMenuRuntime<
|
|
|
240
244
|
storeState: (state: TelegramModelMenuState<TModel>) => void;
|
|
241
245
|
getState: (
|
|
242
246
|
messageId: number | undefined,
|
|
247
|
+
chatId?: number,
|
|
243
248
|
) => TelegramModelMenuState<TModel> | undefined;
|
|
244
249
|
clear: () => void;
|
|
245
250
|
clearCachedInputs: () => void;
|
|
@@ -336,6 +341,9 @@ function sendTelegramMenuMessage(
|
|
|
336
341
|
appliedPayload.text,
|
|
337
342
|
appliedPayload.mode,
|
|
338
343
|
appliedPayload.replyMarkup,
|
|
344
|
+
state.threadId !== undefined
|
|
345
|
+
? { target: { chatId: state.chatId, threadId: state.threadId } }
|
|
346
|
+
: undefined,
|
|
339
347
|
);
|
|
340
348
|
}
|
|
341
349
|
|
|
@@ -364,10 +372,14 @@ export function getModelMenuItems<TModel extends MenuModel = MenuModel>(
|
|
|
364
372
|
: state.allModels;
|
|
365
373
|
}
|
|
366
374
|
|
|
375
|
+
function getTelegramMenuStateKey(chatId: number, messageId: number): string {
|
|
376
|
+
return `${chatId}:${messageId}`;
|
|
377
|
+
}
|
|
378
|
+
|
|
367
379
|
export function pruneStoredTelegramModelMenus<
|
|
368
380
|
TModel extends MenuModel = MenuModel,
|
|
369
381
|
>(
|
|
370
|
-
menus: Map<
|
|
382
|
+
menus: Map<string, StoredTelegramModelMenuState<TModel>>,
|
|
371
383
|
options: TelegramModelMenuStoreOptions,
|
|
372
384
|
): void {
|
|
373
385
|
const now = options.now ?? Date.now();
|
|
@@ -376,40 +388,51 @@ export function pruneStoredTelegramModelMenus<
|
|
|
376
388
|
menus.delete(messageId);
|
|
377
389
|
}
|
|
378
390
|
while (menus.size > options.maxStoredMenus) {
|
|
379
|
-
const
|
|
380
|
-
if (
|
|
381
|
-
menus.delete(
|
|
391
|
+
const oldestKey = menus.keys().next().value as string | undefined;
|
|
392
|
+
if (oldestKey === undefined) return;
|
|
393
|
+
menus.delete(oldestKey);
|
|
382
394
|
}
|
|
383
395
|
}
|
|
384
396
|
|
|
385
397
|
export function storeTelegramModelMenuState<
|
|
386
398
|
TModel extends MenuModel = MenuModel,
|
|
387
399
|
>(
|
|
388
|
-
menus: Map<
|
|
400
|
+
menus: Map<string, StoredTelegramModelMenuState<TModel>>,
|
|
389
401
|
state: TelegramModelMenuState<TModel>,
|
|
390
402
|
options: TelegramModelMenuStoreOptions,
|
|
391
403
|
): void {
|
|
392
404
|
const now = options.now ?? Date.now();
|
|
393
405
|
pruneStoredTelegramModelMenus(menus, { ...options, now });
|
|
394
|
-
menus.set(state.
|
|
406
|
+
menus.set(getTelegramMenuStateKey(state.chatId, state.messageId), {
|
|
407
|
+
state,
|
|
408
|
+
updatedAt: now,
|
|
409
|
+
});
|
|
395
410
|
pruneStoredTelegramModelMenus(menus, { ...options, now });
|
|
396
411
|
}
|
|
397
412
|
|
|
398
413
|
export function getStoredTelegramModelMenuState<
|
|
399
414
|
TModel extends MenuModel = MenuModel,
|
|
400
415
|
>(
|
|
401
|
-
menus: Map<
|
|
416
|
+
menus: Map<string, StoredTelegramModelMenuState<TModel>>,
|
|
402
417
|
messageId: number | undefined,
|
|
403
418
|
options: TelegramModelMenuStoreOptions,
|
|
419
|
+
chatId?: number,
|
|
404
420
|
): TelegramModelMenuState<TModel> | undefined {
|
|
405
421
|
if (messageId === undefined) return undefined;
|
|
406
422
|
const now = options.now ?? Date.now();
|
|
407
423
|
pruneStoredTelegramModelMenus(menus, { ...options, now });
|
|
408
|
-
const
|
|
424
|
+
const key =
|
|
425
|
+
typeof chatId === "number"
|
|
426
|
+
? getTelegramMenuStateKey(chatId, messageId)
|
|
427
|
+
: [...menus.keys()].find((candidate) =>
|
|
428
|
+
candidate.endsWith(`:${messageId}`),
|
|
429
|
+
);
|
|
430
|
+
if (!key) return undefined;
|
|
431
|
+
const entry = menus.get(key);
|
|
409
432
|
if (!entry) return undefined;
|
|
410
|
-
menus.delete(
|
|
433
|
+
menus.delete(key);
|
|
411
434
|
entry.updatedAt = now;
|
|
412
|
-
menus.set(
|
|
435
|
+
menus.set(key, entry);
|
|
413
436
|
return entry.state;
|
|
414
437
|
}
|
|
415
438
|
|
|
@@ -418,7 +441,7 @@ export function createTelegramModelMenuRuntime<
|
|
|
418
441
|
>(
|
|
419
442
|
options: Partial<TelegramModelMenuStoreOptions> = {},
|
|
420
443
|
): TelegramModelMenuRuntime<TModel> {
|
|
421
|
-
const menus = new Map<
|
|
444
|
+
const menus = new Map<string, StoredTelegramModelMenuState<TModel>>();
|
|
422
445
|
let cachedInputs: CachedTelegramModelMenuInputs<TModel> | undefined;
|
|
423
446
|
const getStoreOptions = (): TelegramModelMenuStoreOptions => ({
|
|
424
447
|
maxAgeMs: options.maxAgeMs ?? TELEGRAM_MODEL_MENU_STATE_TTL_MS,
|
|
@@ -429,8 +452,13 @@ export function createTelegramModelMenuRuntime<
|
|
|
429
452
|
storeState: (state) => {
|
|
430
453
|
storeTelegramModelMenuState(menus, state, getStoreOptions());
|
|
431
454
|
},
|
|
432
|
-
getState: (messageId) =>
|
|
433
|
-
getStoredTelegramModelMenuState(
|
|
455
|
+
getState: (messageId, chatId) =>
|
|
456
|
+
getStoredTelegramModelMenuState(
|
|
457
|
+
menus,
|
|
458
|
+
messageId,
|
|
459
|
+
getStoreOptions(),
|
|
460
|
+
chatId,
|
|
461
|
+
),
|
|
434
462
|
clear: () => {
|
|
435
463
|
menus.clear();
|
|
436
464
|
cachedInputs = undefined;
|
|
@@ -456,11 +484,12 @@ export function createTelegramModelMenuStateBuilder<
|
|
|
456
484
|
TelegramModelMenuStateBuilderContext<TModel>,
|
|
457
485
|
>(
|
|
458
486
|
deps: TelegramModelMenuStateBuilderDeps<TModel, TContext>,
|
|
459
|
-
): (chatId: number, ctx: TContext) => Promise<TelegramModelMenuState<TModel>> {
|
|
460
|
-
return async (chatId, ctx) => {
|
|
487
|
+
): (chatId: number, ctx: TContext, threadId?: number) => Promise<TelegramModelMenuState<TModel>> {
|
|
488
|
+
return async (chatId, ctx, threadId) => {
|
|
461
489
|
const settingsManager = deps.createSettingsManager(ctx.cwd);
|
|
462
490
|
return deps.runtime.buildState({
|
|
463
491
|
chatId,
|
|
492
|
+
threadId,
|
|
464
493
|
activeModel: deps.getActiveModel(ctx),
|
|
465
494
|
ctx,
|
|
466
495
|
reloadSettings: () => settingsManager.reload(),
|
|
@@ -521,6 +550,7 @@ export function buildTelegramModelMenuState<
|
|
|
521
550
|
}
|
|
522
551
|
return {
|
|
523
552
|
chatId: params.chatId,
|
|
553
|
+
threadId: params.threadId,
|
|
524
554
|
messageId: 0,
|
|
525
555
|
page: 0,
|
|
526
556
|
scope: scopedModels.length > 0 ? "scoped" : "all",
|
|
@@ -562,6 +592,7 @@ export async function buildTelegramModelMenuStateRuntime<
|
|
|
562
592
|
cachedInputs,
|
|
563
593
|
state: buildTelegramModelMenuState({
|
|
564
594
|
chatId: options.chatId,
|
|
595
|
+
threadId: options.threadId,
|
|
565
596
|
activeModel: options.activeModel,
|
|
566
597
|
availableModels: cachedInputs.availableModels,
|
|
567
598
|
configuredScopedModelPatterns: cachedInputs.configuredScopedModelPatterns,
|
|
@@ -844,7 +875,7 @@ export function buildTelegramModelCallbackPlan<
|
|
|
844
875
|
if (!params.canRestartBusyRun) {
|
|
845
876
|
return {
|
|
846
877
|
kind: "answer",
|
|
847
|
-
text: "
|
|
878
|
+
text: "Pi is busy. Send /abort, /next, or /stop.",
|
|
848
879
|
};
|
|
849
880
|
}
|
|
850
881
|
return {
|
|
@@ -944,7 +975,7 @@ export async function handleTelegramModelMenuCallbackAction<
|
|
|
944
975
|
if (!restarted) {
|
|
945
976
|
await deps.answerCallbackQuery(
|
|
946
977
|
callbackQueryId,
|
|
947
|
-
"
|
|
978
|
+
"Pi is busy. Send /abort, /next, or /stop.",
|
|
948
979
|
);
|
|
949
980
|
return true;
|
|
950
981
|
}
|
package/lib/menu-queue.ts
CHANGED
|
@@ -38,6 +38,7 @@ interface TelegramQueueMenuItem {
|
|
|
38
38
|
statusSummary: string;
|
|
39
39
|
promptText: string;
|
|
40
40
|
}
|
|
41
|
+
|
|
41
42
|
function getTelegramQueueItemPromptText<Context>(
|
|
42
43
|
item: Queue.TelegramQueueItem<Context>,
|
|
43
44
|
): string {
|
|
@@ -50,10 +51,11 @@ function getTelegramQueueItemPromptText<Context>(
|
|
|
50
51
|
.trim() || item.statusSummary
|
|
51
52
|
);
|
|
52
53
|
}
|
|
54
|
+
|
|
53
55
|
function toTelegramQueueMenuItems<Context>(
|
|
54
56
|
items: readonly Queue.TelegramQueueItem<Context>[],
|
|
55
57
|
): TelegramQueueMenuItem[] {
|
|
56
|
-
return items.map(
|
|
58
|
+
return items.map((item, index) => {
|
|
57
59
|
return {
|
|
58
60
|
chatId: item.chatId,
|
|
59
61
|
replyToMessageId: item.replyToMessageId,
|
|
@@ -67,6 +69,7 @@ function toTelegramQueueMenuItems<Context>(
|
|
|
67
69
|
};
|
|
68
70
|
});
|
|
69
71
|
}
|
|
72
|
+
|
|
70
73
|
function buildTelegramQueueMenuReplyMarkup(
|
|
71
74
|
items: readonly TelegramQueueMenuItem[],
|
|
72
75
|
emptyRefreshIndex = 0,
|
|
@@ -80,7 +83,7 @@ function buildTelegramQueueMenuReplyMarkup(
|
|
|
80
83
|
: "queue:refresh";
|
|
81
84
|
const refreshRow = [{ text: "🌀 Refresh", callback_data: refreshData }];
|
|
82
85
|
if (items.length === 0) return { inline_keyboard: [backRow, refreshRow] };
|
|
83
|
-
const rows = items.map(
|
|
86
|
+
const rows = items.map((item, index) => {
|
|
84
87
|
const prefix = item.isPriority
|
|
85
88
|
? `${item.priorityEmoji ?? "⚡"} `
|
|
86
89
|
: item.hasAttachments
|
|
@@ -96,33 +99,38 @@ function buildTelegramQueueMenuReplyMarkup(
|
|
|
96
99
|
});
|
|
97
100
|
return { inline_keyboard: [backRow, refreshRow, ...rows] };
|
|
98
101
|
}
|
|
102
|
+
|
|
99
103
|
function findTelegramQueueItem<Context>(
|
|
100
104
|
items: readonly Queue.TelegramQueueItem<Context>[],
|
|
101
105
|
chatId: number,
|
|
102
106
|
replyToMessageId: number,
|
|
103
107
|
): Queue.TelegramQueueItem<Context> | undefined {
|
|
104
|
-
return items.find(
|
|
108
|
+
return items.find((item) => {
|
|
105
109
|
return item.chatId === chatId && item.replyToMessageId === replyToMessageId;
|
|
106
110
|
});
|
|
107
111
|
}
|
|
112
|
+
|
|
108
113
|
function findTelegramQueueMenuItem(
|
|
109
114
|
items: readonly TelegramQueueMenuItem[],
|
|
110
115
|
chatId: number,
|
|
111
116
|
replyToMessageId: number,
|
|
112
117
|
): TelegramQueueMenuItem | undefined {
|
|
113
|
-
return items.find(
|
|
118
|
+
return items.find((item) => {
|
|
114
119
|
return item.chatId === chatId && item.replyToMessageId === replyToMessageId;
|
|
115
120
|
});
|
|
116
121
|
}
|
|
122
|
+
|
|
117
123
|
function escapeTelegramQueueMenuHtmlChar(char: string): string {
|
|
118
124
|
if (char === "&") return "&";
|
|
119
125
|
if (char === "<") return "<";
|
|
120
126
|
if (char === ">") return ">";
|
|
121
127
|
return char;
|
|
122
128
|
}
|
|
129
|
+
|
|
123
130
|
function escapeTelegramQueueMenuHtml(text: string): string {
|
|
124
131
|
return Array.from(text).map(escapeTelegramQueueMenuHtmlChar).join("");
|
|
125
132
|
}
|
|
133
|
+
|
|
126
134
|
function escapeTelegramQueueMenuHtmlPreview(text: string): string {
|
|
127
135
|
const suffix = escapeTelegramQueueMenuHtml(
|
|
128
136
|
QUEUE_ITEM_PROMPT_TRUNCATION_SUFFIX,
|
|
@@ -142,12 +150,14 @@ function escapeTelegramQueueMenuHtmlPreview(text: string): string {
|
|
|
142
150
|
}
|
|
143
151
|
return truncated ? escaped + suffix : escaped;
|
|
144
152
|
}
|
|
153
|
+
|
|
145
154
|
function getTelegramQueueMenuItemText(item: TelegramQueueMenuItem): string {
|
|
146
155
|
const badge = item.isPriority ? ` ${item.priorityEmoji ?? "⚡"}` : "";
|
|
147
156
|
const heading = `<b>${item.queuePosition}.</b>${badge}`;
|
|
148
157
|
const preview = `<pre>${escapeTelegramQueueMenuHtmlPreview(item.promptText)}</pre>`;
|
|
149
158
|
return `${heading}\n${preview}`;
|
|
150
159
|
}
|
|
160
|
+
|
|
151
161
|
function buildTelegramQueueItemSubmenuReplyMarkup(
|
|
152
162
|
chatId: number,
|
|
153
163
|
replyToMessageId: number,
|
|
@@ -175,6 +185,7 @@ function buildTelegramQueueItemSubmenuReplyMarkup(
|
|
|
175
185
|
],
|
|
176
186
|
};
|
|
177
187
|
}
|
|
188
|
+
|
|
178
189
|
function buildTelegramQueueDeleteConfirmationReplyMarkup(
|
|
179
190
|
chatId: number,
|
|
180
191
|
replyToMessageId: number,
|
|
@@ -223,6 +234,7 @@ interface TelegramQueueMenuCallbackDeps<Context = unknown> {
|
|
|
223
234
|
) => Promise<void>;
|
|
224
235
|
updateStatus: (ctx: Context) => void;
|
|
225
236
|
}
|
|
237
|
+
|
|
226
238
|
async function handleTelegramQueueMenuCallback<Context>(
|
|
227
239
|
callbackQueryId: string,
|
|
228
240
|
data: string,
|
|
@@ -337,6 +349,7 @@ async function handleTelegramQueueMenuCallback<Context>(
|
|
|
337
349
|
}
|
|
338
350
|
return false;
|
|
339
351
|
}
|
|
352
|
+
|
|
340
353
|
function getTelegramQueueMenuListText(
|
|
341
354
|
items: readonly TelegramQueueMenuItem[],
|
|
342
355
|
emptyRefreshIndex?: number,
|
|
@@ -347,6 +360,7 @@ function getTelegramQueueMenuListText(
|
|
|
347
360
|
emptyRefreshIndex % EMPTY_QUEUE_REFRESH_TITLES.length
|
|
348
361
|
];
|
|
349
362
|
}
|
|
363
|
+
|
|
350
364
|
async function updateTelegramQueueMenuList<Context>(
|
|
351
365
|
callbackQueryId: string,
|
|
352
366
|
replyChatId: number,
|
|
@@ -364,6 +378,7 @@ async function updateTelegramQueueMenuList<Context>(
|
|
|
364
378
|
);
|
|
365
379
|
await deps.answerCallbackQuery(callbackQueryId, notice);
|
|
366
380
|
}
|
|
381
|
+
|
|
367
382
|
async function refreshStaleTelegramQueueMenuItem<Context>(
|
|
368
383
|
callbackQueryId: string,
|
|
369
384
|
replyChatId: number,
|
|
@@ -378,6 +393,7 @@ async function refreshStaleTelegramQueueMenuItem<Context>(
|
|
|
378
393
|
"Item no longer in queue.",
|
|
379
394
|
);
|
|
380
395
|
}
|
|
396
|
+
|
|
381
397
|
async function handleTelegramQueueMenuPick<Context>(
|
|
382
398
|
callbackQueryId: string,
|
|
383
399
|
replyChatId: number,
|
|
@@ -403,6 +419,7 @@ async function handleTelegramQueueMenuPick<Context>(
|
|
|
403
419
|
);
|
|
404
420
|
await deps.answerCallbackQuery(callbackQueryId);
|
|
405
421
|
}
|
|
422
|
+
|
|
406
423
|
async function handleTelegramQueueMenuPriority<Context>(
|
|
407
424
|
callbackQueryId: string,
|
|
408
425
|
replyChatId: number,
|
|
@@ -432,6 +449,7 @@ async function handleTelegramQueueMenuPriority<Context>(
|
|
|
432
449
|
deps,
|
|
433
450
|
);
|
|
434
451
|
}
|
|
452
|
+
|
|
435
453
|
async function handleTelegramQueueMenuPrioritySet<Context>(
|
|
436
454
|
callbackQueryId: string,
|
|
437
455
|
replyChatId: number,
|
|
@@ -462,6 +480,7 @@ async function handleTelegramQueueMenuPrioritySet<Context>(
|
|
|
462
480
|
deps,
|
|
463
481
|
);
|
|
464
482
|
}
|
|
483
|
+
|
|
465
484
|
async function updateTelegramQueueMenuPriority<Context>(
|
|
466
485
|
callbackQueryId: string,
|
|
467
486
|
replyChatId: number,
|
|
@@ -494,6 +513,7 @@ async function updateTelegramQueueMenuPriority<Context>(
|
|
|
494
513
|
updated.isPriority ? "Prioritized." : "Normal priority.",
|
|
495
514
|
);
|
|
496
515
|
}
|
|
516
|
+
|
|
497
517
|
async function handleTelegramQueueMenuDeleteRequest<Context>(
|
|
498
518
|
callbackQueryId: string,
|
|
499
519
|
replyChatId: number,
|
|
@@ -519,6 +539,7 @@ async function handleTelegramQueueMenuDeleteRequest<Context>(
|
|
|
519
539
|
);
|
|
520
540
|
await deps.answerCallbackQuery(callbackQueryId);
|
|
521
541
|
}
|
|
542
|
+
|
|
522
543
|
async function handleTelegramQueueMenuKeep<Context>(
|
|
523
544
|
callbackQueryId: string,
|
|
524
545
|
replyChatId: number,
|
|
@@ -544,6 +565,7 @@ async function handleTelegramQueueMenuKeep<Context>(
|
|
|
544
565
|
);
|
|
545
566
|
await deps.answerCallbackQuery(callbackQueryId, "Kept in queue.");
|
|
546
567
|
}
|
|
568
|
+
|
|
547
569
|
async function handleTelegramQueueMenuConfirmDelete<Context>(
|
|
548
570
|
callbackQueryId: string,
|
|
549
571
|
replyChatId: number,
|
|
@@ -609,6 +631,7 @@ export function createTelegramQueueMenuRuntime<
|
|
|
609
631
|
) => Promise<TelegramModelMenuState<TModel>>;
|
|
610
632
|
getStoredModelMenuState: (
|
|
611
633
|
messageId: number | undefined,
|
|
634
|
+
chatId?: number,
|
|
612
635
|
) => TelegramModelMenuState<TModel> | undefined;
|
|
613
636
|
storeModelMenuState: (state: TelegramModelMenuState<TModel>) => void;
|
|
614
637
|
updateStatusMessage: (
|
|
@@ -641,6 +664,7 @@ export function createTelegramQueueMenuRuntime<
|
|
|
641
664
|
}),
|
|
642
665
|
};
|
|
643
666
|
}
|
|
667
|
+
|
|
644
668
|
function createOpenQueueMenu<
|
|
645
669
|
Context,
|
|
646
670
|
TModel extends MenuModel = MenuModel,
|
|
@@ -658,11 +682,11 @@ function createOpenQueueMenu<
|
|
|
658
682
|
replyMarkup: TelegramQueueMenuReplyMarkup,
|
|
659
683
|
) => Promise<number | undefined>;
|
|
660
684
|
}) {
|
|
661
|
-
return async
|
|
685
|
+
return async (
|
|
662
686
|
chatId: number,
|
|
663
687
|
replyToMessageId: number,
|
|
664
688
|
ctx: Context,
|
|
665
|
-
): Promise<void> {
|
|
689
|
+
): Promise<void> => {
|
|
666
690
|
const state = await deps.getModelMenuState(chatId, ctx);
|
|
667
691
|
const menuItems = toTelegramQueueMenuItems(deps.getQueuedItems());
|
|
668
692
|
const text = getTelegramQueueMenuListText(menuItems);
|
|
@@ -678,6 +702,7 @@ function createOpenQueueMenu<
|
|
|
678
702
|
deps.storeModelMenuState(state);
|
|
679
703
|
};
|
|
680
704
|
}
|
|
705
|
+
|
|
681
706
|
function createQueueMenuCallbackHandler<
|
|
682
707
|
Context,
|
|
683
708
|
TModel extends MenuModel = MenuModel,
|
|
@@ -692,6 +717,7 @@ function createQueueMenuCallbackHandler<
|
|
|
692
717
|
) => Promise<number | undefined>;
|
|
693
718
|
getStoredModelMenuState: (
|
|
694
719
|
messageId: number | undefined,
|
|
720
|
+
chatId?: number,
|
|
695
721
|
) => TelegramModelMenuState<TModel> | undefined;
|
|
696
722
|
updateStatusMessage: (
|
|
697
723
|
state: TelegramModelMenuState<TModel>,
|
|
@@ -703,17 +729,17 @@ function createQueueMenuCallbackHandler<
|
|
|
703
729
|
) => Promise<void>;
|
|
704
730
|
updateStatus: (ctx: Context) => void;
|
|
705
731
|
}) {
|
|
706
|
-
return async
|
|
732
|
+
return async (
|
|
707
733
|
query: TelegramQueueMenuCallbackQuery,
|
|
708
734
|
ctx: Context,
|
|
709
|
-
): Promise<boolean> {
|
|
735
|
+
): Promise<boolean> => {
|
|
710
736
|
const data = query.data;
|
|
711
737
|
const chatId = query.message?.chat?.id;
|
|
712
738
|
const messageId = query.message?.message_id;
|
|
713
739
|
if (!data || typeof chatId !== "number" || typeof messageId !== "number")
|
|
714
740
|
return false;
|
|
715
741
|
if (data === "menu:queue" || data === "status:queue") {
|
|
716
|
-
const state = deps.getStoredModelMenuState(messageId);
|
|
742
|
+
const state = deps.getStoredModelMenuState(messageId, chatId);
|
|
717
743
|
if (!state) {
|
|
718
744
|
await deps.answerCallbackQuery(
|
|
719
745
|
query.id,
|
|
@@ -735,13 +761,13 @@ function createQueueMenuCallbackHandler<
|
|
|
735
761
|
return true;
|
|
736
762
|
}
|
|
737
763
|
if (!data.startsWith("queue:")) return false;
|
|
738
|
-
const getQueueSnapshot =
|
|
764
|
+
const getQueueSnapshot = () => {
|
|
739
765
|
return deps.telegramQueueStore.getQueuedItems();
|
|
740
766
|
};
|
|
741
|
-
const toMenuItems =
|
|
767
|
+
const toMenuItems = () => {
|
|
742
768
|
return toTelegramQueueMenuItems(getQueueSnapshot());
|
|
743
769
|
};
|
|
744
|
-
const findItem =
|
|
770
|
+
const findItem = (cId: number, rId: number) => {
|
|
745
771
|
return findTelegramQueueMenuItem(toMenuItems(), cId, rId);
|
|
746
772
|
};
|
|
747
773
|
return handleTelegramQueueMenuCallback(
|
|
@@ -753,19 +779,19 @@ function createQueueMenuCallbackHandler<
|
|
|
753
779
|
{
|
|
754
780
|
getQueuedItems: toMenuItems,
|
|
755
781
|
findItem,
|
|
756
|
-
togglePriority:
|
|
782
|
+
togglePriority: (cId, rId) => {
|
|
757
783
|
return toggleQueuedTelegramPromptPriority(cId, rId, ctx, {
|
|
758
784
|
getQueueSnapshot,
|
|
759
785
|
queueMutationRuntime: deps.queueMutationRuntime,
|
|
760
786
|
});
|
|
761
787
|
},
|
|
762
|
-
setPriority:
|
|
788
|
+
setPriority: (cId, rId, enabled) => {
|
|
763
789
|
return setQueuedTelegramPromptPriority(cId, rId, enabled, ctx, {
|
|
764
790
|
getQueueSnapshot,
|
|
765
791
|
queueMutationRuntime: deps.queueMutationRuntime,
|
|
766
792
|
});
|
|
767
793
|
},
|
|
768
|
-
cancelItem:
|
|
794
|
+
cancelItem: (cId, rId, c) => {
|
|
769
795
|
return cancelQueuedTelegramItem(cId, rId, c, {
|
|
770
796
|
getQueueSnapshot,
|
|
771
797
|
queueMutationRuntime: deps.queueMutationRuntime,
|
|
@@ -778,6 +804,7 @@ function createQueueMenuCallbackHandler<
|
|
|
778
804
|
);
|
|
779
805
|
};
|
|
780
806
|
}
|
|
807
|
+
|
|
781
808
|
function toggleQueuedTelegramPromptPriority<Context>(
|
|
782
809
|
chatId: number,
|
|
783
810
|
replyToMessageId: number,
|
|
@@ -800,6 +827,7 @@ function toggleQueuedTelegramPromptPriority<Context>(
|
|
|
800
827
|
}
|
|
801
828
|
return true;
|
|
802
829
|
}
|
|
830
|
+
|
|
803
831
|
function setQueuedTelegramPromptPriority<Context>(
|
|
804
832
|
chatId: number,
|
|
805
833
|
replyToMessageId: number,
|
|
@@ -823,6 +851,7 @@ function setQueuedTelegramPromptPriority<Context>(
|
|
|
823
851
|
}
|
|
824
852
|
return true;
|
|
825
853
|
}
|
|
854
|
+
|
|
826
855
|
function cancelQueuedTelegramItem<Context>(
|
|
827
856
|
chatId: number,
|
|
828
857
|
replyToMessageId: number,
|
|
@@ -843,6 +872,7 @@ function cancelQueuedTelegramItem<Context>(
|
|
|
843
872
|
0
|
|
844
873
|
);
|
|
845
874
|
}
|
|
875
|
+
|
|
846
876
|
function createQueueMenuSendMessageAdapter(
|
|
847
877
|
sendInteractiveMessage: (
|
|
848
878
|
chatId: number,
|
|
@@ -851,15 +881,16 @@ function createQueueMenuSendMessageAdapter(
|
|
|
851
881
|
replyMarkup: TelegramQueueMenuReplyMarkup,
|
|
852
882
|
) => Promise<number | undefined>,
|
|
853
883
|
) {
|
|
854
|
-
return
|
|
884
|
+
return (
|
|
855
885
|
chatId: number,
|
|
856
886
|
_replyToMessageId: number,
|
|
857
887
|
text: string,
|
|
858
888
|
replyMarkup: TelegramQueueMenuReplyMarkup,
|
|
859
|
-
): Promise<number | undefined> {
|
|
889
|
+
): Promise<number | undefined> => {
|
|
860
890
|
return sendInteractiveMessage(chatId, text, "html", replyMarkup);
|
|
861
891
|
};
|
|
862
892
|
}
|
|
893
|
+
|
|
863
894
|
function createQueueMenuEditMessageAdapter(
|
|
864
895
|
editInteractiveMessage: (
|
|
865
896
|
chatId: number,
|
|
@@ -869,19 +900,19 @@ function createQueueMenuEditMessageAdapter(
|
|
|
869
900
|
replyMarkup: TelegramQueueMenuReplyMarkup,
|
|
870
901
|
) => Promise<void>,
|
|
871
902
|
) {
|
|
872
|
-
return
|
|
903
|
+
return (
|
|
873
904
|
chatId: number,
|
|
874
905
|
messageId: number,
|
|
875
906
|
text: string,
|
|
876
907
|
replyMarkup: TelegramQueueMenuReplyMarkup,
|
|
877
|
-
): Promise<number | undefined> {
|
|
908
|
+
): Promise<number | undefined> => {
|
|
878
909
|
return editInteractiveMessage(
|
|
879
910
|
chatId,
|
|
880
911
|
messageId,
|
|
881
912
|
text,
|
|
882
913
|
"html",
|
|
883
914
|
replyMarkup,
|
|
884
|
-
).then(
|
|
915
|
+
).then(() => {
|
|
885
916
|
return undefined as number | undefined;
|
|
886
917
|
});
|
|
887
918
|
};
|
package/lib/menu-settings.ts
CHANGED
|
@@ -65,7 +65,7 @@ export interface TelegramSettingsMenuRuntime<TContext> {
|
|
|
65
65
|
query: {
|
|
66
66
|
id: string;
|
|
67
67
|
data?: string;
|
|
68
|
-
message?: { message_id?: number };
|
|
68
|
+
message?: { message_id?: number; chat?: { id?: number } };
|
|
69
69
|
},
|
|
70
70
|
ctx: TContext,
|
|
71
71
|
) => Promise<boolean>;
|
|
@@ -92,6 +92,7 @@ export interface TelegramSettingsMenuRuntimeDeps<
|
|
|
92
92
|
) => Promise<TelegramModelMenuState<TModel>>;
|
|
93
93
|
getStoredModelMenuState: (
|
|
94
94
|
messageId: number | undefined,
|
|
95
|
+
chatId?: number,
|
|
95
96
|
) => TelegramModelMenuState<TModel> | undefined;
|
|
96
97
|
storeModelMenuState: (state: TelegramModelMenuState<TModel>) => void;
|
|
97
98
|
editInteractiveMessage: (
|
|
@@ -126,7 +127,7 @@ function getVoiceReplyModeLabel(mode: TelegramVoiceReplyModeSetting): string {
|
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
function getTelegramSettingsStateValueLabel(value: string): string {
|
|
129
|
-
return value.
|
|
130
|
+
return value.toLowerCase();
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
function getVoiceReplyModeSetting(
|
|
@@ -146,7 +147,7 @@ export function buildProactivePushSettingsText(
|
|
|
146
147
|
return [
|
|
147
148
|
`${PROACTIVE_PUSH_SETTINGS_TITLE} <code>${proactivePushEnabled ? "on" : "off"}</code>`,
|
|
148
149
|
"",
|
|
149
|
-
"Send successful local
|
|
150
|
+
"Send successful local Pi task results to Telegram when the bridge is connected.",
|
|
150
151
|
].join("\n");
|
|
151
152
|
}
|
|
152
153
|
|
|
@@ -218,7 +219,7 @@ export function buildTelegramSettingsMenuReplyMarkup(
|
|
|
218
219
|
],
|
|
219
220
|
[
|
|
220
221
|
{
|
|
221
|
-
text: `📌 Proactive push: ${proactivePushEnabled ? "
|
|
222
|
+
text: `📌 Proactive push: ${proactivePushEnabled ? "on" : "off"}`,
|
|
222
223
|
callback_data: "settings:open:proactive",
|
|
223
224
|
},
|
|
224
225
|
],
|
|
@@ -490,7 +491,10 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
490
491
|
),
|
|
491
492
|
handleCallbackQuery: async (query) => {
|
|
492
493
|
if (!query.data?.startsWith("settings:")) return false;
|
|
493
|
-
const state = deps.getStoredModelMenuState(
|
|
494
|
+
const state = deps.getStoredModelMenuState(
|
|
495
|
+
query.message?.message_id,
|
|
496
|
+
query.message?.chat?.id,
|
|
497
|
+
);
|
|
494
498
|
if (!state) {
|
|
495
499
|
const voiceMode = query.data.slice("settings:set:voice-reply:".length);
|
|
496
500
|
if (
|
package/lib/menu-status.ts
CHANGED
package/lib/menu-thinking.ts
CHANGED