@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,9 +5,7 @@
5
5
  */
6
6
 
7
7
  export type TelegramInlineKeyboardButtonStyle =
8
- | "danger"
9
- | "success"
10
- | "primary";
8
+ "danger" | "success" | "primary";
11
9
 
12
10
  export type TelegramInlineKeyboardButton = {
13
11
  text: string;
@@ -6,10 +6,8 @@
6
6
  */
7
7
 
8
8
  import { randomUUID } from "node:crypto";
9
- import { formatTelegramConnectionFailure } from "./status.ts";
9
+
10
10
  import * as BusFollower from "./bus-follower.ts";
11
- import * as Queue from "./queue.ts";
12
- import * as TextGroups from "./text-groups.ts";
13
11
  import type {
14
12
  AgentEndEvent,
15
13
  AgentSettledEvent,
@@ -31,24 +29,22 @@ import type {
31
29
  UIPromptEndEvent,
32
30
  UIPromptStartEvent,
33
31
  } from "./pi.ts";
34
-
35
- let resetTransportReplyDedupFn: (() => void) | undefined;
36
-
37
- export function setResetTransportReplyDedup(fn: () => void): void {
38
- resetTransportReplyDedupFn = fn;
39
- }
32
+ import * as Queue from "./queue.ts";
33
+ import { formatTelegramConnectionFailure } from "./status.ts";
34
+ import * as TextGroups from "./text-groups.ts";
40
35
 
41
36
  export function createAgentStartDedupHook(
42
37
  inner: (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>,
38
+ resetReplyDedup: () => void,
43
39
  schedulePublication?: (task: () => Promise<void>) => void,
44
40
  ): (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void> {
45
41
  return async (event, ctx) => {
46
- const reset = resetTransportReplyDedupFn;
47
- if (reset) {
48
- // A new turn must not erase the anchor of a final still ahead in the FIFO.
49
- if (schedulePublication) schedulePublication(async () => { reset(); });
50
- else reset();
51
- }
42
+ // A new turn must not erase the anchor of a final still ahead in the FIFO.
43
+ if (schedulePublication)
44
+ schedulePublication(async () => {
45
+ resetReplyDedup();
46
+ });
47
+ else resetReplyDedup();
52
48
  return inner(event, ctx);
53
49
  };
54
50
  }
@@ -175,12 +171,18 @@ export interface TelegramConnectionHandoffStore {
175
171
  }
176
172
  const HANDOFF_KEY = Symbol.for("pi-telegram.connection-resume.v1");
177
173
  function processHandoffStore(): TelegramConnectionHandoffStore {
178
- const globals = globalThis as unknown as Record<symbol, TelegramConnectionHandoffStore>;
179
- return globals[HANDOFF_KEY] ??= {};
174
+ const globals = globalThis as unknown as Record<
175
+ symbol,
176
+ TelegramConnectionHandoffStore
177
+ >;
178
+ return (globals[HANDOFF_KEY] ??= {});
180
179
  }
181
180
 
182
181
  export interface TelegramConnectionLifecycle {
183
- prepare(event: SessionStartEvent, ctx: ExtensionContext): (() => void) | undefined;
182
+ prepare(
183
+ event: SessionStartEvent,
184
+ ctx: ExtensionContext,
185
+ ): (() => void) | undefined;
184
186
  onSessionShutdown(event: SessionShutdownEvent, ctx: ExtensionContext): void;
185
187
  }
186
188
 
@@ -190,52 +192,81 @@ export function createTelegramConnectionLifecycle(deps: {
190
192
  isCurrent(ctx: ExtensionContext): boolean;
191
193
  getProfileName(): string | undefined;
192
194
  isConnected(): boolean;
193
- activateProfile(profileName: string | undefined, isCurrent: () => boolean): Promise<boolean>;
195
+ activateProfile(
196
+ profileName: string | undefined,
197
+ isCurrent: () => boolean,
198
+ ): Promise<boolean>;
194
199
  start(ctx: ExtensionContext): Promise<{ ok: boolean; message?: string }>;
195
200
  recordError(error: unknown): void;
196
201
  }): TelegramConnectionLifecycle {
197
202
  return {
198
203
  onSessionShutdown(event, ctx) {
199
- deps.intent.suspend({ reason: event.reason, cwd: ctx.cwd,
200
- targetSessionFile: event.targetSessionFile, connected: deps.isConnected(),
201
- profileName: deps.getProfileName() });
204
+ deps.intent.suspend({
205
+ reason: event.reason,
206
+ cwd: ctx.cwd,
207
+ targetSessionFile: event.targetSessionFile,
208
+ connected: deps.isConnected(),
209
+ profileName: deps.getProfileName(),
210
+ });
202
211
  },
203
212
  prepare(event, ctx) {
204
- const intent = deps.intent.resume({ reason: event.reason, cwd: ctx.cwd,
205
- sessionFile: event.reason === "resume" ? ctx.sessionManager.getSessionFile() : undefined });
213
+ const intent = deps.intent.resume({
214
+ reason: event.reason,
215
+ cwd: ctx.cwd,
216
+ sessionFile:
217
+ event.reason === "resume"
218
+ ? ctx.sessionManager.getSessionFile()
219
+ : undefined,
220
+ });
206
221
  if (!intent) return undefined;
207
222
  const generation = deps.getGeneration();
208
- const isCurrent = () => deps.intent.isActive(intent.id) &&
209
- generation === deps.getGeneration() && deps.isCurrent(ctx);
223
+ const isCurrent = () =>
224
+ deps.intent.isActive(intent.id) &&
225
+ generation === deps.getGeneration() &&
226
+ deps.isCurrent(ctx);
210
227
  return () => {
211
228
  // Startup remains extension-owned background work; no captured command ctx crosses resume.
212
229
  void (async () => {
213
230
  if (!isCurrent()) return;
214
- if (!await deps.activateProfile(intent.profileName, isCurrent)) {
215
- if (isCurrent()) ctx.ui.notify("Telegram profile unavailable. Run /telegram-setup.", "warning");
231
+ if (!(await deps.activateProfile(intent.profileName, isCurrent))) {
232
+ if (isCurrent())
233
+ ctx.ui.notify(
234
+ "Telegram profile unavailable. Run /telegram-setup.",
235
+ "warning",
236
+ );
216
237
  return;
217
238
  }
218
239
  if (!isCurrent()) return;
219
240
  const result = await deps.start(ctx);
220
241
  if (!isCurrent()) return;
221
242
  if (!result.ok) {
222
- deps.recordError(new Error(result.message ?? "Telegram resume connection failed."));
223
- ctx.ui.notify(formatTelegramConnectionFailure(result.message), "warning");
243
+ deps.recordError(
244
+ new Error(result.message ?? "Telegram resume connection failed."),
245
+ );
246
+ ctx.ui.notify(
247
+ formatTelegramConnectionFailure(result.message),
248
+ "warning",
249
+ );
224
250
  }
225
- })().catch((error) => {
226
- deps.recordError(error);
227
- if (isCurrent()) ctx.ui.notify(formatTelegramConnectionFailure(error), "warning");
228
- }).finally(() => deps.intent.finish(intent.id));
251
+ })()
252
+ .catch((error) => {
253
+ deps.recordError(error);
254
+ if (isCurrent())
255
+ ctx.ui.notify(formatTelegramConnectionFailure(error), "warning");
256
+ })
257
+ .finally(() => deps.intent.finish(intent.id));
229
258
  };
230
259
  },
231
260
  };
232
261
  }
233
262
 
234
- export function createTelegramConnectionIntentRuntime(options: {
235
- store?: TelegramConnectionHandoffStore;
236
- now?: () => number;
237
- pid?: number;
238
- } = {}) {
263
+ export function createTelegramConnectionIntentRuntime(
264
+ options: {
265
+ store?: TelegramConnectionHandoffStore;
266
+ now?: () => number;
267
+ pid?: number;
268
+ } = {},
269
+ ) {
239
270
  const store = options.store ?? processHandoffStore();
240
271
  const now = options.now ?? Date.now;
241
272
  const pid = options.pid ?? process.pid;
@@ -263,22 +294,45 @@ export function createTelegramConnectionIntentRuntime(options: {
263
294
  connected: boolean;
264
295
  profileName?: string;
265
296
  }): void {
266
- const intent = active ?? (input.connected
267
- ? { id: randomUUID(), cwd: input.cwd, profileName: input.profileName }
268
- : undefined);
297
+ const intent =
298
+ active ??
299
+ (input.connected
300
+ ? { id: randomUUID(), cwd: input.cwd, profileName: input.profileName }
301
+ : undefined);
269
302
  active = undefined;
270
- store.pending = input.reason === "resume" && input.targetSessionFile &&
271
- intent?.cwd === input.cwd
272
- ? { ...intent, pid, targetSessionFile: input.targetSessionFile, expiresAtMs: now() + 30_000 }
273
- : undefined;
303
+ store.pending =
304
+ input.reason === "resume" &&
305
+ input.targetSessionFile &&
306
+ intent?.cwd === input.cwd
307
+ ? {
308
+ ...intent,
309
+ pid,
310
+ targetSessionFile: input.targetSessionFile,
311
+ expiresAtMs: now() + 30_000,
312
+ }
313
+ : undefined;
274
314
  },
275
- resume(input: { reason: string; cwd: string; sessionFile?: string }): TelegramConnectionIntent | undefined {
315
+ resume(input: {
316
+ reason: string;
317
+ cwd: string;
318
+ sessionFile?: string;
319
+ }): TelegramConnectionIntent | undefined {
276
320
  const handoff = store.pending;
277
321
  store.pending = undefined;
278
- if (!handoff || handoff.pid !== pid || now() >= handoff.expiresAtMs ||
279
- input.reason !== "resume" || input.cwd !== handoff.cwd ||
280
- input.sessionFile !== handoff.targetSessionFile) return undefined;
281
- active = { id: randomUUID(), cwd: handoff.cwd, profileName: handoff.profileName };
322
+ if (
323
+ !handoff ||
324
+ handoff.pid !== pid ||
325
+ now() >= handoff.expiresAtMs ||
326
+ input.reason !== "resume" ||
327
+ input.cwd !== handoff.cwd ||
328
+ input.sessionFile !== handoff.targetSessionFile
329
+ )
330
+ return undefined;
331
+ active = {
332
+ id: randomUUID(),
333
+ cwd: handoff.cwd,
334
+ profileName: handoff.profileName,
335
+ };
282
336
  return { ...active };
283
337
  },
284
338
  };
@@ -394,7 +448,9 @@ export interface TelegramBridgeSessionServiceRuntime {
394
448
  capabilityMonitor: { start(ctx: ExtensionContext): void; stop(): void };
395
449
  queueWatchdog: { start(ctx: ExtensionContext): void; stop(): void };
396
450
  guestPlaceholder?: { stopAll(): void };
397
- prepareThreadPreservationOnQuit?: (isSessionCurrent: () => boolean) => (() => Promise<void>) | undefined;
451
+ prepareThreadPreservationOnQuit?: (
452
+ isSessionCurrent: () => boolean,
453
+ ) => (() => Promise<void>) | undefined;
398
454
  }
399
455
 
400
456
  export interface TelegramBridgeSessionLifecycleAssemblyDeps<
@@ -482,7 +538,8 @@ export function createTelegramBridgeSessionLifecycleDeps<
482
538
  capabilityMonitor: ports.services.capabilityMonitor,
483
539
  queueWatchdog: ports.services.queueWatchdog,
484
540
  guestPlaceholder: ports.services.guestPlaceholder,
485
- prepareThreadPreservationOnQuit: ports.services.prepareThreadPreservationOnQuit,
541
+ prepareThreadPreservationOnQuit:
542
+ ports.services.prepareThreadPreservationOnQuit,
486
543
  },
487
544
  };
488
545
  }
@@ -530,9 +587,12 @@ export function createTelegramBridgeSessionLifecycleAssembly<
530
587
  let preserveThread: (() => Promise<void>) | undefined;
531
588
  if (event.reason === "quit") {
532
589
  try {
533
- preserveThread = deps.services.prepareThreadPreservationOnQuit?.(isCurrent);
590
+ preserveThread =
591
+ deps.services.prepareThreadPreservationOnQuit?.(isCurrent);
534
592
  } catch (error) {
535
- deps.follower.recordRuntimeEvent("session", error, { phase: "preserve-thread-on-quit" });
593
+ deps.follower.recordRuntimeEvent("session", error, {
594
+ phase: "preserve-thread-on-quit",
595
+ });
536
596
  }
537
597
  }
538
598
  deps.services.guestPlaceholder?.stopAll();
@@ -547,7 +607,9 @@ export function createTelegramBridgeSessionLifecycleAssembly<
547
607
  try {
548
608
  await preserveThread?.();
549
609
  } catch (error) {
550
- deps.follower.recordRuntimeEvent("session", error, { phase: "preserve-thread-on-quit" });
610
+ deps.follower.recordRuntimeEvent("session", error, {
611
+ phase: "preserve-thread-on-quit",
612
+ });
551
613
  }
552
614
  },
553
615
  };
