docs(agents): add AGENTS.md documentation for interview bot project
This commit is contained in:
4
.github/Repo.toml
vendored
Normal file
4
.github/Repo.toml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[scopes]
|
||||
config = ["wrangler.toml", "package.json", ".gitignore"]
|
||||
docs = ["README.md"]
|
||||
core = ["src"]
|
||||
178
AGENTS.md
Normal file
178
AGENTS.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# AGENTS.md - Interview Bot
|
||||
|
||||
> AI-powered interviewer bot with video call interface and calendar scheduling on Cloudflare Workers.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `npm run dev` | Start local dev server (port 8787) |
|
||||
| `npm run deploy` | Deploy to Cloudflare Workers |
|
||||
| `npm run tail` | Stream production logs |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/index.ts # Entire app: API routes, AI chat, HTML/CSS/JS frontend
|
||||
wrangler.toml # Cloudflare Workers config (KV bindings, AI binding)
|
||||
package.json # Dependencies and npm scripts
|
||||
```
|
||||
|
||||
**Single-file architecture**: All backend routes + frontend UI lives in `src/index.ts`.
|
||||
|
||||
## Build & Development
|
||||
|
||||
```bash
|
||||
npm install && npm run dev # Local dev at http://localhost:8787
|
||||
npm run deploy # Deploy to production
|
||||
```
|
||||
|
||||
### KV Setup (First-time only)
|
||||
```bash
|
||||
npx wrangler kv namespace create INTERVIEWS
|
||||
npx wrangler kv namespace create INTERVIEWS --preview
|
||||
# Update wrangler.toml with returned IDs
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
**No test framework.** Manual testing only:
|
||||
- `GET /api/interviews` - List interviews
|
||||
- `POST /api/interviews` - Create interview
|
||||
- `PUT /api/interviews/:id` - Update interview
|
||||
- `DELETE /api/interviews/:id` - Delete interview
|
||||
- `POST /api/chat` - Stream AI chat
|
||||
|
||||
## Code Style
|
||||
|
||||
### TypeScript Patterns
|
||||
|
||||
- **Runtime**: Cloudflare Workers (no Node.js APIs)
|
||||
- **No tsconfig.json**: Wrangler handles TypeScript compilation
|
||||
- **Explicit types**: Always type function params and return values
|
||||
- **Interfaces**: Define at file top, before constants
|
||||
|
||||
```typescript
|
||||
// Interfaces at top
|
||||
interface Interview {
|
||||
id: string;
|
||||
candidateName: string;
|
||||
status: 'scheduled' | 'in-progress' | 'completed' | 'cancelled';
|
||||
}
|
||||
|
||||
// Explicit return types
|
||||
async function getInterviews(env: Env, corsHeaders: Record<string, string>): Promise<Response> {
|
||||
// ...
|
||||
}
|
||||
|
||||
// Type assertions for JSON
|
||||
const body = await request.json() as Partial<Interview>;
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
| Element | Convention | Example |
|
||||
|---------|------------|---------|
|
||||
| Interfaces | PascalCase | `Interview`, `ChatMessage`, `Env` |
|
||||
| Functions | camelCase | `handleChat`, `getInterviews` |
|
||||
| Constants | SCREAMING_SNAKE | `SYSTEM_PROMPT` |
|
||||
| Variables | camelCase | `corsHeaders`, `currentView` |
|
||||
|
||||
### Error Handling
|
||||
|
||||
```typescript
|
||||
try {
|
||||
// operation
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json', ...corsHeaders },
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### API Response Pattern
|
||||
|
||||
```typescript
|
||||
// Always include CORS headers
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type',
|
||||
};
|
||||
|
||||
// JSON response
|
||||
return new Response(JSON.stringify(data), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json', ...corsHeaders },
|
||||
});
|
||||
|
||||
// SSE streaming response
|
||||
return new Response(stream as ReadableStream, {
|
||||
headers: { 'Content-Type': 'text/event-stream', ...corsHeaders },
|
||||
});
|
||||
```
|
||||
|
||||
### Routing (No framework)
|
||||
|
||||
```typescript
|
||||
if (path === '/api/interviews' && request.method === 'GET') {
|
||||
return await getInterviews(env, corsHeaders);
|
||||
}
|
||||
if (path.startsWith('/api/interviews/') && request.method === 'DELETE') {
|
||||
const id = path.split('/')[3];
|
||||
return await deleteInterview(id, env, corsHeaders);
|
||||
}
|
||||
```
|
||||
|
||||
### Frontend (Inline in getHTML())
|
||||
|
||||
- CSS: Custom properties in `:root`, inline `<style>` block
|
||||
- JS: Inline `<script>` at end of body, vanilla DOM manipulation
|
||||
- State: Module-level variables (`let interviews = []`)
|
||||
|
||||
## Environment Bindings
|
||||
|
||||
```typescript
|
||||
export interface Env {
|
||||
AI: Ai; // Workers AI
|
||||
INTERVIEWS: KVNamespace; // KV storage
|
||||
}
|
||||
```
|
||||
|
||||
## Key Data Structures
|
||||
|
||||
```typescript
|
||||
interface Interview {
|
||||
id: string;
|
||||
candidateName: string;
|
||||
email: string;
|
||||
scheduledAt: string; // ISO 8601
|
||||
duration: number; // minutes
|
||||
status: 'scheduled' | 'in-progress' | 'completed' | 'cancelled';
|
||||
notes: string[];
|
||||
transcript: string[];
|
||||
}
|
||||
|
||||
interface ChatMessage {
|
||||
role: 'system' | 'user' | 'assistant';
|
||||
content: string;
|
||||
}
|
||||
```
|
||||
|
||||
## Common Tasks
|
||||
|
||||
**Add API endpoint**: Add handler function + path match in `fetch` handler + include `corsHeaders`
|
||||
|
||||
**Modify AI behavior**: Edit `SYSTEM_PROMPT` constant or adjust `max_tokens` in `handleChat()`
|
||||
|
||||
**Update UI**: Modify HTML/CSS/JS in `getHTML()` function
|
||||
|
||||
## Gotchas
|
||||
|
||||
1. **No Node.js APIs** - Edge runtime only
|
||||
2. **Single file** - Don't split into modules
|
||||
3. **KV IDs** - Must update `wrangler.toml` after namespace creation
|
||||
4. **Template literals** - Frontend uses escaped backticks (\`\`) for nested templates
|
||||
5. **AI model** - Default `llama-3.1-8b-instruct`; use `llama-3.3-70b-instruct-fp8-fast` for quality
|
||||
Reference in New Issue
Block a user