@llblab/pi-telegram 0.52.2 → 0.53.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.
- package/AGENTS.md +9 -7
- package/BACKLOG.md +1 -18
- package/CHANGELOG.md +15 -0
- package/README.md +7 -11
- package/api/commands.ts +3 -0
- package/dist/api/commands.d.ts +1 -1
- package/dist/lib/activity-verbosity.d.ts +1 -5
- package/dist/lib/activity-verbosity.js +15 -42
- package/dist/lib/activity.d.ts +9 -0
- package/dist/lib/activity.js +39 -10
- package/dist/lib/agent-messages.js +7 -3
- package/dist/lib/bindings.d.ts +43 -5
- package/dist/lib/bindings.js +163 -20
- package/dist/lib/bus-api.d.ts +12 -0
- package/dist/lib/bus-api.js +182 -79
- package/dist/lib/bus-follower.d.ts +111 -31
- package/dist/lib/bus-follower.js +1324 -359
- package/dist/lib/bus-leader.d.ts +41 -91
- package/dist/lib/bus-leader.js +969 -637
- package/dist/lib/bus-transport.js +16 -9
- package/dist/lib/bus.d.ts +215 -18
- package/dist/lib/bus.js +1048 -327
- package/dist/lib/channel-posts.d.ts +5 -0
- package/dist/lib/channel-posts.js +434 -261
- package/dist/lib/command-templates.d.ts +26 -5
- package/dist/lib/command-templates.js +92 -176
- package/dist/lib/commands.d.ts +168 -82
- package/dist/lib/commands.js +1409 -291
- package/dist/lib/config.d.ts +1 -8
- package/dist/lib/config.js +34 -76
- package/dist/lib/delivery.d.ts +2 -2
- package/dist/lib/delivery.js +16 -16
- package/dist/lib/extension.js +639 -171
- package/dist/lib/generative-app-worker.mjs +19 -7
- package/dist/lib/generative-apps.d.ts +0 -5
- package/dist/lib/generative-apps.js +61 -49
- package/dist/lib/inbound.d.ts +5 -0
- package/dist/lib/inbound.js +35 -59
- package/dist/lib/journal.d.ts +33 -3
- package/dist/lib/journal.js +2063 -782
- package/dist/lib/lifecycle.d.ts +2 -6
- package/dist/lib/lifecycle.js +75 -58
- package/dist/lib/locks.d.ts +29 -3
- package/dist/lib/locks.js +289 -108
- package/dist/lib/logging.js +50 -14
- package/dist/lib/media.d.ts +22 -1
- package/dist/lib/media.js +46 -28
- package/dist/lib/menu-model.d.ts +19 -5
- package/dist/lib/menu-model.js +53 -11
- package/dist/lib/menu-queue.d.ts +5 -4
- package/dist/lib/menu-queue.js +45 -63
- package/dist/lib/menu-settings.d.ts +5 -4
- package/dist/lib/menu-settings.js +114 -78
- package/dist/lib/menu-status.d.ts +1 -1
- package/dist/lib/menu-status.js +8 -25
- package/dist/lib/menu-thinking.d.ts +6 -1
- package/dist/lib/menu-thinking.js +14 -21
- package/dist/lib/menu.d.ts +8 -61
- package/dist/lib/menu.js +92 -164
- package/dist/lib/model.d.ts +1 -1
- package/dist/lib/model.js +2 -16
- package/dist/lib/outbound-attachments.d.ts +6 -27
- package/dist/lib/outbound-attachments.js +45 -38
- package/dist/lib/outbound-buttons.js +22 -16
- package/dist/lib/outbound-markup.d.ts +0 -2
- package/dist/lib/outbound-markup.js +51 -64
- package/dist/lib/outbound-voice.js +6 -3
- package/dist/lib/outbound.d.ts +6 -6
- package/dist/lib/outbound.js +65 -51
- package/dist/lib/ownership.js +6 -2
- package/dist/lib/paths.d.ts +5 -0
- package/dist/lib/paths.js +37 -21
- package/dist/lib/pi.d.ts +2 -0
- package/dist/lib/pi.js +8 -1
- package/dist/lib/polling.d.ts +21 -37
- package/dist/lib/polling.js +59 -50
- package/dist/lib/preview.js +39 -19
- package/dist/lib/process-identity.d.ts +24 -0
- package/dist/lib/process-identity.js +133 -0
- package/dist/lib/prompts.js +2 -7
- package/dist/lib/queue.d.ts +14 -16
- package/dist/lib/queue.js +252 -127
- package/dist/lib/recovery.d.ts +2 -83
- package/dist/lib/recovery.js +20 -274
- package/dist/lib/replies.d.ts +16 -24
- package/dist/lib/replies.js +99 -116
- package/dist/lib/routing.d.ts +120 -7
- package/dist/lib/routing.js +4667 -1152
- package/dist/lib/runtime.d.ts +1 -11
- package/dist/lib/sections.d.ts +4 -29
- package/dist/lib/sections.js +7 -20
- package/dist/lib/skills.js +4 -3
- package/dist/lib/status.js +86 -57
- package/dist/lib/sync.d.ts +1 -3
- package/dist/lib/sync.js +67 -43
- package/dist/lib/target.d.ts +4 -0
- package/dist/lib/target.js +18 -0
- package/dist/lib/telegram-api.d.ts +18 -13
- package/dist/lib/telegram-api.js +148 -53
- package/dist/lib/text-groups.js +4 -39
- package/dist/lib/thread-cleanup-manager.d.ts +6 -27
- package/dist/lib/thread-cleanup-manager.js +369 -186
- package/dist/lib/thread-display.d.ts +1 -2
- package/dist/lib/thread-display.js +58 -38
- package/dist/lib/thread-naming.d.ts +28 -8
- package/dist/lib/thread-naming.js +175 -66
- package/dist/lib/thread-reconciler.d.ts +42 -16
- package/dist/lib/thread-reconciler.js +90 -50
- package/dist/lib/threads.d.ts +82 -20
- package/dist/lib/threads.js +2247 -855
- package/dist/lib/time-injection.js +1 -2
- package/dist/lib/turns.js +1 -19
- package/dist/lib/updates.d.ts +169 -80
- package/dist/lib/updates.js +2418 -641
- package/dist/lib/voice.d.ts +7 -22
- package/dist/lib/voice.js +7 -22
- package/dist/lib/wire.js +1 -1
- package/dist/lib/workspace-admission.d.ts +3 -1
- package/dist/lib/workspace-admission.js +425 -211
- package/dist/lib/workspace-identity.js +8 -13
- package/dist/lib/workspace-retirement.d.ts +1 -1
- package/dist/lib/workspace-retirement.js +328 -140
- package/dist/lib/workspace-slots.js +8 -4
- package/dist/package.json +1 -1
- package/docs/architecture.md +31 -29
- package/docs/inbound.md +1 -1
- package/docs/multi-instance-bus.md +15 -3
- package/docs/outbound.md +1 -1
- package/docs/public-api.md +29 -1
- package/docs/ui-style.md +25 -8
- package/lib/activity-verbosity.ts +59 -82
- package/lib/activity.ts +146 -102
- package/lib/agent-messages.ts +12 -5
- package/lib/bindings.ts +389 -82
- package/lib/bus-api.ts +263 -102
- package/lib/bus-follower.ts +2440 -601
- package/lib/bus-leader.ts +2209 -1290
- package/lib/bus-transport.ts +46 -12
- package/lib/bus.ts +1673 -444
- package/lib/channel-posts.ts +848 -327
- package/lib/command-templates.ts +152 -265
- package/lib/commands.ts +2398 -555
- package/lib/config.ts +177 -170
- package/lib/delivery.ts +41 -29
- package/lib/extension.ts +1206 -433
- package/lib/generative-app-worker.mjs +19 -7
- package/lib/generative-apps.ts +324 -211
- package/lib/inbound.ts +95 -97
- package/lib/journal.ts +5311 -1763
- package/lib/keyboard.ts +1 -3
- package/lib/lifecycle.ts +128 -78
- package/lib/locks.ts +677 -203
- package/lib/logging.ts +147 -58
- package/lib/media.ts +82 -43
- package/lib/menu-model.ts +85 -18
- package/lib/menu-queue.ts +88 -129
- package/lib/menu-settings.ts +260 -155
- package/lib/menu-status.ts +20 -60
- package/lib/menu-thinking.ts +41 -56
- package/lib/menu.ts +112 -285
- package/lib/model.ts +8 -22
- package/lib/outbound-attachments.ts +156 -125
- package/lib/outbound-buttons.ts +76 -49
- package/lib/outbound-markup.ts +96 -94
- package/lib/outbound-voice.ts +33 -27
- package/lib/outbound.ts +128 -125
- package/lib/ownership.ts +19 -10
- package/lib/paths.ts +148 -49
- package/lib/pi.ts +35 -15
- package/lib/polling.ts +144 -147
- package/lib/preview.ts +93 -40
- package/lib/process-identity.ts +164 -0
- package/lib/prompts.ts +4 -11
- package/lib/queue.ts +516 -301
- package/lib/recovery.ts +50 -454
- package/lib/rendering.ts +1 -3
- package/lib/replies.ts +248 -209
- package/lib/routing.ts +8509 -2186
- package/lib/runtime.ts +1 -12
- package/lib/sections.ts +24 -89
- package/lib/setup.ts +1 -3
- package/lib/skills.ts +9 -4
- package/lib/status.ts +215 -110
- package/lib/sync.ts +448 -361
- package/lib/target.ts +22 -3
- package/lib/telegram-api.ts +302 -127
- package/lib/text-groups.ts +5 -39
- package/lib/thread-cleanup-manager.ts +833 -331
- package/lib/thread-display.ts +213 -97
- package/lib/thread-naming.ts +232 -87
- package/lib/thread-reconciler.ts +155 -72
- package/lib/threads.ts +5318 -1845
- package/lib/time-injection.ts +1 -4
- package/lib/turns.ts +15 -28
- package/lib/updates.ts +5184 -1612
- package/lib/voice.ts +7 -35
- package/lib/wire.ts +1 -1
- package/lib/workspace-admission.ts +996 -416
- package/lib/workspace-identity.ts +14 -17
- package/lib/workspace-retirement.ts +878 -376
- package/lib/workspace-slots.ts +22 -13
- package/package.json +1 -1
- package/scripts/check-downgrade.mjs +0 -472
- package/scripts/measure-workspace.mjs +0 -108
package/lib/thread-reconciler.ts
CHANGED
|
@@ -132,14 +132,6 @@ export type ThreadReconciliationAction =
|
|
|
132
132
|
messageId?: number;
|
|
133
133
|
leaderEpoch?: number | string;
|
|
134
134
|
}
|
|
135
|
-
| {
|
|
136
|
-
kind: "close-delete-disconnected-instance-topic";
|
|
137
|
-
target: TelegramTarget & { threadId: number };
|
|
138
|
-
reason: "manual-disconnect";
|
|
139
|
-
instanceId?: string;
|
|
140
|
-
messageId?: number;
|
|
141
|
-
leaderEpoch?: number | string;
|
|
142
|
-
}
|
|
143
135
|
| {
|
|
144
136
|
kind: "close-delete-graceful-shutdown-topic";
|
|
145
137
|
target: TelegramTarget & { threadId: number };
|
|
@@ -204,7 +196,10 @@ export interface ThreadReconciliationApplyResult {
|
|
|
204
196
|
export interface ThreadReconciliationApplyPorts {
|
|
205
197
|
/** Private-chat temporary tabs support deletion, not forum closing. */
|
|
206
198
|
skipCloseBeforeDelete?: boolean;
|
|
207
|
-
isCleanupTargetProtected?: (
|
|
199
|
+
isCleanupTargetProtected?: (
|
|
200
|
+
target: ThreadTarget,
|
|
201
|
+
action: ThreadReconciliationAction,
|
|
202
|
+
) => boolean;
|
|
208
203
|
callApi?: <TResponse>(
|
|
209
204
|
method: string,
|
|
210
205
|
body: Record<string, unknown>,
|
|
@@ -249,7 +244,10 @@ function targetKey(target: ThreadTarget): string {
|
|
|
249
244
|
return `${target.chatId}:${target.threadId}`;
|
|
250
245
|
}
|
|
251
246
|
|
|
252
|
-
|
|
247
|
+
/** A Thread record still claims its slot/target while active, starting or pending. */
|
|
248
|
+
export function isCurrentThreadRecord(record: {
|
|
249
|
+
readonly status: string;
|
|
250
|
+
}): boolean {
|
|
253
251
|
return (
|
|
254
252
|
record.status === "active" ||
|
|
255
253
|
record.status === "starting" ||
|
|
@@ -323,7 +321,6 @@ function isCleanupAction(action: ThreadReconciliationAction): boolean {
|
|
|
323
321
|
action.kind === "close-stale-replaced-topic" ||
|
|
324
322
|
action.kind === "close-delete-replaced-follower-topic" ||
|
|
325
323
|
action.kind === "close-delete-previous-leader-topic" ||
|
|
326
|
-
action.kind === "close-delete-disconnected-instance-topic" ||
|
|
327
324
|
action.kind === "close-delete-graceful-shutdown-topic" ||
|
|
328
325
|
action.kind === "cancel-superseded-graceful-shutdown-cleanup" ||
|
|
329
326
|
action.kind === "close-delete-expired-pending-provision-topic"
|
|
@@ -331,7 +328,9 @@ function isCleanupAction(action: ThreadReconciliationAction): boolean {
|
|
|
331
328
|
}
|
|
332
329
|
|
|
333
330
|
function isSyncAction(action: ThreadReconciliationAction): boolean {
|
|
334
|
-
return
|
|
331
|
+
return (
|
|
332
|
+
action.kind === "mark-topic-active" || action.kind === "mark-topic-stale"
|
|
333
|
+
);
|
|
335
334
|
}
|
|
336
335
|
|
|
337
336
|
function createThreadReconciliationMachineState(
|
|
@@ -392,27 +391,40 @@ function getActionLeaderEpoch(
|
|
|
392
391
|
return "leaderEpoch" in action ? action.leaderEpoch : undefined;
|
|
393
392
|
}
|
|
394
393
|
|
|
394
|
+
/** Pure Bot API vocabulary for a deleted/missing Thread; callers own their HTTP-status policy. */
|
|
395
|
+
export function isTelegramTopicDeletedErrorMessage(message: string): boolean {
|
|
396
|
+
const text = message.toLowerCase();
|
|
397
|
+
return [
|
|
398
|
+
"topic_id_invalid",
|
|
399
|
+
"message thread not found",
|
|
400
|
+
"thread not found",
|
|
401
|
+
"topic not found",
|
|
402
|
+
"topic deleted",
|
|
403
|
+
].some((fragment) => text.includes(fragment));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/** Pure Bot API vocabulary for a closed Thread; closure is not deletion evidence. */
|
|
407
|
+
export function isTelegramTopicClosedErrorMessage(message: string): boolean {
|
|
408
|
+
const text = message.toLowerCase();
|
|
409
|
+
return [
|
|
410
|
+
"topic closed",
|
|
411
|
+
"thread closed",
|
|
412
|
+
"forum topic closed",
|
|
413
|
+
"message thread closed",
|
|
414
|
+
].some((fragment) => text.includes(fragment));
|
|
415
|
+
}
|
|
416
|
+
|
|
395
417
|
function isTelegramTopicTargetDeletedOrMissingError(error: unknown): boolean {
|
|
396
|
-
if (!(error instanceof Error)) return false;
|
|
397
|
-
const message = error.message.toLowerCase();
|
|
398
418
|
return (
|
|
399
|
-
message
|
|
400
|
-
message.includes("message thread not found") ||
|
|
401
|
-
message.includes("thread not found") ||
|
|
402
|
-
message.includes("topic not found") ||
|
|
403
|
-
message.includes("topic deleted")
|
|
419
|
+
error instanceof Error && isTelegramTopicDeletedErrorMessage(error.message)
|
|
404
420
|
);
|
|
405
421
|
}
|
|
406
422
|
|
|
407
423
|
function isTelegramTopicTargetGoneError(error: unknown): boolean {
|
|
408
|
-
if (isTelegramTopicTargetDeletedOrMissingError(error)) return true;
|
|
409
|
-
if (!(error instanceof Error)) return false;
|
|
410
|
-
const message = error.message.toLowerCase();
|
|
411
424
|
return (
|
|
412
|
-
|
|
413
|
-
message
|
|
414
|
-
|
|
415
|
-
message.includes("message thread closed")
|
|
425
|
+
error instanceof Error &&
|
|
426
|
+
(isTelegramTopicDeletedErrorMessage(error.message) ||
|
|
427
|
+
isTelegramTopicClosedErrorMessage(error.message))
|
|
416
428
|
);
|
|
417
429
|
}
|
|
418
430
|
|
|
@@ -501,26 +513,96 @@ export function createThreadReconciliationRuntime(deps: {
|
|
|
501
513
|
};
|
|
502
514
|
}
|
|
503
515
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
516
|
+
/** Momentary preparation evidence only: not an action, lease, issued effect or reusable deletion grant. */
|
|
517
|
+
export interface TelegramLiveRebindCleanupPreparation {
|
|
518
|
+
status: "prepared";
|
|
519
|
+
operationId: string;
|
|
520
|
+
target: ThreadTarget;
|
|
521
|
+
recipientTarget: ThreadTarget;
|
|
522
|
+
leaderEpoch: string;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
export function prepareLiveRebindThreadCleanup(input: {
|
|
526
|
+
operationId: string;
|
|
527
|
+
oldTarget: ThreadTarget;
|
|
528
|
+
recipientTarget: ThreadTarget;
|
|
529
|
+
leaderEpoch: string;
|
|
530
|
+
targetProtected: boolean;
|
|
531
|
+
/** Narrow body-free current-work projection; no cached idle or historical disposition proof. */
|
|
532
|
+
work:
|
|
533
|
+
| Readonly<{
|
|
534
|
+
sessionBusy: boolean;
|
|
535
|
+
targetWork: boolean;
|
|
536
|
+
deliveryPending: boolean;
|
|
537
|
+
unknown: boolean;
|
|
538
|
+
}>
|
|
539
|
+
| undefined;
|
|
540
|
+
}): TelegramLiveRebindCleanupPreparation | undefined {
|
|
541
|
+
const { operationId, oldTarget, recipientTarget, leaderEpoch, work } = input;
|
|
542
|
+
const validTarget = (target: ThreadTarget) =>
|
|
543
|
+
Number.isSafeInteger(target?.chatId) &&
|
|
544
|
+
target.chatId !== 0 &&
|
|
545
|
+
Number.isSafeInteger(target.threadId) &&
|
|
546
|
+
target.threadId > 0;
|
|
547
|
+
if (
|
|
548
|
+
!operationId?.trim() ||
|
|
549
|
+
!leaderEpoch?.trim() ||
|
|
550
|
+
!validTarget(oldTarget) ||
|
|
551
|
+
!validTarget(recipientTarget) ||
|
|
552
|
+
oldTarget.chatId !== recipientTarget.chatId ||
|
|
553
|
+
oldTarget.threadId === recipientTarget.threadId ||
|
|
554
|
+
input.targetProtected !== false ||
|
|
555
|
+
work?.sessionBusy !== false ||
|
|
556
|
+
work.targetWork !== false ||
|
|
557
|
+
work.deliveryPending !== false ||
|
|
558
|
+
work.unknown !== false
|
|
559
|
+
)
|
|
560
|
+
return undefined;
|
|
509
561
|
return {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
instanceId: input.instanceId,
|
|
516
|
-
...(input.leaderEpoch !== undefined
|
|
517
|
-
? { leaderEpoch: input.leaderEpoch }
|
|
518
|
-
: {}),
|
|
519
|
-
},
|
|
520
|
-
],
|
|
562
|
+
status: "prepared",
|
|
563
|
+
operationId,
|
|
564
|
+
target: { ...oldTarget },
|
|
565
|
+
recipientTarget: { ...recipientTarget },
|
|
566
|
+
leaderEpoch,
|
|
521
567
|
};
|
|
522
568
|
}
|
|
523
569
|
|
|
570
|
+
export type TelegramLiveRebindCleanupOutcome =
|
|
571
|
+
"confirmed" | "failed" | "unknown";
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* One unretried deletion for an already issued live-rebind cleanup grant. Success or confirmed absence is `confirmed`;
|
|
575
|
+
* protection or authority loss before the request and a definite request rejection are `failed`; every other outcome is
|
|
576
|
+
* `unknown`. The caller owns the durable issue marker and terminal record; this never repeats or rolls back.
|
|
577
|
+
*/
|
|
578
|
+
export async function issueLiveRebindThreadCleanup(
|
|
579
|
+
prepared: TelegramLiveRebindCleanupPreparation,
|
|
580
|
+
ports: {
|
|
581
|
+
/** Throws when the issuer's current recipient/work/ownership authority no longer holds. */
|
|
582
|
+
assertCurrent(): void;
|
|
583
|
+
deleteTopic(target: ThreadTarget): Promise<unknown>;
|
|
584
|
+
classifyFailure(error: unknown): "absent" | "rejected" | "unknown";
|
|
585
|
+
},
|
|
586
|
+
): Promise<TelegramLiveRebindCleanupOutcome> {
|
|
587
|
+
const target = { ...prepared.target };
|
|
588
|
+
try {
|
|
589
|
+
ports.assertCurrent();
|
|
590
|
+
} catch {
|
|
591
|
+
return "failed";
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
await ports.deleteTopic(target);
|
|
595
|
+
} catch (error) {
|
|
596
|
+
const failure = ports.classifyFailure(error);
|
|
597
|
+
return failure === "absent"
|
|
598
|
+
? "confirmed"
|
|
599
|
+
: failure === "rejected"
|
|
600
|
+
? "failed"
|
|
601
|
+
: "unknown";
|
|
602
|
+
}
|
|
603
|
+
return "confirmed";
|
|
604
|
+
}
|
|
605
|
+
|
|
524
606
|
export async function applyThreadReconciliationPlan(
|
|
525
607
|
plan: ThreadReconciliationPlan,
|
|
526
608
|
ports: ThreadReconciliationApplyPorts,
|
|
@@ -614,7 +696,6 @@ export async function applyThreadReconciliationPlan(
|
|
|
614
696
|
action.kind === "close-delete-reserved-topic" ||
|
|
615
697
|
action.kind === "close-delete-replaced-follower-topic" ||
|
|
616
698
|
action.kind === "close-delete-previous-leader-topic" ||
|
|
617
|
-
action.kind === "close-delete-disconnected-instance-topic" ||
|
|
618
699
|
action.kind === "close-delete-graceful-shutdown-topic" ||
|
|
619
700
|
action.kind === "close-delete-expired-pending-provision-topic"
|
|
620
701
|
) {
|
|
@@ -638,7 +719,9 @@ export async function applyThreadReconciliationPlan(
|
|
|
638
719
|
}
|
|
639
720
|
let deleteConfirmed = false;
|
|
640
721
|
let superseded = false;
|
|
641
|
-
for (const method of ports.skipCloseBeforeDelete
|
|
722
|
+
for (const method of ports.skipCloseBeforeDelete
|
|
723
|
+
? ["deleteForumTopic"]
|
|
724
|
+
: ["closeForumTopic", "deleteForumTopic"]) {
|
|
642
725
|
if (ports.isCleanupTargetProtected?.(action.target, action)) {
|
|
643
726
|
superseded = true;
|
|
644
727
|
break;
|
|
@@ -670,13 +753,20 @@ export async function applyThreadReconciliationPlan(
|
|
|
670
753
|
incompleteActions.push(action);
|
|
671
754
|
continue;
|
|
672
755
|
}
|
|
673
|
-
if (
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
756
|
+
if (
|
|
757
|
+
superseded ||
|
|
758
|
+
ports.isCleanupTargetProtected?.(action.target, action)
|
|
759
|
+
) {
|
|
760
|
+
ports.recordRuntimeEvent?.(
|
|
761
|
+
"telegram",
|
|
762
|
+
"Cancelled cleanup of a protected Telegram target",
|
|
763
|
+
{
|
|
764
|
+
phase: "thread-reconciler-cleanup-target-reused",
|
|
765
|
+
action: action.kind,
|
|
766
|
+
chatId: action.target.chatId,
|
|
767
|
+
threadId: action.target.threadId,
|
|
768
|
+
},
|
|
769
|
+
);
|
|
680
770
|
continue;
|
|
681
771
|
}
|
|
682
772
|
if (!deleteConfirmed) {
|
|
@@ -699,7 +789,6 @@ export async function applyThreadReconciliationPlan(
|
|
|
699
789
|
if (
|
|
700
790
|
action.kind !== "close-delete-previous-leader-topic" &&
|
|
701
791
|
action.kind !== "close-delete-replaced-follower-topic" &&
|
|
702
|
-
action.kind !== "close-delete-disconnected-instance-topic" &&
|
|
703
792
|
action.kind !== "close-delete-expired-pending-provision-topic"
|
|
704
793
|
) {
|
|
705
794
|
const changed =
|
|
@@ -714,14 +803,12 @@ export async function applyThreadReconciliationPlan(
|
|
|
714
803
|
: action.kind === "close-delete-reserved-topic"
|
|
715
804
|
? "Reserved Telegram topic deleted"
|
|
716
805
|
: action.kind === "close-delete-replaced-follower-topic"
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
? "Graceful shutdown Telegram topic deleted"
|
|
724
|
-
: "Expired pending provision Telegram topic deleted",
|
|
806
|
+
? "Replaced follower Telegram topic deleted"
|
|
807
|
+
: action.kind === "close-delete-previous-leader-topic"
|
|
808
|
+
? "Previous leader Telegram topic deleted"
|
|
809
|
+
: action.kind === "close-delete-graceful-shutdown-topic"
|
|
810
|
+
? "Graceful shutdown Telegram topic deleted"
|
|
811
|
+
: "Expired pending provision Telegram topic deleted",
|
|
725
812
|
{
|
|
726
813
|
phase:
|
|
727
814
|
action.kind === "close-delete-unbound-topic"
|
|
@@ -729,16 +816,12 @@ export async function applyThreadReconciliationPlan(
|
|
|
729
816
|
: action.kind === "close-delete-reserved-topic"
|
|
730
817
|
? "thread-reconciler-reserved-topic-delete"
|
|
731
818
|
: action.kind === "close-delete-replaced-follower-topic"
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
: action.kind ===
|
|
739
|
-
"close-delete-graceful-shutdown-topic"
|
|
740
|
-
? "thread-reconciler-graceful-shutdown-topic-delete"
|
|
741
|
-
: "thread-reconciler-expired-pending-provision-topic-delete",
|
|
819
|
+
? "thread-reconciler-replaced-follower-topic-delete"
|
|
820
|
+
: action.kind === "close-delete-previous-leader-topic"
|
|
821
|
+
? "thread-reconciler-previous-leader-topic-delete"
|
|
822
|
+
: action.kind === "close-delete-graceful-shutdown-topic"
|
|
823
|
+
? "thread-reconciler-graceful-shutdown-topic-delete"
|
|
824
|
+
: "thread-reconciler-expired-pending-provision-topic-delete",
|
|
742
825
|
chatId: action.target.chatId,
|
|
743
826
|
threadId: action.target.threadId,
|
|
744
827
|
...("messageId" in action ? { messageId: action.messageId } : {}),
|
|
@@ -793,7 +876,7 @@ export function planThreadReconciliation(
|
|
|
793
876
|
);
|
|
794
877
|
const currentTargets = new Set(
|
|
795
878
|
input.records
|
|
796
|
-
.filter(
|
|
879
|
+
.filter(isCurrentThreadRecord)
|
|
797
880
|
.map((record) => targetKey(record.target)),
|
|
798
881
|
);
|
|
799
882
|
const reservedTargets = new Set(
|
|
@@ -826,7 +909,7 @@ export function planThreadReconciliation(
|
|
|
826
909
|
for (const cleanup of input.pendingCleanups ?? []) {
|
|
827
910
|
const superseded = input.records.some(
|
|
828
911
|
(record) =>
|
|
829
|
-
|
|
912
|
+
isCurrentThreadRecord(record) &&
|
|
830
913
|
targetKey(record.target) === targetKey(cleanup.target) &&
|
|
831
914
|
record.instanceId !== cleanup.instanceId,
|
|
832
915
|
);
|