SettingsViewModel.logout() and deleteAccount() each called
authRepository.logout() directly before flipping the state flag that
drives the screen's LaunchedEffect -> onLogout callback ->
NavHostViewModel.logout(), which invokes authRepository.logout() again.
Each redundant call fires a POST /api/auth/logout that 401s (tokens
already gone) and re-runs session cleanup; with the planned full-wipe
change that duplication becomes actively harmful.
Collapse SettingsViewModel.logout() to a single state update, and drop
the direct authRepository.logout() call from the deleteAccount success
branch. NavHostViewModel.logout() remains the single source of truth
for the cleanup side of the flow.
Five Android producers wrote temp files directly into cacheDir root,
bypassing CommonSessionCacheCleaner which only sweeps entries listed in
CACHE_SUBDIRECTORIES. Moved each producer to its own named subdir and
registered the new names so logout actually clears them.
Breaking changes:
- 2FA enable changed from GET to POST with OTP verification body
- Backup code regeneration now requires OTP verification
- Account deletion requires OTP when 2FA is enabled
- New shared OtpVerificationDialog component in core/ui
- Fix OTP digit box layout (weight-based instead of fixed size)
Additive changes:
- Add effort (AnthropicEffort) and thinkingLevel (Google) fields to
Conversation, Preset, and ChatRequest models
- Add tool_options to Agent model and create/update requests
- Add artifacts field to EphemeralAgent
- Add remoteAgents to InterfaceConfig
- Add programmatic_tools and deferred_tools agent capabilities
- Add thinkingLevel parameter to EndpointParameterRegistry
SSE hardening:
- Implement mapSyncEvent() for resume state-snapshot protocol
- Preserve partial stream content on disconnect (don't wipe visible text)
- Persist conversation to Room on stream creation (not just on Final)
- Auto-reconnect SSE stream when network recovers via ConnectivityObserver
- Network-aware retries in SseClient (wait for connectivity, don't burn attempts)
- Add StreamEvent.Retrying for retry progress UI feedback
- Lazy connectivity observation (only when network error occurs)
- Clear draft/streaming state on SSE stream expiry
- Add isNetworkError flag to StreamEvent.Error for typed detection
Code quality:
- Remove [Comparison] debug Timber logs (perf overhead on every SSE event)
- Replace Log.d with Timber.d across feature modules
- Extract hardcoded OTP dialog strings to strings.xml for localization
- Parameterize OtpVerificationDialog labels for localizability
- Add auto-submit guard with reset on failure for OTP input
- Replace fake QR code generator with copyable otpauth:// URI
- Replace fragile OTP string matching with HTTP status code checks
- Consolidate identical request classes into OtpVerificationRequest
- Share isHttpStatus helper across settings module
- Remove duplicate verifyTempToken method (identical to verifyTwoFactor)
- Remove duplicate 2FA dialog composables from AccountSettingsScreen
- Extract shared resume stream logic to reduce duplication
- Guard no-op retryInfo state updates
- Move ApiException to core:common for cross-module access
- Document SseEventMapper single-stream threading constraint
Bump SUPPORTED_BACKEND_VERSION to 0.8.4, advance upstream submodule.