@llblab/pi-telegram 0.36.9 → 0.36.10
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/CHANGELOG.md +4 -0
- package/index.ts +9 -0
- package/lib/runtime.ts +52 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> Each release keeps at most 8 outcome records of at most 512 characters.
|
|
4
4
|
|
|
5
|
+
## 0.36.10: Transport-Fenced Typing Hotfix
|
|
6
|
+
|
|
7
|
+
- `Typing Authority Fence`: Starts and continues Telegram typing activity only while the Pi instance has direct ownership or a live follower registration, stopping quietly when authority disappears so classic takeover cannot re-arm a stale loop or flood diagnostics with expected follower-registration errors.
|
|
8
|
+
|
|
5
9
|
## 0.36.9: Telegram Status And Generated Controls Hotfix
|
|
6
10
|
|
|
7
11
|
- `Classic Takeover Status`: Keeps a classic-mode client visibly `disconnected` after another Pi instance takes Telegram ownership, preventing stale transport-side activity errors from overriding the authoritative connection state.
|
package/index.ts
CHANGED
|
@@ -465,6 +465,15 @@ export default function (pi: Pi.ExtensionAPI) {
|
|
|
465
465
|
BusApi.createTelegramAggregateTypingActionSender(telegramApiRuntime),
|
|
466
466
|
updateStatus,
|
|
467
467
|
isContextActive: telegramSessionContextStore.isCurrent,
|
|
468
|
+
getTransportAuthority() {
|
|
469
|
+
if (ownsTelegramDirectDelivery()) {
|
|
470
|
+
const epoch = getCurrentLeaderEpoch();
|
|
471
|
+
return epoch === undefined ? undefined : `direct:${epoch}`;
|
|
472
|
+
}
|
|
473
|
+
if (!telegramBusFollowerRegistrationState.isRegistered()) return undefined;
|
|
474
|
+
const generation = telegramBusFollowerRegistrationState.getGeneration();
|
|
475
|
+
return generation ? `follower:${generation}` : undefined;
|
|
476
|
+
},
|
|
468
477
|
recordRuntimeEvent,
|
|
469
478
|
});
|
|
470
479
|
const currentModelRuntime = Model.createCurrentModelRuntime({
|
package/lib/runtime.ts
CHANGED
|
@@ -320,6 +320,8 @@ export interface TelegramTypingLoopDeps {
|
|
|
320
320
|
options?: { message_thread_id?: number },
|
|
321
321
|
) => Promise<unknown>;
|
|
322
322
|
sendAggregateTypingAction?: (chatId: number) => Promise<unknown>;
|
|
323
|
+
shouldContinue?: () => boolean;
|
|
324
|
+
onStopped?: () => void;
|
|
323
325
|
}
|
|
324
326
|
|
|
325
327
|
export interface TelegramRuntimeEventRecorderPort {
|
|
@@ -365,6 +367,8 @@ export interface TelegramTypingLoopStarterDeps<
|
|
|
365
367
|
sendAggregateTypingAction?: (chatId: number) => Promise<unknown>;
|
|
366
368
|
updateStatus: (ctx: TContext, error?: string) => void;
|
|
367
369
|
isContextActive?: (ctx: TContext) => boolean;
|
|
370
|
+
isTransportAvailable?: () => boolean;
|
|
371
|
+
getTransportAuthority?: () => string | number | undefined;
|
|
368
372
|
intervalMs?: number;
|
|
369
373
|
}
|
|
370
374
|
|
|
@@ -376,15 +380,33 @@ export function createTelegramTypingLoopStarter<TContext>(
|
|
|
376
380
|
options?: { target?: TelegramTypingLoopTarget },
|
|
377
381
|
) => void {
|
|
378
382
|
return (ctx, chatId, options) => {
|
|
383
|
+
const transportAuthority = deps.getTransportAuthority?.();
|
|
384
|
+
const hasTransport = (): boolean =>
|
|
385
|
+
deps.getTransportAuthority
|
|
386
|
+
? transportAuthority !== undefined &&
|
|
387
|
+
Object.is(deps.getTransportAuthority(), transportAuthority)
|
|
388
|
+
: deps.isTransportAvailable?.() !== false;
|
|
389
|
+
if (!hasTransport()) return;
|
|
390
|
+
let active = true;
|
|
379
391
|
deps.typing.start({
|
|
380
392
|
chatId: chatId ?? deps.getDefaultChatId(),
|
|
381
393
|
target: options?.target,
|
|
382
394
|
intervalMs: deps.intervalMs ?? TELEGRAM_TYPING_ACTION_INTERVAL_MS,
|
|
383
395
|
sendTypingAction: async (targetChatId, actionOptions) => {
|
|
396
|
+
if (!active) return;
|
|
397
|
+
if (!hasTransport()) {
|
|
398
|
+
deps.typing.stop();
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
384
401
|
try {
|
|
385
402
|
await deps.sendTypingAction(targetChatId, actionOptions);
|
|
386
403
|
} catch (error) {
|
|
387
404
|
if (deps.isContextActive?.(ctx) === false) return;
|
|
405
|
+
if (!active) return;
|
|
406
|
+
if (!hasTransport()) {
|
|
407
|
+
deps.typing.stop();
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
388
410
|
const message =
|
|
389
411
|
error instanceof Error ? error.message : String(error);
|
|
390
412
|
updateTelegramRuntimeStatusSafely(deps.updateStatus, ctx, {
|
|
@@ -404,10 +426,20 @@ export function createTelegramTypingLoopStarter<TContext>(
|
|
|
404
426
|
},
|
|
405
427
|
sendAggregateTypingAction: deps.sendAggregateTypingAction
|
|
406
428
|
? async (targetChatId) => {
|
|
429
|
+
if (!active) return;
|
|
430
|
+
if (!hasTransport()) {
|
|
431
|
+
deps.typing.stop();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
407
434
|
try {
|
|
408
435
|
await deps.sendAggregateTypingAction?.(targetChatId);
|
|
409
436
|
} catch (error) {
|
|
410
437
|
if (deps.isContextActive?.(ctx) === false) return;
|
|
438
|
+
if (!active) return;
|
|
439
|
+
if (!hasTransport()) {
|
|
440
|
+
deps.typing.stop();
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
411
443
|
const message =
|
|
412
444
|
error instanceof Error ? error.message : String(error);
|
|
413
445
|
updateTelegramRuntimeStatusSafely(deps.updateStatus, ctx, {
|
|
@@ -427,6 +459,10 @@ export function createTelegramTypingLoopStarter<TContext>(
|
|
|
427
459
|
}
|
|
428
460
|
}
|
|
429
461
|
: undefined,
|
|
462
|
+
shouldContinue: hasTransport,
|
|
463
|
+
onStopped: () => {
|
|
464
|
+
active = false;
|
|
465
|
+
},
|
|
430
466
|
});
|
|
431
467
|
};
|
|
432
468
|
}
|
|
@@ -442,7 +478,12 @@ export function startTelegramTypingLoop(
|
|
|
442
478
|
): boolean {
|
|
443
479
|
if (deps.chatId === undefined || deps.chatId === 0) return false;
|
|
444
480
|
const previousKey = state.typingLoopKey;
|
|
481
|
+
const previousDeps = state.typingLoopDeps;
|
|
445
482
|
const nextKey = getTelegramTypingLoopKey(deps);
|
|
483
|
+
if (previousDeps && previousDeps !== deps) {
|
|
484
|
+
previousDeps.onStopped?.();
|
|
485
|
+
state.typingInFlight = undefined;
|
|
486
|
+
}
|
|
446
487
|
state.typingLoopDeps = deps;
|
|
447
488
|
state.typingLoopKey = nextKey;
|
|
448
489
|
const sendTyping = (): void => {
|
|
@@ -450,10 +491,14 @@ export function startTelegramTypingLoop(
|
|
|
450
491
|
if (
|
|
451
492
|
!activeDeps ||
|
|
452
493
|
activeDeps.chatId === undefined ||
|
|
453
|
-
activeDeps.chatId === 0
|
|
454
|
-
state.typingInFlight
|
|
494
|
+
activeDeps.chatId === 0
|
|
455
495
|
)
|
|
456
496
|
return;
|
|
497
|
+
if (activeDeps.shouldContinue?.() === false) {
|
|
498
|
+
stopTelegramTypingLoop(state);
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
if (state.typingInFlight) return;
|
|
457
502
|
const targetChatId = activeDeps.chatId;
|
|
458
503
|
const threadParams = getTelegramTypingLoopThreadParams(activeDeps.target);
|
|
459
504
|
const typing = Promise.resolve()
|
|
@@ -486,9 +531,12 @@ export function stopTelegramTypingLoop(
|
|
|
486
531
|
): boolean {
|
|
487
532
|
if (!state.typingInterval) return false;
|
|
488
533
|
clearInterval(state.typingInterval);
|
|
534
|
+
const activeDeps = state.typingLoopDeps;
|
|
489
535
|
state.typingInterval = undefined;
|
|
490
536
|
state.typingLoopDeps = undefined;
|
|
491
537
|
state.typingLoopKey = undefined;
|
|
538
|
+
state.typingInFlight = undefined;
|
|
539
|
+
activeDeps?.onStopped?.();
|
|
492
540
|
return true;
|
|
493
541
|
}
|
|
494
542
|
|
|
@@ -571,6 +619,8 @@ export interface TelegramPromptDispatchRuntimeDeps<
|
|
|
571
619
|
sendAggregateTypingAction?: (chatId: number) => Promise<unknown>;
|
|
572
620
|
updateStatus: (ctx: TContext, error?: string) => void;
|
|
573
621
|
isContextActive?: (ctx: TContext) => boolean;
|
|
622
|
+
isTransportAvailable?: () => boolean;
|
|
623
|
+
getTransportAuthority?: () => string | number | undefined;
|
|
574
624
|
intervalMs?: number;
|
|
575
625
|
}
|
|
576
626
|
|