61 Commits

Author SHA1 Message Date
Sergei
51d533f133 feat: Validate Deployment ID through API before saving
- Add validateDeploymentId() method in api.ts that checks if ID exists
  in user's deployments list
- Update profile.tsx to validate deployment ID before saving
- Show validation error message if ID is invalid
- Display deployment name alongside ID after validation
- Add loading state during validation
2026-01-24 20:50:40 -08:00
Sergei
9ae23cfef3 feat: Add Deployment ID setting in Profile
- Add deploymentId storage methods in api.ts (set/get/clear)
- Add Settings section in Profile with Deployment ID menu item
- Add modal dialog to edit deployment ID
- Update chat.tsx to use custom deployment ID from settings
- Priority: custom > currentBeneficiary > first beneficiary > fallback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:48:18 -08:00
Sergei
664759dee9 feat: Add sort button to toggle message order in chat
Add a sort button in the chat header that toggles between oldest-first
(default) and newest-first message ordering. The arrow icon indicates
the current sort direction.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:45:42 -08:00
Sergei
5724e7ab76 feat: Add erase button to clear chat messages
Add trash icon button in chat header that clears all messages
after confirmation. Resets chat to initial welcome message.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:44:49 -08:00
Sergei
09fc6ce8ad feat: Display voice messages in chat in real-time
Voice transcripts from both user and Julia now appear in the chat
immediately during the call, not just after it ends. Each voice call
shows a "Voice Call" separator, and voice messages display with a
microphone icon indicator.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:43:24 -08:00
Sergei
560722e8af fix: Tap on floating bubble ends the call
Changed tap behavior on the floating call bubble to end the call
instead of maximizing it. Removed the separate small end call button
since it's no longer needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:41:36 -08:00
Sergei
aec300bd98 feat: Add floating bubble during voice calls
- Create VoiceCallContext for global voice call state management
- Add FloatingCallBubble component with drag support
- Add minimize button to voice call screen
- Show bubble when call is minimized, tap to return to call
- Button shows active call state with green color

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:39:27 -08:00
Sergei
513d9c3c7d fix: Use safe area insets for tab bar to avoid Samsung nav button overlap
Use useSafeAreaInsets() to dynamically calculate tab bar height and bottom
padding instead of hardcoded values. This ensures the tab bar properly
accounts for Android navigation buttons (Samsung) and iOS home indicator.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:33:59 -08:00
Sergei
89afe86f54 feat: Integrate LiveKit voice calls into chat screen
- Add voice call button in chat input area
- Implement LiveKit room connection with Julia AI agent
- Create full-screen voice call modal with:
  - Visual avatar with speaking indicator
  - Call duration timer
  - Agent state display (listening/thinking/speaking)
  - Hang up button
- Add real-time transcription tracking for voice calls
- Keep screen awake during active calls
- Integrate with existing VoiceTranscriptContext for history

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:27:40 -08:00
Sergei
6f7c79f601 Remove separate voice call screen
Deleted app/voice-call.tsx fullscreen modal and removed all navigation
references to it from chat.tsx, voice.tsx and _layout.tsx.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:19:19 -08:00
Sergei
a23116a796 Remove Debug tab completely
- Remove debug screen from tab navigator
- Delete app/(tabs)/debug.tsx file

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 20:14:33 -08:00
Sergei
a578ec8081 feat: Pass Debug tab deployment ID to voice calls
- Add debugDeploymentId to BeneficiaryContext for sharing between screens
- Sync Debug tab's deploymentId state with global context
- voice-call.tsx now prioritizes debugDeploymentId when starting calls
- Enables testing voice calls with specific deployment IDs from Debug screen
2026-01-24 00:05:47 -08:00
Sergei
5ecb5f9683 Fix Julia AI voice: use SINGLE_DEPLOYMENT_MODE for Lite
- livekitService.ts: send empty beneficiaryNamesDict in Lite mode
- agent.py: handle None beneficiary_names_dict correctly
- chat.tsx: align text chat with same SINGLE_DEPLOYMENT_MODE flag

