158 lines
4.3 KiB
C#
158 lines
4.3 KiB
C#
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<IEnumerable<LauncherItem>> 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<LauncherItem>)Array.Empty<LauncherItem>());
|
|
}
|
|
List<LauncherItem> list = new List<LauncherItem>();
|
|
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<ChatConversation> 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<LauncherItem>)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");
|
|
}
|
|
}
|