@llblab/pi-telegram 0.52.2 → 0.53.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 +9 -7
- package/BACKLOG.md +1 -18
- package/CHANGELOG.md +11 -0
- package/README.md +7 -11
- package/api/commands.ts +3 -0
- package/dist/api/commands.d.ts +1 -1
- package/dist/lib/activity-verbosity.d.ts +1 -5
- package/dist/lib/activity-verbosity.js +15 -42
- package/dist/lib/activity.d.ts +9 -0
- package/dist/lib/activity.js +39 -10
- package/dist/lib/agent-messages.js +7 -3
- package/dist/lib/bindings.d.ts +43 -5
- package/dist/lib/bindings.js +163 -20
- package/dist/lib/bus-api.d.ts +12 -0
- package/dist/lib/bus-api.js +182 -79
- package/dist/lib/bus-follower.d.ts +111 -31
- package/dist/lib/bus-follower.js +1324 -359
- package/dist/lib/bus-leader.d.ts +41 -91
- package/dist/lib/bus-leader.js +969 -637
- package/dist/lib/bus-transport.js +16 -9
- package/dist/lib/bus.d.ts +215 -18
- package/dist/lib/bus.js +1048 -327
- package/dist/lib/channel-posts.d.ts +5 -0
- package/dist/lib/channel-posts.js +434 -261
- package/dist/lib/command-templates.d.ts +26 -5
- package/dist/lib/command-templates.js +92 -176
- package/dist/lib/commands.d.ts +168 -82
- package/dist/lib/commands.js +1409 -291
- package/dist/lib/config.d.ts +1 -8
- package/dist/lib/config.js +34 -76
- package/dist/lib/delivery.d.ts +2 -2
- package/dist/lib/delivery.js +16 -16
- package/dist/lib/extension.js +639 -171
- package/dist/lib/generative-app-worker.mjs +19 -7
- package/dist/lib/generative-apps.d.ts +0 -5
- package/dist/lib/generative-apps.js +61 -49
- package/dist/lib/inbound.d.ts +5 -0
- package/dist/lib/inbound.js +35 -59
- package/dist/lib/journal.d.ts +33 -3
- package/dist/lib/journal.js +2063 -782
- package/dist/lib/lifecycle.d.ts +2 -6
- package/dist/lib/lifecycle.js +75 -58
- package/dist/lib/locks.d.ts +29 -3
- package/dist/lib/locks.js +289 -108
- package/dist/lib/logging.js +50 -14
- package/dist/lib/media.d.ts +22 -1
- package/dist/lib/media.js +46 -28
- package/dist/lib/menu-model.d.ts +19 -5
- package/dist/lib/menu-model.js +53 -11
- package/dist/lib/menu-queue.d.ts +5 -4
- package/dist/lib/menu-queue.js +45 -63
- package/dist/lib/menu-settings.d.ts +5 -4
- package/dist/lib/menu-settings.js +114 -78
- package/dist/lib/menu-status.d.ts +1 -1
- package/dist/lib/menu-status.js +8 -25
- package/dist/lib/menu-thinking.d.ts +6 -1
- package/dist/lib/menu-thinking.js +14 -21
- package/dist/lib/menu.d.ts +8 -61
- package/dist/lib/menu.js +92 -164
- package/dist/lib/model.d.ts +1 -1
- package/dist/lib/model.js +2 -16
- package/dist/lib/outbound-attachments.d.ts +6 -27
- package/dist/lib/outbound-attachments.js +45 -38
- package/dist/lib/outbound-buttons.js +22 -16
- package/dist/lib/outbound-markup.d.ts +0 -2
- package/dist/lib/outbound-markup.js +51 -64
- package/dist/lib/outbound-voice.js +6 -3
- package/dist/lib/outbound.d.ts +6 -6
- package/dist/lib/outbound.js +61 -51
- package/dist/lib/ownership.js +6 -2
- package/dist/lib/paths.d.ts +5 -0
- package/dist/lib/paths.js +37 -21
- package/dist/lib/pi.d.ts +2 -0
- package/dist/lib/pi.js +8 -1
- package/dist/lib/polling.d.ts +21 -37
- package/dist/lib/polling.js +59 -50
- package/dist/lib/preview.js +39 -19
- package/dist/lib/process-identity.d.ts +24 -0
- package/dist/lib/process-identity.js +133 -0
- package/dist/lib/prompts.js +2 -7
- package/dist/lib/queue.d.ts +14 -16
- package/dist/lib/queue.js +249 -126
- package/dist/lib/recovery.d.ts +2 -83
- package/dist/lib/recovery.js +20 -274
- package/dist/lib/replies.d.ts +16 -24
- package/dist/lib/replies.js +99 -116
- package/dist/lib/routing.d.ts +120 -7
- package/dist/lib/routing.js +4667 -1152
- package/dist/lib/runtime.d.ts +1 -11
- package/dist/lib/sections.d.ts +4 -29
- package/dist/lib/sections.js +7 -20
- package/dist/lib/skills.js +4 -3
- package/dist/lib/status.js +86 -57
- package/dist/lib/sync.d.ts +1 -3
- package/dist/lib/sync.js +67 -43
- package/dist/lib/target.d.ts +4 -0
- package/dist/lib/target.js +18 -0
- package/dist/lib/telegram-api.d.ts +18 -13
- package/dist/lib/telegram-api.js +148 -53
- package/dist/lib/text-groups.js +4 -39
- package/dist/lib/thread-cleanup-manager.d.ts +6 -27
- package/dist/lib/thread-cleanup-manager.js +369 -186
- package/dist/lib/thread-display.d.ts +1 -2
- package/dist/lib/thread-display.js +58 -38
- package/dist/lib/thread-naming.d.ts +28 -8
- package/dist/lib/thread-naming.js +175 -66
- package/dist/lib/thread-reconciler.d.ts +42 -16
- package/dist/lib/thread-reconciler.js +90 -50
- package/dist/lib/threads.d.ts +82 -20
- package/dist/lib/threads.js +2247 -855
- package/dist/lib/time-injection.js +1 -2
- package/dist/lib/turns.js +1 -19
- package/dist/lib/updates.d.ts +169 -80
- package/dist/lib/updates.js +2418 -641
- package/dist/lib/voice.d.ts +7 -22
- package/dist/lib/voice.js +7 -22
- package/dist/lib/wire.js +1 -1
- package/dist/lib/workspace-admission.d.ts +3 -1
- package/dist/lib/workspace-admission.js +425 -211
- package/dist/lib/workspace-identity.js +8 -13
- package/dist/lib/workspace-retirement.d.ts +1 -1
- package/dist/lib/workspace-retirement.js +328 -140
- package/dist/lib/workspace-slots.js +8 -4
- package/dist/package.json +1 -1
- package/docs/architecture.md +31 -29
- package/docs/inbound.md +1 -1
- package/docs/multi-instance-bus.md +15 -3
- package/docs/outbound.md +1 -1
- package/docs/public-api.md +29 -1
- package/docs/ui-style.md +25 -8
- package/lib/activity-verbosity.ts +59 -82
- package/lib/activity.ts +146 -102
- package/lib/agent-messages.ts +12 -5
- package/lib/bindings.ts +389 -82
- package/lib/bus-api.ts +263 -102
- package/lib/bus-follower.ts +2440 -601
- package/lib/bus-leader.ts +2209 -1290
- package/lib/bus-transport.ts +46 -12
- package/lib/bus.ts +1673 -444
- package/lib/channel-posts.ts +848 -327
- package/lib/command-templates.ts +152 -265
- package/lib/commands.ts +2398 -555
- package/lib/config.ts +177 -170
- package/lib/delivery.ts +41 -29
- package/lib/extension.ts +1206 -433
- package/lib/generative-app-worker.mjs +19 -7
- package/lib/generative-apps.ts +324 -211
- package/lib/inbound.ts +95 -97
- package/lib/journal.ts +5311 -1763
- package/lib/keyboard.ts +1 -3
- package/lib/lifecycle.ts +128 -78
- package/lib/locks.ts +677 -203
- package/lib/logging.ts +147 -58
- package/lib/media.ts +82 -43
- package/lib/menu-model.ts +85 -18
- package/lib/menu-queue.ts +88 -129
- package/lib/menu-settings.ts +260 -155
- package/lib/menu-status.ts +20 -60
- package/lib/menu-thinking.ts +41 -56
- package/lib/menu.ts +112 -285
- package/lib/model.ts +8 -22
- package/lib/outbound-attachments.ts +156 -125
- package/lib/outbound-buttons.ts +76 -49
- package/lib/outbound-markup.ts +96 -94
- package/lib/outbound-voice.ts +33 -27
- package/lib/outbound.ts +125 -125
- package/lib/ownership.ts +19 -10
- package/lib/paths.ts +148 -49
- package/lib/pi.ts +35 -15
- package/lib/polling.ts +144 -147
- package/lib/preview.ts +93 -40
- package/lib/process-identity.ts +164 -0
- package/lib/prompts.ts +4 -11
- package/lib/queue.ts +511 -300
- package/lib/recovery.ts +50 -454
- package/lib/rendering.ts +1 -3
- package/lib/replies.ts +248 -209
- package/lib/routing.ts +8509 -2186
- package/lib/runtime.ts +1 -12
- package/lib/sections.ts +24 -89
- package/lib/setup.ts +1 -3
- package/lib/skills.ts +9 -4
- package/lib/status.ts +215 -110
- package/lib/sync.ts +448 -361
- package/lib/target.ts +22 -3
- package/lib/telegram-api.ts +302 -127
- package/lib/text-groups.ts +5 -39
- package/lib/thread-cleanup-manager.ts +833 -331
- package/lib/thread-display.ts +213 -97
- package/lib/thread-naming.ts +232 -87
- package/lib/thread-reconciler.ts +155 -72
- package/lib/threads.ts +5318 -1845
- package/lib/time-injection.ts +1 -4
- package/lib/turns.ts +15 -28
- package/lib/updates.ts +5184 -1612
- package/lib/voice.ts +7 -35
- package/lib/wire.ts +1 -1
- package/lib/workspace-admission.ts +996 -416
- package/lib/workspace-identity.ts +14 -17
- package/lib/workspace-retirement.ts +878 -376
- package/lib/workspace-slots.ts +22 -13
- package/package.json +1 -1
- package/scripts/check-downgrade.mjs +0 -472
- package/scripts/measure-workspace.mjs +0 -108
package/lib/menu-model.ts
CHANGED
|
@@ -16,6 +16,11 @@ import {
|
|
|
16
16
|
type TelegramModelSwitchContinuationSource,
|
|
17
17
|
type ThinkingLevel,
|
|
18
18
|
} from "./model.ts";
|
|
19
|
+
import type { TelegramTarget } from "./target.ts";
|
|
20
|
+
import {
|
|
21
|
+
TelegramApiAuthorityError,
|
|
22
|
+
type TelegramApiCallOptions,
|
|
23
|
+
} from "./telegram-api.ts";
|
|
19
24
|
|
|
20
25
|
const TELEGRAM_MODEL_MENU_CACHE_TTL_MS = 5000;
|
|
21
26
|
const TELEGRAM_MODEL_MENU_STATE_TTL_MS = 10 * 60 * 1000;
|
|
@@ -141,10 +146,72 @@ export interface TelegramMenuMessageRuntimeDeps {
|
|
|
141
146
|
text: string,
|
|
142
147
|
mode: "markdown" | "html" | "plain",
|
|
143
148
|
replyMarkup: TelegramReplyMarkup,
|
|
144
|
-
options?: { target?:
|
|
149
|
+
options?: { target?: TelegramTarget } & Pick<
|
|
150
|
+
TelegramApiCallOptions,
|
|
151
|
+
"assertAuthority"
|
|
152
|
+
>,
|
|
145
153
|
) => Promise<number | undefined>;
|
|
146
154
|
}
|
|
147
155
|
|
|
156
|
+
/** Per-open delivery lifetime; never retain this guard in stored callback state. */
|
|
157
|
+
export function createTelegramMenuDelivery<TModel extends MenuModel>(
|
|
158
|
+
target: TelegramTarget,
|
|
159
|
+
options: Pick<TelegramApiCallOptions, "assertAuthority"> | undefined,
|
|
160
|
+
deps: Pick<TelegramMenuMessageRuntimeDeps, "sendInteractiveMessage"> & {
|
|
161
|
+
storeModelMenuState: (state: TelegramModelMenuState<TModel>) => void;
|
|
162
|
+
},
|
|
163
|
+
) {
|
|
164
|
+
const assertAuthority = options?.assertAuthority,
|
|
165
|
+
capturedTarget = { ...target };
|
|
166
|
+
const sendInteractiveMessage = deps.sendInteractiveMessage,
|
|
167
|
+
storeModelMenuState = deps.storeModelMenuState;
|
|
168
|
+
let requestIssued = false;
|
|
169
|
+
const assertCurrent = () => {
|
|
170
|
+
try {
|
|
171
|
+
assertAuthority?.();
|
|
172
|
+
} catch {
|
|
173
|
+
throw new TelegramApiAuthorityError(requestIssued);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
assertCurrent();
|
|
177
|
+
return {
|
|
178
|
+
assertCurrent,
|
|
179
|
+
assertAuthority,
|
|
180
|
+
sendInteractiveMessage: async (
|
|
181
|
+
...args: Parameters<
|
|
182
|
+
TelegramMenuMessageRuntimeDeps["sendInteractiveMessage"]
|
|
183
|
+
>
|
|
184
|
+
) => {
|
|
185
|
+
assertCurrent();
|
|
186
|
+
const [chatId, text, mode, replyMarkup, sendOptions] = args;
|
|
187
|
+
const messageId = await sendInteractiveMessage(
|
|
188
|
+
assertAuthority ? capturedTarget.chatId : chatId,
|
|
189
|
+
text,
|
|
190
|
+
mode,
|
|
191
|
+
replyMarkup,
|
|
192
|
+
assertAuthority
|
|
193
|
+
? { ...sendOptions, target: { ...capturedTarget }, assertAuthority }
|
|
194
|
+
: sendOptions,
|
|
195
|
+
);
|
|
196
|
+
requestIssued = true;
|
|
197
|
+
assertCurrent();
|
|
198
|
+
return messageId;
|
|
199
|
+
},
|
|
200
|
+
storeModelMenuState: (state: TelegramModelMenuState<TModel>) => {
|
|
201
|
+
assertCurrent();
|
|
202
|
+
if (
|
|
203
|
+
assertAuthority &&
|
|
204
|
+
(state.chatId !== capturedTarget.chatId ||
|
|
205
|
+
state.threadId !== capturedTarget.threadId)
|
|
206
|
+
) {
|
|
207
|
+
throw new TelegramApiAuthorityError(requestIssued);
|
|
208
|
+
}
|
|
209
|
+
storeModelMenuState(state);
|
|
210
|
+
assertCurrent();
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
148
215
|
export type TelegramModelMenuCallbackDeps<
|
|
149
216
|
TModel extends MenuModel = MenuModel,
|
|
150
217
|
> = {
|
|
@@ -322,7 +389,8 @@ function applyTelegramMenuRenderPayload(
|
|
|
322
389
|
return payload;
|
|
323
390
|
}
|
|
324
391
|
|
|
325
|
-
|
|
392
|
+
/** Apply the payload mode to state, then edit the existing menu message in place. */
|
|
393
|
+
export async function editTelegramMenuMessage(
|
|
326
394
|
state: TelegramModelMenuState,
|
|
327
395
|
payload: TelegramMenuRenderPayload,
|
|
328
396
|
deps: TelegramMenuMessageRuntimeDeps,
|
|
@@ -337,7 +405,8 @@ async function editTelegramMenuMessage(
|
|
|
337
405
|
);
|
|
338
406
|
}
|
|
339
407
|
|
|
340
|
-
|
|
408
|
+
/** Apply the payload mode to state, then send a fresh menu message to its exact chat/Thread. */
|
|
409
|
+
export function sendTelegramMenuMessage(
|
|
341
410
|
state: TelegramModelMenuState,
|
|
342
411
|
payload: TelegramMenuRenderPayload,
|
|
343
412
|
deps: TelegramMenuMessageRuntimeDeps,
|
|
@@ -661,9 +730,9 @@ function applyTelegramModelDetailSelection(
|
|
|
661
730
|
return "changed";
|
|
662
731
|
}
|
|
663
732
|
|
|
664
|
-
function getTelegramSelectedDetailModel<
|
|
665
|
-
TModel
|
|
666
|
-
|
|
733
|
+
function getTelegramSelectedDetailModel<TModel extends MenuModel = MenuModel>(
|
|
734
|
+
state: TelegramModelMenuState<TModel>,
|
|
735
|
+
): TelegramMenuSelectionResult<TModel> {
|
|
667
736
|
const indexedSelection = getTelegramModelSelection(
|
|
668
737
|
state,
|
|
669
738
|
state.selectedModelIndex?.toString(),
|
|
@@ -810,7 +879,7 @@ export function buildTelegramModelCallbackPlan<
|
|
|
810
879
|
action.value,
|
|
811
880
|
);
|
|
812
881
|
if (detailResult === "invalid") {
|
|
813
|
-
return { kind: "answer", text: "Selected model is no longer available
|
|
882
|
+
return { kind: "answer", text: "Selected model is no longer available" };
|
|
814
883
|
}
|
|
815
884
|
return { kind: "update-menu" };
|
|
816
885
|
}
|
|
@@ -822,12 +891,12 @@ export function buildTelegramModelCallbackPlan<
|
|
|
822
891
|
if (params.state.canMutateScope === false) {
|
|
823
892
|
return {
|
|
824
893
|
kind: "answer",
|
|
825
|
-
text: "Model scope is controlled by CLI --models
|
|
894
|
+
text: "Model scope is controlled by CLI --models",
|
|
826
895
|
};
|
|
827
896
|
}
|
|
828
897
|
const selectionResult = getTelegramSelectedDetailModel(params.state);
|
|
829
898
|
if (selectionResult.kind !== "selected") {
|
|
830
|
-
return { kind: "answer", text: "Selected model is no longer available
|
|
899
|
+
return { kind: "answer", text: "Selected model is no longer available" };
|
|
831
900
|
}
|
|
832
901
|
const model = selectionResult.selection.model;
|
|
833
902
|
const enabled =
|
|
@@ -854,10 +923,10 @@ export function buildTelegramModelCallbackPlan<
|
|
|
854
923
|
? getTelegramSelectedDetailModel(params.state)
|
|
855
924
|
: getTelegramModelSelection(params.state, action.value);
|
|
856
925
|
if (selectionResult.kind === "invalid") {
|
|
857
|
-
return { kind: "answer", text: "Invalid model selection
|
|
926
|
+
return { kind: "answer", text: "Invalid model selection" };
|
|
858
927
|
}
|
|
859
928
|
if (selectionResult.kind === "missing") {
|
|
860
|
-
return { kind: "answer", text: "Selected model is no longer available
|
|
929
|
+
return { kind: "answer", text: "Selected model is no longer available" };
|
|
861
930
|
}
|
|
862
931
|
const selection = selectionResult.selection;
|
|
863
932
|
if (modelsMatch(selection.model, params.activeModel)) {
|
|
@@ -877,7 +946,7 @@ export function buildTelegramModelCallbackPlan<
|
|
|
877
946
|
if (!params.canRestartBusyRun) {
|
|
878
947
|
return {
|
|
879
948
|
kind: "answer",
|
|
880
|
-
text: "Pi is busy. Send /abort, /next, or /stop
|
|
949
|
+
text: "Pi is busy. Send /abort, /next, or /stop",
|
|
881
950
|
};
|
|
882
951
|
}
|
|
883
952
|
return {
|
|
@@ -940,7 +1009,7 @@ export async function handleTelegramModelMenuCallbackAction<
|
|
|
940
1009
|
if (!deps.persistScopedModelPatterns) {
|
|
941
1010
|
await deps.answerCallbackQuery(
|
|
942
1011
|
callbackQueryId,
|
|
943
|
-
"Scoped model persistence is unavailable
|
|
1012
|
+
"Scoped model persistence is unavailable",
|
|
944
1013
|
);
|
|
945
1014
|
return true;
|
|
946
1015
|
}
|
|
@@ -959,7 +1028,7 @@ export async function handleTelegramModelMenuCallbackAction<
|
|
|
959
1028
|
}
|
|
960
1029
|
const changed = await deps.setModel(plan.selection.model);
|
|
961
1030
|
if (changed === false) {
|
|
962
|
-
await deps.answerCallbackQuery(callbackQueryId, "Model is not available
|
|
1031
|
+
await deps.answerCallbackQuery(callbackQueryId, "Model is not available");
|
|
963
1032
|
return true;
|
|
964
1033
|
}
|
|
965
1034
|
deps.setCurrentModel(plan.selection.model);
|
|
@@ -991,7 +1060,7 @@ export async function handleTelegramModelMenuCallbackAction<
|
|
|
991
1060
|
if (!restarted) {
|
|
992
1061
|
await deps.answerCallbackQuery(
|
|
993
1062
|
callbackQueryId,
|
|
994
|
-
"Pi is busy. Send /abort, /next, or /stop
|
|
1063
|
+
"Pi is busy. Send /abort, /next, or /stop",
|
|
995
1064
|
);
|
|
996
1065
|
return true;
|
|
997
1066
|
}
|
|
@@ -1100,9 +1169,7 @@ function buildModelDetailMenuReplyMarkup(
|
|
|
1100
1169
|
};
|
|
1101
1170
|
}
|
|
1102
1171
|
|
|
1103
|
-
function buildModelDetailMenuText(
|
|
1104
|
-
state: TelegramModelMenuState,
|
|
1105
|
-
): string {
|
|
1172
|
+
function buildModelDetailMenuText(state: TelegramModelMenuState): string {
|
|
1106
1173
|
const selection = getTelegramSelectedDetailModel(state);
|
|
1107
1174
|
if (selection.kind !== "selected") return MODEL_DETAIL_MENU_TITLE;
|
|
1108
1175
|
const model = selection.selection.model;
|
package/lib/menu-queue.ts
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { TelegramInlineKeyboardMarkup } from "./keyboard.ts";
|
|
8
|
-
import
|
|
8
|
+
import {
|
|
9
|
+
createTelegramMenuDelivery,
|
|
10
|
+
type TelegramMenuMessageRuntimeDeps,
|
|
11
|
+
type TelegramModelMenuState,
|
|
12
|
+
} from "./menu-model.ts";
|
|
9
13
|
import type { MenuModel } from "./model.ts";
|
|
10
14
|
import * as Queue from "./queue.ts";
|
|
11
|
-
|
|
12
|
-
// --- Queue Menu ---
|
|
15
|
+
import type { TelegramApiCallOptions } from "./telegram-api.ts";
|
|
13
16
|
|
|
14
17
|
const QUEUE_ITEM_PROMPT_HTML_LIMIT = 3600;
|
|
15
18
|
const QUEUE_ITEM_PROMPT_TRUNCATION_SUFFIX = "\n… [truncated]";
|
|
@@ -119,21 +122,13 @@ function buildTelegramQueueMenuReplyMarkup(
|
|
|
119
122
|
return { inline_keyboard: [backRow, refreshRow, ...rows] };
|
|
120
123
|
}
|
|
121
124
|
|
|
122
|
-
function findTelegramQueueItem<
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
): Queue.TelegramQueueItem<Context> | undefined {
|
|
127
|
-
return items.find((item) => {
|
|
128
|
-
return item.chatId === chatId && item.replyToMessageId === replyToMessageId;
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function findTelegramQueueMenuItem(
|
|
133
|
-
items: readonly TelegramQueueMenuItem[],
|
|
125
|
+
function findTelegramQueueItem<
|
|
126
|
+
TItem extends { chatId: number; replyToMessageId: number },
|
|
127
|
+
>(
|
|
128
|
+
items: readonly TItem[],
|
|
134
129
|
chatId: number,
|
|
135
130
|
replyToMessageId: number,
|
|
136
|
-
):
|
|
131
|
+
): TItem | undefined {
|
|
137
132
|
return items.find((item) => {
|
|
138
133
|
return item.chatId === chatId && item.replyToMessageId === replyToMessageId;
|
|
139
134
|
});
|
|
@@ -327,7 +322,7 @@ async function handleTelegramQueueMenuCallback<Context>(
|
|
|
327
322
|
replyChatId,
|
|
328
323
|
replyMessageId,
|
|
329
324
|
deps,
|
|
330
|
-
"Guest prompt skipped
|
|
325
|
+
"Guest prompt skipped",
|
|
331
326
|
);
|
|
332
327
|
return true;
|
|
333
328
|
}
|
|
@@ -372,9 +367,7 @@ async function handleTelegramQueueMenuCallback<Context>(
|
|
|
372
367
|
);
|
|
373
368
|
return true;
|
|
374
369
|
}
|
|
375
|
-
const skipSetMatch = data.match(
|
|
376
|
-
/^queue:skip-set:(\d+):(\d+):(skip|keep)$/,
|
|
377
|
-
);
|
|
370
|
+
const skipSetMatch = data.match(/^queue:skip-set:(\d+):(\d+):(skip|keep)$/);
|
|
378
371
|
if (skipSetMatch) {
|
|
379
372
|
await handleTelegramQueueMenuSkipSet(
|
|
380
373
|
callbackQueryId,
|
|
@@ -431,7 +424,7 @@ async function refreshStaleTelegramQueueMenuItem<Context>(
|
|
|
431
424
|
replyChatId,
|
|
432
425
|
replyMessageId,
|
|
433
426
|
deps,
|
|
434
|
-
"Item no longer in queue
|
|
427
|
+
"Item no longer in queue",
|
|
435
428
|
);
|
|
436
429
|
}
|
|
437
430
|
|
|
@@ -586,7 +579,7 @@ async function updateTelegramQueueMenuPriority<Context>(
|
|
|
586
579
|
);
|
|
587
580
|
await deps.answerCallbackQuery(
|
|
588
581
|
callbackQueryId,
|
|
589
|
-
updated.isPriority ? "Prioritized
|
|
582
|
+
updated.isPriority ? "Prioritized" : "Normal priority",
|
|
590
583
|
);
|
|
591
584
|
}
|
|
592
585
|
|
|
@@ -644,6 +637,8 @@ interface TelegramQueueMenuRuntime<Context> {
|
|
|
644
637
|
chatId: number,
|
|
645
638
|
replyToMessageId: number,
|
|
646
639
|
ctx: Context,
|
|
640
|
+
threadId?: number,
|
|
641
|
+
options?: Pick<TelegramApiCallOptions, "assertAuthority">,
|
|
647
642
|
) => Promise<void>;
|
|
648
643
|
handleCallbackQuery: (
|
|
649
644
|
query: TelegramQueueMenuCallbackQuery,
|
|
@@ -656,12 +651,7 @@ export function createTelegramQueueMenuRuntime<
|
|
|
656
651
|
>(deps: {
|
|
657
652
|
telegramQueueStore: Queue.TelegramQueueStateStore<Context>;
|
|
658
653
|
queueMutationRuntime: Queue.TelegramQueueMutationController<Context>;
|
|
659
|
-
sendInteractiveMessage:
|
|
660
|
-
chatId: number,
|
|
661
|
-
text: string,
|
|
662
|
-
mode: "html",
|
|
663
|
-
replyMarkup: TelegramQueueMenuReplyMarkup,
|
|
664
|
-
) => Promise<number | undefined>;
|
|
654
|
+
sendInteractiveMessage: TelegramMenuMessageRuntimeDeps["sendInteractiveMessage"];
|
|
665
655
|
editInteractiveMessage: (
|
|
666
656
|
chatId: number,
|
|
667
657
|
messageId: number,
|
|
@@ -676,6 +666,7 @@ export function createTelegramQueueMenuRuntime<
|
|
|
676
666
|
getModelMenuState: (
|
|
677
667
|
chatId: number,
|
|
678
668
|
ctx: Context,
|
|
669
|
+
threadId?: number,
|
|
679
670
|
) => Promise<TelegramModelMenuState<TModel>>;
|
|
680
671
|
getStoredModelMenuState: (
|
|
681
672
|
messageId: number | undefined,
|
|
@@ -696,12 +687,22 @@ export function createTelegramQueueMenuRuntime<
|
|
|
696
687
|
deps.editInteractiveMessage,
|
|
697
688
|
);
|
|
698
689
|
return {
|
|
699
|
-
openQueueMenu:
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
690
|
+
openQueueMenu: (chatId, replyToMessageId, ctx, threadId, options) => {
|
|
691
|
+
const delivery = createTelegramMenuDelivery(
|
|
692
|
+
{ chatId, threadId },
|
|
693
|
+
options,
|
|
694
|
+
deps,
|
|
695
|
+
);
|
|
696
|
+
return createOpenQueueMenu<Context, TModel>({
|
|
697
|
+
getQueuedItems: deps.telegramQueueStore.getQueuedItems,
|
|
698
|
+
getModelMenuState: (chat, context) =>
|
|
699
|
+
deps.getModelMenuState(chat, context, threadId),
|
|
700
|
+
storeModelMenuState: delivery.storeModelMenuState,
|
|
701
|
+
sendInteractiveMessage: delivery.assertAuthority
|
|
702
|
+
? createQueueMenuSendMessageAdapter(delivery.sendInteractiveMessage)
|
|
703
|
+
: sendQueueMenuMessage,
|
|
704
|
+
})(chatId, replyToMessageId, ctx);
|
|
705
|
+
},
|
|
705
706
|
handleCallbackQuery: createQueueMenuCallbackHandler<Context, TModel>({
|
|
706
707
|
telegramQueueStore: deps.telegramQueueStore,
|
|
707
708
|
queueMutationRuntime: deps.queueMutationRuntime,
|
|
@@ -792,10 +793,7 @@ function createQueueMenuCallbackHandler<
|
|
|
792
793
|
if (data === "menu:queue" || data === "status:queue") {
|
|
793
794
|
const state = deps.getStoredModelMenuState(messageId, chatId);
|
|
794
795
|
if (!state) {
|
|
795
|
-
await deps.answerCallbackQuery(
|
|
796
|
-
query.id,
|
|
797
|
-
"Interactive message expired.",
|
|
798
|
-
);
|
|
796
|
+
await deps.answerCallbackQuery(query.id, "Interactive message expired");
|
|
799
797
|
return true;
|
|
800
798
|
}
|
|
801
799
|
const menuItems = toTelegramQueueMenuItems(
|
|
@@ -819,13 +817,17 @@ function createQueueMenuCallbackHandler<
|
|
|
819
817
|
return toTelegramQueueMenuItems(getQueueSnapshot());
|
|
820
818
|
};
|
|
821
819
|
const findItem = (cId: number, rId: number) => {
|
|
822
|
-
return
|
|
820
|
+
return findTelegramQueueItem(toMenuItems(), cId, rId);
|
|
823
821
|
};
|
|
824
822
|
const findGuestItem = (queueOrder: number) => {
|
|
825
823
|
return toMenuItems().find((item) => {
|
|
826
824
|
return item.isGuest && item.queueOrder === queueOrder;
|
|
827
825
|
});
|
|
828
826
|
};
|
|
827
|
+
const flagDeps = {
|
|
828
|
+
getQueueSnapshot,
|
|
829
|
+
queueMutationRuntime: deps.queueMutationRuntime,
|
|
830
|
+
};
|
|
829
831
|
return handleTelegramQueueMenuCallback(
|
|
830
832
|
query.id,
|
|
831
833
|
data,
|
|
@@ -843,24 +845,34 @@ function createQueueMenuCallbackHandler<
|
|
|
843
845
|
dismissGuestPlaceholder: deps.dismissGuestPlaceholder,
|
|
844
846
|
});
|
|
845
847
|
},
|
|
846
|
-
togglePriority: (cId, rId) =>
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
848
|
+
togglePriority: (cId, rId) =>
|
|
849
|
+
applyQueuedTelegramPromptMenuFlags(
|
|
850
|
+
cId,
|
|
851
|
+
rId,
|
|
852
|
+
ctx,
|
|
853
|
+
flagDeps,
|
|
854
|
+
(item) => ({
|
|
855
|
+
priority: item.queueLane !== "priority",
|
|
856
|
+
skipped: isQueuedTelegramPromptSkipped(item),
|
|
857
|
+
}),
|
|
858
|
+
),
|
|
859
|
+
setPriority: (cId, rId, enabled) =>
|
|
860
|
+
applyQueuedTelegramPromptMenuFlags(
|
|
861
|
+
cId,
|
|
862
|
+
rId,
|
|
863
|
+
ctx,
|
|
864
|
+
flagDeps,
|
|
865
|
+
(item) => ({
|
|
866
|
+
priority: enabled,
|
|
867
|
+
skipped: isQueuedTelegramPromptSkipped(item),
|
|
868
|
+
}),
|
|
869
|
+
),
|
|
870
|
+
setSkipped: (cId, rId, skipped) =>
|
|
871
|
+
applyQueuedTelegramPromptMenuFlags(cId, rId, ctx, flagDeps, (item) =>
|
|
872
|
+
item.kind === "prompt"
|
|
873
|
+
? { priority: item.queueLane === "priority", skipped }
|
|
874
|
+
: undefined,
|
|
875
|
+
),
|
|
864
876
|
updateQueueMessage: deps.editInteractiveMessage,
|
|
865
877
|
answerCallbackQuery: deps.answerCallbackQuery,
|
|
866
878
|
updateStatus: deps.updateStatus,
|
|
@@ -879,9 +891,11 @@ async function skipQueuedTelegramGuestPrompt<Context>(
|
|
|
879
891
|
},
|
|
880
892
|
): Promise<boolean> {
|
|
881
893
|
const item = deps.getQueueSnapshot().find((candidate) => {
|
|
882
|
-
return
|
|
894
|
+
return (
|
|
895
|
+
candidate.kind === "prompt" &&
|
|
883
896
|
candidate.guestQueryId !== undefined &&
|
|
884
|
-
candidate.queueOrder === queueOrder
|
|
897
|
+
candidate.queueOrder === queueOrder
|
|
898
|
+
);
|
|
885
899
|
});
|
|
886
900
|
if (!item || !deps.queueMutationRuntime.removeGuestPromptByQueueOrder) {
|
|
887
901
|
return false;
|
|
@@ -906,111 +920,56 @@ function getQueueMenuReactionDisposition<Context>(
|
|
|
906
920
|
return {
|
|
907
921
|
kind: "priority-suppressed",
|
|
908
922
|
priorityEmoji:
|
|
909
|
-
item.kind === "prompt" ? item.priorityEmoji ?? "⚡" : "⚡",
|
|
923
|
+
item.kind === "prompt" ? (item.priorityEmoji ?? "⚡") : "⚡",
|
|
910
924
|
suppressionEmoji:
|
|
911
|
-
item.kind === "prompt"
|
|
912
|
-
? item.reactionSuppressionEmoji ?? "👎"
|
|
913
|
-
: "👎",
|
|
925
|
+
item.kind === "prompt" ? (item.reactionSuppressionEmoji ?? "👎") : "👎",
|
|
914
926
|
};
|
|
915
927
|
}
|
|
916
928
|
if (priority) {
|
|
917
929
|
return {
|
|
918
930
|
kind: "priority",
|
|
919
|
-
emoji: item.kind === "prompt" ? item.priorityEmoji ?? "⚡" : "⚡",
|
|
931
|
+
emoji: item.kind === "prompt" ? (item.priorityEmoji ?? "⚡") : "⚡",
|
|
920
932
|
};
|
|
921
933
|
}
|
|
922
934
|
if (skipped) {
|
|
923
935
|
return {
|
|
924
936
|
kind: "suppressed",
|
|
925
937
|
emoji:
|
|
926
|
-
item.kind === "prompt"
|
|
927
|
-
? item.reactionSuppressionEmoji ?? "👎"
|
|
928
|
-
: "👎",
|
|
938
|
+
item.kind === "prompt" ? (item.reactionSuppressionEmoji ?? "👎") : "👎",
|
|
929
939
|
};
|
|
930
940
|
}
|
|
931
941
|
return { kind: "default" };
|
|
932
942
|
}
|
|
933
943
|
|
|
934
|
-
function
|
|
935
|
-
|
|
936
|
-
replyToMessageId: number,
|
|
937
|
-
ctx: Context,
|
|
938
|
-
deps: {
|
|
939
|
-
getQueueSnapshot: () => Queue.TelegramQueueItem<Context>[];
|
|
940
|
-
queueMutationRuntime: Queue.TelegramQueueMutationController<Context>;
|
|
941
|
-
},
|
|
942
|
-
): boolean {
|
|
943
|
-
const item = findTelegramQueueItem(
|
|
944
|
-
deps.getQueueSnapshot(),
|
|
945
|
-
chatId,
|
|
946
|
-
replyToMessageId,
|
|
947
|
-
);
|
|
948
|
-
if (!item) return false;
|
|
949
|
-
deps.queueMutationRuntime.applyReactionByMessageId(
|
|
950
|
-
replyToMessageId,
|
|
951
|
-
getQueueMenuReactionDisposition(
|
|
952
|
-
item,
|
|
953
|
-
item.queueLane !== "priority",
|
|
954
|
-
item.kind === "prompt" &&
|
|
955
|
-
item.reactionSuppressionEmoji !== undefined,
|
|
956
|
-
),
|
|
957
|
-
ctx,
|
|
958
|
-
);
|
|
959
|
-
return true;
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
function setQueuedTelegramPromptPriority<Context>(
|
|
963
|
-
chatId: number,
|
|
964
|
-
replyToMessageId: number,
|
|
965
|
-
enabled: boolean,
|
|
966
|
-
ctx: Context,
|
|
967
|
-
deps: {
|
|
968
|
-
getQueueSnapshot: () => Queue.TelegramQueueItem<Context>[];
|
|
969
|
-
queueMutationRuntime: Queue.TelegramQueueMutationController<Context>;
|
|
970
|
-
},
|
|
944
|
+
function isQueuedTelegramPromptSkipped<Context>(
|
|
945
|
+
item: Queue.TelegramQueueItem<Context>,
|
|
971
946
|
): boolean {
|
|
972
|
-
|
|
973
|
-
deps.getQueueSnapshot(),
|
|
974
|
-
chatId,
|
|
975
|
-
replyToMessageId,
|
|
976
|
-
);
|
|
977
|
-
if (!item) return false;
|
|
978
|
-
deps.queueMutationRuntime.applyReactionByMessageId(
|
|
979
|
-
replyToMessageId,
|
|
980
|
-
getQueueMenuReactionDisposition(
|
|
981
|
-
item,
|
|
982
|
-
enabled,
|
|
983
|
-
item.kind === "prompt" &&
|
|
984
|
-
item.reactionSuppressionEmoji !== undefined,
|
|
985
|
-
),
|
|
986
|
-
ctx,
|
|
987
|
-
);
|
|
988
|
-
return true;
|
|
947
|
+
return item.kind === "prompt" && item.reactionSuppressionEmoji !== undefined;
|
|
989
948
|
}
|
|
990
949
|
|
|
991
|
-
|
|
950
|
+
/** Applies a menu Priority/Skip choice to one queued item through the reaction disposition path. */
|
|
951
|
+
function applyQueuedTelegramPromptMenuFlags<Context>(
|
|
992
952
|
chatId: number,
|
|
993
953
|
replyToMessageId: number,
|
|
994
|
-
skipped: boolean,
|
|
995
954
|
ctx: Context,
|
|
996
955
|
deps: {
|
|
997
956
|
getQueueSnapshot: () => Queue.TelegramQueueItem<Context>[];
|
|
998
957
|
queueMutationRuntime: Queue.TelegramQueueMutationController<Context>;
|
|
999
958
|
},
|
|
959
|
+
chooseFlags: (
|
|
960
|
+
item: Queue.TelegramQueueItem<Context>,
|
|
961
|
+
) => { priority: boolean; skipped: boolean } | undefined,
|
|
1000
962
|
): boolean {
|
|
1001
963
|
const item = findTelegramQueueItem(
|
|
1002
964
|
deps.getQueueSnapshot(),
|
|
1003
965
|
chatId,
|
|
1004
966
|
replyToMessageId,
|
|
1005
967
|
);
|
|
1006
|
-
|
|
968
|
+
const flags = item ? chooseFlags(item) : undefined;
|
|
969
|
+
if (!item || !flags) return false;
|
|
1007
970
|
deps.queueMutationRuntime.applyReactionByMessageId(
|
|
1008
971
|
replyToMessageId,
|
|
1009
|
-
getQueueMenuReactionDisposition(
|
|
1010
|
-
item,
|
|
1011
|
-
item.queueLane === "priority",
|
|
1012
|
-
skipped,
|
|
1013
|
-
),
|
|
972
|
+
getQueueMenuReactionDisposition(item, flags.priority, flags.skipped),
|
|
1014
973
|
ctx,
|
|
1015
974
|
);
|
|
1016
975
|
return true;
|