@llblab/pi-telegram 0.46.0 → 0.47.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 (199) hide show
  1. package/BACKLOG.md +0 -1
  2. package/CHANGELOG.md +8 -0
  3. package/README.md +2 -2
  4. package/dist/api/activity.d.ts +6 -0
  5. package/dist/api/activity.js +6 -0
  6. package/dist/api/commands.d.ts +6 -0
  7. package/dist/api/commands.js +6 -0
  8. package/dist/api/delivery.d.ts +6 -0
  9. package/dist/api/delivery.js +6 -0
  10. package/dist/api/inbound.d.ts +6 -0
  11. package/dist/api/inbound.js +6 -0
  12. package/dist/api/keyboard.d.ts +6 -0
  13. package/dist/api/keyboard.js +6 -0
  14. package/dist/api/outbound.d.ts +6 -0
  15. package/dist/api/outbound.js +6 -0
  16. package/dist/api/sections.d.ts +7 -0
  17. package/dist/api/sections.js +6 -0
  18. package/dist/api/status.d.ts +6 -0
  19. package/dist/api/status.js +6 -0
  20. package/dist/api/updates.d.ts +6 -0
  21. package/dist/api/updates.js +6 -0
  22. package/dist/api/voice.d.ts +6 -0
  23. package/dist/api/voice.js +6 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.js +6 -0
  26. package/dist/lib/activity-verbosity.d.ts +52 -0
  27. package/dist/lib/activity-verbosity.js +596 -0
  28. package/dist/lib/activity.d.ts +220 -0
  29. package/dist/lib/activity.js +574 -0
  30. package/dist/lib/agent-messages.d.ts +28 -0
  31. package/dist/lib/agent-messages.js +86 -0
  32. package/dist/lib/bindings.d.ts +250 -0
  33. package/dist/lib/bindings.js +936 -0
  34. package/dist/lib/bus-api.d.ts +18 -0
  35. package/dist/lib/bus-api.js +254 -0
  36. package/dist/lib/bus-follower.d.ts +464 -0
  37. package/dist/lib/bus-follower.js +1686 -0
  38. package/dist/lib/bus-leader.d.ts +292 -0
  39. package/dist/lib/bus-leader.js +2242 -0
  40. package/dist/lib/bus-transport.d.ts +64 -0
  41. package/dist/lib/bus-transport.js +140 -0
  42. package/dist/lib/bus.d.ts +518 -0
  43. package/dist/lib/bus.js +2055 -0
  44. package/dist/lib/channel-posts.d.ts +170 -0
  45. package/dist/lib/channel-posts.js +611 -0
  46. package/dist/lib/command-templates.d.ts +70 -0
  47. package/dist/lib/command-templates.js +744 -0
  48. package/dist/lib/commands.d.ts +541 -0
  49. package/dist/lib/commands.js +1155 -0
  50. package/dist/lib/config.d.ts +252 -0
  51. package/dist/lib/config.js +889 -0
  52. package/dist/lib/delivery.d.ts +163 -0
  53. package/dist/lib/delivery.js +542 -0
  54. package/dist/lib/extension.d.ts +7 -0
  55. package/dist/lib/extension.js +1608 -0
  56. package/dist/lib/generative-app-worker.mjs +104 -0
  57. package/dist/lib/generative-apps.d.ts +212 -0
  58. package/dist/lib/generative-apps.js +1006 -0
  59. package/dist/lib/inbound.d.ts +91 -0
  60. package/dist/lib/inbound.js +502 -0
  61. package/dist/lib/journal.d.ts +665 -0
  62. package/dist/lib/journal.js +3701 -0
  63. package/dist/lib/keyboard.d.ts +23 -0
  64. package/dist/lib/keyboard.js +37 -0
  65. package/dist/lib/lifecycle.d.ts +157 -0
  66. package/dist/lib/lifecycle.js +395 -0
  67. package/dist/lib/locks.d.ts +164 -0
  68. package/dist/lib/locks.js +1208 -0
  69. package/dist/lib/logging.d.ts +50 -0
  70. package/dist/lib/logging.js +274 -0
  71. package/dist/lib/media.d.ts +181 -0
  72. package/dist/lib/media.js +602 -0
  73. package/dist/lib/menu-model.d.ts +217 -0
  74. package/dist/lib/menu-model.js +663 -0
  75. package/dist/lib/menu-queue.d.ts +37 -0
  76. package/dist/lib/menu-queue.js +408 -0
  77. package/dist/lib/menu-settings.d.ts +116 -0
  78. package/dist/lib/menu-settings.js +595 -0
  79. package/dist/lib/menu-status.d.ts +32 -0
  80. package/dist/lib/menu-status.js +112 -0
  81. package/dist/lib/menu-thinking.d.ts +29 -0
  82. package/dist/lib/menu-thinking.js +82 -0
  83. package/dist/lib/menu.d.ts +171 -0
  84. package/dist/lib/menu.js +323 -0
  85. package/dist/lib/model.d.ts +127 -0
  86. package/dist/lib/model.js +409 -0
  87. package/dist/lib/outbound-attachments.d.ts +241 -0
  88. package/dist/lib/outbound-attachments.js +639 -0
  89. package/dist/lib/outbound-buttons.d.ts +69 -0
  90. package/dist/lib/outbound-buttons.js +248 -0
  91. package/dist/lib/outbound-markup.d.ts +42 -0
  92. package/dist/lib/outbound-markup.js +678 -0
  93. package/dist/lib/outbound-voice.d.ts +55 -0
  94. package/dist/lib/outbound-voice.js +152 -0
  95. package/dist/lib/outbound.d.ts +185 -0
  96. package/dist/lib/outbound.js +516 -0
  97. package/dist/lib/ownership.d.ts +77 -0
  98. package/dist/lib/ownership.js +174 -0
  99. package/dist/lib/paths.d.ts +40 -0
  100. package/dist/lib/paths.js +94 -0
  101. package/dist/lib/pi.d.ts +72 -0
  102. package/dist/lib/pi.js +121 -0
  103. package/dist/lib/polling.d.ts +351 -0
  104. package/dist/lib/polling.js +1196 -0
  105. package/dist/lib/preview.d.ts +192 -0
  106. package/dist/lib/preview.js +614 -0
  107. package/dist/lib/prompt-templates.d.ts +24 -0
  108. package/dist/lib/prompt-templates.js +118 -0
  109. package/dist/lib/prompts.d.ts +57 -0
  110. package/dist/lib/prompts.js +167 -0
  111. package/dist/lib/queue.d.ts +766 -0
  112. package/dist/lib/queue.js +1965 -0
  113. package/dist/lib/recovery.d.ts +86 -0
  114. package/dist/lib/recovery.js +285 -0
  115. package/dist/lib/rendering.d.ts +20 -0
  116. package/dist/lib/rendering.js +983 -0
  117. package/dist/lib/replies.d.ts +214 -0
  118. package/dist/lib/replies.js +737 -0
  119. package/dist/lib/routing.d.ts +207 -0
  120. package/dist/lib/routing.js +2282 -0
  121. package/dist/lib/runtime.d.ts +172 -0
  122. package/dist/lib/runtime.js +402 -0
  123. package/dist/lib/sections.d.ts +165 -0
  124. package/dist/lib/sections.js +327 -0
  125. package/dist/lib/setup.d.ts +82 -0
  126. package/dist/lib/setup.js +150 -0
  127. package/dist/lib/skills.d.ts +8 -0
  128. package/dist/lib/skills.js +12 -0
  129. package/dist/lib/status.d.ts +442 -0
  130. package/dist/lib/status.js +1006 -0
  131. package/dist/lib/sync.d.ts +179 -0
  132. package/dist/lib/sync.js +782 -0
  133. package/dist/lib/target.d.ts +20 -0
  134. package/dist/lib/target.js +27 -0
  135. package/dist/lib/telegram-api.d.ts +541 -0
  136. package/dist/lib/telegram-api.js +1159 -0
  137. package/dist/lib/text-groups.d.ts +89 -0
  138. package/dist/lib/text-groups.js +317 -0
  139. package/dist/lib/thread-cleanup-manager.d.ts +288 -0
  140. package/dist/lib/thread-cleanup-manager.js +560 -0
  141. package/dist/lib/thread-display.d.ts +46 -0
  142. package/dist/lib/thread-display.js +257 -0
  143. package/dist/lib/thread-naming.d.ts +46 -0
  144. package/dist/lib/thread-naming.js +78 -0
  145. package/dist/lib/thread-reconciler.d.ts +239 -0
  146. package/dist/lib/thread-reconciler.js +644 -0
  147. package/dist/lib/threads.d.ts +621 -0
  148. package/dist/lib/threads.js +3679 -0
  149. package/dist/lib/time-injection.d.ts +15 -0
  150. package/dist/lib/time-injection.js +56 -0
  151. package/dist/lib/turns.d.ts +109 -0
  152. package/dist/lib/turns.js +500 -0
  153. package/dist/lib/updates.d.ts +1290 -0
  154. package/dist/lib/updates.js +3634 -0
  155. package/dist/lib/voice.d.ts +117 -0
  156. package/dist/lib/voice.js +174 -0
  157. package/dist/lib/workspace-admission.d.ts +264 -0
  158. package/dist/lib/workspace-admission.js +1136 -0
  159. package/dist/lib/workspace-retirement.d.ts +219 -0
  160. package/dist/lib/workspace-retirement.js +587 -0
  161. package/dist/lib/workspace-slots.d.ts +30 -0
  162. package/dist/lib/workspace-slots.js +54 -0
  163. package/dist/package.json +126 -0
  164. package/dist/pi-telegram/index.js +1 -0
  165. package/dist/skills/generated-control-surface/SKILL.md +107 -0
  166. package/dist/skills/generated-control-surface/references/capability-adapters.md +27 -0
  167. package/dist/skills/generated-control-surface/references/layout-and-state.md +37 -0
  168. package/dist/skills/generative-apps/SKILL.md +115 -0
  169. package/dist/skills/show-me/SKILL.md +166 -0
  170. package/dist/skills/show-me/references/telegram-surfaces.md +43 -0
  171. package/dist/skills/telegram-bridge/SKILL.md +129 -0
  172. package/dist/skills/telegram-bridge/references/configuration.md +15 -0
  173. package/dist/skills/telegram-bridge/references/delivery-and-threads.md +27 -0
  174. package/dist/skills/telegram-bridge/references/diagnosis.md +18 -0
  175. package/docs/architecture.md +1 -1
  176. package/docs/compact-matrix-literal.md +10 -3
  177. package/docs/generative-apps.md +15 -13
  178. package/docs/multi-instance-bus.md +4 -2
  179. package/docs/outbound.md +1 -1
  180. package/docs/public-api.md +2 -2
  181. package/lib/bindings.ts +89 -6
  182. package/lib/bus-follower.ts +7 -3
  183. package/lib/bus-leader.ts +44 -19
  184. package/lib/bus.ts +4 -1
  185. package/lib/commands.ts +2 -2
  186. package/lib/config.ts +14 -7
  187. package/lib/delivery.ts +38 -6
  188. package/lib/extension.ts +19 -0
  189. package/lib/generative-apps.ts +379 -13
  190. package/lib/menu-settings.ts +21 -5
  191. package/lib/outbound-markup.ts +16 -7
  192. package/lib/telegram-api.ts +12 -1
  193. package/lib/thread-display.ts +96 -18
  194. package/package.json +56 -13
  195. package/scripts/build-dist.mjs +44 -0
  196. package/scripts/measure-bus.mjs +8 -1
  197. package/scripts/measure-workspace.mjs +8 -1
  198. package/skills/generative-apps/SKILL.md +1 -1
  199. package/skills/telegram-bridge/SKILL.md +1 -1
