@llblab/pi-telegram 0.24.3 → 0.24.5

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.
@@ -26,6 +26,7 @@ export interface TelegramSettingsStateDeps {
26
26
  getTimeInjectionMode: () => TelegramTimeMode;
27
27
  getVoiceReplyMode: () => TelegramVoiceReplyMode;
28
28
  isVoiceReplyModeConfigured: () => boolean;
29
+ isAutomaticThreadCleanupEnabled: () => boolean;
29
30
  }
30
31
 
31
32
  export interface TelegramSettingsMutationDeps extends TelegramSettingsStateDeps {
@@ -38,6 +39,7 @@ export interface TelegramSettingsMutationDeps extends TelegramSettingsStateDeps
38
39
  mode: TelegramVoiceReplyMode | undefined,
39
40
  ) => Promise<void>;
40
41
  setTimeInjectionMode: (mode: TelegramTimeMode) => Promise<void>;
42
+ setAutomaticThreadCleanupEnabled: (enabled: boolean) => Promise<void>;
41
43
  }
42
44
 
43
45
  export interface TelegramSettingsMenuOpenDeps<
@@ -99,6 +101,7 @@ export interface TelegramSettingsMenuRuntimeDeps<
99
101
  TContext,
100
102
  TModel extends MenuModel = MenuModel,
