Compare commits
2 Commits
554b1fb83e
...
28869caa32
| Author | SHA1 | Date | |
|---|---|---|---|
| 28869caa32 | |||
| bd8a1ef7bd |
@@ -753,6 +753,8 @@ ow + toggle 시각 언어로 통일했습니다.
|
||||
- `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 자동 이어달리기가 입력창 상태를 덜 건드리게 됐습니다.
|
||||
- 실패 후 재시도도 같은 방향으로 정리했습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `RetryLastUserMessageFromConversation()`는 이제 입력창에 마지막 요청을 다시 밀어 넣지 않고, 유휴 상태면 `SendMessageAsync(lastUserMessage)`로 바로 다시 실행하고, 이미 작업 중이면 같은 요청을 곧바로 대기열에 적재합니다. 재시도 동작도 입력창 포커스와 높이를 흔들지 않게 만든 조정입니다.
|
||||
- 이어서 구형 본문 재시도 카드도 제거했습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `AddRetryButton()` 경로를 걷어내고, 실패 시에는 본문에 임시 재시도 카드를 꽂지 않고 짧은 토스트로만 안내한 뒤 작업 요약/실패 이력 쪽 재시도 액션을 사용하도록 정리했습니다. 본문을 메시지와 상태 중심으로 유지하는 `claw-code` 방향에 더 가깝게 맞춘 것입니다.
|
||||
- UI도 `claw-code` 기준으로 1차 정리를 넣었습니다. [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml) 에서 메시지 컬럼 폭을 `880`으로 더 정리하고, 상단 진행률 바 패딩과 폭을 줄였으며, 빈 상태는 떠다니는 그라디언트 아이콘 대신 더 작고 정적인 카드형 아이콘으로 단순화했습니다. 컴포저도 `800px` 축으로 넓히면서 라운드와 그림자를 조금 눌러, 화면 장식보다는 메시지/입력 흐름이 먼저 보이게 다듬은 단계입니다.
|
||||
- 검증: `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)
|
||||
@@ -767,6 +769,8 @@ ow + toggle 시각 언어로 통일했습니다.
|
||||
- 업데이트: 2026-04-05 13:29 (KST)
|
||||
- 업데이트: 2026-04-05 13:37 (KST)
|
||||
- 업데이트: 2026-04-05 13:44 (KST)
|
||||
- 업데이트: 2026-04-05 13:52 (KST)
|
||||
- 업데이트: 2026-04-05 14:00 (KST)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4528,3 +4528,9 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎.
|
||||
- 업데이트: 2026-04-05 13:44 (KST)
|
||||
- `RetryLastUserMessageFromConversation()`도 입력창 의존을 제거했습니다. 마지막 사용자 요청을 재시도할 때 더 이상 `InputBox.Text`를 바꾸지 않고, 유휴 상태면 `SendMessageAsync(lastUserMessage)`로 바로 실행하며, 이미 작업 중이면 `ChatSession.EnqueueDraft(..., \"now\", ..., \"direct\")`로 곧바로 대기열에 올립니다.
|
||||
- 이 조정으로 실패 후 재시도 역시 입력창 포커스/높이/슬래시 칩 상태와 분리되었고, Cowork/Code의 재시도 흐름이 세션/대기열 중심으로 더 정리됐습니다.
|
||||
- 업데이트: 2026-04-05 13:52 (KST)
|
||||
- 남아 있던 구형 본문 재시도 카드도 제거했습니다. [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `AddRetryButton()` 메서드와 그 호출 경로를 걷어내고, 예외 발생 시에는 토스트로만 짧게 안내한 뒤 작업 요약/실패 이력의 재시도 액션을 사용하게 했습니다.
|
||||
- 이 변경으로 본문 `MessagePanel`에 실패 카드가 임시로 직접 삽입되는 구형 흐름이 사라졌고, 오류 복구도 메시지 축보다는 작업 요약 액션 축으로 수렴하게 됐습니다.
|
||||
- 업데이트: 2026-04-05 14:00 (KST)
|
||||
- UI도 `claw-code` 레퍼런스 방향으로 1차 단순화를 반영했습니다. [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml) 에서 `MessagePanel` / `EmptyState`의 폭을 `880`으로 낮추고, 메시지 스크롤 여백을 줄여 메시지 축이 더 밀도 있게 보이도록 조정했습니다.
|
||||
- 빈 상태는 부유 애니메이션이 있는 그라디언트 아이콘을 제거하고, 작은 정적 카드형 아이콘 + 짧은 문구로 바꿨습니다. 상단 `AgentProgressBar`는 패딩과 프로그레스 바 높이를 줄였고, 컴포저는 `800px` 축으로 넓히면서 `DraftPreviewCard`, `InputGlowBorder`, `InputBorder`의 라운드/그림자 강도를 낮춰 장식량을 줄였습니다.
|
||||
|
||||
@@ -912,7 +912,7 @@
|
||||
<Border x:Name="AgentProgressBar" Grid.Row="2" Visibility="Collapsed"
|
||||
Background="{DynamicResource HintBackground}"
|
||||
BorderBrush="{DynamicResource SeparatorColor}" BorderThickness="0,0,0,1"
|
||||
Padding="16,6,16,6">
|
||||
Padding="14,4,14,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
@@ -931,10 +931,10 @@
|
||||
Text="" FontSize="12"
|
||||
Foreground="{DynamicResource PrimaryText}"
|
||||
VerticalAlignment="Center" TextTrimming="CharacterEllipsis"
|
||||
MaxWidth="300" Margin="0,0,12,0"/>
|
||||
MaxWidth="260" Margin="0,0,10,0"/>
|
||||
<!-- 프로그레스 바 -->
|
||||
<Border Grid.Column="2" CornerRadius="3" Background="{DynamicResource ItemHoverBackground}"
|
||||
Height="6" VerticalAlignment="Center" Margin="0,0,12,0">
|
||||
Height="5" VerticalAlignment="Center" Margin="0,0,10,0">
|
||||
<Border x:Name="ProgressFill" CornerRadius="3" HorizontalAlignment="Left"
|
||||
Width="0" Background="{DynamicResource AccentColor}"/>
|
||||
</Border>
|
||||
@@ -1172,10 +1172,10 @@
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
Background="{DynamicResource LauncherBackground}"
|
||||
Padding="24,20,24,10">
|
||||
Padding="24,14,24,8">
|
||||
<StackPanel x:Name="MessagePanel"
|
||||
Margin="0,4,0,28"
|
||||
MaxWidth="920"
|
||||
Margin="0,2,0,24"
|
||||
MaxWidth="880"
|
||||
HorizontalAlignment="Center">
|
||||
<StackPanel.RenderTransform>
|
||||
<TranslateTransform/>
|
||||
@@ -1187,7 +1187,7 @@
|
||||
<Grid x:Name="EmptyState" Grid.Row="3"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
MaxWidth="920"
|
||||
MaxWidth="880"
|
||||
Margin="24,8,24,8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
@@ -1198,47 +1198,25 @@
|
||||
<StackPanel Grid.Row="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Margin="0,22,0,4">
|
||||
<!-- 부유 AI 아이콘 -->
|
||||
<Border x:Name="EmptyIcon" CornerRadius="24" Width="72" Height="72"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,18">
|
||||
<Border.Background>
|
||||
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Color="#4B5EFC" Offset="0"/>
|
||||
<GradientStop Color="#8B6DFF" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<Border.RenderTransform>
|
||||
<TranslateTransform x:Name="EmptyIconTranslate"/>
|
||||
</Border.RenderTransform>
|
||||
<Border.Triggers>
|
||||
<EventTrigger RoutedEvent="Loaded">
|
||||
<BeginStoryboard>
|
||||
<Storyboard RepeatBehavior="Forever" AutoReverse="True">
|
||||
<DoubleAnimation Storyboard.TargetName="EmptyIconTranslate"
|
||||
Storyboard.TargetProperty="Y"
|
||||
From="0" To="-6" Duration="0:0:1.8">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<SineEase EasingMode="EaseInOut"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
</Border.Triggers>
|
||||
Margin="0,10,0,2">
|
||||
<Border x:Name="EmptyIcon" CornerRadius="18" Width="54" Height="54"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,14"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="1">
|
||||
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="30"
|
||||
Foreground="White"
|
||||
Foreground="{DynamicResource AccentColor}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
|
||||
<TextBlock x:Name="EmptyStateTitle" Text="작업 유형을 선택하세요" FontSize="22" FontWeight="SemiBold"
|
||||
<TextBlock x:Name="EmptyStateTitle" Text="작업을 시작하세요" FontSize="20" FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource PrimaryText}" HorizontalAlignment="Center"/>
|
||||
<TextBlock x:Name="EmptyStateDesc" Text="주제에 맞는 전문 프리셋이 자동 적용됩니다"
|
||||
FontSize="12.5" Foreground="{DynamicResource SecondaryText}"
|
||||
<TextBlock x:Name="EmptyStateDesc" Text="프롬프트를 입력하거나 아래 작업 유형을 선택하면 됩니다"
|
||||
FontSize="12" Foreground="{DynamicResource SecondaryText}"
|
||||
HorizontalAlignment="Center"
|
||||
TextAlignment="Center"
|
||||
Width="360"
|
||||
Margin="0,10,0,0"/>
|
||||
Width="340"
|
||||
Margin="0,8,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer x:Name="TopicPresetScrollViewer"
|
||||
@@ -1574,8 +1552,8 @@
|
||||
<!-- ── 입력 바 ── -->
|
||||
<Border x:Name="ComposerShell" Grid.Row="4"
|
||||
Margin="18,0,18,20"
|
||||
Width="760"
|
||||
MaxWidth="760"
|
||||
Width="800"
|
||||
MaxWidth="800"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom">
|
||||
<StackPanel HorizontalAlignment="Stretch">
|
||||
@@ -1584,9 +1562,9 @@
|
||||
Background="{DynamicResource LauncherBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="22"
|
||||
Padding="14,12,14,12"
|
||||
Margin="0,0,0,10">
|
||||
CornerRadius="16"
|
||||
Padding="12,10,12,10"
|
||||
Margin="0,0,0,8">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="14" ShadowDepth="0" Opacity="0.06"/>
|
||||
</Border.Effect>
|
||||
@@ -1641,7 +1619,7 @@
|
||||
<StackPanel x:Name="DraftQueuePanel"
|
||||
Visibility="Collapsed"
|
||||
Margin="0,0,0,10"/>
|
||||
<Border x:Name="InputGlowBorder" CornerRadius="18" Opacity="0"
|
||||
<Border x:Name="InputGlowBorder" CornerRadius="16" Opacity="0"
|
||||
Margin="-3" IsHitTestVisible="False">
|
||||
<Border.BorderBrush>
|
||||
<LinearGradientBrush x:Name="RainbowBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
@@ -1664,10 +1642,10 @@
|
||||
<!-- 실제 입력 영역 -->
|
||||
<Border x:Name="InputBorder"
|
||||
Background="{DynamicResource LauncherBackground}"
|
||||
CornerRadius="16" Padding="8"
|
||||
CornerRadius="14" Padding="8"
|
||||
BorderBrush="{DynamicResource BorderColor}" BorderThickness="1">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="28" ShadowDepth="0" Opacity="0.10"/>
|
||||
<DropShadowEffect BlurRadius="20" ShadowDepth="0" Opacity="0.08"/>
|
||||
</Border.Effect>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
|
||||
@@ -8461,7 +8461,7 @@ public partial class ChatWindow : Window
|
||||
{
|
||||
var errMsg = $"⚠ 오류: {ex.Message}";
|
||||
assistantContent = errMsg;
|
||||
AddRetryButton();
|
||||
ShowToast("실패한 요청은 작업 요약에서 다시 시도할 수 있습니다.", "\uE783", 2600);
|
||||
draftFailure = ex.Message;
|
||||
}
|
||||
finally
|
||||
@@ -11025,7 +11025,7 @@ public partial class ChatWindow : Window
|
||||
{
|
||||
var errMsg = $"⚠ 오류: {ex.Message}";
|
||||
assistantContent = errMsg;
|
||||
AddRetryButton();
|
||||
ShowToast("실패한 요청은 작업 요약에서 다시 시도할 수 있습니다.", "\uE783", 2600);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -11821,61 +11821,6 @@ public partial class ChatWindow : Window
|
||||
// 현재는 BringIntoView 기반이므로 별도 하이라이트 제거 불필요
|
||||
}
|
||||
|
||||
// ─── 에러 복구 재시도 버튼 ──────────────────────────────────────────────
|
||||
|
||||
private void AddRetryButton()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var retryBorder = new Border
|
||||
{
|
||||
Background = new SolidColorBrush(Color.FromArgb(0x18, 0xEF, 0x44, 0x44)),
|
||||
CornerRadius = new CornerRadius(8),
|
||||
Padding = new Thickness(12, 8, 12, 8),
|
||||
Margin = new Thickness(40, 4, 80, 4),
|
||||
HorizontalAlignment = HorizontalAlignment.Left,
|
||||
Cursor = System.Windows.Input.Cursors.Hand,
|
||||
};
|
||||
var retrySp = new StackPanel { Orientation = Orientation.Horizontal };
|
||||
retrySp.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "\uE72C", FontFamily = new FontFamily("Segoe MDL2 Assets"),
|
||||
FontSize = 12, Foreground = new SolidColorBrush(Color.FromRgb(0xEF, 0x44, 0x44)),
|
||||
VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 6, 0),
|
||||
});
|
||||
retrySp.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "재시도", FontSize = 12, FontWeight = FontWeights.SemiBold,
|
||||
Foreground = new SolidColorBrush(Color.FromRgb(0xEF, 0x44, 0x44)),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
});
|
||||
retryBorder.Child = retrySp;
|
||||
retryBorder.MouseEnter += (s, _) => { if (s is Border b) b.Background = new SolidColorBrush(Color.FromArgb(0x30, 0xEF, 0x44, 0x44)); };
|
||||
retryBorder.MouseLeave += (s, _) => { if (s is Border b) b.Background = new SolidColorBrush(Color.FromArgb(0x18, 0xEF, 0x44, 0x44)); };
|
||||
retryBorder.MouseLeftButtonUp += (_, _) =>
|
||||
{
|
||||
lock (_convLock)
|
||||
{
|
||||
var session = ChatSession;
|
||||
if (session != null)
|
||||
{
|
||||
session.RemoveLastAssistantMessage(_activeTab, _storage);
|
||||
_currentConversation = session.CurrentConversation;
|
||||
}
|
||||
else if (_currentConversation != null)
|
||||
{
|
||||
var lastIdx = _currentConversation.Messages.Count - 1;
|
||||
if (lastIdx >= 0 && _currentConversation.Messages[lastIdx].Role == "assistant")
|
||||
_currentConversation.Messages.RemoveAt(lastIdx);
|
||||
}
|
||||
}
|
||||
_ = RegenerateLastAsync();
|
||||
};
|
||||
MessagePanel.Children.Add(retryBorder);
|
||||
ForceScrollToEnd();
|
||||
});
|
||||
}
|
||||
|
||||
// ─── 메시지 우클릭 컨텍스트 메뉴 ───────────────────────────────────────
|
||||
|
||||
private void ShowMessageContextMenu(string content, string role)
|
||||
|
||||
Reference in New Issue
Block a user