revert: AI 코드 검토 기능 제거 (85ae82f 되돌림)
통짜 코드 전송 방식이 토큰 비효율·부정확해, 검색 기반(grep으로 좁힌 뒤 관련
스니펫만 판정) 방식으로 재설계하기 위해 일괄 제거. 추후 개선안으로 재작업 예정.
This reverts commit 85ae82f.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { useApi } from './useApi'
|
||||
import type {
|
||||
ChecklistReviewResult,
|
||||
ConversationDetail,
|
||||
ConversationSummary,
|
||||
SendResult,
|
||||
@@ -56,17 +55,6 @@ export function useAi() {
|
||||
})) as unknown as SuggestChecklistResult
|
||||
}
|
||||
|
||||
// 코드 검토 — 체크리스트 구현 여부 판정(서버가 체크리스트에 반영). 코드 양에 따라 오래 걸림
|
||||
async function reviewChecklist(payload: {
|
||||
repoId: string
|
||||
taskSeq: number
|
||||
}): Promise<ChecklistReviewResult> {
|
||||
return (await api.post('/ai/review-checklist', payload, {
|
||||
silent: true,
|
||||
timeout: 90_000,
|
||||
})) as unknown as ChecklistReviewResult
|
||||
}
|
||||
|
||||
return {
|
||||
listConversations,
|
||||
getConversation,
|
||||
@@ -74,6 +62,5 @@ export function useAi() {
|
||||
sendMessage,
|
||||
deleteConversation,
|
||||
suggestChecklist,
|
||||
reviewChecklist,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ export interface ChecklistItem {
|
||||
id?: string
|
||||
text: string
|
||||
done: boolean
|
||||
/** AI 코드 검토 판정 — 'done'(구현) | 'missing'(미구현) | null(미검토) */
|
||||
reviewVerdict?: 'done' | 'missing' | null
|
||||
}
|
||||
|
||||
/** 저장소 */
|
||||
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
} from '@/mock/relay.mock'
|
||||
import { useTaskStore } from '@/stores/task.store'
|
||||
import { useAuthStore } from '@/stores/auth.store'
|
||||
import { useAi } from '@/composables/useAi'
|
||||
import UserAvatar from '@/components/UserAvatar.vue'
|
||||
import { attachmentKindOf, fileBadge } from '@/shared/utils/format'
|
||||
|
||||
@@ -32,7 +31,6 @@ const taskId = computed(() => Number(route.params.taskId))
|
||||
|
||||
const taskStore = useTaskStore()
|
||||
const authStore = useAuthStore()
|
||||
const ai = useAi()
|
||||
|
||||
// 업무 상세 — API 연동
|
||||
const task = ref<TaskDetail | null>(null)
|
||||
@@ -171,33 +169,6 @@ async function sendApproval() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- AI 코드 검토 ---
|
||||
// 연결된 Gitea 코드를 검토해 체크리스트 항목별 구현 여부(✓/✗)를 채운다.
|
||||
const aiReviewing = ref(false)
|
||||
const aiReviewSummary = ref<string | null>(null)
|
||||
const aiReviewTruncated = ref(false)
|
||||
async function runAiReview() {
|
||||
if (!task.value || aiReviewing.value) return
|
||||
aiReviewing.value = true
|
||||
aiReviewSummary.value = null
|
||||
try {
|
||||
const result = await ai.reviewChecklist({
|
||||
repoId: repoId.value,
|
||||
taskSeq: task.value.id,
|
||||
})
|
||||
aiReviewSummary.value = result.summary
|
||||
aiReviewTruncated.value = result.truncated
|
||||
// 서버가 체크리스트에 판정을 반영했으므로 상세를 다시 불러와 ✓/✗ 갱신
|
||||
await loadTask()
|
||||
} catch {
|
||||
window.alert(
|
||||
'AI 코드 검토에 실패했습니다. Gitea 연결 상태를 확인하거나 잠시 후 다시 시도해 주세요.',
|
||||
)
|
||||
} finally {
|
||||
aiReviewing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 댓글 / 활동 탭
|
||||
* ============================================================ */
|
||||
@@ -515,48 +486,20 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
</div>
|
||||
<!--
|
||||
체크리스트는 읽기 전용 — 사용자가 개별 토글/추가/삭제하지 않는다.
|
||||
완료 처리는 승인 워크플로우(승인 완료 시 일괄 완료) 또는 AI 코드 검토로 채워진다.
|
||||
완료 처리는 승인 워크플로우(승인 완료 시 일괄 완료)로만 이루어진다.
|
||||
-->
|
||||
<div
|
||||
v-if="aiReviewSummary"
|
||||
class="ai-review-summary"
|
||||
>
|
||||
<svg
|
||||
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" /></svg>
|
||||
<span>{{ aiReviewSummary }}<template v-if="aiReviewTruncated"> (코드 일부만 검토됨)</template></span>
|
||||
</div>
|
||||
<div class="checklist">
|
||||
<div
|
||||
v-for="(item, i) in task.checklist"
|
||||
:key="item.id ?? i"
|
||||
class="citem"
|
||||
:class="{ done: item.done, missing: item.reviewVerdict === 'missing' }"
|
||||
:title="item.reviewVerdict === 'missing' ? '미구현으로 판정됨' : undefined"
|
||||
:class="{ done: item.done }"
|
||||
>
|
||||
<span
|
||||
class="cbox"
|
||||
:class="{
|
||||
done: item.done,
|
||||
missing: item.reviewVerdict === 'missing',
|
||||
}"
|
||||
:class="{ done: item.done }"
|
||||
>
|
||||
<svg
|
||||
v-if="item.reviewVerdict === 'missing'"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="3.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
><path d="M18 6 6 18M6 6l12 12" /></svg>
|
||||
<svg
|
||||
v-else
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
@@ -921,23 +864,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
placeholder="승인 요청 메시지(선택) — 작업 내용이나 검토 포인트를 적어주세요."
|
||||
/>
|
||||
<div class="ap-card-actions">
|
||||
<button
|
||||
class="ap-btn ai-review"
|
||||
type="button"
|
||||
:disabled="aiReviewing"
|
||||
title="연결된 Gitea 코드를 검토해 체크리스트 구현 여부를 채웁니다"
|
||||
@click="runAiReview"
|
||||
>
|
||||
<svg
|
||||
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" /></svg>
|
||||
{{ aiReviewing ? '검토 중…' : 'AI 검토' }}
|
||||
</button>
|
||||
<button
|
||||
class="ap-btn request-send"
|
||||
type="button"
|
||||
@@ -985,23 +911,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
placeholder="보완 내용 메시지(선택)"
|
||||
/>
|
||||
<div class="ap-card-actions">
|
||||
<button
|
||||
class="ap-btn ai-review"
|
||||
type="button"
|
||||
:disabled="aiReviewing"
|
||||
title="연결된 Gitea 코드를 검토해 체크리스트 구현 여부를 채웁니다"
|
||||
@click="runAiReview"
|
||||
>
|
||||
<svg
|
||||
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" /></svg>
|
||||
{{ aiReviewing ? '검토 중…' : 'AI 검토' }}
|
||||
</button>
|
||||
<button
|
||||
class="ap-btn request-send"
|
||||
type="button"
|
||||
@@ -1588,18 +1497,13 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
background: var(--green);
|
||||
border-color: var(--green);
|
||||
}
|
||||
.cbox.missing {
|
||||
background: var(--red);
|
||||
border-color: var(--red);
|
||||
}
|
||||
.cbox svg {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
}
|
||||
.cbox.done svg,
|
||||
.cbox.missing svg {
|
||||
.cbox.done svg {
|
||||
opacity: 1;
|
||||
}
|
||||
.citem .ctext {
|
||||
@@ -1610,31 +1514,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
color: var(--text-3);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.citem.missing .ctext {
|
||||
color: var(--red);
|
||||
}
|
||||
|
||||
/* AI 코드 검토 요약 배너 */
|
||||
.ai-review-summary {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.4375rem;
|
||||
margin-bottom: 0.625rem;
|
||||
padding: 0.5625rem 0.75rem;
|
||||
background: var(--accent-weak);
|
||||
border: 1px solid var(--accent-border);
|
||||
border-radius: var(--radius);
|
||||
font-size: 0.781rem;
|
||||
line-height: 1.5;
|
||||
color: var(--text);
|
||||
}
|
||||
.ai-review-summary svg {
|
||||
width: 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
color: var(--accent);
|
||||
flex-shrink: 0;
|
||||
margin-top: 0.125rem;
|
||||
}
|
||||
|
||||
/* 댓글/활동 탭 */
|
||||
.thread-tabs {
|
||||
@@ -2370,18 +2249,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
.ap-btn.request-send:hover {
|
||||
background: var(--accent-hover);
|
||||
}
|
||||
.ap-btn.ai-review {
|
||||
color: var(--accent);
|
||||
background: var(--accent-weak);
|
||||
border-color: var(--accent-border);
|
||||
}
|
||||
.ap-btn.ai-review:hover:not(:disabled) {
|
||||
background: #e7e4fb;
|
||||
}
|
||||
.ap-btn.ai-review:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* ===== 5단계: 첨부파일 ===== */
|
||||
.files-head {
|
||||
|
||||
@@ -176,12 +176,7 @@ function toTaskDetailView(api: ApiTaskDetail): TaskDetailView {
|
||||
status: api.status,
|
||||
statusLabel: taskStatusLabel(api.status),
|
||||
content: api.content,
|
||||
checklist: api.checklist.map((c) => ({
|
||||
id: c.id,
|
||||
text: c.text,
|
||||
done: c.done,
|
||||
reviewVerdict: c.reviewVerdict,
|
||||
})),
|
||||
checklist: api.checklist.map((c) => ({ id: c.id, text: c.text, done: c.done })),
|
||||
comments: api.comments.map((c) => toCommentView(c, issuerId)),
|
||||
activities: api.activities.map(toTaskActivityView),
|
||||
assignees: api.assignees.map(toUserView),
|
||||
|
||||
@@ -33,17 +33,3 @@ export interface ChecklistSuggestionGroup {
|
||||
export interface SuggestChecklistResult {
|
||||
groups: ChecklistSuggestionGroup[]
|
||||
}
|
||||
|
||||
// 코드 검토 — 항목별 판정 결과
|
||||
export type ReviewVerdict = 'done' | 'missing'
|
||||
export interface ChecklistReviewItem {
|
||||
id: string
|
||||
text: string
|
||||
verdict: ReviewVerdict
|
||||
reason: string
|
||||
}
|
||||
export interface ChecklistReviewResult {
|
||||
items: ChecklistReviewItem[]
|
||||
summary: string
|
||||
truncated: boolean
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ export interface ApiChecklistItem {
|
||||
id: string
|
||||
text: string
|
||||
done: boolean
|
||||
reviewVerdict: 'done' | 'missing' | null // AI 코드 검토 판정(미검토면 null)
|
||||
}
|
||||
|
||||
// 첨부파일(API 원시) — 백엔드 AttachmentResponse 와 1:1
|
||||
|
||||
Reference in New Issue
Block a user