@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-settings.ts
CHANGED
|
@@ -7,16 +7,21 @@
|
|
|
7
7
|
import type {
|
|
8
8
|
TelegramActivityVerbosity,
|
|
9
9
|
TelegramAssistantRenderingMode,
|
|
10
|
-
TelegramTimeMode,
|
|
11
10
|
TelegramThreadDisplayMode,
|
|
11
|
+
TelegramTimeMode,
|
|
12
12
|
} from "./config.ts";
|
|
13
13
|
import type { TelegramInlineKeyboardMarkup } from "./keyboard.ts";
|
|
14
|
-
import
|
|
14
|
+
import {
|
|
15
|
+
createTelegramMenuDelivery,
|
|
16
|
+
type TelegramMenuMessageRuntimeDeps,
|
|
17
|
+
type TelegramModelMenuState,
|
|
18
|
+
} from "./menu-model.ts";
|
|
15
19
|
import type { MenuModel } from "./model.ts";
|
|
16
20
|
import {
|
|
17
21
|
getTelegramExtensionSettingsRows,
|
|
18
22
|
type TelegramSectionRegistry,
|
|
19
23
|
} from "./sections.ts";
|
|
24
|
+
import type { TelegramApiCallOptions } from "./telegram-api.ts";
|
|
20
25
|
import type { TelegramVoiceReplyMode } from "./voice.ts";
|
|
21
26
|
|
|
22
27
|
export type TelegramSettingsMenuReplyMarkup = TelegramInlineKeyboardMarkup;
|
|
@@ -39,18 +44,22 @@ export interface TelegramSettingsMutationDeps extends TelegramSettingsStateDeps
|
|
|
39
44
|
setAssistantRenderingMode: (
|
|
40
45
|
mode: TelegramAssistantRenderingMode,
|
|
41
46
|
) => Promise<void>;
|
|
42
|
-
setActivityVerbosity: (
|
|
43
|
-
verbosity: TelegramActivityVerbosity,
|
|
44
|
-
) => Promise<void>;
|
|
47
|
+
setActivityVerbosity: (verbosity: TelegramActivityVerbosity) => Promise<void>;
|
|
45
48
|
setVoiceReplyMode: (
|
|
46
49
|
mode: TelegramVoiceReplyMode | undefined,
|
|
47
50
|
) => Promise<void>;
|
|
48
51
|
setTimeInjectionMode: (mode: TelegramTimeMode) => Promise<void>;
|
|
49
52
|
setAutomaticThreadCleanupEnabled: (enabled: boolean) => Promise<void>;
|
|
50
|
-
reviewInactiveThreads?: () => Promise<{
|
|
53
|
+
reviewInactiveThreads?: () => Promise<{
|
|
54
|
+
count: number;
|
|
55
|
+
operationId?: string;
|
|
56
|
+
}>;
|
|
51
57
|
cleanInactiveThreads?: (operationId: string) => Promise<{
|
|
52
|
-
deleted: number;
|
|
53
|
-
|
|
58
|
+
deleted: number;
|
|
59
|
+
outcomeUnknown: number;
|
|
60
|
+
blocked?: number;
|
|
61
|
+
recovery?:
|
|
62
|
+
"commit-ready" | "deletion-outcome-unknown" | "authority-blocked";
|
|
54
63
|
}>;
|
|
55
64
|
}
|
|
56
65
|
|
|
@@ -83,6 +92,8 @@ export interface TelegramSettingsMenuRuntime<TContext> {
|
|
|
83
92
|
chatId: number,
|
|
84
93
|
replyToMessageId: number,
|
|
85
94
|
ctx: TContext,
|
|
95
|
+
threadId?: number,
|
|
96
|
+
options?: Pick<TelegramApiCallOptions, "assertAuthority">,
|
|
86
97
|
) => Promise<void>;
|
|
87
98
|
handleCallbackQuery: (
|
|
88
99
|
query: {
|
|
@@ -131,12 +142,7 @@ export interface TelegramSettingsMenuRuntimeDeps<
|
|
|
131
142
|
mode: "markdown" | "html" | "plain",
|
|
132
143
|
replyMarkup: TelegramSettingsMenuReplyMarkup,
|
|
133
144
|
) => Promise<void>;
|
|
134
|
-
sendInteractiveMessage:
|
|
135
|
-
chatId: number,
|
|
136
|
-
text: string,
|
|
137
|
-
mode: "markdown" | "html" | "plain",
|
|
138
|
-
replyMarkup: TelegramSettingsMenuReplyMarkup,
|
|
139
|
-
) => Promise<number | undefined>;
|
|
145
|
+
sendInteractiveMessage: TelegramMenuMessageRuntimeDeps["sendInteractiveMessage"];
|
|
140
146
|
answerCallbackQuery: (
|
|
141
147
|
callbackQueryId: string,
|
|
142
148
|
text?: string,
|
|
@@ -144,16 +150,12 @@ export interface TelegramSettingsMenuRuntimeDeps<
|
|
|
144
150
|
}
|
|
145
151
|
|
|
146
152
|
const SETTINGS_MENU_TITLE = "<b>⚙️ Settings:</b>";
|
|
147
|
-
const AUTOMATIC_THREAD_CLEANUP_SETTINGS_TITLE =
|
|
148
|
-
"<b>🧹 Thread cleanup:</b>";
|
|
153
|
+
const AUTOMATIC_THREAD_CLEANUP_SETTINGS_TITLE = "<b>🧹 Thread cleanup:</b>";
|
|
149
154
|
const INACTIVE_THREAD_REVIEW_TITLE = "<b>🔎 Inactive tabs review:</b>";
|
|
150
155
|
const DRAFT_PREVIEWS_SETTINGS_TITLE = "<b>📝 Draft previews:</b>";
|
|
151
|
-
const ASSISTANT_RENDERING_SETTINGS_TITLE =
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
"<b>🔬 Activity:</b>";
|
|
155
|
-
const TIME_INJECTION_MODE_SETTINGS_TITLE =
|
|
156
|
-
"<b>🕒 Time injection mode:</b>";
|
|
156
|
+
const ASSISTANT_RENDERING_SETTINGS_TITLE = "<b>🧾 Assistant rendering:</b>";
|
|
157
|
+
const ACTIVITY_VERBOSITY_SETTINGS_TITLE = "<b>🔬 Activity:</b>";
|
|
158
|
+
const TIME_INJECTION_MODE_SETTINGS_TITLE = "<b>🕒 Time injection mode:</b>";
|
|
157
159
|
const VOICE_REPLY_MODE_SETTINGS_TITLE = "<b>👄 Voice reply mode:</b>";
|
|
158
160
|
const THREAD_DISPLAY_SETTINGS_TITLE = "<b>🧵 Thread display:</b>";
|
|
159
161
|
|
|
@@ -210,7 +212,9 @@ export function buildAutomaticThreadCleanupSettingsText(
|
|
|
210
212
|
}
|
|
211
213
|
|
|
212
214
|
function buildInactiveThreadReviewText(count: number): string {
|
|
213
|
-
return [
|
|
215
|
+
return [
|
|
216
|
+
INACTIVE_THREAD_REVIEW_TITLE,
|
|
217
|
+
"",
|
|
214
218
|
`${count} proven inactive tab${count === 1 ? "" : "s"}.`,
|
|
215
219
|
"No tabs were deleted.",
|
|
216
220
|
"Deletion requires a separate confirmed Clean action.",
|
|
@@ -221,16 +225,29 @@ export function buildInactiveThreadReviewReplyMarkup(
|
|
|
221
225
|
operationId?: string,
|
|
222
226
|
canCleanInactiveThreads = false,
|
|
223
227
|
): TelegramSettingsMenuReplyMarkup {
|
|
224
|
-
const validOperationId =
|
|
228
|
+
const validOperationId =
|
|
229
|
+
typeof operationId === "string" &&
|
|
225
230
|
/^thread-cleanup:[a-f0-9]{32}$/u.test(operationId);
|
|
226
|
-
return {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
return {
|
|
232
|
+
inline_keyboard: [
|
|
233
|
+
[
|
|
234
|
+
{
|
|
235
|
+
text: "⬆️ Back to Thread cleanup",
|
|
236
|
+
callback_data: "settings:open:automatic-thread-cleanup",
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
...(canCleanInactiveThreads && validOperationId
|
|
240
|
+
? [
|
|
241
|
+
[
|
|
242
|
+
{
|
|
243
|
+
text: "🧹 Clean inactive tabs",
|
|
244
|
+
callback_data: `settings:clean:${operationId}`,
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
]
|
|
248
|
+
: []),
|
|
249
|
+
],
|
|
250
|
+
};
|
|
234
251
|
}
|
|
235
252
|
|
|
236
253
|
export function buildDraftPreviewsSettingsText(enabled: boolean): string {
|
|
@@ -352,13 +369,13 @@ export function buildTelegramSettingsMenuReplyMarkup(
|
|
|
352
369
|
},
|
|
353
370
|
{
|
|
354
371
|
text: `👄 Voice reply: ${getTelegramSettingsStateValueLabel(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
),
|
|
372
|
+
getVoiceReplyModeLabel(
|
|
373
|
+
getVoiceReplyModeSetting(
|
|
374
|
+
voiceReplyMode,
|
|
375
|
+
effectiveVoiceReplyModeConfigured,
|
|
360
376
|
),
|
|
361
|
-
)
|
|
377
|
+
),
|
|
378
|
+
)}`,
|
|
362
379
|
callback_data: "settings:open:voice-reply",
|
|
363
380
|
},
|
|
364
381
|
{
|
|
@@ -370,16 +387,17 @@ export function buildTelegramSettingsMenuReplyMarkup(
|
|
|
370
387
|
callback_data: "settings:open:time-injection",
|
|
371
388
|
},
|
|
372
389
|
];
|
|
373
|
-
if (threadDisplayMode)
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
390
|
+
if (threadDisplayMode)
|
|
391
|
+
settingsButtons.push(
|
|
392
|
+
{
|
|
393
|
+
text: `🧹 Thread cleanup: ${automaticThreadCleanupEnabled ? "on" : "off"}`,
|
|
394
|
+
callback_data: "settings:open:automatic-thread-cleanup",
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
text: `🧵 Thread display: ${threadDisplayCustom ? "custom" : threadDisplayMode}`,
|
|
398
|
+
callback_data: "settings:open:thread-display",
|
|
399
|
+
},
|
|
400
|
+
);
|
|
383
401
|
if (sectionRegistry) {
|
|
384
402
|
const extensionRows = getTelegramExtensionSettingsRows(sectionRegistry);
|
|
385
403
|
settingsButtons.push(
|
|
@@ -393,9 +411,7 @@ export function buildTelegramSettingsMenuReplyMarkup(
|
|
|
393
411
|
return { inline_keyboard: rows };
|
|
394
412
|
}
|
|
395
413
|
|
|
396
|
-
async function openTelegramSettingsMenu<
|
|
397
|
-
TModel extends MenuModel = MenuModel,
|
|
398
|
-
>(
|
|
414
|
+
async function openTelegramSettingsMenu<TModel extends MenuModel = MenuModel>(
|
|
399
415
|
deps: TelegramSettingsMenuOpenDeps<TModel>,
|
|
400
416
|
sectionRegistry?: TelegramSectionRegistry,
|
|
401
417
|
): Promise<void> {
|
|
@@ -403,18 +419,7 @@ async function openTelegramSettingsMenu<
|
|
|
403
419
|
const messageId = await deps.sendSettingsMenu(
|
|
404
420
|
state,
|
|
405
421
|
buildTelegramSettingsMenuText(),
|
|
406
|
-
|
|
407
|
-
deps.areDraftPreviewsEnabled(),
|
|
408
|
-
deps.getAssistantRenderingMode(),
|
|
409
|
-
deps.getVoiceReplyMode(),
|
|
410
|
-
deps.getTimeInjectionMode(),
|
|
411
|
-
sectionRegistry,
|
|
412
|
-
deps.isVoiceReplyModeConfigured(),
|
|
413
|
-
deps.isAutomaticThreadCleanupEnabled(),
|
|
414
|
-
deps.getActivityVerbosity(),
|
|
415
|
-
deps.getThreadDisplayMode?.(),
|
|
416
|
-
deps.isThreadDisplayCustom?.() ?? false,
|
|
417
|
-
),
|
|
422
|
+
buildCurrentTelegramSettingsMenuReplyMarkup(deps, sectionRegistry),
|
|
418
423
|
);
|
|
419
424
|
if (messageId === undefined) return;
|
|
420
425
|
state.messageId = messageId;
|
|
@@ -424,11 +429,16 @@ async function openTelegramSettingsMenu<
|
|
|
424
429
|
|
|
425
430
|
function threadDisplayModeLabel(mode: TelegramThreadDisplayMode): string {
|
|
426
431
|
switch (mode) {
|
|
427
|
-
case "letters":
|
|
428
|
-
|
|
429
|
-
case "
|
|
430
|
-
|
|
431
|
-
|
|
432
|
+
case "letters":
|
|
433
|
+
return "letters";
|
|
434
|
+
case "names":
|
|
435
|
+
return "names";
|
|
436
|
+
case "directory-title":
|
|
437
|
+
return "directory-title";
|
|
438
|
+
case "directory-snake":
|
|
439
|
+
return "directory-snake";
|
|
440
|
+
default:
|
|
441
|
+
return "letters";
|
|
432
442
|
}
|
|
433
443
|
}
|
|
434
444
|
|
|
@@ -436,13 +446,19 @@ export function buildThreadDisplaySettingsReplyMarkup(
|
|
|
436
446
|
mode: TelegramThreadDisplayMode,
|
|
437
447
|
custom = false,
|
|
438
448
|
): TelegramSettingsMenuReplyMarkup {
|
|
439
|
-
return {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
449
|
+
return {
|
|
450
|
+
inline_keyboard: [
|
|
451
|
+
[{ text: "⬆️ Back", callback_data: "settings:list" }],
|
|
452
|
+
...(
|
|
453
|
+
["letters", "names", "directory-title", "directory-snake"] as const
|
|
454
|
+
).map((value) => [
|
|
455
|
+
{
|
|
456
|
+
text: `${!custom && mode === value ? "🟢 " : ""}${threadDisplayModeLabel(value)}`,
|
|
457
|
+
callback_data: `settings:set:thread-display:${value}`,
|
|
458
|
+
},
|
|
459
|
+
]),
|
|
460
|
+
],
|
|
461
|
+
};
|
|
446
462
|
}
|
|
447
463
|
|
|
448
464
|
export function buildAutomaticThreadCleanupSettingsReplyMarkup(
|
|
@@ -462,10 +478,16 @@ export function buildAutomaticThreadCleanupSettingsReplyMarkup(
|
|
|
462
478
|
callback_data: "settings:set:automatic-thread-cleanup:off",
|
|
463
479
|
},
|
|
464
480
|
],
|
|
465
|
-
...(canReviewInactiveThreads
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
481
|
+
...(canReviewInactiveThreads
|
|
482
|
+
? [
|
|
483
|
+
[
|
|
484
|
+
{
|
|
485
|
+
text: "🔎 Review inactive tabs",
|
|
486
|
+
callback_data: "settings:review:inactive-threads",
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
]
|
|
490
|
+
: []),
|
|
469
491
|
],
|
|
470
492
|
};
|
|
471
493
|
}
|
|
@@ -560,24 +582,45 @@ export function buildVoiceReplyModeSettingsReplyMarkup(
|
|
|
560
582
|
};
|
|
561
583
|
}
|
|
562
584
|
|
|
585
|
+
type TelegramSettingsMenuValuePorts = Pick<
|
|
586
|
+
TelegramSettingsMenuMessageUpdateDeps,
|
|
587
|
+
| "areDraftPreviewsEnabled"
|
|
588
|
+
| "getAssistantRenderingMode"
|
|
589
|
+
| "getVoiceReplyMode"
|
|
590
|
+
| "getTimeInjectionMode"
|
|
591
|
+
| "isVoiceReplyModeConfigured"
|
|
592
|
+
| "isAutomaticThreadCleanupEnabled"
|
|
593
|
+
| "getActivityVerbosity"
|
|
594
|
+
| "getThreadDisplayMode"
|
|
595
|
+
| "isThreadDisplayCustom"
|
|
596
|
+
>;
|
|
597
|
+
|
|
598
|
+
/** Settings markup from the current setting values; rendering only, no state mutation. */
|
|
599
|
+
function buildCurrentTelegramSettingsMenuReplyMarkup(
|
|
600
|
+
deps: TelegramSettingsMenuValuePorts,
|
|
601
|
+
sectionRegistry?: TelegramSectionRegistry,
|
|
602
|
+
) {
|
|
603
|
+
return buildTelegramSettingsMenuReplyMarkup(
|
|
604
|
+
deps.areDraftPreviewsEnabled(),
|
|
605
|
+
deps.getAssistantRenderingMode(),
|
|
606
|
+
deps.getVoiceReplyMode(),
|
|
607
|
+
deps.getTimeInjectionMode(),
|
|
608
|
+
sectionRegistry,
|
|
609
|
+
deps.isVoiceReplyModeConfigured(),
|
|
610
|
+
deps.isAutomaticThreadCleanupEnabled(),
|
|
611
|
+
deps.getActivityVerbosity(),
|
|
612
|
+
deps.getThreadDisplayMode?.(),
|
|
613
|
+
deps.isThreadDisplayCustom?.() ?? false,
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
|
|
563
617
|
async function updateTelegramSettingsMenuMessage(
|
|
564
618
|
deps: TelegramSettingsMenuMessageUpdateDeps,
|
|
565
619
|
sectionRegistry?: TelegramSectionRegistry,
|
|
566
620
|
): Promise<void> {
|
|
567
621
|
await deps.updateSettingsMessage(
|
|
568
622
|
buildTelegramSettingsMenuText(),
|
|
569
|
-
|
|
570
|
-
deps.areDraftPreviewsEnabled(),
|
|
571
|
-
deps.getAssistantRenderingMode(),
|
|
572
|
-
deps.getVoiceReplyMode(),
|
|
573
|
-
deps.getTimeInjectionMode(),
|
|
574
|
-
sectionRegistry,
|
|
575
|
-
deps.isVoiceReplyModeConfigured(),
|
|
576
|
-
deps.isAutomaticThreadCleanupEnabled(),
|
|
577
|
-
deps.getActivityVerbosity(),
|
|
578
|
-
deps.getThreadDisplayMode?.(),
|
|
579
|
-
deps.isThreadDisplayCustom?.() ?? false,
|
|
580
|
-
),
|
|
623
|
+
buildCurrentTelegramSettingsMenuReplyMarkup(deps, sectionRegistry),
|
|
581
624
|
);
|
|
582
625
|
}
|
|
583
626
|
|
|
@@ -587,7 +630,10 @@ async function updateAutomaticThreadCleanupSettingsMessage(
|
|
|
587
630
|
const enabled = deps.isAutomaticThreadCleanupEnabled();
|
|
588
631
|
await deps.updateSettingsMessage(
|
|
589
632
|
buildAutomaticThreadCleanupSettingsText(enabled),
|
|
590
|
-
buildAutomaticThreadCleanupSettingsReplyMarkup(
|
|
633
|
+
buildAutomaticThreadCleanupSettingsReplyMarkup(
|
|
634
|
+
enabled,
|
|
635
|
+
!!deps.reviewInactiveThreads,
|
|
636
|
+
),
|
|
591
637
|
);
|
|
592
638
|
}
|
|
593
639
|
|
|
@@ -648,33 +694,58 @@ export async function handleTelegramSettingsMenuCallbackAction(
|
|
|
648
694
|
deps: TelegramSettingsMenuCallbackDeps,
|
|
649
695
|
): Promise<boolean> {
|
|
650
696
|
if (!data?.startsWith("settings:")) return false;
|
|
651
|
-
if (
|
|
697
|
+
if (
|
|
698
|
+
data === "settings:open:thread-display" ||
|
|
699
|
+
data.startsWith("settings:set:thread-display:")
|
|
700
|
+
) {
|
|
652
701
|
if (!deps.getThreadDisplayMode?.() || !deps.setThreadDisplayMode) {
|
|
653
|
-
await deps.answerCallbackQuery(
|
|
702
|
+
await deps.answerCallbackQuery(
|
|
703
|
+
callbackQueryId,
|
|
704
|
+
"Thread display requires Threaded Mode and a connected instance",
|
|
705
|
+
);
|
|
654
706
|
return true;
|
|
655
707
|
}
|
|
656
708
|
if (data.startsWith("settings:set:thread-display:")) {
|
|
657
709
|
const mode = data.slice("settings:set:thread-display:".length);
|
|
658
|
-
if (
|
|
659
|
-
|
|
660
|
-
|
|
710
|
+
if (
|
|
711
|
+
mode !== "letters" &&
|
|
712
|
+
mode !== "names" &&
|
|
713
|
+
mode !== "directory-snake" &&
|
|
714
|
+
mode !== "directory-title"
|
|
715
|
+
) {
|
|
716
|
+
await deps.answerCallbackQuery(
|
|
717
|
+
callbackQueryId,
|
|
718
|
+
"Unknown Thread display mode",
|
|
719
|
+
);
|
|
661
720
|
return true;
|
|
662
721
|
}
|
|
663
722
|
try {
|
|
664
723
|
await deps.setThreadDisplayMode(mode);
|
|
665
724
|
} catch {
|
|
666
|
-
await deps.answerCallbackQuery(
|
|
725
|
+
await deps.answerCallbackQuery(
|
|
726
|
+
callbackQueryId,
|
|
727
|
+
"Thread display was not fully applied. The preference may be saved; retry after checking the leader",
|
|
728
|
+
);
|
|
667
729
|
return true;
|
|
668
730
|
}
|
|
669
731
|
}
|
|
670
732
|
const mode = deps.getThreadDisplayMode();
|
|
671
733
|
if (!mode) {
|
|
672
|
-
await deps.answerCallbackQuery(
|
|
734
|
+
await deps.answerCallbackQuery(
|
|
735
|
+
callbackQueryId,
|
|
736
|
+
"Threaded Mode is no longer available",
|
|
737
|
+
);
|
|
673
738
|
return true;
|
|
674
739
|
}
|
|
675
740
|
await deps.updateSettingsMessage(
|
|
676
|
-
buildThreadDisplaySettingsText(
|
|
677
|
-
|
|
741
|
+
buildThreadDisplaySettingsText(
|
|
742
|
+
mode,
|
|
743
|
+
deps.isThreadDisplayCustom?.() ?? false,
|
|
744
|
+
),
|
|
745
|
+
buildThreadDisplaySettingsReplyMarkup(
|
|
746
|
+
mode,
|
|
747
|
+
deps.isThreadDisplayCustom?.() ?? false,
|
|
748
|
+
),
|
|
678
749
|
);
|
|
679
750
|
await deps.answerCallbackQuery(callbackQueryId);
|
|
680
751
|
return true;
|
|
@@ -697,7 +768,7 @@ export async function handleTelegramSettingsMenuCallbackAction(
|
|
|
697
768
|
await updateTelegramSettingsMenuMessage(deps, deps.sectionRegistry);
|
|
698
769
|
await deps.answerCallbackQuery(
|
|
699
770
|
callbackQueryId,
|
|
700
|
-
"Public assistant output is always delivered while Telegram is connected
|
|
771
|
+
"Public assistant output is always delivered while Telegram is connected",
|
|
701
772
|
);
|
|
702
773
|
return true;
|
|
703
774
|
}
|
|
@@ -806,48 +877,77 @@ export async function handleTelegramSettingsMenuCallbackAction(
|
|
|
806
877
|
) {
|
|
807
878
|
await deps.setActivityVerbosity(verbosity);
|
|
808
879
|
await updateActivityVerbositySettingsMessage(deps);
|
|
809
|
-
await deps.answerCallbackQuery(
|
|
810
|
-
callbackQueryId,
|
|
811
|
-
`Activity: ${verbosity}`,
|
|
812
|
-
);
|
|
880
|
+
await deps.answerCallbackQuery(callbackQueryId, `Activity: ${verbosity}`);
|
|
813
881
|
return true;
|
|
814
882
|
}
|
|
815
883
|
}
|
|
816
884
|
if (data === "settings:review:inactive-threads") {
|
|
817
885
|
if (!deps.reviewInactiveThreads) {
|
|
818
|
-
await deps.answerCallbackQuery(
|
|
886
|
+
await deps.answerCallbackQuery(
|
|
887
|
+
callbackQueryId,
|
|
888
|
+
"Inactive tab review is unavailable",
|
|
889
|
+
);
|
|
819
890
|
return true;
|
|
820
891
|
}
|
|
821
892
|
try {
|
|
822
893
|
const review = await deps.reviewInactiveThreads();
|
|
823
894
|
if (review.count === 0) {
|
|
824
|
-
await deps.answerCallbackQuery(
|
|
895
|
+
await deps.answerCallbackQuery(
|
|
896
|
+
callbackQueryId,
|
|
897
|
+
"No proven inactive tabs",
|
|
898
|
+
);
|
|
825
899
|
} else {
|
|
826
|
-
await deps.updateSettingsMessage(
|
|
827
|
-
|
|
828
|
-
|
|
900
|
+
await deps.updateSettingsMessage(
|
|
901
|
+
buildInactiveThreadReviewText(review.count),
|
|
902
|
+
buildInactiveThreadReviewReplyMarkup(
|
|
903
|
+
review.operationId,
|
|
904
|
+
!!deps.cleanInactiveThreads,
|
|
905
|
+
),
|
|
906
|
+
);
|
|
907
|
+
await deps.answerCallbackQuery(
|
|
908
|
+
callbackQueryId,
|
|
909
|
+
"Review prepared. No tabs were deleted",
|
|
910
|
+
);
|
|
829
911
|
}
|
|
830
912
|
} catch {
|
|
831
|
-
await deps.answerCallbackQuery(
|
|
913
|
+
await deps.answerCallbackQuery(
|
|
914
|
+
callbackQueryId,
|
|
915
|
+
"Could not safely review inactive tabs",
|
|
916
|
+
);
|
|
832
917
|
}
|
|
833
918
|
return true;
|
|
834
919
|
}
|
|
835
920
|
if (data.startsWith("settings:clean:")) {
|
|
836
921
|
const operationId = data.slice("settings:clean:".length);
|
|
837
|
-
if (
|
|
838
|
-
|
|
922
|
+
if (
|
|
923
|
+
!/^thread-cleanup:[a-f0-9]{32}$/u.test(operationId) ||
|
|
924
|
+
!deps.cleanInactiveThreads
|
|
925
|
+
) {
|
|
926
|
+
await deps.answerCallbackQuery(
|
|
927
|
+
callbackQueryId,
|
|
928
|
+
"Cleanup confirmation is unavailable or stale",
|
|
929
|
+
);
|
|
839
930
|
return true;
|
|
840
931
|
}
|
|
841
932
|
try {
|
|
842
933
|
const result = await deps.cleanInactiveThreads(operationId);
|
|
843
|
-
await deps.answerCallbackQuery(
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
934
|
+
await deps.answerCallbackQuery(
|
|
935
|
+
callbackQueryId,
|
|
936
|
+
`Deleted: ${result.deleted}. Outcome unknown: ${result.outcomeUnknown}` +
|
|
937
|
+
(result.blocked ? `. Blocked: ${result.blocked}` : "") +
|
|
938
|
+
(result.recovery === "commit-ready"
|
|
939
|
+
? ". Recovery: safe local commit pending"
|
|
940
|
+
: result.recovery === "deletion-outcome-unknown"
|
|
941
|
+
? ". Recovery: deletion outcome unknown; no retry"
|
|
942
|
+
: result.recovery === "authority-blocked"
|
|
943
|
+
? ". Recovery: cleanup authority unavailable"
|
|
944
|
+
: ""),
|
|
945
|
+
);
|
|
849
946
|
} catch {
|
|
850
|
-
await deps.answerCallbackQuery(
|
|
947
|
+
await deps.answerCallbackQuery(
|
|
948
|
+
callbackQueryId,
|
|
949
|
+
"Cleanup could not be safely completed",
|
|
950
|
+
);
|
|
851
951
|
}
|
|
852
952
|
return true;
|
|
853
953
|
}
|
|
@@ -875,29 +975,46 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
875
975
|
deps: TelegramSettingsMenuRuntimeDeps<TContext, TModel>,
|
|
876
976
|
sectionRegistry?: TelegramSectionRegistry,
|
|
877
977
|
): TelegramSettingsMenuRuntime<TContext> {
|
|
978
|
+
// Read per call so later port replacement on deps stays visible.
|
|
979
|
+
const readSettingsState = (): TelegramSettingsStateDeps => ({
|
|
980
|
+
areDraftPreviewsEnabled: deps.areDraftPreviewsEnabled,
|
|
981
|
+
getAssistantRenderingMode: deps.getAssistantRenderingMode,
|
|
982
|
+
getActivityVerbosity: deps.getActivityVerbosity,
|
|
983
|
+
getVoiceReplyMode: deps.getVoiceReplyMode,
|
|
984
|
+
isVoiceReplyModeConfigured: deps.isVoiceReplyModeConfigured,
|
|
985
|
+
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
986
|
+
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
987
|
+
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
988
|
+
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
989
|
+
});
|
|
878
990
|
return {
|
|
879
|
-
openSettingsMenu: async (
|
|
991
|
+
openSettingsMenu: async (
|
|
992
|
+
chatId,
|
|
993
|
+
_replyToMessageId,
|
|
994
|
+
ctx,
|
|
995
|
+
threadId,
|
|
996
|
+
options,
|
|
997
|
+
) => {
|
|
998
|
+
const delivery = createTelegramMenuDelivery(
|
|
999
|
+
{ chatId, threadId },
|
|
1000
|
+
options,
|
|
1001
|
+
deps,
|
|
1002
|
+
);
|
|
880
1003
|
await deps.reloadConfig?.();
|
|
1004
|
+
delivery.assertCurrent();
|
|
881
1005
|
return openTelegramSettingsMenu(
|
|
882
1006
|
{
|
|
883
|
-
getModelMenuState: () =>
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
getActivityVerbosity: deps.getActivityVerbosity,
|
|
887
|
-
getVoiceReplyMode: deps.getVoiceReplyMode,
|
|
888
|
-
isVoiceReplyModeConfigured: deps.isVoiceReplyModeConfigured,
|
|
889
|
-
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
890
|
-
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
891
|
-
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
892
|
-
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
1007
|
+
getModelMenuState: () =>
|
|
1008
|
+
deps.getModelMenuState(chatId, ctx, threadId),
|
|
1009
|
+
...readSettingsState(),
|
|
893
1010
|
sendSettingsMenu: (state, text, replyMarkup) =>
|
|
894
|
-
|
|
1011
|
+
delivery.sendInteractiveMessage(
|
|
895
1012
|
state.chatId,
|
|
896
1013
|
text,
|
|
897
1014
|
"html",
|
|
898
1015
|
replyMarkup,
|
|
899
1016
|
),
|
|
900
|
-
storeModelMenuState:
|
|
1017
|
+
storeModelMenuState: delivery.storeModelMenuState,
|
|
901
1018
|
},
|
|
902
1019
|
sectionRegistry,
|
|
903
1020
|
);
|
|
@@ -906,15 +1023,7 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
906
1023
|
await deps.reloadConfig?.();
|
|
907
1024
|
return updateTelegramSettingsMenuMessage(
|
|
908
1025
|
{
|
|
909
|
-
|
|
910
|
-
getAssistantRenderingMode: deps.getAssistantRenderingMode,
|
|
911
|
-
getActivityVerbosity: deps.getActivityVerbosity,
|
|
912
|
-
getVoiceReplyMode: deps.getVoiceReplyMode,
|
|
913
|
-
isVoiceReplyModeConfigured: deps.isVoiceReplyModeConfigured,
|
|
914
|
-
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
915
|
-
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
916
|
-
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
917
|
-
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
1026
|
+
...readSettingsState(),
|
|
918
1027
|
updateSettingsMessage: (text, replyMarkup) =>
|
|
919
1028
|
deps.editInteractiveMessage(
|
|
920
1029
|
state.chatId,
|
|
@@ -937,7 +1046,7 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
937
1046
|
if (typeof messageId !== "number" || typeof chatId !== "number") {
|
|
938
1047
|
await deps.answerCallbackQuery(
|
|
939
1048
|
query.id,
|
|
940
|
-
"Interactive message expired
|
|
1049
|
+
"Interactive message expired",
|
|
941
1050
|
);
|
|
942
1051
|
return true;
|
|
943
1052
|
}
|
|
@@ -951,15 +1060,7 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
951
1060
|
deps.storeModelMenuState(state);
|
|
952
1061
|
}
|
|
953
1062
|
return handleTelegramSettingsMenuCallbackAction(query.id, query.data, {
|
|
954
|
-
|
|
955
|
-
getAssistantRenderingMode: deps.getAssistantRenderingMode,
|
|
956
|
-
getActivityVerbosity: deps.getActivityVerbosity,
|
|
957
|
-
getVoiceReplyMode: deps.getVoiceReplyMode,
|
|
958
|
-
isVoiceReplyModeConfigured: deps.isVoiceReplyModeConfigured,
|
|
959
|
-
getTimeInjectionMode: deps.getTimeInjectionMode,
|
|
960
|
-
isAutomaticThreadCleanupEnabled: deps.isAutomaticThreadCleanupEnabled,
|
|
961
|
-
getThreadDisplayMode: deps.getThreadDisplayMode,
|
|
962
|
-
isThreadDisplayCustom: deps.isThreadDisplayCustom,
|
|
1063
|
+
...readSettingsState(),
|
|
963
1064
|
setThreadDisplayMode: deps.setThreadDisplayMode,
|
|
964
1065
|
setDraftPreviewsEnabled: deps.setDraftPreviewsEnabled,
|
|
965
1066
|
setAssistantRenderingMode: deps.setAssistantRenderingMode,
|
|
@@ -967,8 +1068,12 @@ export function createTelegramSettingsMenuRuntime<
|
|
|
967
1068
|
setVoiceReplyMode: deps.setVoiceReplyMode,
|
|
968
1069
|
setTimeInjectionMode: deps.setTimeInjectionMode,
|
|
969
1070
|
setAutomaticThreadCleanupEnabled: deps.setAutomaticThreadCleanupEnabled,
|
|
970
|
-
...(deps.reviewInactiveThreads
|
|
971
|
-
|
|
1071
|
+
...(deps.reviewInactiveThreads
|
|
1072
|
+
? { reviewInactiveThreads: deps.reviewInactiveThreads }
|
|
1073
|
+
: {}),
|
|
1074
|
+
...(deps.cleanInactiveThreads
|
|
1075
|
+
? { cleanInactiveThreads: deps.cleanInactiveThreads }
|
|
1076
|
+
: {}),
|
|
972
1077
|
updateSettingsMessage: (text, replyMarkup) =>
|
|
973
1078
|
deps.editInteractiveMessage(
|
|
974
1079
|
state.chatId,
|