feat: add conversational Telegram AI chat
This commit is contained in:
35
server.mjs
35
server.mjs
@@ -14,6 +14,7 @@ import { synthesize, generateIdeas } from './dashboard/inject.mjs';
|
||||
import { MemoryManager } from './lib/delta/index.mjs';
|
||||
import { createLLMProvider } from './lib/llm/index.mjs';
|
||||
import { generateLLMIdeas } from './lib/llm/ideas.mjs';
|
||||
import { TelegramChatAssistant, buildTelegramChatContext } from './lib/llm/telegram-chat.mjs';
|
||||
import { TelegramAlerter } from './lib/alerts/telegram.mjs';
|
||||
import { DiscordAlerter } from './lib/alerts/discord.mjs';
|
||||
import { getFetchMetrics } from './apis/utils/fetch.mjs';
|
||||
@@ -53,6 +54,14 @@ await intelligenceStore.init();
|
||||
const llmProvider = createLLMProvider(config.llm);
|
||||
const telegramAlerter = new TelegramAlerter(config.telegram);
|
||||
const discordAlerter = new DiscordAlerter(config.discord || {});
|
||||
const telegramChatAssistant = new TelegramChatAssistant({
|
||||
provider: llmProvider,
|
||||
getContext: () => buildTelegramChatContext(currentData, buildHealth()),
|
||||
historyMessages: config.telegram.aiHistoryMessages,
|
||||
maxInputChars: config.telegram.aiMaxInputChars,
|
||||
maxTokens: config.telegram.aiMaxTokens,
|
||||
timeoutMs: config.telegram.aiTimeoutMs,
|
||||
});
|
||||
|
||||
if (llmProvider) console.log(`[Crucix] LLM enabled: ${llmProvider.name} (${llmProvider.model})`);
|
||||
else if (config.llm.provider) console.warn(`[Crucix] LLM provider "${config.llm.provider}" is not configured; LLM features disabled`);
|
||||
@@ -82,6 +91,7 @@ if (telegramAlerter.isConfigured) {
|
||||
`Sweep in progress: ${sweepInProgress ? '🔄 Yes' : '⏸️ No'}`,
|
||||
`Sources: ${sourcesOk}/${sourcesTotal} OK${sourcesFailed > 0 ? ` (${sourcesFailed} failed)` : ''}`,
|
||||
`LLM: ${llmStatus}`,
|
||||
`AI chat: ${config.telegram.aiChatEnabled && telegramChatAssistant.isConfigured ? 'enabled' : 'disabled'}`,
|
||||
`SSE clients: ${sseClients.size}`,
|
||||
`Dashboard: http://localhost:${config.port}`,
|
||||
].join('\n');
|
||||
@@ -148,6 +158,26 @@ if (telegramAlerter.isConfigured) {
|
||||
return sections.join('\n');
|
||||
});
|
||||
|
||||
const answerTelegramQuestion = async (question, msg) => {
|
||||
if (!config.telegram.aiChatEnabled) {
|
||||
return { text: 'AI chat is disabled by TELEGRAM_AI_CHAT_ENABLED.', parseMode: null };
|
||||
}
|
||||
const text = await telegramChatAssistant.reply(question, { chatId: msg?.chat?.id || config.telegram.chatId });
|
||||
return { text, parseMode: null };
|
||||
};
|
||||
|
||||
telegramAlerter.onMessage((text, msg) => answerTelegramQuestion(text, msg));
|
||||
|
||||
telegramAlerter.onCommand('/ask', async (args, _messageId, msg) => {
|
||||
if (!args.trim()) return { text: 'Usage: /ask <question>', parseMode: null };
|
||||
return answerTelegramQuestion(args, msg);
|
||||
});
|
||||
|
||||
telegramAlerter.onCommand('/reset', async (_args, _messageId, msg) => {
|
||||
telegramChatAssistant.reset(msg?.chat?.id || config.telegram.chatId);
|
||||
return { text: 'AI conversation history cleared.', parseMode: null };
|
||||
});
|
||||
|
||||
telegramAlerter.onCommand('/portfolio', async () => {
|
||||
return '📊 Portfolio integration requires Alpaca MCP connection.\nUse the Crucix dashboard or Claude agent for portfolio queries.';
|
||||
});
|
||||
@@ -547,6 +577,11 @@ function buildHealth() {
|
||||
sourceHealth: currentData?.sourceHealth || currentData?.health || [],
|
||||
llm: getLLMStatus(),
|
||||
telegramEnabled: !!(config.telegram.botToken && config.telegram.chatId),
|
||||
telegramAiChat: {
|
||||
enabled: Boolean(config.telegram.aiChatEnabled && telegramChatAssistant.isConfigured),
|
||||
historyMessages: config.telegram.aiHistoryMessages,
|
||||
maxInputChars: config.telegram.aiMaxInputChars,
|
||||
},
|
||||
discordEnabled: !!(config.discord?.botToken || config.discord?.webhookUrl),
|
||||
terminalActionsEnabled: config.terminalActionsEnabled,
|
||||
terminalActionsTokenRequired: !!config.sweepToken,
|
||||
|
||||
Reference in New Issue
Block a user