AX Agent UI와 응답 마감 엔진을 claw-code 기준으로 1차 재구성
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
사이드바, 메시지 축, 빈 상태, 컴포저를 더 얇고 밀도 높은 구조로 재배치하고 보조 상태 스트립 노출을 줄였습니다. 반응형 폭 계산을 다시 조정해 창 크기 변화에서도 메시지와 컴포저가 같은 중심선으로 자연스럽게 줄어들게 했습니다. 응답 취소와 오류 마감은 AxAgentExecutionEngine의 FinalizeExecutionContent로 공통화해 전송과 재생성의 후처리 경로를 맞췄습니다. 검증: 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:
@@ -8460,16 +8460,17 @@ public partial class ChatWindow : Window
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
assistantContent = string.IsNullOrWhiteSpace(assistantContent) ? "(취소됨)" : assistantContent;
|
||||
draftCancelled = true;
|
||||
draftFailure = "사용자가 작업을 중단했습니다.";
|
||||
var finalized = _chatEngine.FinalizeExecutionContent(assistantContent, cancelled: true);
|
||||
assistantContent = finalized.Content;
|
||||
draftCancelled = finalized.Cancelled;
|
||||
draftFailure = finalized.FailureReason;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errMsg = $"⚠ 오류: {ex.Message}";
|
||||
assistantContent = errMsg;
|
||||
var finalized = _chatEngine.FinalizeExecutionContent(assistantContent, ex);
|
||||
assistantContent = finalized.Content;
|
||||
ShowToast("실패한 요청은 작업 요약에서 다시 시도할 수 있습니다.", "\uE783", 2600);
|
||||
draftFailure = ex.Message;
|
||||
draftFailure = finalized.FailureReason;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -8735,20 +8736,18 @@ public partial class ChatWindow : Window
|
||||
sb.AppendLine("You are AX Copilot Agent. You can read, write, and edit files using the provided tools.");
|
||||
sb.AppendLine($"Today's date: {DateTime.Now:yyyy년 M월 d일} ({DateTime.Now:yyyy-MM-dd}, {DateTime.Now:dddd}).");
|
||||
sb.AppendLine("Available skills: excel_create (.xlsx), docx_create (.docx), csv_create (.csv), markdown_create (.md), html_create (.html), script_create (.bat/.ps1), document_review (품질 검증), format_convert (포맷 변환).");
|
||||
sb.AppendLine("Only present a step-by-step execution plan when the user explicitly asks for a plan or when the session is already in plan mode.");
|
||||
sb.AppendLine("For ordinary Cowork requests, proceed directly with the work instead of stopping for plan approval.");
|
||||
sb.AppendLine("Only present a step-by-step plan when the user explicitly asks for a plan or when the task is too ambiguous to execute safely.");
|
||||
sb.AppendLine("For ordinary Cowork requests, proceed directly with the work and focus on producing the real artifact.");
|
||||
sb.AppendLine("After creating files, summarize what was created and include the actual output path.");
|
||||
sb.AppendLine("Do not stop after a single step. Continue autonomously until the request is completed or a concrete blocker (permission denial, missing dependency, hard error) is encountered.");
|
||||
sb.AppendLine("When adapting external references, rewrite names/structure/comments to AX Copilot style. Avoid clone-like outputs.");
|
||||
sb.AppendLine("IMPORTANT: When creating documents with dates, always use today's actual date above. Never use placeholder or fictional dates.");
|
||||
sb.AppendLine("IMPORTANT: When asked to create a document with multiple sections (reports, proposals, analyses, etc.), you MUST:");
|
||||
sb.AppendLine(" 1. First, plan the document: decide the exact sections (headings), their order, and key points for each section based on the topic.");
|
||||
sb.AppendLine(" 2. Call document_plan with sections_hint = your planned section titles (comma-separated). Example: sections_hint=\"회사 개요, 사업 현황, 재무 분석, SWOT, 전략 제언, 결론\"");
|
||||
sb.AppendLine(" This ensures the document structure matches YOUR plan, not a generic template.");
|
||||
sb.AppendLine(" 3. Then immediately call html_create (or docx_create/file_write) using the scaffold from document_plan.");
|
||||
sb.AppendLine(" 4. Write actual detailed content for EVERY section — no skipping, no placeholders, no minimal content.");
|
||||
sb.AppendLine(" 5. Do NOT call html_create directly without document_plan for multi-section documents.");
|
||||
sb.AppendLine(" 6. Do not finish with a plan only. The task is complete only after the document file has actually been created or updated.");
|
||||
sb.AppendLine("IMPORTANT: For reports, proposals, analyses, and manuals with multiple sections:");
|
||||
sb.AppendLine(" 1. Decide the document structure internally first.");
|
||||
sb.AppendLine(" 2. Use document_plan only when it improves the actual output, not as a mandatory user-facing approval step.");
|
||||
sb.AppendLine(" 3. Then immediately create the real output file with html_create, docx_create, markdown_create, or file_write.");
|
||||
sb.AppendLine(" 4. Fill every section with real content. Do not stop at an outline or plan only.");
|
||||
sb.AppendLine(" 5. The task is complete only after the actual document file has been created or updated.");
|
||||
|
||||
// 문서 품질 검증 루프
|
||||
sb.AppendLine("\n## Document Quality Review");
|
||||
@@ -8854,10 +8853,10 @@ public partial class ChatWindow : Window
|
||||
sb.AppendLine("3. ANALYZE: Use grep (with context_lines=2) + file_read to deeply understand the code you'll modify.");
|
||||
sb.AppendLine(" - Always check callers/references: grep for function/class names to find all usage points.");
|
||||
sb.AppendLine(" - Read test files related to the code you're changing to understand expected behavior.");
|
||||
sb.AppendLine("4. PLAN: Present your analysis + impact assessment. List ALL files that will be modified.");
|
||||
sb.AppendLine("4. PLAN: Build an internal execution outline and impact assessment before editing.");
|
||||
sb.AppendLine(" - Present the outline explicitly only when the user asks for a plan or the change is clearly high risk.");
|
||||
sb.AppendLine(" - Explain WHY each change is needed and what could break.");
|
||||
sb.AppendLine(" - If you touch shared services, interfaces, models, controllers, view-models, app startup, or dependency registration, treat it as a high-impact change.");
|
||||
sb.AppendLine(" - Wait for user approval before proceeding.");
|
||||
sb.AppendLine(" - If you touch shared services, interfaces, models, controllers, view-models, app startup, or dependency registration, treat it as a high-impact change and call out the impact clearly.");
|
||||
sb.AppendLine("5. IMPLEMENT: Apply changes using file_edit (preferred — shows diff). Use file_write only for new files.");
|
||||
sb.AppendLine(" - Make the MINIMUM changes needed. Don't refactor unrelated code.");
|
||||
sb.AppendLine(" - Prefer file_edit with replace_all=false for precision edits.");
|
||||
@@ -9258,7 +9257,18 @@ public partial class ChatWindow : Window
|
||||
|
||||
if (ConversationStatusStrip != null && ConversationStatusStripLabel != null)
|
||||
{
|
||||
if (string.Equals(status.StripKind, "permission_waiting", StringComparison.OrdinalIgnoreCase))
|
||||
var showCompactStrip = !string.Equals(_activeTab, "Chat", StringComparison.OrdinalIgnoreCase)
|
||||
&& (string.Equals(status.StripKind, "permission_waiting", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(status.StripKind, "failed_run", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(status.StripKind, "permission_denied", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(status.StripKind, "queue_blocked", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (!showCompactStrip)
|
||||
{
|
||||
ConversationStatusStrip.Visibility = Visibility.Collapsed;
|
||||
ConversationStatusStripLabel.Text = "";
|
||||
}
|
||||
else if (string.Equals(status.StripKind, "permission_waiting", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ConversationStatusStrip.Visibility = Visibility.Visible;
|
||||
ConversationStatusStrip.Background = BrushFromHex("#FFF7ED");
|
||||
@@ -9266,14 +9276,6 @@ public partial class ChatWindow : Window
|
||||
ConversationStatusStripLabel.Foreground = BrushFromHex("#C2410C");
|
||||
ConversationStatusStripLabel.Text = status.StripText;
|
||||
}
|
||||
else if (string.Equals(status.StripKind, "running", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ConversationStatusStrip.Visibility = Visibility.Visible;
|
||||
ConversationStatusStrip.Background = BrushFromHex("#DBEAFE");
|
||||
ConversationStatusStrip.BorderBrush = BrushFromHex("#93C5FD");
|
||||
ConversationStatusStripLabel.Foreground = BrushFromHex("#1D4ED8");
|
||||
ConversationStatusStripLabel.Text = status.StripText;
|
||||
}
|
||||
else if (string.Equals(status.StripKind, "failed_run", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(status.StripKind, "permission_denied", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -9299,14 +9301,6 @@ public partial class ChatWindow : Window
|
||||
ConversationStatusStripLabel.Foreground = BrushFromHex("#B45309");
|
||||
ConversationStatusStripLabel.Text = status.StripText;
|
||||
}
|
||||
else if (string.Equals(status.StripKind, "background", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ConversationStatusStrip.Visibility = Visibility.Visible;
|
||||
ConversationStatusStrip.Background = BrushFromHex("#EFF6FF");
|
||||
ConversationStatusStrip.BorderBrush = BrushFromHex("#BFDBFE");
|
||||
ConversationStatusStripLabel.Foreground = BrushFromHex("#1D4ED8");
|
||||
ConversationStatusStripLabel.Text = status.StripText;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConversationStatusStrip.Visibility = Visibility.Collapsed;
|
||||
@@ -9323,8 +9317,10 @@ public partial class ChatWindow : Window
|
||||
|| BtnQuickRunningFilter == null || BtnQuickHotSort == null)
|
||||
return;
|
||||
|
||||
var hasQuickSignal = _runningConversationCount > 0
|
||||
|| _spotlightConversationCount > 0;
|
||||
var allowQuickStrip = !string.Equals(_activeTab, "Chat", StringComparison.OrdinalIgnoreCase);
|
||||
var hasQuickSignal = allowQuickStrip
|
||||
&& (_runningConversationCount > 0
|
||||
|| _spotlightConversationCount > 0);
|
||||
|
||||
ConversationQuickStrip.Visibility = hasQuickSignal
|
||||
? Visibility.Visible
|
||||
@@ -10993,12 +10989,11 @@ public partial class ChatWindow : Window
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
assistantContent = string.IsNullOrWhiteSpace(assistantContent) ? "(취소됨)" : assistantContent;
|
||||
assistantContent = _chatEngine.FinalizeExecutionContent(assistantContent, cancelled: true).Content;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errMsg = $"⚠ 오류: {ex.Message}";
|
||||
assistantContent = errMsg;
|
||||
assistantContent = _chatEngine.FinalizeExecutionContent(assistantContent, ex).Content;
|
||||
ShowToast("실패한 요청은 작업 요약에서 다시 시도할 수 있습니다.", "\uE783", 2600);
|
||||
}
|
||||
finally
|
||||
@@ -11039,16 +11034,16 @@ public partial class ChatWindow : Window
|
||||
if (viewportWidth < 200)
|
||||
return false;
|
||||
|
||||
// claw-code처럼 창이 줄어들면 메시지 축과 컴포저가 함께 자연스럽게 줄어들도록,
|
||||
// 남는 본문 폭을 기준으로 상한만 두고 반응형 폭을 다시 계산합니다.
|
||||
var contentWidth = Math.Max(360, viewportWidth - 48);
|
||||
var messageWidth = Math.Clamp(contentWidth * 0.9, 360, 920);
|
||||
var composerWidth = Math.Clamp(contentWidth * 0.82, 360, 820);
|
||||
// claw-code처럼 메시지 축과 입력축이 같은 중심선을 공유하도록,
|
||||
// 본문 폭 상한을 조금 더 낮추고 창 폭 변화에 더 부드럽게 반응시킵니다.
|
||||
var contentWidth = Math.Max(340, viewportWidth - 32);
|
||||
var messageWidth = Math.Clamp(contentWidth * 0.86, 340, 840);
|
||||
var composerWidth = Math.Clamp(contentWidth * 0.78, 340, 760);
|
||||
|
||||
if (contentWidth < 760)
|
||||
{
|
||||
messageWidth = Math.Clamp(contentWidth - 8, 340, 820);
|
||||
composerWidth = Math.Clamp(contentWidth - 28, 332, 760);
|
||||
messageWidth = Math.Clamp(contentWidth - 10, 332, 760);
|
||||
composerWidth = Math.Clamp(contentWidth - 20, 328, 700);
|
||||
}
|
||||
|
||||
var changed = false;
|
||||
|
||||
Reference in New Issue
Block a user