feat(telegram): CLI-Fallback bei fehlendem API-Key (analog Web-UI)

Wenn ein Telegram-Bot eine Nachricht empfängt und für den Agent kein
API-Key zugewiesen ist, fiel der Bot bisher hart aus ("Kein API-Key
für diesen Agent zugewiesen"). Im Web-UI wird in dem Fall bereits auf
Claude-CLI zurückgefallen – das macht der Telegram-Pfad jetzt analog.

- AnthropicService.Cli: Neue Methode ChatNonStreamingViaCli(...) für
  Non-SSE-Caller (Telegram). Macht dasselbe wie StreamChatViaCli aber
  ohne SSE: System-Prompt + Auto-Context, History-Kontext-Block, letzte
  User-Message (inkl. Image/PDF-Refs), Text + tool_use + tool_result in
  DB persistieren, finalen Text zurückgeben + FinalizeChain mit echten
  Token-Counts vom CLI-Result.
- TelegramService: Bei userApiKey == null jetzt CanUseCli, IsAdmin und
  IsCliAvailable prüfen. Bei OpenAI-Providern bleibt der Hard-Fail
  (kein CLI-Äquivalent). Spezifische Fehlermeldungen pro Szenario.
  Zusätzlich Schutz gegen leere Antwort.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MelekiandClaude Opus 4.7 committed 2026-05-31 20:44:36 +02:00
1 parent 205dbab6a0
commit 271902f32d
2 files changed
+208 -3

No files matched your search

+38 -3
View File
@@ -173,12 +173,37 @@ public class TelegramService
// API-Key des Bot-Owners für diesen Agent auflösen
var userApiKey = await _db.GetAgentApiKeyRecord(botUserId, ctx.AgentId);
bool useCliFallback = false;
if (userApiKey == null)
{
await SendMessage(chatId, botToken, "❌ Kein API-Key für diesen Agent zugewiesen. Der Bot-Besitzer muss im Web-UI einen Key zuweisen.");
return;
// Kein Key → CLI-Fallback prüfen (analog ChatEndpoint).
// Nur für Anthropic-Agents möglich (CLI = Claude). OpenAI-Provider haben kein CLI-Äquivalent.
if (!string.IsNullOrEmpty(ctx.Provider))
{
await SendMessage(chatId, botToken, "❌ Kein API-Key für diesen Agent zugewiesen. Für OpenAI-kompatible Provider ist kein CLI-Fallback möglich – der Bot-Besitzer muss im Web-UI einen Key zuweisen.");
return;
}
var botOwner = await _db.GetUser(botUserId);
if (botOwner != null && !botOwner.CanUseCli && !botOwner.IsAdmin)
{
await SendMessage(chatId, botToken, "❌ Kein API-Key für diesen Agent zugewiesen und der Bot-Besitzer hat keine CLI-Berechtigung.");
return;
}
if (!_anthropic.IsCliAvailable)
{
await SendMessage(chatId, botToken, "❌ Kein API-Key für diesen Agent zugewiesen und Claude CLI nicht verfügbar. Der Bot-Besitzer muss im Web-UI einen Key zuweisen oder `claude login` auf dem Server ausführen.");
return;
}
useCliFallback = true;
}
else
{
ctx.ApiToken = userApiKey.ApiKey;
}
ctx.ApiToken = userApiKey.ApiKey;
await SendChatAction(chatId, botToken, "typing");
@@ -211,6 +236,13 @@ public class TelegramService
await SendChatAction(chatId, botToken, "typing");
});
}
else if (useCliFallback)
{
reply = await _anthropic.ChatNonStreamingViaCli(ctx, history, onIteration: async (iteration) =>
{
await SendChatAction(chatId, botToken, "typing");
});
}
else
{
reply = await _anthropic.ChatNonStreaming(ctx, history, onIteration: async (iteration) =>
@@ -220,6 +252,9 @@ public class TelegramService
});
}
if (string.IsNullOrEmpty(reply))
reply = "⚠️ Keine Antwort vom Modell erhalten.";
await SendLongMessage(chatId, botToken, reply);
}
catch (Exception ex)