150 lines
8.8 KiB
Markdown
150 lines
8.8 KiB
Markdown
# Messenger Integration
|
|
|
|
How life-manager connects to the messenger platform. Four integration points, each with a distinct data flow and auth mechanism.
|
|
|
|
## Overview
|
|
|
|
```
|
|
┌──────────────────────┐ ┌──────────────────────┐
|
|
│ LIFE-MANAGER :3700 │ │ MESSENGER :3100 │
|
|
│ │ │ │
|
|
│ ┌─────────────────┐ │ ── proxy ──────────▶ │ Browse API │
|
|
│ │ Messages Proxy │ │ ── enqueue ────────▶ │ Send Queue │
|
|
│ │ AI Loop │ │ ── poll ───────────▶ │ Service API │
|
|
│ │ Health Checker │ │ ── health ─────────▶ │ Health Controller │
|
|
│ └─────────────────┘ │ │ │
|
|
│ │ ◀── credentials ──── │ Credential Service │
|
|
│ Credential Keyring │ │ │
|
|
└──────────────────────┘ └──────────────────────┘
|
|
```
|
|
|
|
## 1. Messenger Proxy Module
|
|
|
|
Life-manager's `/api/messages/*` endpoints proxy to messenger's browse and queue APIs. The web frontend talks to life-manager only — never directly to messenger.
|
|
|
|
```
|
|
Life-Manager UI → /api/messages/conversations → Messenger /api/browse/conversations
|
|
/api/messages/folders /api/browse/folders
|
|
/api/messages/search /api/browse/search
|
|
/api/messages/stats /api/browse/stats
|
|
/api/messages/self /api/messages/self
|
|
/api/messages/queue-stats /api/send-queue/stats
|
|
/api/messages/queue-history /api/send-queue/history
|
|
/api/messages/attachment (streams file directly)
|
|
```
|
|
|
|
**Auth**: `X-Service-Key` header, value from `MESSENGER_API_KEY` env var.
|
|
|
|
**Config**: `MESSENGER_API_URL` (default `http://localhost:3100`).
|
|
|
|
**Life-manager code**: `messages-proxy.service.ts`, `messages.controller.ts`
|
|
|
|
## 2. Messaging AI Loop
|
|
|
|
Polls messenger every minute for self-addressed messages (sent from the user's own phone to themselves). Each new message routes through the agent system, gets an LLM response, and replies via the send queue.
|
|
|
|
```
|
|
life-manager messenger
|
|
┌──────────────┐ GET /messages/self ┌──────────────┐
|
|
│messaging-loop│─────────────────────▶│ service-api │
|
|
│ (cron 1m) │ │ controller │
|
|
│ │◀─────────────────────│ │
|
|
│ new msgs │ messages since T └──────────────┘
|
|
│ │ │
|
|
│ ▼ │
|
|
│ agent-router │───▶ LLM :8210
|
|
│ │ │
|
|
│ ▼ │
|
|
│ send reply │ POST /send-queue/enqueue ┌──────────────┐
|
|
│ │───────────────────────────▶│ send-queue │
|
|
└──────────────┘ └──────┬───────┘
|
|
│
|
|
macOS agent polls
|
|
▼
|
|
sends via Messages.app
|
|
```
|
|
|
|
**Guard**: Only runs when `user_awake` setting is `true`.
|
|
|
|
**Auth**: `X-Service-Key` header on all requests to messenger.
|
|
|
|
**Timestamp tracking**: `messaging.lastProcessed` setting stores the high-water mark.
|
|
|
|
**Life-manager code**: `messaging-loop.service.ts`, `messaging-conversation.service.ts`
|
|
|
|
## 3. Credential Keyring
|
|
|
|
Messenger fetches IMAP/SMTP credentials from life-manager's keyring at startup. Falls back to env vars if life-manager is unavailable.
|
|
|
|
```
|
|
messenger (onModuleInit) life-manager
|
|
┌──────────────┐ GET /api/credentials ┌──────────────┐ SELECT ┌─────────┐
|
|
│ credential │──────────────────────▶│ keyring │──────────▶│ Postgres│
|
|
│ service │ │ controller │ decrypt │ :25471 │
|
|
│ │◀──────────────────────│ │◀──────────│ │
|
|
│ imap creds │ {user, pass, host} └──────────────┘ └─────────┘
|
|
└──────┬───────┘
|
|
│
|
|
▼
|
|
connect IMAP/SMTP (Proton Bridge :1143, iCloud :993)
|
|
```
|
|
|
|
**Direction**: Messenger → life-manager (reverse of the other integrations).
|
|
|
|
**Encryption**: pgcrypto at rest in `keyring_credentials` table.
|
|
|
|
**Credentials stored**: `icloud-imap`, `protonmail-imap` (each with host, port, user, pass, tls, poll interval).
|
|
|
|
**Messenger code**: `credential.service.ts`
|
|
|
|
## 4. Service Health Check
|
|
|
|
Life-manager's health module pings messenger to report combined system status.
|
|
|
|
```
|
|
life-manager messenger
|
|
┌──────────────┐ GET /api/health/status ┌──────────────┐
|
|
│ messenger │─────────────────────────▶│ health │
|
|
│ checker │ │ controller │
|
|
│ │◀─────────────────────────│ │
|
|
│ {healthy, │ {db_ok, device_info, └──────────────┘
|
|
│ latency} │ last_seen}
|
|
└──────────────┘
|
|
```
|
|
|
|
**Degraded status**: If last device sync was >5 minutes ago, reports degraded rather than healthy.
|
|
|
|
**Config**: `MESSENGER_API_URL`, optional `MESSENGER_API_KEY`.
|
|
|
|
**Life-manager code**: `messenger.checker.ts`
|
|
|
|
## Message Send — Two Entry Points
|
|
|
|
Both life-manager (AI loop) and Claude Code (MCP) can send messages. They converge on the same queue:
|
|
|
|
```
|
|
┌──────────┐ ┌──────────┐ INSERT INTO ┌──────────┐ GET /pending ┌──────────┐
|
|
│ Claude │ send_message │ MCP │ pending_msgs │ Postgres │◀──────────────│ Swift │
|
|
│ Code │──────────────▶│ Server │────────────────▶│ messenger│ │ Agent │
|
|
└──────────┘ └──────────┘ (direct SQL) └──────────┘ └────┬─────┘
|
|
│
|
|
┌──────────┐ ┌──────────┐ POST /result ┌──────────┐ AppleScript │
|
|
│ Life │ POST enqueue │ Sync │◀──────────────│ Swift │◀───────────────┘
|
|
│ Manager │──────────────▶│ API │ │ Agent │ send via
|
|
└──────────┘ (HTTP) │ :3100 │ └──────────┘ Messages.app
|
|
└──────────┘
|
|
```
|
|
|
|
- **MCP Server**: Writes directly to `pending_messages` table via SQL
|
|
- **Life-Manager**: Calls `POST /api/send-queue/enqueue` via HTTP with service key auth
|
|
|
|
Both paths result in the macOS agent picking up the message on its next poll.
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Used By | Purpose |
|
|
|----------|---------|---------|
|
|
| `MESSENGER_API_URL` | life-manager | Base URL for messenger API (default: `http://localhost:3100`) |
|
|
| `MESSENGER_API_KEY` | life-manager | Service key sent as `X-Service-Key` header |
|
|
| `LIFE_MANAGER_API_URL` | messenger | Base URL for credential fetches (default: `http://localhost:3700/api`) |
|
|
| `SERVICE_API_KEY` | messenger | Validates incoming `X-Service-Key` headers |
|