@llblab/pi-kit 0.29.1 → 0.30.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 (222) hide show
  1. package/BACKLOG.md +3 -1
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +4 -4
  4. package/node_modules/@llblab/pi-state-flow/CHANGELOG.md +12 -0
  5. package/node_modules/@llblab/pi-state-flow/README.md +2 -2
  6. package/node_modules/@llblab/pi-state-flow/dist/lib/context.d.ts +2 -2
  7. package/node_modules/@llblab/pi-state-flow/dist/lib/context.js +17 -8
  8. package/node_modules/@llblab/pi-state-flow/dist/lib/extension.js +7 -3
  9. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.d.ts +2 -1
  10. package/node_modules/@llblab/pi-state-flow/dist/lib/protocol.js +3 -2
  11. package/node_modules/@llblab/pi-state-flow/dist/package.json +1 -1
  12. package/node_modules/@llblab/pi-state-flow/docs/architecture.md +3 -3
  13. package/node_modules/@llblab/pi-state-flow/docs/usage.md +3 -2
  14. package/node_modules/@llblab/pi-state-flow/lib/context.ts +17 -8
  15. package/node_modules/@llblab/pi-state-flow/lib/extension.ts +6 -3
  16. package/node_modules/@llblab/pi-state-flow/lib/protocol.ts +4 -2
  17. package/node_modules/@llblab/pi-state-flow/package.json +1 -1
  18. package/node_modules/@llblab/pi-telegram/AGENTS.md +13 -10
  19. package/node_modules/@llblab/pi-telegram/BACKLOG.md +1 -1
  20. package/node_modules/@llblab/pi-telegram/CHANGELOG.md +23 -0
  21. package/node_modules/@llblab/pi-telegram/README.md +10 -11
  22. package/node_modules/@llblab/pi-telegram/api/commands.ts +3 -0
  23. package/node_modules/@llblab/pi-telegram/dist/api/commands.d.ts +1 -1
  24. package/node_modules/@llblab/pi-telegram/dist/lib/activity-verbosity.d.ts +1 -5
  25. package/node_modules/@llblab/pi-telegram/dist/lib/activity-verbosity.js +15 -42
  26. package/node_modules/@llblab/pi-telegram/dist/lib/activity.d.ts +9 -0
  27. package/node_modules/@llblab/pi-telegram/dist/lib/activity.js +39 -10
  28. package/node_modules/@llblab/pi-telegram/dist/lib/agent-messages.js +7 -3
  29. package/node_modules/@llblab/pi-telegram/dist/lib/bindings.d.ts +43 -5
  30. package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +164 -20
  31. package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.d.ts +12 -0
  32. package/node_modules/@llblab/pi-telegram/dist/lib/bus-api.js +181 -77
  33. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.d.ts +111 -31
  34. package/node_modules/@llblab/pi-telegram/dist/lib/bus-follower.js +1324 -359
  35. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.d.ts +41 -91
  36. package/node_modules/@llblab/pi-telegram/dist/lib/bus-leader.js +969 -637
  37. package/node_modules/@llblab/pi-telegram/dist/lib/bus-transport.js +16 -9
  38. package/node_modules/@llblab/pi-telegram/dist/lib/bus.d.ts +215 -18
  39. package/node_modules/@llblab/pi-telegram/dist/lib/bus.js +1048 -327
  40. package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.d.ts +5 -0
  41. package/node_modules/@llblab/pi-telegram/dist/lib/channel-posts.js +434 -261
  42. package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.d.ts +26 -5
  43. package/node_modules/@llblab/pi-telegram/dist/lib/command-templates.js +92 -176
  44. package/node_modules/@llblab/pi-telegram/dist/lib/commands.d.ts +168 -82
  45. package/node_modules/@llblab/pi-telegram/dist/lib/commands.js +1409 -291
  46. package/node_modules/@llblab/pi-telegram/dist/lib/config.d.ts +1 -8
  47. package/node_modules/@llblab/pi-telegram/dist/lib/config.js +34 -76
  48. package/node_modules/@llblab/pi-telegram/dist/lib/delivery.d.ts +2 -2
  49. package/node_modules/@llblab/pi-telegram/dist/lib/delivery.js +16 -16
  50. package/node_modules/@llblab/pi-telegram/dist/lib/extension.js +642 -170
  51. package/node_modules/@llblab/pi-telegram/dist/lib/generative-app-worker.mjs +19 -7
  52. package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.d.ts +0 -5
  53. package/node_modules/@llblab/pi-telegram/dist/lib/generative-apps.js +61 -49
  54. package/node_modules/@llblab/pi-telegram/dist/lib/inbound.d.ts +5 -0
  55. package/node_modules/@llblab/pi-telegram/dist/lib/inbound.js +35 -59
  56. package/node_modules/@llblab/pi-telegram/dist/lib/journal.d.ts +40 -4
  57. package/node_modules/@llblab/pi-telegram/dist/lib/journal.js +2102 -760
  58. package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.d.ts +2 -6
  59. package/node_modules/@llblab/pi-telegram/dist/lib/lifecycle.js +75 -58
  60. package/node_modules/@llblab/pi-telegram/dist/lib/locks.d.ts +34 -3
  61. package/node_modules/@llblab/pi-telegram/dist/lib/locks.js +318 -119
  62. package/node_modules/@llblab/pi-telegram/dist/lib/logging.js +50 -14
  63. package/node_modules/@llblab/pi-telegram/dist/lib/media.d.ts +22 -1
  64. package/node_modules/@llblab/pi-telegram/dist/lib/media.js +46 -28
  65. package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.d.ts +19 -5
  66. package/node_modules/@llblab/pi-telegram/dist/lib/menu-model.js +53 -11
  67. package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.d.ts +5 -4
  68. package/node_modules/@llblab/pi-telegram/dist/lib/menu-queue.js +45 -63
  69. package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.d.ts +5 -4
  70. package/node_modules/@llblab/pi-telegram/dist/lib/menu-settings.js +114 -78
  71. package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.d.ts +1 -1
  72. package/node_modules/@llblab/pi-telegram/dist/lib/menu-status.js +8 -25
  73. package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.d.ts +6 -1
  74. package/node_modules/@llblab/pi-telegram/dist/lib/menu-thinking.js +14 -21
  75. package/node_modules/@llblab/pi-telegram/dist/lib/menu.d.ts +8 -61
  76. package/node_modules/@llblab/pi-telegram/dist/lib/menu.js +92 -164
  77. package/node_modules/@llblab/pi-telegram/dist/lib/model.d.ts +1 -1
  78. package/node_modules/@llblab/pi-telegram/dist/lib/model.js +2 -16
  79. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.d.ts +6 -27
  80. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-attachments.js +45 -38
  81. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-buttons.js +22 -16
  82. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.d.ts +0 -2
  83. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-markup.js +51 -64
  84. package/node_modules/@llblab/pi-telegram/dist/lib/outbound-voice.js +6 -3
  85. package/node_modules/@llblab/pi-telegram/dist/lib/outbound.d.ts +6 -6
  86. package/node_modules/@llblab/pi-telegram/dist/lib/outbound.js +61 -51
  87. package/node_modules/@llblab/pi-telegram/dist/lib/ownership.js +6 -2
  88. package/node_modules/@llblab/pi-telegram/dist/lib/paths.d.ts +5 -0
  89. package/node_modules/@llblab/pi-telegram/dist/lib/paths.js +37 -21
  90. package/node_modules/@llblab/pi-telegram/dist/lib/pi.d.ts +2 -0
  91. package/node_modules/@llblab/pi-telegram/dist/lib/pi.js +8 -1
  92. package/node_modules/@llblab/pi-telegram/dist/lib/polling.d.ts +23 -37
  93. package/node_modules/@llblab/pi-telegram/dist/lib/polling.js +71 -52
  94. package/node_modules/@llblab/pi-telegram/dist/lib/preview.js +39 -19
  95. package/node_modules/@llblab/pi-telegram/dist/lib/process-identity.d.ts +24 -0
  96. package/node_modules/@llblab/pi-telegram/dist/lib/process-identity.js +133 -0
  97. package/node_modules/@llblab/pi-telegram/dist/lib/prompts.js +2 -7
  98. package/node_modules/@llblab/pi-telegram/dist/lib/queue.d.ts +16 -16
  99. package/node_modules/@llblab/pi-telegram/dist/lib/queue.js +261 -116
  100. package/node_modules/@llblab/pi-telegram/dist/lib/recovery.d.ts +2 -83
  101. package/node_modules/@llblab/pi-telegram/dist/lib/recovery.js +20 -274
  102. package/node_modules/@llblab/pi-telegram/dist/lib/replies.d.ts +16 -24
  103. package/node_modules/@llblab/pi-telegram/dist/lib/replies.js +99 -116
  104. package/node_modules/@llblab/pi-telegram/dist/lib/routing.d.ts +121 -7
  105. package/node_modules/@llblab/pi-telegram/dist/lib/routing.js +4750 -1161
  106. package/node_modules/@llblab/pi-telegram/dist/lib/runtime.d.ts +1 -11
  107. package/node_modules/@llblab/pi-telegram/dist/lib/sections.d.ts +4 -29
  108. package/node_modules/@llblab/pi-telegram/dist/lib/sections.js +7 -20
  109. package/node_modules/@llblab/pi-telegram/dist/lib/skills.js +4 -3
  110. package/node_modules/@llblab/pi-telegram/dist/lib/status.js +86 -57
  111. package/node_modules/@llblab/pi-telegram/dist/lib/sync.d.ts +6 -3
  112. package/node_modules/@llblab/pi-telegram/dist/lib/sync.js +112 -45
  113. package/node_modules/@llblab/pi-telegram/dist/lib/target.d.ts +4 -0
  114. package/node_modules/@llblab/pi-telegram/dist/lib/target.js +18 -0
  115. package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.d.ts +18 -11
  116. package/node_modules/@llblab/pi-telegram/dist/lib/telegram-api.js +165 -49
  117. package/node_modules/@llblab/pi-telegram/dist/lib/text-groups.js +4 -39
  118. package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.d.ts +6 -27
  119. package/node_modules/@llblab/pi-telegram/dist/lib/thread-cleanup-manager.js +369 -186
  120. package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.d.ts +1 -2
  121. package/node_modules/@llblab/pi-telegram/dist/lib/thread-display.js +58 -38
  122. package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.d.ts +28 -8
  123. package/node_modules/@llblab/pi-telegram/dist/lib/thread-naming.js +175 -66
  124. package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.d.ts +42 -16
  125. package/node_modules/@llblab/pi-telegram/dist/lib/thread-reconciler.js +90 -50
  126. package/node_modules/@llblab/pi-telegram/dist/lib/threads.d.ts +88 -24
  127. package/node_modules/@llblab/pi-telegram/dist/lib/threads.js +2276 -842
  128. package/node_modules/@llblab/pi-telegram/dist/lib/time-injection.js +1 -2
  129. package/node_modules/@llblab/pi-telegram/dist/lib/turns.js +1 -19
  130. package/node_modules/@llblab/pi-telegram/dist/lib/updates.d.ts +178 -82
  131. package/node_modules/@llblab/pi-telegram/dist/lib/updates.js +2438 -645
  132. package/node_modules/@llblab/pi-telegram/dist/lib/voice.d.ts +7 -22
  133. package/node_modules/@llblab/pi-telegram/dist/lib/voice.js +7 -22
  134. package/node_modules/@llblab/pi-telegram/dist/lib/wire.js +1 -1
  135. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.d.ts +3 -1
  136. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-admission.js +425 -211
  137. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-identity.js +8 -13
  138. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.d.ts +1 -1
  139. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-retirement.js +328 -140
  140. package/node_modules/@llblab/pi-telegram/dist/lib/workspace-slots.js +8 -4
  141. package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
  142. package/node_modules/@llblab/pi-telegram/docs/architecture.md +43 -35
  143. package/node_modules/@llblab/pi-telegram/docs/inbound.md +1 -1
  144. package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +15 -3
  145. package/node_modules/@llblab/pi-telegram/docs/outbound.md +1 -1
  146. package/node_modules/@llblab/pi-telegram/docs/public-api.md +29 -1
  147. package/node_modules/@llblab/pi-telegram/docs/ui-style.md +25 -8
  148. package/node_modules/@llblab/pi-telegram/lib/activity-verbosity.ts +59 -82
  149. package/node_modules/@llblab/pi-telegram/lib/activity.ts +146 -102
  150. package/node_modules/@llblab/pi-telegram/lib/agent-messages.ts +12 -5
  151. package/node_modules/@llblab/pi-telegram/lib/bindings.ts +390 -82
  152. package/node_modules/@llblab/pi-telegram/lib/bus-api.ts +262 -99
  153. package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +2440 -601
  154. package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +2209 -1290
  155. package/node_modules/@llblab/pi-telegram/lib/bus-transport.ts +46 -12
  156. package/node_modules/@llblab/pi-telegram/lib/bus.ts +1673 -444
  157. package/node_modules/@llblab/pi-telegram/lib/channel-posts.ts +848 -327
  158. package/node_modules/@llblab/pi-telegram/lib/command-templates.ts +152 -265
  159. package/node_modules/@llblab/pi-telegram/lib/commands.ts +2398 -555
  160. package/node_modules/@llblab/pi-telegram/lib/config.ts +177 -170
  161. package/node_modules/@llblab/pi-telegram/lib/delivery.ts +41 -29
  162. package/node_modules/@llblab/pi-telegram/lib/extension.ts +1209 -431
  163. package/node_modules/@llblab/pi-telegram/lib/generative-app-worker.mjs +19 -7
  164. package/node_modules/@llblab/pi-telegram/lib/generative-apps.ts +324 -211
  165. package/node_modules/@llblab/pi-telegram/lib/inbound.ts +95 -97
  166. package/node_modules/@llblab/pi-telegram/lib/journal.ts +5329 -1712
  167. package/node_modules/@llblab/pi-telegram/lib/keyboard.ts +1 -3
  168. package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +128 -78
  169. package/node_modules/@llblab/pi-telegram/lib/locks.ts +703 -212
  170. package/node_modules/@llblab/pi-telegram/lib/logging.ts +147 -58
  171. package/node_modules/@llblab/pi-telegram/lib/media.ts +82 -43
  172. package/node_modules/@llblab/pi-telegram/lib/menu-model.ts +85 -18
  173. package/node_modules/@llblab/pi-telegram/lib/menu-queue.ts +88 -129
  174. package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +260 -155
  175. package/node_modules/@llblab/pi-telegram/lib/menu-status.ts +20 -60
  176. package/node_modules/@llblab/pi-telegram/lib/menu-thinking.ts +41 -56
  177. package/node_modules/@llblab/pi-telegram/lib/menu.ts +112 -285
  178. package/node_modules/@llblab/pi-telegram/lib/model.ts +8 -22
  179. package/node_modules/@llblab/pi-telegram/lib/outbound-attachments.ts +156 -125
  180. package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +76 -49
  181. package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +96 -94
  182. package/node_modules/@llblab/pi-telegram/lib/outbound-voice.ts +33 -27
  183. package/node_modules/@llblab/pi-telegram/lib/outbound.ts +125 -125
  184. package/node_modules/@llblab/pi-telegram/lib/ownership.ts +19 -10
  185. package/node_modules/@llblab/pi-telegram/lib/paths.ts +148 -49
  186. package/node_modules/@llblab/pi-telegram/lib/pi.ts +35 -15
  187. package/node_modules/@llblab/pi-telegram/lib/polling.ts +165 -149
  188. package/node_modules/@llblab/pi-telegram/lib/preview.ts +93 -40
  189. package/node_modules/@llblab/pi-telegram/lib/process-identity.ts +164 -0
  190. package/node_modules/@llblab/pi-telegram/lib/prompts.ts +4 -11
  191. package/node_modules/@llblab/pi-telegram/lib/queue.ts +523 -289
  192. package/node_modules/@llblab/pi-telegram/lib/recovery.ts +50 -454
  193. package/node_modules/@llblab/pi-telegram/lib/rendering.ts +1 -3
  194. package/node_modules/@llblab/pi-telegram/lib/replies.ts +248 -209
  195. package/node_modules/@llblab/pi-telegram/lib/routing.ts +8527 -2149
  196. package/node_modules/@llblab/pi-telegram/lib/runtime.ts +1 -12
  197. package/node_modules/@llblab/pi-telegram/lib/sections.ts +24 -89
  198. package/node_modules/@llblab/pi-telegram/lib/setup.ts +1 -3
  199. package/node_modules/@llblab/pi-telegram/lib/skills.ts +9 -4
  200. package/node_modules/@llblab/pi-telegram/lib/status.ts +215 -110
  201. package/node_modules/@llblab/pi-telegram/lib/sync.ts +488 -359
  202. package/node_modules/@llblab/pi-telegram/lib/target.ts +22 -3
  203. package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +322 -122
  204. package/node_modules/@llblab/pi-telegram/lib/text-groups.ts +5 -39
  205. package/node_modules/@llblab/pi-telegram/lib/thread-cleanup-manager.ts +833 -331
  206. package/node_modules/@llblab/pi-telegram/lib/thread-display.ts +213 -97
  207. package/node_modules/@llblab/pi-telegram/lib/thread-naming.ts +232 -87
  208. package/node_modules/@llblab/pi-telegram/lib/thread-reconciler.ts +155 -72
  209. package/node_modules/@llblab/pi-telegram/lib/threads.ts +5329 -1817
  210. package/node_modules/@llblab/pi-telegram/lib/time-injection.ts +1 -4
  211. package/node_modules/@llblab/pi-telegram/lib/turns.ts +15 -28
  212. package/node_modules/@llblab/pi-telegram/lib/updates.ts +5194 -1600
  213. package/node_modules/@llblab/pi-telegram/lib/voice.ts +7 -35
  214. package/node_modules/@llblab/pi-telegram/lib/wire.ts +1 -1
  215. package/node_modules/@llblab/pi-telegram/lib/workspace-admission.ts +996 -416
  216. package/node_modules/@llblab/pi-telegram/lib/workspace-identity.ts +14 -17
  217. package/node_modules/@llblab/pi-telegram/lib/workspace-retirement.ts +878 -376
  218. package/node_modules/@llblab/pi-telegram/lib/workspace-slots.ts +22 -13
  219. package/node_modules/@llblab/pi-telegram/package.json +1 -1
  220. package/package.json +3 -3
  221. package/node_modules/@llblab/pi-telegram/scripts/check-downgrade.mjs +0 -472
  222. package/node_modules/@llblab/pi-telegram/scripts/measure-workspace.mjs +0 -108
