@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
@@ -5,10 +5,9 @@
5
5
  * Transport authority, durable bindings, and queue custody remain with their owners.
6
6
  */
7
7
  import * as BusFollower from "./bus-follower.ts";
8
- import * as Queue from "./queue.ts";
9
8
  import type { AgentEndEvent, AgentSettledEvent, AgentStartEvent, AssistantMessageEvent, BeforeAgentStartEvent, ExtensionAPI, ExtensionContext, InputEvent, MessageEndEvent, SessionBeforeCompactEvent, SessionCompactEvent, SessionCompactFailedEvent, SessionShutdownEvent, SessionStartEvent, ToolExecutionEndEvent, ToolExecutionStartEvent, ToolExecutionUpdateEvent, UIPromptEndEvent, UIPromptStartEvent } from "./pi.ts";
10
- export declare function setResetTransportReplyDedup(fn: () => void): void;
11
- export declare function createAgentStartDedupHook(inner: (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>, schedulePublication?: (task: () => Promise<void>) => void): (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>;
9
+ import * as Queue from "./queue.ts";
10
+ export declare function createAgentStartDedupHook(inner: (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>, resetReplyDedup: () => void, schedulePublication?: (task: () => Promise<void>) => void): (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>;
12
11
  type TelegramBeforeAgentStartEvent = Omit<BeforeAgentStartEvent, "systemPrompt"> & {
13
12
  systemPrompt: string | string[];
14
13
  };
@@ -202,9 +201,6 @@ export interface TelegramMessageActivityTypingDeps<TContext> {
202
201
  recordRuntimeEvent?: (category: string, error: unknown, details?: Record<string, unknown>) => void;
203
202
  }
204
203
  export declare function createTelegramMessageActivityTypingHooks<TContext extends ExtensionContext>(deps: TelegramMessageActivityTypingDeps<TContext>): Pick<TelegramLifecycleRegistrationDeps, "onMessageStart" | "onMessageUpdate">;
205
- export declare function createDedupAgentStartHook(dedup: {
206
- reset(): void;
207
- }, inner: (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>): (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>;
208
204
  export interface TelegramExtraLifecycleHooks {
209
205
  onSessionStart?: (event: SessionStartEvent, ctx: ExtensionContext) => Promise<void>;
210
206
  onSessionShutdown?: (event: SessionShutdownEvent, ctx: ExtensionContext) => Promise<void>;
@@ -5,53 +5,58 @@
5
5
  * Transport authority, durable bindings, and queue custody remain with their owners.
6
6
  */
7
7
  import { randomUUID } from "node:crypto";
8
- import { formatTelegramConnectionFailure } from "./status.js";
9
8
  import * as BusFollower from "./bus-follower.js";
10
9
  import * as Queue from "./queue.js";
10
+ import { formatTelegramConnectionFailure } from "./status.js";
11
11
  import * as TextGroups from "./text-groups.js";
12
- let resetTransportReplyDedupFn;
13
- export function setResetTransportReplyDedup(fn) {
14
- resetTransportReplyDedupFn = fn;
15
- }
16
- export function createAgentStartDedupHook(inner, schedulePublication) {
12
+ export function createAgentStartDedupHook(inner, resetReplyDedup, schedulePublication) {
17
13
  return async (event, ctx) => {
18
- const reset = resetTransportReplyDedupFn;
19
- if (reset) {
20
- // A new turn must not erase the anchor of a final still ahead in the FIFO.
21
- if (schedulePublication)
22
- schedulePublication(async () => { reset(); });
23
- else
24
- reset();
25
- }
14
+ // A new turn must not erase the anchor of a final still ahead in the FIFO.
15
+ if (schedulePublication)
16
+ schedulePublication(async () => {
17
+ resetReplyDedup();
18
+ });
19
+ else
20
+ resetReplyDedup();
26
21
  return inner(event, ctx);
27
22
  };
28
23
  }
29
24
  const HANDOFF_KEY = Symbol.for("pi-telegram.connection-resume.v1");
30
25
  function processHandoffStore() {
31
26
  const globals = globalThis;
32
- return globals[HANDOFF_KEY] ??= {};
27
+ return (globals[HANDOFF_KEY] ??= {});
33
28
  }
34
29
  export function createTelegramConnectionLifecycle(deps) {
35
30
  return {
36
31
  onSessionShutdown(event, ctx) {
37
- deps.intent.suspend({ reason: event.reason, cwd: ctx.cwd,
38
- targetSessionFile: event.targetSessionFile, connected: deps.isConnected(),
39
- profileName: deps.getProfileName() });
32
+ deps.intent.suspend({
33
+ reason: event.reason,
34
+ cwd: ctx.cwd,
35
+ targetSessionFile: event.targetSessionFile,
36
+ connected: deps.isConnected(),
37
+ profileName: deps.getProfileName(),
38
+ });
40
39
  },
41
40
  prepare(event, ctx) {
42
- const intent = deps.intent.resume({ reason: event.reason, cwd: ctx.cwd,
43
- sessionFile: event.reason === "resume" ? ctx.sessionManager.getSessionFile() : undefined });
41
+ const intent = deps.intent.resume({
42
+ reason: event.reason,
43
+ cwd: ctx.cwd,
44
+ sessionFile: event.reason === "resume"
45
+ ? ctx.sessionManager.getSessionFile()
46
+ : undefined,
47
+ });
44
48
  if (!intent)
45
49
  return undefined;
46
50
  const generation = deps.getGeneration();
47
51
  const isCurrent = () => deps.intent.isActive(intent.id) &&
48
- generation === deps.getGeneration() && deps.isCurrent(ctx);
52
+ generation === deps.getGeneration() &&
53
+ deps.isCurrent(ctx);
49
54
  return () => {
50
55
  // Startup remains extension-owned background work; no captured command ctx crosses resume.
51
56
  void (async () => {
52
57
  if (!isCurrent())
53
58
  return;
54
- if (!await deps.activateProfile(intent.profileName, isCurrent)) {
59
+ if (!(await deps.activateProfile(intent.profileName, isCurrent))) {
55
60
  if (isCurrent())
56
61
  ctx.ui.notify("Telegram profile unavailable. Run /telegram-setup.", "warning");
57
62
  return;
@@ -65,11 +70,13 @@ export function createTelegramConnectionLifecycle(deps) {
65
70
  deps.recordError(new Error(result.message ?? "Telegram resume connection failed."));
66
71
  ctx.ui.notify(formatTelegramConnectionFailure(result.message), "warning");
67
72
  }
68
- })().catch((error) => {
73
+ })()
74
+ .catch((error) => {
69
75
  deps.recordError(error);
70
76
  if (isCurrent())
71
77
  ctx.ui.notify(formatTelegramConnectionFailure(error), "warning");
72
- }).finally(() => deps.intent.finish(intent.id));
78
+ })
79
+ .finally(() => deps.intent.finish(intent.id));
73
80
  };
74
81
  },
75
82
  };
@@ -97,23 +104,38 @@ export function createTelegramConnectionIntentRuntime(options = {}) {
97
104
  store.pending = undefined;
98
105
  },
99
106
  suspend(input) {
100
- const intent = active ?? (input.connected
101
- ? { id: randomUUID(), cwd: input.cwd, profileName: input.profileName }
102
- : undefined);
107
+ const intent = active ??
108
+ (input.connected
109
+ ? { id: randomUUID(), cwd: input.cwd, profileName: input.profileName }
110
+ : undefined);
103
111
  active = undefined;
104
- store.pending = input.reason === "resume" && input.targetSessionFile &&
105
- intent?.cwd === input.cwd
106
- ? { ...intent, pid, targetSessionFile: input.targetSessionFile, expiresAtMs: now() + 30_000 }
107
- : undefined;
112
+ store.pending =
113
+ input.reason === "resume" &&
114
+ input.targetSessionFile &&
115
+ intent?.cwd === input.cwd
116
+ ? {
117
+ ...intent,
118
+ pid,
119
+ targetSessionFile: input.targetSessionFile,
120
+ expiresAtMs: now() + 30_000,
121
+ }
122
+ : undefined;
108
123
  },
109
124
  resume(input) {
110
125
  const handoff = store.pending;
111
126
  store.pending = undefined;
112
- if (!handoff || handoff.pid !== pid || now() >= handoff.expiresAtMs ||
113
- input.reason !== "resume" || input.cwd !== handoff.cwd ||
127
+ if (!handoff ||
128
+ handoff.pid !== pid ||
129
+ now() >= handoff.expiresAtMs ||
130
+ input.reason !== "resume" ||
131
+ input.cwd !== handoff.cwd ||
114
132
  input.sessionFile !== handoff.targetSessionFile)
115
133
  return undefined;
116
- active = { id: randomUUID(), cwd: handoff.cwd, profileName: handoff.profileName };
134
+ active = {
135
+ id: randomUUID(),
136
+ cwd: handoff.cwd,
137
+ profileName: handoff.profileName,
138
+ };
117
139
  return { ...active };
118
140
  },
119
141
  };
@@ -258,10 +280,13 @@ export function createTelegramBridgeSessionLifecycleAssembly(deps) {
258
280
  let preserveThread;
259
281
  if (event.reason === "quit") {
260
282
  try {
261
- preserveThread = deps.services.prepareThreadPreservationOnQuit?.(isCurrent);
283
+ preserveThread =
284
+ deps.services.prepareThreadPreservationOnQuit?.(isCurrent);
262
285
  }
263
286
  catch (error) {
264
- deps.follower.recordRuntimeEvent("session", error, { phase: "preserve-thread-on-quit" });
287
+ deps.follower.recordRuntimeEvent("session", error, {
288
+ phase: "preserve-thread-on-quit",
289
+ });
265
290
  }
266
291
  }
267
292
  deps.services.guestPlaceholder?.stopAll();
@@ -280,7 +305,9 @@ export function createTelegramBridgeSessionLifecycleAssembly(deps) {
280
305
  await preserveThread?.();
281
306
  }
282
307
  catch (error) {
283
- deps.follower.recordRuntimeEvent("session", error, { phase: "preserve-thread-on-quit" });
308
+ deps.follower.recordRuntimeEvent("session", error, {
309
+ phase: "preserve-thread-on-quit",
310
+ });
284
311
  }
285
312
  },
286
313
  };
@@ -316,6 +343,14 @@ export function createTelegramCompactionObserverRuntime(deps) {
316
343
  clearTimer(fallbackTimer);
317
344
  fallbackTimer = undefined;
318
345
  };
346
+ // Stop only a typing loop this observer started; a pre-existing agent-owned loop is preserved.
347
+ const releaseCompactionPresence = (ctx) => {
348
+ deps.setCompactionInProgress(false);
349
+ if (typingStartedByObserver)
350
+ deps.stopTypingLoop?.();
351
+ typingStartedByObserver = false;
352
+ deps.updateStatus(ctx);
353
+ };
319
354
  const requestDispatch = () => {
320
355
  deps.requestDeferredDispatchNextQueuedTelegramTurn(deps.dispatchNextQueuedTelegramTurn);
321
356
  };
@@ -337,11 +372,7 @@ export function createTelegramCompactionObserverRuntime(deps) {
337
372
  fallbackTimer = undefined;
338
373
  if (deps.isContextActive && !deps.isContextActive(ctx))
339
374
  return;
340
- deps.setCompactionInProgress(false);
341
- if (typingStartedByObserver)
342
- deps.stopTypingLoop?.();
343
- typingStartedByObserver = false;
344
- deps.updateStatus(ctx);
375
+ releaseCompactionPresence(ctx);
345
376
  deps.recordRuntimeEvent?.("compact", new Error("Compaction observer timed out"));
346
377
  // Observer expiry releases local presence, not Pi's eventual terminal result.
347
378
  requestDispatch();
@@ -352,22 +383,14 @@ export function createTelegramCompactionObserverRuntime(deps) {
352
383
  if (deps.isContextActive && !deps.isContextActive(ctx))
353
384
  return;
354
385
  clearFallbackTimer();
355
- deps.setCompactionInProgress(false);
356
- if (typingStartedByObserver)
357
- deps.stopTypingLoop?.();
358
- typingStartedByObserver = false;
359
- deps.updateStatus(ctx);
386
+ releaseCompactionPresence(ctx);
360
387
  requestDispatch();
361
388
  },
362
389
  onSessionCompactFailed: (_event, ctx) => {
363
390
  if (deps.isContextActive && !deps.isContextActive(ctx))
364
391
  return;
365
392
  clearFallbackTimer();
366
- deps.setCompactionInProgress(false);
367
- if (typingStartedByObserver)
368
- deps.stopTypingLoop?.();
369
- typingStartedByObserver = false;
370
- deps.updateStatus(ctx);
393
+ releaseCompactionPresence(ctx);
371
394
  deps.onCompactionAbandoned?.();
372
395
  requestDispatch();
373
396
  },
@@ -402,12 +425,6 @@ export function createTelegramMessageActivityTypingHooks(deps) {
402
425
  onMessageUpdate: (event, ctx) => handleMessageActivity("update", event, ctx, deps.onMessageUpdate),
403
426
  };
404
427
  }
405
- export function createDedupAgentStartHook(dedup, inner) {
406
- return async (event, ctx) => {
407
- dedup.reset();
408
- await inner(event, ctx);
409
- };
410
- }
411
428
  export function appendTelegramLifecycleHooks(base, extra, isSessionActive) {
412
429
  return {
413
430
  onSessionStart: async (event, ctx) => {
@@ -84,7 +84,7 @@ export interface TelegramLockRuntime<TContext extends TelegramLockContext> {
84
84
  owns: (ctx?: TelegramLockContext) => boolean;
85
85
  commitIfOwned: (commit: () => void) => boolean;
86
86
  /** Consolidated-store publication; domain reducers retain their own exact payload/CAS rules. */
87
- publishStateSectionIfOwned?: <T>(section: "workspace" | "runtime", mutate: (current: unknown, observed: Readonly<TelegramRuntimeStateProfile>) => TelegramRuntimeStateMutation<T>, options: TelegramOwnedStatePublicationOptions) => TelegramOwnedStatePublicationResult<T>;
87
+ publishStateSectionIfOwned?: <T>(section: "workspace" | "runtime", mutate: TelegramRuntimeStateSectionReducer<T>, options: TelegramOwnedStatePublicationOptions) => TelegramOwnedStatePublicationResult<T>;
88
88
  refresh: (ctx?: TelegramLockContext) => boolean;
89
89
  /** The polling journal named by owners.json for this key, owned or not. */
90
90
  getJournalPath: () => string | undefined;
@@ -135,6 +135,31 @@ interface TelegramRenameRetryOptions {
135
135
  attempts?: number;
136
136
  retryDelayMs?: number;
137
137
  }
138
+ export type TelegramPrivateFileFailure = "capacity" | "unsafe" | "changed";
139
+ /** Typed private-file refusal; owners map the failure into their own error vocabulary. */
140
+ export declare class TelegramPrivateFileError extends Error {
141
+ readonly failure: TelegramPrivateFileFailure;
142
+ constructor(failure: TelegramPrivateFileFailure, message: string);
143
+ }
144
+ /**
145
+ * Read flags for private runtime files. Where the platform offers them, no-follow and non-blocking opens refuse a
146
+ * swapped link or FIFO at open time. Windows has neither flag and no FIFOs in the file namespace; there the
147
+ * lstat-before/fstat-after identity binding every strict reader performs is the guard, so a link swapped in after
148
+ * inspection opens a different file and is refused as changed.
149
+ */
150
+ export declare const TELEGRAM_STRICT_READ_FLAGS: number;
151
+ /** POSIX owner and permission bits; Windows has no uid, so its ACL-protected agent directory carries privacy. */
152
+ export declare function isTelegramOwnerPrivate(stat: {
153
+ uid: bigint;
154
+ mode: bigint;
155
+ }): boolean;
156
+ /**
157
+ * Read one owner-private, single-link, bounded regular file without following links. Absence returns undefined;
158
+ * an inode or metadata change between inspection and open refuses as `changed`.
159
+ */
160
+ export declare function readTelegramPrivateFile(path: string, maxBytes: number): string | undefined;
161
+ /** Atomically publish owner-private contents through a unique staging file; the rename consumes staging. */
162
+ export declare function publishTelegramPrivateFile(path: string, temporaryBasePath: string, contents: string, label: string, onBoundary?: (boundary: "after-write-before-rename" | "after-rename") => void): void;
138
163
  /** Rename one Telegram runtime artifact with bounded Windows sharing retries. */
139
164
  export declare function renameTelegramPathWithRetry(sourcePath: string, destinationPath: string, options?: TelegramRenameRetryOptions): boolean;
140
165
  export interface TelegramFileTransactionOptions {
@@ -162,6 +187,8 @@ export declare function readTelegramRuntimeState(path: string): TelegramRuntimeS
162
187
  * continuity. Filesystem access errors are not damage and still throw. Returns whether a reset was published.
163
188
  */
164
189
  export declare function resetDamagedTelegramRuntimeState(path: string, validateProfile?: (profile: string, sections: Readonly<TelegramRuntimeStateProfile>) => void): boolean;
190
+ /** Pure section reducer: receives the stored section and its profile, returns the next section and result. */
191
+ export type TelegramRuntimeStateSectionReducer<T> = (current: unknown, observed: Readonly<TelegramRuntimeStateProfile>) => TelegramRuntimeStateMutation<T>;
165
192
  export interface TelegramRuntimeStateMutation<T> {
166
193
  value: unknown;
167
194
  result: T;
@@ -183,10 +210,9 @@ export interface TelegramOwnedStatePublicationOptions extends TelegramRuntimeSta
183
210
  * One physical read/check/write transaction for one named section. The caller supplies domain policy; copies expose
184
211
  * current sibling facts without granting writes to them. No await, nested transaction, repair or legacy import.
185
212
  */
186
- export declare function mutateTelegramRuntimeStateSection<T>(path: string, profile: string, section: TelegramRuntimeStateSection, mutate: (current: unknown, observed: Readonly<TelegramRuntimeStateProfile>) => TelegramRuntimeStateMutation<T>, options: TelegramRuntimeStatePublicationOptions): T;
213
+ export declare function mutateTelegramRuntimeStateSection<T>(path: string, profile: string, section: TelegramRuntimeStateSection, mutate: TelegramRuntimeStateSectionReducer<T>, options: TelegramRuntimeStatePublicationOptions): T;
187
214
  export declare function writeLocks(path: string, locks: Record<string, unknown>): void;
188
215
  export declare function parseTelegramLockEntry(value: unknown): TelegramLockEntry | undefined;
189
- export declare function isProcessAlive(pid: number): boolean;
190
216
  export declare function createTelegramLockRuntime<TContext extends TelegramLockContext>(options?: TelegramLockRuntimeOptions): TelegramLockRuntime<TContext>;
191
217
  export declare function createTelegramLockOwnershipGuard<TContext extends TelegramLockContext>(lock: TelegramLockRuntime<TContext>): TelegramLockOwnershipGuard<TContext>;
192
218
  export declare function createTelegramDirectDeliveryOwnershipChecker<TContext extends TelegramLockContext>(deps: {
@@ -215,6 +241,11 @@ type TelegramLockedPollingStartResult = {
215
241
  export interface TelegramLockedPollingRuntime<TContext extends TelegramLockContext> {
216
242
  start: (ctx: TContext, options?: TelegramLockedPollingStartOptions) => Promise<TelegramLockedPollingStartResult>;
217
243
  stop: () => Promise<string>;
244
+ /** Capture one disconnect attempt before cleanup awaits; a newer start revokes it. */
245
+ captureStop: () => {
246
+ isCurrent: () => boolean;
247
+ stop: () => Promise<string>;
248
+ };
218
249
  suspend: () => Promise<void>;
219
250
  isSuspended: () => boolean;
220
251
  /** Fence one owned polling generation; suspension, restart, conflict or lock loss revokes it. */