feat(chat): typing indicator для ботов, кнопки ботов в мессенджере, VPN-бот с кнопками

- Добавлены SSE-события conv_typing_started/stopped и их обработка в Chat.tsx
- AI-бот публикует typing events перед/после генерации ответа
- Боты могут отправлять сообщения с кнопками через /api/bot/conversations/:id/messages
- Добавлен callback /api/messenger/messages/:id/callback для нажатий кнопок
- VPN-бот использует кнопки Android/iOS вместо текстового prompt
- Оптимистичное обновление unread count, ускоренный reportActiveChat, polling fallback,
  логирование SSE, push suppression для bot_direct
This commit is contained in:
2026-07-17 11:25:25 +03:00
parent 586a591773
commit 6bb89b4cf8
16 changed files with 492 additions and 60 deletions

View File

@@ -8,6 +8,7 @@ import { decrypt } from '../crypto';
import { semanticSearch } from './embedding.service';
import { McpClient } from '../utils/mcp-client';
import { eventBus } from '../routes/shared';
import { publishConvTypingEvent } from '../routes/messenger.helpers';
import { getOllamaNumThread, getOllamaNumCtx } from '../utils/ollama-config';
import type { Bot, Task, User } from '@shared/schema';
import { db } from '../db';
@@ -512,7 +513,10 @@ export async function handleAiBotDirectMessage(ctx: {
return;
}
const messages: LlmMessage[] = [];
try {
await publishConvTypingEvent(conversationId, bot.name, organizationId, true);
const messages: LlmMessage[] = [];
if (bot.sendSystemPrompt !== false) {
const systemContent = bot.systemPrompt?.trim()
@@ -657,7 +661,10 @@ export async function handleAiBotDirectMessage(ctx: {
mentionedUserIds: null,
attachments: null,
});
} catch (err) {
} finally {
await publishConvTypingEvent(conversationId, bot.name, organizationId, false).catch(() => {});
}
} catch (err) {
console.error('[AI-Bot Direct] Error:', err);
await db.insert(conversationMessages).values({
conversationId,