This fixes Julia saying "I didn't get the name of beneficiary"
by letting WellNuo API use the default beneficiary for deployment_id.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-22 16:49:55 -08:00
Sergei
8d98bab3cf Remove expo-speech-recognition plugin from app.json
The package was removed in commit d9fff44 but the plugin
entry was left in app.json, causing EAS Build to fail with
'Unknown error in Read app config' phase.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-22 10:25:29 -08:00
Sergei
e36b9bbf4a Add fallback audio configurations for iOS
If primary audio config fails (OSStatus -50), automatically try:
1. videoChat mode (speaker default)
2. voiceChat mode (earpiece default)
3. minimal config (most compatible)

Also make speaker output setting non-critical - call will work
even if output can't be changed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-22 09:43:05 -08:00
Sergei
d9fff44fc9 Remove unused expo-speech packages to avoid AudioSession conflicts
- Remove expo-speech (TTS) - not used
- Remove expo-speech-recognition (STT) - not used
- Delete dead code: hooks/useSpeechRecognition.ts

These packages add native audio modules that can conflict with
LiveKit's AudioSession management on iOS.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-22 09:41:35 -08:00
Sergei
42e3f389f7 Fix iOS AudioSession OSStatus error -50
- Remove 'defaultToSpeaker' from audioCategoryOptions (conflicts with some iOS versions)
- Use 'videoChat' mode instead of 'voiceChat' for speaker output
- Reorder operations: set config first, start session, then configure output
- Keep audioCategoryOptions minimal to avoid param conflicts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-22 09:36:20 -08:00
Sergei
ac6d458aae Fix Julia AI agent race condition - wait for participant metadata
The agent was reading participant metadata immediately after connecting,
but the mobile user might not have joined yet or metadata wasn't synced.

Changes:
- Replace extract_beneficiary_data() with wait_for_participant_with_metadata()
- Wait up to 10 seconds for participant with deploymentId
- Log waiting status every 2 seconds for debugging
- Fallback gracefully if timeout reached

This fixes "I couldn't get that information right now" error in voice calls.
2026-01-21 14:51:53 -08:00
Sergei
204cb87f05 Fix voice call race condition - ensure beneficiaryData is passed
- Fix race condition where connect() was called before beneficiaryData loaded
- Add connectCalledRef to prevent duplicate connect calls
- Wait for beneficiaryData.deploymentId before initiating call
- Add 5s timeout fallback for edge cases (API failure/no beneficiaries)
- Hide Debug tab, show only Julia tab in navigation
- Add Android keyboard layout fix for password fields
- Bump version to 1.0.5

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-21 14:30:59 -08:00
Sergei
906213e620 Add beneficiary_names_dict support for voice assistant
- Voice agent now extracts deploymentId and beneficiaryNamesDict from
  participant metadata passed via LiveKit token
- WellNuoLLM class accepts dynamic deployment_id and beneficiary_names_dict
- API calls now include personalized beneficiary names for better responses
- Text chat already has this functionality (verified)
- Updated LiveKit agent deployed to cloud

Also includes:
- Speaker toggle button in voice call UI
- Keyboard controller integration for chat
- Various UI improvements
2026-01-20 14:41:33 -08:00
Sergei
4b97689dd3 UI improvements: voice call layout and chat keyboard
- Remove speaker button empty space (2-button centered layout)
- Remove "Asteria voice" text from voice call screen
- Fix chat input visibility with keyboard
- Add keyboard show listener for auto-scroll

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 11:28:24 -08:00
Sergei
0d872a09b7 Fix iOS audio session "status -50" error
Remove allowBluetoothA2DP from audioCategoryOptions. This option is
incompatible with playAndRecord category on some iOS versions.
The allowBluetooth (HFP profile) is sufficient for voice calls.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 09:41:14 -08:00
Sergei
e3192ead12 Voice call improvements: single call limit, hide debug tab, remove speaker toggle
Changes:
- Add CallManager singleton to ensure only 1 call per device at a time
- Hide Debug tab from production (href: null)
- Remove speaker/earpiece toggle button (always use speaker)
- Agent uses voice_ask API (fast ~1 sec latency)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-19 23:55:27 -08:00
Sergei
57577b42c9 Fix Android audio routing - use music stream for speaker output
- Changed audioStreamType from 'voiceCall' to 'music' on Android
  - voiceCall stream defaults to earpiece
  - music stream defaults to speaker
