- Cowork/Code 실행 시작 직후 라이브 진행 힌트를 즉시 표시하고 중간 이벤트마다 사라지지 않도록 유지 로직 수정 - 프리셋 선택 화면, 권한 요청 팝업, 실행 전환 게이트 안내 문자열의 깨진 한글을 정상 한국어로 복구 - 내부 중단 경로의 완료 문구를 사용자 취소로 오해하지 않도록 중립 표현으로 정리 - 검증: 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:
10
README.md
10
README.md
@@ -7,6 +7,11 @@ Windows 전용 시맨틱 런처 & 워크스페이스 매니저
|
|||||||
개발 참고: Claw Code 동등성 작업 추적 문서
|
개발 참고: Claw Code 동등성 작업 추적 문서
|
||||||
`docs/claw-code-parity-plan.md`
|
`docs/claw-code-parity-plan.md`
|
||||||
|
|
||||||
|
- 업데이트: 2026-04-07 02:03 (KST)
|
||||||
|
- Cowork 진행 표시가 오래 비거나 완료 후 실패처럼 깜박이던 흐름을 정리했습니다. 진행 힌트는 작업 시작 직후부터 즉시 보이게 하고, 중간 이벤트가 들어와도 불필요하게 사라지지 않도록 유지 로직을 조정했습니다.
|
||||||
|
- 프리셋/입력창/진행 카드에 남아 있던 깨진 한글을 복구했고, 내부 실행 게이트 문구도 정상 한국어로 정리해 Cowork 루프가 잘못된 안내 문구에 끌리지 않도록 보강했습니다.
|
||||||
|
- 중단 문구는 더 이상 무조건 사용자 취소처럼 보이지 않도록 `작업이 중단되었습니다` 기준으로 통일했습니다.
|
||||||
|
|
||||||
- 업데이트: 2026-04-06 20:05 (KST)
|
- 업데이트: 2026-04-06 20:05 (KST)
|
||||||
- AX Agent 입력 영역의 토큰 사용량 원형 카드와 전송 버튼 테두리를 더 깔끔하게 정리했습니다. 토큰 카드는 내부 원 두께와 여백을 줄여 덜 답답하게 보이게 했고, 전송 버튼은 불필요한 외곽 테두리를 제거해 더 매끈한 원형 버튼처럼 보이도록 조정했습니다.
|
- AX Agent 입력 영역의 토큰 사용량 원형 카드와 전송 버튼 테두리를 더 깔끔하게 정리했습니다. 토큰 카드는 내부 원 두께와 여백을 줄여 덜 답답하게 보이게 했고, 전송 버튼은 불필요한 외곽 테두리를 제거해 더 매끈한 원형 버튼처럼 보이도록 조정했습니다.
|
||||||
|
|
||||||
@@ -1428,3 +1433,8 @@ MIT License
|
|||||||
- 메모리 include 감사는 `최근 3일` 기준으로 다시 집계해 보여주도록 정리했고, `/memory list`·`/memory search` 결과도 우선순위·레이어·설명·paths·tags를 두 줄 구조로 더 읽기 쉽게 정리했습니다.
|
- 메모리 include 감사는 `최근 3일` 기준으로 다시 집계해 보여주도록 정리했고, `/memory list`·`/memory search` 결과도 우선순위·레이어·설명·paths·tags를 두 줄 구조로 더 읽기 쉽게 정리했습니다.
|
||||||
- 업데이트: 2026-04-07 01:44 (KST)
|
- 업데이트: 2026-04-07 01:44 (KST)
|
||||||
- AX Agent footer/preset 안내에 남아 있던 한글 깨짐 문자열을 복구했습니다. Cowork/Code 입력창 워터마크, 선택된 프리셋 설명, 메모리 상태 팝업 문구가 정상 한글로 다시 표시됩니다.
|
- AX Agent footer/preset 안내에 남아 있던 한글 깨짐 문자열을 복구했습니다. Cowork/Code 입력창 워터마크, 선택된 프리셋 설명, 메모리 상태 팝업 문구가 정상 한글로 다시 표시됩니다.
|
||||||
|
- 업데이트: 2026-04-07 02:08 (KST)
|
||||||
|
- Cowork/Code 진행 표시가 오래 걸릴 때도 비어 보이지 않도록 live progress fallback을 보강했습니다. 이벤트가 계속 들어오는 경우에도 일정 시간이 지나면 `작업을 진행하는 중입니다...` 줄이 transcript에 표시됩니다.
|
||||||
|
- 진행 줄 재렌더 시 과한 fade 애니메이션을 제거해 깜박이듯 보이던 문제를 줄였고, 장시간 실행 뒤 내부 중단이 발생해도 더 이상 무조건 `사용자가 작업을 취소했습니다`로 표기하지 않도록 중립 문구로 정리했습니다.
|
||||||
|
- 깨진 한글이 남아 있던 [ChatWindow.FooterPresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs), [ChatWindow.TimelinePresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.TimelinePresentation.cs), [ChatWindow.AgentEventRendering.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs)의 표시 문자열을 다시 복구했습니다.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
# AX Copilot - 媛쒕컻 臾몄꽌
|
- Document update: 2026-04-07 02:03 (KST) - Fixed broken Korean strings in Cowork preset selection, composer guidance, and live progress/process-feed rendering. Rewrote ChatWindow.TopicPresetPresentation, normalized live progress copy, and cleaned up loop gate guidance strings that had become mojibake.
|
||||||
|
- Document update: 2026-04-07 02:03 (KST) - Adjusted AX Agent progress visibility so Cowork/Code now shows an immediate live hint when a run starts and no longer clears that hint on every intermediate agent event. Neutralized cancellation wording to 작업이 중단되었습니다 for non-user interruption paths.
|
||||||
|
|
||||||
|
# AX Copilot - 媛쒕컻 臾몄꽌
|
||||||
|
|
||||||
- Document update: 2026-04-06 20:05 (KST) - Refined the AX Agent composer token indicator and send button surface. The context-usage circle now uses a roomier 32px shell with thinner ring strokes and a smaller threshold marker for a cleaner outline, while the send button now drops its redundant outer border and uses a more precisely centered arrow glyph.
|
- Document update: 2026-04-06 20:05 (KST) - Refined the AX Agent composer token indicator and send button surface. The context-usage circle now uses a roomier 32px shell with thinner ring strokes and a smaller threshold marker for a cleaner outline, while the send button now drops its redundant outer border and uses a more precisely centered arrow glyph.
|
||||||
- Document update: 2026-04-06 19:56 (KST) - Fine-tuned the AX Agent top tab vertical centering. The shared TopTabBtn style now uses explicit centered content alignment plus slightly reduced wrapper/button padding and height so 채팅 / Cowork / 코드 sit more evenly within the segmented control.
|
- Document update: 2026-04-06 19:56 (KST) - Fine-tuned the AX Agent top tab vertical centering. The shared TopTabBtn style now uses explicit centered content alignment plus slightly reduced wrapper/button padding and height so 채팅 / Cowork / 코드 sit more evenly within the segmented control.
|
||||||
@@ -5263,3 +5266,18 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎.
|
|||||||
- [ChatWindow.FooterPresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs)
|
- [ChatWindow.FooterPresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs)
|
||||||
- Cowork/Code 입력창 워터마크, 선택된 프리셋 안내, 메모리 상태 팝업 문구에 섞여 들어간 깨진 한글 리터럴을 정상 문자열로 복구했다.
|
- Cowork/Code 입력창 워터마크, 선택된 프리셋 안내, 메모리 상태 팝업 문구에 섞여 들어간 깨진 한글 리터럴을 정상 문자열로 복구했다.
|
||||||
- `메모리 규칙 n개 · 학습 n개 적용 중` 근거 표시와 메모리 팝업 상세 문구도 읽기 쉬운 한글 기준으로 다시 정리했다.
|
- `메모리 규칙 n개 · 학습 n개 적용 중` 근거 표시와 메모리 팝업 상세 문구도 읽기 쉬운 한글 기준으로 다시 정리했다.
|
||||||
|
|
||||||
|
## 2026-04-07 02:08 (KST)
|
||||||
|
|
||||||
|
- [ChatWindow.FooterPresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs)
|
||||||
|
- Cowork/Code 워터마크, 선택된 프리셋 안내, 메모리 상태 팝업 관련 문자열을 다시 한 번 전면 교체해 남아 있던 한글 깨짐을 제거했다.
|
||||||
|
- [ChatWindow.TimelinePresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.TimelinePresentation.cs)
|
||||||
|
- 이전 대화 load more 카드와 압축 메타 카드의 깨진 표시 문자열을 정상 한국어로 복구했다.
|
||||||
|
- [ChatWindow.AgentEventRendering.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.AgentEventRendering.cs)
|
||||||
|
- `처리 중...`, `컨텍스트 압축 중...`, `단계 진행/완료`, `스킬 실행` 등 중간 진행 메시지 요약을 정상 한국어로 다시 맞췄다.
|
||||||
|
- live progress 줄에 들어가던 fade 애니메이션을 제거해 재렌더 시 깜박이던 문제를 줄였다.
|
||||||
|
- [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)
|
||||||
|
- 이벤트가 자주 들어와 idle 시간이 짧아도 일정 경과 시간 이후에는 `작업을 진행하는 중입니다...` 라이브 진행 줄이 뜨도록 fallback을 추가했다.
|
||||||
|
- [AgentLoopService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/AgentLoopService.cs)
|
||||||
|
- 내부 중단/취소가 발생했을 때 사용자 취소로 단정하는 문구를 중립적으로 조정해 오탐성 `사용자가 작업을 취소했습니다` 표시를 줄였다.
|
||||||
|
|
||||||
|
|||||||
@@ -338,8 +338,8 @@ public partial class AgentLoopService
|
|||||||
|
|
||||||
if (decision == "취소")
|
if (decision == "취소")
|
||||||
{
|
{
|
||||||
EmitEvent(AgentEventType.Complete, "", "사용자가 작업을 취소했습니다");
|
EmitEvent(AgentEventType.Complete, "", "작업이 중단되었습니다");
|
||||||
return "작업이 취소되었습니다.";
|
return "작업이 중단되었습니다.";
|
||||||
}
|
}
|
||||||
else if (TryParseApprovedPlanDecision(decision, out var approvedPlanText, out var approvedPlanSteps))
|
else if (TryParseApprovedPlanDecision(decision, out var approvedPlanText, out var approvedPlanSteps))
|
||||||
{
|
{
|
||||||
@@ -378,8 +378,8 @@ public partial class AgentLoopService
|
|||||||
|
|
||||||
if (decision == "취소")
|
if (decision == "취소")
|
||||||
{
|
{
|
||||||
EmitEvent(AgentEventType.Complete, "", "사용자가 작업을 취소했습니다");
|
EmitEvent(AgentEventType.Complete, "", "작업이 중단되었습니다");
|
||||||
return "작업이 취소되었습니다.";
|
return "작업이 중단되었습니다.";
|
||||||
}
|
}
|
||||||
if (TryParseApprovedPlanDecision(decision, out var revisedPlanText, out var revisedPlanSteps))
|
if (TryParseApprovedPlanDecision(decision, out var revisedPlanText, out var revisedPlanSteps))
|
||||||
{
|
{
|
||||||
@@ -659,8 +659,8 @@ public partial class AgentLoopService
|
|||||||
|
|
||||||
if (decision == "취소")
|
if (decision == "취소")
|
||||||
{
|
{
|
||||||
EmitEvent(AgentEventType.Complete, "", "사용자가 작업을 취소했습니다");
|
EmitEvent(AgentEventType.Complete, "", "작업이 중단되었습니다");
|
||||||
return "작업이 취소되었습니다.";
|
return "작업이 중단되었습니다.";
|
||||||
}
|
}
|
||||||
else if (TryParseApprovedPlanDecision(decision, out var approvedPlanText, out var approvedPlanSteps))
|
else if (TryParseApprovedPlanDecision(decision, out var approvedPlanText, out var approvedPlanSteps))
|
||||||
{
|
{
|
||||||
@@ -1216,15 +1216,15 @@ public partial class AgentLoopService
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
EmitEvent(AgentEventType.StopRequested, "", "사용자가 작업 중단을 요청했습니다");
|
EmitEvent(AgentEventType.StopRequested, "", "작업 중단이 요청되었습니다");
|
||||||
await RunRuntimeHooksAsync(
|
await RunRuntimeHooksAsync(
|
||||||
"__stop_requested__",
|
"__stop_requested__",
|
||||||
"post",
|
"post",
|
||||||
JsonSerializer.Serialize(new { runId = _currentRunId, tool = effectiveCall.ToolName }),
|
JsonSerializer.Serialize(new { runId = _currentRunId, tool = effectiveCall.ToolName }),
|
||||||
"cancelled",
|
"cancelled",
|
||||||
success: false);
|
success: false);
|
||||||
EmitEvent(AgentEventType.Complete, "", "사용자가 작업을 취소했습니다.");
|
EmitEvent(AgentEventType.Complete, "", "작업이 중단되었습니다.");
|
||||||
return "사용자가 작업을 취소했습니다.";
|
return "작업이 중단되었습니다.";
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1445,7 +1445,7 @@ public partial class AgentLoopService
|
|||||||
|
|
||||||
if (ct.IsCancellationRequested)
|
if (ct.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
EmitEvent(AgentEventType.StopRequested, "", "사용자가 작업 중단을 요청했습니다");
|
EmitEvent(AgentEventType.StopRequested, "", "작업 중단이 요청되었습니다");
|
||||||
await RunRuntimeHooksAsync(
|
await RunRuntimeHooksAsync(
|
||||||
"__stop_requested__",
|
"__stop_requested__",
|
||||||
"post",
|
"post",
|
||||||
@@ -4833,3 +4833,4 @@ public partial class AgentLoopService
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,11 +142,11 @@ public partial class AgentLoopService
|
|||||||
messages.Add(new ChatMessage
|
messages.Add(new ChatMessage
|
||||||
{
|
{
|
||||||
Role = "user",
|
Role = "user",
|
||||||
Content = "[System:CodeDiffGate] 肄붾뱶 蹂寃??댄썑 diff 洹쇨굅媛 遺議깊빀?덈떎. " +
|
Content = "[System:CodeDiffGate] 코드 변경 이후 diff 근거가 부족합니다. " +
|
||||||
"git_tool ?꾧뎄濡?蹂寃??뚯씪怨??듭떖 diff瑜?癒쇱? ?뺤씤?섍퀬 ?붿빟?섏꽭?? " +
|
"git_tool 도구로 변경 파일과 핵심 diff를 먼저 확인하고 요약하세요. " +
|
||||||
"吏湲?利됱떆 git_tool ?꾧뎄瑜??몄텧?섏꽭??"
|
"지금 즉시 git_tool 도구를 호출하세요."
|
||||||
});
|
});
|
||||||
EmitEvent(AgentEventType.Thinking, "", "肄붾뱶 diff 洹쇨굅媛 遺議깊빐 git diff 寃利앹쓣 異붽??⑸땲??..");
|
EmitEvent(AgentEventType.Thinking, "", "코드 diff 근거가 부족해 git diff 검증을 추가합니다...");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ public partial class AgentLoopService
|
|||||||
Role = "user",
|
Role = "user",
|
||||||
Content = BuildRecentExecutionEvidencePrompt(taskPolicy)
|
Content = BuildRecentExecutionEvidencePrompt(taskPolicy)
|
||||||
});
|
});
|
||||||
EmitEvent(AgentEventType.Thinking, "", "理쒓렐 ?섏젙 ?댄썑 ?ㅽ뻾 洹쇨굅媛 遺議깊빐 build/test ?ш?利앹쓣 ?섑뻾?⑸땲??..");
|
EmitEvent(AgentEventType.Thinking, "", "최근 수정 이후 실행 근거가 부족해 build/test 재검증을 수행합니다...");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ public partial class AgentLoopService
|
|||||||
Role = "user",
|
Role = "user",
|
||||||
Content = BuildExecutionSuccessGatePrompt(taskPolicy)
|
Content = BuildExecutionSuccessGatePrompt(taskPolicy)
|
||||||
});
|
});
|
||||||
EmitEvent(AgentEventType.Thinking, "", "?ㅽ뙣???ㅽ뻾 洹쇨굅留??덉뼱 build/test瑜??ㅼ떆 ?깃났?쒖폒 寃利앺빀?덈떎...");
|
EmitEvent(AgentEventType.Thinking, "", "실패한 실행 근거만 있어 build/test 성공 결과를 다시 검증합니다...");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ public partial class AgentLoopService
|
|||||||
EmitEvent(
|
EmitEvent(
|
||||||
AgentEventType.Thinking,
|
AgentEventType.Thinking,
|
||||||
"",
|
"",
|
||||||
$"醫낅즺 ???ㅽ뻾 利앷굅媛 遺議깊빐 蹂닿컯 ?④퀎瑜?吏꾪뻾?⑸땲??({runState.TerminalEvidenceGateRetry}/{retryMax})");
|
$"종료 전 실행 증거가 부족해 보강 단계를 진행합니다 ({runState.TerminalEvidenceGateRetry}/{retryMax})");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,27 +305,27 @@ public partial class AgentLoopService
|
|||||||
{
|
{
|
||||||
if (string.Equals(taskPolicy.TaskType, "docs", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(taskPolicy.TaskType, "docs", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var fileHint = string.IsNullOrWhiteSpace(lastArtifactFilePath) ? "寃곌낵 臾몄꽌 ?뚯씪" : $"'{lastArtifactFilePath}'";
|
var fileHint = string.IsNullOrWhiteSpace(lastArtifactFilePath) ? "결과 문서 파일" : $"'{lastArtifactFilePath}'";
|
||||||
return "[System:TerminalEvidenceGate] ?꾩옱 醫낅즺 ?묐떟?먮뒗 ?ㅽ뻾 寃곌낵 利앷굅媛 遺議깊빀?덈떎. " +
|
return "[System:TerminalEvidenceGate] 현재 종료 응답에는 실행 결과 증거가 부족합니다. " +
|
||||||
$"{fileHint}???ㅼ젣濡??앹꽦/媛깆떊?섍퀬 file_read ?먮뒗 document_read濡?寃利앺븳 洹쇨굅瑜??④릿 ??醫낅즺?섏꽭??";
|
$"{fileHint}을 실제로 생성 또는 갱신하고 file_read 또는 document_read로 검증한 근거를 남긴 뒤 종료하세요.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "[System:TerminalEvidenceGate] ?꾩옱 醫낅즺 ?묐떟?먮뒗 ?ㅽ뻾 寃곌낵 利앷굅媛 遺議깊빀?덈떎. " +
|
return "[System:TerminalEvidenceGate] 현재 종료 응답에는 실행 결과 증거가 부족합니다. " +
|
||||||
"理쒖냼 1媛??댁긽??吏꾪뻾 ?꾧뎄(?섏젙/?ㅽ뻾/?앹꽦)瑜??깃났?쒗궎怨? 洹?寃곌낵瑜?洹쇨굅濡?理쒖쥌 ?묐떟???ㅼ떆 ?묒꽦?섏꽭??";
|
"최소 1개 이상의 진행 도구(수정/실행/생성)를 성공시키고 그 결과를 근거로 최종 응답을 다시 작성하세요.";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildRecentExecutionEvidencePrompt(TaskTypePolicy taskPolicy)
|
private static string BuildRecentExecutionEvidencePrompt(TaskTypePolicy taskPolicy)
|
||||||
{
|
{
|
||||||
var taskHint = taskPolicy.TaskType switch
|
var taskHint = taskPolicy.TaskType switch
|
||||||
{
|
{
|
||||||
"bugfix" => "?ы쁽 寃쎈줈 湲곗??쇰줈 ?섏젙 吏?먯씠 ?ㅼ젣濡??닿껐?먮뒗吏 寃利앺븯?몄슂.",
|
"bugfix" => "재현 경로 기준으로 수정 지점이 실제로 해결됐는지 검증하세요.",
|
||||||
"feature" => "?좉퇋 ?숈옉 寃쎈줈???뺤긽/?ㅻ쪟 耳?댁뒪瑜?理쒖냼 1媛??댁긽 ?뺤씤?섏꽭??",
|
"feature" => "추가 동작 경로와 정상/오류 케이스를 최소 1개 이상 확인하세요.",
|
||||||
"refactor" => "湲곗〈 ?숈옉 蹂댁〈 ?щ?瑜??뚭? 愿?먯쑝濡??뺤씤?섏꽭??",
|
"refactor" => "기존 동작 보존 여부를 핵심 관점으로 확인하세요.",
|
||||||
_ => "?섏젙 ?곹뼢 踰붿쐞瑜?湲곗??쇰줈 ?ㅽ뻾 寃利앹쓣 吏꾪뻾?섏꽭??"
|
_ => "수정 영향 범위를 기준으로 실행 검증을 진행하세요."
|
||||||
};
|
};
|
||||||
|
|
||||||
return "[System:RecentExecutionGate] 留덉?留?肄붾뱶 ?섏젙 ?댄썑 build/test ?ㅽ뻾 洹쇨굅媛 ?놁뒿?덈떎. " +
|
return "[System:RecentExecutionGate] 마지막 코드 수정 이후 build/test 실행 근거가 없습니다. " +
|
||||||
"吏湲?利됱떆 build_run ?먮뒗 test_loop瑜??몄텧??理쒖떊 ?곹깭瑜?寃利앺븯怨?寃곌낵瑜??④린?몄슂. " +
|
"지금 즉시 build_run 또는 test_loop를 호출해 최신 상태를 검증하고 결과를 남기세요. " +
|
||||||
taskHint;
|
taskHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,14 +333,14 @@ public partial class AgentLoopService
|
|||||||
{
|
{
|
||||||
var taskHint = taskPolicy.TaskType switch
|
var taskHint = taskPolicy.TaskType switch
|
||||||
{
|
{
|
||||||
"bugfix" => "?ㅽ뙣 ?먯씤??癒쇱? ?섏젙?????숈씪 ?ы쁽 寃쎈줈 湲곗??쇰줈 ?뚯뒪?몃? ?ㅼ떆 ?듦낵?쒗궎?몄슂.",
|
"bugfix" => "실패 원인을 먼저 수정하고 동일 재현 경로 기준으로 테스트를 다시 통과시키세요.",
|
||||||
"feature" => "?듭떖 ?좉퇋 ?숈옉 寃쎈줈瑜??ы븿??build/test瑜??듦낵?쒗궎?몄슂.",
|
"feature" => "추가된 신규 동작 경로를 포함해 build/test를 통과시키세요.",
|
||||||
"refactor" => "?뚭? ?щ?瑜??뺤씤?????덈뒗 ?뚯뒪?몃? ?듦낵?쒗궎?몄슂.",
|
"refactor" => "동작 보존 여부를 확인할 수 있는 테스트를 통과시키세요.",
|
||||||
_ => "?섏젙 ?곹뼢 踰붿쐞瑜??뺤씤?????덈뒗 ?ㅽ뻾 寃利앹쓣 ?듦낵?쒗궎?몄슂."
|
_ => "수정 영향 범위를 확인할 수 있는 실행 검증을 통과시키세요."
|
||||||
};
|
};
|
||||||
|
|
||||||
return "[System:ExecutionSuccessGate] ?꾩옱 ?ㅽ뻾 洹쇨굅媛 ?ㅽ뙣 寃곌낵肉먯엯?덈떎. " +
|
return "[System:ExecutionSuccessGate] 현재 실행 근거가 실패 결과뿐입니다. " +
|
||||||
"醫낅즺?섏? 留먭퀬 build_run ?먮뒗 test_loop瑜??몄텧???깃났 寃곌낵瑜??뺣낫?섏꽭?? " +
|
"종료하지 말고 build_run 또는 test_loop를 호출해 성공 결과를 확보하세요. " +
|
||||||
taskHint;
|
taskHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@@ -172,8 +172,6 @@ public partial class ChatWindow
|
|||||||
processMeta,
|
processMeta,
|
||||||
liveWaitingStyle,
|
liveWaitingStyle,
|
||||||
out var pulseMarker);
|
out var pulseMarker);
|
||||||
summaryRow.Opacity = 0;
|
|
||||||
summaryRow.BeginAnimation(UIElement.OpacityProperty, new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(140)));
|
|
||||||
if (liveWaitingStyle)
|
if (liveWaitingStyle)
|
||||||
ApplyLiveWaitingPulseToMarker(pulseMarker);
|
ApplyLiveWaitingPulseToMarker(pulseMarker);
|
||||||
stack.Children.Add(summaryRow);
|
stack.Children.Add(summaryRow);
|
||||||
@@ -183,8 +181,6 @@ public partial class ChatWindow
|
|||||||
&& !string.Equals(body, summary, StringComparison.OrdinalIgnoreCase))
|
&& !string.Equals(body, summary, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var bodyBlock = CreateProcessFeedBody(body, primaryText);
|
var bodyBlock = CreateProcessFeedBody(body, primaryText);
|
||||||
bodyBlock.Opacity = 0;
|
|
||||||
bodyBlock.BeginAnimation(UIElement.OpacityProperty, new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(180)));
|
|
||||||
stack.Children.Add(bodyBlock);
|
stack.Children.Add(bodyBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1230,10 +1226,6 @@ public partial class ChatWindow
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
banner.Opacity = 0;
|
|
||||||
banner.BeginAnimation(UIElement.OpacityProperty,
|
|
||||||
new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(200)));
|
|
||||||
|
|
||||||
MessagePanel.Children.Add(banner);
|
MessagePanel.Children.Add(banner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
@@ -12,7 +12,7 @@ namespace AxCopilot.Views;
|
|||||||
|
|
||||||
public partial class ChatWindow
|
public partial class ChatWindow
|
||||||
{
|
{
|
||||||
/// <summary>프리셋에서 대화 주제 버튼을 동적으로 생성합니다.</summary>
|
/// <summary>프리셋 대화 주제 버튼을 동적으로 생성합니다.</summary>
|
||||||
private void BuildTopicButtons()
|
private void BuildTopicButtons()
|
||||||
{
|
{
|
||||||
TopicButtonPanel.Children.Clear();
|
TopicButtonPanel.Children.Clear();
|
||||||
@@ -22,17 +22,19 @@ public partial class ChatWindow
|
|||||||
|
|
||||||
if (_activeTab == "Cowork" || _activeTab == "Code")
|
if (_activeTab == "Cowork" || _activeTab == "Code")
|
||||||
{
|
{
|
||||||
if (EmptyStateTitle != null) EmptyStateTitle.Text = _activeTab == "Code"
|
if (EmptyStateTitle != null)
|
||||||
? "코드 작업을 입력하세요"
|
EmptyStateTitle.Text = _activeTab == "Code" ? "코드 작업을 입력하세요" : "작업 유형을 선택하세요";
|
||||||
: "작업 유형을 선택하세요";
|
if (EmptyStateDesc != null)
|
||||||
if (EmptyStateDesc != null) EmptyStateDesc.Text = _activeTab == "Code"
|
EmptyStateDesc.Text = _activeTab == "Code"
|
||||||
? "코딩 에이전트가 코드 분석, 수정, 빌드, 테스트를 수행합니다"
|
? "코딩 에이전트가 코드 분석, 수정, 빌드, 테스트를 수행합니다"
|
||||||
: "에이전트가 상세한 데이터를 작성합니다";
|
: "에이전트가 상세한 데이터를 작성합니다";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (EmptyStateTitle != null) EmptyStateTitle.Text = "대화 주제를 선택하세요";
|
if (EmptyStateTitle != null)
|
||||||
if (EmptyStateDesc != null) EmptyStateDesc.Text = "주제에 맞는 전문 프리셋이 자동 적용됩니다";
|
EmptyStateTitle.Text = "대화 주제를 선택하세요";
|
||||||
|
if (EmptyStateDesc != null)
|
||||||
|
EmptyStateDesc.Text = "주제에 맞는 전문 프리셋이 자동 적용됩니다";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_activeTab == "Code")
|
if (_activeTab == "Code")
|
||||||
@@ -129,9 +131,10 @@ public partial class ChatWindow
|
|||||||
MaxWidth = 112,
|
MaxWidth = 112,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
contentGrid.Children.Add(stack);
|
||||||
|
|
||||||
if (capturedPreset.IsCustom)
|
if (capturedPreset.IsCustom)
|
||||||
{
|
{
|
||||||
contentGrid.Children.Add(stack);
|
|
||||||
var badge = new Border
|
var badge = new Border
|
||||||
{
|
{
|
||||||
Width = 16,
|
Width = 16,
|
||||||
@@ -153,10 +156,6 @@ public partial class ChatWindow
|
|||||||
};
|
};
|
||||||
contentGrid.Children.Add(badge);
|
contentGrid.Children.Add(badge);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
contentGrid.Children.Add(stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
border.Child = contentGrid;
|
border.Child = contentGrid;
|
||||||
AttachTopicCardHover(border, cardBackground, cardHoverBackground);
|
AttachTopicCardHover(border, cardBackground, cardHoverBackground);
|
||||||
@@ -215,7 +214,6 @@ public partial class ChatWindow
|
|||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
};
|
};
|
||||||
etcStack.Children.Add(etcIconCircle);
|
etcStack.Children.Add(etcIconCircle);
|
||||||
|
|
||||||
etcStack.Children.Add(new TextBlock
|
etcStack.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = "기타",
|
Text = "기타",
|
||||||
@@ -361,7 +359,6 @@ public partial class ChatWindow
|
|||||||
|
|
||||||
var menuBackground = TryFindResource("LauncherBackground") as Brush ?? Brushes.Black;
|
var menuBackground = TryFindResource("LauncherBackground") as Brush ?? Brushes.Black;
|
||||||
var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
|
||||||
var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
|
|
||||||
var borderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.Gray;
|
var borderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.Gray;
|
||||||
|
|
||||||
var menuBorder = new Border
|
var menuBorder = new Border
|
||||||
@@ -515,7 +512,7 @@ public partial class ChatWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasMessages || hasInput)
|
if (hasMessages || hasInput)
|
||||||
ShowToast($"프리셋 변경: {preset.Label}");
|
ShowToast($"프리셋 변경 · {preset.Label}");
|
||||||
|
|
||||||
if (_activeTab == "Cowork")
|
if (_activeTab == "Cowork")
|
||||||
BuildBottomBar();
|
BuildBottomBar();
|
||||||
|
|||||||
@@ -6270,7 +6270,16 @@ public partial class ChatWindow : Window
|
|||||||
private void StartLiveAgentProgressHints()
|
private void StartLiveAgentProgressHints()
|
||||||
{
|
{
|
||||||
_lastAgentProgressEventAt = DateTime.UtcNow;
|
_lastAgentProgressEventAt = DateTime.UtcNow;
|
||||||
|
var runTab = string.IsNullOrWhiteSpace(_streamRunTab) ? _activeTab : _streamRunTab!;
|
||||||
|
if (string.Equals(runTab, "Cowork", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| string.Equals(runTab, "Code", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
UpdateLiveAgentProgressHint("작업을 준비하는 중입니다...", "agent_wait");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
UpdateLiveAgentProgressHint(null);
|
UpdateLiveAgentProgressHint(null);
|
||||||
|
}
|
||||||
_agentProgressHintTimer.Stop();
|
_agentProgressHintTimer.Stop();
|
||||||
_agentProgressHintTimer.Start();
|
_agentProgressHintTimer.Start();
|
||||||
}
|
}
|
||||||
@@ -6284,7 +6293,6 @@ public partial class ChatWindow : Window
|
|||||||
private void TouchLiveAgentProgressHints()
|
private void TouchLiveAgentProgressHints()
|
||||||
{
|
{
|
||||||
_lastAgentProgressEventAt = DateTime.UtcNow;
|
_lastAgentProgressEventAt = DateTime.UtcNow;
|
||||||
UpdateLiveAgentProgressHint(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AgentProgressHintTimer_Tick(object? sender, EventArgs e)
|
private void AgentProgressHintTimer_Tick(object? sender, EventArgs e)
|
||||||
@@ -6304,6 +6312,7 @@ public partial class ChatWindow : Window
|
|||||||
}
|
}
|
||||||
|
|
||||||
var idle = DateTime.UtcNow - _lastAgentProgressEventAt;
|
var idle = DateTime.UtcNow - _lastAgentProgressEventAt;
|
||||||
|
var elapsed = DateTime.UtcNow - _streamStartTime.ToUniversalTime();
|
||||||
string? summary = null;
|
string? summary = null;
|
||||||
var toolName = "agent_wait";
|
var toolName = "agent_wait";
|
||||||
|
|
||||||
@@ -6322,6 +6331,10 @@ public partial class ChatWindow : Window
|
|||||||
{
|
{
|
||||||
summary = "생각을 정리하는 중입니다...";
|
summary = "생각을 정리하는 중입니다...";
|
||||||
}
|
}
|
||||||
|
else if (elapsed >= TimeSpan.FromSeconds(4))
|
||||||
|
{
|
||||||
|
summary = "작업을 진행하는 중입니다...";
|
||||||
|
}
|
||||||
|
|
||||||
UpdateLiveAgentProgressHint(summary, toolName);
|
UpdateLiveAgentProgressHint(summary, toolName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ internal sealed class PermissionRequestWindow : Window
|
|||||||
{
|
{
|
||||||
stack.Children.Add(new TextBlock
|
stack.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = "沅뚰븳 ?좏깮",
|
Text = "권한 선택",
|
||||||
FontSize = 12.5,
|
FontSize = 12.5,
|
||||||
FontWeight = FontWeights.SemiBold,
|
FontWeight = FontWeights.SemiBold,
|
||||||
Foreground = primary,
|
Foreground = primary,
|
||||||
@@ -197,24 +197,24 @@ internal sealed class PermissionRequestWindow : Window
|
|||||||
var optionList = new StackPanel();
|
var optionList = new StackPanel();
|
||||||
optionList.Children.Add(BuildOption(
|
optionList.Children.Add(BuildOption(
|
||||||
icon: "\uE73E",
|
icon: "\uE73E",
|
||||||
title: "?대쾲留??덉슜",
|
title: "이번만 허용",
|
||||||
description: uiProfile.ShowOptionDescription ? "?꾩옱 ?붿껌 1?뚮쭔 ?덉슜?⑸땲??" : "",
|
description: uiProfile.ShowOptionDescription ? "현재 요청 1회만 허용합니다." : "",
|
||||||
fg: new SolidColorBrush(Color.FromRgb(0x05, 0x96, 0x69)),
|
fg: new SolidColorBrush(Color.FromRgb(0x05, 0x96, 0x69)),
|
||||||
bg: hoverBg,
|
bg: hoverBg,
|
||||||
onClick: () => CloseWith(PermissionPromptResult.AllowOnce)));
|
onClick: () => CloseWith(PermissionPromptResult.AllowOnce)));
|
||||||
|
|
||||||
optionList.Children.Add(BuildOption(
|
optionList.Children.Add(BuildOption(
|
||||||
icon: "\uE8FB",
|
icon: "\uE8FB",
|
||||||
title: "?대쾲 ?ㅽ뻾 ?숈븞 ?덉슜",
|
title: "이번 실행 동안 허용",
|
||||||
description: uiProfile.ShowOptionDescription ? "?꾩옱 ?ㅽ뻾 以??숈씪 踰붿쐞 ?붿껌???먮룞 ?덉슜?⑸땲??" : "",
|
description: uiProfile.ShowOptionDescription ? "현재 실행 중 같은 범위 요청을 자동 허용합니다." : "",
|
||||||
fg: accent,
|
fg: accent,
|
||||||
bg: hoverBg,
|
bg: hoverBg,
|
||||||
onClick: () => CloseWith(PermissionPromptResult.AllowForSession)));
|
onClick: () => CloseWith(PermissionPromptResult.AllowForSession)));
|
||||||
|
|
||||||
optionList.Children.Add(BuildOption(
|
optionList.Children.Add(BuildOption(
|
||||||
icon: "\uE711",
|
icon: "\uE711",
|
||||||
title: "嫄곕?",
|
title: "거부",
|
||||||
description: uiProfile.ShowOptionDescription ? "?붿껌??李⑤떒?섍퀬 ???묒뾽 ?놁씠 怨꾩냽 吏꾪뻾?⑸땲??" : "",
|
description: uiProfile.ShowOptionDescription ? "요청을 차단하고 현재 작업은 중단 없이 계속 진행합니다." : "",
|
||||||
fg: new SolidColorBrush(Color.FromRgb(0xDC, 0x26, 0x26)),
|
fg: new SolidColorBrush(Color.FromRgb(0xDC, 0x26, 0x26)),
|
||||||
bg: hoverBg,
|
bg: hoverBg,
|
||||||
onClick: () => CloseWith(PermissionPromptResult.Reject)));
|
onClick: () => CloseWith(PermissionPromptResult.Reject)));
|
||||||
@@ -223,8 +223,8 @@ internal sealed class PermissionRequestWindow : Window
|
|||||||
stack.Children.Add(new TextBlock
|
stack.Children.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = uiProfile.Key == "simple"
|
Text = uiProfile.Key == "simple"
|
||||||
? "Esc: 嫄곕?"
|
? "Esc: 거부"
|
||||||
: "Esc: 嫄곕? | Enter: ?대쾲留??덉슜",
|
: "Esc: 거부 | Enter: 이번만 허용",
|
||||||
FontSize = 11,
|
FontSize = 11,
|
||||||
Foreground = secondary,
|
Foreground = secondary,
|
||||||
Margin = new Thickness(2, 12, 0, 0),
|
Margin = new Thickness(2, 12, 0, 0),
|
||||||
@@ -273,9 +273,9 @@ internal sealed class PermissionRequestWindow : Window
|
|||||||
{
|
{
|
||||||
return new PermissionPromptProfile(
|
return new PermissionPromptProfile(
|
||||||
HeaderIcon: "\uE8A5",
|
HeaderIcon: "\uE8A5",
|
||||||
HeaderTitle: "AX Agent ?뚯씪 沅뚰븳 ?붿껌",
|
HeaderTitle: "AX Agent 파일 권한 요청",
|
||||||
Headline: "?먯씠?꾪듃媛 ?뚯씪 蹂寃쎌쓣 ?붿껌?덉뒿?덈떎.",
|
Headline: "에이전트가 파일 변경을 요청했습니다.",
|
||||||
RiskLabel: "以묎컙 ?꾪뿕",
|
RiskLabel: "중간 위험",
|
||||||
RiskColor: Color.FromRgb(0xEA, 0x58, 0x0C));
|
RiskColor: Color.FromRgb(0xEA, 0x58, 0x0C));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,9 +283,9 @@ internal sealed class PermissionRequestWindow : Window
|
|||||||
{
|
{
|
||||||
return new PermissionPromptProfile(
|
return new PermissionPromptProfile(
|
||||||
HeaderIcon: "\uE756",
|
HeaderIcon: "\uE756",
|
||||||
HeaderTitle: "AX Agent 紐낅졊 ?ㅽ뻾 沅뚰븳 ?붿껌",
|
HeaderTitle: "AX Agent 명령 실행 권한 요청",
|
||||||
Headline: "?먯씠?꾪듃媛 ??紐낅졊 ?ㅽ뻾???붿껌?덉뒿?덈떎.",
|
Headline: "에이전트가 시스템 명령 실행을 요청했습니다.",
|
||||||
RiskLabel: "?믪? ?꾪뿕",
|
RiskLabel: "높은 위험",
|
||||||
RiskColor: Color.FromRgb(0xDC, 0x26, 0x26));
|
RiskColor: Color.FromRgb(0xDC, 0x26, 0x26));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,17 +293,17 @@ internal sealed class PermissionRequestWindow : Window
|
|||||||
{
|
{
|
||||||
return new PermissionPromptProfile(
|
return new PermissionPromptProfile(
|
||||||
HeaderIcon: "\uE774",
|
HeaderIcon: "\uE774",
|
||||||
HeaderTitle: "AX Agent ?ㅽ듃?뚰겕 沅뚰븳 ?붿껌",
|
HeaderTitle: "AX Agent 네트워크 권한 요청",
|
||||||
Headline: "?먯씠?꾪듃媛 ?몃? 由ъ냼???묎렐???붿껌?덉뒿?덈떎.",
|
Headline: "에이전트가 외부 리소스 접근을 요청했습니다.",
|
||||||
RiskLabel: "以묎컙 ?꾪뿕",
|
RiskLabel: "중간 위험",
|
||||||
RiskColor: Color.FromRgb(0xD9, 0x77, 0x06));
|
RiskColor: Color.FromRgb(0xD9, 0x77, 0x06));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PermissionPromptProfile(
|
return new PermissionPromptProfile(
|
||||||
HeaderIcon: "\uE897",
|
HeaderIcon: "\uE897",
|
||||||
HeaderTitle: "AX Agent 沅뚰븳 ?붿껌",
|
HeaderTitle: "AX Agent 권한 요청",
|
||||||
Headline: "怨꾩냽 吏꾪뻾?섎젮硫?沅뚰븳 ?뺤씤???꾩슂?⑸땲??",
|
Headline: "계속 진행하려면 권한 확인이 필요합니다.",
|
||||||
RiskLabel: "寃???꾩슂",
|
RiskLabel: "검토 필요",
|
||||||
RiskColor: Color.FromRgb(0x25, 0x63, 0xEB));
|
RiskColor: Color.FromRgb(0x25, 0x63, 0xEB));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user