@llblab/pi-telegram 0.51.6 → 0.52.1

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 (178) hide show
  1. package/AGENTS.md +15 -12
  2. package/BACKLOG.md +16 -9
  3. package/CHANGELOG.md +19 -0
  4. package/LICENSE +21 -0
  5. package/README.md +17 -6
  6. package/dist/lib/activity-verbosity.d.ts +1 -5
  7. package/dist/lib/activity-verbosity.js +5 -7
  8. package/dist/lib/bindings.d.ts +5 -1
  9. package/dist/lib/bindings.js +7 -1
  10. package/dist/lib/bus-api.js +8 -5
  11. package/dist/lib/bus-follower.d.ts +54 -56
  12. package/dist/lib/bus-follower.js +206 -139
  13. package/dist/lib/bus-leader.d.ts +21 -2
  14. package/dist/lib/bus-leader.js +181 -25
  15. package/dist/lib/bus-transport.d.ts +4 -1
  16. package/dist/lib/bus-transport.js +28 -4
  17. package/dist/lib/bus.d.ts +52 -56
  18. package/dist/lib/bus.js +78 -246
  19. package/dist/lib/channel-posts.d.ts +1 -3
  20. package/dist/lib/channel-posts.js +23 -26
  21. package/dist/lib/command-templates.d.ts +0 -5
  22. package/dist/lib/command-templates.js +5 -5
  23. package/dist/lib/commands.d.ts +0 -23
  24. package/dist/lib/commands.js +15 -15
  25. package/dist/lib/config.d.ts +0 -17
  26. package/dist/lib/config.js +12 -14
  27. package/dist/lib/delivery.d.ts +0 -4
  28. package/dist/lib/delivery.js +2 -5
  29. package/dist/lib/extension.js +258 -61
  30. package/dist/lib/generative-apps.d.ts +0 -19
  31. package/dist/lib/inbound.d.ts +0 -2
  32. package/dist/lib/inbound.js +2 -2
  33. package/dist/lib/journal.d.ts +183 -16
  34. package/dist/lib/journal.js +1175 -248
  35. package/dist/lib/keyboard.d.ts +0 -2
  36. package/dist/lib/keyboard.js +2 -2
  37. package/dist/lib/lifecycle.js +1 -1
  38. package/dist/lib/locks.d.ts +100 -12
  39. package/dist/lib/locks.js +380 -14
  40. package/dist/lib/logging.d.ts +30 -12
  41. package/dist/lib/logging.js +129 -72
  42. package/dist/lib/media.d.ts +28 -5
  43. package/dist/lib/media.js +26 -8
  44. package/dist/lib/menu-model.d.ts +0 -11
  45. package/dist/lib/menu-model.js +8 -8
  46. package/dist/lib/menu-settings.d.ts +0 -18
  47. package/dist/lib/menu-settings.js +18 -18
  48. package/dist/lib/menu-status.d.ts +4 -4
  49. package/dist/lib/menu-status.js +12 -7
  50. package/dist/lib/menu-thinking.d.ts +1 -1
  51. package/dist/lib/menu-thinking.js +1 -1
  52. package/dist/lib/menu.d.ts +1 -0
  53. package/dist/lib/menu.js +4 -3
  54. package/dist/lib/outbound-attachments.d.ts +0 -1
  55. package/dist/lib/outbound-attachments.js +1 -1
  56. package/dist/lib/outbound-buttons.js +1 -8
  57. package/dist/lib/outbound-markup.d.ts +1 -6
  58. package/dist/lib/outbound-markup.js +4 -21
  59. package/dist/lib/outbound.d.ts +0 -8
  60. package/dist/lib/outbound.js +5 -5
  61. package/dist/lib/paths.d.ts +50 -7
  62. package/dist/lib/paths.js +155 -17
  63. package/dist/lib/pi.d.ts +1 -0
  64. package/dist/lib/pi.js +2 -1
  65. package/dist/lib/polling.d.ts +0 -5
  66. package/dist/lib/polling.js +5 -5
  67. package/dist/lib/preview.d.ts +0 -3
  68. package/dist/lib/preview.js +3 -3
  69. package/dist/lib/prompt-templates.d.ts +0 -1
  70. package/dist/lib/prompt-templates.js +1 -1
  71. package/dist/lib/queue.d.ts +5 -15
  72. package/dist/lib/queue.js +94 -11
  73. package/dist/lib/recovery.d.ts +29 -9
  74. package/dist/lib/recovery.js +104 -33
  75. package/dist/lib/replies.d.ts +0 -4
  76. package/dist/lib/replies.js +1 -1
  77. package/dist/lib/routing.d.ts +74 -8
  78. package/dist/lib/routing.js +2280 -307
  79. package/dist/lib/sections.d.ts +0 -2
  80. package/dist/lib/sections.js +1 -1
  81. package/dist/lib/status.d.ts +44 -9
  82. package/dist/lib/status.js +149 -27
  83. package/dist/lib/sync.d.ts +0 -5
  84. package/dist/lib/sync.js +5 -4
  85. package/dist/lib/telegram-api.d.ts +13 -3
  86. package/dist/lib/telegram-api.js +38 -23
  87. package/dist/lib/thread-cleanup-manager.d.ts +1 -0
  88. package/dist/lib/thread-cleanup-manager.js +18 -21
  89. package/dist/lib/thread-naming.d.ts +32 -5
  90. package/dist/lib/thread-naming.js +191 -7
  91. package/dist/lib/thread-reconciler.d.ts +2 -0
  92. package/dist/lib/thread-reconciler.js +1 -1
  93. package/dist/lib/threads.d.ts +293 -59
  94. package/dist/lib/threads.js +1689 -369
  95. package/dist/lib/turns.d.ts +0 -1
  96. package/dist/lib/turns.js +1 -1
  97. package/dist/lib/updates.d.ts +191 -28
  98. package/dist/lib/updates.js +1048 -114
  99. package/dist/lib/wire.d.ts +12 -0
  100. package/dist/lib/wire.js +21 -0
  101. package/dist/lib/workspace-admission.d.ts +25 -17
  102. package/dist/lib/workspace-admission.js +95 -20
  103. package/dist/lib/workspace-identity.d.ts +20 -0
  104. package/dist/lib/workspace-identity.js +103 -0
  105. package/dist/lib/workspace-retirement.d.ts +43 -8
  106. package/dist/lib/workspace-retirement.js +148 -52
  107. package/dist/package.json +6 -6
  108. package/dist/skills/generated-control-surface/SKILL.md +3 -3
  109. package/dist/skills/telegram-bridge/references/diagnosis.md +3 -3
  110. package/docs/README.md +1 -1
  111. package/docs/activity.md +1 -1
  112. package/docs/architecture.md +156 -36
  113. package/docs/callback-namespaces.md +1 -1
  114. package/docs/delivery.md +1 -1
  115. package/docs/generative-apps.md +2 -2
  116. package/docs/inbound.md +1 -1
  117. package/docs/multi-instance-bus.md +125 -19
  118. package/docs/public-api.md +3 -1
  119. package/docs/ui-style.md +23 -9
  120. package/docs/updates.md +1 -1
  121. package/lib/activity-verbosity.ts +5 -9
  122. package/lib/bindings.ts +7 -0
  123. package/lib/bus-api.ts +9 -4
  124. package/lib/bus-follower.ts +243 -224
  125. package/lib/bus-leader.ts +178 -31
  126. package/lib/bus-transport.ts +30 -8
  127. package/lib/bus.ts +110 -334
  128. package/lib/channel-posts.ts +29 -29
  129. package/lib/command-templates.ts +5 -5
  130. package/lib/commands.ts +15 -15
  131. package/lib/config.ts +12 -17
  132. package/lib/delivery.ts +2 -8
  133. package/lib/extension.ts +261 -72
  134. package/lib/generative-apps.ts +0 -22
  135. package/lib/inbound.ts +2 -2
  136. package/lib/journal.ts +1250 -325
  137. package/lib/keyboard.ts +2 -2
  138. package/lib/lifecycle.ts +1 -1
  139. package/lib/locks.ts +402 -23
  140. package/lib/logging.ts +151 -101
  141. package/lib/media.ts +51 -9
  142. package/lib/menu-model.ts +8 -8
  143. package/lib/menu-settings.ts +18 -18
  144. package/lib/menu-status.ts +11 -0
  145. package/lib/menu-thinking.ts +2 -2
  146. package/lib/menu.ts +5 -1
  147. package/lib/outbound-attachments.ts +1 -1
  148. package/lib/outbound-buttons.ts +1 -10
  149. package/lib/outbound-markup.ts +5 -24
  150. package/lib/outbound.ts +5 -5
  151. package/lib/paths.ts +177 -17
  152. package/lib/pi.ts +5 -2
  153. package/lib/polling.ts +5 -5
  154. package/lib/preview.ts +3 -3
  155. package/lib/prompt-templates.ts +1 -1
  156. package/lib/queue.ts +93 -12
  157. package/lib/recovery.ts +104 -44
  158. package/lib/replies.ts +1 -1
  159. package/lib/routing.ts +2010 -375
  160. package/lib/sections.ts +1 -1
  161. package/lib/status.ts +156 -36
  162. package/lib/sync.ts +4 -4
  163. package/lib/telegram-api.ts +53 -33
  164. package/lib/thread-cleanup-manager.ts +24 -21
  165. package/lib/thread-naming.ts +267 -9
  166. package/lib/thread-reconciler.ts +3 -1
  167. package/lib/threads.ts +1736 -488
  168. package/lib/turns.ts +1 -1
  169. package/lib/updates.ts +1094 -151
  170. package/lib/wire.ts +28 -0
  171. package/lib/workspace-admission.ts +97 -47
  172. package/lib/workspace-identity.ts +147 -0
  173. package/lib/workspace-retirement.ts +188 -89
  174. package/package.json +6 -6
  175. package/scripts/audit-exports.mjs +100 -0
  176. package/scripts/check-downgrade.mjs +80 -43
  177. package/skills/generated-control-surface/SKILL.md +3 -3
  178. package/skills/telegram-bridge/references/diagnosis.md +3 -3
