diff --git a/Endpoints/AgentEndpoint.cs b/Endpoints/AgentEndpoint.cs index fb572b1..1bd1f06 100644 --- a/Endpoints/AgentEndpoint.cs +++ b/Endpoints/AgentEndpoint.cs @@ -65,6 +65,7 @@ public static class AgentEndpoint UseMemory = !body.TryGetProperty("useMemory", out var um) || um.GetBoolean(), UseWebSearch = body.TryGetProperty("webSearchVersion", out var wsv) && !string.IsNullOrEmpty(wsv.GetString()), WebSearchVersion = body.TryGetProperty("webSearchVersion", out var wsv2) ? wsv2.GetString() ?? "" : "", + AllowUserChoice = !body.TryGetProperty("allowUserChoice", out var auc) || auc.GetBoolean(), AvatarScale = body.TryGetProperty("avatarScale", out var asc) ? asc.GetDouble() : 1.0, AvatarOffsetX = body.TryGetProperty("avatarOffsetX", out var aox) ? aox.GetDouble() : 0, AvatarOffsetY = body.TryGetProperty("avatarOffsetY", out var aoy) ? aoy.GetDouble() : 0 @@ -103,6 +104,7 @@ public static class AgentEndpoint agent.WebSearchVersion = wsv.GetString() ?? ""; agent.UseWebSearch = !string.IsNullOrEmpty(agent.WebSearchVersion); } + if (body.TryGetProperty("allowUserChoice", out var auc)) agent.AllowUserChoice = auc.GetBoolean(); if (body.TryGetProperty("avatarScale", out var asc)) agent.AvatarScale = asc.GetDouble(); if (body.TryGetProperty("avatarOffsetX", out var aox)) agent.AvatarOffsetX = aox.GetDouble(); if (body.TryGetProperty("avatarOffsetY", out var aoy)) agent.AvatarOffsetY = aoy.GetDouble(); diff --git a/Endpoints/ChatEndpoint.cs b/Endpoints/ChatEndpoint.cs index 6fcefc1..35543d3 100644 --- a/Endpoints/ChatEndpoint.cs +++ b/Endpoints/ChatEndpoint.cs @@ -132,7 +132,7 @@ public static class ChatEndpoint try { - await anthropic.StreamChat(res, ctx.ModelId, ctx.SystemPrompt, messages, ctx.ChainId, ctx.Workspace, sessionId, agentId: ctx.AgentId, useMemory: ctx.UseMemory, webSearchVersion: ctx.WebSearchVersion, maxIterations: ctx.MaxIterations, toolChoice: effectiveToolChoice, review: ctx.Review, finalizer: ctx.Finalizer, cancellationToken: linkedCts.Token); + await anthropic.StreamChat(res, ctx.ModelId, ctx.SystemPrompt, messages, ctx.ChainId, ctx.Workspace, sessionId, agentId: ctx.AgentId, useMemory: ctx.UseMemory, webSearchVersion: ctx.WebSearchVersion, maxIterations: ctx.MaxIterations, toolChoice: effectiveToolChoice, review: ctx.Review, finalizer: ctx.Finalizer, allowUserChoice: ctx.Agent?.AllowUserChoice ?? true, cancellationToken: linkedCts.Token); } finally { diff --git a/Models/AgentRecord.cs b/Models/AgentRecord.cs index cfa8e5d..cea8231 100644 --- a/Models/AgentRecord.cs +++ b/Models/AgentRecord.cs @@ -17,6 +17,7 @@ public class AgentRecord public bool UseMemory { get; set; } = true; public bool UseWebSearch { get; set; } public string WebSearchVersion { get; set; } = ""; + public bool AllowUserChoice { get; set; } = true; public double AvatarScale { get; set; } = 1.0; public double AvatarOffsetX { get; set; } public double AvatarOffsetY { get; set; } diff --git a/Services/AnthropicService.cs b/Services/AnthropicService.cs index 51beea6..22dffe4 100644 --- a/Services/AnthropicService.cs +++ b/Services/AnthropicService.cs @@ -49,6 +49,7 @@ public class AnthropicService string toolChoice = "any", ReviewContext review = null, FinalizerContext finalizer = null, + bool allowUserChoice = true, CancellationToken cancellationToken = default) { var sw = System.Diagnostics.Stopwatch.StartNew(); @@ -92,7 +93,7 @@ public class AnthropicService { var tools = new List(); if (hasTools) - tools.AddRange(_toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory)); + tools.AddRange(_toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory, includeUserChoice: allowUserChoice)); if (hasWebSearch) tools.Add(new { type = webSearchVersion, name = "web_search", max_uses = 5 }); payload["tools"] = tools; @@ -543,7 +544,7 @@ public class AnthropicService { var tools = new List(); if (hasTools) - tools.AddRange(_toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory)); + tools.AddRange(_toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory, includeUserChoice: false)); if (hasWebSearch) tools.Add(new { type = webSearchVersion, name = "web_search", max_uses = 5 }); payload["tools"] = tools; @@ -768,7 +769,7 @@ public class AnthropicService { var tools = new List(); if (hasTools) - tools.AddRange(_toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory)); + tools.AddRange(_toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory, includeUserChoice: false)); if (hasWebSearch) tools.Add(new { type = ctx.WebSearchVersion, name = "web_search", max_uses = 5 }); payload["tools"] = tools; diff --git a/Services/ChatService.cs b/Services/ChatService.cs index f4b7550..6cf44a1 100644 --- a/Services/ChatService.cs +++ b/Services/ChatService.cs @@ -73,7 +73,7 @@ public class ChatService var includeMemory = agent.UseMemory && !string.IsNullOrEmpty(agent.AgentId); var toolDefs = (hasWorkspace || includeMemory) - ? _toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory) + ? _toolService.GetToolDefinitions(includeFileTools: hasWorkspace, includeMemory: includeMemory, includeUserChoice: agent.AllowUserChoice) : Array.Empty(); var toolNames = toolDefs.Length > 0 ? JsonSerializer.Serialize(toolDefs.Select(td => diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs index 8290ebc..890f628 100644 --- a/Services/DatabaseService.cs +++ b/Services/DatabaseService.cs @@ -178,6 +178,7 @@ public class DatabaseService TryAddColumn(conn, "agents", "avatar_offset_x", "REAL NOT NULL DEFAULT 0"); TryAddColumn(conn, "agents", "avatar_offset_y", "REAL NOT NULL DEFAULT 0"); TryAddColumn(conn, "sessions", "finalizer_agent_id", "TEXT"); + TryAddColumn(conn, "agents", "allow_user_choice", "INTEGER NOT NULL DEFAULT 1"); conn.Execute(@" CREATE TABLE IF NOT EXISTS agent_skills ( @@ -330,8 +331,8 @@ public class DatabaseService agent.CreatedAt = now; agent.UpdatedAt = now; await conn.ExecuteAsync(@" - INSERT INTO agents (agent_id, user_id, name, avatar, description, model, tool_choice, custom_commands, auto_commit, use_soul, use_identity, use_user_info, use_memory, use_web_search, web_search_version, avatar_scale, avatar_offset_x, avatar_offset_y, is_deleted, created_at, updated_at) - VALUES (@AgentId, @UserId, @Name, @Avatar, @Description, @Model, @ToolChoice, @CustomCommands, @AutoCommit, @UseSoul, @UseIdentity, @UseUserInfo, @UseMemory, @UseWebSearch, @WebSearchVersion, @AvatarScale, @AvatarOffsetX, @AvatarOffsetY, 0, @CreatedAt, @UpdatedAt) + INSERT INTO agents (agent_id, user_id, name, avatar, description, model, tool_choice, custom_commands, auto_commit, use_soul, use_identity, use_user_info, use_memory, use_web_search, web_search_version, allow_user_choice, avatar_scale, avatar_offset_x, avatar_offset_y, is_deleted, created_at, updated_at) + VALUES (@AgentId, @UserId, @Name, @Avatar, @Description, @Model, @ToolChoice, @CustomCommands, @AutoCommit, @UseSoul, @UseIdentity, @UseUserInfo, @UseMemory, @UseWebSearch, @WebSearchVersion, @AllowUserChoice, @AvatarScale, @AvatarOffsetX, @AvatarOffsetY, 0, @CreatedAt, @UpdatedAt) ", agent); return agent; } @@ -359,6 +360,7 @@ public class DatabaseService model = @Model, tool_choice = @ToolChoice, custom_commands = @CustomCommands, auto_commit = @AutoCommit, use_soul = @UseSoul, use_identity = @UseIdentity, use_user_info = @UseUserInfo, use_memory = @UseMemory, use_web_search = @UseWebSearch, web_search_version = @WebSearchVersion, + allow_user_choice = @AllowUserChoice, avatar_scale = @AvatarScale, avatar_offset_x = @AvatarOffsetX, avatar_offset_y = @AvatarOffsetY, updated_at = @UpdatedAt WHERE agent_id = @AgentId AND user_id = @UserId ", agent); diff --git a/Services/ToolService.cs b/Services/ToolService.cs index 4aa2571..e138d53 100644 --- a/Services/ToolService.cs +++ b/Services/ToolService.cs @@ -17,11 +17,11 @@ public class ToolService { public const string AskUserChoiceToolName = "ask_user_choice"; - public object[] GetToolDefinitions(bool includeFileTools = false, bool includeMemory = false) + public object[] GetToolDefinitions(bool includeFileTools = false, bool includeMemory = false, bool includeUserChoice = true) { var allTools = new List(); - // ask_user_choice ist immer verfügbar wenn Tools aktiv sind - allTools.Add(GetAskUserChoiceTool()); + if (includeUserChoice) + allTools.Add(GetAskUserChoiceTool()); if (includeFileTools) allTools.AddRange(GetFileTools()); if (includeMemory) diff --git a/wwwroot/css/chat.css b/wwwroot/css/chat.css index 71303ab..5269afa 100644 --- a/wwwroot/css/chat.css +++ b/wwwroot/css/chat.css @@ -1145,15 +1145,6 @@ max-width: 80%; display: flex; flex-direction: column; - gap: var(--box-spacing); -} - -.choice-question { - font-size: 0.95em; -} - -.choice-question p { - margin: 0; } .choice-buttons { @@ -1163,24 +1154,15 @@ } .choice-btn { - padding: 0.45em 1em; border: var(--border-width) solid var(--primary); border-radius: var(--border-radius); background: transparent; color: var(--primary); - font-size: 0.9em; - cursor: pointer; - transition: all 0.15s ease; - font-family: inherit; } .choice-btn:hover:not(:disabled) { background: var(--primary); - color: var(--primary-text); -} - -.choice-btn:active:not(:disabled) { - transform: scale(0.97); + color: var(--f1-bg); } .choice-btn:disabled { @@ -1189,17 +1171,12 @@ .choice-btn.choice-selected { background: var(--primary); - color: var(--primary-text); + color: var(--f1-bg); border-color: var(--primary); - font-weight: 600; } .choice-btn.choice-unselected { - opacity: 0.4; + opacity: var(--semi-transparent); border-color: var(--f1-border); color: var(--muted); } - -.choice-answered .choice-question { - opacity: 0.7; -} diff --git a/wwwroot/index.html b/wwwroot/index.html index e3d137a..8753801 100644 --- a/wwwroot/index.html +++ b/wwwroot/index.html @@ -193,6 +193,10 @@ Tool-Nutzung erzwingen (tool_choice: any) +