@llblab/pi-telegram 0.43.2 → 0.45.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.
- package/AGENTS.md +14 -9
- package/BACKLOG.md +20 -4
- package/CHANGELOG.md +22 -5
- package/README.md +13 -9
- package/docs/README.md +1 -0
- package/docs/architecture.md +220 -18
- package/docs/generative-apps.md +1 -1
- package/docs/multi-instance-bus.md +70 -19
- package/docs/outbound.md +13 -7
- package/docs/public-api.md +13 -5
- package/docs/ui-style.md +3 -1
- package/index.ts +4 -1415
- package/lib/activity.ts +19 -5
- package/lib/agent-messages.ts +6 -3
- package/lib/bindings.ts +37 -2
- package/lib/bus-follower.ts +600 -135
- package/lib/bus-leader.ts +962 -55
- package/lib/bus.ts +350 -26
- package/lib/channel-posts.ts +544 -0
- package/lib/commands.ts +234 -11
- package/lib/config.ts +178 -25
- package/lib/delivery.ts +18 -18
- package/lib/extension.ts +1792 -0
- package/lib/generative-apps.ts +20 -2
- package/lib/journal.ts +2184 -126
- package/lib/lifecycle.ts +7 -1
- package/lib/locks.ts +38 -1
- package/lib/menu-settings.ts +154 -15
- package/lib/outbound-attachments.ts +74 -40
- package/lib/outbound-voice.ts +28 -42
- package/lib/outbound.ts +18 -14
- package/lib/paths.ts +29 -0
- package/lib/polling.ts +85 -17
- package/lib/preview.ts +115 -70
- package/lib/prompts.ts +5 -2
- package/lib/queue.ts +66 -22
- package/lib/replies.ts +47 -39
- package/lib/routing.ts +305 -112
- package/lib/status.ts +10 -0
- package/lib/sync.ts +308 -39
- package/lib/telegram-api.ts +315 -7
- package/lib/thread-cleanup-manager.ts +664 -0
- package/lib/thread-display.ts +226 -0
- package/lib/thread-naming.ts +118 -0
- package/lib/threads.ts +1686 -129
- package/lib/updates.ts +1319 -97
- package/lib/workspace-admission.ts +1643 -0
- package/lib/workspace-retirement.ts +968 -0
- package/lib/workspace-slots.ts +84 -0
- package/package.json +1 -1
- package/screenshot.png +0 -0
- package/scripts/measure-bus.mjs +83 -0
- package/scripts/measure-workspace.mjs +101 -0
- package/skills/show-me/SKILL.md +166 -0
- package/skills/show-me/references/telegram-surfaces.md +43 -0
- package/skills/telegram-bridge/references/delivery-and-threads.md +1 -1
package/lib/replies.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
getTelegramTargetThreadParams,
|
|
10
10
|
type TelegramTarget,
|
|
11
11
|
} from "./target.ts";
|
|
12
|
+
import { isTelegramApiCommitUnknownError } from "./telegram-api.ts";
|
|
12
13
|
import type {
|
|
13
14
|
TelegramInputRichMessage,
|
|
14
15
|
TelegramReplyParameters,
|
|
@@ -67,6 +68,7 @@ export function createReplyDedupRuntime(): ReplyDedupRuntime {
|
|
|
67
68
|
// --- Transport-level dedup ---
|
|
68
69
|
|
|
69
70
|
const lastRepliedToMessageIdByTarget = new Map<string, number>();
|
|
71
|
+
let replyDedupGeneration = 0;
|
|
70
72
|
|
|
71
73
|
function getReplyDedupTargetKey(
|
|
72
74
|
chatId: number,
|
|
@@ -79,6 +81,7 @@ function getReplyDedupTargetKey(
|
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
export function resetTransportReplyDedup(): void {
|
|
84
|
+
replyDedupGeneration += 1;
|
|
82
85
|
lastRepliedToMessageIdByTarget.clear();
|
|
83
86
|
}
|
|
84
87
|
|
|
@@ -99,13 +102,29 @@ export function buildTelegramReplyParameters(
|
|
|
99
102
|
};
|
|
100
103
|
}
|
|
101
104
|
|
|
102
|
-
|
|
105
|
+
// Answer publications are caller-serialized. A rejected send releases its anchor;
|
|
106
|
+
// an uncertain ACK retains it because Telegram may already have delivered it.
|
|
107
|
+
export async function withTelegramReplyParameters<T>(
|
|
103
108
|
chatId: number,
|
|
104
109
|
messageId: number | undefined,
|
|
105
|
-
target
|
|
106
|
-
|
|
110
|
+
target: TelegramTarget | undefined,
|
|
111
|
+
send: (parameters: TelegramReplyParameters | undefined) => Promise<T>,
|
|
112
|
+
): Promise<T> {
|
|
113
|
+
const key = getReplyDedupTargetKey(chatId, target);
|
|
114
|
+
const generation = replyDedupGeneration;
|
|
115
|
+
const previous = lastRepliedToMessageIdByTarget.get(key);
|
|
107
116
|
const parameters = buildTelegramReplyParameters(chatId, messageId, target);
|
|
108
|
-
|
|
117
|
+
try {
|
|
118
|
+
return await send(parameters);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (parameters && !isTelegramApiCommitUnknownError(error)
|
|
121
|
+
&& generation === replyDedupGeneration
|
|
122
|
+
&& lastRepliedToMessageIdByTarget.get(key) === messageId) {
|
|
123
|
+
if (previous === undefined) lastRepliedToMessageIdByTarget.delete(key);
|
|
124
|
+
else lastRepliedToMessageIdByTarget.set(key, previous);
|
|
125
|
+
}
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
109
128
|
}
|
|
110
129
|
|
|
111
130
|
function getAgentMessageField(message: unknown, field: string): unknown {
|
|
@@ -239,24 +258,18 @@ export async function sendTelegramRenderedChunks<TReplyMarkup>(
|
|
|
239
258
|
assertTelegramInlineKeyboardCallbackData(options?.replyMarkup);
|
|
240
259
|
let lastMessageId: number | undefined;
|
|
241
260
|
for (const [index, chunk] of chunks.entries()) {
|
|
242
|
-
const
|
|
243
|
-
index === 0
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
reply_markup:
|
|
255
|
-
index === chunks.length - 1 ? options?.replyMarkup : undefined,
|
|
256
|
-
...(replyParameters ? { reply_parameters: replyParameters } : {}),
|
|
257
|
-
...(options?.target ? getTelegramTargetThreadParams(options.target) : {}),
|
|
258
|
-
};
|
|
259
|
-
const sent = await deps.sendMessage(body);
|
|
261
|
+
const sent = await withTelegramReplyParameters(
|
|
262
|
+
chatId, index === 0 ? options?.replyToMessageId : undefined, options?.target,
|
|
263
|
+
(replyParameters) => deps.sendMessage({
|
|
264
|
+
chat_id: chatId,
|
|
265
|
+
text: chunk.text,
|
|
266
|
+
parse_mode: chunk.parseMode,
|
|
267
|
+
reply_markup:
|
|
268
|
+
index === chunks.length - 1 ? options?.replyMarkup : undefined,
|
|
269
|
+
...(replyParameters ? { reply_parameters: replyParameters } : {}),
|
|
270
|
+
...(options?.target ? getTelegramTargetThreadParams(options.target) : {}),
|
|
271
|
+
}),
|
|
272
|
+
);
|
|
260
273
|
lastMessageId = sent.message_id;
|
|
261
274
|
deps.recordOwnership?.({
|
|
262
275
|
chatId,
|
|
@@ -655,22 +668,17 @@ export async function sendTelegramNativeMarkdownReply<TReplyMarkup = unknown>(
|
|
|
655
668
|
let lastMessageId: number | undefined;
|
|
656
669
|
const chunks = splitTelegramNativeMarkdown(markdown);
|
|
657
670
|
for (const [index, chunk] of chunks.entries()) {
|
|
658
|
-
const
|
|
659
|
-
index === 0
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
:
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
reply_markup:
|
|
670
|
-
index === chunks.length - 1 ? options?.replyMarkup : undefined,
|
|
671
|
-
...(replyParameters ? { reply_parameters: replyParameters } : {}),
|
|
672
|
-
...(options?.target ? getTelegramTargetThreadParams(options.target) : {}),
|
|
673
|
-
});
|
|
671
|
+
const sent = await withTelegramReplyParameters(
|
|
672
|
+
chatId, index === 0 ? replyToMessageId : undefined, options?.target,
|
|
673
|
+
(replyParameters) => deps.sendRichMessage({
|
|
674
|
+
chat_id: chatId,
|
|
675
|
+
rich_message: { markdown: chunk },
|
|
676
|
+
reply_markup:
|
|
677
|
+
index === chunks.length - 1 ? options?.replyMarkup : undefined,
|
|
678
|
+
...(replyParameters ? { reply_parameters: replyParameters } : {}),
|
|
679
|
+
...(options?.target ? getTelegramTargetThreadParams(options.target) : {}),
|
|
680
|
+
}),
|
|
681
|
+
);
|
|
674
682
|
lastMessageId = sent.message_id;
|
|
675
683
|
deps.recordOwnership?.({
|
|
676
684
|
chatId,
|
|
@@ -886,7 +894,7 @@ export function createGuestMarkdownReplySender(deps: {
|
|
|
886
894
|
return async (guestQueryId: string, markdown: string) => {
|
|
887
895
|
const [richMarkdown = markdown] = splitTelegramNativeMarkdown(markdown);
|
|
888
896
|
await deps.answerGuestQuery(guestQueryId, undefined, {
|
|
889
|
-
richMessage: { markdown: richMarkdown
|
|
897
|
+
richMessage: { markdown: richMarkdown },
|
|
890
898
|
});
|
|
891
899
|
};
|
|
892
900
|
}
|