@llblab/pi-telegram 0.8.2 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/menu.ts CHANGED
@@ -118,6 +118,7 @@ export interface TelegramMenuEffectPort<TModel extends MenuModel = MenuModel> {
118
118
  updateModelMenuMessage: () => Promise<void>;
119
119
  updateThinkingMenuMessage: () => Promise<void>;
120
120
  updateStatusMessage: () => Promise<void>;
121
+ persistScopedModelPatterns?: (patterns: string[]) => Promise<void>;
121
122
  setModel: (model: TModel) => Promise<boolean>;
122
123
  setCurrentModel: (model: TModel) => void;
123
124
  setThinkingLevel: (level: ThinkingLevel) => void;
@@ -188,6 +189,10 @@ export interface TelegramMenuCallbackRuntimeDeps<
188
189
  state: TelegramModelMenuState<TModel>,
189
190
  ctx: TContext,
190
191
  ) => Promise<void>;
192
+ updateSettingsMenuMessage?: (
193
+ state: TelegramModelMenuState<TModel>,
194
+ ctx: TContext,
195
+ ) => Promise<void>;
191
196
  answerCallbackQuery: (
192
197
  callbackQueryId: string,
193
198
  text?: string,
@@ -196,6 +201,10 @@ export interface TelegramMenuCallbackRuntimeDeps<
196
201
  hasActiveTelegramTurn: () => boolean;
197
202
  hasAbortHandler: () => boolean;
198
203
  hasActiveToolExecutions: () => boolean;
204
+ persistScopedModelPatterns?: (
205
+ patterns: string[],
206
+ ctx: TContext,
207
+ ) => Promise<void>;
199
208
  setModel: (model: TModel) => Promise<boolean>;
200
209
  setCurrentModel: (model: TModel, ctx: TContext) => void;
201
210
  stagePendingModelSwitch: (
@@ -265,11 +274,21 @@ export interface TelegramMenuActionRuntime<
265
274
 
266
275
  export type TelegramMenuCallbackAction =
267
276
  | { kind: "ignore" }
268
- | { kind: "status"; action: "model" | "thinking" | "queue" }
277
+ | { kind: "status"; action: "model" | "thinking" | "queue" | "settings" }
269
278
  | { kind: "thinking:set"; level: string }
270
279
  | {
271
280
  kind: "model";
272
- action: "noop" | "scope" | "page" | "pages" | "pick";
281
+ action:
282
+ | "noop"
283
+ | "scope"
284
+ | "page"
285
+ | "pages"
286
+ | "open"
287
+ | "pick"
288
+ | "pick-selected"
289
+ | "scope-enable"
290
+ | "scope-disable"
291
+ | "scope-toggle";
273
292
  value?: string;
274
293
  };
275
294
 
@@ -285,6 +304,9 @@ export function parseTelegramMenuCallbackAction(
285
304
  if (data === "menu:queue" || data === "status:queue") {
286
305
  return { kind: "status", action: "queue" };
287
306
  }
307
+ if (data === "menu:settings" || data === "status:settings") {
308
+ return { kind: "status", action: "settings" };
309
+ }
288
310
  if (data?.startsWith("thinking:set:")) {
289
311
  return {
290
312
  kind: "thinking:set",
@@ -298,7 +320,12 @@ export function parseTelegramMenuCallbackAction(
298
320
  action === "scope" ||
299
321
  action === "page" ||
300
322
  action === "pages" ||
301
- action === "pick"
323
+ action === "open" ||
324
+ action === "pick" ||
325
+ action === "pick-selected" ||
326
+ action === "scope-enable" ||
327
+ action === "scope-disable" ||
328
+ action === "scope-toggle"
302
329
  ) {
303
330
  return { kind: "model", action, value };
304
331
  }
@@ -379,6 +406,10 @@ export interface TelegramMenuCallbackRuntimeAdapterDeps<
379
406
  state: TelegramModelMenuState<TModel>,
380
407
  ctx: TContext,
381
408
  ) => Promise<void>;
409
+ updateSettingsMenuMessage?: (
410
+ state: TelegramModelMenuState<TModel>,
411
+ ctx: TContext,
412
+ ) => Promise<void>;
382
413
  answerCallbackQuery: (
383
414
  callbackQueryId: string,
384
415
  text?: string,
@@ -387,6 +418,10 @@ export interface TelegramMenuCallbackRuntimeAdapterDeps<
387
418
  hasActiveTelegramTurn: () => boolean;
388
419
  hasAbortHandler: () => boolean;
389
420
  getActiveToolExecutions: () => number;
421
+ persistScopedModelPatterns?: (
422
+ patterns: string[],
423
+ ctx: TContext,
424
+ ) => Promise<void>;
390
425
  setModel: (model: TModel) => Promise<boolean>;
391
426
  setCurrentModel: (model: TModel, ctx: TContext) => void;
392
427
  stagePendingModelSwitch: (
@@ -425,11 +460,13 @@ export function createTelegramMenuCallbackHandlerForContext<
425
460
  updateModelMenuMessage: deps.updateModelMenuMessage,
426
461
  updateThinkingMenuMessage: deps.updateThinkingMenuMessage,
427
462
  updateStatusMessage: deps.updateStatusMessage,
463
+ updateSettingsMenuMessage: deps.updateSettingsMenuMessage,
428
464
  answerCallbackQuery: deps.answerCallbackQuery,
429
465
  isIdle: deps.isIdle,
430
466
  hasActiveTelegramTurn: deps.hasActiveTelegramTurn,
431
467
  hasAbortHandler: deps.hasAbortHandler,
432
468
  hasActiveToolExecutions: () => deps.getActiveToolExecutions() > 0,
469
+ persistScopedModelPatterns: deps.persistScopedModelPatterns,
433
470
  setModel: deps.setModel,
434
471
  setCurrentModel: deps.setCurrentModel,
435
472
  stagePendingModelSwitch: deps.stagePendingModelSwitch,
@@ -467,6 +504,8 @@ export async function handleTelegramMenuCallbackRuntime<
467
504
  updateModelMenuMessage: () => deps.updateModelMenuMessage(state, ctx),
468
505
  updateThinkingMenuMessage: () =>
469
506
  deps.updateThinkingMenuMessage(state, ctx),
507
+ updateSettingsMenuMessage: () =>
508
+ deps.updateSettingsMenuMessage?.(state, ctx) ?? Promise.resolve(),
470
509
  answerCallbackQuery: deps.answerCallbackQuery,
471
510
  },
472
511
  ),
@@ -504,6 +543,9 @@ export async function handleTelegramMenuCallbackRuntime<
504
543
  deps.updateModelMenuMessage(state, ctx),
505
544
  updateStatusMessage: () => deps.updateStatusMessage(state, ctx),
506
545
  answerCallbackQuery: deps.answerCallbackQuery,
546
+ persistScopedModelPatterns: deps.persistScopedModelPatterns
547
+ ? (patterns) => deps.persistScopedModelPatterns!(patterns, ctx)
548
+ : undefined,
507
549
  setModel: deps.setModel,
508
550
  setCurrentModel: (model) => deps.setCurrentModel(model, ctx),
509
551
  setThinkingLevel: (level) => {
package/lib/pi.ts CHANGED
@@ -31,7 +31,9 @@ export type {
31
31
 
32
32
  export interface PiSettingsManager {
33
33
  reload: () => Promise<void>;
34
+ flush: () => Promise<void>;
34
35
  getEnabledModels: () => string[] | undefined;
36
+ setEnabledModels: (patterns: string[] | undefined) => void;
35
37
  }
36
38
 
37
39
  export type PiSlashCommandInfo = SlashCommandInfo;
@@ -70,6 +72,20 @@ export function createSettingsManager(cwd: string): PiSettingsManager {
70
72
  return SettingsManager.create(cwd);
71
73
  }
72
74
 
75
+ export function createScopedModelPatternPersister(deps: {
76
+ createSettingsManager: (cwd: string) => PiSettingsManager;
77
+ clearCachedModelMenuInputs: () => void;
78
+ }): (patterns: string[], ctx: ExtensionContext) => Promise<void> {
79
+ return async function persistScopedModelPatterns(patterns, ctx) {
80
+ const settingsManager = deps.createSettingsManager(ctx.cwd);
81
+ settingsManager.setEnabledModels(
82
+ patterns.length > 0 ? patterns : undefined,
83
+ );
84
+ await settingsManager.flush();
85
+ deps.clearCachedModelMenuInputs();
86
+ };
87
+ }
88
+
73
89
  export function getExtensionContextModel(
74
90
  ctx: ExtensionContext,
75
91
  ): ExtensionContext["model"] {
package/lib/prompts.ts CHANGED
@@ -18,7 +18,9 @@ Inbound context:
18
18
  - Unknown \`[callback] ...\` messages may be intended for another extension; if you see one, say the callback was not handled and the environment may be misconfigured.
19
19
 
20
20
  Telegram-visible output:
21
- - Telegram is often phone-width; prefer narrow table columns because wide monospace tables can become unreadable.
21
+ - Telegram is often phone-width; keep tables, dense list items, and compact text blocks at or below 37 visible cells when possible.
22
+ - Count display width, not raw characters: emoji and some glyphs are wide, so prefer shorter labels when unsure.
23
+ - Wide monospace blocks can become unreadable on mobile; use them only when structure or literal code requires them.
22
24
  - For requested/generated files, call tool \`telegram_attach(local_path)\`; mentioning a local path in text does not send it.
23
25
 
24
26
  Native outbound actions:
@@ -55,3 +57,24 @@ export function createTelegramBeforeAgentStartHook(
55
57
  systemPromptSuffix: options.systemPromptSuffix ?? SYSTEM_PROMPT_SUFFIX,
56
58
  });
57
59
  }
60
+
61
+ export interface TelegramProactivePromptHookDeps<TContext> {
62
+ baseHook?: (event: BeforeAgentStartEvent) => { systemPrompt: string };
63
+ isProactivePushEnabled: () => boolean;
64
+ isCurrentOwner: (ctx: TContext) => boolean;
65
+ }
66
+
67
+ export function createTelegramProactiveBeforeAgentStartHook<TContext>(
68
+ deps: TelegramProactivePromptHookDeps<TContext>,
69
+ ): (
70
+ event: BeforeAgentStartEvent,
71
+ ctx: TContext,
72
+ ) => Promise<{ systemPrompt: string }> {
73
+ const baseHook = deps.baseHook ?? createTelegramBeforeAgentStartHook();
74
+ return async function onBeforeAgentStart(event, ctx) {
75
+ const result = baseHook(event);
76
+ if (!deps.isProactivePushEnabled()) return result;
77
+ if (!deps.isCurrentOwner(ctx)) return result;
78
+ return result;
79
+ };
80
+ }
package/lib/queue.ts CHANGED
@@ -357,7 +357,7 @@ function formatTelegramQueueItemStatusSummary<TContext = unknown>(
357
357
  item: TelegramQueueItem<TContext>,
358
358
  ): string {
359
359
  if (item.queueLane === "priority") {
360
- return `${item.kind === "prompt" ? item.priorityEmoji ?? "⚡" : "⚡"} ${item.statusSummary}`;
360
+ return `${item.kind === "prompt" ? (item.priorityEmoji ?? "⚡") : "⚡"} ${item.statusSummary}`;
361
361
  }
362
362
  return item.statusSummary;
363
363
  }
@@ -365,15 +365,7 @@ function formatTelegramQueueItemStatusSummary<TContext = unknown>(
365
365
  export function formatQueuedTelegramItemsStatus<TContext = unknown>(
366
366
  items: TelegramQueueItem<TContext>[],
367
367
  ): string {
368
- if (items.length === 0) return "";
369
- const previewCount = 4;
370
- const summaries = items
371
- .slice(0, previewCount)
372
- .map(formatTelegramQueueItemStatusSummary)
373
- .filter(Boolean);
374
- if (summaries.length === 0) return ` +${items.length}`;
375
- const suffix = items.length > summaries.length ? ", …" : "";
376
- return ` +${items.length}: [${summaries.join(", ")}${suffix}]`;
368
+ return items.length === 0 ? "" : ` +${items.length}`;
377
369
  }
378
370
 
379
371
  export function canDispatchTelegramTurnState(
@@ -783,7 +775,7 @@ export interface TelegramAgentEndRuntimeDeps<
783
775
  ) => Promise<boolean>;
784
776
  sendMarkdownReply: (
785
777
  chatId: number,
786
- replyToMessageId: number,
778
+ replyToMessageId: number | undefined,
787
779
  markdown: string,
788
780
  options?: { replyMarkup?: TReplyMarkup },
789
781
  ) => Promise<unknown>;
@@ -801,6 +793,13 @@ export interface TelegramAgentEndRuntimeDeps<
801
793
  plan: TelegramAgentEndOutboundReplyPlan,
802
794
  options?: { replyToPrompt?: boolean },
803
795
  ) => Promise<void>;
796
+ getDefaultChatId?: () => number | undefined;
797
+ isProactivePushEnabled?: () => boolean;
798
+ recordRuntimeEvent?: (
799
+ category: string,
800
+ error: unknown,
801
+ details?: Record<string, unknown>,
802
+ ) => void;
804
803
  }
805
804
 
806
805
  export interface TelegramAgentEndHookRuntimeDeps<
@@ -838,6 +837,9 @@ export interface TelegramAgentEndHookRuntimeDeps<
838
837
  TReplyMarkup
839
838
  >["planOutboundReply"];
840
839
  sendOutboundReplyArtifacts?: TelegramAgentEndRuntimeDeps<TTurn>["sendOutboundReplyArtifacts"];
840
+ getDefaultChatId?: TelegramAgentEndRuntimeDeps<TTurn>["getDefaultChatId"];
841
+ isProactivePushEnabled?: TelegramAgentEndRuntimeDeps<TTurn>["isProactivePushEnabled"];
842
+ recordRuntimeEvent?: TelegramAgentEndRuntimeDeps<TTurn>["recordRuntimeEvent"];
841
843
  }
842
844
 
843
845
  export interface TelegramAgentEndHookEvent<TMessage> {
@@ -928,9 +930,11 @@ export function createTelegramAgentEndHook<
928
930
  ctx: TContext,
929
931
  ): Promise<void> {
930
932
  const turn = deps.getActiveTurn();
933
+ const proactiveEnabled = deps.isProactivePushEnabled?.() ?? false;
931
934
  await handleTelegramAgentEndRuntime({
932
935
  turn,
933
- assistant: turn ? deps.extractAssistant(event.messages) : {},
936
+ assistant:
937
+ turn || proactiveEnabled ? deps.extractAssistant(event.messages) : {},
934
938
  preserveQueuedTurnsAsHistory: deps.getPreserveQueuedTurnsAsHistory(),
935
939
  resetRuntimeState: deps.resetRuntimeState,
936
940
  updateStatus: () => deps.updateStatus(ctx),
@@ -950,6 +954,9 @@ export function createTelegramAgentEndHook<
950
954
  sendQueuedAttachments: deps.sendQueuedAttachments,
951
955
  planOutboundReply: deps.planOutboundReply,
952
956
  sendOutboundReplyArtifacts: deps.sendOutboundReplyArtifacts,
957
+ getDefaultChatId: deps.getDefaultChatId,
958
+ isProactivePushEnabled: deps.isProactivePushEnabled,
959
+ recordRuntimeEvent: deps.recordRuntimeEvent,
953
960
  });
954
961
  };
955
962
  }
@@ -969,8 +976,8 @@ export async function handleTelegramAgentEndRuntime<
969
976
  const replyMarkup = outboundReply?.replyMarkup;
970
977
  deps.resetRuntimeState();
971
978
  deps.updateStatus();
972
- if (turn && deps.isCurrentOwner && !deps.isCurrentOwner()) {
973
- await deps.clearPreview(turn.chatId);
979
+ if (deps.isCurrentOwner && !deps.isCurrentOwner()) {
980
+ if (turn) await deps.clearPreview(turn.chatId);
974
981
  return;
975
982
  }
976
983
  const endPlan = buildTelegramAgentEndPlan({
@@ -981,6 +988,22 @@ export async function handleTelegramAgentEndRuntime<
981
988
  preserveQueuedTurnsAsHistory: deps.preserveQueuedTurnsAsHistory,
982
989
  });
983
990
  if (!turn) {
991
+ if (
992
+ deps.isProactivePushEnabled?.() &&
993
+ finalText &&
994
+ !assistant.errorMessage
995
+ ) {
996
+ const defaultChatId = deps.getDefaultChatId?.();
997
+ if (defaultChatId !== undefined) {
998
+ try {
999
+ await deps.sendMarkdownReply(defaultChatId, undefined, finalText);
1000
+ } catch (error) {
1001
+ deps.recordRuntimeEvent?.("proactive-push", error, {
1002
+ chatId: defaultChatId,
1003
+ });
1004
+ }
1005
+ }
1006
+ }
984
1007
  if (endPlan.shouldDispatchNext) deps.dispatchNextQueuedTelegramTurn();
985
1008
  return;
986
1009
  }
package/lib/routing.ts CHANGED
@@ -50,11 +50,24 @@ export interface TelegramInboundRouteRuntimeDeps<
50
50
  Model.ScopedTelegramModel<TModel>
51
51
  >;
52
52
  menuActions: Menu.TelegramMenuActionRuntime<TContext, TModel>;
53
+ updateSettingsMenuMessage?: (
54
+ state: Menu.TelegramModelMenuState<TModel>,
55
+ ctx: TContext,
56
+ ) => Promise<void>;
53
57
  openQueueMenu: (
54
58
  chatId: number,
55
59
  replyToMessageId: number,
56
60
  ctx: TContext,
57
61
  ) => Promise<void>;
62
+ openSettingsMenu?: (
63
+ chatId: number,
64
+ replyToMessageId: number,
65
+ ctx: TContext,
66
+ ) => Promise<void>;
67
+ settingsMenuCallbackHandler?: (
68
+ query: TCallbackQuery,
69
+ ctx: TContext,
70
+ ) => Promise<boolean>;
58
71
  queueMenuCallbackHandler: (
59
72
  query: TCallbackQuery,
60
73
  ctx: TContext,
@@ -79,6 +92,10 @@ export interface TelegramInboundRouteRuntimeDeps<
79
92
  downloadFile: Media.DownloadTelegramMessageFilesDeps["downloadFile"];
80
93
  getThinkingLevel: () => Model.ThinkingLevel;
81
94
  setThinkingLevel: (level: Model.ThinkingLevel) => void;
95
+ persistScopedModelPatterns?: (
96
+ patterns: string[],
97
+ ctx: TContext,
98
+ ) => Promise<void>;
82
99
  setModel: (model: TModel) => Promise<boolean>;
83
100
  sendUserMessage?: (message: string) => void;
84
101
  isIdle: (ctx: TContext) => boolean;
@@ -98,6 +115,7 @@ const TELEGRAM_OWNED_CALLBACK_PREFIXES = [
98
115
  "menu:",
99
116
  "model:",
100
117
  "queue:",
118
+ "settings:",
101
119
  "status:",
102
120
  "tgbtn:",
103
121
  "thinking:",
@@ -140,12 +158,14 @@ export function createTelegramInboundRouteRuntime<
140
158
  updateModelMenuMessage: deps.menuActions.updateModelMenuMessage,
141
159
  updateThinkingMenuMessage: deps.menuActions.updateThinkingMenuMessage,
142
160
  updateStatusMessage: deps.menuActions.updateStatusMessage,
161
+ updateSettingsMenuMessage: deps.updateSettingsMenuMessage,
143
162
  answerCallbackQuery: deps.answerCallbackQuery,
144
163
  isIdle: deps.isIdle,
145
164
  hasActiveTelegramTurn: deps.activeTurnRuntime.has,
146
165
  hasAbortHandler: deps.bridgeRuntime.abort.hasHandler,
147
166
  getActiveToolExecutions:
148
167
  deps.bridgeRuntime.lifecycle.getActiveToolExecutions,
168
+ persistScopedModelPatterns: deps.persistScopedModelPatterns,
149
169
  setModel: deps.setModel,
150
170
  setCurrentModel: deps.currentModelRuntime.setCurrentModel,
151
171
  stagePendingModelSwitch: deps.modelSwitchController.stagePendingSwitch,
@@ -187,6 +207,11 @@ export function createTelegramInboundRouteRuntime<
187
207
  }
188
208
  const handledByQueue = await deps.queueMenuCallbackHandler(query, ctx);
189
209
  if (handledByQueue) return;
210
+ const handledBySettings = await deps.settingsMenuCallbackHandler?.(
211
+ query,
212
+ ctx,
213
+ );
214
+ if (handledBySettings) return;
190
215
  const callbackData = query.data;
191
216
  if (
192
217
  deps.sendUserMessage &&
@@ -279,6 +304,7 @@ export function createTelegramInboundRouteRuntime<
279
304
  const chatId = (message as { chat: { id: number } }).chat.id;
280
305
  return deps.openQueueMenu(chatId, message.message_id, ctx);
281
306
  },
307
+ openSettingsMenu: deps.openSettingsMenu,
282
308
  getAllowedUserId: deps.configStore.getAllowedUserId,
283
309
  setAllowedUserId: deps.configStore.setAllowedUserId,
284
310
  setMyCommands: deps.setMyCommands,
package/lib/status.ts CHANGED
@@ -44,6 +44,7 @@ export interface TelegramStatusContext {
44
44
  getContextUsage(): TelegramContextUsage | undefined;
45
45
  isIdle?: () => boolean;
46
46
  hasPendingMessages?: () => boolean;
47
+ isCompactionInProgress?: () => boolean;
47
48
  modelRegistry: {
48
49
  isUsingOAuth(model: TelegramStatusActiveModel): boolean;
49
50
  };
@@ -303,8 +304,13 @@ export function buildTelegramRuntimeEventLines(
303
304
 
304
305
  export function createTelegramStatusHtmlBuilder<TContext>(deps: {
305
306
  getActiveModel: (ctx: TContext) => TelegramStatusActiveModel | undefined;
307
+ isCompactionInProgress?: () => boolean;
306
308
  }): (ctx: TContext & TelegramStatusContext) => string {
307
- return (ctx) => buildStatusHtml(ctx, deps.getActiveModel(ctx));
309
+ return (ctx) =>
310
+ buildStatusHtml(
311
+ { ...ctx, isCompactionInProgress: deps.isCompactionInProgress },
312
+ deps.getActiveModel(ctx),
313
+ );
308
314
  }
309
315
 
310
316
  export function createTelegramStatusRuntime<
@@ -348,7 +354,11 @@ export function createTelegramBridgeStatusRuntime<
348
354
  paired: !!config.allowedUserId,
349
355
  compactionInProgress,
350
356
  processing:
351
- hasActiveTurn || hasPendingDispatch || queuedItems.length > 0,
357
+ hasActiveTurn ||
358
+ hasPendingDispatch ||
359
+ hasPendingModelSwitch ||
360
+ activeToolExecutions > 0 ||
361
+ queuedItems.length > 0,
352
362
  processingStatus: getTelegramStatusBarProcessingStatus({
353
363
  hasActiveTurn,
354
364
  hasPendingDispatch,
@@ -388,8 +398,9 @@ export function getTelegramStatusBarProcessingStatus(state: {
388
398
  queuedItems: number;
389
399
  }): string | undefined {
390
400
  if (state.hasPendingModelSwitch) return "model";
391
- if (state.activeToolExecutions > 0) return "tool running";
392
- if (state.hasActiveTurn) return "active";
401
+ if (state.hasActiveTurn && state.activeToolExecutions > 0)
402
+ return "tool running";
403
+ if (state.hasActiveTurn || state.activeToolExecutions > 0) return "active";
393
404
  if (state.hasPendingDispatch) return "dispatching";
394
405
  if (state.queuedItems > 0) return "queued";
395
406
  return undefined;
@@ -410,13 +421,15 @@ export function buildTelegramStatusBarText(
410
421
  if (!state.paired)
411
422
  return `${label} ${theme.fg("warning", "awaiting pairing")}`;
412
423
  const queued = state.queuedStatus
413
- ? theme.fg("muted", state.queuedStatus)
424
+ ? theme.fg("success", state.queuedStatus)
414
425
  : "";
415
426
  if (state.compactionInProgress) {
416
427
  return `${label} ${theme.fg("accent", "compacting")}${queued}`;
417
428
  }
418
429
  if (state.processing) {
419
- const processingStatus = state.processingStatus ?? "processing";
430
+ const processingStatus = state.queuedStatus
431
+ ? "active"
432
+ : (state.processingStatus ?? "processing");
420
433
  const processingToken =
421
434
  processingStatus === "active" ? "warning" : "accent";
422
435
  return `${label} ${theme.fg(processingToken, processingStatus)}${queued}`;
@@ -537,6 +550,7 @@ function buildContextSummary(
537
550
  }
538
551
 
539
552
  function buildStatusSummary(ctx: TelegramStatusContext): string {
553
+ if (ctx.isCompactionInProgress?.()) return "compacting";
540
554
  if (ctx.hasPendingMessages?.()) return "pending";
541
555
  if (ctx.isIdle?.() === false) return "active";
542
556
  if (ctx.isIdle?.() === true) return "idle";
package/lib/updates.ts CHANGED
@@ -31,12 +31,14 @@ export const TELEGRAM_PRIORITY_REACTIONS = [
31
31
  { id: 11, name: "lightning", emoji: "⚡" },
32
32
  { id: 12, name: "heart", emoji: "❤" },
33
33
  { id: 13, name: "dove", emoji: "🕊" },
34
+ { id: 14, name: "fire", emoji: "🔥" },
34
35
  ] as const;
35
36
  export const TELEGRAM_REMOVAL_REACTIONS = [
36
37
  { id: 20, name: "dislike", emoji: "👎" },
37
38
  { id: 21, name: "ghost", emoji: "👻" },
38
39
  { id: 22, name: "broken-heart", emoji: "💔" },
39
40
  { id: 23, name: "poop", emoji: "💩" },
41
+ { id: 24, name: "wastebasket", emoji: "🗑" },
40
42
  ] as const;
41
43
  export const TELEGRAM_PRIORITY_REACTION_EMOJIS =
42
44
  TELEGRAM_PRIORITY_REACTIONS.map((reaction) => reaction.emoji);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-telegram",
3
- "version": "0.8.2",
3
+ "version": "0.9.1",
4
4
  "private": false,
5
5
  "description": "Better Telegram DM bridge extension for π",
6
6
  "type": "module",