diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..4578180 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,259 @@ +# API Reference + +Base URL: `http://app-01:8080` + +The Work Queue WebUI connects to the Work Queue API to display and manage work items. All endpoints return JSON. + +--- + +## Work Items + +### GET /work + +List work items with optional filters. + +**Query Parameters:** +| Parameter | Type | Description | +|---|---|---| +| `status` | `string` | Filter by status | +| `agent` | `string` | Filter by assigned agent | +| `project_id` | `uuid` | Filter by project | +| `since` | `ISO8601` | Return items created after this time | +| `type` | `string` | Filter by work item type | + +**Status values:** `queued`, `dispatched`, `in_progress`, `completed`, `failed`, `blocked`, `cancelled` + +**Response:** `200 OK` +```json +[ + { + "id": "550e8400-e29b-41d4-a716-446655440000", + "type": "infra_setup", + "description": "Set up nginx reverse proxy", + "priority": 2, + "status": "completed", + "assigned_agent": "lennie-s", + "created_by": "marcus-a", + "created_at": "2026-04-12T00:00:00Z", + "updated_at": "2026-04-12T00:30:00Z", + "outcome": "success", + "notes": "Deployed successfully" + } +] +``` + +--- + +### POST /work + +Submit a new work item. + +**Request Body:** +```json +{ + "type": "code_review", + "description": "Review PR #42 in work-queue-api", + "priority": 1, + "agent": "steve-w", + "project_id": "d1457588-d7ad-4bbe-a252-ffe42cb55a77", + "payload": { + "pr": 42, + "repo": "work-queue-api" + } +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `type` | `string` | Yes | Work category (e.g. `code_review`, `bug_fix`, `infra_setup`) | +| `description` | `string` | Yes | Human-readable task description | +| `priority` | `integer` | No | 1 (highest) to 5 (lowest), default 3 | +| `agent` | `string` | No | Agent username to assign | +| `project_id` | `uuid` | No | Associated project | +| `payload` | `object` | No | Arbitrary type-specific data | + +**Response:** `201 Created` + +--- + +### PATCH /work/{id} + +Update a work item. + +**Request Body:** +```json +{ + "status": "completed", + "outcome": "success", + "notes": "All checks passed", + "agent": "lennie-s" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `status` | `string` | No | New status | +| `outcome` | `string` | Yes | Required when status is terminal (`success`, `failed`, `cancelled`) | +| `notes` | `string` | No | Human-readable notes | +| `agent` | `string` | No | Reassign to different agent | + +**Response:** `200 OK` + +--- + +### GET /work/{id} + +Get a single work item with dispatch history. + +**Response:** `200 OK` +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "type": "infra_setup", + "description": "Set up nginx reverse proxy", + "priority": 2, + "status": "completed", + "assigned_agent": "lennie-s", + "created_by": "marcus-a", + "created_at": "2026-04-12T00:00:00Z", + "updated_at": "2026-04-12T00:30:00Z", + "completed_at": "2026-04-12T00:30:00Z", + "outcome": "success", + "notes": "Deployed successfully", + "dispatch_log": [ + { + "id": "dispatch-uuid", + "work_item_id": "550e8400-e29b-41d4-a716-446655440000", + "dispatched_at": "2026-04-12T00:05:00Z", + "agent": "lennie-s", + "completed_at": "2026-04-12T00:30:00Z", + "outcome": "success" + } + ] +} +``` + +--- + +## Projects + +### GET /projects + +List all projects. + +**Response:** `200 OK` +```json +[ + { + "id": "d1457588-d7ad-4bbe-a252-ffe42cb55a77", + "name": "Work Queue WebUI", + "external_ref": "git.danhenry.dev/thelab/work-queue-webui", + "created_at": "2026-04-11T00:00:00Z" + } +] +``` + +--- + +### POST /projects + +Create a new project. + +**Request Body:** +```json +{ + "name": "Shopping List API", + "external_ref": "git.danhenry.dev/thelab/shopping-list-api" +} +``` + +| Field | Type | Required | Description | +|---|---|---|---| +| `name` | `string` | Yes | Project name | +| `external_ref` | `string` | No | External identifier (repo URL, Todoist ID, etc.) | + +**Response:** `201 Created` + +--- + +### PATCH /projects/{id} + +Update a project. + +**Request Body:** +```json +{ + "name": "Shopping List API (revived)", + "external_ref": "git.danhenry.dev/thelab/shopping-list-api" +} +``` + +**Response:** `200 OK` + +--- + +## WorkItem Shape + +| Field | Type | Description | +|---|---|---| +| `id` | `uuid` | Unique identifier | +| `type` | `string` | Work category | +| `description` | `string` | Task description | +| `priority` | `integer` | 1 (highest) to 5 (lowest) | +| `status` | `string` | Current lifecycle state | +| `assigned_agent` | `string\|null` | Agent username | +| `created_by` | `string` | Creator username | +| `created_at` | `ISO8601` | Creation timestamp | +| `updated_at` | `ISO8601` | Last update timestamp | +| `completed_at` | `ISO8601\|null` | Completion timestamp | +| `outcome` | `string\|null` | `success`, `failed`, or `cancelled` | +| `notes` | `string\|null` | Optional notes | +| `payload` | `object\|null` | Type-specific data | +| `project_id` | `uuid\|null` | Associated project | +| `dispatch_log` | `array` | Dispatch history entries | + +--- + +## Status Lifecycle + +``` +queued → dispatched → in_progress → completed + ↘ blocked + ↘ failed + ↘ cancelled (from queued or dispatched only) +``` + +| Transition | From → To | Notes | +|---|---|---| +| submit | — → queued | New work item created | +| dispatch | queued → dispatched | Assigned to agent | +| pick up | dispatched → in_progress | Agent starts work | +| block | in_progress → blocked | Work stalled | +| complete | in_progress → completed | Requires `outcome: success` | +| fail | in_progress → failed | Requires `outcome: failed` | +| cancel | queued/dispatched → cancelled | Requires `outcome: cancelled` | + +--- + +## Agent Queue + +### GET /work/agent/{agent} + +Get all work items for a specific agent. + +**Response:** `200 OK` — array of WorkItem objects + +--- + +## Health + +### GET /health + +Returns API health status. + +**Response:** `200 OK` +```json +{ + "status": "ok" +} +``` diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..a3ee8b2 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,121 @@ +# Deployment + +## Docker + +The WebUI ships as a multi-stage Docker image. + +### Build + +```bash +git clone https://git.danhenry.dev/thelab/work-queue-webui.git +cd work-queue-webui +docker build -t git.danhenry.dev/thelab/work-queue-webui:latest . +``` + +### Run + +```bash +docker run -d \ + --name work-queue-webui \ + -p 8081:80 \ + git.danhenry.dev/thelab/work-queue-webui:latest +``` + +The WebUI will be available at `http://localhost:8081`. + +### Environment + +| Variable | Default | Description | +|---|---|---| +| `WORK_QUEUE_API_URL` | `http://app-01:8080` | Work Queue API endpoint | + +### Volumes + +| Path | Description | +|---|---| +| `/app/data` | Persistent data directory | + +--- + +## Docker Compose + +```yaml +services: + webui: + image: git.danhenry.dev/thelab/work-queue-webui:latest + volumes: + - ./data:/app/data + restart: unless-stopped + + proxy: + image: nginx:alpine + ports: + - "8081:80" + volumes: + - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + webui: + condition: service_healthy + restart: unless-stopped + +volumes: + data: +``` + +--- + +## Ansible + +An Ansible role is available in `roles/work_queue_webui/`. See the role's `defaults/main.yml` for configuration options. + +### Variables + +| Variable | Default | Description | +|---|---|---| +| `work_queue_webui_image_tag` | `latest` | Docker image tag | +| `work_queue_webui_proxy_port` | `8081` | External port | +| `work_queue_webui_data_path` | `.../work-queue-webui/data` | Data volume path | + +### Deploy + +```bash +cd infrastructure/ansible +ansible-playbook -i inventory playbooks/services/work_queue_webui.yml +``` + +--- + +## Nginx Reverse Proxy + +If deploying behind an existing nginx instance, proxy to the container port: + +```nginx +location / { + proxy_pass http://localhost:8081; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; +} +``` + +--- + +## Health Check + +The WebUI exposes a basic health endpoint at `/health` (returns `{"status": "ok"}`). The container uses `wget` to verify the nginx frontend is responding. + +--- + +## CI Pipeline + +A Gitea Actions workflow (`.gitea/workflows/docker.yml`) automatically builds and pushes the image on every push to `main`: + +- **Triggers:** push to `main` +- **Platforms:** `linux/amd64`, `linux/arm64` +- **Tags:** `git.danhenry.dev/thelab/work-queue-webui:` and `:latest` +- **Registry:** Gitea container registry at `git.danhenry.dev` + +Required secrets in the repo: +- `DOCKER_REGISTRY_USER` — Gitea username +- `DOCKER_REGISTRY_TOKEN` — Gitea API token diff --git a/docs/guide.md b/docs/guide.md new file mode 100644 index 0000000..41d5770 --- /dev/null +++ b/docs/guide.md @@ -0,0 +1,55 @@ +# User Guide + +## How the Queue System Works + +TheLab's work queue system dispatches tasks to autonomous agents. Each work item has a lifecycle: + +``` +queued → dispatched → in_progress → completed + ↘ blocked + ↘ failed + ↘ cancelled (from queued or dispatched only) +``` + +1. **Marcus** (or another human) creates a work item via the Work Queue API +2. Work items wait in `queued` until an agent is available +3. The item is `dispatched` to an agent — the agent picks it up and it becomes `in_progress` +4. On completion, the item reaches `completed` (or `failed` if something went wrong) +5. Agents can only have one `in_progress` item at a time + +## Viewing the Queue + +On the main dashboard you can see: +- **Queued** — work items waiting for an agent +- **In Progress** — items currently being worked on +- **Completed** — finished items with outcomes + +## Work Item Fields + +| Field | Description | +|---|---| +| `id` | Unique identifier (UUID) | +| `type` | Category: `code_review`, `bug_fix`, `infra_setup`, etc. | +| `description` | Human-readable task description | +| `priority` | 1 (highest) to 5 (lowest) | +| `status` | Current lifecycle state | +| `assigned_agent` | Agent currently handling the item | +| `outcome` | `success`, `failed`, or `cancelled` | +| `created_at` | ISO8601 timestamp | +| `notes` | Optional human notes | + +## Agents + +Agents are autonomous workers assigned to the queue. Each agent picks up dispatched items and works through them one at a time. + +Current known agents: +- **lennie-s** — infrastructure and tooling tasks +- **steve-w** — general development tasks + +## Projects + +Work items can be grouped under projects. Projects have a name and an optional external reference (e.g., a Git repo URL or Todoist project ID). + +## Priorities + +Work items have priorities from 1 (highest) to 5 (lowest). Higher priority items are picked up first by agents. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..b713036 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,34 @@ +# Work Queue WebUI + +A web interface for managing TheLab's distributed work queue system. It connects to the [Work Queue API](https://git.danhenry.dev/thelab/work-queue-api) and presents queue state in real time. + +## Overview + +The Work Queue WebUI provides a visual interface for monitoring and managing work items dispatched to agents across TheLab's infrastructure. + +## Features + +- Real-time queue status monitoring +- Agent activity tracking +- Work item lifecycle visibility +- Project-based work organization + +## Quick Start + +1. Open the WebUI in your browser (default: `http://localhost:8081`) +2. View active work items and their current status +3. Monitor agent activity and queue depth + +## Architecture + +The WebUI is a React frontend that communicates with the Work Queue API backend. It polls for updates and displays the current state of all queued, in-progress, and completed work items. + +``` +Browser → Work Queue WebUI → Work Queue API (app-01:8080) → PostgreSQL +``` + +## Related + +- [Work Queue API](https://git.danhenry.dev/thelab/work-queue-api) +- [Deployment Guide](./deployment.md) +- [API Reference](./api.md) diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..aa34137 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,36 @@ +site_name: Work Queue WebUI +site_description: Web interface for TheLab Work Queue system +site_url: https://git.danhenry.dev/thelab/work-queue-webui + +repo_name: thelab/work-queue-webui +repo_url: https://git.danhenry.dev/thelab/work-queue-webui + +theme: + name: material + palette: + - media: "(prefers-color-scheme: light)" + primary: indigo + accent: indigo + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + primary: indigo + accent: indigo + toggle: + icon: material/brightness-4 + name: Switch to light mode + +nav: + - Home: index.md + - User Guide: guide.md + - API Reference: api.md + - Deployment: deployment.md + +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.superfences + - admonition + - toc: + permalink: true