refactor: Backend deduplizieren – 13 Dateien, -528 Zeilen netto

ChatContext: 3 identische Context-Klassen (PreparerContext, ReviewContext,
FinalizerContext) zu einer SubAgentContext-Klasse zusammengefasst.

ChatService: 3x40 Zeilen Sub-Agent-Setup durch BuildSubAgentContext() ersetzt.

AnthropicService: 5 Hilfsmethoden extrahiert – ExtractWebSearchSources(),
TruncateToolResult(), AddToolsToPayload(), ParseServerToolUse(), TrackUsage().

WorkspaceEndpoint: 5 Session/Agent-Endpoint-Paare durch generische Core-Handler
mit basePath-Parameter ersetzt. Ungenutzte rmdir-Endpoints entfernt.

AgentEndpoint: Doppeltes Agent-DTO-Mapping durch MapAgentList() ersetzt.

SessionEndpoint: Doppelte Session/Agent-Auflösung durch ResolvePromptContext() ersetzt.

DatabaseService: Toten Code entfernt (SetSessionTelegramChatId,
ClearSessionTelegramChatId, GetSessions, GetUserSessions). ConvertDataUrlToWebP
und ResizeDataUrlToWebP zu einer Methode zusammengefasst.

TelegramEndpoint: Bot-DTO-Mapping durch MapBotResponse() dedupliziert.

KreaEndpoint + SkillEndpoint: Thumbnail-Generierung in ImageService.GenerateThumbnail()
extrahiert, SixLabors-Imports aus Endpoints entfernt.

CronjobEndpoint: 7x ctx.Items[UserId] durch ctx.GetUserId() ersetzt.
This commit is contained in:
Meleki committed 2026-03-09 09:18:49 +01:00
1 parent 0097ce69db
commit dcedbaa074
13 files changed
+447 -975

No files matched your search