- Added Debug tab to test voice calls with detailed logs
- Added speaker/earpiece toggle button with proper stream switching
- Full Android AudioSession support for LiveKit voice calls

audioSession.ts:
- configureAudioForVoiceCall: uses music/media for speaker output
- setAudioOutput: switches between music (speaker) and voiceCall (earpiece)
- reconfigureAudioForPlayback: ensures speaker output on Android

debug.tsx:
- Added platform info display
- Added speaker toggle with logging
- Improved UI with control rows
2026-01-19 22:54:59 -08:00
Sergei
bbc59e61ce Switch from voice_ask to ask_wellnuo_ai API function
As requested - same parameters, same response format.
Changed in both:
- chat.tsx (text chat)
- agent.py (voice agent)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-19 21:16:52 -08:00
Sergei
122f521af6 Fix chat to use exact same API logic as voice agent
Changes:
- Use anandk credentials (same as julia-agent)
- Add normalizeQuestion() function to transform questions
  into format WellNuo API understands
- "how is my dad" → "how is dad doing"
- Remove user's SecureStore credentials
- Use cached token with auto-refresh on 401

This makes text chat return real Ferdinand sensor data
just like voice calls do.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-18 23:12:15 -08:00
Sergei
9b152bdf9d Fix chat API params to match voice agent
- Change clientId from '001' to 'MA_001'
- Change deployment_id to '21' (Ferdinand)
- Send raw question without context wrapping
- Same params as julia-agent/julia-ai/src/agent.py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-18 22:51:39 -08:00
Sergei
173c0a8262 Add session expired detection and auto-refresh in WebView
- Monitor page content for "session expired" patterns
- Send message to React Native when detected
- Auto-refresh token and reload WebView
- Add logging to refreshToken for debugging
2026-01-18 22:48:41 -08:00
Sergei
bc33230739 Clean up voice call UI - remove debug panel and technical info
- Remove debug logs panel entirely
- Simplify top bar (only back button)
- Remove unused imports, variables and styles
- Update component description
2026-01-18 22:39:43 -08:00
Sergei
cd9dddda34 Add Chat tab with Julia AI + voice call improvements
- Enable Chat tab (replace Debug) - text chat with Julia AI
- Add voice call button in chat header and input area
- Add speaker/earpiece toggle in voice-call screen
- setAudioOutput() function for switching audio output
2026-01-18 22:00:26 -08:00
Sergei
6a6c85f7c3 Add normalize_question() for Ferdinand data
WellNuo API only returns real sensor data for exact phrase
"how is dad doing". This function maps various user questions
(how is Ferdinand, how's dad, is he okay, etc.) to that phrase.

- Added keyword detection for status, subject, sleep, activity
- All variations now return Ferdinand's real data
2026-01-18 21:50:33 -08:00
Sergei
321cd721ac Fix clientId: use MA_001 instead of 001
This enables WellNuo voice_ask API to return real sensor data
about Ferdinand (deployment_id=21) instead of generic responses.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-18 21:30:46 -08:00
Sergei
dcdd06739d Fix WellNuoLLM custom implementation for livekit-agents 1.3.11
- chat() must be synchronous, returning LLMStream directly
- LLMStream.__init__() takes 4 params: llm, chat_ctx, tools, conn_options
- _run() emits chunks via self._event_ch.send_nowait()
- Added model and provider properties required by LLM base class

Tested: STT (Deepgram Nova-2), TTS (Deepgram Aura Asteria), VAD (Silero)
all working. WellNuo voice_ask API integration confirmed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-18 21:20:43 -08:00
Sergei
cb0c83d82a Bump version to 1.0.4 for TestFlight build with LiveKit integration 2026-01-18 20:20:58 -08:00
Sergei
20d5f42114 Add Julia AI voice integration documentation 2026-01-18 20:17:30 -08:00
Sergei
059bc29b6b WIP: LiveKit voice call integration with Julia AI agent
NOT TESTED ON REAL DEVICE - simulator only verification

Components:
- LiveKit Cloud agent deployment (julia-agent/julia-ai/)
- React Native LiveKit client (hooks/useLiveKitRoom.ts)
- Voice call screen with audio session management
- WellNuo voice_ask API integration in Python agent

Tech stack:
- LiveKit Cloud for agent hosting
- @livekit/react-native SDK
- Deepgram STT/TTS (via LiveKit Cloud)
- Silero VAD for voice activity detection

Known issues:
- Microphone permissions may need manual testing on real device
- LiveKit audio playback not verified on physical hardware
- Agent greeting audio not confirmed working end-to-end

Next steps:
- Test on physical iOS device
- Verify microphone capture works
- Confirm TTS audio playback
- Test full conversation loop
2026-01-18 20:16:25 -08:00
Sergei
7525bdc0f8 Add NSPhotoLibraryUsageDescription and NSCameraUsageDescription, bump to 1.0.2 2026-01-17 18:38:48 -08:00
Sergei
f6edf3e1f5 Bump version to 1.0.1 for TestFlight submission 2026-01-17 18:30:26 -08:00
Sergei
eaa7828e65 Add App Store build docs and LiveKit Agents guide
- Add App Store build credentials and build-ios.sh script
- Document Julia AI voice agent architecture
- Add detailed instructions for editing agent behavior
- Document token server deployment
2026-01-17 18:17:37 -08:00
Sergei
dde0ecb9cd Add Julia AI voice agent with LiveKit integration
Voice AI Features:
- LiveKit Agents integration for real-time voice calls
- Julia AI agent (Python) deployed to LiveKit Cloud
- Token server for authentication
- Debug screen with voice call testing
- Voice call screen with full-screen UI

Agent Configuration:
- STT: Deepgram Nova-2
- LLM: OpenAI GPT-4o
- TTS: Deepgram Aura Asteria (female voice)
- Turn Detection: LiveKit Multilingual Model
- VAD: Silero
- Noise Cancellation: LiveKit BVC

Files added:
- julia-agent/ - Complete agent code and token server
- app/voice-call.tsx - Full-screen voice call UI
- services/livekitService.ts - LiveKit client service
- contexts/VoiceTranscriptContext.tsx - Transcript state
- polyfills/livekit-globals.ts - WebRTC polyfills

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-17 17:58:31 -08:00
Sergei
a2eb4e6882 Fix iOS audio and transcript streaming
- Add AVAudioSession configuration via @livekit/react-native
- Configure playAndRecord, defaultToSpeaker, voiceChat for iOS
- Fix transcript spam: update existing message until isFinal
- Remove unused Sherpa TTS service
- Add simulator build profile to eas.json
2026-01-16 13:56:29 -08:00
Sergei
c1380b55dd Add unified assistant with Ultravox voice AI
Chat screen now supports both:
- Text messaging (keyboard input)
- High-quality Ultravox voice calls (WebRTC)

Features:
- Voice call button in input bar (phone icon)
- Green status bar when call is active
- Transcripts from voice calls appear in chat history
- Voice badge on messages from voice conversation
- Mute button during calls
- Auto-end call when leaving screen

Background audio configured for iOS (audio, voip modes)
2026-01-16 12:20:17 -08:00
Sergei
cde44adc5c Add TTS model metadata and documentation
TTS Model (Piper VITS):
- MODEL_CARD: Voice model information
- tokens.txt: Phoneme tokenization
- onnx.json: Model configuration
- Model: en_US-lessac-medium (60MB ONNX - not in git)

Documentation:
- APP_REVIEW_NOTES.txt: App Store review notes
- specs/: Feature specifications
- plugins/: Expo config plugins

.gitignore updates:
- Exclude large ONNX models (60MB+)
- Exclude espeak-ng-data (phoneme data)
- Exclude credentials.json
- Exclude store-screenshots/

Note: TTS models must be downloaded separately.
See specs/ for setup instructions.
2026-01-14 19:10:13 -08:00
Sergei
da2c4bebc9 Integrate voice chat with TTS and speech recognition
App screens:
- chat.tsx: Voice-enabled chat with TTS responses
- debug.tsx: TTS debugging and testing screen
- index.tsx: Updated home with voice indicators
- _layout.tsx: Added TTS and error boundaries

Config:
- app.json: Microphone permissions for voice input
- package.json: Added Sherpa ONNX dependencies
- constants/theme.ts: Voice UI colors

Features:
- Voice input via speech recognition
- TTS voice output for chat responses
- Real-time voice activity indication
- Debug screen for TTS testing
- Error boundaries for stability

User experience:
- Hands-free chat interaction
- Visual feedback during voice processing
- Graceful error handling
2026-01-14 19:09:50 -08:00
Sergei
b2639dd540 Add Sherpa TTS voice synthesis system
Core TTS infrastructure:
- sherpaTTS.ts: Sherpa ONNX integration for offline TTS
- TTSErrorBoundary.tsx: Error boundary for TTS failures
- ErrorBoundary.tsx: Generic error boundary component
- VoiceIndicator.tsx: Visual indicator for voice activity
- useSpeechRecognition.ts: Speech-to-text hook
- DebugLogger.ts: Debug logging utility

Features:
- Offline voice synthesis (no internet needed)
- Multiple voices support
- Real-time voice activity indication
- Error recovery and fallback
- Debug logging for troubleshooting

Tech stack:
- Sherpa ONNX runtime
- React Native Audio
- Expo modules
2026-01-14 19:09:27 -08:00
Sergei
b5eef6760c Add WellNuo logo to Dashboard header
Replaced "Dashboard" text with app logo image in header:
- Import Image component from react-native
- Replace Text with Image (icon.png) in both header states
- Add logo style: 36x36px with horizontal margins
- Remove unused headerTitle and headerTitleWithBack styles
- Refresh button now uses marginLeft: 'auto' for proper spacing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-12 12:09:13 -08:00
Sergei
5fc7586f09 Revert Account Deletion feature - B2B model exception
Removed in-app account deletion implementation.

Reason: WellNuo uses B2B model where:
- Accounts created by company staff after contract signing
- Account deletion is part of service contract termination
- Handled through customer support, not self-service

Updated APPLE_REVIEW_RESPONSE.md with B2B exception explanation
for Apple Guidelines 5.1.1(v) and 3.1.1.
2026-01-12 12:01:23 -08:00
Sergei
cddc766a34 Remove 'Dashboard' text from header
User requested to remove duplicate 'Dashboard' text from header
since the WebView already displays its own dashboard header.
2026-01-12 11:56:41 -08:00
Sergei
7205c2ad1e Fix Apple Review issues: Login cleanup + Account Deletion
Apple App Store Review - Submission ID: 0992528e-4ce9-4167-9a1b-07f4334a8055

Fix #2: Login Screen Cleanup (Guideline 2.1)
- Removed non-functional "Create Account" button
- Removed "Forgot Password" button (not needed)
- Added actual logo image instead of text
- Streamlined login screen to focus on core functionality

Fix #3: Account Deletion Feature (Guideline 5.1.1(v))
- Added "Delete Account" button to Profile screen
- Implemented confirmation dialog with clear warning
- API integration: deleteAccount() method in api.ts
- Automatically logs out and clears data after deletion
- Redirects to login screen after successful deletion

Updated APPLE_REVIEW_RESPONSE.md with full documentation.
2026-01-12 11:55:31 -08:00
Sergei
e4a70ef8c1 Fix: Add back button to Chat screen for App Store review
Apple Review Issue: Guideline 4.0 - Design
- Added back button in Chat screen header for iOS navigation
- Button navigates to Dashboard screen
- Includes proper touch target sizing (hitSlop) for accessibility

Technical changes:
- Added useRouter hook from expo-router
- Implemented TouchableOpacity with arrow-back icon
- Styled with consistent padding and app color scheme

Also added:
- APPLE_REVIEW_RESPONSE.md to track all review fixes

Submission ID: 0992528e-4ce9-4167-9a1b-07f4334a8055
2026-01-12 11:51:28 -08:00