File size: 5,304 Bytes
363cda9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# API Layer πŸ”Œ

> FastAPI backend decoupling agents from frontends.

## Quick Start

```bash
# Local
uvicorn src.api.app:app --reload --port 8080

# Docker
docker compose --env-file .env -f docker/docker-compose.yml up supervisor_api
```

**Docs:** http://localhost:8080/docs

## Endpoints

### Supervisor Agent `/api/v1/supervisor`

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/chat` | Batch response with context compaction |
| POST | `/chat/stream` | SSE streaming with context compaction ⚠️ |
| POST | `/raw/chat` | Batch response, direct agent (no compaction) |
| POST | `/raw/chat/stream` | SSE streaming, direct agent ⚠️ |
| POST | `/new` | Create new chat session |
| GET | `/health` | Health check |

⚠️ **Note:** Streaming endpoints have known issues. Use batch endpoints (`/chat` or `/raw/chat`) for reliable operation.

**With vs Raw endpoints:**
- `/chat` and `/chat/stream` use `CompactingSupervisor` wrapper (auto context management)
- `/raw/chat` and `/raw/chat/stream` bypass wrapper (direct agent access, useful for debugging)

**Streaming (SSE) events:**
```
event: token    β†’ {"content": "Hello"}
event: done     β†’ {"thread_id": "abc123", "token_count": 150}
event: error    β†’ {"error": "Something went wrong"}
```

### CV Upload `/api/v1/cv`

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/submit` | Submit application + CV |
| GET | `/health` | Health check |

**Submit flow:**
1. Save CV file to disk
2. Register candidate in DB
3. Parse CV β†’ Markdown (GPT-4 Vision)
4. Update parsed path in DB

### Database `/api/v1/db`

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/query` | Flexible query any table |
| GET | `/candidates` | List candidates with filters |
| GET | `/candidates/{id}` | Get full candidate profile by UUID |
| GET | `/candidates/email/{email}` | Get full candidate profile by email |
| GET | `/cv-screening` | List CV screening results |
| GET | `/voice-screening` | List voice screening results |
| GET | `/interviews` | List interview scheduling |
| GET | `/decisions` | List final decisions |
| GET | `/stats` | Database statistics |
| GET | `/health` | Health check |

**Full Candidate Profile** (`/candidates/{id}` and `/candidates/email/{email}`):

Returns ALL data for a candidate including related records (by default `include_relations=true`):
- **Base fields:** id, full_name, email, phone_number, cv_file_path, parsed_cv_file_path, status, created_at, updated_at
- **cv_screening_results:** list of CV screening scores and feedback
- **voice_screening_results:** list of voice screening transcripts and scores
- **interview_scheduling:** list of scheduled interviews
- **final_decision:** hiring decision with rationale (if any)

Use `?include_relations=false` to fetch only base candidate fields.

**Flexible Query Example:**
```json
POST /api/v1/db/query
{
    "table": "candidates",
    "filters": {"status": "applied"},
    "fields": ["id", "full_name", "email"],
    "include_relations": true,
    "limit": 10,
    "offset": 0,
    "sort_by": "created_at",
    "sort_order": "desc"
}
```

**Supported filter operators:**
- `$eq`, `$ne`: equality/inequality
- `$gt`, `$gte`, `$lt`, `$lte`: comparisons
- `$in`, `$nin`: list membership
- `$like`, `$ilike`: pattern matching

## Structure

```
src/api/
β”œβ”€β”€ app.py              ← FastAPI app + CORS + router mounting
β”œβ”€β”€ routers/
β”‚   β”œβ”€β”€ supervisor.py   ← Chat endpoints (regular + streaming)
β”‚   β”œβ”€β”€ cv_upload.py    ← CV submission endpoint
β”‚   └── database.py     ← Flexible database query endpoints
└── schemas/
    β”œβ”€β”€ supervisor_chat.py  ← ChatRequest, ChatResponse
    β”œβ”€β”€ cv_upload.py        ← SubmitResponse
    └── database.py         ← QueryRequest, QueryResponse, etc.
```

## SDK Clients

Frontends use SDK clients instead of raw HTTP:

```python
# Supervisor
from src.sdk import SupervisorClient
client = SupervisorClient()
for chunk in client.stream("Show candidates", thread_id):
    print(chunk.content)

# CV Upload
from src.sdk import CVUploadClient
client = CVUploadClient()
response = client.submit(name, email, phone, cv_file, filename)

# Database Queries
from src.sdk import DatabaseClient
db = DatabaseClient()

# List candidates
candidates = db.get_candidates(status="applied", include_relations=True)
for c in candidates.data:
    print(c["full_name"], c["status"])

# Get full candidate profile by email
profile = db.get_candidate_by_email("ada@example.com")
print(profile.data["cv_screening_results"])

# Flexible query with filters
results = db.query(
    table="cv_screening_results",
    filters={"overall_fit_score": {"$gte": 0.8}},
    sort_by="overall_fit_score",
    sort_order="desc"
)

# Get database stats
stats = db.get_stats()
print(stats.stats["candidates"]["by_status"])
```

## Environment

| Variable | Default | Used By |
|----------|---------|---------|
| `OPENAI_API_KEY` | required | Validated at startup |
| `CV_UPLOAD_PATH` | `src/database/cvs/uploads` | CV router |
| `CV_PARSED_PATH` | `src/database/cvs/parsed` | CV router |
| `POSTGRES_*` | varies | Database connection |

## TODO

- [ ] Voice agent router
- [x] Candidate database router