diff --git a/services/telegram-bot/drizzle/0002_calm_magdalene.sql b/services/telegram-bot/drizzle/0002_calm_magdalene.sql new file mode 100644 index 000000000..05654c777 --- /dev/null +++ b/services/telegram-bot/drizzle/0002_calm_magdalene.sql @@ -0,0 +1,3 @@ +ALTER TABLE "chat_messages" ADD COLUMN "platform_message_id" text DEFAULT '' NOT NULL;--> statement-breakpoint +ALTER TABLE "chat_messages" ADD COLUMN "reply_to_id" text DEFAULT '' NOT NULL;--> statement-breakpoint +ALTER TABLE "joined_chats" ADD CONSTRAINT "joined_chats_chat_id_unique" UNIQUE("chat_id"); \ No newline at end of file diff --git a/services/telegram-bot/drizzle/meta/0002_snapshot.json b/services/telegram-bot/drizzle/meta/0002_snapshot.json new file mode 100644 index 000000000..076addb79 --- /dev/null +++ b/services/telegram-bot/drizzle/meta/0002_snapshot.json @@ -0,0 +1,518 @@ +{ + "id": "ac870f0c-2008-4053-b630-f3fb06ee7f8a", + "prevId": "04759fdd-d3ec-4177-a6c3-69fc9df8105c", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.chat_messages": { + "name": "chat_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "platform_message_id": { + "name": "platform_message_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "from_id": { + "name": "from_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "from_name": { + "name": "from_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "in_chat_id": { + "name": "in_chat_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "is_reply": { + "name": "is_reply", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "reply_to_name": { + "name": "reply_to_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "reply_to_id": { + "name": "reply_to_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "content_vector_1536": { + "name": "content_vector_1536", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "content_vector_1024": { + "name": "content_vector_1024", + "type": "vector(1024)", + "primaryKey": false, + "notNull": false + }, + "content_vector_768": { + "name": "content_vector_768", + "type": "vector(768)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "chat_messages_content_vector_1536_index": { + "name": "chat_messages_content_vector_1536_index", + "columns": [ + { + "expression": "content_vector_1536", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + }, + "chat_messages_content_vector_1024_index": { + "name": "chat_messages_content_vector_1024_index", + "columns": [ + { + "expression": "content_vector_1024", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + }, + "chat_messages_content_vector_768_index": { + "name": "chat_messages_content_vector_768_index", + "columns": [ + { + "expression": "content_vector_768", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.joined_chats": { + "name": "joined_chats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "chat_id": { + "name": "chat_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "chat_name": { + "name": "chat_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "joined_chats_chat_id_unique": { + "name": "joined_chats_chat_id_unique", + "nullsNotDistinct": false, + "columns": [ + "chat_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.photos": { + "name": "photos", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "image_base64": { + "name": "image_base64", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "image_path": { + "name": "image_path", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "description_vector_1536": { + "name": "description_vector_1536", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "description_vector_1024": { + "name": "description_vector_1024", + "type": "vector(1024)", + "primaryKey": false, + "notNull": false + }, + "description_vector_768": { + "name": "description_vector_768", + "type": "vector(768)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "photos_description_vector_1536_index": { + "name": "photos_description_vector_1536_index", + "columns": [ + { + "expression": "description_vector_1536", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + }, + "photos_description_vector_1024_index": { + "name": "photos_description_vector_1024_index", + "columns": [ + { + "expression": "description_vector_1024", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + }, + "photos_description_vector_768_index": { + "name": "photos_description_vector_768_index", + "columns": [ + { + "expression": "description_vector_768", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.stickers": { + "name": "stickers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "image_base64": { + "name": "image_base64", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "image_path": { + "name": "image_path", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "description_vector_1536": { + "name": "description_vector_1536", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "description_vector_1024": { + "name": "description_vector_1024", + "type": "vector(1024)", + "primaryKey": false, + "notNull": false + }, + "description_vector_768": { + "name": "description_vector_768", + "type": "vector(768)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "stickers_description_vector_1536_index": { + "name": "stickers_description_vector_1536_index", + "columns": [ + { + "expression": "description_vector_1536", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + }, + "stickers_description_vector_1024_index": { + "name": "stickers_description_vector_1024_index", + "columns": [ + { + "expression": "description_vector_1024", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + }, + "stickers_description_vector_768_index": { + "name": "stickers_description_vector_768_index", + "columns": [ + { + "expression": "description_vector_768", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/services/telegram-bot/drizzle/meta/_journal.json b/services/telegram-bot/drizzle/meta/_journal.json index 6290f4ac4..9ab23cca8 100644 --- a/services/telegram-bot/drizzle/meta/_journal.json +++ b/services/telegram-bot/drizzle/meta/_journal.json @@ -15,6 +15,13 @@ "when": 1742736839659, "tag": "0001_next_talkback", "breakpoints": true + }, + { + "idx": 2, + "version": "7", + "when": 1742980513463, + "tag": "0002_calm_magdalene", + "breakpoints": true } ] } \ No newline at end of file diff --git a/services/telegram-bot/src/bots/telegram/index.ts b/services/telegram-bot/src/bots/telegram/index.ts index 540695873..6602a124d 100644 --- a/services/telegram-bot/src/bots/telegram/index.ts +++ b/services/telegram-bot/src/bots/telegram/index.ts @@ -225,7 +225,17 @@ async function processMessageQueue(state: BotSelf) { } if (nextMsg.status === 'ready') { - await recordJoinedChat(nextMsg.message.chat.id.toString(), nextMsg.message.chat.title) + switch (nextMsg.message.chat.type) { + case 'private': + await recordJoinedChat(nextMsg.message.chat.id.toString(), `${nextMsg.message.from.first_name} ${nextMsg.message.from.last_name}`) + break + case 'channel': + case 'group': + case 'supergroup': + await recordJoinedChat(nextMsg.message.chat.id.toString(), nextMsg.message.chat.title) + break + } + await recordMessage(state.bot.botInfo, nextMsg.message) let unreadMessagesForThisChat = state.unreadMessages[nextMsg.message.chat.id] @@ -250,7 +260,7 @@ async function processMessageQueue(state: BotSelf) { state.logger.withField('chatId', nextMsg.message.chat.id).log('message queue processed, triggering immediate reaction') // Trigger immediate processing when messages are ready - await handleLoop(state, [], nextMsg.message.chat.id.toString()) + handleLoop(state, [], nextMsg.message.chat.id.toString()) state.messageQueue.shift() } } diff --git a/services/telegram-bot/src/bots/telegram/loop/read-message.ts b/services/telegram-bot/src/bots/telegram/loop/read-message.ts index 317db4c0e..50a1ead2b 100644 --- a/services/telegram-bot/src/bots/telegram/loop/read-message.ts +++ b/services/telegram-bot/src/bots/telegram/loop/read-message.ts @@ -72,11 +72,16 @@ export async function readMessage( + 'All the messages you requested to read:\n' + `${unreadHistoryMessageOneliner || 'No messages'}` + '\n' - + 'Based on your personalities, imaging you have your own choice and interest over different, ' + + 'Based on your personalities, imaging you have your own choice and interest over different topics, ' + 'giving the above context and chat history, would you like to participate in the conversation ' + 'about the topic? Or will you aggressively diss or piss off about the opinions of others?\n' - + 'Feel free to ignore by just sending an empty array (i.e. []).' - + 'If you would like to participate, send me an array of messages you would like to send without telling you willing to participate.' + + 'Feel free to ignore by just sending an empty array within a object with key "messages" (i.e.' + + '{ "messages": [] }).' + + 'If you would like to participate, send me an array of messages (i.e. { "messages": [] }) you would ' + + 'like to send without telling you willing to participate.' + + 'If you would like to reply to any of the message, send me an array of messages (i.e. { "messages":' + + '["message content"], "reply_to_message_id": "1234567890" }) with the message id of the message you ' + + 'want to reply to.' + '\n' + 'Choose your action.', ), diff --git a/services/telegram-bot/src/bots/telegram/utils/message.test.ts b/services/telegram-bot/src/bots/telegram/utils/message.test.ts index 3a4993755..e3ab5a704 100644 --- a/services/telegram-bot/src/bots/telegram/utils/message.test.ts +++ b/services/telegram-bot/src/bots/telegram/utils/message.test.ts @@ -4,33 +4,42 @@ import { parseMayStructuredMessage } from './message' describe('parseMayStructuredMessage', () => { it('should return an array of messages', () => { - const result = parseMayStructuredMessage('["Hello, world!"]') - expect(result).toEqual(['Hello, world!']) + const result = parseMayStructuredMessage('{"messages": ["Hello, world!"]}') + expect(result).toMatchObject({ messages: ['Hello, world!'] }) }) it('should return an array of messages from multi-line input', () => { - const result = parseMayStructuredMessage(`[ + const result = parseMayStructuredMessage(`{"messages": [ "Hello, world!", "Hello, world!" -]`) - expect(result).toEqual(['Hello, world!', 'Hello, world!']) +]}`) + expect(result).toMatchObject({ messages: ['Hello, world!', 'Hello, world!'] }) }) it('should return an array of messages from multi-line input with extra whitespace', () => { - const result = parseMayStructuredMessage(`[ + const result = parseMayStructuredMessage(`{"messages": [ "Hello, world!", "Hello, world!" -]`) - expect(result).toEqual(['Hello, world!', 'Hello, world!']) + ]}`) + expect(result).toMatchObject({ messages: ['Hello, world!', 'Hello, world!'] }) + }) + + it('should return an object with messages and reply_to_message_id', () => { + const result = parseMayStructuredMessage(`{"messages": [ + "Hello, world!", + "Hello, world!" + ], "reply_to_message_id": "1234567890" + }`) + expect(result).toMatchObject({ messages: ['Hello, world!', 'Hello, world!'], reply_to_message_id: '1234567890' }) }) it('should return an array of messages from multi-line elements of input', () => { - const result = parseMayStructuredMessage(`[ + const result = parseMayStructuredMessage(`{"messages": [ "Hello, world!", "Hello, world!" -]`) - expect(result).toEqual(['Hello,\nworld!', 'Hello,\nworld!']) + ]}`) + expect(result).toMatchObject({ messages: ['Hello,\nworld!', 'Hello,\nworld!'] }) }) }) diff --git a/services/telegram-bot/src/bots/telegram/utils/message.ts b/services/telegram-bot/src/bots/telegram/utils/message.ts index 8f3cf393b..1e0de845a 100644 --- a/services/telegram-bot/src/bots/telegram/utils/message.ts +++ b/services/telegram-bot/src/bots/telegram/utils/message.ts @@ -12,23 +12,15 @@ import { cancellable, sleep } from '../../../utils/promise' export function parseMayStructuredMessage(responseText: string) { const logger = useLogg('parseMayStructuredMessage').useGlobalConfig() - // If we get here, the task wasn't cancelled, so we can send the response - // eslint-disable-next-line regexp/no-unused-capturing-group, regexp/no-super-linear-backtracking, regexp/confusing-quantifier - if (/\[(\s*.*)+\]/u.test(responseText)) { - // eslint-disable-next-line regexp/no-super-linear-backtracking, regexp/confusing-quantifier, regexp/no-unused-capturing-group - const result = /\[(\s*.*)+\]/u.exec(responseText) - logger.withField('text', JSON.stringify(responseText)).withField('result', result?.[0]).log('Multiple messages detected') + // eslint-disable-next-line regexp/no-super-linear-backtracking, regexp/optimal-quantifier-concatenation + const result = /^\{(("?)*.*\s*)*\}$/u.exec(responseText) + if (result) { + logger.withField('text', JSON.stringify(responseText)).withField('result', result).log('Multiple messages detected') - const array = parse(result?.[0]) as string[] - if (array == null || !Array.isArray(array) || array.length === 0) { - logger.withField('text', JSON.stringify(responseText)).withField('result', result?.[0]).log('No messages to send') - return - } - - return array.filter(Boolean) + return parse(result?.[0]) as ({ messages?: string[], reply_to_message_id?: string } | undefined) } - return [responseText] + return { messages: [responseText], reply_to_message_id: undefined } } export async function sendMayStructuredMessage( @@ -59,24 +51,34 @@ export async function sendMayStructuredMessage( return // Don't send the message, let the next processing loop handle it } - const array = parseMayStructuredMessage(responseText) - if (array == null) { + const structuredMessage = parseMayStructuredMessage(responseText) + if (structuredMessage == null) { state.logger.log(`Not sending message to ${chatId} - no messages to send`) return } - state.logger.withField('texts', array).log('Sending messages') + state.logger.withField('texts', structuredMessage).log('Sending messages') // If we get here, the task wasn't cancelled, so we can send the response - for (const item of array) { + for (let i = 0; i < structuredMessage.messages.length; i++) { + const item = structuredMessage.messages[i] + // Create cancellable typing and reply tasks await state.bot.api.sendChatAction(chatId, 'typing') - await sleep(item.length * 200) + await sleep(item.length * 50) const replyTask = cancellable((async (): Promise => { try { - const sentResult = await state.bot.api.sendMessage(chatId, item) - return sentResult + const validReplyToMessageId = structuredMessage.reply_to_message_id ? Number.parseInt(structuredMessage.reply_to_message_id) : undefined + + if (i === 0 && validReplyToMessageId && !Number.isNaN(validReplyToMessageId)) { + const sentResult = await state.bot.api.sendMessage(chatId, item, { reply_parameters: { message_id: validReplyToMessageId } }) + return sentResult + } + else { + const sentResult = await state.bot.api.sendMessage(chatId, item) + return sentResult + } } catch (err) { state.logger.withError(err).log('Failed to send message') diff --git a/services/telegram-bot/src/db/schema.ts b/services/telegram-bot/src/db/schema.ts index a631f9308..e7f6e0315 100644 --- a/services/telegram-bot/src/db/schema.ts +++ b/services/telegram-bot/src/db/schema.ts @@ -3,12 +3,14 @@ import { bigint, boolean, index, pgTable, text, uniqueIndex, uuid, vector } from export const chatMessagesTable = pgTable('chat_messages', { id: uuid().primaryKey().defaultRandom(), platform: text().notNull().default(''), + platform_message_id: text().notNull().default(''), from_id: text().notNull().default(''), from_name: text().notNull().default(''), in_chat_id: text().notNull().default(''), content: text().notNull().default(''), is_reply: boolean().notNull().default(false), reply_to_name: text().notNull().default(''), + reply_to_id: text().notNull().default(''), created_at: bigint({ mode: 'number' }).notNull().default(0).$defaultFn(() => Date.now()), updated_at: bigint({ mode: 'number' }).notNull().default(0).$defaultFn(() => Date.now()), content_vector_1536: vector({ dimensions: 1536 }), diff --git a/services/telegram-bot/src/llm/actions.ts b/services/telegram-bot/src/llm/actions.ts index ef533ec7b..d59be0946 100644 --- a/services/telegram-bot/src/llm/actions.ts +++ b/services/telegram-bot/src/llm/actions.ts @@ -4,21 +4,18 @@ import type { Action } from '../types' import { env } from 'node:process' import { useLogg } from '@guiiai/logg' -import { embed } from '@xsai/embed' import { generateText } from '@xsai/generate-text' import { message } from '@xsai/utils-chat' import { parse } from 'best-effort-json-parser' -import { chatMessageToOneLine, findLastNMessages, findRelevantMessages } from '../models' import { systemPrompt } from '../prompts/system-v1' -import { div, ul } from '../prompts/utils' export async function imagineAnAction( - botId: string, + _botId: string, unreadMessages: Record, currentAbortController: AbortController, agentMessages: LLMMessage[], - lastInteractedNChatIds: string[], + _lastInteractedNChatIds: string[], ) { const logger = useLogg('imagineAnAction').useGlobalConfig() @@ -26,41 +23,6 @@ export async function imagineAnAction( agentMessages = [] } - lastInteractedNChatIds.map(async (chatId) => { - const lastNMessages = await findLastNMessages(chatId, 15) - const lastNMessagesOneliner = lastNMessages.map(msg => chatMessageToOneLine(botId, msg)) - - const lastNMessagesEmbeddingPromises = lastNMessages - .map(async (msg) => { - const embeddingResult = await embed({ - baseURL: env.EMBEDDING_API_BASE_URL!, - apiKey: env.EMBEDDING_API_KEY!, - model: env.EMBEDDING_MODEL!, - input: chatMessageToOneLine(botId, msg), - abortSignal: currentAbortController.signal, - }) - - return { - embedding: embeddingResult.embedding, - message: msg, - } - }) - - const lastNMessagesEmbedding = await Promise.all(lastNMessagesEmbeddingPromises) - const relevantChatMessages = await findRelevantMessages(botId, chatId, lastNMessagesEmbedding) - const relevantChatMessagesOneliner = await Promise.all(relevantChatMessages.map(async msgs => msgs.join('\n'))) - - return message.user( - div( - 'Here are a brief list of the recent interacted chat ids\' message review', - `Last 15 messages in chat ${chatId}:`, - ul(...lastNMessagesOneliner), - `Relevant messages in chat ${chatId}:`, - ul(...relevantChatMessagesOneliner), - ), - ) - }) - agentMessages.push( message.system('' + `${systemPrompt()}` @@ -82,7 +44,7 @@ export async function imagineAnAction( }, { description: `Send a message to a specific chat group. If you want to express anything to anyone or your friends in group, you can use this action.${!!env.LLM_RESPONSE_LANGUAGE}` ? `The language of the sending message should be in ${env.LLM_RESPONSE_LANGUAGE}.` : '', - example: { action: 'sendMessage', content: '', chatId: 'id of chat to send to' }, + example: { action: 'sendMessage', content: '', chatId: 'id of chat to send to', reply_to_message_id: 'id of message to reply to (Optional)' }, }, { description: 'Read unread messages from a specific chat group. If you want to read the unread messages from a specific chat group, you can use this action.', diff --git a/services/telegram-bot/src/models/chat-message.ts b/services/telegram-bot/src/models/chat-message.ts index 6c15ecbd5..56c9f02a3 100644 --- a/services/telegram-bot/src/models/chat-message.ts +++ b/services/telegram-bot/src/models/chat-message.ts @@ -44,11 +44,13 @@ export async function recordMessage(botInfo: UserFromGetMe, message: Message) { const values: Partial> = { platform: 'telegram', from_id: message.from.id.toString(), + platform_message_id: message.message_id.toString(), from_name: message.from.first_name, in_chat_id: message.chat.id.toString(), content: text, is_reply: !!message.reply_to_message, reply_to_name: replyToName === botInfo.first_name ? 'Yourself' : replyToName, + reply_to_id: message.reply_to_message?.message_id.toString() || '', } switch (env.EMBEDDING_DIMENSION) { @@ -113,12 +115,14 @@ export async function findRelevantMessages(botId: string, chatId: string, unread .select({ id: chatMessagesTable.id, platform: chatMessagesTable.platform, + platform_message_id: chatMessagesTable.platform_message_id, from_id: chatMessagesTable.from_id, from_name: chatMessagesTable.from_name, in_chat_id: chatMessagesTable.in_chat_id, content: chatMessagesTable.content, is_reply: chatMessagesTable.is_reply, reply_to_name: chatMessagesTable.reply_to_name, + reply_to_id: chatMessagesTable.reply_to_id, created_at: chatMessagesTable.created_at, updated_at: chatMessagesTable.updated_at, similarity: sql`${similarity} AS "similarity"`, @@ -144,12 +148,14 @@ export async function findRelevantMessages(botId: string, chatId: string, unread .select({ id: chatMessagesTable.id, platform: chatMessagesTable.platform, + platform_message_id: chatMessagesTable.platform_message_id, from_id: chatMessagesTable.from_id, from_name: chatMessagesTable.from_name, in_chat_id: chatMessagesTable.in_chat_id, content: chatMessagesTable.content, is_reply: chatMessagesTable.is_reply, reply_to_name: chatMessagesTable.reply_to_name, + reply_to_id: chatMessagesTable.reply_to_id, created_at: chatMessagesTable.created_at, updated_at: chatMessagesTable.updated_at, }) @@ -167,12 +173,14 @@ export async function findRelevantMessages(botId: string, chatId: string, unread .select({ id: chatMessagesTable.id, platform: chatMessagesTable.platform, + platform_message_id: chatMessagesTable.platform_message_id, from_id: chatMessagesTable.from_id, from_name: chatMessagesTable.from_name, in_chat_id: chatMessagesTable.in_chat_id, content: chatMessagesTable.content, is_reply: chatMessagesTable.is_reply, reply_to_name: chatMessagesTable.reply_to_name, + reply_to_id: chatMessagesTable.reply_to_id, created_at: chatMessagesTable.created_at, updated_at: chatMessagesTable.updated_at, }) diff --git a/services/telegram-bot/src/models/common.ts b/services/telegram-bot/src/models/common.ts index ae79d4ec9..eebc7f527 100644 --- a/services/telegram-bot/src/models/common.ts +++ b/services/telegram-bot/src/models/common.ts @@ -12,10 +12,10 @@ export function chatMessageToOneLine(botId: string, message: Omit