Files
AX-Copilot-Codex/.decompiledproj/AxCopilot/Services/AgentTriggerService.cs

202 lines
4.7 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Windows;
using System.Windows.Threading;
namespace AxCopilot.Services;
public class AgentTriggerService : IDisposable
{
private readonly SettingsService _settings;
private FileSystemWatcher? _fileWatcher;
private DispatcherTimer? _scheduleTimer;
private readonly List<TriggerRule> _rules = new List<TriggerRule>();
private bool _disposed;
public Action<string, string>? OnTriggerFired { get; set; }
public IReadOnlyList<TriggerRule> Rules => _rules;
public AgentTriggerService(SettingsService settings)
{
_settings = settings;
}
public void Start()
{
LoadRules();
StartFileWatcher();
StartScheduleTimer();
LogService.Info($"에이전트 트리거 서비스 시작: {_rules.Count}개 규칙");
}
public void Reload()
{
Stop();
Start();
}
public void Stop()
{
_fileWatcher?.Dispose();
_fileWatcher = null;
DispatcherTimer? scheduleTimer = _scheduleTimer;
if (scheduleTimer != null)
{
scheduleTimer.Stop();
}
}
private void LoadRules()
{
_rules.Clear();
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "triggers.json");
if (!File.Exists(path))
{
return;
}
try
{
string json = File.ReadAllText(path);
List<TriggerRule> list = JsonSerializer.Deserialize<List<TriggerRule>>(json);
if (list != null)
{
_rules.AddRange(list.Where((TriggerRule r) => r.Enabled));
}
}
catch (Exception ex)
{
LogService.Warn("트리거 규칙 로드 실패: " + ex.Message);
}
}
private void StartFileWatcher()
{
List<TriggerRule> fileRules = _rules.Where((TriggerRule r) => r.Type == "file_change").ToList();
if (fileRules.Count == 0)
{
return;
}
string workFolder = _settings.Settings.Llm.WorkFolder;
if (string.IsNullOrEmpty(workFolder) || !Directory.Exists(workFolder))
{
return;
}
_fileWatcher = new FileSystemWatcher(workFolder)
{
IncludeSubdirectories = true,
NotifyFilter = (NotifyFilters.FileName | NotifyFilters.LastWrite),
EnableRaisingEvents = true
};
DateTime lastTrigger = DateTime.MinValue;
_fileWatcher.Changed += delegate(object _, FileSystemEventArgs e)
{
if ((DateTime.Now - lastTrigger).TotalSeconds < 5.0)
{
return;
}
foreach (TriggerRule rule in fileRules)
{
if (MatchesPattern(e.FullPath, rule.Pattern))
{
lastTrigger = DateTime.Now;
string prompt = rule.Prompt.Replace("{file}", e.FullPath).Replace("{name}", e.Name ?? "");
Application current = Application.Current;
if (current != null)
{
((DispatcherObject)current).Dispatcher.BeginInvoke((Delegate)(Action)delegate
{
OnTriggerFired?.Invoke(rule.Name, prompt);
}, Array.Empty<object>());
}
break;
}
}
};
}
private void StartScheduleTimer()
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Expected O, but got Unknown
List<TriggerRule> scheduleRules = _rules.Where((TriggerRule r) => r.Type == "schedule").ToList();
if (scheduleRules.Count == 0)
{
return;
}
_scheduleTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMinutes(1.0)
};
_scheduleTimer.Tick += delegate
{
DateTime now = DateTime.Now;
foreach (TriggerRule item in scheduleRules)
{
if (ShouldRunSchedule(item, now))
{
item.LastRun = now;
OnTriggerFired?.Invoke(item.Name, item.Prompt);
}
}
};
_scheduleTimer.Start();
}
private static bool MatchesPattern(string filePath, string? pattern)
{
if (string.IsNullOrEmpty(pattern))
{
return true;
}
if (pattern.StartsWith("*."))
{
return filePath.EndsWith(pattern.Substring(1, pattern.Length - 1), StringComparison.OrdinalIgnoreCase);
}
return filePath.Contains(pattern, StringComparison.OrdinalIgnoreCase);
}
private static bool ShouldRunSchedule(TriggerRule rule, DateTime now)
{
if (rule.LastRun.HasValue && (now - rule.LastRun.Value).TotalMinutes < (double)(rule.IntervalMinutes ?? 60))
{
return false;
}
if (rule.ActiveHourStart.HasValue && now.Hour < rule.ActiveHourStart.Value)
{
return false;
}
if (rule.ActiveHourEnd.HasValue && now.Hour >= rule.ActiveHourEnd.Value)
{
return false;
}
return true;
}
public void FireManual(string ruleName)
{
TriggerRule triggerRule = _rules.FirstOrDefault((TriggerRule r) => r.Name == ruleName);
if (triggerRule != null)
{
OnTriggerFired?.Invoke(triggerRule.Name, triggerRule.Prompt);
}
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
Stop();
}
}
}