@llblab/pi-telegram 0.9.7 → 0.9.8
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 +7 -0
- package/lib/api.ts +1 -0
- package/lib/prompts.ts +2 -2
- package/lib/routing.ts +74 -3
- package/lib/updates.ts +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.8: Guest Mode Context
|
|
4
|
+
|
|
5
|
+
- `[Guest Mode]` Extended the [telegram] prefix with |from:user (sender) and |guest:GroupName (source chat for group guest messages) so the agent sees who sent the message and where from. Private guest chats omit the guest: suffix.
|
|
6
|
+
- `[Guest Mode]` Added |from:user to the [reply] block so the agent knows the original author of a replied-to message in guest mode.
|
|
7
|
+
- `[Guest Mode]` Formatted guest prompt text identically to regular DMs through buildTelegramTurnPrompt, including [attachments] and [outputs] sections with file downloads and inbound handler processing.
|
|
8
|
+
- `[Prompts]` Added compact agent guidance explaining guest-mode prefix suffixes (|from:, |guest:) and reply-from context.
|
|
9
|
+
|
|
3
10
|
## 0.9.7: Bot API 10.0 Alignment
|
|
4
11
|
|
|
5
12
|
- `[Dependencies]` Migrated peer dependencies and imports from `@mariozechner/*` to `@earendil-works/*` (`pi-agent-core`, `pi-ai`, `pi-coding-agent`). Impact: the extension now tracks the new `@earendil-works` package scope; transitive `@mariozechner` packages remain in the lockfile until their upstreams migrate.
|
package/lib/api.ts
CHANGED
package/lib/prompts.ts
CHANGED
|
@@ -12,8 +12,8 @@ const SYSTEM_PROMPT_SUFFIX = `
|
|
|
12
12
|
Telegram bridge extension is active.
|
|
13
13
|
|
|
14
14
|
Inbound context:
|
|
15
|
-
- \`[telegram]\` marks Telegram-originated messages.
|
|
16
|
-
- \`[reply]\` is quoted context from the replied-to message, not a new instruction by itself. Use it to resolve references like "this", "it", or "that message"; the actual instruction is before [reply] unless it explicitly asks to act on the quote.
|
|
15
|
+
- \`[telegram]\` marks Telegram-originated messages. Suffixes \`|from:user\` (sender) and \`|guest:group\` (guest mode — message from another chat where the bot is not a member) may be present; the bot sees the message as if forwarded from that user/chat.
|
|
16
|
+
- \`[reply]\` is quoted context from the replied-to message, not a new instruction by itself. Suffix \`|from:user\` identifies the original author in guest-mode replies. Use it to resolve references like "this", "it", or "that message"; the actual instruction is before [reply] unless it explicitly asks to act on the quote.
|
|
17
17
|
- \`[attachments]\` gives a base directory plus relative local files; resolve and read them as needed. \`[outputs]\` contains inbound-handler stdout such as transcriptions or extracted text for those attachments.
|
|
18
18
|
- Unknown \`[callback] ...\` messages may be intended for another extension; if you see one, say the callback was not handled and the environment may be misconfigured.
|
|
19
19
|
|
package/lib/routing.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import * as OutboundHandlers from "./outbound-handlers.ts";
|
|
8
8
|
import * as Commands from "./commands.ts";
|
|
9
|
+
import { readFile } from "node:fs/promises";
|
|
9
10
|
import type { TelegramConfigStore } from "./config.ts";
|
|
10
11
|
import type { TelegramInboundHandlerRuntime } from "./inbound-handlers.ts";
|
|
11
12
|
import * as Media from "./media.ts";
|
|
@@ -371,7 +372,71 @@ export function createTelegramInboundRouteRuntime<
|
|
|
371
372
|
ctx: TContext,
|
|
372
373
|
): Promise<void> => {
|
|
373
374
|
const text = guestMessage.text ?? "";
|
|
375
|
+
const gm = guestMessage as unknown as Record<string, unknown>;
|
|
376
|
+
// Build telegram prefix with guest context
|
|
377
|
+
const fromRaw = gm.from as Record<string, unknown> | undefined;
|
|
378
|
+
const fromName =
|
|
379
|
+
(fromRaw?.username as string) ||
|
|
380
|
+
(fromRaw?.first_name as string) ||
|
|
381
|
+
"";
|
|
382
|
+
const chatRaw = gm.chat as Record<string, unknown>;
|
|
383
|
+
const chatTitle = chatRaw?.title as string | undefined;
|
|
384
|
+
const chatType = chatRaw?.type as string;
|
|
385
|
+
const prefixParts = ["telegram"];
|
|
386
|
+
if (fromName) prefixParts.push(`from:${fromName}`);
|
|
387
|
+
if (chatType !== "private" && chatTitle) {
|
|
388
|
+
prefixParts.push(`guest:${chatTitle}`);
|
|
389
|
+
}
|
|
390
|
+
const telegramPrefix = `[${prefixParts.join("|")}]`;
|
|
391
|
+
// Extract reply context
|
|
392
|
+
const replyMsg = gm.reply_to_message as Record<string, unknown> | undefined;
|
|
393
|
+
const replyText =
|
|
394
|
+
replyMsg
|
|
395
|
+
? ((replyMsg.text as string) || (replyMsg.caption as string) || "").trim()
|
|
396
|
+
: "";
|
|
397
|
+
const replyFrom =
|
|
398
|
+
replyMsg
|
|
399
|
+
? (replyMsg.from as Record<string, unknown> | undefined)?.username as string | undefined
|
|
400
|
+
: undefined;
|
|
401
|
+
// Download files, run inbound handlers
|
|
402
|
+
const guestMsg = guestMessage as unknown as Media.TelegramMediaMessage;
|
|
403
|
+
const files = await Media.downloadTelegramMessageFiles([guestMsg], {
|
|
404
|
+
downloadFile: deps.downloadFile,
|
|
405
|
+
});
|
|
406
|
+
const processed = await deps.inboundHandlerRuntime.process(files, text, ctx);
|
|
407
|
+
let rawText = processed.rawText || text;
|
|
408
|
+
// Append reply context after handler processing
|
|
409
|
+
if (replyText) {
|
|
410
|
+
const replyBlock = replyFrom
|
|
411
|
+
? `[reply|from:${replyFrom}] ${replyText}`
|
|
412
|
+
: `[reply] ${replyText}`;
|
|
413
|
+
rawText = `${rawText}\n\n${replyBlock}`;
|
|
414
|
+
}
|
|
415
|
+
const promptText = Turns.buildTelegramTurnPrompt({
|
|
416
|
+
telegramPrefix,
|
|
417
|
+
rawText,
|
|
418
|
+
files,
|
|
419
|
+
promptFiles: processed.promptFiles,
|
|
420
|
+
handlerOutputs: processed.handlerOutputs,
|
|
421
|
+
});
|
|
374
422
|
const order = deps.bridgeRuntime.queue.allocateItemOrder();
|
|
423
|
+
const content: Queue.TelegramPromptContent[] = [
|
|
424
|
+
{ type: "text", text: promptText },
|
|
425
|
+
];
|
|
426
|
+
for (const file of processed.promptFiles) {
|
|
427
|
+
if (file.isImage && file.mimeType) {
|
|
428
|
+
try {
|
|
429
|
+
const buffer = await readFile(file.path);
|
|
430
|
+
content.push({
|
|
431
|
+
type: "image",
|
|
432
|
+
data: Buffer.from(buffer).toString("base64"),
|
|
433
|
+
mimeType: file.mimeType,
|
|
434
|
+
});
|
|
435
|
+
} catch {
|
|
436
|
+
// skip unreadable files
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
375
440
|
const guestTurn: Queue.PendingTelegramTurn = {
|
|
376
441
|
kind: "prompt",
|
|
377
442
|
chatId: 0,
|
|
@@ -382,9 +447,15 @@ export function createTelegramInboundRouteRuntime<
|
|
|
382
447
|
queueLane: "default",
|
|
383
448
|
laneOrder: order,
|
|
384
449
|
queuedAttachments: [],
|
|
385
|
-
content
|
|
386
|
-
historyText:
|
|
387
|
-
|
|
450
|
+
content,
|
|
451
|
+
historyText: Turns.formatTelegramTurnStatusSummary(
|
|
452
|
+
processed.rawText || text,
|
|
453
|
+
processed.promptFiles,
|
|
454
|
+
processed.handlerOutputs,
|
|
455
|
+
),
|
|
456
|
+
statusSummary: Turns.truncateTelegramQueueSummary(
|
|
457
|
+
processed.rawText || text,
|
|
458
|
+
),
|
|
388
459
|
};
|
|
389
460
|
const items = deps.telegramQueueStore.getQueuedItems();
|
|
390
461
|
deps.telegramQueueStore.setQueuedItems(
|
package/lib/updates.ts
CHANGED