diff --git a/PROJECT.md b/PROJECT.md index 4db8743..5350309 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -6,54 +6,141 @@ The `vibn-agent-runner` is a service responsible for executing tasks or "agents" ## API Endpoints -(Note: These are example endpoints. Please refer to the source code or API documentation for exact details.) +### `GET /api/status` -### `POST /run-agent` +Retrieves server status and job statistics. -Initiates the execution of an agent. +- **Method:** `GET` +- **URL:** `/api/status` +- **Response Body Example:** + ```json + { + "total_jobs": 100, + "by_status": { + "queued": 10, + "running": 5, + "completed": 80, + "failed": 5 + }, + "uptime_seconds": 3600, + "agents": ["Coder", "PM", "Marketing"] + } + ``` + +### `GET /health` + +Health check endpoint. + +- **Method:** `GET` +- **URL:** `/health` +- **Response Body Example:** + ```json + { + "status": "ok", + "timestamp": "2023-10-27T10:00:00.000Z" + } + ``` + +### `GET /api/agents` + +Lists available agents. + +- **Method:** `GET` +- **URL:** `/api/agents` +- **Response Body Example:** + ```json + [ + { + "name": "Coder", + "description": "An agent that writes and modifies code.", + "tools": ["read_file", "write_file", "replace_in_file", "list_directory", "find_files", "search_code", "execute_command", "git_commit_and_push", "gitea_create_issue", "gitea_list_issues", "gitea_close_issue"] + } + ] + ``` + +### `POST /api/agent/run` + +Submits a new job to run an agent. - **Method:** `POST` -- **URL:** `/run-agent` +- **URL:** `/api/agent/run` - **Request Body Example:** ```json { - "agentId": "your-agent-id", - "payload": { - "param1": "value1", - "param2": "value2" - } + "agent": "Coder", + "task": "Fix bug in user authentication", + "repo": "owner/repo-name" } ``` - **Response Body Example (Success):** ```json { - "status": "success", - "runId": "unique-run-id", - "message": "Agent execution started." - } - ``` -- **Response Body Example (Error):** - ```json - { - "status": "error", - "message": "Failed to start agent execution.", - "details": "Error message details" + "jobId": "unique-job-id", + "status": "queued" } ``` -### `GET /agent-status/{runId}` +### `GET /api/jobs/:id` -Retrieves the status of a running or completed agent. +Retrieves the status of a specific job. - **Method:** `GET` -- **URL:** `/agent-status/{runId}` +- **URL:** `/api/jobs/:id` - **Response Body Example:** ```json { - "runId": "unique-run-id", - "status": "running", // or "completed", "failed" - "progress": "50%", - "results": {} // or actual results if completed + "id": "unique-job-id", + "agent": "Coder", + "task": "Fix bug in user authentication", + "repo": "owner/repo-name", + "status": "running", + "progress": "Executing tests...", + "createdAt": "2023-10-27T10:00:00.000Z" + } + ``` + +### `GET /api/jobs` + +Lists recent jobs. + +- **Method:** `GET` +- **URL:** `/api/jobs` +- **Query Parameters:** + - `limit`: (Optional) Number of jobs to return (default: 20) +- **Response Body Example:** + ```json + [ + { + "id": "job-id-1", + "agent": "Coder", + "task": "Implement feature X", + "status": "completed" + }, + { + "id": "job-id-2", + "agent": "PM", + "task": "Write project brief", + "status": "running" + } + ] + ``` + +### `POST /webhook/gitea` + +Gitea webhook endpoint to trigger agents from issue events. + +- **Method:** `POST` +- **URL:** `/webhook/gitea` +- **Headers:** + - `X-Gitea-Event`: e.g., `issues` + - `X-Gitea-Signature`: HMAC-SHA256 signature (if `WEBHOOK_SECRET` is set) +- **Request Body:** Gitea webhook payload (JSON) +- **Response Body Example:** + ```json + { + "jobId": "unique-job-id", + "agent": "Coder", + "event": "issues" } ``` diff --git a/src/server.ts b/src/server.ts index 389ef49..f1d0df0 100644 --- a/src/server.ts +++ b/src/server.ts @@ -12,6 +12,8 @@ import { ToolContext } from './tools'; const app = express(); app.use(cors()); +const startTime = new Date(); + // Raw body capture for webhook HMAC — must come before express.json() app.use('/webhook/gitea', express.raw({ type: '*/*' })); @@ -87,6 +89,33 @@ app.get('/api/agents', (_req: Request, res: Response) => { res.json(agents); }); +// Get server status and job statistics +app.get('/api/status', (_req: Request, res: Response) => { + const allJobs = listJobs(Infinity); + const total_jobs = allJobs.length; + + const by_status: { [key: string]: number } = { + queued: 0, + running: 0, + completed: 0, + failed: 0, + }; + for (const job of allJobs) { + by_status[job.status] = (by_status[job.status] || 0) + 1; + } + + const uptime_seconds = Math.floor((new Date().getTime() - startTime.getTime()) / 1000); + + const agents = Object.values(AGENTS).map(a => a.name); + + res.json({ + total_jobs, + by_status, + uptime_seconds, + agents, + }); +}); + // Submit a new job app.post('/api/agent/run', async (req: Request, res: Response) => { const { agent: agentName, task, repo } = req.body as { agent?: string; task?: string; repo?: string };