+55 -108
View File
@@ -114,29 +114,18 @@ public class ChatService
if (!string.IsNullOrWhiteSpace(systemPromptText))
systemPrompt.Add(new { type = "text", text = systemPromptText });
// Preparer-Agent vorbereiten (falls konfiguriert)
PreparerContext preparerContext = null;
if (!string.IsNullOrEmpty(session.PreparerAgentId))
// Sub-Agents vorbereiten (falls konfiguriert)
var preparerContext = await BuildSubAgentContext(
session.PreparerAgentId, sessionId, workspace, session, user);
var reviewContext = await BuildSubAgentContext(
session.ReviewAgentId, sessionId, workspace, session, user);
var finalizerContext = await BuildSubAgentContext(
session.FinalizerAgentId, sessionId, workspace, session, user);
if (preparerContext != null)
{
var preparerAgent = await _db.GetAgent(session.PreparerAgentId);
if (preparerAgent != null)
{
var preparerModelId = ResolveModelId(preparerAgent.Model);
var preparerMarked = await _db.GetMarkedMessages(sessionId);
var preparerMemDir = _memoryService.GetAgentMemoryDir(preparerAgent.AgentId);
var preparerSkills = await _db.GetAgentSkills(preparerAgent.AgentId);
var preparerWorkspace = workspace;
var preparerSystemText = SystemPromptBuilder.Build(
preparerAgent, session, preparerMarked, _memoryService, preparerMemDir,
preparerSkills, _skillService, userPersona: user?.GetEffectivePersona(),
resolvedWorkspace: preparerWorkspace);
var preparerPrompt = new List<object>();
if (!string.IsNullOrWhiteSpace(preparerSystemText))
preparerPrompt.Add(new { type = "text", text = preparerSystemText });
// Preparer-Instruktion: erklärt Vorbereiter-Mechanismus
preparerPrompt.Add(new { type = "text", text = @"## KRITISCH: Deine Rolle als Vorbereiter-Agent
preparerContext.AllowUserChoice = preparerContext.Agent?.AllowUserChoice ?? false;
preparerContext.SystemPrompt.Add(new { type = "text", text = @"## KRITISCH: Deine Rolle als Vorbereiter-Agent
Du bist ein Vorbereiter-Agent. Deine Aufgabe: Die Anfrage des Users aufbereiten, deine Fähigkeiten nutzen, und das Ergebnis an den Session-Agent weiterleiten.
@@ -165,95 +154,11 @@ Rückfrage (NUR mit [QUESTION] – stoppt die Weiterleitung):
[QUESTION]
Für welche Plattform soll die App entwickelt werden? Web, Mobile oder Desktop?
```" });
var preparerHasTools = !string.IsNullOrEmpty(preparerWorkspace) || preparerAgent.UseMemory;
preparerContext = new PreparerContext
{
ModelId = preparerModelId,
SystemPrompt = preparerPrompt,
AgentId = preparerAgent.AgentId,
Workspace = preparerWorkspace,
UseMemory = preparerAgent.UseMemory,
WebSearchVersion = preparerAgent.WebSearchVersion,
ToolChoice = preparerHasTools ? "any" : "auto",
AllowUserChoice = preparerAgent.AllowUserChoice,
Agent = preparerAgent
};
}
}
// Review-Agent vorbereiten (falls konfiguriert)
ReviewContext reviewContext = null;
if (!string.IsNullOrEmpty(session.ReviewAgentId))
{
var reviewAgent = await _db.GetAgent(session.ReviewAgentId);
if (reviewAgent != null)
{
var reviewModelId = ResolveModelId(reviewAgent.Model);
var reviewMarked = await _db.GetMarkedMessages(sessionId);
var reviewMemDir = _memoryService.GetAgentMemoryDir(reviewAgent.AgentId);
var reviewSkills = await _db.GetAgentSkills(reviewAgent.AgentId);
var reviewWorkspace = workspace; // gleicher Workspace wie Worker
var reviewSystemText = SystemPromptBuilder.Build(
reviewAgent, session, reviewMarked, _memoryService, reviewMemDir,
reviewSkills, _skillService, userPersona: user?.GetEffectivePersona(),
resolvedWorkspace: reviewWorkspace);
if (reviewContext != null)
reviewContext.MaxReviewIterations = session.MaxReviewIterations > 0 ? session.MaxReviewIterations : 3;
var reviewPrompt = new List<object>();
if (!string.IsNullOrWhiteSpace(reviewSystemText))
reviewPrompt.Add(new { type = "text", text = reviewSystemText });
var reviewHasTools = !string.IsNullOrEmpty(reviewWorkspace) || reviewAgent.UseMemory;
reviewContext = new ReviewContext
{
ModelId = reviewModelId,
SystemPrompt = reviewPrompt,
AgentId = reviewAgent.AgentId,
Workspace = reviewWorkspace,
UseMemory = reviewAgent.UseMemory,
WebSearchVersion = reviewAgent.WebSearchVersion,
ToolChoice = reviewHasTools ? "any" : "auto",
MaxReviewIterations = session.MaxReviewIterations > 0 ? session.MaxReviewIterations : 3,
Agent = reviewAgent
};
}
}
// Finalizer-Agent vorbereiten (falls konfiguriert)
FinalizerContext finalizerContext = null;
if (!string.IsNullOrEmpty(session.FinalizerAgentId))
{
var finalizerAgent = await _db.GetAgent(session.FinalizerAgentId);
if (finalizerAgent != null)
{
var finalizerModelId = ResolveModelId(finalizerAgent.Model);
var finalizerMarked = await _db.GetMarkedMessages(sessionId);
var finalizerMemDir = _memoryService.GetAgentMemoryDir(finalizerAgent.AgentId);
var finalizerSkills = await _db.GetAgentSkills(finalizerAgent.AgentId);
var finalizerWorkspace = workspace;
var finalizerSystemText = SystemPromptBuilder.Build(
finalizerAgent, session, finalizerMarked, _memoryService, finalizerMemDir,
finalizerSkills, _skillService, userPersona: user?.GetEffectivePersona(),
resolvedWorkspace: finalizerWorkspace);
var finalizerPrompt = new List<object>();
if (!string.IsNullOrWhiteSpace(finalizerSystemText))
finalizerPrompt.Add(new { type = "text", text = finalizerSystemText });
var finalizerHasTools = !string.IsNullOrEmpty(finalizerWorkspace) || finalizerAgent.UseMemory;
finalizerContext = new FinalizerContext
{
ModelId = finalizerModelId,
SystemPrompt = finalizerPrompt,
AgentId = finalizerAgent.AgentId,
Workspace = finalizerWorkspace,
UseMemory = finalizerAgent.UseMemory,
WebSearchVersion = finalizerAgent.WebSearchVersion,
ToolChoice = finalizerHasTools ? "any" : "auto",
Agent = finalizerAgent
};
}
}
return new ChatContext
{
@@ -531,4 +436,46 @@ Für welche Plattform soll die App entwickelt werden? Web, Mobile oder Desktop?
return history;
}
/// <summary>
/// Baut einen SubAgentContext für Preparer/Review/Finalizer.
/// Gemeinsame Logik: Agent laden, Model auflösen, SystemPrompt bauen, ToolChoice bestimmen.
/// </summary>
private async Task<SubAgentContext> BuildSubAgentContext(
string agentId, string sessionId, string workspace, SessionRecord session, UserRecord user)
{
if (string.IsNullOrEmpty(agentId))
return null;
var agent = await _db.GetAgent(agentId);
if (agent == null)
return null;
var modelId = ResolveModelId(agent.Model);
var markedMessages = await _db.GetMarkedMessages(sessionId);
var memDir = _memoryService.GetAgentMemoryDir(agent.AgentId);
var skills = await _db.GetAgentSkills(agent.AgentId);
var systemText = SystemPromptBuilder.Build(
agent, session, markedMessages, _memoryService, memDir,
skills, _skillService, userPersona: user?.GetEffectivePersona(),
resolvedWorkspace: workspace);
var prompt = new List<object>();
if (!string.IsNullOrWhiteSpace(systemText))
prompt.Add(new { type = "text", text = systemText });
var hasTools = !string.IsNullOrEmpty(workspace) || agent.UseMemory;
return new SubAgentContext
{
ModelId = modelId,
SystemPrompt = prompt,
AgentId = agent.AgentId,
Workspace = workspace,
UseMemory = agent.UseMemory,
WebSearchVersion = agent.WebSearchVersion,
ToolChoice = hasTools ? "any" : "auto",
Agent = agent
};
}
}