[Phase L3-9 + 버그] AX Agent 오류 수정 + 런처 미니 위젯 4종 구현
AX Agent 오류 수정: - AgentSettingsPanel.xaml에 <UserControl.Resources> 추가 - ToggleSwitch 스타일 자체 정의 (SettingsWindow 리소스 미접근 문제 해결) - 원인: XamlParseException — 'ToggleSwitch' 리소스 찾을 수 없음 (CS 로그 확인) PerformanceMonitorService.cs (신규, 138줄): - GetSystemTimes P/Invoke → CPU% (이전/현재 샘플 델타 계산) - GlobalMemoryStatusEx P/Invoke → RAM% + "6.1/16GB" 형식 텍스트 - DriveInfo → C: 드라이브 사용률/용량 텍스트 - 2초 폴링, StartPolling/StopPolling 제어 PomodoroService.cs (신규, 179줄): - 집중(25분)/휴식(5분) 타이머, 상태: Idle/Focus/Break - pomodoro.json 영속성 (경과 시간 자동 보정) - StateChanged 이벤트 → 위젯 실시간 갱신 ServerStatusService.cs (신규, 124줄): - Ollama(/api/version), LLM API, 첫 번째 MCP 서버 15초 주기 핑 - HttpClient 1.5초 타임아웃, StatusChanged 이벤트 PomoHandler.cs (신규, 130줄): - pomo prefix: 상태보기/start/break/stop/reset - PomodoroService 직접 연동 LauncherViewModel.Widgets.cs (신규, 81줄): - Widget_PerfText, Widget_PomoText, Widget_PomoRunning - Widget_NoteText, Widget_OllamaOnline, Widget_LlmOnline, Widget_McpOnline - UpdateWidgets() — 5틱마다 메모 건수 갱신 (파일 I/O 최소화) LauncherWindow.Widgets.cs (신규, 143줄): - IsVisibleChanged 이벤트로 위젯 자동 시작/중지 - DispatcherTimer 1초마다 UpdateWidgets + 서버 상태 dot 색상 직접 갱신 - 위젯 클릭 → 해당 prefix 자동 입력 (perf→info, pomo→pomo, note→note, server→port) LauncherWindow.xaml: - RowDefinition 6개 → 7개 - Row 6: 위젯 바 (시스템모니터/뽀모도로/메모/서버 4열) 빌드: 경고 0, 오류 0
This commit is contained in:
@@ -174,6 +174,9 @@ public class NoteHandler : IActionHandler
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>저장된 메모 건수를 반환합니다 (위젯 표시용).</summary>
|
||||
public static int GetNoteCount() => ReadNotes().Count;
|
||||
|
||||
/// <summary>
|
||||
/// 특정 메모 1건 삭제. content가 일치하는 가장 최근 항목을 제거합니다.
|
||||
/// </summary>
|
||||
|
||||
130
src/AxCopilot/Handlers/PomoHandler.cs
Normal file
130
src/AxCopilot/Handlers/PomoHandler.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using AxCopilot.SDK;
|
||||
using AxCopilot.Services;
|
||||
using AxCopilot.Themes;
|
||||
|
||||
namespace AxCopilot.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// Phase L3-9: 뽀모도로 타이머 핸들러. "pomo" 프리픽스로 사용합니다.
|
||||
///
|
||||
/// 사용법:
|
||||
/// pomo → 현재 타이머 상태 표시
|
||||
/// pomo start → 집중 타이머 시작 (25분)
|
||||
/// pomo break → 휴식 타이머 시작 (5분)
|
||||
/// pomo stop → 타이머 중지
|
||||
/// pomo reset → 타이머 초기화
|
||||
///
|
||||
/// Enter → 해당 명령 실행.
|
||||
/// </summary>
|
||||
public class PomoHandler : IActionHandler
|
||||
{
|
||||
public string? Prefix => "pomo";
|
||||
|
||||
public PluginMetadata Metadata => new(
|
||||
"Pomodoro",
|
||||
"뽀모도로 타이머 — pomo",
|
||||
"1.0",
|
||||
"AX",
|
||||
"집중/휴식 타이머를 관리합니다.");
|
||||
|
||||
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
|
||||
{
|
||||
var q = query.Trim().ToLowerInvariant();
|
||||
var svc = PomodoroService.Instance;
|
||||
var items = new List<LauncherItem>();
|
||||
|
||||
// ─── 명령 분기 ────────────────────────────────────────────────────────
|
||||
|
||||
if (q is "start" or "focus")
|
||||
{
|
||||
items.Add(new LauncherItem("집중 타이머 시작",
|
||||
$"{svc.FocusMinutes}분 집중 모드 시작 · Enter로 실행",
|
||||
null, "__START__", Symbol: Symbols.Timer));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
if (q is "break" or "rest")
|
||||
{
|
||||
items.Add(new LauncherItem("휴식 타이머 시작",
|
||||
$"{svc.BreakMinutes}분 휴식 모드 시작 · Enter로 실행",
|
||||
null, "__BREAK__", Symbol: Symbols.Timer));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
if (q is "stop" or "pause")
|
||||
{
|
||||
items.Add(new LauncherItem("타이머 중지",
|
||||
"현재 타이머를 중지합니다 · Enter로 실행",
|
||||
null, "__STOP__", Symbol: Symbols.MediaPlay));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
if (q == "reset")
|
||||
{
|
||||
items.Add(new LauncherItem("타이머 초기화",
|
||||
"타이머를 처음 상태로 초기화합니다 · Enter로 실행",
|
||||
null, "__RESET__", Symbol: Symbols.Restart));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
// ─── 기본: 현재 상태 + 명령 목록 ─────────────────────────────────────
|
||||
|
||||
var remaining = svc.Remaining;
|
||||
var timeStr = $"{(int)remaining.TotalMinutes:D2}:{remaining.Seconds:D2}";
|
||||
var stateStr = svc.Mode switch
|
||||
{
|
||||
PomodoroMode.Focus => svc.IsRunning ? $"집중 중 {timeStr} 남음" : $"집중 일시정지 {timeStr} 남음",
|
||||
PomodoroMode.Break => svc.IsRunning ? $"휴식 중 {timeStr} 남음" : $"휴식 일시정지 {timeStr} 남음",
|
||||
_ => "대기 중",
|
||||
};
|
||||
|
||||
// 상태 카드
|
||||
items.Add(new LauncherItem(
|
||||
"🍅 뽀모도로 타이머",
|
||||
stateStr,
|
||||
null, null, Symbol: Symbols.Timer));
|
||||
|
||||
// 빠른 명령들
|
||||
if (!svc.IsRunning)
|
||||
{
|
||||
items.Add(new LauncherItem("집중 시작",
|
||||
$"{svc.FocusMinutes}분 집중 모드 시작 · Enter로 실행",
|
||||
null, "__START__", Symbol: Symbols.Timer));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(new LauncherItem("타이머 중지",
|
||||
"현재 타이머를 중지합니다 · Enter로 실행",
|
||||
null, "__STOP__", Symbol: Symbols.MediaPlay));
|
||||
}
|
||||
|
||||
if (svc.Mode == PomodoroMode.Focus && svc.IsRunning)
|
||||
{
|
||||
items.Add(new LauncherItem("휴식 시작",
|
||||
$"{svc.BreakMinutes}분 휴식 모드로 전환 · Enter로 실행",
|
||||
null, "__BREAK__", Symbol: Symbols.Timer));
|
||||
}
|
||||
|
||||
items.Add(new LauncherItem("타이머 초기화",
|
||||
"타이머를 처음 상태로 초기화합니다 · Enter로 실행",
|
||||
null, "__RESET__", Symbol: Symbols.Restart));
|
||||
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
|
||||
{
|
||||
if (item.Data is not string cmd) return Task.CompletedTask;
|
||||
|
||||
var svc = PomodoroService.Instance;
|
||||
switch (cmd)
|
||||
{
|
||||
case "__START__": svc.StartFocus(); break;
|
||||
case "__BREAK__": svc.StartBreak(); break;
|
||||
case "__STOP__": svc.Stop(); break;
|
||||
case "__RESET__": svc.Reset(); break;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user