Provider-Abstraktion: Agents unterstützen jetzt OpenAI + Anthropic
Backend: - ChatEndpoint: Globaler OpenAI-Fallback entfernt, Key-Check pro Provider - TelegramService/CronjobService: Provider-Weiche statt hardcoded Anthropic - AnthropicService: Preparer/Review/Finalizer sind Provider-aware - OpenAiService: Neue ChatNonStreaming()-Methode für agentic loop - ToolService: send_to_session lädt Key des Ziel-Agents - SubAgentContext: Provider-Feld hinzugefügt - ChatService: BuildSubAgentContext setzt Provider Frontend: - Key-Switch-Modal: 'Kein Key'-Option zum Entfernen der Zuweisung - ApiKeysEndpoint: keyId='none' löscht Key-Zuweisung
This commit is contained in:
1 parent
1effc6d00f
commit
02f5fe2faf
11 files changed
+422
-69
No files matched your search
+29
-28
@@ -62,14 +62,8 @@ public static class ChatEndpoint
|
||||
return;
|
||||
}
|
||||
|
||||
// API-Key des Users für diesen Agent auflösen
|
||||
// API-Key des Users für diesen Agent auflösen (kann null sein)
|
||||
var userApiKey = await db.GetAgentApiKeyRecord(userId, ctx.AgentId);
|
||||
if (userApiKey == null)
|
||||
{
|
||||
res.StatusCode = 400;
|
||||
await res.WriteAsJsonAsync(new { error = "Kein API-Key für diesen Agent zugewiesen. Bitte weise einen Key zu." });
|
||||
return;
|
||||
}
|
||||
|
||||
if (isChoiceResponse)
|
||||
{
|
||||
@@ -146,12 +140,21 @@ public static class ChatEndpoint
|
||||
// ── Preparer-Agent Phase (vor dem Worker) ──
|
||||
if (ctx.Preparer != null && !isChoiceResponse)
|
||||
{
|
||||
var preparerApiToken = userApiKey?.ApiKey;
|
||||
// Anthropic-Preparer braucht zwingend einen Key, OpenAI-Provider können ohne auskommen
|
||||
if (string.IsNullOrEmpty(ctx.Preparer.Provider) && string.IsNullOrEmpty(preparerApiToken))
|
||||
{
|
||||
res.StatusCode = 400;
|
||||
await res.WriteAsJsonAsync(new { error = "Kein API-Key für diesen Agent zugewiesen. Bitte weise einen Key zu." });
|
||||
return;
|
||||
}
|
||||
|
||||
// Preparer bekommt History MIT seinen eigenen vorherigen Messages (Tag "preparer"),
|
||||
// damit er den Kontext seiner Rückfragen kennt
|
||||
var preparerHistory = await chatService.BuildHistoryFromDb(sessionId, includeTag: "preparer", promptBlocks: ctx.PromptBlocks);
|
||||
|
||||
var preparerResult = await anthropic.RunPreparer(
|
||||
res, ctx.Preparer, preparerHistory, ctx.ChainId, ctx.Workspace, sessionId, userApiKey.ApiKey, cancellationToken);
|
||||
res, ctx.Preparer, preparerHistory, ctx.ChainId, ctx.Workspace, sessionId, preparerApiToken, cancellationToken);
|
||||
|
||||
if (!preparerResult.ShouldForward)
|
||||
{
|
||||
@@ -219,33 +222,31 @@ public static class ChatEndpoint
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ctx.Provider))
|
||||
{
|
||||
// OpenAI-kompatibler Provider – für "openai" den User-Key aus DB verwenden
|
||||
string openAiKeyOverride = null;
|
||||
if (ctx.Provider == "openai")
|
||||
{
|
||||
// Zuerst prüfen ob der ausgewählte Key ein OpenAI-Key ist
|
||||
if (userApiKey.Provider == "openai")
|
||||
openAiKeyOverride = userApiKey.ApiKey;
|
||||
else
|
||||
{
|
||||
// Fallback: ersten aktiven OpenAI-Key aus DB holen
|
||||
openAiKeyOverride = await db.GetFirstActiveKeyByProvider("openai");
|
||||
}
|
||||
// OpenAI-kompatibler Provider – Key des Users für diesen Agent verwenden
|
||||
string openAiKeyOverride = userApiKey?.ApiKey;
|
||||
|
||||
if (string.IsNullOrEmpty(openAiKeyOverride))
|
||||
{
|
||||
await SseHelper.TryWriteSse(res, "error", new { error = "Kein OpenAI API-Key vorhanden. Bitte einen OpenAI-Key in den API-Keys hinzufügen." }, sseCt);
|
||||
await SseHelper.TryWriteSse(res, "done", new { chainId = ctx.ChainId }, sseCt);
|
||||
return;
|
||||
}
|
||||
// OpenAI-Provider braucht zwingend einen Key
|
||||
if (ctx.Provider == "openai" && string.IsNullOrEmpty(openAiKeyOverride))
|
||||
{
|
||||
await SseHelper.TryWriteSse(res, "error", new { error = "Kein API-Key für diesen Agent zugewiesen. Bitte einen OpenAI-Key zuweisen." }, sseCt);
|
||||
await SseHelper.TryWriteSse(res, "done", new { chainId = ctx.ChainId }, sseCt);
|
||||
return;
|
||||
}
|
||||
|
||||
await openAi.StreamChat(res, ctx.ModelId, ctx.SystemPromptText, messages, ctx.ChainId, workspace: ctx.Workspace, sessionId: sessionId, agentId: ctx.AgentId, apiKeyOverride: openAiKeyOverride, workCt: workCt, sseCt: sseCt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Standard: Anthropic
|
||||
await anthropic.StreamChat(res, ctx.ModelId, ctx.SystemPrompt, messages, ctx.ChainId, ctx.Workspace, apiToken: userApiKey.ApiKey, sessionId: sessionId, agentId: ctx.AgentId, userId: userId, useMemory: ctx.UseMemory, webSearchVersion: ctx.WebSearchVersion, maxIterations: ctx.MaxIterations, toolChoice: effectiveToolChoice, review: ctx.Review, finalizer: ctx.Finalizer, allowUserChoice: ctx.Agent?.AllowUserChoice ?? true, planMode: ctx.PlanMode, useAutoContext: ctx.Agent?.UseAutoContext ?? true, useGitHubSearch: ctx.Agent?.UseGitHubSearch ?? false, useSerperSearch: ctx.Agent?.UseSerperSearch ?? false, workCt: workCt, hardCt: hardCt, sseCt: sseCt, remoteMgr: remoteMgr);
|
||||
// Standard: Anthropic – Key wird zwingend benötigt
|
||||
var anthropicToken = userApiKey?.ApiKey;
|
||||
if (string.IsNullOrEmpty(anthropicToken))
|
||||
{
|
||||
await SseHelper.TryWriteSse(res, "error", new { error = "Kein API-Key für diesen Agent zugewiesen. Bitte weise einen Key zu." }, sseCt);
|
||||
await SseHelper.TryWriteSse(res, "done", new { chainId = ctx.ChainId }, sseCt);
|
||||
return;
|
||||
}
|
||||
|
||||
await anthropic.StreamChat(res, ctx.ModelId, ctx.SystemPrompt, messages, ctx.ChainId, ctx.Workspace, apiToken: anthropicToken, sessionId: sessionId, agentId: ctx.AgentId, userId: userId, useMemory: ctx.UseMemory, webSearchVersion: ctx.WebSearchVersion, maxIterations: ctx.MaxIterations, toolChoice: effectiveToolChoice, review: ctx.Review, finalizer: ctx.Finalizer, allowUserChoice: ctx.Agent?.AllowUserChoice ?? true, planMode: ctx.PlanMode, useAutoContext: ctx.Agent?.UseAutoContext ?? true, useGitHubSearch: ctx.Agent?.UseGitHubSearch ?? false, useSerperSearch: ctx.Agent?.UseSerperSearch ?? false, workCt: workCt, hardCt: hardCt, sseCt: sseCt, remoteMgr: remoteMgr);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
||||
Reference in new issue
Block a user