@@ -3,9 +3,9 @@
3
3
  * Zones: telegram config, pairing, filesystem
4
4
  * Owns persisted bot/session pairing state, local config storage, live config controls, authorization policy, and first-user pairing side effects
5
5
  */
6
- export { TELEGRAM_DEFAULT_PROFILE_NAME } from "./paths.ts";
7
6
  import type { CommandTemplateObjectConfig } from "./command-templates.ts";
8
7
  import type { TelegramInboundHandlerConfig } from "./inbound.ts";
8
+ export { TELEGRAM_DEFAULT_PROFILE_NAME } from "./paths.ts";
9
9
  /** Parsed stored bot-token form: a literal secret or one environment-variable reference. */
10
10
  export type TelegramBotTokenReference = {
11
11
  kind: "literal";
@@ -152,20 +152,13 @@ export interface TelegramInvalidConfigRecovery {
152
152
  recoveryPath: string;
153
153
  error: unknown;
154
154
  }
155
- export interface TelegramConfigRuntime {
156
- updateVoiceConfig: (voice: NonNullable<TelegramConfig["voice"]>) => void;
157
- }
158
- export declare function setGlobalTelegramConfigRuntime(runtime: TelegramConfigRuntime | undefined): void;
159
- export declare function updateTelegramVoiceConfig(voice: NonNullable<TelegramConfig["voice"]>): boolean;
160
155
  type TelegramMutableConfigStore = Pick<TelegramConfigStore, "get" | "set" | "persist"> & {
161
156
  load?: () => Promise<void>;
162
157
  didLastLoadRecoverInvalidConfig?: () => boolean;
163
158
  };
164
- export declare function bindGlobalTelegramConfigRuntime(configStore: TelegramMutableConfigStore): void;
165
159
  export declare function readTelegramConfig(configPath: string, options?: {
166
160
  onInvalidConfig?: (recovery: TelegramInvalidConfigRecovery) => void;
167
161
  }): Promise<TelegramConfig>;
168
- export declare function writeTelegramConfig(agentDir: string, configPath: string, config: TelegramConfig): Promise<void>;
169
162
  export declare function getTelegramProfileFields(config: TelegramConfig): TelegramBotProfile | undefined;
170
163
  export declare function normalizeTelegramDefaultProfileConfig(config: TelegramConfig): {
171
164
  config: TelegramConfig;
@@ -5,12 +5,11 @@
5
5
  */
6
6
  import { createHash, randomUUID } from "node:crypto";
7
7
  import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
8
- import { chmod, mkdir, rename, writeFile } from "node:fs/promises";
8
+ import { withTelegramFileTransaction } from "./locks.js";
9
9
  import { resolveAgentDir, resolveTelegramConfigPath, TELEGRAM_DEFAULT_PROFILE_NAME, } from "./paths.js";
10
- export { TELEGRAM_DEFAULT_PROFILE_NAME } from "./paths.js";
10
+ import { isPiStaleContextError } from "./pi.js";
11
11
  import { isWireRecord as isPlainConfigRecord } from "./wire.js";
12
- import { withTelegramFileTransaction } from "./locks.js";
13
- const CONFIG_RUNTIME_KEY = "__piTelegramConfigRuntime__";
12
+ export { TELEGRAM_DEFAULT_PROFILE_NAME } from "./paths.js";
14
13
  const CONFIG_REPLACE_RETRY_ATTEMPTS = 5;
15
14
  const CONFIG_REPLACE_RETRY_DELAY_MS = 25;
16
15
  function isRetryableConfigReplaceError(error) {
@@ -81,7 +80,10 @@ export function getTelegramBotTokenDiagnostic(value, env = process.env) {
81
80
  return `Telegram bot token environment variable ${reference.variable} is not set.`;
82
81
  }
83
82
  const TELEGRAM_THREAD_DISPLAY_MODES = [
84
- "letters", "names", "directory-snake", "directory-title",
83
+ "letters",
84
+ "names",
85
+ "directory-snake",
86
+ "directory-title",
85
87
  ];
86
88
  export function resolveTelegramThreadDisplayMode(config) {
87
89
  return TELEGRAM_THREAD_DISPLAY_MODES.includes(config.threadDisplayMode)
@@ -124,20 +126,6 @@ export function createTelegramConfigBotIdGetter(store) {
124
126
  export function createTelegramActiveProfileKeyGetter(store) {
125
127
  return () => store.getActiveProfileName() ?? TELEGRAM_DEFAULT_PROFILE_NAME;
126
128
  }
127
- export function setGlobalTelegramConfigRuntime(runtime) {
128
- const globals = globalThis;
129
- if (runtime)
130
- globals[CONFIG_RUNTIME_KEY] = runtime;
131
- else
132
- delete globals[CONFIG_RUNTIME_KEY];
133
- }
134
- export function updateTelegramVoiceConfig(voice) {
135
- const runtime = globalThis[CONFIG_RUNTIME_KEY];
136
- if (!runtime || typeof runtime.updateVoiceConfig !== "function")
137
- return false;
138
- runtime.updateVoiceConfig(voice);
139
- return true;
140
- }
141
129
  function isEmptyTelegramConfig(config) {
142
130
  return Object.keys(config).length === 0;
143
131
  }
@@ -151,19 +139,6 @@ async function loadLatestTelegramConfig(configStore) {
151
139
  configStore.set(before);
152
140
  }
153
141
  }
154
- export function bindGlobalTelegramConfigRuntime(configStore) {
155
- setGlobalTelegramConfigRuntime({
156
- updateVoiceConfig(voice) {
157
- const current = configStore.get();
158
- const next = {
159
- ...current,
160
- voice: { ...(current.voice ?? {}), ...voice },
161
- };
162
- configStore.set(next);
163
- void configStore.persist(next);
164
- },
165
- });
166
- }
167
142
  function getInvalidTelegramConfigRecoveryPath(configPath) {
168
143
  return `${configPath}.invalid-${process.pid}-${Date.now()}`;
169
144
  }
@@ -201,17 +176,6 @@ export async function readTelegramConfig(configPath, options = {}) {
201
176
  });
202
177
  }
203
178
  }
204
- export async function writeTelegramConfig(agentDir, configPath, config) {
205
- await mkdir(agentDir, { recursive: true });
206
- const tempConfigPath = `${configPath}.tmp-${process.pid}-${Date.now()}`;
207
- await writeFile(tempConfigPath, JSON.stringify(config, null, "\t") + "\n", {
208
- encoding: "utf8",
209
- mode: 0o600,
210
- });
211
- await chmod(tempConfigPath, 0o600);
212
- await rename(tempConfigPath, configPath);
213
- await chmod(configPath, 0o600);
214
- }
215
179
  function cloneTelegramConfig(value) {
216
180
  return structuredClone(value);
217
181
  }
@@ -275,10 +239,13 @@ export function getTelegramProfileFields(config) {
275
239
  const token = config.botToken?.trim();
276
240
  if (!token)
277
241
  return undefined;
242
+ return { botToken: token, ...pickTelegramRootProfileFields(config) };
243
+ }
244
+ /** Root-level profile fields other than the token, including the retired legacy cursor. */
245
+ function pickTelegramRootProfileFields(config) {
278
246
  const legacyCursor = config
279
247
  .lastUpdateId;
280
248
  return {
281
- botToken: token,
282
249
  ...(config.botUsername !== undefined
283
250
  ? { botUsername: config.botUsername }
284
251
  : {}),
@@ -332,23 +299,7 @@ export function normalizeTelegramDefaultProfileConfig(config) {
332
299
  }
333
300
  const legacyProfile = {
334
301
  ...(legacyToken ? { botToken: legacyToken } : {}),
335
- ...(config.botUsername !== undefined
336
- ? { botUsername: config.botUsername }
337
- : {}),
338
- ...(config.botId !== undefined ? { botId: config.botId } : {}),
339
- ...(config.allowedUserId !== undefined
340
- ? { allowedUserId: config.allowedUserId }
341
- : {}),
342
- ...(config.threadDisplayMode !== undefined
343
- ? { threadDisplayMode: config.threadDisplayMode }
344
- : {}),
345
- ...(config
346
- .lastUpdateId !== undefined
347
- ? {
348
- lastUpdateId: config
349
- .lastUpdateId,
350
- }
351
- : {}),
302
+ ...pickTelegramRootProfileFields(config),
352
303
  };
353
304
  if (!canonicalProfile && !legacyToken) {
354
305
  throw new Error("Legacy Telegram default profile has no bot token");
@@ -421,7 +372,8 @@ export function createTelegramConfigStore(options = {}) {
421
372
  config = nextConfig;
422
373
  };
423
374
  const withPersistedPairingProfile = (profileName, tokenSha256, observe) => {
424
- if ((profileName !== TELEGRAM_DEFAULT_PROFILE_NAME && !isValidTelegramProfileName(profileName)) ||
375
+ if ((profileName !== TELEGRAM_DEFAULT_PROFILE_NAME &&
376
+ !isValidTelegramProfileName(profileName)) ||
425
377
  !/^[a-f0-9]{64}$/u.test(tokenSha256)) {
426
378
  throw new Error("Invalid Telegram pairing admission identity.");
427
379
  }
@@ -431,10 +383,13 @@ export function createTelegramConfigStore(options = {}) {
431
383
  const resolvedToken = typeof profile?.botToken === "string"
432
384
  ? resolveTelegramBotToken(profile.botToken, env)
433
385
  : undefined;
434
- if (!profile || !resolvedToken ||
435
- createHash("sha256").update(resolvedToken).digest("hex") !== tokenSha256 ||
386
+ if (!profile ||
387
+ !resolvedToken ||
388
+ createHash("sha256").update(resolvedToken).digest("hex") !==
389
+ tokenSha256 ||
436
390
  (profile.allowedUserId !== undefined &&
437
- (!Number.isSafeInteger(profile.allowedUserId) || profile.allowedUserId <= 0))) {
391
+ (!Number.isSafeInteger(profile.allowedUserId) ||
392
+ profile.allowedUserId <= 0))) {
438
393
  throw new Error("Telegram pairing admission authority is unavailable or changed.");
439
394
  }
440
395
  return observe(latest, profile);
@@ -506,9 +461,11 @@ export function createTelegramConfigStore(options = {}) {
506
461
  assertExecutionCurrent?.();
507
462
  const current = getEffectiveConfig();
508
463
  const previousOwner = persistedConfig.profiles?.[profileName]?.allowedUserId;
509
- if ((activeProfileName ?? TELEGRAM_DEFAULT_PROFILE_NAME) !== profileName ||
464
+ if ((activeProfileName ?? TELEGRAM_DEFAULT_PROFILE_NAME) !==
465
+ profileName ||
510
466
  current.botToken !== profile.botToken ||
511
- (current.allowedUserId !== undefined && current.allowedUserId !== userId) ||
467
+ (current.allowedUserId !== undefined &&
468
+ current.allowedUserId !== userId) ||
512
469
  (current.allowedUserId === undefined && previousOwner !== undefined)) {
513
470
  throw new Error("Telegram paired admission lost local profile authority.");
514
471
  }
@@ -524,7 +481,8 @@ export function createTelegramConfigStore(options = {}) {
524
481
  const previousOwner = getEffectiveConfig().allowedUserId;
525
482
  const assertCurrent = () => {
526
483
  assertExecutionCurrent?.();
527
- if (activeProfileName !== profileName || getEffectiveConfig().botToken !== botToken ||
484
+ if (activeProfileName !== profileName ||
485
+ getEffectiveConfig().botToken !== botToken ||
528
486
  getEffectiveConfig().allowedUserId !== previousOwner) {
529
487
  throw new Error("Telegram pairing lost its originating profile authority.");
530
488
  }
@@ -544,8 +502,13 @@ export function createTelegramConfigStore(options = {}) {
544
502
  assertCurrent();
545
503
  if (profile.allowedUserId !== undefined)
546
504
  return latest;
547
- const next = { ...latest, profiles: { ...latest.profiles,
548
- [profileKey]: { ...profile, allowedUserId: userId } } };
505
+ const next = {
506
+ ...latest,
507
+ profiles: {
508
+ ...latest.profiles,
509
+ [profileKey]: { ...profile, allowedUserId: userId },
510
+ },
511
+ };
549
512
  writeTelegramConfigInTransaction(agentDir, configPath, next);
550
513
  return next;
551
514
  });
@@ -851,11 +814,6 @@ export function getTelegramAuthorizationState(userId, allowedUserId) {
851
814
  }
852
815
  return { kind: "deny" };
853
816
  }
854
- function isTelegramStaleContextError(error) {
855
- return (error instanceof Error &&
856
- (error.message.includes("stale after session") ||
857
- error.message.includes("stale ctx")));
858
- }
859
817
  export async function pairTelegramUserIfNeeded(userId, deps) {
860
818
  const authorization = getTelegramAuthorizationState(userId, deps.allowedUserId);
861
819
  if (authorization.kind !== "pair")
@@ -869,7 +827,7 @@ export async function pairTelegramUserIfNeeded(userId, deps) {
869
827
  deps.updateStatus(deps.ctx);
870
828
  }
871
829
  catch (error) {
872
- if (!isTelegramStaleContextError(error))
830
+ if (!isPiStaleContextError(error))
873
831
  throw error;
874
832
  }
875
833
  return true;
@@ -49,6 +49,7 @@ export type TelegramDeliveryChatAction = "typing" | "upload_document" | "upload_
49
49
  /** @internal */
50
50
  export interface TelegramDeliveryRuntime {
51
51
  readonly generation: string;
52
+ hasPendingTarget?: (target: TelegramDeliveryTarget) => boolean;
52
53
  shutdown: () => void;
53
54
  sendView: (view: TelegramDeliveryView, options: SendTelegramViewOptions) => Promise<TelegramDeliveryResult<TelegramDeliveryHandle>>;
54
55
  editView: (handle: TelegramDeliveryHandle, view: TelegramDeliveryView) => Promise<TelegramDeliveryResult<TelegramDeliveryHandle>>;
@@ -100,6 +101,7 @@ export interface TelegramBridgeDeliveryRuntimeDeps {
100
101
  export declare function createTelegramDeliveryLifecycleHooks(createRuntime: () => TelegramDeliveryRuntime): {
101
102
  onSessionStart: () => Promise<void>;
102
103
  onSessionShutdown: () => Promise<void>;
104
+ hasPendingTarget: (target: TelegramDeliveryTarget) => boolean | undefined;
103
105
  };
104
106
  export declare function createTelegramDeliveryGenerationSeed(instanceId: string): string;
105
107
  /** @internal */
@@ -152,8 +154,6 @@ export declare function clearTelegramDeliveryRuntime(): void;
152
154
  /** @internal */
153
155
  export declare function isTelegramDeliveryHandleCurrent(handle: TelegramDeliveryHandle): boolean;
154
156
  export declare function sendTelegramView(view: TelegramDeliveryView, options: SendTelegramViewOptions): Promise<TelegramDeliveryResult<TelegramDeliveryHandle>>;
155
- /** @internal Edit an exact Telegram message through the currently bound runtime generation. */
156
- export declare function editTelegramTargetView(target: TelegramDeliveryTarget, messageId: number, view: TelegramDeliveryView): Promise<TelegramDeliveryResult<TelegramDeliveryHandle>>;
157
157
  export declare function editTelegramView(handle: TelegramDeliveryHandle, view: TelegramDeliveryView): Promise<TelegramDeliveryResult<TelegramDeliveryHandle>>;
158
158
  export declare function deleteTelegramView(handle: TelegramDeliveryHandle): Promise<TelegramDeliveryResult<void>>;
159
159
  export declare function sendTelegramChatAction(action: TelegramDeliveryChatAction, options: {
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { markTelegramBusAggregateDelivery } from "./bus.js";
7
7
  import { assertTelegramInlineKeyboardCallbackData, } from "./keyboard.js";
8
- import { withTelegramReplyParameters, renderTelegramMessage, } from "./replies.js";
8
+ import { renderTelegramMessage, withTelegramReplyParameters, } from "./replies.js";
9
9
  import { areTelegramTargetsEqual as areDeliveryTargetsEqual, getTelegramTargetThreadParams, } from "./target.js";
10
10
  import { getTelegramApiRetryAfterMs, isRetryableTelegramApiError, isTelegramApiCommitUnknownError, isTelegramMessageUnavailableError, } from "./telegram-api.js";
11
11
  const TELEGRAM_DELIVERY_RUNTIME_KEY = "__piTelegramDeliveryRuntime__";
@@ -26,6 +26,7 @@ export function createTelegramDeliveryLifecycleHooks(createRuntime) {
26
26
  runtime = undefined;
27
27
  };
28
28
  return {
29
+ hasPendingTarget: (target) => runtime?.hasPendingTarget?.(target),
29
30
  onSessionStart: async () => {
30
31
  stopCurrentRuntime();
31
32
  runtime = createRuntime();
@@ -167,7 +168,7 @@ function resolveTelegramDeliveryTarget(scope, deps) {
167
168
  }
168
169
  function createTelegramDeliveryTargetQueue() {
169
170
  const queues = new Map();
170
- return async function run(target, operation) {
171
+ async function run(target, operation) {
171
172
  const key = targetKey(target);
172
173
  const previous = queues.get(key) ?? Promise.resolve();
173
174
  const current = previous.then(operation, operation);
@@ -180,6 +181,10 @@ function createTelegramDeliveryTargetQueue() {
180
181
  if (queues.get(key) === settled)
181
182
  queues.delete(key);
182
183
  }
184
+ }
185
+ return {
186
+ run,
187
+ hasPendingTarget: (target) => queues.has(targetKey(target)),
183
188
  };
184
189
  }
185
190
  function getChunkTransportOptions(view, index, chunkCount, replyToMessageId, editing = false) {
@@ -198,7 +203,8 @@ function getChunkTransportOptions(view, index, chunkCount, replyToMessageId, edi
198
203
  export function createTelegramDeliveryRuntime(deps) {
199
204
  let active = true;
200
205
  const handleBindings = new WeakMap();
201
- const runForTarget = createTelegramDeliveryTargetQueue();
206
+ const targetQueue = createTelegramDeliveryTargetQueue();
207
+ const runForTarget = targetQueue.run;
202
208
  const render = (view) => {
203
209
  const chunks = deps.renderView(view);
204
210
  if (chunks.length === 0 ||
@@ -247,6 +253,7 @@ export function createTelegramDeliveryRuntime(deps) {
247
253
  };
248
254
  return {
249
255
  generation: deps.generation,
256
+ hasPendingTarget: targetQueue.hasPendingTarget,
250
257
  shutdown() {
251
258
  active = false;
252
259
  },
@@ -420,10 +427,14 @@ export function createTelegramBridgeDeliveryRuntime(deps) {
420
427
  const body = {
421
428
  chat_id: target.chatId,
422
429
  text: chunk.text,
423
- ...(chunk.parseMode === "html" ? { parse_mode: "HTML" } : {}),
430
+ ...(chunk.parseMode === "html"
431
+ ? { parse_mode: "HTML" }
432
+ : {}),
424
433
  ...getTelegramTargetThreadParams(target),
425
434
  ...(replyParameters ? { reply_parameters: replyParameters } : {}),
426
- ...(options.replyMarkup ? { reply_markup: options.replyMarkup } : {}),
435
+ ...(options.replyMarkup
436
+ ? { reply_markup: options.replyMarkup }
437
+ : {}),
427
438
  };
428
439
  return deps.api.sendMessage(target.threadId === undefined
429
440
  ? markTelegramBusAggregateDelivery(body)
@@ -515,17 +526,6 @@ export async function sendTelegramView(view, options) {
515
526
  return invalid;
516
527
  return runDeliveryOperation((runtime) => runtime.sendView(view, options));
517
528
  }
518
- /** @internal Edit an exact Telegram message through the currently bound runtime generation. */
519
- export async function editTelegramTargetView(target, messageId, view) {
520
- const invalid = validateView(view);
521
- if (invalid)
522
- return invalid;
523
- return runDeliveryOperation((runtime) => runtime.editView({
524
- target: { ...target },
525
- messageIds: [messageId],
526
- generation: runtime.generation,
527
- }, view));
528
- }
529
529
  export async function editTelegramView(handle, view) {
530
530
  const invalid = validateView(view);
531
531
  if (invalid)