diff --git a/src/main/ai/AiWorker.ts b/src/main/ai/AiWorker.ts index 73a4b83..76718dc 100644 --- a/src/main/ai/AiWorker.ts +++ b/src/main/ai/AiWorker.ts @@ -140,15 +140,18 @@ export class AiWorker { const candidates = parseAllCandidates(note.rawText, todayDate); const vocab = this.repo.getTopUsedTags(VOCAB_TOP_N); // v0.3.1 Cut F — vision path: visionModel + note.media → base64 images + // final review fix: note.media[].bytes 로 fast-fail (readFile/base64 비용 회피). + // 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 oversize = note.media.find((m) => m.bytes > 5 * 1024 * 1024); + if (oversize) { + throw new Error(`image ${oversize.relPath} exceeds 5MB cap (${oversize.bytes} bytes)`); + } images = await Promise.all( note.media.map(async (m) => { const buf = await readFile(this.mediaStore!.absolutePath(m.relPath)); - if (buf.byteLength > 5 * 1024 * 1024) { - throw new Error(`image ${m.relPath} exceeds 5MB cap`); - } return { base64: buf.toString('base64'), mime: m.mime }; }) ); diff --git a/src/main/ipc/settingsApi.ts b/src/main/ipc/settingsApi.ts index 8294a11..1214ef5 100644 --- a/src/main/ipc/settingsApi.ts +++ b/src/main/ipc/settingsApi.ts @@ -14,6 +14,7 @@ import type { SyncTimer } from '../services/SyncTimer.js'; import { collectAutostartState } from '../services/AutostartDiagnostic.js'; import { getInboxWindow as getInboxWindowSingleton } from '../windows/inboxWindow.js'; import { refreshVisionCache } from '../services/VisionDetect.js'; +import { DEFAULT_OLLAMA_ENDPOINT } from '../../shared/constants.js'; /** * 외부 (트레이 / second-instance / 기타 main 프로세스 호출자) 에서 inbox 창에 view 전환을 @@ -395,11 +396,13 @@ export function registerSettingsApi(deps?: SettingsIpcDeps): void { }); ipcMain.handle('settings:refresh-vision-cache', async () => { + // Cut F final review fix — index.ts 의 resolvedEndpoint (settings → env → default) + // 와 동일한 fallback 체인 사용. settings.ollama 미설정 + env / default 만 있는 dev + // 환경에서도 manual "다시 감지" 가 동작하도록. const all = await deps.settings.getAll(); - const endpoint = all.ollama?.endpoint; - if (!endpoint) { - return { ok: false as const, reason: 'no_endpoint' }; - } + const endpoint = all.ollama?.endpoint + ?? process.env.INKLING_OLLAMA_ENDPOINT + ?? DEFAULT_OLLAMA_ENDPOINT; return refreshVisionCache({ settings: deps.settings, endpoint }); }); }