feat: AI 채팅 패널 (Claude API)
- 백엔드 modules/ai: POST /ai/chat — Anthropic Messages API 프록시(키 서버 env 한정, 30s 타임아웃, throttle 20/분, 미설정 503/외부오류 502) - ChatDto 검증(role enum, content 8000자, 메시지 50개 상한), 모델 CLAUDE_MODEL(기본 claude-sonnet-4-6) - 프론트 AgentChatPanel: 우측 슬라이드 채팅(말풍선/타이핑/에러/새 대화), plain text 렌더로 XSS 안전 - AppShell 헤더에 AI 버튼 상시 노출 — 모든 화면에서 열림 - 대화 이력은 stores/ai.store(싱글톤)에 보관 → 화면 이동에도 유지, '새 대화'로만 초기화 - TaskDetailPage 의 기존 목업 에이전트 패널 전부 제거(보안 L1 해소) - env.example 에 CLAUDE_MODEL 추가 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,12 +7,16 @@ import { useRoute, useRouter, RouterLink } from 'vue-router'
|
||||
import { useAuthStore } from '@/stores/auth.store'
|
||||
import { useNotificationStore } from '@/stores/notification.store'
|
||||
import UserAvatar from '@/components/UserAvatar.vue'
|
||||
import AgentChatPanel from '@/components/AgentChatPanel.vue'
|
||||
import type { NotificationView } from '@/types/notification'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
// AI 채팅 패널 — 모든 화면 헤더에서 열 수 있다
|
||||
const agentOpen = ref(false)
|
||||
|
||||
// 현재 경로 기준으로 상단 네비 활성 항목을 판별
|
||||
const activeNav = computed<'tasks' | 'repos'>(() =>
|
||||
route.path.startsWith('/repos') ? 'repos' : 'tasks',
|
||||
@@ -86,9 +90,32 @@ async function onLogout() {
|
||||
</nav>
|
||||
|
||||
<div class="topbar-right">
|
||||
<!-- 화면별 추가 액션(예: AI 에이전트 버튼)을 끼워 넣는 슬롯 -->
|
||||
<!-- 화면별 추가 액션을 끼워 넣는 슬롯 -->
|
||||
<slot name="actions" />
|
||||
|
||||
<!-- AI 어시스턴트 — 모든 화면에서 상시 노출 -->
|
||||
<button
|
||||
class="icon-btn agent"
|
||||
type="button"
|
||||
title="AI 어시스턴트"
|
||||
aria-label="AI 어시스턴트"
|
||||
@click="agentOpen = true"
|
||||
>
|
||||
<svg
|
||||
width="17"
|
||||
height="17"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M12 3 13.4 8.6 19 10l-5.6 1.4L12 17l-1.4-5.6L5 10l5.6-1.4Z" />
|
||||
<path d="M18 16l.7 2.3L21 19l-2.3.7L18 22l-.7-2.3L15 19l2.3-.7Z" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="icon-btn"
|
||||
type="button"
|
||||
@@ -263,6 +290,12 @@ async function onLogout() {
|
||||
</header>
|
||||
|
||||
<slot />
|
||||
|
||||
<!-- AI 채팅 패널 — 헤더 어디서든 열림 -->
|
||||
<AgentChatPanel
|
||||
:open="agentOpen"
|
||||
@close="agentOpen = false"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -348,6 +381,14 @@ async function onLogout() {
|
||||
background: #f1f2f4;
|
||||
color: var(--text);
|
||||
}
|
||||
/* AI 어시스턴트 버튼 강조 */
|
||||
.icon-btn.agent {
|
||||
color: var(--accent);
|
||||
}
|
||||
.icon-btn.agent:hover {
|
||||
background: var(--accent-weak);
|
||||
color: var(--accent-hover);
|
||||
}
|
||||
/* 알림 종 + 드롭다운 */
|
||||
.noti-wrap {
|
||||
position: relative;
|
||||
|
||||
Reference in New Issue
Block a user