using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace AxCopilot.Services.Agent; public class OpenExternalTool : IAgentTool { public string Name => "open_external"; public string Description => "Open a file with its default application or open a URL in the default browser. Also supports opening a folder in File Explorer. Use after creating documents, reports, or charts for the user to view."; public ToolParameterSchema Parameters { get { ToolParameterSchema obj = new ToolParameterSchema { Properties = new Dictionary { ["path"] = new ToolProperty { Type = "string", Description = "File path, directory path, or URL to open" } } }; int num = 1; List list = new List(num); CollectionsMarshal.SetCount(list, num); CollectionsMarshal.AsSpan(list)[0] = "path"; obj.Required = list; return obj; } } public Task ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default(CancellationToken)) { string text = args.GetProperty("path").GetString() ?? ""; if (string.IsNullOrWhiteSpace(text)) { return Task.FromResult(ToolResult.Fail("경로가 비어 있습니다.")); } try { if (text.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || text.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { Process.Start(new ProcessStartInfo(text) { UseShellExecute = true }); return Task.FromResult(ToolResult.Ok("URL 열기: " + text)); } string text2 = (Path.IsPathRooted(text) ? text : Path.Combine(context.WorkFolder, text)); if (!context.IsPathAllowed(text2)) { return Task.FromResult(ToolResult.Fail("경로 접근 차단: " + text2)); } if (File.Exists(text2)) { Process.Start(new ProcessStartInfo(text2) { UseShellExecute = true }); return Task.FromResult(ToolResult.Ok("파일 열기: " + text2, text2)); } if (Directory.Exists(text2)) { Process.Start(new ProcessStartInfo("explorer.exe", text2)); return Task.FromResult(ToolResult.Ok("폴더 열기: " + text2, text2)); } return Task.FromResult(ToolResult.Fail("경로를 찾을 수 없습니다: " + text2)); } catch (Exception ex) { return Task.FromResult(ToolResult.Fail("열기 오류: " + ex.Message)); } } }