Send cronjob result and notify-agent reaction to Telegram
The cronjob notification ran the notify-agent on the result summary and sent only its reaction to Telegram. When the agent merely acknowledged the summary (e.g. "👍"), the actual cronjob result never reached Telegram — the user got a header plus an emoji and no information. Send the real result as the guaranteed first Telegram message, then run the notify-agent best-effort and send its reaction as a separate second message. The agent run is wrapped in try/catch with a canRunNotifyAgent guard instead of the old return-aborts, so a missing key / OpenAI without key / unavailable CLI only skips the reaction — the result is already delivered. The notify-agent still persists its reaction to the web history automatically (ChatNonStreaming / ChatNonStreamingViaCli). TelegramService.SendNotification now uses SendLongMessage so long results are chunked into 4096-char messages instead of being rejected whole. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
6e301b7498
commit
e395927a67
2 files changed
+87
-57
No files matched your search
+83
-56
@@ -178,43 +178,9 @@ public class CronjobService : BackgroundService
|
||||
return;
|
||||
}
|
||||
|
||||
// API-Key des Cronjob-Owners für Notify-Agent auflösen
|
||||
var notifyApiKey = await _db.GetAgentApiKeyRecord(job.UserId, notifyCtx.AgentId);
|
||||
bool notifyUseCliFallback = false;
|
||||
|
||||
if (notifyApiKey == null)
|
||||
{
|
||||
// Kein User-Key – Verhalten wie ExecuteCronjob/ChatEndpoint:
|
||||
// - Anthropic (Provider leer) → Claude-CLI-Fallback (sofern berechtigt/verfügbar)
|
||||
// - "openai" → abbrechen (kein Server-Key, kein CLI-Äquivalent)
|
||||
// - nvidia/gemini/minimax/pollinations → durchlassen: Server-Key via ResolveProviderConfig
|
||||
if (string.IsNullOrEmpty(notifyCtx.Provider))
|
||||
{
|
||||
var notifyOwner = await _db.GetUser(job.UserId);
|
||||
if ((notifyOwner != null && !notifyOwner.CanUseCli && !notifyOwner.IsAdmin) || !_anthropicService.IsCliAvailable)
|
||||
{
|
||||
_logger.LogWarning("Kein API-Key für Agent {AgentId} (Cronjob '{Name}' Notification) und CLI nicht verfügbar/berechtigt", notifyCtx.AgentId, job.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
notifyUseCliFallback = true;
|
||||
}
|
||||
else if (notifyCtx.Provider == "openai")
|
||||
{
|
||||
_logger.LogWarning("Kein API-Key für Agent {AgentId} (Cronjob '{Name}' Notification, OpenAI benötigt zwingend einen Key)", notifyCtx.AgentId, job.Name);
|
||||
return;
|
||||
}
|
||||
// sonst: nvidia/gemini/minimax/pollinations → notifyCtx.ApiToken bleibt leer (Server-Key-Auflösung).
|
||||
}
|
||||
else
|
||||
{
|
||||
notifyCtx.ApiToken = notifyApiKey.ApiKey;
|
||||
}
|
||||
|
||||
// Kurze Zusammenfassung als User-Nachricht in die Notify-Session schreiben
|
||||
// Cronjob-Ergebnis als Nachricht in die Notify-Session schreiben (für die Web-History).
|
||||
var summary = $"[Cronjob \"{job.Name}\" wurde in Session \"{job.SessionName}\" ausgeführt]\n\nAntwort:\n{Truncate(responseText, 2000)}";
|
||||
|
||||
// In Notify-Session als Nachricht speichern
|
||||
await _db.SaveMessage(new MessageRecord
|
||||
{
|
||||
ChainId = notifyCtx.ChainId,
|
||||
@@ -224,31 +190,92 @@ public class CronjobService : BackgroundService
|
||||
Content = summary
|
||||
});
|
||||
|
||||
// Nur die Benachrichtigung als History senden (nicht volle Session-History,
|
||||
// da diese mit einer assistant-Nachricht enden könnte → prefill-Fehler)
|
||||
var notifyHistory = new List<object>
|
||||
{
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
["role"] = "user",
|
||||
["content"] = new List<object> { new { type = "text", text = summary } }
|
||||
}
|
||||
};
|
||||
string notifyResponse;
|
||||
if (!string.IsNullOrEmpty(notifyCtx.Provider))
|
||||
notifyResponse = await _openAiService.ChatNonStreaming(notifyCtx, notifyHistory);
|
||||
else if (notifyUseCliFallback)
|
||||
notifyResponse = await _anthropicService.ChatNonStreamingViaCli(notifyCtx, notifyHistory);
|
||||
else
|
||||
notifyResponse = await _anthropicService.ChatNonStreaming(notifyCtx, notifyHistory);
|
||||
|
||||
await _db.UpdateSessionTimestamp(job.NotifySessionId);
|
||||
|
||||
// Telegram auf Notify-Session senden
|
||||
if (!string.IsNullOrEmpty(notifyResponse))
|
||||
// ── Nachricht 1 (Pflicht): das echte Cronjob-Ergebnis ──────────────────────────
|
||||
// Geht IMMER raus, unabhängig vom Notify-Agent / API-Key. Früher lief hier nur der
|
||||
// Notify-Agent auf der Zusammenfassung; quittierte er bloß mit "👍", erreichte der
|
||||
// eigentliche Inhalt Telegram nie. Das Ergebnis ist jetzt die garantierte Nachricht.
|
||||
if (!string.IsNullOrEmpty(responseText))
|
||||
{
|
||||
await _telegramService.SendNotification(job.NotifySessionId,
|
||||
$"📋 Cronjob: {job.Name}\n📂 Session: {job.SessionName}\n\n{notifyResponse}");
|
||||
$"📋 Cronjob: {job.Name}\n📂 Session: {job.SessionName}\n\n{responseText}");
|
||||
}
|
||||
|
||||
// ── Nachricht 2 (optional, best effort): die Reaktion des Notify-Agenten ────────
|
||||
// Der Notify-Agent reagiert auf das Ergebnis; seine Antwort geht als SEPARATE
|
||||
// Telegram-Nachricht raus und wird (über ChatNonStreaming*) automatisch in die
|
||||
// Web-History persistiert. Schlägt der Lauf fehl (kein Key / OpenAI ohne Key /
|
||||
// CLI nicht verfügbar), wird die Reaktion still übersprungen – Nachricht 1 ist
|
||||
// dann längst zugestellt, es geht also nie wieder Information verloren.
|
||||
try
|
||||
{
|
||||
// API-Key des Cronjob-Owners für den Notify-Agenten auflösen (wie ChatEndpoint):
|
||||
// - Anthropic (Provider leer) → Claude-CLI-Fallback (sofern berechtigt/verfügbar)
|
||||
// - "openai" → überspringen (kein Server-Key, kein CLI-Äquivalent)
|
||||
// - nvidia/gemini/minimax/pollinations → durchlassen: Server-Key via ResolveProviderConfig
|
||||
var notifyApiKey = await _db.GetAgentApiKeyRecord(job.UserId, notifyCtx.AgentId);
|
||||
bool notifyUseCliFallback = false;
|
||||
bool canRunNotifyAgent = true;
|
||||
|
||||
if (notifyApiKey == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(notifyCtx.Provider))
|
||||
{
|
||||
var notifyOwner = await _db.GetUser(job.UserId);
|
||||
if ((notifyOwner != null && !notifyOwner.CanUseCli && !notifyOwner.IsAdmin) || !_anthropicService.IsCliAvailable)
|
||||
{
|
||||
_logger.LogWarning("Notify-Agent-Reaktion für Cronjob '{Name}' übersprungen: kein API-Key und CLI nicht verfügbar/berechtigt", job.Name);
|
||||
canRunNotifyAgent = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
notifyUseCliFallback = true;
|
||||
}
|
||||
}
|
||||
else if (notifyCtx.Provider == "openai")
|
||||
{
|
||||
_logger.LogWarning("Notify-Agent-Reaktion für Cronjob '{Name}' übersprungen: OpenAI benötigt zwingend einen Key", job.Name);
|
||||
canRunNotifyAgent = false;
|
||||
}
|
||||
// sonst: nvidia/gemini/minimax/pollinations → notifyCtx.ApiToken bleibt leer (Server-Key-Auflösung).
|
||||
}
|
||||
else
|
||||
{
|
||||
notifyCtx.ApiToken = notifyApiKey.ApiKey;
|
||||
}
|
||||
|
||||
if (canRunNotifyAgent)
|
||||
{
|
||||
// Nur die Benachrichtigung als History senden (nicht volle Session-History,
|
||||
// da diese mit einer assistant-Nachricht enden könnte → prefill-Fehler)
|
||||
var notifyHistory = new List<object>
|
||||
{
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
["role"] = "user",
|
||||
["content"] = new List<object> { new { type = "text", text = summary } }
|
||||
}
|
||||
};
|
||||
|
||||
string notifyResponse;
|
||||
if (!string.IsNullOrEmpty(notifyCtx.Provider))
|
||||
notifyResponse = await _openAiService.ChatNonStreaming(notifyCtx, notifyHistory);
|
||||
else if (notifyUseCliFallback)
|
||||
notifyResponse = await _anthropicService.ChatNonStreamingViaCli(notifyCtx, notifyHistory);
|
||||
else
|
||||
notifyResponse = await _anthropicService.ChatNonStreaming(notifyCtx, notifyHistory);
|
||||
|
||||
if (!string.IsNullOrEmpty(notifyResponse))
|
||||
{
|
||||
await _telegramService.SendNotification(job.NotifySessionId, $"💬 {notifyResponse}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception reactEx)
|
||||
{
|
||||
// Reaktion ist rein optional – das Ergebnis (Nachricht 1) ist bereits zugestellt.
|
||||
_logger.LogWarning(reactEx, "Notify-Agent-Reaktion für Cronjob '{Name}' fehlgeschlagen (Ergebnis wurde dennoch gesendet)", job.Name);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -280,7 +280,10 @@ public class TelegramService
|
||||
if (bot == null || string.IsNullOrEmpty(bot.BotToken)) return;
|
||||
|
||||
var chatId = long.Parse(session.TelegramChatId);
|
||||
await SendMessage(chatId, bot.BotToken, text);
|
||||
// SendLongMessage statt SendMessage: lange Ergebnisse (z.B. Cronjob-Antworten) werden in
|
||||
// 4096-Zeichen-Chunks zerlegt. Sonst lehnt die Telegram-API zu lange Texte komplett ab
|
||||
// (400 → der User bekäme gar nichts).
|
||||
await SendLongMessage(chatId, bot.BotToken, text);
|
||||
}
|
||||
|
||||
// ── Telegram Bot API ──
|
||||
|
||||
Reference in new issue
Block a user