fix: make dave telegram alerts conversational
All checks were successful
Codex Template Compliance / template-compliance (pull_request) Successful in 32s
Build / test-and-image (pull_request) Successful in 2m4s

This commit is contained in:
2026-07-11 10:58:37 +02:00
parent 8de9feda62
commit 1178146d59
7 changed files with 178 additions and 40 deletions

View File

@@ -212,9 +212,6 @@ if (telegramAlerter.isConfigured) {
}
const chatId = msg?.chat?.id || config.telegram.chatId;
const result = await telegramChatAssistant.replyDetailed(question, { chatId });
const german = securityProfileStore.getAgentProfile()?.language === 'de';
const tools = [...new Set((result.trace || []).filter(item => item.status === 'ok').map(item => item.tool))];
const traceSuffix = tools.length ? `\n\n${german ? 'Verwendete Werkzeuge' : 'Tools used'}: ${tools.join(', ')}` : '';
if (result.pendingAction) {
const action = result.pendingAction;
return {
@@ -228,7 +225,7 @@ if (telegramAlerter.isConfigured) {
},
};
}
return { text: `${result.answer}${traceSuffix}`, parseMode: null, conversation: true, maxChunkChars: 900 };
return { text: result.answer, parseMode: null, conversation: true, maxChunkChars: 380 };
};
telegramAlerter.onMessage((text, msg) => {
@@ -872,15 +869,16 @@ async function runSweepCycle() {
// 6. Alert evaluation — Telegram + Discord (LLM with rule-based fallback, multi-tier, semantic dedup)
if (delta?.summary?.totalChanges > 0) {
if (telegramAlerter.isConfigured) {
const telegramAlertOpts = { language: securityProfileStore.getAgentProfile()?.language || null };
if (config.telegram.agentEnabled && config.telegram.agentProactiveEnabled && shouldRunProactiveAgent(delta)) {
runProactiveAgent(synthesized, delta).catch(err => {
console.error('[Agent] Proactive analysis failed, using rule fallback:', err.message);
telegramAlerter.evaluateAndAlert(null, delta, memory).catch(fallbackError => {
telegramAlerter.evaluateAndAlert(null, delta, memory, telegramAlertOpts).catch(fallbackError => {
console.error('[Crucix] Telegram alert fallback error:', fallbackError.message);
});
});
} else {
telegramAlerter.evaluateAndAlert(llmProvider, delta, memory).catch(err => {
telegramAlerter.evaluateAndAlert(llmProvider, delta, memory, telegramAlertOpts).catch(err => {
console.error('[Crucix] Telegram alert error:', err.message);
});
}
@@ -927,7 +925,7 @@ function shouldRunProactiveAgent(delta) {
async function runProactiveAgent(data, delta) {
if (telegramAlerter.getMuteStatus().muted) return false;
const prompt = `Evaluate the latest sweep as the operator's Security Manager. Use the security profile when available to assess geographic and personal relevance, dependencies, urgency, and preferred language. Cross-check material changes with source health, evidence, scenarios, memory, predictions, and web_search when current external corroboration is needed. Distinguish verified facts from inference. Do not call mutating tools. If you notify, write like a live Telegram chat: short first message, no visible Markdown, no report wall. Delta summary: ${JSON.stringify(delta?.summary || {})}`;
const prompt = `Evaluate the latest sweep as the operator's Security Manager. Use the security profile when available to assess geographic and personal relevance, dependencies, urgency, and preferred language. Cross-check material changes with source health, evidence, scenarios, memory, predictions, and web_search when current external corroboration is needed. Distinguish verified facts from inference. Do not call mutating tools. If you notify, write like a human Telegram contact: one short thought, one optional follow-up question, no visible Markdown, no headings, no lists, no report wall, no tool names, and keep the final answer below 420 characters when possible. Delta summary: ${JSON.stringify(delta?.summary || {})}`;
const profile = securityProfileStore.getAgentProfile();
const result = await terminalAgent.analyzeProactively(prompt, {
context: buildTelegramChatContext(data, buildHealth()),
@@ -937,25 +935,22 @@ async function runProactiveAgent(data, delta) {
if (result.pendingAction) return false;
const policy = evaluateSecurityAlertPolicy(result, profile);
if (!profile && !result.notify) {
return telegramAlerter.evaluateAndAlert(null, delta, memory);
return telegramAlerter.evaluateAndAlert(null, delta, memory, { language: profile?.language || null });
}
if (!policy.send) {
console.log(`[Security Manager] Proactive notification suppressed: ${policy.reason}`);
return false;
}
const german = profile?.language === 'de';
const evidence = result.evidence?.length ? `${german ? 'Belege' : 'Evidence'}:\n${result.evidence.map(item => `- ${item}`).join('\n')}` : '';
const tools = [...new Set((result.trace || []).filter(item => item.status === 'ok').map(item => item.tool))];
const trace = tools.length ? `${german ? 'Werkzeuge' : 'Tools'}: ${tools.join(', ')}` : '';
const evidence = result.evidence?.length ? `${german ? 'Belege' : 'Evidence'}:\n${result.evidence.slice(0, 2).map(item => `- ${String(item).slice(0, 120)}`).join('\n')}` : '';
const priority = german
? ({ routine: 'HINWEIS', priority: 'PRIORITÄT', flash: 'SOFORT' }[result.priority] || 'HINWEIS')
: String(result.priority || 'routine').toUpperCase();
const messages = [
`[DAVE // ${priority}]\n${result.answer}`,
evidence,
trace,
].filter(Boolean);
const sent = await telegramAlerter.sendConversation(messages, { maxChunkChars: 800 });
const sent = await telegramAlerter.sendConversation(messages, { maxChunkChars: 380 });
return sent.ok;
}