PAILot Flutter - TODO
High Priority
MQTT Protocol Migration — NEXT MAJOR TASK
Replace ad-hoc WebSocket protocol with MQTT for reliable, ordered messaging.
Why: Current protocol has no delivery guarantees, no message ordering, no offline queuing.
Messages get lost on daemon restart, duplicated on catch_up, and arrive out of order.
Server (AIBroker):
- Embed MQTT broker (aedes) in daemon alongside existing WebSocket
- Topics: pailot/{sessionId}/out (server→app), pailot/{sessionId}/in (app→server)
- System topics: pailot/sessions, pailot/status, pailot/typing/{sessionId}
- QoS 1 (at-least-once) for messages, QoS 0 for typing indicators
- Retained messages for session list and last screenshot
- Clean session=false so broker queues messages for offline clients
- Bridge MQTT messages to/from existing AIBP routing
Flutter App:
- Replace WebSocket client with mqtt_client package
- Subscribe to pailot/+/out for all session messages
- Publish to pailot/{sessionId}/in for user messages
- Message ID-based dedup (MQTT can deliver duplicates with QoS 1)
- Ordered by broker — no client-side sorting needed
- Offline messages delivered automatically on reconnect
Migration:
- Phase 1: Add MQTT alongside WebSocket, dual-publish
- Phase 2: Flutter app switches to MQTT
- Phase 3: Remove WebSocket from PAILot gateway
Pending Features
File Transfer (send/receive arbitrary files)
- File picker in app (PDFs, Word docs, attachments, etc.)
- New
file message type in WebSocket protocol
- Gateway handler to save received files and route to session
- Session can send files back via
pailot_send_file
- Display file attachments in chat bubbles (icon + filename + tap to open)
Voice+Image Combined Message
- When voice caption is recorded with images, hold images on server until voice transcript arrives
- Deliver transcript + images together as one message to Claude
- Ensures voice prefix sets reply channel correctly
Push Notifications (iOS APNs) — NEXT SESSION with user at computer
- Step 1: User creates APNs key in Apple Developer Portal (needs login)
- Step 2: Save
.p8 key to ~/.aibroker/apns-key.p8, add env vars (key ID, team ID)
- Step 3: Server-side APNs HTTP/2 sender (
src/daemon/apns.ts) with JWT auth
- Step 4: App sends device token on WebSocket connect
- Step 5: Gateway buffers messages when no WS clients, sends push notification
- Step 6: App receives push → user taps → opens app → catch_up drains messages
- Optional: silent push to wake app briefly for critical messages
App Name Renaming (Runner → PAILot)
- Rename Xcode target from Runner to PAILot (like Glidr did)
- Update scheme names, bundle paths
Known Issues
Audio
- Background audio may not survive full app termination (only screen lock)
- Audio session category may conflict with phone calls
UI
- Launch image still uses default Flutter placeholder
- No app splash screen with PAILot branding
Navigation
- vi keys (0, G, dd) are sent as literal text paste — works for Claude Code but may not for other terminals