Metadata-Version: 2.4
Name: megan
Version: 0.1.11
Summary: Megan personal AI assistant CLI and memory runtime.
Project-URL: Homepage, https://megan.ai
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: anthropic<1.0,>=0.52.0
Requires-Dist: cryptography>=44.0.0
Requires-Dist: celery[redis]==5.4.0
Requires-Dist: datasets<4.0,>=3.0.0
Requires-Dist: Flask==3.0.3
Requires-Dist: neo4j==5.28.1
Requires-Dist: openai==1.82.0
Requires-Dist: psycopg[binary]>=3.2.0
Requires-Dist: python-dotenv==1.0.1
Requires-Dist: stripe>=12.0.0
Requires-Dist: zeroconf<1.0,>=0.136
Provides-Extra: test
Requires-Dist: pytest==8.3.5; extra == "test"
Provides-Extra: voice
Requires-Dist: speechbrain<2.0,>=1.0.0; extra == "voice"
Requires-Dist: torch>=2.2; extra == "voice"
Requires-Dist: torchaudio>=2.2; extra == "voice"

# Megan Memory Prototype

Python/Flask prototype for a personal AI assistant with long-term graph-style memory, inspired by the architecture diagrams in the project brief.

## What It Does

- Stores production memories in Neo4j as a knowledge graph.
- Keeps a SQLite local graph fallback so terminal tests run without external services.
- Extracts memory summaries, importance, nodes, and relationships with OpenAI when `OPENAI_API_KEY` is set.
- Falls back to deterministic local extraction when no API key is present.
- Answers questions by retrieving a graph neighborhood first: query terms -> seed entities -> related entities -> mentioned memories -> model answer.
- Runs Celery-powered sleep cycles that consolidate recent memories, strengthen useful graph links, rescore importance, and archive low-value noise.
- Maintains long-running teaching conversations with persisted messages and rolling summaries.
- Tracks token usage by conversation, day, week, and month.
- Exposes API endpoints for remembering, querying, graph inspection, and consolidation.

## Setup

```powershell
uv sync --extra test
copy .env.example .env
```

Add your key to `.env` when you want live OpenAI calls.

```text
OPENAI_API_KEY=your_key_here
OPENAI_MODEL=gpt-4.1-mini
```

## Production Graph DB

Use Neo4j for the real memory graph:

```powershell
docker run --name megan-neo4j -p 7474:7474 -p 7687:7687 -e NEO4J_AUTH=neo4j/password neo4j:5
```

Then set:

```text
NEO4J_URI=bolt://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=password
NEO4J_DATABASE=neo4j
```

When `NEO4J_URI` is absent, the app uses `instance/megan.sqlite3` as a local graph-compatible fallback for terminal-only development.

## Live Data Stores

For a commercial/live deployment, Megan is configured for:

- Railway Postgres via `DATABASE_URL` or `APP_DATABASE_URL` as the main app data store.
- Neo4j Aura via `NEO4J_URI` for long-term graph memory.
- Railway Redis via `REDIS_URL` for Celery/background work.
- Local SQLite as a development/offline cache with a sync outbox at `SYNC_DATABASE`.
- Tenant/user/device scope via `MEGAN_TENANT_ID`, `MEGAN_USER_ID`, and `SYNC_DEVICE_ID`.

See `docs/live-data-architecture.md` for the production store map and sync rules. At runtime, `GET /api/data/topology` reports configured storage targets without exposing credentials.

## Background Sleep Cycle

Celery runs the memory sleep cycle. Redis is the default broker/result backend:

```powershell
docker run --name megan-redis -p 6379:6379 redis:7
```

Start the worker:

```powershell
uv run celery -A megan.celery_app.celery_app worker --loglevel=info
```

Start the scheduler that triggers sleep every 4 hours:

```powershell
uv run celery -A megan.celery_app.celery_app beat --loglevel=info
```

Trigger a background sleep cycle through Flask:

```powershell
curl -X POST http://127.0.0.1:5000/api/sleep-cycle
```

For terminal-only testing without Redis/Celery worker:

```powershell
uv run python -m megan.cli sleep-cycle
```

## Native Desktop Direction

The commercial Windows desktop direction lives in `desktop/`.

It is a Windows App SDK / WinUI app backed by `Megan.Desktop.Core`, which writes local tenant-scoped data under `%APPDATA%\Megan` and syncs through the Megan API. This path is intended to replace the development-only Tauri/Flask desktop bridge so users do not need to run `app.py` or install Python.

The older Tauri shell remains available for experimentation. It no longer auto-starts the Flask backend unless `MEGAN_TAURI_AUTOSTART_BACKEND=1` is set.

## Native Android Direction

The Android companion app lives in `android/`.

It is a Kotlin / Jetpack Compose app focused on the two mobile surfaces Megan needs first:

- Conversation
- Settings

Android talks to the same Flask API as web and desktop. For emulator testing, set the mobile server URL to `http://10.0.2.2:5000`. For a real phone, bind Flask to `0.0.0.0` and use your PC's LAN address.

