feat: Payload-Preview im Chat-Menü + Reminder von hinten gezählt

- Neuer Endpoint GET /api/sessions/{id}/payload-preview
  Gibt den exakten Anthropic-API-Payload als JSON zurück (read-only)
- Chat-Menü: 'Payload anzeigen' öffnet Modal mit formatiertem JSON
- Reminder-Logik umgebaut: halbes Intervall (15) vor Ende,
  dann volle Intervalle (30) rückwärts statt von vorne gezählt
- CSS: Payload-Modal Styling, kleine Variable-Fixes
This commit is contained in:
Meleki committed 2026-03-15 10:46:51 +01:00
1 parent 229e6d9e53
commit 49ef6bedc6
7 files changed
+154 -21

No files matched your search

+70
View File
@@ -26,6 +26,7 @@ public static class SessionEndpoint
app.MapDelete("/api/sessions/{sessionId}", HandleDelete);
app.MapGet("/api/sessions/{sessionId}/system-prompt", HandleSystemPrompt);
app.MapGet("/api/sessions/{sessionId}/system-prompt-blocks", HandleSystemPromptBlocks);
app.MapGet("/api/sessions/{sessionId}/payload-preview", HandlePayloadPreview);
app.MapGet("/api/sessions/{sessionId}/streaming", HandleStreaming);
app.MapPost("/api/sessions/{sessionId}/exec", HandleExec);
app.MapGet("/api/sessions/{sessionId}/git-status", HandleGitStatus);
@@ -266,6 +267,75 @@ public static class SessionEndpoint
await ctx.Response.WriteAsJsonAsync(blocks.Select(b => new { b.Icon, b.Label, b.Content }));
}
private static async Task HandlePayloadPreview(HttpContext ctx, DatabaseService db, MemoryService memoryService, SkillService skillService, ChatService chatService, ToolService toolService, ServerSettingsService settings)
{
var result = await ResolvePromptContext(ctx, db, memoryService);
if (result == null) return;
var (session, agent, marked, memDir, skills, user, workspace, planMode) = result.Value;
// System-Prompt
var promptBlocks = SystemPromptBuilder.BuildBlocks(agent, session, marked, memoryService, memDir,
skills, skillService, userPersona: user?.GetEffectivePersona(), resolvedWorkspace: workspace, planMode: planMode);
var systemPromptText = string.Join("\n\n", promptBlocks.Select(b => b.Content));
var systemPrompt = new List<object>();
if (!string.IsNullOrWhiteSpace(systemPromptText))
systemPrompt.Add(new { type = "text", text = systemPromptText });
// Model
var modelId = ChatService.ResolveModelId(agent.Model);
// Messages aus der DB (exakt wie beim Chat)
var messages = await chatService.BuildHistoryFromDb(session.SessionId, promptBlocks: promptBlocks);
// Tools (exakt wie AddToolsToPayload es machen würde)
var hasWorkspace = !string.IsNullOrEmpty(workspace);
var includeMemory = agent.UseMemory && !string.IsNullOrEmpty(agent.AgentId);
var includeGitHubSearch = agent.UseGitHubSearch && toolService.HasGitHubToken;
var includeSerperSearch = agent.UseSerperSearch && toolService.HasSerperKey;
var hasTools = hasWorkspace || includeMemory || includeGitHubSearch || includeSerperSearch;
var tools = new List<object>();
if (hasTools)
{
var allTools = toolService.GetToolDefinitions(
includeFileTools: hasWorkspace,
includeMemory: includeMemory,
includeUserChoice: agent.AllowUserChoice,
includeGitHubSearch: includeGitHubSearch,
includeSerperSearch: includeSerperSearch);
if (planMode)
allTools = toolService.FilterReadOnlyTools(allTools);
tools.AddRange(allTools);
}
if (!string.IsNullOrEmpty(agent.WebSearchVersion))
tools.Add(new { type = agent.WebSearchVersion, name = "web_search", max_uses = 5 });
var toolChoice = hasTools || !string.IsNullOrEmpty(agent.WebSearchVersion) ? "any" : null;
var effectiveChoice = toolChoice == "any" ? "any" : "auto";
// Payload zusammenbauen (Anthropic-Format)
var payload = new Dictionary<string, object>
{
["model"] = modelId,
["max_tokens"] = 16384,
["messages"] = messages,
["stream"] = true
};
if (systemPrompt.Count > 0)
payload["system"] = systemPrompt;
if (tools.Count > 0)
{
payload["tools"] = tools;
payload["tool_choice"] = new { type = effectiveChoice };
}
ctx.Response.ContentType = "application/json; charset=utf-8";
await ctx.Response.WriteAsync(JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true }));
}
private static async Task HandleStreaming(HttpContext ctx, DatabaseService db, StreamingTracker streamingTracker)
{
var userId = ctx.GetUserId();