101
103
  > extends TelegramSettingsMutationDeps {
104
+ reloadConfig?: () => Promise<void>;
102
105
  getModelMenuState: (
103
106
  chatId: number,
104
107
  ctx: TContext,
@@ -129,6 +132,8 @@ export interface TelegramSettingsMenuRuntimeDeps<
129
132
  }
130
133
 
131
134
  export const SETTINGS_MENU_TITLE = "<b>⚙️ Settings:</b>";
135
+ export const AUTOMATIC_THREAD_CLEANUP_SETTINGS_TITLE =
136
+ "<b>🧹 Automatic thread cleanup:</b>";
132
137
  export const PROACTIVE_PUSH_SETTINGS_TITLE = "<b>📌 Proactive push:</b>";
133
138
  export const DRAFT_PREVIEWS_SETTINGS_TITLE = "<b>📝 Draft previews:</b>";
134
139
  export const ASSISTANT_RENDERING_SETTINGS_TITLE =
@@ -158,6 +163,19 @@ export function buildTelegramSettingsMenuText(): string {
158
163
  return SETTINGS_MENU_TITLE;
159
164
  }
160
165
 
166
+ export function buildAutomaticThreadCleanupSettingsText(
167
+ enabled: boolean,
168
+ ): string {
169
+ return [
170
+ `${AUTOMATIC_THREAD_CLEANUP_SETTINGS_TITLE} <code>${enabled ? "on" : "off"}</code>`,
171
+ "",
172
+ "Delete this Pi instance's Telegram tab when Pi quits normally.",
173
+ "",
174
+ "<code>-</code> <code>on</code> (default): delete the bound thread and release Telegram authority on graceful quit.",
175
+ "<code>-</code> <code>off</code>: preserve the tab as a restart hint; manual /telegram-disconnect still confirms and deletes it.",
176
+ ].join("\n");
177
+ }
178
+
161
179
  export function buildProactivePushSettingsText(
162
180
  proactivePushEnabled: boolean,
163
181
  ): string {
@@ -236,6 +254,7 @@ export function buildTelegramSettingsMenuReplyMarkup(
236
254
  TelegramTimeMode | TelegramSectionRegistry,
237
255
  sectionRegistryOrVoiceReplyModeConfigured?: TelegramSectionRegistry | boolean,
238
256
  voiceReplyModeConfigured = true,
257
+ automaticThreadCleanupEnabled = true,
239
258
  ): TelegramSettingsMenuReplyMarkup {
240
259
  const hasRenderingMode =
241
260
  assistantRenderingModeOrVoiceReplyMode === "rich" ||
@@ -269,6 +288,12 @@ export function buildTelegramSettingsMenuReplyMarkup(
269
288
  }
270
289
  }
271
290
  rows.push(
291
+ [
292
+ {
293
+ text: `🧹 Auto thread cleanup: ${automaticThreadCleanupEnabled ? "on" : "off"}`,
294
+ callback_data: "settings:open:automatic-thread-cleanup",
295
+ },
296
+ ],
272
297
  [
273
298
  {
274
299
  text: `👄 Voice reply: ${getTelegramSettingsStateValueLabel(
@@ -328,6 +353,7 @@ export async function openTelegramSettingsMenu<
328
353
  deps.getTimeInjectionMode(),
329
354
  sectionRegistry,
330
355
  deps.isVoiceReplyModeConfigured(),
356
+ deps.isAutomaticThreadCleanupEnabled(),
331
357
  ),
332
358
  );
333
359
  if (messageId === undefined) return;
@@ -336,6 +362,26 @@ export async function openTelegramSettingsMenu<
336
362
  deps.storeModelMenuState(state);
337
363
  }
338
364
 
365
+ export function buildAutomaticThreadCleanupSettingsReplyMarkup(
366
+ enabled: boolean,
367
+ ): TelegramSettingsMenuReplyMarkup {
368
+ return {
369
+ inline_keyboard: [
370
+ [{ text: "⬆️ Back", callback_data: "settings:list" }],
371
+ [
372
+ {
373
+ text: enabled ? "🟢 On" : "⚫️ On",
374
+ callback_data: "settings:set:automatic-thread-cleanup:on",
375
+ },
376
+ {
377
+ text: enabled ? "⚫️ Off" : "🟡 Off",
378
+ callback_data: "settings:set:automatic-thread-cleanup:off",
379
+ },
380
+ ],
381
+ ],
382
+ };
383
+ }
384
+
339
385
  export function buildProactivePushSettingsReplyMarkup(
340
386
  proactivePushEnabled: boolean,
341
387
  ): TelegramSettingsMenuReplyMarkup {
@@ -443,10 +489,21 @@ export async function updateTelegramSettingsMenuMessage(
443
489
  deps.getTimeInjectionMode(),
444
490
  sectionRegistry,
445
491
  deps.isVoiceReplyModeConfigured(),
492
+ deps.isAutomaticThreadCleanupEnabled(),
446
493
  ),
447
494
  );
448
495
  }
449
496
 
497
+ export async function updateAutomaticThreadCleanupSettingsMessage(
498
+ deps: TelegramSettingsMenuCallbackDeps,
499
+ ): Promise<void> {
500
+ const enabled = deps.isAutomaticThreadCleanupEnabled();
501
+ await deps.updateSettingsMessage(
502
+ buildAutomaticThreadCleanupSettingsText(enabled),
503
+ buildAutomaticThreadCleanupSettingsReplyMarkup(enabled),
504
+ );
505
+ }
506
+
450
507
  export async function updateProactivePushSettingsMessage(
451
508
  deps: TelegramSettingsMenuCallbackDeps,
452
509
  ): Promise<void> {
@@ -509,6 +566,11 @@ export async function handleTelegramSettingsMenuCallbackAction(
509
566
  await deps.answerCallbackQuery(callbackQueryId);
510
567
  return true;
511
568
  }
569
+ if (data === "settings:open:automatic-thread-cleanup") {
570
+ await updateAutomaticThreadCleanupSettingsMessage(deps);
571
+ await deps.answerCallbackQuery(callbackQueryId);
572
+ return true;
573
+ }
512
574
  if (data === "settings:open:proactive") {
513
575
  await updateProactivePushSettingsMessage(deps);
514
576
  await deps.answerCallbackQuery(callbackQueryId);
@@ -598,6 +660,19 @@ export async function handleTelegramSettingsMenuCallbackAction(
598
660
  return true;
599
661
  }
600
662
  }
663
+ if (
664
+ data === "settings:set:automatic-thread-cleanup:on" ||
665
+ data === "settings:set:automatic-thread-cleanup:off"
666
+ ) {
667
+ const enabled = data.endsWith(":on");
668
+ await deps.setAutomaticThreadCleanupEnabled(enabled);
669
+ await updateAutomaticThreadCleanupSettingsMessage(deps);
670
+ await deps.answerCallbackQuery(
671
+ callbackQueryId,
672
+ `Automatic thread cleanup ${enabled ? "enabled" : "disabled"}`,
673
+ );
674
+ return true;
675
+ }
601
676
  if (
602
677
  data === "settings:set:proactive:on" ||
603
678
  data === "settings:set:proactive:off"
@@ -623,8 +698,9 @@ export function createTelegramSettingsMenuRuntime<
623
698
  sectionRegistry?: TelegramSectionRegistry,
624
699
  ): TelegramSettingsMenuRuntime<TContext> {
625
700
  return {
626
- openSettingsMenu: (chatId, _replyToMessageId, ctx) =>
627
- openTelegramSettingsMenu(
701
+ openSettingsMenu: async (chatId, _replyToMessageId, ctx) => {
702
+ await deps.reloadConfig?.();
703
+ return openTelegramSettingsMenu(
628
704
  {
629
705
  getModelMenuState: () => deps.getModelMenuState(chatId, ctx),
630
706
  isProactivePushEnabled: deps.isProactivePushEnabled,
@@ -633,6 +709,8 @@ export function createTelegramSettingsMenuRuntime<
633
709
  getVoiceReplyMode: deps.getVoiceReplyMode,
634
710
  isVoiceReplyModeConfigured: deps.isVoiceReplyModeConfigured,
635
711
  getTimeInjectionMode: deps.getTimeInjectionMode,
712
+ isAutomaticThreadCleanupEnabled:
713
+ deps.isAutomaticThreadCleanupEnabled,
636
714
  sendSettingsMenu: (state, text, replyMarkup) =>
637
715
  deps.sendInteractiveMessage(
638
716
  state.chatId,
@@ -643,9 +721,11 @@ export function createTelegramSettingsMenuRuntime<
643
721
  storeModelMenuState: deps.storeModelMenuState,
644
722
  },
645
723
  sectionRegistry,
646
- ),
647
- updateSettingsMenuMessage: (state) =>
648
- updateTelegramSettingsMenuMessage(
724
+ );
725
+ },
726
+ updateSettingsMenuMessage: async (state) => {
727
+ await deps.reloadConfig?.();
728
+ return updateTelegramSettingsMenuMessage(
649
729
  {
650
730
  isProactivePushEnabled: deps.isProactivePushEnabled,
651
731
  areDraftPreviewsEnabled: deps.areDraftPreviewsEnabled,
@@ -653,6 +733,8 @@ export function createTelegramSettingsMenuRuntime<
653
733
  getVoiceReplyMode: deps.getVoiceReplyMode,
654
734
  isVoiceReplyModeConfigured: deps.isVoiceReplyModeConfigured,
655
735
  getTimeInjectionMode: deps.getTimeInjectionMode,
736
+ isAutomaticThreadCleanupEnabled:
737
+ deps.isAutomaticThreadCleanupEnabled,
656
738
  updateSettingsMessage: (text, replyMarkup) =>
657
739
  deps.editInteractiveMessage(
658
740
  state.chatId,
@@ -663,9 +745,11 @@ export function createTelegramSettingsMenuRuntime<
663
745
  ),
664
746
  },
665
747
  sectionRegistry,
666
- ),
748
+ );
749
+ },
667
750
  handleCallbackQuery: async (query, ctx) => {
668
751
  if (!query.data?.startsWith("settings:")) return false;
752
+ await deps.reloadConfig?.();
669
753
  const messageId = query.message?.message_id;
670
754
  const chatId = query.message?.chat?.id;
671
755
  let state = deps.getStoredModelMenuState(messageId, chatId);
@@ -693,11 +777,15 @@ export function createTelegramSettingsMenuRuntime<
693
777
  getVoiceReplyMode: deps.getVoiceReplyMode,
694
778
  isVoiceReplyModeConfigured: deps.isVoiceReplyModeConfigured,
695
779
  getTimeInjectionMode: deps.getTimeInjectionMode,
780
+ isAutomaticThreadCleanupEnabled:
781
+ deps.isAutomaticThreadCleanupEnabled,
696
782
  setProactivePushEnabled: deps.setProactivePushEnabled,
697
783
  setDraftPreviewsEnabled: deps.setDraftPreviewsEnabled,
698
784
  setAssistantRenderingMode: deps.setAssistantRenderingMode,
699
785
  setVoiceReplyMode: deps.setVoiceReplyMode,
700
786
  setTimeInjectionMode: deps.setTimeInjectionMode,
787
+ setAutomaticThreadCleanupEnabled:
788
+ deps.setAutomaticThreadCleanupEnabled,
701
789
  updateSettingsMessage: (text, replyMarkup) =>
702
790
  deps.editInteractiveMessage(
703
791
  state.chatId,
@@ -10,6 +10,12 @@ import { basename } from "node:path";
10
10
  import { Type } from "@sinclair/typebox";
11
11
 
12
12
  import type { ExtensionAPI } from "./pi.ts";
13
+ import {
14
+ TELEGRAM_ATTACH_PROMPT_GUIDELINES,
15
+ TELEGRAM_ATTACH_PROMPT_SNIPPET,
16
+ TELEGRAM_MESSAGE_PROMPT_GUIDELINES,
17
+ TELEGRAM_MESSAGE_PROMPT_SNIPPET,
18
+ } from "./prompts.ts";
13
19
  import {
14
20
  buildTelegramMultipartReplyParameters,
15
21
  normalizeTelegramNativeMarkdown,
@@ -432,13 +438,8 @@ export function registerTelegramOutboundAttachmentTool(
432
438
  label: "Telegram Attach",
433
439
  description:
434
440
  "Queue one or more local files for the active Telegram reply, or send them immediately to Telegram when no Telegram turn is active.",
435
- promptSnippet:
436
- "Queue files for the active Telegram reply; outside Telegram turns, send files directly to Telegram.",
437
- promptGuidelines: [
438
- "When handling a [telegram] message and the user asked for a file or generated artifact, call telegram_attach with the local path instead of only mentioning the path in text.",
439
- "When a local/TUI user explicitly asks to send a generated file to Telegram, telegram_attach can deliver it to the paired/default Telegram chat even without an active Telegram turn.",
440
- "For an explicit thread target, provide chat_id plus thread_id; registered multi-instance followers default to their assigned thread target.",
441
- ],
441
+ promptSnippet: TELEGRAM_ATTACH_PROMPT_SNIPPET,
442
+ promptGuidelines: [...TELEGRAM_ATTACH_PROMPT_GUIDELINES],
442
443
  parameters: Type.Object({
443
444
  paths: Type.Array(
444
445
  Type.String({ description: "Local file path to attach" }),
@@ -499,14 +500,8 @@ export function registerTelegramOutboundMessageTool(
499
500
  label: "Telegram Message",
500
501
  description:
501
502
  "Send a Markdown text message directly to the paired/default Telegram chat or an explicit chat_id. Hidden telegram_button comments in the text become attached inline prompt buttons.",
502
- promptSnippet:
503
- "Send direct Telegram Markdown text when the user explicitly asks for Telegram delivery outside the normal reply flow.",
504
- promptGuidelines: [
505
- "Use telegram_message only when the user explicitly asks to send a message to Telegram from the local/TUI side, or names a concrete Telegram delivery target.",
506
- "For an explicit thread target, provide chat_id plus thread_id; registered multi-instance followers default to their assigned thread target.",
507
- "Add buttons by embedding the same top-level telegram_button HTML comments used in normal Telegram replies; Telegram does not support standalone buttons.",
508
- "Do not use this tool for ordinary Telegram-originated replies; answer normally so the bridge can deliver the active turn reply.",
509
- ],
503
+ promptSnippet: TELEGRAM_MESSAGE_PROMPT_SNIPPET,
504
+ promptGuidelines: [...TELEGRAM_MESSAGE_PROMPT_GUIDELINES],
510
505
  parameters: Type.Object({
511
506
  text: Type.String({ description: "Message text to send" }),
512
507
  chat_id: Type.Optional(
package/lib/pi.ts CHANGED
@@ -120,6 +120,8 @@ export interface PiExtensionApiRuntimePorts {
120
120
  getCommands: ExtensionAPI["getCommands"];
121
121
  getThinkingLevel: ExtensionAPI["getThinkingLevel"];
122
122
  setThinkingLevel: ExtensionAPI["setThinkingLevel"];
123
+ getActiveTools: ExtensionAPI["getActiveTools"];
124
+ setActiveTools: ExtensionAPI["setActiveTools"];
123
125
  setModel: ExtensionAPI["setModel"];
124
126
  }
125
127
 
@@ -131,6 +133,8 @@ export function createExtensionApiRuntimePorts(
131
133
  | "getCommands"
132
134
  | "getThinkingLevel"
133
135
  | "setThinkingLevel"
136
+ | "getActiveTools"
137
+ | "setActiveTools"
134
138
  | "setModel"
135
139
  >,
136
140
  ): PiExtensionApiRuntimePorts {
@@ -141,6 +145,8 @@ export function createExtensionApiRuntimePorts(
141
145
  getCommands: () => api.getCommands(),
142
146
  getThinkingLevel: () => api.getThinkingLevel(),
143
147
  setThinkingLevel: (level) => api.setThinkingLevel(level),
148
+ getActiveTools: () => api.getActiveTools(),
149
+ setActiveTools: (names) => api.setActiveTools(names),
144
150
  setModel: (model) => api.setModel(model),
145
151
  };
146
152
  }
package/lib/prompts.ts CHANGED
@@ -18,6 +18,106 @@ const TELEGRAM_TURN_SYSTEM_PROMPT_SUFFIX = `
18
18
 
19
19
  Telegram turn note: Call \`telegram_help\` if you need the pi-telegram bridge action contract.`;
20
20
 
21
+ export const TELEGRAM_ATTACH_PROMPT_SNIPPET =
22
+ "Queue files for the active Telegram reply; outside Telegram turns, send files directly to Telegram.";
23
+ export const TELEGRAM_ATTACH_PROMPT_GUIDELINES = [
24
+ "When handling a [telegram] message and the user asked for a file or generated artifact, call telegram_attach with the local path instead of only mentioning the path in text.",
25
+ "When a local/TUI user explicitly asks to send a generated file to Telegram, telegram_attach can deliver it to the paired/default Telegram chat even without an active Telegram turn.",
26
+ "For an explicit thread target, provide chat_id plus thread_id; registered multi-instance followers default to their assigned thread target.",
27
+ ] as const;
28
+ export const TELEGRAM_MESSAGE_PROMPT_SNIPPET =
29
+ "Send direct Telegram Markdown text when the user explicitly asks for Telegram delivery outside the normal reply flow.";
30
+ export const TELEGRAM_MESSAGE_PROMPT_GUIDELINES = [
31
+ "Use telegram_message only when the user explicitly asks to send a message to Telegram from the local/TUI side, or names a concrete Telegram delivery target.",
32
+ "For an explicit thread target, provide chat_id plus thread_id; registered multi-instance followers default to their assigned thread target.",
33
+ "Add buttons by embedding the same top-level telegram_button HTML comments used in normal Telegram replies; Telegram does not support standalone buttons.",
34
+ "Do not use this tool for ordinary Telegram-originated replies; answer normally so the bridge can deliver the active turn reply.",
35
+ ] as const;
36
+
37
+ const TELEGRAM_MODEL_CONTEXT_TOOL_NAMES = new Set([
38
+ "telegram_attach",
39
+ "telegram_message",
40
+ "telegram_help",
41
+ ]);
42
+ const TELEGRAM_MODEL_CONTEXT_MEMORY_KEY = Symbol.for(
43
+ "@llblab/pi-telegram:model-context-suspended-tools",
44
+ );
45
+
46
+ export interface TelegramModelContextAvailabilityMemory {
47
+ suspended: boolean;
48
+ toolNames: Set<string>;
49
+ }
50
+
51
+ function getTelegramModelContextAvailabilityMemory(): TelegramModelContextAvailabilityMemory {
52
+ const globals = globalThis as unknown as Record<symbol, unknown>;
53
+ const existing = globals[TELEGRAM_MODEL_CONTEXT_MEMORY_KEY];
54
+ if (
55
+ existing &&
56
+ typeof existing === "object" &&
57
+ "toolNames" in existing &&
58
+ (existing as { toolNames?: unknown }).toolNames instanceof Set
59
+ ) {
60
+ return existing as TelegramModelContextAvailabilityMemory;
61
+ }
62
+ const memory: TelegramModelContextAvailabilityMemory = {
63
+ suspended: false,
64
+ toolNames: new Set<string>(),
65
+ };
66
+ globals[TELEGRAM_MODEL_CONTEXT_MEMORY_KEY] = memory;
67
+ return memory;
68
+ }
69
+
70
+ export interface TelegramModelContextAvailabilityRuntime {
71
+ reconcile: () => void;
72
+ }
73
+
74
+ export function createTelegramModelContextAvailabilityRuntime(deps: {
75
+ getActiveTools: () => string[];
76
+ setActiveTools: (names: string[]) => void;
77
+ isAvailable: () => boolean;
78
+ canReconcile?: () => boolean;
79
+ memory?: TelegramModelContextAvailabilityMemory;
80
+ }): TelegramModelContextAvailabilityRuntime {
81
+ const memory =
82
+ deps.memory ?? getTelegramModelContextAvailabilityMemory();
83
+ return {
84
+ reconcile() {
85
+ if (deps.canReconcile && !deps.canReconcile()) return;
86
+ const activeTools = deps.getActiveTools();
87
+ if (!deps.isAvailable()) {
88
+ if (!memory.suspended) {
89
+ memory.toolNames.clear();
90
+ for (const name of activeTools) {
91
+ if (TELEGRAM_MODEL_CONTEXT_TOOL_NAMES.has(name)) {
92
+ memory.toolNames.add(name);
93
+ }
94
+ }
95
+ memory.suspended = true;
96
+ }
97
+ const nextTools = activeTools.filter(
98
+ (name) => !TELEGRAM_MODEL_CONTEXT_TOOL_NAMES.has(name),
99
+ );
100
+ if (nextTools.length !== activeTools.length) {
101
+ deps.setActiveTools(nextTools);
102
+ }
103
+ return;
104
+ }
105
+ if (!memory.suspended) return;
106
+ const nextTools = [...activeTools];
107
+ for (const name of TELEGRAM_MODEL_CONTEXT_TOOL_NAMES) {
108
+ if (memory.toolNames.has(name) && !nextTools.includes(name)) {
109
+ nextTools.push(name);
110
+ }
111
+ }
112
+ memory.toolNames.clear();
113
+ memory.suspended = false;
114
+ if (nextTools.length !== activeTools.length) {
115
+ deps.setActiveTools(nextTools);
116
+ }
117
+ },
118
+ };
119
+ }
120
+
21
121
  function buildTelegramHelpText(profileName?: string): string {
22
122
  const diagnosticsPaths = getTelegramDiagnosticsDisplayPaths(profileName);
23
123
  return `--- TELEGRAM BRIDGE HELP ---
@@ -143,11 +243,25 @@ export function createTelegramBeforeAgentStartHook(
143
243
  });
144
244
  }
145
245
 
246
+ function stripTelegramToolMetadataFromSystemPrompt(
247
+ systemPrompt: string,
248
+ ): string {
249
+ const telegramLines = new Set([
250
+ `- telegram_attach: ${TELEGRAM_ATTACH_PROMPT_SNIPPET}`,
251
+ `- telegram_message: ${TELEGRAM_MESSAGE_PROMPT_SNIPPET}`,
252
+ ...TELEGRAM_ATTACH_PROMPT_GUIDELINES.map((line) => `- ${line}`),
253
+ ...TELEGRAM_MESSAGE_PROMPT_GUIDELINES.map((line) => `- ${line}`),
254
+ ]);
255
+ return systemPrompt
256
+ .split("\n")
257
+ .filter((line) => !telegramLines.has(line))
258
+ .join("\n");
259
+ }
260
+
146
261
  export interface TelegramProactivePromptHookDeps<TContext> {
147
262
  baseHook?: (event: BeforeAgentStartEvent) => { systemPrompt: string };
148
- isConfigured: () => boolean;
149
- isProactivePushEnabled: () => boolean;
150
- isCurrentOwner: (ctx: TContext) => boolean;
263
+ reconcileAvailability?: () => void;
264
+ isAvailable: (ctx: TContext) => boolean;
151
265
  }
152
266
 
153
267
  export function createTelegramProactiveBeforeAgentStartHook<TContext>(
@@ -158,10 +272,14 @@ export function createTelegramProactiveBeforeAgentStartHook<TContext>(
158
272
  ) => Promise<{ systemPrompt: string }> {
159
273
  const baseHook = deps.baseHook ?? createTelegramBeforeAgentStartHook();
160
274
  return async (event, ctx) => {
161
- if (!deps.isConfigured()) return { systemPrompt: event.systemPrompt };
162
- const result = baseHook(event);
163
- if (!deps.isProactivePushEnabled()) return result;
164
- if (!deps.isCurrentOwner(ctx)) return result;
165
- return result;
275
+ deps.reconcileAvailability?.();
276
+ if (!deps.isAvailable(ctx)) {
277
+ return {
278
+ systemPrompt: stripTelegramToolMetadataFromSystemPrompt(
279
+ event.systemPrompt,
280
+ ),
281
+ };
282
+ }
283
+ return baseHook(event);
166
284
  };
167
285
  }