@@ -1,37 +1,17 @@
1
1
  /**
2
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
3
+ * Zones: multi-instance bus, Telegram UI threads, durable Workspace state
4
+ * Owns live mappings, Workspace bindings and guarded Restore transitions; routing and transport effects stay outside.
5
5
  */
6
6
  import { type TelegramApiCallOptions } from "./telegram-api.ts";
7
- import type { TelegramTarget } from "./target.ts";
7
+ import { type TelegramTarget } from "./target.ts";
8
+ export { chooseTelegramThreadName, createTelegramThreadName, getTelegramManualThreadDisplayNameValidationError, getTelegramTopicIdentityName, getTelegramTopicThreadNameValidationError, getTelegramTopicTitleForThreadName, isTelegramTopicThreadNameValidForSlot, type TelegramThreadNameInput, } from "./thread-naming.ts";
9
+ export declare const getTelegramTopicName: (request: TelegramTopicTargetProvisionRequest, template?: string, slot?: string) => string;
10
+ import { type TelegramWorkspaceBindingIdentity } from "./workspace-identity.ts";
11
+ export { createTelegramWorkspaceBindingIdentity, createTelegramWorkspaceDirectoryKey, normalizeTelegramSessionId, normalizeTelegramWorkspacePath, type TelegramWorkspaceBindingIdentity, } from "./workspace-identity.ts";
12
+ import { type TelegramLockRuntime, type TelegramLockContext, type TelegramRuntimeStateMutation, type TelegramOwnedStatePublicationOptions, type TelegramOwnedStatePublicationResult } from "./locks.ts";
8
13
  import * as ThreadReconciler from "./thread-reconciler.ts";
