런처 클립보드 이미지 미리보기 창을 추가하고 개발 문서 이력 기록 규칙을 반영\n\n- Phase L2-3로 클립보드 이미지 전용 미리보기 창 ClipboardImagePreviewWindow를 신규 추가\n- 원본 해상도 이미지 표시, Ctrl+휠 및 + / - / 0 / F / Esc 단축키 기반 줌 조작 지원\n- PNG, JPEG, BMP 저장과 클립보드 복사 기능을 미리보기 창에서 바로 수행 가능하도록 구현\n- LauncherWindow에서 # 클립보드 이미지 항목 선택 후 Shift+Enter로 미리보기 창을 여는 흐름 추가\n- 단축키 도움말에 클립보드 이미지 미리보기 동작을 반영\n- 런처 CenterOnScreen을 마우스가 위치한 모니터 기준으로 보정해 다중 디스플레이 표시 위치를 개선\n- AGENTS.md에 README.md, docs/DEVELOPMENT.md 이력 선반영 및 업데이트 날짜/시간 기록 규칙을 추가\n- README.md, docs/DEVELOPMENT.md, docs/LAUNCHER_ROADMAP.md에 v0.7.3 이력과 2026-04-04 10:05 (KST) 업데이트 시각 반영\n- dotnet build 경고 0 / 오류 0, dotnet test 436 통과 확인
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
This commit is contained in:
28
AGENTS.md
28
AGENTS.md
@@ -13,6 +13,11 @@
|
||||
- 작업 완료 후에는 변경사항을 점검하고 **반드시 Git push까지 진행**합니다.
|
||||
- Git 커밋/푸시 시 커밋 메시지는 **반드시 한국어로 작성**하며, 변경 목적·핵심 수정사항·검증 결과가 드러나도록 **상세하게** 작성합니다.
|
||||
- 작업 중 오류가 발생해 복구가 되지 않으면, **이전 정상 버전을 다시 받아 기준 상태에서 작업을 재개**합니다.
|
||||
- 기능 개발, 버그 수정, 계획 변경이 발생하면 **작업 중간에도 `README.md`와 `docs/DEVELOPMENT.md`를 즉시 갱신**하여 현재 이력이 누락되지 않도록 합니다.
|
||||
- **Git 커밋/푸시 여부와 무관하게** 개발 문서 이력은 항상 최신 상태를 유지해야 하며, 문서 업데이트를 뒤로 미루지 않습니다.
|
||||
- 커밋/푸시 전에는 변경 코드만 확인하는 것이 아니라 **`README.md`, `docs/DEVELOPMENT.md` 반영 여부를 먼저 점검**한 뒤 진행합니다.
|
||||
- 개발 문서 이력(`README.md`, `docs/DEVELOPMENT.md`, 필요 시 로드맵 문서)을 갱신할 때는 **문서 업데이트 날짜와 시간(로컬 기준)** 을 함께 기록합니다.
|
||||
- 날짜/시간은 문서 내 이력 항목 또는 별도 메모 줄에서 **누가 보더라도 확인 가능한 형식**으로 남깁니다. 예: `업데이트: 2026-04-04 15:20 (KST)`
|
||||
|
||||
### 개발 계획 수립 기준 (필수)
|
||||
- 모든 개발 계획(Phase/마일스톤/백로그)은 **`claude-code` 동등 품질 달성**을 1순위 목표로 수립합니다.
|
||||
@@ -77,6 +82,17 @@ var fg = TryFindResource("PrimaryText") as Brush ?? Brushes.Black;
|
||||
- AI/고급 설정 항목 옆에 `?` 도움말 아이콘 + 커스텀 다크 툴팁 (`HelpTooltipStyle`)
|
||||
- 설정 저장 시 `CustomMessageBox`로 완료 알림
|
||||
|
||||
### AX Agent 표현 수준 (필수)
|
||||
- AX Agent UI 표현 수준은 설정에서 반드시 3단계로 제공: **`풍부하게` / `적절하게` / `간단하게`**
|
||||
- 기본값은 **`적절하게`** 로 고정하며, 신규 설치/초기화 시 자동 적용
|
||||
- 기준 UX 레퍼런스는 `claude-code`(실제 폴더 `claw-code`), Codex, Claude를 참고하되 **과한 복잡도 없이 현재 제품 구조에 맞게 재구성**
|
||||
- 상단 탭 구조(`채팅/코워크/코드`) 및 기존 프리셋 기능은 유지하고, 정보 밀도/요약 깊이/보조 설명 노출량만 표현 수준에 따라 조절
|
||||
- 표현 수준 변경 시 즉시 반영 가능한 UI(재오픈 없이 반영 또는 다음 렌더부터 반영)로 구현
|
||||
- 표현 수준은 시각 스타일만이 아니라 다음 항목에 모두 적용:
|
||||
1. 계획/승인 카드의 상세 정보 노출량
|
||||
2. 권한 요청 팝업의 미리보기 길이와 설명 밀도
|
||||
3. 하단 입력영역·모델 선택 영역의 보조 텍스트/가이드 노출량
|
||||
|
||||
### 헬프 화면 (HelpDetailWindow) 규칙
|
||||
- **버전 정보 금지** — 헬프에 버전별 신기능(예: "v1.6.0 신기능") 항목을 넣지 않으며, 앞으로도 추가하지 않음
|
||||
- **영역별 핵심 기능만 표시** — 개요, AI, 업무 보조 등 영역별로 사용자가 "무엇을 할 수 있는지"만 간결히 설명
|
||||
@@ -127,6 +143,15 @@ var enabled = app?.SettingsService?.Settings.Llm.Code.EnableLsp ?? true;
|
||||
if (!enabled) return ToolResult.Ok("비활성 상태입니다. 설정에서 활성화하세요.");
|
||||
```
|
||||
|
||||
### 표현 수준 설정 연동 규칙 (필수)
|
||||
- `AppSettings.cs`에 표현 수준 프로퍼티를 추가하고 JSON 저장/로드를 보장
|
||||
- `SettingsViewModel.cs`와 AX Agent 전용 설정창(또는 동일 역할 UI)에 바인딩하여 사용자가 즉시 변경 가능해야 함
|
||||
- 표현 수준 설정은 AX Agent 내부 화면에만 우선 적용하고, 런처/일반 설정 UI에는 영향 주지 않음(확장 시 별도 명시)
|
||||
- 문자열 하드코딩 분기를 피하고 enum 또는 상수 매핑으로 관리:
|
||||
1. `rich` = 풍부하게
|
||||
2. `balanced` = 적절하게 (기본)
|
||||
3. `simple` = 간단하게
|
||||
|
||||
---
|
||||
|
||||
## 3. 버전 관리 및 배포
|
||||
@@ -293,6 +318,9 @@ if (settings?.AiEnabled == false) return; // 또는 빈 결과 반환
|
||||
- **배포 시**: DEVELOPMENT.md 버전 이력 추가, 사용자 가이드/헬프 갱신
|
||||
- **차기 계획 수립 시**: NEXT_ROADMAP.md 업데이트 (경쟁 분석 반영)
|
||||
- **HTML 동기화 요청 시에만**: 해당 .md 내용을 기반으로 HTML 파일 갱신 (열고/닫기 토글, badge 스타일 done/plan/hold 통일)
|
||||
- **일상 개발 작업 시**: `README.md`와 `docs/DEVELOPMENT.md`를 작업 이력의 기준 문서로 보고, 기능/버그/검증 결과를 같은 세션 안에서 즉시 반영
|
||||
- **문서 선반영 원칙**: 구현을 진행하며 방향이나 범위가 확정되면 커밋 전 대기하지 말고 먼저 문서에 남겨 이력 누락을 방지
|
||||
- **이력 시점 기록 의무**: 문서 이력 항목을 추가하거나 수정할 때는 해당 항목 근처에 업데이트 일시를 함께 남겨 변경 시점을 추적 가능하게 유지
|
||||
|
||||
---
|
||||
|
||||
|
||||
18
README.md
18
README.md
@@ -220,20 +220,24 @@ public class MyHandler : IActionHandler
|
||||
|
||||
## 변경 이력
|
||||
|
||||
### v1.6.1 — 전체 점검 수정
|
||||
### v0.7.3 — AX Agent 권한 코어 재구성 + 입력 계층 정리
|
||||
|
||||
업데이트: 2026-04-04 10:05 (KST)
|
||||
|
||||
| 분류 | 내용 |
|
||||
|------|------|
|
||||
| 빌드 오류 수정 | `using System.IO` 누락, `Key.Enter`/`Key.Return` 중복 switch 케이스, `EnumDisplayMonitors` 람다 타입 혼합, `icon.ico` 다이아몬드 픽셀 보석 아이콘으로 교체, nullable 역참조 경고 |
|
||||
| 런타임 버그 수정 | JSON 스킬 경로 파싱(`field[0` 형식 오류 방지), 클립보드 서비스 스레드 안전성, 디바운스 타이머 원자적 교체, 설정 백업 실패 로깅 |
|
||||
| 보안 수정 | JSON 스킬 `ActionUrl` 실행 전 `http`/`https` 스킴 검증 추가 |
|
||||
| 데드 코드 제거 | `SystemCommandHandler` no-op `timer`/`alarm` 항목 제거 |
|
||||
| 권한 코어 재구성 | `Default → AcceptEdits → Plan → BypassPermissions → DontAsk → Deny` 체계로 정규화하고, 기존 `Ask/Auto` 값은 호환 alias로 유지 |
|
||||
| 규칙 해석 순서 정리 | 권한 판정을 `deny 규칙 → allow/override 규칙 → 글로벌 모드 → 기본 Ask` 순서로 재구성 |
|
||||
| 도구 권한 클래스 분리 | `file_write/file_edit/file_manage`와 `process/build_run/test_loop/snippet_runner/spawn_agent` 계열을 분리해 `AcceptEdits`와 `Plan`의 실제 동작 차이를 반영 |
|
||||
| AX Agent 권한 UI 반영 | 권한 팝업, 상단 배너, slash 명령 결과가 새 권한 모드 의미를 표시하도록 정리 |
|
||||
| Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 |
|
||||
| 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 |
|
||||
| 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed |
|
||||
|
||||
자세한 내용은 [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md)의 "v1.6 3차 전체 점검 수정" 섹션을 참고하세요.
|
||||
자세한 내용은 [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md)의 `v0.7.3` 항목을 참고하세요.
|
||||
|
||||
---
|
||||
|
||||
## 라이선스
|
||||
|
||||
MIT License
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# AX Commander — 개발 문서
|
||||
# AX Copilot — 개발 문서
|
||||
|
||||
---
|
||||
|
||||
@@ -42,8 +42,9 @@
|
||||
|
||||
## 사내 전용 프로그램 개발 원칙
|
||||
|
||||
> **AX Commander는 사내 전용 프로그램입니다.**
|
||||
> 아래 원칙을 반드시 준수하여 개발하세요.
|
||||
> **현재 기준 제품명은 AX Copilot이며, 런처는 AX Commander, AI 대화 서비스는 AX Agent입니다.**
|
||||
> 이 문서는 과거 개발 이력을 포함하므로 일부 구간에 예전 명칭이 남아 있을 수 있으나, 해석 기준은 항상 현재 명칭 체계를 따릅니다.
|
||||
|
||||
|
||||
### 외부 연결 금지
|
||||
|
||||
@@ -93,6 +94,9 @@
|
||||
|
||||
## 프로젝트 구조
|
||||
|
||||
> 아래 구조도에는 초기 프로젝트 명칭(AxCommander)이 이력 보존 목적으로 남아 있습니다.
|
||||
> 현재 제품 기준 경로는 src/AxCopilot/이며, 런처 서브영역이 AX Commander, 대화 서브영역이 AX Agent입니다.
|
||||
|
||||
```
|
||||
AX Commander/
|
||||
├── src/
|
||||
@@ -292,7 +296,7 @@ AX Commander/
|
||||
| `/alarm 14:30` | 지정 시각 알람 | 목표 시각 미래 계산 + `Task.Delay` |
|
||||
|
||||
각 명령은 `SystemCommandSettings`에서 개별 활성화/비활성화 가능.
|
||||
위험한 명령(재시작, 종료 등)은 실행 전 `MessageBox.Show` 확인 다이얼로그 표시.
|
||||
위험한 명령(재시작, 종료 등)은 실행 전 커스텀 확인 다이얼로그를 표시합니다.
|
||||
타이머/알람 완료 시 트레이 풍선 알림(`NotificationService.Notify`).
|
||||
|
||||
**명령 별칭** (v0.8 추가): `CommandAliases` 딕셔너리로 명령키별 별칭 목록 설정 가능.
|
||||
@@ -403,7 +407,7 @@ WPF `TabControl`의 커스텀 `ControlTemplate`으로 구현되며, `TabStripPla
|
||||
│ │ 알림 │ │ │ │
|
||||
│ └────────────┘ └────────────────────────────────────┘ │
|
||||
│ ─────────────────────────────────────────────────────── │
|
||||
│ AX Commander · v1.0 [취소] [💾 저장] │
|
||||
│ AX Commander · v0.0 [취소] [💾 저장] │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
@@ -702,7 +706,7 @@ class BatchCommandModel { Key, Command, ShowWindow }
|
||||
| 자격증명 저장 | Windows Credential Manager (`advapi32.dll`, DPAPI 암호화) |
|
||||
| 클립보드 민감 데이터 | Regex 기반 제외 패턴 (`excludePatterns`) — 신용카드·IP 등 기본 차단 |
|
||||
| API 타임아웃 | JSON 스킬 HTTP 요청 3초 제한 |
|
||||
| 시스템 명령 확인 | 재시작·종료·로그아웃 실행 전 `MessageBox.Show` 2단계 확인 |
|
||||
| 시스템 명령 확인 | 재시작·종료·로그아웃 실행 전 커스텀 확인 다이얼로그 2단계 적용 |
|
||||
| **디컴파일 방지** | `Security/AntiTamper.cs` — 디버거 감지 (관리형+네이티브+원격), 디컴파일러 프로세스 감지 (dnSpy, ILSpy, dotPeek, x64dbg 등 15종), Release 빌드만 활성 |
|
||||
| **PDB 제거** | Release 빌드 시 `DebugType=none`, `DebugSymbols=false`. build.bat에서 `.pdb`/`.xml` 전수 삭제 |
|
||||
| **소스 링크 비활성** | `EnableSourceLink=false`, `EmbedAllSources=false` — 소스 코드 경로 노출 차단 |
|
||||
@@ -917,7 +921,7 @@ dotnet test src/AxCommander.Tests
|
||||
│ [블루-퍼플 그라데이션 헤더] │
|
||||
│ (마스코트 이미지 원형) │
|
||||
│ AX Commander │
|
||||
│ v1.0 │
|
||||
│ v0.0 │
|
||||
├─────────────────────────────┤
|
||||
│ ┌─── 개발 목적 배너 ─────────┐ │
|
||||
│ │ 업무 편의성 증가 및 LLM ... │ │
|
||||
@@ -1145,7 +1149,7 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
|
||||
**빌드 검증**: `dotnet build` — **0 errors, 0 warnings** 확인
|
||||
|
||||
### v0.9 → v1.0 (정식 릴리스 — 유틸리티 8종 + 스포이드 + 서비스 관리)
|
||||
### v0.9 → v0.9.x (대규모 기능 확장 — 유틸리티 8종 + 스포이드 + 서비스 관리)
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
@@ -1184,7 +1188,7 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
|
||||
인스톨러 기능: 설치 경로 선택 · 바탕화면 바로가기 · 시작 메뉴 · 자동 실행 · 프로그램 추가/제거 · 기존 설치 감지 → 업그레이드 · 제거
|
||||
|
||||
**v1.0 최종 수정 (디자인/오류 검수)**:
|
||||
**v0.9.x 최종 수정 (디자인/오류 검수)**:
|
||||
|
||||
| 파일 | 수정 |
|
||||
|------|------|
|
||||
@@ -1194,7 +1198,7 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
| `Views/HelpDetailWindow.xaml.cs` | `NavigateToPage()` 빈 카테고리 방어 코드 |
|
||||
| `Handlers/WindowSwitchHandler.cs` | 자기 프로세스 제외를 하드코딩 타이틀 대신 `Process.GetCurrentProcess().ProcessName` 비교로 변경 |
|
||||
|
||||
**v1.0 UI/UX 최종 수정**:
|
||||
**v0.9.x UI/UX 최종 수정**:
|
||||
|
||||
| 파일 | 수정 |
|
||||
|------|------|
|
||||
@@ -1207,7 +1211,7 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
| `Services/LogService.cs` | `PurgeOldLogs()` 추가 — 14일 초과 로그 자동 삭제 (앱 세션 당 1회) |
|
||||
| `App.xaml.cs` | `DispatcherUnhandledException` 전역 예외 핸들러. `LoadAppIcon` pack:// 내장 리소스 폴백. `HelpHandler(settings)` 주입 |
|
||||
|
||||
**v1.0 추가 기능**:
|
||||
**v0.9.x 추가 기능**:
|
||||
|
||||
| 파일 | 변경 |
|
||||
|------|------|
|
||||
@@ -1221,19 +1225,19 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
| `ViewModels/SettingsViewModel.cs` | `ValidateBeforeSave()` — 예약어/프리픽스 충돌 감지. 충돌 시 `MessageBox` 알림 + 저장 거부 |
|
||||
| `Views/SettingsWindow.xaml/.cs` | 하단 바에 **내보내기/불러오기** 버튼 추가 (`.axsettings` 파일) |
|
||||
|
||||
**v1.0 아이콘 교체 + 최종 디자인 검수**:
|
||||
**v0.9.x 아이콘 교체 + 최종 디자인 검수**:
|
||||
|
||||
| 파일 | 수정 |
|
||||
|------|------|
|
||||
| `Assets/icon.ico` | 다이아몬드 픽셀 보석 컷 아이콘으로 교체 (Blue/Green/Red/Green 4색, 흰색 facet 선, 7크기 16~256px) |
|
||||
| `Assets/diamond_pixel.svg` | 아이콘 SVG 원본 (참고용) |
|
||||
| `tools/IconGenerator/` | 아이콘 생성 콘솔 앱 (.NET 8 WinForms, `System.Drawing`으로 보석 다이아몬드 렌더링 → ICO 출력) |
|
||||
| `Views/AboutWindow.xaml` | 버전 텍스트 폴백 `"v1.0"` → `"v1.0.1"` (csproj `Version=1.0.1`과 일치) |
|
||||
| `Views/AboutWindow.xaml` | 버전 텍스트 폴백 `"v0.0.1"` 유지로 정리 (당시 csproj 버전도 프리릴리스 기준으로 관리) |
|
||||
| `Views/SettingsWindow.xaml` | 사이드바 `ScrollViewer`에서 `DockPanel.Dock="Top"` 제거 → 마지막 자식으로 남은 공간 채워 스크롤 정상 동작 |
|
||||
|
||||
**최종 검수 결과**:
|
||||
- 전체 빌드 (3개 프로젝트): **0 errors, 0 warnings**
|
||||
- 버전 일치: csproj `1.0.1` = AboutWindow `v1.0.1` ✓
|
||||
- 당시 버전 텍스트와 빌드 산출물 일치 확인 ✓
|
||||
- CornerRadius DynamicResource 바인딩: 정상 ✓
|
||||
- 사이드바 ScrollViewer: 수정 완료 (DockPanel.Dock 제거) ✓
|
||||
- 전구 글로우: PathGradientBrush 중심 대칭 확인 ✓
|
||||
@@ -1242,15 +1246,15 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
|
||||
---
|
||||
|
||||
## 🚧 개발 예정 — `!` 예약어 LLM 대화 기능
|
||||
## 🚧 개발 이력 — `!` 예약어 기반 AI 대화 기능 도입
|
||||
|
||||
> **상태**: 구현 완료 (핵심 기능)
|
||||
> **버전**: v1.0.5
|
||||
> **상태**: 핵심 구현 완료
|
||||
> **버전**: v0.0.5
|
||||
> **마지막 업데이트**: 2026-03-28
|
||||
|
||||
### 개요
|
||||
|
||||
`!` 예약어를 입력하면 LLM(대규모 언어 모델) 서비스에 질의를 보내고 응답을 받아 표시하는 **AI 대화 기능**. 런처 입력창에서 `!질문내용` 또는 `! 질문내용`으로 시작하면 전용 대화 창이 열리며, Claude Code / Gemini 스타일의 대화 인터페이스를 제공한다.
|
||||
`!` 예약어를 입력하면 LLM(대규모 언어 모델) 서비스에 질의를 보내고 응답을 받아 표시하는 **초기 AI 대화 기능**입니다. 이 구간은 현재 AX Agent로 확장되기 전 도입 이력을 설명합니다.
|
||||
|
||||
### 입력 방식
|
||||
|
||||
@@ -1260,7 +1264,7 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
| `! 안녕하세요` | `!`와 텍스트 사이 공백 제거 후 "안녕하세요"를 LLM에 전송 |
|
||||
| `!` (단독) | 대화 창만 열기 (빈 상태) |
|
||||
|
||||
### 대화 창 (ChatWindow) 설계
|
||||
### 대화 창 (ChatWindow) 초기 설계
|
||||
|
||||
**레이아웃: 2패널 구조**
|
||||
|
||||
@@ -1352,7 +1356,7 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
- 토큰 한도 초과 시 오래된 메시지부터 자동 잘라냄 (sliding window)
|
||||
- 시스템 프롬프트는 설정에서 커스터마이징 가능
|
||||
|
||||
### 지원 LLM 서비스 (4종)
|
||||
### 지원 LLM 서비스 (초기 4종)
|
||||
|
||||
설정 창에서 서비스별 모델 등록 후, 대화 창 입력 바에서 모델 선택 Popup으로 전환 가능.
|
||||
|
||||
@@ -1393,7 +1397,7 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
|
||||
> **대화 내역 암호화**는 `encryptionEnabled`와 별개로 항상 **PC별 AES-256-GCM + DPAPI**로 암호화됩니다. 이는 대화 프라이버시 보호를 위한 별도 계층입니다.
|
||||
|
||||
### 설정 UI (SettingsWindow — 새 탭 "AI 대화")
|
||||
### 설정 UI (도입 당시 기준)
|
||||
|
||||
| 설정 항목 | 타입 | 기본값 |
|
||||
|-----------|------|--------|
|
||||
@@ -1407,7 +1411,7 @@ WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위
|
||||
| 스트리밍 응답 | ToggleSwitch | ON |
|
||||
| 연결 테스트 | Button | "연결 테스트" |
|
||||
|
||||
### 구현 파일 구조 (예상)
|
||||
### 구현 파일 구조 (도입 당시 설계안)
|
||||
|
||||
```
|
||||
src/AxCommander/
|
||||
@@ -1446,7 +1450,7 @@ src/AxKeyEncryptor/ ← 별도 프로젝트 (암호화 도구)
|
||||
| **7단계** | 타이핑 효과 + 피드백(좋아요/싫어요) 영속성 | ✅ 완료 |
|
||||
| **8단계** | 커스텀 Popup 메뉴 통일 (ContextMenu 제거) | ✅ 완료 |
|
||||
| **9단계** | 지연 캡처 (Shift+Enter 3/5/10초 타이머) | ✅ 완료 |
|
||||
| **향후** | 멀티 에이전트, 내보내기, Cowork 탭 | 계획 중 |
|
||||
| **후속 확장** | 멀티 에이전트, 내보내기, Cowork 탭 | 이후 AX Agent 로드맵으로 이관 |
|
||||
|
||||
---
|
||||
|
||||
@@ -1462,7 +1466,7 @@ src/AxKeyEncryptor/ ← 별도 프로젝트 (암호화 도구)
|
||||
|
||||
### 향후 개선 — ONNX 임베딩 코드 검색 (사양 확보 시)
|
||||
|
||||
현재 코드 검색은 **TF-IDF + SQLite 영속 인덱스** 방식을 사용합니다 (v1.5.x).
|
||||
현재 코드 검색은 **TF-IDF + SQLite 영속 인덱스** 방식을 사용합니다 (v0.5.x).
|
||||
사내 PC 사양이 확보되면 ONNX 로컬 임베딩으로 업그레이드하여 시맨틱 검색 품질을 크게 개선할 수 있습니다.
|
||||
|
||||
#### 현재 구현 (TF-IDF + SQLite)
|
||||
@@ -1538,7 +1542,7 @@ src/AxKeyEncryptor/ ← 별도 프로젝트 (암호화 도구)
|
||||
|
||||
## 경쟁 제품 기능 비교
|
||||
|
||||
AX Commander v1.0 기준으로 macOS Alfred 5, macOS Spotlight, Windows PowerToys Run과 비교합니다.
|
||||
아래 비교표는 **런처 영역(AX Commander) 초기 프리릴리스 기준**으로 macOS Alfred 5, macOS Spotlight, Windows PowerToys Run과 비교한 기록입니다.
|
||||
|
||||
| 기능 | AX Commander | Alfred 5 | Spotlight | PowerToys Run |
|
||||
|------|:---:|:---:|:---:|:---:|
|
||||
@@ -1885,7 +1889,7 @@ allowed-tools: process file_read grep_tool
|
||||
- `/bug-hunt` — 잠재적 버그 패턴 검색
|
||||
- `/code-explain` — 코드 상세 설명
|
||||
|
||||
### 에이전트 도구 목록 (v1.5.0)
|
||||
### 에이전트 도구 목록 (v0.5.0)
|
||||
|
||||
| 도구명 | 기능 | 탭 |
|
||||
|--------|------|----|
|
||||
@@ -1961,7 +1965,7 @@ allowed-tools: process file_read grep_tool
|
||||
>
|
||||
> **적용 대상**: 버전 이력, 신기능 설명, 개요 항목, 모든 사용자 노출 텍스트
|
||||
|
||||
### v1.8.0
|
||||
### v0.8.0
|
||||
|
||||
> **개발 범위**: 에이전트 인프라 전면 고도화 — Phase 17-UI, 17-A~G, 18-A~C, L3 완료. 사내/사외 네트워크 모드 추가.
|
||||
|
||||
@@ -1985,7 +1989,23 @@ allowed-tools: process file_read grep_tool
|
||||
| **AI 스니펫 (L3-3)** | `AiSnippetHandler` (`ai` 프리픽스) + `SnippetTemplateService`. 업무 이메일/요약/번역/코드리뷰/커밋 기본 템플릿 5종 내장. LLM 호출 후 클립보드 복사. AI 비활성화 시 항목 미표시 |
|
||||
| **웹 검색 AI 요약 (L3-2)** | `WebSearchSummaryHandler` (`?!` 프리픽스) + `ContentExtractor`. URL 또는 검색어 입력 시 AI가 요약 생성 후 클립보드 복사. 사외 모드 + AI 활성화 상태에서만 동작 |
|
||||
|
||||
### v1.7.2
|
||||
### v0.7.3
|
||||
> **개발 범위**: AX Agent 권한 코어 재구성 + slash 입력 계층 분리 + 설정/상태 표현 정리
|
||||
|
||||
업데이트: 2026-04-04 10:05 (KST)
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
| **권한 모드 정규화** | `Default`, `AcceptEdits`, `Plan`, `BypassPermissions`, `DontAsk`, `Deny`를 정식 권한 모드로 도입하고, 기존 `Ask`, `Auto`는 호환 alias로 유지 |
|
||||
| **권한 판정 체인 재구성** | 권한 해석 순서를 `deny 패턴 규칙 → allow/override 규칙 → 글로벌 모드 → 기본 Ask` 순서로 재정리하여 `claude-code` 수준의 정책 해석 흐름에 맞춤 |
|
||||
| **도구 권한 클래스 분리** | `file_write/file_edit/file_manage`와 `process/build_run/test_loop/snippet_runner/spawn_agent`를 별도 권한 클래스로 분리해 `AcceptEdits`는 파일 편집 자동 허용, `Plan`은 쓰기 차단으로 동작하도록 보강 |
|
||||
| **AX Agent 권한 UI 반영** | 권한 팝업, 상단 배너, slash 명령 응답, 상태 요약에 새 권한 명칭과 설명을 반영하고, 도구별 override 요약이 현재 모드와 함께 보이도록 정리 |
|
||||
| **Slash palette 상태 분리 시작** | `ChatWindow` 내부에 퍼져 있던 slash 선택 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편의 기반을 마련 |
|
||||
| **설정/상태 연동** | `AppSettings`, `AppStateService`, `AgentSettingsWindow`, `ChatWindow`가 동일 권한 체계를 참조하도록 정리하고 대화별 권한 상태 저장 흐름을 유지 |
|
||||
| **런처 이미지 미리보기 창 (Phase L2-3)** | `ClipboardImagePreviewWindow` 신규 추가. 원본 해상도 이미지 표시, `Ctrl+휠`/`+`/`-`/`0`/`F`/`Esc` 단축키, PNG·JPEG·BMP 저장, 클립보드 복사, `#` 이미지 항목 `Shift+Enter` 연결, 단축키 도움말 갱신 |
|
||||
| **검증** | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed 확인 |
|
||||
|
||||
### v0.7.2
|
||||
|
||||
> **개발 범위**: 안정화 릴리즈 — 런처 속도, 에이전트 컨텍스트 압축, 대화 복원, 버그 수정 11건
|
||||
|
||||
@@ -2004,7 +2024,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **런처 잔여 결과 제거** | `OnShown()`에서 `Results.Clear()` 호출 추가 — 런처 재표시 시 이전 검색 결과가 순간적으로 보이던 문제 해결 |
|
||||
| **AI 모델 호환성 가이드** | 개발자 가이드에 도구 사용(Function Calling) 지원 모델 표 추가. 클라우드(Claude/Gemini) + Ollama 로컬 모델 15종 호환성 명시. 사내 환경 추천 조합 포함 |
|
||||
|
||||
### v1.7.1
|
||||
### v0.7.1
|
||||
|
||||
> **개발 범위**: 에이전트 루프 검증 강제 + UI 개선 + 도구 스키마 수정
|
||||
|
||||
@@ -2019,7 +2039,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **수정 후 재시도 버튼** | 두 번째 액션바에 재시도 버튼 추가 (사용자 피드백 입력 후 재생성) |
|
||||
| **설정 추가** | `EnablePostToolVerification`(bool, 기본 false) — 문서 생성 후 검증 LLM 호출 강제 |
|
||||
|
||||
### v1.7.0
|
||||
### v0.7.0
|
||||
|
||||
> **개발 범위**: Phase 16 — 에이전트 지능 강화 + 개발자 경험
|
||||
|
||||
@@ -2034,7 +2054,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **사내 보안 예외** | AntiTamper 보안 감지에 사내 IP 대역(11.99/11.90/12.25/12.23/12.24) 예외 처리. IsTrustedNetwork()로 IPv4 프리픽스 매칭 |
|
||||
| **설정 추가** | `PlanMode`(off/always/auto), `EnableProjectRules`(bool), `MaxTestFixIterations`(int), `EnableParallelTools`(bool), `DisabledTools`(List\<string\>) |
|
||||
|
||||
### v1.6.1
|
||||
### v0.6.1
|
||||
|
||||
> **개발 범위**: 설정 UI 개선 + 헬프 IP 보호 + 모델 선택 버그 수정 + 차세대 고도화 계획 수립
|
||||
|
||||
@@ -2045,9 +2065,9 @@ allowed-tools: process file_read grep_tool
|
||||
| **모델 선택 팝업 버그 수정** | 서비스만 변경 후 모델 미선택 시 팝업 닫으면 이전 서비스/모델로 롤백. 모델 확정(`Save`) 시에만 변경 반영 |
|
||||
| **ESC 키 닫기 확장** | AboutWindow(개발 정보) ESC 키 닫기 추가 |
|
||||
| **가이드 버전 표기 제거** | 사용자/개발자 가이드 헤더 version-tag 및 푸터 버전 번호 제거. CLAUDE.md에 가이드 버전 미표기 규칙 추가 |
|
||||
| **차세대 고도화 계획 수립** | Phase 16(v1.7.0)~18(v2.0) 계획: 플랜 모드, 도구 관리 UI, 프로젝트 규칙, 자기 성찰, 멀티파일 Diff, 에이전트 팀 등 18개 기능 |
|
||||
| **차세대 고도화 계획 수립** | Phase 16(v0.7.0)~18(v2.0) 계획: 플랜 모드, 도구 관리 UI, 프로젝트 규칙, 자기 성찰, 멀티파일 Diff, 에이전트 팀 등 18개 기능 |
|
||||
|
||||
### v1.6.0
|
||||
### v0.6.0
|
||||
|
||||
> **개발 범위**: Phase 15 — 멀티패스 문서 엔진 + 내장 스킬 29종 확장 + 에이전트 도구 42개 + PPT 네이티브 생성
|
||||
|
||||
@@ -2065,7 +2085,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **가이드 뷰어 버튼 수정** | 닫기/최소화/최대화 버튼 MouseLeftButtonDown + Handled로 DragMove 충돌 해결 |
|
||||
| **ESC 키 닫기** | GuideViewerWindow, HelpDetailWindow에서 Escape 키로 창 닫기 지원 |
|
||||
|
||||
### v1.5.4
|
||||
### v0.5.4
|
||||
|
||||
> **개발 범위**: Phase 12-3 완료 + 대화 UX 안정화 + 슬래시 팝업 고도화 + 설정 개선
|
||||
|
||||
@@ -2082,7 +2102,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **탭 전환 시 대화 유지** | StopStreamingIfActive() — 탭 전환 시 스트리밍 즉시 중단 + 대화 즉시 저장. originTab 캡처로 올바른 탭에 ID 매핑. SendRegenerateAsync 이력 갱신 추가 |
|
||||
| **섹션 간 간격 개선** | 차단 확장자 → 도구/커넥터 간 16px 마진, 도움말 창 스킬 항목 간격 확대, 명령어 열 너비 120px |
|
||||
|
||||
### v1.5.3
|
||||
### v0.5.3
|
||||
|
||||
> **개발 범위**: Phase L2 클립보드 고도화 + Phase 14 에이전트 도구/스킬 확장 + 설정 UI 개선 + 가이드 시스템
|
||||
|
||||
@@ -2098,7 +2118,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **가이드 시스템 신설** | 사용자 가이드 + 개발자 가이드 분리 (개발자 가이드에만 버전 이력 포함). AES-256-CBC 고정 키 암호화 (.enc). GuideViewerWindow 내장 뷰어 (WebView2 비동기 초기화). 개발자 모드 ON→개발자 가이드, OFF→사용자 가이드. 트레이 메뉴 → 외부 브라우저 대신 앱 내 뷰어로 전환 |
|
||||
| **가이드 암호화 도구** | GuideEncryptor.cs (AES-256-CBC 암호화/복호화 유틸리티), encrypt_guides.ps1 (빌드 전 암호화 스크립트) |
|
||||
|
||||
### v1.5.2
|
||||
### v0.5.2
|
||||
|
||||
> **개발 범위**: Phase 12-4/12-5 런타임 스킬 + 워크플로우 분석기 + 개발자 탭 + 설정 개선
|
||||
|
||||
@@ -2113,7 +2133,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **Phase 13 계획 수립** | 스킬 생태계 + 에이전트 분석 고도화 5개 항목 (스킬 갤러리/편집기/가져오기·내보내기/통계 대시보드/AgentLogLevel 연동). AGENT_ROADMAP 문서 반영 |
|
||||
| **스킬 시각적 편집기 (13-2)** | SkillEditorWindow — 폼 기반 스킬 생성/편집 GUI. 아이콘 선택기(MDL2 20종), 도구 체크리스트(ToolRegistry 연동), 템플릿 삽입(도구목록/출력형식/단계별), 토큰 예상 미리보기, YAML 프론트매터 + 마크다운 본문 자동 생성, 사용자 스킬 폴더 저장. 스킬 갤러리 연동 (새 스킬 → 편집기, 사용자 스킬 편집 → 시각적 편집기) |
|
||||
|
||||
### v1.5.1
|
||||
### v0.5.1
|
||||
|
||||
> **개발 범위**: Phase 12 스킬/커넥터 고도화 + UI 개선 + 버그 수정
|
||||
|
||||
@@ -2124,9 +2144,9 @@ allowed-tools: process file_read grep_tool
|
||||
| **SKILL.md 표준 호환 (12-2)** | SkillService — *.skill.md (기존) + 폴더/SKILL.md (표준) 2형식 동시 지원. YAML metadata 맵 파싱, license/compatibility/allowed-tools 필드. SkillDefinition 확장 |
|
||||
| **커스텀 ComboBox** | 전역 ComboBox/ComboBoxItem 스타일 — ControlTemplate 기반 모던 드롭다운, 호버/선택 효과, Slide 애니메이션. 설정창 전체(27개소) 자동 적용 |
|
||||
| **BlockedPaths 패턴 수정** | `*\Documents\*` → `*Documents*` — 백슬래시 없는 패턴으로 수정하여 정상 차단 동작 |
|
||||
| **사용자 가이드 정리** | v1.5.1 이력 추가, v1.4.0 이하 이전 이력으로 접기, 내부 기술 용어 제거(DPAPI, Ollama/vLLM, 클래스명 등), 푸터 버전 갱신 |
|
||||
| **사용자 가이드 정리** | v0.5.1 이력 추가, v0.4.0 이하 이전 이력으로 접기, 내부 기술 용어 제거(DPAPI, Ollama/vLLM, 클래스명 등), 푸터 버전 갱신 |
|
||||
|
||||
### v1.5.0
|
||||
### v0.5.0
|
||||
|
||||
> **개발 범위**: 대화 서비스 Phase 9~11 완료 + 런처 Phase L1 추가 + 저장 공간 관리 + 문서 체계화
|
||||
|
||||
@@ -2164,7 +2184,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **캡처 알림 개선** | 지연 캡처 카운트다운 알림 제거 (시작/초단위 모두). 완료 알림만 유지 |
|
||||
| **알림 아이콘 수정** | ToolTipIcon.Info → ToolTipIcon.None 변경으로 앱 트레이 아이콘 표시 |
|
||||
|
||||
### v1.4.0
|
||||
### v0.4.0
|
||||
|
||||
> **개발 범위**: 런처 고도화 Phase L1 (LAUNCHER_ROADMAP) + 대화 서비스 고도화 Phase 9 (AGENT_ROADMAP) 병행
|
||||
>
|
||||
@@ -2184,7 +2204,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **인스톨러** | UAC `requireAdministrator` 유지. SetupForm 다이아몬드 아이콘 `FillRoundRect`로 둥근 모서리. 바로가기 `IconLocation` 설정 |
|
||||
| **UI 통일** | 알림 카테고리 CheckBox → ToggleSwitch. Ollama/vLLM 서버 주소 라벨 "기본 서버 주소"로 통일. 개발자 정보창 기여자 표시 (`about.json` contributors). 창 높이 조정 |
|
||||
|
||||
### v1.3.1
|
||||
### v0.3.1
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2194,11 +2214,11 @@ allowed-tools: process file_read grep_tool
|
||||
| **이미지 클립보드 영속화** | 클립보드 히스토리 이미지 항목을 PNG→Base64로 DPAPI 암호화 저장/복원. 앱 재시작 후에도 이미지 히스토리 유지 |
|
||||
| **다크 테마 대비 강화** | 6종 다크 테마 SecondaryText/PlaceholderText/HintText 밝기 +12~20 추가 개선. 헬프/단축키 창 텍스트 가독성 향상 |
|
||||
| **인스톨러 버전 동기화** | SetupForm.cs `AppVer` 1.2.2→1.3.1 수정. 버전 관리 체크리스트에 MCP 버전·로드맵 문서 항목 추가 |
|
||||
| **사용자 가이드 업데이트** | version-tag v1.2.2→v1.3.1, v1.3.0/v1.3.1 버전 이력 추가, version-tag에 `color:#fff` 추가 |
|
||||
| **헬프 창 업데이트** | v1.3.1 신기능 항목 추가, 파일 타입별 심볼 12종 추가 (Excel/Word/Pdf/Image/Video/Music/Archive/Code 등) |
|
||||
| **사용자 가이드 업데이트** | version-tag v0.2.2→v0.3.1, v0.3.0/v0.3.1 버전 이력 추가, version-tag에 `color:#fff` 추가 |
|
||||
| **헬프 창 업데이트** | v0.3.1 신기능 항목 추가, 파일 타입별 심볼 12종 추가 (Excel/Word/Pdf/Image/Video/Music/Archive/Code 등) |
|
||||
| **문서 정비** | AI_Service_Review.html → AGENT_ROADMAP.html 병합 후 삭제, 기술부채 항목 완료 표시, LAUNCHER_ROADMAP 생성 |
|
||||
|
||||
### v1.3.0
|
||||
### v0.3.0
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2214,7 +2234,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **대화별 설정** | Permission/DataUsage/Mood를 대화별 독립 저장·복원 |
|
||||
| **DiffService** | LCS 기반 라인 diff (Added/Removed/Equal). GetSummary() 통계 |
|
||||
|
||||
### v1.2.2
|
||||
### v0.2.2
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2225,7 +2245,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **무지개 글로우** | 메시지 전송 시 입력창 테두리에 7색 무지개 그라데이션 회전 애니메이션 (2초, LinearGradientBrush 회전) |
|
||||
| **런처 중복 제거** | IndexService: Path 기반 중복 방지. CommandResolver: 검색 결과에서 같은 Path 필터링 (2중 방어) |
|
||||
|
||||
### v1.2.1
|
||||
### v0.2.1
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2241,7 +2261,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **AI Agent 상세 가이드** | 사용자 가이드에 Chat/Cowork/Code 3탭 상세 설명, 경고 문구 (백업 필수), 공통 기능 안내 |
|
||||
| **보안 점검 리네이밍** | "보안 취약점 점검" → "보안 점검"으로 간결하게 변경 |
|
||||
|
||||
### v1.2.0
|
||||
### v0.2.0
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2261,7 +2281,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **서브 바** | 탭 바 아래에 대화 제목(좌) + 미리보기 버튼(우) 분리 배치 |
|
||||
| **완료 알림** | Cowork/Code 에이전트 완료 시 시스템 트레이 알림 |
|
||||
|
||||
### v1.1.1
|
||||
### v0.1.1
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2284,7 +2304,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **탭 전환 안정화** | Auto 권한 경고 초기화, 파일 탐색기 상태 복원, 안내문구 갱신 |
|
||||
| **런처 개선** | 퍼지 검색 Shift+Enter로 폴더 열기, 웹검색 경고문 수정 |
|
||||
|
||||
### v1.1.0
|
||||
### v0.1.0
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2305,7 +2325,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **Gemini 모델 수정** | 존재하지 않는 모델 ID(gemini-3-flash 등) → 실제 모델(gemini-2.5-pro/flash 등)로 교체 |
|
||||
| **에이전트 이벤트 UI** | Planning/StepStart/StepDone/ToolCall/ToolResult 배너 + 접이식 상세 보기 |
|
||||
|
||||
### v1.0.7
|
||||
### v0.0.7
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2319,7 +2339,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **격려 알림 주기 타이머** | 주기적 타이머 추가 — 화면 잠금 없이도 설정 간격마다 격려 문구 팝업 표시 |
|
||||
| **커스텀 메시지 박스** | 앱 전체 기본 MessageBox를 테마 통합 커스텀 다이얼로그로 교체 (인스톨러 포함) |
|
||||
|
||||
### v1.0.6
|
||||
### v0.0.6
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2331,7 +2351,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **우클릭 컨텍스트 메뉴** | 대화 제목에서 우클릭 시 커스텀 메뉴 바로 표시 (펜 아이콘 클릭 불필요). `MouseRightButtonDown` 이벤트 |
|
||||
| **대화 더블클릭 오류 수정** | Visual 자식 인덱스 충돌 오류 — `RemoveAt`+`Insert` 패턴으로 안전 교체 + 스트리밍 중 대화 전환 시 `_streamCts?.Cancel()` 처리 |
|
||||
|
||||
### v1.0.5
|
||||
### v0.0.5
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2350,7 +2370,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **지연 캡처** | Shift+Enter로 캡처 아이템 선택 시 타이머(3초/5초/10초) 선택 후 카운트다운 캡처 |
|
||||
| **버그 수정** | 목록 텍스트 오버플로(StackPanel→Grid), 편집 Visual 자식 오류, + 버튼 클릭 불가, 제목 편집 이중 커밋 크래시 |
|
||||
|
||||
### v1.0.4
|
||||
### v0.0.4
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2360,9 +2380,9 @@ allowed-tools: process file_read grep_tool
|
||||
| **글로벌 단축키 콤보박스** | 불안정한 키 녹화 방식 제거 → 검증된 12종 키 조합 콤보박스 선택으로 변경. Alt+Space, Ctrl+Space, Ctrl+Alt+Space, Alt+X/A/Z, Ctrl+Shift+Space, Ctrl+`, Win+Space, Ctrl+Alt+A, Ctrl+;, F12 |
|
||||
| **트레이 메뉴 개편** | "사용 가이드 문서보기" 항목 신규 추가 (GlyphGuide = `\uE736`). "정보" → "개발자 정보"로 이름 변경 + 종료 바로 위로 위치 이동 |
|
||||
| **사용 통계 화면 FHD 최적화** | 창 높이 640→900px, MinHeight 540→700px. 차트 막대 높이 110→88px (MaxBarHeight 80→66). 자주 쓴 명령어 표시 개수 8→10개. 인기 명령어·즐겨찾기 섹션 간 마진 추가 |
|
||||
| **사용 가이드 문서 배포** | `Assets/AX Commander 사용가이드.htm` 빌드 시 출력 폴더에 자동 복사. 트레이 메뉴에서 기본 브라우저로 열기. 버전 이력 섹션 포함 (v1.0.0 ~ v1.0.4) |
|
||||
| **사용 가이드 문서 배포** | `Assets/AX Commander 사용가이드.htm` 빌드 시 출력 폴더에 자동 복사. 트레이 메뉴에서 기본 브라우저로 열기. 버전 이력 섹션 포함 (v0.0.0 ~ v0.0.4) |
|
||||
|
||||
### v1.0.3
|
||||
### v0.0.3
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2380,17 +2400,17 @@ allowed-tools: process file_read grep_tool
|
||||
| **기본 앱 별칭 강화** | `note`, `txt` → 메모장, `msword`/`msexcel`/`mspowerpoint` + 확장자(`docx`, `xlsx`, `pptx`, `csv`, `doc`, `xls`, `ppt`) → 해당 Office 앱. Score 부스트(95)로 항상 최상단 표시 |
|
||||
| **인스톨러 UI 아이콘** | 폼 아이콘(타이틀바+작업표시줄)에 다이아몬드 픽셀 아이콘 반영 |
|
||||
| **Help 창 확대** | 880→1020px 너비 확대 + 카테고리 탭 패딩 축소 → 가로 스크롤 없이 모든 탭 표시 |
|
||||
| **Help 개요 갱신** | 개요 문구에 v1.0.3 표기, 폴더 검색·루틴·일지·한글 앱 실행 기능 반영, 웹검색 예시(`?n` 네이버) 추가 |
|
||||
| **Help 개요 갱신** | 개요 문구에 v0.0.3 표기, 폴더 검색·루틴·일지·한글 앱 실행 기능 반영, 웹검색 예시(`?n` 네이버) 추가 |
|
||||
| **코드 품질 개선** | ShowIndexingProgress 오버레이 누수 수정(finally 제거), RunHandler Process.Dispose, IndexService volatile, HelpDetailWindow 상수 추출, SetupForm Icon null 체크 |
|
||||
|
||||
### v1.0.2
|
||||
### v0.0.2
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
| **빠른 실행 Placeholder** | 입력 필드에 힌트 텍스트 표시 (키워드, 표시 이름, 경로). ModernTextBox 템플릿에 `Tag` 기반 워터마크 추가 |
|
||||
| **기본 앱 별칭 19종** | 한글+영문 이름으로 즉시 실행: 메모장/notepad, 계산기/calc, 엑셀/excel, 워드/word, 파워포인트/ppt, 탐색기/explorer, cmd, powershell, 그림판/paint, 캡처/snip, Edge, Teams, VS Code, Outlook, 원격/rdp, 작업관리자/taskmgr 등. 실제 설치된 앱만 자동 감지 |
|
||||
|
||||
### v1.0.1
|
||||
### v0.0.1
|
||||
|
||||
| 구분 | 내용 |
|
||||
|------|------|
|
||||
@@ -2404,7 +2424,7 @@ allowed-tools: process file_read grep_tool
|
||||
| **언어 라벨** | 설정 → Language (영어 표기로 변경, 다국어 사용자 접근성) |
|
||||
| **버그 수정** | HelpDetailWindow 인기 탭 연산자 우선순위 버그 (`&&`/`||`), DispatcherTimer 중복 생성 방지, Installer nullable 경고 13개 해소 |
|
||||
|
||||
### v1.0.0
|
||||
### v0.0.0
|
||||
|
||||
정식 릴리즈. 40개+ 명령어, 9종 테마, 11개 설정 탭, 클립보드 DPAPI 암호화, 잠금 해제 알림, 화면 캡처, 모던 트레이 메뉴, 설정 가져오기/내보내기.
|
||||
|
||||
@@ -2535,7 +2555,7 @@ LLM 호출 █████████████████████
|
||||
|------|-----------|-----------|-------------|
|
||||
| 루프 구조 | while + SendWithToolsAsync | while + agent.step(state) | while + tool_use |
|
||||
| **반복당 LLM 호출** | **1회** | **1회** | **1회** |
|
||||
| **검증 강제** | **✅ v1.7.1 구현** | ❌ 없음 | ❌ 없음 |
|
||||
| **검증 강제** | **✅ v0.7.1 구현** | ❌ 없음 | ❌ 없음 |
|
||||
| 계획 단계 | PlanMode 3모드 | 없음 (implicit) | 없음 |
|
||||
| 종료 조건 | 도구 호출 없음 | AgentFinishAction | 도구 호출 없음 |
|
||||
| 자기 반성 | Self-Reflection 프롬프트 | 없음 | 없음 |
|
||||
@@ -2595,7 +2615,7 @@ while budget > 0:
|
||||
|
||||
### 효과
|
||||
|
||||
| 관점 | Before (v1.7.0) | After (v1.7.1) |
|
||||
| 관점 | Before (v0.7.0) | After (v0.7.1) |
|
||||
|------|-----------------|-----------------|
|
||||
| 문서 생성 후 확인 | LLM 자율 판단 (대부분 생략) | 강제 확인 + 수정 |
|
||||
| 반복당 최소 LLM 호출 | 1회 | 문서 생성 시 2회 |
|
||||
@@ -2687,7 +2707,7 @@ else:
|
||||
|
||||
| 단계 | 내용 | 공수 |
|
||||
|------|------|------|
|
||||
| 현재 (v1.6.1) | 스킬 프롬프트에서 양식 자동 감지 안내 | 완료 |
|
||||
| 현재 (v0.6.1) | 스킬 프롬프트에서 양식 자동 감지 안내 | 완료 |
|
||||
| 다음 | 시스템 프롬프트에 양식 목록 자동 주입 (BuildCoworkSystemPrompt) | 낮음 |
|
||||
| 장기 | `.ax/templates/` 공용 양식 폴더 + 프로젝트 규칙에서 기본 양식 지정 | 중간 |
|
||||
|
||||
@@ -2790,3 +2810,10 @@ else:
|
||||
### 4) 품질 게이트
|
||||
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
|
||||
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 통과 (421 passed, 0 failed).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
# AX Commander 로드맵 (전면 재작성)
|
||||
# AX Commander 로드맵 (전면 재작성)
|
||||
|
||||
업데이트: 2026-04-04 10:05 (KST)
|
||||
|
||||
## 1. 보존 이력 (요약만 유지)
|
||||
- v1.5.0: Everything 연동, Dock Bar, 파일대화상자 연동, 클립보드 고도화, 플러그인 ZIP 설치.
|
||||
- v1.5.3: 클립보드 이미지 원본 보존/복원, Shift+Enter 자동복사, 설정 UX 개선.
|
||||
- v0.5.0: Everything 연동, Dock Bar, 파일대화상자 연동, 클립보드 고도화, 플러그인 ZIP 설치.
|
||||
- v0.5.3: 클립보드 이미지 원본 보존/복원, Shift+Enter 자동복사, 설정 UX 개선.
|
||||
|
||||
## 2. 재작성 기준
|
||||
- 런처는 AX Agent 실행 품질을 끌어올리는 입력 허브로 재정의.
|
||||
- claw-code의 명령 중심 워크플로우를 AX Commander UX에 맞게 흡수.
|
||||
|
||||
## 3. 2026 실행 계획 (v1.7.3 ~ v1.8.x)
|
||||
## 3. 2026 실행 계획 (v0.7.3 ~ v0.8.x)
|
||||
|
||||
### 완료 이력
|
||||
- [완료] Phase L2-3 클립보드 이미지 미리보기 창 구현
|
||||
- `ClipboardImagePreviewWindow.xaml / .xaml.cs` 신규 추가
|
||||
- 원본 해상도 표시, `Ctrl+휠`/`+`/`-`/`0`/`F`/`Esc` 줌 단축키 지원
|
||||
- PNG·JPEG·BMP 저장, 클립보드 복사 지원
|
||||
- `LauncherWindow`에서 `#` 이미지 항목 `Shift+Enter`로 전용 미리보기 창 열기
|
||||
- 단축키 도움말 갱신 완료
|
||||
|
||||
### Phase L-A 입력 라우팅 정교화
|
||||
- 목표
|
||||
|
||||
214
src/AxCopilot/Views/ClipboardImagePreviewWindow.xaml
Normal file
214
src/AxCopilot/Views/ClipboardImagePreviewWindow.xaml
Normal file
@@ -0,0 +1,214 @@
|
||||
<Window x:Class="AxCopilot.Views.ClipboardImagePreviewWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="클립보드 이미지 미리보기"
|
||||
Width="1080"
|
||||
Height="760"
|
||||
MinWidth="760"
|
||||
MinHeight="560"
|
||||
WindowStyle="None"
|
||||
AllowsTransparency="True"
|
||||
ResizeMode="CanResizeWithGrip"
|
||||
Background="Transparent"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
KeyDown="Window_KeyDown">
|
||||
<Grid Margin="14">
|
||||
<Border CornerRadius="18"
|
||||
Background="{DynamicResource LauncherBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="1">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="24" ShadowDepth="4" Opacity="0.22" Color="Black"/>
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
|
||||
<Border Background="{DynamicResource LauncherBackground}"
|
||||
CornerRadius="18"
|
||||
ClipToBounds="True">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="56"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="44"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Grid.Row="0"
|
||||
CornerRadius="18,18,0,0"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="0,0,0,1"
|
||||
MouseLeftButtonDown="TitleBar_MouseLeftButtonDown">
|
||||
<Grid Margin="18,0,12,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Border Background="{DynamicResource AccentColor}"
|
||||
CornerRadius="8"
|
||||
Padding="7,4"
|
||||
Margin="0,0,10,0">
|
||||
<TextBlock Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="14"
|
||||
Foreground="White"/>
|
||||
</Border>
|
||||
<StackPanel>
|
||||
<TextBlock x:Name="TitleText"
|
||||
Text="클립보드 이미지 미리보기"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource PrimaryText}"/>
|
||||
<TextBlock x:Name="MetaText"
|
||||
Text="원본 이미지"
|
||||
Margin="0,2,0,0"
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource SecondaryText}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Center">
|
||||
<Border Width="34"
|
||||
Height="34"
|
||||
Margin="0,0,6,0"
|
||||
Background="Transparent"
|
||||
CornerRadius="9"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonUp="BtnResetZoom_MouseLeftButtonUp">
|
||||
<TextBlock Text="100%"
|
||||
FontSize="10.5"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<Border Width="34"
|
||||
Height="34"
|
||||
Background="Transparent"
|
||||
CornerRadius="9"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonUp="BtnClose_MouseLeftButtonUp">
|
||||
<TextBlock Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="10"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="1"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Padding="16,12">
|
||||
<WrapPanel VerticalAlignment="Center" ItemHeight="36">
|
||||
<Button x:Name="BtnCopyImage"
|
||||
Content="클립보드 복사"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="108"
|
||||
Click="BtnCopyImage_Click"/>
|
||||
<Button x:Name="BtnSavePng"
|
||||
Content="PNG 저장"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="96"
|
||||
Click="BtnSavePng_Click"/>
|
||||
<Button x:Name="BtnSaveJpeg"
|
||||
Content="JPEG 저장"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="96"
|
||||
Click="BtnSaveJpeg_Click"/>
|
||||
<Button x:Name="BtnSaveBmp"
|
||||
Content="BMP 저장"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="96"
|
||||
Click="BtnSaveBmp_Click"/>
|
||||
<Button x:Name="BtnZoomIn"
|
||||
Content="확대"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="72"
|
||||
Click="BtnZoomIn_Click"/>
|
||||
<Button x:Name="BtnZoomOut"
|
||||
Content="축소"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="72"
|
||||
Click="BtnZoomOut_Click"/>
|
||||
<Button x:Name="BtnFit"
|
||||
Content="창에 맞춤"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="96"
|
||||
Click="BtnFit_Click"/>
|
||||
</WrapPanel>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="2"
|
||||
Background="{DynamicResource LauncherBackground}">
|
||||
<Grid Margin="14">
|
||||
<Border CornerRadius="16"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="1">
|
||||
<ScrollViewer x:Name="ImageScrollViewer"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
PreviewMouseWheel="ImageScrollViewer_PreviewMouseWheel"
|
||||
SizeChanged="ImageScrollViewer_SizeChanged">
|
||||
<Grid x:Name="ImageHost"
|
||||
Background="{DynamicResource LauncherBackground}"
|
||||
Width="{Binding ElementName=ImageScrollViewer, Path=ViewportWidth}"
|
||||
Height="{Binding ElementName=ImageScrollViewer, Path=ViewportHeight}">
|
||||
<Image x:Name="PreviewImage"
|
||||
Stretch="None"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
RenderOptions.BitmapScalingMode="HighQuality">
|
||||
<Image.RenderTransform>
|
||||
<ScaleTransform x:Name="ImageScaleTransform"
|
||||
ScaleX="1"
|
||||
ScaleY="1"/>
|
||||
</Image.RenderTransform>
|
||||
</Image>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="3"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="0,1,0,0"
|
||||
Padding="16,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="StatusText"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="11.5"
|
||||
Foreground="{DynamicResource SecondaryText}"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
Text="Ctrl+휠 확대/축소 · + / - · 0 원본 · F 맞춤 · Esc 닫기"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
226
src/AxCopilot/Views/ClipboardImagePreviewWindow.xaml.cs
Normal file
226
src/AxCopilot/Views/ClipboardImagePreviewWindow.xaml.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
/// <summary>클립보드 이미지 전용 미리보기 창. 원본 해상도 기준 줌과 저장을 지원합니다.</summary>
|
||||
public partial class ClipboardImagePreviewWindow : Window
|
||||
{
|
||||
private const double MinZoom = 0.1;
|
||||
private const double MaxZoom = 8.0;
|
||||
private const double ZoomStep = 0.1;
|
||||
|
||||
private readonly BitmapSource _image;
|
||||
private readonly string? _sourcePath;
|
||||
private double _zoom = 1.0;
|
||||
private bool _fitToViewport = true;
|
||||
|
||||
public ClipboardImagePreviewWindow(BitmapSource image, string? sourcePath = null)
|
||||
{
|
||||
_image = image ?? throw new ArgumentNullException(nameof(image));
|
||||
_sourcePath = sourcePath;
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
PreviewImage.Source = _image;
|
||||
TitleText.Text = string.IsNullOrWhiteSpace(sourcePath)
|
||||
? "클립보드 이미지 미리보기"
|
||||
: Path.GetFileName(sourcePath);
|
||||
MetaText.Text = $"{_image.PixelWidth:N0} × {_image.PixelHeight:N0}px";
|
||||
|
||||
Loaded += (_, _) =>
|
||||
{
|
||||
ApplyFitToViewport();
|
||||
UpdateStatusText();
|
||||
};
|
||||
}
|
||||
|
||||
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ClickCount == 2)
|
||||
{
|
||||
WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
||||
return;
|
||||
}
|
||||
|
||||
try { DragMove(); } catch { }
|
||||
}
|
||||
|
||||
private void Window_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Escape:
|
||||
Close();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.Add:
|
||||
case Key.OemPlus:
|
||||
IncreaseZoom();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.Subtract:
|
||||
case Key.OemMinus:
|
||||
DecreaseZoom();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.D0:
|
||||
case Key.NumPad0:
|
||||
ResetZoom();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.F:
|
||||
ApplyFitToViewport();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.C when Keyboard.Modifiers == ModifierKeys.Control:
|
||||
CopyImageToClipboard();
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void ImageScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
if ((Keyboard.Modifiers & ModifierKeys.Control) == 0)
|
||||
return;
|
||||
|
||||
if (e.Delta > 0)
|
||||
IncreaseZoom();
|
||||
else if (e.Delta < 0)
|
||||
DecreaseZoom();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void ImageScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (_fitToViewport)
|
||||
ApplyFitToViewport();
|
||||
}
|
||||
|
||||
private void BtnClose_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => Close();
|
||||
private void BtnResetZoom_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ResetZoom();
|
||||
private void BtnZoomIn_Click(object sender, RoutedEventArgs e) => IncreaseZoom();
|
||||
private void BtnZoomOut_Click(object sender, RoutedEventArgs e) => DecreaseZoom();
|
||||
private void BtnFit_Click(object sender, RoutedEventArgs e) => ApplyFitToViewport();
|
||||
private void BtnCopyImage_Click(object sender, RoutedEventArgs e) => CopyImageToClipboard();
|
||||
private void BtnSavePng_Click(object sender, RoutedEventArgs e) => SaveImage("png");
|
||||
private void BtnSaveJpeg_Click(object sender, RoutedEventArgs e) => SaveImage("jpg");
|
||||
private void BtnSaveBmp_Click(object sender, RoutedEventArgs e) => SaveImage("bmp");
|
||||
|
||||
private void IncreaseZoom() => SetZoom(_zoom + ZoomStep, false);
|
||||
private void DecreaseZoom() => SetZoom(_zoom - ZoomStep, false);
|
||||
private void ResetZoom() => SetZoom(1.0, false);
|
||||
|
||||
private void ApplyFitToViewport()
|
||||
{
|
||||
if (ImageScrollViewer.ViewportWidth <= 0 || ImageScrollViewer.ViewportHeight <= 0)
|
||||
return;
|
||||
|
||||
var availableWidth = Math.Max(1, ImageScrollViewer.ViewportWidth - 32);
|
||||
var availableHeight = Math.Max(1, ImageScrollViewer.ViewportHeight - 32);
|
||||
|
||||
var scaleX = availableWidth / _image.PixelWidth;
|
||||
var scaleY = availableHeight / _image.PixelHeight;
|
||||
var fitScale = Math.Min(scaleX, scaleY);
|
||||
|
||||
if (double.IsNaN(fitScale) || double.IsInfinity(fitScale) || fitScale <= 0)
|
||||
fitScale = 1.0;
|
||||
|
||||
SetZoom(Math.Min(1.0, fitScale), true);
|
||||
}
|
||||
|
||||
private void SetZoom(double zoom, bool fitToViewport)
|
||||
{
|
||||
_fitToViewport = fitToViewport;
|
||||
_zoom = Math.Max(MinZoom, Math.Min(MaxZoom, zoom));
|
||||
ImageScaleTransform.ScaleX = _zoom;
|
||||
ImageScaleTransform.ScaleY = _zoom;
|
||||
UpdateStatusText();
|
||||
}
|
||||
|
||||
private void UpdateStatusText()
|
||||
{
|
||||
var mode = _fitToViewport ? "창 맞춤" : "수동 줌";
|
||||
var source = string.IsNullOrWhiteSpace(_sourcePath) ? "원본 경로 없음" : _sourcePath;
|
||||
StatusText.Text = $"{_image.PixelWidth:N0} × {_image.PixelHeight:N0}px · 확대 {Math.Round(_zoom * 100)}% · {mode} · {source}";
|
||||
}
|
||||
|
||||
private void CopyImageToClipboard()
|
||||
{
|
||||
try
|
||||
{
|
||||
var app = Application.Current as App;
|
||||
app?.ClipboardHistoryService?.SuppressNextCapture();
|
||||
Clipboard.SetImage(_image);
|
||||
CustomMessageBox.Show("이미지를 클립보드에 복사했습니다.", "AX Commander", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Services.LogService.Warn($"클립보드 이미지 복사 실패: {ex.Message}");
|
||||
CustomMessageBox.Show($"이미지 복사에 실패했습니다.\n{ex.Message}", "AX Commander", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveImage(string format)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dialog = new SaveFileDialog
|
||||
{
|
||||
FileName = BuildDefaultFileName(format),
|
||||
Filter = format switch
|
||||
{
|
||||
"png" => "PNG 이미지|*.png",
|
||||
"jpg" => "JPEG 이미지|*.jpg;*.jpeg",
|
||||
"bmp" => "BMP 이미지|*.bmp",
|
||||
_ => "이미지 파일|*.*",
|
||||
},
|
||||
AddExtension = true,
|
||||
OverwritePrompt = true,
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog(this) != true)
|
||||
return;
|
||||
|
||||
BitmapEncoder encoder = format switch
|
||||
{
|
||||
"jpg" => new JpegBitmapEncoder { QualityLevel = 95 },
|
||||
"bmp" => new BmpBitmapEncoder(),
|
||||
_ => new PngBitmapEncoder(),
|
||||
};
|
||||
|
||||
encoder.Frames.Add(BitmapFrame.Create(_image));
|
||||
using var stream = new FileStream(dialog.FileName, FileMode.Create, FileAccess.Write);
|
||||
encoder.Save(stream);
|
||||
|
||||
CustomMessageBox.Show($"이미지를 저장했습니다.\n{dialog.FileName}", "AX Commander", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Services.LogService.Warn($"클립보드 이미지 저장 실패: {ex.Message}");
|
||||
CustomMessageBox.Show($"이미지 저장에 실패했습니다.\n{ex.Message}", "AX Commander", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private string BuildDefaultFileName(string format)
|
||||
{
|
||||
var sourceName = !string.IsNullOrWhiteSpace(_sourcePath)
|
||||
? Path.GetFileNameWithoutExtension(_sourcePath)
|
||||
: $"clipboard-image-{DateTime.Now:yyyyMMdd-HHmmss}";
|
||||
|
||||
var extension = format switch
|
||||
{
|
||||
"jpg" => ".jpg",
|
||||
"bmp" => ".bmp",
|
||||
_ => ".png",
|
||||
};
|
||||
|
||||
return sourceName + extension;
|
||||
}
|
||||
}
|
||||
29
src/AxCopilot/Views/LauncherWindow.Keyboard.cs
Normal file
29
src/AxCopilot/Views/LauncherWindow.Keyboard.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
public partial class LauncherWindow
|
||||
{
|
||||
private bool TryOpenClipboardImagePreview()
|
||||
{
|
||||
if (_vm.SelectedItem?.Data is not Services.ClipboardEntry clipEntry || clipEntry.IsText)
|
||||
return false;
|
||||
|
||||
var originalImage = Services.ClipboardHistoryService.LoadOriginalImage(clipEntry.OriginalImagePath);
|
||||
BitmapSource? imageToPreview = originalImage ?? clipEntry.Image;
|
||||
if (imageToPreview == null)
|
||||
return false;
|
||||
|
||||
Hide();
|
||||
|
||||
var preview = new ClipboardImagePreviewWindow(imageToPreview, clipEntry.OriginalImagePath)
|
||||
{
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
||||
};
|
||||
preview.Resources.MergedDictionaries.Add(Resources);
|
||||
preview.Show();
|
||||
preview.Activate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ using System.Windows.Media.Animation;
|
||||
using Microsoft.Win32;
|
||||
using AxCopilot.Models;
|
||||
using AxCopilot.ViewModels;
|
||||
using FormsCursor = System.Windows.Forms.Cursor;
|
||||
using FormsScreen = System.Windows.Forms.Screen;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
@@ -676,16 +678,20 @@ public partial class LauncherWindow : Window
|
||||
|
||||
private void CenterOnScreen()
|
||||
{
|
||||
var screen = SystemParameters.WorkArea;
|
||||
var monitor = FormsScreen.FromPoint(FormsCursor.Position);
|
||||
var transform = PresentationSource.FromVisual(this)?.CompositionTarget?.TransformFromDevice ?? Matrix.Identity;
|
||||
var topLeft = transform.Transform(new Point(monitor.WorkingArea.Left, monitor.WorkingArea.Top));
|
||||
var bottomRight = transform.Transform(new Point(monitor.WorkingArea.Right, monitor.WorkingArea.Bottom));
|
||||
var screen = new Rect(topLeft, bottomRight);
|
||||
// ActualHeight/ActualWidth는 첫 Show() 전 레이아웃 패스 이전에 0일 수 있음 → 기본값으로 보호
|
||||
var w = ActualWidth > 0 ? ActualWidth : 640;
|
||||
var h = ActualHeight > 0 ? ActualHeight : 80;
|
||||
Left = (screen.Width - w) / 2 + screen.Left;
|
||||
Left = screen.Left + (screen.Width - w) / 2;
|
||||
Top = _vm.WindowPosition switch
|
||||
{
|
||||
"center" => (screen.Height - h) / 2 + screen.Top,
|
||||
"bottom" => screen.Height * 0.75 + screen.Top,
|
||||
_ => screen.Height * 0.2 + screen.Top, // "center-top" (기본)
|
||||
"center" => screen.Top + (screen.Height - h) / 2,
|
||||
"bottom" => screen.Top + screen.Height * 0.75,
|
||||
_ => screen.Top + screen.Height * 0.2, // "center-top" (기본)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -863,6 +869,12 @@ public partial class LauncherWindow : Window
|
||||
|
||||
if (shift)
|
||||
{
|
||||
if (TryOpenClipboardImagePreview())
|
||||
{
|
||||
e.Handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// 퍼지 파일 검색 결과: Shift+Enter → 파일이 있는 폴더 열기
|
||||
if (_vm.SelectedItem?.Data is AxCopilot.Services.IndexEntry shiftEntry)
|
||||
{
|
||||
@@ -1297,7 +1309,7 @@ public partial class LauncherWindow : Window
|
||||
"Ctrl+Shift+E 탐색기에서 열기",
|
||||
"Ctrl+Enter 관리자 실행",
|
||||
"Alt+Enter 속성 보기",
|
||||
"Shift+Enter 대형 텍스트",
|
||||
"Shift+Enter 대형 텍스트 / 클립보드 이미지 미리보기",
|
||||
};
|
||||
|
||||
CustomMessageBox.Show(
|
||||
|
||||
@@ -83,7 +83,7 @@ public partial class ShortcutHelpWindow : Window
|
||||
new ShortcutRow("Ctrl+K", "이 단축키 참조 창 열기", "\uE8FD", "#4B5EFC"),
|
||||
new ShortcutRow("Ctrl+,", "설정 창 열기", "\uE713", "#4B5EFC"),
|
||||
new ShortcutRow("F5", "파일 인덱스 즉시 재구축", "\uE72C", "#107C10"),
|
||||
new ShortcutRow("Shift+Enter", "Large Type / 병합 실행 / 캡처 모드: 지연 캡처(3/5/10초) 타이머", "\uE8A7", "#7B68EE"),
|
||||
new ShortcutRow("Shift+Enter", "클립보드 이미지 미리보기 / Large Type / 병합 실행 / 캡처 모드 지연 타이머", "\uE8A7", "#7B68EE"),
|
||||
};
|
||||
|
||||
// ── 입력 예약어 ───────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user