@llblab/pi-telegram 0.48.2 → 0.48.3
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 +5 -0
- package/dist/lib/activity.d.ts +2 -0
- package/dist/lib/activity.js +12 -0
- package/dist/lib/bindings.d.ts +1 -1
- package/dist/lib/bindings.js +5 -1
- package/dist/lib/queue.d.ts +2 -0
- package/dist/lib/queue.js +5 -1
- package/dist/lib/replies.d.ts +1 -0
- package/dist/lib/replies.js +1 -0
- package/dist/lib/routing.js +4 -2
- package/dist/package.json +1 -1
- package/lib/activity.ts +14 -0
- package/lib/bindings.ts +7 -2
- package/lib/queue.ts +7 -1
- package/lib/replies.ts +2 -0
- package/lib/routing.ts +6 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.48.3: Assistant publication identity hotfix
|
|
8
|
+
|
|
9
|
+
- `Thread restore display identity`: Restoring or reclaiming a Thread now renames the destination from its current Workspace display title when available, rather than leaking the internal baked slot name such as `Moss` into directory-title mode.
|
|
10
|
+
- `Assistant publication identity`: An empty terminal assistant message may recover an earlier preserved answer, but it no longer republishes that text when the same Telegram intermediate output was already admitted; the pre-send turn fence also prevents lost-acknowledgement retries while allowing later turns.
|
|
11
|
+
|
|
7
12
|
## 0.48.2: Follower promotion recovery
|
|
8
13
|
|
|
9
14
|
- `Follower promotion recovery`: A failed follower-to-leader promotion, including unavailable Thread slot authority, is now contained as a retryable bus recovery event instead of escaping a detached heartbeat recovery promise and terminating Pi.
|
package/dist/lib/activity.d.ts
CHANGED
|
@@ -201,7 +201,9 @@ export interface TelegramActivityPublicationRuntime {
|
|
|
201
201
|
export declare function createTelegramActivityPublicationRuntime(): TelegramActivityPublicationRuntime;
|
|
202
202
|
export interface TelegramAssistantOutputRuntime {
|
|
203
203
|
start: () => void;
|
|
204
|
+
beginTurn: () => void;
|
|
204
205
|
accept: (event: TelegramAssistantSegmentEvent) => void;
|
|
206
|
+
hasAdmittedTelegramIntermediate: (text: string) => boolean;
|
|
205
207
|
waitForIdle: () => Promise<void>;
|
|
206
208
|
stop: () => void;
|
|
207
209
|
}
|
package/dist/lib/activity.js
CHANGED
|
@@ -520,6 +520,7 @@ export function createTelegramAssistantOutputRuntime(deps) {
|
|
|
520
520
|
let running = false;
|
|
521
521
|
let tail = Promise.resolve();
|
|
522
522
|
const admitted = new Set();
|
|
523
|
+
const admittedTelegramIntermediateText = new Set();
|
|
523
524
|
const isEligibleEvent = (event) => (event.source === "telegram" && event.placement === "intermediate") ||
|
|
524
525
|
event.source === "local" ||
|
|
525
526
|
event.source === "autonomous" ||
|
|
@@ -529,8 +530,12 @@ export function createTelegramAssistantOutputRuntime(deps) {
|
|
|
529
530
|
generation += 1;
|
|
530
531
|
running = true;
|
|
531
532
|
admitted.clear();
|
|
533
|
+
admittedTelegramIntermediateText.clear();
|
|
532
534
|
tail = Promise.resolve();
|
|
533
535
|
},
|
|
536
|
+
beginTurn() {
|
|
537
|
+
admittedTelegramIntermediateText.clear();
|
|
538
|
+
},
|
|
534
539
|
accept(event) {
|
|
535
540
|
if (!running || !isEligibleEvent(event) || !event.text.trim())
|
|
536
541
|
return;
|
|
@@ -538,6 +543,9 @@ export function createTelegramAssistantOutputRuntime(deps) {
|
|
|
538
543
|
if (admitted.has(key))
|
|
539
544
|
return;
|
|
540
545
|
admitted.add(key);
|
|
546
|
+
if (event.source === "telegram" && event.placement === "intermediate") {
|
|
547
|
+
admittedTelegramIntermediateText.add(event.text.trim());
|
|
548
|
+
}
|
|
541
549
|
const admittedGeneration = generation;
|
|
542
550
|
const admittedAuthority = deps.captureAuthority?.();
|
|
543
551
|
const preparation = deps.prepareSend?.(event);
|
|
@@ -562,6 +570,9 @@ export function createTelegramAssistantOutputRuntime(deps) {
|
|
|
562
570
|
}
|
|
563
571
|
}).finally(() => preparation?.settle());
|
|
564
572
|
},
|
|
573
|
+
hasAdmittedTelegramIntermediate(text) {
|
|
574
|
+
return admittedTelegramIntermediateText.has(text.trim());
|
|
575
|
+
},
|
|
565
576
|
waitForIdle() {
|
|
566
577
|
return tail;
|
|
567
578
|
},
|
|
@@ -569,6 +580,7 @@ export function createTelegramAssistantOutputRuntime(deps) {
|
|
|
569
580
|
generation += 1;
|
|
570
581
|
running = false;
|
|
571
582
|
admitted.clear();
|
|
583
|
+
admittedTelegramIntermediateText.clear();
|
|
572
584
|
},
|
|
573
585
|
};
|
|
574
586
|
}
|
package/dist/lib/bindings.d.ts
CHANGED
|
@@ -202,7 +202,7 @@ interface TelegramLifecycleBindingDeps {
|
|
|
202
202
|
publicationRuntime: TelegramBridgePublicationRuntime;
|
|
203
203
|
activityRuntime: Activity.TelegramActivityRuntime;
|
|
204
204
|
activityVerbosityRuntime?: ActivityVerbosity.TelegramActivityVerbosityRuntime;
|
|
205
|
-
assistantOutputRuntime: Pick<Activity.TelegramAssistantOutputRuntime, "start" | "waitForIdle" | "stop">;
|
|
205
|
+
assistantOutputRuntime: Pick<Activity.TelegramAssistantOutputRuntime, "start" | "beginTurn" | "hasAdmittedTelegramIntermediate" | "waitForIdle" | "stop">;
|
|
206
206
|
sessionLifecycleRuntime: Pick<Lifecycle.TelegramLifecycleRegistrationDeps, "onSessionStart" | "onSessionShutdown" | "onModelSelect">;
|
|
207
207
|
configStore: Pick<Config.TelegramConfigStore, "get" | "getOutboundHandlers" | "hasBotToken" | "load">;
|
|
208
208
|
abort: Runtime.TelegramRuntimeAbortPort;
|
package/dist/lib/bindings.js
CHANGED
|
@@ -615,7 +615,10 @@ export function registerTelegramLifecycleRuntimeHooks({ pi, publicationRuntime,
|
|
|
615
615
|
clearDispatchPending: lifecycle.clearDispatchPending,
|
|
616
616
|
setFoldQueuedPromptsIntoHistory: lifecycle.setFoldQueuedPromptsIntoHistory,
|
|
617
617
|
setActiveTurn: activeTurnRuntime.set,
|
|
618
|
-
onPromptHandedOff,
|
|
618
|
+
onPromptHandedOff: (turn, ctx) => {
|
|
619
|
+
assistantOutputRuntime.beginTurn();
|
|
620
|
+
onPromptHandedOff?.(turn, ctx);
|
|
621
|
+
},
|
|
619
622
|
createPreviewState: previewRuntime.resetState,
|
|
620
623
|
startTypingLoop: (ctx) => {
|
|
621
624
|
const turn = activeTurnRuntime.get();
|
|
@@ -627,6 +630,7 @@ export function registerTelegramLifecycleRuntimeHooks({ pi, publicationRuntime,
|
|
|
627
630
|
getActiveTurn: activeTurnRuntime.get,
|
|
628
631
|
loadConfig: configStore.load,
|
|
629
632
|
extractAssistant: Replies.extractRunAssistantMessage,
|
|
633
|
+
isRecoveredAssistantAlreadyPublished: (assistant) => !!assistant.text && assistantOutputRuntime.hasAdmittedTelegramIntermediate(assistant.text),
|
|
630
634
|
getFoldQueuedPromptsIntoHistory: lifecycle.shouldFoldQueuedPromptsIntoHistory,
|
|
631
635
|
resetRuntimeState: agentEndResetter,
|
|
632
636
|
isSessionActive: isSessionContextActive,
|
package/dist/lib/queue.d.ts
CHANGED
|
@@ -393,6 +393,7 @@ export interface TelegramAgentEndAssistantResult {
|
|
|
393
393
|
text?: string;
|
|
394
394
|
stopReason?: string;
|
|
395
395
|
errorMessage?: string;
|
|
396
|
+
recoveredFromEarlier?: boolean;
|
|
396
397
|
}
|
|
397
398
|
export interface TelegramAgentEndOutboundVoiceReply {
|
|
398
399
|
text: string;
|
|
@@ -468,6 +469,7 @@ export interface TelegramAgentEndHookRuntimeDeps<TTurn extends PendingTelegramTu
|
|
|
468
469
|
getActiveTurn: () => TTurn | undefined;
|
|
469
470
|
loadConfig?: () => Promise<void>;
|
|
470
471
|
extractAssistant: (messages: readonly TMessage[]) => TelegramAgentEndAssistantResult;
|
|
472
|
+
isRecoveredAssistantAlreadyPublished?: (assistant: TelegramAgentEndAssistantResult) => boolean;
|
|
471
473
|
getFoldQueuedPromptsIntoHistory: () => boolean;
|
|
472
474
|
resetRuntimeState: () => void;
|
|
473
475
|
isSessionActive?: (ctx: TContext) => boolean;
|
package/dist/lib/queue.js
CHANGED
|
@@ -853,7 +853,11 @@ export function createTelegramAgentEndHook(deps) {
|
|
|
853
853
|
if (deps.isSessionActive?.(ctx) === false)
|
|
854
854
|
return;
|
|
855
855
|
const turn = deps.getActiveTurn();
|
|
856
|
-
const
|
|
856
|
+
const extractedAssistant = assistantOverride ?? (turn ? deps.extractAssistant(event.messages) : {});
|
|
857
|
+
const assistant = extractedAssistant.recoveredFromEarlier &&
|
|
858
|
+
deps.isRecoveredAssistantAlreadyPublished?.(extractedAssistant)
|
|
859
|
+
? { stopReason: extractedAssistant.stopReason }
|
|
860
|
+
: extractedAssistant;
|
|
857
861
|
const hasPublication = !!assistant.text || assistant.stopReason === "error" || !!turn?.queuedAttachments.length;
|
|
858
862
|
const reservation = turn && !turn.guestQueryId && hasPublication ? deps.reserveActiveTurnDelivery?.() : undefined;
|
|
859
863
|
const scheduleDelivery = reservation?.schedule ?? deps.scheduleActiveTurnDelivery;
|
package/dist/lib/replies.d.ts
CHANGED
|
@@ -44,6 +44,7 @@ export declare function extractRunAssistantMessage(messages: readonly unknown[])
|
|
|
44
44
|
text?: string;
|
|
45
45
|
stopReason?: string;
|
|
46
46
|
errorMessage?: string;
|
|
47
|
+
recoveredFromEarlier?: boolean;
|
|
47
48
|
};
|
|
48
49
|
export interface TelegramReplyOwnershipRecorder {
|
|
49
50
|
record: (input: {
|
package/dist/lib/replies.js
CHANGED
|
@@ -142,6 +142,7 @@ export function extractRunAssistantMessage(messages) {
|
|
|
142
142
|
text,
|
|
143
143
|
stopReason: typeof rawStopReason === "string" ? rawStopReason : undefined,
|
|
144
144
|
errorMessage: typeof rawErrorMessage === "string" ? rawErrorMessage : undefined,
|
|
145
|
+
recoveredFromEarlier: true,
|
|
145
146
|
};
|
|
146
147
|
}
|
|
147
148
|
return latest;
|
package/dist/lib/routing.js
CHANGED
|
@@ -923,7 +923,8 @@ export function createTelegramInboundRouteRuntime(deps) {
|
|
|
923
923
|
await deps.callApi("editForumTopic", {
|
|
924
924
|
chat_id: sourceTarget.chatId,
|
|
925
925
|
message_thread_id: sourceTarget.threadId,
|
|
926
|
-
name:
|
|
926
|
+
name: deps.getDisplayTitle?.(sourceTarget) ??
|
|
927
|
+
Threads.getTelegramTopicTitleForThreadName(threadName, slot),
|
|
927
928
|
});
|
|
928
929
|
assertExecutionCurrent();
|
|
929
930
|
}
|
|
@@ -1024,7 +1025,8 @@ export function createTelegramInboundRouteRuntime(deps) {
|
|
|
1024
1025
|
await deps.callApi("editForumTopic", {
|
|
1025
1026
|
chat_id: sourceTarget.chatId,
|
|
1026
1027
|
message_thread_id: sourceTarget.threadId,
|
|
1027
|
-
name:
|
|
1028
|
+
name: deps.getDisplayTitle?.(sourceTarget) ??
|
|
1029
|
+
Threads.getTelegramTopicTitleForThreadName(threadName, slot),
|
|
1028
1030
|
});
|
|
1029
1031
|
assertExecutionCurrent();
|
|
1030
1032
|
}
|
package/dist/package.json
CHANGED
package/lib/activity.ts
CHANGED
|
@@ -804,7 +804,9 @@ export function createTelegramActivityPublicationRuntime(): TelegramActivityPubl
|
|
|
804
804
|
|
|
805
805
|
export interface TelegramAssistantOutputRuntime {
|
|
806
806
|
start: () => void;
|
|
807
|
+
beginTurn: () => void;
|
|
807
808
|
accept: (event: TelegramAssistantSegmentEvent) => void;
|
|
809
|
+
hasAdmittedTelegramIntermediate: (text: string) => boolean;
|
|
808
810
|
waitForIdle: () => Promise<void>;
|
|
809
811
|
stop: () => void;
|
|
810
812
|
}
|
|
@@ -834,6 +836,7 @@ export function createTelegramAssistantOutputRuntime<TAuthority = undefined>(dep
|
|
|
834
836
|
let running = false;
|
|
835
837
|
let tail: Promise<void> = Promise.resolve();
|
|
836
838
|
const admitted = new Set<string>();
|
|
839
|
+
const admittedTelegramIntermediateText = new Set<string>();
|
|
837
840
|
const isEligibleEvent = (event: TelegramAssistantSegmentEvent): boolean =>
|
|
838
841
|
(event.source === "telegram" && event.placement === "intermediate") ||
|
|
839
842
|
event.source === "local" ||
|
|
@@ -845,13 +848,20 @@ export function createTelegramAssistantOutputRuntime<TAuthority = undefined>(dep
|
|
|
845
848
|
generation += 1;
|
|
846
849
|
running = true;
|
|
847
850
|
admitted.clear();
|
|
851
|
+
admittedTelegramIntermediateText.clear();
|
|
848
852
|
tail = Promise.resolve();
|
|
849
853
|
},
|
|
854
|
+
beginTurn() {
|
|
855
|
+
admittedTelegramIntermediateText.clear();
|
|
856
|
+
},
|
|
850
857
|
accept(event) {
|
|
851
858
|
if (!running || !isEligibleEvent(event) || !event.text.trim()) return;
|
|
852
859
|
const key = `${event.activityId}:${event.sequence}`;
|
|
853
860
|
if (admitted.has(key)) return;
|
|
854
861
|
admitted.add(key);
|
|
862
|
+
if (event.source === "telegram" && event.placement === "intermediate") {
|
|
863
|
+
admittedTelegramIntermediateText.add(event.text.trim());
|
|
864
|
+
}
|
|
855
865
|
const admittedGeneration = generation;
|
|
856
866
|
const admittedAuthority = deps.captureAuthority?.();
|
|
857
867
|
const preparation = deps.prepareSend?.(event);
|
|
@@ -877,6 +887,9 @@ export function createTelegramAssistantOutputRuntime<TAuthority = undefined>(dep
|
|
|
877
887
|
}
|
|
878
888
|
}).finally(() => preparation?.settle());
|
|
879
889
|
},
|
|
890
|
+
hasAdmittedTelegramIntermediate(text) {
|
|
891
|
+
return admittedTelegramIntermediateText.has(text.trim());
|
|
892
|
+
},
|
|
880
893
|
waitForIdle() {
|
|
881
894
|
return tail;
|
|
882
895
|
},
|
|
@@ -884,6 +897,7 @@ export function createTelegramAssistantOutputRuntime<TAuthority = undefined>(dep
|
|
|
884
897
|
generation += 1;
|
|
885
898
|
running = false;
|
|
886
899
|
admitted.clear();
|
|
900
|
+
admittedTelegramIntermediateText.clear();
|
|
887
901
|
},
|
|
888
902
|
};
|
|
889
903
|
}
|
package/lib/bindings.ts
CHANGED
|
@@ -835,7 +835,7 @@ interface TelegramLifecycleBindingDeps {
|
|
|
835
835
|
activityVerbosityRuntime?: ActivityVerbosity.TelegramActivityVerbosityRuntime;
|
|
836
836
|
assistantOutputRuntime: Pick<
|
|
837
837
|
Activity.TelegramAssistantOutputRuntime,
|
|
838
|
-
"start" | "waitForIdle" | "stop"
|
|
838
|
+
"start" | "beginTurn" | "hasAdmittedTelegramIntermediate" | "waitForIdle" | "stop"
|
|
839
839
|
>;
|
|
840
840
|
sessionLifecycleRuntime: Pick<
|
|
841
841
|
Lifecycle.TelegramLifecycleRegistrationDeps,
|
|
@@ -1136,7 +1136,10 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1136
1136
|
clearDispatchPending: lifecycle.clearDispatchPending,
|
|
1137
1137
|
setFoldQueuedPromptsIntoHistory: lifecycle.setFoldQueuedPromptsIntoHistory,
|
|
1138
1138
|
setActiveTurn: activeTurnRuntime.set,
|
|
1139
|
-
onPromptHandedOff,
|
|
1139
|
+
onPromptHandedOff: (turn, ctx) => {
|
|
1140
|
+
assistantOutputRuntime.beginTurn();
|
|
1141
|
+
onPromptHandedOff?.(turn, ctx);
|
|
1142
|
+
},
|
|
1140
1143
|
createPreviewState: previewRuntime.resetState,
|
|
1141
1144
|
startTypingLoop: (ctx) => {
|
|
1142
1145
|
const turn = activeTurnRuntime.get();
|
|
@@ -1148,6 +1151,8 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1148
1151
|
getActiveTurn: activeTurnRuntime.get,
|
|
1149
1152
|
loadConfig: configStore.load,
|
|
1150
1153
|
extractAssistant: Replies.extractRunAssistantMessage,
|
|
1154
|
+
isRecoveredAssistantAlreadyPublished: (assistant) =>
|
|
1155
|
+
!!assistant.text && assistantOutputRuntime.hasAdmittedTelegramIntermediate(assistant.text),
|
|
1151
1156
|
getFoldQueuedPromptsIntoHistory:
|
|
1152
1157
|
lifecycle.shouldFoldQueuedPromptsIntoHistory,
|
|
1153
1158
|
resetRuntimeState: agentEndResetter,
|
package/lib/queue.ts
CHANGED
|
@@ -1474,6 +1474,7 @@ export interface TelegramAgentEndAssistantResult {
|
|
|
1474
1474
|
text?: string;
|
|
1475
1475
|
stopReason?: string;
|
|
1476
1476
|
errorMessage?: string;
|
|
1477
|
+
recoveredFromEarlier?: boolean;
|
|
1477
1478
|
}
|
|
1478
1479
|
|
|
1479
1480
|
export interface TelegramAgentEndOutboundVoiceReply {
|
|
@@ -1592,6 +1593,7 @@ export interface TelegramAgentEndHookRuntimeDeps<
|
|
|
1592
1593
|
extractAssistant: (
|
|
1593
1594
|
messages: readonly TMessage[],
|
|
1594
1595
|
) => TelegramAgentEndAssistantResult;
|
|
1596
|
+
isRecoveredAssistantAlreadyPublished?: (assistant: TelegramAgentEndAssistantResult) => boolean;
|
|
1595
1597
|
getFoldQueuedPromptsIntoHistory: () => boolean;
|
|
1596
1598
|
resetRuntimeState: () => void;
|
|
1597
1599
|
isSessionActive?: (ctx: TContext) => boolean;
|
|
@@ -1736,7 +1738,11 @@ export function createTelegramAgentEndHook<
|
|
|
1736
1738
|
): Promise<void> => {
|
|
1737
1739
|
if (deps.isSessionActive?.(ctx) === false) return;
|
|
1738
1740
|
const turn = deps.getActiveTurn();
|
|
1739
|
-
const
|
|
1741
|
+
const extractedAssistant = assistantOverride ?? (turn ? deps.extractAssistant(event.messages) : {});
|
|
1742
|
+
const assistant = extractedAssistant.recoveredFromEarlier &&
|
|
1743
|
+
deps.isRecoveredAssistantAlreadyPublished?.(extractedAssistant)
|
|
1744
|
+
? { stopReason: extractedAssistant.stopReason }
|
|
1745
|
+
: extractedAssistant;
|
|
1740
1746
|
const hasPublication = !!assistant.text || assistant.stopReason === "error" || !!turn?.queuedAttachments.length;
|
|
1741
1747
|
const reservation = turn && !turn.guestQueryId && hasPublication ? deps.reserveActiveTurnDelivery?.() : undefined;
|
|
1742
1748
|
const scheduleDelivery = reservation?.schedule ?? deps.scheduleActiveTurnDelivery;
|
package/lib/replies.ts
CHANGED
|
@@ -191,6 +191,7 @@ export function extractRunAssistantMessage(
|
|
|
191
191
|
text?: string;
|
|
192
192
|
stopReason?: string;
|
|
193
193
|
errorMessage?: string;
|
|
194
|
+
recoveredFromEarlier?: boolean;
|
|
194
195
|
} {
|
|
195
196
|
const latest = extractLatestAssistantMessageText(messages);
|
|
196
197
|
if (latest.text || latest.stopReason !== "stop") return latest;
|
|
@@ -213,6 +214,7 @@ export function extractRunAssistantMessage(
|
|
|
213
214
|
stopReason: typeof rawStopReason === "string" ? rawStopReason : undefined,
|
|
214
215
|
errorMessage:
|
|
215
216
|
typeof rawErrorMessage === "string" ? rawErrorMessage : undefined,
|
|
217
|
+
recoveredFromEarlier: true,
|
|
216
218
|
};
|
|
217
219
|
}
|
|
218
220
|
return latest;
|
package/lib/routing.ts
CHANGED
|
@@ -1560,7 +1560,9 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1560
1560
|
await deps.callApi("editForumTopic", {
|
|
1561
1561
|
chat_id: sourceTarget.chatId,
|
|
1562
1562
|
message_thread_id: sourceTarget.threadId,
|
|
1563
|
-
name:
|
|
1563
|
+
name:
|
|
1564
|
+
deps.getDisplayTitle?.(sourceTarget) ??
|
|
1565
|
+
Threads.getTelegramTopicTitleForThreadName(threadName, slot),
|
|
1564
1566
|
});
|
|
1565
1567
|
assertExecutionCurrent();
|
|
1566
1568
|
} catch (renameError) {
|
|
@@ -1717,7 +1719,9 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1717
1719
|
await deps.callApi("editForumTopic", {
|
|
1718
1720
|
chat_id: sourceTarget.chatId,
|
|
1719
1721
|
message_thread_id: sourceTarget.threadId,
|
|
1720
|
-
name:
|
|
1722
|
+
name:
|
|
1723
|
+
deps.getDisplayTitle?.(sourceTarget) ??
|
|
1724
|
+
Threads.getTelegramTopicTitleForThreadName(threadName, slot),
|
|
1721
1725
|
});
|
|
1722
1726
|
assertExecutionCurrent();
|
|
1723
1727
|
} catch (renameError) {
|