@llblab/pi-telegram 0.17.4 → 0.18.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.
Files changed (62) hide show
  1. package/AGENTS.md +67 -32
  2. package/BACKLOG.md +59 -14
  3. package/CHANGELOG.md +40 -15
  4. package/README.md +63 -35
  5. package/docs/README.md +3 -1
  6. package/docs/architecture.md +55 -23
  7. package/docs/callback-namespaces.md +1 -1
  8. package/docs/inbound.md +1 -1
  9. package/docs/locks.md +0 -2
  10. package/docs/multi-instance-bus.md +483 -0
  11. package/docs/outbound.md +4 -3
  12. package/docs/public-api.md +12 -10
  13. package/docs/sections.md +2 -2
  14. package/docs/ui-style.md +76 -0
  15. package/index.ts +789 -32
  16. package/lib/bindings.ts +68 -12
  17. package/lib/bus-api.ts +314 -0
  18. package/lib/bus-follower.ts +853 -0
  19. package/lib/bus-leader.ts +915 -0
  20. package/lib/bus.ts +866 -0
  21. package/lib/command-templates.ts +9 -11
  22. package/lib/commands.ts +133 -47
  23. package/lib/config.ts +53 -5
  24. package/lib/lifecycle.ts +23 -7
  25. package/lib/locks.ts +230 -66
  26. package/lib/media.ts +30 -2
  27. package/lib/menu-model.ts +48 -17
  28. package/lib/menu-queue.ts +51 -20
  29. package/lib/menu-settings.ts +9 -5
  30. package/lib/menu-status.ts +3 -0
  31. package/lib/menu-thinking.ts +3 -0
  32. package/lib/menu.ts +67 -26
  33. package/lib/outbound-attachments.ts +102 -17
  34. package/lib/outbound-buttons.ts +6 -2
  35. package/lib/outbound-voice.ts +31 -11
  36. package/lib/outbound.ts +6 -4
  37. package/lib/ownership.ts +119 -0
  38. package/lib/pi.ts +26 -3
  39. package/lib/polling.ts +477 -7
  40. package/lib/preview.ts +141 -88
  41. package/lib/prompt-templates.ts +3 -3
  42. package/lib/prompts.ts +80 -30
  43. package/lib/queue.ts +193 -91
  44. package/lib/rendering.ts +0 -25
  45. package/lib/replies.ts +187 -55
  46. package/lib/routing.ts +1673 -9
  47. package/lib/runtime-log.ts +123 -0
  48. package/lib/runtime.ts +84 -12
  49. package/lib/sections.ts +28 -21
  50. package/lib/setup.ts +1 -1
  51. package/lib/status.ts +532 -9
  52. package/lib/sync.ts +618 -0
  53. package/lib/target.ts +49 -0
  54. package/lib/telegram-api.ts +405 -40
  55. package/lib/text-groups.ts +5 -1
  56. package/lib/thread-reconciler.ts +915 -0
  57. package/lib/threads.ts +2205 -0
  58. package/lib/turns.ts +48 -3
  59. package/lib/updates.ts +355 -32
  60. package/package.json +24 -2
  61. package/screenshot.png +0 -0
  62. package/docs/telegram-bot-api-rich-messages.md +0 -890
