@llblab/pi-telegram 0.36.2 → 0.36.3

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/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  > Each release keeps at most 8 outcome records of at most 512 characters.
4
4
 
5
+ ## 0.36.3: Ordered Prompt Compatibility
6
+
7
+ - `Prompt Compatibility`: Preserves plain and ordered-block system prompts across Pi-compatible runtimes; Telegram guidance remains a distinct block when the host supplies blocks, while unavailable transport strips only Telegram tool metadata without collapsing unrelated prompt context.
8
+
5
9
  ## 0.36.2: Provider-Compatible Controls
6
10
 
7
11
  - `Provider-Compatible Bind Schema`: Exposes `telegram_bind` through one top-level JSON object schema while retaining runtime enforcement of mutually exclusive install and invocation forms, avoiding providers that reject top-level union schemas before any tool call can run.
package/lib/lifecycle.ts CHANGED
@@ -40,8 +40,15 @@ export function createAgentStartDedupHook(
40
40
  };
41
41
  }
42
42
 
43
+ type TelegramBeforeAgentStartEvent = Omit<
44
+ BeforeAgentStartEvent,
45
+ "systemPrompt"
46
+ > & {
47
+ systemPrompt: string | string[];
48
+ };
49
+
43
50
  export interface TelegramBeforeAgentStartResult {
44
- systemPrompt?: string;
51
+ systemPrompt?: string | string[];
45
52
  }
46
53
 
47
54
  type TelegramBeforeAgentStartReturn =
@@ -72,7 +79,7 @@ export interface TelegramLifecycleRegistrationDeps {
72
79
  ctx: ExtensionContext,
73
80
  ) => Promise<void> | void;
74
81
  onBeforeAgentStart: (
75
- event: BeforeAgentStartEvent,
82
+ event: TelegramBeforeAgentStartEvent,
76
83
  ctx: ExtensionContext,
77
84
  ) => TelegramBeforeAgentStartReturn;
78
85
  onModelSelect: (
@@ -581,7 +588,16 @@ export function registerTelegramLifecycleHooks(
581
588
  if (!isActive(ctx)) return;
582
589
  await deps.onSessionCompact?.(event, ctx);
583
590
  });