@@ -623,6 +685,13 @@ export function createTelegramCompactionObserverRuntime<TContext>(
623
685
  clearTimer(fallbackTimer);
624
686
  fallbackTimer = undefined;
625
687
  };
688
+ // Stop only a typing loop this observer started; a pre-existing agent-owned loop is preserved.
689
+ const releaseCompactionPresence = (ctx: TContext): void => {
690
+ deps.setCompactionInProgress(false);
691
+ if (typingStartedByObserver) deps.stopTypingLoop?.();
692
+ typingStartedByObserver = false;
693
+ deps.updateStatus(ctx);
694
+ };
626
695
  const requestDispatch = (): void => {
627
696
  deps.requestDeferredDispatchNextQueuedTelegramTurn(
628
697
  deps.dispatchNextQueuedTelegramTurn,
@@ -643,10 +712,7 @@ export function createTelegramCompactionObserverRuntime<TContext>(
643
712
  observationGeneration += 1;
644
713
  fallbackTimer = undefined;
645
714
  if (deps.isContextActive && !deps.isContextActive(ctx)) return;
646
- deps.setCompactionInProgress(false);
647
- if (typingStartedByObserver) deps.stopTypingLoop?.();
648
- typingStartedByObserver = false;
649
- deps.updateStatus(ctx);
715
+ releaseCompactionPresence(ctx);
650
716
  deps.recordRuntimeEvent?.(
651
717
  "compact",
652
718
  new Error("Compaction observer timed out"),
@@ -659,19 +725,13 @@ export function createTelegramCompactionObserverRuntime<TContext>(
659
725
  onSessionCompact: (_event, ctx) => {
660
726
  if (deps.isContextActive && !deps.isContextActive(ctx)) return;
661
727
  clearFallbackTimer();
662
- deps.setCompactionInProgress(false);
663
- if (typingStartedByObserver) deps.stopTypingLoop?.();
664
- typingStartedByObserver = false;
665
- deps.updateStatus(ctx);
728
+ releaseCompactionPresence(ctx);
666
729
  requestDispatch();
667
730
  },
668
731
  onSessionCompactFailed: (_event, ctx) => {
669
732
  if (deps.isContextActive && !deps.isContextActive(ctx)) return;
670
733
  clearFallbackTimer();
671
- deps.setCompactionInProgress(false);
672
- if (typingStartedByObserver) deps.stopTypingLoop?.();
673
- typingStartedByObserver = false;
674
- deps.updateStatus(ctx);
734
+ releaseCompactionPresence(ctx);
675
735
  deps.onCompactionAbandoned?.();
676
736
  requestDispatch();
677
737
  },
@@ -730,16 +790,6 @@ export function createTelegramMessageActivityTypingHooks<
730
790
  };
731
791
  }
732
792
 
733
- export function createDedupAgentStartHook(
734
- dedup: { reset(): void },
735
- inner: (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void>,
736
- ): (event: AgentStartEvent, ctx: ExtensionContext) => Promise<void> {
737
- return async (event, ctx) => {
738
- dedup.reset();
739
- await inner(event, ctx);
740
- };
741
- }
742
-
743
793
  export interface TelegramExtraLifecycleHooks {
744
794
  onSessionStart?: (
745
795
  event: SessionStartEvent,