Files
gott/Models/ChatModels.cs
T
Meleki 6d95f9aec2 feat: Plan-Modus – Toggle im Chat zum Umschalten zwischen Plan/Ausführung
- Toggle-Button (🗺️) im Chat-Input-Bereich neben Explorer
- Plan-Modus wird per ChatRequest.planMode an Backend gesendet
- Backend: Write-Tools gefiltert (nur read_file, list_files, glob, grep,
  todo_write, memory_*, ask_user_choice bleiben), System-Prompt-Block
  ergänzt der Änderungen verbietet, tool_choice nie 'any' erzwungen
- ChainRecord.PlanMode: pro Chain gespeichert (informativ für History)
- Chain-Meta-Badge '📋 Plan-Modus' bei Plan-Chains
- Choice-Response erbt planMode vom vorherigen Chain
- CSS: .plan-mode-active Styling (Primary-Color Highlight)
- Placeholder wechselt zu 'Plannen...' wenn aktiv
- Plan-Modus wird bei Session-Wechsel zurückgesetzt
2026-03-07 12:07:39 +01:00

154 lines
4.9 KiB
C#

using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Gott.Models;
public class ChatMessage
{
[JsonPropertyName("role")]
public string Role { get; set; } = "";
[JsonPropertyName("content")]
public JsonElement Content { get; set; }
/// <summary>
/// Extrahiert den reinen Text aus Content (egal ob string oder content-block array).
/// </summary>
public string GetTextContent()
{
if (Content.ValueKind == JsonValueKind.String)
return Content.GetString() ?? "";
if (Content.ValueKind == JsonValueKind.Array)
{
var parts = new List<string>();
foreach (var block in Content.EnumerateArray())
{
if (block.TryGetProperty("type", out var t) && t.GetString() == "text"
&& block.TryGetProperty("text", out var txt))
parts.Add(txt.GetString() ?? "");
}
return string.Join("\n", parts);
}
return Content.ToString();
}
/// <summary>
/// Prüft ob Datei-Attachments (image/document) enthalten sind.
/// </summary>
public bool HasAttachments()
{
if (Content.ValueKind != JsonValueKind.Array) return false;
foreach (var block in Content.EnumerateArray())
{
if (block.TryGetProperty("type", out var t))
{
var type = t.GetString();
if (type == "image" || type == "document") return true;
}
}
return false;
}
/// <summary>
/// Gibt Attachment-Infos zurück (type + media_type).
/// </summary>
public List<AttachmentInfo> GetAttachments()
{
var result = new List<AttachmentInfo>();
if (Content.ValueKind != JsonValueKind.Array) return result;
foreach (var block in Content.EnumerateArray())
{
if (block.TryGetProperty("type", out var t))
{
var type = t.GetString();
if (type == "image" || type == "document")
{
var mediaType = "";
if (block.TryGetProperty("source", out var src) && src.TryGetProperty("media_type", out var mt))
mediaType = mt.GetString() ?? "";
result.Add(new AttachmentInfo { Type = type, MediaType = mediaType });
}
}
}
return result;
}
/// <summary>
/// Gibt vollständige Attachment-Blöcke zurück (inkl. Base64-Daten).
/// </summary>
public List<AttachmentBlock> GetAttachmentBlocks()
{
var result = new List<AttachmentBlock>();
if (Content.ValueKind != JsonValueKind.Array) return result;
foreach (var block in Content.EnumerateArray())
{
if (block.TryGetProperty("type", out var t))
{
var type = t.GetString();
if (type == "image" || type == "document")
{
var mediaType = "";
var data = "";
var fileName = "";
if (block.TryGetProperty("source", out var src))
{
if (src.TryGetProperty("media_type", out var mt))
mediaType = mt.GetString() ?? "";
if (src.TryGetProperty("data", out var d))
data = d.GetString() ?? "";
}
if (block.TryGetProperty("_file_name", out var fn))
fileName = fn.GetString() ?? "";
result.Add(new AttachmentBlock { Type = type, MediaType = mediaType, Data = data, FileName = fileName });
}
}
}
return result;
}
}
public class AttachmentBlock
{
public string Type { get; set; } = "";
public string MediaType { get; set; } = "";
public string Data { get; set; } = "";
public string FileName { get; set; } = "";
}
public class AttachmentInfo
{
public string Type { get; set; } = "";
public string MediaType { get; set; } = "";
}
public class ChatRequest
{
[JsonPropertyName("content")]
public JsonElement Content { get; set; }
[JsonPropertyName("sessionId")]
public string SessionId { get; set; } = "";
/// <summary>
/// Wenn gesetzt: Dies ist eine Antwort auf ein ask_user_choice Tool.
/// Enthält die tool_use_id des offenen ask_user_choice-Calls.
/// </summary>
[JsonPropertyName("choiceToolCallId")]
public string ChoiceToolCallId { get; set; }
/// <summary>
/// Der gewählte Text aus den Auswahloptionen.
/// </summary>
[JsonPropertyName("choiceResult")]
public string ChoiceResult { get; set; }
/// <summary>
/// Wenn true: Plan-Modus aktiv. Nur Read-only Tools, keine Datei-Änderungen.
/// </summary>
[JsonPropertyName("planMode")]
public bool PlanMode { get; set; }
}