feat: Remote-Verbindungen – Windows-Workstations per WebSocket steuern
- RemoteConnectionManager: Singleton-Service verwaltet WebSocket-Verbindungen mit Command-Execution (Send/Receive mit Timeout + SemaphoreSlim-Locking) - RemoteEndpoint: WebSocket-Endpoint /api/remote (auth-frei), REST-APIs für Connections/Assign/Unassign, PowerShell-Script-Auslieferung mit dynamischer URL - remote.ps1: PowerShell-Client für Windows – verbindet per WebSocket, sendet Hostname/User/OS, empfängt und führt Befehle aus, Heartbeat - remote_execute Tool: Neues Agent-Tool, nur verfügbar wenn Session eine zugeordnete Remote-Verbindung hat, führt PowerShell-Befehle remote aus - Frontend: Menüpunkt 'Remote-Verbindungen' im Chat-Dropdown, Modal zeigt alle aktiven WebSocket-Verbindungen (Hostname, User, OS, Verbindungszeit), Verbinden/Trennen-Buttons pro Verbindung und Session - Auth: /api/remote und /remote.ps1 von Authentifizierung ausgenommen Architektur: Windows-Client → WebSocket → GOTT-Server → Agent-Tool Session-gebunden: Eine Verbindung wird einer Session zugeordnet
This commit is contained in:
1 parent
9f4746c2e7
commit
10da2bd964
14 files changed
+706
-18
No files matched your search
@@ -53,7 +53,8 @@ public class AnthropicService
|
||||
bool planMode = false,
|
||||
CancellationToken workCt = default,
|
||||
CancellationToken hardCt = default,
|
||||
CancellationToken sseCt = default)
|
||||
CancellationToken sseCt = default,
|
||||
RemoteConnectionManager remoteMgr = null)
|
||||
{
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
var usage = new TokenUsage();
|
||||
@@ -90,7 +91,8 @@ public class AnthropicService
|
||||
if (systemPrompt != null && systemPrompt.Count > 0)
|
||||
payload["system"] = systemPrompt;
|
||||
|
||||
AddToolsToPayload(payload, workspace, agentId, useMemory, webSearchVersion, toolChoice, iterations, allowUserChoice, planMode);
|
||||
var hasRemote = remoteMgr?.GetBySessionId(sessionId) != null;
|
||||
AddToolsToPayload(payload, workspace, agentId, useMemory, webSearchVersion, toolChoice, iterations, allowUserChoice, planMode, includeRemote: hasRemote);
|
||||
|
||||
var client = CreateClient();
|
||||
var json = JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true });
|
||||
@@ -136,7 +138,7 @@ public class AnthropicService
|
||||
return;
|
||||
}
|
||||
|
||||
var (stopReason, assistantContent, executedTools, streamErrorInfo) = await ProcessStream(response, httpResp, usage, workspace, agentId, workCt, sseCt);
|
||||
var (stopReason, assistantContent, executedTools, streamErrorInfo) = await ProcessStream(response, httpResp, usage, workspace, agentId, workCt, sseCt, remoteMgr, sessionId);
|
||||
lastStopReason = stopReason;
|
||||
promptTrimRetries = 0; // Erfolgreicher API-Call → Retry-Counter resetten
|
||||
|
||||
@@ -1153,7 +1155,9 @@ public class AnthropicService
|
||||
string workspace,
|
||||
string agentId = null,
|
||||
CancellationToken workCt = default,
|
||||
CancellationToken sseCt = default)
|
||||
CancellationToken sseCt = default,
|
||||
RemoteConnectionManager remoteMgr = null,
|
||||
string sessionId = null)
|
||||
{
|
||||
var stream = await httpResp.Content.ReadAsStreamAsync(workCt);
|
||||
// Bei Cancellation den Stream disposen, damit ReadLineAsync sofort abbricht.
|
||||
@@ -1335,7 +1339,7 @@ public class AnthropicService
|
||||
|
||||
string toolResult;
|
||||
bool isError = false;
|
||||
try { toolResult = await _toolService.ExecuteTool(currentToolName, inputEl, workspace, _memoryService, agentId, workCt); }
|
||||
try { toolResult = await _toolService.ExecuteTool(currentToolName, inputEl, workspace, _memoryService, agentId, workCt, remoteMgr: remoteMgr, sessionId: sessionId); }
|
||||
catch (OperationCanceledException) { throw; }
|
||||
catch (Exception ex) { toolResult = $"Fehler: {ex.Message}"; isError = true; }
|
||||
|
||||
@@ -1508,7 +1512,7 @@ public class AnthropicService
|
||||
/// <summary>
|
||||
/// Fügt Tool-Definitionen und WebSearch zum Payload hinzu.
|
||||
/// </summary>
|
||||
private void AddToolsToPayload(Dictionary<string, object> payload, string workspace, string agentId, bool useMemory, string webSearchVersion, string toolChoice, int iteration, bool allowUserChoice = false, bool planMode = false)
|
||||
private void AddToolsToPayload(Dictionary<string, object> payload, string workspace, string agentId, bool useMemory, string webSearchVersion, string toolChoice, int iteration, bool allowUserChoice = false, bool planMode = false, bool includeRemote = false)
|
||||
{
|
||||
var hasWorkspace = !string.IsNullOrEmpty(workspace);
|
||||
var includeMemory = useMemory && _memoryService != null && !string.IsNullOrEmpty(agentId);
|
||||
@@ -1520,7 +1524,7 @@ public class AnthropicService
|
||||
var tools = new List<object>();
|
||||
if (hasTools)
|
||||
{
|
||||
var allTools = _toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory, includeUserChoice: allowUserChoice);
|
||||
var allTools = _toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory, includeUserChoice: allowUserChoice, includeRemote: includeRemote);
|
||||
if (planMode)
|
||||
allTools = _toolService.FilterReadOnlyTools(allTools);
|
||||
tools.AddRange(allTools);
|
||||
|
||||
Reference in new issue
Block a user