using System.Text.Json; using System.Windows; namespace AxCopilot.Services.Agent; /// /// Windows 클립보드 읽기·쓰기 도구. /// 에이전트가 클립보드를 통해 데이터를 주고받을 수 있게 합니다. /// public class ClipboardTool : IAgentTool { public string Name => "clipboard_tool"; public string Description => "Read or write the Windows clipboard. Actions: " + "'read' — get current clipboard text content; " + "'write' — set clipboard text content; " + "'has_text' — check if clipboard contains text; " + "'has_image' — check if clipboard contains an image."; public ToolParameterSchema Parameters => new() { Properties = new() { ["action"] = new() { Type = "string", Description = "Action to perform", Enum = ["read", "write", "has_text", "has_image"], }, ["text"] = new() { Type = "string", Description = "Text to write to clipboard (required for 'write' action)", }, }, Required = ["action"], }; public async Task ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default) { var action = args.GetProperty("action").SafeGetString() ?? ""; try { // 클립보드는 STA 스레드에서만 접근 가능 — InvokeAsync로 UI 스레드 블로킹 방지 var result = await Application.Current.Dispatcher.InvokeAsync(() => { return action switch { "read" => ReadClipboard(), "write" => WriteClipboard(args), "has_text" => ToolResult.Ok(Clipboard.ContainsText() ? "true" : "false"), "has_image" => ToolResult.Ok(Clipboard.ContainsImage() ? "true" : "false"), _ => ToolResult.Fail($"Unknown action: {action}"), }; }); return result ?? ToolResult.Fail("클립보드 접근 실패"); } catch (Exception ex) { return ToolResult.Fail($"클립보드 오류: {ex.Message}"); } } private static ToolResult ReadClipboard() { if (!Clipboard.ContainsText()) return ToolResult.Ok("(clipboard is empty or contains non-text data)"); var text = Clipboard.GetText(); if (string.IsNullOrEmpty(text)) return ToolResult.Ok("(empty)"); if (text.Length > 10000) return ToolResult.Ok(text[..10000] + $"\n\n... (truncated, total {text.Length} chars)"); return ToolResult.Ok(text); } private static ToolResult WriteClipboard(JsonElement args) { if (!args.SafeTryGetProperty("text", out var textProp)) return ToolResult.Fail("'text' parameter is required for write action"); var text = textProp.SafeGetString() ?? ""; Clipboard.SetText(text); return ToolResult.Ok($"✓ Clipboard updated ({text.Length} chars)"); } }