# Multi-Service AI Agent

Connect Gmail, Outlook, Google Drive, and OneDrive via per-connector OAuth. Each service has its own credentials, auto-sync, and independent connect/disconnect.

## Project Structure

```
multi-service-agent/
├── server.js                       ← Express bootstrap
├── src/
│   ├── config.js                   ← Env variable loader
│   ├── config/
│   │   └── tenantManager.js        ← Tenant DB connections
│   ├── controllers/
│   │   ├── oauthController.js      ← OAuth start/callback/disconnect
│   │   ├── connectorController.js  ← Connector CRUD endpoints
│   │   └── agentHelper.js          ← Agent tool definitions + executor
│   ├── middleware/
│   │   ├── connectorAuth.js        ← Auth + tenant DB init + migrations
│   │   └── auth.js                 ← Legacy auth middleware
│   ├── models/
│   │   ├── index.js                ← Master DB (pg.Pool)
│   │   ├── Nonce.js                ← Nonce for stateless auth
│   │   ├── SyncState.js            ← Sync cursor management
│   │   └── tenants/
│   │       ├── google.js           ← Google credentials model
│   │       ├── microsoft.js        ← Microsoft credentials model
│   │       ├── slack.js            ← Slack credentials model
│   │       └── users.js            ← Tenant user model
│   ├── oauth/
│   │   ├── google.js               ← Google OAuth (per-connector scopes)
│   │   ├── microsoft.js            ← Microsoft OAuth (per-connector scopes)
│   │   └── slack.js                ← Slack OAuth
│   ├── routes/
│   │   ├── index.js                ← Main router
│   │   ├── auth.js                 ← OAuth routes
│   │   ├── connectors.js           ← Connector API routes
│   │   ├── agent.js                ← Agent query route
│   │   └── sync.js                 ← Sync status/trigger routes
│   ├── services/
│   │   ├── userConnections.js      ← Token CRUD (per-connector)
│   │   ├── gmail.js                ← Gmail API
│   │   ├── googleDrive.js          ← Google Drive API
│   │   ├── outlook.js              ← Outlook via Microsoft Graph
│   │   ├── onedrive.js             ← OneDrive via Microsoft Graph
│   │   ├── slack.js                ← Slack API
│   │   ├── autoSync.js             ← Polling auto-sync per connector
│   │   ├── fullIngest.js           ← Full ingest per connector
│   │   ├── insightQueue.js         ← Insight ingestion queue
│   │   ├── insightWorker.js        ← Queue worker
│   │   └── connectorPayload.js     ← Response payload builders
│   └── views/
│       └── oauth.js                ← OAuth popup HTML
├── test/
│   ├── agent.test.js
│   ├── auth_nonce.test.js
│   ├── oauth_insight.test.js
│   └── user_scoping.test.js
├── .env.example
└── package.json
```

## Quick Start

```bash
npm install
cp .env.example .env
# Fill in .env with your API keys
npm start
```

Server runs at `http://localhost:3322`

## OAuth Routes (per-connector)

Each connector has its own OAuth flow with dedicated scopes:

| Connector | Start URL | Scopes |
|-----------|-----------|--------|
| Gmail | `GET /auth/google/gmail/start` | gmail.readonly, gmail.send, gmail.modify, userinfo.email |
| Drive | `GET /auth/google/drive/start` | drive, userinfo.email |
| Outlook | `GET /auth/microsoft/outlook/start` | offline_access, User.Read, Mail.ReadWrite, Mail.Send |
| OneDrive | `GET /auth/microsoft/onedrive/start` | offline_access, User.Read, Files.ReadWrite |
| Slack | `GET /auth/slack/start` | (Slack scopes) |

Callback URLs:
- `GET /auth/google/callback`
- `GET /auth/microsoft/callback`
- `GET /auth/slack/callback`

## API Routes

### Session
- `GET /api/session/status` — Get connected services status
- `DELETE /api/session/disconnect/:connector` — Disconnect a connector
- `POST /api/auth/nonce` — Generate a nonce for stateless auth

### Connectors (all require auth)
- `GET /api/connectors/:connector/search` — Search (emails or files)
- `GET /api/connectors/:connector/list` — List (emails or files)
- `GET /api/connectors/:connector/read/:id` — Read by ID
- `POST /api/connectors/:connector/send` — Send email (Gmail/Outlook)
- `POST /api/connectors/:connector/ingest` — Trigger full ingest
- `POST /api/connectors/:connector/disable` — Enable/disable connector

### Agent
- `POST /api/agent/query` — Ask a question / run a tool

### Sync
- `GET /api/sync/status` — Auto-sync status
- `POST /api/sync/trigger` — Trigger sync

## Setting Up Google OAuth

1. Go to https://console.cloud.google.com
2. Create a project, enable **Gmail API** and **Google Drive API**
3. **APIs & Services → Credentials → OAuth 2.0 Client ID** (Web application)
4. Add redirect URI: `http://localhost:3322/auth/google/callback`
5. Copy Client ID and Secret to `.env`

```env
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxx
GOOGLE_REDIRECT_URI=http://localhost:3322/auth/google/callback
```

## Setting Up Microsoft OAuth

1. Azure AD → App registrations → New registration
2. Redirect URI: `http://localhost:3322/auth/microsoft/callback`
3. Certificates & secrets → New client secret
4. API permissions → Microsoft Graph → Delegated: Mail.ReadWrite, Mail.Send, Files.ReadWrite, offline_access, User.Read

```env
MICROSOFT_CLIENT_ID=your-app-id
MICROSOFT_CLIENT_SECRET=your-secret-value
MICROSOFT_REDIRECT_URI=http://localhost:3322/auth/microsoft/callback
```

## What the Agent Can Do

| Service | Actions |
|---------|---------|
| Gmail | List inbox, read emails, send emails, search, reply, delete |
| Google Drive | List files, search files, read file content, create files, delete |
| Outlook | List inbox, read emails, send emails, search, reply, delete, move |
| OneDrive | List files, search files, read file content, create files, create folders, delete |
| Slack | List channels, read channel messages, read threads, search messages, send messages |
