diff --git a/README.md b/README.md index 1623656..548bb66 100644 --- a/README.md +++ b/README.md @@ -751,6 +751,7 @@ ow + toggle 시각 언어로 통일했습니다. - 같은 수정에서 `PersistConversationSnapshot(...)`를 추가해 중간 저장, 최종 저장, 지연 저장 flush를 한 경로로 묶었고, `RunAgentLoopAsync(...)` 안의 중복 `_storage.Save(...)` / `RememberConversation(...)`는 제거했습니다. 이제 Cowork/Code 완료 시점 저장은 `FinalizeConversationTurn(...)` 쪽의 단일 완료 경로가 맡습니다. - 이번엔 실행 이벤트가 들어올 때 창 코드가 즉시 많이 만지던 UI 갱신도 배치형으로 묶었습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)에 `_agentUiEventTimer`, `ScheduleAgentUiEvent(...)`, `FlushPendingAgentUiEvent()`를 추가해서, 상태바/스티키 진행률/플랜 뷰어/파일 탐색기 자동 새로고침/제안 토스트/자동 프리뷰 반영이 가장 최근 이벤트 기준으로 90ms 단위로만 화면에 반영되게 했습니다. - `OnAgentEvent(...)`는 이제 실행 이벤트 자체를 대화 모델과 앱 상태에 먼저 반영하고, 화면 갱신은 배치된 UI 이벤트 flush가 담당합니다. 이 조정으로 Cowork/Code 실행 중 빠른 이벤트 연속 구간에서 상태바와 진행률, 파일 미리보기 쪽이 따로따로 즉시 흔들리던 체감을 더 줄이는 방향으로 정리했습니다. +- 대기열 다음 작업 시작도 입력창 UI에 의존하지 않게 바꿨습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `SendMessageAsync(...)`는 이제 선택적으로 직접 텍스트를 받을 수 있고, `StartNextQueuedDraftIfAny(...)`는 더 이상 `InputBox.Text`를 바꿔 포커스를 흔든 뒤 전송하지 않고 `SendMessageAsync(next.Text)`로 바로 실행합니다. 이걸로 Cowork/Code 자동 이어달리기가 입력창 상태를 덜 건드리게 됐습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0 - 업데이트: 2026-04-05 12:24 (KST) - 업데이트: 2026-04-05 12:31 (KST) @@ -763,6 +764,7 @@ ow + toggle 시각 언어로 통일했습니다. - 업데이트: 2026-04-05 13:12 (KST) - 업데이트: 2026-04-05 13:20 (KST) - 업데이트: 2026-04-05 13:29 (KST) +- 업데이트: 2026-04-05 13:37 (KST) --- diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 94d24a2..6d3bad8 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4522,3 +4522,6 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎. - 업데이트: 2026-04-05 13:29 (KST) - 실행 이벤트가 들어올 때 즉시 많이 흔들리던 UI 갱신도 배치형으로 추가 정리했습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)에 `_agentUiEventTimer`, `ScheduleAgentUiEvent(...)`, `FlushPendingAgentUiEvent()`를 넣어, `UpdateStatusBar(...)`, `UpdateAgentProgressBar(...)`, `UpdatePlanViewerStep(...)`, `CompletePlanViewer()`, `RefreshFileTreeIfVisible()`, `RenderSuggestActionChips(...)`, 자동 프리뷰 반영이 모두 최근 이벤트 기준 90ms 배치 갱신을 타게 했습니다. - `OnAgentEvent(...)`는 이제 실행 이벤트를 먼저 대화 모델(`ExecutionEvents`, `AgentRuns`)과 앱 상태에 반영하고, UI는 배치 flush가 따라가도록 정리됐습니다. 이건 `claw-code` 기준의 “세션/상태 우선, 화면은 그 결과를 따라감” 원칙을 AX 구조에서 더 강화하는 단계입니다. +- 업데이트: 2026-04-05 13:37 (KST) +- 남아 있던 큰 UI 결합점인 “대기열 실행이 입력창을 거쳐 시작되는 구조”도 줄였습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `SendMessageAsync(...)`는 이제 직접 텍스트 인자를 받을 수 있고, `StartNextQueuedDraftIfAny(...)`는 `InputBox.Text = next.Text` / `Focus()` / `UpdateInputBoxHeight()`를 거치지 않고 `SendMessageAsync(next.Text)`를 바로 호출합니다. +- 이 변경으로 대기열 기반 Cowork/Code 후속 작업은 입력창 상태와 포커스를 덜 흔들고, 실행 축 자체가 입력 UI보다 엔진/세션 흐름에 더 가까워졌습니다. 현재 남은 마감 작업은 완료 카드와 일부 에러 재시도 표시처럼 아직 창 코드에 남아 있는 소수의 직접 UI 후처리를 더 줄이는 단계입니다. diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index 6c58091..4cadbfb 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -7988,15 +7988,17 @@ public partial class ChatWindow : Window return true; } - private async Task SendMessageAsync() + private async Task SendMessageAsync(string? directText = null) { - var rawText = InputBox.Text.Trim(); + var useComposerInput = directText == null; + var rawText = (directText ?? InputBox.Text).Trim(); // 슬래시 칩이 활성화된 경우 명령어 앞에 붙임 - var text = _slashPalette.ActiveCommand != null + var text = useComposerInput && _slashPalette.ActiveCommand != null ? (_slashPalette.ActiveCommand + " " + rawText).Trim() : rawText; - HideSlashChip(restoreText: false); + if (useComposerInput) + HideSlashChip(restoreText: false); if (string.IsNullOrEmpty(text) || _isStreaming) return; @@ -8334,8 +8336,11 @@ public partial class ChatWindow : Window TryPersistConversation(force: true); UpdateChatTitle(); - InputBox.Text = ""; - UpdateInputBoxHeight(); + if (useComposerInput) + { + InputBox.Text = ""; + UpdateInputBoxHeight(); + } EmptyState.Visibility = Visibility.Collapsed; RenderMessages(preserveViewport: true); @@ -20048,7 +20053,7 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi private void StartNextQueuedDraftIfAny(string? preferredDraftId = null) { - if (_isStreaming || InputBox == null) + if (_isStreaming) return; DraftQueueItem? next = null; @@ -20063,12 +20068,8 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi _currentConversation = session?.CurrentConversation ?? _currentConversation; } - InputBox.Text = next.Text; - InputBox.CaretIndex = InputBox.Text.Length; - InputBox.Focus(); - UpdateInputBoxHeight(); RefreshDraftQueueUi(); - _ = SendMessageAsync(); + _ = SendMessageAsync(next.Text); } private static int GetDraftStateRank(DraftQueueItem item)