설정 fan-out 통합과 AX Agent 대기열 상태 분리 정리
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- AX Agent가 SettingsService 변경 이벤트를 직접 구독해 메인 설정과 AX Agent 설정 어느 경로에서 저장하더라도 테마, 모델, 권한, 데이터 활용, composer, 대기열 UI를 즉시 다시 읽어오도록 fan-out 경로를 통합함 - AX Agent 설정 저장 경로와 구형 Agent 설정창에서 표현 수준을 rich로 덮어쓰던 처리를 제거해 풍부하게/적절하게/간단하게 설정이 유지되도록 보정함 - DraftQueue 패널을 실행 중/다음 작업/보류/완료/실패 개별 섹션으로 재구성해 queue state를 더 빠르게 파악할 수 있게 정리함 - README, DEVELOPMENT, AGENT_ROADMAP 문서 이력을 2026-04-04 23:23 (KST) 기준으로 갱신함 - 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0 / 오류 0)
This commit is contained in:
@@ -379,6 +379,11 @@ ow + toggle 시각 언어로 통일했습니다.
|
|||||||
- DraftQueue 패널 상단에 실행 중 / 다음 / 보류 / 완료 / 실패 요약 pill을 추가하고, composer 상단의 모델/컨텍스트/프리셋 줄도 더 낮고 평평한 밀도로 정리했습니다.
|
- DraftQueue 패널 상단에 실행 중 / 다음 / 보류 / 완료 / 실패 요약 pill을 추가하고, composer 상단의 모델/컨텍스트/프리셋 줄도 더 낮고 평평한 밀도로 정리했습니다.
|
||||||
- 브랜치/워크트리 패널에는 공통 요약 strip을 추가해 현재 상태를 같은 시각 언어로 보여주도록 맞췄고, 저장소 루트 `.gitignore`에는 빌드 산출물·IDE 파일·OS 잡파일·비밀정보 패턴을 추가했습니다.
|
- 브랜치/워크트리 패널에는 공통 요약 strip을 추가해 현재 상태를 같은 시각 언어로 보여주도록 맞췄고, 저장소 루트 `.gitignore`에는 빌드 산출물·IDE 파일·OS 잡파일·비밀정보 패턴을 추가했습니다.
|
||||||
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0
|
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0
|
||||||
|
- 업데이트: 2026-04-04 23:23 (KST)
|
||||||
|
- AX Agent는 이제 설정 서비스 변경 이벤트를 직접 구독해 메인 설정, AX Agent 설정, 저장 경로와 관계없이 테마/권한/데이터 활용/모델 라벨/composer/대기열 UI를 즉시 다시 읽어오도록 fan-out 경로를 통합했습니다.
|
||||||
|
- AX Agent 설정 저장 경로에서 표현 수준을 `rich`로 고정 덮어쓰던 처리도 제거해, 사용자가 선택한 `풍부하게 / 적절하게 / 간단하게` 값이 다른 설정 저장 흐름에서도 유지되도록 보정했습니다.
|
||||||
|
- DraftQueue 패널은 실행 중 / 다음 작업 / 보류 / 완료 / 실패를 개별 섹션으로 나눠 현재 실행 상태와 최근 결과를 더 빠르게 파악할 수 있도록 재구성했습니다.
|
||||||
|
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -97,3 +97,7 @@
|
|||||||
- 트레이 좌클릭 기본 진입점을 AX Agent로 전환하고, 우클릭 메뉴 상단에 앱 버전 헤더를 추가해 AX Agent 중심 진입 흐름을 강화함.
|
- 트레이 좌클릭 기본 진입점을 AX Agent로 전환하고, 우클릭 메뉴 상단에 앱 버전 헤더를 추가해 AX Agent 중심 진입 흐름을 강화함.
|
||||||
- 메인 설정 저장 완료 후 열린 AX Agent 창이 즉시 테마/모델/권한/하단 상태줄을 다시 읽어오도록 fan-out 경로를 추가해 설정 반영 지연을 줄임.
|
- 메인 설정 저장 완료 후 열린 AX Agent 창이 즉시 테마/모델/권한/하단 상태줄을 다시 읽어오도록 fan-out 경로를 추가해 설정 반영 지연을 줄임.
|
||||||
- DraftQueue kind 분류를 message/command/steering/direct/followup 기준으로 재정리해 큐 타입과 실제 입력 성격이 더 잘 맞도록 보강함.
|
- DraftQueue kind 분류를 message/command/steering/direct/followup 기준으로 재정리해 큐 타입과 실제 입력 성격이 더 잘 맞도록 보강함.
|
||||||
|
- 업데이트: 2026-04-04 23:23 (KST)
|
||||||
|
- AX Agent가 `SettingsService.SettingsChanged`를 직접 구독하도록 바꿔 메인 설정/AX Agent 설정 어느 경로에서 저장하더라도 테마, 모델, 권한, 데이터 활용, composer, 대기열 UI가 즉시 동일 상태를 반영하도록 fan-out을 통합함.
|
||||||
|
- AX Agent 설정 저장 경로에서 표현 수준을 무조건 `rich`로 덮어쓰던 로직을 제거해 `풍부하게 / 적절하게 / 간단하게`가 다른 설정 저장 경로에서도 유지되도록 보정함.
|
||||||
|
- DraftQueue 패널은 `실행 중 / 다음 작업 / 보류 / 완료 / 실패` 개별 섹션 구조로 다시 나눠 현재 실행 흐름과 재시도 대기, 결과 이력을 더 빠르게 파악할 수 있도록 정리함.
|
||||||
|
|||||||
@@ -4068,3 +4068,11 @@ ow + toggle 시각 언어로 다시 정렬했다.
|
|||||||
- 메인 설정 저장 완료 시 열려 있는 AX Agent 창이 즉시 테마, 모델, 권한, 데이터 활용, overlay/inline 빠른 설정, 하단 composer 라벨을 다시 읽어오도록 `RefreshFromSavedSettings()` fan-out 경로를 추가했다.
|
- 메인 설정 저장 완료 시 열려 있는 AX Agent 창이 즉시 테마, 모델, 권한, 데이터 활용, overlay/inline 빠른 설정, 하단 composer 라벨을 다시 읽어오도록 `RefreshFromSavedSettings()` fan-out 경로를 추가했다.
|
||||||
- DraftQueue kind 판정은 일반 입력(message), 슬래시 명령(command), 조정 입력(steering), 직접 실행 요청(direct), 후속 작업(followup)이 실제 입력 형태와 더 일치하도록 보강했고, 전송 버튼은 일반 메시지 전송 경로를 사용하도록 정리했다.
|
- DraftQueue kind 판정은 일반 입력(message), 슬래시 명령(command), 조정 입력(steering), 직접 실행 요청(direct), 후속 작업(followup)이 실제 입력 형태와 더 일치하도록 보강했고, 전송 버튼은 일반 메시지 전송 경로를 사용하도록 정리했다.
|
||||||
- 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\ (경고 0 / 오류 0)
|
- 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\ (경고 0 / 오류 0)
|
||||||
|
|
||||||
|
### 2026-04-04 추가 진행 기록 (연속 실행 76차: 설정 이벤트 fan-out 통합과 큐 상태 섹션 재구성)
|
||||||
|
- 업데이트: 2026-04-04 23:23 (KST)
|
||||||
|
- AX Agent 창이 `SettingsService.SettingsChanged`를 직접 구독하도록 연결해 메인 설정, AX Agent 설정, 저장 방식이 달라도 테마/권한/데이터 활용/모델 라벨/하단 composer/대기열 UI가 즉시 같은 상태를 반영하도록 fan-out 경로를 통합했다.
|
||||||
|
- `RefreshFromSavedSettings()`는 기존 시각 요소 갱신 외에도 대기열 패널과 대화 목록까지 다시 읽어오도록 확장해 저장 후 AX Agent 화면과 실제 실행 상태가 더 빠르게 맞춰지도록 보강했다.
|
||||||
|
- AX Agent 설정 저장 경로와 구형 Agent 설정창에서 표현 수준을 무조건 `rich`로 덮어쓰던 코드를 제거해, 사용자가 선택한 `풍부하게 / 적절하게 / 간단하게` 값이 다른 설정 흐름에서도 유지되도록 수정했다.
|
||||||
|
- DraftQueue 패널은 기존 `실행 대기 / 최근 결과` 묶음에서 `실행 중 / 다음 작업 / 보류 / 완료 / 실패` 개별 섹션 구조로 재편해 queue state가 많은 경우에도 현재 진행, 다음 실행, 재시도 대기, 완료/실패 이력을 더 빠르게 구분할 수 있게 했다.
|
||||||
|
- 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\ (경고 0 / 오류 0)
|
||||||
|
|||||||
@@ -383,7 +383,6 @@ public partial class AgentSettingsWindow : Window
|
|||||||
_llm.PlanMode = _planMode;
|
_llm.PlanMode = _planMode;
|
||||||
_llm.AgentDecisionLevel = _reasoningMode;
|
_llm.AgentDecisionLevel = _reasoningMode;
|
||||||
_llm.FolderDataUsage = _folderDataUsage;
|
_llm.FolderDataUsage = _folderDataUsage;
|
||||||
_llm.AgentUiExpressionLevel = "rich";
|
|
||||||
|
|
||||||
_llm.EnableProactiveContextCompact = ChkEnableProactiveCompact.IsChecked == true;
|
_llm.EnableProactiveContextCompact = ChkEnableProactiveCompact.IsChecked == true;
|
||||||
_llm.ContextCompactTriggerPercent = ParseInt(TxtContextCompactTriggerPercent.Text, 80, 10, 95);
|
_llm.ContextCompactTriggerPercent = ParseInt(TxtContextCompactTriggerPercent.Text, 80, 10, 95);
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ public partial class ChatWindow : Window
|
|||||||
private string _gitBranchSearchText = "";
|
private string _gitBranchSearchText = "";
|
||||||
private StackPanel? _selectedMessageActionBar;
|
private StackPanel? _selectedMessageActionBar;
|
||||||
private Border? _selectedMessageBorder;
|
private Border? _selectedMessageBorder;
|
||||||
|
private bool _isRefreshingFromSettings;
|
||||||
private void ApplyQuickActionVisual(Button button, bool active, string activeBg, string activeFg)
|
private void ApplyQuickActionVisual(Button button, bool active, string activeBg, string activeFg)
|
||||||
{
|
{
|
||||||
if (button?.Content is not string text)
|
if (button?.Content is not string text)
|
||||||
@@ -134,6 +135,7 @@ public partial class ChatWindow : Window
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
|
_settings.SettingsChanged += Settings_SettingsChanged;
|
||||||
_storage = new ChatStorageService();
|
_storage = new ChatStorageService();
|
||||||
_llm = new LlmService(settings);
|
_llm = new LlmService(settings);
|
||||||
_router = new ModelRouterService(settings);
|
_router = new ModelRouterService(settings);
|
||||||
@@ -297,6 +299,7 @@ public partial class ChatWindow : Window
|
|||||||
};
|
};
|
||||||
Closed += (_, _) =>
|
Closed += (_, _) =>
|
||||||
{
|
{
|
||||||
|
_settings.SettingsChanged -= Settings_SettingsChanged;
|
||||||
SubAgentTool.StatusChanged -= OnSubAgentStatusChanged;
|
SubAgentTool.StatusChanged -= OnSubAgentStatusChanged;
|
||||||
_streamCts?.Cancel();
|
_streamCts?.Cancel();
|
||||||
_cursorTimer.Stop();
|
_cursorTimer.Stop();
|
||||||
@@ -306,6 +309,28 @@ public partial class ChatWindow : Window
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Settings_SettingsChanged(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_forceClose || !IsLoaded || _isRefreshingFromSettings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Dispatcher.BeginInvoke(new Action(() =>
|
||||||
|
{
|
||||||
|
if (_forceClose || !IsLoaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_isRefreshingFromSettings = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RefreshFromSavedSettings();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isRefreshingFromSettings = false;
|
||||||
|
}
|
||||||
|
}), DispatcherPriority.Input);
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsPermissionAutoApprovedForSession(string toolName, string target)
|
private bool IsPermissionAutoApprovedForSession(string toolName, string target)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(toolName) || string.IsNullOrWhiteSpace(target))
|
if (string.IsNullOrWhiteSpace(toolName) || string.IsNullOrWhiteSpace(target))
|
||||||
@@ -13956,6 +13981,8 @@ public partial class ChatWindow : Window
|
|||||||
RefreshContextUsageVisual();
|
RefreshContextUsageVisual();
|
||||||
UpdateTabUI();
|
UpdateTabUI();
|
||||||
BuildBottomBar();
|
BuildBottomBar();
|
||||||
|
RefreshDraftQueueUi();
|
||||||
|
RefreshConversationList();
|
||||||
}, DispatcherPriority.Input);
|
}, DispatcherPriority.Input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13978,7 +14005,6 @@ public partial class ChatWindow : Window
|
|||||||
llm.Code.EnableCodeVerification = ChkOverlayEnableCodeVerification?.IsChecked == true;
|
llm.Code.EnableCodeVerification = ChkOverlayEnableCodeVerification?.IsChecked == true;
|
||||||
llm.EnableParallelTools = ChkOverlayEnableParallelTools?.IsChecked == true;
|
llm.EnableParallelTools = ChkOverlayEnableParallelTools?.IsChecked == true;
|
||||||
llm.FolderDataUsage = _folderDataUsage;
|
llm.FolderDataUsage = _folderDataUsage;
|
||||||
llm.AgentUiExpressionLevel = "rich";
|
|
||||||
|
|
||||||
CommitOverlayEndpointInput(normalizeOnInvalid: true);
|
CommitOverlayEndpointInput(normalizeOnInvalid: true);
|
||||||
CommitOverlayApiKeyInput();
|
CommitOverlayApiKeyInput();
|
||||||
@@ -17228,45 +17254,35 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
|
|||||||
}
|
}
|
||||||
|
|
||||||
DraftQueuePanel.Visibility = Visibility.Visible;
|
DraftQueuePanel.Visibility = Visibility.Visible;
|
||||||
const int maxVisible = 8;
|
|
||||||
var summary = _appState.GetDraftQueueSummary(_activeTab);
|
var summary = _appState.GetDraftQueueSummary(_activeTab);
|
||||||
var activeItems = visibleItems
|
|
||||||
.Where(item => !string.Equals(item.State, "completed", StringComparison.OrdinalIgnoreCase)
|
|
||||||
&& !string.Equals(item.State, "failed", StringComparison.OrdinalIgnoreCase))
|
|
||||||
.Take(maxVisible)
|
|
||||||
.ToList();
|
|
||||||
var historyItems = visibleItems
|
|
||||||
.Where(item => string.Equals(item.State, "completed", StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| string.Equals(item.State, "failed", StringComparison.OrdinalIgnoreCase))
|
|
||||||
.Take(Math.Max(0, maxVisible - activeItems.Count))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
DraftQueuePanel.Children.Add(CreateDraftQueueSummaryStrip(summary));
|
DraftQueuePanel.Children.Add(CreateDraftQueueSummaryStrip(summary));
|
||||||
|
const int maxPerSection = 3;
|
||||||
|
var runningItems = visibleItems
|
||||||
|
.Where(item => string.Equals(item.State, "running", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Take(maxPerSection)
|
||||||
|
.ToList();
|
||||||
|
var queuedItems = visibleItems
|
||||||
|
.Where(item => string.Equals(item.State, "queued", StringComparison.OrdinalIgnoreCase) && !IsDraftBlocked(item))
|
||||||
|
.Take(maxPerSection)
|
||||||
|
.ToList();
|
||||||
|
var blockedItems = visibleItems
|
||||||
|
.Where(IsDraftBlocked)
|
||||||
|
.Take(maxPerSection)
|
||||||
|
.ToList();
|
||||||
|
var completedItems = visibleItems
|
||||||
|
.Where(item => string.Equals(item.State, "completed", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Take(maxPerSection)
|
||||||
|
.ToList();
|
||||||
|
var failedItems = visibleItems
|
||||||
|
.Where(item => string.Equals(item.State, "failed", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Take(maxPerSection)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (activeItems.Count > 0)
|
AddDraftQueueSection("실행 중", runningItems, summary.RunningCount);
|
||||||
{
|
AddDraftQueueSection("다음 작업", queuedItems, summary.QueuedCount);
|
||||||
DraftQueuePanel.Children.Add(CreateDraftQueueSectionLabel($"실행 대기 · {activeItems.Count}"));
|
AddDraftQueueSection("보류", blockedItems, summary.BlockedCount);
|
||||||
foreach (var item in activeItems)
|
AddDraftQueueSection("완료", completedItems, summary.CompletedCount);
|
||||||
DraftQueuePanel.Children.Add(CreateDraftQueueCard(item));
|
AddDraftQueueSection("실패", failedItems, summary.FailedCount);
|
||||||
}
|
|
||||||
|
|
||||||
if (historyItems.Count > 0)
|
|
||||||
{
|
|
||||||
DraftQueuePanel.Children.Add(CreateDraftQueueSectionLabel($"최근 결과 · {historyItems.Count}"));
|
|
||||||
foreach (var item in historyItems)
|
|
||||||
DraftQueuePanel.Children.Add(CreateDraftQueueCard(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visibleItems.Count > activeItems.Count + historyItems.Count)
|
|
||||||
{
|
|
||||||
DraftQueuePanel.Children.Add(new TextBlock
|
|
||||||
{
|
|
||||||
Text = $"추가 항목 {visibleItems.Count - (activeItems.Count + historyItems.Count)}개",
|
|
||||||
Margin = new Thickness(8, 4, 0, 0),
|
|
||||||
FontSize = 11,
|
|
||||||
Foreground = TryFindResource("SecondaryText") as Brush ?? BrushFromHex("#7A7F87"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (summary.CompletedCount > 0 || summary.FailedCount > 0)
|
if (summary.CompletedCount > 0 || summary.FailedCount > 0)
|
||||||
{
|
{
|
||||||
@@ -17286,6 +17302,27 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddDraftQueueSection(string label, IReadOnlyList<DraftQueueItem> items, int totalCount)
|
||||||
|
{
|
||||||
|
if (DraftQueuePanel == null || totalCount <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DraftQueuePanel.Children.Add(CreateDraftQueueSectionLabel($"{label} · {totalCount}"));
|
||||||
|
foreach (var item in items)
|
||||||
|
DraftQueuePanel.Children.Add(CreateDraftQueueCard(item));
|
||||||
|
|
||||||
|
if (totalCount > items.Count)
|
||||||
|
{
|
||||||
|
DraftQueuePanel.Children.Add(new TextBlock
|
||||||
|
{
|
||||||
|
Text = $"추가 항목 {totalCount - items.Count}개",
|
||||||
|
Margin = new Thickness(8, -2, 0, 8),
|
||||||
|
FontSize = 10.5,
|
||||||
|
Foreground = TryFindResource("SecondaryText") as Brush ?? BrushFromHex("#7A7F87"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private UIElement CreateDraftQueueSummaryStrip(AppStateService.DraftQueueSummaryState summary)
|
private UIElement CreateDraftQueueSummaryStrip(AppStateService.DraftQueueSummaryState summary)
|
||||||
{
|
{
|
||||||
var wrap = new WrapPanel
|
var wrap = new WrapPanel
|
||||||
|
|||||||
Reference in New Issue
Block a user