Local model support is routed through Megan's provider/model contract. The recommended first setup is to configure the Flask server with an OpenAI-compatible local endpoint, then select the local route from Android settings.

## Run The App

```powershell
uv run python app.py
```

Health check:

```powershell
curl http://127.0.0.1:5000/api/health
```

## Run The Vite React Client

The Flask app is the API server on port 5000. The React voice client runs through Vite on port 5173.

Terminal 1:

```powershell
uv run python app.py
```

For local speaker recognition testing with SpeechBrain, run Flask without the debug
reloader so Werkzeug does not scan SpeechBrain's lazy optional modules:

```powershell
uv run flask --app app run --no-reload
```

Appearance recognition uses the optional InsightFace provider when installed. On
Windows, prefer Python 3.10 or 3.11 for this stack, then install:

```powershell
uv pip install insightface onnxruntime opencv-python
```

Terminal 2:

```powershell
cd client
npm install
npm run dev
```

Open:

```text
http://127.0.0.1:5173
```

The client supports browser speech input, optional spoken replies, direct memory capture, graph inspection, and per-request provider/model selection.

Model credentials stay server-side in `.env`. The default provider is OpenAI:

```text
DEFAULT_AI_PROVIDER=openai
OPENAI_API_KEY=your_key_here
OPENAI_MODEL=gpt-4.1-mini
OPENAI_MODEL_OPTIONS=gpt-4.1-mini,gpt-4.1,gpt-4o,gpt-4o-mini
```

DeepSeek:

```text
DEEPSEEK_API_KEY=your_key_here
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-chat
DEEPSEEK_MODEL_OPTIONS=deepseek-chat,deepseek-reasoner
```

Anthropic Claude:

```text
ANTHROPIC_API_KEY=your_key_here
ANTHROPIC_MODEL=claude-sonnet-4-20250514
ANTHROPIC_MODEL_OPTIONS=claude-sonnet-4-20250514,claude-opus-4-20250514,claude-3-7-sonnet-20250219,claude-3-5-haiku-latest
```

When credentials are configured, Megan asks the provider API for its available models and caches the result for five minutes. The configured model lists are used as an offline fallback.

For an OpenAI-compatible endpoint, configure:

```text
OPENAI_COMPATIBLE_API_KEY=your_key_here
OPENAI_COMPATIBLE_BASE_URL=http://127.0.0.1:11434/v1
OPENAI_COMPATIBLE_MODEL=local-model
OPENAI_COMPATIBLE_MODEL_OPTIONS=local-model,another-model
```

If the selected provider is not configured, Megan falls back to local deterministic behavior.

## Test In The Terminal

```powershell
uv run pytest
uv run python -m megan.cli smoke-test
uv run python -m megan.cli remember "Megan met John at Hospital Nairobi and discussed diabetes follow-up."
uv run python -m megan.cli ask "What does Megan remember about John?"
uv run python -m megan.cli chat "Teach me graph memory from where we left off."
uv run python -m megan.cli usage
uv run python -m megan.cli graph
uv run python -m megan.cli sleep-cycle
```

`smoke-test` deliberately disables OpenAI and Neo4j and runs the sleep cycle inline, so it proves the terminal path works anywhere.

## Knowledge Graph Shape

Neo4j stores:

- `(:Memory)` nodes for timestamped experiences.
- `(:Entity {label, kind})` nodes for people, places, concepts, events, emotions, states, and procedures.
- `(:Memory)-[:MENTIONS]->(:Entity)` links for provenance.
- `(:Entity)-[:RELATED_TO {relation, confidence}]->(:Entity)` links for semantic, episodic, and procedural relationships.

The answer path is:

```text
question -> query terms -> seed Entity nodes -> related Entity nodes + Memory provenance -> graph context -> OpenAI answer
```

## Sleep Cycle

The sleep cycle is the offline learning loop:

```text
active memories -> graph neighborhoods -> cluster repeated themes -> rescore importance -> archive noise -> write consolidated memory -> strengthen useful edges
```

It is implemented in `megan/sleep_cycle.py` and can run either inline for testing or through Celery for background processing.

## Long Conversations And Token Usage

Megan stores every conversation turn in `CONVERSATION_DATABASE`. For sessions that last more than an hour, it keeps continuity with:

- full persisted message history
- a rolling summary of older turns
- recent message window
- graph memory retrieval for the newest user message

The answer prompt is built from:

```text
rolling summary + recent messages + graph context + latest user message
```

Token usage is recorded after every model operation. The client at `http://127.0.0.1:5000/` shows daily, weekly, and monthly totals. The same data is available through:

```powershell
curl http://127.0.0.1:5000/api/usage/summary
```

## API

`POST /api/memory/event`

```json
{
  "event": "On June 1, 2026, Megan met John at Hospital Nairobi..."
}
```

`POST /api/memory/query`

```json
{
  "question": "What does Megan remember about John?"
}
```

`GET /api/memory/graph`

`POST /api/memory/consolidate`