@@ -0,0 +1,1290 @@
1
+ /**
2
+ * Telegram updates domain helpers
3
+ * Zones: telegram inbound, authorization, routing plans
4
+ * Owns update extraction, authorization, execution planning, generation-fenced journal draining, and the public update-handler registry
5
+ */
6
+ import { type TelegramTarget } from "./target.ts";
7
+ import type { TelegramBusEnvelope, TelegramBusFollowerView, TelegramBusForwardOwnership, TelegramBusForeignUpdateSettlement, TelegramProcessLiveness } from "./bus.ts";
8
+ import type { TelegramMessageOwnershipStore } from "./ownership.ts";
9
+ import { TELEGRAM_UPDATE_JOURNAL_VERSION, TELEGRAM_UPDATE_JOURNAL_EXCLUSION_VERSION, TELEGRAM_UPDATE_JOURNAL_CUSTODY_VERSION, type TelegramInputJournalReceipt, type TelegramInputJournalSourceReference, type TelegramInputJournalStore, type TelegramJournaledUpdate, type TelegramUpdateJournalDeadQueueOwnerRecoveryResult, type TelegramUpdateJournalAppendResult, type TelegramUpdateJournalInputClaim, type TelegramUpdateJournalOperatorDispositionInput, type TelegramUpdateJournalOperatorDispositionResult, type TelegramUpdateJournalQueueDiscardResult, type TelegramUpdateJournalQueueHandoffAcceptResult, type TelegramUpdateJournalQueueHandoffCancelResult, type TelegramUpdateJournalQueueHandoffInput, type TelegramUpdateJournalQueueHandoffOfferResult, type TelegramUpdateJournalQueueOwner, type TelegramUpdateJournalQueueOwnerIdentity } from "./journal.ts";
10
+ import { type PendingTelegramControlItem, type TelegramControlQueueHandoffPayload, type TelegramQueueAdmissionReceipt, type TelegramQueueHandoffPayload, type TelegramQueueHandoffStageResult, type TelegramQueueReactionDisposition, type TelegramQueueHandoffStagingRuntime, type TelegramQueueItem } from "./queue.ts";
11
+ import { type TelegramAuthorizationState, type TelegramUserPairingRuntimeDeps } from "./config.ts";
12
+ export interface TelegramReactionTypeEmoji {
13
+ type: "emoji";
14
+ emoji: string;
15
+ }
16
+ export interface TelegramReactionTypeNonEmoji {
17
+ type: string;
18
+ }
19
+ export type TelegramReactionType = TelegramReactionTypeEmoji | TelegramReactionTypeNonEmoji;
20
+ export declare const TELEGRAM_PRIORITY_REACTIONS: readonly [{
21
+ readonly id: 10;
22
+ readonly name: "like";
23
+ readonly emoji: "👍";
24
+ }, {
25
+ readonly id: 11;
26
+ readonly name: "lightning";
27
+ readonly emoji: "⚡";
28
+ }, {
29
+ readonly id: 12;
30
+ readonly name: "heart";
31
+ readonly emoji: "❤";
32
+ }, {
33
+ readonly id: 13;
34
+ readonly name: "dove";
35
+ readonly emoji: "🕊";
36
+ }, {
37
+ readonly id: 14;
38
+ readonly name: "fire";
39
+ readonly emoji: "🔥";
40
+ }];
41
+ export declare const TELEGRAM_REMOVAL_REACTIONS: readonly [{
42
+ readonly id: 20;
43
+ readonly name: "dislike";
44
+ readonly emoji: "👎";
45
+ }, {
46
+ readonly id: 21;
47
+ readonly name: "ghost";
48
+ readonly emoji: "👻";
49
+ }, {
50
+ readonly id: 22;
51
+ readonly name: "broken-heart";
52
+ readonly emoji: "💔";
53
+ }, {
54
+ readonly id: 23;
55
+ readonly name: "poop";
56
+ readonly emoji: "💩";
57
+ }, {
58
+ readonly id: 24;
59
+ readonly name: "wastebasket";
60
+ readonly emoji: "🗑";
61
+ }];
62
+ export declare const TELEGRAM_PRIORITY_REACTION_EMOJIS: ("👍" | "⚡" | "❤" | "🕊" | "🔥")[];
63
+ export declare const TELEGRAM_REMOVAL_REACTION_EMOJIS: ("👎" | "👻" | "💔" | "💩" | "🗑")[];
64
+ export interface TelegramUpdateDeletion {
65
+ deleted_business_messages?: {
66
+ message_ids?: unknown;
67
+ };
68
+ }
69
+ export declare function normalizeTelegramReactionEmoji(emoji: string): string;
70
+ export declare function collectTelegramReactionEmojis(reactions: TelegramReactionType[]): Set<string>;
71
+ export declare function getTelegramQueueReactionDisposition(reactions: TelegramReactionType[]): TelegramQueueReactionDisposition;
72
+ export declare function extractDeletedTelegramMessageIds(update: TelegramUpdateDeletion): number[];
73
+ export interface TelegramUser {
74
+ id: number;
75
+ is_bot: boolean;
76
+ }
77
+ export interface TelegramChat {
78
+ id?: number;
79
+ type: string;
80
+ }
81
+ export interface TelegramUpdateMessage {
82
+ chat: TelegramChat;
83
+ from?: TelegramUser;
84
+ message_id?: number;
85
+ message_thread_id?: number;
86
+ pi_telegram_agent_source_thread?: string;
87
+ forum_topic_created?: unknown;
88
+ forum_topic_closed?: unknown;
89
+ forum_topic_reopened?: unknown;
90
+ }
91
+ export type TelegramTopicLifecycleKind = "created" | "closed" | "reopened";
92
+ export interface TelegramTopicLifecycleUpdate<TMessage = TelegramUpdateMessage> {
93
+ kind: TelegramTopicLifecycleKind;
94
+ message: TMessage;
95
+ target: TelegramTarget & {
96
+ threadId: number;
97
+ };
98
+ }
99
+ export declare function getTelegramTopicLifecycleUpdate<TMessage extends TelegramUpdateMessage>(message: TMessage | undefined): TelegramTopicLifecycleUpdate<TMessage> | undefined;
100
+ export interface TelegramCallbackQuery {
101
+ id?: string;
102
+ from: TelegramUser;
103
+ message?: TelegramUpdateMessage;
104
+ }
105
+ export interface TelegramGuestMessage {
106
+ guest_query_id: string;
107
+ chat: TelegramChat;
108
+ from?: TelegramUser;
109
+ message_id?: number;
110
+ text?: string;
111
+ reply_to_message?: TelegramUpdateMessage;
112
+ }
113
+ export declare function getTelegramMessageTarget(message: TelegramUpdateMessage): TelegramTarget | undefined;
114
+ export interface TelegramUpdateRouting {
115
+ message?: TelegramUpdateMessage;
116
+ edited_message?: TelegramUpdateMessage;
117
+ callback_query?: TelegramCallbackQuery;
118
+ guest_message?: TelegramGuestMessage;
119
+ }
120
+ export declare function getAuthorizedTelegramCallbackQuery(update: TelegramUpdateRouting, allowedUserId?: number): TelegramCallbackQuery | undefined;
121
+ export declare function getAuthorizedTelegramMessage(update: TelegramUpdateRouting, allowedUserId?: number): TelegramUpdateMessage | undefined;
122
+ export declare function getAuthorizedTelegramEditedMessage(update: TelegramUpdateRouting, allowedUserId?: number): TelegramUpdateMessage | undefined;
123
+ export declare function getAuthorizedTelegramGuestMessage(update: TelegramUpdateRouting): TelegramGuestMessage | undefined;
124
+ export type TelegramMessageOwnershipView = TelegramBusForwardOwnership;
125
+ export type TelegramMessageOwnershipLookup = (chatId: number, messageId: number) => TelegramMessageOwnershipView | undefined;
126
+ export type TelegramTargetOwnershipView = TelegramBusForwardOwnership;
127
+ export type TelegramTargetOwnershipLookup = (target: TelegramTarget) => TelegramTargetOwnershipView | undefined;
128
+ export interface TelegramForeignOwnedUpdateForwarder<TContext, TReactionUpdate extends TelegramMessageReactionUpdated = TelegramMessageReactionUpdated, TCallbackQuery extends TelegramCallbackQuery = TelegramCallbackQuery, TMessage extends TelegramUpdateMessage = TelegramUpdateMessage> {
129
+ forwardCallback?: (input: {
130
+ query: TCallbackQuery;
131
+ ownership: TelegramMessageOwnershipView;
132
+ ctx: TContext;
133
+ }) => Promise<TelegramBusForeignUpdateSettlement> | TelegramBusForeignUpdateSettlement;
134
+ forwardReaction?: (input: {
135
+ reactionUpdate: TReactionUpdate;
136
+ ownership: TelegramMessageOwnershipView;
137
+ ctx: TContext;
138
+ }) => Promise<TelegramBusForeignUpdateSettlement> | TelegramBusForeignUpdateSettlement;
139
+ forwardMessage?: (input: {
140
+ message: TMessage;
141
+ ownership: TelegramTargetOwnershipView;
142
+ ctx: TContext;
143
+ }) => Promise<TelegramBusForeignUpdateSettlement> | TelegramBusForeignUpdateSettlement;
144
+ forwardEditedMessage?: (input: {
145
+ message: TMessage;
146
+ ownership: TelegramTargetOwnershipView;
147
+ ctx: TContext;
148
+ }) => Promise<TelegramBusForeignUpdateSettlement> | TelegramBusForeignUpdateSettlement;
149
+ }
150
+ type TelegramForeignUpdateSettlementFailure = Exclude<TelegramBusForeignUpdateSettlement, {
151
+ status: "accepted";
152
+ }> | {
153
+ status: "terminal-rejected";
154
+ failureClass: "forwarder-unavailable";
155
+ message: string;
156
+ sourceUpdateId?: number;
157
+ };
158
+ export declare class TelegramForeignUpdateSettlementError extends Error {
159
+ readonly settlement: TelegramForeignUpdateSettlementFailure;
160
+ constructor(operation: string, settlement: TelegramForeignUpdateSettlementFailure);
161
+ }
162
+ export interface TelegramMessageReactionUpdated {
163
+ chat: {
164
+ id?: number;
165
+ type: string;
166
+ };
167
+ user?: TelegramUser;
168
+ actor_chat?: unknown;
169
+ message_id: number;
170
+ old_reaction: TelegramReactionType[];
171
+ new_reaction: TelegramReactionType[];
172
+ }
173
+ export declare const TELEGRAM_INTERNAL_AGENT_MESSAGE: unique symbol;
174
+ export interface TelegramUpdateFlow extends TelegramUpdateRouting, TelegramUpdateDeletion {
175
+ message_reaction?: TelegramMessageReactionUpdated;
176
+ [TELEGRAM_INTERNAL_AGENT_MESSAGE]?: true;
177
+ }
178
+ export type TelegramUpdateAdmissionOutcome = {
179
+ kind: "complete";
180
+ } | {
181
+ kind: "deferred";
182
+ } | {
183
+ kind: "queued";
184
+ queueKind: "prompt" | "control";
185
+ receiptId: string;
186
+ sourceUpdateIds: readonly number[];
187
+ };
188
+ interface TelegramUpdateAdmissionBinding {
189
+ sourceUpdateId: number;
190
+ report: (outcome: TelegramUpdateAdmissionOutcome) => void;
191
+ }
192
+ export type TelegramQueueAdmissionReceiptLike = TelegramQueueAdmissionReceipt;
193
+ export declare function bindTelegramUpdateAdmissionSource<TUpdate extends TelegramUpdateFlow & {
194
+ update_id: number;
195
+ }>(update: TUpdate, report: TelegramUpdateAdmissionBinding["report"]): TUpdate;
196
+ export declare function collectTelegramAdmissionSourceUpdateIds(values: readonly unknown[]): number[];
197
+ /** Report source completion; true means reported, not a durable settlement acknowledgement. */
198
+ export declare function reportTelegramUpdateCompleted(value: unknown): boolean;
199
+ export declare function reportTelegramUpdateDeferred(value: unknown): boolean;
200
+ export declare function reportTelegramQueueAdmission(values: readonly unknown[], receipts: readonly TelegramQueueAdmissionReceiptLike[]): boolean;
201
+ export type TelegramUpdateFlowAction<TReactionUpdate extends TelegramMessageReactionUpdated = TelegramMessageReactionUpdated, TCallbackQuery extends TelegramCallbackQuery = TelegramCallbackQuery, TMessage extends TelegramUpdateMessage = TelegramUpdateMessage, TGuestMessage extends TelegramGuestMessage = TelegramGuestMessage> = {
202
+ kind: "ignore";
203
+ } | {
204
+ kind: "deleted";
205
+ messageIds: number[];
206
+ } | {
207
+ kind: "reaction";
208
+ reactionUpdate: TReactionUpdate;
209
+ } | {
210
+ kind: "topic-lifecycle";
211
+ lifecycle: TelegramTopicLifecycleUpdate<TMessage>;
212
+ } | {
213
+ kind: "callback";
214
+ query: TCallbackQuery;
215
+ authorization: TelegramAuthorizationState;
216
+ } | {
217
+ kind: "message";
218
+ message: TMessage & {
219
+ from: TelegramUser;
220
+ };
221
+ authorization: TelegramAuthorizationState;
222
+ } | {
223
+ kind: "edited-message";
224
+ message: TMessage & {
225
+ from: TelegramUser;
226
+ };
227
+ authorization: TelegramAuthorizationState;
228
+ } | {
229
+ kind: "guest";
230
+ guestMessage: TGuestMessage & {
231
+ from: TelegramUser;
232
+ };
233
+ authorization: TelegramAuthorizationState;
234
+ };
235
+ export declare function buildTelegramUpdateFlowAction<TUpdate extends TelegramUpdateFlow>(update: TUpdate, allowedUserId?: number): TelegramUpdateFlowAction<NonNullable<TUpdate["message_reaction"]>, NonNullable<TUpdate["callback_query"]>, NonNullable<TUpdate["message"] | TUpdate["edited_message"]>, NonNullable<TUpdate["guest_message"]>>;
236
+ export type TelegramUpdateExecutionPlan<TReactionUpdate extends TelegramMessageReactionUpdated = TelegramMessageReactionUpdated, TCallbackQuery extends TelegramCallbackQuery = TelegramCallbackQuery, TMessage extends TelegramUpdateMessage = TelegramUpdateMessage, TGuestMessage extends TelegramGuestMessage = TelegramGuestMessage> = {
237
+ kind: "ignore";
238
+ } | {
239
+ kind: "deleted";
240
+ messageIds: number[];
241
+ } | {
242
+ kind: "reaction";
243
+ reactionUpdate: TReactionUpdate;
244
+ } | {
245
+ kind: "topic-lifecycle";
246
+ lifecycle: TelegramTopicLifecycleUpdate<TMessage>;
247
+ } | {
248
+ kind: "callback";
249
+ query: TCallbackQuery;
250
+ shouldPair: boolean;
251
+ shouldDeny: boolean;
252
+ } | {
253
+ kind: "message";
254
+ message: TMessage & {
255
+ from: TelegramUser;
256
+ };
257
+ shouldPair: boolean;
258
+ shouldNotifyPaired: boolean;
259
+ shouldDeny: boolean;
260
+ } | {
261
+ kind: "edited-message";
262
+ message: TMessage & {
263
+ from: TelegramUser;
264
+ };
265
+ shouldPair: boolean;
266
+ shouldDeny: boolean;
267
+ } | {
268
+ kind: "guest";
269
+ guestMessage: TGuestMessage & {
270
+ from: TelegramUser;
271
+ };
272
+ shouldDeny: boolean;
273
+ };
274
+ export declare function buildTelegramUpdateExecutionPlan<TReactionUpdate extends TelegramMessageReactionUpdated, TCallbackQuery extends TelegramCallbackQuery, TMessage extends TelegramUpdateMessage, TGuestMessage extends TelegramGuestMessage>(action: TelegramUpdateFlowAction<TReactionUpdate, TCallbackQuery, TMessage, TGuestMessage>): TelegramUpdateExecutionPlan<TReactionUpdate, TCallbackQuery, TMessage, TGuestMessage>;
275
+ export declare function buildTelegramUpdateExecutionPlanFromUpdate<TUpdate extends TelegramUpdateFlow>(update: TUpdate, allowedUserId?: number): TelegramUpdateExecutionPlan<NonNullable<TUpdate["message_reaction"]>, NonNullable<TUpdate["callback_query"]>, NonNullable<TUpdate["message"] | TUpdate["edited_message"]>>;
276
+ export type TelegramMessageOwnershipRecorderInput = Parameters<TelegramMessageOwnershipStore["record"]>[0];
277
+ export type TelegramMessageOwnershipRecorder = (input: TelegramMessageOwnershipRecorderInput) => void;
278
+ interface TelegramUnauthorizedReplyOptions {
279
+ parseMode?: "HTML";
280
+ target?: {
281
+ chatId: number;
282
+ threadId?: number;
283
+ };
284
+ }
285
+ export interface TelegramUpdateRuntimeDeps<TContext = unknown, TReactionUpdate extends TelegramMessageReactionUpdated = TelegramMessageReactionUpdated, TCallbackQuery extends TelegramCallbackQuery = TelegramCallbackQuery, TMessage extends TelegramUpdateMessage = TelegramUpdateMessage> {
286
+ ctx: TContext;
287
+ execution?: TelegramUpdateExecutionFence;
288
+ getCurrentInstanceId?: () => string | undefined;
289
+ getMessageOwnership?: TelegramMessageOwnershipLookup;
290
+ getTargetOwnership?: TelegramTargetOwnershipLookup;
291
+ recordMessageOwnership?: TelegramMessageOwnershipRecorder;
292
+ foreignOwnedUpdateForwarder?: TelegramForeignOwnedUpdateForwarder<TContext, TReactionUpdate, TCallbackQuery, TMessage>;
293
+ removePendingMediaGroupMessages: (messageIds: number[]) => void;
294
+ removeQueuedTelegramTurnsByMessageIds: (messageIds: number[], ctx: TContext) => number;
295
+ handleAuthorizedTelegramReactionUpdate: (reactionUpdate: TReactionUpdate, ctx: TContext) => Promise<void>;
296
+ handleTelegramTopicLifecycleUpdate?: (lifecycle: TelegramTopicLifecycleUpdate<TMessage>, ctx: TContext) => Promise<void> | void;
297
+ pairTelegramUserIfNeeded: (userId: number, ctx: TContext, assertExecutionCurrent?: () => void) => Promise<boolean>;
298
+ answerCallbackQuery: (callbackQueryId: string, text?: string) => Promise<void>;
299
+ answerGuestQuery: (guestQueryId: string, text?: string, options?: Pick<TelegramUnauthorizedReplyOptions, "parseMode">) => Promise<void>;
300
+ handleAuthorizedTelegramCallbackQuery: (query: TCallbackQuery, ctx: TContext) => Promise<void>;
301
+ sendTextReply: (chatId: number, replyToMessageId: number, text: string, options?: TelegramUnauthorizedReplyOptions) => Promise<number | undefined>;
302
+ handleAuthorizedTelegramMessage: (message: TMessage, ctx: TContext) => Promise<void>;
303
+ handleAuthorizedTelegramEditedMessage: (message: TMessage, ctx: TContext) => unknown;
304
+ handleAuthorizedTelegramGuestMessage?: (guestMessage: TelegramGuestMessage & {
305
+ from: TelegramUser;
306
+ }, ctx: TContext) => Promise<void>;
307
+ /** Called when the owner writes in an unbound thread no live instance owns. */
308
+ handleUnboundTelegramTopicMessage?: (message: TMessage & {
309
+ from: TelegramUser;
310
+ }, ctx: TContext) => Promise<void>;
311
+ }
312
+ export interface TelegramUpdateRuntimeControllerDeps<TContext = unknown, TCallbackQuery extends TelegramCallbackQuery = TelegramCallbackQuery, TMessage extends TelegramUpdateMessage = TelegramUpdateMessage> {
313
+ getAllowedUserId: () => number | undefined;
314
+ getCurrentInstanceId?: () => string | undefined;
315
+ getMessageOwnership?: TelegramMessageOwnershipLookup;
316
+ getTargetOwnership?: TelegramTargetOwnershipLookup;
317
+ recordMessageOwnership?: TelegramMessageOwnershipRecorder;
318
+ foreignOwnedUpdateForwarder?: TelegramForeignOwnedUpdateForwarder<TContext, TelegramMessageReactionUpdated, TCallbackQuery, TMessage>;
319
+ removePendingMediaGroupMessages: (messageIds: number[]) => void;
320
+ flushPendingMediaGroupMessage?: (messageId: number) => Promise<boolean>;
321
+ flushPendingTextGroupMessage?: (messageId: number) => Promise<boolean>;
322
+ removeQueuedTelegramTurnsByMessageIds: (messageIds: number[], ctx: TContext, scope?: {
323
+ chatId?: number;
324
+ threadId?: number;
325
+ }) => number;
326
+ applyQueuedTelegramTurnReactionByMessageId: (messageId: number, disposition: TelegramQueueReactionDisposition, ctx: TContext, scope?: {
327
+ chatId?: number;
328
+ threadId?: number;
329
+ }) => boolean;
330
+ pairTelegramUserIfNeeded: (userId: number, ctx: TContext, assertExecutionCurrent?: () => void) => Promise<boolean>;
331
+ answerCallbackQuery: (callbackQueryId: string, text?: string) => Promise<void>;
332
+ answerGuestQuery: (guestQueryId: string, text?: string, options?: Pick<TelegramUnauthorizedReplyOptions, "parseMode">) => Promise<void>;
333
+ handleAuthorizedTelegramCallbackQuery: (query: TCallbackQuery, ctx: TContext) => Promise<void>;
334
+ sendTextReply: (chatId: number, replyToMessageId: number, text: string, options?: TelegramUnauthorizedReplyOptions) => Promise<number | undefined>;
335
+ handleAuthorizedTelegramMessage: (message: TMessage, ctx: TContext) => Promise<void>;
336
+ handleAuthorizedTelegramEditedMessage: (message: TMessage, ctx: TContext) => unknown;
337
+ handleAuthorizedTelegramGuestMessage?: (guestMessage: TelegramGuestMessage & {
338
+ from: TelegramUser;
339
+ }, ctx: TContext) => Promise<void>;
340
+ handleTelegramTopicLifecycleUpdate?: (lifecycle: TelegramTopicLifecycleUpdate<TMessage>, ctx: TContext) => Promise<void> | void;
341
+ /** Called when the owner writes in an unbound thread no live instance owns. */
342
+ handleUnboundTelegramTopicMessage?: (message: TMessage & {
343
+ from: TelegramUser;
344
+ }, ctx: TContext) => Promise<void>;
345
+ }
346
+ export interface TelegramUpdateRuntimeController<TContext = unknown, TUpdate extends TelegramUpdateFlow = TelegramUpdateFlow> {
347
+ handleAuthorizedReactionUpdate: (reactionUpdate: NonNullable<TUpdate["message_reaction"]>, ctx: TContext) => Promise<void>;
348
+ handleUpdate: (update: TUpdate, ctx: TContext, execution?: TelegramUpdateExecutionFence) => Promise<void>;
349
+ }
350
+ export declare function executeTelegramUpdate<TUpdate extends TelegramUpdateFlow, TContext = unknown>(update: TUpdate, allowedUserId: number | undefined, deps: TelegramUpdateRuntimeDeps<TContext, NonNullable<TUpdate["message_reaction"]>, NonNullable<TUpdate["callback_query"]>, NonNullable<TUpdate["message"] | TUpdate["edited_message"]>>): Promise<void>;
351
+ export type TelegramPairedUpdateRuntimeControllerDeps<TContext = unknown, TUpdate extends TelegramUpdateFlow = TelegramUpdateFlow> = Omit<TelegramUpdateRuntimeControllerDeps<TContext, NonNullable<TUpdate["callback_query"]>, NonNullable<TUpdate["message"] | TUpdate["edited_message"]>>, "pairTelegramUserIfNeeded"> & TelegramUserPairingRuntimeDeps<TContext>;
352
+ export declare function createTelegramPairedUpdateRuntime<TContext = unknown, TUpdate extends TelegramUpdateFlow = TelegramUpdateFlow>(deps: TelegramPairedUpdateRuntimeControllerDeps<TContext, TUpdate>): TelegramUpdateRuntimeController<TContext, TUpdate>;
353
+ export declare function createTelegramUpdateRuntime<TContext = unknown, TUpdate extends TelegramUpdateFlow = TelegramUpdateFlow>(deps: TelegramUpdateRuntimeControllerDeps<TContext, NonNullable<TUpdate["callback_query"]>, NonNullable<TUpdate["message"] | TUpdate["edited_message"]>>): TelegramUpdateRuntimeController<TContext, TUpdate>;
354
+ export interface AuthorizedTelegramReactionUpdateDeps<TContext> {
355
+ allowedUserId?: number;
356
+ ctx: TContext;
357
+ getCurrentInstanceId?: () => string | undefined;
358
+ getMessageOwnership?: TelegramMessageOwnershipLookup;
359
+ foreignOwnedUpdateForwarder?: TelegramForeignOwnedUpdateForwarder<TContext>;
360
+ assertExecutionCurrent?: () => void;
361
+ flushPendingMediaGroupMessage?: (messageId: number) => Promise<boolean>;
362
+ flushPendingTextGroupMessage?: (messageId: number) => Promise<boolean>;
363
+ applyQueuedTelegramTurnReactionByMessageId: (messageId: number, disposition: TelegramQueueReactionDisposition, ctx: TContext, scope?: {
364
+ chatId?: number;
365
+ threadId?: number;
366
+ }) => boolean;
367
+ }
368
+ export declare function handleAuthorizedTelegramReactionUpdate<TContext>(reactionUpdate: TelegramMessageReactionUpdated, deps: AuthorizedTelegramReactionUpdateDeps<TContext>): Promise<void>;
369
+ export declare function executeTelegramUpdatePlan<TContext = unknown, TReactionUpdate extends TelegramMessageReactionUpdated = TelegramMessageReactionUpdated, TCallbackQuery extends TelegramCallbackQuery = TelegramCallbackQuery, TMessage extends TelegramUpdateMessage = TelegramUpdateMessage>(plan: TelegramUpdateExecutionPlan<TReactionUpdate, TCallbackQuery, TMessage>, deps: TelegramUpdateRuntimeDeps<TContext, TReactionUpdate, TCallbackQuery, TMessage>): Promise<void>;
370
+ export declare const TELEGRAM_UPDATE_RETRY_BASE_DELAY_MS = 1000;
371
+ export declare const TELEGRAM_UPDATE_RETRY_MAX_DELAY_MS = 60000;
372
+ export declare const TELEGRAM_UPDATE_WORKER_BATCH_SIZE = 64;
373
+ export type TelegramUpdateWorkerPhase = "stopped" | "idle" | "executing" | "retry-wait" | "failed" | "deferred" | "queued" | "blocked";
374
+ export type TelegramUpdateWorkerBlockedReason = "authority-lost" | "authority-check" | "journal-read" | "journal-write" | "execution" | "input-custody" | "prior-generation-executing" | "invalid-outcome";
375
+ export interface TelegramUpdateWorkerStateSnapshot {
376
+ phase: TelegramUpdateWorkerPhase;
377
+ generation: number;
378
+ phaseStartedAtMs?: number;
379
+ currentUpdateId?: number;
380
+ blockedReason?: TelegramUpdateWorkerBlockedReason;
381
+ blockedInputCustody?: {
382
+ updateId: number;
383
+ kind: "running-outcome-unknown" | "foreign-ready" | "handoff-frozen" | "legacy-retry-state";
384
+ };
385
+ journalEntryCount: number;
386
+ journalSerializedBytes: number;
387
+ oldestAdmittedAtMs?: number;
388
+ deferredClaimCount: number;
389
+ queuedClaimCount: number;
390
+ foreignQueuedCount: number;
391
+ foreignQueuedOwner?: TelegramUpdateJournalQueueOwner;
392
+ foreignQueuedOwnerLiveness?: TelegramProcessLiveness;
393
+ retryWaitCount: number;
394
+ failedCount: number;
395
+ nextRetryUpdateId?: number;
396
+ nextRetryAtMs?: number;
397
+ nextRetryAttemptCount?: number;
398
+ nextRetryFailureClass?: string;
399
+ failedUpdateId?: number;
400
+ failedFailureId?: string;
401
+ failedAttemptCount?: number;
402
+ failedClass?: string;
403
+ failedSummary?: string;
404
+ terminalFailureAtMs?: number;
405
+ unsettledExecutionCount: number;
406
+ lastCompletedUpdateId?: number;
407
+ lastCompletedAtMs?: number;
408
+ lastFailureAtMs?: number;
409
+ lastFailurePhase?: string;
410
+ }
411
+ export interface TelegramUpdateWorkerJournalSnapshot {
412
+ version: typeof TELEGRAM_UPDATE_JOURNAL_VERSION | typeof TELEGRAM_UPDATE_JOURNAL_EXCLUSION_VERSION | typeof TELEGRAM_UPDATE_JOURNAL_CUSTODY_VERSION;
413
+ acceptedThroughUpdateId?: number;
414
+ entries: readonly {
415
+ updateId: number;
416
+ update: TelegramJournaledUpdate;
417
+ readonly preApprovalExcluded?: boolean;
418
+ admittedAtMs: number;
419
+ state: "pending" | "retry-wait" | "queued" | "failed";
420
+ inputClaim?: TelegramUpdateJournalInputClaim;
421
+ queueKind?: "prompt" | "control";
422
+ queueReceiptId?: string;
423
+ queueOwner?: TelegramUpdateJournalQueueOwner;
424
+ queueHandoff?: {
425
+ handoffId: string;
426
+ offeredAtMs: number;
427
+ recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
428
+ };
429
+ failure?: {
430
+ attemptCount: number;
431
+ failedAtMs: number;
432
+ failureClass: string;
433
+ summary: string;
434
+ };
435
+ nextRetryAtMs?: number;
436
+ terminalAtMs?: number;
437
+ terminalReason?: string;
438
+ terminalFailureId?: string;
439
+ }[];
440
+ serializedBytes: number;
441
+ }
442
+ export interface TelegramUpdateWorkerJournalPort {
443
+ read: () => TelegramUpdateWorkerJournalSnapshot;
444
+ markQueued: (receipt: {
445
+ queueKind: "prompt" | "control";
446
+ receiptId: string;
447
+ sourceUpdateIds: readonly number[];
448
+ owner: TelegramUpdateJournalQueueOwnerIdentity;
449
+ }) => {
450
+ queuedUpdateIds: readonly number[];
451
+ duplicateUpdateIds: readonly number[];
452
+ queueOwner?: TelegramUpdateJournalQueueOwner;
453
+ };
454
+ completeQueued: (receipts: readonly {
455
+ queueKind: "prompt" | "control";
456
+ receiptId: string;
457
+ sourceUpdateIds: readonly number[];
458
+ queueOwner: TelegramUpdateJournalQueueOwner;
459
+ }[]) => {
460
+ removedUpdateIds: readonly number[];
461
+ };
462
+ markExecutionFailure: (input: {
463
+ updateId: number;
464
+ expectedAttemptCount: number;
465
+ failedAtMs: number;
466
+ failureClass: string;
467
+ summary: string;
468
+ disposition: "retry-wait" | "failed";
469
+ nextRetryAtMs?: number;
470
+ terminalReason?: string;
471
+ }) => {
472
+ entry: TelegramUpdateWorkerJournalSnapshot["entries"][number];
473
+ };
474
+ removeCompleted: (updateIds: readonly number[]) => {
475
+ removedUpdateIds: readonly number[];
476
+ };
477
+ }
478
+ export interface TelegramUpdateRetryPolicy {
479
+ baseDelayMs: number;
480
+ maxDelayMs: number;
481
+ }
482
+ export interface TelegramUpdateExecutionFailureClassification {
483
+ disposition: "retryable" | "terminal";
484
+ failureClass: string;
485
+ summary: string;
486
+ }
487
+ export interface TelegramUpdateWorkerRuntimeDeps<TContext> {
488
+ journal: TelegramUpdateWorkerJournalPort;
489
+ executeUpdate: (update: TelegramJournaledUpdate, ctx: TContext, signal: AbortSignal) => Promise<TelegramUpdateAdmissionOutcome> | TelegramUpdateAdmissionOutcome;
490
+ executeCustodiedUpdate?: (update: TelegramJournaledUpdate, ctx: TContext, signal: AbortSignal) => Promise<TelegramCustodiedExecutionResult>;
491
+ hasAuthority: (ctx: TContext) => boolean;
492
+ getJournalBindingKey?: () => string | undefined;
493
+ getRecipientBindingKey?: () => string | undefined;
494
+ getQueueOwnerIdentity?: (ctx: TContext) => TelegramUpdateJournalQueueOwnerIdentity;
495
+ isContextCurrent?: (ctx: TContext) => boolean;
496
+ createAbortController?: () => AbortController;
497
+ getNowMs?: () => number;
498
+ retryPolicy?: Partial<TelegramUpdateRetryPolicy>;
499
+ classifyExecutionFailure?: (error: unknown) => TelegramUpdateExecutionFailureClassification;
500
+ settleTerminalExecutionFailure?: (error: unknown) => Promise<boolean>;
501
+ scheduleRetry?: (callback: () => void, delayMs: number) => unknown;
502
+ cancelRetry?: (handle: unknown) => void;
503
+ batchSize?: number;
504
+ yieldToEventLoop?: () => Promise<void>;
505
+ onStateChange?: (state: TelegramUpdateWorkerStateSnapshot) => void;
506
+ onQueueReceiptCommitted?: (receipt: TelegramQueueAdmissionReceiptLike, ctx: TContext) => void;
507
+ onUpdateCompleted?: (updateId: number, ctx: TContext) => void;
508
+ recordRuntimeEvent?: (category: string, error: unknown, details?: Record<string, unknown>) => void;
509
+ }
510
+ export type TelegramQueueReceiptCompletionReason = "prompt-handoff" | "control-settlement" | "discard";
511
+ export interface TelegramUpdateWorkerRuntime<TContext> {
512
+ start: (ctx: TContext) => void;
513
+ signal: () => void;
514
+ settleDeferred: (input: {
515
+ updateId: number;
516
+ outcome: TelegramUpdateAdmissionOutcome;
517
+ signal: AbortSignal;
518
+ }) => void;
519
+ settleCustodied: (input: {
520
+ updateId: number;
521
+ result: TelegramCustodiedExecutionResult;
522
+ signal: AbortSignal;
523
+ }) => void;
524
+ isQueueReceiptCommitted: (receipt: TelegramQueueAdmissionReceiptLike) => boolean;
525
+ getQueueReceiptOwner: (receipt: TelegramQueueAdmissionReceiptLike) => TelegramUpdateJournalQueueOwner | undefined;
526
+ completeQueueReceipts: (input: {
527
+ receipts: readonly TelegramQueueAdmissionReceiptLike[];
528
+ ctx: TContext;
529
+ reason: TelegramQueueReceiptCompletionReason;
530
+ }) => void;
531
+ stop: () => Promise<void>;
532
+ waitForDrain: () => Promise<void>;
533
+ getState: () => TelegramUpdateWorkerStateSnapshot;
534
+ }
535
+ export declare class TelegramUpdateAdmissionOutcomeError extends Error {
536
+ constructor(message: string);
537
+ }
538
+ export declare function createTelegramUpdateWorkerRuntime<TContext>(deps: TelegramUpdateWorkerRuntimeDeps<TContext>): TelegramUpdateWorkerRuntime<TContext>;
539
+ /**
540
+ * Verdict returned by a public Telegram update handler.
541
+ *
542
+ * - `"consume"` — the handler processed this update; pi-telegram skips default routing.
543
+ * - `"pass"` (or `void`/`undefined`) — pi-telegram routes the update normally.
544
+ */
545
+ export type TelegramUpdateHandlerVerdict = "consume" | "pass";
546
+ export interface TelegramUpdateExecutionFence {
547
+ readonly generation: number;
548
+ readonly updateId: number;
549
+ readonly signal: AbortSignal;
550
+ isCurrent: () => boolean;
551
+ assertCurrent: () => void;
552
+ }
553
+ export declare function getTelegramUpdateExecutionFence(update: unknown): TelegramUpdateExecutionFence | undefined;
554
+ export declare function assertTelegramUpdateExecutionCurrent(update: unknown): void;
555
+ export declare function createTelegramUpdateExecutionFenceGuard(update: unknown): () => void;
556
+ export declare function carryTelegramUpdateExecutionFence<TTarget extends object>(source: unknown, target: TTarget): TTarget;
557
+ export type TelegramUpdateHandler = (update: unknown, execution?: TelegramUpdateExecutionFence) => TelegramUpdateHandlerVerdict | void | Promise<TelegramUpdateHandlerVerdict | void>;
558
+ export interface TelegramUpdateHandlerRegistry {
559
+ /** Schema version of this registry shape. */
560
+ readonly version: 1;
561
+ /**
562
+ * Register an update handler. Returns a disposer that removes it.
563
+ *
564
+ * Handlers are invoked in registration order on every Telegram update,
565
+ * before pi-telegram's own routing. The first handler that returns
566
+ * `"consume"` wins and stops the chain for that update.
567
+ */
568
+ add: (handler: TelegramUpdateHandler) => () => void;
569
+ /**
570
+ * Run all registered handlers against an update.
571
+ *
572
+ * Used by pi-telegram's polling runtime; extension consumers should call
573
+ * {@link registerTelegramUpdateHandler} or `add` instead of dispatching directly.
574
+ */
575
+ dispatch: (update: unknown, execution?: TelegramUpdateExecutionFence) => Promise<TelegramUpdateHandlerVerdict>;
576
+ }
577
+ /**
578
+ * Called by pi-telegram's own runtime to obtain the registry it dispatches
579
+ * through. Extension consumers should not call this; use
580
+ * {@link registerTelegramUpdateHandler} instead.
581
+ */
582
+ export declare function getTelegramUpdateHandlerRegistry(): TelegramUpdateHandlerRegistry;
583
+ export interface TelegramUpdateHandlerWrapDeps<TUpdate, TContext> {
584
+ defaultHandle: (update: TUpdate, ctx: TContext) => Promise<void>;
585
+ registry?: TelegramUpdateHandlerRegistry;
586
+ }
587
+ /**
588
+ * Wrap a default polling `handleUpdate` with the public update handler registry.
589
+ */
590
+ export declare function createTelegramUpdateHandle<TUpdate, TContext>(deps: TelegramUpdateHandlerWrapDeps<TUpdate, TContext>): (update: TUpdate, ctx: TContext) => Promise<void>;
591
+ export interface TelegramUpdateAdmissionHandleDeps<TUpdate extends TelegramUpdateFlow & {
592
+ update_id: number;
593
+ }, TContext> {
594
+ defaultHandle: (update: TUpdate, ctx: TContext, execution?: TelegramUpdateExecutionFence) => Promise<void>;
595
+ registry?: TelegramUpdateHandlerRegistry;
596
+ onLateOutcome?: (outcome: TelegramUpdateAdmissionOutcome, details: {
597
+ updateId: number;
598
+ ctx: TContext;
599
+ signal: AbortSignal;
600
+ }) => void | Promise<void>;
601
+ onLateOutcomeError?: (error: unknown, updateId: number) => void;
602
+ }
603
+ export type TelegramCustodiedExecutionResult = {
604
+ status: "completed";
605
+ } | {
606
+ status: "deferred";
607
+ receipt: TelegramInputJournalReceipt;
608
+ } | {
609
+ status: "queued";
610
+ queueReceipt: ReturnType<TelegramInputJournalStore["queueInputs"]>["queueReceipt"];
611
+ } | {
612
+ status: "outcome-unknown";
613
+ receipt: TelegramInputJournalReceipt;
614
+ };
615
+ type TelegramCustodyExecutionJournal = Pick<TelegramInputJournalStore, "acquireInput" | "startInput" | "completeInput" | "queueInputs">;
616
+ export declare function createTelegramInputCustodyWorkerJournalPort(store: TelegramInputJournalStore): TelegramUpdateWorkerJournalPort & {
617
+ inputCustody: TelegramCustodyExecutionJournal;
618
+ };
619
+ export declare function createTelegramInputCustodyLegacyDispositionRuntime(deps: {
620
+ withBindingReference<T>(recoveryKey: string, operation: (binding: {
621
+ recoveryKey: string;
622
+ journal: Pick<TelegramInputJournalStore, "listLegacyCustodyCandidates" | "applyLegacyCustodyDisposition">;
623
+ }) => T): T;
624
+ }): {
625
+ list(recoveryKey: string): import("./journal.ts").TelegramUpdateJournalLegacyCustodyCandidate[];
626
+ apply(recoveryKey: string, authority: Parameters<TelegramInputJournalStore["applyLegacyCustodyDisposition"]>[0]): import("./journal.ts").TelegramUpdateJournalLegacyCustodyDispositionResult;
627
+ };
628
+ export declare function createTelegramInputCustodyHandoffClient(deps: {
629
+ journal: Pick<TelegramInputJournalStore, "offerInputHandoff">;
630
+ resolveAcceptedReference?: (input: {
631
+ sourceUpdateId: number;
632
+ recipientBindingKey: string;
633
+ }) => {
634
+ sourceRecoveryKey: string;
635
+ source: {
636
+ updateId: number;
637
+ owner: {
638
+ acquisitionId: string;
639
+ handoffId: string;
640
+ };
641
+ };
642
+ } | undefined;
643
+ sendEnvelope(envelope: Extract<TelegramBusEnvelope, {
644
+ kind: "leader.offerInputCustodyHandoff";
645
+ }>): Promise<TelegramBusEnvelope | undefined>;
646
+ }): {
647
+ transfer(input: {
648
+ requestId: string;
649
+ receipt: TelegramInputJournalReceipt;
650
+ recipientInstanceId: string;
651
+ recipientRegistrationGeneration: string;
652
+ recipientBindingKey: string;
653
+ recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
654
+ handoffToken: string;
655
+ sentAtMs: number;
656
+ auth?: string;
657
+ }): Promise<{
658
+ sourceRecoveryKey: string;
659
+ source: {
660
+ updateId: number;
661
+ owner: {
662
+ acquisitionId: string;
663
+ handoffId: string;
664
+ };
665
+ };
666
+ duplicate: boolean;
667
+ }>;
668
+ };
669
+ export interface TelegramInputCustodyHandoffAcceptanceInput {
670
+ sourceRecoveryKey: string;
671
+ recipientBindingKey: string;
672
+ source: TelegramInputJournalSourceReference;
673
+ handoffId: string;
674
+ }
675
+ export declare function createTelegramInputCustodyHandoffAcceptanceRuntime<TContext>(deps: {
676
+ resolveBinding(recoveryKey: string): {
677
+ recoveryKey: string;
678
+ recipientBindingKey: string;
679
+ recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
680
+ journal: Pick<TelegramInputJournalStore, "acceptInputHandoff">;
681
+ signalWorker(ctx: TContext): void;
682
+ } | undefined;
683
+ }): {
684
+ accept(input: TelegramInputCustodyHandoffAcceptanceInput, ctx: TContext): {
685
+ sourceRecoveryKey: string;
686
+ source: {
687
+ updateId: number;
688
+ owner: {
689
+ acquisitionId: string;
690
+ handoffId: string;
691
+ };
692
+ };
693
+ duplicate: boolean;
694
+ };
695
+ };
696
+ export declare function createTelegramInputCustodyForwardReferenceResolver(deps: {
697
+ recoveryKey: string;
698
+ recipientBindingKey: string;
699
+ recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
700
+ journal: Pick<TelegramInputJournalStore, "read">;
701
+ }): (input: {
702
+ sourceUpdateId: number;
703
+ recipientBindingKey: string;
704
+ }) => {
705
+ sourceRecoveryKey: string;
706
+ source: {
707
+ updateId: number;
708
+ owner: {
709
+ acquisitionId: string;
710
+ handoffId: string;
711
+ };
712
+ };
713
+ } | undefined;
714
+ export interface TelegramCustodiedSourceReferenceWakeInput {
715
+ deliveryId: string;
716
+ sourceUpdateId: number;
717
+ recipientBindingKey: string;
718
+ sourceRecoveryKey: string;
719
+ sourceClaim: {
720
+ acquisitionId: string;
721
+ handoffId: string;
722
+ };
723
+ }
724
+ export declare function createTelegramInputCustodySourceReferenceWakeRuntime<TContext>(deps: {
725
+ resolveBinding(recoveryKey: string): {
726
+ recoveryKey: string;
727
+ recipientBindingKey: string;
728
+ recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
729
+ journal: Pick<TelegramInputJournalStore, "read">;
730
+ signalWorker(ctx: TContext): void;
731
+ } | undefined;
732
+ }): {
733
+ wakeSource(input: TelegramCustodiedSourceReferenceWakeInput, ctx: TContext): void;
734
+ };
735
+ export interface TelegramInputCustodyBusBindingRuntime<TContext> {
736
+ acceptHandoff(input: TelegramInputCustodyHandoffAcceptanceInput, ctx: TContext): {
737
+ sourceRecoveryKey: string;
738
+ source: {
739
+ updateId: number;
740
+ owner: {
741
+ acquisitionId: string;
742
+ handoffId: string;
743
+ };
744
+ };
745
+ duplicate: boolean;
746
+ };
747
+ wakeSource(input: TelegramCustodiedSourceReferenceWakeInput, ctx: TContext): void;
748
+ resolveForwardReference(input: {
749
+ sourceUpdateId: number;
750
+ recipientBindingKey: string;
751
+ }): {
752
+ sourceRecoveryKey: string;
753
+ source: {
754
+ updateId: number;
755
+ owner: {
756
+ acquisitionId: string;
757
+ handoffId: string;
758
+ };
759
+ };
760
+ } | undefined;
761
+ }
762
+ export declare function createTelegramInputCustodyBusBindingRuntime<TContext>(deps: {
763
+ getForwardRecoveryKey(): string | undefined;
764
+ resolveBinding(recoveryKey: string): {
765
+ recoveryKey: string;
766
+ recipientBindingKey: string;
767
+ recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
768
+ journal: Pick<TelegramInputJournalStore, "read" | "acceptInputHandoff">;
769
+ signalWorker(ctx: TContext): void;
770
+ } | undefined;
771
+ }): TelegramInputCustodyBusBindingRuntime<TContext>;
772
+ export type TelegramInputCustodyActivationBlocker = "disabled" | "source-unready" | "legacy-writers-present" | "migration-incomplete" | "peer-capability-mismatch";
773
+ export declare function evaluateTelegramInputCustodyActivationReadiness(input: {
774
+ requested: boolean;
775
+ sourceStatus: "absent" | "v3" | "legacy" | "unsupported" | "ambiguous";
776
+ legacyWritersExcluded: boolean;
777
+ historicalMigrationComplete: boolean;
778
+ peerReadiness: readonly ("ready" | "legacy" | "unknown")[];
779
+ }): {
780
+ enabled: true;
781
+ } | {
782
+ enabled: false;
783
+ blocker: TelegramInputCustodyActivationBlocker;
784
+ };
785
+ export interface TelegramInputCustodyReadinessEvidenceSnapshot {
786
+ version: 1;
787
+ revision: number;
788
+ writerExclusion?: TelegramInputCustodyWriterExclusionEvidence;
789
+ migration?: TelegramInputCustodyMigrationEvidence;
790
+ startupExclusion?: TelegramInputCustodyStartupExclusionAuthority;
791
+ migrationCompletion?: TelegramInputCustodyMigrationCompletionAuthority;
792
+ }
793
+ export declare function createTelegramInputCustodyReadinessEvidenceStore(deps: {
794
+ readRetained(): string | undefined;
795
+ publishRetained(serialized: string): void;
796
+ withSerialization<T>(operation: () => T): T;
797
+ authorizePublication(kind: "writer-exclusion" | "migration" | "startup-exclusion" | "migration-completion", evidence: TelegramInputCustodyWriterExclusionEvidence | TelegramInputCustodyMigrationEvidence | TelegramInputCustodyStartupExclusionAuthority | TelegramInputCustodyMigrationCompletionAuthority): boolean;
798
+ }): {
799
+ read: () => TelegramInputCustodyReadinessEvidenceSnapshot;
800
+ publish: (input: {
801
+ expectedRevision: number;
802
+ } & ({
803
+ kind: "writer-exclusion";
804
+ evidence: TelegramInputCustodyWriterExclusionEvidence;
805
+ } | {
806
+ kind: "migration";
807
+ evidence: TelegramInputCustodyMigrationEvidence;
808
+ } | {
809
+ kind: "startup-exclusion";
810
+ evidence: TelegramInputCustodyStartupExclusionAuthority;
811
+ } | {
812
+ kind: "migration-completion";
813
+ evidence: TelegramInputCustodyMigrationCompletionAuthority;
814
+ })) => TelegramInputCustodyReadinessEvidenceSnapshot;
815
+ };
816
+ export interface TelegramInputCustodyActivationEvidenceIdentity {
817
+ profileKey: string;
818
+ recoveryKey: string;
819
+ }
820
+ export interface TelegramInputCustodyStartupExclusionAuthority extends TelegramInputCustodyActivationEvidenceIdentity {
821
+ version: 1;
822
+ status: "enforced" | "revoked";
823
+ authorityId: string;
824
+ closureOperationId: string;
825
+ writerInventorySha256: string;
826
+ allowedWriterProtocol: "custody-v3";
827
+ authorizedAtMs: number;
828
+ }
829
+ export declare function normalizeTelegramInputCustodyStartupExclusionAuthority(value: unknown, expected: TelegramInputCustodyActivationEvidenceIdentity): TelegramInputCustodyStartupExclusionAuthority | undefined;
830
+ export interface TelegramInputCustodyWriterExclusionEvidence extends TelegramInputCustodyActivationEvidenceIdentity {
831
+ version: 1;
832
+ status: "excluded" | "present" | "unknown";
833
+ startupAuthorityId?: string;
834
+ closureOperationId?: string;
835
+ writerInventorySha256?: string;
836
+ }
837
+ export interface TelegramInputCustodyWriterInventory extends TelegramInputCustodyActivationEvidenceIdentity {
838
+ complete: boolean;
839
+ writerInventorySha256: string;
840
+ writers: readonly {
841
+ processId: number;
842
+ processBirthId: string;
843
+ }[];
844
+ }
845
+ export declare function evaluateTelegramInputCustodyWriterExclusionEvidence(input: {
846
+ expected: TelegramInputCustodyActivationEvidenceIdentity;
847
+ inventory: TelegramInputCustodyWriterInventory;
848
+ startupAuthority: TelegramInputCustodyStartupExclusionAuthority | undefined;
849
+ getProcessLiveness(writer: {
850
+ processId: number;
851
+ processBirthId: string;
852
+ }): TelegramProcessLiveness;
853
+ }): TelegramInputCustodyWriterExclusionEvidence;
854
+ export interface TelegramInputCustodyMigrationCompletionAuthority extends TelegramInputCustodyActivationEvidenceIdentity {
855
+ version: 1;
856
+ status: "authorized" | "revoked";
857
+ authorityId: string;
858
+ startupAuthorityId: string;
859
+ closureOperationId: string;
860
+ migrationInventorySha256: string;
861
+ resultingSourceFamily: "absent" | "v3";
862
+ authorizedAtMs: number;
863
+ }
864
+ export declare function normalizeTelegramInputCustodyMigrationCompletionAuthority(value: unknown, expected: TelegramInputCustodyActivationEvidenceIdentity): TelegramInputCustodyMigrationCompletionAuthority | undefined;
865
+ export interface TelegramInputCustodyMigrationEvidence extends TelegramInputCustodyActivationEvidenceIdentity {
866
+ version: 1;
867
+ status: "complete" | "incomplete" | "unknown";
868
+ migrationAuthorityId?: string;
869
+ startupAuthorityId?: string;
870
+ closureOperationId?: string;
871
+ migrationInventorySha256?: string;
872
+ resultingSourceFamily?: "absent" | "v3";
873
+ }
874
+ export type TelegramInputCustodyWriterCutoverResult<TMode> = {
875
+ kind: "blocked";
876
+ blocker: "startup-authority" | "writer-inventory";
877
+ evidence?: TelegramInputCustodyWriterExclusionEvidence;
878
+ } | {
879
+ kind: "completed";
880
+ mode: TMode;
881
+ evidence: TelegramInputCustodyWriterExclusionEvidence;
882
+ resumed: boolean;
883
+ };
884
+ export declare function executeTelegramInputCustodyWriterCutover<TClosure extends {
885
+ operationId: string;
886
+ profileKey: string;
887
+ recoveryKey: string;
888
+ }, TMode extends TelegramInputCustodyWriterProtocolModeEvidence>(input: {
889
+ expected: TelegramInputCustodyActivationEvidenceIdentity;
890
+ closure: TClosure;
891
+ startupAuthority: TelegramInputCustodyStartupExclusionAuthority;
892
+ inventory: TelegramInputCustodyWriterInventory;
893
+ getProcessLiveness(writer: {
894
+ processId: number;
895
+ processBirthId: string;
896
+ }): TelegramProcessLiveness;
897
+ installProtocolMode(closure: TClosure, authority: {
898
+ startupAuthorityId: string;
899
+ writerInventorySha256: string;
900
+ }): {
901
+ mode: TMode;
902
+ resumed: boolean;
903
+ };
904
+ evidenceStore: {
905
+ read(): TelegramInputCustodyReadinessEvidenceSnapshot;
906
+ publish(input: {
907
+ expectedRevision: number;
908
+ kind: "writer-exclusion";
909
+ evidence: TelegramInputCustodyWriterExclusionEvidence;
910
+ }): TelegramInputCustodyReadinessEvidenceSnapshot;
911
+ };
912
+ }): TelegramInputCustodyWriterCutoverResult<TMode>;
913
+ export type TelegramInputCustodyMigrationCompletionResult = {
914
+ kind: "blocked";
915
+ blocker: "migration-authority" | "source-drift" | "inventory-drift";
916
+ } | {
917
+ kind: "completed";
918
+ evidence: TelegramInputCustodyMigrationEvidence;
919
+ resumed: boolean;
920
+ };
921
+ export declare function executeTelegramInputCustodyMigrationCompletion(input: {
922
+ expected: TelegramInputCustodyActivationEvidenceIdentity;
923
+ authority: TelegramInputCustodyMigrationCompletionAuthority;
924
+ migrationInventorySha256: string;
925
+ inspectSource(): "absent" | "v3" | "legacy" | "unsupported" | "ambiguous";
926
+ evidenceStore: {
927
+ read(): TelegramInputCustodyReadinessEvidenceSnapshot;
928
+ publish(input: {
929
+ expectedRevision: number;
930
+ kind: "migration";
931
+ evidence: TelegramInputCustodyMigrationEvidence;
932
+ }): TelegramInputCustodyReadinessEvidenceSnapshot;
933
+ };
934
+ }): TelegramInputCustodyMigrationCompletionResult;
935
+ export interface TelegramInputCustodyWriterProtocolModeEvidence extends TelegramInputCustodyActivationEvidenceIdentity {
936
+ protocol: "custody-v3";
937
+ startupAuthorityId: string;
938
+ closureOperationId: string;
939
+ writerInventorySha256: string;
940
+ }
941
+ export declare function createTelegramInputCustodyProvenReadinessResolver(deps: {
942
+ isRequested(): boolean;
943
+ expectedIdentity(): TelegramInputCustodyActivationEvidenceIdentity;
944
+ inspectSource(): "absent" | "v3" | "legacy" | "unsupported" | "ambiguous";
945
+ readWriterExclusionEvidence(): TelegramInputCustodyWriterExclusionEvidence | undefined;
946
+ readStartupExclusionAuthority(): TelegramInputCustodyStartupExclusionAuthority | undefined;
947
+ readWriterProtocolMode(): TelegramInputCustodyWriterProtocolModeEvidence | undefined;
948
+ readMigrationCompletionAuthority(): TelegramInputCustodyMigrationCompletionAuthority | undefined;
949
+ readMigrationEvidence(): TelegramInputCustodyMigrationEvidence | undefined;
950
+ listPeerReadiness(): readonly ("ready" | "legacy" | "unknown")[];
951
+ }): () => ReturnType<typeof evaluateTelegramInputCustodyActivationReadiness>;
952
+ export declare function createTelegramInputCustodyActivationReadinessResolver(deps: {
953
+ isRequested(): boolean;
954
+ inspectSource(): "absent" | "v3" | "legacy" | "unsupported" | "ambiguous";
955
+ areLegacyWritersExcluded(): boolean;
956
+ isHistoricalMigrationComplete(): boolean;
957
+ listPeerReadiness(): readonly ("ready" | "legacy" | "unknown")[];
958
+ }): () => ReturnType<typeof evaluateTelegramInputCustodyActivationReadiness>;
959
+ export declare function createTelegramInputCustodyLifecycleBindingResolver(deps: {
960
+ isEnabled(): boolean;
961
+ resolveInputJournal(): {
962
+ runtimeKey: string;
963
+ recoveryKey: string;
964
+ journal: TelegramInputJournalStore;
965
+ } | undefined;
966
+ getRecipientBindingKey(): string | undefined;
967
+ }): () => TelegramUpdateAdmissionLifecycleJournalBinding | undefined;
968
+ export declare function createTelegramCustodiedExecutionSession(input: {
969
+ journal: TelegramCustodyExecutionJournal;
970
+ recipientBindingKey: string;
971
+ }): {
972
+ execute(update: TelegramJournaledUpdate, handler: (update: TelegramJournaledUpdate) => Promise<TelegramUpdateAdmissionOutcome>): Promise<TelegramCustodiedExecutionResult>;
973
+ settle(updateId: number, outcome: TelegramUpdateAdmissionOutcome): Promise<TelegramCustodiedExecutionResult>;
974
+ };
975
+ export declare function executeTelegramCustodiedInput(input: {
976
+ journal: TelegramCustodyExecutionJournal;
977
+ update: TelegramJournaledUpdate;
978
+ recipientBindingKey: string;
979
+ execute(update: TelegramJournaledUpdate): Promise<TelegramUpdateAdmissionOutcome>;
980
+ }): Promise<TelegramCustodiedExecutionResult>;
981
+ /**
982
+ * Compose the stable public handler registry with source-bound semantic
983
+ * admission. Production polling switches to this only with the journal worker.
984
+ */
985
+ export declare function createTelegramUpdateAdmissionHandle<TUpdate extends TelegramUpdateFlow & {
986
+ update_id: number;
987
+ }, TContext>(deps: TelegramUpdateAdmissionHandleDeps<TUpdate, TContext>): (update: TUpdate, ctx: TContext, signal: AbortSignal) => Promise<TelegramUpdateAdmissionOutcome>;
988
+ export declare function createTelegramCustodiedUpdateAdmissionHandle<TUpdate extends TelegramJournaledUpdate & TelegramUpdateFlow, TContext>(deps: Omit<TelegramUpdateAdmissionHandleDeps<TUpdate, TContext>, "onLateOutcome" | "onLateOutcomeError"> & {
989
+ journal: TelegramCustodyExecutionJournal;
990
+ recipientBindingKey: string;
991
+ onLateOutcomeError(error: unknown, updateId: number): void;
992
+ onCustodiedLateSettlement?: (result: TelegramCustodiedExecutionResult, details: {
993
+ updateId: number;
994
+ signal: AbortSignal;
995
+ }) => void;
996
+ }): (update: TUpdate, ctx: TContext, signal: AbortSignal) => Promise<TelegramCustodiedExecutionResult>;
997
+ export interface TelegramQueueAdmissionItemLike {
998
+ admissionReceipts?: readonly TelegramQueueAdmissionReceiptLike[];
999
+ }
1000
+ export interface TelegramQueueAdmissionSettlementRuntime<TContext> {
1001
+ isItemReady: (item: TelegramQueueAdmissionItemLike) => boolean;
1002
+ getQueueReceiptOwner: (receipt: TelegramQueueAdmissionReceiptLike) => TelegramUpdateJournalQueueOwner | undefined;
1003
+ onPromptHandedOff: (item: TelegramQueueAdmissionItemLike, ctx: TContext) => void;
1004
+ onControlSettled: (item: TelegramQueueAdmissionItemLike, ctx: TContext) => void;
1005
+ onItemsDiscarded: (items: readonly TelegramQueueAdmissionItemLike[], ctx: TContext) => void;
1006
+ }
1007
+ export declare function createTelegramQueueAdmissionSettlementMuxRuntime<TContext>(runtimes: readonly TelegramQueueAdmissionSettlementRuntime<TContext>[]): TelegramQueueAdmissionSettlementRuntime<TContext>;
1008
+ export declare function createTelegramQueueAdmissionSettlementRuntime<TContext>(worker: TelegramUpdateWorkerRuntime<TContext>): TelegramQueueAdmissionSettlementRuntime<TContext>;
1009
+ export interface TelegramUpdateAdmissionLifecycleJournalBinding {
1010
+ runtimeKey: string;
1011
+ recoveryKey: string;
1012
+ recipientBindingKey?: string;
1013
+ journal: TelegramUpdateWorkerJournalPort & {
1014
+ inputCustody?: TelegramCustodyExecutionJournal;
1015
+ appendBatch: (updates: readonly TelegramJournaledUpdate[], acceptedThroughUpdateId?: number) => Pick<TelegramUpdateJournalAppendResult, "nonExcludedUpdateIds">;
1016
+ applyOperatorDisposition?: (input: TelegramUpdateJournalOperatorDispositionInput) => TelegramUpdateJournalOperatorDispositionResult;
1017
+ discardQueued?: (input: {
1018
+ queueKind: "prompt" | "control";
1019
+ receiptId: string;
1020
+ sourceUpdateIds: readonly number[];
1021
+ expectedOwner: TelegramUpdateJournalQueueOwner;
1022
+ }) => TelegramUpdateJournalQueueDiscardResult;
1023
+ offerQueuedHandoff?: (input: TelegramUpdateJournalQueueHandoffInput) => TelegramUpdateJournalQueueHandoffOfferResult;
1024
+ acceptQueuedHandoff?: (input: TelegramUpdateJournalQueueHandoffInput) => TelegramUpdateJournalQueueHandoffAcceptResult;
1025
+ cancelQueuedHandoff?: (input: TelegramUpdateJournalQueueHandoffInput) => TelegramUpdateJournalQueueHandoffCancelResult;
1026
+ recoverDeadQueueOwner?: (input: {
1027
+ queueKind: "prompt" | "control";
1028
+ receiptId: string;
1029
+ sourceUpdateIds: readonly number[];
1030
+ deadOwner: TelegramUpdateJournalQueueOwner;
1031
+ recoveryOwner: TelegramUpdateJournalQueueOwnerIdentity;
1032
+ }) => TelegramUpdateJournalDeadQueueOwnerRecoveryResult;
1033
+ };
1034
+ hasAuthority?: () => boolean;
1035
+ }
1036
+ export interface TelegramQueueHandoffControlExecutionDeps<TContext> {
1037
+ isContextCurrent: (ctx: TContext) => boolean;
1038
+ showStatus: (chatId: number, replyToMessageId: number, ctx: TContext, threadId?: number) => Promise<void>;
1039
+ openModelMenu: (chatId: number, replyToMessageId: number, ctx: TContext, threadId?: number) => Promise<void>;
1040
+ }
1041
+ export declare function createTelegramQueueHandoffControlExecutionFactory<TContext>(deps: TelegramQueueHandoffControlExecutionDeps<TContext>): (payload: TelegramControlQueueHandoffPayload) => PendingTelegramControlItem<TContext>["execute"];
1042
+ export interface TelegramQueueHandoffCoordinatorInput<TContext> {
1043
+ item: TelegramQueueItem<TContext>;
1044
+ expectedOwner: TelegramUpdateJournalQueueOwner;
1045
+ recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
1046
+ handoffToken: string;
1047
+ stageRemote: (input: {
1048
+ handoffToken: string;
1049
+ expectedOwner: TelegramUpdateJournalQueueOwner;
1050
+ recipientOwner: TelegramUpdateJournalQueueOwnerIdentity;
1051
+ payload: TelegramQueueHandoffPayload;
1052
+ }) => Promise<TelegramQueueHandoffStageResult>;
1053
+ lifecycle: Pick<TelegramUpdateAdmissionLifecycleRuntime<TContext>, "offerQueueReceiptHandoff" | "acceptQueueReceiptHandoff" | "cancelQueueReceiptHandoff">;
1054
+ removeDonorItem: (receipt: TelegramQueueAdmissionReceipt) => boolean;
1055
+ }
1056
+ export type TelegramQueueHandoffCoordinatorResult = {
1057
+ status: "transferred";
1058
+ receipt: TelegramQueueAdmissionReceipt;
1059
+ queueOwner: TelegramUpdateJournalQueueOwner;
1060
+ } | {
1061
+ status: "retained";
1062
+ receipt: TelegramQueueAdmissionReceipt;
1063
+ error: unknown;
1064
+ cancelled: boolean;
1065
+ };
1066
+ export declare function coordinateTelegramQueueHandoff<TContext>(input: TelegramQueueHandoffCoordinatorInput<TContext>): Promise<TelegramQueueHandoffCoordinatorResult>;
1067
+ export interface TelegramQueueHandoffReconciliationBinding<TContext> {
1068
+ request: (ctx: TContext) => void;
1069
+ set: (reconcile: (ctx: TContext) => Promise<void>) => void;
1070
+ }
1071
+ export declare function createTelegramQueueHandoffReconciliationBinding<TContext>(recordFailure?: (error: unknown) => void): TelegramQueueHandoffReconciliationBinding<TContext>;
1072
+ export interface TelegramQueueHandoffRecipientRuntimeDeps<TContext> {
1073
+ staging: TelegramQueueHandoffStagingRuntime;
1074
+ getRecipientOwner: () => TelegramUpdateJournalQueueOwnerIdentity;
1075
+ getLifecycleForBinding: (journalBindingKey: string) => TelegramUpdateAdmissionLifecycleRuntime<TContext> | undefined;
1076
+ isTransportStampActive?: (stamp: TelegramQueueHandoffPayload["transportStamp"]) => boolean;
1077
+ dispatchNext: (ctx: TContext) => void;
1078
+ }
1079
+ export declare function createTelegramQueueHandoffRecipientRuntime<TContext>(deps: TelegramQueueHandoffRecipientRuntimeDeps<TContext>): (envelope: Extract<TelegramBusEnvelope, {
1080
+ kind: "leader.offerQueueHandoff";
1081
+ }>, ctx: TContext) => Promise<TelegramQueueHandoffStageResult>;
1082
+ export interface TelegramQueueHandoffReconcilerDeps<TContext> {
1083
+ ownsDirect: () => boolean;
1084
+ isFollowerRegistered: () => boolean;
1085
+ isBusEnabled: () => boolean;
1086
+ canHandoffWithLeader?: () => boolean;
1087
+ listFollowers: () => readonly TelegramBusFollowerView[];
1088
+ createRecipientJournalBindingKey: (recipient: TelegramBusFollowerView) => string | undefined;
1089
+ getQueuedItems: () => readonly TelegramQueueItem<TContext>[];
1090
+ getReceiptOwner: (receipt: TelegramQueueAdmissionReceipt) => TelegramUpdateJournalQueueOwner | undefined;
1091
+ getLifecycleForReceipt: (receipt: TelegramQueueAdmissionReceipt) => TelegramUpdateAdmissionLifecycleRuntime<TContext> | undefined;
1092
+ createHandoffToken: () => string;
1093
+ createRequestId: () => string;
1094
+ donorInstanceId: string;
1095
+ authSecret?: string;
1096
+ stageThroughFollower: (input: {
1097
+ recipient: TelegramBusFollowerView;
1098
+ expectedOwner: TelegramUpdateJournalQueueOwner;
1099
+ handoffToken: string;
1100
+ payload: TelegramQueueHandoffPayload;
1101
+ }) => Promise<TelegramQueueHandoffStageResult>;
1102
+ routeThroughLeader: (input: {
1103
+ requestId: string;
1104
+ auth?: string;
1105
+ recipientInstanceId: string;
1106
+ recipientRegistrationGeneration: string;
1107
+ donorInstanceId: string;
1108
+ donorProcessId: number;
1109
+ donorProcessBirthId: string;
1110
+ donorSessionGeneration: number;
1111
+ donorAcquisitionId: string;
1112
+ donorAcquiredAtMs: number;
1113
+ handoffToken: string;
1114
+ payload: TelegramQueueHandoffPayload;
1115
+ sentAtMs: number;
1116
+ }) => Promise<TelegramBusEnvelope>;
1117
+ removeDonorItem: (receipt: TelegramQueueAdmissionReceipt, ctx: TContext) => boolean;
1118
+ recordFailure?: (error: unknown, details: Record<string, unknown>) => void;
1119
+ }
1120
+ export interface TelegramQueueHandoffReconciliationRuntimeAssemblyDeps<TContext> {
1121
+ ownsDirect: () => boolean;
1122
+ isFollowerRegistered: () => boolean;
1123
+ isBusEnabled: () => boolean;
1124
+ canHandoffWithLeader?: () => boolean;
1125
+ listFollowers: () => readonly TelegramBusFollowerView[];
1126
+ createRecipientJournalResolver: (profileKey: string) => (() => {
1127
+ recoveryKey: string;
1128
+ } | undefined);
1129
+ queueStore: {
1130
+ getQueuedItems: () => TelegramQueueItem<TContext>[];
1131
+ setQueuedItems: (items: TelegramQueueItem<TContext>[]) => void;
1132
+ };
1133
+ admission: Pick<TelegramUpdateAdmissionRuntimeBinding<TContext>, "getSettlement" | "getLifecycleForJournalBinding">;
1134
+ createHandoffToken: () => string;
1135
+ createRequestId: () => string;
1136
+ donorInstanceId: string;
1137
+ authSecret?: string;
1138
+ stageThroughFollower: (input: {
1139
+ recipientInstanceId: string;
1140
+ recipientRegistrationGeneration: string;
1141
+ donorProcessId: number;
1142
+ donorProcessBirthId: string;
1143
+ donorSessionGeneration: number;
1144
+ donorAcquisitionId: string;
1145
+ donorAcquiredAtMs: number;
1146
+ handoffToken: string;
1147
+ payload: TelegramQueueHandoffPayload;
1148
+ }) => Promise<TelegramQueueHandoffStageResult>;
1149
+ routeThroughLeader: TelegramQueueHandoffReconcilerDeps<TContext>["routeThroughLeader"];
1150
+ recordRuntimeEvent?: (category: string, error: unknown, details?: Record<string, unknown>) => void;
1151
+ }
1152
+ /** Own queue-handoff projections over journals, admission, IPC, and live queue state. */
1153
+ export declare function createTelegramQueueHandoffReconciliationRuntimeAssembly<TContext>(deps: TelegramQueueHandoffReconciliationRuntimeAssemblyDeps<TContext>): (ctx: TContext) => Promise<void>;
1154
+ export declare function createTelegramQueueHandoffReconciler<TContext>(deps: TelegramQueueHandoffReconcilerDeps<TContext>): (ctx: TContext) => Promise<void>;
1155
+ export interface TelegramQueueMutationDependencyItem {
1156
+ chatId: number;
1157
+ target?: {
1158
+ chatId: number;
1159
+ };
1160
+ replyToMessageId: number;
1161
+ sourceMessageIds?: readonly number[];
1162
+ }
1163
+ export interface TelegramUpdateAdmissionLifecycleRuntimeDeps<TContext> {
1164
+ resolveBinding: () => TelegramUpdateAdmissionLifecycleJournalBinding | undefined;
1165
+ getQueueOwnerIdentity?: (ctx: TContext) => TelegramUpdateJournalQueueOwnerIdentity;
1166
+ createWorker: (journal: TelegramUpdateWorkerJournalPort, binding: TelegramUpdateAdmissionLifecycleJournalBinding) => TelegramUpdateWorkerRuntime<TContext>;
1167
+ acquireSourceReference?: (binding: TelegramUpdateAdmissionLifecycleJournalBinding) => () => void;
1168
+ recordRuntimeEvent?: TelegramUpdateWorkerRuntimeDeps<TContext>["recordRuntimeEvent"];
1169
+ }
1170
+ export interface TelegramUpdateAdmissionLifecycleRuntime<TContext> extends TelegramQueueAdmissionSettlementRuntime<TContext> {
1171
+ onSessionStart: (ctx: TContext) => Promise<void>;
1172
+ onSessionShutdown: () => Promise<void>;
1173
+ onTransportChanged: (ctx?: TContext) => Promise<void>;
1174
+ appendBatch: (updates: readonly TelegramJournaledUpdate[], acceptedThroughUpdateId?: number) => Pick<TelegramUpdateJournalAppendResult, "nonExcludedUpdateIds">;
1175
+ discardQueueReceipt: (input: {
1176
+ queueKind: "prompt" | "control";
1177
+ receiptId: string;
1178
+ sourceUpdateIds: readonly number[];
1179
+ expectedOwner: TelegramUpdateJournalQueueOwner;
1180
+ }) => TelegramUpdateJournalQueueDiscardResult;
1181
+ recoverDeadQueueReceipt: (input: {
1182
+ queueKind: "prompt" | "control";
1183
+ receiptId: string;
1184
+ sourceUpdateIds: readonly number[];
1185
+ deadOwner: TelegramUpdateJournalQueueOwner;
1186
+ recoveryOwner: TelegramUpdateJournalQueueOwnerIdentity;
1187
+ }) => TelegramUpdateJournalDeadQueueOwnerRecoveryResult;
1188
+ offerQueueReceiptHandoff: (input: TelegramUpdateJournalQueueHandoffInput) => TelegramUpdateJournalQueueHandoffOfferResult;
1189
+ acceptQueueReceiptHandoff: (input: TelegramUpdateJournalQueueHandoffInput) => TelegramUpdateJournalQueueHandoffAcceptResult;
1190
+ cancelQueueReceiptHandoff: (input: TelegramUpdateJournalQueueHandoffInput) => TelegramUpdateJournalQueueHandoffCancelResult;
1191
+ publishAcceptedQueueReceipt: (input: {
1192
+ receipt: TelegramQueueAdmissionReceiptLike;
1193
+ queueOwner: TelegramUpdateJournalQueueOwner;
1194
+ ctx: TContext;
1195
+ }) => Promise<void>;
1196
+ getQueueReceiptOwner: (receipt: TelegramQueueAdmissionReceiptLike) => TelegramUpdateJournalQueueOwner | undefined;
1197
+ getJournalBindingKey: () => string | undefined;
1198
+ getJournalPath: () => string | undefined;
1199
+ ownsJournalBinding: (journalBindingKey: string) => boolean;
1200
+ getJournalEntryCount: () => number;
1201
+ getForeignQueueOwnerLiveness: () => TelegramProcessLiveness | undefined;
1202
+ hasPendingQueueMutationForItem: (item: TelegramQueueMutationDependencyItem) => boolean;
1203
+ signal: () => void;
1204
+ getState: () => TelegramUpdateWorkerStateSnapshot | undefined;
1205
+ }
1206
+ export interface TelegramUpdateWorkerOwnerRuntime<TContext> {
1207
+ getQueueOwnerIdentity: () => TelegramUpdateJournalQueueOwnerIdentity;
1208
+ onQueueReceiptCommitted: (receipt: unknown, ctx: TContext) => void;
1209
+ onUpdateCompleted: (updateId: number, ctx: TContext) => void;
1210
+ }
1211
+ export interface TelegramUpdateWorkerOwnerRuntimeDeps<TContext> {
1212
+ instanceId: string;
1213
+ processId: number;
1214
+ processBirthId: string;
1215
+ getSessionGeneration: () => number;
1216
+ isContextCurrent: (ctx: TContext) => boolean;
1217
+ dispatchNext: (ctx: TContext) => void;
1218
+ requestQueueHandoffReconciliation: (ctx: TContext) => void;
1219
+ }
1220
+ export declare function createTelegramUpdateWorkerOwnerRuntime<TContext>(deps: TelegramUpdateWorkerOwnerRuntimeDeps<TContext>): TelegramUpdateWorkerOwnerRuntime<TContext>;
1221
+ export interface TelegramUpdateAdmissionRuntimeBinding<TContext> {
1222
+ bind: (input: {
1223
+ leader: TelegramUpdateAdmissionLifecycleRuntime<TContext>;
1224
+ follower: TelegramUpdateAdmissionLifecycleRuntime<TContext>;
1225
+ inputCustodyBus?: TelegramInputCustodyBusBindingRuntime<TContext>;
1226
+ }) => void;
1227
+ getLeader: () => TelegramUpdateAdmissionLifecycleRuntime<TContext> | undefined;
1228
+ getFollower: () => TelegramUpdateAdmissionLifecycleRuntime<TContext> | undefined;
1229
+ getActive: () => TelegramUpdateAdmissionLifecycleRuntime<TContext> | undefined;
1230
+ getSettlement: () => TelegramQueueAdmissionSettlementRuntime<TContext> | undefined;
1231
+ getInputCustodyBus: () => TelegramInputCustodyBusBindingRuntime<TContext> | undefined;
1232
+ getLifecycleForJournalBinding: (journalBindingKey: string) => TelegramUpdateAdmissionLifecycleRuntime<TContext> | undefined;
1233
+ hasPendingQueueMutationForItem: (item: TelegramQueueMutationDependencyItem) => boolean;
1234
+ onSessionShutdown: () => Promise<void>;
1235
+ }
1236
+ export declare function createTelegramUpdateAdmissionRuntimeBinding<TContext>(deps: {
1237
+ isFollowerRegistered: () => boolean;
1238
+ }): TelegramUpdateAdmissionRuntimeBinding<TContext>;
1239
+ /** Own one worker per active transport identity without assuming queued-owner death. */
1240
+ export declare function createTelegramUpdateAdmissionLifecycleRuntime<TContext>(deps: TelegramUpdateAdmissionLifecycleRuntimeDeps<TContext>): TelegramUpdateAdmissionLifecycleRuntime<TContext>;
1241
+ export interface TelegramUpdateAdmissionLifecycleAssembly<TContext> {
1242
+ leader: TelegramUpdateAdmissionLifecycleRuntime<TContext>;
1243
+ follower: TelegramUpdateAdmissionLifecycleRuntime<TContext>;
1244
+ }
1245
+ export interface TelegramUpdateAdmissionLifecycleAssemblyDeps<TUpdate extends TelegramJournaledUpdate & TelegramUpdateFlow, TContext> {
1246
+ runtimeBinding: TelegramUpdateAdmissionRuntimeBinding<TContext>;
1247
+ inputCustodyBus?: TelegramInputCustodyBusBindingRuntime<TContext>;
1248
+ acquireSourceReference?: (role: "leader" | "follower", binding: TelegramUpdateAdmissionLifecycleJournalBinding) => () => void;
1249
+ worker: Omit<TelegramUpdateAdmissionWorkerRuntimeDeps<TUpdate, TContext>, "journal" | "getJournalBindingKey" | "getRecipientBindingKey" | "hasAuthority" | "prepareUpdateForExecution">;
1250
+ leader: {
1251
+ resolveBinding: () => TelegramUpdateAdmissionLifecycleJournalBinding | undefined;
1252
+ hasAuthority: (ctx: TContext) => boolean;
1253
+ };
1254
+ follower: {
1255
+ resolveBinding: () => TelegramUpdateAdmissionLifecycleJournalBinding | undefined;
1256
+ isRegistered: () => boolean;
1257
+ getGeneration: () => string | undefined;
1258
+ prepareUpdateForExecution: (update: TUpdate) => TUpdate;
1259
+ };
1260
+ recordRuntimeEvent?: TelegramUpdateWorkerRuntimeDeps<TContext>["recordRuntimeEvent"];
1261
+ }
1262
+ export type TelegramUpdateAdmissionWorkerRuntimeDeps<TUpdate extends TelegramJournaledUpdate & TelegramUpdateFlow, TContext> = Omit<TelegramUpdateWorkerRuntimeDeps<TContext>, "executeUpdate" | "executeCustodiedUpdate"> & {
1263
+ inputCustody?: TelegramCustodyExecutionJournal;
1264
+ defaultHandle: (update: TUpdate, ctx: TContext, execution?: TelegramUpdateExecutionFence) => Promise<void>;
1265
+ prepareUpdateForExecution?: (update: TUpdate) => TUpdate;
1266
+ registry?: TelegramUpdateHandlerRegistry;
1267
+ };
1268
+ /** Compose source-bound routing and late grouped settlement under one worker. */
1269
+ export declare function createTelegramUpdateAdmissionWorkerRuntime<TUpdate extends TelegramJournaledUpdate & TelegramUpdateFlow, TContext>(deps: TelegramUpdateAdmissionWorkerRuntimeDeps<TUpdate, TContext>): TelegramUpdateWorkerRuntime<TContext>;
1270
+ /** Own leader/follower journal lifecycle construction and generation fencing. */
1271
+ export declare function createTelegramUpdateAdmissionLifecycleAssembly<TUpdate extends TelegramJournaledUpdate & TelegramUpdateFlow, TContext>(deps: TelegramUpdateAdmissionLifecycleAssemblyDeps<TUpdate, TContext>): TelegramUpdateAdmissionLifecycleAssembly<TContext>;
1272
+ export interface TelegramUpdateAdmissionRuntimeAssembly<TContext> extends TelegramUpdateAdmissionLifecycleAssembly<TContext> {
1273
+ owner: TelegramUpdateWorkerOwnerRuntime<TContext>;
1274
+ }
1275
+ export type TelegramUpdateAdmissionRuntimeAssemblyDeps<TUpdate extends TelegramJournaledUpdate & TelegramUpdateFlow, TContext> = Omit<TelegramUpdateAdmissionLifecycleAssemblyDeps<TUpdate, TContext>, "worker" | "recordRuntimeEvent"> & {
1276
+ owner: TelegramUpdateWorkerOwnerRuntimeDeps<TContext>;
1277
+ worker: Omit<TelegramUpdateAdmissionLifecycleAssemblyDeps<TUpdate, TContext>["worker"], keyof TelegramUpdateWorkerOwnerRuntime<TContext> | "isContextCurrent" | "recordRuntimeEvent">;
1278
+ recordRuntimeEvent?: TelegramUpdateWorkerRuntimeDeps<TContext>["recordRuntimeEvent"];
1279
+ };
1280
+ /** Own queue-owner projection and shared leader/follower worker composition. */
1281
+ export declare function createTelegramUpdateAdmissionRuntimeAssembly<TUpdate extends TelegramJournaledUpdate & TelegramUpdateFlow, TContext>(deps: TelegramUpdateAdmissionRuntimeAssemblyDeps<TUpdate, TContext>): TelegramUpdateAdmissionRuntimeAssembly<TContext>;
1282
+ /**
1283
+ * Register a handler that runs before pi-telegram routes a Telegram update
1284
+ * through its built-in handlers.
1285
+ *
1286
+ * This is the low-level public surface for extensions that share the same bot
1287
+ * and Pi process with pi-telegram.
1288
+ */
1289
+ export declare function registerTelegramUpdateHandler(handler: TelegramUpdateHandler): () => void;
1290
+ export {};