feat(v029): ai_status 'disabled' enum + CaptureService ai_enabled 분기 (skip pending_jobs)
- AiStatus enum 'disabled' 추가 — settings.ai_enabled=false 일 때 새 노트의 초기 status.
- m005 migration: ai_status CHECK 제약을 ('pending','done','failed','disabled') 로 relax.
SQLite 가 ALTER COLUMN CHECK 미지원 → table recreate (notes_new INSERT SELECT DROP RENAME).
기존 인덱스 (idx_notes_created_at, idx_notes_ai_status, idx_notes_deleted_at) 재생성.
- SettingsService schema 에 ai_enabled / onboarding_completed (optional) 추가 +
isAiEnabled / setAiEnabled / isOnboardingCompleted / setOnboardingCompleted accessor.
기본 fallback (ai_enabled=true, onboarding_completed=false) — 기존 settings.json 무영향.
- NoteRepository.create 가 optional aiStatus 받도록 — 'pending' 외 값일 때 pending_jobs skip.
기존 caller (rawText 만 전달) 무영향.
- CaptureService deps 에 settings (좁은 AiEnabledSource 인터페이스) 추가.
submit() 가 ai_enabled 조회 → false 면 ai_status='disabled' insert + enqueue skip.
settings 미주입 시 기존 동작 (항상 enabled) 보존 — 테스트 케이스 무영향.
- main/index.ts wiring: settings: settingsSvc 주입.
Tests: 489 → 494 (CaptureService ai_enabled 2건 + m005 migration 3건). typecheck 0.
This commit is contained in:
@@ -2,6 +2,14 @@ import type { NoteRepository } from '../repository/NoteRepository.js';
|
||||
import type { MediaStore } from './MediaStore.js';
|
||||
import type { Note } from '@shared/types';
|
||||
|
||||
/**
|
||||
* v0.2.9 Cut B — CaptureService 가 ai_enabled 를 조회할 때만 의존하는 좁은 인터페이스.
|
||||
* SettingsService 직접 의존을 피해 테스트 mock 이 단순해짐 (entire SettingsService 면 불필요).
|
||||
*/
|
||||
export interface AiEnabledSource {
|
||||
isAiEnabled(): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface TelemetryEmitter {
|
||||
emit(input:
|
||||
| { kind: 'capture'; payload: { noteId: string; rawTextLength: number; hasMedia: boolean } }
|
||||
@@ -23,6 +31,9 @@ export interface CaptureDeps {
|
||||
enqueue: (noteId: string) => Promise<void>;
|
||||
celebrate: (noteId: string) => void;
|
||||
telemetry?: TelemetryEmitter;
|
||||
// v0.2.9 Cut B — settings.ai_enabled=false 면 새 노트는 ai_status='disabled' + enqueue skip.
|
||||
// 미주입 시 기존 동작 (항상 enabled) 보존 — 기존 caller 무영향.
|
||||
settings?: AiEnabledSource;
|
||||
}
|
||||
|
||||
export interface SubmitInput {
|
||||
@@ -44,7 +55,12 @@ export class CaptureService {
|
||||
if (trimmed.length === 0 && input.images.length === 0) {
|
||||
throw new Error('empty submission');
|
||||
}
|
||||
const { id } = this.repo.create({ rawText: input.text });
|
||||
// v0.2.9 Cut B — settings 미주입 시 기본 enabled (backward compat).
|
||||
const aiEnabled = this.deps.settings ? await this.deps.settings.isAiEnabled() : true;
|
||||
const { id } = this.repo.create({
|
||||
rawText: input.text,
|
||||
aiStatus: aiEnabled ? 'pending' : 'disabled'
|
||||
});
|
||||
if (input.images.length > 0) {
|
||||
const rows = [];
|
||||
for (const img of input.images) {
|
||||
@@ -70,7 +86,9 @@ export class CaptureService {
|
||||
}
|
||||
}).catch(() => {});
|
||||
}
|
||||
await this.deps.enqueue(id);
|
||||
if (aiEnabled) {
|
||||
await this.deps.enqueue(id);
|
||||
}
|
||||
this.deps.celebrate(id);
|
||||
return { noteId: id };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user