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:
@@ -8,7 +8,12 @@ const OllamaSettingsSchema = z.object({
|
||||
}).strict();
|
||||
|
||||
const SettingsSchema = z.object({
|
||||
ollama: OllamaSettingsSchema.optional()
|
||||
ollama: OllamaSettingsSchema.optional(),
|
||||
// v0.2.9 Cut B — AI-less mode toggle. 기존 settings 파일에 없으면 isAiEnabled() 가
|
||||
// true 로 fallback (기본 enabled). zod default 는 file 이 존재 + 키 부재일 때만 적용 —
|
||||
// load() 의 file-missing 분기에선 cache={} 라 isAiEnabled() 의 fallback 이 작동.
|
||||
ai_enabled: z.boolean().optional(),
|
||||
onboarding_completed: z.boolean().optional()
|
||||
}).strict();
|
||||
|
||||
export type Settings = z.infer<typeof SettingsSchema>;
|
||||
@@ -38,6 +43,37 @@ export class SettingsService {
|
||||
const validated = OllamaSettingsSchema.parse(value);
|
||||
const current = await this.load();
|
||||
const next: Settings = { ...current, ollama: validated };
|
||||
await this.persist(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* v0.2.9 Cut B — AI-less mode 의 기본값은 enabled (true). 기존 settings 파일을
|
||||
* 가진 사용자 (ai_enabled 키 부재) 도 무영향.
|
||||
*/
|
||||
async isAiEnabled(): Promise<boolean> {
|
||||
const s = await this.load();
|
||||
return s.ai_enabled ?? true;
|
||||
}
|
||||
|
||||
async setAiEnabled(value: boolean): Promise<void> {
|
||||
const current = await this.load();
|
||||
const next: Settings = { ...current, ai_enabled: value };
|
||||
await this.persist(next);
|
||||
}
|
||||
|
||||
/** v0.2.9 Cut B — 첫 실행 onboarding completion 표지. 기본 false. */
|
||||
async isOnboardingCompleted(): Promise<boolean> {
|
||||
const s = await this.load();
|
||||
return s.onboarding_completed ?? false;
|
||||
}
|
||||
|
||||
async setOnboardingCompleted(value: boolean): Promise<void> {
|
||||
const current = await this.load();
|
||||
const next: Settings = { ...current, onboarding_completed: value };
|
||||
await this.persist(next);
|
||||
}
|
||||
|
||||
private async persist(next: Settings): Promise<void> {
|
||||
await mkdir(dirname(this.filePath), { recursive: true });
|
||||
const tmpPath = this.filePath + '.tmp';
|
||||
await writeFile(tmpPath, JSON.stringify(next, null, 2), 'utf8');
|
||||
|
||||
Reference in New Issue
Block a user