using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using AxCopilot.Models; using AxCopilot.SDK; using AxCopilot.Services; using AxCopilot.Views; namespace AxCopilot.Handlers; public class ChatHandler : IActionHandler { private const bool DEPLOY_STUB = false; private readonly SettingsService _settings; private readonly object _windowLock = new object(); private ChatWindow? _chatWindow; public string? Prefix => "!"; public PluginMetadata Metadata => new PluginMetadata("ax.agent", "AX Agent", "1.0", "AX Agent — AI 어시스턴트"); public ChatHandler(SettingsService settings) { _settings = settings; } public Task> GetItemsAsync(string query, CancellationToken ct) { bool flag = false; AppSettings appSettings = (Application.Current as App)?.SettingsService?.Settings; if (appSettings != null && !appSettings.AiEnabled) { return Task.FromResult((IEnumerable)Array.Empty()); } List list = new List(); string text = query.Trim(); if (string.IsNullOrEmpty(text)) { list.Add(new LauncherItem("AX Agent 대화하기", "AI 비서와 대화를 시작합니다", null, "open_chat", null, "\ue8bd")); try { ChatStorageService chatStorageService = new ChatStorageService(); List source = chatStorageService.LoadAllMeta(); foreach (ChatConversation item in source.Take(5)) { string value = FormatTimeAgo(item.UpdatedAt); string symbol = ChatCategory.GetSymbol(item.Category); list.Add(new LauncherItem(item.Title, $"{value} · 메시지 {item.Messages.Count}개", null, "resume:" + item.Id, null, symbol)); } if (source.Any()) { list.Add(new LauncherItem("새 대화 시작", "이전 대화와 별개의 새 대화를 시작합니다", null, "new_chat", null, "\ue710")); } } catch { } } else { list.Add(new LauncherItem("AI에게 물어보기: " + ((text.Length > 40) ? (text.Substring(0, 40) + "…") : text), "Enter를 누르면 AX Agent이 열리고 질문이 전송됩니다", null, "ask:" + text, null, "\ue8bd")); list.Add(new LauncherItem("AX Agent 대화하기", "질문 없이 Agent 창만 엽니다", null, "open_chat", null, "\ue8bd")); } return Task.FromResult((IEnumerable)list); } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { bool flag = false; AppSettings appSettings = (Application.Current as App)?.SettingsService?.Settings; if (appSettings != null && !appSettings.AiEnabled) { return Task.CompletedTask; } string data = (item.Data as string) ?? "open_chat"; ((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate { EnsureChatWindow(); if (data.StartsWith("ask:")) { string text = data; string message = text.Substring(4, text.Length - 4); _chatWindow.Show(); _chatWindow.Activate(); _chatWindow.SendInitialMessage(message); } else if (data.StartsWith("resume:")) { string text = data; string conversationId = text.Substring(7, text.Length - 7); _chatWindow.Show(); _chatWindow.Activate(); _chatWindow.ResumeConversation(conversationId); } else if (data == "new_chat") { _chatWindow.Show(); _chatWindow.Activate(); _chatWindow.StartNewAndFocus(); } else { _chatWindow.Show(); _chatWindow.Activate(); } }); return Task.CompletedTask; } private void EnsureChatWindow() { lock (_windowLock) { if (_chatWindow != null && _chatWindow.IsLoaded) { return; } _chatWindow = new ChatWindow(_settings); _chatWindow.Closed += delegate { lock (_windowLock) { _chatWindow = null; } }; } } private static string FormatTimeAgo(DateTime dt) { TimeSpan timeSpan = DateTime.Now - dt; if (timeSpan.TotalMinutes < 1.0) { return "방금 전"; } if (timeSpan.TotalHours < 1.0) { return $"{(int)timeSpan.TotalMinutes}분 전"; } if (timeSpan.TotalDays < 1.0) { return $"{(int)timeSpan.TotalHours}시간 전"; } if (timeSpan.TotalDays < 7.0) { return $"{(int)timeSpan.TotalDays}일 전"; } return dt.ToString("yyyy-MM-dd"); } }