CortX (SecondMind) is a voice-memory system that captures speech from ESP32 or phone, stores audio + transcript, structures it into actionable intelligence, and serves it back in a mobile app.
This README documents what is implemented right now across:
- Backend (
FastAPI + PostgreSQL + Redis + Celery + MinIO) - Flutter app (
flutterapp/AIDevice) - Firmware (
ESP32-S3 Sense, BLE pairing + audio capture) - Supabase AI pipeline (
Supabase + LM Studio worker)
There are two working backend paths in this repo:
-
FastAPI stack (primary API platform in repo)
- Device/app auth
- BLE pairing token exchange
- Capture session/chunk ingestion
- WAV upload ingestion
- Transcription + AI extraction workers
- App APIs for captures, AI cards, memory links, idea graph, founder intelligence
-
Supabase AI memory pipeline (MVP track)
- Audio + transcript stored in Supabase
- Job queue table in Supabase
- Python worker (
scripts/supabase_ai_worker.py) calls LM Studio - Structured outputs persisted in Supabase memory tables
- SQL RPCs for tasks/ideas/discussions/daily summary
Both tracks exist because product and team experimentation moved quickly (device direct, phone gateway, and Supabase-only AI phases).
flowchart LR
E["ESP32 Device"] -->|"/v1/device/auth"| API["FastAPI API"]
E -->|"/v1/device/capture/sessions + chunks + finalize"| API
P["Flutter App"] -->|"/v1/app/*"| API
P -->|"/v1/pairing/start"| API
E -->|"/v1/device/pairing/complete"| API
API --> PG["PostgreSQL"]
API --> RQ["Redis + Celery queues"]
RQ --> TW["Transcription Worker (Whisper)"]
TW --> PG
RQ --> AIW["AI Worker (LM Studio extractors)"]
AIW --> PG
flowchart LR
A["Audio in Supabase bucket"] --> T["public.transcripts"]
T --> J["public.ai_pipeline_jobs (pending)"]
J --> W["scripts/supabase_ai_worker.py"]
W --> L["LM Studio /v1/chat/completions"]
W --> M["memory_items + entities + memory_item_entities"]
W --> S["ai_pipeline_logs + job status done/failed"]
/Users/sujeetkumarsingh/Desktop/CortX
├── app/ # FastAPI backend, DB models, services, workers
├── docs/ # API contracts, runbooks, flow docs, SQL migrations
├── firmware/
│ └── arduino_ide/
│ ├── SecondMindESP32S3/ # BLE live audio gateway sketch
│ └── SecondMindESP32S3BackendDB/ # direct backend chunk upload sketch
├── flutterapp/AIDevice/ # Flutter mobile app (Riverpod + Dio + BLE)
├── scripts/
│ ├── supabase_ai_worker.py # Supabase -> LM Studio -> structured memory
│ └── download_whisper_model.py
├── supabase/sql/
│ └── 001_ai_memory_mvp.sql # Supabase schema + RPCs + triggers
└── docker-compose.yml
Base prefix: /v1
GET /v1/healthGET /v1/health/ai-metrics
POST /v1/device/register(admin-key protected)POST /v1/device/auth(returns device JWT)POST /v1/device/heartbeat
POST /v1/pairing/start(app-auth)POST /v1/device/pairing/complete(device-auth)GET /v1/device/pairing/status
Implements:
- one-time short-lived pair token
- token hash storage (
pairing_sessions) - conflict handling for already-paired devices
- durable device-user binding (
device_user_bindings)
POST /v1/device/capture/sessionsPOST /v1/device/capture/chunksPOST /v1/device/capture/sessions/{id}/finalizePOST /v1/device/captures/upload-wav(compat route)
Implements:
- chunk ordering checks
- duplicate chunk handling (idempotent response)
- sequence ACK/next expectations
- final assembly to WAV (
audio_blob_wavin DB) - enqueue to transcription queue
POST /v1/app/registerPOST /v1/app/authPOST /v1/app/password/forgot/requestPOST /v1/app/password/forgot/confirmGET /v1/app/me,PATCH /v1/app/me- avatar APIs:
GET/PUT/DELETE /v1/app/me/avatar - preferences APIs:
GET/PATCH /v1/app/me/preferences - account deletion:
POST /v1/app/me/delete
GET /v1/app/devicesPATCH /v1/app/devices/{device_id}DELETE /v1/app/devices/{device_id}POST /v1/app/devices/{device_id}/network-profile
POST /v1/app/captures/upload-wavGET /v1/app/capturesGET /v1/app/captures/{session_id}/audioGET /v1/app/captures/{session_id}/transcriptGET /v1/app/captures/{session_id}/aiPOST /v1/app/captures/{session_id}/ai/reprocess
GET /v1/app/memories/searchPOST /v1/app/memories/ask
GET /v1/app/assistant/itemsPATCH /v1/app/assistant/items/{item_id}GET /v1/app/dashboard/daily-summary
- Capture link APIs:
GET/POST/PATCH/DELETE /v1/app/captures/{session_id}/links...GET /v1/app/link-targets/search
- Idea graph APIs:
GET /v1/app/idea-graphGET /v1/app/idea-graph/entities/{entity_id}GET /v1/app/idea-graph/entities/{entity_id}/mentions
- Founder intelligence APIs:
GET /v1/app/founder/ideasGET /v1/app/founder/ideas/{idea_id}GET /v1/app/founder/signalsGET /v1/app/founder/weekly-memoPATCH /v1/app/founder/actions/{action_id}
Core tables:
app_users,app_user_preferences,app_password_reset_tokensdevicesdevice_user_bindings,pairing_sessionscapture_sessions,audio_chunks,transcripts,transcript_segmentsai_extractions,ai_itemsentities,entity_mentionsmemory_linksfounder_idea_clusters,founder_idea_memories,founder_idea_actions,founder_signals,weekly_founder_memos
capture_sessions.status lifecycle:
receiving -> queued -> transcribing -> done | failed
Task: app.workers.tasks.process_session_transcription
- reads finalized WAV from
capture_sessions.audio_blob_wav - runs whisper transcription (
app/services/transcriber.py) - writes transcript + segments
- sets fallback
memory_titleandmemory_gist - queues AI extraction
Task: app.workers.tasks.process_session_ai_extraction
- calls LM Studio via assistant extractor
- writes
ai_extractions+ai_items - generates memory card title/gist
- runs entity extraction and persists mentions
- queues founder intelligence pipeline
Task: app.workers.tasks.process_session_founder_intelligence
- clusters startup ideas across sessions
- emits signals and action candidates
- updates weekly founder memo
Task: app.workers.tasks.recover_stale_sessions
- requeues stale transcribing sessions
- helps reliability for long-run deployments
Tech stack:
- Flutter + Riverpod
- Dio for HTTP
flutter_blue_plusfor BLErecordfor on-phone WAV capture
- Sign up, login
- Forgot password request/confirm
- Profile fetch/update
- Avatar upload/download/delete
- Preferences update
- Account delete
- BLE scan + filter for SecondMind/ESP devices
- Connect + read
device_infoandpair_nonce - Call backend
/v1/pairing/start - Write returned
pair_tokenback via BLE char - Listen for
pair_status - Poll
/v1/app/devicesuntil confirmed
- Daily snapshot card from
/v1/app/dashboard/daily-summary - Assistant queue (open items)
- Memory board (captures list)
- Pull-to-refresh + error handling
- Capture list
- Audio playback via
/v1/app/captures/{id}/audio - Transcript view
- AI detail view
- Memory search (
/v1/app/memories/search) - Memory ask (
/v1/app/memories/ask)
- Idea graph visual data from
/v1/app/idea-graph - Entity detail + mentions timeline
- Founder ideas/signals/memo views
- list paired devices
- alias update
- unpair action
- online/offline status view
app_audio_service.dart implements:
- local WAV recording (16kHz mono)
- upload to
/v1/app/captures/upload-wav - status notifier: idle/recording/uploading
There are two Arduino sketches:
Path: firmware/arduino_ide/SecondMindESP32S3/SecondMindESP32S3.ino
Implements:
- device auth to backend (
/v1/device/auth) - BLE pairing service + characteristics
- pair token write callback and pairing completion call
- live PDM capture from onboard mic (
GPIO 42/41) - BLE audio packet notifications to phone
- serial commands (
p,s,t,u,x,h)
Path: firmware/arduino_ide/SecondMindESP32S3BackendDB/SecondMindESP32S3BackendDB.ino
Implements:
- BLE pairing same contract
- direct session/chunk/finalize uploads to backend
- ping-pong chunk buffering + uploader task
- retry logic + finalization control
- serial commands for start/stop/finalize/test
See: firmware/arduino_ide/SecondMindESP32S3/README_ARDUINO.md
Service UUID:
8b6ad1ca-c85d-4262-b1f6-85e134fdb2f0
Pairing characteristics:
device_info(READ)pair_nonce(READ)pair_token(WRITE)pair_status(READ/NOTIFY)
Optional audio characteristics (gateway mode):
audio_control(WRITE)audio_data(NOTIFY)audio_state(READ/NOTIFY)
- ESP enters pairing mode + advertises service.
- App reads
device_info+pair_nonce. - App calls
POST /v1/pairing/start. - Backend returns short-lived
pair_token. - App writes token to ESP
pair_tokenchar. - ESP calls
POST /v1/device/pairing/completewith device JWT. - Backend creates/updates
device_user_bindings. - ESP notifies
pair_status=success.
Files:
- SQL schema/RPC:
supabase/sql/001_ai_memory_mvp.sql - Worker:
scripts/supabase_ai_worker.py - Runbook:
docs/supabase_ai_pipeline_runbook.md - System flow doc:
docs/ai_pipeline_system_flow.md
- Enqueues transcript rows into
ai_pipeline_jobs - Worker claims pending job via RPC
- Sends transcript text to LM Studio
- Parses strict JSON extraction (
tasks/ideas/decisions/reminders/entities) - Writes
memory_items,entities,memory_item_entities - Marks job
doneorfailed - Writes logs into
ai_pipeline_logs
transcriptsai_pipeline_jobsai_pipeline_logsmemory_itemsentitiesmemory_item_entitiesdaily_summaries
api_memory_tasks(...)api_memory_ideas(...)api_memory_discussions(...)fn_daily_summary_v1(...)
cd /Users/sujeetkumarsingh/Desktop/CortX
cp .env.example .env
# fill required values in .env
docker compose up -d --build api worker postgres redis minio nginxHealth checks:
curl http://localhost:8000/v1/health
curl http://localhost:8000/v1/health/ai-metricscd /Users/sujeetkumarsingh/Desktop/CortX/flutterapp/AIDevice
flutter pub get
flutter run- Board:
XIAO_ESP32S3 - Enable PSRAM where required
- Update config values in selected sketch:
- Wi-Fi
API_BASE_URLDEVICE_CODEDEVICE_SECRET
cd /Users/sujeetkumarsingh/Desktop/CortX
export SUPABASE_URL="https://<project>.supabase.co"
export SUPABASE_SERVICE_ROLE_KEY="<service_role_key>"
export LM_STUDIO_BASE_URL="http://127.0.0.1:1234/v1"
export LM_STUDIO_MODEL="dolphin3.0-llama3.1-8b"
python3 scripts/supabase_ai_worker.py- Register/login from Flutter app.
- Put ESP in pairing mode.
- Start scan and pair in app.
- Verify
GET /v1/app/devicesshows paired device.
- Start device capture (direct backend sketch) or app WAV capture.
- Confirm session appears in
/v1/app/captures. - Confirm transcript endpoint returns text.
- Confirm AI endpoint returns extraction + items.
- Ensure transcript rows are inserted into
public.transcriptswithuser_id. - Check
ai_pipeline_jobstransitions:pending -> processing -> done. - Verify memory rows in
memory_itemsand linked entities.
Current state in local/dev has used hard-coded secrets during rapid testing. For production:
- Never ship service-role keys in firmware or app binaries.
- Keep
SUPABASE_SERVICE_ROLE_KEYserver/worker-only. - Keep admin bootstrap key server-side only.
- Rotate any keys already exposed in commits/screenshots/testing logs.
- Use private storage buckets for user audio.
- Enforce per-user access control in APIs and DB policies.
- Multiple ingestion modes coexist (gateway, direct backend, Supabase-only), so operational path must be explicitly chosen per deployment.
- Some older docs mention deprecated live stream endpoints; use
docs/api_contract_v1_freeze.mdas canonical contract for current backend routes. app/api/v1/stream.pyexists but is not wired intoapp/api/v1/router.py.- Flutter branch quality can vary by branch; run
flutter analyze+ app smoke tests before releases.
- API contract freeze:
docs/api_contract_v1_freeze.md - IoT pairing guide:
docs/iot_pairing_guide.md - App pairing flow:
docs/app_pairing_api_flow.md - BLE phone gateway flow:
docs/ble_phone_gateway_flow.md - FastAPI DB migrations:
docs/postgres_audio_storage_migration.sqldocs/postgres_ai_assistant_migration.sqldocs/postgres_daily_summary_profile_device_migration.sqldocs/postgres_founder_intelligence_migration.sqldocs/postgres_memory_search_linking_migration.sql
- Supabase AI runbook:
docs/supabase_ai_pipeline_runbook.md - Supabase AI flow:
docs/ai_pipeline_system_flow.md
SecondMind/CortX is positioned as a personal cognitive operating system:
- capture thoughts with minimal friction
- convert unstructured speech to structured memory
- track tasks, ideas, decisions, reminders, entities
- connect memory over time (graph + founder intelligence)
- expose actionable summaries in the app
This repository already contains the core primitives for that MVP: pairing, capture, transcript, extraction, memory storage, query APIs, and app surfaces.