Initial commit to new repository
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
using AxCopilot.Models;
|
||||
using AxCopilot.SDK;
|
||||
using AxCopilot.Services;
|
||||
using AxCopilot.Views;
|
||||
|
||||
namespace AxCopilot.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// "!" 프리픽스 핸들러. AX Agent (AI 어시스턴트) 기능.
|
||||
/// ★ DEPLOY_STUB = true → 배포용 "개발 중" 표시
|
||||
/// ★ DEPLOY_STUB = false → 실제 ChatWindow 동작
|
||||
/// </summary>
|
||||
public class ChatHandler : IActionHandler
|
||||
{
|
||||
// ┌──────────────────────────────────────────────────────────────┐
|
||||
// │ 배포 시 true, 개발 활성화 시 false 로 전환 │
|
||||
// └──────────────────────────────────────────────────────────────┘
|
||||
private const bool DEPLOY_STUB = false;
|
||||
|
||||
private readonly SettingsService _settings;
|
||||
private readonly object _windowLock = new();
|
||||
private ChatWindow? _chatWindow;
|
||||
|
||||
public string? Prefix => "!";
|
||||
public PluginMetadata Metadata => new("ax.agent", "AX Agent", "1.0", "AX Agent — AI 어시스턴트");
|
||||
|
||||
public ChatHandler(SettingsService settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
|
||||
{
|
||||
// ── 배포용 스텁 ─────────────────────────────────────────────
|
||||
#pragma warning disable CS0162 // DEPLOY_STUB 플래그에 의한 의도된 비활성 코드
|
||||
if (DEPLOY_STUB)
|
||||
{
|
||||
var stub = new List<LauncherItem>
|
||||
{
|
||||
new LauncherItem(
|
||||
"AX Agent (개발 중)",
|
||||
"이 기능은 다음 버전에서 제공될 예정입니다. 기대해 주세요!",
|
||||
null, null, Symbol: "\uE8BD")
|
||||
};
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(stub);
|
||||
}
|
||||
#pragma warning restore CS0162
|
||||
|
||||
// ── AI 비활성화 체크 ─────────────────────────────────────────
|
||||
var appSettings = (System.Windows.Application.Current as App)?.SettingsService?.Settings;
|
||||
if (appSettings?.AiEnabled == false)
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(Array.Empty<LauncherItem>());
|
||||
|
||||
// ── 실제 구현 ───────────────────────────────────────────────
|
||||
var items = new List<LauncherItem>();
|
||||
var q = query.Trim();
|
||||
|
||||
if (string.IsNullOrEmpty(q))
|
||||
{
|
||||
items.Add(new LauncherItem(
|
||||
"AX Agent 대화하기",
|
||||
"AI 비서와 대화를 시작합니다",
|
||||
null, "open_chat", Symbol: "\uE8BD"));
|
||||
|
||||
try
|
||||
{
|
||||
var storage = new ChatStorageService();
|
||||
var metas = storage.LoadAllMeta();
|
||||
foreach (var conv in metas.Take(5))
|
||||
{
|
||||
var ago = FormatTimeAgo(conv.UpdatedAt);
|
||||
var symbol = ChatCategory.GetSymbol(conv.Category);
|
||||
items.Add(new LauncherItem(
|
||||
conv.Title,
|
||||
$"{ago} · 메시지 {conv.Messages.Count}개",
|
||||
null, $"resume:{conv.Id}", Symbol: symbol));
|
||||
}
|
||||
if (metas.Any())
|
||||
items.Add(new LauncherItem(
|
||||
"새 대화 시작",
|
||||
"이전 대화와 별개의 새 대화를 시작합니다",
|
||||
null, "new_chat", Symbol: "\uE710"));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(new LauncherItem(
|
||||
$"AI에게 물어보기: {(q.Length > 40 ? q[..40] + "…" : q)}",
|
||||
"Enter를 누르면 AX Agent이 열리고 질문이 전송됩니다",
|
||||
null, $"ask:{q}", Symbol: "\uE8BD"));
|
||||
items.Add(new LauncherItem(
|
||||
"AX Agent 대화하기",
|
||||
"질문 없이 Agent 창만 엽니다",
|
||||
null, "open_chat", Symbol: "\uE8BD"));
|
||||
}
|
||||
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
|
||||
{
|
||||
#pragma warning disable CS0162 // DEPLOY_STUB 플래그에 의한 의도된 비활성 코드
|
||||
if (DEPLOY_STUB) return Task.CompletedTask;
|
||||
#pragma warning restore CS0162
|
||||
|
||||
// AI 비활성화 시 실행 차단
|
||||
var appSettings2 = (System.Windows.Application.Current as App)?.SettingsService?.Settings;
|
||||
if (appSettings2?.AiEnabled == false) return Task.CompletedTask;
|
||||
|
||||
var data = item.Data as string ?? "open_chat";
|
||||
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
EnsureChatWindow();
|
||||
|
||||
if (data.StartsWith("ask:"))
|
||||
{
|
||||
var question = data[4..];
|
||||
_chatWindow!.Show();
|
||||
_chatWindow.Activate();
|
||||
_chatWindow.SendInitialMessage(question);
|
||||
}
|
||||
else if (data.StartsWith("resume:"))
|
||||
{
|
||||
var convId = data[7..];
|
||||
_chatWindow!.Show();
|
||||
_chatWindow.Activate();
|
||||
_chatWindow.ResumeConversation(convId);
|
||||
}
|
||||
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)
|
||||
{
|
||||
_chatWindow = new ChatWindow(_settings);
|
||||
_chatWindow.Closed += (_, _) => { lock (_windowLock) _chatWindow = null; };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string FormatTimeAgo(DateTime dt)
|
||||
{
|
||||
var diff = DateTime.Now - dt;
|
||||
if (diff.TotalMinutes < 1) return "방금 전";
|
||||
if (diff.TotalHours < 1) return $"{(int)diff.TotalMinutes}분 전";
|
||||
if (diff.TotalDays < 1) return $"{(int)diff.TotalHours}시간 전";
|
||||
if (diff.TotalDays < 7) return $"{(int)diff.TotalDays}일 전";
|
||||
return dt.ToString("yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user