5b4c05316a
[03-Developer] #311 LLM warm-up + concurrent guard + quickCheck
...
ChatScreen 마운트 시 백그라운드 native init 으로 첫 send 시점에 native
load 지연을 안 보이게 한다. 12개 AC + UX-Reviewer 의 6개 권고 모두 코드
반영.
핵심 변경:
- `chat_warmup_provider.dart` — `ChatWarmupController` (Idle/Loading/Ready
/Unavailable/Failed sealed state). fast path (`llm.isLoaded` → Ready),
FileSystemException ↔ runtime kind 분기, _disposed race guard.
- `model_lifecycle.dart` — `quickCheck()`: 2.4GB SHA-256 hashing 없이
meta_kv + 파일 존재만 보고 ready 추정 (R4 UX 권고).
- `gemma_llm_service.dart` + `llm_service.dart` — `_loadingFuture` 동시
호출 가드. 두 caller 가 동시에 load() 해도 native init 은 1 회만.
- `chat_screen.dart` — initState postFrameCallback 에서 warmup.start().
warmup 상태에 따라 hintText / spinner / 실패 banner 분기.
AC coverage (12개):
- AC1~AC8: ChatWarmupController unit (chat_warmup_test.dart 8 tests).
- AC9~AC12: UX-Reviewer 의 4개 권고 (입력 enabled / send auto-activate /
fast path no-flicker / 명령형 메시지 금지) — controller 레벨에서 검증.
테스트: 167 passed (1 pre-existing skip). `flutter analyze` clean.
Refs #311
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-06-15 12:52:50 +09:00
b1bed4d5ca
[03-Developer] #260 in-app tool calling (Gemma 4 multi-turn)
...
ADR-0005 in-process tool runtime — 6 tools (catalog 2 + tracker 2 +
habit 2), ToolDispatcher with JSON-schema validation + modal ConfirmGate
for destructive ops, multi-turn LlmChatSession abstraction wired to
flutter_gemma 0.16.5 (ToolChoice.auto), ChatSessionController with
MAX_TURNS=4 safety + 8-turn history hint, ChatScreen entry behind AI
opt-in. R3/R7/R8 enforced inside handlers. 41 new tests (envelope,
catalog/tracker/habit tools, dispatcher, controller loop) — 151 total
passing.
Refs #260
2026-06-15 10:42:43 +09:00
9a9eb2abd5
[Developer] #218 Real Gemma 4 E2B integration via flutter_gemma 0.16.5
...
Implements the OQ-1 follow-up to #215 v0.2.0: replace the placeholder
GemmaLlmService stub with a real flutter_gemma 0.16.5 backend driving
Gemma 4 E2B (litert-community/gemma-4-E2B-it-litert-lm, 2.41GB).
Highlights:
- GemmaLlmService.load → FlutterGemma.initialize + installModel.fromFile +
getActiveModel; idempotent + FileSystemException on missing file.
- generateStructured uses Gemma 4 native function calling via
createChat(tools: [Tool(...)], toolChoice: required). Stream parsed by
collectFunctionCall — first FCR wins, ParallelFCR first-call wins,
TextResponse/ThinkingResponse skipped, errors sanitized to prevent
prompt leakage.
- main.dart wires _LazyLlmService adapter that resolves to GemmaLlmService
when ModelLifecycle reports ready, MockLlmService otherwise.
- ai_providers.dart pins real model URL + SHA-256 (181938...39a63c).
- F2 hardening: ModelLifecycle.purge wraps each delete + meta remove in
try/catch so a single OS-level flake cannot block opt-out.
- Android: INTERNET / FOREGROUND_SERVICE / POST_NOTIFICATIONS permissions
+ R8 proguard-rules.pro keeping MediaPipe / LiteRT / TFLite / protobuf
JNI entry points (release builds otherwise crash on first inference).
Design-First: fn-gemma_llm_service.md updated to v2 — §C
(_appendSchemaInstruction) deprecated after reading flutter_gemma
0.16.5 source (Gemma 4 SDK injects tool declarations via template;
prompt-side append would double-wrap).
Tests:
- 10 new unit tests for collectFunctionCall covering all 8 fn-spec
cases + 2 ParallelFunctionCallResponse paths.
- All 81 existing tests still pass.
- flutter analyze: 0 issues.
Refs #218
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-06-12 15:18:08 +09:00
6ab4c0da7d
[Developer] #215 AI frame-suggest vertical slice (mock LlmService)
...
설계서대로 구현. flutter_gemma 실제 통합은 OQ-1 (모델 URL+SHA) 확정 후.
v1은 LlmService 추상 + ModelLifecycle (다운로드/SHA/purge) + Riverpod
providers + 다이얼로그 + Settings 화면까지. main.dart 가 MockLlmService 를
override 해 모든 경로가 graceful (suggest 결과는 빈 리스트).
추가:
- lib/data/ai/{llm_service,gemma_llm_service,model_lifecycle}.dart
- lib/domain/ai/{frame_candidate,few_shot_builder,parse_response,suggest_frame}.dart
- lib/state/ai_providers.dart (aiSettings + modelAvailability + frameSuggestions)
- lib/ui/screens/settings_screen.dart (opt-in 토글 + 모델 상태 표시)
- lib/ui/widgets/frame_suggestion_dialog.dart (후보 3개 카드 + 다시 시도)
- HabitCreateScreen: "AI 제안" 버튼 (opt-in + ready 일 때만 노출)
- MetaDao.remove(key) 추가 (purge 용)
테스트 31개 신규 추가 (총 62개 통과):
- test/domain/ai/{suggest_frame, few_shot_builder, parse_response}_test.dart
- test/data/ai/model_lifecycle_test.dart (download/SHA/purge/availability)
flutter analyze 0 issue, flutter build apk --debug 통과.
Refs #215
2026-06-12 12:08:25 +09:00