Files
AX-Copilot-Codex/.decompiledproj/AxCopilot/Core/CommandResolver.cs

250 lines
6.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AxCopilot.SDK;
using AxCopilot.Services;
namespace AxCopilot.Core;
public class CommandResolver
{
private readonly FuzzyEngine _fuzzy;
private readonly SettingsService _settings;
private readonly Dictionary<string, IActionHandler> _handlers = new Dictionary<string, IActionHandler>();
private readonly List<IActionHandler> _fuzzyHandlers = new List<IActionHandler>();
public IReadOnlyDictionary<string, IActionHandler> RegisteredHandlers => _handlers;
public CommandResolver(FuzzyEngine fuzzy, SettingsService settings)
{
_fuzzy = fuzzy;
_settings = settings;
}
public void RegisterHandler(IActionHandler handler)
{
if (handler.Prefix == null)
{
_fuzzyHandlers.Add(handler);
LogService.Info("FuzzyHandler 등록: name='" + handler.Metadata.Name + "'");
return;
}
if (_handlers.ContainsKey(handler.Prefix))
{
LogService.Warn($"Prefix '{handler.Prefix}' 중복 등록: '{handler.Metadata.Name}'이 기존 핸들러를 덮어씁니다.");
}
_handlers[handler.Prefix] = handler;
LogService.Info($"Handler 등록: prefix='{handler.Prefix}', name='{handler.Metadata.Name}'");
}
public async Task<IEnumerable<LauncherItem>> ResolveAsync(string input, CancellationToken ct)
{
if (string.IsNullOrWhiteSpace(input))
{
return Enumerable.Empty<LauncherItem>();
}
foreach (var (prefix, handler) in _handlers)
{
if (input.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
object obj;
if (input.Length <= prefix.Length)
{
obj = "";
}
else
{
string text2 = input;
int length = prefix.Length;
obj = text2.Substring(length, text2.Length - length).Trim();
}
string query = (string)obj;
try
{
return await handler.GetItemsAsync(query, ct);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex2)
{
LogService.Error("Handler '" + handler.Metadata.Name + "' 오류: " + ex2.Message);
return new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("오류: " + ex2.Message, handler.Metadata.Name, null, null));
}
}
}
int maxResults = _settings.Settings.Launcher.MaxResults;
HashSet<string> seenPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
List<LauncherItem> fuzzyItems = UsageRankingService.SortByUsage((from r in _fuzzy.Search(input, maxResults * 2)
where seenPaths.Add(r.Entry.Path)
select r).Take(maxResults).Select(delegate(FuzzyResult r)
{
string displayName = r.Entry.DisplayName;
string subtitle;
if (r.Entry.Type == IndexEntryType.Alias)
{
string aliasType = r.Entry.AliasType;
if (1 == 0)
{
}
string text3 = ((aliasType == "url") ? "URL 단축키" : ((!(aliasType == "batch")) ? r.Entry.Path : "명령 단축키"));
if (1 == 0)
{
}
subtitle = text3;
}
else
{
subtitle = r.Entry.Path + " ⇧ Shift+Enter: 폴더 열기";
}
object entry = r.Entry;
IndexEntryType type = r.Entry.Type;
if (1 == 0)
{
}
string symbol;
switch (type)
{
case IndexEntryType.App:
symbol = "\uecaa";
break;
case IndexEntryType.Folder:
symbol = "\ue8b7";
break;
case IndexEntryType.Alias:
{
string aliasType2 = r.Entry.AliasType;
if (1 == 0)
{
}
string text3 = ((aliasType2 == "url") ? "\ue774" : ((!(aliasType2 == "batch")) ? "\uecca" : "\ue756"));
if (1 == 0)
{
}
symbol = text3;
break;
}
default:
symbol = "\ue8a5";
break;
}
if (1 == 0)
{
}
return new LauncherItem(displayName, subtitle, null, entry, null, symbol);
}), (LauncherItem item) => (item.Data as IndexEntry)?.Path).ToList();
if (_fuzzyHandlers.Count > 0)
{
List<Task<IEnumerable<LauncherItem>>> extraTasks = _fuzzyHandlers.Select((IActionHandler h) => SafeGetItemsAsync(h, input, ct)).ToList();
await Task.WhenAll(extraTasks);
foreach (Task<IEnumerable<LauncherItem>> task in extraTasks)
{
if (task.IsCompletedSuccessfully)
{
fuzzyItems.AddRange(task.Result.Take(3));
}
}
}
return fuzzyItems;
}
public async Task ExecuteAsync(LauncherItem item, string lastInput, CancellationToken ct)
{
foreach (var (prefix, handler) in _handlers)
{
if (lastInput.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
object obj;
if (lastInput.Length <= prefix.Length)
{
obj = "";
}
else
{
int length = prefix.Length;
obj = lastInput.Substring(length, lastInput.Length - length).Trim().Split(' ')[0];
}
string q = (string)obj;
string cmdKey = (string.IsNullOrEmpty(q) ? prefix : (prefix + q));
UsageStatisticsService.RecordCommandUsage(cmdKey);
await handler.ExecuteAsync(item, ct);
return;
}
}
object data = item.Data;
if (data is string urlData && urlData.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
await ExecuteNullPrefixAsync(item, ct);
return;
}
data = item.Data;
IndexEntry entry = data as IndexEntry;
if (entry == null)
{
return;
}
string expanded = Environment.ExpandEnvironmentVariables(entry.Path);
try
{
await Task.Run(() => Process.Start(new ProcessStartInfo(expanded)
{
UseShellExecute = true
}));
}
catch (Exception ex)
{
Exception ex2 = ex;
LogService.Error("실행 실패: " + expanded + " - " + ex2.Message);
}
Task.Run(delegate
{
UsageRankingService.RecordExecution(entry.Path);
});
}
public async Task ExecuteNullPrefixAsync(LauncherItem item, CancellationToken ct)
{
foreach (IActionHandler handler in _fuzzyHandlers)
{
try
{
await handler.ExecuteAsync(item, ct);
return;
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex2)
{
LogService.Error("FuzzyHandler '" + handler.Metadata.Name + "' 실행 오류: " + ex2.Message);
}
}
}
private static async Task<IEnumerable<LauncherItem>> SafeGetItemsAsync(IActionHandler handler, string query, CancellationToken ct)
{
try
{
return await handler.GetItemsAsync(query, ct);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex2)
{
Exception ex3 = ex2;
LogService.Error("FuzzyHandler '" + handler.Metadata.Name + "' 오류: " + ex3.Message);
return Enumerable.Empty<LauncherItem>();
}
}
}