This commit is contained in:
Taras Lukavyi 2026-01-30 17:41:44 +02:00 committed by GitHub
commit df9c1c786b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 3 deletions

View File

@ -56,6 +56,33 @@ describe("buildTelegramMessageContext dm thread sessions", () => {
expect(ctx?.ctxPayload?.SessionKey).toBe("agent:main:main:thread:42"); expect(ctx?.ctxPayload?.SessionKey).toBe("agent:main:main:thread:42");
}); });
it("sets ThreadLabel for dm topics for display in Sessions tab", async () => {
const ctx = await buildContext({
message_id: 1,
chat: { id: 1234, type: "private" },
date: 1700000000,
text: "hello",
message_thread_id: 42,
from: { id: 42, first_name: "Alice" },
});
expect(ctx).not.toBeNull();
expect(ctx?.ctxPayload?.ThreadLabel).toBe("Thread: 42");
});
it("does not set ThreadLabel for dm without thread id", async () => {
const ctx = await buildContext({
message_id: 1,
chat: { id: 1234, type: "private" },
date: 1700000000,
text: "hello",
from: { id: 42, first_name: "Alice" },
});
expect(ctx).not.toBeNull();
expect(ctx?.ctxPayload?.ThreadLabel).toBeUndefined();
});
it("keeps legacy dm session key when no thread id", async () => { it("keeps legacy dm session key when no thread id", async () => {
const ctx = await buildContext({ const ctx = await buildContext({
message_id: 2, message_id: 2,

View File

@ -161,6 +161,9 @@ export const buildTelegramMessageContext = async ({
isForum, isForum,
messageThreadId, messageThreadId,
}); });
// Effective thread ID for outbound delivery: groups use forum-resolved; DMs use raw messageThreadId
// (private chats never set is_forum=true per Telegram Bot API, so resolvedThreadId is always undefined for DMs)
const effectiveThreadId = isGroup ? resolvedThreadId : messageThreadId;
const { groupConfig, topicConfig } = resolveTelegramGroupConfig(chatId, resolvedThreadId); const { groupConfig, topicConfig } = resolveTelegramGroupConfig(chatId, resolvedThreadId);
const peerId = isGroup ? buildTelegramGroupPeerId(chatId, resolvedThreadId) : String(chatId); const peerId = isGroup ? buildTelegramGroupPeerId(chatId, resolvedThreadId) : String(chatId);
const route = resolveAgentRoute({ const route = resolveAgentRoute({
@ -203,7 +206,8 @@ export const buildTelegramMessageContext = async ({
const sendTyping = async () => { const sendTyping = async () => {
await withTelegramApiErrorLogging({ await withTelegramApiErrorLogging({
operation: "sendChatAction", operation: "sendChatAction",
fn: () => bot.api.sendChatAction(chatId, "typing", buildTypingThreadParams(resolvedThreadId)), fn: () =>
bot.api.sendChatAction(chatId, "typing", buildTypingThreadParams(effectiveThreadId)),
}); });
}; };
@ -212,7 +216,11 @@ export const buildTelegramMessageContext = async ({
await withTelegramApiErrorLogging({ await withTelegramApiErrorLogging({
operation: "sendChatAction", operation: "sendChatAction",
fn: () => fn: () =>
bot.api.sendChatAction(chatId, "record_voice", buildTypingThreadParams(resolvedThreadId)), bot.api.sendChatAction(
chatId,
"record_voice",
buildTypingThreadParams(effectiveThreadId),
),
}); });
} catch (err) { } catch (err) {
logVerbose(`telegram record_voice cue failed for chat ${chatId}: ${String(err)}`); logVerbose(`telegram record_voice cue failed for chat ${chatId}: ${String(err)}`);
@ -606,6 +614,8 @@ export const buildTelegramMessageContext = async ({
// For groups: use resolvedThreadId (forum topics only); for DMs: use raw messageThreadId // For groups: use resolvedThreadId (forum topics only); for DMs: use raw messageThreadId
MessageThreadId: isGroup ? resolvedThreadId : messageThreadId, MessageThreadId: isGroup ? resolvedThreadId : messageThreadId,
IsForum: isForum, IsForum: isForum,
// DM thread label for display in Sessions tab (e.g., "Sender Name (Thread: 42)")
ThreadLabel: !isGroup && messageThreadId != null ? `Thread: ${messageThreadId}` : undefined,
// Originating channel for reply routing. // Originating channel for reply routing.
OriginatingChannel: "telegram" as const, OriginatingChannel: "telegram" as const,
OriginatingTo: `telegram:${chatId}`, OriginatingTo: `telegram:${chatId}`,
@ -656,7 +666,7 @@ export const buildTelegramMessageContext = async ({
msg, msg,
chatId, chatId,
isGroup, isGroup,
resolvedThreadId, resolvedThreadId: effectiveThreadId,
isForum, isForum,
historyKey, historyKey,
historyLimit, historyLimit,

View File

@ -35,6 +35,8 @@ type LifecycleHost = {
export function handleConnected(host: LifecycleHost) { export function handleConnected(host: LifecycleHost) {
host.basePath = inferBasePath(); host.basePath = inferBasePath();
// Apply URL settings FIRST so sessionKey is read before syncTabWithLocation
// overwrites it with the localStorage value
applySettingsFromUrl( applySettingsFromUrl(
host as unknown as Parameters<typeof applySettingsFromUrl>[0], host as unknown as Parameters<typeof applySettingsFromUrl>[0],
); );