From e34f036f20a4452a6b952eba0b76269452fd0c9b Mon Sep 17 00:00:00 2001
From: th-kim0823
Date: Tue, 12 May 2026 14:44:41 +0900
Subject: [PATCH] =?UTF-8?q?fix(vision):=20graceful=20fallback=20=EA=B0=80?=
=?UTF-8?q?=EC=8B=9C=ED=99=94=20+=20=EC=A7=84=EB=8B=A8=20=EB=A1=9C?=
=?UTF-8?q?=EA=B7=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
이전 fix 후에도 사용자가 "(첨부 메모)" placeholder 만 보이면 왜 fail 한지 모름.
가능성 큰 원인: vision_model 미설정 → text-only path → 본문 빈 응답.
- AiWorker: ai.vision.decide 로그 추가 — visionActive / visionModelConfigured /
mediaCount / mediaStorePresent. logs/main.log 에서 진단 가능.
- NoteCard: ai_status='done' + title='(첨부 메모)' + media 있을 때 노란 banner.
"vision 모델 설정 확인 + 직접 편집" 안내.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
src/main/ai/AiWorker.ts | 12 +++++++++++-
src/renderer/inbox/components/NoteCard.tsx | 12 ++++++++++++
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/src/main/ai/AiWorker.ts b/src/main/ai/AiWorker.ts
index 9cb314f..73c4790 100644
--- a/src/main/ai/AiWorker.ts
+++ b/src/main/ai/AiWorker.ts
@@ -144,7 +144,17 @@ export class AiWorker {
// 5MB cap 초과 시 throw → AiWorker 의 'other' 분기 → markAiFailed 도달.
const visionModel = this.settings ? await this.settings.getVisionModel() : null;
let images: Array<{ base64: string; mime: string }> | undefined;
- if (visionModel && note.media.length > 0 && this.mediaStore) {
+ const visionActive = !!(visionModel && note.media.length > 0 && this.mediaStore);
+ // v0.3.14 — vision 활성 여부 진단 로그. 사용자가 vision_model 미설정으로 text-only
+ // path 가 도는지 / 이미지가 모델에 전달되는지 확인 가능 (logs/main.log).
+ this.logger.info('ai.vision.decide', {
+ noteId: job.noteId,
+ visionActive,
+ visionModelConfigured: !!visionModel,
+ mediaCount: note.media.length,
+ mediaStorePresent: !!this.mediaStore
+ });
+ if (visionActive) {
const oversize = note.media.find((m) => m.bytes > 5 * 1024 * 1024);
if (oversize) {
throw new Error(`image ${oversize.relPath} exceeds 5MB cap (${oversize.bytes} bytes)`);
diff --git a/src/renderer/inbox/components/NoteCard.tsx b/src/renderer/inbox/components/NoteCard.tsx
index 474dd59..80bf483 100644
--- a/src/renderer/inbox/components/NoteCard.tsx
+++ b/src/renderer/inbox/components/NoteCard.tsx
@@ -279,6 +279,18 @@ export function NoteCard({ note, onDeleted, onUpdated, mode = 'inbox', onRestore
{fallbackTitle}
)}
+ {/* v0.3.14 — graceful fallback 가시화. title 이 placeholder 면 vision 처리 실패
+ (모델 미선택 / 응답 unparseable / null 반환). 사용자가 설정 점검 + 수동 편집 유도. */}
+ {!isTrash && local.aiStatus === 'done' && local.aiTitle === '(첨부 메모)' && local.media.length > 0 && (
+
+ 💡 AI 가 이미지 내용을 정리하지 못했습니다. 설정 → AI 제공자 → Vision 섹션에서
+ vision-capable 모델 (예: gemma4:26b, gemma3:27b) 선택 여부 확인하세요.
+ 제목/요약을 직접 클릭해 수정 가능합니다.
+
+ )}
{local.aiStatus === 'done' && (
<>
{isTrash ? (