@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,621 @@
1
+ /**
2
+ * Telegram thread binding helpers
3
+ * Zones: multi-instance bus, Telegram UI threads, volatile extension state
4
+ * Owns current live instance-binding to Telegram UI thread mappings backed by Bot API ForumTopic/message_thread_id transport
5
+ */
6
+ import { type TelegramApiCallOptions } from "./telegram-api.ts";
7
+ import type { TelegramTarget } from "./target.ts";
8
+ import * as ThreadReconciler from "./thread-reconciler.ts";
9
+ import { type TelegramWorkspaceSlotOccupancy } from "./workspace-slots.ts";
10
+ export interface TelegramThreadNameInput {
11
+ seed: string;
12
+ cwd?: string;
13
+ role?: "leader" | "follower";
14
+ peers?: readonly string[];
15
+ slot?: string;
16
+ }
17
+ export interface TelegramWorkspaceBindingIdentity {
18
+ cwd: string;
19
+ workspaceKey: string;
20
+ /** Exact durable Pi session identity; absent only on legacy cwd-only bindings. */
21
+ sessionId?: string;
22
+ /** Full SHA-256 index component for session-qualified bindings. */
23
+ sessionKey?: string;
24
+ /** Immutable legacy binding-key component, not the displayed global letter. */
25
+ instanceSlot: string;
26
+ bindingKey: string;
27
+ /** Profile-wide letter reserved by the transient claim. */
28
+ slot?: string;
29
+ }
30
+ export declare function normalizeTelegramSessionId(sessionId: string): string | undefined;
31
+ export declare function createTelegramSessionKey(sessionId: string): string | undefined;
32
+ export declare function normalizeTelegramWorkspacePath(cwd: string): string | undefined;
33
+ export declare function createTelegramWorkspaceDirectoryKey(cwd: string): string | undefined;
34
+ export declare function createTelegramWorkspaceBindingIdentity(cwd: string, ordinal?: number, sessionId?: string): TelegramWorkspaceBindingIdentity | undefined;
35
+ export type TelegramTopicTargetStatus = "active" | "offline" | "stale" | "pending" | "starting" | "probe-required" | "failed";
36
+ export type TelegramTopicSyncStatus = "open" | "closed" | "deleted" | "unknown";
37
+ export type TelegramThreadOwner = {
38
+ kind: "leader";
39
+ cwd?: string;
40
+ instanceId?: string;
41
+ telegramProfile?: string;
42
+ } | {
43
+ kind: "manual-follower";
44
+ instanceId: string;
45
+ telegramProfile?: string;
46
+ } | {
47
+ kind: "pending-topic";
48
+ chatId: number;
49
+ threadId: number;
50
+ } | {
51
+ kind: "legacy";
52
+ key: string;
53
+ };
54
+ export interface TelegramThreadReservation {
55
+ target: TelegramTarget & {
56
+ threadId: number;
57
+ };
58
+ slot: string;
59
+ reason: string;
60
+ createdAtMs: number;
61
+ updatedAtMs: number;
62
+ expiresAtMs?: number;
63
+ instanceId?: string;
64
+ lastReconcileAction?: string;
65
+ }
66
+ export interface TelegramThreadPendingProvision {
67
+ id: string;
68
+ owner: "leader" | "manual-follower";
69
+ instanceId: string;
70
+ profileKey?: string;
71
+ status?: "in-flight" | "ambiguous";
72
+ threadName?: string;
73
+ displayTitle?: string;
74
+ slot?: string;
75
+ target?: TelegramTarget & {
76
+ threadId: number;
77
+ };
78
+ startedAtMs: number;
79
+ expiresAtMs?: number;
80
+ leaderEpoch?: number | string;
81
+ }
82
+ export type TelegramThreadCleanupIntent = ThreadReconciler.TelegramThreadCleanupIntent;
83
+ export interface TelegramTopicSyncObservation {
84
+ target: TelegramTarget & {
85
+ threadId: number;
86
+ };
87
+ syncStatus: TelegramTopicSyncStatus;
88
+ observedAtMs: number;
89
+ instanceId?: string;
90
+ slot?: string;
91
+ lastSyncError?: string;
92
+ lastReconcileAction?: string;
93
+ }
94
+ export interface TelegramTopicTargetRecord {
95
+ /** Legacy string key derived from `owner`; always present in memory, never persisted. */
96
+ profileKey: string;
97
+ owner?: TelegramThreadOwner;
98
+ target: TelegramTarget & {
99
+ threadId: number;
100
+ };
101
+ status: TelegramTopicTargetStatus;
102
+ createdAtMs: number;
103
+ updatedAtMs: number;
104
+ threadName?: string;
105
+ /** Explicit per-Workspace display override set by the operator. */
106
+ manualThreadName?: string;
107
+ instanceId?: string;
108
+ slot?: string;
109
+ lastError?: string;
110
+ syncStatus?: TelegramTopicSyncStatus;
111
+ lastSyncObservedAtMs?: number;
112
+ lastSyncProbeAtMs?: number;
113
+ lastSyncError?: string;
114
+ lastReconcileAction?: string;
115
+ rerouteConfirmedAtMs?: number;
116
+ }
117
+ export interface TelegramThreadIdentityRecord {
118
+ profileKey: string;
119
+ threadName?: string;
120
+ slot?: string;
121
+ updatedAtMs: number;
122
+ }
123
+ export interface TelegramWorkspaceThreadBinding {
124
+ cwd: string;
125
+ workspaceKey: string;
126
+ /** Exact durable Pi session identity; absent only on legacy cwd-only bindings. */
127
+ sessionId?: string;
128
+ /** Full SHA-256 index component for session-qualified bindings. */
129
+ sessionKey?: string;
130
+ instanceSlot: string;
131
+ bindingKey: string;
132
+ target: TelegramTarget & {
133
+ threadId: number;
134
+ };
135
+ /** Stable generated identity retained for compatibility and recovery. */
136
+ threadName?: string;
137
+ /** Explicit display override; absence selects the profile's automatic mode. */
138
+ manualThreadName?: string;
139
+ slot?: string;
140
+ /** Last title acknowledged by Telegram; never replaces the stable name. */
141
+ displayTitle?: string;
142
+ /** Historical follower-journal routing keys that may retain accepted work. */
143
+ journalBindingKeys?: string[];
144
+ /** True only when the historical journal-key set is proven complete. */
145
+ journalBindingsComplete?: true;
146
+ /** Sticky once this directory has multiple retained bindings. */
147
+ showSlotSuffix?: boolean;
148
+ /** First continuously proven no-owner transition; absent means active or unproven. */
149
+ inactiveSinceMs?: number;
150
+ updatedAtMs: number;
151
+ }
152
+ export type TelegramWorkspaceDisplayBinding = Pick<TelegramWorkspaceThreadBinding, "bindingKey" | "cwd" | "slot" | "threadName" | "manualThreadName" | "showSlotSuffix">;
153
+ export interface TelegramWorkspaceRetirementIntent {
154
+ id: string;
155
+ reason: "pressure";
156
+ profileKey: string;
157
+ binding: TelegramWorkspaceThreadBinding;
158
+ leaderEpoch: number | string;
159
+ requestedAtMs: number;
160
+ }
161
+ export type TelegramWorkspaceProtectionState = "clear" | "protected" | "unknown";
162
+ export interface TelegramWorkspaceExternalProtectionEvidence {
163
+ liveOwner: TelegramWorkspaceProtectionState;
164
+ acceptedWork: TelegramWorkspaceProtectionState;
165
+ deliveryAuthority: TelegramWorkspaceProtectionState;
166
+ }
167
+ export interface TelegramWorkspaceSlotOccupancySnapshot {
168
+ bindings: TelegramWorkspaceSlotOccupancy[];
169
+ reservedSlots: string[];
170
+ }
171
+ export type TelegramBotThreadMode = "unknown" | "enabled" | "disabled";
172
+ export interface TelegramBotStateSnapshot {
173
+ threadMode: TelegramBotThreadMode;
174
+ updatedAtMs?: number;
175
+ lastSlot?: string;
176
+ lastReconcileAction?: string;
177
+ }
178
+ export interface TelegramTopicTargetFile {
179
+ version: 1;
180
+ source: "snapshot";
181
+ writtenAtMs: number;
182
+ bot: TelegramBotStateSnapshot;
183
+ runtime?: Record<string, unknown>;
184
+ liveRoster?: Record<string, unknown>;
185
+ diagnostics?: Record<string, unknown>;
186
+ threads: TelegramTopicTargetRecord[];
187
+ identities?: TelegramThreadIdentityRecord[];
188
+ workspaceBindings?: TelegramWorkspaceThreadBinding[];
189
+ workspaceRetirements?: TelegramWorkspaceRetirementIntent[];
190
+ reservations?: TelegramThreadReservation[];
191
+ pendingProvisions?: TelegramThreadPendingProvision[];
192
+ pendingCleanups?: TelegramThreadCleanupIntent[];
193
+ syncObservations?: TelegramTopicSyncObservation[];
194
+ }
195
+ export interface TelegramTopicTargetStore {
196
+ load: () => Promise<void>;
197
+ /** Discard process-local projections and reload owner-published state. */
198
+ refresh?: () => Promise<void>;
199
+ persist: () => Promise<void>;
200
+ invalidateTarget: (target: TelegramTarget, isCurrent: () => boolean, lastSyncError: string) => Promise<boolean>;
201
+ list: () => TelegramTopicTargetRecord[];
202
+ getFollowerRecoveryHintByTarget?: (target: TelegramTarget) => {
203
+ slot?: string;
204
+ threadName?: string;
205
+ } | undefined;
206
+ listReservations: () => TelegramThreadReservation[];
207
+ listPendingProvisions: () => TelegramThreadPendingProvision[];
208
+ listPendingCleanups: () => TelegramThreadCleanupIntent[];
209
+ listSyncObservations: () => TelegramTopicSyncObservation[];
210
+ reserveThread: (reservation: TelegramThreadReservation) => void;
211
+ upsertPendingProvision: (provision: TelegramThreadPendingProvision) => void;
212
+ recordPendingProvisionTargetRecovery: (provision: TelegramThreadPendingProvision, target: TelegramTarget & {
213
+ threadId: number;
214
+ }) => Promise<boolean>;
215
+ removePendingProvision: (id: string) => boolean;
216
+ upsertPendingCleanup: (intent: TelegramThreadCleanupIntent) => void;
217
+ removePendingCleanup: (id: string) => boolean;
218
+ getBotState: () => TelegramBotStateSnapshot;
219
+ setBotState: (state: Partial<TelegramBotStateSnapshot>) => void;
220
+ setStatusSnapshot: (snapshot: {
221
+ runtime?: Record<string, unknown>;
222
+ liveRoster?: Record<string, unknown>;
223
+ diagnostics?: Record<string, unknown>;
224
+ }) => void;
225
+ getByProfileKey: (profileKey: string) => TelegramTopicTargetRecord | undefined;
226
+ getActiveByInstanceId: (instanceId: string) => TelegramTopicTargetRecord | undefined;
227
+ getIdentityByProfileKey: (profileKey: string) => TelegramThreadIdentityRecord | undefined;
228
+ forgetIdentityByProfileKey: (profileKey: string) => boolean;
229
+ listWorkspaceBindings: () => TelegramWorkspaceThreadBinding[];
230
+ listWorkspaceRetirementIntents: () => TelegramWorkspaceRetirementIntent[];
231
+ commitWorkspaceJournalEvidence: (expected: TelegramWorkspaceThreadBinding, journalBindingKeys: readonly string[], complete: boolean) => TelegramWorkspaceThreadBinding | undefined;
232
+ upsertWorkspaceRetirementIntent: (intent: TelegramWorkspaceRetirementIntent) => boolean;
233
+ removeWorkspaceRetirementIntent: (expected: TelegramWorkspaceRetirementIntent) => boolean;
234
+ replaceWorkspaceRetirementIntent: (expected: TelegramWorkspaceRetirementIntent, replacement: TelegramWorkspaceRetirementIntent, isCurrent: () => boolean) => Promise<boolean>;
235
+ commitWorkspaceRetirement: (expected: TelegramWorkspaceRetirementIntent, isCurrent: () => boolean) => Promise<boolean>;
236
+ commitInactiveWorkspaceCleanup: (expected: TelegramWorkspaceThreadBinding | {
237
+ cwd: string;
238
+ workspaceKey: string;
239
+ sessionId?: string;
240
+ sessionKey?: string;
241
+ instanceSlot: string;
242
+ slot: string;
243
+ bindingKey: string;
244
+ target: {
245
+ chatId: number;
246
+ threadId: number;
247
+ };
248
+ inactiveSinceMs: number;
249
+ bindingUpdatedAtMs: number;
250
+ }, isCurrent: () => boolean) => Promise<boolean>;
251
+ /** Caller must separately prove no external live owner, accepted work, or delivery authority. */
252
+ captureWorkspaceSlotOccupancy: (getExternalProtection: (binding: TelegramWorkspaceThreadBinding) => TelegramWorkspaceExternalProtectionEvidence, options?: {
253
+ expectedRetirement?: TelegramWorkspaceRetirementIntent;
254
+ }) => TelegramWorkspaceSlotOccupancySnapshot;
255
+ hasWorkspaceBinding: (cwd: string, sessionId?: string) => boolean;
256
+ setWorkspaceDisplayTitle: (expected: TelegramWorkspaceThreadBinding, title: string) => boolean;
257
+ markWorkspaceBindingInactiveByTarget: (target: TelegramTarget, inactiveSinceMs?: number) => boolean;
258
+ markWorkspaceBindingActiveByTarget: (target: TelegramTarget) => boolean;
259
+ getWorkspaceBinding: (cwd: string, instanceSlot?: string, sessionId?: string) => TelegramWorkspaceThreadBinding | undefined;
260
+ claimWorkspaceIdentity: (cwd: string, instanceId: string, previousInstanceId?: string, options?: {
261
+ existingBindingOnly?: boolean;
262
+ sessionId?: string;
263
+ onCapacityUnavailable?: () => void;
264
+ }) => TelegramWorkspaceBindingIdentity | undefined;
265
+ releaseWorkspaceClaim: (instanceId: string) => boolean;
266
+ upsertWorkspaceBinding: (binding: TelegramWorkspaceThreadBinding, claimInstanceId?: string) => TelegramWorkspaceThreadBinding | undefined;
267
+ upsert: (record: TelegramTopicTargetRecord) => TelegramTopicTargetRecord;
268
+ markOfflineByInstanceId: (instanceId: string) => number;
269
+ markStaleByTarget: (target: TelegramTarget, syncStatus?: TelegramTopicSyncStatus, lastSyncError?: string) => boolean;
270
+ markActiveByTarget: (target: TelegramTarget) => boolean;
271
+ renameByTarget: (target: TelegramTarget, threadName: string, options?: {
272
+ updateDisplayTitle: boolean;
273
+ }) => TelegramTopicTargetRecord | undefined;
274
+ clearManualNameByTarget: (target: TelegramTarget, automaticTitle: string) => TelegramTopicTargetRecord | undefined;
275
+ allocateSlot: (profileKey: string, preferredSlot?: string, workspaceBindingKey?: string, options?: {
276
+ excludeCurrentRecord?: boolean;
277
+ }) => string | undefined;
278
+ /** Claim the first reusable inactive thread for an instance, linking it to instanceId. */
279
+ claimReusableTarget: (instanceId: string, threadName?: string) => TelegramTopicTargetRecord | undefined;
280
+ }
281
+ export declare function reconcileTelegramFreshAllocationCursor(store: Pick<TelegramTopicTargetStore, "getBotState" | "list" | "setBotState">, nowMs?: number): boolean;
282
+ export declare function createTelegramCleanupTargetProtection(store: Pick<TelegramTopicTargetStore, "list"> & Partial<Pick<TelegramTopicTargetStore, "listReservations" | "listPendingProvisions" | "listPendingCleanups">>, departingRecord?: TelegramTopicTargetRecord): NonNullable<ThreadReconciler.ThreadReconciliationApplyPorts["isCleanupTargetProtected"]>;
283
+ export interface TelegramTopicTargetStoreOptions {
284
+ path: string | (() => string);
285
+ telegramProfile?: string | (() => string | undefined);
286
+ getNowMs?: () => number;
287
+ canPersist?: () => boolean;
288
+ commitPersist?: (commit: () => void) => boolean;
289
+ getExternalReservedSlots?: () => readonly string[];
290
+ }
291
+ export interface TelegramTopicTargetProvisionerDeps {
292
+ topicChatId: number;
293
+ store: Pick<TelegramTopicTargetStore, "list" | "getByProfileKey" | "getActiveByInstanceId" | "getIdentityByProfileKey" | "forgetIdentityByProfileKey" | "upsert" | "markStaleByTarget" | "allocateSlot" | "claimReusableTarget" | "listWorkspaceBindings" | "listPendingProvisions" | "upsertPendingProvision" | "recordPendingProvisionTargetRecovery" | "removePendingProvision" | "listSyncObservations" | "listPendingCleanups" | "persist">;
294
+ callApi: <TResponse>(method: string, body: Record<string, unknown>, options?: TelegramApiCallOptions) => Promise<TResponse>;
295
+ topicNameTemplate?: string;
296
+ resolveInitialWorkspaceDisplayTitle?: (binding: TelegramWorkspaceDisplayBinding) => string | undefined;
297
+ getNowMs?: () => number;
298
+ getRandom?: () => number;
299
+ getCurrentLeaderEpoch?: () => number | string | undefined;
300
+ claimPendingTargets?: boolean;
301
+ }
302
+ export interface TelegramTopicTargetRenamerDeps {
303
+ store: Pick<TelegramTopicTargetStore, "renameByTarget" | "list" | "listWorkspaceBindings" | "listPendingProvisions">;
304
+ callApi: <TResponse>(method: string, body: Record<string, unknown>) => Promise<TResponse>;
305
+ assertAuthority?: () => void;
306
+ shouldRenameDisplayedTitle?: () => boolean;
307
+ topicNameTemplate?: string;
308
+ }
309
+ export interface TelegramTopicTargetProvisionRequest {
310
+ instanceId: string;
311
+ owner?: TelegramThreadOwner;
312
+ /** Legacy string key derived from `owner`; always present in memory. */
313
+ profileKey: string;
314
+ threadName?: string;
315
+ preferredSlot?: string;
316
+ workspaceBindingKey?: string;
317
+ workspaceCwd?: string;
318
+ }
319
+ /** Pending creation evidence cannot bypass an exact target's unresolved cleanup or closure. */
320
+ export declare function assertTelegramPendingTopicRecoveryAllowed(store: Pick<TelegramTopicTargetStore, "listPendingProvisions" | "listPendingCleanups" | "listSyncObservations">, target: TelegramTarget): void;
321
+ /** Settle creation-title evidence with the exact Workspace claim; caller fences and persists. */
322
+ export declare function commitTelegramWorkspaceProvisionBinding(input: {
323
+ store: Pick<TelegramTopicTargetStore, "upsertWorkspaceBinding" | "setWorkspaceDisplayTitle" | "listPendingProvisions" | "removePendingProvision" | "listPendingCleanups" | "listSyncObservations">;
324
+ binding: TelegramWorkspaceThreadBinding;
325
+ instanceId: string;
326
+ profileKey: string;
327
+ displayTitle?: string;
328
+ }): TelegramWorkspaceThreadBinding;
329
+ export interface TelegramTopicTargetRenameRequest {
330
+ target: TelegramTarget & {
331
+ threadId: number;
332
+ };
333
+ threadName: string;
334
+ slot?: string;
335
+ }
336
+ export interface TelegramTopicTargetProvisionResult {
337
+ target: TelegramTarget & {
338
+ threadId: number;
339
+ };
340
+ reused: boolean;
341
+ record: TelegramTopicTargetRecord;
342
+ displayTitle?: string;
343
+ }
344
+ export declare function createTelegramThreadName(input: TelegramThreadNameInput): string;
345
+ export declare function getTelegramStatePath(agentDir?: string, profileName?: string): string;
346
+ export declare function getTelegramTopicTargetsPath(agentDir?: string, profileName?: string): string;
347
+ export declare const TELEGRAM_LEADER_SESSION_HANDOFF_TTL_MS = 30000;
348
+ export interface TelegramLeaderSessionHandoff {
349
+ pid: number;
350
+ instanceId: string;
351
+ createdAtMs: number;
352
+ profileKey: string;
353
+ target: TelegramTarget & {
354
+ threadId: number;
355
+ };
356
+ slot?: string;
357
+ threadName?: string;
358
+ }
359
+ export declare function getTelegramLeaderSessionHandoff(): TelegramLeaderSessionHandoff | undefined;
360
+ export declare function setTelegramLeaderSessionHandoff(handoff: TelegramLeaderSessionHandoff | undefined): void;
361
+ export declare function isTelegramLeaderSessionHandoffFresh(handoff: TelegramLeaderSessionHandoff | undefined, options?: {
362
+ pid?: number;
363
+ nowMs?: number;
364
+ ttlMs?: number;
365
+ }): handoff is TelegramLeaderSessionHandoff;
366
+ export declare function getTelegramThreadOwnerKey(owner: TelegramThreadOwner): string;
367
+ export declare function getTelegramThreadOwnerFromProfileKey(profileKey: string): TelegramThreadOwner;
368
+ export declare function isSameTelegramProcessInstance(left: string | undefined, right: string | undefined): boolean;
369
+ export declare function createTelegramTopicTargetStore(options: TelegramTopicTargetStoreOptions): TelegramTopicTargetStore;
370
+ export declare function normalizeTelegramTopicTargetThreadName(threadName: string): string;
371
+ export declare function getTelegramTopicIdentityName(threadName: string): string;
372
+ export declare function listOccupiedTelegramThreadIdentities(input: {
373
+ records: readonly TelegramTopicTargetRecord[];
374
+ workspaceBindings?: readonly TelegramWorkspaceThreadBinding[];
375
+ pendingProvisions?: readonly TelegramThreadPendingProvision[];
376
+ exceptTarget?: TelegramTarget;
377
+ exceptWorkspaceBindingKey?: string;
378
+ }): string[];
379
+ export declare function chooseTelegramThreadName(input: {
380
+ slot: string | undefined;
381
+ entropy?: number | string;
382
+ getRandom?: () => number;
383
+ occupied?: readonly string[];
384
+ }): string | undefined;
385
+ export declare function getTelegramTopicThreadNameValidationError(threadName: string, _slot: string | undefined): string | undefined;
386
+ export declare function getTelegramManualThreadDisplayNameValidationError(threadName: string): string | undefined;
387
+ export declare function isTelegramTopicThreadNameValidForSlot(threadName: string, slot: string | undefined): boolean;
388
+ export declare function getTelegramTopicName(request: TelegramTopicTargetProvisionRequest, template?: string, slot?: string): string;
389
+ export interface TelegramPromoteFollowerBindingToLeaderDeps {
390
+ store: TelegramTopicTargetStore;
391
+ instanceId: string;
392
+ cwd?: string;
393
+ sessionId?: string;
394
+ telegramProfile?: string;
395
+ target?: TelegramTarget;
396
+ slot?: string;
397
+ threadName?: string;
398
+ nowMs?: number;
399
+ }
400
+ export declare function promoteTelegramFollowerBindingToLeader(deps: TelegramPromoteFollowerBindingToLeaderDeps): Promise<TelegramTopicTargetRecord | undefined>;
401
+ export interface TelegramOwnTopicProvisionDeps {
402
+ getAllowedUserId: () => number | undefined;
403
+ instanceId: string;
404
+ cwd?: string;
405
+ telegramProfile?: string;
406
+ requestedThreadName?: string;
407
+ preferredSlot?: string;
408
+ workspaceBindingKey?: string;
409
+ resolveInitialWorkspaceDisplayTitle?: (binding: TelegramWorkspaceDisplayBinding) => string | undefined;
410
+ getNowMs?: () => number;
411
+ getRandom?: () => number;
412
+ getCurrentLeaderEpoch?: () => number | string | undefined;
413
+ getThreadReconciliationMachineState?: () => ThreadReconciler.ThreadReconciliationMachineState | undefined;
414
+ recordThreadReconciliationPlan?: (plan: ThreadReconciler.ThreadReconciliationPlan) => void;
415
+ store: TelegramTopicTargetStore;
416
+ callApi: <TResponse>(method: string, body: Record<string, unknown>) => Promise<TResponse>;
417
+ recordEvent: (category: string, message: string, details?: Record<string, unknown>) => void;
418
+ }
419
+ export interface TelegramOwnTopicProvisionResult {
420
+ target: TelegramTarget & {
421
+ threadId: number;
422
+ };
423
+ slot: string;
424
+ threadName?: string;
425
+ displayTitle?: string;
426
+ reused: boolean;
427
+ }
428
+ /**
429
+ * Provision a topic for the bus leader's own use (slot A).
430
+ * This is a thread-binding primitive; sync policy decides when startup/connect
431
+ * should call it to ensure the leader has a visible working thread.
432
+ */
433
+ export declare function provisionOwnBusTopic(deps: TelegramOwnTopicProvisionDeps): Promise<TelegramOwnTopicProvisionResult | undefined>;
434
+ export interface TelegramInstanceThreadIdentityCandidate {
435
+ target?: TelegramTarget;
436
+ slot?: string;
437
+ threadName?: string;
438
+ }
439
+ export declare function resolveTelegramInstanceThreadIdentity(options: {
440
+ target?: TelegramTarget;
441
+ follower?: TelegramInstanceThreadIdentityCandidate;
442
+ leader?: TelegramInstanceThreadIdentityCandidate;
443
+ record?: TelegramTopicTargetRecord;
444
+ }): TelegramInstanceThreadIdentityCandidate;
445
+ export interface TelegramLeaderThreadStateRuntime {
446
+ getTarget(): TelegramTarget | undefined;
447
+ getIdentity(): TelegramInstanceThreadIdentityCandidate | undefined;
448
+ set(input: TelegramInstanceThreadIdentityCandidate & {
449
+ target: TelegramTarget;
450
+ }): void;
451
+ clear(): void;
452
+ }
453
+ export declare function createTelegramLeaderThreadStateRuntime(): TelegramLeaderThreadStateRuntime;
454
+ export interface TelegramCurrentInstanceThreadRuntime {
455
+ findRecord(): TelegramTopicTargetRecord | undefined;
456
+ getRecord(): TelegramTopicTargetRecord | undefined;
457
+ getIdentity(target?: TelegramTarget): TelegramInstanceThreadIdentityCandidate;
458
+ getRestorationIdentity(): TelegramInstanceThreadIdentityCandidate;
459
+ }
460
+ export interface TelegramCurrentInstanceThreadRuntimeDeps {
461
+ instanceId: string;
462
+ listRecords(): readonly TelegramTopicTargetRecord[];
463
+ getPreferredTarget(): TelegramTarget | undefined;
464
+ getFollower(): (TelegramInstanceThreadIdentityCandidate & {
465
+ registered: boolean;
466
+ }) | undefined;
467
+ getLeader(): TelegramInstanceThreadIdentityCandidate | undefined;
468
+ }
469
+ export declare function createTelegramCurrentInstanceThreadRuntime(deps: TelegramCurrentInstanceThreadRuntimeDeps): TelegramCurrentInstanceThreadRuntime;
470
+ export declare function findCurrentTelegramInstanceThreadRecord(options: {
471
+ records: readonly TelegramTopicTargetRecord[];
472
+ instanceId: string;
473
+ preferredTarget?: TelegramTarget;
474
+ }): TelegramTopicTargetRecord | undefined;
475
+ export declare function resolveTelegramInstanceThreadTarget(options: {
476
+ followerTarget?: TelegramTarget;
477
+ leaderTarget?: TelegramTarget;
478
+ currentRecord?: TelegramTopicTargetRecord;
479
+ }): (TelegramTarget & {
480
+ threadId: number;
481
+ }) | undefined;
482
+ export interface TelegramThreadStatusProjectionRuntime {
483
+ getBusRole(): "leader" | "follower" | undefined;
484
+ getBusFollowers(): ReturnType<typeof listTelegramThreadStatusFollowers>;
485
+ getLocalBus(): {
486
+ leaderSocketPath: string;
487
+ leaderTransport: "socket" | "pipe";
488
+ followerSocketPath: string;
489
+ followerTransport: "socket" | "pipe";
490
+ followerRegistered: boolean;
491
+ followerTarget?: TelegramTarget;
492
+ followerSlot?: string;
493
+ followerThreadName?: string;
494
+ leaderProtocol?: {
495
+ protocolVersion: number;
496
+ runtimeBuild: string;
497
+ capabilities: string[];
498
+ };
499
+ };
500
+ getTopicTargets(): ReturnType<typeof listTelegramThreadStatusTargets>;
501
+ getThreadReservations(): ReturnType<typeof listTelegramThreadStatusReservations>;
502
+ getTopicSyncObservations(): ReturnType<typeof listTelegramThreadStatusObservations>;
503
+ getInstanceSlot(): string | undefined;
504
+ getInstanceThreadName(): string | undefined;
505
+ }
506
+ export interface TelegramThreadStatusProjectionRuntimeDeps {
507
+ getThreadMode(): "unknown" | "enabled" | "disabled";
508
+ isBusPollingStarted(): boolean;
509
+ isFollowerRegistered(): boolean;
510
+ listFollowers(): readonly TelegramThreadStatusFollowerView[];
511
+ listRecords(): readonly TelegramTopicTargetRecord[];
512
+ listReservations(): readonly TelegramThreadReservation[];
513
+ listSyncObservations(): readonly TelegramTopicSyncObservation[];
514
+ getLeaderSocketPath(): string;
515
+ getFollowerSocketPath(): string;
516
+ getTransportKind(path: string): "socket" | "pipe";
517
+ getFollowerTarget(): TelegramTarget | undefined;
518
+ getFollowerSlot(): string | undefined;
519
+ getFollowerThreadName(): string | undefined;
520
+ getLeaderProtocol?(): {
521
+ protocolVersion: number;
522
+ runtimeBuild: string;
523
+ capabilities: string[];
524
+ } | undefined;
525
+ getCurrentIdentity(): TelegramInstanceThreadIdentityCandidate;
526
+ getDisplayTitle?: (target: TelegramTarget) => string | undefined;
527
+ }
528
+ export declare function createTelegramThreadStatusProjectionRuntime(deps: TelegramThreadStatusProjectionRuntimeDeps): TelegramThreadStatusProjectionRuntime;
529
+ export interface TelegramCurrentThreadAssemblyDeps {
530
+ instanceId: string;
531
+ listRecords: TelegramCurrentInstanceThreadRuntimeDeps["listRecords"];
532
+ listWorkspaceBindings?: () => readonly TelegramWorkspaceThreadBinding[];
533
+ getFollowerDisplayTitle?: () => string | undefined;
534
+ getActiveTurnTarget(): TelegramTarget | undefined;
535
+ getFollowerTarget(): TelegramTarget | undefined;
536
+ isFollowerRegistered(): boolean;
537
+ getFollowerSlot(): string | undefined;
538
+ getFollowerThreadName(): string | undefined;
539
+ getLeaderIdentity(): TelegramInstanceThreadIdentityCandidate | undefined;
540
+ getLeaderTarget(): TelegramTarget | undefined;
541
+ getLeaderProtocol?: TelegramThreadStatusProjectionRuntimeDeps["getLeaderProtocol"];
542
+ status: Pick<TelegramThreadStatusProjectionRuntimeDeps, "getThreadMode" | "isBusPollingStarted" | "listFollowers" | "listReservations" | "listSyncObservations" | "getLeaderSocketPath" | "getFollowerSocketPath" | "getTransportKind">;
543
+ }
544
+ export interface TelegramCurrentThreadAssembly {
545
+ getDisplayTitle: (target: TelegramTarget) => string | undefined;
546
+ current: TelegramCurrentInstanceThreadRuntime;
547
+ status: TelegramThreadStatusProjectionRuntime;
548
+ }
549
+ /** Own current-thread preference and its matching status projection. */
550
+ export declare function createTelegramCurrentThreadAssembly(deps: TelegramCurrentThreadAssemblyDeps): TelegramCurrentThreadAssembly;
551
+ export interface TelegramThreadStatusFollowerView {
552
+ instanceId: string;
553
+ cwd?: string;
554
+ lastHeartbeatMs: number;
555
+ target?: TelegramTarget;
556
+ protocol?: {
557
+ protocolVersion: number;
558
+ runtimeBuild: string;
559
+ capabilities: string[];
560
+ };
561
+ }
562
+ export declare function listTelegramThreadStatusFollowers(options: {
563
+ followers: readonly TelegramThreadStatusFollowerView[];
564
+ records: readonly TelegramTopicTargetRecord[];
565
+ }): Array<{
566
+ instanceId: string;
567
+ cwd?: string;
568
+ lastHeartbeatMs: number;
569
+ target?: TelegramTarget;
570
+ protocol?: {
571
+ protocolVersion: number;
572
+ runtimeBuild: string;
573
+ capabilities: string[];
574
+ };
575
+ slot?: string;
576
+ threadName?: string;
577
+ status?: string;
578
+ }>;
579
+ export declare function listTelegramThreadStatusTargets(records: readonly TelegramTopicTargetRecord[]): Array<{
580
+ instanceId?: string;
581
+ status: TelegramTopicTargetStatus;
582
+ target: TelegramTarget & {
583
+ threadId: number;
584
+ };
585
+ slot?: string;
586
+ threadName?: string;
587
+ syncStatus?: TelegramTopicSyncStatus;
588
+ lastSyncObservedAtMs?: number;
589
+ lastSyncProbeAtMs?: number;
590
+ lastSyncError?: string;
591
+ lastReconcileAction?: string;
592
+ }>;
593
+ export declare function listTelegramThreadStatusReservations(reservations: readonly TelegramThreadReservation[]): Array<{
594
+ target: TelegramTarget & {
595
+ threadId: number;
596
+ };
597
+ slot: string;
598
+ reason: string;
599
+ instanceId?: string;
600
+ expiresAtMs?: number;
601
+ lastReconcileAction?: string;
602
+ }>;
603
+ export declare function listTelegramThreadStatusObservations(observations: readonly TelegramTopicSyncObservation[]): Array<{
604
+ target: TelegramTarget & {
605
+ threadId: number;
606
+ };
607
+ syncStatus: TelegramTopicSyncStatus;
608
+ observedAtMs: number;
609
+ instanceId?: string;
610
+ slot?: string;
611
+ lastSyncError?: string;
612
+ lastReconcileAction?: string;
613
+ }>;
614
+ export declare function getTelegramTargetFromApiBody(body: unknown): (TelegramTarget & {
615
+ threadId: number;
616
+ }) | undefined;
617
+ export declare function isTelegramTopicTargetStaleError(error: unknown): boolean;
618
+ export declare function isTelegramTopicModeUnavailableError(error: unknown): boolean;
619
+ export declare function getTelegramTopicTitleForThreadName(threadName: string, slot: string, template?: string): string;
620
+ export declare function createTelegramTopicTargetRenamer(deps: TelegramTopicTargetRenamerDeps): (request: TelegramTopicTargetRenameRequest) => Promise<TelegramTopicTargetRecord | undefined>;
621
+ export declare function createTelegramTopicTargetProvisioner(deps: TelegramTopicTargetProvisionerDeps): (request: TelegramTopicTargetProvisionRequest) => Promise<TelegramTopicTargetProvisionResult>;