package/lib/turns.ts CHANGED
@@ -44,13 +44,47 @@ export {
44
44
 
45
45
  export const TELEGRAM_PREFIX = "[telegram]";
46
46
 
47
+ export interface TelegramTurnTarget {
48
+ chatId: number;
49
+ threadId?: number;
50
+ }
51
+
47
52
  export interface TelegramTurnMessage {
48
53
  message_id: number;
49
- chat: { id: number };
54
+ message_thread_id?: number;
55
+ chat: { id: number; type?: string };
50
56
  }
51
57
 
52
58
  export type DownloadedTelegramTurnFile = DownloadedTelegramMessageFile;
53
59
 
60
+ function getTelegramTurnTarget(message: TelegramTurnMessage): TelegramTurnTarget {
61
+ return Number.isInteger(message.message_thread_id)
62
+ ? { chatId: message.chat.id, threadId: message.message_thread_id }
63
+ : { chatId: message.chat.id };
64
+ }
65
+
66
+ function formatTelegramPrefixAttributeValue(value: string): string {
67
+ return value.replace(/[\]\n\r|]+/g, " ").replace(/\s+/g, " ").trim();
68
+ }
69
+
70
+ export function createTelegramTurnPrefix(
71
+ attributes: Record<string, string | undefined> = {},
72
+ ): string {
73
+ const parts = [TELEGRAM_PREFIX.slice(1, -1)];
74
+ for (const [key, value] of Object.entries(attributes)) {
75
+ const normalized = value ? formatTelegramPrefixAttributeValue(value) : "";
76
+ if (normalized) parts.push(`${key}:${normalized}`);
77
+ }
78
+ return `[${parts.join("|")}]`;
79
+ }
80
+
81
+ export function formatTelegramTurnPrefix(
82
+ _message: TelegramTurnMessage,
83
+ basePrefix = TELEGRAM_PREFIX,
84
+ ): string {
85
+ return basePrefix;
86
+ }
87
+
54
88
  import { truncateTelegramQueueSummary } from "./queue.ts";
55
89
  export { truncateTelegramQueueSummary };
56
90
 
@@ -363,6 +397,8 @@ export interface TelegramPromptTurnRuntimeBuilderDeps<
363
397
  resolveTimeLine?: (chatId: number) => string | null;
364
398
  getVoiceReplyMode?: () => TelegramVoiceReplyMode;
365
399
  isVoiceReplyModeConfigured?: () => boolean;
400
+ /** Returns the visible thread label for a message target, used to add thread context to the prompt prefix. */
401
+ getTelegramThreadLabel?: (message: { chat: { id: number }; message_thread_id?: number }) => string | undefined;
366
402
  }
367
403
 
368
404
  export function createTelegramPromptTurnRuntimeBuilder<
@@ -397,8 +433,13 @@ export function createTelegramPromptTurnRuntimeBuilder<
397
433
  deps.resolveTimeLine && chatId !== undefined
398
434
  ? deps.resolveTimeLine(chatId)
399
435
  : null;
436
+ const firstMessage = messages[0];
437
+ const threadLabel = firstMessage
438
+ ? deps.getTelegramThreadLabel?.(firstMessage)
439
+ : undefined;
440
+ const telegramPrefix = createTelegramTurnPrefix({ thread: threadLabel });
400
441
  return buildTelegramPromptTurnRuntime({
401
- telegramPrefix: TELEGRAM_PREFIX,
442
+ telegramPrefix,
402
443
  messages,
403
444
  historyTurns,
404
445
  queueOrder: deps.allocateQueueOrder(),
@@ -446,7 +487,10 @@ export async function buildTelegramPromptTurn(
446
487
  {
447
488
  type: "text",
448
489
  text: buildTelegramTurnPrompt({
449
- telegramPrefix: options.telegramPrefix,
490
+ telegramPrefix: formatTelegramTurnPrefix(
491
+ firstMessage,
492
+ options.telegramPrefix,
493
+ ),
450
494
  rawText: options.rawText,
451
495
  files: options.files,
452
496
  promptFiles: options.promptFiles,
@@ -482,6 +526,7 @@ export async function buildTelegramPromptTurn(
482
526
  return {
483
527
  kind: "prompt",
484
528
  chatId: firstMessage.chat.id,
529
+ target: getTelegramTurnTarget(firstMessage),
485
530
  replyToMessageId: firstMessage.message_id,
486
531
  sourceMessageIds: collectTelegramMessageIds(options.messages),
487
532
  queueOrder: options.queueOrder,