From 3f913f14b5135329290351230bc2dbbf12556be1 Mon Sep 17 00:00:00 2001 From: Meleki Date: Sun, 31 May 2026 21:33:32 +0200 Subject: [PATCH] Add per-agent reasoning effort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Opus 4.5+ and Sonnet 4.6+ support a new "effort" knob that controls how much budget the model spends on thinking and tool calls. Plumb it through end to end so each agent can pick its own level. Storage & shape: - New TEXT column agents.effort (default '') added via TryAddColumn. - AgentRecord.Effort + INSERT/UPDATE in DatabaseService.Agents.cs. - ChatContext.Effort + SubAgentContext.Effort so the value travels with the request alongside model and tool settings. Agent editor: - Effort dropdown above git-commit behavior in the agent form (low/medium/ high/xhigh/max plus empty = "use default"). Always visible; on OpenAI providers the value is sent but silently ignored. - agent-page.js load/save and AgentEndpoint create/update wired up. Anthropic API path: - StreamChat and RunNonStreamingToolLoop add output_config: { effort } when effort is set and not "high" – empty/null/"high" means "omit and let the API pick its default". - Sub-agents (preparer/review/finalizer) get the parameter through RunAgentChat so each step uses its own agent's effort. Anthropic CLI path: - ClaudeCliService.ChatStreamingAsync takes an effort parameter and exports CLAUDE_CODE_EFFORT_LEVEL on the spawned process. Env-var beats the --effort flag because it also covers "max" and "ultracode". - StreamChatViaCli, ChatNonStreamingViaCli, RunSubAgentViaCli, and the ChatEndpoint anthropic branches all hand the value through. ARCHITECTURE.md / ARCHITECTURE_QUICK.md updated with the new field. Co-Authored-By: Claude Opus 4.7 (1M context) --- ARCHITECTURE.md | 1 + ARCHITECTURE_QUICK.md | 2 +- Endpoints/AgentEndpoint.cs | 3 +++ Endpoints/ChatEndpoint.cs | 4 ++-- Models/AgentRecord.cs | 7 +++++++ Models/ChatContext.cs | 2 ++ Services/AnthropicService.Agents.cs | 23 ++++++++++++++++------- Services/AnthropicService.Cli.cs | 3 +++ Services/AnthropicService.Streaming.cs | 6 ++++++ Services/ChatService.cs | 2 ++ Services/ClaudeCliService.cs | 15 +++++++++++---- Services/DatabaseService.Agents.cs | 6 +++--- Services/DatabaseService.cs | 1 + wwwroot/index.html | 9 +++++++++ wwwroot/js/pages/agent-page.js | 3 +++ 15 files changed, 70 insertions(+), 17 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e19a547..8a1b61e 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -854,6 +854,7 @@ Ein **Agent** definiert die Persönlichkeit und Fähigkeiten der AI: | `WebSearchVersion`| Web-Suche aktivieren (z.B. `web_search_20260209`) | | `AllowUserChoice` | `ask_user_choice`-Tool verfügbar (Default: true) | | `TaskInstruction` | Aufgabe/Anweisung – optionaler Text, wird als `## Anweisungen`-Block in System-Prompt eingefügt | +| `Effort` | Reasoning-Effort-Level für Claude. `""` (=high, Default), `low`, `medium`, `high`, `xhigh` (nur Opus 4.7+), `max` (nur Opus 4.6+/Sonnet 4.6). API: als `output_config.effort` gesendet. CLI: via Env-Var `CLAUDE_CODE_EFFORT_LEVEL`. Bei OpenAI-Providern ignoriert. | | `IsPublic` | Andere User können den Agent in ihren Sessions verwenden (aber nicht bearbeiten) | ### Model-Auflösung diff --git a/ARCHITECTURE_QUICK.md b/ARCHITECTURE_QUICK.md index 8cf5c0e..1ad0b82 100644 --- a/ARCHITECTURE_QUICK.md +++ b/ARCHITECTURE_QUICK.md @@ -87,7 +87,7 @@ User 1──* TelegramBot 1──* Session (via telegram_bot_id) |---------|-------| | `users` | Login, DisplayName, IsAdmin, Persona, Settings (JSON), DefaultPath | | `tokens` | Auth-Tokens → User | -| `agents` | AI-Agenten (Model – z.B. `claude-sonnet-4-6` oder `nvidia:model-id`, CustomCommands, AutoCommit, UseSoul/Identity/UserInfo/Memory/AutoContext, UseGitHubSearch, UseSerperSearch, WebSearch, AllowUserChoice, TaskInstruction, AvatarScale/Offset, AvatarSmall, IsPublic) | +| `agents` | AI-Agenten (Model – z.B. `claude-sonnet-4-6` oder `nvidia:model-id`, CustomCommands, AutoCommit, UseSoul/Identity/UserInfo/Memory/AutoContext, UseGitHubSearch, UseSerperSearch, WebSearch, AllowUserChoice, TaskInstruction, Effort, AvatarScale/Offset, AvatarSmall, IsPublic) | | `sessions` | Chat-Sessions (Description, Image, ImageSmall, Workspace, Context, CustomCommands, TelegramBotId, TelegramChatId, AvatarScale/Offset, PreparerAgentId, ReviewAgentId, MaxReviewIterations, FinalizerAgentId) | | `chains` | Ein Request-Response-Zyklus (Tokens, Timing, Iterations, PlanMode, ToolChoice, ToolNames, StreamErrorInfo, ArchiveId) | | `messages` | Einzelne Nachrichten (text / tool_use / tool_result / error / web_search_result / auto_context), Tag für Sub-Agent-Markierung oder Import-Herkunft (`openclaw-import`), thought_signature (Gemini) | diff --git a/Endpoints/AgentEndpoint.cs b/Endpoints/AgentEndpoint.cs index f2ffda3..f028653 100644 --- a/Endpoints/AgentEndpoint.cs +++ b/Endpoints/AgentEndpoint.cs @@ -71,6 +71,7 @@ public static class AgentEndpoint a.WebSearchVersion, a.AllowUserChoice, a.TaskInstruction, + a.Effort, a.AvatarScale, a.AvatarOffsetX, a.AvatarOffsetY, @@ -137,6 +138,7 @@ public static class AgentEndpoint WebSearchVersion = body.TryGetProperty("webSearchVersion", out var wsv2) ? wsv2.GetString() ?? "" : "", AllowUserChoice = !body.TryGetProperty("allowUserChoice", out var auc) || auc.GetBoolean(), TaskInstruction = body.TryGetProperty("taskInstruction", out var ti) ? ti.GetString() : null, + Effort = body.TryGetProperty("effort", out var ef) ? ef.GetString() ?? "" : "", 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, @@ -184,6 +186,7 @@ public static class AgentEndpoint } if (body.TryGetProperty("allowUserChoice", out var auc)) agent.AllowUserChoice = auc.GetBoolean(); if (body.TryGetProperty("taskInstruction", out var ti)) agent.TaskInstruction = ti.GetString(); + if (body.TryGetProperty("effort", out var ef)) agent.Effort = ef.GetString() ?? ""; 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 9aea217..7fd8f1f 100644 --- a/Endpoints/ChatEndpoint.cs +++ b/Endpoints/ChatEndpoint.cs @@ -261,7 +261,7 @@ public static class ChatEndpoint if (anthropic.IsCliAvailable) { - await anthropic.StreamChatViaCli(res, ctx.ModelId, ctx.SystemPrompt, messages, ctx.ChainId, workspace: ctx.Workspace, allowUserChoice: ctx.Agent?.AllowUserChoice ?? true, planMode: body.PlanMode, webSearch: !string.IsNullOrEmpty(ctx.WebSearchVersion), sessionId: sessionId, agentId: ctx.AgentId, remoteMgr: remoteMgr, unityMcpUrl: ctx.Session?.UnityMcpUrl, unityMcpToken: ctx.Session?.UnityMcpToken, useAutoContext: ctx.Agent?.UseAutoContext ?? true, workCt: workCt, sseCt: sseCt); + await anthropic.StreamChatViaCli(res, ctx.ModelId, ctx.SystemPrompt, messages, ctx.ChainId, workspace: ctx.Workspace, allowUserChoice: ctx.Agent?.AllowUserChoice ?? true, planMode: body.PlanMode, webSearch: !string.IsNullOrEmpty(ctx.WebSearchVersion), sessionId: sessionId, agentId: ctx.AgentId, remoteMgr: remoteMgr, unityMcpUrl: ctx.Session?.UnityMcpUrl, unityMcpToken: ctx.Session?.UnityMcpToken, useAutoContext: ctx.Agent?.UseAutoContext ?? true, effort: ctx.Effort, workCt: workCt, sseCt: sseCt); } else { @@ -271,7 +271,7 @@ public static class ChatEndpoint 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); + 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, effort: ctx.Effort, workCt: workCt, hardCt: hardCt, sseCt: sseCt, remoteMgr: remoteMgr); } } finally diff --git a/Models/AgentRecord.cs b/Models/AgentRecord.cs index 9fe1c7a..36d3eb0 100644 --- a/Models/AgentRecord.cs +++ b/Models/AgentRecord.cs @@ -23,6 +23,13 @@ public class AgentRecord public string WebSearchVersion { get; set; } = ""; public bool AllowUserChoice { get; set; } = true; public string TaskInstruction { get; set; } + /// + /// Reasoning-Effort-Level für Claude (Opus 4.5+, Sonnet 4.6+). + /// Werte: "" (= high, weglassen), "low", "medium", "high", "xhigh" (Opus 4.7+), "max" (Opus 4.6+, Sonnet 4.6). + /// API-Pfad: wird als output_config.effort gesendet. CLI-Pfad: wird via CLAUDE_CODE_EFFORT_LEVEL gesetzt. + /// Bei OpenAI-Providern (MiniMax/Nvidia/etc.) wird das Feld stillschweigend ignoriert. + /// + public string Effort { get; set; } = ""; public double AvatarScale { get; set; } = 1.0; public double AvatarOffsetX { get; set; } public double AvatarOffsetY { get; set; } diff --git a/Models/ChatContext.cs b/Models/ChatContext.cs index cda5d43..dd268b1 100644 --- a/Models/ChatContext.cs +++ b/Models/ChatContext.cs @@ -17,6 +17,7 @@ public class ChatContext public string ToolChoice { get; set; } public bool UseMemory { get; set; } public string WebSearchVersion { get; set; } + public string Effort { get; set; } public int MaxIterations { get; set; } public AgentRecord Agent { get; set; } public SessionRecord Session { get; set; } @@ -43,6 +44,7 @@ public class SubAgentContext public bool UseMemory { get; set; } public string WebSearchVersion { get; set; } public string ToolChoice { get; set; } + public string Effort { get; set; } public AgentRecord Agent { get; set; } // Preparer-spezifisch diff --git a/Services/AnthropicService.Agents.cs b/Services/AnthropicService.Agents.cs index 48678d1..2bbdd19 100644 --- a/Services/AnthropicService.Agents.cs +++ b/Services/AnthropicService.Agents.cs @@ -77,7 +77,7 @@ public partial class AnthropicService preparer.Workspace, preparer.UseMemory, preparer.WebSearchVersion, preparer.ToolChoice, preparerMessages, chainId, sessionId, apiToken, usage, 0, "preparer", preparer.Agent?.Name ?? "Vorbereiter-Agent", - cancellationToken, cancellationToken); + cancellationToken, cancellationToken, preparer.Effort); } var result = new PreparerResult { IterationCount = iterations, ResponseText = text }; @@ -185,7 +185,7 @@ public partial class AnthropicService review.Workspace, review.UseMemory, review.WebSearchVersion, review.ToolChoice, reviewMessages, chainId, sessionId, apiToken, usage, baseIterations, "review", review.Agent?.Name ?? "Review-Agent", - workCt, sseCt); + workCt, sseCt, review.Effort); } var result = new ReviewResult { ReviewIterationCount = iterations }; @@ -256,7 +256,7 @@ public partial class AnthropicService finalizer.Workspace, finalizer.UseMemory, finalizer.WebSearchVersion, finalizer.ToolChoice, finalizerMessages, chainId, sessionId, apiToken, usage, baseIterations, "finalizer", finalizer.Agent?.Name ?? "Finalizer-Agent", - workCt, sseCt); + workCt, sseCt, finalizer.Effort); } await SseHelper.TryWriteSse(response, "finalizer_done", new @@ -446,7 +446,8 @@ public partial class AnthropicService int baseIteration, int maxIterations, CancellationToken ct, - NonStreamingLoopCallbacks cb = null) + NonStreamingLoopCallbacks cb = null, + string effort = null) { cb ??= new NonStreamingLoopCallbacks(); int iterations = 0; @@ -465,6 +466,10 @@ public partial class AnthropicService ["messages"] = messages }; + // Reasoning-Effort (Opus 4.5+, Sonnet 4.6+). "" / "high" / null = Default weglassen. + if (!string.IsNullOrEmpty(effort) && effort != "high") + payload["output_config"] = new { effort }; + if (systemPrompt is List spBlocks && spBlocks.Count > 0) { // Cache-Breakpoint auf den letzten System-Prompt-Block (1h TTL). @@ -640,7 +645,8 @@ public partial class AnthropicService string agentType, string agentName, CancellationToken workCt, - CancellationToken sseCt) + CancellationToken sseCt, + string effort = null) { return RunNonStreamingToolLoop( modelId, systemPrompt, @@ -657,7 +663,8 @@ public partial class AnthropicService SseResponse = response, SseCt = sseCt, SsePrefix = agentType, AgentName = agentName, Tag = agentType - }); + }, + effort); } /// @@ -722,6 +729,7 @@ public partial class AnthropicService systemPrompt: systemText.ToString(), workspace: sub.Workspace, hasWorkspace: !string.IsNullOrEmpty(sub.Workspace), + effort: sub.Effort, cancellationToken: workCt ); @@ -785,7 +793,8 @@ public partial class AnthropicService CancellationToken = ct, VectorSearch = _vectorSearch, EmbeddingBg = _embeddingBg, Db = _db, ChatService = _chatService, AnthropicService = this, OpenAiService = _openAiService }) - }); + }, + ctx.Effort); var finalStopReason = text.Length > 0 ? "end_turn" : "error"; await FinalizeChain(chain, usage, iterations, finalStopReason, sw); diff --git a/Services/AnthropicService.Cli.cs b/Services/AnthropicService.Cli.cs index d16e9fa..c1b8384 100644 --- a/Services/AnthropicService.Cli.cs +++ b/Services/AnthropicService.Cli.cs @@ -37,6 +37,7 @@ public partial class AnthropicService string unityMcpUrl = null, string unityMcpToken = null, bool useAutoContext = true, + string effort = null, CancellationToken workCt = default, CancellationToken sseCt = default) { @@ -250,6 +251,7 @@ public partial class AnthropicService webSearch: webSearch, mcpConfigPath: mcpConfigPath, hasUnityMcp: !string.IsNullOrEmpty(unityMcpUrl), + effort: effort, cancellationToken: workCt ); @@ -491,6 +493,7 @@ public partial class AnthropicService systemPrompt: systemText.ToString(), workspace: ctx.Workspace, hasWorkspace: !string.IsNullOrEmpty(ctx.Workspace), + effort: ctx.Effort, cancellationToken: cancellationToken ); diff --git a/Services/AnthropicService.Streaming.cs b/Services/AnthropicService.Streaming.cs index c7f24e9..aa56e38 100644 --- a/Services/AnthropicService.Streaming.cs +++ b/Services/AnthropicService.Streaming.cs @@ -36,6 +36,7 @@ public partial class AnthropicService bool useAutoContext = true, bool useGitHubSearch = false, bool useSerperSearch = false, + string effort = null, CancellationToken workCt = default, CancellationToken hardCt = default, CancellationToken sseCt = default, @@ -97,6 +98,11 @@ public partial class AnthropicService ["stream"] = true }; + // Reasoning-Effort (Opus 4.5+, Sonnet 4.6+). "" / "high" / null = Default weglassen. + // Werte: low / medium / high / xhigh (Opus 4.7+) / max (Opus 4.6+, Sonnet 4.6). + if (!string.IsNullOrEmpty(effort) && effort != "high") + payload["output_config"] = new { effort }; + if (systemPrompt != null && systemPrompt.Count > 0) { // Cache-Breakpoint auf den letzten System-Prompt-Block (1h TTL). diff --git a/Services/ChatService.cs b/Services/ChatService.cs index 9337990..1c7aabd 100644 --- a/Services/ChatService.cs +++ b/Services/ChatService.cs @@ -194,6 +194,7 @@ Für welche Plattform soll die App entwickelt werden? Web, Mobile oder Desktop? ToolChoice = toolChoice, UseMemory = agent.UseMemory, WebSearchVersion = agent.WebSearchVersion, + Effort = agent.Effort, MaxIterations = maxIterations, Agent = agent, Session = session, @@ -880,6 +881,7 @@ Für welche Plattform soll die App entwickelt werden? Web, Mobile oder Desktop? UseMemory = agent.UseMemory, WebSearchVersion = agent.WebSearchVersion, ToolChoice = hasTools ? "any" : "auto", + Effort = agent.Effort, Agent = agent }; } diff --git a/Services/ClaudeCliService.cs b/Services/ClaudeCliService.cs index 411a29f..5368086 100644 --- a/Services/ClaudeCliService.cs +++ b/Services/ClaudeCliService.cs @@ -56,7 +56,7 @@ public class ClaudeCliService return dir; } - private ProcessStartInfo CreateCliStartInfo(List args, bool redirectInput = false) + private ProcessStartInfo CreateCliStartInfo(List args, bool redirectInput = false, string effort = null) { var psi = new ProcessStartInfo { @@ -75,6 +75,11 @@ public class ClaudeCliService // dieser Flag holt die 1h-TTL zurück (gilt für API-Key, Bedrock, Vertex, Foundry). psi.Environment["ENABLE_PROMPT_CACHING_1H"] = "1"; + // Effort-Level via Env-Var setzen (höchste Priorität, deckt auch "max" und "ultracode" ab). + // Das "--effort"-Flag unterstützt nur low/medium/high/xhigh – Env-Var deckt alles. + if (!string.IsNullOrEmpty(effort) && effort != "high") + psi.Environment["CLAUDE_CODE_EFFORT_LEVEL"] = effort; + foreach (var arg in args) psi.ArgumentList.Add(arg); @@ -140,6 +145,7 @@ public class ClaudeCliService bool webSearch = false, string mcpConfigPath = null, bool hasUnityMcp = false, + string effort = null, CancellationToken cancellationToken = default) { if (!_isAvailable) @@ -223,14 +229,15 @@ public class ClaudeCliService args.Add(mcpConfigPath); } - return await RunCliStreamingAsync(args, prompt, onEvent, cancellationToken); + return await RunCliStreamingAsync(args, prompt, onEvent, cancellationToken, effort); } private async Task RunCliStreamingAsync( List args, string stdinPrompt, Func onEvent, - CancellationToken cancellationToken) + CancellationToken cancellationToken, + string effort = null) { var result = new CliChatResult(); var fullOutput = new StringBuilder(); @@ -250,7 +257,7 @@ public class ClaudeCliService try { - var startInfo = CreateCliStartInfo(args, redirectInput: true); + var startInfo = CreateCliStartInfo(args, redirectInput: true, effort: effort); using var process = new Process { StartInfo = startInfo }; diff --git a/Services/DatabaseService.Agents.cs b/Services/DatabaseService.Agents.cs index 4b03053..6cabd97 100644 --- a/Services/DatabaseService.Agents.cs +++ b/Services/DatabaseService.Agents.cs @@ -19,8 +19,8 @@ public partial class DatabaseService agent.CreatedAt = now; agent.UpdatedAt = now; await conn.ExecuteAsync(@" - INSERT INTO agents (agent_id, user_id, name, avatar, avatar_small, description, model, tool_choice, custom_commands, auto_commit, use_soul, use_identity, use_user_info, use_memory, use_auto_context, use_github_search, use_serper_search, use_web_search, web_search_version, allow_user_choice, task_instruction, avatar_scale, avatar_offset_x, avatar_offset_y, is_public, is_deleted, created_at, updated_at) - VALUES (@AgentId, @UserId, @Name, @Avatar, @AvatarSmall, @Description, @Model, @ToolChoice, @CustomCommands, @AutoCommit, @UseSoul, @UseIdentity, @UseUserInfo, @UseMemory, @UseAutoContext, @UseGitHubSearch, @UseSerperSearch, @UseWebSearch, @WebSearchVersion, @AllowUserChoice, @TaskInstruction, @AvatarScale, @AvatarOffsetX, @AvatarOffsetY, @IsPublic, 0, @CreatedAt, @UpdatedAt) + INSERT INTO agents (agent_id, user_id, name, avatar, avatar_small, description, model, tool_choice, custom_commands, auto_commit, use_soul, use_identity, use_user_info, use_memory, use_auto_context, use_github_search, use_serper_search, use_web_search, web_search_version, allow_user_choice, task_instruction, effort, avatar_scale, avatar_offset_x, avatar_offset_y, is_public, is_deleted, created_at, updated_at) + VALUES (@AgentId, @UserId, @Name, @Avatar, @AvatarSmall, @Description, @Model, @ToolChoice, @CustomCommands, @AutoCommit, @UseSoul, @UseIdentity, @UseUserInfo, @UseMemory, @UseAutoContext, @UseGitHubSearch, @UseSerperSearch, @UseWebSearch, @WebSearchVersion, @AllowUserChoice, @TaskInstruction, @Effort, @AvatarScale, @AvatarOffsetX, @AvatarOffsetY, @IsPublic, 0, @CreatedAt, @UpdatedAt) ", agent); return agent; } @@ -55,7 +55,7 @@ public partial 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_auto_context = @UseAutoContext, use_github_search = @UseGitHubSearch, use_serper_search = @UseSerperSearch, use_web_search = @UseWebSearch, web_search_version = @WebSearchVersion, - allow_user_choice = @AllowUserChoice, task_instruction = @TaskInstruction, + allow_user_choice = @AllowUserChoice, task_instruction = @TaskInstruction, effort = @Effort, avatar_scale = @AvatarScale, avatar_offset_x = @AvatarOffsetX, avatar_offset_y = @AvatarOffsetY, is_public = @IsPublic, updated_at = @UpdatedAt WHERE agent_id = @AgentId AND user_id = @UserId diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs index 15c8958..027efe3 100644 --- a/Services/DatabaseService.cs +++ b/Services/DatabaseService.cs @@ -196,6 +196,7 @@ public partial class DatabaseService TryAddColumn(conn, "sessions", "unity_mcp_url", "TEXT"); TryAddColumn(conn, "sessions", "unity_mcp_token", "TEXT"); TryAddColumn(conn, "messages", "tag", "TEXT"); + TryAddColumn(conn, "agents", "effort", "TEXT NOT NULL DEFAULT ''"); // Migration: 1M-Suffix entfernen (Mai 2026). Seit März 2026 ist 1M-Context Default // bei Opus 4.6/4.7/4.8 + Sonnet 4.6 – kein "[1m]"-Suffix mehr nötig. diff --git a/wwwroot/index.html b/wwwroot/index.html index 913dd19..cae705a 100644 --- a/wwwroot/index.html +++ b/wwwroot/index.html @@ -240,6 +240,15 @@ + +