feat: send_to_session tool – agent-to-agent messaging
- Neues Tool send_to_session: Agent kann Nachrichten in andere Sessions schicken - Ziel-Session per ID oder Name (case-insensitive) auffindbar - User-Message wird nicht in DB gespeichert (wie Cronjob) – keine Bubble im Frontend - Nachricht wird als '[Nachricht von Agent "X"]' kontextualisiert injiziert - Sicherheitscheck: Ziel-Session muss demselben User gehören, keine eigene Session - Zirkuläre Abhängigkeit ChatService ↔ AnthropicService via SetChatService() gelöst - tool-ui.js: Display-Name für send_to_session
This commit is contained in:
1 parent
20d891c9ef
commit
c18b94cd4e
5 files changed
+99
-11
No files matched your search
@@ -24,6 +24,7 @@ public class AnthropicService
|
||||
private readonly bool _payloadLoggingGzip;
|
||||
private readonly VectorSearchService _vectorSearch;
|
||||
private readonly EmbeddingBackgroundService _embeddingBg;
|
||||
private ChatService _chatService;
|
||||
|
||||
public AnthropicService(IHttpClientFactory httpFactory, string token, ToolService toolService, DatabaseService db, MemoryService memoryService = null, bool payloadLogging = false, bool payloadLoggingGzip = false, VectorSearchService vectorSearch = null, EmbeddingBackgroundService embeddingBg = null)
|
||||
{
|
||||
@@ -38,6 +39,15 @@ public class AnthropicService
|
||||
_embeddingBg = embeddingBg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wird nach der Konstruktion gesetzt um zirkuläre Abhängigkeit zu vermeiden
|
||||
/// (ChatService → AnthropicService → ChatService).
|
||||
/// </summary>
|
||||
public void SetChatService(ChatService chatService)
|
||||
{
|
||||
_chatService = chatService;
|
||||
}
|
||||
|
||||
public async Task StreamChat(
|
||||
HttpResponse response,
|
||||
string modelId,
|
||||
@@ -47,6 +57,7 @@ public class AnthropicService
|
||||
string workspace,
|
||||
string sessionId = null,
|
||||
string agentId = null,
|
||||
string userId = null,
|
||||
bool useMemory = true,
|
||||
string webSearchVersion = null,
|
||||
int maxIterations = 100,
|
||||
@@ -183,7 +194,7 @@ public class AnthropicService
|
||||
return;
|
||||
}
|
||||
|
||||
var (stopReason, assistantContent, executedTools, streamErrorInfo) = await ProcessStream(response, httpResp, usage, workspace, agentId, workCt, sseCt, remoteMgr, sessionId);
|
||||
var (stopReason, assistantContent, executedTools, streamErrorInfo) = await ProcessStream(response, httpResp, usage, workspace, agentId, workCt, sseCt, remoteMgr, sessionId, userId);
|
||||
lastStopReason = stopReason;
|
||||
promptTrimRetries = 0; // Erfolgreicher API-Call → Retry-Counter resetten
|
||||
|
||||
@@ -1204,7 +1215,8 @@ public class AnthropicService
|
||||
CancellationToken workCt = default,
|
||||
CancellationToken sseCt = default,
|
||||
RemoteConnectionManager remoteMgr = null,
|
||||
string sessionId = null)
|
||||
string sessionId = null,
|
||||
string userId = null)
|
||||
{
|
||||
var stream = await httpResp.Content.ReadAsStreamAsync(workCt);
|
||||
// Bei Cancellation den Stream disposen, damit ReadLineAsync sofort abbricht.
|
||||
@@ -1386,7 +1398,7 @@ public class AnthropicService
|
||||
|
||||
string toolResult;
|
||||
bool isError = false;
|
||||
try { toolResult = await _toolService.ExecuteTool(currentToolName, inputEl, workspace, _memoryService, agentId, workCt, remoteMgr: remoteMgr, sessionId: sessionId, vectorSearch: _vectorSearch, embeddingBg: _embeddingBg); }
|
||||
try { toolResult = await _toolService.ExecuteTool(currentToolName, inputEl, workspace, _memoryService, agentId, workCt, remoteMgr: remoteMgr, sessionId: sessionId, vectorSearch: _vectorSearch, embeddingBg: _embeddingBg, db: _db, chatService: _chatService, anthropicService: this, userId: userId); }
|
||||
catch (OperationCanceledException) { throw; }
|
||||
catch (Exception ex) { toolResult = $"Fehler: {ex.Message}"; isError = true; }
|
||||
|
||||
@@ -1593,7 +1605,8 @@ public class AnthropicService
|
||||
var hasWorkspace = !string.IsNullOrEmpty(workspace);
|
||||
var includeMemory = useMemory && _memoryService != null && !string.IsNullOrEmpty(agentId);
|
||||
var includeMemorySearch = _vectorSearch != null && _vectorSearch.GetEmbeddingCount() > 0;
|
||||
var hasTools = hasWorkspace || includeMemory || includeRemote || includeMemorySearch;
|
||||
var includeSendToSession = _db != null && _chatService != null;
|
||||
var hasTools = hasWorkspace || includeMemory || includeRemote || includeMemorySearch || includeSendToSession;
|
||||
var hasWebSearch = !string.IsNullOrEmpty(webSearchVersion);
|
||||
|
||||
if (!hasTools && !hasWebSearch) return;
|
||||
@@ -1601,7 +1614,7 @@ public class AnthropicService
|
||||
var tools = new List<object>();
|
||||
if (hasTools)
|
||||
{
|
||||
var allTools = _toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory, includeUserChoice: allowUserChoice, includeRemote: includeRemote, includeMemorySearch: includeMemorySearch);
|
||||
var allTools = _toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory, includeUserChoice: allowUserChoice, includeRemote: includeRemote, includeMemorySearch: includeMemorySearch, includeSendToSession: includeSendToSession);
|
||||
if (planMode)
|
||||
allTools = _toolService.FilterReadOnlyTools(allTools);
|
||||
tools.AddRange(allTools);
|
||||
|
||||
Reference in new issue
Block a user