9
14
  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
15
  export type TelegramTopicTargetStatus = "active" | "offline" | "stale" | "pending" | "starting" | "probe-required" | "failed";
36
16
  export type TelegramTopicSyncStatus = "open" | "closed" | "deleted" | "unknown";
37
17
  export type TelegramThreadOwner = {
@@ -81,6 +61,14 @@ export interface TelegramThreadPendingProvision {
81
61
  leaderEpoch?: number | string;
82
62
  }
83
63
  export type TelegramThreadCleanupIntent = ThreadReconciler.TelegramThreadCleanupIntent;
64
+ export type TelegramProvisionRecoveryFile = Record<string, {
65
+ instanceId: string;
66
+ profileKey?: string;
67
+ leaderEpoch?: number | string;
68
+ target: TelegramTarget & {
69
+ threadId: number;
70
+ };
71
+ }>;
84
72
  export interface TelegramTopicSyncObservation {
85
73
  target: TelegramTarget & {
86
74
  threadId: number;
@@ -121,6 +109,10 @@ export interface TelegramThreadIdentityRecord {
121
109
  slot?: string;
122
110
  updatedAtMs: number;
123
111
  }
112
+ export interface TelegramWorkspaceJournalSource {
113
+ sessionId: string;
114
+ recipientBindingKey: string;
115
+ }
124
116
  export interface TelegramWorkspaceThreadBinding {
125
117
  cwd: string;
126
118
  workspaceKey: string;
@@ -142,6 +134,8 @@ export interface TelegramWorkspaceThreadBinding {
142
134
  displayTitle?: string;
143
135
  /** Historical follower-journal routing keys that may retain accepted work. */
144
136
  journalBindingKeys?: string[];
137
+ /** Exact session-qualified journal addresses; retained across session re-key. */
138
+ journalSources?: TelegramWorkspaceJournalSource[];
145
139
  /** True only when the historical journal-key set is proven complete. */
146
140
  journalBindingsComplete?: true;
147
141
  /** Sticky once this directory has multiple retained bindings. */
@@ -176,6 +170,223 @@ export interface TelegramBotStateSnapshot {
176
170
  lastSlot?: string;
177
171
  lastReconcileAction?: string;
178
172
  }
173
+ export interface TelegramWorkspaceRelocationRequest {
174
+ operationId: string;
175
+ binding: TelegramWorkspaceThreadBinding;
176
+ owner: TelegramTopicTargetRecord;
177
+ target: TelegramTarget & {
178
+ threadId: number;
179
+ };
180
+ }
181
+ export interface TelegramWorkspaceRestoreRequest extends TelegramWorkspaceRelocationRequest {
182
+ source: {
183
+ journalBindingKey: string;
184
+ updateIds: number[];
185
+ };
186
+ }
187
+ export interface TelegramWorkspaceRestoreExecutor {
188
+ instanceId: string;
189
+ leaderEpoch: string;
190
+ }
191
+ export interface TelegramWorkspaceRestoreAuthority {
192
+ executor: TelegramWorkspaceRestoreExecutor;
193
+ operatorUserId: number;
194
+ /** Exact profile, transport, session, source and Workspace-admission authority. */
195
+ isCurrent: () => boolean;
196
+ }
197
+ export type TelegramWorkspaceRestoreRecipient = {
198
+ kind: "leader" | "follower";
199
+ instanceId: string;
200
+ sessionId: string;
201
+ generation: string;
202
+ };
203
+ /** Retained queue admission is nonterminal; queue-completed requires positive journal-owner disposition. */
204
+ export type TelegramWorkspaceRestoreSourceSettlement = {
205
+ journalBindingKey: string;
206
+ updateIds: number[];
207
+ } & ({
208
+ kind: "completed";
209
+ } | {
210
+ kind: "queued" | "queue-completed";
211
+ receiptId: string;
212
+ queueKind: "prompt" | "control";
213
+ });
214
+ /** Positive execution/recipient acceptance, retained before source disposition; never a source-removal ACK. */
215
+ export type TelegramWorkspaceRestoreSourceAcceptance = {
216
+ journalBindingKey: string;
217
+ updateId: number;
218
+ /** SHA-256 of the exact journal entry captured by its worker owner, not a routed message projection. */
219
+ sourceSha256: string;
220
+ recipient: TelegramWorkspaceRestoreRecipient;
221
+ } & ({
222
+ kind: "completed";
223
+ } | {
224
+ kind: "forwarded";
225
+ deliveryId: string;
226
+ recipientBindingKey: string;
227
+ } | {
228
+ kind: "queued";
229
+ receiptId: string;
230
+ queueKind: "prompt" | "control";
231
+ queueOwnerSha256: string;
232
+ });
233
+ export interface TelegramWorkspaceRestoreIntent {
234
+ request: TelegramWorkspaceRestoreRequest;
235
+ operatorUserId: number;
236
+ executor: TelegramWorkspaceRestoreExecutor;
237
+ revision: number;
238
+ createdAtMs: number;
239
+ updatedAtMs: number;
240
+ phase: "relocated" | "recipient-issued" | "ready";
241
+ committedAtMs: number;
242
+ recipient?: TelegramWorkspaceRestoreRecipient;
243
+ readyRecipient?: TelegramWorkspaceRestoreRecipient;
244
+ routing?: {
245
+ acceptances?: TelegramWorkspaceRestoreSourceAcceptance[];
246
+ settlements: TelegramWorkspaceRestoreSourceSettlement[];
247
+ cleanup?: "issued" | "completed" | "not-issued";
248
+ };
249
+ }
250
+ /** Immutable source membership, not readiness, cancellation, or proof of complete Thread coverage. */
251
+ export interface TelegramTemporaryThreadInput {
252
+ journalBindingKey: string;
253
+ updateIds: number[];
254
+ }
255
+ /** Journal-owned donor discard evidence: retained manual cancellation or body-free chooser expiry, never recipient cancellation. */
256
+ export interface TelegramTemporaryThreadCancellationEvidence {
257
+ journalBindingKey: string;
258
+ updateId: number;
259
+ operatorAuthorityId: string;
260
+ }
261
+ /** A bot-created routing tab with an exact creation source; it owns no Pi binding or slot. */
262
+ export interface TelegramTemporaryThreadEntry {
263
+ source: {
264
+ journalBindingKey: string;
265
+ updateId: number;
266
+ };
267
+ /** Append-only known source groups. Missing legacy metadata never proves that the creation source was alone. */
268
+ inputs?: TelegramTemporaryThreadInput[];
269
+ /** Whole known groups with positively observed donor cancellation or expiry; never recipient cancellation or deletion authority. */
270
+ cancelledInputs?: TelegramTemporaryThreadInput[];
271
+ /** Whole known groups whose Forward was positively completed by the journal owner; never deletion authority alone. */
272
+ completedInputs?: TelegramTemporaryThreadInput[];
273
+ /** Whole known groups whose Forward was durably issued before local handling/queueing or follower RPC; never delivery proof or a retry grant. */
274
+ forwardedInputs?: TelegramTemporaryThreadInput[];
275
+ /** Published at creation only: every subsequent Forward path must record issuance; missing legacy coverage stays unknown. */
276
+ forwardProtocol?: "one-shot-v1";
277
+ /** Published before the sole cleanup attempt; uncertainty survives executor adoption and restart. */
278
+ cleanupIssued?: true;
279
+ operatorUserId: number;
280
+ executor: TelegramWorkspaceRestoreExecutor;
281
+ /** Unique title token; the only identity an unacknowledged creation may later be matched by. */
282
+ token: string;
283
+ /** `creating` is published before the one creation request, so after a crash its outcome is unknown. */
284
+ phase: "creating" | "created";
285
+ target?: TelegramTarget & {
286
+ threadId: number;
287
+ };
288
+ revision: number;
289
+ createdAtMs: number;
290
+ updatedAtMs: number;
291
+ }
292
+ /** Canonical target classification only; a bound target still needs live same-session readiness proof. */
293
+ export type TelegramTemporaryThreadTargetObservation = {
294
+ kind: "bound";
295
+ binding: TelegramWorkspaceThreadBinding;
296
+ } | {
297
+ kind: "temporary";
298
+ } | {
299
+ kind: "unknown";
300
+ };
301
+ interface TelegramWorkspaceRestoreSnapshot {
302
+ version: 1;
303
+ profileName: string;
304
+ tokenSha256: string;
305
+ revision: number;
306
+ operations: TelegramWorkspaceRestoreIntent[];
307
+ temporaryThreads?: TelegramTemporaryThreadEntry[];
308
+ }
309
+ /** Scope-bound Workspace operations; raw snapshot mutation is private to the store. */
310
+ export interface TelegramWorkspaceRestore {
311
+ list(): TelegramWorkspaceRestoreIntent[];
312
+ commit(request: TelegramWorkspaceRestoreRequest, authority: TelegramWorkspaceRestoreAuthority): Promise<TelegramWorkspaceRestoreIntent | undefined>;
313
+ adopt(expected: TelegramWorkspaceRestoreIntent, authority: TelegramWorkspaceRestoreAuthority): TelegramWorkspaceRestoreIntent | undefined;
314
+ issueRecipient(expected: TelegramWorkspaceRestoreIntent, recipient: TelegramWorkspaceRestoreRecipient, authority: TelegramWorkspaceRestoreAuthority): {
315
+ issued: true;
316
+ intent: TelegramWorkspaceRestoreIntent;
317
+ } | undefined;
318
+ confirmReady(expected: TelegramWorkspaceRestoreIntent, acknowledged: TelegramWorkspaceRestoreRecipient, authority: TelegramWorkspaceRestoreAuthority): TelegramWorkspaceRestoreIntent | undefined;
319
+ confirmInspectedReady(expected: TelegramWorkspaceRestoreIntent, observed: TelegramWorkspaceRestoreRecipient, authority: TelegramWorkspaceRestoreAuthority): TelegramWorkspaceRestoreIntent | undefined;
320
+ issueRouting(expected: TelegramWorkspaceRestoreIntent, authority: TelegramWorkspaceRestoreAuthority): {
321
+ issued: true;
322
+ intent: TelegramWorkspaceRestoreIntent;
323
+ } | undefined;
324
+ recordSourceAcceptance(expected: TelegramWorkspaceRestoreIntent, evidence: TelegramWorkspaceRestoreSourceAcceptance, authority: TelegramWorkspaceRestoreAuthority): TelegramWorkspaceRestoreIntent | undefined;
325
+ recordSourceSettlement(expected: TelegramWorkspaceRestoreIntent, evidence: TelegramWorkspaceRestoreSourceSettlement, authority: TelegramWorkspaceRestoreAuthority): TelegramWorkspaceRestoreIntent | undefined;
326
+ issueCleanup(expected: TelegramWorkspaceRestoreIntent, authority: TelegramWorkspaceRestoreAuthority): {
327
+ issued: true;
328
+ intent: TelegramWorkspaceRestoreIntent;
329
+ } | undefined;
330
+ recordCleanup(expected: TelegramWorkspaceRestoreIntent, result: {
331
+ target: TelegramWorkspaceRestoreRequest["target"];
332
+ kind: "completed" | "not-issued";
333
+ }, authority: TelegramWorkspaceRestoreAuthority): TelegramWorkspaceRestoreIntent | undefined;
334
+ retire(expected: TelegramWorkspaceRestoreIntent, authority: TelegramWorkspaceRestoreAuthority): TelegramWorkspaceRestoreIntent | undefined;
335
+ /** Caller proves exact operator abandonment of every original; no dispatch grant may exist. */
336
+ retireAbandoned(expected: TelegramWorkspaceRestoreIntent, abandonedUpdateIds: readonly number[], authority: TelegramWorkspaceRestoreAuthority): TelegramWorkspaceRestoreIntent | undefined;
337
+ listTemporaryThreads(): TelegramTemporaryThreadEntry[];
338
+ /** Caller holds admission for effectful use. Fresh exact read grants no adoption, routing, disposition or deletion. */
339
+ inspectTemporaryThreadTarget(expected: TelegramTemporaryThreadEntry, authority: TelegramWorkspaceRestoreAuthority): TelegramTemporaryThreadTargetObservation | undefined;
340
+ /** Read-only veto for an already-granted in-flight attempt; never another grant, disposable classification or deletion ACK. */
341
+ isTemporaryThreadCleanupCurrent(expected: TelegramTemporaryThreadEntry, authority: TelegramWorkspaceRestoreAuthority): boolean;
342
+ /** Publishes `creating` before the caller's single creation request; an existing source entry is returned, never recreated. */
343
+ reserveTemporaryThread(source: TelegramTemporaryThreadEntry["source"], token: string, authority: TelegramWorkspaceRestoreAuthority): {
344
+ reserved: boolean;
345
+ entry: TelegramTemporaryThreadEntry;
346
+ } | undefined;
347
+ /** Caller proves a fresh owner-authenticated implicit Telegram creation and exact live source under profile admission.
348
+ * Registers that observed unbound target without issuing or fabricating a Bot API creation. */
349
+ registerImplicitTemporaryThread(input: TelegramTemporaryThreadInput, target: TelegramTarget & {
350
+ threadId: number;
351
+ }, token: string, authority: TelegramWorkspaceRestoreAuthority): TelegramTemporaryThreadEntry | undefined;
352
+ /** Records the exact acknowledged creation target; it never reopens a created entry. */
353
+ acknowledgeTemporaryThread(expected: TelegramTemporaryThreadEntry, target: TelegramTarget & {
354
+ threadId: number;
355
+ }, authority: TelegramWorkspaceRestoreAuthority): TelegramTemporaryThreadEntry | undefined;
356
+ adoptTemporaryThread(expected: TelegramTemporaryThreadEntry, authority: TelegramWorkspaceRestoreAuthority): TelegramTemporaryThreadEntry | undefined;
357
+ /** Caller supplies exact live source/group authority; duplicate membership is read-only, never a new dispatch grant. */
358
+ recordTemporaryThreadInput(expected: TelegramTemporaryThreadEntry, input: TelegramTemporaryThreadInput, authority: TelegramWorkspaceRestoreAuthority): TelegramTemporaryThreadEntry | undefined;
359
+ /** Records a positively completed Forward group; the caller proves every source of the group completed. */
360
+ /** Publishes the one-time Forward issuance fact before any RPC; a duplicate, cancelled, completed or Restore-owned group is refused. */
361
+ recordTemporaryThreadForwardIssued(expected: TelegramTemporaryThreadEntry, input: TelegramTemporaryThreadInput, authority: TelegramWorkspaceRestoreAuthority): TelegramTemporaryThreadEntry | undefined;
362
+ recordTemporaryThreadInputCompletion(expected: TelegramTemporaryThreadEntry, input: TelegramTemporaryThreadInput, authority: TelegramWorkspaceRestoreAuthority): TelegramTemporaryThreadEntry | undefined;
363
+ recordTemporaryThreadInputCancellation(expected: TelegramTemporaryThreadEntry, input: TelegramTemporaryThreadInput, authority: TelegramWorkspaceRestoreAuthority, inspect: (updateId: number) => TelegramTemporaryThreadCancellationEvidence | undefined): TelegramTemporaryThreadEntry | undefined;
364
+ /** Body-free chooser expiry may terminate an uncertain donor Forward/Restore, never accepted recipient work or a bound target. */
365
+ recordTemporaryThreadInputExpiry(expected: TelegramTemporaryThreadEntry, input: TelegramTemporaryThreadInput, authority: TelegramWorkspaceRestoreAuthority, inspect: (updateId: number) => TelegramTemporaryThreadCancellationEvidence | undefined): TelegramTemporaryThreadEntry | undefined;
366
+ /** Caller holds profile admission and proves fresh source/protection clearance; publication grants one attempt, never retry. */
367
+ issueTemporaryThreadCleanup(expected: TelegramTemporaryThreadEntry, authority: TelegramWorkspaceRestoreAuthority): {
368
+ issued: true;
369
+ entry: TelegramTemporaryThreadEntry;
370
+ } | undefined;
371
+ /** Caller proves source settlement or cancellation and target disposition; this releases protection only. */
372
+ /** `completed` names one newly completed group; every other known group must already be cancelled or completed. */
373
+ retireTemporaryThread(expected: TelegramTemporaryThreadEntry, authority: TelegramWorkspaceRestoreAuthority, completed?: TelegramTemporaryThreadInput): TelegramTemporaryThreadEntry | undefined;
374
+ /** New-world restart: atomically forgets this operator's Restore intents and temporary entries from previous runtime instances.
375
+ * Caller may preserve exact unbound temporary tokens for clock-bearing sources. Committed bindings stay; nothing is rolled back, replayed or deleted here. */
376
+ forgetPreviousWorld(authority: TelegramWorkspaceRestoreAuthority, preserveTemporaryTokens?: readonly string[]): {
377
+ operations: TelegramWorkspaceRestoreIntent[];
378
+ temporaryThreads: TelegramTemporaryThreadEntry[];
379
+ } | undefined;
380
+ }
381
+ export interface TelegramWorkspaceRestoreOptions {
382
+ profileName: string;
383
+ tokenSha256: string;
384
+ isCurrentScope?: () => boolean;
385
+ maxBytes?: number;
386
+ getNowMs?: () => number;
387
+ legacyPath?: string;
388
+ onPublicationBoundary?: (boundary: "after-write-before-rename" | "after-rename") => void;
389
+ }
179
390
  export interface TelegramSessionReplacementIntent {
180
391
  continuity: "workspace-thread" | "classic-chat";
181
392
  cwd: string;
@@ -200,13 +411,11 @@ export interface TelegramTopicTargetFile {
200
411
  source: "snapshot";
201
412
  writtenAtMs: number;
202
413
  bot: TelegramBotStateSnapshot;
203
- runtime?: Record<string, unknown>;
204
- liveRoster?: Record<string, unknown>;
205
- diagnostics?: Record<string, unknown>;
206
414
  threads: TelegramTopicTargetRecord[];
207
415
  identities?: TelegramThreadIdentityRecord[];
208
416
  workspaceBindings?: TelegramWorkspaceThreadBinding[];
209
417
  workspaceRetirements?: TelegramWorkspaceRetirementIntent[];
418
+ workspaceRestore?: TelegramWorkspaceRestoreSnapshot;
210
419
  sessionReplacement?: TelegramSessionReplacementIntent;
211
420
  reservations?: TelegramThreadReservation[];
212
421
  pendingProvisions?: TelegramThreadPendingProvision[];
@@ -221,6 +430,20 @@ export interface TelegramTopicTargetStore {
221
430
  invalidateTarget: (target: TelegramTarget, isCurrent: () => boolean, lastSyncError: string) => Promise<boolean>;
222
431
  /** Caller proves owner detachment; this does not assert Telegram Thread absence. */
223
432
  detachTargetOwner: (expected: TelegramTopicTargetRecord, isCurrent: () => boolean) => Promise<boolean>;
433
+ /** Caller holds Workspace admission; publication uses this store's exact transport-owner fence. */
434
+ workspaceRestore: (options: TelegramWorkspaceRestoreOptions) => TelegramWorkspaceRestore;
435
+ /** Read-only precondition under caller-owned admission; not registration or transport authority. */
436
+ assertWorkspaceRestoreRegistration: (candidate: {
437
+ target: TelegramTarget;
438
+ bindingKey?: string;
439
+ slot?: string;
440
+ }) => void;
441
+ /** Runs synchronous live publication under the same evidence transaction; caller retains authentication/admission. */
442
+ commitWorkspaceRestoreRegistration: (candidate: Parameters<TelegramTopicTargetStore["assertWorkspaceRestoreRegistration"]>[0], publish: () => void) => void;
443
+ /** Read-only canonical observation; the callback must finish synchronously under the snapshot transaction. */
444
+ withWorkspaceRestoreSnapshot: (expected: TelegramWorkspaceRestoreIntent, observe: (snapshot: Readonly<Pick<TelegramTopicTargetFile, "threads" | "workspaceBindings">>) => undefined) => void;
445
+ /** Fresh strict disk read of acknowledged temporary-tab targets; throws rather than guessing absence. */
446
+ listTemporaryThreadTargets: () => TelegramTarget[];
224
447
  list: () => TelegramTopicTargetRecord[];
225
448
  getFollowerRecoveryHintByTarget?: (target: TelegramTarget) => {
226
449
  slot?: string;
@@ -245,6 +468,8 @@ export interface TelegramTopicTargetStore {
245
468
  liveRoster?: Record<string, unknown>;
246
469
  diagnostics?: Record<string, unknown>;
247
470
  }) => void;
471
+ /** Writes the non-canonical status projection to its own file; it never touches canonical state or grants authority. */
472
+ persistStatus: () => Promise<void>;
248
473
  getByProfileKey: (profileKey: string) => TelegramTopicTargetRecord | undefined;
249
474
  getActiveByInstanceId: (instanceId: string) => TelegramTopicTargetRecord | undefined;
250
475
  getIdentityByProfileKey: (profileKey: string) => TelegramThreadIdentityRecord | undefined;
@@ -255,7 +480,10 @@ export interface TelegramTopicTargetStore {
255
480
  commitSessionReplacementIntent: (intent: TelegramSessionReplacementIntent, isCurrent: () => boolean) => Promise<boolean>;
256
481
  removeSessionReplacementIntent: (expected: TelegramSessionReplacementIntent, isCurrent: () => boolean) => Promise<boolean>;
257
482
  listWorkspaceRetirementIntents: () => TelegramWorkspaceRetirementIntent[];
258
- commitWorkspaceJournalEvidence: (expected: TelegramWorkspaceThreadBinding, journalBindingKeys: readonly string[], complete: boolean) => TelegramWorkspaceThreadBinding | undefined;
483
+ /** Metadata subset CAS only: callers prove exact-source/writer evidence; independent snapshot roots are untouched. */
484
+ commitWorkspaceJournalEvidence: (expected: TelegramWorkspaceThreadBinding, journalBindingKeys: readonly string[], complete: boolean, journalSources?: readonly TelegramWorkspaceJournalSource[]) => TelegramWorkspaceThreadBinding | undefined;
485
+ /** Acknowledge publication of the exact current metadata frame; never roll it back after an uncertain write. */
486
+ persistWorkspaceJournalEvidence: (expected: TelegramWorkspaceThreadBinding, isCurrent: () => boolean) => Promise<boolean>;
259
487
  upsertWorkspaceRetirementIntent: (intent: TelegramWorkspaceRetirementIntent) => boolean;
260
488
  removeWorkspaceRetirementIntent: (expected: TelegramWorkspaceRetirementIntent) => boolean;
261
489
  replaceWorkspaceRetirementIntent: (expected: TelegramWorkspaceRetirementIntent, replacement: TelegramWorkspaceRetirementIntent, isCurrent: () => boolean) => Promise<boolean>;
@@ -306,13 +534,14 @@ export interface TelegramTopicTargetStore {
306
534
  claimReusableTarget: (instanceId: string, threadName?: string) => TelegramTopicTargetRecord | undefined;
307
535
  }
308
536
  export declare function reconcileTelegramFreshAllocationCursor(store: Pick<TelegramTopicTargetStore, "getBotState" | "list" | "setBotState">, nowMs?: number): boolean;
309
- export declare function createTelegramCleanupTargetProtection(store: Pick<TelegramTopicTargetStore, "list"> & Partial<Pick<TelegramTopicTargetStore, "listReservations" | "listPendingProvisions" | "listPendingCleanups">>, departingRecord?: TelegramTopicTargetRecord): NonNullable<ThreadReconciler.ThreadReconciliationApplyPorts["isCleanupTargetProtected"]>;
537
+ export declare function createTelegramCleanupTargetProtection(store: Pick<TelegramTopicTargetStore, "list"> & Partial<Pick<TelegramTopicTargetStore, "listReservations" | "listPendingProvisions" | "listPendingCleanups" | "listTemporaryThreadTargets">>, departingRecord?: TelegramTopicTargetRecord): NonNullable<ThreadReconciler.ThreadReconciliationApplyPorts["isCleanupTargetProtected"]>;
310
538
  export interface TelegramTopicTargetStoreOptions {
311
539
  path: string | (() => string);
312
540
  telegramProfile?: string | (() => string | undefined);
313
541
  getNowMs?: () => number;
314
542
  canPersist?: () => boolean;
315
543
  commitPersist?: (commit: () => void) => boolean;
544
+ consolidated?: Pick<TelegramConsolidatedWorkspaceStorageOptions, "captureAuthority" | "publishIfOwned">;
316
545
  getExternalReservedSlots?: () => readonly string[];
317
546
  }
318
547
  export interface TelegramTopicTargetProvisionerDeps {
@@ -368,7 +597,6 @@ export interface TelegramTopicTargetProvisionResult {
368
597
  record: TelegramTopicTargetRecord;
369
598
  displayTitle?: string;
370
599
  }
371
- export declare function createTelegramThreadName(input: TelegramThreadNameInput): string;
372
600
  export declare function getTelegramStatePath(agentDir?: string, profileName?: string): string;
373
601
  export declare function getTelegramTopicTargetsPath(agentDir?: string, profileName?: string): string;
374
602
  export declare const TELEGRAM_LEADER_SESSION_HANDOFF_TTL_MS = 30000;
@@ -385,35 +613,42 @@ export interface TelegramLeaderSessionHandoff {
385
613
  }
386
614
  export declare function getTelegramLeaderSessionHandoff(): TelegramLeaderSessionHandoff | undefined;
387
615
  export declare function setTelegramLeaderSessionHandoff(handoff: TelegramLeaderSessionHandoff | undefined): void;
388
- export declare function isTelegramLeaderSessionHandoffFresh(handoff: TelegramLeaderSessionHandoff | undefined, options?: {
389
- pid?: number;
390
- nowMs?: number;
391
- ttlMs?: number;
392
- }): handoff is TelegramLeaderSessionHandoff;
393
616
  export declare function getTelegramThreadOwnerKey(owner: TelegramThreadOwner): string;
394
617
  export declare function getTelegramThreadOwnerFromProfileKey(profileKey: string): TelegramThreadOwner;
395
618
  export declare function normalizeTelegramSessionReplacementIntent(value: unknown): TelegramSessionReplacementIntent | undefined;
619
+ export declare const isTelegramWorkspaceRestoreRecipient: (value: unknown) => value is TelegramWorkspaceRestoreRecipient;
620
+ export declare function isTelegramWorkspaceRestoreRequest(value: unknown): value is TelegramWorkspaceRestoreRequest;
621
+ /** Stable acceptance scope, not a removal ACK; adoption and mutable progress cannot change it. */
622
+ export declare function getTelegramWorkspaceRestoreSourceCompletionSha256(operation: TelegramWorkspaceRestoreIntent, acceptance: TelegramWorkspaceRestoreSourceAcceptance): string;
623
+ export declare function getTelegramTemporaryThreadInputs(entry: TelegramTemporaryThreadEntry): TelegramTemporaryThreadInput[];
624
+ /** Every known group is durably cancelled or Forward-completed; still not deletion authority by itself. */
625
+ export declare function isTelegramTemporaryThreadFullyResolved(entry: TelegramTemporaryThreadEntry): boolean;
626
+ /** The unified section accepts only lossless current-format Workspace evidence, never tolerant legacy repair. */
627
+ export declare function parseTelegramWorkspaceStateSection(value: unknown, profile: string): TelegramTopicTargetFile | undefined;
628
+ export declare function resolveTelegramWorkspaceProvisionRecoveryPath(statePath: string, profileName?: string, layout?: "consolidated"): string;
629
+ export interface TelegramConsolidatedWorkspaceStorageOptions {
630
+ getPath: () => string;
631
+ getProfile: () => string | undefined;
632
+ /** Exact owner/context/session grant captured before the caller's first await. */
633
+ captureAuthority: () => (() => boolean) | undefined;
634
+ publishIfOwned: NonNullable<TelegramLockRuntime<TelegramLockContext>["publishStateSectionIfOwned"]>;
635
+ }
636
+ export type TelegramWorkspaceStatePublication = <T>(mutate: (current: unknown) => TelegramRuntimeStateMutation<T>, publication?: Partial<Pick<TelegramOwnedStatePublicationOptions, "onPublicationBoundary" | "publishRename" | "isCurrent">>) => TelegramOwnedStatePublicationResult<T>;
637
+ /** Prepared Workspace IO adapter; transition/CAS policy remains with the existing Threads owner. */
638
+ export declare function createTelegramConsolidatedWorkspaceStorage(options: TelegramConsolidatedWorkspaceStorageOptions): {
639
+ readRaw: () => unknown;
640
+ read: () => TelegramTopicTargetFile | undefined;
641
+ capturePublication(): TelegramWorkspaceStatePublication | undefined;
642
+ };
396
643
  export declare function isSameTelegramProcessInstance(left: string | undefined, right: string | undefined): boolean;
644
+ /** Resolving selects a scope-bound view of the existing Workspace owner; it creates no files. */
645
+ export declare function createTelegramWorkspaceRestoreResolver(deps: {
646
+ getProfileName: () => string | undefined;
647
+ getBotToken: () => string | undefined;
648
+ threadStore: Pick<TelegramTopicTargetStore, "workspaceRestore">;
649
+ agentDir?: string;
650
+ }): () => TelegramWorkspaceRestore | undefined;
397
651
  export declare function createTelegramTopicTargetStore(options: TelegramTopicTargetStoreOptions): TelegramTopicTargetStore;
398
- export declare function normalizeTelegramTopicTargetThreadName(threadName: string): string;
399
- export declare function getTelegramTopicIdentityName(threadName: string): string;
400
- export declare function listOccupiedTelegramThreadIdentities(input: {
401
- records: readonly TelegramTopicTargetRecord[];
402
- workspaceBindings?: readonly TelegramWorkspaceThreadBinding[];
403
- pendingProvisions?: readonly TelegramThreadPendingProvision[];
404
- exceptTarget?: TelegramTarget;
405
- exceptWorkspaceBindingKey?: string;
406
- }): string[];
407
- export declare function chooseTelegramThreadName(input: {
408
- slot: string | undefined;
409
- entropy?: number | string;
410
- getRandom?: () => number;
411
- occupied?: readonly string[];
412
- }): string | undefined;
413
- export declare function getTelegramTopicThreadNameValidationError(threadName: string, _slot: string | undefined): string | undefined;
414
- export declare function getTelegramManualThreadDisplayNameValidationError(threadName: string): string | undefined;
415
- export declare function isTelegramTopicThreadNameValidForSlot(threadName: string, slot: string | undefined): boolean;
416
- export declare function getTelegramTopicName(request: TelegramTopicTargetProvisionRequest, template?: string, slot?: string): string;
417
652
  export interface TelegramPromoteFollowerBindingToLeaderDeps {
418
653
  store: TelegramTopicTargetStore;
419
654
  instanceId: string;
@@ -644,6 +879,5 @@ export declare function getTelegramTargetFromApiBody(body: unknown): (TelegramTa
644
879
  }) | undefined;
645
880
  export declare function isTelegramTopicTargetStaleError(error: unknown): boolean;
646
881
  export declare function isTelegramTopicModeUnavailableError(error: unknown): boolean;
647
- export declare function getTelegramTopicTitleForThreadName(threadName: string, slot: string, template?: string): string;
648
882
  export declare function createTelegramTopicTargetRenamer(deps: TelegramTopicTargetRenamerDeps): (request: TelegramTopicTargetRenameRequest) => Promise<TelegramTopicTargetRecord | undefined>;
649
883
  export declare function createTelegramTopicTargetProvisioner(deps: TelegramTopicTargetProvisionerDeps): (request: TelegramTopicTargetProvisionRequest) => Promise<TelegramTopicTargetProvisionResult>;