584
- pi.on("before_agent_start", async (event, ctx) => {
591
+ // The Pi SDK still types this result as a string; compatible runtimes may
592
+ // preserve ordered system prompt blocks through the same public hook.
593
+ const registerBeforeAgentStart = pi.on.bind(pi) as unknown as (
594
+ event: "before_agent_start",
595
+ handler: (
596
+ event: TelegramBeforeAgentStartEvent,
597
+ ctx: ExtensionContext,
598
+ ) => TelegramBeforeAgentStartReturn,
599
+ ) => void;
600
+ registerBeforeAgentStart("before_agent_start", async (event, ctx) => {
585
601
  return deps.onBeforeAgentStart(event, ctx);
586
602
  });
587
603
  pi.on("model_select", async (event, ctx) => {
package/lib/prompts.ts CHANGED
@@ -31,6 +31,15 @@ export const TELEGRAM_MESSAGE_PROMPT_GUIDELINES = [
31
31
  "During an active Telegram turn, omit telegram_message for the current target and answer normally; use thread only when the user requests delivery to a different live Pi thread.",
32
32
  ] as const;
33
33
 
34
+ const TELEGRAM_TOOL_METADATA_LINES = Object.fromEntries(
35
+ [
36
+ `- telegram_attach: ${TELEGRAM_ATTACH_PROMPT_SNIPPET}`,
37
+ `- telegram_message: ${TELEGRAM_MESSAGE_PROMPT_SNIPPET}`,
38
+ ...TELEGRAM_ATTACH_PROMPT_GUIDELINES.map((line) => `- ${line}`),
39
+ ...TELEGRAM_MESSAGE_PROMPT_GUIDELINES.map((line) => `- ${line}`),
40
+ ].map((line) => [line, true]),
41
+ ) as Record<string, true>;
42
+
34
43
  const TELEGRAM_MODEL_CONTEXT_TOOL_NAMES = new Set([
35
44
  "telegram_attach",
36
45
  "telegram_bind",
@@ -132,13 +141,30 @@ export function createTelegramModelContextAvailabilityRuntime(deps: {
132
141
  };
133
142
  }
134
143
 
144
+ export type TelegramSystemPrompt = string | string[];
145
+
146
+ type TelegramBeforeAgentStartEvent = Omit<
147
+ BeforeAgentStartEvent,
148
+ "systemPrompt"
149
+ > & {
150
+ systemPrompt: TelegramSystemPrompt;
151
+ };
152
+
153
+ type TelegramBeforeAgentStartResult = {
154
+ systemPrompt: TelegramSystemPrompt;
155
+ };
156
+
157
+ type TelegramBeforeAgentStartHook = (
158
+ event: TelegramBeforeAgentStartEvent,
159
+ ) => TelegramBeforeAgentStartResult;
160
+
135
161
  export function buildTelegramBridgeSystemPrompt(options: {
136
162
  prompt: string;
137
- systemPrompt: string;
163
+ systemPrompt: TelegramSystemPrompt;
138
164
  telegramPrefix?: string;
139
165
  localSystemPromptSuffix: string;
140
166
  telegramTurnSystemPromptSuffix: string;
141
- }): { systemPrompt: string } {
167
+ }): TelegramBeforeAgentStartResult {
142
168
  const telegramPrefix = options.telegramPrefix ?? TELEGRAM_PREFIX;
143
169
  const telegramHead = telegramPrefix.endsWith("]")
144
170
  ? telegramPrefix.slice(0, -1)
@@ -151,8 +177,14 @@ export function buildTelegramBridgeSystemPrompt(options: {
151
177
  ? `${options.telegramTurnSystemPromptSuffix}\n- The current user message came from Telegram.`
152
178
  : "";
153
179
  return {
154
- systemPrompt:
155
- options.systemPrompt + options.localSystemPromptSuffix + telegramSuffix,
180
+ systemPrompt: Array.isArray(options.systemPrompt)
181
+ ? [
182
+ ...options.systemPrompt,
183
+ options.localSystemPromptSuffix + telegramSuffix,
184
+ ]
185
+ : options.systemPrompt +
186
+ options.localSystemPromptSuffix +
187
+ telegramSuffix,
156
188
  };
157
189
  }
158
190
 
@@ -162,7 +194,7 @@ export function createTelegramBeforeAgentStartHook(
162
194
  localSystemPromptSuffix?: string;
163
195
  telegramTurnSystemPromptSuffix?: string;
164
196
  } = {},
165
- ): (event: BeforeAgentStartEvent) => { systemPrompt: string } {
197
+ ): TelegramBeforeAgentStartHook {
166
198
  return (event) =>
167
199
  buildTelegramBridgeSystemPrompt({
168
200
  prompt: event.prompt,
@@ -176,23 +208,23 @@ export function createTelegramBeforeAgentStartHook(
176
208
  });
177
209
  }
178
210
 
179
- function stripTelegramToolMetadataFromSystemPrompt(
180
- systemPrompt: string,
181
- ): string {
182
- const telegramLines = new Set([
183
- `- telegram_attach: ${TELEGRAM_ATTACH_PROMPT_SNIPPET}`,
184
- `- telegram_message: ${TELEGRAM_MESSAGE_PROMPT_SNIPPET}`,
185
- ...TELEGRAM_ATTACH_PROMPT_GUIDELINES.map((line) => `- ${line}`),
186
- ...TELEGRAM_MESSAGE_PROMPT_GUIDELINES.map((line) => `- ${line}`),
187
- ]);
211
+ function stripTelegramToolMetadataFromString(systemPrompt: string): string {
188
212
  return systemPrompt
189
213
  .split("\n")
190
- .filter((line) => !telegramLines.has(line))
214
+ .filter((line) => TELEGRAM_TOOL_METADATA_LINES[line] !== true)
191
215
  .join("\n");
192
216
  }
193
217
 
218
+ function stripTelegramToolMetadataFromSystemPrompt(
219
+ systemPrompt: TelegramSystemPrompt,
220
+ ): TelegramSystemPrompt {
221
+ return Array.isArray(systemPrompt)
222
+ ? systemPrompt.map(stripTelegramToolMetadataFromString)
223
+ : stripTelegramToolMetadataFromString(systemPrompt);
224
+ }
225
+
194
226
  export interface TelegramProactivePromptHookDeps<TContext> {
195
- baseHook?: (event: BeforeAgentStartEvent) => { systemPrompt: string };
227
+ baseHook?: TelegramBeforeAgentStartHook;
196
228
  reconcileAvailability?: () => void;
197
229
  isAvailable: (ctx: TContext) => boolean;
198
230
  }
@@ -200,9 +232,9 @@ export interface TelegramProactivePromptHookDeps<TContext> {
200
232
  export function createTelegramProactiveBeforeAgentStartHook<TContext>(
201
233
  deps: TelegramProactivePromptHookDeps<TContext>,
202
234
  ): (
203
- event: BeforeAgentStartEvent,
235
+ event: TelegramBeforeAgentStartEvent,
204
236
  ctx: TContext,
205
- ) => Promise<{ systemPrompt: string }> {
237
+ ) => Promise<TelegramBeforeAgentStartResult> {
206
238
  const baseHook = deps.baseHook ?? createTelegramBeforeAgentStartHook();
207
239
  return async (event, ctx) => {
208
240
  deps.reconcileAvailability?.();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-telegram",
3
- "version": "0.36.2",
3
+ "version": "0.36.3",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"